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.
Files changed (114) hide show
  1. package/README.md +300 -10
  2. package/THIRD_PARTY_NOTICES.md +4 -2
  3. package/dist/browser.d.ts +1 -1
  4. package/dist/browser.d.ts.map +1 -1
  5. package/dist/document-options.d.ts +36 -0
  6. package/dist/document-options.d.ts.map +1 -0
  7. package/dist/document-options.js +236 -0
  8. package/dist/document-options.js.map +1 -0
  9. package/dist/node.d.ts +1 -1
  10. package/dist/node.d.ts.map +1 -1
  11. package/dist/options.d.ts +35 -1
  12. package/dist/options.d.ts.map +1 -1
  13. package/dist/options.js +21 -14
  14. package/dist/options.js.map +1 -1
  15. package/dist/types.d.ts +71 -1
  16. package/dist/types.d.ts.map +1 -1
  17. package/dist/validation.d.ts +2 -0
  18. package/dist/validation.d.ts.map +1 -0
  19. package/dist/validation.js +7 -0
  20. package/dist/validation.js.map +1 -0
  21. package/examples/zugferd.mjs +41 -0
  22. package/licenses/RUST_DEPENDENCIES.txt +27 -0
  23. package/package.json +3 -2
  24. package/src/browser.ts +1 -1
  25. package/src/document-options.ts +218 -0
  26. package/src/node.ts +1 -1
  27. package/src/options.ts +18 -13
  28. package/src/types.ts +76 -1
  29. package/src/validation.ts +6 -0
  30. package/vendor/README.md +27 -2
  31. package/vendor/krilla/.cargo-ok +1 -0
  32. package/vendor/krilla/.cargo_vcs_info.json +6 -0
  33. package/vendor/krilla/Cargo.lock +1357 -0
  34. package/vendor/krilla/Cargo.toml +165 -0
  35. package/vendor/krilla/LICENSE_APACHE +202 -0
  36. package/vendor/krilla/LICENSE_MIT +21 -0
  37. package/vendor/krilla/README.md +156 -0
  38. package/vendor/krilla/examples/basic.rs +117 -0
  39. package/vendor/krilla/examples/empty_document.rs +25 -0
  40. package/vendor/krilla/examples/parley.rs +174 -0
  41. package/vendor/krilla/examples/simple_text.rs +118 -0
  42. package/vendor/krilla/examples/stream_builder.rs +93 -0
  43. package/vendor/krilla/icc/LICENSE +116 -0
  44. package/vendor/krilla/icc/README.md +1 -0
  45. package/vendor/krilla/icc/sGrey-v2-magic.icc +0 -0
  46. package/vendor/krilla/icc/sGrey-v4.icc +0 -0
  47. package/vendor/krilla/icc/sRGB-v2-magic.icc +0 -0
  48. package/vendor/krilla/icc/sRGB-v4.icc +0 -0
  49. package/vendor/krilla/src/chunk_container.rs +503 -0
  50. package/vendor/krilla/src/configure/PDF_A1.md +227 -0
  51. package/vendor/krilla/src/configure/PDF_A2.md +269 -0
  52. package/vendor/krilla/src/configure/PDF_A3.md +31 -0
  53. package/vendor/krilla/src/configure/PDF_A4.md +211 -0
  54. package/vendor/krilla/src/configure/PDF_UA1.md +202 -0
  55. package/vendor/krilla/src/configure/README.md +23 -0
  56. package/vendor/krilla/src/configure/mod.rs +197 -0
  57. package/vendor/krilla/src/configure/validate.rs +1244 -0
  58. package/vendor/krilla/src/configure/version.rs +134 -0
  59. package/vendor/krilla/src/content.rs +1352 -0
  60. package/vendor/krilla/src/data.rs +49 -0
  61. package/vendor/krilla/src/document.rs +156 -0
  62. package/vendor/krilla/src/error.rs +170 -0
  63. package/vendor/krilla/src/geom.rs +341 -0
  64. package/vendor/krilla/src/graphics/blend.rs +46 -0
  65. package/vendor/krilla/src/graphics/color.rs +552 -0
  66. package/vendor/krilla/src/graphics/graphic.rs +30 -0
  67. package/vendor/krilla/src/graphics/graphics_state.rs +251 -0
  68. package/vendor/krilla/src/graphics/icc.rs +218 -0
  69. package/vendor/krilla/src/graphics/image.rs +835 -0
  70. package/vendor/krilla/src/graphics/mask.rs +128 -0
  71. package/vendor/krilla/src/graphics/mod.rs +14 -0
  72. package/vendor/krilla/src/graphics/paint.rs +434 -0
  73. package/vendor/krilla/src/graphics/separation.rs +86 -0
  74. package/vendor/krilla/src/graphics/shading_function.rs +865 -0
  75. package/vendor/krilla/src/graphics/shading_pattern.rs +60 -0
  76. package/vendor/krilla/src/graphics/tiling_pattern.rs +119 -0
  77. package/vendor/krilla/src/graphics/xobject.rs +150 -0
  78. package/vendor/krilla/src/interactive/action.rs +68 -0
  79. package/vendor/krilla/src/interactive/annotation.rs +283 -0
  80. package/vendor/krilla/src/interactive/destination.rs +289 -0
  81. package/vendor/krilla/src/interactive/mod.rs +3 -0
  82. package/vendor/krilla/src/interchange/embed.rs +240 -0
  83. package/vendor/krilla/src/interchange/metadata.rs +564 -0
  84. package/vendor/krilla/src/interchange/mod.rs +4 -0
  85. package/vendor/krilla/src/interchange/outline.rs +263 -0
  86. package/vendor/krilla/src/interchange/tagging/fmt.rs +733 -0
  87. package/vendor/krilla/src/interchange/tagging/generate.toml +474 -0
  88. package/vendor/krilla/src/interchange/tagging/generated.rs +4754 -0
  89. package/vendor/krilla/src/interchange/tagging/mod.rs +1324 -0
  90. package/vendor/krilla/src/interchange/tagging/tag.rs +686 -0
  91. package/vendor/krilla/src/lib.rs +179 -0
  92. package/vendor/krilla/src/num.rs +26 -0
  93. package/vendor/krilla/src/page.rs +612 -0
  94. package/vendor/krilla/src/pdf.rs +313 -0
  95. package/vendor/krilla/src/resource.rs +436 -0
  96. package/vendor/krilla/src/serialize.rs +1101 -0
  97. package/vendor/krilla/src/stream.rs +368 -0
  98. package/vendor/krilla/src/surface.rs +664 -0
  99. package/vendor/krilla/src/text/cid.rs +488 -0
  100. package/vendor/krilla/src/text/font.rs +351 -0
  101. package/vendor/krilla/src/text/glyph/bitmap.rs +81 -0
  102. package/vendor/krilla/src/text/glyph/colr.rs +581 -0
  103. package/vendor/krilla/src/text/glyph/mod.rs +205 -0
  104. package/vendor/krilla/src/text/glyph/outline.rs +72 -0
  105. package/vendor/krilla/src/text/glyph/svg.rs +34 -0
  106. package/vendor/krilla/src/text/group.rs +463 -0
  107. package/vendor/krilla/src/text/mod.rs +232 -0
  108. package/vendor/krilla/src/text/shape.rs +102 -0
  109. package/vendor/krilla/src/text/type3.rs +514 -0
  110. package/vendor/krilla/src/util.rs +286 -0
  111. package/vendor/stylo/properties/longhands.toml +0 -1
  112. package/vendor/stylo/stylesheets/rule_parser.rs +1 -1
  113. package/wasm/blitz_pdf.js +10 -5
  114. package/wasm/blitz_pdf_bg.wasm +0 -0
@@ -0,0 +1,286 @@
1
+ use std::any::Any;
2
+ use std::fmt;
3
+ use std::fmt::Debug;
4
+ use std::hash::{Hash, Hasher};
5
+ use std::ops::Deref;
6
+
7
+ use crate::geom::Rect;
8
+ use crate::graphics::color::{DEVICE_CMYK, DEVICE_GRAY, DEVICE_RGB};
9
+ use crate::graphics::paint::Stroke;
10
+ use crate::resource::Resource;
11
+ use crate::serialize::MaybeDeviceColorSpace;
12
+ use base64::Engine;
13
+ pub(crate) use deferred::*;
14
+ use pdf_writer::{Dict, Name};
15
+ use siphasher::sip128::{Hasher128, SipHasher13};
16
+ use tiny_skia_path::Path;
17
+
18
+ pub(crate) trait NameExt {
19
+ fn to_pdf_name(&self) -> Name<'_>;
20
+ }
21
+
22
+ impl NameExt for String {
23
+ fn to_pdf_name(&self) -> Name<'_> {
24
+ Name(self.as_bytes())
25
+ }
26
+ }
27
+
28
+ impl NameExt for &str {
29
+ fn to_pdf_name(&self) -> Name<'_> {
30
+ Name(self.as_bytes())
31
+ }
32
+ }
33
+
34
+ pub(crate) fn calculate_stroke_bbox(stroke: &Stroke, path: &Path) -> Option<Rect> {
35
+ let stroke = stroke.clone().into_tiny_skia();
36
+
37
+ if let Some(stroked_path) = path.stroke(&stroke, 1.0) {
38
+ return Some(Rect::from_tsp(stroked_path.compute_tight_bounds()?));
39
+ }
40
+
41
+ None
42
+ }
43
+
44
+ pub(crate) struct Prehashed<T: ?Sized> {
45
+ hash: u128,
46
+ value: T,
47
+ }
48
+
49
+ impl<T: Hash + 'static> Prehashed<T> {
50
+ #[inline]
51
+ pub fn new(value: T) -> Self {
52
+ let hash = value.sip_hash();
53
+ Self { hash, value }
54
+ }
55
+ }
56
+
57
+ impl<T: Hash + ?Sized + 'static> Eq for Prehashed<T> {}
58
+
59
+ impl<T: Hash + ?Sized + 'static> PartialEq for Prehashed<T> {
60
+ #[inline]
61
+ fn eq(&self, other: &Self) -> bool {
62
+ self.hash == other.hash
63
+ }
64
+ }
65
+
66
+ impl<T: ?Sized> Deref for Prehashed<T> {
67
+ type Target = T;
68
+
69
+ #[inline]
70
+ fn deref(&self) -> &Self::Target {
71
+ &self.value
72
+ }
73
+ }
74
+
75
+ impl<T: Hash + Clone + 'static> Clone for Prehashed<T> {
76
+ fn clone(&self) -> Self {
77
+ Self {
78
+ hash: self.hash,
79
+ value: self.value.clone(),
80
+ }
81
+ }
82
+ }
83
+
84
+ impl<T: Debug> Debug for Prehashed<T> {
85
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86
+ self.value.fmt(f)
87
+ }
88
+ }
89
+
90
+ impl<T: Hash + ?Sized + 'static> Hash for Prehashed<T> {
91
+ #[inline]
92
+ fn hash<H: Hasher>(&self, state: &mut H) {
93
+ state.write_u128(self.hash);
94
+ }
95
+ }
96
+
97
+ /// Extra methods for [`[T]`](slice).
98
+ pub(crate) trait SliceExt<T> {
99
+ /// Split a slice into consecutive runs with the same key and yield for
100
+ /// each such run the key and the slice of elements with that key.
101
+ fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F>
102
+ where
103
+ F: FnMut(&T) -> K,
104
+ K: PartialEq;
105
+ }
106
+
107
+ impl<T> SliceExt<T> for [T] {
108
+ fn group_by_key<K, F>(&self, f: F) -> GroupByKey<'_, T, F> {
109
+ GroupByKey { slice: self, f }
110
+ }
111
+ }
112
+
113
+ /// This struct is created by [`SliceExt::group_by_key`].
114
+ pub(crate) struct GroupByKey<'a, T, F> {
115
+ slice: &'a [T],
116
+ f: F,
117
+ }
118
+
119
+ impl<'a, T, K, F> Iterator for GroupByKey<'a, T, F>
120
+ where
121
+ F: FnMut(&T) -> K,
122
+ K: PartialEq,
123
+ {
124
+ type Item = (K, &'a [T]);
125
+
126
+ fn next(&mut self) -> Option<Self::Item> {
127
+ let mut iter = self.slice.iter();
128
+ let key = (self.f)(iter.next()?);
129
+ let count = 1 + iter.take_while(|t| (self.f)(t) == key).count();
130
+ let (head, tail) = self.slice.split_at(count);
131
+ self.slice = tail;
132
+ Some((key, head))
133
+ }
134
+ }
135
+
136
+ pub(crate) trait SipHashable {
137
+ fn sip_hash(&self) -> u128;
138
+ }
139
+
140
+ impl<T> SipHashable for T
141
+ where
142
+ T: Hash + ?Sized + 'static,
143
+ {
144
+ fn sip_hash(&self) -> u128 {
145
+ let mut state = SipHasher13::new();
146
+ self.type_id().hash(&mut state);
147
+ self.hash(&mut state);
148
+ state.finish128().as_u128()
149
+ }
150
+ }
151
+
152
+ /// Create a base64-encoded hash of the value.
153
+ pub(crate) fn stable_hash_base64<T: Hash + ?Sized>(value: &T) -> String {
154
+ base64::engine::general_purpose::STANDARD.encode(stable_hash128(value).to_be_bytes())
155
+ }
156
+
157
+ /// Calculate a 128-bit siphash of a value.
158
+ pub(crate) fn stable_hash128<T: Hash + ?Sized>(value: &T) -> u128 {
159
+ /// A hasher that hashes usize as u64 to produce stable hashes between
160
+ /// 32-bit and 64-bit architectures.
161
+ struct StableHasher(SipHasher13);
162
+
163
+ impl Hasher for StableHasher {
164
+ fn finish(&self) -> u64 {
165
+ self.0.finish()
166
+ }
167
+
168
+ fn write(&mut self, bytes: &[u8]) {
169
+ self.0.write(bytes);
170
+ }
171
+
172
+ fn write_usize(&mut self, i: usize) {
173
+ self.0.write_u64(i as u64);
174
+ }
175
+ }
176
+
177
+ let mut state = StableHasher(SipHasher13::new());
178
+ value.hash(&mut state);
179
+ state.0.finish128().as_u128()
180
+ }
181
+
182
+ pub(crate) fn set_colorspace(cs: MaybeDeviceColorSpace, target: &mut Dict) {
183
+ let pdf_cs = target.insert(Name(b"ColorSpace"));
184
+
185
+ match cs {
186
+ MaybeDeviceColorSpace::DeviceGray => pdf_cs.primitive(DEVICE_GRAY.to_pdf_name()),
187
+ MaybeDeviceColorSpace::DeviceRgb => pdf_cs.primitive(DEVICE_RGB.to_pdf_name()),
188
+ MaybeDeviceColorSpace::DeviceCMYK => pdf_cs.primitive(DEVICE_CMYK.to_pdf_name()),
189
+ MaybeDeviceColorSpace::ColorSpace(cs) => pdf_cs.primitive(cs.get_ref()),
190
+ }
191
+ }
192
+
193
+ #[cfg(not(feature = "rayon"))]
194
+ mod deferred {
195
+ pub(crate) struct Deferred<T>(T);
196
+
197
+ impl<T: Send + Sync + 'static> Deferred<T> {
198
+ pub fn new<F>(f: F) -> Self
199
+ where
200
+ F: FnOnce() -> T + Send + Sync + 'static,
201
+ {
202
+ Self(f())
203
+ }
204
+
205
+ pub fn wait(&self) -> &T {
206
+ &self.0
207
+ }
208
+ }
209
+ }
210
+
211
+ #[cfg(feature = "rayon")]
212
+ mod deferred {
213
+ /// A value that is lazily executed on another thread.
214
+ ///
215
+ /// Execution will be started in the background and can be waited on.
216
+ pub(crate) struct Deferred<T>(std::sync::Arc<std::sync::OnceLock<T>>);
217
+
218
+ #[cfg(feature = "rayon")]
219
+ impl<T: Send + Sync + 'static> Deferred<T> {
220
+ /// Creates a new deferred value.
221
+ ///
222
+ /// The closure will be called on a secondary thread such that the value
223
+ /// can be initialized in parallel.
224
+ pub fn new<F>(f: F) -> Self
225
+ where
226
+ F: FnOnce() -> T + Send + Sync + 'static,
227
+ {
228
+ let inner = std::sync::Arc::new(std::sync::OnceLock::new());
229
+ let cloned = std::sync::Arc::clone(&inner);
230
+ rayon::spawn(move || {
231
+ // Initialize the value if it hasn't been initialized yet.
232
+ // We do this to avoid panicking in case it was set externally.
233
+ cloned.get_or_init(f);
234
+ });
235
+ Self(inner)
236
+ }
237
+
238
+ /// Waits on the value to be initialized.
239
+ ///
240
+ /// If the value has already been initialized, this will return
241
+ /// immediately. Otherwise, this will block until the value is
242
+ /// initialized in another thread.
243
+ pub fn wait(&self) -> &T {
244
+ // Fast path if the value is already available. We don't want to yield
245
+ // to rayon in that case.
246
+ if let Some(value) = self.0.get() {
247
+ return value;
248
+ }
249
+
250
+ // Ensure that we yield to give the deferred value a chance to compute
251
+ // single-threaded platforms (for WASM compatibility).
252
+ while let Some(rayon::Yield::Executed) = rayon::yield_now() {}
253
+
254
+ self.0.wait()
255
+ }
256
+ }
257
+ }
258
+
259
+ #[cfg(test)]
260
+ pub(crate) mod test_utils {
261
+ use std::path::PathBuf;
262
+ use std::sync::Arc;
263
+ use std::sync::LazyLock;
264
+
265
+ use crate::Data;
266
+
267
+ pub(crate) static WORKSPACE_PATH: LazyLock<PathBuf> =
268
+ LazyLock::new(|| PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../"));
269
+
270
+ pub(crate) static ASSETS_PATH: LazyLock<PathBuf> =
271
+ LazyLock::new(|| WORKSPACE_PATH.join("assets"));
272
+
273
+ static FONT_PATH: LazyLock<PathBuf> = LazyLock::new(|| ASSETS_PATH.join("fonts"));
274
+
275
+ macro_rules! lazy_font {
276
+ ($name:ident, $path:expr) => {
277
+ pub static $name: LazyLock<Data> =
278
+ LazyLock::new(|| Arc::new(std::fs::read($path).unwrap()).into());
279
+ };
280
+ }
281
+
282
+ lazy_font!(
283
+ NOTO_COLOR_EMOJI_COLR,
284
+ FONT_PATH.join("NotoColorEmoji.COLR.subset.ttf")
285
+ );
286
+ }
@@ -1982,7 +1982,6 @@ affects = "layout"
1982
1982
  type = "PageSize"
1983
1983
  initial = "computed::PageSize::auto()"
1984
1984
  struct = "page"
1985
- engine = "gecko"
1986
1985
  spec = "https://drafts.csswg.org/css-page-3/#page-size-prop"
1987
1986
  animation_type = "none"
1988
1987
  rule_types_allowed = ["page"]
@@ -287,7 +287,7 @@ impl AtRuleType {
287
287
  "keyframes" => Self::Keyframes(None),
288
288
  "-webkit-keyframes" => Self::Keyframes(Some(VendorPrefix::WebKit)),
289
289
  "-moz-keyframes" if cfg!(feature = "gecko") => Self::Keyframes(Some(VendorPrefix::Moz)),
290
- "page" if cfg!(feature = "gecko") => Self::Page,
290
+ "page" => Self::Page,
291
291
  "property" if crate::pref!("layout.css.properties-and-values.enabled") => Self::Property,
292
292
  "-moz-document" if cfg!(feature = "gecko") => Self::Document,
293
293
  "import" => Self::Import,
package/wasm/blitz_pdf.js CHANGED
@@ -314,14 +314,14 @@ function __wbg_get_imports() {
314
314
  const ret = getObject(arg0).length;
315
315
  return ret;
316
316
  },
317
- __wbg_new_0_72d020f0c63443d4: function() {
318
- const ret = new Date();
319
- return addHeapObject(ret);
320
- },
321
317
  __wbg_new_1dbf7428bba60a42: function(arg0) {
322
318
  const ret = new Uint8Array(getObject(arg0));
323
319
  return addHeapObject(ret);
324
320
  },
321
+ __wbg_new_34e56228080aa9f8: function(arg0) {
322
+ const ret = new Date(getObject(arg0));
323
+ return addHeapObject(ret);
324
+ },
325
325
  __wbg_next_33784799010f1bbe: function(arg0) {
326
326
  const ret = getObject(arg0).next;
327
327
  return addHeapObject(ret);
@@ -365,7 +365,12 @@ function __wbg_get_imports() {
365
365
  const ret = getObject(arg0).value;
366
366
  return addHeapObject(ret);
367
367
  },
368
- __wbindgen_generic_0000000000000001: function(arg0, arg1) {
368
+ __wbindgen_generic_0000000000000001: function(arg0) {
369
+ // Cast intrinsic for `F64 -> Externref`.
370
+ const ret = arg0;
371
+ return addHeapObject(ret);
372
+ },
373
+ __wbindgen_generic_0000000000000002: function(arg0, arg1) {
369
374
  // Cast intrinsic for `Ref(String) -> Externref`.
370
375
  const ret = getStringFromWasm0(arg0, arg1);
371
376
  return addHeapObject(ret);
Binary file