Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
util.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Utility functions for UI
4 *
5 * Authors:
6 * Tavmjong Bah
7 * John Smith
8 *
9 * Copyright (C) 2004, 2013, 2018 Authors
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11 */
12
13#include "util.h"
14
15#include <cstdint>
16#include <stdexcept>
17
18#include <cairomm/pattern.h>
19#include <glibmm/i18n.h>
20#include <glibmm/regex.h>
21#include <glibmm/spawn.h>
22#include <gtkmm/adjustment.h>
23#include <gtkmm/cssprovider.h>
24#include <gtkmm/image.h>
25#include <gtkmm/label.h>
26#include <gtkmm/messagedialog.h>
27#include <gtkmm/revealer.h>
28#include <gtkmm/spinbutton.h>
29#include <gtkmm/textview.h>
30#include <gtkmm/tooltip.h>
31#include <gtkmm/widget.h>
32#include <pangomm/context.h>
33#include <pangomm/fontdescription.h>
34#include <pangomm/layout.h>
35#include <2geom/bezier.h>
36
37#include "colors/color.h"
38#include "colors/utils.h" // color to hex string
39#include "inkscape-window.h"
41
42#if (defined (_WIN32) || defined (_WIN64))
43#undef NOGDI
44#include <gdk/win32/gdkwin32.h>
45#include <dwmapi.h>
46/* For Windows 10 version 1809, 1903, 1909. */
47#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE_OLD
48#define DWMWA_USE_IMMERSIVE_DARK_MODE_OLD 19
49#endif
50/* For Windows 10 version 2004 and higher, and Windows 11. */
51#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
52#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
53#endif
54#endif
55
56#include "desktop.h"
57#include "inkscape.h"
58
59#include "ui/dialog-run.h"
60#include "ui/util.h" // for_each_child()
61
62
63/*
64 * Ellipse text if longer than maxlen, "50% start text + ... + ~50% end text"
65 * Text should be > length 8 or just return the original text
66 */
67Glib::ustring ink_ellipsize_text(Glib::ustring const &src, std::size_t maxlen)
68{
69 if (src.length() > maxlen && maxlen > 8) {
70 using std::size_t;
71 size_t p1 = (size_t) maxlen / 2;
72 size_t p2 = (size_t) src.length() - (maxlen - p1 - 1);
73 return src.substr(0, p1) + "…" + src.substr(p2);
74 }
75 return src;
76}
77
83void reveal_widget(Gtk::Widget *widget, bool show)
84{
85 auto revealer = dynamic_cast<Gtk::Revealer *>(widget->get_parent());
86 if (revealer) {
87 revealer->set_reveal_child(show);
88 }
89 if (show) {
90 widget->set_visible(true);
91 } else if (!revealer) {
92 widget->set_visible(false);
93 }
94}
95
96
97bool is_widget_effectively_visible(Gtk::Widget const *widget) {
98 if (!widget) return false;
99
100 // TODO: what's the right way to determine if widget is visible on the screen?
101 return widget->get_child_visible();
102}
103
104namespace Inkscape::UI {
105
113void set_icon_sizes(Gtk::Widget *parent, int pixel_size)
114{
115 if (!parent) return;
116 for_each_descendant(*parent, [=](Gtk::Widget &widget) {
117 if (dynamic_cast<Gtk::SpinButton*>(&widget)) {
118 // do not descend into spinbuttons; it will impact +/- icons too
120 }
121 if (auto const ico = dynamic_cast<Gtk::Image *>(&widget)) {
122 ico->set_from_icon_name(ico->get_icon_name());
123 ico->set_pixel_size(pixel_size);
124 }
126 });
127}
128
129void set_icon_sizes(GtkWidget* parent, int pixel_size)
130{
131 set_icon_sizes(Glib::wrap(parent), pixel_size);
132}
133
134void gui_warning(const std::string &msg, Gtk::Window *parent_window) {
135 g_warning("%s", msg.c_str());
136 if (INKSCAPE.active_desktop()) {
137 Gtk::MessageDialog warning(_(msg.c_str()), false, Gtk::MessageType::WARNING, Gtk::ButtonsType::OK, true);
138 warning.set_transient_for(parent_window ? *parent_window : *INKSCAPE.active_desktop()->getInkscapeWindow());
139 dialog_run(warning);
140 }
141}
142
143void system_open(const Glib::ustring &path)
144{
145#ifdef _WIN32
146 ShellExecute(nullptr, "open", path.c_str(), nullptr, nullptr, SW_SHOWDEFAULT);
147#elif defined(__APPLE__)
148 Glib::spawn_async("", { "open", path.raw() }, Glib::SpawnFlags::SEARCH_PATH);
149#else
150 char * const uripath = g_filename_to_uri(path.c_str(), nullptr, nullptr);
151 Glib::spawn_async("", { "xdg-open", uripath }, Glib::SpawnFlags::SEARCH_PATH);
152 g_free(uripath);
153#endif
154}
155
156std::vector<Gtk::Widget *> get_children(Gtk::Widget &widget)
157{
158 auto children = std::vector<Gtk::Widget *>{};
159 for (auto child = widget.get_first_child(); child; child = child->get_next_sibling()) {
160 children.push_back(child);
161 }
162 return children;
163}
164
165Gtk::Widget &get_nth_child(Gtk::Widget &widget, std::size_t const index)
166{
167 auto child = widget.get_first_child();
168 for (std::size_t i = 0; true; ++i) {
169 if (!child) throw std::out_of_range{"get_nth_child()"};
170 if (i == index) break;
171 child = child->get_next_sibling();
172 }
173 return *child;
174}
175
184Gtk::Widget *find_widget_by_name(Gtk::Widget &parent, Glib::ustring const &name, bool visible_only)
185{
186 return for_each_descendant(parent, [&](auto const &widget) {
187 if (visible_only && !widget.get_visible()) return ForEachResult::_skip;
188
189 return widget.get_name().raw() == name.raw() ? ForEachResult::_break : ForEachResult::_continue;
190 });
191}
192
200Gtk::Widget *find_focusable_widget(Gtk::Widget &parent)
201{
202 return for_each_descendant(parent, [](auto const &widget)
203 { return widget.get_focusable() ? ForEachResult::_break : ForEachResult::_continue; });
204}
205
210bool is_descendant_of(Gtk::Widget const &descendant, Gtk::Widget const &ancestor)
211{
212 return nullptr != for_each_parent(const_cast<Gtk::Widget &>(descendant), [&](auto const &parent)
213 { return &parent == &ancestor ? ForEachResult::_break : ForEachResult::_continue; });
214}
215
219bool contains_focus(Gtk::Widget &widget)
220{
221 if (widget.has_focus()) {
222 return true;
223 }
224
225 Gtk::Root const *root = widget.get_root();
226 if (!root) {
227 return false;
228 }
229
230 Gtk::Widget const *focused = root->get_focus();
231 if (!focused) {
232 return false;
233 }
234
235 return focused->is_ancestor(widget);
236}
237
239int get_font_size(Gtk::Widget &widget)
240{
241 auto pango_context = widget.get_pango_context();
242 auto font_description = pango_context->get_font_description();
243 double font_size = font_description.get_size();
244 font_size /= Pango::SCALE;
245 if (font_description.get_size_is_absolute()) {
246 font_size *= 0.75;
247 }
248 return font_size;
249}
250
251void ellipsize(Gtk::Label &label, int const max_width_chars, Pango::EllipsizeMode const mode)
252{
253 if (max_width_chars <= 0) return;
254
255 label.set_max_width_chars(max_width_chars);
256 label.set_ellipsize(mode);
257 label.set_has_tooltip(true);
258 label.signal_query_tooltip().connect([&](int, int, bool,
259 Glib::RefPtr<Gtk::Tooltip> const &tooltip)
260 {
261 if (!label.get_layout()->is_ellipsized()) return false;
262
263 tooltip->set_text(label.get_text());
264 return true;
265 }, true);
266}
267
268} // namespace Inkscape::UI
269
275unsigned int get_color_value(const Glib::ustring color)
276{
277 Gdk::RGBA gdk_color = Gdk::RGBA(color);
278 return SP_RGBA32_F_COMPOSE(gdk_color.get_red(), gdk_color.get_green(),
279 gdk_color.get_blue(), gdk_color.get_alpha());
280}
281
282
283Gdk::RGBA mix_colors(const Gdk::RGBA& a, const Gdk::RGBA& b, float ratio) {
284 auto lerp = [](double v0, double v1, double t){ return (1.0 - t) * v0 + t * v1; };
285 Gdk::RGBA result;
286 result.set_rgba(
287 lerp(a.get_red(), b.get_red(), ratio),
288 lerp(a.get_green(), b.get_green(), ratio),
289 lerp(a.get_blue(), b.get_blue(), ratio),
290 lerp(a.get_alpha(), b.get_alpha(), ratio)
291 );
292 return result;
293}
294
295double get_luminance(Gdk::RGBA const &rgba)
296{
297 // This formula is recommended at https://www.w3.org/TR/AERT/#color-contrast
298 return 0.299 * rgba.get_red ()
299 + 0.587 * rgba.get_green()
300 + 0.114 * rgba.get_blue ();
301}
302
303Gdk::RGBA get_color_with_class(Gtk::Widget &widget,
304 Glib::ustring const &css_class)
305{
306 if (!css_class.empty()) widget.add_css_class(css_class);
307 auto result = widget.get_color();
308 if (!css_class.empty()) widget.remove_css_class(css_class);
309 return result;
310}
311
312guint32 to_guint32(Gdk::RGBA const &rgba)
313{
314 return static_cast<guint32>(0xFF * rgba.get_red () + 0.5) << 24 |
315 static_cast<guint32>(0xFF * rgba.get_green() + 0.5) << 16 |
316 static_cast<guint32>(0xFF * rgba.get_blue () + 0.5) << 8 |
317 static_cast<guint32>(0xFF * rgba.get_alpha() + 0.5);
318}
319
321{
322 return to_rgba(color.toRGBA());
323}
324
325Gdk::RGBA to_rgba(guint32 const u32)
326{
327 auto rgba = Gdk::RGBA{};
328 rgba.set_red (((u32 & 0xFF000000) >> 24) / 255.0);
329 rgba.set_green(((u32 & 0x00FF0000) >> 16) / 255.0);
330 rgba.set_blue (((u32 & 0x0000FF00) >> 8) / 255.0);
331 rgba.set_alpha(((u32 & 0x000000FF) ) / 255.0);
332 return rgba;
333}
334
340Glib::ustring gdk_to_css_color(const Gdk::RGBA& color) {
341 return Inkscape::Colors::rgba_to_hex(to_guint32(color), true);
342}
343Gdk::RGBA css_color_to_gdk(const char *value) {
344 try {
345 return to_rgba(value ? Inkscape::Colors::hex_to_rgba(value) : 0x0);
346 } catch (Inkscape::Colors::ColorError &e) {
347 return {};
348 }
349}
350
351// 2Geom <-> Cairo
352
353Cairo::RectangleInt geom_to_cairo(const Geom::IntRect &rect)
354{
355 return Cairo::RectangleInt{rect.left(), rect.top(), rect.width(), rect.height()};
356}
357
358Geom::IntRect cairo_to_geom(const Cairo::RectangleInt &rect)
359{
360 return Geom::IntRect::from_xywh(rect.x, rect.y, rect.width, rect.height);
361}
362
363Cairo::Matrix geom_to_cairo(const Geom::Affine &affine)
364{
365 return Cairo::Matrix(affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]);
366}
367
368Geom::IntPoint dimensions(const Cairo::RefPtr<Cairo::ImageSurface> &surface)
369{
370 return Geom::IntPoint(surface->get_width(), surface->get_height());
371}
372
373Geom::IntPoint dimensions(const Gdk::Rectangle &allocation)
374{
375 return Geom::IntPoint(allocation.get_width(), allocation.get_height());
376}
377
378std::vector<GskColorStop> create_cubic_gradient(
379 const Gdk::RGBA& from,
380 const Gdk::RGBA& to,
381 Geom::Point ctrl1,
382 Geom::Point ctrl2,
383 Geom::Point p0,
384 Geom::Point p1,
385 int steps
386) {
387 // validate input points
388 for (auto&& pt : {p0, ctrl1, ctrl2, p1}) {
389 if (pt.x() < 0 || pt.x() > 1 ||
390 pt.y() < 0 || pt.y() > 1) {
391 throw std::invalid_argument("Invalid points for cubic gradient; 0..1 coordinates expected.");
392 }
393 }
394 if (steps < 2 || steps > 999) {
395 throw std::invalid_argument("Invalid number of steps for cubic gradient; 2 to 999 steps expected.");
396 }
397
398 std::vector<GskColorStop> result;
399
400 --steps;
401 for (int step = 0; step <= steps; ++step) {
402 auto t = static_cast<double>(step) / steps;
403 auto p = Geom::bernstein_value_at(t, std::begin({p0, ctrl1, ctrl2, p1}), 3);
404
405 float offset = p.x();
406 float ratio = p.y();
407
408 result.push_back(GskColorStop{
409 .offset = offset,
410 .color = *mix_colors(from, to, ratio).gobj()
411 });
412 }
413
414 return result;
415}
416
417Gdk::RGBA change_alpha(const Gdk::RGBA& color, double new_alpha) {
418 auto copy(color);
419 copy.set_alpha(new_alpha);
420 return copy;
421}
422
423uint32_t conv_gdk_color_to_rgba(const Gdk::RGBA& color, double replace_alpha) {
424 auto alpha = replace_alpha >= 0 ? replace_alpha : color.get_alpha();
425 auto rgba =
426 uint32_t(0xff * color.get_red()) << 24 |
427 uint32_t(0xff * color.get_green()) << 16 |
428 uint32_t(0xff * color.get_blue()) << 8 |
429 uint32_t(0xff * alpha);
430 return rgba;
431}
432
433void set_dark_titlebar(Glib::RefPtr<Gdk::Surface> const &surface, bool is_dark)
434{
435#if (defined (_WIN32) || defined (_WIN64))
436 if (surface->gobj()) {
437 BOOL w32_darkmode = is_dark;
438 HWND hwnd = (HWND)gdk_win32_surface_get_handle((GdkSurface*)surface->gobj());
439 if (DwmSetWindowAttribute) {
440 DWORD attr = DWMWA_USE_IMMERSIVE_DARK_MODE;
441 if (FAILED(DwmSetWindowAttribute(hwnd, attr, &w32_darkmode, sizeof(w32_darkmode)))) {
442 attr = DWMWA_USE_IMMERSIVE_DARK_MODE_OLD;
443 DwmSetWindowAttribute(hwnd, attr, &w32_darkmode, sizeof(w32_darkmode));
444 }
445 }
446 }
447#endif
448}
449
450// round_numbers helper callback
451static int fmt_number(const _GMatchInfo* match, _GString* ret, void* prec) {
452 auto number = g_match_info_fetch(match, 1);
453
454 char* end = nullptr;
455 double val = g_ascii_strtod(number, &end);
456 if (*number && (end == nullptr || end > number)) {
457 auto precision = *static_cast<int*>(prec);
458 auto fmt = Inkscape::Util::format_number(val, precision);
459 g_string_append(ret, fmt.c_str());
460 } else {
461 g_string_append(ret, number);
462 }
463
464 auto text = g_match_info_fetch(match, 2);
465 g_string_append(ret, text);
466
467 g_free(number);
468 g_free(text);
469
470 return false;
471}
472
473Glib::ustring round_numbers(const Glib::ustring& text, int precision) {
474 // match floating point number followed by something else (not a number); repeat
475 static const auto numbers = Glib::Regex::create("([-+]?(?:(?:\\d+\\.?\\d*)|(?:\\.\\d+))(?:[eE][-+]?\\d*)?)([^+\\-0-9]*)", Glib::Regex::CompileFlags::MULTILINE);
476
477 return numbers->replace_eval(text, text.size(), 0, Glib::Regex::MatchFlags::NOTEMPTY, &fmt_number, &precision);
478}
479
480// Round the selected floating point numbers in the attribute edit popover.
481void truncate_digits(const Glib::RefPtr<Gtk::TextBuffer>& buffer, int precision) {
482 if (!buffer) return;
483
484 auto start = buffer->begin();
485 auto end = buffer->end();
486
487 bool had_selection = buffer->get_has_selection();
488 int start_idx = 0, end_idx = 0;
489 if (had_selection) {
490 buffer->get_selection_bounds(start, end);
491 start_idx = start.get_offset();
492 end_idx = end.get_offset();
493 }
494
495 auto text = buffer->get_text(start, end);
496 auto ret = round_numbers(text, precision);
497 buffer->erase(start, end);
498 buffer->insert_at_cursor(ret);
499
500 if (had_selection) {
501 // Restore selection but note that its length may have decreased.
502 end_idx -= text.size() - ret.size();
503 if (end_idx < start_idx) {
504 end_idx = start_idx;
505 }
506 buffer->select_range(buffer->get_iter_at_offset(start_idx), buffer->get_iter_at_offset(end_idx));
507 }
508}
509
510Glib::RefPtr<Gdk::Texture> to_texture(Cairo::RefPtr<Cairo::Surface> const &surface)
511{
512 if (!surface) {
513 return {};
514 }
515
516 assert(surface->get_type() == Cairo::Surface::Type::IMAGE);
517
518 auto img = Cairo::ImageSurface(surface->cobj());
519 assert(img.get_format() == Cairo::ImageSurface::Format::ARGB32);
520
521 auto bytes = g_bytes_new_with_free_func(img.get_data(),
522 img.get_stride() * img.get_height(),
523 (GDestroyNotify)cairo_surface_destroy,
524 cairo_surface_reference(surface->cobj()));
525
526 auto texture = gdk_memory_texture_new(img.get_width(),
527 img.get_height(),
528 GDK_MEMORY_DEFAULT,
529 bytes,
530 img.get_stride());
531
532 g_bytes_unref(bytes);
533
534 return Glib::wrap(texture);
535}
536
537void restrict_minsize_to_square(Gtk::Widget& widget, int min_size_px) {
538 auto name = widget.get_name();
539 assert(!name.empty());
540 auto css = Gtk::CssProvider::create();
541 std::ostringstream ost;
542 ost << "#" << name << " {min-width:" << min_size_px << "px; min-height:" << min_size_px << "px;}";
543 css->load_from_string(ost.str());
544 auto style_context = widget.get_style_context();
545 // load with a priority higher than that of the "style.css"
546 style_context->add_provider(css, GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 2);
547}
548
549char const *get_text(Gtk::Editable const &editable)
550{
551 return gtk_editable_get_text(const_cast<GtkEditable *>(editable.gobj())); // C API is const-incorrect
552}
553
554/*
555 Local Variables:
556 mode:c++
557 c-file-style:"stroustrup"
558 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
559 indent-tabs-mode:nil
560 fill-column:99
561 End:
562*/
563// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Bernstein-Bezier polynomial.
Cairo::RefPtr< Cairo::ImageSurface > surface
Definition canvas.cpp:137
3x3 matrix representing an affine transformation.
Definition affine.h:70
Axis aligned, non-empty, generic rectangle.
static CRect from_xywh(C x, C y, C w, C h)
Create rectangle from origin and dimensions.
C top() const
Return top coordinate of the rectangle (+Y is downwards).
C left() const
Return leftmost coordinate of the rectangle (+X is to the right).
C height() const
Get the vertical extent of the rectangle.
C width() const
Get the horizontal extent of the rectangle.
Two-dimensional point with integer coordinates.
Definition int-point.h:57
Two-dimensional point that doubles as a vector.
Definition point.h:66
uint32_t toRGBA(double opacity=1.0) const
Return an sRGB conversion of the color in RGBA int32 format.
Definition color.cpp:117
constexpr uint32_t SP_RGBA32_F_COMPOSE(double r, double g, double b, double a)
Definition utils.h:64
RootCluster root
Utility functions to convert ascii representations to numbers.
std::shared_ptr< Css const > css
Css & result
Glib::ustring msg
Editable view implementation.
static char const *const parent
Definition dir-util.cpp:70
unsigned int guint32
Inkscape - An SVG editor.
double offset
Geom::Point start
Glib::ustring label
Geom::Point end
T bernstein_value_at(double t, T const *c_, unsigned n)
Compute the value of a Bernstein-Bezier polynomial.
Definition bezier.h:55
uint32_t hex_to_rgba(std::string const &value)
Parse a color directly without any CSS or CMS support.
Definition utils.cpp:32
std::string rgba_to_hex(uint32_t value, bool alpha)
Output the RGBA value as a #RRGGBB hex color, if alpha is true then the output will be #RRGGBBAA inst...
Definition utils.cpp:70
User interface code.
Definition desktop.h:113
Gtk::Widget * for_each_parent(Gtk::Widget &widget, Func &&func)
Call Func with a reference to successive parents, until Func returns _break.
Definition util.h:139
void set_icon_sizes(Gtk::Widget *parent, int pixel_size)
Recursively set all the icon sizes inside this parent widget.
Definition util.cpp:113
void gui_warning(const std::string &msg, Gtk::Window *parent_window)
Definition util.cpp:134
Gtk::Widget & get_nth_child(Gtk::Widget &widget, std::size_t const index)
Get the widgetʼs child at the given position. Throws std::out_of_range if the index is invalid.
Definition util.cpp:165
Gtk::Widget * for_each_descendant(Gtk::Widget &widget, Func &&func)
Like for_each_child() but also tests the initial widget & recurses through childrenʼs children.
Definition util.h:132
Gtk::Widget * find_widget_by_name(Gtk::Widget &parent, Glib::ustring const &name, bool visible_only)
Returns a named descendent of parent, which has the given name, or nullptr if there's none.
Definition util.cpp:184
bool is_descendant_of(Gtk::Widget const &descendant, Gtk::Widget const &ancestor)
Returns if widget is a descendant of given ancestor, i.e.: itself, a child, or a childʼs child.
Definition util.cpp:210
int get_font_size(Gtk::Widget &widget)
Get the relative font size as determined by a widgetʼs style/Pango contexts.
Definition util.cpp:239
std::vector< Gtk::Widget * > get_children(Gtk::Widget &widget)
Get a vector of the widgetʼs children, from get_first_child() through each get_next_sibling().
Definition util.cpp:156
void ellipsize(Gtk::Label &label, int const max_width_chars, Pango::EllipsizeMode const mode)
Definition util.cpp:251
int dialog_run(Gtk::Dialog &dialog)
This is a GTK4 porting aid meant to replace the removal of the Gtk::Dialog synchronous API.
void system_open(const Glib::ustring &path)
Opens the given path with platform-specific tools.
Definition util.cpp:143
bool contains_focus(Gtk::Widget &widget)
Returns if widget or one of its descendants has focus.
Definition util.cpp:219
Gtk::Widget * find_focusable_widget(Gtk::Widget &parent)
This function traverses a tree of widgets searching for first focusable widget.
Definition util.cpp:200
std::string format_number(double val, unsigned int precision=3)
Definition converters.h:110
int mode
Ocnode * child[8]
Definition quantize.cpp:33
int const char * fmt
Definition safe-printf.h:18
int BOOL
Definition splinefont.h:13
int index
Glib::ustring name
Definition toolbars.cpp:55
Glib::ustring ink_ellipsize_text(Glib::ustring const &src, std::size_t maxlen)
Definition util.cpp:67
Glib::ustring round_numbers(const Glib::ustring &text, int precision)
Definition util.cpp:473
unsigned int get_color_value(const Glib::ustring color)
Color is store as a string in the form #RRGGBBAA, '0' means "unset".
Definition util.cpp:275
Glib::RefPtr< Gdk::Texture > to_texture(Cairo::RefPtr< Cairo::Surface > const &surface)
Convert an image surface in ARGB32 format to a texture.
Definition util.cpp:510
Gdk::RGBA to_rgba(guint32 const u32)
Definition util.cpp:325
Cairo::RectangleInt geom_to_cairo(const Geom::IntRect &rect)
Definition util.cpp:353
guint32 to_guint32(Gdk::RGBA const &rgba)
Definition util.cpp:312
std::vector< GskColorStop > create_cubic_gradient(const Gdk::RGBA &from, const Gdk::RGBA &to, Geom::Point ctrl1, Geom::Point ctrl2, Geom::Point p0, Geom::Point p1, int steps)
Definition util.cpp:378
Gdk::RGBA css_color_to_gdk(const char *value)
Definition util.cpp:343
uint32_t conv_gdk_color_to_rgba(const Gdk::RGBA &color, double replace_alpha)
Definition util.cpp:423
void restrict_minsize_to_square(Gtk::Widget &widget, int min_size_px)
Definition util.cpp:537
bool is_widget_effectively_visible(Gtk::Widget const *widget)
Definition util.cpp:97
static int fmt_number(const _GMatchInfo *match, _GString *ret, void *prec)
Definition util.cpp:451
Gdk::RGBA get_color_with_class(Gtk::Widget &widget, Glib::ustring const &css_class)
Definition util.cpp:303
double get_luminance(Gdk::RGBA const &rgba)
Calculate luminance of an RGBA color from its RGB in range 0 to 1 inclusive.
Definition util.cpp:295
char const * get_text(Gtk::Editable const &editable)
Get the text from a GtkEditable without the temporary copy imposed by gtkmm.
Definition util.cpp:549
Gdk::RGBA change_alpha(const Gdk::RGBA &color, double new_alpha)
Definition util.cpp:417
Gdk::RGBA mix_colors(const Gdk::RGBA &a, const Gdk::RGBA &b, float ratio)
Definition util.cpp:283
Geom::IntRect cairo_to_geom(const Cairo::RectangleInt &rect)
Definition util.cpp:358
void reveal_widget(Gtk::Widget *widget, bool show)
Show widget, if the widget has a Gtk::Reveal parent, reveal instead.
Definition util.cpp:83
void truncate_digits(const Glib::RefPtr< Gtk::TextBuffer > &buffer, int precision)
Definition util.cpp:481
void set_dark_titlebar(Glib::RefPtr< Gdk::Surface > const &surface, bool is_dark)
Definition util.cpp:433
Gdk::RGBA color_to_rgba(Inkscape::Colors::Color const &color)
Definition util.cpp:320
Glib::ustring gdk_to_css_color(const Gdk::RGBA &color)
These GUI related color conversions allow us to convert from SVG xml attributes to Gdk colors,...
Definition util.cpp:340
Geom::IntPoint dimensions(const Cairo::RefPtr< Cairo::ImageSurface > &surface)
Definition util.cpp:368