Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
drawing-utils.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2
3#include "drawing-utils.h"
4
5namespace Inkscape::Util {
6
7Geom::Rect rounded_rectangle(const Cairo::RefPtr<Cairo::Context>& ctx, const Geom::Rect& rect, double radius) {
8 auto x = rect.left();
9 auto y = rect.top();
10 auto width = rect.width();
11 auto height = rect.height();
12 if (radius > 0) {
13 ctx->arc(x + width - radius, y + radius, radius, -M_PI_2, 0);
14 ctx->arc(x + width - radius, y + height - radius, radius, 0, M_PI_2);
15 ctx->arc(x + radius, y + height - radius, radius, M_PI_2, M_PI);
16 ctx->arc(x + radius, y + radius, radius, M_PI, 3 * M_PI_2);
17 ctx->close_path();
18 }
19 else {
20 ctx->move_to(x, y);
21 ctx->line_to(x + width, y);
22 ctx->line_to(x + width, y + width);
23 ctx->line_to(x, y + width);
24 ctx->close_path();
25 }
26 return rect.shrunkBy(1);
27}
28
29void circle(const Cairo::RefPtr<Cairo::Context>& ctx, const Geom::Point& center, double radius) {
30 ctx->arc(center.x(), center.y(), radius, 0, 2 * M_PI);
31}
32
33// draw relief around the given rect to stop colors inside blend with background outside
34void draw_border(const Cairo::RefPtr<Cairo::Context>& ctx, Geom::Rect rect, double radius, const Gdk::RGBA& color, int device_scale, bool circular) {
35 if (rect.width() < 1 || rect.height() < 1) return;
36
37 if (device_scale > 1) {
38 // there's one physical pixel overhang on high-dpi display, so eliminate that:
39 auto pix = 1.0 / device_scale;
40 rect = Geom::Rect::from_xywh(rect.min().x(), rect.min().y(), rect.width() - pix, rect.height() - pix);
41 }
42 ctx->save();
43 // operate on physical pixels
44 ctx->scale(1.0 / device_scale, 1.0 / device_scale);
45 // align 1.0 wide stroke to pixel grid
46 ctx->translate(0.5, 0.5);
47 ctx->set_line_width(1.0);
48 radius *= device_scale;
49 // shadow depth
50 const int steps = 3 * device_scale;
51 auto alpha = color.get_alpha();
52 ctx->set_operator(Cairo::Context::Operator::OVER);
53 // rect in physical pixels
54 rect = Geom::Rect(rect.min() * device_scale, rect.max() * device_scale);
55 for (int i = 0; i < steps; ++i) {
56 if (circular) {
57 circle(ctx, rect.midpoint(), rect.minExtent() / 2);
58 rect.shrinkBy(1);
59 }
60 else {
61 rect = rounded_rectangle(ctx, rect, radius--);
62 }
63 ctx->set_source_rgba(color.get_red(), color.get_green(), color.get_blue(), alpha);
64 ctx->stroke();
65 alpha *= 0.5;
66 }
67 ctx->restore();
68}
69
70void draw_standard_border(const Cairo::RefPtr<Cairo::Context>& ctx, Geom::Rect rect, bool dark_theme, double radius, int device_scale, bool circular) {
71 auto color = dark_theme ? Gdk::RGBA(1, 1, 1, 0.25) : Gdk::RGBA(0, 0, 0, 0.25);
72 draw_border(ctx, rect, radius, color, device_scale, circular);
73}
74
75std::optional<Gdk::RGBA> lookup_background_color(Glib::RefPtr<Gtk::StyleContext>& style) {
76 Gdk::RGBA color;
77 if (style && style->lookup_color("theme_bg_color", color)) {
78 return color;
79 }
80 return {};
81}
82
83std::optional<Gdk::RGBA> lookup_foreground_color(Glib::RefPtr<Gtk::StyleContext>& style) {
84 Gdk::RGBA color;
85 if (style && style->lookup_color("theme_fg_color", color)) {
86 return color;
87 }
88 return {};
89}
90
91}
static CRect from_xywh(Coord x, Coord y, Coord w, Coord h)
Create rectangle from origin and dimensions.
C top() const
Return top coordinate of the rectangle (+Y is downwards).
void shrinkBy(C amount)
Shrink the rectangle in both directions by the specified amount.
CPoint midpoint() const
Get the point in the geometric center of the rectangle.
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 minExtent() const
Get the smaller extent (width or height) of the rectangle.
C width() const
Get the horizontal extent of the rectangle.
CPoint min() const
Get the corner of the rectangle with smallest coordinate values.
CPoint max() const
Get the corner of the rectangle with largest coordinate values.
Two-dimensional point that doubles as a vector.
Definition point.h:66
constexpr Coord y() const noexcept
Definition point.h:106
constexpr Coord x() const noexcept
Definition point.h:104
Axis aligned, non-empty rectangle.
Definition rect.h:92
Rect shrunkBy(Coord amount) const
Return a new rectangle which results from shrinking this one by the same amount along both axes.
Definition rect.cpp:144
Miscellaneous supporting code.
Definition document.h:93
Geom::Rect rounded_rectangle(const Cairo::RefPtr< Cairo::Context > &ctx, const Geom::Rect &rect, double radius)
std::optional< Gdk::RGBA > lookup_background_color(Glib::RefPtr< Gtk::StyleContext > &style)
std::optional< Gdk::RGBA > lookup_foreground_color(Glib::RefPtr< Gtk::StyleContext > &style)
void draw_border(const Cairo::RefPtr< Cairo::Context > &ctx, Geom::Rect rect, double radius, const Gdk::RGBA &color, int device_scale, bool circular)
void circle(const Cairo::RefPtr< Cairo::Context > &ctx, const Geom::Point &center, double radius)
void draw_standard_border(const Cairo::RefPtr< Cairo::Context > &ctx, Geom::Rect rect, bool dark_theme, double radius, int device_scale, bool circular)
double height
double width