diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-08-12 15:04:05 +0000 |
|---|---|---|
| committer | Krzysztof KosiĆski <tweenk.pl@gmail.com> | 2010-08-12 15:04:05 +0000 |
| commit | baa16f58cf5472eaea112b9234b0324c8ca6ff7b (patch) | |
| tree | 502f27615fc6bf1b77713fb4fd563713f6b2fbbc /src | |
| parent | Fix the morphology filter (work on premultiplied colors) (diff) | |
| download | inkscape-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.cpp | 16 | ||||
| -rw-r--r-- | src/display/nr-filter-gaussian.cpp | 13 | ||||
| -rw-r--r-- | src/display/nr-filter.cpp | 48 | ||||
| -rw-r--r-- | src/display/nr-filter.h | 7 |
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 |
