Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
fill-conversion.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
6/*
7 * Authors:
8 * Liam P White
9 *
10 * Copyright (C) 2020 Authors
11 *
12 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
13 */
14
15#include "fill-conversion.h"
16
17#include "document.h"
18#include "desktop-style.h"
19#include "object/sp-shape.h"
20#include "object/sp-defs.h"
23#include "style.h"
24#include "util/units.h"
25
27{
28 // Create new fill and effect object
29 SPDocument *doc = source->document;
30 SPObject *defs = doc->getDefs();
31
32 Inkscape::XML::Node *effectRepr = doc->getReprDoc()->createElement("inkscape:path-effect");
33 SPObject *effectObj = nullptr;
34 Inkscape::XML::Node *pathRepr = doc->getReprDoc()->createElement("svg:path");
35 SPObject *pathObj = nullptr;
36
37 gchar *effectTarget = nullptr;
38 gchar *pathTarget = nullptr;
39
40 effectTarget = g_strdup_printf("#%s,0,1", source->getId());
41 effectRepr->setAttribute("effect", "fill_between_many");
42 effectRepr->setAttribute("method", "bsplinespiro");
43 effectRepr->setAttribute("autoreverse", "false");
44 effectRepr->setAttribute("close", "false");
45 effectRepr->setAttribute("join", "false");
46 effectRepr->setAttribute("linkedpaths", effectTarget);
47 defs->appendChild(effectRepr);
48 Inkscape::GC::release(effectRepr);
49
50 effectObj = doc->getObjectByRepr(effectRepr);
51
52 pathTarget = g_strdup_printf("#%s", effectObj->getId());
53 pathRepr->setAttribute("inkscape:original-d", "M 0,0");
54 pathRepr->setAttribute("inkscape:path-effect", pathTarget);
55 pathRepr->setAttribute("d", "M 0,0");
56
57 SPObject *prev = source->getPrev();
58 source->parent->addChild(pathRepr, prev ? prev->getRepr() : nullptr);
59 Inkscape::GC::release(pathRepr);
60 pathObj = doc->getObjectByRepr(pathRepr);
61 source->setAttribute("inkscape:linked-fill", pathObj->getId());
62
63 g_free(effectTarget);
64 g_free(pathTarget);
65
66 return pathObj;
67}
68
70{
71 SPDocument *doc = source->document;
72
73 char const *linked_fill_id = source->getAttribute("inkscape:linked-fill");
74 if (!linked_fill_id) {
75 return nullptr;
76 }
77
78 return doc->getObjectById(linked_fill_id);
79}
80
82{
83 auto color = source->style->fill.getColor();
84 color.addOpacity(double(source->style->fill_opacity));
85 sp_repr_css_set_property_string(css, "fill", color.toString());
86}
87
89{
90 auto color = source->style->stroke.getColor();
91 color.addOpacity(double(source->style->stroke_opacity));
92 sp_repr_css_set_property_string(css, "fill", color.toString());
93}
94
96{
97 auto color = source->style->fill.getColor();
98 color.addOpacity(double(source->style->fill_opacity));
99 sp_repr_css_set_property_string(css, "stroke", color.toString());
100}
101
103{
104 SPPaintServer *server = source->style->getFillPaintServer();
105
106 if (server) {
107 Glib::ustring str;
108 str += "url(#";
109 str += server->getId();
110 str += ")";
111 sp_repr_css_set_property(css, "fill", str.c_str());
112 }
113}
114
116{
117 SPPaintServer *server = source->style->getStrokePaintServer();
118
119 if (server) {
120 Glib::ustring str;
121 str += "url(#";
122 str += server->getId();
123 str += ")";
124 sp_repr_css_set_property(css, "fill", str.c_str());
125 }
126}
127
129{
130 SPPaintServer *server = source->style->getFillPaintServer();
131
132 if (server) {
133 Glib::ustring str;
134 str += "url(#";
135 str += server->getId();
136 str += ")";
137 sp_repr_css_set_property(css, "stroke", str.c_str());
138 }
139}
140
141static bool has_fill(SPObject *source)
142{
143 return source->style->fill.isColor() || source->style->fill.isPaintserver();
144}
145
146static bool has_stroke(SPObject *source)
147{
148 return source->style->stroke.isColor() || source->style->stroke.isPaintserver();
149}
150
151namespace Inkscape::LivePathEffect {
152
154{
155 if (has_fill(shape)) {
156 SPCSSAttr *fill_css = sp_repr_css_attr_new();
157 SPObject *linked = generate_linked_fill(shape);
158
159 if (shape->style->fill.isColor()) {
160 convert_fill_color(fill_css, shape);
161 } else {
162 convert_fill_server(fill_css, shape);
163 }
164
165 sp_desktop_apply_css_recursive(linked, fill_css, true);
166 sp_repr_css_attr_unref(fill_css);
167 }
168
169 SPCSSAttr *stroke_css = sp_repr_css_attr_new();
170
171 if (has_stroke(shape)) {
172 if (shape->style->stroke.isColor()) {
173 convert_stroke_color(stroke_css, shape);
174 } else {
175 convert_stroke_server(stroke_css, shape);
176 }
177 }
178
179 sp_repr_css_set_property(stroke_css, "fill-rule", "nonzero");
180 sp_repr_css_set_property(stroke_css, "stroke", "none");
181 sp_desktop_apply_css_recursive(shape, stroke_css, true);
182 sp_repr_css_attr_unref(stroke_css);
183}
184
186{
187 // width is in pixels, if use in a LPE with other units convert before use
188 SPObject *linked = get_linked_fill(shape);
190
191 if (has_fill(shape)) {
192 if (shape->style->fill.isColor()) {
193 revert_stroke_color(css, shape);
194 } else {
196 }
197 }
198
199 if (linked != nullptr) {
200 if (linked->style->fill.isColor()) {
201 convert_fill_color(css, linked);
202 } else {
203 convert_fill_server(css, linked);
204 }
205
206 linked->deleteObject();
207 } else {
208 sp_repr_css_set_property(css, "fill", "none");
209 }
211 os << fabs(width);
212 sp_repr_css_set_property(css, "stroke-width", os.str().c_str());
213 // Reverse affine by desktop style apply.
214 {
215 Geom::Affine const local(shape->i2doc_affine());
216 double const ex(local.descrim());
217 if ( ( ex != 0. )
218 && ( ex != 1. ) ) {
220 }
221 }
224}
225
226} // namespace Inkscape::LivePathEffect
227
228/*
229 Local Variables:
230 mode:c++
231 c-file-style:"stroustrup"
232 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
233 indent-tabs-mode:nil
234 fill-column:99
235 End:
236*/
237// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
3x3 matrix representing an affine transformation.
Definition affine.h:70
Coord descrim() const
Calculate the descriminant.
Definition affine.cpp:434
A thin wrapper around std::ostringstream, but writing floating point numbers in the format required b...
Interface for refcounted XML nodes.
Definition node.h:80
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:25
Typed SVG document implementation.
Definition document.h:103
SPObject * getObjectById(std::string const &id) const
SPDefs * getDefs()
Return the main defs object for the document.
Definition document.cpp:245
Inkscape::XML::Document * getReprDoc()
Our Inkscape::XML::Document.
Definition document.h:213
SPObject * getObjectByRepr(Inkscape::XML::Node *repr) const
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
Definition sp-item.cpp:1823
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
void appendChild(Inkscape::XML::Node *child)
void setAttribute(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value)
SPDocument * document
Definition sp-object.h:188
char const * getId() const
Returns the objects current ID string.
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Definition sp-object.h:248
SPObject * getPrev()
Returns previous object in sibling list or NULL.
SPObject * parent
Definition sp-object.h:189
void deleteObject(bool propagate, bool propagate_descendants)
Deletes an object, unparenting it from its parent.
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
char const * getAttribute(char const *name) const
void addChild(Inkscape::XML::Node *child, Inkscape::XML::Node *prev=nullptr)
Base class for shapes, including <path> element.
Definition sp-shape.h:38
SPPaintServer * getFillPaintServer()
Definition style.h:339
T< SPAttr::FILL, SPIPaint > fill
fill
Definition style.h:240
T< SPAttr::STROKE, SPIPaint > stroke
stroke
Definition style.h:247
SPPaintServer * getStrokePaintServer()
Definition style.h:343
T< SPAttr::FILL_OPACITY, SPIScale24 > fill_opacity
fill-opacity
Definition style.h:242
T< SPAttr::STROKE_OPACITY, SPIScale24 > stroke_opacity
stroke-opacity
Definition style.h:261
TODO: insert short description here.
std::shared_ptr< Css const > css
void sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines)
Apply style on object and children, recursively.
static void convert_stroke_server(SPCSSAttr *css, SPObject *source)
static SPObject * get_linked_fill(SPObject *source)
static void revert_stroke_color(SPCSSAttr *css, SPObject *source)
static SPObject * generate_linked_fill(SPShape *source)
static void convert_fill_color(SPCSSAttr *css, SPObject *source)
static void convert_fill_server(SPCSSAttr *css, SPObject *source)
static bool has_fill(SPObject *source)
static void revert_stroke_server(SPCSSAttr *css, SPObject *source)
static bool has_stroke(SPObject *source)
static void convert_stroke_color(SPCSSAttr *css, SPObject *source)
Fill/stroke conversion routines for LPEs which draw a stroke.
static R & release(R &r)
Decrements the reference count of a anchored object.
Live Path Effects code.
void lpe_shape_convert_stroke_and_fill(SPShape *shape)
Prepares a SPShape's fill and stroke for use in a path effect by setting the existing stroke properti...
void lpe_shape_revert_stroke_and_fill(SPShape *shape, double width)
Applies the fill of the SPShape to its stroke, sets the stroke width to the provided parameter,...
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
Definition repr-css.cpp:67
void sp_repr_css_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
Definition repr-css.cpp:76
void sp_repr_css_set_property_string(SPCSSAttr *css, char const *name, std::string const &value)
Set a style property to a standard string.
Definition repr-css.cpp:235
void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
Definition repr-css.cpp:191
virtual Node * createElement(char const *name)=0
SPCSSAttr * sp_css_attr_scale(SPCSSAttr *css, double ex)
Scale any properties that may hold <length> by ex.
Definition style.cpp:1627
SPStyle - a style object for SPItem objects.
double width