summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNiko Kiirala <niko@kiirala.com>2007-06-23 15:35:28 +0000
committerkiirala <kiirala@users.sourceforge.net>2007-06-23 15:35:28 +0000
commitbb9d08a3e32859491a125d8567f387a702795267 (patch)
tree3322ec862746beee7119d8e44e2e47185ae80916 /src
parentAdded polar coordinates. (diff)
downloadinkscape-bb9d08a3e32859491a125d8567f387a702795267.tar.gz
inkscape-bb9d08a3e32859491a125d8567f387a702795267.zip
Using the blur slider no longer destroys filters already applied to the object
(bzr r3086)
Diffstat (limited to 'src')
-rw-r--r--src/desktop-style.cpp31
-rw-r--r--src/dialogs/object-properties.cpp4
-rw-r--r--src/filter-chemistry.cpp183
-rw-r--r--src/filter-chemistry.h5
-rw-r--r--src/sp-feblend.cpp3
-rw-r--r--src/sp-feoffset.cpp8
-rw-r--r--src/sp-filter-primitive.cpp10
-rw-r--r--src/sp-filter.cpp69
-rw-r--r--src/sp-filter.h3
-rw-r--r--src/sp-gaussian-blur.cpp2
10 files changed, 224 insertions, 94 deletions
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index 9c7cbb35f..95abdfa5b 100644
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
@@ -1040,23 +1040,26 @@ objects_query_blur (GSList *objects, SPStyle *style_res)
//if object has a filter
if (style->filter.set && style->filter.filter) {
//cycle through filter primitives
- for(int i=0; i<style->filter.filter->_primitive_count; i++)
- {
- SPFilterPrimitive *primitive = style->filter.filter->_primitives[i];
- //if primitive is gaussianblur
- if(SP_IS_GAUSSIANBLUR(primitive)) {
- SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive);
- float num = spblur->stdDeviation.getNumber();
- blur_sum += num * NR::expansion(i2d);
- if (blur_prev != -1 && fabs (num - blur_prev) > 1e-2) // rather low tolerance because difference in blur radii is much harder to notice than e.g. difference in sizes
- same_blur = false;
- blur_prev = num;
- //TODO: deal with opt number, for the moment it's not necessary to the ui.
- blur_items ++;
+ SPObject *primitive_obj = style->filter.filter->children;
+ while (primitive_obj) {
+ if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) {
+ SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj);
+
+ //if primitive is gaussianblur
+ if(SP_IS_GAUSSIANBLUR(primitive)) {
+ SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive);
+ float num = spblur->stdDeviation.getNumber();
+ blur_sum += num * NR::expansion(i2d);
+ if (blur_prev != -1 && fabs (num - blur_prev) > 1e-2) // rather low tolerance because difference in blur radii is much harder to notice than e.g. difference in sizes
+ same_blur = false;
+ blur_prev = num;
+ //TODO: deal with opt number, for the moment it's not necessary to the ui.
+ blur_items ++;
+ }
}
+ primitive_obj = primitive_obj->next;
}
}
-
}
if (items > 0) {
diff --git a/src/dialogs/object-properties.cpp b/src/dialogs/object-properties.cpp
index 4db82385a..fbc9ab83f 100644
--- a/src/dialogs/object-properties.cpp
+++ b/src/dialogs/object-properties.cpp
@@ -434,9 +434,9 @@ sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *base)
g_assert(style != NULL);
if (radius == 0.0) {
- remove_filter (item, false);
+ remove_filter_gaussian_blur(item);
} else {
- SPFilter *constructed = new_filter_gaussian_blur_from_item(document, item, radius);
+ SPFilter *constructed = modify_filter_gaussian_blur_from_item(document, item, radius);
sp_style_set_property_url (SP_OBJECT(item), "filter", SP_OBJECT(constructed), false);
}
//request update
diff --git a/src/filter-chemistry.cpp b/src/filter-chemistry.cpp
index 164a6594a..90a6e32f2 100644
--- a/src/filter-chemistry.cpp
+++ b/src/filter-chemistry.cpp
@@ -6,8 +6,9 @@
* Authors:
* Hugo Rodrigues
* bulia byak
+ * Niko Kiirala
*
- * Copyright (C) 2006 authors
+ * Copyright (C) 2006,2007 authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -24,24 +25,46 @@
#include "xml/repr.h"
/**
- * Creates a filter with blur primitive of specified radius for an item with the given matrix expansion, width and height
+ * Count how many times the filter is used by the styles of o and its
+ * descendants
*/
-SPFilter *
-new_filter_gaussian_blur (SPDocument *document, gdouble radius, double expansion, double expansionX, double expansionY, double width, double height)
+static guint
+count_filter_hrefs(SPObject *o, SPFilter *filter)
{
- g_return_val_if_fail(document != NULL, NULL);
+ if (!o)
+ return 1;
- SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
+ guint i = 0;
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
+ SPStyle *style = SP_OBJECT_STYLE(o);
+ if (style
+ && style->filter.set
+ && style->filter.filter == filter)
+ {
+ i ++;
+ }
- // create a new filter
- Inkscape::XML::Node *repr;
- repr = xml_doc->createElement("svg:filter");
- repr->setAttribute("inkscape:collect", "always");
+ for (SPObject *child = sp_object_first_child(o);
+ child != NULL; child = SP_OBJECT_NEXT(child)) {
+ i += count_filter_hrefs(child, filter);
+ }
- double rx = radius * (expansionY != 0? (expansion / expansionY) : 1);
- double ry = radius * (expansionX != 0? (expansion / expansionX) : 1);
+ return i;
+}
+
+/**
+ * Sets a suitable filter effects area according to given blur radius,
+ * expansion and object size.
+ */
+static void set_filter_area(Inkscape::XML::Node *repr, gdouble radius,
+ double expansion, double expansionX,
+ double expansionY, double width, double height)
+{
+ // TODO: make this more generic, now assumed, that only the blur
+ // being added can affect the required filter area
+
+ double rx = radius * (expansionY != 0 ? (expansion / expansionY) : 1);
+ double ry = radius * (expansionX != 0 ? (expansion / expansionX) : 1);
if (width != 0 && height != 0 && (2.4 * rx > width * 0.1 || 2.4 * ry > height * 0.1)) {
// If not within the default 10% margin (see
@@ -57,11 +80,32 @@ new_filter_gaussian_blur (SPDocument *document, gdouble radius, double expansion
sp_repr_set_svg_double(repr, "y", -ymargin);
sp_repr_set_svg_double(repr, "height", 1 + 2 * ymargin);
}
+}
+
+/**
+ * Creates a filter with blur primitive of specified radius for an item with the given matrix expansion, width and height
+ */
+SPFilter *
+new_filter_gaussian_blur (SPDocument *document, gdouble radius, double expansion, double expansionX, double expansionY, double width, double height)
+{
+ g_return_val_if_fail(document != NULL, NULL);
+
+ SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
+
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
+
+ // create a new filter
+ Inkscape::XML::Node *repr;
+ repr = xml_doc->createElement("svg:filter");
+ //repr->setAttribute("inkscape:collect", "always");
+
+ set_filter_area(repr, radius, expansion, expansionX, expansionY,
+ width, height);
//create feGaussianBlur node
Inkscape::XML::Node *b_repr;
b_repr = xml_doc->createElement("svg:feGaussianBlur");
- b_repr->setAttribute("inkscape:collect", "always");
+ //b_repr->setAttribute("inkscape:collect", "always");
double stdDeviation = radius;
if (expansion != 0)
@@ -112,6 +156,89 @@ new_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble
return (new_filter_gaussian_blur (document, radius, i2d.expansion(), i2d.expansionX(), i2d.expansionY(), width, height));
}
+/**
+ * Modifies the gaussian blur applied to the item.
+ * If no filters are applied to given item, creates a new blur filter.
+ * If a filter is applied and it contains a blur, modify that blur.
+ * If the filter doesn't contain blur, a blur is added to the filter.
+ * Should there be more references to modified filter, that filter is
+ * duplicated, so that other elements referring that filter are not modified.
+ */
+/* TODO: this should be made more generic, not just for blurs */
+SPFilter *
+modify_filter_gaussian_blur_from_item(SPDocument *document, SPItem *item,
+ gdouble radius)
+{
+ if (!item->style || !item->style->filter.set) {
+ return new_filter_gaussian_blur_from_item(document, item, radius);
+ }
+
+ SPFilter *filter = SP_FILTER(item->style->filter.filter);
+ Inkscape::XML::Document *xml_doc = sp_document_repr_doc(document);
+
+ // If there are more users for this filter, duplicate it
+ if (SP_OBJECT_HREFCOUNT(filter) > count_filter_hrefs(item, filter)) {
+ Inkscape::XML::Node *repr;
+ repr = SP_OBJECT_REPR(item)->duplicate(xml_doc);
+ SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document);
+ SP_OBJECT_REPR(defs)->appendChild(repr);
+
+ filter = SP_FILTER( document->getObjectByRepr(repr) );
+ Inkscape::GC::release(repr);
+ }
+
+ // Determine the required standard deviation value
+ NR::Matrix i2d = sp_item_i2d_affine (item);
+ double expansion = i2d.expansion();
+ double stdDeviation = radius;
+ if (expansion != 0)
+ stdDeviation /= expansion;
+
+ // Get the object size
+ NR::Maybe<NR::Rect> const r = sp_item_bbox_desktop(item);
+ double width;
+ double height;
+ if (r) {
+ width = r->extent(NR::X);
+ height= r->extent(NR::Y);
+ } else {
+ width = height = 0;
+ }
+
+ // Set the filter effects area
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(item->style->filter.filter);
+ set_filter_area(repr, radius, expansion, i2d.expansionX(),
+ i2d.expansionY(), width, height);
+
+ // Search for gaussian blur primitives. If found, set the stdDeviation
+ // of the first one and return.
+ Inkscape::XML::Node *primitive = repr->firstChild();
+ while (primitive) {
+ if (strcmp("svg:feGaussianBlur", primitive->name()) == 0) {
+ sp_repr_set_svg_double(primitive, "stdDeviation",
+ stdDeviation);
+ return filter;
+ }
+ primitive = primitive->next();
+ }
+
+ // If there were no gaussian blur primitives, create a new one
+
+ //create feGaussianBlur node
+ Inkscape::XML::Node *b_repr;
+ b_repr = xml_doc->createElement("svg:feGaussianBlur");
+ //b_repr->setAttribute("inkscape:collect", "always");
+
+ //set stdDeviation attribute
+ sp_repr_set_svg_double(b_repr, "stdDeviation", stdDeviation);
+
+ //set feGaussianBlur as child of filter node
+ SP_OBJECT_REPR(filter)->appendChild(b_repr);
+ Inkscape::GC::release(b_repr);
+
+ return filter;
+}
+
void remove_filter (SPObject *item, bool recursive)
{
SPCSSAttr *css = sp_repr_css_attr_new ();
@@ -123,6 +250,34 @@ void remove_filter (SPObject *item, bool recursive)
sp_repr_css_attr_unref (css);
}
+/**
+ * Removes the first feGaussianBlur from the filter attached to given item.
+ * Should this leave us with an empty filter, remove that filter.
+ */
+/* TODO: the removed filter primitive may had had a named result image, so
+ * after removing, the filter may be in erroneous state, this situation should
+ * be handled gracefully */
+void remove_filter_gaussian_blur (SPObject *item)
+{
+ if (item->style && item->style->filter.set && item->style->filter.filter) {
+ // Search for the first blur primitive and remove it. (if found)
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(item->style->filter.filter);
+ Inkscape::XML::Node *primitive = repr->firstChild();
+ while (primitive) {
+ if (strcmp("svg:feGaussianBlur", primitive->name()) == 0) {
+ sp_repr_unparent(primitive);
+ break;
+ }
+ primitive = primitive->next();
+ }
+
+ // If there are no more primitives left in this filter, discard it.
+ if (repr->childCount() == 0) {
+ remove_filter(item, false);
+ }
+ }
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/filter-chemistry.h b/src/filter-chemistry.h
index 22ae9aecd..b727536ad 100644
--- a/src/filter-chemistry.h
+++ b/src/filter-chemistry.h
@@ -7,8 +7,9 @@
* Authors:
* Hugo Rodrigues
* bulia byak
+ * Niko Kiirala
*
- * Copyright (C) 2006 authors
+ * Copyright (C) 2006,2007 authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -18,7 +19,9 @@
SPFilter *new_filter_gaussian_blur (SPDocument *document, gdouble stdDeviation, double expansion, double expansionX, double expansionY, double width, double height);
SPFilter *new_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble stdDeviation);
+SPFilter *modify_filter_gaussian_blur_from_item (SPDocument *document, SPItem *item, gdouble stdDeviation);
void remove_filter (SPObject *item, bool recursive);
+void remove_filter_gaussian_blur (SPObject *item);
#endif
diff --git a/src/sp-feblend.cpp b/src/sp-feblend.cpp
index bedbf4f61..1c560e81b 100644
--- a/src/sp-feblend.cpp
+++ b/src/sp-feblend.cpp
@@ -187,8 +187,9 @@ sp_feBlend_set(SPObject *object, unsigned int key, gchar const *value)
static void
sp_feBlend_update(SPObject *object, SPCtx *ctx, guint flags)
{
- if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG)) {
+ if (flags & SP_OBJECT_MODIFIED_FLAG) {
sp_object_read_attr(object, "mode");
+ sp_object_read_attr(object, "in2");
}
if (((SPObjectClass *) feBlend_parent_class)->update) {
diff --git a/src/sp-feoffset.cpp b/src/sp-feoffset.cpp
index 298d3e495..b4a50679e 100644
--- a/src/sp-feoffset.cpp
+++ b/src/sp-feoffset.cpp
@@ -154,11 +154,9 @@ sp_feOffset_set(SPObject *object, unsigned int key, gchar const *value)
static void
sp_feOffset_update(SPObject *object, SPCtx *ctx, guint flags)
{
- if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
- SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
-
- /* do something to trigger redisplay, updates? */
-
+ if (flags & SP_OBJECT_MODIFIED_FLAG) {
+ sp_object_read_attr(object, "dx");
+ sp_object_read_attr(object, "dy");
}
if (((SPObjectClass *) feOffset_parent_class)->update) {
diff --git a/src/sp-filter-primitive.cpp b/src/sp-filter-primitive.cpp
index cd8c53c65..e8b7593f0 100644
--- a/src/sp-filter-primitive.cpp
+++ b/src/sp-filter-primitive.cpp
@@ -99,9 +99,6 @@ sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML:
sp_object_read_attr(object, "in");
sp_object_read_attr(object, "result");
-
- if (object->parent)
- add_primitive((SPFilter*)object->parent, (SPFilterPrimitive*)object);
}
/**
@@ -164,10 +161,9 @@ sp_filter_primitive_update(SPObject *object, SPCtx *ctx, guint flags)
{
//SPFilterPrimitive *filter_primitive = SP_FILTER_PRIMITIVE(object);
- if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
- SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
-
- /* do something to trigger redisplay, updates? */
+ if (flags & SP_OBJECT_MODIFIED_FLAG) {
+ sp_object_read_attr(object, "in");
+ sp_object_read_attr(object, "result");
}
if (((SPObjectClass *) filter_primitive_parent_class)->update) {
diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp
index 2b1b94b1f..11aa30e0b 100644
--- a/src/sp-filter.cpp
+++ b/src/sp-filter.cpp
@@ -107,11 +107,6 @@ sp_filter_init(SPFilter *filter)
filter->primitiveUnits = SP_FILTER_UNITS_OBJECTBOUNDINGBOX;
filter->filterUnits_set = FALSE;
filter->primitiveUnits_set = FALSE;
- filter->_primitive_count=0;
-
- filter->_primitive_table_size = 1;
- filter->_primitives = new SPFilterPrimitive*[1];
- filter->_primitives[0] = NULL;
filter->_renderer = NULL;
@@ -375,43 +370,18 @@ filter_ref_modified(SPObject *href, guint flags, SPFilter *filter)
SP_OBJECT(filter)->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
-
-void _enlarge_primitive_table(SPFilter * filter) {
- SPFilterPrimitive **new_tbl = new SPFilterPrimitive*[filter->_primitive_table_size * 2];
- for (int i = 0 ; i < filter->_primitive_count ; i++) {
- new_tbl[i] = filter->_primitives[i];
- }
- filter->_primitive_table_size *= 2;
- for (int i = filter->_primitive_count ; i < filter->_primitive_table_size ; i++) {
- new_tbl[i] = NULL;
- }
- delete[] filter->_primitives;
- filter->_primitives = new_tbl;
-}
-
-SPFilterPrimitive *add_primitive(SPFilter *filter, SPFilterPrimitive *primitive)
-{
- if (filter->_primitive_count >= filter->_primitive_table_size) {
- _enlarge_primitive_table(filter);
- }
- filter->_primitives[filter->_primitive_count] = primitive;
- filter->_primitive_count++;
- return primitive;
-}
-
/**
* Callback for child_added event.
*/
static void
sp_filter_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
-{/*
- SPFilter *f = SP_FILTER(object);
+{
+ //SPFilter *f = SP_FILTER(object);
if (((SPObjectClass *) filter_parent_class)->child_added)
(* ((SPObjectClass *) filter_parent_class)->child_added)(object, child, ref);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
- */
}
/**
@@ -419,17 +389,13 @@ sp_filter_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XM
*/
static void
sp_filter_remove_child(SPObject *object, Inkscape::XML::Node *child)
-{/*
- SPFilter *f = SP_FILTER(object);
+{
+// SPFilter *f = SP_FILTER(object);
if (((SPObjectClass *) filter_parent_class)->remove_child)
(* ((SPObjectClass *) filter_parent_class)->remove_child)(object, child);
- SPObject *ochild;
-
-
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
- */
}
void sp_filter_build_renderer(SPFilter *sp_filter, NR::Filter *nr_filter)
@@ -445,20 +411,31 @@ void sp_filter_build_renderer(SPFilter *sp_filter, NR::Filter *nr_filter)
nr_filter->set_height(sp_filter->height);
nr_filter->clear_primitives();
- for (int i = 0 ; i < sp_filter->_primitive_count ; i++) {
- SPFilterPrimitive *primitive = sp_filter->_primitives[i];
- g_assert(primitive != NULL);
- if (((SPFilterPrimitiveClass*) G_OBJECT_GET_CLASS(primitive))->build_renderer) {
- ((SPFilterPrimitiveClass *) G_OBJECT_GET_CLASS(primitive))->build_renderer(primitive, nr_filter);
- } else {
- g_warning("Cannot build filter renderer: missing builder");
+ SPObject *primitive_obj = sp_filter->children;
+ while (primitive_obj) {
+ if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) {
+ SPFilterPrimitive *primitive = SP_FILTER_PRIMITIVE(primitive_obj);
+ g_assert(primitive != NULL);
+ if (((SPFilterPrimitiveClass*) G_OBJECT_GET_CLASS(primitive))->build_renderer) {
+ ((SPFilterPrimitiveClass *) G_OBJECT_GET_CLASS(primitive))->build_renderer(primitive, nr_filter);
+ } else {
+ g_warning("Cannot build filter renderer: missing builder");
+ }
}
+ primitive_obj = primitive_obj->next;
}
}
int sp_filter_primitive_count(SPFilter *filter) {
g_assert(filter != NULL);
- return filter->_primitive_count;
+ int count = 0;
+
+ SPObject *primitive_obj = filter->children;
+ while (primitive_obj) {
+ if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) count++;
+ primitive_obj = primitive_obj->next;
+ }
+ return count;
}
int sp_filter_get_image_name(SPFilter *filter, gchar const *name) {
diff --git a/src/sp-filter.h b/src/sp-filter.h
index 55e3eaa0a..c6edc6c65 100644
--- a/src/sp-filter.h
+++ b/src/sp-filter.h
@@ -57,9 +57,6 @@ struct SPFilter : public SPObject {
/** HREF attribute */
SPFilterReference *href;
- int _primitive_count;
- int _primitive_table_size;
- SPFilterPrimitive ** _primitives;
NR::Filter *_renderer;
std::map<gchar *, int, ltstr> _image_name;
diff --git a/src/sp-gaussian-blur.cpp b/src/sp-gaussian-blur.cpp
index bc65574ca..8b7578fe8 100644
--- a/src/sp-gaussian-blur.cpp
+++ b/src/sp-gaussian-blur.cpp
@@ -142,7 +142,7 @@ sp_gaussianBlur_set(SPObject *object, unsigned int key, gchar const *value)
static void
sp_gaussianBlur_update(SPObject *object, SPCtx *ctx, guint flags)
{
- if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG)) {
+ if (flags & SP_OBJECT_MODIFIED_FLAG) {
sp_object_read_attr(object, "stdDeviation");
}