Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
object-composite-settings.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * A widget for controlling object compositing (filter, opacity, etc.)
4 *
5 * Authors:
6 * Bryce W. Harrington <bryce@bryceharrington.org>
7 * Gustav Broberg <broberg@kth.se>
8 * Niko Kiirala <niko@kiirala.com>
9 * Abhishek Sharma
10 *
11 * Copyright (C) 2004--2008 Authors
12 *
13 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
14 */
15
17
18#include <utility>
19
20#include "desktop.h"
21#include "desktop-style.h"
22#include "document-undo.h"
23#include "filter-chemistry.h"
24#include "style.h"
26#include "ui/pack.h"
28
29constexpr double BLUR_MULTIPLIER = 4.0;
30
31namespace Inkscape {
32namespace UI {
33namespace Widget {
34
35ObjectCompositeSettings::ObjectCompositeSettings(Glib::ustring icon_name, char const *history_prefix, int flags)
36: Gtk::Box(Gtk::Orientation::VERTICAL),
37 _icon_name(std::move(icon_name)),
38 _blend_tag(Glib::ustring(history_prefix) + ":blend"),
39 _blur_tag(Glib::ustring(history_prefix) + ":blur"),
40 _opacity_tag(Glib::ustring(history_prefix) + ":opacity"),
41 _isolation_tag(Glib::ustring(history_prefix) + ":isolation"),
42 _filter_modifier(flags),
43 _blocked(false)
44{
45 set_name( "ObjectCompositeSettings");
46
47 // Filter Effects
48 UI::pack_start(*this, _filter_modifier, false, false, 2);
49
55}
56
60
62 _subject_changed.disconnect();
63 if (subject) {
64 _subject = subject;
66 }
67}
68
69// We get away with sharing one callback for blend and blur as this is used by
70// * the Layers dialog where only one layer can be selected at a time,
71// * the Fill and Stroke dialog where only blur is used.
72// If both blend and blur are used in a dialog where more than one object can
73// be selected then this should be split into separate functions for blend and
74// blur (like in the Objects dialog).
75void
77{
78 if (!_subject) {
79 return;
80 }
81
83 if (!desktop) {
84 return;
85 }
86 SPDocument *document = desktop->getDocument();
87
88 if (_blocked)
89 return;
90 _blocked = true;
91
93 double radius;
94 if (bbox) {
95 double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct?
96 double blur_value = _filter_modifier.get_blur_value() / 100.0;
97 radius = blur_value * blur_value * perimeter / BLUR_MULTIPLIER;
98 } else {
99 radius = 0;
100 }
101
102 //apply created filter to every selected item
103 std::vector<SPObject*> sel = _subject->list();
104 for (auto i : sel) {
105 if (!is<SPItem>(i)) {
106 continue;
107 }
108 auto item = cast<SPItem>(i);
109 SPStyle *style = item->style;
110 g_assert(style != nullptr);
111 bool change_blend = set_blend_mode(item, _filter_modifier.get_blend_mode());
112
113 if (radius == 0 && item->style->filter.set && item->style->getFilter()
115 remove_filter(item, false);
116 } else if (radius != 0) {
117 SPFilter *filter = modify_filter_gaussian_blur_from_item(document, item, radius);
118 filter->update_filter_region(item);
119 sp_style_set_property_url(item, "filter", filter, false);
120 }
121 if (change_blend) {
122 ; // update done already
123 } else {
124 item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
125 }
126 }
127
128 DocumentUndo::maybeDone(document, _blur_tag.c_str(), _("Change blur/blend filter"), _icon_name);
129
130 _blocked = false;
131}
132
133void
135{
136 if (!_subject) {
137 return;
138 }
139
141 if (!desktop) {
142 return;
143 }
144
145 if (_blocked)
146 return;
147 _blocked = true;
148
150
152 os << CLAMP (_filter_modifier.get_opacity_value() / 100, 0.0, 1.0);
153 sp_repr_css_set_property (css, "opacity", os.str().c_str());
154
156
158
159 DocumentUndo::maybeDone(desktop->getDocument(), _opacity_tag.c_str(), _("Change opacity"), _icon_name);
160
161 _blocked = false;
162}
163
165{
166 if (!_subject) {
167 return;
168 }
169
171 if (!desktop) {
172 return;
173 }
174
175 if (_blocked)
176 return;
177 _blocked = true;
178
179 for (auto item : _subject->list()) {
180 item->style->isolation.set = TRUE;
183 item->style->mix_blend_mode.set = TRUE;
185 }
186 item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT);
187 }
188
189 DocumentUndo::maybeDone(desktop->getDocument(), _isolation_tag.c_str(), _("Change isolation"), _icon_name);
190
191 _blocked = false;
192}
193
194void
196 if (!_subject) {
197 return;
198 }
199
201 if (!desktop) {
202 return;
203 }
204
205 if (_blocked)
206 return;
207 _blocked = true;
208 SPStyle query(desktop->getDocument());
210
211 switch (result) {
213 break;
215 case QUERY_STYLE_MULTIPLE_AVERAGED: // TODO: treat this slightly differently
217 _filter_modifier.set_opacity_value(100 * SP_SCALE24_TO_FLOAT(query.opacity.value));
218 break;
219 }
220
221 //query now for current filter mode and average blurring of selection
222 const int isolation_result = _subject->queryStyle(&query, QUERY_STYLE_PROPERTY_ISOLATION);
223 switch (isolation_result) {
226 break;
229 _filter_modifier.set_isolation_mode(query.isolation.value, true); // here dont work mix_blend_mode.set
230 break;
233 // TODO: set text
234 break;
235 }
236
237 // query now for current filter mode and average blurring of selection
238 const int blend_result = _subject->queryStyle(&query, QUERY_STYLE_PROPERTY_BLEND);
239 switch(blend_result) {
242 break;
245 _filter_modifier.set_blend_mode(query.mix_blend_mode.value, true); // here dont work mix_blend_mode.set
246 break;
249 break;
250 }
251
252 int blur_result = _subject->queryStyle(&query, QUERY_STYLE_PROPERTY_BLUR);
253 switch (blur_result) {
254 case QUERY_STYLE_NOTHING: // no blurring
256 break;
261 if (bbox) {
262 double perimeter =
263 bbox->dimensions()[Geom::X] +
264 bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct?
265 // update blur widget value
266 float radius = query.filter_gaussianBlur_deviation.value;
267 float percent = std::sqrt(radius * BLUR_MULTIPLIER / perimeter) * 100;
269 }
270 break;
271 }
272
273 // If we have nothing selected, disable dialog.
275 blend_result == QUERY_STYLE_NOTHING ) {
276 _filter_modifier.set_sensitive( false );
277 } else {
278 _filter_modifier.set_sensitive( true );
279 }
280
281 _blocked = false;
282}
283
284}
285}
286}
287
288/*
289 Local Variables:
290 mode:c++
291 c-file-style:"stroustrup"
292 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
293 indent-tabs-mode:nil
294 fill-column:99
295 End:
296*/
297// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Axis-aligned rectangle that can be empty.
Definition rect.h:203
A thin wrapper around std::ostringstream, but writing floating point numbers in the format required b...
static void maybeDone(SPDocument *document, const gchar *keyconst, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
ObjectCompositeSettings(Glib::ustring icon_name, char const *history_prefix, int flags)
void set_isolation_mode(const SPIsolation, bool notify)
void set_blend_mode(const SPBlendMode, bool notify)
virtual std::vector< SPObject * > list()
virtual Geom::OptRect getBounds(SPItem::BBoxType type)=0
virtual void setCSS(SPCSSAttr *css)=0
virtual int queryStyle(SPStyle *query, int property)=0
sigc::connection connectChanged(sigc::signal< void()>::slot_type slot)
To do: update description of desktop.
Definition desktop.h:149
SPDocument * getDocument() const
Definition desktop.h:189
Typed SVG document implementation.
Definition document.h:101
void update_filter_region(SPItem *item)
Update the filter region based on the object's bounding box.
@ GEOMETRIC_BBOX
Definition sp-item.h:116
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Definition sp-object.h:248
Inkscape::XML::Node * updateRepr(unsigned int flags=SP_OBJECT_WRITE_EXT)
Updates the object's repr based on the object's state.
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
An SVG style object.
Definition style.h:45
SPFilter * getFilter()
Definition style.h:335
T< SPAttr::ISOLATION, SPIEnum< SPIsolation > > isolation
mix-blend-mode: CSS Compositing and Blending Level 1
Definition style.h:219
T< SPAttr::MIX_BLEND_MODE, SPIEnum< SPBlendMode > > mix_blend_mode
Definition style.h:220
T< SPAttr::OPACITY, SPIScale24 > opacity
opacity
Definition style.h:216
T< SPAttr::FILTER, SPIFilter > filter
Filter effect.
Definition style.h:275
T< SPAttr::INVALID, SPILength > filter_gaussianBlur_deviation
normally not used, but duplicates the Gaussian blur deviation (if any) from the attached filter when ...
Definition style.h:279
TODO: insert short description here.
std::shared_ptr< Css const > css
Css & result
@ QUERY_STYLE_PROPERTY_BLEND
@ QUERY_STYLE_PROPERTY_ISOLATION
@ QUERY_STYLE_PROPERTY_BLUR
@ QUERY_STYLE_PROPERTY_MASTEROPACITY
@ QUERY_STYLE_MULTIPLE_DIFFERENT
@ QUERY_STYLE_SINGLE
@ QUERY_STYLE_NOTHING
@ QUERY_STYLE_MULTIPLE_AVERAGED
@ QUERY_STYLE_MULTIPLE_SAME
Editable view implementation.
TODO: insert short description here.
bool filter_is_single_gaussian_blur(SPFilter *filter)
void remove_filter(SPObject *item, bool recursive)
bool set_blend_mode(SPItem *item, SPBlendMode blend_mode)
SPFilter * modify_filter_gaussian_blur_from_item(SPDocument *document, SPItem *item, gdouble radius)
Modifies the gaussian blur applied to the item.
@ Y
Definition coord.h:48
@ X
Definition coord.h:48
SPItem * item
Definition desktop.h:50
void pack_start(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the start of box.
Definition pack.cpp:141
Helper class to stream background task notifications as a series of messages.
STL namespace.
constexpr double BLUR_MULTIPLIER
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
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(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
Definition repr-css.cpp:191
@ SP_CSS_BLEND_NORMAL
@ SP_CSS_ISOLATION_ISOLATE
@ SP_CSS_ISOLATION_AUTO
Abstraction for different style widget operands.
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