1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
pub use ;
pub use ;
use Diagnostics;
use Page;
use ;
/// `opts` with glyph outlines forced on.
///
/// **The one option this crate overrides, and it is not a preference.** With
/// `subpixel_text_positioning` off — the default, because it is what
/// reproduces the oracle — the engine draws every run below fifty device
/// units per em by rasterizing a *glyph bitmap* and blitting it at a snapped
/// origin. At one pixel per PDF point that is nearly all body text, so an
/// export that honoured the default would be some thousands of small embedded
/// PNGs with no vector text in it at all: on `text_foxittext` the difference
/// is 2891 rasterized regions against none.
///
/// Turning it on is what `RenderDevice`'s own documentation means by "glyphs
/// reach the device as outlines above the hinting threshold" — it removes the
/// threshold. The cost is that a glyph lands where the PDF puts it rather
/// than where a golden expects it, which is the trade this option exists to
/// offer and the right side of it for a vector format.
///
/// Every other field of `opts` is the caller's and is passed through.
/// One page converted: the document and what could not be said in vectors.
///
/// A record of two facts rather than a handle with methods — the conversion
/// is finished by the time this exists, and both fields are the caller's to
/// take.
/// Convert one page to SVG, rasterizing with `backend` what SVG cannot say.
///
/// The document's `viewBox` is the device box the same page would render into
/// under `opts`, so the SVG and a raster render of the same page are in the
/// same coordinates and can be compared pixel for pixel.
///
/// # Errors
///
/// The same as [`pdfrum_render::render_page`]: `Error::TargetEmpty` when the
/// page's box under `opts.transform` is not at least one pixel on both axes,
/// and `Error::TargetTooLarge` when either axis is too big. Damage inside the
/// page is reported through `diags` and never becomes an error.
///
/// ```
/// use pdfrum_common::Diagnostics;
/// use pdfrum_page::Page;
/// use pdfrum_raster_tinyskia::TinySkiaBackend;
/// use pdfrum_render::RenderOptions;
/// use pdfrum_svg::page_to_svg;
///
/// # fn main() -> Result<(), pdfrum_render::Error> {
/// let converted = page_to_svg(
/// &Page::empty(),
/// &RenderOptions::default(),
/// &TinySkiaBackend::new(),
/// &mut Diagnostics::default(),
/// )?;
/// assert!(converted.svg.starts_with("<svg "));
/// # Ok(())
/// # }
/// ```
/// Convert one page to SVG, reusing caller-owned caches and honouring
/// optional content.
///
/// The general entry point: [`page_to_svg`] is this with a default
/// [`RenderSession`], and is the right call when neither of the session's
/// parts applies.
///
/// # Errors
///
/// As [`page_to_svg`].
///
/// ```
/// use pdfrum_common::Diagnostics;
/// use pdfrum_page::Page;
/// use pdfrum_raster_tinyskia::TinySkiaBackend;
/// use pdfrum_render::{RenderOptions, RenderSession};
/// use pdfrum_svg::page_to_svg_with;
///
/// # fn main() -> Result<(), pdfrum_render::Error> {
/// let converted = page_to_svg_with(
/// &Page::empty(),
/// &RenderOptions::default(),
/// &TinySkiaBackend::new(),
/// RenderSession::default(),
/// &mut Diagnostics::default(),
/// )?;
/// assert!(converted.report.is_empty());
/// # Ok(())
/// # }
/// ```