summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorbulia byak <buliabyak@gmail.com>2008-03-23 04:19:06 +0000
committerbuliabyak <buliabyak@users.sourceforge.net>2008-03-23 04:19:06 +0000
commite61c4cf5d00b95697851fc96be86e53b2fb1915a (patch)
tree31c0d3040955953e7276206895593176cd92dbea /src
parenthelper functions to access a single blur primitive in a filter (diff)
downloadinkscape-e61c4cf5d00b95697851fc96be86e53b2fb1915a.tar.gz
inkscape-e61c4cf5d00b95697851fc96be86e53b2fb1915a.zip
expand visual bbox for item with a filter
(bzr r5175)
Diffstat (limited to 'src')
-rw-r--r--src/sp-item.cpp67
1 files changed, 62 insertions, 5 deletions
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 4b5ddb373..ca77296d8 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -53,6 +53,7 @@
#include "conn-avoid-ref.h"
#include "conditions.h"
#include "sp-filter-reference.h"
+#include "filter-chemistry.h"
#include "sp-guide.h"
#include "libnr/nr-matrix-div.h"
@@ -738,11 +739,67 @@ sp_item_invoke_bbox_full(SPItem const *item, NR::Maybe<NR::Rect> *bbox, NR::Matr
((SPItemClass *) G_OBJECT_GET_CLASS(item))->bbox(item, &temp_bbox, transform, flags);
}
- // unless this is geometric bbox, crop the bbox by clip path, if any
- if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX && item->clip_ref->getObject()) {
- NRRect b;
- sp_clippath_get_bbox(SP_CLIPPATH(item->clip_ref->getObject()), &b, transform, flags);
- nr_rect_d_intersect (&temp_bbox, &temp_bbox, &b);
+ // unless this is geometric bbox, extend by filter area and crop the bbox by clip path, if any
+ if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX) {
+ if (SP_OBJECT_STYLE(item) && SP_OBJECT_STYLE(item)->filter.href) {
+ SPObject *filter = SP_OBJECT_STYLE(item)->getFilter();
+ if (filter && SP_IS_FILTER(filter)) {
+ // default filer area per the SVG spec:
+ double x = -0.1;
+ double y = -0.1;
+ double w = 1.2;
+ double h = 1.2;
+
+ // if area is explicitly set, override:
+ if (SP_FILTER(filter)->x._set)
+ x = SP_FILTER(filter)->x.computed;
+ if (SP_FILTER(filter)->y._set)
+ y = SP_FILTER(filter)->y.computed;
+ if (SP_FILTER(filter)->width._set)
+ w = SP_FILTER(filter)->width.computed;
+ if (SP_FILTER(filter)->height._set)
+ h = SP_FILTER(filter)->height.computed;
+
+ double dx0 = 0;
+ double dx1 = 0;
+ double dy0 = 0;
+ double dy1 = 0;
+ if (filter_is_single_gaussian_blur(SP_FILTER(filter))) {
+ // if this is a single blur, use 2.4*radius
+ // which may be smaller than the default area;
+ // see set_filter_area for why it's 2.4
+ double r = get_single_gaussian_blur_radius (SP_FILTER(filter));
+ dx0 = -2.4 * r;
+ dx1 = 2.4 * r;
+ dy0 = -2.4 * r;
+ dy1 = 2.4 * r;
+ } else {
+ // otherwise, calculate expansion from relative to absolute units:
+ dx0 = x * (temp_bbox.x1 - temp_bbox.x0);
+ dx1 = (w + x - 1) * (temp_bbox.x1 - temp_bbox.x0);
+ dy0 = y * (temp_bbox.y1 - temp_bbox.y0);
+ dy1 = (h + y - 1) * (temp_bbox.y1 - temp_bbox.y0);
+ }
+
+ // transform the expansions by the item's transform:
+ NR::Matrix i2d = sp_item_i2d_affine (item);
+ dx0 *= NR::expansionX(i2d);
+ dx1 *= NR::expansionX(i2d);
+ dy0 *= NR::expansionY(i2d);
+ dy1 *= NR::expansionY(i2d);
+
+ // expand the bbox
+ temp_bbox.x0 += dx0;
+ temp_bbox.x1 += dx1;
+ temp_bbox.y0 += dy0;
+ temp_bbox.y1 += dy1;
+ }
+ }
+ if (item->clip_ref->getObject()) {
+ NRRect b;
+ sp_clippath_get_bbox(SP_CLIPPATH(item->clip_ref->getObject()), &b, transform, flags);
+ nr_rect_d_intersect (&temp_bbox, &temp_bbox, &b);
+ }
}
if (temp_bbox.x0 > temp_bbox.x1 || temp_bbox.y0 > temp_bbox.y1) {