Skip to main content

rpdfium_render/
renderdevicedriver_iface.rs

1// Derived from PDFium's core/fxge/cfx_renderdevice.h
2// Original: Copyright 2014 The PDFium Authors
3// Licensed under BSD-3-Clause / Apache-2.0
4// See pdfium-upstream/LICENSE for the original license.
5
6//! Render backend trait defining the interface for 2D rendering engines.
7
8use rpdfium_core::Matrix;
9use rpdfium_graphics::{Bitmap, BlendMode, ClipPath, FillRule, PathOp};
10
11use crate::color_convert::RgbaColor;
12use crate::image::DecodedImage;
13use crate::stroke::StrokeStyle;
14
15/// Trait for a 2D rendering backend.
16///
17/// Implementations provide the actual drawing operations (fill, stroke, clip,
18/// compositing) using a concrete rendering library (e.g., tiny-skia).
19pub trait RenderBackend: Send {
20    /// The surface type used by this backend.
21    type Surface;
22
23    /// Create a new rendering surface with the given dimensions and background.
24    fn create_surface(&self, width: u32, height: u32, bg: &RgbaColor) -> Self::Surface;
25
26    /// Fill a path with the given color and transform.
27    fn fill_path(
28        &mut self,
29        surface: &mut Self::Surface,
30        ops: &[PathOp],
31        fill_rule: FillRule,
32        color: &RgbaColor,
33        transform: &Matrix,
34    );
35
36    /// Fill a path with anti-aliasing forced off.
37    ///
38    /// Used by shading subdivision where upstream PDFium uses `full_cover = true`
39    /// to avoid visible seams between adjacent sub-patches.
40    fn fill_path_no_aa(
41        &mut self,
42        surface: &mut Self::Surface,
43        ops: &[PathOp],
44        fill_rule: FillRule,
45        color: &RgbaColor,
46        transform: &Matrix,
47    ) {
48        // Default: fall back to normal (AA-enabled) fill.
49        self.fill_path(surface, ops, fill_rule, color, transform);
50    }
51
52    /// Stroke a path with the given style, color, and transform.
53    fn stroke_path(
54        &mut self,
55        surface: &mut Self::Surface,
56        ops: &[PathOp],
57        style: &StrokeStyle,
58        color: &RgbaColor,
59        transform: &Matrix,
60    );
61
62    /// Draw a decoded image with the given transform.
63    ///
64    /// When `interpolate` is true, the backend should use bilinear (or higher)
65    /// filtering instead of nearest-neighbor.  This matches PDFium's auto-bilinear
66    /// heuristic for upscaled images (see `CStretchEngine::UseInterpolateBilinear`).
67    fn draw_image(
68        &mut self,
69        surface: &mut Self::Surface,
70        image: &DecodedImage,
71        transform: &Matrix,
72        interpolate: bool,
73    );
74
75    /// Push a clipping region onto the clip stack.
76    fn push_clip(&mut self, surface: &mut Self::Surface, clip: &ClipPath, transform: &Matrix);
77
78    /// Pop the most recent clipping region.
79    fn pop_clip(&mut self, surface: &mut Self::Surface);
80
81    /// Begin a transparency group with the given blend mode, opacity, and
82    /// transparency group attributes.
83    fn push_group(
84        &mut self,
85        surface: &mut Self::Surface,
86        blend_mode: BlendMode,
87        opacity: f32,
88        isolated: bool,
89        knockout: bool,
90    );
91
92    /// End the current transparency group, compositing it onto the surface below.
93    fn pop_group(&mut self, surface: &mut Self::Surface);
94
95    /// Set a soft mask on the topmost group entry.
96    ///
97    /// The mask is provided as a single-channel alpha buffer (one byte per pixel,
98    /// row-major, same dimensions as the surface).  Implementations store it so
99    /// that `pop_group` can apply the mask during compositing.
100    fn set_group_mask(&mut self, _alpha_data: Vec<u8>, _width: u32, _height: u32) {
101        // Default: ignore mask (backends that don't support soft masks).
102    }
103
104    /// Return the dimensions `(width, height)` of the given surface.
105    fn surface_dimensions(&self, surface: &Self::Surface) -> (u32, u32);
106
107    /// Draw the content of `src` over `dst` using normal (SourceOver) blending.
108    ///
109    /// This is used to composite rendered content (on a transparent backdrop)
110    /// onto a background-color surface.
111    fn composite_over(&mut self, dst: &mut Self::Surface, src: &Self::Surface);
112
113    /// Draw a pre-rasterized alpha bitmap at the given position with the given color.
114    ///
115    /// The alpha data is a row-major single-channel bitmap. Each pixel in the output
116    /// should be colored with `color` modulated by the alpha value.
117    #[allow(clippy::too_many_arguments)]
118    fn draw_alpha_bitmap(
119        &mut self,
120        _surface: &mut Self::Surface,
121        _alpha: &[u8],
122        _width: u32,
123        _height: u32,
124        _bearing_x: i32,
125        _bearing_y: i32,
126        _color: &RgbaColor,
127        _transform: &Matrix,
128    ) {
129        // Default: no-op (backends that don't support alpha bitmaps fall back to outline rendering)
130    }
131
132    /// Set whether anti-aliasing is enabled for subsequent fill/stroke operations.
133    ///
134    /// Backends may ignore this hint. The default implementation is a no-op.
135    fn set_antialiasing(&mut self, _enabled: bool) {}
136
137    /// Return the raw pixel data of the surface as premultiplied RGBA bytes.
138    fn surface_pixels(&self, surface: &Self::Surface) -> Vec<u8>;
139
140    /// Finish rendering and return the final bitmap.
141    fn finish(self, surface: Self::Surface) -> Bitmap;
142}