Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
canvas.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <cmath>
5#include <cstdint>
6#include <cstring>
10#include <pulp/canvas/path.hpp>
14#include <string>
15#include <vector>
16#include <memory>
17#include <optional>
18#include <variant>
19#include <functional>
20
21namespace pulp::canvas {
22
37
38constexpr const char* renderer_backend_name(RendererBackend backend) noexcept {
39 switch (backend) {
40 case RendererBackend::unknown: return "unknown";
41 case RendererBackend::recording: return "recording";
42 case RendererBackend::core_graphics: return "core_graphics";
43 case RendererBackend::skia_raster: return "skia_raster";
44 case RendererBackend::skia_ganesh: return "skia_ganesh";
45 case RendererBackend::skia_dawn: return "skia_dawn";
46 }
47 return "unknown";
48}
49
50// ── Color ────────────────────────────────────────────────────────────────────
51
52struct Color {
53 float r = 0.0f, g = 0.0f, b = 0.0f, a = 1.0f;
54
56 static constexpr Color rgba(float r, float g, float b, float a = 1.0f) {
57 return {r, g, b, a};
58 }
59
61 static constexpr Color rgba8(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255) {
62 return {r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f};
63 }
64
66 static Color hex(uint32_t rgb) {
67 return rgba8(static_cast<uint8_t>((rgb >> 16) & 0xFF),
68 static_cast<uint8_t>((rgb >> 8) & 0xFF),
69 static_cast<uint8_t>(rgb & 0xFF));
70 }
71
72 // ── Color space conversions ─────────────────────────────────────
73
74 struct HSV { float h = 0, s = 0, v = 0; };
75 struct HSL { float h = 0, s = 0, l = 0; };
76 struct OKLCH { float L = 0, C = 0, h = 0; };
77
79 HSV to_hsv() const;
80 static Color from_hsv(HSV hsv, float alpha = 1.0f);
81
83 HSL to_hsl() const;
84 static Color from_hsl(HSL hsl, float alpha = 1.0f);
85
88 OKLCH to_oklch() const;
89 static Color from_oklch(OKLCH oklch, float alpha = 1.0f);
90
92 void encode(uint8_t* out) const;
93 static Color decode(const uint8_t* data);
94
95 // ── Color math ──────────────────────────────────────────────────
96
98 Color interpolate(const Color& other, float t) const {
99 return {r + (other.r - r) * t,
100 g + (other.g - g) * t,
101 b + (other.b - b) * t,
102 a + (other.a - a) * t};
103 }
104
106 Color with_hdr_intensity(float multiplier) const {
107 return {r * multiplier, g * multiplier, b * multiplier, a};
108 }
109
111 Color with_alpha(float alpha) const {
112 return {r, g, b, alpha};
113 }
114
116 uint8_t r8() const { return static_cast<uint8_t>(std::clamp(r, 0.0f, 1.0f) * 255.0f + 0.5f); }
117 uint8_t g8() const { return static_cast<uint8_t>(std::clamp(g, 0.0f, 1.0f) * 255.0f + 0.5f); }
118 uint8_t b8() const { return static_cast<uint8_t>(std::clamp(b, 0.0f, 1.0f) * 255.0f + 0.5f); }
119 uint8_t a8() const { return static_cast<uint8_t>(std::clamp(a, 0.0f, 1.0f) * 255.0f + 0.5f); }
120
122 uint32_t to_argb32() const {
123 return (static_cast<uint32_t>(a8()) << 24) |
124 (static_cast<uint32_t>(r8()) << 16) |
125 (static_cast<uint32_t>(g8()) << 8) |
126 static_cast<uint32_t>(b8());
127 }
128
130 static Color from_argb32(uint32_t argb) {
131 return rgba8(static_cast<uint8_t>((argb >> 16) & 0xFF),
132 static_cast<uint8_t>((argb >> 8) & 0xFF),
133 static_cast<uint8_t>(argb & 0xFF),
134 static_cast<uint8_t>((argb >> 24) & 0xFF));
135 }
136
137 bool operator==(const Color& other) const {
138 return r == other.r && g == other.g && b == other.b && a == other.a;
139 }
140 bool operator!=(const Color& other) const { return !(*this == other); }
141};
142
143// ── Paint ────────────────────────────────────────────────────────────────────
144
146 float position; // 0.0 to 1.0
148};
149
151 float x0, y0, x1, y1;
152 std::vector<GradientStop> stops;
153};
154
156 float cx, cy, radius;
157 float focal_x = 0, focal_y = 0;
158 std::vector<GradientStop> stops;
159};
160
163 float cx, cy;
165 std::vector<GradientStop> stops;
166};
167
170
174public:
175 FillStyle() = default;
176 FillStyle(Color c) : color_(c) {} // NOLINT: implicit for convenience
177 FillStyle(LinearGradient g) : linear_(std::move(g)), type_(1) {}
178 FillStyle(RadialGradient g) : radial_(std::move(g)), type_(2) {}
179 FillStyle(ConicGradient g) : conic_(std::move(g)), type_(3) {}
180
181 bool is_solid() const { return type_ == 0; }
182 bool is_linear() const { return type_ == 1; }
183 bool is_radial() const { return type_ == 2; }
184 bool is_conic() const { return type_ == 3; }
185
186 const Color& color() const { return color_; }
187 const LinearGradient& linear() const { return linear_; }
188 const RadialGradient& radial() const { return radial_; }
189 const ConicGradient& conic() const { return conic_; }
190
191 GradientTileMode tile_mode() const { return tile_mode_; }
192 void set_tile_mode(GradientTileMode m) { tile_mode_ = m; }
193
194private:
195 Color color_;
196 LinearGradient linear_;
197 RadialGradient radial_;
198 ConicGradient conic_;
199 int type_ = 0; // 0=solid, 1=linear, 2=radial, 3=conic
201};
202
203using Paint = std::variant<Color, LinearGradient, RadialGradient, ConicGradient>;
204
205// ── Drawing commands ─────────────────────────────────────────────────────────
206
207// LineCap, LineJoin, and FillRule are defined in <pulp/canvas/path.hpp> — the
208// retained Path value type needs them and sits BELOW this header, so they live
209// there and are used unqualified here (same namespace, one definition).
210//
211// FillRule is the Canvas2D fill rule for fill() / clip(). It mirrors the
212// spec's ('nonzero' | 'evenodd') string enum; the default 'nonzero' matches
213// CSS behavior and the JS shim's fillRule==='evenodd'?1:0 mapping in
214// `core/view/js/web-compat-canvas.js`.
215// CSS / RN `text-align: justify`. SkiaCanvas dispatches `kJustify` via
216// SkParagraph when the backend supports it; CG / RecordingCanvas back-ends
217// approximate as `left` (no kerning-controlled space distribution) until full
218// SkParagraph integration lands. `auto` is resolved at the widget layer before
219// reaching the canvas: Label::paint translates it to `left` (LTR) or `right`
220// (RTL).
223// Canvas2D text baselines. `alphabetic` is the CSS/Canvas2D initial value:
224// the y passed to fill_text IS the baseline, which is what browser-authored
225// canvas code assumes when it never assigns ctx.textBaseline. `hanging` and
226// `ideographic` have no dedicated font metric here and are approximated from
227// ascent/descent, matching how engines fall back when the face carries no
228// BASE table. Enumerators are appended so the wire codes the widget bridge
229// records for top/middle/bottom keep their existing values.
232
233// CanvasCapability lives in its own header so capability-query call sites can
234// include just the enum; canvas.hpp re-exports it here for back-compat, so any
235// TU that includes canvas.hpp still sees CanvasCapability unchanged.
236
237// Abstract canvas for 2D drawing
238// Widgets paint against this interface. Concrete backends (Skia, CoreGraphics,
239// software) implement the virtual methods.
240class Canvas {
241public:
242 struct ShaderDrawOptions;
243 virtual ~Canvas() = default;
244
246 virtual RendererBackend renderer_backend() const noexcept {
248 }
249
253 virtual float backing_scale() const noexcept { return 1.0f; }
254
255 // ── State ────────────────────────────────────────────────────────────
256 virtual void save() = 0;
257 virtual void restore() = 0;
258
266 virtual int save_count() const { return 0; }
267
274 virtual void restore_to_count(int target) { (void)target; }
275
276 // ── Transform ────────────────────────────────────────────────────────
277 virtual void translate(float x, float y) = 0;
278 virtual void scale(float sx, float sy) = 0;
279 virtual void rotate(float radians) = 0;
280
289 virtual void set_transform(float a, float b, float c,
290 float d, float e, float f) {
291 (void)a; (void)b; (void)c; (void)d; (void)e; (void)f;
292 }
293
299
311 virtual void concat_transform(float a, float b, float c,
312 float d, float e, float f) {
313 (void)a; (void)b; (void)c; (void)d; (void)e; (void)f;
314 }
315
323 float a = 1.0f, b = 0.0f;
324 float c = 0.0f, d = 1.0f;
325 float e = 0.0f, f = 0.0f;
326 };
327
338 return {};
339 }
340
341 // ── Clipping ─────────────────────────────────────────────────────────
342 virtual void clip_rect(float x, float y, float w, float h) = 0;
343
348 virtual void clip(FillRule rule = FillRule::nonzero) { (void)rule; }
349
358 virtual void clip_path_svg(const std::string& svg_path_d) {
359 (void)svg_path_d;
360 }
361
362 // ── Fill and stroke style ────────────────────────────────────────────
363 virtual void set_fill_color(Color c) = 0;
364 virtual void set_stroke_color(Color c) = 0;
365 virtual void set_line_width(float w) = 0;
366 virtual void set_line_cap(LineCap cap) = 0;
367 virtual void set_line_join(LineJoin join) = 0;
368
377 virtual void set_miter_limit(float limit) { (void)limit; }
378
383
392 virtual void set_image_smoothing(bool enabled,
395 (void)enabled; (void)quality;
396 }
397
398 // ── Gradients ────────────────────────────────────────────────────────
400 virtual void set_fill_gradient_linear(float x0, float y0, float x1, float y1,
401 const Color* colors, const float* positions,
402 int count) {
403 if (count > 0) set_fill_color(colors[0]); // fallback: first color
404 }
405
407 virtual void set_fill_gradient_radial(float cx, float cy, float radius,
408 const Color* colors, const float* positions,
409 int count) {
410 if (count > 0) set_fill_color(colors[0]);
411 }
412
420 float cx, float cy, float rx, float ry,
421 const Color* colors, const float* positions, int count) {
422 (void)ry;
423 set_fill_gradient_radial(cx, cy, rx, colors, positions, count);
424 }
425
433 float x0, float y0, float r0,
434 float x1, float y1, float r1,
435 const Color* colors, const float* positions, int count) {
436 (void)x0; (void)y0; (void)r0;
437 set_fill_gradient_radial(x1, y1, r1, colors, positions, count);
438 }
439
441 virtual void set_fill_gradient_conic(float cx, float cy, float start_angle,
442 const Color* colors, const float* positions,
443 int count) {
444 if (count > 0) set_fill_color(colors[0]); // fallback
445 }
446
448 virtual void clear_fill_gradient() {}
449
450 // ── Stroke gradients ────────────────────────────────────────────────
451 //
452 // Mirror of the fill-gradient surface for `ctx.strokeStyle =
453 // createLinearGradient(...) | createRadialGradient(...) |
454 // createConicGradient(...)`. Defaults degrade to the first-stop
455 // color via `set_stroke_color`; SkiaCanvas overrides with real
456 // `SkShaders` gradient shaders stored on `stroke_shader_` so subsequent
457 // stroke paths
458 // (stroke_rect / stroke_current_path / stroke_text) pick the
459 // gradient up via `apply_stroke_state`.
460 virtual void set_stroke_gradient_linear(float x0, float y0, float x1, float y1,
461 const Color* colors, const float* positions,
462 int count) {
463 if (count > 0) set_stroke_color(colors[0]); // fallback: first color
464 }
465
466 virtual void set_stroke_gradient_radial(float cx, float cy, float radius,
467 const Color* colors, const float* positions,
468 int count) {
469 if (count > 0) set_stroke_color(colors[0]);
470 }
471
474 float x0, float y0, float r0,
475 float x1, float y1, float r1,
476 const Color* colors, const float* positions, int count) {
477 (void)x0; (void)y0; (void)r0;
478 set_stroke_gradient_radial(x1, y1, r1, colors, positions, count);
479 }
480
481 virtual void set_stroke_gradient_conic(float cx, float cy, float start_angle,
482 const Color* colors, const float* positions,
483 int count) {
484 if (count > 0) set_stroke_color(colors[0]);
485 }
486
488 virtual void clear_stroke_gradient() {}
489
498
505 virtual void set_fill_pattern(const std::string& image_src,
506 PatternTileMode tile_x,
507 PatternTileMode tile_y) {
508 (void)image_src; (void)tile_x; (void)tile_y;
509 }
510
514 virtual void set_stroke_pattern(const std::string& image_src,
515 PatternTileMode tile_x,
516 PatternTileMode tile_y) {
517 (void)image_src; (void)tile_x; (void)tile_y;
518 }
519
520 // ── Blend modes ─────────────────────────────────────────────────────
527 enum class BlendMode {
528 // Advanced (separable & non-separable W3C blend modes)
532 // Porter-Duff compositing modes
533 source_over, // 16 — alias for normal/source-over (CSS default)
541 xor_mode, // 24 — "xor" CSS string
542 copy, // 25
543 lighter // 26 — additive ("plus" / SVG kPlus)
544 };
545
547 virtual void set_blend_mode(BlendMode mode) { (void)mode; }
548
549 // ── Path building ───────────────────────────────────────────────────
551 virtual void begin_path() {}
553 virtual void move_to(float x, float y) { (void)x; (void)y; }
555 virtual void line_to(float x, float y) { (void)x; (void)y; }
557 virtual void quad_to(float cpx, float cpy, float x, float y) {
558 (void)cpx; (void)cpy; line_to(x, y); // fallback: straight line
559 }
560
561 virtual void cubic_to(float cp1x, float cp1y, float cp2x, float cp2y,
562 float x, float y) {
563 (void)cp1x; (void)cp1y; (void)cp2x; (void)cp2y; line_to(x, y);
564 }
565
572 virtual void arc(float cx, float cy, float radius,
573 float start_angle, float end_angle,
574 bool anticlockwise) {
575 (void)cx; (void)cy; (void)radius;
576 (void)start_angle; (void)end_angle; (void)anticlockwise;
577 }
578
582 virtual void arc_to(float x1, float y1, float x2, float y2, float radius) {
583 (void)x1; (void)y1; (void)x2; (void)y2; (void)radius;
584 }
585
589 virtual void ellipse(float cx, float cy, float rx, float ry,
590 float rotation,
591 float start_angle, float end_angle,
592 bool anticlockwise) {
593 (void)cx; (void)cy; (void)rx; (void)ry; (void)rotation;
594 (void)start_angle; (void)end_angle; (void)anticlockwise;
595 }
596
602 virtual void round_rect(float x, float y, float w, float h,
603 float tl_x, float tl_y,
604 float tr_x, float tr_y,
605 float br_x, float br_y,
606 float bl_x, float bl_y) {
607 (void)x; (void)y; (void)w; (void)h;
608 (void)tl_x; (void)tl_y; (void)tr_x; (void)tr_y;
609 (void)br_x; (void)br_y; (void)bl_x; (void)bl_y;
610 }
611
612 virtual void close_path() {}
616 (void)rule;
617 }
618
619 virtual void stroke_current_path() {}
620
621 // ── Bloom / Glow post-effect ────────────────────────────────────────
637 virtual void save_layer_with_bloom(float x, float y, float w, float h,
638 float intensity, float threshold,
639 float radius) {
640 save_layer(x, y, w, h, 1.0f, radius * intensity);
641 }
642
643 // ── Shapes ───────────────────────────────────────────────────────────
644 virtual void fill_rect(float x, float y, float w, float h) = 0;
645 virtual void stroke_rect(float x, float y, float w, float h) = 0;
646 virtual void fill_rounded_rect(float x, float y, float w, float h, float radius) = 0;
647 virtual void stroke_rounded_rect(float x, float y, float w, float h, float radius) = 0;
648 virtual void fill_circle(float cx, float cy, float radius) = 0;
649 virtual void stroke_circle(float cx, float cy, float radius) = 0;
650
660 virtual void clear_rect(float x, float y, float w, float h) {
661 // Default: best-effort SrcOver fill with transparent color. Pixel
662 // backends should override to use kSrc / kClear blend.
663 set_fill_color(Color::rgba(0.0f, 0.0f, 0.0f, 0.0f));
664 fill_rect(x, y, w, h);
665 }
666
667 // ── Arcs ─────────────────────────────────────────────────────────────
668 virtual void stroke_arc(float cx, float cy, float radius,
669 float start_angle, float end_angle) = 0;
670
671 // ── Lines ────────────────────────────────────────────────────────────
672 virtual void stroke_line(float x0, float y0, float x1, float y1) = 0;
673
683
685 virtual void stroke_path(const Point2D* points, size_t count) {
686 // Fallback: separate segments, so no joins. Curve backends should override.
687 if (points == nullptr || count < 2) return;
688 for (size_t i = 1; i < count; ++i)
689 stroke_line(points[i-1].x, points[i-1].y, points[i].x, points[i].y);
690 }
691
712 virtual void fill_path(const Point2D* points, size_t count,
714 if (points == nullptr || count < 3) return;
715 begin_path();
716 move_to(points[0].x, points[0].y);
717 for (size_t i = 1; i < count; ++i)
718 line_to(points[i].x, points[i].y);
719 close_path();
720 fill_current_path(rule);
721 }
722
732 virtual void draw_image(void* native_handle,
733 float x, float y, float w, float h) {
734 (void)native_handle; (void)x; (void)y; (void)w; (void)h;
735 }
736
737 // ── Retained paths ────────────────────────────────────────────────────
738 // These take a `pulp::canvas::Path` — a retained VALUE (build once, store
739 // it, draw it every frame) — rather than streaming verbs through the
740 // immediate-mode builder above. See <pulp/canvas/path.hpp>.
741 //
742 // Every default implementation below is a real fallback, not a no-op: it
743 // replays the path through the immediate-mode API that every backend
744 // already implements. A Canvas subclass that overrides nothing still draws
745 // the path correctly; backends override only to skip the state round-trip
746 // and hand a native path object straight to the rasterizer.
747
750 virtual void fill_path(const Path& path, FillRule rule = FillRule::nonzero) {
751 if (path.is_empty()) return;
752 begin_path();
753 path.replay(*this);
754 fill_current_path(rule);
755 }
756
766 virtual void stroke_path(const Path& path, const StrokeStyle& style) {
767 if (path.is_empty()) return;
768 set_line_width(style.width);
769 set_line_cap(style.cap);
770 set_line_join(style.join);
772 if (style.dash.empty())
773 set_line_dash(nullptr, 0, 0.0f);
774 else
775 set_line_dash(style.dash.data(), static_cast<int>(style.dash.size()),
776 style.dash_phase);
777 begin_path();
778 path.replay(*this);
780 }
781
783 virtual void clip_path(const Path& path, FillRule rule = FillRule::nonzero) {
784 if (path.is_empty()) return;
785 begin_path();
786 path.replay(*this);
787 clip(rule);
788 }
789
805 virtual void draw_path_shadow(const Path& path, float dx, float dy,
806 float blur, float spread, Color color) {
807 if (path.is_empty()) return;
808 (void)blur; // the fallback has no blur; backends override.
809 Path shadow = path;
810 if (spread != 0.0f) {
811 const Rect2D b = path.bounds();
812 if (b.width > 0.0f && b.height > 0.0f) {
813 const float sx = (b.width + 2.0f * spread) / b.width;
814 const float sy = (b.height + 2.0f * spread) / b.height;
816 sx, sy, b.x + b.width * 0.5f, b.y + b.height * 0.5f));
817 }
818 }
820 save();
823 restore();
824 }
825
826 // ── Opacity & Layers ──────────────────────────────────────────────────
828 virtual void set_opacity(float alpha) { (void)alpha; }
829
849 struct LayerHandle {
850 uint64_t id = 0;
851 constexpr bool operator==(const LayerHandle& o) const { return id == o.id; }
852 constexpr bool operator!=(const LayerHandle& o) const { return id != o.id; }
853 constexpr explicit operator bool() const { return id != 0; }
854 };
855
868 virtual LayerHandle begin_layer(Rect2D bounds, bool cacheable = false) {
869 (void)cacheable;
870 save();
871 clip_rect(bounds.x, bounds.y, bounds.width, bounds.height);
872 return LayerHandle{};
873 }
874
878 restore();
879 return LayerHandle{};
880 }
881
883 virtual void draw_layer(LayerHandle layer, float alpha = 1.0f,
885 (void)layer; (void)alpha; (void)mode;
886 }
887
889 virtual void draw_layer_fitted(LayerHandle layer, Rect2D dest) {
890 (void)layer; (void)dest;
891 }
892
894 virtual void draw_layer_rotated(LayerHandle layer, float angle_rad) {
895 (void)layer; (void)angle_rad;
896 }
897
901 virtual bool layer_valid(LayerHandle layer) const {
902 (void)layer;
903 return false;
904 }
905
909 virtual void invalidate_layer(LayerHandle layer) { (void)layer; }
910
911 // ── Scene recording (subtree cache, FU-3) ─────────────────────────────
928 virtual std::shared_ptr<SceneRecording> record_scene(
929 float w, float h, const std::function<void(Canvas&)>& paint) {
930 (void)w; (void)h; (void)paint;
931 return nullptr;
932 }
933
938 virtual bool draw_scene(const SceneRecording& rec) {
939 (void)rec;
940 return false;
941 }
942
947 virtual void save_layer(float x, float y, float w, float h,
948 float opacity = 1.0f, float blur_radius = 0.0f) {
949 save(); // fallback: just save state
950 (void)x; (void)y; (void)w; (void)h;
951 (void)opacity; (void)blur_radius;
952 }
953
960 virtual void save_layer_with_blend(float x, float y, float w, float h,
961 float opacity, float blur_radius,
962 BlendMode mode) {
963 (void)mode;
964 save_layer(x, y, w, h, opacity, blur_radius);
965 }
966
995 virtual void save_layer_with_filters(float x, float y, float w, float h,
996 float opacity,
997 const FilterChainEntry* chain,
998 int count) {
999 // Fallback: collapse blur + opacity filters into a plain save_layer.
1000 float blur = 0.0f;
1001 for (int i = 0; i < count; ++i) {
1002 if (chain[i].kind == FilterChainEntry::Kind::blur) {
1003 blur += chain[i].amount;
1004 } else if (chain[i].kind == FilterChainEntry::Kind::opacity) {
1005 opacity *= chain[i].amount;
1006 }
1007 }
1008 save_layer(x, y, w, h, opacity, blur);
1009 }
1010
1026 virtual void save_layer_with_shader_effect(float x, float y,
1027 float w, float h,
1028 const std::string& effect_name,
1029 float intensity) {
1030 (void)effect_name;
1031 (void)intensity;
1032 save_layer(x, y, w, h);
1033 }
1034
1058 virtual void save_layer_with_mask(float x, float y, float w, float h,
1059 float opacity,
1060 const std::string& mask_image,
1061 const std::string& mask_size) {
1062 (void)mask_image; (void)mask_size;
1063 save_layer(x, y, w, h, opacity, 0.0f);
1064 }
1065
1066 // ── Text ─────────────────────────────────────────────────────────────
1067 virtual void set_font(const std::string& family, float size) = 0;
1068 virtual void set_text_align(TextAlign align) = 0;
1069 virtual void fill_text(const std::string& text, float x, float y) = 0;
1070 virtual float measure_text(const std::string& text) = 0;
1071
1084 virtual float text_x_for_byte(const std::string& text,
1085 std::size_t byte_index) {
1086 // Clamp back to a UTF-8 codepoint boundary: a caller-supplied byte
1087 // index that lands inside a multi-byte sequence would otherwise slice
1088 // an invalid prefix. On the CoreGraphics backend that invalid UTF-8
1089 // made NSString conversion return nil and NSAttributedString THROW
1090 // inside the editor's drawRect:, killing the host's whole AU process
1091 // (and every plugin in it). Never measure an invalid prefix.
1092 return measure_text(text.substr(0, safe_utf8_prefix_size(text, byte_index)));
1093 }
1094
1125 virtual void fill_text_anchored(const std::string& text,
1126 float x, float y, TextAnchor anchor) {
1127 // Default fallback: treat all anchors as Baseline. Backends
1128 // that have access to font metrics override this. The override
1129 // path is the one widget callsites use; the default exists so
1130 // RecordingCanvas / base mocks compile without changes.
1131 (void)anchor;
1132 fill_text(text, x, y);
1133 }
1134
1147 virtual void fill_text_with_max_width(const std::string& text,
1148 float x, float y, float max_width) {
1149 (void)max_width;
1150 fill_text(text, x, y);
1151 }
1152
1162 virtual void stroke_text(const std::string& text, float x, float y,
1163 float max_width = 0.0f) {
1164 (void)max_width;
1165 // Fallback: caller must have set fill color to stroke color before
1166 // invoking. Matches the strokeText shim approximation.
1167 fill_text(text, x, y);
1168 }
1169
1178 virtual void set_font_full(const std::string& family, float size,
1179 int weight, int slant, float letter_spacing) {
1180 (void)weight; (void)slant; (void)letter_spacing;
1181 set_font(family, size);
1182 }
1183
1190 virtual void set_font_smoothing(FontSmoothing smoothing) {
1191 (void)smoothing;
1192 }
1193
1194 // OpenType feature flags for font-variant. Each
1195 // FontFeature is a 4-byte tag (e.g. "tnum" / "smcp" / "onum" /
1196 // "lnum" / "pnum") + an on/off value (0 disables, 1 enables).
1197 // SkiaCanvas applies these via SkParagraph TextStyle::addFontFeature
1198 // inside make_paragraph(), at HarfBuzz shape time. The default impl
1199 // is a no-op (CG / Recording canvases ignore); SkiaCanvas captures
1200 // into a vector consumed by the make_paragraph() calls behind
1201 // fill_text / stroke_text / measure_text.
1203 uint32_t tag; // 4-byte big-endian tag (use make_font_feature_tag).
1204 uint32_t value; // 0 = disable, 1 = enable, higher = feature-specific.
1205 bool operator==(const FontFeature&) const = default;
1206 };
1207
1210 static constexpr uint32_t make_font_feature_tag(const char (&s)[5]) {
1211 return (static_cast<uint32_t>(static_cast<uint8_t>(s[0])) << 24) |
1212 (static_cast<uint32_t>(static_cast<uint8_t>(s[1])) << 16) |
1213 (static_cast<uint32_t>(static_cast<uint8_t>(s[2])) << 8) |
1214 static_cast<uint32_t>(static_cast<uint8_t>(s[3]));
1215 }
1216 virtual void set_font_features(std::vector<FontFeature> features) {
1217 (void)features;
1218 // Default: no-op. Backends without HarfBuzz feature support
1219 // (recording canvas, CG path) silently drop the request — text
1220 // still renders, just without the OpenType feature applied.
1221 }
1222 virtual void clear_font_features() {
1223 // Default: no-op. Same rationale as set_font_features.
1224 }
1225
1231 float width = 0;
1232 float ascent = 0;
1233 float descent = 0;
1234 float line_height = 0;
1235
1236 // ── HTML5 TextMetrics extensions ────────────────────────────
1246 };
1247
1248 // ── SDF Text (GPU-accelerated, resolution-independent) ────────────
1249
1254 virtual void fill_text_sdf(const std::string& text, float x, float y,
1255 const class SdfAtlas& atlas) {
1256 // Default: fall back to standard text rendering
1257 (void)atlas;
1258 fill_text(text, x, y);
1259 }
1260
1261 // ── Capability queries ───────────────────────────────────────────────
1268 virtual bool supports(CanvasCapability) const { return false; }
1269
1270 // ── Images ───────────────────────────────────────────────────────────
1278
1281 virtual bool draw_image_from_data(const uint8_t* data, size_t size,
1282 float x, float y, float w, float h) {
1283 (void)data; (void)size; (void)x; (void)y; (void)w; (void)h;
1284 return false; // Base class can't draw images
1285 }
1286
1288 virtual bool draw_image_from_file(const std::string& path,
1289 float x, float y, float w, float h) {
1290 (void)path; (void)x; (void)y; (void)w; (void)h;
1291 return false; // Override in Skia backend
1292 }
1293
1300 virtual bool draw_svg(const std::string& svg_document,
1301 float x, float y, float w, float h) {
1302 (void)svg_document; (void)x; (void)y; (void)w; (void)h;
1303 return false; // Override in Skia backend
1304 }
1305
1306 // 9-arg drawImage(img, sx,sy,sw,sh, dx,dy,dw,dh) source-rect
1307 // slicing. Default impl delegates to the dst-only form (loses the slice);
1308 // Skia overrides to use drawImageRect(src, dst); other backends keep
1309 // the destination-only fallback.
1310 virtual bool draw_image_from_file_rect(const std::string& path,
1311 float sx, float sy, float sw, float sh,
1312 float dx, float dy, float dw, float dh) {
1313 (void)sx; (void)sy; (void)sw; (void)sh;
1314 return draw_image_from_file(path, dx, dy, dw, dh);
1315 }
1316 virtual bool draw_image_from_data_rect(const uint8_t* data, size_t size,
1317 float sx, float sy, float sw, float sh,
1318 float dx, float dy, float dw, float dh) {
1319 (void)sx; (void)sy; (void)sw; (void)sh;
1320 return draw_image_from_data(data, size, dx, dy, dw, dh);
1321 }
1322
1329 virtual bool measure_image_from_file(const std::string& path,
1330 float& out_width, float& out_height) {
1331 (void)path;
1332 out_width = 0.0f; out_height = 0.0f;
1333 return false;
1334 }
1335
1337 virtual TextMetrics measure_text_full(const std::string& text) {
1338 TextMetrics m;
1339 m.width = measure_text(text);
1340 m.ascent = font_size_ * 0.75f; // approximate
1341 m.descent = font_size_ * 0.25f;
1342 m.line_height = font_size_ * 1.2f;
1343 // HTML5 TextMetrics fields — fall back to font-metric
1344 // estimates when no shaped bounding box is available.
1345 m.actual_bounding_box_left = 0;
1346 m.actual_bounding_box_right = m.width;
1347 m.actual_bounding_box_ascent = m.ascent;
1348 m.actual_bounding_box_descent = m.descent;
1349 return m;
1350 }
1351
1352 // ── Line Dash ───────────────────────────────────────────────────
1361 virtual void set_line_dash(const float* intervals, int count, float phase = 0.0f) {
1362 (void)intervals; (void)count; (void)phase;
1363 }
1364
1365 // ── Pixel manipulation ──────────────────────────────────────────
1371 virtual bool read_pixels(int x, int y, int width, int height, uint8_t* out) {
1372 (void)x; (void)y; (void)width; (void)height; (void)out;
1373 return false;
1374 }
1375
1379 virtual bool write_pixels(const uint8_t* data, int width, int height,
1380 int dx, int dy) {
1381 (void)data; (void)width; (void)height; (void)dx; (void)dy;
1382 return false;
1383 }
1384
1385 // ── SDF Shape Primitives (GPU-accelerated) ─────────────────────────
1387 enum class SDFShape {
1388 rect, // 0 — axis-aligned rectangle
1389 circle, // 1 — circle (min dimension as radius)
1390 rounded_rect, // 2 — rectangle with corner_radius
1391 arc, // 3 — ring arc (arc_start + arc_sweep)
1392 diamond, // 4 — rotated square
1393 squircle, // 5 — continuous-curvature rounded rect (power param)
1394 triangle, // 6 — equilateral triangle
1395 ring, // 7 — circle with inner radius (donut)
1396 stadium, // 8 — pill/capsule shape
1397 cross, // 9 — plus sign with configurable arm width
1398 flat_segment, // 10 — line segment with flat caps
1399 rounded_segment,// 11 — line segment with rounded caps
1400 flat_arc, // 12 — arc with thickness and flat caps
1401 quadratic_bezier,// 13 — quadratic bezier curve with thickness
1402 };
1403
1404 struct SDFStyle {
1405 Color fill_color = Color::rgba(0.392f, 1.0f, 0.392f);
1406 Color stroke_color = Color::rgba(0.392f, 1.0f, 0.392f);
1407 float stroke_width = 0;
1408 float corner_radius = 0;
1409 float arc_start = 0;
1410 float arc_sweep = 4.712f;
1411 float squircle_power = 4.0f;
1412 float inner_radius = 0.5f;
1413 float arm_width = 0.3f;
1414 float bezier_cx = 0.0f;
1415 float bezier_cy = -1.0f;
1416 // Analytic chart feathering. 0=uniform, 1=glow, 2=inner,
1417 // 3=outer, 4=inset, 5=radial, 6=sweep.
1418 float feather_sigma = 0.0f;
1421 };
1422
1423 virtual void draw_sdf_shape(SDFShape shape, float x, float y, float w, float h,
1424 const SDFStyle& style) {
1425 // CPU fallback: use existing rect/rounded_rect
1426 if (style.stroke_width > 0) {
1429 if (shape == SDFShape::circle)
1430 stroke_rounded_rect(x, y, w, h, std::min(w, h) * 0.5f);
1431 else if (shape == SDFShape::rounded_rect)
1432 stroke_rounded_rect(x, y, w, h, style.corner_radius);
1433 else
1434 stroke_rounded_rect(x, y, w, h, 0);
1435 } else {
1437 if (shape == SDFShape::circle)
1438 fill_rounded_rect(x, y, w, h, std::min(w, h) * 0.5f);
1439 else if (shape == SDFShape::rounded_rect)
1440 fill_rounded_rect(x, y, w, h, style.corner_radius);
1441 else
1442 fill_rounded_rect(x, y, w, h, 0);
1443 }
1444 }
1445
1464 virtual bool draw_sdf_shape_with_shader(SDFShape shape, float x, float y,
1465 float w, float h,
1466 const SDFStyle& style,
1467 const std::string& sksl,
1468 const ShaderDrawOptions& options) {
1469 (void)sksl; (void)options;
1470 draw_sdf_shape(shape, x, y, w, h, style);
1471 return false;
1472 }
1473
1474 // ── Blur / Backdrop filter ─────────────────────────────────────────
1477 virtual void draw_blurred_backdrop(float x, float y, float w, float h,
1478 float blur_radius, float corner_radius = 0,
1479 Color tint = Color::rgba(0.0f, 0.0f, 0.0f, 0.314f)) {
1480 // CPU fallback: just draw a semi-transparent rect (no blur)
1481 set_fill_color(tint);
1482 fill_rounded_rect(x, y, w, h, corner_radius);
1483 }
1484
1493 virtual void save_backdrop_filter(float x, float y, float w, float h,
1494 float blur_radius) {
1495 (void)x; (void)y; (void)w; (void)h; (void)blur_radius;
1496 save();
1497 }
1498
1510 virtual void save_backdrop_filter_chain(float x, float y, float w, float h,
1511 const FilterChainEntry* chain,
1512 int count) {
1513 float blur = 0.0f;
1514 for (int i = 0; i < count; ++i)
1515 if (chain[i].kind == FilterChainEntry::Kind::blur)
1516 blur += chain[i].amount;
1517 save_backdrop_filter(x, y, w, h, blur);
1518 }
1519
1520 // ── Box shadow ──────────────────────────────────────────────────
1531 virtual void draw_box_shadow(float x, float y, float w, float h,
1532 float dx, float dy, float blur, float spread,
1533 Color color, bool inset = false,
1534 float corner_radius = 0.0f);
1535
1536 // ── Canvas2D drop shadow state ──────────────────────────────────
1552 virtual void set_shadow_color(Color color) { (void)color; }
1553 virtual void set_shadow_blur(float blur) { (void)blur; }
1554 virtual void set_shadow_offset_x(float dx) { (void)dx; }
1555 virtual void set_shadow_offset_y(float dy) { (void)dy; }
1556
1557 // ── Canvas2D direction / filter ─────────────────────────────────
1571 enum class TextDirection { ltr, rtl, inherit };
1572 virtual void set_direction(TextDirection direction) { (void)direction; }
1573
1584 virtual void set_filter(const std::string& filter) { (void)filter; }
1585
1586 // ── Waveform (GPU-accelerated) ─────────────────────────────────────
1590 Color line_color = Color::rgba(0.392f, 0.706f, 0.980f);
1591 Color fill_color = Color::rgba(0.392f, 0.706f, 0.980f, 0.157f);
1592 float line_thickness = 1.5f;
1593 bool show_fill = true;
1594 float fill_center = 0.5f;
1595 };
1596
1597 virtual void draw_waveform(const float* samples, size_t count,
1598 float x, float y, float width, float height,
1599 const WaveformStyle& style) {
1600 // CPU fallback: connected line strip
1601 if (count < 2) return;
1604 float cy = y + height * style.fill_center;
1605 float half_h = height * 0.5f;
1606 float prev_x = x;
1607 float prev_y = cy - samples[0] * half_h;
1608 for (size_t i = 1; i < count; ++i) {
1609 float sx = x + (static_cast<float>(i) / static_cast<float>(count - 1)) * width;
1610 float sy = cy - samples[i] * half_h;
1611 stroke_line(prev_x, prev_y, sx, sy);
1612 prev_x = sx;
1613 prev_y = sy;
1614 }
1615 }
1616
1617 // ── Custom SkSL Shader Rendering (GPU) ──────────────────────────────
1618 //
1619 // SkSL is the custom-widget-shader contract. It is deliberately declared on
1620 // the abstract Canvas rather than on SkiaCanvas: `setWidgetShader(id, sksl)`
1621 // in the JS widget bridge accepts SkSL, so every backend must answer for it
1622 // — either by compiling it or by degrading predictably.
1623 //
1624 // A backend without SkSL degrades gracefully and reports the failure rather
1625 // than pretending to draw: `compile_sksl` returns a non-empty error string
1626 // on non-Skia builds, and `draw_with_sksl` paints a fallback rect and
1627 // returns false. Callers must therefore treat a false return / non-empty
1628 // error as "no shader ran", not as a hard error.
1629 //
1630 // The Skia-independent escape hatch is the WGSL tier — the JS WebGPU bridge
1631 // talks to Dawn directly with zero Skia involvement — for UIs that need GPU
1632 // work on a backend where SkSL is unavailable.
1633
1644
1653 std::string name;
1654 int count = 1;
1655 float v[4] = {0, 0, 0, 0};
1656 };
1657
1662 std::string name;
1663 std::vector<float> samples;
1664 std::uint32_t count = 0;
1665 bool live = false;
1666 float neutral = 0.0f;
1667 std::uint32_t publish_sequence = 0;
1668 };
1669
1673 // Optional generated SDF expression for a bounded operator tree.
1674 // It is emitted from validated geometry JSON and evaluated per
1675 // fragment alongside the primitive prelude.
1676 std::string sdf_expression;
1677 std::uint64_t topology_hash = 0;
1678 // Parameters for a validated operator tree. The expression refers
1679 // to pulp_leafN_* uniforms; keeping the values separate lets a
1680 // same-topology update avoid recompiling the composed shader.
1681 std::vector<NamedUniform> leaf_uniforms;
1682 std::uint32_t leaf_count = 0;
1683 };
1684
1687 std::vector<NamedUniform> named_uniforms;
1688 float reach = 0.0f;
1689 std::shared_ptr<const ShaderDataTexture> data_texture;
1690 std::optional<ShaderGeometry> geometry;
1691 };
1692
1697 static std::string compile_sksl(const std::string& sksl);
1698
1701 static std::string compile_sdf_chart_sksl(SDFShape shape, const std::string& sksl);
1702
1708 static float sdf_feather_min_reach(const SDFStyle& style) {
1709 if (!(style.feather_sigma > 0.0f))
1710 return 0.0f;
1711 if (style.feather_mode != 1 && style.feather_mode != 3)
1712 return 0.0f;
1713 return 3.0f * style.feather_sigma;
1714 }
1715
1723 static bool sksl_declares_uniform(const std::string& sksl,
1724 const std::string& uniform_name);
1725
1730 virtual bool draw_with_sksl(const std::string& sksl,
1731 float x, float y, float w, float h,
1732 const ShaderUniforms& uniforms) {
1733 // CPU fallback: draw a colored placeholder rect
1734 set_fill_color(uniforms.fill_color.a > 0.0f ? uniforms.fill_color : Color::rgba(0.314f, 0.314f, 0.392f, 0.784f));
1735 fill_rect(x, y, w, h);
1736 return false; // shader not rendered
1737 }
1738
1739 virtual bool draw_with_sksl(const std::string& sksl,
1740 float x, float y, float w, float h,
1741 const ShaderDrawOptions& options) {
1742 return draw_with_sksl(sksl, x, y, w, h, options.uniforms);
1743 }
1744
1774 float x, float y, float w, float h,
1775 const std::string& sksl, const ShaderUniforms& uniforms,
1776 float sample_radius = 0.0f,
1777 const std::vector<NamedUniform>& extra_uniforms = {},
1778 BlendMode blend_mode = BlendMode::normal) {
1779 (void)sksl; (void)uniforms; (void)sample_radius;
1780 (void)extra_uniforms; (void)blend_mode;
1781 save_layer(x, y, w, h, 1.0f, 0.0f);
1782 return false;
1783 }
1784
1785 // ── Image transforms, fitting, and tiling ───────────────────────────
1786 //
1787 // These extend the opaque-handle image-draw path (`draw_image`) with the
1788 // rest of the general 2D image-placement vocabulary: an arbitrary affine
1789 // placement, preserve-aspect fitting into a destination box, and tiled
1790 // fill of a region. Every method here has a neutral default expressed in
1791 // primitives every backend already implements (save / restore / clip_rect
1792 // / concat_transform / draw_image), so a backend that overrides none of
1793 // them still paints correctly. Pixel backends may override any of them
1794 // with a single native call (e.g. a shader-backed tile) for efficiency.
1795
1806
1808 struct FitResult { float x = 0, y = 0, w = 0, h = 0; };
1809
1816 static FitResult fit_image_rect(float iw, float ih,
1817 float dx, float dy, float dw, float dh,
1818 ImageFit fit,
1819 float align_x = 0.5f,
1820 float align_y = 0.5f) {
1821 FitResult r{dx, dy, dw, dh};
1822 if (iw <= 0.0f || ih <= 0.0f || dw <= 0.0f || dh <= 0.0f) return r;
1823 float scale = 1.0f;
1824 switch (fit) {
1825 case ImageFit::fill: return {dx, dy, dw, dh};
1826 case ImageFit::contain: scale = std::min(dw / iw, dh / ih); break;
1827 case ImageFit::cover: scale = std::max(dw / iw, dh / ih); break;
1828 case ImageFit::none: scale = 1.0f; break;
1829 case ImageFit::scale_down: scale = std::min(1.0f, std::min(dw / iw, dh / ih)); break;
1830 }
1831 const float w = iw * scale;
1832 const float h = ih * scale;
1833 return {dx + (dw - w) * align_x, dy + (dh - h) * align_y, w, h};
1834 }
1835
1841 virtual void draw_image_transformed(void* native_handle, float w, float h,
1842 const AffineTransform& t) {
1843 save();
1844 concat_transform(t.a, t.b, t.c, t.d, t.e, t.f);
1845 draw_image(native_handle, 0.0f, 0.0f, w, h);
1846 restore();
1847 }
1848
1854 virtual void draw_image_fitted(void* native_handle, float iw, float ih,
1855 float dx, float dy, float dw, float dh,
1856 ImageFit fit,
1857 float align_x = 0.5f,
1858 float align_y = 0.5f) {
1859 const FitResult r = fit_image_rect(iw, ih, dx, dy, dw, dh, fit, align_x, align_y);
1860 save();
1861 clip_rect(dx, dy, dw, dh);
1862 draw_image(native_handle, r.x, r.y, r.w, r.h);
1863 restore();
1864 }
1865
1871 virtual bool draw_image_file_fitted(const std::string& path,
1872 float dx, float dy, float dw, float dh,
1873 ImageFit fit,
1874 float align_x = 0.5f,
1875 float align_y = 0.5f) {
1876 float iw = 0.0f, ih = 0.0f;
1877 if (!measure_image_from_file(path, iw, ih) || iw <= 0.0f || ih <= 0.0f) {
1878 return draw_image_from_file(path, dx, dy, dw, dh);
1879 }
1880 const FitResult r = fit_image_rect(iw, ih, dx, dy, dw, dh, fit, align_x, align_y);
1881 save();
1882 clip_rect(dx, dy, dw, dh);
1883 const bool ok = draw_image_from_file(path, r.x, r.y, r.w, r.h);
1884 restore();
1885 return ok;
1886 }
1887
1896 virtual void draw_image_tiled(void* native_handle,
1897 float tile_w, float tile_h,
1898 float dx, float dy, float dw, float dh,
1899 float offset_x = 0.0f, float offset_y = 0.0f) {
1900 if (tile_w <= 0.0f || tile_h <= 0.0f || dw <= 0.0f || dh <= 0.0f) return;
1901 save();
1902 clip_rect(dx, dy, dw, dh);
1903 // Start at or just before the box's leading edge so the offset never
1904 // leaves an uncovered gap along the top / left.
1905 float start_x = dx - std::fmod(offset_x, tile_w);
1906 if (start_x > dx) start_x -= tile_w;
1907 float start_y = dy - std::fmod(offset_y, tile_h);
1908 if (start_y > dy) start_y -= tile_h;
1909 for (float ty = start_y; ty < dy + dh; ty += tile_h) {
1910 for (float tx = start_x; tx < dx + dw; tx += tile_w) {
1911 draw_image(native_handle, tx, ty, tile_w, tile_h);
1912 }
1913 }
1914 restore();
1915 }
1916
1917protected:
1918 float font_size_ = 14.0f;
1919
1920 public:
1933 virtual void set_fill_gradient_conic_repeating(float cx, float cy, float start_angle,
1934 float sweep_turns,
1935 const Color* colors, const float* positions,
1936 int count) {
1937 (void)sweep_turns;
1938 set_fill_gradient_conic(cx, cy, start_angle, colors, positions, count);
1939 }
1940
1953 virtual void set_fill_gradient_linear_repeating(float x0, float y0,
1954 float x1, float y1,
1955 const Color* colors,
1956 const float* positions,
1957 int count) {
1958 set_fill_gradient_linear(x0, y0, x1, y1, colors, positions, count);
1959 }
1960
1961 public:
1966 virtual bool draw_image_from_static_data_rect(const uint8_t* data, size_t size, float sx,
1967 float sy, float sw, float sh, float dx, float dy,
1968 float dw, float dh) {
1969 return draw_image_from_data_rect(data, size, sx, sy, sw, sh, dx, dy, dw, dh);
1970 }
1971
1979 virtual bool draw_image_from_keyed_data(const std::string& content_key, const uint8_t* data,
1980 size_t size, float x, float y, float w, float h) {
1981 (void)content_key;
1982 return draw_image_from_data(data, size, x, y, w, h);
1983 }
1984
1987 virtual bool draw_image_from_keyed_data_rect(const std::string& content_key,
1988 const uint8_t* data, size_t size, float sx,
1989 float sy, float sw, float sh, float dx, float dy,
1990 float dw, float dh) {
1991 (void)content_key;
1992 return draw_image_from_data_rect(data, size, sx, sy, sw, sh, dx, dy, dw, dh);
1993 }
1994
2001 virtual bool measure_image_from_data(const uint8_t* data, size_t size, float& out_width,
2002 float& out_height) {
2003 out_width = 0.0f;
2004 out_height = 0.0f;
2005 static constexpr uint8_t kPngSignature[] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
2006 if (!data || size < 24)
2007 return false;
2008 for (size_t i = 0; i < sizeof(kPngSignature); ++i)
2009 if (data[i] != kPngSignature[i])
2010 return false;
2011 const auto read_be32 = [&](size_t offset) {
2012 return (static_cast<uint32_t>(data[offset]) << 24) |
2013 (static_cast<uint32_t>(data[offset + 1]) << 16) |
2014 (static_cast<uint32_t>(data[offset + 2]) << 8) |
2015 static_cast<uint32_t>(data[offset + 3]);
2016 };
2017 // The first chunk must be IHDR; PNG caps each dimension at 2^31 - 1.
2018 if (data[12] != 'I' || data[13] != 'H' || data[14] != 'D' || data[15] != 'R')
2019 return false;
2020 const uint32_t w = read_be32(16);
2021 const uint32_t h = read_be32(20);
2022 if (w == 0 || h == 0 || w > 0x7fffffffu || h > 0x7fffffffu)
2023 return false;
2024 out_width = static_cast<float>(w);
2025 out_height = static_cast<float>(h);
2026 return true;
2027 }
2028
2033 gradient_interpolation_ = m;
2034 }
2036 return gradient_interpolation_;
2037 }
2038
2039 private:
2040 GradientInterpolation gradient_interpolation_{};
2041};
2042
2043} // namespace pulp::canvas
2044
2045// RecordingCanvas lives in its own header; included here so consumers that
2046// only include canvas.hpp keep seeing it. The include sits after the
2047// namespace close because RecordingCanvas derives from Canvas.
Definition affine_transform.hpp:48
static constexpr AffineTransform scaling(float sx, float sy)
Definition affine_transform.hpp:66
static constexpr AffineTransform translation(float tx, float ty)
Definition affine_transform.hpp:62
Definition canvas.hpp:240
virtual bool save_layer_with_sksl_post_effect(float x, float y, float w, float h, const std::string &sksl, const ShaderUniforms &uniforms, float sample_radius=0.0f, const std::vector< NamedUniform > &extra_uniforms={}, BlendMode blend_mode=BlendMode::normal)
Save a compositing layer whose ALREADY-PAINTED content is post-processed by a custom SkSL shader.
Definition canvas.hpp:1773
virtual void translate(float x, float y)=0
virtual void stroke_text(const std::string &text, float x, float y, float max_width=0.0f)
Canvas2D strokeText(text, x, y, maxWidth) spec form.
Definition canvas.hpp:1162
virtual void clip(FillRule rule=FillRule::nonzero)
Intersect the current clip region with the current path.
Definition canvas.hpp:348
virtual void set_transform(float a, float b, float c, float d, float e, float f)
Replace the current transform with the affine matrix [ a c e ] [ b d f ] [ 0 0 1 ] Mirrors CanvasRend...
Definition canvas.hpp:289
virtual void set_font_full(const std::string &family, float size, int weight, int slant, float letter_spacing)
Richer font setter that propagates CSS font-weight (100..900), font-slant (0=upright,...
Definition canvas.hpp:1178
virtual bool draw_image_from_keyed_data(const std::string &content_key, const uint8_t *data, size_t size, float x, float y, float w, float h)
Draw encoded image bytes identified by content_key, the lowercase hex SHA-256 of exactly those bytes.
Definition canvas.hpp:1979
virtual void save_layer(float x, float y, float w, float h, float opacity=1.0f, float blur_radius=0.0f)
Save a compositing layer.
Definition canvas.hpp:947
virtual void clip_path_svg(const std::string &svg_path_d)
CSS clip-path: path("...") — intersect the current clip with an SVG-path-d string.
Definition canvas.hpp:358
virtual ~Canvas()=default
virtual void stroke_rect(float x, float y, float w, float h)=0
virtual void save()=0
static std::string compile_sksl(const std::string &sksl)
Validate and compile an SkSL shader without drawing.
virtual void draw_image_tiled(void *native_handle, float tile_w, float tile_h, float dx, float dy, float dw, float dh, float offset_x=0.0f, float offset_y=0.0f)
Fill the destination box (dx, dy, dw, dh) by tiling an opaque image handle at cells of size (tile_w x...
Definition canvas.hpp:1896
virtual bool draw_with_sksl(const std::string &sksl, float x, float y, float w, float h, const ShaderDrawOptions &options)
Definition canvas.hpp:1739
virtual void draw_layer_rotated(LayerHandle layer, float angle_rad)
Composite a sealed layer rotated about its own center.
Definition canvas.hpp:894
virtual void set_stroke_gradient_radial_two_circles(float x0, float y0, float r0, float x1, float y1, float r1, const Color *colors, const float *positions, int count)
Two-circle radial gradient on stroke (mirrors fill counterpart).
Definition canvas.hpp:473
virtual bool draw_image_from_keyed_data_rect(const std::string &content_key, const uint8_t *data, size_t size, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
Source-rect form of draw_image_from_keyed_data, with the same key contract.
Definition canvas.hpp:1987
virtual void invalidate_layer(LayerHandle layer)
Drop layer's texture.
Definition canvas.hpp:909
TextAnchor
Explicit, typed vertical-anchor API.
Definition canvas.hpp:1119
@ EmBoxTop
Definition canvas.hpp:1123
@ GlyphTop
Definition canvas.hpp:1121
@ Baseline
Definition canvas.hpp:1120
@ GlyphCenter
Definition canvas.hpp:1122
virtual bool draw_image_from_file_rect(const std::string &path, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
Definition canvas.hpp:1310
virtual void clip_rect(float x, float y, float w, float h)=0
virtual bool draw_image_from_data_rect(const uint8_t *data, size_t size, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
Definition canvas.hpp:1316
virtual void draw_image_transformed(void *native_handle, float w, float h, const AffineTransform &t)
Draw an opaque image handle (see draw_image) under an arbitrary affine transform.
Definition canvas.hpp:1841
virtual void draw_image_fitted(void *native_handle, float iw, float ih, float dx, float dy, float dw, float dh, ImageFit fit, float align_x=0.5f, float align_y=0.5f)
Draw an opaque image handle fitted into a destination box with a preserve-aspect fit mode and alignme...
Definition canvas.hpp:1854
virtual bool draw_image_from_file(const std::string &path, float x, float y, float w, float h)
Draw an image from a file path at the given rect.
Definition canvas.hpp:1288
GradientInterpolation gradient_interpolation() const
Definition canvas.hpp:2035
virtual void set_shadow_color(Color color)
Sticky drop-shadow state that wraps subsequent draw operations, matching the CanvasRenderingContext2D...
Definition canvas.hpp:1552
virtual bool draw_image_file_fitted(const std::string &path, float dx, float dy, float dw, float dh, ImageFit fit, float align_x=0.5f, float align_y=0.5f)
Draw a file-path image fitted into a destination box.
Definition canvas.hpp:1871
virtual void clear_rect(float x, float y, float w, float h)
Clear a rectangular region to transparent black (rgba 0,0,0,0).
Definition canvas.hpp:660
virtual void capture_paint_baseline_transform()
Snapshot the current device matrix as the baseline for subsequent set_transform() calls.
Definition canvas.hpp:298
virtual void fill_text_sdf(const std::string &text, float x, float y, const class SdfAtlas &atlas)
Render text using an SDF glyph atlas for resolution-independent rendering.
Definition canvas.hpp:1254
virtual void set_shadow_blur(float blur)
Definition canvas.hpp:1553
virtual void fill_rounded_rect(float x, float y, float w, float h, float radius)=0
virtual void set_stroke_gradient_linear(float x0, float y0, float x1, float y1, const Color *colors, const float *positions, int count)
Definition canvas.hpp:460
static std::string compile_sdf_chart_sksl(SDFShape shape, const std::string &sksl)
Compile an author chart shader against the geometry prelude used by draw_sdf_shape_with_shader.
virtual void save_backdrop_filter_chain(float x, float y, float w, float h, const FilterChainEntry *chain, int count)
CSS backdrop-filter with its full function list — saturate(0.2), brightness(2), invert(1),...
Definition canvas.hpp:1510
virtual bool draw_image_from_data(const uint8_t *data, size_t size, float x, float y, float w, float h)
Draw an image from encoded data (PNG, JPEG, WebP) at the given rect.
Definition canvas.hpp:1281
bool supports_image_draw() const
Whether this backend can actually decode + draw a raster image (the draw_image_from_* verbs below).
Definition canvas.hpp:1277
virtual void set_fill_gradient_conic_repeating(float cx, float cy, float start_angle, float sweep_turns, const Color *colors, const float *positions, int count)
Set a REPEATING conic gradient (CSS repeating-conic-gradient).
Definition canvas.hpp:1933
virtual bool layer_valid(LayerHandle layer) const
Is layer still backed by a live texture that can be drawn WITHOUT re-recording it?
Definition canvas.hpp:901
virtual void set_filter(const std::string &filter)
Canvas2D ctx.filter.
Definition canvas.hpp:1584
virtual std::shared_ptr< SceneRecording > record_scene(float w, float h, const std::function< void(Canvas &)> &paint)
Record paint into a replayable SceneRecording, capturing its draw commands ONCE so later frames can d...
Definition canvas.hpp:928
virtual void set_fill_gradient_linear_repeating(float x0, float y0, float x1, float y1, const Color *colors, const float *positions, int count)
Set a REPEATING linear gradient (CSS repeating-linear-gradient).
Definition canvas.hpp:1953
virtual float measure_text(const std::string &text)=0
virtual bool draw_svg(const std::string &svg_document, float x, float y, float w, float h)
Render an SVG document (the literal <svg>…</svg> string) into the box [x,y,w,h], scaled to fit.
Definition canvas.hpp:1300
virtual AffineTransform2x3 current_transform() const
Snapshot the current device matrix (CTM) without mutating canvas state.
Definition canvas.hpp:337
virtual void ellipse(float cx, float cy, float rx, float ry, float rotation, float start_angle, float end_angle, bool anticlockwise)
Native ellipse subpath.
Definition canvas.hpp:589
virtual void set_text_align(TextAlign align)=0
virtual void set_font(const std::string &family, float size)=0
virtual void draw_waveform(const float *samples, size_t count, float x, float y, float width, float height, const WaveformStyle &style)
Definition canvas.hpp:1597
virtual void set_fill_gradient_conic(float cx, float cy, float start_angle, const Color *colors, const float *positions, int count)
Set a conic (sweep) gradient as the fill paint.
Definition canvas.hpp:441
virtual bool write_pixels(const uint8_t *data, int width, int height, int dx, int dy)
Write RGBA pixels (data size = width*height*4) to the current surface at destination (dx,...
Definition canvas.hpp:1379
virtual void stroke_line(float x0, float y0, float x1, float y1)=0
virtual void set_fill_pattern(const std::string &image_src, PatternTileMode tile_x, PatternTileMode tile_y)
Set an image pattern as the fill paint.
Definition canvas.hpp:505
virtual void restore()=0
virtual void save_layer_with_shader_effect(float x, float y, float w, float h, const std::string &effect_name, float intensity)
Curated, named GPU post-effect layer save.
Definition canvas.hpp:1026
pulp::canvas::Point2D Point2D
Stroke a continuous polyline through an array of points.
Definition canvas.hpp:682
virtual void set_fill_gradient_linear(float x0, float y0, float x1, float y1, const Color *colors, const float *positions, int count)
Set a linear gradient as the fill paint.
Definition canvas.hpp:400
virtual void save_layer_with_bloom(float x, float y, float w, float h, float intensity, float threshold, float radius)
Save a compositing layer that applies a real bloom/glow post-effect to the subtree painted into it.
Definition canvas.hpp:637
virtual void set_opacity(float alpha)
Set global alpha for subsequent drawing operations (0.0-1.0).
Definition canvas.hpp:828
virtual void save_layer_with_blend(float x, float y, float w, float h, float opacity, float blur_radius, BlendMode mode)
Save a compositing layer with an explicit blend mode.
Definition canvas.hpp:960
virtual void rotate(float radians)=0
virtual RendererBackend renderer_backend() const noexcept
Identity of the renderer this canvas actually wraps.
Definition canvas.hpp:246
virtual void fill_path(const Path &path, FillRule rule=FillRule::nonzero)
Fill path under rule.
Definition canvas.hpp:750
virtual void set_fill_color(Color c)=0
TextDirection
Canvas2D ctx.direction.
Definition canvas.hpp:1571
@ rtl
Definition canvas.hpp:1571
@ inherit
Definition canvas.hpp:1571
@ ltr
Definition canvas.hpp:1571
virtual void set_image_smoothing(bool enabled, ImageSmoothingQuality quality=ImageSmoothingQuality::low)
Canvas2D ctx.imageSmoothingEnabled + imageSmoothingQuality.
Definition canvas.hpp:392
BlendMode
Indices 0..15 match the existing W3C "advanced" composite ops and must stay stable — set_blend_mode i...
Definition canvas.hpp:527
@ color_dodge
Definition canvas.hpp:530
@ multiply
Definition canvas.hpp:529
@ copy
Definition canvas.hpp:542
@ destination_over
Definition canvas.hpp:534
@ soft_light
Definition canvas.hpp:530
@ overlay
Definition canvas.hpp:529
@ screen
Definition canvas.hpp:529
@ source_atop
Definition canvas.hpp:539
@ lighter
Definition canvas.hpp:543
@ color
Definition canvas.hpp:531
@ hue
Definition canvas.hpp:531
@ source_over
Definition canvas.hpp:533
@ destination_out
Definition canvas.hpp:538
@ luminosity
Definition canvas.hpp:531
@ xor_mode
Definition canvas.hpp:541
@ difference
Definition canvas.hpp:531
@ destination_in
Definition canvas.hpp:536
@ source_in
Definition canvas.hpp:535
@ source_out
Definition canvas.hpp:537
@ hard_light
Definition canvas.hpp:530
@ color_burn
Definition canvas.hpp:530
@ darken
Definition canvas.hpp:529
@ lighten
Definition canvas.hpp:529
@ destination_atop
Definition canvas.hpp:540
@ exclusion
Definition canvas.hpp:531
@ saturation
Definition canvas.hpp:531
@ normal
Definition canvas.hpp:529
virtual void begin_path()
Begin a new path.
Definition canvas.hpp:551
virtual void arc(float cx, float cy, float radius, float start_angle, float end_angle, bool anticlockwise)
Native arc subpath.
Definition canvas.hpp:572
virtual void set_font_smoothing(FontSmoothing smoothing)
CSS -webkit-font-smoothing for the text drawn and measured after it.
Definition canvas.hpp:1190
virtual void set_miter_limit(float limit)
Canvas2D ctx.miterLimit.
Definition canvas.hpp:377
virtual void draw_path_shadow(const Path &path, float dx, float dy, float blur, float spread, Color color)
Draw ONLY the drop shadow cast by path — not the path itself.
Definition canvas.hpp:805
virtual void stroke_circle(float cx, float cy, float radius)=0
static constexpr uint32_t make_font_feature_tag(const char(&s)[5])
Builds a 4-byte big-endian OpenType tag from a 4-char string.
Definition canvas.hpp:1210
virtual void draw_blurred_backdrop(float x, float y, float w, float h, float blur_radius, float corner_radius=0, Color tint=Color::rgba(0.0f, 0.0f, 0.0f, 0.314f))
Save a blurred snapshot of the current canvas content as a backdrop.
Definition canvas.hpp:1477
virtual void set_shadow_offset_x(float dx)
Definition canvas.hpp:1554
virtual void stroke_arc(float cx, float cy, float radius, float start_angle, float end_angle)=0
virtual void fill_text_anchored(const std::string &text, float x, float y, TextAnchor anchor)
Definition canvas.hpp:1125
virtual void concat_transform(float a, float b, float c, float d, float e, float f)
Concat (multiply) the supplied affine matrix onto the current transform — does NOT replace it.
Definition canvas.hpp:311
virtual void fill_circle(float cx, float cy, float radius)=0
virtual void save_layer_with_mask(float x, float y, float w, float h, float opacity, const std::string &mask_image, const std::string &mask_size)
CSS mask-image + mask-size paint slice.
Definition canvas.hpp:1058
virtual void set_line_cap(LineCap cap)=0
virtual float backing_scale() const noexcept
Effective device pixels per local canvas unit at the current transform.
Definition canvas.hpp:253
virtual void clear_fill_gradient()
Clear gradient, return to solid fill color.
Definition canvas.hpp:448
virtual void stroke_path(const Point2D *points, size_t count)
Stroke a continuous polyline — much smoother than individual stroke_line calls.
Definition canvas.hpp:685
virtual float text_x_for_byte(const std::string &text, std::size_t byte_index)
Caret x (in text-local space, measured from the text's leading edge) for the glyph boundary at byte_i...
Definition canvas.hpp:1084
virtual void draw_box_shadow(float x, float y, float w, float h, float dx, float dy, float blur, float spread, Color color, bool inset=false, float corner_radius=0.0f)
Draw a CSS-style box shadow around (or inside, when inset) a rounded rectangle anchored at (x,...
virtual LayerHandle end_layer()
Seal the layer opened by the last begin_layer() and return its handle.
Definition canvas.hpp:877
virtual void draw_image(void *native_handle, float x, float y, float w, float h)
Draw an image identified by an opaque, platform-specific handle into the rectangle (x,...
Definition canvas.hpp:732
virtual bool measure_image_from_file(const std::string &path, float &out_width, float &out_height)
Decoded-image intrinsic dimensions in pixels.
Definition canvas.hpp:1329
virtual void set_font_features(std::vector< FontFeature > features)
Definition canvas.hpp:1216
virtual void save_backdrop_filter(float x, float y, float w, float h, float blur_radius)
CSS backdrop-filter: blur(Npx) — push a compositing layer whose initial contents are the parent surfa...
Definition canvas.hpp:1493
ImageSmoothingQuality
Canvas2D image-smoothing quality enum.
Definition canvas.hpp:382
static bool sksl_declares_uniform(const std::string &sksl, const std::string &uniform_name)
Whether an SkSL shader declares a uniform of the given name.
virtual void fill_rect(float x, float y, float w, float h)=0
virtual void stroke_current_path()
Stroke the current path.
Definition canvas.hpp:619
virtual void set_line_dash(const float *intervals, int count, float phase=0.0f)
Set the line dash pattern for stroke operations.
Definition canvas.hpp:1361
virtual bool draw_with_sksl(const std::string &sksl, float x, float y, float w, float h, const ShaderUniforms &uniforms)
Draw a rectangle filled by a custom SkSL shader.
Definition canvas.hpp:1730
virtual void fill_path(const Point2D *points, size_t count, FillRule rule=FillRule::nonzero)
Fill a closed polygon defined by points, honoring rule.
Definition canvas.hpp:712
float font_size_
Current font size (set by set_font).
Definition canvas.hpp:1918
virtual void set_fill_gradient_radial(float cx, float cy, float radius, const Color *colors, const float *positions, int count)
Set a radial gradient as the fill paint.
Definition canvas.hpp:407
ImageFit
Preserve-aspect fit modes for fit_image_rect / draw_image_fitted: fill — stretch to the destination b...
Definition canvas.hpp:1805
@ none
Definition canvas.hpp:1805
@ cover
Definition canvas.hpp:1805
@ scale_down
Definition canvas.hpp:1805
@ fill
Definition canvas.hpp:1805
@ contain
Definition canvas.hpp:1805
virtual void set_stroke_pattern(const std::string &image_src, PatternTileMode tile_x, PatternTileMode tile_y)
Stroke counterpart.
Definition canvas.hpp:514
virtual void set_fill_gradient_radial_two_circles(float x0, float y0, float r0, float x1, float y1, float r1, const Color *colors, const float *positions, int count)
Canvas2D ctx.createRadialGradient(x0,y0,r0,x1,y1,r1) two-circle form.
Definition canvas.hpp:432
virtual void scale(float sx, float sy)=0
virtual void set_gradient_interpolation(GradientInterpolation m)
Colour space every LATER gradient setter blends its stops in (CSS <color-interpolation-method>),...
Definition canvas.hpp:2032
virtual void fill_text_with_max_width(const std::string &text, float x, float y, float max_width)
Canvas2D fillText(text, x, y, maxWidth) spec form.
Definition canvas.hpp:1147
static float sdf_feather_min_reach(const SDFStyle &style)
The smallest draw-rect reach that holds style's feather: 3 sigma for the glow (1) and outer (3) modes...
Definition canvas.hpp:1708
static FitResult fit_image_rect(float iw, float ih, float dx, float dy, float dw, float dh, ImageFit fit, float align_x=0.5f, float align_y=0.5f)
Pure geometry: place a source image of intrinsic size (iw x ih) into the destination box (dx,...
Definition canvas.hpp:1816
virtual void draw_layer(LayerHandle layer, float alpha=1.0f, BlendMode mode=BlendMode::normal)
Composite a sealed layer at its recorded position.
Definition canvas.hpp:883
virtual void restore_to_count(int target)
Pop the save stack down to target (typically captured earlier via save_count()).
Definition canvas.hpp:274
virtual void fill_text(const std::string &text, float x, float y)=0
virtual void arc_to(float x1, float y1, float x2, float y2, float radius)
Native arcTo.
Definition canvas.hpp:582
virtual void set_stroke_gradient_radial(float cx, float cy, float radius, const Color *colors, const float *positions, int count)
Definition canvas.hpp:466
virtual void cubic_to(float cp1x, float cp1y, float cp2x, float cp2y, float x, float y)
Add a cubic bezier curve.
Definition canvas.hpp:561
PatternTileMode
Canvas2D ctx.createPattern.
Definition canvas.hpp:497
@ repeat
Definition canvas.hpp:497
@ no_repeat
Definition canvas.hpp:497
virtual void round_rect(float x, float y, float w, float h, float tl_x, float tl_y, float tr_x, float tr_y, float br_x, float br_y, float bl_x, float bl_y)
Native rounded-rectangle subpath with per-corner radii.
Definition canvas.hpp:602
virtual void draw_layer_fitted(LayerHandle layer, Rect2D dest)
Composite a sealed layer scaled into dest.
Definition canvas.hpp:889
virtual void set_line_width(float w)=0
SDFShape
Draw an SDF shape with anti-aliased edges via GPU shader.
Definition canvas.hpp:1387
@ squircle
Definition canvas.hpp:1393
@ stadium
Definition canvas.hpp:1396
@ ring
Definition canvas.hpp:1395
@ cross
Definition canvas.hpp:1397
@ rect
Definition canvas.hpp:1388
@ flat_arc
Definition canvas.hpp:1400
@ rounded_rect
Definition canvas.hpp:1390
@ diamond
Definition canvas.hpp:1392
@ flat_segment
Definition canvas.hpp:1398
@ circle
Definition canvas.hpp:1389
@ rounded_segment
Definition canvas.hpp:1399
@ quadratic_bezier
Definition canvas.hpp:1401
@ triangle
Definition canvas.hpp:1394
virtual void line_to(float x, float y)
Add a line segment to (x, y).
Definition canvas.hpp:555
virtual void clip_path(const Path &path, FillRule rule=FillRule::nonzero)
Intersect the current clip with path. Caller owns save()/restore().
Definition canvas.hpp:783
virtual TextMetrics measure_text_full(const std::string &text)
Measure text with full font metrics using current font settings.
Definition canvas.hpp:1337
virtual void clear_font_features()
Definition canvas.hpp:1222
virtual void stroke_path(const Path &path, const StrokeStyle &style)
Stroke path with style.
Definition canvas.hpp:766
virtual bool draw_scene(const SceneRecording &rec)
Replay a recording produced by THIS backend's record_scene() at the current transform/clip.
Definition canvas.hpp:938
virtual bool supports(CanvasCapability) const
Report whether this backend renders cap's verb faithfully.
Definition canvas.hpp:1268
virtual int save_count() const
Return the current save-stack depth.
Definition canvas.hpp:266
virtual bool draw_image_from_static_data_rect(const uint8_t *data, size_t size, float sx, float sy, float sw, float sh, float dx, float dy, float dw, float dh)
Source-rect draw for bytes with static storage duration and immutable contents.
Definition canvas.hpp:1966
virtual void set_stroke_gradient_conic(float cx, float cy, float start_angle, const Color *colors, const float *positions, int count)
Definition canvas.hpp:481
virtual void close_path()
Close the current path subpath.
Definition canvas.hpp:612
virtual void save_layer_with_filters(float x, float y, float w, float h, float opacity, const FilterChainEntry *chain, int count)
Definition canvas.hpp:995
virtual void draw_sdf_shape(SDFShape shape, float x, float y, float w, float h, const SDFStyle &style)
Definition canvas.hpp:1423
virtual void set_shadow_offset_y(float dy)
Definition canvas.hpp:1555
virtual void set_direction(TextDirection direction)
Definition canvas.hpp:1572
virtual void move_to(float x, float y)
Move the pen to (x, y) without drawing.
Definition canvas.hpp:553
virtual void set_fill_gradient_radial_elliptical(float cx, float cy, float rx, float ry, const Color *colors, const float *positions, int count)
Radial gradient with an independent radius per axis — the ending shape CSS calls an ellipse,...
Definition canvas.hpp:419
virtual LayerHandle begin_layer(Rect2D bounds, bool cacheable=false)
Begin recording into an offscreen layer covering bounds (in current user space).
Definition canvas.hpp:868
virtual void set_blend_mode(BlendMode mode)
Set the compositing blend mode for subsequent draw operations.
Definition canvas.hpp:547
virtual void quad_to(float cpx, float cpy, float x, float y)
Add a quadratic bezier curve to (x, y) with control point (cpx, cpy).
Definition canvas.hpp:557
virtual void clear_stroke_gradient()
Clear stroke gradient/pattern shader, restore solid stroke color.
Definition canvas.hpp:488
virtual bool measure_image_from_data(const uint8_t *data, size_t size, float &out_width, float &out_height)
Intrinsic pixel size of encoded image bytes, read from the image header without decoding pixels: the ...
Definition canvas.hpp:2001
virtual bool read_pixels(int x, int y, int width, int height, uint8_t *out)
Read RGBA pixels from the current surface into out (size must be at least width*height*4).
Definition canvas.hpp:1371
virtual void fill_current_path(FillRule rule=FillRule::nonzero)
Fill the current path.
Definition canvas.hpp:615
virtual void stroke_rounded_rect(float x, float y, float w, float h, float radius)=0
virtual void set_stroke_color(Color c)=0
virtual bool draw_sdf_shape_with_shader(SDFShape shape, float x, float y, float w, float h, const SDFStyle &style, const std::string &sksl, const ShaderDrawOptions &options)
Draw a shape through an author-supplied geometry chart shader.
Definition canvas.hpp:1464
virtual void set_line_join(LineJoin join)=0
FillStyle(ConicGradient g)
Definition canvas.hpp:179
FillStyle(LinearGradient g)
Definition canvas.hpp:177
bool is_linear() const
Definition canvas.hpp:182
FillStyle(Color c)
Definition canvas.hpp:176
FillStyle(RadialGradient g)
Definition canvas.hpp:178
const Color & color() const
Definition canvas.hpp:186
void set_tile_mode(GradientTileMode m)
Definition canvas.hpp:192
bool is_conic() const
Definition canvas.hpp:184
bool is_solid() const
Definition canvas.hpp:181
const RadialGradient & radial() const
Definition canvas.hpp:188
GradientTileMode tile_mode() const
Definition canvas.hpp:191
const ConicGradient & conic() const
Definition canvas.hpp:189
const LinearGradient & linear() const
Definition canvas.hpp:187
bool is_radial() const
Definition canvas.hpp:183
Definition path.hpp:87
void apply_transform(const AffineTransform &t)
Transform every point in place.
Opaque handle to a subtree's recorded draw commands, produced by Canvas::record_scene() and replayed ...
Definition scene_recording.hpp:18
Definition sdf_atlas.hpp:39
Definition affine_transform.hpp:24
TextAlign
Definition canvas.hpp:221
@ right
Definition canvas.hpp:221
@ left
Definition canvas.hpp:221
@ justify
Definition canvas.hpp:221
@ center
Definition canvas.hpp:221
std::size_t safe_utf8_prefix_size(const std::string &text, std::size_t byte_index) noexcept
Return the largest prefix length <= byte_index that ends on a valid UTF-8 scalar boundary.
Definition text_utf8.hpp:19
@ oklch
Definition gradient_interpolation.hpp:36
@ hsl
Definition gradient_interpolation.hpp:33
TextVerticalAlign
Definition canvas.hpp:222
@ bottom
Definition canvas.hpp:222
@ top
Definition canvas.hpp:222
@ baseline
Definition canvas.hpp:222
std::variant< Color, LinearGradient, RadialGradient, ConicGradient > Paint
Definition canvas.hpp:203
FontSmoothing
CSS -webkit-font-smoothing as it affects glyph rasterization on macOS.
Definition text_raster_policy.hpp:40
CanvasCapability
Queryable backend capabilities.
Definition canvas_capability.hpp:19
@ images
draw_image_from_* really decode + draw
Definition canvas_capability.hpp:20
@ count
sentinel: number of real capabilities (keep LAST)
Definition canvas_capability.hpp:38
RendererBackend
Runtime identity of the concrete renderer receiving draw calls.
Definition canvas.hpp:29
@ skia_dawn
Definition canvas.hpp:35
@ core_graphics
Definition canvas.hpp:32
@ unknown
Definition canvas.hpp:30
@ skia_raster
Definition canvas.hpp:33
@ skia_ganesh
Definition canvas.hpp:34
@ recording
Definition canvas.hpp:31
FillRule
Winding rule used to decide what counts as "inside" a path.
Definition path.hpp:54
@ nonzero
Definition path.hpp:54
TextBaseline
Definition canvas.hpp:230
@ ideographic
Definition canvas.hpp:230
@ alphabetic
Definition canvas.hpp:230
@ middle
Definition canvas.hpp:230
@ hanging
Definition canvas.hpp:230
TextDirection
Definition canvas.hpp:231
@ left_to_right
Definition canvas.hpp:231
@ right_to_left
Definition canvas.hpp:231
@ bottom_to_top
Definition canvas.hpp:231
@ top_to_bottom
Definition canvas.hpp:231
constexpr const char * renderer_backend_name(RendererBackend backend) noexcept
Definition canvas.hpp:38
LineJoin
Join applied where two segments meet when stroking.
Definition path.hpp:60
@ text
Definition scene_node.hpp:96
@ shape
Definition scene_node.hpp:94
@ path
Definition scene_node.hpp:93
GradientTileMode
Gradient repeat mode.
Definition canvas.hpp:169
@ repeat
Definition canvas.hpp:169
@ clamp
Definition canvas.hpp:169
@ mirror
Definition canvas.hpp:169
LineCap
Line cap applied to the ends of open subpaths when stroking.
Definition path.hpp:57
STL namespace.
Affine 2x3 transform snapshot, six floats laid out as CanvasRenderingContext2D.setTransform / DOMMatr...
Definition canvas.hpp:322
float e
Definition canvas.hpp:325
float a
Definition canvas.hpp:323
float d
Definition canvas.hpp:324
float f
Definition canvas.hpp:325
float b
Definition canvas.hpp:323
float c
Definition canvas.hpp:324
Full CSS filter-chain layer save.
Definition canvas.hpp:974
float amount
Definition canvas.hpp:988
float ds_offset_y
Definition canvas.hpp:991
Kind kind
Definition canvas.hpp:987
float angle_deg
Definition canvas.hpp:989
Color ds_color
Definition canvas.hpp:993
@ drop_shadow
Definition canvas.hpp:985
float ds_offset_x
Definition canvas.hpp:990
float ds_blur
Definition canvas.hpp:992
Placement rectangle produced by fit_image_rect.
Definition canvas.hpp:1808
float w
Definition canvas.hpp:1808
float x
Definition canvas.hpp:1808
float h
Definition canvas.hpp:1808
float y
Definition canvas.hpp:1808
Definition canvas.hpp:1202
uint32_t tag
Definition canvas.hpp:1203
bool operator==(const FontFeature &) const =default
uint32_t value
Definition canvas.hpp:1204
An opaque reference to a compositing layer owned by the canvas.
Definition canvas.hpp:849
constexpr bool operator==(const LayerHandle &o) const
Definition canvas.hpp:851
constexpr bool operator!=(const LayerHandle &o) const
Definition canvas.hpp:852
An arbitrary named shader uniform (name → float / vec2 / vec3 / vec4).
Definition canvas.hpp:1652
int count
1=float, 2=vec2, 3=vec3, 4=vec4
Definition canvas.hpp:1654
float v[4]
Definition canvas.hpp:1655
std::string name
Definition canvas.hpp:1653
Definition canvas.hpp:1404
Color fill_color
Definition canvas.hpp:1405
int feather_curve
0=gaussian, 1=linear
Definition canvas.hpp:1419
float bezier_cy
For quadratic_bezier: control point Y (normalized -1..1).
Definition canvas.hpp:1415
float arc_start
For arc (radians).
Definition canvas.hpp:1409
float arc_sweep
For arc (radians, default 270°).
Definition canvas.hpp:1410
float stroke_width
0 = filled, >0 = stroked
Definition canvas.hpp:1407
int feather_mode
Definition canvas.hpp:1420
float arm_width
For cross (fraction of half-size).
Definition canvas.hpp:1413
float bezier_cx
For quadratic_bezier: control point X (normalized -1..1).
Definition canvas.hpp:1414
float corner_radius
For rounded_rect.
Definition canvas.hpp:1408
Color stroke_color
Definition canvas.hpp:1406
float feather_sigma
Definition canvas.hpp:1418
float inner_radius
For ring (fraction of outer radius).
Definition canvas.hpp:1412
float squircle_power
For squircle (higher = more rectangular).
Definition canvas.hpp:1411
Latest-wins audio/vector payload exposed to an SkSL child shader.
Definition canvas.hpp:1661
std::uint32_t count
Definition canvas.hpp:1664
std::string name
Definition canvas.hpp:1662
bool live
Definition canvas.hpp:1665
std::uint32_t publish_sequence
Definition canvas.hpp:1667
float neutral
Definition canvas.hpp:1666
std::vector< float > samples
Definition canvas.hpp:1663
Definition canvas.hpp:1685
ShaderUniforms uniforms
Definition canvas.hpp:1686
std::shared_ptr< const ShaderDataTexture > data_texture
Definition canvas.hpp:1689
std::vector< NamedUniform > named_uniforms
Definition canvas.hpp:1687
std::optional< ShaderGeometry > geometry
Definition canvas.hpp:1690
float reach
Definition canvas.hpp:1688
Definition canvas.hpp:1670
std::string sdf_expression
Definition canvas.hpp:1676
SDFStyle style
Definition canvas.hpp:1672
std::uint32_t leaf_count
Definition canvas.hpp:1682
std::uint64_t topology_hash
Definition canvas.hpp:1677
SDFShape shape
Definition canvas.hpp:1671
std::vector< NamedUniform > leaf_uniforms
Definition canvas.hpp:1681
Uniforms passed to custom widget shaders.
Definition canvas.hpp:1635
float time
Animation time (seconds).
Definition canvas.hpp:1637
float value
Widget value (0-1).
Definition canvas.hpp:1636
Color track_color
Definition canvas.hpp:1640
Color accent_color
Definition canvas.hpp:1638
Color fill_color
Definition canvas.hpp:1641
Color thumb_color
Definition canvas.hpp:1642
Color bg_color
Definition canvas.hpp:1639
Full text metrics for layout and intrinsic sizing.
Definition canvas.hpp:1230
float actual_bounding_box_right
Distance from text origin to the right edge of the rendering bounding box.
Definition canvas.hpp:1241
float descent
Distance below baseline (positive value, ==fontBoundingBoxDescent).
Definition canvas.hpp:1233
float ascent
Distance above baseline (positive value, ==fontBoundingBoxAscent).
Definition canvas.hpp:1232
float width
Advance width of the text.
Definition canvas.hpp:1231
float line_height
Recommended line spacing (ascent + descent + leading).
Definition canvas.hpp:1234
float actual_bounding_box_descent
Distance from baseline to bottom of the rendering bounding box.
Definition canvas.hpp:1245
float actual_bounding_box_ascent
Distance from baseline to top of the rendering bounding box.
Definition canvas.hpp:1243
float actual_bounding_box_left
Distance from text origin to the left edge of the rendering bounding box.
Definition canvas.hpp:1239
Draw a waveform using GPU shader (SDF anti-aliased line + fill).
Definition canvas.hpp:1589
bool show_fill
Definition canvas.hpp:1593
Color fill_color
Definition canvas.hpp:1591
float fill_center
0=top, 0.5=center, 1=bottom
Definition canvas.hpp:1594
float line_thickness
Definition canvas.hpp:1592
Color line_color
Definition canvas.hpp:1590
Definition canvas.hpp:75
float h
Definition canvas.hpp:75
float l
Definition canvas.hpp:75
float s
Definition canvas.hpp:75
Definition canvas.hpp:74
float s
Definition canvas.hpp:74
float v
Definition canvas.hpp:74
float h
Definition canvas.hpp:74
Definition canvas.hpp:76
float C
Definition canvas.hpp:76
float h
Definition canvas.hpp:76
float L
Definition canvas.hpp:76
Definition canvas.hpp:52
static Color from_argb32(uint32_t argb)
Unpack from uint32_t ARGB.
Definition canvas.hpp:130
HSL to_hsl() const
Convert to HSL (h in [0,360), s and l in [0,1]).
uint8_t b8() const
Definition canvas.hpp:118
static Color decode(const uint8_t *data)
float r
Definition canvas.hpp:53
uint8_t a8() const
Definition canvas.hpp:119
static Color from_hsv(HSV hsv, float alpha=1.0f)
static constexpr Color rgba(float r, float g, float b, float a=1.0f)
Construct from float channels [0,1] (>1.0 allowed for HDR).
Definition canvas.hpp:56
Color with_hdr_intensity(float multiplier) const
Scale color intensity for HDR (channels can exceed 1.0).
Definition canvas.hpp:106
static Color hex(uint32_t rgb)
Construct from hex 0xRRGGBB (alpha = 1.0).
Definition canvas.hpp:66
uint8_t r8() const
Convert to 8-bit values for serialization/interop.
Definition canvas.hpp:116
Color with_alpha(float alpha) const
Return copy with different alpha.
Definition canvas.hpp:111
static Color from_oklch(OKLCH oklch, float alpha=1.0f)
uint32_t to_argb32() const
Pack to uint32_t ARGB (clamped to [0,255]) for Skia/platform interop.
Definition canvas.hpp:122
float b
Definition canvas.hpp:53
float a
Definition canvas.hpp:53
static constexpr Color rgba8(uint8_t r, uint8_t g, uint8_t b, uint8_t a=255)
Construct from 8-bit channels [0,255] — convenience for legacy/hex code.
Definition canvas.hpp:61
HSV to_hsv() const
Convert to HSV (h in [0,360), s and v in [0,1]).
bool operator!=(const Color &other) const
Definition canvas.hpp:140
uint8_t g8() const
Definition canvas.hpp:117
bool operator==(const Color &other) const
Definition canvas.hpp:137
float g
Definition canvas.hpp:53
OKLCH to_oklch() const
Convert to OKLCH (perceptually uniform, CSS Color Level 4) L in [0,1], C in [0,~0....
void encode(uint8_t *out) const
Serialize to compact binary (4x float LE, 16 bytes).
static Color from_hsl(HSL hsl, float alpha=1.0f)
Color interpolate(const Color &other, float t) const
Interpolate between this color and other by factor t [0,1].
Definition canvas.hpp:98
Conic (sweep) gradient — colors sweep around a center point.
Definition canvas.hpp:162
float cx
Definition canvas.hpp:163
float start_angle
Starting angle in radians.
Definition canvas.hpp:164
float cy
Center point.
Definition canvas.hpp:163
std::vector< GradientStop > stops
Definition canvas.hpp:165
Definition gradient_interpolation.hpp:43
Definition canvas.hpp:145
float position
Definition canvas.hpp:146
Color color
Definition canvas.hpp:147
Definition canvas.hpp:150
float x0
Definition canvas.hpp:151
float x1
Definition canvas.hpp:151
std::vector< GradientStop > stops
Definition canvas.hpp:152
float y0
Definition canvas.hpp:151
float y1
Definition canvas.hpp:151
A 2D point.
Definition affine_transform.hpp:37
Definition canvas.hpp:155
float cx
Definition canvas.hpp:156
float focal_y
Focal point offset for spotlight effects.
Definition canvas.hpp:157
std::vector< GradientStop > stops
Definition canvas.hpp:158
float cy
Definition canvas.hpp:156
float radius
Definition canvas.hpp:156
float focal_x
Definition canvas.hpp:157
Axis-aligned rectangle in canvas coordinates.
Definition rectangle_list.hpp:28
Everything needed to stroke a path, as one value.
Definition path.hpp:67
LineCap cap
Definition path.hpp:69
float miter_limit
Definition path.hpp:71
float dash_phase
Definition path.hpp:77
float width
Definition path.hpp:68
std::vector< float > dash
Dash pattern: alternating on/off lengths in user units.
Definition path.hpp:76
LineJoin join
Definition path.hpp:70