blitz-pdf 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +266 -12
- package/THIRD_PARTY_NOTICES.md +4 -2
- package/dist/browser.d.ts +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/document-options.d.ts +36 -0
- package/dist/document-options.d.ts.map +1 -0
- package/dist/document-options.js +236 -0
- package/dist/document-options.js.map +1 -0
- package/dist/node.d.ts +1 -1
- package/dist/node.d.ts.map +1 -1
- package/dist/options.d.ts +35 -1
- package/dist/options.d.ts.map +1 -1
- package/dist/options.js +21 -14
- package/dist/options.js.map +1 -1
- package/dist/types.d.ts +71 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/validation.d.ts +2 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +7 -0
- package/dist/validation.js.map +1 -0
- package/examples/zugferd.mjs +41 -0
- package/licenses/RUST_DEPENDENCIES.txt +27 -0
- package/package.json +3 -2
- package/src/browser.ts +1 -1
- package/src/document-options.ts +218 -0
- package/src/node.ts +1 -1
- package/src/options.ts +18 -13
- package/src/types.ts +76 -1
- package/src/validation.ts +6 -0
- package/vendor/README.md +27 -2
- package/vendor/krilla/.cargo-ok +1 -0
- package/vendor/krilla/.cargo_vcs_info.json +6 -0
- package/vendor/krilla/Cargo.lock +1357 -0
- package/vendor/krilla/Cargo.toml +165 -0
- package/vendor/krilla/LICENSE_APACHE +202 -0
- package/vendor/krilla/LICENSE_MIT +21 -0
- package/vendor/krilla/README.md +156 -0
- package/vendor/krilla/examples/basic.rs +117 -0
- package/vendor/krilla/examples/empty_document.rs +25 -0
- package/vendor/krilla/examples/parley.rs +174 -0
- package/vendor/krilla/examples/simple_text.rs +118 -0
- package/vendor/krilla/examples/stream_builder.rs +93 -0
- package/vendor/krilla/icc/LICENSE +116 -0
- package/vendor/krilla/icc/README.md +1 -0
- package/vendor/krilla/icc/sGrey-v2-magic.icc +0 -0
- package/vendor/krilla/icc/sGrey-v4.icc +0 -0
- package/vendor/krilla/icc/sRGB-v2-magic.icc +0 -0
- package/vendor/krilla/icc/sRGB-v4.icc +0 -0
- package/vendor/krilla/src/chunk_container.rs +503 -0
- package/vendor/krilla/src/configure/PDF_A1.md +227 -0
- package/vendor/krilla/src/configure/PDF_A2.md +269 -0
- package/vendor/krilla/src/configure/PDF_A3.md +31 -0
- package/vendor/krilla/src/configure/PDF_A4.md +211 -0
- package/vendor/krilla/src/configure/PDF_UA1.md +202 -0
- package/vendor/krilla/src/configure/README.md +23 -0
- package/vendor/krilla/src/configure/mod.rs +197 -0
- package/vendor/krilla/src/configure/validate.rs +1244 -0
- package/vendor/krilla/src/configure/version.rs +134 -0
- package/vendor/krilla/src/content.rs +1352 -0
- package/vendor/krilla/src/data.rs +49 -0
- package/vendor/krilla/src/document.rs +156 -0
- package/vendor/krilla/src/error.rs +170 -0
- package/vendor/krilla/src/geom.rs +341 -0
- package/vendor/krilla/src/graphics/blend.rs +46 -0
- package/vendor/krilla/src/graphics/color.rs +552 -0
- package/vendor/krilla/src/graphics/graphic.rs +30 -0
- package/vendor/krilla/src/graphics/graphics_state.rs +251 -0
- package/vendor/krilla/src/graphics/icc.rs +218 -0
- package/vendor/krilla/src/graphics/image.rs +835 -0
- package/vendor/krilla/src/graphics/mask.rs +128 -0
- package/vendor/krilla/src/graphics/mod.rs +14 -0
- package/vendor/krilla/src/graphics/paint.rs +434 -0
- package/vendor/krilla/src/graphics/separation.rs +86 -0
- package/vendor/krilla/src/graphics/shading_function.rs +865 -0
- package/vendor/krilla/src/graphics/shading_pattern.rs +60 -0
- package/vendor/krilla/src/graphics/tiling_pattern.rs +119 -0
- package/vendor/krilla/src/graphics/xobject.rs +150 -0
- package/vendor/krilla/src/interactive/action.rs +68 -0
- package/vendor/krilla/src/interactive/annotation.rs +283 -0
- package/vendor/krilla/src/interactive/destination.rs +289 -0
- package/vendor/krilla/src/interactive/mod.rs +3 -0
- package/vendor/krilla/src/interchange/embed.rs +240 -0
- package/vendor/krilla/src/interchange/metadata.rs +564 -0
- package/vendor/krilla/src/interchange/mod.rs +4 -0
- package/vendor/krilla/src/interchange/outline.rs +263 -0
- package/vendor/krilla/src/interchange/tagging/fmt.rs +733 -0
- package/vendor/krilla/src/interchange/tagging/generate.toml +474 -0
- package/vendor/krilla/src/interchange/tagging/generated.rs +4754 -0
- package/vendor/krilla/src/interchange/tagging/mod.rs +1324 -0
- package/vendor/krilla/src/interchange/tagging/tag.rs +686 -0
- package/vendor/krilla/src/lib.rs +179 -0
- package/vendor/krilla/src/num.rs +26 -0
- package/vendor/krilla/src/page.rs +612 -0
- package/vendor/krilla/src/pdf.rs +313 -0
- package/vendor/krilla/src/resource.rs +436 -0
- package/vendor/krilla/src/serialize.rs +1101 -0
- package/vendor/krilla/src/stream.rs +368 -0
- package/vendor/krilla/src/surface.rs +664 -0
- package/vendor/krilla/src/text/cid.rs +488 -0
- package/vendor/krilla/src/text/font.rs +351 -0
- package/vendor/krilla/src/text/glyph/bitmap.rs +81 -0
- package/vendor/krilla/src/text/glyph/colr.rs +581 -0
- package/vendor/krilla/src/text/glyph/mod.rs +205 -0
- package/vendor/krilla/src/text/glyph/outline.rs +72 -0
- package/vendor/krilla/src/text/glyph/svg.rs +34 -0
- package/vendor/krilla/src/text/group.rs +463 -0
- package/vendor/krilla/src/text/mod.rs +232 -0
- package/vendor/krilla/src/text/shape.rs +102 -0
- package/vendor/krilla/src/text/type3.rs +514 -0
- package/vendor/krilla/src/util.rs +286 -0
- package/vendor/stylo/properties/longhands.toml +0 -1
- package/vendor/stylo/stylesheets/rule_parser.rs +1 -1
- package/wasm/blitz_pdf.js +10 -5
- package/wasm/blitz_pdf_bg.wasm +0 -0
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
use std::marker::PhantomData;
|
|
2
|
+
use std::num::{NonZeroU16, NonZeroU32};
|
|
3
|
+
|
|
4
|
+
use smallvec::SmallVec;
|
|
5
|
+
|
|
6
|
+
use crate::geom::Rect;
|
|
7
|
+
use crate::surface::Location;
|
|
8
|
+
|
|
9
|
+
include!("generated.rs");
|
|
10
|
+
|
|
11
|
+
impl TagKind {
|
|
12
|
+
/// Get the location.
|
|
13
|
+
pub fn location(&self) -> Option<Location> {
|
|
14
|
+
self.as_any().location
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// Set the location.
|
|
18
|
+
pub fn set_location(&mut self, location: Option<Location>) {
|
|
19
|
+
self.as_any_mut().location = location;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// Set the location.
|
|
23
|
+
pub fn with_location(mut self, location: Option<Location>) -> Self {
|
|
24
|
+
self.as_any_mut().location = location;
|
|
25
|
+
self
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/// A specific tag which allows accessing attributes specific to this [`TagKind`].
|
|
30
|
+
///
|
|
31
|
+
/// # Example
|
|
32
|
+
/// ```
|
|
33
|
+
/// use std::num::NonZeroU32;
|
|
34
|
+
/// use krilla::tagging::{TagGroup, TagTree, TableHeaderScope, Tag, TagId};
|
|
35
|
+
///
|
|
36
|
+
/// let tag = Tag::TH(TableHeaderScope::Row)
|
|
37
|
+
/// .with_id(Some(TagId::from(*b"this id")))
|
|
38
|
+
/// .with_col_span(Some(NonZeroU32::new(3).unwrap()))
|
|
39
|
+
/// .with_headers(Some([TagId::from(*b"parent id")]))
|
|
40
|
+
/// .with_width(Some(250.0))
|
|
41
|
+
/// .with_height(Some(100.0));
|
|
42
|
+
/// let group = TagGroup::new(tag);
|
|
43
|
+
///
|
|
44
|
+
/// let mut tree = TagTree::new();
|
|
45
|
+
/// tree.push(group);
|
|
46
|
+
/// ```
|
|
47
|
+
#[derive(Clone, Debug, PartialEq)]
|
|
48
|
+
pub struct Tag<T> {
|
|
49
|
+
inner: AnyTag,
|
|
50
|
+
/// Compile time marker for a type-safe API.
|
|
51
|
+
pub(crate) ty: PhantomData<T>,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
impl<T> Tag<T> {
|
|
55
|
+
/// This can't be public, otherwise tags could be constructed without
|
|
56
|
+
/// providing required attributes.
|
|
57
|
+
pub(crate) const fn new() -> Self {
|
|
58
|
+
Self {
|
|
59
|
+
inner: AnyTag::new(),
|
|
60
|
+
ty: PhantomData,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/// A raw tag, which allows reading all attributes.
|
|
65
|
+
pub fn as_any(&self) -> &AnyTag {
|
|
66
|
+
&self.inner
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// A raw tag, which allows reading all attributes and additionally writing
|
|
70
|
+
/// all global ones.
|
|
71
|
+
pub fn as_any_mut(&mut self) -> &mut AnyTag {
|
|
72
|
+
&mut self.inner
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// Get the location.
|
|
76
|
+
pub fn location(&self) -> Option<Location> {
|
|
77
|
+
self.as_any().location
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Set the location.
|
|
81
|
+
pub fn set_location(&mut self, location: Option<Location>) {
|
|
82
|
+
self.as_any_mut().location = location;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// Set the location.
|
|
86
|
+
pub fn with_location(mut self, location: Option<Location>) -> Self {
|
|
87
|
+
self.as_any_mut().location = location;
|
|
88
|
+
self
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// A raw tag, which allows reading all attributes and additionally writing all
|
|
93
|
+
/// global ones.
|
|
94
|
+
#[derive(Clone, Debug, PartialEq)]
|
|
95
|
+
pub struct AnyTag {
|
|
96
|
+
/// The location of the tag.
|
|
97
|
+
pub location: Option<Location>,
|
|
98
|
+
pub(crate) attrs: OrdinalSet<Attr>,
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
impl AnyTag {
|
|
102
|
+
pub(crate) const fn new() -> Self {
|
|
103
|
+
Self {
|
|
104
|
+
attrs: OrdinalSet::new(),
|
|
105
|
+
location: None,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/// An ordered set using ordinal numbers to sort and identify elements.
|
|
111
|
+
#[derive(Clone, Debug, PartialEq)]
|
|
112
|
+
pub(crate) struct OrdinalSet<A> {
|
|
113
|
+
items: SmallVec<[A; 1]>,
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
impl<A> OrdinalSet<A> {
|
|
117
|
+
pub(crate) const fn new() -> Self {
|
|
118
|
+
Self {
|
|
119
|
+
items: SmallVec::new_const(),
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
impl<A: Ordinal> OrdinalSet<A> {
|
|
125
|
+
pub(crate) fn iter(&self) -> impl Iterator<Item = &A> {
|
|
126
|
+
self.items.iter()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
pub(crate) fn set(&mut self, attr: A) {
|
|
130
|
+
for (i, item) in self.items.iter().enumerate() {
|
|
131
|
+
if item.ordinal() == attr.ordinal() {
|
|
132
|
+
self.items[i] = attr;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if item.ordinal() > attr.ordinal() {
|
|
136
|
+
self.items.insert(i, attr);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
self.items.push(attr);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
pub(crate) fn remove(&mut self, ordinal: usize) {
|
|
144
|
+
for (i, item) in self.items.iter().enumerate() {
|
|
145
|
+
if item.ordinal() == ordinal {
|
|
146
|
+
self.items.remove(i);
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if item.ordinal() > ordinal {
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
pub(crate) fn get(&self, ordinal: usize) -> Option<&A> {
|
|
156
|
+
for item in self.items.iter() {
|
|
157
|
+
if item.ordinal() == ordinal {
|
|
158
|
+
return Some(item);
|
|
159
|
+
}
|
|
160
|
+
if item.ordinal() > ordinal {
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
None
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
pub(crate) fn set_or_remove(&mut self, ordinal: usize, attr: Option<A>) {
|
|
168
|
+
match attr {
|
|
169
|
+
Some(attr) => self.set(attr),
|
|
170
|
+
None => self.remove(ordinal),
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/// Identifies elements using an ordinal number.
|
|
176
|
+
pub(crate) trait Ordinal {
|
|
177
|
+
fn ordinal(&self) -> usize;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/// An identifier of a [`Tag`].
|
|
181
|
+
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
|
182
|
+
pub struct TagId(pub(crate) SmallVec<[u8; 16]>);
|
|
183
|
+
|
|
184
|
+
impl<I: IntoIterator<Item = u8>> From<I> for TagId {
|
|
185
|
+
fn from(value: I) -> Self {
|
|
186
|
+
// Disambiguate ids provided by the user from ids automatically assigned
|
|
187
|
+
// to notes by prefixing them with a `U`.
|
|
188
|
+
let bytes = std::iter::once(b'U').chain(value).collect();
|
|
189
|
+
TagId(bytes)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
impl TagId {
|
|
194
|
+
/// Returns the identifier as a byte slice.
|
|
195
|
+
pub fn as_bytes(&self) -> &[u8] {
|
|
196
|
+
self.0.as_slice()
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/// The list numbering type.
|
|
201
|
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
202
|
+
pub enum ListNumbering {
|
|
203
|
+
/// No numbering.
|
|
204
|
+
None,
|
|
205
|
+
/// Solid circular bullets.
|
|
206
|
+
Disc,
|
|
207
|
+
/// Open circular bullets.
|
|
208
|
+
Circle,
|
|
209
|
+
/// Solid square bullets.
|
|
210
|
+
Square,
|
|
211
|
+
/// Decimal numbers.
|
|
212
|
+
Decimal,
|
|
213
|
+
/// Lowercase Roman numerals.
|
|
214
|
+
LowerRoman,
|
|
215
|
+
/// Uppercase Roman numerals.
|
|
216
|
+
UpperRoman,
|
|
217
|
+
/// Lowercase letters.
|
|
218
|
+
LowerAlpha,
|
|
219
|
+
/// Uppercase letters.
|
|
220
|
+
UpperAlpha,
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
impl ListNumbering {
|
|
224
|
+
pub(crate) fn to_pdf(self) -> pdf_writer::types::ListNumbering {
|
|
225
|
+
match self {
|
|
226
|
+
ListNumbering::None => pdf_writer::types::ListNumbering::None,
|
|
227
|
+
ListNumbering::Disc => pdf_writer::types::ListNumbering::Disc,
|
|
228
|
+
ListNumbering::Circle => pdf_writer::types::ListNumbering::Circle,
|
|
229
|
+
ListNumbering::Square => pdf_writer::types::ListNumbering::Square,
|
|
230
|
+
ListNumbering::Decimal => pdf_writer::types::ListNumbering::Decimal,
|
|
231
|
+
ListNumbering::LowerRoman => pdf_writer::types::ListNumbering::LowerRoman,
|
|
232
|
+
ListNumbering::UpperRoman => pdf_writer::types::ListNumbering::UpperRoman,
|
|
233
|
+
ListNumbering::LowerAlpha => pdf_writer::types::ListNumbering::LowerAlpha,
|
|
234
|
+
ListNumbering::UpperAlpha => pdf_writer::types::ListNumbering::UpperAlpha,
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/// The scope of a table header cell.
|
|
240
|
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
241
|
+
pub enum TableHeaderScope {
|
|
242
|
+
/// The header cell refers to the row.
|
|
243
|
+
Row,
|
|
244
|
+
/// The header cell refers to the column.
|
|
245
|
+
Column,
|
|
246
|
+
/// The header cell refers to both the row and the column.
|
|
247
|
+
Both,
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
impl TableHeaderScope {
|
|
251
|
+
pub(crate) fn to_pdf(self) -> pdf_writer::types::TableHeaderScope {
|
|
252
|
+
match self {
|
|
253
|
+
TableHeaderScope::Row => pdf_writer::types::TableHeaderScope::Row,
|
|
254
|
+
TableHeaderScope::Column => pdf_writer::types::TableHeaderScope::Column,
|
|
255
|
+
TableHeaderScope::Both => pdf_writer::types::TableHeaderScope::Both,
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/// The positioning of the element with respect to the enclosing reference area
|
|
261
|
+
/// and other content.
|
|
262
|
+
/// When applied to an ILSE, any value except Inline shall cause the element to
|
|
263
|
+
/// be treated as a BLSE instead.
|
|
264
|
+
///
|
|
265
|
+
/// Default value: [`Placement::Inline`].
|
|
266
|
+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
|
267
|
+
pub enum Placement {
|
|
268
|
+
/// Stacked in the block-progression direction within an enclosing reference
|
|
269
|
+
/// area or parent BLSE.
|
|
270
|
+
Block,
|
|
271
|
+
/// Packed in the inline-progression direction within an enclosing BLSE.
|
|
272
|
+
#[default]
|
|
273
|
+
Inline,
|
|
274
|
+
/// Placed so that the before edge of the element’s allocation rectangle.
|
|
275
|
+
/// (see “Content and Allocation Rectangles” in 14.8.5.4, “Layout Attributes”)
|
|
276
|
+
/// coincides with that of the nearest enclosing reference area. The element
|
|
277
|
+
/// may float, if necessary, to achieve the specified placement. The element
|
|
278
|
+
/// shall be treated as a block occupying the full extent of the enclosing
|
|
279
|
+
/// reference area in the inline direction. Other content shall be stacked
|
|
280
|
+
/// so as to begin at the after edge of the element’s allocation rectangle.
|
|
281
|
+
Before,
|
|
282
|
+
/// Placed so that the start edge of the element’s allocation rectangle
|
|
283
|
+
/// (see “Content and Allocation Rectangles” in 14.8.5.4, “Layout Attributes”)
|
|
284
|
+
/// coincides with that of the nearest enclosing reference area. The element
|
|
285
|
+
/// may float, if necessary, to achieve the specified placement. Other
|
|
286
|
+
/// content that would intrude into the element’s allocation rectangle
|
|
287
|
+
/// shall be laid out as a runaround.
|
|
288
|
+
Start,
|
|
289
|
+
/// Placed so that the end edge of the element’s allocation rectangle
|
|
290
|
+
/// (see “Content and Allocation Rectangles” in 14.8.5.4, “Layout Attributes”)
|
|
291
|
+
/// coincides with that of the nearest enclosing reference area. The element
|
|
292
|
+
/// may float, if necessary, to achieve the specified placement. Other
|
|
293
|
+
/// content that would intrude into the element’s allocation rectangle
|
|
294
|
+
/// shall be laid out as a runaround.
|
|
295
|
+
End,
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
impl Placement {
|
|
299
|
+
pub(crate) fn to_pdf(self) -> pdf_writer::types::Placement {
|
|
300
|
+
match self {
|
|
301
|
+
Placement::Block => pdf_writer::types::Placement::Block,
|
|
302
|
+
Placement::Inline => pdf_writer::types::Placement::Inline,
|
|
303
|
+
Placement::Before => pdf_writer::types::Placement::Before,
|
|
304
|
+
Placement::Start => pdf_writer::types::Placement::Start,
|
|
305
|
+
Placement::End => pdf_writer::types::Placement::End,
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/// The directions of layout progression for packing of ILSEs (inline progression)
|
|
311
|
+
/// and stacking of BLSEs (block progression).
|
|
312
|
+
/// The specified layout directions shall apply to the given structure element
|
|
313
|
+
/// and all of its descendants to any level of nesting.
|
|
314
|
+
///
|
|
315
|
+
/// Default value: [`WritingMode::LrTb`].
|
|
316
|
+
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
|
|
317
|
+
pub enum WritingMode {
|
|
318
|
+
/// Inline progression from left to right; block progression from top to
|
|
319
|
+
/// bottom. This is the typical writing mode for Western writing systems.
|
|
320
|
+
#[default]
|
|
321
|
+
LrTb,
|
|
322
|
+
/// Inline progression from right to left; block progression from top to
|
|
323
|
+
/// bottom. This is the typical writing mode for Arabic and Hebrew writing
|
|
324
|
+
/// systems.
|
|
325
|
+
RlTb,
|
|
326
|
+
/// Inline progression from top to bottom; block progression from right to
|
|
327
|
+
/// left. This is the typical writing mode for Chinese and Japanese writing
|
|
328
|
+
/// systems.
|
|
329
|
+
TbRl,
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
impl WritingMode {
|
|
333
|
+
pub(crate) fn to_pdf(self) -> pdf_writer::types::WritingMode {
|
|
334
|
+
match self {
|
|
335
|
+
WritingMode::LrTb => pdf_writer::types::WritingMode::LtrTtb,
|
|
336
|
+
WritingMode::RlTb => pdf_writer::types::WritingMode::RtlTtb,
|
|
337
|
+
WritingMode::TbRl => pdf_writer::types::WritingMode::TtbRtl,
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/// The bounding box of a tag that encloses its visible content.
|
|
343
|
+
/// If the content spans multiple pages, this should be omitted.
|
|
344
|
+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
345
|
+
pub struct BBox {
|
|
346
|
+
/// The page index of the bounding box.
|
|
347
|
+
pub page_idx: usize,
|
|
348
|
+
/// The rectangle that encloses the content.
|
|
349
|
+
pub rect: Rect,
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
impl BBox {
|
|
353
|
+
/// Create a new bounding box.
|
|
354
|
+
pub fn new(page_idx: usize, rect: Rect) -> Self {
|
|
355
|
+
Self { page_idx, rect }
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/// An RGB color within the tag tree. The color space of this color is not
|
|
360
|
+
/// specified. Each component is in the range [0.0, 1.0].
|
|
361
|
+
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
362
|
+
pub struct NaiveRgbColor {
|
|
363
|
+
/// The red component of the color.
|
|
364
|
+
pub red: u8,
|
|
365
|
+
/// The green component of the color.
|
|
366
|
+
pub green: u8,
|
|
367
|
+
/// The blue component of the color.
|
|
368
|
+
pub blue: u8,
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
impl NaiveRgbColor {
|
|
372
|
+
/// Create a new RGB color.
|
|
373
|
+
pub fn new(red: u8, green: u8, blue: u8) -> Self {
|
|
374
|
+
Self { red, green, blue }
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/// Create a new RGB color from normalized floating point values.
|
|
378
|
+
pub fn new_f32(red: f32, green: f32, blue: f32) -> Self {
|
|
379
|
+
if !(0.0..=1.0).contains(&red)
|
|
380
|
+
|| !(0.0..=1.0).contains(&green)
|
|
381
|
+
|| !(0.0..=1.0).contains(&blue)
|
|
382
|
+
{
|
|
383
|
+
panic!("RGB color components must be in the range [0.0, 1.0]");
|
|
384
|
+
}
|
|
385
|
+
Self {
|
|
386
|
+
red: (255.0 * red).round() as u8,
|
|
387
|
+
green: (255.0 * green).round() as u8,
|
|
388
|
+
blue: (255.0 * blue).round() as u8,
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/// Convert the color into an array of f32 components for PDF serialization.
|
|
393
|
+
pub fn into_f32_array(self) -> [f32; 3] {
|
|
394
|
+
let normalize = |n| n as f32 / 255.0;
|
|
395
|
+
[self.red, self.green, self.blue].map(normalize)
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
impl From<NaiveRgbColor> for crate::graphics::color::rgb::Color {
|
|
400
|
+
fn from(color: NaiveRgbColor) -> Self {
|
|
401
|
+
crate::graphics::color::rgb::Color::new(color.red, color.green, color.blue)
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
impl From<NaiveRgbColor> for [f32; 3] {
|
|
406
|
+
fn from(color: NaiveRgbColor) -> Self {
|
|
407
|
+
color.into_f32_array()
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/// The border style of an element.
|
|
412
|
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
413
|
+
pub enum BorderStyle {
|
|
414
|
+
/// No border.
|
|
415
|
+
None,
|
|
416
|
+
/// Hidden border.
|
|
417
|
+
Hidden,
|
|
418
|
+
/// Solid border.
|
|
419
|
+
Solid,
|
|
420
|
+
/// Dashed border.
|
|
421
|
+
Dashed,
|
|
422
|
+
/// Dotted border.
|
|
423
|
+
Dotted,
|
|
424
|
+
/// Double border.
|
|
425
|
+
Double,
|
|
426
|
+
/// Groove border.
|
|
427
|
+
Groove,
|
|
428
|
+
/// Ridge border.
|
|
429
|
+
Ridge,
|
|
430
|
+
/// Inset border.
|
|
431
|
+
Inset,
|
|
432
|
+
/// Outset border.
|
|
433
|
+
Outset,
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
impl BorderStyle {
|
|
437
|
+
pub(super) fn to_pdf(self) -> pdf_writer::types::LayoutBorderStyle {
|
|
438
|
+
match self {
|
|
439
|
+
BorderStyle::None => pdf_writer::types::LayoutBorderStyle::None,
|
|
440
|
+
BorderStyle::Hidden => pdf_writer::types::LayoutBorderStyle::Hidden,
|
|
441
|
+
BorderStyle::Solid => pdf_writer::types::LayoutBorderStyle::Solid,
|
|
442
|
+
BorderStyle::Dashed => pdf_writer::types::LayoutBorderStyle::Dashed,
|
|
443
|
+
BorderStyle::Dotted => pdf_writer::types::LayoutBorderStyle::Dotted,
|
|
444
|
+
BorderStyle::Double => pdf_writer::types::LayoutBorderStyle::Double,
|
|
445
|
+
BorderStyle::Groove => pdf_writer::types::LayoutBorderStyle::Groove,
|
|
446
|
+
BorderStyle::Ridge => pdf_writer::types::LayoutBorderStyle::Ridge,
|
|
447
|
+
BorderStyle::Inset => pdf_writer::types::LayoutBorderStyle::Inset,
|
|
448
|
+
BorderStyle::Outset => pdf_writer::types::LayoutBorderStyle::Outset,
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
/// The text alignment.
|
|
454
|
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
455
|
+
pub enum TextAlign {
|
|
456
|
+
/// At the start of the inline advance direction.
|
|
457
|
+
Start,
|
|
458
|
+
/// Centered.
|
|
459
|
+
Center,
|
|
460
|
+
/// At the end of the inline advance direction.
|
|
461
|
+
End,
|
|
462
|
+
/// Justified.
|
|
463
|
+
Justify,
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
impl TextAlign {
|
|
467
|
+
pub(super) fn to_pdf(self) -> pdf_writer::types::TextAlign {
|
|
468
|
+
match self {
|
|
469
|
+
TextAlign::Start => pdf_writer::types::TextAlign::Start,
|
|
470
|
+
TextAlign::Center => pdf_writer::types::TextAlign::Center,
|
|
471
|
+
TextAlign::End => pdf_writer::types::TextAlign::End,
|
|
472
|
+
TextAlign::Justify => pdf_writer::types::TextAlign::Justify,
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/// The block alignment.
|
|
478
|
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
479
|
+
pub enum BlockAlign {
|
|
480
|
+
/// At the start of the block advance direction.
|
|
481
|
+
Begin,
|
|
482
|
+
/// Centered.
|
|
483
|
+
Middle,
|
|
484
|
+
/// At the end of the block advance direction.
|
|
485
|
+
After,
|
|
486
|
+
/// Justified.
|
|
487
|
+
Justify,
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
impl BlockAlign {
|
|
491
|
+
pub(super) fn to_pdf(self) -> pdf_writer::types::BlockAlign {
|
|
492
|
+
match self {
|
|
493
|
+
BlockAlign::Begin => pdf_writer::types::BlockAlign::Before,
|
|
494
|
+
BlockAlign::Middle => pdf_writer::types::BlockAlign::Middle,
|
|
495
|
+
BlockAlign::After => pdf_writer::types::BlockAlign::After,
|
|
496
|
+
BlockAlign::Justify => pdf_writer::types::BlockAlign::Justify,
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/// The inline alignment.
|
|
502
|
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
503
|
+
pub enum InlineAlign {
|
|
504
|
+
/// At the start of the inline advance direction.
|
|
505
|
+
Start,
|
|
506
|
+
/// Centered.
|
|
507
|
+
Center,
|
|
508
|
+
/// At the end of the inline advance direction.
|
|
509
|
+
End,
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
impl InlineAlign {
|
|
513
|
+
pub(super) fn to_pdf(self) -> pdf_writer::types::InlineAlign {
|
|
514
|
+
match self {
|
|
515
|
+
InlineAlign::Start => pdf_writer::types::InlineAlign::Start,
|
|
516
|
+
InlineAlign::Center => pdf_writer::types::InlineAlign::Center,
|
|
517
|
+
InlineAlign::End => pdf_writer::types::InlineAlign::End,
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/// The height of a line.
|
|
523
|
+
#[derive(Debug, Copy, Clone, PartialEq)]
|
|
524
|
+
pub enum LineHeight {
|
|
525
|
+
/// Adjust the line height automatically, taking `/BaselineShift` into
|
|
526
|
+
/// account.
|
|
527
|
+
Normal,
|
|
528
|
+
/// Adjust the line height automatically.
|
|
529
|
+
Auto,
|
|
530
|
+
/// Set a fixed line height.
|
|
531
|
+
Custom(f32),
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
impl LineHeight {
|
|
535
|
+
pub(super) fn to_pdf(self) -> pdf_writer::types::LineHeight {
|
|
536
|
+
match self {
|
|
537
|
+
LineHeight::Auto => pdf_writer::types::LineHeight::Auto,
|
|
538
|
+
LineHeight::Normal => pdf_writer::types::LineHeight::Normal,
|
|
539
|
+
LineHeight::Custom(height) => pdf_writer::types::LineHeight::Custom(height),
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/// The text decoration type (over- and underlines).
|
|
545
|
+
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
|
546
|
+
pub enum TextDecorationType {
|
|
547
|
+
/// No decoration.
|
|
548
|
+
None,
|
|
549
|
+
/// Underlined.
|
|
550
|
+
Underline,
|
|
551
|
+
/// Line over the text.
|
|
552
|
+
Overline,
|
|
553
|
+
/// Strike the text.
|
|
554
|
+
LineThrough,
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
impl TextDecorationType {
|
|
558
|
+
pub(super) fn to_pdf(self) -> pdf_writer::types::TextDecorationType {
|
|
559
|
+
match self {
|
|
560
|
+
Self::None => pdf_writer::types::TextDecorationType::None,
|
|
561
|
+
Self::Underline => pdf_writer::types::TextDecorationType::Underline,
|
|
562
|
+
Self::Overline => pdf_writer::types::TextDecorationType::Overline,
|
|
563
|
+
Self::LineThrough => pdf_writer::types::TextDecorationType::LineThrough,
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/// The rotation of glyphs in vertical writing modes.
|
|
569
|
+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
570
|
+
pub enum GlyphOrientationVertical {
|
|
571
|
+
/// Determine the rotation based on whether the text is full-width.
|
|
572
|
+
Auto,
|
|
573
|
+
/// No rotation.
|
|
574
|
+
None,
|
|
575
|
+
/// Rotate 90 degrees clockwise.
|
|
576
|
+
Clockwise90,
|
|
577
|
+
/// Rotate 90 degrees counter-clockwise.
|
|
578
|
+
CounterClockwise90,
|
|
579
|
+
/// Rotate 180 degrees clockwise.
|
|
580
|
+
Clockwise180,
|
|
581
|
+
/// Rotate 180 degrees counter-clockwise.
|
|
582
|
+
CounterClockwise180,
|
|
583
|
+
/// Rotate 270 degrees clockwise.
|
|
584
|
+
Clockwise270,
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
impl GlyphOrientationVertical {
|
|
588
|
+
/// Convert the rotation to a number. If the rotation is `Auto`, returns
|
|
589
|
+
/// `None`.
|
|
590
|
+
pub(super) fn to_pdf(self) -> pdf_writer::types::GlyphOrientationVertical {
|
|
591
|
+
let angle = match self {
|
|
592
|
+
GlyphOrientationVertical::Auto => {
|
|
593
|
+
return pdf_writer::types::GlyphOrientationVertical::Auto
|
|
594
|
+
}
|
|
595
|
+
GlyphOrientationVertical::None => 0,
|
|
596
|
+
GlyphOrientationVertical::Clockwise90 => 90,
|
|
597
|
+
GlyphOrientationVertical::CounterClockwise90 => -90,
|
|
598
|
+
GlyphOrientationVertical::Clockwise180 => 180,
|
|
599
|
+
GlyphOrientationVertical::CounterClockwise180 => -180,
|
|
600
|
+
GlyphOrientationVertical::Clockwise270 => 270,
|
|
601
|
+
};
|
|
602
|
+
pdf_writer::types::GlyphOrientationVertical::Angle(angle)
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/// An attribute value that can apply to all sides of the element, or have a specific value for each side.
|
|
607
|
+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
608
|
+
pub struct Sides<T> {
|
|
609
|
+
/// The start of the element on the block axis.
|
|
610
|
+
pub before: T,
|
|
611
|
+
/// The end of the element on the block axis.
|
|
612
|
+
pub after: T,
|
|
613
|
+
/// The start of the element on the inline axis.
|
|
614
|
+
pub start: T,
|
|
615
|
+
/// The end of the element on the inline axis.
|
|
616
|
+
pub end: T,
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
impl<T> Sides<T> {
|
|
620
|
+
/// Construct a new `Sides` value with specific values for each side.
|
|
621
|
+
pub fn new(before: T, after: T, start: T, end: T) -> Self {
|
|
622
|
+
Self {
|
|
623
|
+
before,
|
|
624
|
+
after,
|
|
625
|
+
start,
|
|
626
|
+
end,
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
/// Construct a new `Sides` value with the same value for all sides.
|
|
631
|
+
pub fn uniform(value: T) -> Self
|
|
632
|
+
where
|
|
633
|
+
T: Copy,
|
|
634
|
+
{
|
|
635
|
+
Sides {
|
|
636
|
+
before: value,
|
|
637
|
+
after: value,
|
|
638
|
+
start: value,
|
|
639
|
+
end: value,
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
pub(crate) fn is_uniform(&self) -> bool
|
|
644
|
+
where
|
|
645
|
+
T: PartialEq,
|
|
646
|
+
{
|
|
647
|
+
self.before == self.after && self.before == self.start && self.before == self.end
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/// Returns an array for all sides.
|
|
651
|
+
pub(super) fn into_array(self) -> [T; 4] {
|
|
652
|
+
[self.before, self.after, self.start, self.end]
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/// Convert into [`pdf_writer::types::Sides`].
|
|
656
|
+
pub(super) fn into_pdf(self) -> pdf_writer::types::Sides<T> {
|
|
657
|
+
pdf_writer::types::Sides::from_array(self.into_array())
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/// Convert into [`pdf_writer::types::Sides`] by each side value.
|
|
661
|
+
pub(super) fn map_pdf<P>(self, to_pdf: impl Fn(T) -> P) -> pdf_writer::types::Sides<P> {
|
|
662
|
+
pdf_writer::types::Sides::from_array(self.into_array().map(to_pdf))
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/// Widths related to columns, either for all columns or
|
|
667
|
+
/// with specific values for each.
|
|
668
|
+
#[derive(Debug, Clone, PartialEq)]
|
|
669
|
+
pub enum ColumnDimensions {
|
|
670
|
+
/// The same value applies to all columns.
|
|
671
|
+
All(f32),
|
|
672
|
+
/// The value varies for each column or column gap.
|
|
673
|
+
Specific(Vec<f32>),
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
impl ColumnDimensions {
|
|
677
|
+
/// Construct a new `ColumnDimensions` with the same value for all columns.
|
|
678
|
+
pub fn all(value: f32) -> Self {
|
|
679
|
+
ColumnDimensions::All(value)
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/// Construct a new `ColumnDimensions` with specific values for each column.
|
|
683
|
+
pub fn specific(values: Vec<f32>) -> Self {
|
|
684
|
+
ColumnDimensions::Specific(values)
|
|
685
|
+
}
|
|
686
|
+
}
|