filter-chemistry.cpp revision 07b7f1aaaf1087716e784a50cf574a059f7018d3
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/*
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Various utility methods for filters
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Authors:
506aa7c68b127eefb0197e329af7e9abcc3ebc98Garrett D'Amore * Hugo Rodrigues
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore * bulia byak
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Niko Kiirala
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Jon A. Cruz <jon@joncruz.org>
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Abhishek Sharma
18c2aff776a775d34a4c9893a4c72e0434d68e36artem *
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Copyright (C) 2006-2008 authors
00687e57f8c568d4f8fb446b6530a2942842292fartem *
00687e57f8c568d4f8fb446b6530a2942842292fartem * Released under GNU GPL, read the file 'COPYING' for more information
00687e57f8c568d4f8fb446b6530a2942842292fartem */
00687e57f8c568d4f8fb446b6530a2942842292fartem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "style.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "document-private.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "desktop-style.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "filter-chemistry.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "filter-enums.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "filters/blend.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "sp-filter.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "sp-filter-reference.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "sp-gaussian-blur.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "svg/css-ostringstream.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "libnr/nr-matrix-fns.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem#include "xml/repr.h"
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/**
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Count how many times the filter is used by the styles of o and its
7b840e52d558c34b70cbcde044d8d79852d169d2phitran * descendants
a9da3307db733eb1739ba859952610bba3d894abnp */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic guint count_filter_hrefs(SPObject *o, SPFilter *filter)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!o)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return 1;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem guint i = 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPStyle *style = o->style;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (style
18c2aff776a775d34a4c9893a4c72e0434d68e36artem && style->filter.set
18c2aff776a775d34a4c9893a4c72e0434d68e36artem && style->getFilter() == filter)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem i ++;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem for ( SPObject *child = o->firstChild(); child; child = child->getNext() ) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem i += count_filter_hrefs(child, filter);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return i;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/**
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Sets a suitable filter effects area according to given blur radius,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * expansion and object size.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemstatic void set_filter_area(Inkscape::XML::Node *repr, gdouble radius,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double expansion, double expansionX,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double expansionY, double width, double height)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // TODO: make this more generic, now assumed, that only the blur
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // being added can affect the required filter area
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double rx = radius * (expansionY != 0 ? (expansion / expansionY) : 1);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double ry = radius * (expansionX != 0 ? (expansion / expansionX) : 1);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (width != 0 && height != 0 && (2.4 * rx > width * 0.1 || 2.4 * ry > height * 0.1)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // If not within the default 10% margin (see
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion), specify margins
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // The 2.4 is an empirical coefficient: at that distance the cutoff is practically invisible
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // (the opacity at 2.4*radius is about 3e-3)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double xmargin = 2.4 * (rx) / width;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double ymargin = 2.4 * (ry) / height;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // TODO: set it in UserSpaceOnUse instead?
18c2aff776a775d34a4c9893a4c72e0434d68e36artem sp_repr_set_svg_double(repr, "x", -xmargin);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem sp_repr_set_svg_double(repr, "width", 1 + 2 * xmargin);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem sp_repr_set_svg_double(repr, "y", -ymargin);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem sp_repr_set_svg_double(repr, "height", 1 + 2 * ymargin);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemSPFilter *new_filter(SPDocument *document)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_return_val_if_fail(document != NULL, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
00687e57f8c568d4f8fb446b6530a2942842292fartem SPDefs *defs = document->getDefs();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Document *xml_doc = document->getReprDoc();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // create a new filter
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *repr;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr = xml_doc->createElement("svg:filter");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Append the new filter node to defs
18c2aff776a775d34a4c9893a4c72e0434d68e36artem defs->appendChild(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::GC::release(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // get corresponding object
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPFilter *f = SP_FILTER( document->getObjectByRepr(repr) );
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(f != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(SP_IS_FILTER(f));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return f;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artemSPFilterPrimitive *
18c2aff776a775d34a4c9893a4c72e0434d68e36artemfilter_add_primitive(SPFilter *filter, const Inkscape::Filters::FilterPrimitiveType type)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Document *xml_doc = filter->document->getReprDoc();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //create filter primitive node
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *repr;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr = xml_doc->createElement(FPConverter.get_key(type).c_str());
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // set default values
18c2aff776a775d34a4c9893a4c72e0434d68e36artem switch(type) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_BLEND:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr->setAttribute("blend", "normal");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_COLORMATRIX:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_COMPONENTTRANSFER:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_COMPOSITE:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
3f7d54a6b84904c8f4d8daa4c7b577bede7df8b9Garrett D'Amore case Inkscape::Filters::NR_FILTER_CONVOLVEMATRIX:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr->setAttribute("order", "3 3");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr->setAttribute("kernelMatrix", "0 0 0 0 0 0 0 0 0");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_DIFFUSELIGHTING:
7b840e52d558c34b70cbcde044d8d79852d169d2phitran break;
d2ec54f7875f7e05edd56195adbeb593c947763fphitran case Inkscape::Filters::NR_FILTER_DISPLACEMENTMAP:
d2ec54f7875f7e05edd56195adbeb593c947763fphitran break;
b453864f3587ccc3324d7a3b0438a1e542dcfde7Lin Guo - Sun Microsystems case Inkscape::Filters::NR_FILTER_FLOOD:
17c1f1d29d41a12dc893091f0bf870753774dd1aLin Guo - Sun Microsystems break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_GAUSSIANBLUR:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr->setAttribute("stdDeviation", "1");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_IMAGE:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_MERGE:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_MORPHOLOGY:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_OFFSET:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr->setAttribute("dx", "0");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr->setAttribute("dy", "0");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_SPECULARLIGHTING:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_TILE:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem case Inkscape::Filters::NR_FILTER_TURBULENCE:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem default:
18c2aff776a775d34a4c9893a4c72e0434d68e36artem break;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //set primitive as child of filter node
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // XML tree being used directly while/where it shouldn't be...
00687e57f8c568d4f8fb446b6530a2942842292fartem filter->appendChild(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::GC::release(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // get corresponding object
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPFilterPrimitive *prim = SP_FILTER_PRIMITIVE( filter->document->getObjectByRepr(repr) );
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(prim != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(SP_IS_FILTER_PRIMITIVE(prim));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return prim;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/**
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Creates a filter with blur primitive of specified radius for an item with the given matrix expansion, width and height
18c2aff776a775d34a4c9893a4c72e0434d68e36artem */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemSPFilter *
18c2aff776a775d34a4c9893a4c72e0434d68e36artemnew_filter_gaussian_blur (SPDocument *document, gdouble radius, double expansion, double expansionX, double expansionY, double width, double height)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_return_val_if_fail(document != NULL, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPDefs *defs = document->getDefs();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Document *xml_doc = document->getReprDoc();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // create a new filter
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *repr;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr = xml_doc->createElement("svg:filter");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //repr->setAttribute("inkscape:collect", "always");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem set_filter_area(repr, radius, expansion, expansionX, expansionY,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem width, height);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //create feGaussianBlur node
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *b_repr;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem b_repr = xml_doc->createElement("svg:feGaussianBlur");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //b_repr->setAttribute("inkscape:collect", "always");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double stdDeviation = radius;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (expansion != 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem stdDeviation /= expansion;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //set stdDeviation attribute
18c2aff776a775d34a4c9893a4c72e0434d68e36artem sp_repr_set_svg_double(b_repr, "stdDeviation", stdDeviation);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //set feGaussianBlur as child of filter node
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr->appendChild(b_repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::GC::release(b_repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Append the new filter node to defs
18c2aff776a775d34a4c9893a4c72e0434d68e36artem defs->appendChild(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::GC::release(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // get corresponding object
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPFilter *f = SP_FILTER( document->getObjectByRepr(repr) );
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPGaussianBlur *b = SP_GAUSSIANBLUR( document->getObjectByRepr(b_repr) );
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(f != NULL);
00687e57f8c568d4f8fb446b6530a2942842292fartem g_assert(SP_IS_FILTER(f));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(b != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(SP_IS_GAUSSIANBLUR(b));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return f;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/**
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Creates a simple filter with a blend primitive and a blur primitive of specified radius for
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * an item with the given matrix expansion, width and height
18c2aff776a775d34a4c9893a4c72e0434d68e36artem */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemSPFilter *
18c2aff776a775d34a4c9893a4c72e0434d68e36artemnew_filter_blend_gaussian_blur (SPDocument *document, const char *blendmode, gdouble radius, double expansion,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double expansionX, double expansionY, double width, double height)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_return_val_if_fail(document != NULL, NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPDefs *defs = document->getDefs();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Document *xml_doc = document->getReprDoc();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // create a new filter
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *repr;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr = xml_doc->createElement("svg:filter");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem repr->setAttribute("inkscape:collect", "always");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Append the new filter node to defs
18c2aff776a775d34a4c9893a4c72e0434d68e36artem defs->appendChild(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::GC::release(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // get corresponding object
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPFilter *f = SP_FILTER( document->getObjectByRepr(repr) );
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Gaussian blur primitive
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if(radius != 0) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem set_filter_area(repr, radius, expansion, expansionX, expansionY, width, height);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //create feGaussianBlur node
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *b_repr;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem b_repr = xml_doc->createElement("svg:feGaussianBlur");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem b_repr->setAttribute("inkscape:collect", "always");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double stdDeviation = radius;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (expansion != 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem stdDeviation /= expansion;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //set stdDeviation attribute
18c2aff776a775d34a4c9893a4c72e0434d68e36artem sp_repr_set_svg_double(b_repr, "stdDeviation", stdDeviation);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //set feGaussianBlur as child of filter node
00687e57f8c568d4f8fb446b6530a2942842292fartem repr->appendChild(b_repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::GC::release(b_repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPGaussianBlur *b = SP_GAUSSIANBLUR( document->getObjectByRepr(b_repr) );
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(b != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(SP_IS_GAUSSIANBLUR(b));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Blend primitive
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if(strcmp(blendmode, "normal")) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *b_repr;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem b_repr = xml_doc->createElement("svg:feBlend");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem b_repr->setAttribute("inkscape:collect", "always");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem b_repr->setAttribute("mode", blendmode);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem b_repr->setAttribute("in2", "BackgroundImage");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems // set feBlend as child of filter node
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems repr->appendChild(b_repr);
00687e57f8c568d4f8fb446b6530a2942842292fartem Inkscape::GC::release(b_repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems // Enable background image buffer for document
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems Inkscape::XML::Node *root = b_repr->root();
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems if (!root->attribute("enable-background")) {
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems root->setAttribute("enable-background", "new");
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems }
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems SPFeBlend *b = SP_FEBLEND(document->getObjectByRepr(b_repr));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(b != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(SP_IS_FEBLEND(b));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(f != NULL);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem g_assert(SP_IS_FILTER(f));
112cd14a18db3bd3fac4ff92c4117b51ddd339abqz
112cd14a18db3bd3fac4ff92c4117b51ddd339abqz return f;
112cd14a18db3bd3fac4ff92c4117b51ddd339abqz}
112cd14a18db3bd3fac4ff92c4117b51ddd339abqz
112cd14a18db3bd3fac4ff92c4117b51ddd339abqz/**
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Creates a simple filter for the given item with blend and blur primitives, using the
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * specified mode and radius, respectively
18c2aff776a775d34a4c9893a4c72e0434d68e36artem */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemSPFilter *
18c2aff776a775d34a4c9893a4c72e0434d68e36artemnew_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mode, gdouble radius)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems Geom::OptRect const r = item->getBboxDesktop(SPItem::GEOMETRIC_BBOX);
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems double width;
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems double height;
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems if (r) {
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems width = r->dimensions()[Geom::X];
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems height= r->dimensions()[Geom::Y];
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems } else {
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems width = height = 0;
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems }
8b80e8cb6855118d46f605e91b5ed4ce83417395Lin Guo - Sun Microsystems
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Geom::Affine i2d (item->i2d_affine () );
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return (new_filter_blend_gaussian_blur (document, mode, radius, i2d.descrim(), i2d.expansionX(), i2d.expansionY(), width, height));
18c2aff776a775d34a4c9893a4c72e0434d68e36artem}
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/**
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Modifies the gaussian blur applied to the item.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * If no filters are applied to given item, creates a new blur filter.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * If a filter is applied and it contains a blur, modify that blur.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * If the filter doesn't contain blur, a blur is added to the filter.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * Should there be more references to modified filter, that filter is
18c2aff776a775d34a4c9893a4c72e0434d68e36artem * duplicated, so that other elements referring that filter are not modified.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem */
18c2aff776a775d34a4c9893a4c72e0434d68e36artem/* TODO: this should be made more generic, not just for blurs */
18c2aff776a775d34a4c9893a4c72e0434d68e36artemSPFilter *modify_filter_gaussian_blur_from_item(SPDocument *document, SPItem *item,
18c2aff776a775d34a4c9893a4c72e0434d68e36artem gdouble radius)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem{
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (!item->style || !item->style->filter.set) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return new_filter_simple_from_item(document, item, "normal", radius);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPFilter *filter = SP_FILTER(item->style->getFilter());
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Document *xml_doc = document->getReprDoc();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
00687e57f8c568d4f8fb446b6530a2942842292fartem // If there are more users for this filter, duplicate it
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (filter->hrefcount > count_filter_hrefs(item, filter)) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *repr = item->style->getFilter()->getRepr()->duplicate(xml_doc);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem SPDefs *defs = document->getDefs();
00687e57f8c568d4f8fb446b6530a2942842292fartem defs->appendChild(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem filter = SP_FILTER( document->getObjectByRepr(repr) );
00687e57f8c568d4f8fb446b6530a2942842292fartem Inkscape::GC::release(repr);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Determine the required standard deviation value
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Geom::Affine i2d (item->i2d_affine ());
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double expansion = i2d.descrim();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double stdDeviation = radius;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (expansion != 0)
18c2aff776a775d34a4c9893a4c72e0434d68e36artem stdDeviation /= expansion;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Get the object size
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Geom::OptRect const r = item->getBboxDesktop(SPItem::GEOMETRIC_BBOX);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double width;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem double height;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (r) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem width = r->dimensions()[Geom::X];
00687e57f8c568d4f8fb446b6530a2942842292fartem height= r->dimensions()[Geom::Y];
18c2aff776a775d34a4c9893a4c72e0434d68e36artem } else {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem width = height = 0;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Set the filter effects area
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *repr = item->style->getFilter()->getRepr();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem set_filter_area(repr, radius, expansion, i2d.expansionX(),
18c2aff776a775d34a4c9893a4c72e0434d68e36artem i2d.expansionY(), width, height);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // Search for gaussian blur primitives. If found, set the stdDeviation
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // of the first one and return.
18c2aff776a775d34a4c9893a4c72e0434d68e36artem Inkscape::XML::Node *primitive = repr->firstChild();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem while (primitive) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem if (strcmp("svg:feGaussianBlur", primitive->name()) == 0) {
18c2aff776a775d34a4c9893a4c72e0434d68e36artem sp_repr_set_svg_double(primitive, "stdDeviation",
18c2aff776a775d34a4c9893a4c72e0434d68e36artem stdDeviation);
18c2aff776a775d34a4c9893a4c72e0434d68e36artem return filter;
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem primitive = primitive->next();
18c2aff776a775d34a4c9893a4c72e0434d68e36artem }
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem // If there were no gaussian blur primitives, create a new one
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //create feGaussianBlur node
076d97abc78bcba2f2216859fe2c6913cc7aff32Phi Tran Inkscape::XML::Node *b_repr;
076d97abc78bcba2f2216859fe2c6913cc7aff32Phi Tran b_repr = xml_doc->createElement("svg:feGaussianBlur");
7b840e52d558c34b70cbcde044d8d79852d169d2phitran //b_repr->setAttribute("inkscape:collect", "always");
18c2aff776a775d34a4c9893a4c72e0434d68e36artem
18c2aff776a775d34a4c9893a4c72e0434d68e36artem //set stdDeviation attribute
18c2aff776a775d34a4c9893a4c72e0434d68e36artem sp_repr_set_svg_double(b_repr, "stdDeviation", stdDeviation);
42a7bded1b1244af097afdc88654381a3d3879f9jacobs
42a7bded1b1244af097afdc88654381a3d3879f9jacobs //set feGaussianBlur as child of filter node
42a7bded1b1244af097afdc88654381a3d3879f9jacobs filter->getRepr()->appendChild(b_repr);
42a7bded1b1244af097afdc88654381a3d3879f9jacobs Inkscape::GC::release(b_repr);
42a7bded1b1244af097afdc88654381a3d3879f9jacobs
42a7bded1b1244af097afdc88654381a3d3879f9jacobs return filter;
42a7bded1b1244af097afdc88654381a3d3879f9jacobs}
42a7bded1b1244af097afdc88654381a3d3879f9jacobs
42a7bded1b1244af097afdc88654381a3d3879f9jacobsvoid remove_filter (SPObject *item, bool recursive)
42a7bded1b1244af097afdc88654381a3d3879f9jacobs{
42a7bded1b1244af097afdc88654381a3d3879f9jacobs SPCSSAttr *css = sp_repr_css_attr_new();
42a7bded1b1244af097afdc88654381a3d3879f9jacobs sp_repr_css_unset_property(css, "filter");
42a7bded1b1244af097afdc88654381a3d3879f9jacobs if (recursive) {
42a7bded1b1244af097afdc88654381a3d3879f9jacobs sp_repr_css_change_recursive(item->getRepr(), css, "style");
42a7bded1b1244af097afdc88654381a3d3879f9jacobs } else {
42a7bded1b1244af097afdc88654381a3d3879f9jacobs sp_repr_css_change(item->getRepr(), css, "style");
42a7bded1b1244af097afdc88654381a3d3879f9jacobs }
42a7bded1b1244af097afdc88654381a3d3879f9jacobs sp_repr_css_attr_unref(css);
42a7bded1b1244af097afdc88654381a3d3879f9jacobs}
42a7bded1b1244af097afdc88654381a3d3879f9jacobs
42a7bded1b1244af097afdc88654381a3d3879f9jacobs/**
* 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->getFilter()) {
// Search for the first blur primitive and remove it. (if found)
Inkscape::XML::Node *repr = item->style->getFilter()->getRepr();
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);
}
}
}
bool filter_is_single_gaussian_blur(SPFilter *filter)
{
return (filter->firstChild() &&
(filter->firstChild() == filter->lastChild()) &&
SP_IS_GAUSSIANBLUR(filter->firstChild()));
}
double get_single_gaussian_blur_radius(SPFilter *filter)
{
if (filter->firstChild() &&
(filter->firstChild() == filter->lastChild()) &&
SP_IS_GAUSSIANBLUR(filter->firstChild())) {
SPGaussianBlur *gb = SP_GAUSSIANBLUR(filter->firstChild());
double x = gb->stdDeviation.getNumber();
double y = gb->stdDeviation.getOptNumber();
if (x > 0 && y > 0) {
return MAX(x, y);
}
return x;
}
return 0.0;
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :