diff options
Diffstat (limited to 'src/object')
| -rw-r--r-- | src/object/sp-hatch.cpp | 70 | ||||
| -rw-r--r-- | src/object/sp-hatch.h | 10 | ||||
| -rw-r--r-- | src/object/sp-item.cpp | 32 | ||||
| -rw-r--r-- | src/object/sp-item.h | 17 |
4 files changed, 116 insertions, 13 deletions
diff --git a/src/object/sp-hatch.cpp b/src/object/sp-hatch.cpp index ae91b4dd2..3c5da9bd9 100644 --- a/src/object/sp-hatch.cpp +++ b/src/object/sp-hatch.cpp @@ -31,7 +31,9 @@ #include "display/drawing.h" #include "display/drawing-pattern.h" +#include "sp-defs.h" #include "sp-hatch-path.h" +#include "sp-item.h" #include "svg/svg.h" @@ -482,6 +484,74 @@ gdouble SPHatch::rotate() const return val; } +guint SPHatch::_countHrefs(SPObject *o) const +{ + if (!o) + return 1; + + guint i = 0; + + SPStyle *style = o->style; + if (style && style->fill.isPaintserver() && SP_IS_HATCH(SP_STYLE_FILL_SERVER(style)) && + SP_HATCH(SP_STYLE_FILL_SERVER(style)) == this) { + i++; + } + if (style && style->stroke.isPaintserver() && SP_IS_HATCH(SP_STYLE_STROKE_SERVER(style)) && + SP_HATCH(SP_STYLE_STROKE_SERVER(style)) == this) { + i++; + } + + for (auto &child : o->children) { + i += _countHrefs(&child); + } + + return i; +} + +SPHatch *SPHatch::clone_if_necessary(SPItem *item, const gchar *property) +{ + SPHatch *hatch = this; + if (hatch->href.empty() || hatch->hrefcount > _countHrefs(item)) { + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + Inkscape::XML::Node *defsrepr = document->getDefs()->getRepr(); + + Inkscape::XML::Node *repr = xml_doc->createElement("svg:hatch"); + repr->setAttribute("inkscape:collect", "always"); + Glib::ustring parent_ref = Glib::ustring::compose("#%1", getRepr()->attribute("id")); + repr->setAttribute("xlink:href", parent_ref); + + defsrepr->addChild(repr, nullptr); + const gchar *child_id = repr->attribute("id"); + SPObject *child = document->getObjectById(child_id); + g_assert(SP_IS_HATCH(child)); + + hatch = SP_HATCH(child); + + Glib::ustring href = Glib::ustring::compose("url(#%1)", hatch->getRepr()->attribute("id")); + + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, property, href.c_str()); + sp_repr_css_change_recursive(item->getRepr(), css, "style"); + } + + return hatch; +} + +void SPHatch::transform_multiply(Geom::Affine postmul, bool set) +{ + if (set) { + _hatchTransform = postmul; + } else { + _hatchTransform = hatchTransform() * postmul; + } + + _hatchTransform_set = true; + + gchar *c = sp_svg_transform_write(_hatchTransform); + setAttribute("transform", c); + g_free(c); +} + bool SPHatch::isValid() const { bool valid = false; diff --git a/src/object/sp-hatch.h b/src/object/sp-hatch.h index 446be0357..f548163a1 100644 --- a/src/object/sp-hatch.h +++ b/src/object/sp-hatch.h @@ -42,6 +42,9 @@ class Node; } } +#define SP_HATCH(obj) (dynamic_cast<SPHatch *>((SPObject *)obj)) +#define SP_IS_HATCH(obj) (dynamic_cast<const SPHatch *>((SPObject *)obj) != NULL) + class SPHatch : public SPPaintServer { public: enum HatchUnits { @@ -82,6 +85,9 @@ public: std::vector<SPHatchPath *> hatchPaths(); std::vector<SPHatchPath const *> hatchPaths() const; + SPHatch *clone_if_necessary(SPItem *item, const gchar *property); + void transform_multiply(Geom::Affine postmul, bool set); + bool isValid() const override; Inkscape::DrawingPattern *show(Inkscape::Drawing &drawing, unsigned int key, Geom::OptRect bbox) override; @@ -124,6 +130,10 @@ private: RenderInfo _calculateRenderInfo(View const &view) const; Geom::OptInterval _calculateStripExtents(Geom::OptRect const &bbox) const; + /** + Count how many times hatch is used by the styles of o and its descendants + */ + guint _countHrefs(SPObject *o) const; /** * Gets called when the hatch is reattached to another <hatch> diff --git a/src/object/sp-item.cpp b/src/object/sp-item.cpp index dfc482267..003562269 100644 --- a/src/object/sp-item.cpp +++ b/src/object/sp-item.cpp @@ -34,11 +34,12 @@ #include "sp-clippath.h" #include "sp-desc.h" #include "sp-guide.h" +#include "sp-hatch.h" #include "sp-item-rm-unsatisfied-cns.h" #include "sp-mask.h" #include "sp-pattern.h" -#include "sp-root.h" #include "sp-rect.h" +#include "sp-root.h" #include "sp-switch.h" #include "sp-text.h" #include "sp-textpath.h" @@ -730,7 +731,7 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X } } } - + gchar *c = sp_svg_transform_write(item->transform); repr->setAttribute("transform", c); g_free(c); @@ -825,7 +826,7 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const double len_x = bbox ? bbox->width() : 0; double len_y = bbox ? bbox->height() : 0; - + x.update(12, 6, len_x); y.update(12, 6, len_y); w.update(12, 6, len_x); @@ -1233,7 +1234,7 @@ void SPItem::invoke_hide(unsigned key) // Adjusters -void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransform pt) +void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PaintServerTransform pt) { bool fill = (pt == TRANSFORM_FILL || pt == TRANSFORM_BOTH); if (fill && style && (style->fill.isPaintserver())) { @@ -1256,6 +1257,29 @@ void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransf } } +void SPItem::adjust_hatch(Geom::Affine const &postmul, bool set, PaintServerTransform pt) +{ + bool fill = (pt == TRANSFORM_FILL || pt == TRANSFORM_BOTH); + if (fill && style && (style->fill.isPaintserver())) { + SPObject *server = style->getFillPaintServer(); + SPHatch *serverHatch = dynamic_cast<SPHatch *>(server); + if (serverHatch) { + SPHatch *hatch = serverHatch->clone_if_necessary(this, "fill"); + hatch->transform_multiply(postmul, set); + } + } + + bool stroke = (pt == TRANSFORM_STROKE || pt == TRANSFORM_BOTH); + if (stroke && style && (style->stroke.isPaintserver())) { + SPObject *server = style->getStrokePaintServer(); + SPHatch *serverHatch = dynamic_cast<SPHatch *>(server); + if (serverHatch) { + SPHatch *hatch = serverHatch->clone_if_necessary(this, "stroke"); + hatch->transform_multiply(postmul, set); + } + } +} + void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set ) { if ( style && style->fill.isPaintserver() ) { diff --git a/src/object/sp-item.h b/src/object/sp-item.h index 8a4eb7e78..04f0f5fd7 100644 --- a/src/object/sp-item.h +++ b/src/object/sp-item.h @@ -55,11 +55,7 @@ class SVGViewWidget; // TODO make a completely new function that transforms either the fill or // stroke of any SPItem without adding an extra parameter to adjust_pattern. -enum PatternTransform { - TRANSFORM_BOTH, - TRANSFORM_FILL, - TRANSFORM_STROKE -}; +enum PaintServerTransform { TRANSFORM_BOTH, TRANSFORM_FILL, TRANSFORM_STROKE }; /** * Event structure. @@ -180,9 +176,9 @@ public: bool isHighlightSet() const; guint32 highlight_color() const; - + void setHighlightColor(guint32 color); - + void unsetHighlightColor(); //==================== @@ -306,7 +302,7 @@ public: /** * Allocates unique integer keys. - * + * * @param numkeys Number of keys required. * @return First allocated key; hence if the returned key is n * you can use n, n + 1, ..., n + (numkeys - 1) @@ -319,7 +315,10 @@ public: void invoke_hide(unsigned int key); void getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs=nullptr) const; - void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false, PatternTransform = TRANSFORM_BOTH); + void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false, + PaintServerTransform = TRANSFORM_BOTH); + void adjust_hatch(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false, + PaintServerTransform = TRANSFORM_BOTH); void adjust_gradient(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false); void adjust_stroke(double ex); |
