summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 885f1aa)
raw | patch | inline | side by side (parent: 885f1aa)
author | kiirala <kiirala@users.sourceforge.net> | |
Sat, 23 Jun 2007 15:35:28 +0000 (15:35 +0000) | ||
committer | kiirala <kiirala@users.sourceforge.net> | |
Sat, 23 Jun 2007 15:35:28 +0000 (15:35 +0000) |
diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp
index 9c7cbb35ffc59bdd4b5fb788177b7daad8a9ab30..95abdfa5bc6c04d4316b2e288d5d9a44399697c7 100644 (file)
--- a/src/desktop-style.cpp
+++ b/src/desktop-style.cpp
//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) {
index 4db82385afcaca5b140128d6e53ff90bffca1248..fbc9ab83fc432292aa2d5f39e87001ac64ef9e3c 100644 (file)
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
index 164a6594a71fe16c483f979921c2cd6be995603a..90a6e32f2ca4aede9b6bb2d7aa716ed8489f7f02 100644 (file)
--- a/src/filter-chemistry.cpp
+++ b/src/filter-chemistry.cpp
* 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
*/
#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 ();
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 22ae9aecd2c52cc53ab943d8e53344e0c16ecf64..b727536adaf645a81f34e4de513d9a619c748fd2 100644 (file)
--- a/src/filter-chemistry.h
+++ b/src/filter-chemistry.h
* 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
*/
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 bedbf4f610710da3f9d29048693d1544997d40e6..1c560e81bdc96c31a3b37599d31ba183f3dad624 100644 (file)
--- a/src/sp-feblend.cpp
+++ b/src/sp-feblend.cpp
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 298d3e495981cd25e8197d16b9d24d423dd3ceff..b4a50679ed18fcec7280c5df422c4ce3b35caca2 100644 (file)
--- a/src/sp-feoffset.cpp
+++ b/src/sp-feoffset.cpp
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) {
index cd8c53c653b88255356fe30329a8e7b12e4a9766..e8b7593f0a9e5e5ecb57eaaacafcd67968219ad5 100644 (file)
sp_object_read_attr(object, "in");
sp_object_read_attr(object, "result");
-
- if (object->parent)
- add_primitive((SPFilter*)object->parent, (SPFilterPrimitive*)object);
}
/**
{
//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 2b1b94b1fa9c32782fe0b978c2501cb3ea39be29..11aa30e0bc37d8d2bc74b70cd10b38d1ffa2b1e2 100644 (file)
--- a/src/sp-filter.cpp
+++ b/src/sp-filter.cpp
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;
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)
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 55e3eaa0ad5228a48ba78a7a38472bcda2d050e2..c6edc6c65caf8407033c91b8f86056e0aac619e5 100644 (file)
--- a/src/sp-filter.h
+++ b/src/sp-filter.h
/** HREF attribute */
SPFilterReference *href;
- int _primitive_count;
- int _primitive_table_size;
- SPFilterPrimitive ** _primitives;
NR::Filter *_renderer;
std::map<gchar *, int, ltstr> _image_name;
index bc65574ca6982dd9311b3294ce788e5755651e65..8b7578fe8f058b751e54715cb95c412725487624 100644 (file)
--- a/src/sp-gaussian-blur.cpp
+++ b/src/sp-gaussian-blur.cpp
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");
}