index 2e973b4ec9d258b0f928ed912c6fb0d7c4ab77ba..8930a74dfb5171b09996d3101078def85e4d5d92 100644 (file)
#include <glib.h>
#include <cmath>
+#include <cstring>
+#include <string>
#include "display/nr-filter.h"
#include "display/nr-filter-primitive.h"
#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
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) {
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;
}
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);
}
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];
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];
} 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;
}