pdf_interpret/device.rs
1use crate::font::Glyph;
2use crate::soft_mask::SoftMask;
3use crate::{BlendMode, ClipPath, Image};
4use crate::{GlyphDrawMode, Paint, PathDrawMode};
5use kurbo::{Affine, BezPath, Rect, Shape};
6
7/// A trait for a device that can be used to process PDF drawing instructions.
8pub trait Device<'a> {
9 /// Set the properties for future stroking operations.
10 /// Set a soft mask to be used for future drawing instructions.
11 fn set_soft_mask(&mut self, mask: Option<SoftMask<'a>>);
12 /// Set the blend mode that should be used for rendering operations.
13 fn set_blend_mode(&mut self, blend_mode: BlendMode);
14 /// Draw a path.
15 fn draw_path(
16 &mut self,
17 path: &BezPath,
18 transform: Affine,
19 paint: &Paint<'a>,
20 draw_mode: &PathDrawMode,
21 );
22 /// Push a new clip path to the clip stack.
23 fn push_clip_path(&mut self, clip_path: &ClipPath);
24 /// Push a new transparency group to the blend stack.
25 fn push_transparency_group(
26 &mut self,
27 opacity: f32,
28 mask: Option<SoftMask<'a>>,
29 blend_mode: BlendMode,
30 );
31 /// Draw a glyph.
32 fn draw_glyph(
33 &mut self,
34 glyph: &Glyph<'a>,
35 transform: Affine,
36 glyph_transform: Affine,
37 paint: &Paint<'a>,
38 // TODO: Move this into outline glyph.
39 draw_mode: &GlyphDrawMode,
40 );
41 /// Draw an image.
42 fn draw_image(&mut self, image: Image<'a, '_>, transform: Affine);
43 /// Pop the last clip path from the clip stack.
44 fn pop_clip_path(&mut self);
45 /// Pop the last transparency group from the blend stack.
46 fn pop_transparency_group(&mut self);
47 /// Draw a rectangle directly, without going through the general path pipeline.
48 fn draw_rect(
49 &mut self,
50 rect: &Rect,
51 transform: Affine,
52 paint: &Paint<'a>,
53 draw_mode: &PathDrawMode,
54 ) {
55 self.draw_path(&rect.to_path(0.1), transform, paint, draw_mode);
56 }
57 /// Called at the beginning of a marked content sequence (BMC/BDC).
58 ///
59 /// The tag is the marked content tag (e.g. b"P", b"Span"). The mcid is
60 /// the marked content identifier from the properties dict, if present.
61 /// The actual text is the decoded `/ActualText` replacement from the
62 /// properties dict, if present.
63 fn begin_marked_content(
64 &mut self,
65 _tag: &[u8],
66 _mcid: Option<i32>,
67 _actual_text: Option<&str>,
68 ) {
69 }
70 /// Called at the end of a marked content sequence (EMC).
71 fn end_marked_content(&mut self) {}
72 /// Called around the appearance stream of one annotation.
73 ///
74 /// `rect` is the annotation's rectangle, already in the device's own
75 /// coordinate system, like [`Self::draw_placed_text`]. A text device
76 /// reads a glyphless replacement inside as the value the widget shows,
77 /// which is the only place that value is painted. The default
78 /// implementation ignores the bracket.
79 fn begin_annotation_appearance(&mut self, _rect: Rect) {}
80 /// Called after the appearance stream of one annotation.
81 fn end_annotation_appearance(&mut self) {}
82 /// Text the page carries at a known place with no glyph drawn for it.
83 ///
84 /// `rect` is where that text sits, already in the device's own coordinate
85 /// system. The one producer today is a form field whose widget has no
86 /// appearance stream to draw: the value is in `/V` and nothing paints it,
87 /// so a device that reads glyphs would never see it (#549). A rendering
88 /// device has nothing to draw either -- synthesising the missing
89 /// appearance is a different job -- and the default implementation
90 /// ignores it.
91 fn draw_placed_text(&mut self, _text: &str, _rect: Rect) {}
92 /// Called when a TJ-array numeric adjustment is encountered between
93 /// substrings. Positive values shift text backward, negative values shift
94 /// it forward (1/1000 em units, per PDF ยง9.4.3). Text extractors use this
95 /// as a high-confidence word-boundary signal.
96 // ANN[r17/TEX1] Raw TJ offset surfaced so TextExtractionDevice can use it
97 // as the highest-confidence signal in the multi-signal space-detection
98 // consensus. Default is no-op to stay transparent to rendering devices.
99 fn text_adjustment(&mut self, _amount: f32) {}
100}
101
102/// A device that discards all drawing operations.
103pub struct DummyDevice;
104
105impl Device<'_> for DummyDevice {
106 fn set_soft_mask(&mut self, _: Option<SoftMask<'_>>) {}
107 fn set_blend_mode(&mut self, _: BlendMode) {}
108 fn draw_path(&mut self, _: &BezPath, _: Affine, _: &Paint<'_>, _: &PathDrawMode) {}
109 fn push_clip_path(&mut self, _: &ClipPath) {}
110 fn push_transparency_group(&mut self, _: f32, _: Option<SoftMask<'_>>, _: BlendMode) {}
111 fn draw_glyph(
112 &mut self,
113 _: &Glyph<'_>,
114 _: Affine,
115 _: Affine,
116 _: &Paint<'_>,
117 _: &GlyphDrawMode,
118 ) {
119 }
120 fn draw_image(&mut self, _: Image<'_, '_>, _: Affine) {}
121 fn pop_clip_path(&mut self) {}
122 fn pop_transparency_group(&mut self) {}
123}