Code

Merging from trunk
[inkscape.git] / src / display / nr-filter.cpp
index 2e973b4ec9d258b0f928ed912c6fb0d7c4ab77ba..8930a74dfb5171b09996d3101078def85e4d5d92 100644 (file)
@@ -13,6 +13,8 @@
 
 #include <glib.h>
 #include <cmath>
+#include <cstring>
+#include <string>
 
 #include "display/nr-filter.h"
 #include "display/nr-filter-primitive.h"
@@ -44,7 +46,7 @@
 #include "libnr/nr-scale.h"
 #include "svg/svg-length.h"
 #include "sp-filter-units.h"
-#if defined (SOLARIS_2_8)
+#if defined (SOLARIS) && (SOLARIS == 8)
 #include "round.h"
 using Inkscape::round;
 #endif 
@@ -104,20 +106,39 @@ Filter::~Filter()
 
 int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
 {
-    if(!_primitive[0]) {
+    if (!_primitive[0]) {
         // TODO: Should clear the input buffer instead of just returning
-       return 0
+       return 1
     }
 
-    Matrix trans = *item->ctm;
+    Matrix trans = item->ctm;
     FilterSlot slot(_slot_count, item);
 
-    Rect item_bbox = *item->item_bbox;
-    Rect filter_area = filter_effect_area(item_bbox);
+    Geom::Rect item_bbox;
+    if (item->item_bbox) {
+        item_bbox = *(item->item_bbox);
+    } else {
+        // Bounding box might not exist, so create a dummy one.
+        Geom::Point zero(0, 0);
+        item_bbox = Geom::Rect(zero, zero);
+    }
+    if (item_bbox.min()[X] > item_bbox.max()[X]
+        || item_bbox.min()[Y] > item_bbox.max()[Y])
+    {
+        // Code below assumes non-negative size.
+        return 1;
+    }
+
+    Geom::Rect filter_area = filter_effect_area(item_bbox);
+    if (item_bbox.isEmpty()) {
+        // It's no use to try and filter an empty object.
+        return 1;
+    }
+        
     FilterUnits units(_filter_units, _primitive_units);
     units.set_ctm(trans);
-    units.set_item_bbox(item_bbox);
-    units.set_filter_area(filter_area);
+    units.set_item_bbox(from_2geom(item_bbox));
+    units.set_filter_area(from_2geom(filter_area));
 
     // TODO: with filterRes of 0x0 should return an empty image
     if (_x_pixels > 0) {
@@ -157,7 +178,7 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
 
     NRPixBlock *in = new NRPixBlock;
     nr_pixblock_setup_fast(in, pb->mode, pb->area.x0, pb->area.y0,
-                           pb->area.x1, pb->area.y1, false);
+                           pb->area.x1, pb->area.y1, true);
     if (in->size != NR_PIXBLOCK_SIZE_TINY && in->data.px == NULL) {
         g_warning("NR::Filter::render: failed to reserve temporary buffer");
         return 0;
@@ -177,11 +198,8 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
     }
     in = NULL; // in is now handled by FilterSlot, we should not touch it
 
-    // TODO: filters may need both filterUnits and primitiveUnits,
-    // so we should pass FilterUnits to render method, not just one Matrix
-    Matrix primitiveunits2pixblock = units.get_matrix_primitiveunits2pb();
     for (int i = 0 ; i < _primitive_count ; i++) {
-        _primitive[i]->render(slot, primitiveunits2pixblock);
+        _primitive[i]->render(slot, units);
     }
 
     slot.get_final(_output_slot, pb);
@@ -200,13 +218,17 @@ void Filter::area_enlarge(NRRectL &bbox, Matrix const &m) {
 }
 
 void Filter::bbox_enlarge(NRRectL &bbox) {
+    // Modifying empty bounding boxes confuses rest of the renderer, so
+    // let's not do that.
+    if (bbox.x0 > bbox.x1 || bbox.y0 > bbox.y1) return;
+
     /* TODO: this is wrong. Should use bounding box in user coordinates
      * and find its extents in display coordinates. */
-    Point min(bbox.x0, bbox.y0);
-    Point max(bbox.x1, bbox.y1);
-    Rect tmp_bbox(min, max);
+    Geom::Point min(bbox.x0, bbox.y0);
+    Geom::Point max(bbox.x1, bbox.y1);
+    Geom::Rect tmp_bbox(min, max);
 
-    Rect enlarged = filter_effect_area(tmp_bbox);
+    Geom::Rect enlarged = filter_effect_area(tmp_bbox);
 
     bbox.x0 = (ICoord)enlarged.min()[X];
     bbox.y0 = (ICoord)enlarged.min()[Y];
@@ -214,7 +236,7 @@ void Filter::bbox_enlarge(NRRectL &bbox) {
     bbox.y1 = (ICoord)enlarged.max()[Y];
 }
 
-Rect Filter::filter_effect_area(Rect const &bbox)
+Geom::Rect Filter::filter_effect_area(Geom::Rect const &bbox)
 {
     Point minp, maxp;
     double len_x = bbox.max()[X] - bbox.min()[X];
@@ -255,7 +277,7 @@ Rect Filter::filter_effect_area(Rect const &bbox)
     } else {
         g_warning("Error in NR::Filter::bbox_enlarge: unrecognized value of _filter_units");
     }
-    Rect area(minp, maxp);
+    Geom::Rect area(minp, maxp);
     return area;
 }