diff options
| author | Tomasz Boczkowski <penginsbacon@gmail.com> | 2015-04-25 12:59:51 +0000 |
|---|---|---|
| committer | Tomasz Boczkowski <penginsbacon@gmail.com> | 2015-04-25 12:59:51 +0000 |
| commit | 3eb2b94eded9236bea634cd28eae13a3645a8cfb (patch) | |
| tree | f89f5fc023b87e5127ed57a1fc22c6d21e88fbd0 /src/sp-pattern.cpp | |
| parent | merged SPColorSlider c++-sification from svgpaints branch (diff) | |
| parent | SPPattern c++-sification: class fields are private (diff) | |
| download | inkscape-3eb2b94eded9236bea634cd28eae13a3645a8cfb.tar.gz inkscape-3eb2b94eded9236bea634cd28eae13a3645a8cfb.zip | |
merged SPPattern c++-sification from svgpaints branch
(bzr r14059.1.2)
Diffstat (limited to 'src/sp-pattern.cpp')
| -rw-r--r-- | src/sp-pattern.cpp | 242 |
1 files changed, 105 insertions, 137 deletions
diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index 987a86fe4..df8086ae7 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -20,8 +20,8 @@ #include <string> #include <glibmm.h> #include <2geom/transforms.h> +#include <sigc++/functors/mem_fun.h> -#include "macros.h" #include "svg/svg.h" #include "display/cairo-utils.h" #include "display/drawing-context.h" @@ -34,31 +34,21 @@ #include "style.h" #include "sp-pattern.h" #include "xml/repr.h" -#include "display/grayscale.h" -#include <sigc++/functors/ptr_fun.h> -#include <sigc++/adaptors/bind.h> - -/* - * Pattern - */ -static void pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat); -static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern); +#include "sp-factory.h" SPPattern::SPPattern() : SPPaintServer(), SPViewBox() { - this->href = NULL; - this->ref = new SPPatternReference(this); - this->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(pattern_ref_changed), this)); + this->ref->changedSignal().connect(sigc::mem_fun(this, &SPPattern::_on_ref_changed)); - this->patternUnits = SP_PATTERN_UNITS_OBJECTBOUNDINGBOX; - this->patternUnits_set = FALSE; + this->patternUnits = UNITS_OBJECTBOUNDINGBOX; + this->patternUnits_set = false; - this->patternContentUnits = SP_PATTERN_UNITS_USERSPACEONUSE; - this->patternContentUnits_set = FALSE; + this->patternContentUnits = UNITS_USERSPACEONUSE; + this->patternContentUnits_set = false; this->patternTransform = Geom::identity(); - this->patternTransform_set = FALSE; + this->patternTransform_set = false; this->x.unset(); this->y.unset(); @@ -108,14 +98,14 @@ void SPPattern::set(unsigned int key, const gchar* value) { case SP_ATTR_PATTERNUNITS: if (value) { if (!strcmp (value, "userSpaceOnUse")) { - this->patternUnits = SP_PATTERN_UNITS_USERSPACEONUSE; + this->patternUnits = UNITS_USERSPACEONUSE; } else { - this->patternUnits = SP_PATTERN_UNITS_OBJECTBOUNDINGBOX; + this->patternUnits = UNITS_OBJECTBOUNDINGBOX; } - this->patternUnits_set = TRUE; + this->patternUnits_set = true; } else { - this->patternUnits_set = FALSE; + this->patternUnits_set = false; } this->requestModified(SP_OBJECT_MODIFIED_FLAG); @@ -124,14 +114,14 @@ void SPPattern::set(unsigned int key, const gchar* value) { case SP_ATTR_PATTERNCONTENTUNITS: if (value) { if (!strcmp (value, "userSpaceOnUse")) { - this->patternContentUnits = SP_PATTERN_UNITS_USERSPACEONUSE; + this->patternContentUnits = UNITS_USERSPACEONUSE; } else { - this->patternContentUnits = SP_PATTERN_UNITS_OBJECTBOUNDINGBOX; + this->patternContentUnits = UNITS_OBJECTBOUNDINGBOX; } - this->patternContentUnits_set = TRUE; + this->patternContentUnits_set = true; } else { - this->patternContentUnits_set = FALSE; + this->patternContentUnits_set = false; } this->requestModified(SP_OBJECT_MODIFIED_FLAG); @@ -142,10 +132,10 @@ void SPPattern::set(unsigned int key, const gchar* value) { if (value && sp_svg_transform_read (value, &t)) { this->patternTransform = t; - this->patternTransform_set = TRUE; + this->patternTransform_set = true; } else { this->patternTransform = Geom::identity(); - this->patternTransform_set = FALSE; + this->patternTransform_set = false; } this->requestModified(SP_OBJECT_MODIFIED_FLAG); @@ -182,15 +172,14 @@ void SPPattern::set(unsigned int key, const gchar* value) { break; case SP_ATTR_XLINK_HREF: - if ( value && this->href && ( strcmp(value, this->href) == 0 ) ) { + if ( value && this->href == value ) { /* Href unchanged, do nothing. */ } else { - g_free(this->href); - this->href = NULL; + this->href.clear(); if (value) { // First, set the href field; it's only used in the "unchanged" check above. - this->href = g_strdup(value); + this->href = value; // Now do the attaching, which emits the changed signal. if (value) { try { @@ -217,37 +206,34 @@ void SPPattern::set(unsigned int key, const gchar* value) { /* fixme: We need ::order_changed handler too (Lauris) */ -static GSList *pattern_getchildren(SPPattern *pat) -{ - GSList *l = NULL; - +void SPPattern::_get_children(std::list<SPObject*>& l) { + SPPattern *pat = this; for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->firstChild()) { // find the first one with children for (SPObject *child = pat->firstChild() ; child ; child = child->getNext() ) { - l = g_slist_prepend (l, child); + l.push_back(child); } break; // do not go further up the chain if children are found } } - - return l; } void SPPattern::update(SPCtx* ctx, unsigned int flags) { - if (flags & SP_OBJECT_MODIFIED_FLAG) { + typedef std::list<SPObject*>::iterator SPObjectIterator; + + if (flags & SP_OBJECT_MODIFIED_FLAG) { flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = pattern_getchildren (this); - l = g_slist_reverse (l); + std::list<SPObject*> l; + _get_children(l); - while (l) { - SPObject *child = SP_OBJECT (l->data); + for (SPObjectIterator it = l.begin(); it != l.end(); it++) { + SPObject *child = *it; sp_object_ref (child, NULL); - l = g_slist_remove (l, child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->updateDisplay(ctx, flags); @@ -258,20 +244,21 @@ void SPPattern::update(SPCtx* ctx, unsigned int flags) { } void SPPattern::modified(unsigned int flags) { + typedef std::list<SPObject*>::iterator SPObjectIterator; + if (flags & SP_OBJECT_MODIFIED_FLAG) { flags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } flags &= SP_OBJECT_MODIFIED_CASCADE; - GSList *l = pattern_getchildren (this); - l = g_slist_reverse (l); + std::list<SPObject*> l; + _get_children(l); - while (l) { - SPObject *child = SP_OBJECT (l->data); + for (SPObjectIterator it = l.begin(); it != l.end(); it++) { + SPObject *child = *it; sp_object_ref (child, NULL); - l = g_slist_remove (l, child); if (flags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(flags); @@ -281,40 +268,25 @@ void SPPattern::modified(unsigned int flags) { } } -/** -Gets called when the pattern is reattached to another <pattern> -*/ -static void -pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat) -{ +void SPPattern::_on_ref_changed(SPObject *old_ref, SPObject *ref) { if (old_ref) { - pat->modified_connection.disconnect(); + modified_connection.disconnect(); } if (SP_IS_PATTERN (ref)) { - pat->modified_connection = ref->connectModified(sigc::bind<2>(sigc::ptr_fun(&pattern_ref_modified), pat)); + modified_connection = ref->connectModified(sigc::mem_fun(this, &SPPattern::_on_ref_modified)); } - pattern_ref_modified (ref, 0, pat); + _on_ref_modified(ref, 0); } -/** -Gets called when the referenced <pattern> is changed -*/ -static void pattern_ref_modified (SPObject */*ref*/, guint /*flags*/, SPPattern *pattern) +void SPPattern::_on_ref_modified(SPObject */*ref*/, guint /*flags*/) { - if ( SP_IS_OBJECT(pattern) ) { - pattern->requestModified(SP_OBJECT_MODIFIED_FLAG); - } + requestModified(SP_OBJECT_MODIFIED_FLAG); // Conditional to avoid causing infinite loop if there's a cycle in the href chain. } - -/** -Count how many times pat is used by the styles of o and its descendants -*/ -static guint -count_pattern_hrefs(SPObject *o, SPPattern *pat) +guint SPPattern::_count_hrefs(SPObject *o) const { if (!o) return 1; @@ -325,36 +297,33 @@ count_pattern_hrefs(SPObject *o, SPPattern *pat) if (style && style->fill.isPaintserver() && SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style)) - && SP_PATTERN(SP_STYLE_FILL_SERVER(style)) == pat) + && SP_PATTERN(SP_STYLE_FILL_SERVER(style)) == this) { i ++; } if (style && style->stroke.isPaintserver() && SP_IS_PATTERN(SP_STYLE_STROKE_SERVER(style)) - && SP_PATTERN(SP_STYLE_STROKE_SERVER(style)) == pat) + && SP_PATTERN(SP_STYLE_STROKE_SERVER(style)) == this) { i ++; } for ( SPObject *child = o->firstChild(); child != NULL; child = child->next ) { - i += count_pattern_hrefs(child, pat); + i += _count_hrefs(child); } return i; } -SPPattern *pattern_chain(SPPattern *pattern) -{ - SPDocument *document = pattern->document; - Inkscape::XML::Document *xml_doc = document->getReprDoc(); +SPPattern *SPPattern::_chain() const { + Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:pattern"); repr->setAttribute("inkscape:collect", "always"); - gchar *parent_ref = g_strconcat("#", pattern->getRepr()->attribute("id"), NULL); + Glib::ustring parent_ref = Glib::ustring::compose("#%1", getRepr()->attribute("id")); repr->setAttribute("xlink:href", parent_ref); - g_free (parent_ref); defsrepr->addChild(repr, NULL); const gchar *child_id = repr->attribute("id"); @@ -364,42 +333,42 @@ SPPattern *pattern_chain(SPPattern *pattern) return SP_PATTERN (child); } -SPPattern * -sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *property) -{ - if (!pattern->href || pattern->hrefcount > count_pattern_hrefs(item, pattern)) { - pattern = pattern_chain (pattern); - gchar *href = g_strconcat("url(#", pattern->getRepr()->attribute("id"), ")", NULL); +SPPattern *SPPattern::clone_if_necessary(SPItem *item, const gchar *property) { + SPPattern *pattern = this; + if (pattern->href.empty() || pattern->hrefcount > _count_hrefs(item)) { + pattern = _chain(); + Glib::ustring href = Glib::ustring::compose("url(#%1)", pattern->getRepr()->attribute("id")); SPCSSAttr *css = sp_repr_css_attr_new (); - sp_repr_css_set_property (css, property, href); + sp_repr_css_set_property (css, property, href.c_str()); sp_repr_css_change_recursive(item->getRepr(), css, "style"); + } return pattern; } -void -sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set) -{ +void SPPattern::transform_multiply(Geom::Affine postmul, bool set) { // this formula is for a different interpretation of pattern transforms as described in (*) in sp-pattern.cpp // for it to work, we also need sp_object_read_attr( item, "transform"); //pattern->patternTransform = premul * item->transform * pattern->patternTransform * item->transform.inverse() * postmul; // otherwise the formula is much simpler if (set) { - pattern->patternTransform = postmul; + patternTransform = postmul; } else { - pattern->patternTransform = pattern_patternTransform(pattern) * postmul; + patternTransform = get_transform() * postmul; } - pattern->patternTransform_set = TRUE; + patternTransform_set = true; - gchar *c=sp_svg_transform_write(pattern->patternTransform); - pattern->getRepr()->setAttribute("patternTransform", c); - g_free(c); + Glib::ustring c=sp_svg_transform_write(patternTransform); + getRepr()->setAttribute("patternTransform", c); } -const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move) +const gchar *SPPattern::produce(const std::list<Inkscape::XML::Node*> &reprs, Geom::Rect bounds, + SPDocument *document, Geom::Affine transform, Geom::Affine move) { + typedef std::list<Inkscape::XML::Node*>::const_iterator NodePtrIterator; + Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); @@ -408,16 +377,15 @@ const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document sp_repr_set_svg_double(repr, "width", bounds.dimensions()[Geom::X]); sp_repr_set_svg_double(repr, "height", bounds.dimensions()[Geom::Y]); - gchar *t=sp_svg_transform_write(transform); + Glib::ustring t=sp_svg_transform_write(transform); repr->setAttribute("patternTransform", t); - g_free(t); defsrepr->appendChild(repr); const gchar *pat_id = repr->attribute("id"); SPObject *pat_object = document->getObjectById(pat_id); - for (GSList *i = reprs; i != NULL; i = i->next) { - Inkscape::XML::Node *node = (Inkscape::XML::Node *)(i->data); + for (NodePtrIterator i = reprs.begin(); i != reprs.end(); i++) { + Inkscape::XML::Node *node = *i; SPItem *copy = SP_ITEM(pat_object->appendChildRepr(node)); Geom::Affine dup_transform; @@ -432,14 +400,14 @@ const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document return pat_id; } -SPPattern *pattern_getroot(SPPattern *pat) +SPPattern *SPPattern::get_root() { - for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if ( pat_i->firstChild() ) { // find the first one with children return pat_i; } } - return pat; // document is broken, we can't get to root; but at least we can return pat which is supposedly a valid pattern + return this; // document is broken, we can't get to root; but at least we can return pat which is supposedly a valid pattern } @@ -447,73 +415,73 @@ SPPattern *pattern_getroot(SPPattern *pat) // Access functions that look up fields up the chain of referenced patterns and return the first one which is set // FIXME: all of them must use chase_hrefs the same as in SPGradient, to avoid lockup on circular refs -guint pattern_patternUnits (SPPattern const *pat) +SPPattern::PatternUnits SPPattern::get_pattern_units() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->patternUnits_set) return pat_i->patternUnits; } - return pat->patternUnits; + return patternUnits; } -guint pattern_patternContentUnits (SPPattern const *pat) +SPPattern::PatternUnits SPPattern::get_pattern_content_units() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->patternContentUnits_set) return pat_i->patternContentUnits; } - return pat->patternContentUnits; + return patternContentUnits; } -Geom::Affine const &pattern_patternTransform(SPPattern const *pat) +Geom::Affine const &SPPattern::get_transform() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->patternTransform_set) return pat_i->patternTransform; } - return pat->patternTransform; + return patternTransform; } -gdouble pattern_x (SPPattern const *pat) +gdouble SPPattern::get_x() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->x._set) return pat_i->x.computed; } return 0; } -gdouble pattern_y (SPPattern const *pat) +gdouble SPPattern::get_y() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->y._set) return pat_i->y.computed; } return 0; } -gdouble pattern_width (SPPattern const* pat) +gdouble SPPattern::get_width() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->width._set) return pat_i->width.computed; } return 0; } -gdouble pattern_height (SPPattern const *pat) +gdouble SPPattern::get_height() const { - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->height._set) return pat_i->height.computed; } return 0; } -Geom::OptRect pattern_viewBox (SPPattern const *pat) +Geom::OptRect SPPattern::get_viewbox() const { Geom::OptRect viewbox; - for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { + for (SPPattern const *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->viewBox_set) { viewbox = pat_i->viewBox; break; @@ -522,10 +490,10 @@ Geom::OptRect pattern_viewBox (SPPattern const *pat) return viewbox; } -static bool pattern_hasItemChildren (SPPattern const *pat) +bool SPPattern::_has_item_children() const { bool hasChildren = false; - for (SPObject const *child = pat->firstChild() ; child && !hasChildren ; child = child->getNext() ) { + for (SPObject const *child = firstChild() ; child && !hasChildren ; child = child->getNext() ) { if (SP_IS_ITEM(child)) { hasChildren = true; } @@ -535,8 +503,8 @@ static bool pattern_hasItemChildren (SPPattern const *pat) bool SPPattern::isValid() const { - double tile_width = pattern_width(this); - double tile_height = pattern_height(this); + double tile_width = get_width(); + double tile_height = get_height(); if (tile_width <= 0 || tile_height <= 0) return false; @@ -557,7 +525,7 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b for (SPPattern *pat_i = this; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { // find the first one with item children - if (pat_i && SP_IS_OBJECT(pat_i) && pattern_hasItemChildren(pat_i)) { + if (pat_i && SP_IS_OBJECT(pat_i) && pat_i->_has_item_children()) { shown = pat_i; break; // do not go further up the chain if children are found } @@ -591,11 +559,11 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b // * "x", "y", and "patternTransform" transform tile to user space after tile is generated. // These functions recursively search up the tree to find the values. - double tile_x = pattern_x(this); - double tile_y = pattern_y(this); - double tile_width = pattern_width(this); - double tile_height = pattern_height(this); - if ( bbox && (pattern_patternUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) ) { + double tile_x = get_x(); + double tile_y = get_y(); + double tile_width = get_width(); + double tile_height = get_height(); + if ( bbox && (get_pattern_units() == UNITS_OBJECTBOUNDINGBOX) ) { tile_x *= bbox->width(); tile_y *= bbox->height(); tile_width *= bbox->width(); @@ -607,7 +575,7 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b // Content to tile (pattern space) Geom::Affine content2ps; - Geom::OptRect effective_view_box = pattern_viewBox(this); + Geom::OptRect effective_view_box = get_viewbox(); if (effective_view_box) { // viewBox to pattern server (using SPViewBox) viewBox = *effective_view_box; @@ -617,14 +585,14 @@ cairo_pattern_t* SPPattern::pattern_new(cairo_t *base_ct, Geom::OptRect const &b } else { // Content to bbox - if (bbox && (pattern_patternContentUnits(this) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) ) { + if (bbox && (get_pattern_content_units() == UNITS_OBJECTBOUNDINGBOX) ) { content2ps = Geom::Affine(bbox->width(), 0.0, 0.0, bbox->height(), 0,0); } } // Tile (pattern space) to user. - Geom::Affine ps2user = Geom::Translate(tile_x,tile_y) * pattern_patternTransform(this); + Geom::Affine ps2user = Geom::Translate(tile_x,tile_y) * get_transform(); // Transform of object with pattern (includes screen scaling) |
