blitz-pdf 0.1.0 → 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 +300 -10
- 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,263 @@
|
|
|
1
|
+
//! Building outlines for the navigation of the document.
|
|
2
|
+
//!
|
|
3
|
+
//! An outline is a tree-like structure that stores the hierarchical structure of a document.
|
|
4
|
+
//! In particular, in most cases it is used to define the hierarchy of headings in the document.
|
|
5
|
+
//! For example, your document might consist of two first-level headings, which in turn have
|
|
6
|
+
//! more nested headings, which in turn might be nested even further, and so on. The [`Outline`]
|
|
7
|
+
//! allows you to encode this behavior, and makes it easier to navigate the document in PDF
|
|
8
|
+
//! viewers that support this feature.
|
|
9
|
+
//!
|
|
10
|
+
//! The intended usage is to create a new, empty outline in the very beginning. It represents
|
|
11
|
+
//! the root of the tree. Then, you can create new outline nodes, which you can recursively
|
|
12
|
+
//! nest in any way you wish while processing your document. In the end, you need to push
|
|
13
|
+
//! the first layer of children to the [`Outline`] object.
|
|
14
|
+
//!
|
|
15
|
+
//! Finally, once you are done building your outline tree, you can use the [`Document::set_outline`]
|
|
16
|
+
//! function of [`Document`] to store the outline in the document.
|
|
17
|
+
//!
|
|
18
|
+
//! [`Document`]: crate::Document
|
|
19
|
+
//! [`Document::set_outline`]: crate::Document::set_outline
|
|
20
|
+
|
|
21
|
+
use pdf_writer::writers::OutlineItem;
|
|
22
|
+
use pdf_writer::{Chunk, Finish, Name, Ref, TextStr};
|
|
23
|
+
|
|
24
|
+
use crate::chunk_container::ChunkContainer;
|
|
25
|
+
use crate::interactive::destination::XyzDestination;
|
|
26
|
+
use crate::serialize::SerializeContext;
|
|
27
|
+
|
|
28
|
+
/// An outline.
|
|
29
|
+
///
|
|
30
|
+
/// This represents the root of the outline tree.
|
|
31
|
+
#[derive(Debug, Clone)]
|
|
32
|
+
pub struct Outline {
|
|
33
|
+
children: Vec<OutlineNode>,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
impl Outline {
|
|
37
|
+
pub(crate) fn is_empty(&self) -> bool {
|
|
38
|
+
self.children.is_empty()
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
impl Default for Outline {
|
|
43
|
+
fn default() -> Self {
|
|
44
|
+
Self::new()
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
trait Outlineable {
|
|
49
|
+
fn first(&mut self, item: Ref) -> &mut Self;
|
|
50
|
+
fn last(&mut self, item: Ref) -> &mut Self;
|
|
51
|
+
fn count(&mut self, count: i32) -> &mut Self;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
impl Outlineable for pdf_writer::writers::Outline<'_> {
|
|
55
|
+
fn first(&mut self, item: Ref) -> &mut Self {
|
|
56
|
+
self.first(item)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
fn last(&mut self, item: Ref) -> &mut Self {
|
|
60
|
+
self.last(item)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
fn count(&mut self, count: i32) -> &mut Self {
|
|
64
|
+
self.count(count)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
impl Outlineable for OutlineItem<'_> {
|
|
69
|
+
fn first(&mut self, item: Ref) -> &mut Self {
|
|
70
|
+
self.first(item)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
fn last(&mut self, item: Ref) -> &mut Self {
|
|
74
|
+
self.last(item)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
fn count(&mut self, count: i32) -> &mut Self {
|
|
78
|
+
self.count(count)
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
struct SerializedChildren {
|
|
83
|
+
first: Ref,
|
|
84
|
+
last: Ref,
|
|
85
|
+
visible_count: usize,
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
impl SerializedChildren {
|
|
89
|
+
fn write(&self, outlineable: &mut impl Outlineable, negate_count: bool) {
|
|
90
|
+
outlineable.first(self.first);
|
|
91
|
+
outlineable.last(self.last);
|
|
92
|
+
|
|
93
|
+
let mut count = i32::try_from(self.visible_count).unwrap();
|
|
94
|
+
if negate_count {
|
|
95
|
+
count = -count;
|
|
96
|
+
}
|
|
97
|
+
outlineable.count(count);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
impl Outline {
|
|
102
|
+
/// Create a new, empty outline.
|
|
103
|
+
pub fn new() -> Self {
|
|
104
|
+
Self { children: vec![] }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/// Push a new child (which may in turn contain other children) to the outline.
|
|
108
|
+
pub fn push_child(&mut self, node: OutlineNode) {
|
|
109
|
+
self.children.push(node)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
pub(crate) fn serialize(
|
|
113
|
+
&self,
|
|
114
|
+
sc: &mut SerializeContext,
|
|
115
|
+
chunk_container: &mut ChunkContainer,
|
|
116
|
+
root: Ref,
|
|
117
|
+
) {
|
|
118
|
+
let mut chunk = sc.new_chunk();
|
|
119
|
+
let children = serialize_children(&self.children, root, &mut chunk, sc);
|
|
120
|
+
|
|
121
|
+
let mut outline = chunk.outline(root);
|
|
122
|
+
if let Some(children) = &children {
|
|
123
|
+
children.write(&mut outline, false);
|
|
124
|
+
}
|
|
125
|
+
outline.finish();
|
|
126
|
+
|
|
127
|
+
chunk_container.non_stream.outline = Some((root, chunk));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/// An outline node.
|
|
132
|
+
///
|
|
133
|
+
/// This represents either an intermediate node in the outline tree, or a leaf node
|
|
134
|
+
/// if it does not contain any further children itself.
|
|
135
|
+
#[derive(Debug, Clone)]
|
|
136
|
+
pub struct OutlineNode {
|
|
137
|
+
/// The children of the outline node.
|
|
138
|
+
children: Vec<OutlineNode>,
|
|
139
|
+
/// The text of the outline entry.
|
|
140
|
+
text: String,
|
|
141
|
+
/// The destination of the outline entry.
|
|
142
|
+
destination: XyzDestination,
|
|
143
|
+
/// Whether this node is initially open (children shown expanded).
|
|
144
|
+
open: bool,
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
impl OutlineNode {
|
|
148
|
+
/// Create a new outline node.
|
|
149
|
+
///
|
|
150
|
+
/// `text` is the string that should be displayed in the outline tree, and
|
|
151
|
+
/// `destination` is the destination that should be jumped to when clicking on
|
|
152
|
+
/// the outline entry.
|
|
153
|
+
pub fn new(text: String, destination: XyzDestination) -> Self {
|
|
154
|
+
Self {
|
|
155
|
+
children: vec![],
|
|
156
|
+
text,
|
|
157
|
+
destination,
|
|
158
|
+
open: false,
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/// Set whether this node is initially open (children shown expanded).
|
|
163
|
+
///
|
|
164
|
+
/// If `open` is `true`, the node's children will be shown expanded when the
|
|
165
|
+
/// document is opened in a PDF viewer; if `false`, the children will be
|
|
166
|
+
/// collapsed. Leaf nodes (nodes without children) are unaffected by this flag.
|
|
167
|
+
///
|
|
168
|
+
/// By default, this flag is set to `false`.
|
|
169
|
+
pub fn with_open(mut self, open: bool) -> Self {
|
|
170
|
+
self.open = open;
|
|
171
|
+
self
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/// Add a new child to the outline node.
|
|
175
|
+
pub fn push_child(&mut self, node: OutlineNode) {
|
|
176
|
+
self.children.push(node)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
pub(crate) fn serialize(
|
|
180
|
+
&self,
|
|
181
|
+
sc: &mut SerializeContext,
|
|
182
|
+
parent: Ref,
|
|
183
|
+
root: Ref,
|
|
184
|
+
next: Option<Ref>,
|
|
185
|
+
prev: Option<Ref>,
|
|
186
|
+
chunk: &mut Chunk,
|
|
187
|
+
) -> usize {
|
|
188
|
+
let children = serialize_children(&self.children, root, chunk, sc);
|
|
189
|
+
let mut outline_entry = chunk.outline_item(root);
|
|
190
|
+
outline_entry.parent(parent);
|
|
191
|
+
|
|
192
|
+
if let Some(next) = next {
|
|
193
|
+
outline_entry.next(next);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
if let Some(prev) = prev {
|
|
197
|
+
outline_entry.prev(prev);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if let Some(children) = &children {
|
|
201
|
+
children.write(&mut outline_entry, !self.open);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
outline_entry.title(TextStr(&self.text));
|
|
205
|
+
|
|
206
|
+
let dest_ref = sc.register_xyz_destination(self.destination.clone());
|
|
207
|
+
outline_entry.pair(Name(b"Dest"), dest_ref);
|
|
208
|
+
|
|
209
|
+
outline_entry.finish();
|
|
210
|
+
|
|
211
|
+
// See the algorithm described in the PDF spec. When recursing down, we
|
|
212
|
+
// do not go into nodes that whose count is negative (i.e. nodes that are
|
|
213
|
+
// closed). Therefore, in case the node is closed, the visible count is
|
|
214
|
+
// just the node itself, so 1.
|
|
215
|
+
|
|
216
|
+
if self.open {
|
|
217
|
+
1 + children.map_or(0, |children| children.visible_count)
|
|
218
|
+
} else {
|
|
219
|
+
1
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
fn serialize_children(
|
|
225
|
+
children: &[OutlineNode],
|
|
226
|
+
parent: Ref,
|
|
227
|
+
chunk: &mut Chunk,
|
|
228
|
+
sc: &mut SerializeContext,
|
|
229
|
+
) -> Option<SerializedChildren> {
|
|
230
|
+
let mut visible_count = 0;
|
|
231
|
+
|
|
232
|
+
if !children.is_empty() {
|
|
233
|
+
let first = sc.new_ref();
|
|
234
|
+
let mut last = first;
|
|
235
|
+
|
|
236
|
+
let mut prev = None;
|
|
237
|
+
let mut cur = Some(first);
|
|
238
|
+
|
|
239
|
+
for i in 0..children.len() {
|
|
240
|
+
let next = if i < children.len() - 1 {
|
|
241
|
+
Some(sc.new_ref())
|
|
242
|
+
} else {
|
|
243
|
+
None
|
|
244
|
+
};
|
|
245
|
+
|
|
246
|
+
last = cur.unwrap();
|
|
247
|
+
|
|
248
|
+
let child_visible_count = children[i].serialize(sc, parent, last, next, prev, chunk);
|
|
249
|
+
visible_count += child_visible_count;
|
|
250
|
+
|
|
251
|
+
prev = cur;
|
|
252
|
+
cur = next;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
Some(SerializedChildren {
|
|
256
|
+
first,
|
|
257
|
+
last,
|
|
258
|
+
visible_count,
|
|
259
|
+
})
|
|
260
|
+
} else {
|
|
261
|
+
None
|
|
262
|
+
}
|
|
263
|
+
}
|