Skip to main content

RenderDevice

Trait RenderDevice 

Source
pub trait RenderDevice {
    // Required methods
    fn fill_path(
        &mut self,
        path: &BezPath,
        t: Affine,
        brush: &Brush<'_>,
        rule: FillRule,
        aa: AntiAlias,
    );
    fn stroke_path(
        &mut self,
        path: &BezPath,
        t: Affine,
        brush: &Brush<'_>,
        stroke: &Stroke,
        aa: AntiAlias,
    );
    fn draw_image(
        &mut self,
        img: &RasterImage,
        t: Affine,
        quality: ImageQuality,
        alpha: f32,
    );
    fn push_clip(&mut self, path: &BezPath, rule: FillRule);
    fn push_clip_rect(&mut self, rect: Rect);
    fn push_layer(
        &mut self,
        blend: BlendMode,
        alpha: f32,
        mask: Option<&AlphaMask>,
    );
    fn pop(&mut self);

    // Provided method
    fn draw_glyph_lcd(
        &mut self,
        glyph: &SubpixelBitmap,
        origin: (f64, f64),
        colour: Color,
    ) { ... }
}
Expand description

The device a page is drawn into: six primitives plus a hard-edged rect clip, all object-safe.

The engine holds one of these per render target — the page, each transparency group, each soft mask, each pattern cell — and never learns which rasterizer is behind it.

Required Methods§

Source

fn fill_path( &mut self, path: &BezPath, t: Affine, brush: &Brush<'_>, rule: FillRule, aa: AntiAlias, )

Fill path (in user space) transformed by t.

Source

fn stroke_path( &mut self, path: &BezPath, t: Affine, brush: &Brush<'_>, stroke: &Stroke, aa: AntiAlias, )

Stroke path (in user space) transformed by t.

The engine has already resolved the stroke’s device width — including the one-device-pixel minimum — and normalised its dash array to an even-length, all-positive list, so stroke is always directly usable.

Source

fn draw_image( &mut self, img: &RasterImage, t: Affine, quality: ImageQuality, alpha: f32, )

Draw img with its own pixel grid mapped through t, at a constant alpha.

t maps image pixel (0, 0)’s corner to its device position, so an identity transform is a texel-for-pixel blit at the origin and a translation moves it whole pixels — not a unit-square mapping. Reading t the other way collapses a whole-page image onto a single pixel, which is silent and total.

An image being reduced has already been box-filtered down to roughly its device size by crate::stretch::prescale, so t scales it by less than a pixel in each axis and the two-tap kernel below is running near 1:1. An image being enlarged arrives at its own resolution, which is where the two-tap kernel is the right one and quality chooses it.

Source

fn push_clip(&mut self, path: &BezPath, rule: FillRule)

Intersect the clip with path (already in device space).

Source

fn push_clip_rect(&mut self, rect: Rect)

Intersect the clip with an axis-aligned rectangle, hard-edged.

PDFium’s SetClip_PathFill takes a rect fast path that snaps to the outer integer rect and applies it with no antialiasing at all; re W n is the commonest clip in the corpus, so routing it through RenderDevice::push_clip would add a soft pixel along every clipped edge on a large fraction of the corpus.

Source

fn push_layer(&mut self, blend: BlendMode, alpha: f32, mask: Option<&AlphaMask>)

Begin a layer that will be composited back with blend, scaled by alpha and masked by mask.

mask, when present, is device-sized and device-aligned. That is an invariant, not a convention: a mismatched mask is silently ignored by vello_cpu and merely warned about by tiny-skia, so violating it fails open, producing unmasked output. Backends assert it.

Source

fn pop(&mut self)

End the innermost clip or layer.

Provided Methods§

Source

fn draw_glyph_lcd( &mut self, glyph: &SubpixelBitmap, origin: (f64, f64), colour: Color, )

Blit one glyph whose coverage is three values per pixel, one per LCD stripe, each merged into its own destination channel.

The oracle’s ClearType text (DrawNormalTextHelper’s MergeGammaAdjustRgb arm): for each pixel and each channel c, dest_c = (dest_c·(255 − a_c) + colour_c·a_c) / 255 where a_c = coverage_c · colour_alpha / 255, and the destination is left opaque. Three independent alphas is exactly what RenderDevice::draw_image cannot express — one RGBA pixel carries one — which is why this is its own primitive rather than a flag on that one.

origin is the device position of the bitmap’s top-left corner, in whole pixels: both terms of it are integers by construction, so there is nothing to resample and a backend blits texel for pixel.

Defaulted to grayscale. The default averages each pixel’s three coverages and draws the result through RenderDevice::draw_image, so a backend that cannot address channels separately still renders the text — in grey, without the colour fringes, which is what every other run of text on the page looks like anyway. That is a visible difference from the oracle on live-edit text and nothing worse: no glyph goes missing and no geometry moves. A backend that owns its pixels should override it.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§