Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
fill-style.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
6/* Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 * Frank Felfe <innerspace@iname.com>
9 * bulia byak <buliabyak@users.sf.net>
10 * Jon A. Cruz <jon@joncruz.org>
11 * Abhishek Sharma
12 *
13 * Copyright (C) 1999-2005 authors
14 * Copyright (C) 2001-2002 Ximian, Inc.
15 * Copyright (C) 2010 Jon A. Cruz
16 *
17 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
18 */
19
20#define noSP_FS_VERBOSE
21
22#include "fill-style.h"
23
24#include <glibmm/i18n.h>
25
26#include "desktop-style.h"
27#include "desktop.h"
28#include "document-undo.h"
29#include "document.h"
30#include "gradient-chemistry.h"
32#include "selection.h"
33#include "style.h"
34
36#include "object/sp-defs.h"
39#include "object/sp-object.h"
40#include "object/sp-pattern.h"
42#include "object/sp-stop.h"
43#include "object/sp-text.h"
44#include "object/sp-use.h"
46#include "ui/icon-names.h"
47
48// These can be deleted once we sort out the libart dependence.
49
50#define ART_WIND_RULE_NONZERO 0
51
52/* Fill */
53
54namespace Inkscape {
55namespace UI {
56namespace Widget {
57
59 : Gtk::Box(Gtk::Orientation::VERTICAL)
60 , kind(k)
61 , _solid_colors(std::make_shared<Colors::ColorSet>())
62 , subselChangedConn()
63 , eventContextConn()
64{
65 // Single fallback color
66 _solid_colors->set(Color(0x000000ff));
67
68 // Add and connect up the paint selector widget:
69 _psel = Gtk::make_managed<UI::Widget::PaintSelector>(kind, _solid_colors);
70 _psel->set_visible(true);
71 append(*_psel);
72 _psel->signal_mode_changed().connect(sigc::mem_fun(*this, &FillNStroke::paintModeChangeCB));
73 _psel->signal_dragged().connect(sigc::mem_fun(*this, &FillNStroke::dragFromPaint));
74 _psel->signal_changed().connect(sigc::mem_fun(*this, &FillNStroke::paintChangedCB));
75 _psel->signal_stop_selected().connect([this](SPStop *stop) {
76 if (_desktop) {
77 auto guard = _blocker.block();
79 }
80 });
81 _psel->signal_edit_pattern().connect([this](){
82 if (_desktop) set_active_tool(_desktop, "Node");
83 });
84
85 if (kind == FILL) {
86 _psel->signal_fillrule_changed().connect(sigc::mem_fun(*this, &FillNStroke::setFillrule));
87 }
88
90}
91
93{
94 if (_drag_id) {
95 g_source_remove(_drag_id);
96 _drag_id = 0;
97 }
98
99 _psel = nullptr;
100 subselChangedConn.disconnect();
101 eventContextConn.disconnect();
102}
103
108{
109 if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
110#ifdef SP_FS_VERBOSE
111 g_message("selectionModifiedCB(%d) on %p", flags, this);
112#endif
114 }
115}
116
118{
119 if (_desktop != desktop) {
120 if (_drag_id) {
121 g_source_remove(_drag_id);
122 _drag_id = 0;
123 }
124 if (_desktop) {
125 subselChangedConn.disconnect();
126 eventContextConn.disconnect();
127 stop_selected_connection.disconnect();
128 }
130 if (desktop && desktop->getSelection()) {
133 });
134
135 eventContextConn = desktop->connectEventContextChanged(sigc::hide(sigc::bind(
136 sigc::mem_fun(*this, &FillNStroke::eventContextCB), (Inkscape::UI::Tools::ToolBase *)nullptr)));
137
139 if (_blocker.pending()) {
140 return;
141 }
143 });
144 }
146 }
147}
148
154{
156}
157
165{
166 if (_update || !_desktop) {
167 return;
168 }
169 auto *widg = get_parent()->get_parent()->get_parent()->get_parent();
170 auto dialogbase = dynamic_cast<Inkscape::UI::Dialog::DialogBase*>(widg);
171 if (dialogbase && !dialogbase->getShowing()) {
172 return;
173 }
174 if (_drag_id) {
175 // local change; do nothing, but reset the flag
176 g_source_remove(_drag_id);
177 _drag_id = 0;
178 return;
179 }
180
181 _update = true;
182
183 // create temporary style
184 SPStyle query(_desktop->doc());
185
186 // query style from desktop into it. This returns a result flag and fills query with the style of subselection, if
187 // any, or selection
189 int result = sp_desktop_query_style(_desktop, &query, property);
190 SPIPaint& paint = *query.getFillOrStroke(kind == FILL);
191 auto stop = cast<SPStop>(paint.getTag());
192 if (stop) {
193 // there's a stop selected, which is part of subselection, now query selection only to find selected gradient
194 if (auto selection = _desktop->getSelection()) {
195 std::vector<SPItem*> vec(selection->items().begin(), selection->items().end());
196 result = sp_desktop_query_style_from_list(vec, &query, property);
197 }
198 }
199 SPIPaint &targPaint = *query.getFillOrStroke(kind == FILL);
200 double targOpacity = kind == FILL ? query.fill_opacity : query.stroke_opacity;
201
202 switch (result) {
203 case QUERY_STYLE_NOTHING: {
204 /* No paint at all */
206 break;
207 }
208
210 case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently, e.g. display "averaged" somewhere
211 // in paint selector
213 auto pselmode = UI::Widget::PaintSelector::getModeForStyle(query, kind);
214 _psel->setMode(pselmode);
215
216 if (kind == FILL) {
217 _psel->setFillrule(query.fill_rule.computed == ART_WIND_RULE_NONZERO
220 }
221
222 if (targPaint.set && targPaint.isColor()) {
223 // This is terrible, future refactoring has been written
224 auto color = targPaint.getColor();
225 color.addOpacity(targOpacity);
226 _solid_colors->set(color);
227 } else if (targPaint.set && targPaint.isPaintserver()) {
228 SPPaintServer* server = (kind == FILL) ? query.getFillPaintServer() : query.getStrokePaintServer();
229
230 if (server) {
231 if (is<SPGradient>(server) && cast<SPGradient>(server)->getVector()->isSwatch()) {
232 auto vector = cast<SPGradient>(server)->getVector();
233 _psel->setSwatch(vector);
234 } else if (is<SPLinearGradient>(server)) {
235 auto vector = cast<SPGradient>(server)->getVector();
236 auto lg = cast<SPLinearGradient>(server);
237 _psel->setGradientLinear(vector, lg, stop);
238
239 _psel->setGradientProperties(lg->getUnits(), lg->getSpread());
240 } else if (is<SPRadialGradient>(server)) {
241 auto vector = cast<SPGradient>(server)->getVector();
242 auto rg = cast<SPRadialGradient>(server);
243 _psel->setGradientRadial(vector, rg, stop);
244
245 _psel->setGradientProperties(rg->getUnits(), rg->getSpread());
246#ifdef WITH_MESH
247 } else if (is<SPMeshGradient>(server)) {
248 auto array = cast<SPGradient>(server)->getArray();
249 _psel->setGradientMesh(cast<SPMeshGradient>(array));
250 _psel->updateMeshList(cast<SPMeshGradient>(array));
251#endif
252 } else if (is<SPPattern>(server)) {
253 _psel->updatePatternList(cast<SPPattern>(server));
254 }
255 }
256 }
257 break;
258 }
259
262 break;
263 }
264 }
265
266 _update = false;
267}
268
273{
274#ifdef SP_FS_VERBOSE
275 g_message("paintModeChangeCB()");
276#endif
277 if (!_update) {
278 updateFromPaint(switch_style);
279 }
280}
281
283{
284 if (!_update && _desktop) {
286 sp_repr_css_set_property(css, "fill-rule",
287 (mode == UI::Widget::PaintSelector::FILLRULE_EVENODD) ? "evenodd" : "nonzero");
288
290
292 css = nullptr;
293
294 DocumentUndo::done(_desktop->doc(), _("Change fill rule"), INKSCAPE_ICON("dialog-fill-and-stroke"));
295 }
296}
297
298static gchar const *undo_F_label_1 = "fill:flatcolor:1";
299static gchar const *undo_F_label_2 = "fill:flatcolor:2";
300
301static gchar const *undo_S_label_1 = "stroke:flatcolor:1";
302static gchar const *undo_S_label_2 = "stroke:flatcolor:2";
303
304static gchar const *undo_F_label = undo_F_label_1;
305static gchar const *undo_S_label = undo_S_label_1;
306
308{
309 gboolean keepGoing = TRUE;
310 if (data) {
311 FillNStroke *self = reinterpret_cast<FillNStroke *>(data);
312 if (!self->_update) {
313 if (self->_drag_id) {
314 g_source_remove(self->_drag_id);
315 self->_drag_id = 0;
316
317 self->dragFromPaint();
318 self->performUpdate();
319 }
320 keepGoing = FALSE;
321 }
322 } else {
323 keepGoing = FALSE;
324 }
325 return keepGoing;
326}
327
335{
336 if (!_desktop || _update) {
337 return;
338 }
339
340 guint32 when = g_get_monotonic_time() / 1000; // ms
341
342 // Don't attempt too many updates per second.
343 // Assume a base 15.625ms resolution on the timer.
344 if (!_drag_id && _last_drag && when && ((when - _last_drag) < 32)) {
345 // local change, do not update from selection
346 _drag_id = g_timeout_add_full(G_PRIORITY_DEFAULT, 33, dragDelayCB, this, nullptr);
347 }
348
349 if (_drag_id) {
350 // previous local flag not cleared yet;
351 // this means dragged events come too fast, so we better skip this one to speed up display
352 // (it's safe to do this in any case)
353 return;
354 }
355 _last_drag = when;
356
357 _update = true;
358
359 switch (_psel->get_mode()) {
361 // local change, do not update from selection
362 _drag_id = g_timeout_add_full(G_PRIORITY_DEFAULT, 100, dragDelayCB, this, nullptr);
363
364 sp_desktop_set_color(_desktop, _solid_colors->getAverage(), false, kind == FILL);
365
367 (kind == FILL) ? _("Set fill color") : _("Set stroke color"),
368 INKSCAPE_ICON("dialog-fill-and-stroke"));
369 break;
370 }
371
372 default:
373 g_warning("file %s: line %d: Paint %d should not emit 'dragged'", __FILE__, __LINE__, _psel->get_mode());
374 break;
375 }
376 _update = false;
377}
378
379void unset_recursive(const char *attribute, SPObject* object)
380{
381 object->removeAttribute(attribute);
382
383 for (auto& child: object->children)
384 {
385 if (is<SPUse> (object)) return;
386 unset_recursive(attribute, &child);
387 }
388}
397{
398#ifdef SP_FS_VERBOSE
399 g_message("paintChangedCB()");
400#endif
401 if (!_update) {
403 }
404}
405
406void FillNStroke::updateFromPaint(bool switch_style)
407{
408 if (!_desktop) {
409 return;
410 }
411 _update = true;
412
413 auto document = _desktop->getDocument();
414 auto selection = _desktop->getSelection();
415
416 std::vector<SPItem *> const items(selection->items().begin(), selection->items().end());
417
418 switch (_psel->get_mode()) {
420 // This should not happen.
421 g_warning("file %s: line %d: Paint %d should not emit 'changed'", __FILE__, __LINE__, _psel->get_mode());
422 break;
424 // This happens when you switch multiple objects with different gradients to flat color;
425 // nothing to do here.
426 break;
427
430 sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", "none");
431
432 sp_desktop_set_style(_desktop, css, true, true, switch_style);
433
435 css = nullptr;
436
437 DocumentUndo::done(document, (kind == FILL) ? _("Remove fill") : _("Remove stroke"), INKSCAPE_ICON("dialog-fill-and-stroke"));
438 break;
439 }
440
442
443 sp_desktop_set_color(_desktop, _solid_colors->getAverage(), false, kind == FILL);
444
446 (kind == FILL) ? _("Set fill color") : _("Set stroke color"),
447 INKSCAPE_ICON("dialog-fill-and-stroke"));
448
449 // on release, toggle undo_label so that the next drag will not be lumped with this one
453 } else {
456 }
457
458 break;
459 }
460
464 if (!items.empty()) {
465 SPGradientType const gradient_type =
468 bool createSwatch = (_psel->get_mode() == UI::Widget::PaintSelector::MODE_SWATCH);
469
470 auto vector = _psel->getGradientVector();
471 if (!vector) {
472 /* No vector in paint selector should mean that we just changed mode */
473 SPStyle query(_desktop->doc());
474 int result = objects_query_fillstroke(items, &query, kind == FILL);
476 SPIPaint &targPaint = *query.getFillOrStroke(kind == FILL);
477 Inkscape::Colors::Color common(0x000000ff);
478 if (!targPaint.isColor()) {
479 if (auto color = sp_desktop_get_color(_desktop, kind == FILL))
480 common = *color;
481 } else {
482 common = targPaint.getColor();
483 }
484 vector = sp_document_default_gradient_vector(document, common, 1.0, createSwatch);
485 }
486 if (vector)
487 vector->setSwatch(createSwatch);
488
489 for (auto item : items) {
490 if (!vector) {
492 document, _desktop, item,
493 (kind == FILL) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE, createSwatch);
494 if (gr) {
495 gr->setSwatch(createSwatch);
496 }
497 sp_item_set_gradient(item, gr, gradient_type,
499 } else {
500 sp_item_set_gradient(item, vector, gradient_type,
502 }
503 }
504 } else {
505 // We have changed from another gradient type, or modified spread/units within
506 // this gradient type.
508 for (auto item : items) {
510 item, vector, gradient_type, (kind == FILL) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE);
512 }
513 }
514
515 for (auto item : items) {
516 // fill and stroke opacity should never be set on gradients since in our user interface
517 // these are controlled by the gradient stops themselves.
519 }
520 DocumentUndo::done(document, (kind == FILL) ? _("Set gradient on fill") : _("Set gradient on stroke"), INKSCAPE_ICON("dialog-fill-and-stroke"));
521 }
522 break;
523
524#ifdef WITH_MESH
526
527 if (!items.empty()) {
528 SPCSSAttr *css = nullptr;
529 if (kind == FILL) {
530 // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider
531 // for all tabs
533 sp_repr_css_set_property(css, "fill-opacity", "1.0");
534 }
535
536 Inkscape::XML::Document *xml_doc = document->getReprDoc();
537 SPDefs *defs = document->getDefs();
538
539 auto mesh = _psel->getMeshGradient();
540
541 for (auto item : items) {
542
543 // FIXME: see above
544 if (kind == FILL) {
546 }
547
548 // Check if object already has mesh.
549 bool has_mesh = false;
550 SPStyle *style = item->style;
551 if (style) {
552 SPPaintServer *server =
553 (kind == FILL) ? style->getFillPaintServer() : style->getStrokePaintServer();
554 if (server && is<SPMeshGradient>(server))
555 has_mesh = true;
556 }
557
558 if (!mesh || !has_mesh) {
559 // No mesh in document or object does not already have mesh ->
560 // Create new mesh.
561
562 // Create mesh element
563 Inkscape::XML::Node *repr = xml_doc->createElement("svg:meshgradient");
564
565 // privates are garbage-collectable
566 repr->setAttribute("inkscape:collect", "always");
567
568 // Attach to document
569 defs->getRepr()->appendChild(repr);
571
572 // Get corresponding object
573 SPMeshGradient *mg = static_cast<SPMeshGradient *>(document->getObjectByRepr(repr));
574 mg->array.create(mg, item, (kind == FILL) ? item->geometricBounds() : item->visualBounds());
575
576 bool isText = is<SPText>(item);
577 sp_style_set_property_url(item, ((kind == FILL) ? "fill" : "stroke"), mg, isText);
578
579 // (*i)->requestModified(SP_OBJECT_MODIFIED_FLAG|SP_OBJECT_STYLE_MODIFIED_FLAG);
580
581 } else {
582 // Using found mesh
583
584 // Duplicate
585 Inkscape::XML::Node *mesh_repr = mesh->getRepr();
586 Inkscape::XML::Node *copy_repr = mesh_repr->duplicate(xml_doc);
587
588 // privates are garbage-collectable
589 copy_repr->setAttribute("inkscape:collect", "always");
590
591 // Attach to document
592 defs->getRepr()->appendChild(copy_repr);
593 Inkscape::GC::release(copy_repr);
594
595 // Get corresponding object
596 SPMeshGradient *mg = static_cast<SPMeshGradient *>(document->getObjectByRepr(copy_repr));
597 // std::cout << " " << (mg->getId()?mg->getId():"null") << std::endl;
598 mg->array.read(mg);
599
600 Geom::OptRect item_bbox = (kind == FILL) ? item->geometricBounds() : item->visualBounds();
601 mg->array.fill_box(item_bbox);
602
603 bool isText = is<SPText>(item);
604 sp_style_set_property_url(item, ((kind == FILL) ? "fill" : "stroke"), mg, isText);
605 }
606 }
607
608 if (css) {
610 css = nullptr;
611 }
612
613 DocumentUndo::done(document, (kind == FILL) ? _("Set mesh on fill") : _("Set mesh on stroke"), INKSCAPE_ICON("dialog-fill-and-stroke"));
614 }
615 break;
616#endif
617
619
620 if (!items.empty()) {
621
622 auto pattern = _psel->getPattern();
623 if (!pattern) {
624 /* No Pattern in paint selector should mean that we just
625 * changed mode - don't do jack.
626 */
627 } else {
628 auto link_pattern = pattern;
629 auto root_pattern = pattern->rootPattern();
630 if (auto color = _psel->get_pattern_color()) {
631 sp_pattern_set_color(root_pattern, color.value());
632 }
633 // pattern name is applied to the root
634 root_pattern->setAttribute("inkscape:label", _psel->get_pattern_label().c_str());
635 // remaining settings apply to link pattern
636 if (link_pattern != root_pattern) {
637 auto transform = _psel->get_pattern_transform();
638 sp_pattern_set_transform(link_pattern, transform);
640 sp_pattern_set_offset(link_pattern, offset);
643 // gap requires both patterns, but they are only created later by calling "adjust_pattern" below
644 // it is OK to ignore it for now, during initial creation gap is 0,0
645 auto gap = _psel->get_pattern_gap();
646 sp_pattern_set_gap(link_pattern, gap);
647 }
648
649 Inkscape::XML::Node *patrepr = root_pattern->getRepr();
651 gchar *urltext = g_strdup_printf("url(#%s)", patrepr->attribute("id"));
652 sp_repr_css_set_property(css, (kind == FILL) ? "fill" : "stroke", urltext);
653
654 // HACK: reset fill-opacity - that 0.75 is annoying; BUT remove this when we have an opacity slider
655 // for all tabs
656 if (kind == FILL) {
657 sp_repr_css_set_property(css, "fill-opacity", "1.0");
658 }
659
660 // cannot just call sp_desktop_set_style, because we don't want to touch those
661 // objects who already have the same root pattern but through a different href
662 // chain. FIXME: move this to a sp_item_set_pattern
663 for (auto item : items) {
664 Inkscape::XML::Node *selrepr = item->getRepr();
665 if ((kind == STROKE) && !selrepr) {
666 continue;
667 }
668 SPObject *selobj = item;
669
670 SPStyle *style = selobj->style;
671 if (style && ((kind == FILL) ? style->fill.isPaintserver() : style->stroke.isPaintserver())) {
672 SPPaintServer *server = (kind == FILL) ? selobj->style->getFillPaintServer()
673 : selobj->style->getStrokePaintServer();
674 if (is<SPPattern>(server) && cast<SPPattern>(server)->rootPattern() == root_pattern)
675 // only if this object's pattern is not rooted in our selected pattern, apply
676 continue;
677 }
678
679 if (kind == FILL) {
680 sp_desktop_apply_css_recursive(selobj, css, true);
681 } else {
682 sp_repr_css_change_recursive(selrepr, css, "style");
683 }
684
685 // create link to pattern right away, without waiting for object to be moved;
686 // otherwise pattern editor may end up modifying pattern shared by different objects
688 }
689
691 css = nullptr;
692 g_free(urltext);
693 } // end if
694
695 DocumentUndo::done(document, (kind == FILL) ? _("Set pattern on fill") : _("Set pattern on stroke"), INKSCAPE_ICON("dialog-fill-and-stroke"));
696 } // end if
697
698 break;
699
701 if (!items.empty()) {
702 for (auto item: items) {
703 if (item) {
704 unset_recursive((kind == FILL) ? "fill" : "stroke", item);
705 }
706 }
708 if (kind == FILL) {
710 } else {
712 sp_repr_css_unset_property(css, "stroke-opacity");
713 sp_repr_css_unset_property(css, "stroke-width");
714 sp_repr_css_unset_property(css, "stroke-miterlimit");
715 sp_repr_css_unset_property(css, "stroke-linejoin");
716 sp_repr_css_unset_property(css, "stroke-linecap");
717 sp_repr_css_unset_property(css, "stroke-dashoffset");
718 sp_repr_css_unset_property(css, "stroke-dasharray");
719 }
720
723 css = nullptr;
724
725 DocumentUndo::done(document, (kind == FILL) ? _("Unset fill") : _("Unset stroke"), INKSCAPE_ICON("dialog-fill-and-stroke"));
726 }
727 break;
728
729 default:
730 g_warning("file %s: line %d: Paint selector should not be in "
731 "mode %d",
732 __FILE__, __LINE__, _psel->get_mode());
733 break;
734 }
735
736 _update = false;
737}
738
739} // namespace Widget
740} // namespace UI
741} // namespace Inkscape
742
743/*
744 Local Variables:
745 mode:c++
746 c-file-style:"stroustrup"
747 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
748 indent-tabs-mode:nil
749 fill-column:99
750 End:
751*/
752// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
void set_active_tool(InkscapeWindow *win, Glib::ustring const &tool)
@ FILL_OPACITY
@ STROKE_OPACITY
3x3 matrix representing an affine transformation.
Definition affine.h:70
Axis-aligned rectangle that can be empty.
Definition rect.h:203
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
static void maybeDone(SPDocument *document, const gchar *keyconst, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
DialogBase is the base class for the dialog system.
Definition dialog-base.h:42
Base class for Event processors.
Definition tool-base.h:107
void paintModeChangeCB(UI::Widget::PaintSelector::Mode mode, bool switch_style)
When the mode is changed, invoke a regular changed handler.
void setDesktop(SPDesktop *desktop)
void setFillrule(PaintSelector::FillRule mode)
void selectionModifiedCB(guint flags)
On signal modified, invokes an update of the fill or stroke style paint object.
sigc::connection eventContextConn
Definition fill-style.h:49
void eventContextCB(SPDesktop *desktop, Inkscape::UI::Tools::ToolBase *eventcontext)
Listen to this "change in tool" event, in case a subselection tool (such as Gradient or Node) selecti...
sigc::connection subselChangedConn
Definition fill-style.h:48
sigc::connection stop_selected_connection
Definition fill-style.h:50
static gboolean dragDelayCB(gpointer data)
void paintChangedCB()
This is called (at least) when: 1 paint selector mode is switched (e.g.
std::shared_ptr< Colors::ColorSet > _solid_colors
Definition fill-style.h:40
void performUpdate()
Gets the active fill or stroke style property, then sets the appropriate color, alpha,...
void dragFromPaint()
This is called repeatedly while you are dragging a color slider, only for flat color modes.
void updateFromPaint(bool switch_style=false)
void setGradientRadial(SPGradient *vector, SPRadialGradient *gradient, SPStop *selected)
void updateMeshList(SPMeshGradient *pat)
void setGradientLinear(SPGradient *vector, SPLinearGradient *gradient, SPStop *selected)
decltype(_signal_edit_pattern) signal_edit_pattern() const
void setGradientProperties(SPGradientUnits units, SPGradientSpread spread)
decltype(_signal_stop_selected) signal_stop_selected() const
std::optional< Colors::Color > get_pattern_color()
decltype(_signal_mode_changed) signal_mode_changed() const
void setGradientMesh(SPMeshGradient *array)
decltype(_signal_dragged) signal_dragged() const
decltype(_signal_fillrule_changed) signal_fillrule_changed() const
decltype(_signal_changed) signal_changed() const
void pushAttrsToGradient(SPGradient *gr) const
static Mode getModeForStyle(SPStyle const &style, FillOrStroke kind)
Interface for refcounted XML nodes.
Definition node.h:80
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:25
virtual Node * duplicate(Document *doc) const =0
Create a duplicate of this node.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
scoped_block block()
To do: update description of desktop.
Definition desktop.h:149
SPDocument * getDocument() const
Definition desktop.h:189
sigc::connection connect_gradient_stop_selected(sigc::slot< void(SPStop *)> const &slot)
Definition desktop.cpp:1349
Inkscape::Selection * getSelection() const
Definition desktop.h:188
sigc::connection connect_text_cursor_moved(sigc::slot< void(Inkscape::UI::Tools::TextTool *)> const &slot)
Definition desktop.cpp:1357
SPDocument * doc() const
Definition desktop.h:159
void emit_gradient_stop_selected(SPStop *stop)
Definition desktop.cpp:1361
sigc::connection connectEventContextChanged(F &&slot)
Definition desktop.h:261
Gradient.
Definition sp-gradient.h:86
SPMeshNodeArray array
Mesh Gradients.
void setSwatch(bool swatch=true)
Paint type internal to SPStyle.
bool isPaintserver() const
bool isColor() const
SPObject * getTag()
Colors::Color const & getColor() const
void adjust_pattern(Geom::Affine const &postmul, bool set=false, PaintServerTransform=TRANSFORM_BOTH)
Definition sp-item.cpp:1396
Geom::OptRect geometricBounds(Geom::Affine const &transform=Geom::identity()) const
Get item's geometric bounding box in this item's coordinate system.
Definition sp-item.cpp:927
Geom::OptRect visualBounds(Geom::Affine const &transform=Geom::identity(), bool wfilter=true, bool wclip=true, bool wmask=true) const
Get item's visual bounding box in this item's coordinate system.
Definition sp-item.cpp:932
Mesh gradient.
bool fill_box(Geom::OptRect &box)
bool read(SPMeshGradient *mg)
void create(SPMeshGradient *mg, SPItem *item, Geom::OptRect bbox)
Create a default mesh.
SPObject is an abstract base class of all of the document nodes at the SVG document level.
Definition sp-object.h:160
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Definition sp-object.h:248
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
SPPattern const * rootPattern() const
Gradient stop.
Definition sp-stop.h:31
An SVG style object.
Definition style.h:45
void clear()
Definition style.cpp:505
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_RULE, SPIEnum< SPWindRule > > fill_rule
fill-rule: 0 nonzero, 1 evenodd
Definition style.h:244
T< SPAttr::FILL_OPACITY, SPIScale24 > fill_opacity
fill-opacity
Definition style.h:242
SPIPaint * getFillOrStroke(bool fill_)
Get either the fill or the stroke property.
Definition style.h:355
T< SPAttr::STROKE_OPACITY, SPIScale24 > stroke_opacity
stroke-opacity
Definition style.h:261
std::shared_ptr< Css const > css
Css & result
int sp_desktop_query_style_from_list(const std::vector< SPItem * > &list, SPStyle *style, int property)
Query the given list of objects for the given property, write the result to style,...
std::optional< Color > sp_desktop_get_color(SPDesktop *desktop, bool is_fill)
Return the desktop's current color.
void sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines)
Apply style on object and children, recursively.
void sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write_current, bool switch_style)
Apply style on selection on desktop.
int sp_desktop_query_style(SPDesktop *desktop, SPStyle *style, int property)
Query the subselection (if any) or selection on the given desktop for the given property,...
int objects_query_fillstroke(const std::vector< SPItem * > &objects, SPStyle *style_res, bool const isfill)
Write to style_res the average fill or stroke of list of objects, if applicable.
void sp_desktop_set_color(SPDesktop *desktop, Color const &color, bool is_relative, bool fill)
Set color on selection on desktop.
@ QUERY_STYLE_PROPERTY_STROKE
@ QUERY_STYLE_PROPERTY_FILL
@ QUERY_STYLE_MULTIPLE_DIFFERENT
@ QUERY_STYLE_SINGLE
@ QUERY_STYLE_NOTHING
@ QUERY_STYLE_MULTIPLE_AVERAGED
@ QUERY_STYLE_MULTIPLE_SAME
Editable view implementation.
A base class for all dialogs.
TODO: insert short description here.
unsigned int guint32
@ FILL
@ STROKE
Fill style configuration.
SPGradient * sp_gradient_ensure_vector_normalized(SPGradient *gr)
Either normalizes given gradient to vector, or returns fresh normalized vector - in latter case,...
SPGradient * sp_document_default_gradient_vector(SPDocument *document, Color const &color, double opacity, bool singleStop)
SPGradient * sp_gradient_vector_for_object(SPDocument *const doc, SPDesktop *const desktop, SPObject *const o, Inkscape::PaintTarget const fill_or_stroke, bool singleStop)
Return the preferred vector for o, made from (in order of preference) its current vector,...
SPGradient * sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType type, Inkscape::PaintTarget fill_or_stroke)
Sets item fill or stroke to the gradient of the specified type with given vector, creating new privat...
Macro for icon names used in Inkscape.
SPItem * item
double offset
Definition desktop.h:50
static R & release(R &r)
Decrements the reference count of a anchored object.
static gchar const * undo_S_label_2
void unset_recursive(const char *attribute, SPObject *object)
static gchar const * undo_F_label
static gchar const * undo_S_label
static gchar const * undo_F_label_2
static gchar const * undo_S_label_1
static gchar const * undo_F_label_1
Helper class to stream background task notifications as a series of messages.
static void append(std::vector< T > &target, std::vector< T > &&source)
STL namespace.
int mode
void sp_pattern_set_uniform_scale(SPPattern *pattern, bool uniform)
void sp_pattern_set_gap(SPPattern *link_pattern, Geom::Scale gap_percent)
void sp_pattern_set_offset(SPPattern *pattern, const Geom::Point &offset)
void sp_pattern_set_color(SPPattern *pattern, Inkscape::Colors::Color const &c)
void sp_pattern_set_transform(SPPattern *pattern, const Geom::Affine &transform)
Ocnode * child[8]
Definition quantize.cpp:33
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_change_recursive(Node *repr, SPCSSAttr *css, gchar const *attr)
Definition repr-css.cpp:371
void sp_repr_css_unset_property(SPCSSAttr *css, gchar const *name)
Set a style property to "inkscape:unset".
Definition repr-css.cpp:202
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
GList * items
SPGradientType
Definition sp-gradient.h:33
@ SP_GRADIENT_TYPE_LINEAR
Definition sp-gradient.h:35
@ SP_GRADIENT_TYPE_RADIAL
Definition sp-gradient.h:36
TODO: insert short description here.
TODO: insert short description here.
SVG <pattern> implementation.
TODO: insert short description here.
TODO: insert short description here.
static const Point data[]
Interface for XML documents.
Definition document.h:43
virtual Node * createElement(char const *name)=0
void sp_style_set_property_url(SPObject *item, gchar const *property, SPObject *linked, bool recursive)
Definition style.cpp:1380
SPStyle - a style object for SPItem objects.
SPDesktop * desktop
double uniform()