summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-08-12 15:04:05 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-08-12 15:04:05 +0000
commitbaa16f58cf5472eaea112b9234b0324c8ca6ff7b (patch)
tree502f27615fc6bf1b77713fb4fd563713f6b2fbbc /src
parentFix the morphology filter (work on premultiplied colors) (diff)
downloadinkscape-baa16f58cf5472eaea112b9234b0324c8ca6ff7b.tar.gz
inkscape-baa16f58cf5472eaea112b9234b0324c8ca6ff7b.zip
Fix computation of drawbox for filtered, rotated items
(bzr r9508.1.60)
Diffstat (limited to 'src')
-rw-r--r--src/display/nr-arena-item.cpp16
-rw-r--r--src/display/nr-filter-gaussian.cpp13
-rw-r--r--src/display/nr-filter.cpp48
-rw-r--r--src/display/nr-filter.h7
4 files changed, 34 insertions, 50 deletions
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index adbf772bc..ea162ca3d 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -265,12 +265,15 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
if (item->state & NR_ARENA_ITEM_STATE_INVALID)
return item->state;
- // get a copy of bbox
- memcpy(&item->drawbox, &item->bbox, sizeof(item->bbox));
-
/* Enlarge the drawbox to contain filter effects */
- if (item->filter && filter) {
- item->filter->bbox_enlarge (item->drawbox);
+ if (item->filter && filter && item->item_bbox) {
+ item->drawbox.x0 = item->item_bbox->min()[Geom::X];
+ item->drawbox.y0 = item->item_bbox->min()[Geom::Y];
+ item->drawbox.x1 = item->item_bbox->max()[Geom::X];
+ item->drawbox.y1 = item->item_bbox->max()[Geom::Y];
+ item->filter->compute_drawbox (item, item->drawbox);
+ } else {
+ memcpy(&item->drawbox, &item->bbox, sizeof(item->bbox));
}
// fixme: to fix the display glitches, in outline mode bbox must be a combination of
// full item bbox and its clip and mask (after we have the API to get these)
@@ -568,7 +571,8 @@ nr_arena_item_invoke_pick (NRArenaItem *item, Geom::Point p, double delta,
if (((x + delta) >= item->bbox.x0) &&
((x - delta) < item->bbox.x1) &&
- ((y + delta) >= item->bbox.y0) && ((y - delta) < item->bbox.y1)) {
+ ((y + delta) >= item->bbox.y0) && ((y - delta) < item->bbox.y1))
+ {
if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->pick)
return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
pick (item, p, delta, sticky);
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index f8a483acb..ba6f0bbe7 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -648,14 +648,13 @@ void FilterGaussian::area_enlarge(NRRectL &area, Geom::Matrix const &trans)
area.y1 += area_max;
}
-bool FilterGaussian::can_handle_affine(Geom::Matrix const &m)
+bool FilterGaussian::can_handle_affine(Geom::Matrix const &)
{
- if (Geom::are_near(_deviation_x, _deviation_y)) {
- // TODO after 2Geom sync, change this to m.preservesAngles()
- return Geom::are_near(m[0], m[3]) && Geom::are_near(m[1], -m[2]);
- } else {
- return false;
- }
+ // Previously we tried to be smart and return true for rotations.
+ // However, the transform passed here is NOT the total transform
+ // from filter user space to screen.
+ // TODO: fix this, or replace can_handle_affine() with isotropic().
+ return false;
}
void FilterGaussian::set_deviation(double deviation)
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index e163b6346..148b14f53 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -59,24 +59,6 @@ namespace Filters {
using Geom::X;
using Geom::Y;
-static Geom::OptRect get_item_bbox(NRArenaItem const *item) {
- 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])
- {
- // In case of negative-size bbox, return an empty OptRect
- return Geom::OptRect();
- }
- return Geom::OptRect(item_bbox);
-}
-
Filter::Filter()
{
_common_init();
@@ -134,19 +116,18 @@ int Filter::render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea
Geom::Rect item_bbox;
{
- Geom::OptRect maybe_bbox = get_item_bbox(item);
+ Geom::OptRect maybe_bbox = item->item_bbox;
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return 1;
}
item_bbox = *maybe_bbox;
}
-
- Geom::Rect filter_area = filter_effect_area(item_bbox);
if (item_bbox.hasZeroArea()) {
// It's no use to try and filter an empty object.
return 1;
}
+ Geom::Rect filter_area = filter_effect_area(item_bbox);
FilterUnits units(_filter_units, _primitive_units);
units.set_ctm(trans);
@@ -225,7 +206,7 @@ void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
}
Geom::Rect item_bbox;
- Geom::OptRect maybe_bbox = get_item_bbox(item);
+ Geom::OptRect maybe_bbox = item->item_bbox;
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return;
@@ -245,30 +226,29 @@ void Filter::area_enlarge(NRRectL &bbox, NRArenaItem const *item) const {
*/
}
-void Filter::bbox_enlarge(NRRectL &bbox) {
+void Filter::compute_drawbox(NRArenaItem const *item, NRRectL &item_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;
+ if (item_bbox.x0 > item_bbox.x1 || item_bbox.y0 > item_bbox.y1) return;
- /* TODO: this is wrong. Should use bounding box in user coordinates
- * and find its extents in display coordinates. */
- Geom::Point min(bbox.x0, bbox.y0);
- Geom::Point max(bbox.x1, bbox.y1);
+ Geom::Point min(item_bbox.x0, item_bbox.y0);
+ Geom::Point max(item_bbox.x1, item_bbox.y1);
Geom::Rect tmp_bbox(min, max);
Geom::Rect enlarged = filter_effect_area(tmp_bbox);
+ enlarged = enlarged * item->ctm;
- bbox.x0 = (NR::ICoord) floor(enlarged.min()[X]);
- bbox.y0 = (NR::ICoord) floor(enlarged.min()[Y]);
- bbox.x1 = (NR::ICoord) ceil(enlarged.max()[X]);
- bbox.y1 = (NR::ICoord) ceil(enlarged.max()[Y]);
+ item_bbox.x0 = (NR::ICoord) floor(enlarged.min()[X]);
+ item_bbox.y0 = (NR::ICoord) floor(enlarged.min()[Y]);
+ item_bbox.x1 = (NR::ICoord) ceil(enlarged.max()[X]);
+ item_bbox.y1 = (NR::ICoord) ceil(enlarged.max()[Y]);
}
Geom::Rect Filter::filter_effect_area(Geom::Rect const &bbox)
{
Geom::Point minp, maxp;
- double len_x = bbox.max()[X] - bbox.min()[X];
- double len_y = bbox.max()[Y] - bbox.min()[Y];
+ double len_x = bbox.width();
+ double len_y = bbox.height();
/* TODO: fetch somehow the object ex and em lengths */
_region_x.update(12, 6, len_x);
_region_y.update(12, 6, len_y);
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index 9349ba9c6..b266ba053 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -151,10 +151,11 @@ public:
*/
void area_enlarge(NRRectL &area, NRArenaItem const *item) const;
/**
- * Given an object bounding box, this function enlarges it so that
- * it contains the filter effect area.
+ * Given an item bounding box (in user coords), this function enlarges it
+ * to contain the filter effects region and transforms it to screen
+ * coordinates
*/
- void bbox_enlarge(NRRectL &bbox);
+ void compute_drawbox(NRArenaItem const *item, NRRectL &item_bbox);
/**
* Returns the filter effects area in user coordinate system.
* The given bounding box should be a bounding box as specified in