summaryrefslogtreecommitdiffstats
path: root/src/object
diff options
context:
space:
mode:
authorvanntile <valentin.ionita1201@gmail.com>2019-08-02 16:23:28 +0000
committervanntile <valentin.ionita1201@gmail.com>2019-08-17 15:33:45 +0000
commit56d76b4861d034dad8b4eeb25e86308e233202e4 (patch)
tree9edc93e1ac61c7e176fdb7050594f0c8ee43ad57 /src/object
parentHatch knot editing initial commit (diff)
downloadinkscape-56d76b4861d034dad8b4eeb25e86308e233202e4.tar.gz
inkscape-56d76b4861d034dad8b4eeb25e86308e233202e4.zip
Added knot holder entities
Diffstat (limited to 'src/object')
-rw-r--r--src/object/sp-hatch.cpp70
-rw-r--r--src/object/sp-hatch.h10
-rw-r--r--src/object/sp-item.cpp32
-rw-r--r--src/object/sp-item.h17
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);