ltk::gles_render

Struct GlesCanvas

Source
pub struct GlesCanvas {
    pub gl: Arc<Context>,
    pub version: GlesVersion,
    pub font: Arc<Font>,
    pub font_bytes: Arc<Vec<u8>>,
    pub font_face: u32,
    pub font_registry: Option<Arc<FontRegistry>>,
    pub dpi_scale: f32,
    pub global_alpha: f32,
    pub width: u32,
    pub height: u32,
    /* private fields */
}
Expand description

GPU-accelerated canvas using EGL + GLES2/3.

Renders into a persistent FBO (the “shadow canvas”) so widget pixels survive across frames — this mirrors the software pixmap model and is what enables the partial-redraw path on the GPU side. Self::present blits the FBO onto the default framebuffer; the caller is responsible for the eglSwapBuffers that follows.

Fields§

§gl: Arc<Context>§version: GlesVersion§font: Arc<Font>

Default font loaded from the system via system_fonts::default_handle. Kept as a fallback for callers that do not route through the theme registry.

§font_bytes: Arc<Vec<u8>>

Raw bytes of the default font. Required by rustybuzz for HarfBuzz shaping (see the text_shaping private module). Kept on the canvas so the shape pipeline has direct access without a global lookup.

§font_face: u32

TTC sub-face index for the default font (0 for non-.ttc files).

§font_registry: Option<Arc<FontRegistry>>

Optional theme font registry. Populated by the runtime after theme load; until then it is None and Self::font_for falls back to Self::font.

§dpi_scale: f32§global_alpha: f32§width: u32§height: u32

Implementations§

Source§

impl GlesCanvas

Source

pub fn new( gl: Arc<Context>, version: GlesVersion, width: u32, height: u32, ) -> Self

Build a GPU canvas of width × height physical px on an already-current EGL/GLES context. Compiles every shader program, looks up its uniforms, uploads the shared quad geometry and the glyph atlas (format chosen per ES profile), then allocates the persistent shadow FBO and makes it the active draw target — every draw writes into the FBO, and Self::present is the only call that blits it to the default framebuffer. dpi_scale and global_alpha start at 1.0; the default font comes from the process-wide cached handle. Panics if the FBO is incomplete or a program fails to link.

Source

pub fn sub_canvas(&self, width: u32, height: u32) -> GlesCanvas

Build a sub-canvas: a separate render target sharing this canvas’s GL context, font, shader programs, geometry, and uniform locations, but with its own FBO + color texture sized to width × height. Used to render content into an off-screen target that can then be composited back via Self::blit.

The returned canvas inherits the parent’s dpi_scale and global_alpha (so glyphs render at the same pixel size). Its glyph cache starts empty — re-rasterising on first use is the cost of not sharing GL textures across canvases.

Source

pub fn size(&self) -> (u32, u32)

( width, height ) of the FBO in physical px.

Source

pub fn clear_gradient_cache(&mut self)

Discard all cached gradient LUT textures. Call after a theme change so stale LUTs for old palette colours are freed and rebuilt fresh.

Source

pub fn dpi_scale(&self) -> f32

DPI scale factor applied to font sizes before rasterisation.

Source

pub fn set_dpi_scale(&mut self, s: f32)

Set the DPI scale factor applied to font sizes.

Source

pub fn global_alpha(&self) -> f32

Global alpha multiplier applied to every draw (0.0 transparent, 1.0 opaque).

Source

pub fn set_global_alpha(&mut self, a: f32)

Set the global alpha multiplier applied to every draw.

Source

pub fn font(&self) -> &Font

The canvas default font, used when no specific face is resolved.

Source

pub fn set_font_registry(&mut self, registry: Arc<FontRegistry>)

Install a theme font registry so Self::font_for can resolve family+weight+style triples declared by the theme’s fonts block.

Source

pub fn font_for(&self, family: &str, weight: u16, style: FontStyle) -> Arc<Font>

Resolve a specific font from the theme registry, falling back to the canvas’ default Self::font when no registry is installed or the triple cannot be satisfied.

Source

pub fn font_for_char(&self, ch: char) -> Arc<Font>

Pick the right font for ch. Tries the primary Self::font first; on a miss, delegates to the crate-private system-fonts fallback chain (lazy load of the relevant Noto pack). Falls back to the primary (which paints a .notdef box) when no installed fallback covers the codepoint.

Source

pub fn font_metrics(&self, ch: char, size: f32) -> Metrics

Glyph metrics for ch at size logical px, resolved through the fallback chain and pre-scaled by dpi_scale.

Source

pub fn font_line_metrics(&self, size: f32) -> Option<LineMetrics>

Horizontal line metrics of the default font at size px (None if the font lacks them). Not pre-scaled by dpi_scale.

Source

pub fn resize(&mut self, width: u32, height: u32)

Resize the FBO and viewport. The previous color attachment is freed and a fresh one of the new size is attached — frame-N pixels are dropped, so the caller should expect to do a full redraw immediately after a resize.

Source§

impl GlesCanvas

Source

pub fn blit(&mut self, src: &GlesCanvas, dest_x: i32, dest_y: i32)

Composite src’s FBO into this canvas at top-left ( dest_x, dest_y ), premultiplied over. src must share this canvas’s GL context (guaranteed for sub-canvases). Equivalent to Self::blit_fade_bottom with no fade.

Source

pub fn blit_fade_bottom( &mut self, src: &GlesCanvas, dest_x: i32, dest_y: i32, fade_bottom_px: f32, )

Blit src into this canvas at ( dest_x, dest_y ), optionally feathering the last fade_bottom_px source rows so the bottom edge dissolves into transparency instead of cutting off cleanly. Used by viewports whose bottom edge is the leading edge of a slide-down animation, where a hard cut against the underlying layer reads as a knife. With fade_bottom_px == 0.0 this matches Self::blit exactly.

Source

pub fn borrowed_texture(&self) -> BorrowedGlesTexture

Return a borrowed descriptor for the FBO color texture containing the latest rendered pixels.

y_inverted is true: the FBO uses GL’s native lower-left origin, so row 0 in texture memory is the bottom of the rendered image. Consumers that follow the same convention flip during sampling when this flag is set, producing a correctly- oriented result. The CPU-side counterpart Self::read_rgba_pixels does the same flip inline so the byte buffer is top-down.

Source

pub fn read_rgba_pixels(&self, out: &mut [u8]) -> Result<(), String>

Read the FBO color attachment into out as tightly packed RGBA8, top-left row first.

This is a compatibility escape hatch. It forces a GPU→CPU sync and should not be used in steady-state hot paths.

Source

pub fn present(&mut self)

Blit the FBO color attachment onto the default framebuffer (the EGL window). Caller is responsible for the eglSwapBuffers that publishes the result. After present, the FBO is rebound so the next frame’s draws keep accumulating into the shadow canvas.

The blit always covers the full surface — partial-redraw still saves work upstream (only changed widget pixels are repainted into the FBO), but the FBO→FB0 transfer itself is a single cheap fullscreen op.

Source§

impl GlesCanvas

Source

pub fn set_clip_rects(&mut self, rects: &[Rect])

Clip subsequent draws to rects via glScissor. The scissor is the bounding-box union of all rects clamped to the canvas — a coarse clip, unlike the software backend’s exact per-rect mask, so pixels between disjoint rects are not culled. An empty slice clears the clip; an empty union installs a zero-area scissor so subsequent draws become no-ops. Replaces any active path clip, flushing its layer first.

Source

pub fn clear_clip(&mut self)

Drop the active clip — disable the scissor test and flush any open path clip layer (compositing it back). Subsequent draws cover the whole canvas.

Source

pub fn set_clip_path(&mut self, cmds: &[PathCmd])

Clip subsequent draws to an arbitrary vector path, with an anti-aliased edge. Begins capturing draws into the offscreen clip layer; the path’s anti-aliased coverage is rasterised (tiny-skia) into clip_mask_tex and applied when the layer is composited back by flush_clip_layer (on the next clear_clip / set_clip_rects). GLES counterpart of the software backend’s set_clip_path.

Source

pub fn clip_bounds_snapshot(&self) -> Vec<Rect>

Snapshot of the active scissor as a Vec<Rect> (empty when no scissor is set).

Source

pub fn fill(&mut self, color: Color)

Clear to a solid color. Honours the active scissor — if a clip is set, only the clipped region is filled.

Source

pub fn clear(&mut self)

Clear to fully transparent. Honours the active scissor.

Source

pub fn clear_rects_transparent(&mut self, rects: &[Rect])

Zero the pixels inside each rect (alpha+RGB → 0).

Source§

impl GlesCanvas

Source

pub fn fill_path(&mut self, cmds: &[PathCmd], color: Color)

Fill an arbitrary vector path (commands in surface coordinates) with a solid colour. CPU fallback: rasterised with tiny-skia into a bbox-sized pixmap and blitted as a transient texture — there is no GPU path shader.

Source

pub fn stroke_path(&mut self, cmds: &[PathCmd], color: Color, width: f32)

Stroke an arbitrary vector path (commands in surface coordinates) with a centered stroke of width px. Same tiny-skia-into-texture CPU fallback as Self::fill_path.

Source

pub fn fill_rect(&mut self, rect: Rect, color: Color, corners: Corners)

Fill rect with a solid colour, with per-corner rounding from corners. Coverage (including the rounded corners) comes from an SDF in the rect shader; color.a is multiplied by global_alpha. Culled early when the rect falls entirely outside the active scissor.

Source

pub fn fill_linear_gradient_rect( &mut self, rect: Rect, g: &LinearGradient, corners: Corners, )

Fill a rectangle with a linear gradient.

Bakes a CPU-side LUT from g.stops and fetches (or creates) the corresponding cached GPU texture via ensure_lut_texture, then draws the quad with the gradient shader.

Source

pub fn fill_radial_gradient_rect( &mut self, rect: Rect, g: &RadialGradient, corners: Corners, )

Fill a rectangle with a radial gradient.

g.center is interpreted in box-relative fractions (as declared by the theme), g.radius is the fractional radial extent. Same cached LUT strategy as Self::fill_linear_gradient_rect.

Source

pub fn fill_shadow_outer( &mut self, target: Rect, shadow: &Shadow, corners: Corners, )

Paint an outer drop shadow behind a rounded rect.

Analytic Gaussian approximation over the shape SDF — see the note above SHADOW_OUTER_FRAG_SRC. The drawing quad is expanded on each side by max(blur, 0) + max(spread, 0) + 1 (the + 1 leaves a single antialias pixel of slack) and offset by shadow.offset so the fragment shader sees the full falloff region.

Only BlendMode::Normal is honoured today; other modes silently fall through to Normal because the analytic shader only outputs over.

Source

pub fn fill_shadow_inset( &mut self, target: Rect, shadow: &InsetShadow, corners: Corners, )

Paint an inner (inset) shadow inside a rounded rect.

Differences versus Self::fill_shadow_outer:

  • The drawing quad matches the target rect exactly — the inset is clipped to the outer SDF by the shader, so no external padding is needed and there is no spatial offset of the geometry.
  • The shader carries the per-shadow offset as a uniform rather than translating the quad, because the inset is biased inside the shape rather than cast outside it.
  • The pipeline blend state is switched for the duration of the draw to honour InsetShadow::blend and restored afterwards.

Blend modes: Normal stays on the pipeline default (ONE, ONE_MINUS_SRC_ALPHA). PlusLighter uses (ONE, ONE) — pure additive on premultiplied inputs, naturally clamped by the framebuffer to [0, 1], which is exactly the CSS definition. Multiply uses (DST_COLOR, ZERO) on RGB and (DST_ALPHA, ZERO) on alpha — a straight multiplicative blend. Screen uses (ONE_MINUS_DST_COLOR, ONE), the canonical a + b − a·b form. Overlay cannot be expressed with GL’s fixed-function blend state alone — it needs to read the destination pixel. This branch snapshots the current FBO into aux_a via glCopyTexSubImage2D, then draws through shadow_inset_overlay_program which samples that snapshot at gl_FragCoord.xy / canvas_size, computes the per-channel CSS Overlay formula in-shader, and emits premultiplied (overlay * mask, mask) — so the usual premul over blend composes the blended colour on top of the base. One FBO snapshot per Overlay shadow.

Source

pub fn stroke_rect( &mut self, rect: Rect, color: Color, width: f32, corners: Corners, )

Stroke a rectangle outline. The stroke is centered on the (rounded) boundary, matching tiny-skia’s stroke_path so software and GPU paths produce the same shape (e.g. a circular focus ring around an icon button stays circular).

The drawing quad is expanded by width / 2 so the outer half of the stroke — which lies outside the original rect — has fragments to cover; the SDF in the rect shader then clamps to the ring.

Source

pub fn draw_line( &mut self, x0: f32, y0: f32, x1: f32, y1: f32, color: Color, width: f32, )

Draw a line as a thin axis-aligned rect (diagonal lines fall back to stamping small squares).

Source§

impl GlesCanvas

Source

pub fn draw_text(&mut self, text: &str, x: f32, y: f32, size: f32, color: Color)

Draw a single shaped line of text with the canvas default font and the system fallback chain, baseline at ( x, y ) in surface px. size is in logical px and scaled by dpi_scale before rasterisation. Glyphs are shelf-packed into the GPU atlas and the whole line is flushed in one batched draw call.

Source

pub fn draw_text_with_font( &mut self, text: &str, x: f32, y: f32, size: f32, color: Color, font: &Arc<Font>, )

Like Self::draw_text but leads the resolver with font instead of the canvas default, falling back to the system chain for codepoints it does not cover.

Source

pub fn measure_text(&self, text: &str, size: f32) -> f32

Advance width of one shaped line of text in surface px, using the canvas default font and the system fallback chain. Shapes through the same path as Self::draw_text (so kerning and fallback advances match) without drawing.

Source

pub fn measure_text_with_font( &self, text: &str, size: f32, font: &Arc<Font>, ) -> f32

Like Self::measure_text but measures with font leading the resolver, so text laid out at one weight and drawn at another stays aligned.

Source§

impl GlesCanvas

Source

pub fn draw_image_data( &mut self, rgba_data: &[u8], img_w: u32, img_h: u32, dest: Rect, opacity: f32, )

Blit RGBA image data scaled to dest rect with opacity.

Defensive: rejects buffers whose declared img_w × img_h × 4 does not match rgba_data.len(). The mismatch path logs a one-line warning and returns without uploading or drawing — the same boundary that the internal upload_rgba_texture helper enforces, raised one level so the cache key is never seeded with a bogus mapping.

Source

pub fn draw_external_texture( &mut self, texture: Texture, dest: Rect, opacity: f32, )

Draw an externally-owned GL texture into dest.

The caller owns the texture and is responsible for keeping it valid for the duration of this call. No upload, no caching — used to composite content rendered by another GL producer (web engine, video decoder, …) into the LTK widget tree.

Trait Implementations§

Source§

impl Drop for GlesCanvas

Free this canvas’s owned GL resources: FBO, color attachment, aux FBOs if allocated, and any cached glyph / image textures. Shader programs and the quad VAO/VBO are shared with sub-canvases and intentionally NOT deleted here — they leak at process exit, which is fine for a process-wide GL context.

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

impl<T> Downcast for T
where T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,