#include <canvas.hpp>
Classes | |
| struct | AffineTransform2x3 |
| Affine 2x3 transform snapshot, six floats laid out as CanvasRenderingContext2D.setTransform / DOMMatrix: [ a c e ] [ b d f ] [ 0 0 1 ] Identity is {1, 0, 0, 1, 0, 0}. More... | |
| struct | LayerHandle |
| An opaque reference to a compositing layer owned by the canvas. More... | |
| struct | FilterChainEntry |
| Full CSS filter-chain layer save. More... | |
| struct | FontFeature |
| struct | TextMetrics |
| Full text metrics for layout and intrinsic sizing. More... | |
| struct | SDFStyle |
| struct | WaveformStyle |
| Draw a waveform using GPU shader (SDF anti-aliased line + fill). More... | |
| struct | ShaderUniforms |
| Uniforms passed to custom widget shaders. More... | |
| struct | NamedUniform |
| An arbitrary named shader uniform (name → float / vec2 / vec3 / vec4). More... | |
| struct | ShaderDataTexture |
| Latest-wins audio/vector payload exposed to an SkSL child shader. More... | |
| struct | ShaderGeometry |
| struct | ShaderDrawOptions |
| struct | FitResult |
| Placement rectangle produced by fit_image_rect. More... | |
Public Types | |
| enum class | ImageSmoothingQuality { low , medium , high } |
| Canvas2D image-smoothing quality enum. More... | |
| enum class | PatternTileMode { repeat , no_repeat } |
| Canvas2D ctx.createPattern. More... | |
| enum class | BlendMode { normal = 0 , multiply , screen , overlay , darken , lighten , color_dodge , color_burn , hard_light , soft_light , difference , exclusion , hue , saturation , color , luminosity , source_over , destination_over , source_in , destination_in , source_out , destination_out , source_atop , destination_atop , xor_mode , copy , lighter } |
| Indices 0..15 match the existing W3C "advanced" composite ops and must stay stable — set_blend_mode in the JS bridge currently passes int_val 1/2/3 = multiply/screen/overlay. More... | |
| enum class | TextAnchor { Baseline , GlyphTop , GlyphCenter , EmBoxTop } |
| Explicit, typed vertical-anchor API. More... | |
| enum class | SDFShape { rect , circle , rounded_rect , arc , diamond , squircle , triangle , ring , stadium , cross , flat_segment , rounded_segment , flat_arc , quadratic_bezier } |
| Draw an SDF shape with anti-aliased edges via GPU shader. More... | |
| enum class | TextDirection { ltr , rtl , inherit } |
| Canvas2D ctx.direction. More... | |
| enum class | ImageFit { fill , contain , cover , none , scale_down } |
| Preserve-aspect fit modes for fit_image_rect / draw_image_fitted: fill — stretch to the destination box, ignoring aspect ratio. More... | |
| using | Point2D = pulp::canvas::Point2D |
| Stroke a continuous polyline through an array of points. | |
Public Member Functions | |
| virtual | ~Canvas ()=default |
| virtual RendererBackend | renderer_backend () const noexcept |
| Identity of the renderer this canvas actually wraps. | |
| virtual float | backing_scale () const noexcept |
| Effective device pixels per local canvas unit at the current transform. | |
| virtual void | save ()=0 |
| virtual void | restore ()=0 |
| virtual int | save_count () const |
| Return the current save-stack depth. | |
| virtual void | restore_to_count (int target) |
| Pop the save stack down to target (typically captured earlier via save_count()). | |
| virtual void | translate (float x, float y)=0 |
| virtual void | scale (float sx, float sy)=0 |
| virtual void | rotate (float radians)=0 |
| 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 CanvasRenderingContext2D.setTransform(a, b, c, d, e, f). | |
| virtual void | capture_paint_baseline_transform () |
| Snapshot the current device matrix as the baseline for subsequent set_transform() calls. | |
| 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. | |
| virtual AffineTransform2x3 | current_transform () const |
| Snapshot the current device matrix (CTM) without mutating canvas state. | |
| virtual void | clip_rect (float x, float y, float w, float h)=0 |
| virtual void | clip (FillRule rule=FillRule::nonzero) |
| Intersect the current clip region with the current path. | |
| 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. | |
| virtual void | set_fill_color (Color c)=0 |
| virtual void | set_stroke_color (Color c)=0 |
| virtual void | set_line_width (float w)=0 |
| virtual void | set_line_cap (LineCap cap)=0 |
| virtual void | set_line_join (LineJoin join)=0 |
| virtual void | set_miter_limit (float limit) |
| Canvas2D ctx.miterLimit. | |
| virtual void | set_image_smoothing (bool enabled, ImageSmoothingQuality quality=ImageSmoothingQuality::low) |
| Canvas2D ctx.imageSmoothingEnabled + imageSmoothingQuality. | |
| 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. | |
| 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. | |
| 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, which is radial-gradient's DEFAULT shape and the only one a two-value size (90% 70%) can express. | |
| 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. | |
| 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. | |
| virtual void | clear_fill_gradient () |
| Clear gradient, return to solid fill color. | |
| virtual void | set_stroke_gradient_linear (float x0, float y0, float x1, float y1, const Color *colors, const float *positions, int count) |
| virtual void | set_stroke_gradient_radial (float cx, float cy, float radius, const Color *colors, const float *positions, int count) |
| 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). | |
| virtual void | set_stroke_gradient_conic (float cx, float cy, float start_angle, const Color *colors, const float *positions, int count) |
| virtual void | clear_stroke_gradient () |
| Clear stroke gradient/pattern shader, restore solid stroke color. | |
| virtual void | set_fill_pattern (const std::string &image_src, PatternTileMode tile_x, PatternTileMode tile_y) |
| Set an image pattern as the fill paint. | |
| virtual void | set_stroke_pattern (const std::string &image_src, PatternTileMode tile_x, PatternTileMode tile_y) |
| Stroke counterpart. | |
| virtual void | set_blend_mode (BlendMode mode) |
| Set the compositing blend mode for subsequent draw operations. | |
| virtual void | begin_path () |
| Begin a new path. | |
| virtual void | move_to (float x, float y) |
| Move the pen to (x, y) without drawing. | |
| virtual void | line_to (float x, float y) |
| Add a line segment to (x, y). | |
| 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). | |
| virtual void | cubic_to (float cp1x, float cp1y, float cp2x, float cp2y, float x, float y) |
| Add a cubic bezier curve. | |
| virtual void | arc (float cx, float cy, float radius, float start_angle, float end_angle, bool anticlockwise) |
| Native arc subpath. | |
| virtual void | arc_to (float x1, float y1, float x2, float y2, float radius) |
| Native arcTo. | |
| virtual void | ellipse (float cx, float cy, float rx, float ry, float rotation, float start_angle, float end_angle, bool anticlockwise) |
| Native ellipse subpath. | |
| 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. | |
| virtual void | close_path () |
| Close the current path subpath. | |
| virtual void | fill_current_path (FillRule rule=FillRule::nonzero) |
| Fill the current path. | |
| virtual void | stroke_current_path () |
| Stroke the current path. | |
| 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. | |
| virtual void | fill_rect (float x, float y, float w, float h)=0 |
| virtual void | stroke_rect (float x, float y, float w, float h)=0 |
| virtual void | fill_rounded_rect (float x, float y, float w, float h, float radius)=0 |
| virtual void | stroke_rounded_rect (float x, float y, float w, float h, float radius)=0 |
| virtual void | fill_circle (float cx, float cy, float radius)=0 |
| virtual void | stroke_circle (float cx, float cy, float radius)=0 |
| virtual void | clear_rect (float x, float y, float w, float h) |
| Clear a rectangular region to transparent black (rgba 0,0,0,0). | |
| virtual void | stroke_arc (float cx, float cy, float radius, float start_angle, float end_angle)=0 |
| virtual void | stroke_line (float x0, float y0, float x1, float y1)=0 |
| virtual void | stroke_path (const Point2D *points, size_t count) |
| Stroke a continuous polyline — much smoother than individual stroke_line calls. | |
| virtual void | fill_path (const Point2D *points, size_t count, FillRule rule=FillRule::nonzero) |
| Fill a closed polygon defined by points, honoring rule. | |
| 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, y, w, h). | |
| virtual void | fill_path (const Path &path, FillRule rule=FillRule::nonzero) |
| Fill path under rule. | |
| virtual void | stroke_path (const Path &path, const StrokeStyle &style) |
| Stroke path with style. | |
| virtual void | clip_path (const Path &path, FillRule rule=FillRule::nonzero) |
| Intersect the current clip with path. Caller owns save()/restore(). | |
| 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. | |
| virtual void | set_opacity (float alpha) |
| Set global alpha for subsequent drawing operations (0.0-1.0). | |
| virtual LayerHandle | begin_layer (Rect2D bounds, bool cacheable=false) |
| Begin recording into an offscreen layer covering bounds (in current user space). | |
| virtual LayerHandle | end_layer () |
| Seal the layer opened by the last begin_layer() and return its handle. | |
| virtual void | draw_layer (LayerHandle layer, float alpha=1.0f, BlendMode mode=BlendMode::normal) |
| Composite a sealed layer at its recorded position. | |
| virtual void | draw_layer_fitted (LayerHandle layer, Rect2D dest) |
| Composite a sealed layer scaled into dest. | |
| virtual void | draw_layer_rotated (LayerHandle layer, float angle_rad) |
| Composite a sealed layer rotated about its own center. | |
| virtual bool | layer_valid (LayerHandle layer) const |
| Is layer still backed by a live texture that can be drawn WITHOUT re-recording it? | |
| virtual void | invalidate_layer (LayerHandle layer) |
| Drop layer's texture. | |
| 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 draw_scene() the result instead of re-running the (recursive, allocating) paint. | |
| virtual bool | draw_scene (const SceneRecording &rec) |
| Replay a recording produced by THIS backend's record_scene() at the current transform/clip. | |
| 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. | |
| 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. | |
| virtual void | save_layer_with_filters (float x, float y, float w, float h, float opacity, const FilterChainEntry *chain, int count) |
| 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. | |
| 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. | |
| virtual void | set_font (const std::string &family, float size)=0 |
| virtual void | set_text_align (TextAlign align)=0 |
| virtual void | fill_text (const std::string &text, float x, float y)=0 |
| virtual float | measure_text (const std::string &text)=0 |
| 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_index within text. | |
| virtual void | fill_text_anchored (const std::string &text, float x, float y, TextAnchor anchor) |
| 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. | |
| 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. | |
| 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, 1=italic), and letter-spacing (px between glyphs) through to the backend. | |
| virtual void | set_font_smoothing (FontSmoothing smoothing) |
| CSS -webkit-font-smoothing for the text drawn and measured after it. | |
| virtual void | set_font_features (std::vector< FontFeature > features) |
| virtual void | clear_font_features () |
| 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. | |
| virtual bool | supports (CanvasCapability) const |
| Report whether this backend renders cap's verb faithfully. | |
| bool | supports_image_draw () const |
| Whether this backend can actually decode + draw a raster image (the draw_image_from_* verbs below). | |
| 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. | |
| 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. | |
| 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. | |
| 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) |
| 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) |
| virtual bool | measure_image_from_file (const std::string &path, float &out_width, float &out_height) |
| Decoded-image intrinsic dimensions in pixels. | |
| virtual TextMetrics | measure_text_full (const std::string &text) |
| Measure text with full font metrics using current font settings. | |
| virtual void | set_line_dash (const float *intervals, int count, float phase=0.0f) |
| Set the line dash pattern for stroke operations. | |
| 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). | |
| 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, dy). | |
| virtual void | draw_sdf_shape (SDFShape shape, float x, float y, float w, float h, const SDFStyle &style) |
| 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. | |
| 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. | |
| 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 surface filtered through a Gaussian blur of blur_radius. | |
| 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), a grayscale(1) brightness(1.6) pair. | |
| 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, y, w, h). | |
| virtual void | set_shadow_color (Color color) |
| Sticky drop-shadow state that wraps subsequent draw operations, matching the CanvasRenderingContext2D shadowColor / shadowBlur / shadowOffsetX / shadowOffsetY properties. | |
| virtual void | set_shadow_blur (float blur) |
| virtual void | set_shadow_offset_x (float dx) |
| virtual void | set_shadow_offset_y (float dy) |
| virtual void | set_direction (TextDirection direction) |
| virtual void | set_filter (const std::string &filter) |
| Canvas2D ctx.filter. | |
| virtual void | draw_waveform (const float *samples, size_t count, float x, float y, float width, float height, const WaveformStyle &style) |
| 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. | |
| virtual bool | draw_with_sksl (const std::string &sksl, float x, float y, float w, float h, const ShaderDrawOptions &options) |
| 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. | |
| 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. | |
| 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 alignment. | |
| 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. | |
| 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 tile_h). | |
| 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). | |
| 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). | |
| 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. | |
| 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. | |
| 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. | |
| 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 size draw_image_from_data would draw the full image at. | |
| virtual void | set_gradient_interpolation (GradientInterpolation m) |
| Colour space every LATER gradient setter blends its stops in (CSS <color-interpolation-method>), until set again; save() does not keep it. | |
| GradientInterpolation | gradient_interpolation () const |
Static Public Member Functions | |
| 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. | |
| static std::string | compile_sksl (const std::string &sksl) |
| Validate and compile an SkSL shader without drawing. | |
| 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. | |
| 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, whose coverage lives outside the shape, and 0 for every other mode or a zero sigma. | |
| 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. | |
| 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, dy, dw, dh) per fit. | |
Protected Attributes | |
| float | font_size_ = 14.0f |
| Current font size (set by set_font). | |
Stroke a continuous polyline through an array of points.
Much smoother than individual stroke_line calls — produces proper anti-aliased curves with line joins between segments. Alias, not a second type. The canonical point lives at namespace scope in <pulp/canvas/affine_transform.hpp> so Path can use it; this name keeps every existing Canvas::Point2D call site working. (It is spelled Point2D rather than Point because Apple's MacTypes.h declares a global Point — see the note on pulp::canvas::Point2D.)
|
strong |
Indices 0..15 match the existing W3C "advanced" composite ops and must stay stable — set_blend_mode in the JS bridge currently passes int_val 1/2/3 = multiply/screen/overlay.
Indices 16+ are Porter-Duff and "extra" CSS composite ops added so the JS bridge can support the full CanvasRenderingContext2D.globalCompositeOperation surface.
|
strong |
Preserve-aspect fit modes for fit_image_rect / draw_image_fitted: fill — stretch to the destination box, ignoring aspect ratio.
contain — scale (preserving aspect) to the largest size that fits fully inside the box; may leave margins. cover — scale (preserving aspect) to the smallest size that fully covers the box; may crop (clipped to the box). none — natural pixel size, no scaling; positioned by alignment. scale_down — like none when the image already fits, otherwise like contain (never scales up).
| Enumerator | |
|---|---|
| fill | |
| contain | |
| cover | |
| none | |
| scale_down | |
|
strong |
|
strong |
Canvas2D ctx.createPattern.
Tile mode per axis: repeat mirrors Skia's SkTileMode::kRepeat, no_repeat mirrors SkTileMode::kDecal. Spec values map as: "repeat" → (repeat, repeat) "repeat-x" → (repeat, no_repeat) "repeat-y" → (no_repeat, repeat) "no-repeat" → (no_repeat, no_repeat)
| Enumerator | |
|---|---|
| repeat | |
| no_repeat | |
|
strong |
|
strong |
Explicit, typed vertical-anchor API.
The historical fill_text(text, x, y) follows the Canvas2D spec (web-compat baseline semantics) — y is the text baseline. Non-spec callers (widgets that mix labels with knobs / faders inside flex rows) need to opt for a different reference line so mixed-fontSize centered rows align on glyph reference, not box reference. Anchor modes:
Baseline — y is the baseline (Canvas2D web-spec default). GlyphTop — y is the top of the worst-case glyph bbox (SkFontMetrics::fTop). Useful when the caller computes top-of-text manually. GlyphCenter — y is the vertical CENTER of the glyph bbox. Use for vertical-align: middle semantics where you want the painted glyphs (not the measure box) centered on a target line. EmBoxTop — y is the top of the em-box (font-size based, font-independent). Use when laying out uniform-sized glyph grids.
Default implementation ignores anchor and treats y as the baseline, delegating straight to fill_text. Backends with font metrics override to translate y into a per-anchor baseline-y so glyphs land on the exact pixel the parity harness asserts.
| Enumerator | |
|---|---|
| Baseline | |
| GlyphTop | |
| GlyphCenter | |
| EmBoxTop | |
|
strong |
Canvas2D ctx.direction.
Sticky text-shaping direction that applies to subsequent fillText / strokeText calls. Spec values: ltr — left-to-right (default; matches SkShaper leftToRight=true) rtl — right-to-left (HarfBuzz buffer direction RTL) inherit — pulled from the canvas element / document writing direction. On backends without a per-View writing direction yet, treated as ltr (the most common case). Default no-op so backends without a real bidi/HarfBuzz path remain unaffected; SkiaCanvas overrides to wire through to the SkShaper invocation flag, RecordingCanvas captures one set_direction command per setter so canvas2d harness tests can assert flush order. Real bidi support (mixed-script paragraphs requiring the Bidi algorithm) tracks separately.
| Enumerator | |
|---|---|
| ltr | |
| rtl | |
| inherit | |
|
virtualdefault |
|
inlinevirtual |
Native arc subpath.
Maps to Canvas2D ctx.arc(cx, cy, r, startAngle, endAngle, anticlockwise) and to SkPath::arcTo(SkRect, startDeg, sweepDeg, false) on Skia. Replaces the JS shim's bezier approximation. The default fallback emits a quadrant-segmented cubic-bezier polyline so capture-only backends (RecordingCanvas) still produce a meaningful command stream when they choose not to override.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Native arcTo.
Maps to Canvas2D ctx.arcTo(x1, y1, x2, y2, radius) and to SkPath::arcTo(p1, p2, radius) on Skia (the 5-arg overload that computes the tangent arc between the current point, p1, and p2).
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtualnoexcept |
Effective device pixels per local canvas unit at the current transform.
Backends with an inspectable CTM override this when necessary; the default is correct for logical 1x recording/test canvases.
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
inlinevirtual |
Begin recording into an offscreen layer covering bounds (in current user space).
Drawing between this and end_layer() goes to the layer, not the canvas.
cacheable asks the backend to KEEP the layer's texture after end_layer() so it can be redrawn on later frames without re-recording. A non-cacheable layer may be discarded as soon as it has been drawn once.
Backends without offscreen support return the null handle and draw through to the canvas directly. That degrades to "re-record every frame", which is correct — just not cached — because layer_valid() keeps returning false and the caller's if above keeps re-recording.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Begin a new path.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Snapshot the current device matrix as the baseline for subsequent set_transform() calls.
CanvasWidget::paint() calls this at entry so JS-supplied setTransform() composes onto the parent View transform rather than wiping it. Default no-op for non-Skia backends.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Clear gradient, return to solid fill color.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
inlinevirtual |
Clear a rectangular region to transparent black (rgba 0,0,0,0).
Equivalent to CanvasRenderingContext2D.clearRect — replaces existing pixels rather than compositing over them. Pixel backends (SkiaCanvas) override with a kSrc/kClear paint so the underlying texels actually become transparent; the default falls back to a SrcOver fill with a transparent color (a no-op on most surfaces, but keeps recording / introspection backends inert). Without this replacement path, ctx.clearRect() on the canvas widget would not clear residual or parent-painted pixels.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Clear stroke gradient/pattern shader, restore solid stroke color.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Intersect the current clip region with the current path.
Mirrors CanvasRenderingContext2D.clip(). Default no-op so backends without a path builder remain unaffected. rule selects nonzero vs evenodd winding.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Intersect the current clip with path. Caller owns save()/restore().
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
CSS clip-path: path("...") — intersect the current clip with an SVG-path-d string.
Skia maps to SkPath::FromSVGString + SkCanvas::clipPath. RecordingCanvas captures a clip_path_svg command for tests; backends without a path parser fall back to a no-op so callers can invoke it unconditionally without breaking save/restore bookkeeping. The caller is responsible for save()/restore() balancing — typical usage is save(); clip_path_svg("M..."); ...children...; restore();.
Reimplemented in pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Close the current path subpath.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
static |
Compile an author chart shader against the geometry prelude used by draw_sdf_shape_with_shader.
The author source must define shade(PulpChart).
|
static |
Validate and compile an SkSL shader without drawing.
Returns error string (empty = success). Static so it can be called without a Canvas instance. Non-Skia builds return a non-empty "Skia not available" error rather than reporting a false success — there is no compiler to ask.
|
inlinevirtual |
Concat (multiply) the supplied affine matrix onto the current transform — does NOT replace it.
Used by View::paint_all() when a JS-supplied setTransform(id,a,b,c,d,e,f) is active on a View, so the View's transform composes with parent transforms (translate to bounds, outer transforms, etc.) rather than wiping them. Mirrors SkCanvas::concat. Matrix layout matches CanvasRenderingContext2D.setTransform: [ a c e ] [ b d f ] [ 0 0 1 ] Default no-op so non-Skia backends compile; Skia overrides to call SkCanvas::concat, RecordingCanvas overrides to capture the command.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Add a cubic bezier curve.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Snapshot the current device matrix (CTM) without mutating canvas state.
Used by CanvasWidget::paint() diagnostics to log the inbound transform per paint when PULP_LOG_CANVAS_PAINT=1 is set, so we can confirm whether a missing canvas paint is caused by the CTM ending up off-window vs the widget never being painted at all. Default returns identity for backends without an introspectable matrix; SkiaCanvas (getTotalMatrix), CoreGraphicsCanvas (CGContextGetCTM), and RecordingCanvas (manual matrix tracking) override.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Save a blurred snapshot of the current canvas content as a backdrop.
Call before painting the overlay content.
|
virtual |
Draw a CSS-style box shadow around (or inside, when inset) a rounded rectangle anchored at (x, y, w, h).
When inset is false this is a drop shadow rendered outside the box; when true it is an inner shadow rendered inside the box clipped to the box geometry. Default implementation is a CPU fallback that approximates the blur with stacked translucent rounded rects — Skia overrides with SkImageFilters::DropShadowOnly for a true Gaussian shadow. The out-of-line definition lives in core/canvas/src/recording_canvas.cpp so the CPU fallback is exercised by the canvas-level tests during coverage runs.
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Draw an image identified by an opaque, platform-specific handle into the rectangle (x, y, w, h).
The handle is the native_handle published by pulp::view::ImageCache (see core/view/include/pulp/view/image_cache.hpp). Backends know how to interpret their own handles:
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Draw a file-path image fitted into a destination box.
Consults measure_image_from_file for the intrinsic size; if the backend cannot measure it, falls back to stretching the image to the box (the plain draw_image_from_file behavior). Returns whatever the underlying draw returns (false when the backend cannot draw the image).
|
inlinevirtual |
Draw an opaque image handle fitted into a destination box with a preserve-aspect fit mode and alignment.
iw / ih are the image's intrinsic pixel dimensions (the handle is opaque, so the caller supplies them). The default clips to the destination box — so cover cannot paint outside it — and draws the fitted rectangle via draw_image.
|
inlinevirtual |
Draw an image from encoded data (PNG, JPEG, WebP) at the given rect.
Returns true if the image was decoded and drawn successfully.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Draw an image from a file path at the given rect.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Draw encoded image bytes identified by content_key, the lowercase hex SHA-256 of exactly those bytes.
A backend may retain the decoded or GPU-uploaded image under that key across frames, so the key must change whenever the bytes do and must never be derived from the buffer address (a freed buffer's address is reused for different bytes). An empty key draws uncached. The default does not cache; it draws exactly as draw_image_from_data. Appended to preserve existing vtable slots.
|
inlinevirtual |
Source-rect form of draw_image_from_keyed_data, with the same key contract.
The default draws exactly as draw_image_from_data_rect.
|
inlinevirtual |
Source-rect draw for bytes with static storage duration and immutable contents.
GPU backends may retain a decoded/uploaded image across frames. Appended to preserve the slots of existing Canvas virtual methods. Never use this for a mutable or short-lived buffer.
|
inlinevirtual |
Fill the destination box (dx, dy, dw, dh) by tiling an opaque image handle at cells of size (tile_w x tile_h).
offset_x / offset_y shift the tile origin (for scrolling patterns). The default clips to the box and lays whole tiles via repeated draw_image; the trailing row / column overshoot the box but are clipped away. Pixel backends may override with a single tiled-shader fill; set_fill_pattern is the sticky shader-based alternative when a fill PATH (rather than a direct box) is what needs the tiling.
|
inlinevirtual |
Draw an opaque image handle (see draw_image) under an arbitrary affine transform.
The image's natural box [0, 0, w, h] is painted through t, composed onto the current transform. Default composes concat_transform + draw_image inside a save / restore pair so the caller's transform state is preserved.
|
inlinevirtual |
Composite a sealed layer at its recorded position.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Composite a sealed layer scaled into dest.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Composite a sealed layer rotated about its own center.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Draw ONLY the drop shadow cast by path — not the path itself.
This is a shadow-*rendering* primitive, deliberately separate from save_layer_with_filters's drop_shadow filter Kind (which shadows a whole painted subtree). The split exists because the common case — "shadow behind this icon, then the icon on top, in a different color" — needs the shadow WITHOUT the source, and a filter chain always composites the source too.
spread grows the shadow's silhouette before blurring, matching the CSS box-shadow spread term. The default fallback approximates it by scaling the path about its own center, which is exact for convex shapes and an approximation for concave ones (a true spread is a Minkowski sum / path outset, which is not something the immediate-mode API can express).
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Replay a recording produced by THIS backend's record_scene() at the current transform/clip.
Returns false when rec is not this backend's recording type (defensive — a foreign or base recording is never drawn), leaving the caller to fall back to a direct paint.
|
inlinevirtual |
|
inlinevirtual |
Draw a shape through an author-supplied geometry chart shader.
The shader must define half4 shade(PulpChart g).
Charted shapes are flat_arc, ring, flat_segment, rounded_segment and stadium; any other shape is refused, by name, rather than drawn. g.cross is the signed offset from the centre line, g.d the band's distance. g.valid is zero for degenerate geometry (no sweep, length or band); callers must not interpret chart fields when it is zero.
g.px is one device pixel expressed in the same units as g.d, taken from backing_scale(), so 2.0 * g.px is two device pixels at any backing scale rather than only at 1x.
The shader is evaluated over the w x h rect grown by options.reach on every side, so a feather or glow can paint past the shape's box. A glow or outer feather whose reach is below sdf_feather_min_reach(style) is refused (returns false, draws nothing) rather than drawn with its falloff cut off at the rect edge.
|
inlinevirtual |
Render an SVG document (the literal <svg>…</svg> string) into the box [x,y,w,h], scaled to fit.
Backed by Skia's SkSVGDOM, so gradients, filters (drop shadows), masks, opacities, and transforms render exactly as authored — the faithful-vector design-import lane draws a Figma node's own SVG export through here instead of approximating it. Returns false if the backend can't render SVG (non-Skia) or the document fails to parse.
|
inlinevirtual |
|
inlinevirtual |
|
inlinevirtual |
Draw a rectangle filled by a custom SkSL shader.
Only works on GPU backends (SkiaCanvas). CPU backends draw a fallback rect. The shader receives: uniform float2 resolution, float value, float time, layout(color) float4 accentColor/bgColor/trackColor/fillColor/thumbColor.
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Native ellipse subpath.
Maps to Canvas2D ctx.ellipse(cx, cy, rx, ry, rotation, startAngle, endAngle, anticlockwise). Honours rotation (rx/ry axis rotation in radians) by transforming the arc through SkMatrix on Skia.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Seal the layer opened by the last begin_layer() and return its handle.
After this, drawing goes back to the canvas (or the enclosing layer).
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Fill the current path.
rule selects nonzero vs evenodd winding, matching Canvas2D ctx.fill('evenodd').
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Fill path under rule.
Resets the current path, matching the Canvas2D convention that a shape-drawing call owns the path it builds.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Fill a closed polygon defined by points, honoring rule.
rule selects nonzero vs even-odd winding, exactly as fill_current_path(rule) / Canvas2D ctx.fill('evenodd') do. Without it a compound point array (an outer contour followed by an inner one) could only ever fill as a solid disc — there was no way to punch the hole that makes it a ring.
The default is NOT a no-op. It synthesizes the polygon through the path API — begin_path / move_to / line_to / close_path / fill_current_path(rule) — which every backend already implements, so a Canvas subclass that does not override fill_path still draws the polygon instead of silently dropping it. Backends override only to skip the state round-trip (SkiaCanvas builds one SkPath; CoreGraphicsCanvas one CGPath).
Note the default resets the current path (begin_path), matching the Canvas2D convention that a shape-drawing call owns the path it builds. Degenerate input (null array, or fewer than three points — no enclosed area) draws nothing and never reads the array.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
|
inlinevirtual |
Render text using an SDF glyph atlas for resolution-independent rendering.
The atlas must be pre-built via SdfAtlas::build(). Falls back to fill_text() if GPU is unavailable or the atlas doesn't contain the required glyphs.
|
inlinevirtual |
Canvas2D fillText(text, x, y, maxWidth) spec form.
When max_width > 0 and the natural rendered advance exceeds it, the backend MUST scale the text horizontally so the resulting run is exactly max_width px wide (vertical metrics unchanged). The default implementation falls through to fill_text(text, x, y), preserving legacy behavior for backends that don't yet honor the constraint (RecordingCanvas, base mocks). Skia and CoreGraphics override this to apply an SkMatrix::Scale(maxWidth/measured, 1) (Skia) / CGContextScaleCTM(scale, 1) (CG) around the text origin. Glyph cluster boundaries are unaffected — HarfBuzz already shapes each cluster as an indivisible unit, so horizontal compression preserves cluster integrity by construction.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinestatic |
Pure geometry: place a source image of intrinsic size (iw x ih) into the destination box (dx, dy, dw, dh) per fit.
Alignment align_x / align_y are fractions in [0, 1]: 0 = left / top, 0.5 = center, 1 = right / bottom, positioning the scaled image inside (or, for cover, over) the box. Side-effect free, so it is unit-testable on its own without a backend.
|
inline |
|
inlinevirtual |
Drop layer's texture.
The next layer_valid() returns false, so the caller re-records it. Call this when the layer's contents change; backends may also perform the same retirement for context/scale changes.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Is layer still backed by a live texture that can be drawn WITHOUT re-recording it?
Check every frame: explicit invalidation and backend context/backing-scale lifecycle changes may retire a handle.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Add a line segment to (x, y).
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinestaticconstexpr |
Builds a 4-byte big-endian OpenType tag from a 4-char string.
Caller supplies exactly 4 ASCII chars (e.g. "tnum"); shorter strings are a compile error.
|
inlinevirtual |
Intrinsic pixel size of encoded image bytes, read from the image header without decoding pixels: the size draw_image_from_data would draw the full image at.
Returns false (sizes 0) when the bytes are not an image this backend can decode. The default reads a PNG IHDR only, so a backend with no decoder still sizes PNGs; Skia and CoreGraphics read every format their decoders accept. Appended after the existing virtuals.
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
inlinevirtual |
Decoded-image intrinsic dimensions in pixels.
Returned via out-params so backends without image decode just leave them at 0 and callers short-circuit to "use destination bounds" (the previous behavior). Used by ImageView::paint to honor CSS object-fit / object-position and by canvas2d sprite sizing. Default returns false; Skia overrides to consult its decoder.
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Measure text with full font metrics using current font settings.
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
inlinevirtual |
Move the pen to (x, y) without drawing.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Add a quadratic bezier curve to (x, y) with control point (cpx, cpy).
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Read RGBA pixels from the current surface into out (size must be at least width*height*4).
Returns true on success. Default returns false (RecordingCanvas, CG fallback) — only Skia raster surfaces implement this end-to-end. Mirrors CanvasRenderingContext2D.getImageData().
|
inlinevirtual |
Record paint into a replayable SceneRecording, capturing its draw commands ONCE so later frames can draw_scene() the result instead of re-running the (recursive, allocating) paint.
w/h are the recorded content's logical size — the recording is resolution-INDEPENDENT (it stores commands in logical coordinates), so a DPI change replays the same recording with no re-record and no image re-upload.
Distinct from the begin_layer/draw_layer texture cache above: that snapshots a rasterised texture (Visage-style), this records the command stream (a lighter, resolution-free cache). Both are opt-in caches over the same "paint a subtree once, reuse it" need.
Returns nullptr when the backend cannot record (the base class, the CoreGraphics backend, and RecordingCanvas all do) — the caller MUST then paint directly every frame. supports(CanvasCapability::scene_cache) reports which backends record for real, so a caller can decide up front.
|
inlinevirtualnoexcept |
Identity of the renderer this canvas actually wraps.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Pop the save stack down to target (typically captured earlier via save_count()).
Backends that support it pop any leftover saves so an unbalanced JS draw script can't leak a ctx.save() into the parent View's paint scope. Default is a no-op so non-tracking backends keep their existing behavior; the CanvasWidget defense is meaningful only on backends that override both methods.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Native rounded-rectangle subpath with per-corner radii.
Maps to Canvas2D ctx.roundRect(x, y, w, h, radii) and to SkRRect::MakeRectRadii on Skia. Radii layout matches the CSS 8-value form: top-left x/y, top-right x/y, bottom-right x/y, bottom-left x/y. The JS shim normalizes the 1/2/3/4-value forms to 8 floats before crossing the bridge.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
CSS backdrop-filter: blur(Npx) — push a compositing layer whose initial contents are the parent surface filtered through a Gaussian blur of blur_radius.
Subsequent draws into this layer composite over the blurred backdrop. Must be paired with restore().
Skia maps to SkCanvas::saveLayer(SaveLayerRec{ .fBackdrop = Blur }). CPU/recording fallback is a plain save() so the matching restore() stays balanced — visual fidelity downgrades to an unblurred overlay.
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
CSS backdrop-filter with its full function list — saturate(0.2), brightness(2), invert(1), a grayscale(1) brightness(1.6) pair.
Same layer contract as save_backdrop_filter: the layer's initial contents are the parent surface run through the composed filter, and it must be paired with restore().
The default keeps exactly the behaviour every backend already had — blur entries summed, everything else dropped — so a backend that has not implemented the chain renders an unfiltered (or merely blurred) backdrop rather than an unbalanced canvas stack. Query CanvasCapability::backdrop_filter_chain to find out which you got.
|
inlinevirtual |
Return the current save-stack depth.
Used by CanvasWidget::paint() to defend against JS-driven ctx.save() / ctx.restore() imbalance: snapshot the depth at paint entry, replay the queued commands, then restore_to_count(initial_depth) to drop any leftover saves. Mirrors SkCanvas::getSaveCount / CGContext save-stack depth. Default returns 0 — backends without an introspectable stack rely on the default restore_to_count no-op below to leave behavior unchanged.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Save a compositing layer.
All drawing until restore() is composited with the given opacity and optional blur. This is the correct way to implement CSS opacity and filter:blur() — the subtree paints into an offscreen buffer and is composited back as a single unit.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Save a compositing layer with an explicit blend mode.
Used by CSS / RN mix-blend-mode: the subtree paints into the offscreen layer and the layer-paint composites back with the requested blend mode. Default BlendMode::normal is equivalent to the plain save_layer overload (kSrcOver). Subclasses that don't know how to honor the blend mode fall back to the plain overload.
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Save a compositing layer that applies a real bloom/glow post-effect to the subtree painted into it.
The layer content is thresholded (only pixels brighter than threshold contribute), blurred by radius, and additively composited (kPlus) back over the original — so bright regions bleed a glow beyond their edges. Restored by the matching restore().
| intensity | glow gain applied to the thresholded highlights |
| threshold | brightness cutoff in [0,1]; pixels below it don't glow |
| radius | blur radius (px) of the glow |
The base implementation has no offscreen post-processing, so it degrades to a plain blurred layer (save_layer with radius * intensity blur) — the de-facto behavior effects had before a real bloom existed. Only the GPU backend (SkiaCanvas) implements the true threshold+blur+additive graph; RecordingCanvas records the bloom intent for headless assertions.
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
CSS mask-image + mask-size paint slice.
Composes the subtree with a mask shader applied via SkBlendMode:: kDstIn so the painted result keeps only the alpha that the mask permits. The Pulp pipeline: saveLayer(opacity) <- subtree paint target ... subtree paints into the layer ... saveLayer(SkBlendMode::kDstIn) <- mask composite layer drawShader(mask_image, scaled by mask_size) restore() <- composes the mask alpha onto the subtree restore() <- composes the masked subtree to the parent
mask_image is the CSS value verbatim — typically linear-gradient(...), radial-gradient(...), url(...), or none. mask_size is the CSS mask-size value (auto | cover | contain | <length>{1,2}).
The matching restore() call drives the mask composite (the canvas tracks pending masks on its save stack). Subclasses that can't honor the mask fall back to the plain save_layer overload (no mask applied — matches the existing behavior for backends without shader support). Unrecognized / unparseable mask_image values also fall back to the no-mask path so authors don't lose their content to a parser error.
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Curated, named GPU post-effect layer save.
This is the SAFE shader-effect entry for scripted / generated UIs: the subtree paints into an offscreen layer, and at restore() the whole layer is post-processed by ONE of a small vetted set of SkSL effects selected BY NAME — never arbitrary shader source. Known names (see core/canvas/src/named_shader_effects.hpp): crt, grain, vignette, noise, brushed, bloom. intensity is the single 0..1 strength knob (clamped by the backend).
Unknown names, degenerate sizes, or a Skia/GPU-unavailable backend all degrade gracefully to a plain save_layer (effect skipped) so a generated UI can request an effect unconditionally and headless CPU renders never crash. The default impl here IS that fallback; only SkiaCanvas builds the runtime-effect image filter.
|
inlinevirtual |
Save a compositing layer whose ALREADY-PAINTED content is post-processed by a custom SkSL shader.
Unlike draw_with_sksl (which fills a fresh rect from a generative shader), this is a child-shader compositor: the subtree paints into the layer, then on restore() the shader runs over that content. The SkSL MUST declare uniform shader content; as its child — content.eval(xy) samples the subtree's rendered pixels — e.g. uniform shader content; half4 main(float2 xy) { return content.eval(xy).bgra; } // channel swap The same fixed uniform vocabulary as draw_with_sksl (resolution / value / time / accentColor / bgColor / trackColor / fillColor / thumbColor) is bound when declared, PLUS any arbitrary extra_uniforms (name → float/vec) the shader declares — guarded by findUniform, so unknown names are ignored.
blend_mode is how the finished post-effect layer composites back onto its parent (default source-over). BlendMode::lighter gives the additive audio-UI glow pattern.
sample_radius is the maximum distance (px) the shader may sample content.eval() away from the pixel being shaded — Skia needs this so a shader that reads neighboring texels (e.g. chromatic aberration's per-channel offset) gets valid samples near the layer edge instead of transparent black. Leave 0 for shaders that only read the current pixel.
Returns true when the shader was installed on the layer. Only the GPU backend (SkiaCanvas) implements it; the base falls back to a plain save_layer (still balanced — the subtree renders unfiltered) and returns false so callers can log the unsupported path once.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinestatic |
The smallest draw-rect reach that holds style's feather: 3 sigma for the glow (1) and outer (3) modes, whose coverage lives outside the shape, and 0 for every other mode or a zero sigma.
Beyond 3 sigma the Gaussian falloff is under 0.15%, so a reach at or above this value never shows a hard edge where the draw rect ends.
|
inlinevirtual |
Set the compositing blend mode for subsequent draw operations.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Set a conic (sweep) gradient as the fill paint.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Set a REPEATING conic gradient (CSS repeating-conic-gradient).
The stop list spans sweep_turns of a full turn — positions are normalized to 0..1 across that band — and the band tiles around the circle.
Declared LAST, and as its own virtual rather than a wider set_fill_gradient_conic, on both of the usual grounds: a signature change would reorder this vtable under every prebuilt SDK consumer, and the Canvas2D command recorders would have to grow a field to carry the span. The default paints the band ONCE and clamps the rest, which is what a backend that cannot tile should show — recognisably the right colours in the wrong places, rather than nothing or a silent full-circle stretch.
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
inlinevirtual |
Set a linear gradient as the fill paint.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Set a REPEATING linear gradient (CSS repeating-linear-gradient).
The two points delimit ONE BAND rather than the whole box — positions are normalized to 0..1 across that band — and the band tiles along the gradient line in both directions.
Declared after the conic form above and for the same two reasons: a wider set_fill_gradient_linear would reorder this vtable under every prebuilt SDK consumer, and the Canvas2D command recorders would have to grow a field to carry the tile mode. The default paints the band ONCE and clamps the rest, which is what a backend that cannot tile should show — recognisably the right colours in the wrong places, rather than nothing or a silent stretch across the box.
|
inlinevirtual |
Set a radial gradient as the fill paint.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Radial gradient with an independent radius per axis — the ending shape CSS calls an ellipse, which is radial-gradient's DEFAULT shape and the only one a two-value size (90% 70%) can express.
Backends that can carry a local matrix on the shader override this; the default forwards to the circular overload using the horizontal radius, which is the pre-existing approximation rather than a blank fill.
|
inlinevirtual |
Canvas2D ctx.createRadialGradient(x0,y0,r0,x1,y1,r1) two-circle form.
(x0,y0,r0) is the inner / start circle, (x1,y1,r1) is the outer / end circle. Backends with a real two-circle shader (Skia MakeTwoPointConical, CG CGContextDrawRadialGradient) override; the default forwards to the single-circle overload using the outer circle so older fallbacks still get a usable gradient.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Set an image pattern as the fill paint.
image_src is a file path or data: URL — same identifier shape draw_image_from_file consumes, so backends share one decode path. Default is no-op so CPU-only / minimal canvases compile; SkiaCanvas overrides with a real SkShader::MakeImage. Empty image_src clears any active pattern (mirrors clear_fill_gradient's reset semantics).
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Canvas2D ctx.filter.
Sticky CSS <filter-function-list> string applied to subsequent fill / stroke / text / image draws. Spec supports: blur, brightness, contrast, drop-shadow, grayscale, hue-rotate, invert, opacity, saturate, sepia. The default is "none". SkiaCanvas parses the string into an SkImageFilter chain and applies via SkPaint::setImageFilter; CG and other backends can store the value but render unfiltered. RecordingCanvas captures the raw string. Distinct from CSS filter on a View: that filter applies to the View element, this one applies to the per-context Canvas2D paints inside it.
Reimplemented in pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
inlinevirtual |
Richer font setter that propagates CSS font-weight (100..900), font-slant (0=upright, 1=italic), and letter-spacing (px between glyphs) through to the backend.
Default implementation forwards to the legacy set_font(family, size) so non-Label callers keep working unchanged. Backends that honor these properties (Skia, CoreText, RecordingCanvas) override this to capture or apply them. Label widget honors setFontFamily / setFontWeight / setLetterSpacing from JS.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
CSS -webkit-font-smoothing for the text drawn and measured after it.
antialiased turns glyph hinting off, which with a chromium surface (pulp/canvas/text_raster_policy.hpp) reproduces Chromium's antialiased glyphs; auto keeps the default light hinting. Scoped by save()/restore() like the clip and matrix. Skia, CoreGraphics and RecordingCanvas implement it; the default ignores it.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Colour space every LATER gradient setter blends its stops in (CSS <color-interpolation-method>), until set again; save() does not keep it.
Appended for the vtable. Skia blends natively, CoreGraphics resamples.
Reimplemented in pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Canvas2D ctx.imageSmoothingEnabled + imageSmoothingQuality.
Sticky paint flag honored by subsequent drawImage calls. When enabled is false the backend uses nearest-neighbor sampling; when true the quality enum picks the resampler. Default no-op so backends without smoothing support compile; SkiaCanvas (SkSamplingOptions) and CoreGraphicsCanvas (CGContextSetInterpolationQuality) override. RecordingCanvas captures a set_image_smoothing command for tests.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Set the line dash pattern for stroke operations.
Mirrors CanvasRenderingContext2D.setLineDash(). intervals alternate "on" / "off" lengths in pixels. An empty pattern (count == 0) clears the dash and reverts to solid strokes. HTML5 spec: an odd-length pattern is duplicated to even length; callers that want spec compliance must duplicate before invoking this method (the JS bridge does so). Default no-op for backends without dash support.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Canvas2D ctx.miterLimit.
Sticky stroke state — controls when a miter join collapses to a bevel (Skia / CG default = 10). Spec requires non-finite or non-positive values to be silently ignored; callers that want spec semantics should clamp at the JS bridge. Default no-op so backends without miter-limit support compile; SkiaCanvas (SkPaint::setStrokeMiter) and CoreGraphicsCanvas (CGContextSetMiterLimit) override. RecordingCanvas captures a set_miter_limit command for tests.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Set global alpha for subsequent drawing operations (0.0-1.0).
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Sticky drop-shadow state that wraps subsequent draw operations, matching the CanvasRenderingContext2D shadowColor / shadowBlur / shadowOffsetX / shadowOffsetY properties.
The shadow renders only when color.a > 0 AND (blur > 0 OR offset_x != 0 OR offset_y != 0) — same gate Chromium / WebKit use. Setting color to fully transparent (alpha == 0) effectively disables the shadow even if blur/offset are non-zero, mirroring spec semantics.
Backends that draw via SkPaint / CGContext layer the shadow onto the next draw call by configuring an image filter (Skia DropShadow) or CGContextSetShadowWithColor respectively. The default implementation here is a no-op so backends that haven't opted into shadow support compile unchanged; SkiaCanvas, CoreGraphicsCanvas, and RecordingCanvas override to actually honor (or capture) the state.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Two-circle radial gradient on stroke (mirrors fill counterpart).
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Stroke counterpart.
Rare in production code; default no-op. SkiaCanvas overrides via the same SkShader::MakeImage path applied to the stroke paint.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Replace the current transform with the affine matrix [ a c e ] [ b d f ] [ 0 0 1 ] Mirrors CanvasRenderingContext2D.setTransform(a, b, c, d, e, f).
Default implementation is a no-op so non-GPU backends still compile; SkiaCanvas overrides to compose the supplied matrix onto the paint baseline captured via capture_paint_baseline_transform().
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
static |
Whether an SkSL shader declares a uniform of the given name.
Compiles via the same process-lifetime cache as compile_sksl, so repeat queries are free; false if the source does not compile.
Used to decide whether a shader is time-driven and needs continuous repaint. Not a substring search: a timeline uniform must not pin the render loop, and a differently-spelled one must not silently freeze.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Stroke the current path.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Stroke path with style.
Unlike the set_line_width / set_line_cap / set_line_join triplet, the whole stroke configuration arrives as one value and cannot be half-applied.
NOTE the default fallback mutates the canvas's stroke state (width / cap / join / dash) and does not restore it, because the immediate-mode API has no way to read the previous values back. Backends that override this — Skia and CoreGraphics both do — keep the style local to the one draw. Callers that care should save()/restore() around it.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Stroke a continuous polyline — much smoother than individual stroke_line calls.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Canvas2D strokeText(text, x, y, maxWidth) spec form.
True outlined-glyph rendering: builds a stroked paint (SkPaint::kStroke_Style on Skia, CG text drawing mode kCTLineDrawingModeStroke on CoreGraphics) so the glyph outlines honor the current lineWidth / strokeStyle. The default implementation degrades to fill_text with the stroke color pre-set by the caller — visually approximate but spec-incompatible. Backends override to render real glyph outlines. max_width semantics match fill_text_with_max_width.
Reimplemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Report whether this backend renders cap's verb faithfully.
Base returns false for everything: the base-class verb defaults are all degradations (silent no-op, color/mask/blur op dropped, filename placeholder). Concrete backends override to advertise the subset they actually implement. Callers branch on this to log-once and keep the documented fallback rather than silently emitting an unfaithful frame.
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
inline |
Whether this backend can actually decode + draw a raster image (the draw_image_from_* verbs below).
Thin alias for supports(CanvasCapability::images) — kept because it is public API used by headless tooling (ImageView placeholder path, CG image tests). Not virtual: backends express image support through supports(), and this forwards to it so there is one vocabulary and one source of truth.
|
inlinevirtual |
Caret x (in text-local space, measured from the text's leading edge) for the glyph boundary at byte_index within text.
This is the drift-proof companion to measure_text: it shapes the FULL run with the current font state (family / size / weight / slant / letter-spacing / direction / features) and returns the caret offset for the cluster boundary at byte_index, so a kerned pair like "AV" reports the same advance the painter actually draws — not the sum of isolated glyph widths.
The default implementation measures the prefix substring, which is correct for unkerned, unspaced text but drifts on kerned runs. The Skia backend overrides this to query the shaped paragraph directly.
Reimplemented in pulp::canvas::CoreGraphicsCanvas.
|
pure virtual |
Implemented in pulp::canvas::CoreGraphicsCanvas, and pulp::canvas::RecordingCanvas.
|
inlinevirtual |
Write RGBA pixels (data size = width*height*4) to the current surface at destination (dx, dy).
Returns true on success. Mirrors CanvasRenderingContext2D.putImageData().
Reimplemented in pulp::canvas::RecordingCanvas.
|
protected |
Current font size (set by set_font).