Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
stroke_raster.h
Go to the documentation of this file.
1/*
2 This file is part of Ansel,
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#ifndef DT_WIDGETS_STROKE_RASTER_H
20#define DT_WIDGETS_STROKE_RASTER_H
21
22/* A stroke rasteriser for GUI overlays.
23 *
24 * An overlay line -- a mask's outline, its feather border -- arrives as a polyline already
25 * sampled at the resolution it is shown at: one vertex per device pixel or so. Handing that to
26 * cairo means turning pixels back into a vector path and asking a general-purpose stroker to
27 * tessellate and rasterise it, twice per line (a wide dark pass under a narrow bright one). What
28 * the overlays actually use of a stroker is small and fixed: two widths, two colours with alpha,
29 * two dash patterns, round or butt caps, and a one-pixel antialiasing ramp. This is that, and
30 * nothing more, painting straight into the ARGB32 pixels of the surface the overlay is drawn on.
31 *
32 * It knows nothing about masks, nodes or handles. Everything drawn with a cairo primitive that
33 * is NOT a long polyline -- discs, arcs, arrows, the CLEAR-operator punch under a node -- stays
34 * with cairo, on the same surface, before or after these strokes as the caller likes.
35 *
36 * The coverage model is a distance field: for every pixel within reach of a polyline, the
37 * distance to the nearest point of it (a union of capsules, one per segment, so joins and caps
38 * come out round with no seams). Coverage of a pass of half-width R is clamp(R + 1/2 - d, 0, 1),
39 * the same one-pixel ramp CAIRO_ANTIALIAS_FAST draws. Dashes are cut along the polyline's arc
40 * length before the capsules are stamped, so a dash end is a round cap exactly as cairo's
41 * CAIRO_LINE_CAP_ROUND makes it. Compositing is premultiplied OVER, dark pass then bright pass,
42 * which is what the two cairo_stroke() calls it replaces composed. */
43
44#include <cairo.h>
45#include <glib.h>
46
47G_BEGIN_DECLS
48
50typedef struct dt_stroke_pass_t
51{
52 double width;
53 double red;
54 double green;
55 double blue;
56 double alpha;
58
69
71gboolean dt_stroke_raster_can_paint(cairo_surface_t *surface);
72
77gboolean dt_stroke_raster_polyline(cairo_surface_t *surface, const double *xy, int count,
78 const dt_stroke_style_t *style);
79
86gboolean dt_stroke_raster_path(cairo_t *cr, const dt_stroke_style_t *style);
87
91gboolean dt_stroke_raster_touched(cairo_surface_t *surface, cairo_rectangle_int_t *touched);
92
94void dt_stroke_raster_touched_reset(cairo_surface_t *surface);
95
96G_END_DECLS
97
98#endif // DT_WIDGETS_STROKE_RASTER_H
99
100// clang-format off
101// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
102// vim: shiftwidth=2 expandtab tabstop=2 cindent
103// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
104// clang-format on
void dt_stroke_raster_touched_reset(cairo_surface_t *surface)
gboolean dt_stroke_raster_polyline(cairo_surface_t *surface, const double *xy, int count, const dt_stroke_style_t *style)
gboolean dt_stroke_raster_path(cairo_t *cr, const dt_stroke_style_t *style)
gboolean dt_stroke_raster_can_paint(cairo_surface_t *surface)
gboolean dt_stroke_raster_touched(cairo_surface_t *surface, cairo_rectangle_int_t *touched)
dt_stroke_pass_t dark
dt_stroke_pass_t bright