Showing
57 changed files
with
1257 additions
and
876 deletions
@@ -21,6 +21,8 @@ export 'src/pdf/document_parser.dart'; | @@ -21,6 +21,8 @@ export 'src/pdf/document_parser.dart'; | ||
21 | export 'src/pdf/exif.dart'; | 21 | export 'src/pdf/exif.dart'; |
22 | export 'src/pdf/font/font_metrics.dart'; | 22 | export 'src/pdf/font/font_metrics.dart'; |
23 | export 'src/pdf/font/ttf_parser.dart'; | 23 | export 'src/pdf/font/ttf_parser.dart'; |
24 | +export 'src/pdf/format/name.dart'; | ||
25 | +export 'src/pdf/format/object_base.dart' show DeflateCallback, PdfVersion; | ||
24 | export 'src/pdf/graphic_state.dart'; | 26 | export 'src/pdf/graphic_state.dart'; |
25 | export 'src/pdf/graphics.dart'; | 27 | export 'src/pdf/graphics.dart'; |
26 | export 'src/pdf/obj/annotation.dart'; | 28 | export 'src/pdf/obj/annotation.dart'; |
pdf/lib/src/pdf/data_types.dart
deleted
100644 → 0
1 | -/* | ||
2 | - * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | - * | ||
4 | - * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | - * you may not use this file except in compliance with the License. | ||
6 | - * You may obtain a copy of the License at | ||
7 | - * | ||
8 | - * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | - * | ||
10 | - * Unless required by applicable law or agreed to in writing, software | ||
11 | - * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | - * See the License for the specific language governing permissions and | ||
14 | - * limitations under the License. | ||
15 | - */ | ||
16 | - | ||
17 | -import 'dart:collection'; | ||
18 | -import 'dart:convert'; | ||
19 | -import 'dart:math' as math; | ||
20 | -import 'dart:typed_data'; | ||
21 | - | ||
22 | -import 'package:meta/meta.dart'; | ||
23 | - | ||
24 | -import 'ascii85.dart'; | ||
25 | -import 'color.dart'; | ||
26 | -import 'obj/object.dart'; | ||
27 | -import 'stream.dart'; | ||
28 | - | ||
29 | -const _kIndentSize = 2; | ||
30 | - | ||
31 | -abstract class PdfDataType { | ||
32 | - const PdfDataType(); | ||
33 | - | ||
34 | - void output(PdfStream s, [int? indent]); | ||
35 | - | ||
36 | - PdfStream _toStream() { | ||
37 | - final s = PdfStream(); | ||
38 | - output(s); | ||
39 | - return s; | ||
40 | - } | ||
41 | - | ||
42 | - @override | ||
43 | - String toString() { | ||
44 | - return String.fromCharCodes(_toStream().output()); | ||
45 | - } | ||
46 | - | ||
47 | - @visibleForTesting | ||
48 | - Uint8List toList() { | ||
49 | - return _toStream().output(); | ||
50 | - } | ||
51 | -} | ||
52 | - | ||
53 | -class PdfBool extends PdfDataType { | ||
54 | - const PdfBool(this.value); | ||
55 | - | ||
56 | - final bool value; | ||
57 | - | ||
58 | - @override | ||
59 | - void output(PdfStream s, [int? indent]) { | ||
60 | - s.putString(value ? 'true' : 'false'); | ||
61 | - } | ||
62 | - | ||
63 | - @override | ||
64 | - bool operator ==(Object other) { | ||
65 | - if (other is PdfBool) { | ||
66 | - return value == other.value; | ||
67 | - } | ||
68 | - | ||
69 | - return false; | ||
70 | - } | ||
71 | - | ||
72 | - @override | ||
73 | - int get hashCode => value.hashCode; | ||
74 | -} | ||
75 | - | ||
76 | -class PdfNum extends PdfDataType { | ||
77 | - const PdfNum(this.value) | ||
78 | - : assert(value != double.infinity), | ||
79 | - assert(value != double.negativeInfinity); | ||
80 | - | ||
81 | - static const int precision = 5; | ||
82 | - | ||
83 | - final num value; | ||
84 | - | ||
85 | - @override | ||
86 | - void output(PdfStream s, [int? indent]) { | ||
87 | - assert(!value.isNaN); | ||
88 | - assert(!value.isInfinite); | ||
89 | - | ||
90 | - if (value is int) { | ||
91 | - s.putString(value.toInt().toString()); | ||
92 | - } else { | ||
93 | - var r = value.toStringAsFixed(precision); | ||
94 | - if (r.contains('.')) { | ||
95 | - var n = r.length - 1; | ||
96 | - while (r[n] == '0') { | ||
97 | - n--; | ||
98 | - } | ||
99 | - if (r[n] == '.') { | ||
100 | - n--; | ||
101 | - } | ||
102 | - r = r.substring(0, n + 1); | ||
103 | - } | ||
104 | - s.putString(r); | ||
105 | - } | ||
106 | - } | ||
107 | - | ||
108 | - @override | ||
109 | - bool operator ==(Object other) { | ||
110 | - if (other is PdfNum) { | ||
111 | - return value == other.value; | ||
112 | - } | ||
113 | - | ||
114 | - return false; | ||
115 | - } | ||
116 | - | ||
117 | - PdfNum operator |(PdfNum other) { | ||
118 | - return PdfNum(value.toInt() | other.value.toInt()); | ||
119 | - } | ||
120 | - | ||
121 | - @override | ||
122 | - int get hashCode => value.hashCode; | ||
123 | -} | ||
124 | - | ||
125 | -class PdfNumList extends PdfDataType { | ||
126 | - const PdfNumList(this.values); | ||
127 | - | ||
128 | - final List<num> values; | ||
129 | - | ||
130 | - @override | ||
131 | - void output(PdfStream s, [int? indent]) { | ||
132 | - for (var n = 0; n < values.length; n++) { | ||
133 | - if (n > 0) { | ||
134 | - s.putByte(0x20); | ||
135 | - } | ||
136 | - PdfNum(values[n]).output(s, indent); | ||
137 | - } | ||
138 | - } | ||
139 | - | ||
140 | - @override | ||
141 | - bool operator ==(Object other) { | ||
142 | - if (other is PdfNumList) { | ||
143 | - return values == other.values; | ||
144 | - } | ||
145 | - | ||
146 | - return false; | ||
147 | - } | ||
148 | - | ||
149 | - @override | ||
150 | - int get hashCode => values.hashCode; | ||
151 | -} | ||
152 | - | ||
153 | -enum PdfStringFormat { binary, literal } | ||
154 | - | ||
155 | -class PdfString extends PdfDataType { | ||
156 | - const PdfString(this.value, [this.format = PdfStringFormat.literal]); | ||
157 | - | ||
158 | - factory PdfString.fromString(String value) { | ||
159 | - return PdfString(_string(value), PdfStringFormat.literal); | ||
160 | - } | ||
161 | - | ||
162 | - factory PdfString.fromStream(PdfStream value, | ||
163 | - [PdfStringFormat format = PdfStringFormat.literal]) { | ||
164 | - return PdfString(value.output(), format); | ||
165 | - } | ||
166 | - | ||
167 | - factory PdfString.fromDate(DateTime date) { | ||
168 | - return PdfString(_date(date)); | ||
169 | - } | ||
170 | - | ||
171 | - final Uint8List value; | ||
172 | - | ||
173 | - final PdfStringFormat format; | ||
174 | - | ||
175 | - static Uint8List _string(String value) { | ||
176 | - try { | ||
177 | - return latin1.encode(value); | ||
178 | - } catch (e) { | ||
179 | - return Uint8List.fromList(<int>[0xfe, 0xff] + _encodeUtf16be(value)); | ||
180 | - } | ||
181 | - } | ||
182 | - | ||
183 | - static Uint8List _date(DateTime date) { | ||
184 | - final utcDate = date.toUtc(); | ||
185 | - final year = utcDate.year.toString().padLeft(4, '0'); | ||
186 | - final month = utcDate.month.toString().padLeft(2, '0'); | ||
187 | - final day = utcDate.day.toString().padLeft(2, '0'); | ||
188 | - final hour = utcDate.hour.toString().padLeft(2, '0'); | ||
189 | - final minute = utcDate.minute.toString().padLeft(2, '0'); | ||
190 | - final second = utcDate.second.toString().padLeft(2, '0'); | ||
191 | - return _string('D:$year$month$day$hour$minute${second}Z'); | ||
192 | - } | ||
193 | - | ||
194 | - /// Produce a list of UTF-16BE encoded bytes. | ||
195 | - static List<int> _encodeUtf16be(String str) { | ||
196 | - const unicodeReplacementCharacterCodePoint = 0xfffd; | ||
197 | - const unicodeByteZeroMask = 0xff; | ||
198 | - const unicodeByteOneMask = 0xff00; | ||
199 | - const unicodeValidRangeMax = 0x10ffff; | ||
200 | - const unicodePlaneOneMax = 0xffff; | ||
201 | - const unicodeUtf16ReservedLo = 0xd800; | ||
202 | - const unicodeUtf16ReservedHi = 0xdfff; | ||
203 | - const unicodeUtf16Offset = 0x10000; | ||
204 | - const unicodeUtf16SurrogateUnit0Base = 0xd800; | ||
205 | - const unicodeUtf16SurrogateUnit1Base = 0xdc00; | ||
206 | - const unicodeUtf16HiMask = 0xffc00; | ||
207 | - const unicodeUtf16LoMask = 0x3ff; | ||
208 | - | ||
209 | - final encoding = <int>[]; | ||
210 | - | ||
211 | - void add(int unit) { | ||
212 | - encoding.add((unit & unicodeByteOneMask) >> 8); | ||
213 | - encoding.add(unit & unicodeByteZeroMask); | ||
214 | - } | ||
215 | - | ||
216 | - for (final unit in str.codeUnits) { | ||
217 | - if ((unit >= 0 && unit < unicodeUtf16ReservedLo) || | ||
218 | - (unit > unicodeUtf16ReservedHi && unit <= unicodePlaneOneMax)) { | ||
219 | - add(unit); | ||
220 | - } else if (unit > unicodePlaneOneMax && unit <= unicodeValidRangeMax) { | ||
221 | - final base = unit - unicodeUtf16Offset; | ||
222 | - add(unicodeUtf16SurrogateUnit0Base + | ||
223 | - ((base & unicodeUtf16HiMask) >> 10)); | ||
224 | - add(unicodeUtf16SurrogateUnit1Base + (base & unicodeUtf16LoMask)); | ||
225 | - } else { | ||
226 | - add(unicodeReplacementCharacterCodePoint); | ||
227 | - } | ||
228 | - } | ||
229 | - return encoding; | ||
230 | - } | ||
231 | - | ||
232 | - /// Escape special characters | ||
233 | - /// \ddd Character code ddd (octal) | ||
234 | - void _putTextBytes(PdfStream s, List<int> b) { | ||
235 | - for (final c in b) { | ||
236 | - switch (c) { | ||
237 | - case 0x0a: // \n Line feed (LF) | ||
238 | - s.putByte(0x5c); | ||
239 | - s.putByte(0x6e); | ||
240 | - break; | ||
241 | - case 0x0d: // \r Carriage return (CR) | ||
242 | - s.putByte(0x5c); | ||
243 | - s.putByte(0x72); | ||
244 | - break; | ||
245 | - case 0x09: // \t Horizontal tab (HT) | ||
246 | - s.putByte(0x5c); | ||
247 | - s.putByte(0x74); | ||
248 | - break; | ||
249 | - case 0x08: // \b Backspace (BS) | ||
250 | - s.putByte(0x5c); | ||
251 | - s.putByte(0x62); | ||
252 | - break; | ||
253 | - case 0x0c: // \f Form feed (FF) | ||
254 | - s.putByte(0x5c); | ||
255 | - s.putByte(0x66); | ||
256 | - break; | ||
257 | - case 0x28: // \( Left parenthesis | ||
258 | - s.putByte(0x5c); | ||
259 | - s.putByte(0x28); | ||
260 | - break; | ||
261 | - case 0x29: // \) Right parenthesis | ||
262 | - s.putByte(0x5c); | ||
263 | - s.putByte(0x29); | ||
264 | - break; | ||
265 | - case 0x5c: // \\ Backslash | ||
266 | - s.putByte(0x5c); | ||
267 | - s.putByte(0x5c); | ||
268 | - break; | ||
269 | - default: | ||
270 | - s.putByte(c); | ||
271 | - } | ||
272 | - } | ||
273 | - } | ||
274 | - | ||
275 | - /// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit | ||
276 | - /// [digit]. | ||
277 | - int _codeUnitForDigit(int digit) => | ||
278 | - digit < 10 ? digit + 0x30 : digit + 0x61 - 10; | ||
279 | - | ||
280 | - void _output(PdfStream s, Uint8List value) { | ||
281 | - switch (format) { | ||
282 | - case PdfStringFormat.binary: | ||
283 | - s.putByte(0x3c); | ||
284 | - for (final byte in value) { | ||
285 | - s.putByte(_codeUnitForDigit((byte & 0xF0) >> 4)); | ||
286 | - s.putByte(_codeUnitForDigit(byte & 0x0F)); | ||
287 | - } | ||
288 | - s.putByte(0x3e); | ||
289 | - break; | ||
290 | - case PdfStringFormat.literal: | ||
291 | - s.putByte(40); | ||
292 | - _putTextBytes(s, value); | ||
293 | - s.putByte(41); | ||
294 | - break; | ||
295 | - } | ||
296 | - } | ||
297 | - | ||
298 | - @override | ||
299 | - void output(PdfStream s, [int? indent]) { | ||
300 | - _output(s, value); | ||
301 | - } | ||
302 | - | ||
303 | - @override | ||
304 | - bool operator ==(Object other) { | ||
305 | - if (other is PdfString) { | ||
306 | - return value == other.value; | ||
307 | - } | ||
308 | - | ||
309 | - return false; | ||
310 | - } | ||
311 | - | ||
312 | - @override | ||
313 | - int get hashCode => value.hashCode; | ||
314 | -} | ||
315 | - | ||
316 | -class PdfSecString extends PdfString { | ||
317 | - const PdfSecString(this.object, Uint8List value, | ||
318 | - [PdfStringFormat format = PdfStringFormat.binary]) | ||
319 | - : super(value, format); | ||
320 | - | ||
321 | - factory PdfSecString.fromString( | ||
322 | - PdfObject object, | ||
323 | - String value, [ | ||
324 | - PdfStringFormat format = PdfStringFormat.literal, | ||
325 | - ]) { | ||
326 | - return PdfSecString( | ||
327 | - object, | ||
328 | - PdfString._string(value), | ||
329 | - format, | ||
330 | - ); | ||
331 | - } | ||
332 | - | ||
333 | - factory PdfSecString.fromStream( | ||
334 | - PdfObject object, | ||
335 | - PdfStream value, [ | ||
336 | - PdfStringFormat format = PdfStringFormat.literal, | ||
337 | - ]) { | ||
338 | - return PdfSecString( | ||
339 | - object, | ||
340 | - value.output(), | ||
341 | - format, | ||
342 | - ); | ||
343 | - } | ||
344 | - | ||
345 | - factory PdfSecString.fromDate(PdfObject object, DateTime date) { | ||
346 | - return PdfSecString( | ||
347 | - object, | ||
348 | - PdfString._date(date), | ||
349 | - PdfStringFormat.literal, | ||
350 | - ); | ||
351 | - } | ||
352 | - | ||
353 | - final PdfObject object; | ||
354 | - | ||
355 | - @override | ||
356 | - void output(PdfStream s, [int? indent]) { | ||
357 | - if (object.pdfDocument.encryption == null) { | ||
358 | - return super.output(s, indent); | ||
359 | - } | ||
360 | - | ||
361 | - final enc = object.pdfDocument.encryption!.encrypt(value, object); | ||
362 | - _output(s, enc); | ||
363 | - } | ||
364 | -} | ||
365 | - | ||
366 | -class PdfName extends PdfDataType { | ||
367 | - const PdfName(this.value); | ||
368 | - | ||
369 | - final String value; | ||
370 | - | ||
371 | - @override | ||
372 | - void output(PdfStream s, [int? indent]) { | ||
373 | - assert(value[0] == '/'); | ||
374 | - final bytes = <int>[]; | ||
375 | - for (final c in value.codeUnits) { | ||
376 | - assert(c < 0xff && c > 0x00); | ||
377 | - | ||
378 | - if (c < 0x21 || | ||
379 | - c > 0x7E || | ||
380 | - c == 0x23 || | ||
381 | - (c == 0x2f && bytes.isNotEmpty) || | ||
382 | - c == 0x5b || | ||
383 | - c == 0x5d || | ||
384 | - c == 0x28 || | ||
385 | - c == 0x3c || | ||
386 | - c == 0x3e) { | ||
387 | - bytes.add(0x23); | ||
388 | - final x = c.toRadixString(16).padLeft(2, '0'); | ||
389 | - bytes.addAll(x.codeUnits); | ||
390 | - } else { | ||
391 | - bytes.add(c); | ||
392 | - } | ||
393 | - } | ||
394 | - s.putBytes(bytes); | ||
395 | - } | ||
396 | - | ||
397 | - @override | ||
398 | - bool operator ==(Object other) { | ||
399 | - if (other is PdfName) { | ||
400 | - return value == other.value; | ||
401 | - } | ||
402 | - | ||
403 | - return false; | ||
404 | - } | ||
405 | - | ||
406 | - @override | ||
407 | - int get hashCode => value.hashCode; | ||
408 | -} | ||
409 | - | ||
410 | -class PdfNull extends PdfDataType { | ||
411 | - const PdfNull(); | ||
412 | - | ||
413 | - @override | ||
414 | - void output(PdfStream s, [int? indent]) { | ||
415 | - s.putString('null'); | ||
416 | - } | ||
417 | - | ||
418 | - @override | ||
419 | - bool operator ==(Object other) { | ||
420 | - return other is PdfNull; | ||
421 | - } | ||
422 | - | ||
423 | - @override | ||
424 | - int get hashCode => null.hashCode; | ||
425 | -} | ||
426 | - | ||
427 | -class PdfIndirect extends PdfDataType { | ||
428 | - const PdfIndirect(this.ser, this.gen); | ||
429 | - | ||
430 | - final int ser; | ||
431 | - | ||
432 | - final int gen; | ||
433 | - | ||
434 | - @override | ||
435 | - void output(PdfStream s, [int? indent]) { | ||
436 | - s.putString('$ser $gen R'); | ||
437 | - } | ||
438 | - | ||
439 | - @override | ||
440 | - bool operator ==(Object other) { | ||
441 | - if (other is PdfIndirect) { | ||
442 | - return ser == other.ser && gen == other.gen; | ||
443 | - } | ||
444 | - | ||
445 | - return false; | ||
446 | - } | ||
447 | - | ||
448 | - @override | ||
449 | - int get hashCode => ser.hashCode + gen.hashCode; | ||
450 | -} | ||
451 | - | ||
452 | -class PdfArray<T extends PdfDataType> extends PdfDataType { | ||
453 | - PdfArray([Iterable<T>? values]) { | ||
454 | - if (values != null) { | ||
455 | - this.values.addAll(values); | ||
456 | - } | ||
457 | - } | ||
458 | - | ||
459 | - static PdfArray<PdfIndirect> fromObjects(List<PdfObject> objects) { | ||
460 | - return PdfArray( | ||
461 | - objects.map<PdfIndirect>((PdfObject e) => e.ref()).toList()); | ||
462 | - } | ||
463 | - | ||
464 | - static PdfArray<PdfNum> fromNum(List<num> list) { | ||
465 | - return PdfArray(list.map<PdfNum>((num e) => PdfNum(e)).toList()); | ||
466 | - } | ||
467 | - | ||
468 | - final List<T> values = <T>[]; | ||
469 | - | ||
470 | - void add(T v) { | ||
471 | - values.add(v); | ||
472 | - } | ||
473 | - | ||
474 | - @override | ||
475 | - void output(PdfStream s, [int? indent]) { | ||
476 | - if (indent != null) { | ||
477 | - s.putBytes(List<int>.filled(indent, 0x20)); | ||
478 | - indent += _kIndentSize; | ||
479 | - } | ||
480 | - s.putString('['); | ||
481 | - if (values.isNotEmpty) { | ||
482 | - for (var n = 0; n < values.length; n++) { | ||
483 | - final val = values[n]; | ||
484 | - if (indent != null) { | ||
485 | - s.putByte(0x0a); | ||
486 | - if (val is! PdfDict && val is! PdfArray) { | ||
487 | - s.putBytes(List<int>.filled(indent, 0x20)); | ||
488 | - } | ||
489 | - } else { | ||
490 | - if (n > 0 && | ||
491 | - !(val is PdfName || | ||
492 | - val is PdfString || | ||
493 | - val is PdfArray || | ||
494 | - val is PdfDict)) { | ||
495 | - s.putByte(0x20); | ||
496 | - } | ||
497 | - } | ||
498 | - val.output(s, indent); | ||
499 | - } | ||
500 | - if (indent != null) { | ||
501 | - s.putByte(0x0a); | ||
502 | - } | ||
503 | - } | ||
504 | - if (indent != null) { | ||
505 | - indent -= _kIndentSize; | ||
506 | - s.putBytes(List<int>.filled(indent, 0x20)); | ||
507 | - } | ||
508 | - s.putString(']'); | ||
509 | - } | ||
510 | - | ||
511 | - /// Make all values unique, preserving the order | ||
512 | - void uniq() { | ||
513 | - if (values.length <= 1) { | ||
514 | - return; | ||
515 | - } | ||
516 | - | ||
517 | - // ignore: prefer_collection_literals | ||
518 | - final uniques = LinkedHashMap<T, bool>(); | ||
519 | - for (final s in values) { | ||
520 | - uniques[s] = true; | ||
521 | - } | ||
522 | - values.clear(); | ||
523 | - values.addAll(uniques.keys); | ||
524 | - } | ||
525 | - | ||
526 | - @override | ||
527 | - bool operator ==(Object other) { | ||
528 | - if (other is PdfArray) { | ||
529 | - return values == other.values; | ||
530 | - } | ||
531 | - | ||
532 | - return false; | ||
533 | - } | ||
534 | - | ||
535 | - bool get isEmpty => values.isEmpty; | ||
536 | - | ||
537 | - bool get isNotEmpty => values.isNotEmpty; | ||
538 | - | ||
539 | - @override | ||
540 | - int get hashCode => values.hashCode; | ||
541 | -} | ||
542 | - | ||
543 | -class PdfDict<T extends PdfDataType> extends PdfDataType { | ||
544 | - factory PdfDict([Map<String, T>? values]) { | ||
545 | - final _values = <String, T>{}; | ||
546 | - if (values != null) { | ||
547 | - _values.addAll(values); | ||
548 | - } | ||
549 | - return PdfDict.values(_values); | ||
550 | - } | ||
551 | - | ||
552 | - const PdfDict.values([this.values = const {}]); | ||
553 | - | ||
554 | - static PdfDict<PdfIndirect> fromObjectMap(Map<String, PdfObject> objects) { | ||
555 | - return PdfDict( | ||
556 | - objects.map<String, PdfIndirect>( | ||
557 | - (String key, PdfObject value) => | ||
558 | - MapEntry<String, PdfIndirect>(key, value.ref()), | ||
559 | - ), | ||
560 | - ); | ||
561 | - } | ||
562 | - | ||
563 | - final Map<String, T> values; | ||
564 | - | ||
565 | - bool get isNotEmpty => values.isNotEmpty; | ||
566 | - | ||
567 | - operator []=(String k, T v) { | ||
568 | - values[k] = v; | ||
569 | - } | ||
570 | - | ||
571 | - T? operator [](String k) { | ||
572 | - return values[k]; | ||
573 | - } | ||
574 | - | ||
575 | - @override | ||
576 | - void output(PdfStream s, [int? indent]) { | ||
577 | - if (indent != null) { | ||
578 | - s.putBytes(List<int>.filled(indent, 0x20)); | ||
579 | - } | ||
580 | - s.putBytes(const <int>[0x3c, 0x3c]); | ||
581 | - var len = 0; | ||
582 | - var n = 1; | ||
583 | - if (indent != null) { | ||
584 | - s.putByte(0x0a); | ||
585 | - indent += _kIndentSize; | ||
586 | - len = values.keys.fold<int>(0, (p, e) => math.max(p, e.length)); | ||
587 | - } | ||
588 | - values.forEach((String k, T v) { | ||
589 | - if (indent != null) { | ||
590 | - s.putBytes(List<int>.filled(indent, 0x20)); | ||
591 | - n = len - k.length + 1; | ||
592 | - } | ||
593 | - s.putString(k); | ||
594 | - if (indent != null) { | ||
595 | - if (v is PdfDict || v is PdfArray) { | ||
596 | - s.putByte(0x0a); | ||
597 | - } else { | ||
598 | - s.putBytes(List<int>.filled(n, 0x20)); | ||
599 | - } | ||
600 | - } else { | ||
601 | - if (v is PdfNum || v is PdfBool || v is PdfNull || v is PdfIndirect) { | ||
602 | - s.putByte(0x20); | ||
603 | - } | ||
604 | - } | ||
605 | - v.output(s, indent); | ||
606 | - if (indent != null) { | ||
607 | - s.putByte(0x0a); | ||
608 | - } | ||
609 | - }); | ||
610 | - if (indent != null) { | ||
611 | - indent -= _kIndentSize; | ||
612 | - s.putBytes(List<int>.filled(indent, 0x20)); | ||
613 | - } | ||
614 | - s.putBytes(const <int>[0x3e, 0x3e]); | ||
615 | - } | ||
616 | - | ||
617 | - bool containsKey(String key) { | ||
618 | - return values.containsKey(key); | ||
619 | - } | ||
620 | - | ||
621 | - void merge(PdfDict<T> other) { | ||
622 | - for (final key in other.values.keys) { | ||
623 | - final value = other[key]!; | ||
624 | - final current = values[key]; | ||
625 | - if (current == null) { | ||
626 | - values[key] = value; | ||
627 | - } else if (value is PdfArray && current is PdfArray) { | ||
628 | - current.values.addAll(value.values); | ||
629 | - current.uniq(); | ||
630 | - } else if (value is PdfDict && current is PdfDict) { | ||
631 | - current.merge(value); | ||
632 | - } else { | ||
633 | - values[key] = value; | ||
634 | - } | ||
635 | - } | ||
636 | - } | ||
637 | - | ||
638 | - void addAll(PdfDict<T> other) { | ||
639 | - values.addAll(other.values); | ||
640 | - } | ||
641 | - | ||
642 | - @override | ||
643 | - bool operator ==(Object other) { | ||
644 | - if (other is PdfDict) { | ||
645 | - return values == other.values; | ||
646 | - } | ||
647 | - | ||
648 | - return false; | ||
649 | - } | ||
650 | - | ||
651 | - @override | ||
652 | - int get hashCode => values.hashCode; | ||
653 | -} | ||
654 | - | ||
655 | -class PdfDictStream extends PdfDict<PdfDataType> { | ||
656 | - factory PdfDictStream({ | ||
657 | - required PdfObject object, | ||
658 | - Map<String, PdfDataType>? values, | ||
659 | - Uint8List? data, | ||
660 | - bool isBinary = false, | ||
661 | - bool encrypt = true, | ||
662 | - bool compress = true, | ||
663 | - }) { | ||
664 | - return PdfDictStream.values( | ||
665 | - object: object, | ||
666 | - values: values ?? {}, | ||
667 | - data: data ?? Uint8List(0), | ||
668 | - encrypt: encrypt, | ||
669 | - compress: compress, | ||
670 | - isBinary: isBinary, | ||
671 | - ); | ||
672 | - } | ||
673 | - | ||
674 | - PdfDictStream.values({ | ||
675 | - required this.object, | ||
676 | - required Map<String, PdfDataType> values, | ||
677 | - required this.data, | ||
678 | - this.isBinary = false, | ||
679 | - this.encrypt = true, | ||
680 | - this.compress = true, | ||
681 | - }) : super.values(values); | ||
682 | - | ||
683 | - Uint8List data; | ||
684 | - | ||
685 | - final PdfObject object; | ||
686 | - | ||
687 | - final bool isBinary; | ||
688 | - | ||
689 | - final bool encrypt; | ||
690 | - | ||
691 | - final bool compress; | ||
692 | - | ||
693 | - @override | ||
694 | - void output(PdfStream s, [int? indent]) { | ||
695 | - final _values = PdfDict(values); | ||
696 | - | ||
697 | - Uint8List? _data; | ||
698 | - | ||
699 | - if (_values.containsKey('/Filter')) { | ||
700 | - // The data is already in the right format | ||
701 | - _data = data; | ||
702 | - } else if (compress && object.pdfDocument.compress) { | ||
703 | - // Compress the data | ||
704 | - final newData = Uint8List.fromList(object.pdfDocument.deflate!(data)); | ||
705 | - if (newData.lengthInBytes < data.lengthInBytes) { | ||
706 | - _values['/Filter'] = const PdfName('/FlateDecode'); | ||
707 | - _data = newData; | ||
708 | - } | ||
709 | - } | ||
710 | - | ||
711 | - if (_data == null) { | ||
712 | - if (isBinary) { | ||
713 | - // This is an Ascii85 stream | ||
714 | - final e = Ascii85Encoder(); | ||
715 | - _data = e.convert(data); | ||
716 | - _values['/Filter'] = const PdfName('/ASCII85Decode'); | ||
717 | - } else { | ||
718 | - // This is a non-deflated stream | ||
719 | - _data = data; | ||
720 | - } | ||
721 | - } | ||
722 | - | ||
723 | - if (encrypt && object.pdfDocument.encryption != null) { | ||
724 | - _data = object.pdfDocument.encryption!.encrypt(_data, object); | ||
725 | - } | ||
726 | - | ||
727 | - _values['/Length'] = PdfNum(_data.length); | ||
728 | - | ||
729 | - _values.output(s, indent); | ||
730 | - if (indent != null) { | ||
731 | - s.putByte(0x0a); | ||
732 | - } | ||
733 | - s.putString('stream\n'); | ||
734 | - s.putBytes(_data); | ||
735 | - s.putString('\nendstream\n'); | ||
736 | - } | ||
737 | -} | ||
738 | - | ||
739 | -class PdfColorType extends PdfDataType { | ||
740 | - const PdfColorType(this.color); | ||
741 | - | ||
742 | - final PdfColor color; | ||
743 | - | ||
744 | - @override | ||
745 | - void output(PdfStream s, [int? indent]) { | ||
746 | - if (color is PdfColorCmyk) { | ||
747 | - final k = color as PdfColorCmyk; | ||
748 | - PdfArray.fromNum(<double>[ | ||
749 | - k.cyan, | ||
750 | - k.magenta, | ||
751 | - k.yellow, | ||
752 | - k.black, | ||
753 | - ]).output(s, indent); | ||
754 | - } else { | ||
755 | - PdfArray.fromNum(<double>[ | ||
756 | - color.red, | ||
757 | - color.green, | ||
758 | - color.blue, | ||
759 | - ]).output(s, indent); | ||
760 | - } | ||
761 | - } | ||
762 | - | ||
763 | - @override | ||
764 | - bool operator ==(Object other) { | ||
765 | - if (other is PdfColorType) { | ||
766 | - return color == other.color; | ||
767 | - } | ||
768 | - | ||
769 | - return false; | ||
770 | - } | ||
771 | - | ||
772 | - @override | ||
773 | - int get hashCode => color.hashCode; | ||
774 | -} |
@@ -20,6 +20,9 @@ import 'dart:typed_data'; | @@ -20,6 +20,9 @@ import 'dart:typed_data'; | ||
20 | import 'package:crypto/crypto.dart'; | 20 | import 'package:crypto/crypto.dart'; |
21 | 21 | ||
22 | import 'document_parser.dart'; | 22 | import 'document_parser.dart'; |
23 | +import 'format/object_base.dart'; | ||
24 | +import 'format/stream.dart'; | ||
25 | +import 'format/xref.dart'; | ||
23 | import 'graphic_state.dart'; | 26 | import 'graphic_state.dart'; |
24 | import 'io/vm.dart' if (dart.library.js) 'io/js.dart'; | 27 | import 'io/vm.dart' if (dart.library.js) 'io/js.dart'; |
25 | import 'obj/catalog.dart'; | 28 | import 'obj/catalog.dart'; |
@@ -34,17 +37,6 @@ import 'obj/page_label.dart'; | @@ -34,17 +37,6 @@ import 'obj/page_label.dart'; | ||
34 | import 'obj/page_list.dart'; | 37 | import 'obj/page_list.dart'; |
35 | import 'obj/signature.dart'; | 38 | import 'obj/signature.dart'; |
36 | import 'output.dart'; | 39 | import 'output.dart'; |
37 | -import 'stream.dart'; | ||
38 | -import 'xref.dart'; | ||
39 | - | ||
40 | -/// PDF version to generate | ||
41 | -enum PdfVersion { | ||
42 | - /// PDF 1.4 | ||
43 | - pdf_1_4, | ||
44 | - | ||
45 | - /// PDF 1.5 to 1.7 | ||
46 | - pdf_1_5, | ||
47 | -} | ||
48 | 40 | ||
49 | /// Display hint for the PDF viewer | 41 | /// Display hint for the PDF viewer |
50 | enum PdfPageMode { | 42 | enum PdfPageMode { |
@@ -66,9 +58,6 @@ enum PdfPageMode { | @@ -66,9 +58,6 @@ enum PdfPageMode { | ||
66 | fullscreen | 58 | fullscreen |
67 | } | 59 | } |
68 | 60 | ||
69 | -/// Callback used to compress the data | ||
70 | -typedef DeflateCallback = List<int> Function(List<int> data); | ||
71 | - | ||
72 | /// This class is the base of the Pdf generator. A [PdfDocument] class is | 61 | /// This class is the base of the Pdf generator. A [PdfDocument] class is |
73 | /// created for a document, and each page, object, annotation, | 62 | /// created for a document, and each page, object, annotation, |
74 | /// etc is added to the document. | 63 | /// etc is added to the document. |
@@ -163,6 +152,7 @@ class PdfDocument { | @@ -163,6 +152,7 @@ class PdfDocument { | ||
163 | 152 | ||
164 | bool get compress => deflate != null; | 153 | bool get compress => deflate != null; |
165 | 154 | ||
155 | + /// Output a PDF document with comments and formatted data | ||
166 | final bool verbose; | 156 | final bool verbose; |
167 | 157 | ||
168 | /// Generates the document ID | 158 | /// Generates the document ID |
@@ -17,6 +17,7 @@ | @@ -17,6 +17,7 @@ | ||
17 | import 'dart:typed_data'; | 17 | import 'dart:typed_data'; |
18 | 18 | ||
19 | import 'document.dart'; | 19 | import 'document.dart'; |
20 | +import 'format/object_base.dart'; | ||
20 | 21 | ||
21 | /// Base class for loading an existing PDF document. | 22 | /// Base class for loading an existing PDF document. |
22 | abstract class PdfDocumentParserBase { | 23 | abstract class PdfDocumentParserBase { |
pdf/lib/src/pdf/format/array.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'dart:collection'; | ||
18 | + | ||
19 | +import '../color.dart'; | ||
20 | +import 'base.dart'; | ||
21 | +import 'dict.dart'; | ||
22 | +import 'indirect.dart'; | ||
23 | +import 'name.dart'; | ||
24 | +import 'num.dart'; | ||
25 | +import 'object_base.dart'; | ||
26 | +import 'stream.dart'; | ||
27 | +import 'string.dart'; | ||
28 | + | ||
29 | +class PdfArray<T extends PdfDataType> extends PdfDataType { | ||
30 | + PdfArray([Iterable<T>? values]) { | ||
31 | + if (values != null) { | ||
32 | + this.values.addAll(values); | ||
33 | + } | ||
34 | + } | ||
35 | + | ||
36 | + static PdfArray<PdfIndirect> fromObjects(List<PdfObjectBase> objects) { | ||
37 | + return PdfArray(objects.map<PdfIndirect>((e) => e.ref()).toList()); | ||
38 | + } | ||
39 | + | ||
40 | + static PdfArray<PdfNum> fromNum(List<num> list) { | ||
41 | + return PdfArray(list.map<PdfNum>((num e) => PdfNum(e)).toList()); | ||
42 | + } | ||
43 | + | ||
44 | + static PdfArray fromColor(PdfColor color) { | ||
45 | + if (color is PdfColorCmyk) { | ||
46 | + return PdfArray.fromNum(<double>[ | ||
47 | + color.cyan, | ||
48 | + color.magenta, | ||
49 | + color.yellow, | ||
50 | + color.black, | ||
51 | + ]); | ||
52 | + } else { | ||
53 | + return PdfArray.fromNum(<double>[ | ||
54 | + color.red, | ||
55 | + color.green, | ||
56 | + color.blue, | ||
57 | + ]); | ||
58 | + } | ||
59 | + } | ||
60 | + | ||
61 | + final List<T> values = <T>[]; | ||
62 | + | ||
63 | + void add(T v) { | ||
64 | + values.add(v); | ||
65 | + } | ||
66 | + | ||
67 | + @override | ||
68 | + void output(PdfStream s, [int? indent]) { | ||
69 | + if (indent != null) { | ||
70 | + s.putBytes(List<int>.filled(indent, 0x20)); | ||
71 | + indent += kIndentSize; | ||
72 | + } | ||
73 | + s.putString('['); | ||
74 | + if (values.isNotEmpty) { | ||
75 | + for (var n = 0; n < values.length; n++) { | ||
76 | + final val = values[n]; | ||
77 | + if (indent != null) { | ||
78 | + s.putByte(0x0a); | ||
79 | + if (val is! PdfDict && val is! PdfArray) { | ||
80 | + s.putBytes(List<int>.filled(indent, 0x20)); | ||
81 | + } | ||
82 | + } else { | ||
83 | + if (n > 0 && | ||
84 | + !(val is PdfName || | ||
85 | + val is PdfString || | ||
86 | + val is PdfArray || | ||
87 | + val is PdfDict)) { | ||
88 | + s.putByte(0x20); | ||
89 | + } | ||
90 | + } | ||
91 | + val.output(s, indent); | ||
92 | + } | ||
93 | + if (indent != null) { | ||
94 | + s.putByte(0x0a); | ||
95 | + } | ||
96 | + } | ||
97 | + if (indent != null) { | ||
98 | + indent -= kIndentSize; | ||
99 | + s.putBytes(List<int>.filled(indent, 0x20)); | ||
100 | + } | ||
101 | + s.putString(']'); | ||
102 | + } | ||
103 | + | ||
104 | + /// Make all values unique, preserving the order | ||
105 | + void uniq() { | ||
106 | + if (values.length <= 1) { | ||
107 | + return; | ||
108 | + } | ||
109 | + | ||
110 | + // ignore: prefer_collection_literals | ||
111 | + final uniques = LinkedHashMap<T, bool>(); | ||
112 | + for (final s in values) { | ||
113 | + uniques[s] = true; | ||
114 | + } | ||
115 | + values.clear(); | ||
116 | + values.addAll(uniques.keys); | ||
117 | + } | ||
118 | + | ||
119 | + @override | ||
120 | + bool operator ==(Object other) { | ||
121 | + if (other is PdfArray) { | ||
122 | + return values == other.values; | ||
123 | + } | ||
124 | + | ||
125 | + return false; | ||
126 | + } | ||
127 | + | ||
128 | + bool get isEmpty => values.isEmpty; | ||
129 | + | ||
130 | + bool get isNotEmpty => values.isNotEmpty; | ||
131 | + | ||
132 | + @override | ||
133 | + int get hashCode => values.hashCode; | ||
134 | +} |
pdf/lib/src/pdf/format/base.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'dart:typed_data'; | ||
18 | + | ||
19 | +import 'package:meta/meta.dart'; | ||
20 | + | ||
21 | +import 'stream.dart'; | ||
22 | + | ||
23 | +const kIndentSize = 2; | ||
24 | + | ||
25 | +abstract class PdfDataType { | ||
26 | + const PdfDataType(); | ||
27 | + | ||
28 | + void output(PdfStream s, [int? indent]); | ||
29 | + | ||
30 | + PdfStream _toStream() { | ||
31 | + final s = PdfStream(); | ||
32 | + output(s); | ||
33 | + return s; | ||
34 | + } | ||
35 | + | ||
36 | + @override | ||
37 | + String toString() { | ||
38 | + return String.fromCharCodes(_toStream().output()); | ||
39 | + } | ||
40 | + | ||
41 | + @visibleForTesting | ||
42 | + Uint8List toList() { | ||
43 | + return _toStream().output(); | ||
44 | + } | ||
45 | +} |
pdf/lib/src/pdf/format/bool.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'base.dart'; | ||
18 | +import 'stream.dart'; | ||
19 | + | ||
20 | +class PdfBool extends PdfDataType { | ||
21 | + const PdfBool(this.value); | ||
22 | + | ||
23 | + final bool value; | ||
24 | + | ||
25 | + @override | ||
26 | + void output(PdfStream s, [int? indent]) { | ||
27 | + s.putString(value ? 'true' : 'false'); | ||
28 | + } | ||
29 | + | ||
30 | + @override | ||
31 | + bool operator ==(Object other) { | ||
32 | + if (other is PdfBool) { | ||
33 | + return value == other.value; | ||
34 | + } | ||
35 | + | ||
36 | + return false; | ||
37 | + } | ||
38 | + | ||
39 | + @override | ||
40 | + int get hashCode => value.hashCode; | ||
41 | +} |
pdf/lib/src/pdf/format/dict.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'dart:math' as math; | ||
18 | + | ||
19 | +import 'array.dart'; | ||
20 | +import 'base.dart'; | ||
21 | +import 'bool.dart'; | ||
22 | +import 'indirect.dart'; | ||
23 | +import 'null.dart'; | ||
24 | +import 'num.dart'; | ||
25 | +import 'object_base.dart'; | ||
26 | +import 'stream.dart'; | ||
27 | + | ||
28 | +class PdfDict<T extends PdfDataType> extends PdfDataType { | ||
29 | + factory PdfDict([Map<String, T>? values]) { | ||
30 | + final _values = <String, T>{}; | ||
31 | + if (values != null) { | ||
32 | + _values.addAll(values); | ||
33 | + } | ||
34 | + return PdfDict.values(_values); | ||
35 | + } | ||
36 | + | ||
37 | + const PdfDict.values([this.values = const {}]); | ||
38 | + | ||
39 | + static PdfDict<PdfIndirect> fromObjectMap( | ||
40 | + Map<String, PdfObjectBase> objects) { | ||
41 | + return PdfDict( | ||
42 | + objects.map<String, PdfIndirect>( | ||
43 | + (key, value) => MapEntry<String, PdfIndirect>(key, value.ref()), | ||
44 | + ), | ||
45 | + ); | ||
46 | + } | ||
47 | + | ||
48 | + final Map<String, T> values; | ||
49 | + | ||
50 | + bool get isNotEmpty => values.isNotEmpty; | ||
51 | + | ||
52 | + operator []=(String k, T v) { | ||
53 | + values[k] = v; | ||
54 | + } | ||
55 | + | ||
56 | + T? operator [](String k) { | ||
57 | + return values[k]; | ||
58 | + } | ||
59 | + | ||
60 | + @override | ||
61 | + void output(PdfStream s, [int? indent]) { | ||
62 | + if (indent != null) { | ||
63 | + s.putBytes(List<int>.filled(indent, 0x20)); | ||
64 | + } | ||
65 | + s.putBytes(const <int>[0x3c, 0x3c]); | ||
66 | + var len = 0; | ||
67 | + var n = 1; | ||
68 | + if (indent != null) { | ||
69 | + s.putByte(0x0a); | ||
70 | + indent += kIndentSize; | ||
71 | + len = values.keys.fold<int>(0, (p, e) => math.max(p, e.length)); | ||
72 | + } | ||
73 | + values.forEach((String k, T v) { | ||
74 | + if (indent != null) { | ||
75 | + s.putBytes(List<int>.filled(indent, 0x20)); | ||
76 | + n = len - k.length + 1; | ||
77 | + } | ||
78 | + s.putString(k); | ||
79 | + if (indent != null) { | ||
80 | + if (v is PdfDict || v is PdfArray) { | ||
81 | + s.putByte(0x0a); | ||
82 | + } else { | ||
83 | + s.putBytes(List<int>.filled(n, 0x20)); | ||
84 | + } | ||
85 | + } else { | ||
86 | + if (v is PdfNum || v is PdfBool || v is PdfNull || v is PdfIndirect) { | ||
87 | + s.putByte(0x20); | ||
88 | + } | ||
89 | + } | ||
90 | + v.output(s, indent); | ||
91 | + if (indent != null) { | ||
92 | + s.putByte(0x0a); | ||
93 | + } | ||
94 | + }); | ||
95 | + if (indent != null) { | ||
96 | + indent -= kIndentSize; | ||
97 | + s.putBytes(List<int>.filled(indent, 0x20)); | ||
98 | + } | ||
99 | + s.putBytes(const <int>[0x3e, 0x3e]); | ||
100 | + } | ||
101 | + | ||
102 | + bool containsKey(String key) { | ||
103 | + return values.containsKey(key); | ||
104 | + } | ||
105 | + | ||
106 | + void merge(PdfDict<T> other) { | ||
107 | + for (final key in other.values.keys) { | ||
108 | + final value = other[key]!; | ||
109 | + final current = values[key]; | ||
110 | + if (current == null) { | ||
111 | + values[key] = value; | ||
112 | + } else if (value is PdfArray && current is PdfArray) { | ||
113 | + current.values.addAll(value.values); | ||
114 | + current.uniq(); | ||
115 | + } else if (value is PdfDict && current is PdfDict) { | ||
116 | + current.merge(value); | ||
117 | + } else { | ||
118 | + values[key] = value; | ||
119 | + } | ||
120 | + } | ||
121 | + } | ||
122 | + | ||
123 | + void addAll(PdfDict<T> other) { | ||
124 | + values.addAll(other.values); | ||
125 | + } | ||
126 | + | ||
127 | + @override | ||
128 | + bool operator ==(Object other) { | ||
129 | + if (other is PdfDict) { | ||
130 | + return values == other.values; | ||
131 | + } | ||
132 | + | ||
133 | + return false; | ||
134 | + } | ||
135 | + | ||
136 | + @override | ||
137 | + int get hashCode => values.hashCode; | ||
138 | +} |
pdf/lib/src/pdf/format/dict_stream.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'dart:typed_data'; | ||
18 | + | ||
19 | +import 'ascii85.dart'; | ||
20 | +import 'base.dart'; | ||
21 | +import 'dict.dart'; | ||
22 | +import 'name.dart'; | ||
23 | +import 'num.dart'; | ||
24 | +import 'object_base.dart'; | ||
25 | +import 'stream.dart'; | ||
26 | + | ||
27 | +class PdfDictStream extends PdfDict<PdfDataType> { | ||
28 | + factory PdfDictStream({ | ||
29 | + required PdfObjectBase object, | ||
30 | + Map<String, PdfDataType>? values, | ||
31 | + Uint8List? data, | ||
32 | + bool isBinary = false, | ||
33 | + bool encrypt = true, | ||
34 | + bool compress = true, | ||
35 | + }) { | ||
36 | + return PdfDictStream.values( | ||
37 | + object: object, | ||
38 | + values: values ?? {}, | ||
39 | + data: data ?? Uint8List(0), | ||
40 | + encrypt: encrypt, | ||
41 | + compress: compress, | ||
42 | + isBinary: isBinary, | ||
43 | + ); | ||
44 | + } | ||
45 | + | ||
46 | + PdfDictStream.values({ | ||
47 | + required this.object, | ||
48 | + required Map<String, PdfDataType> values, | ||
49 | + required this.data, | ||
50 | + this.isBinary = false, | ||
51 | + this.encrypt = true, | ||
52 | + this.compress = true, | ||
53 | + }) : super.values(values); | ||
54 | + | ||
55 | + Uint8List data; | ||
56 | + | ||
57 | + final PdfObjectBase object; | ||
58 | + | ||
59 | + final bool isBinary; | ||
60 | + | ||
61 | + final bool encrypt; | ||
62 | + | ||
63 | + final bool compress; | ||
64 | + | ||
65 | + @override | ||
66 | + void output(PdfStream s, [int? indent]) { | ||
67 | + final _values = PdfDict(values); | ||
68 | + | ||
69 | + Uint8List? _data; | ||
70 | + | ||
71 | + if (_values.containsKey('/Filter')) { | ||
72 | + // The data is already in the right format | ||
73 | + _data = data; | ||
74 | + } else if (compress && object.deflate != null) { | ||
75 | + // Compress the data | ||
76 | + final newData = Uint8List.fromList(object.deflate!(data)); | ||
77 | + if (newData.lengthInBytes < data.lengthInBytes) { | ||
78 | + _values['/Filter'] = const PdfName('/FlateDecode'); | ||
79 | + _data = newData; | ||
80 | + } | ||
81 | + } | ||
82 | + | ||
83 | + if (_data == null) { | ||
84 | + if (isBinary) { | ||
85 | + // This is an Ascii85 stream | ||
86 | + final e = Ascii85Encoder(); | ||
87 | + _data = e.convert(data); | ||
88 | + _values['/Filter'] = const PdfName('/ASCII85Decode'); | ||
89 | + } else { | ||
90 | + // This is a non-deflated stream | ||
91 | + _data = data; | ||
92 | + } | ||
93 | + } | ||
94 | + | ||
95 | + if (encrypt && object.encryptCallback != null) { | ||
96 | + _data = object.encryptCallback!(_data, object); | ||
97 | + } | ||
98 | + | ||
99 | + _values['/Length'] = PdfNum(_data.length); | ||
100 | + | ||
101 | + _values.output(s, indent); | ||
102 | + if (indent != null) { | ||
103 | + s.putByte(0x0a); | ||
104 | + } | ||
105 | + s.putString('stream\n'); | ||
106 | + s.putBytes(_data); | ||
107 | + s.putString('\nendstream\n'); | ||
108 | + } | ||
109 | +} |
pdf/lib/src/pdf/format/indirect.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'base.dart'; | ||
18 | +import 'stream.dart'; | ||
19 | + | ||
20 | +class PdfIndirect extends PdfDataType { | ||
21 | + const PdfIndirect(this.ser, this.gen); | ||
22 | + | ||
23 | + final int ser; | ||
24 | + | ||
25 | + final int gen; | ||
26 | + | ||
27 | + @override | ||
28 | + void output(PdfStream s, [int? indent]) { | ||
29 | + s.putString('$ser $gen R'); | ||
30 | + } | ||
31 | + | ||
32 | + @override | ||
33 | + bool operator ==(Object other) { | ||
34 | + if (other is PdfIndirect) { | ||
35 | + return ser == other.ser && gen == other.gen; | ||
36 | + } | ||
37 | + | ||
38 | + return false; | ||
39 | + } | ||
40 | + | ||
41 | + @override | ||
42 | + int get hashCode => ser.hashCode + gen.hashCode; | ||
43 | +} |
pdf/lib/src/pdf/format/name.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'base.dart'; | ||
18 | +import 'stream.dart'; | ||
19 | + | ||
20 | +class PdfName extends PdfDataType { | ||
21 | + const PdfName(this.value); | ||
22 | + | ||
23 | + final String value; | ||
24 | + | ||
25 | + @override | ||
26 | + void output(PdfStream s, [int? indent]) { | ||
27 | + assert(value[0] == '/'); | ||
28 | + final bytes = <int>[]; | ||
29 | + for (final c in value.codeUnits) { | ||
30 | + assert(c < 0xff && c > 0x00); | ||
31 | + | ||
32 | + if (c < 0x21 || | ||
33 | + c > 0x7E || | ||
34 | + c == 0x23 || | ||
35 | + (c == 0x2f && bytes.isNotEmpty) || | ||
36 | + c == 0x5b || | ||
37 | + c == 0x5d || | ||
38 | + c == 0x28 || | ||
39 | + c == 0x3c || | ||
40 | + c == 0x3e) { | ||
41 | + bytes.add(0x23); | ||
42 | + final x = c.toRadixString(16).padLeft(2, '0'); | ||
43 | + bytes.addAll(x.codeUnits); | ||
44 | + } else { | ||
45 | + bytes.add(c); | ||
46 | + } | ||
47 | + } | ||
48 | + s.putBytes(bytes); | ||
49 | + } | ||
50 | + | ||
51 | + @override | ||
52 | + bool operator ==(Object other) { | ||
53 | + if (other is PdfName) { | ||
54 | + return value == other.value; | ||
55 | + } | ||
56 | + | ||
57 | + return false; | ||
58 | + } | ||
59 | + | ||
60 | + @override | ||
61 | + int get hashCode => value.hashCode; | ||
62 | +} |
pdf/lib/src/pdf/format/null.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'base.dart'; | ||
18 | +import 'stream.dart'; | ||
19 | + | ||
20 | +class PdfNull extends PdfDataType { | ||
21 | + const PdfNull(); | ||
22 | + | ||
23 | + @override | ||
24 | + void output(PdfStream s, [int? indent]) { | ||
25 | + s.putString('null'); | ||
26 | + } | ||
27 | + | ||
28 | + @override | ||
29 | + bool operator ==(Object other) { | ||
30 | + return other is PdfNull; | ||
31 | + } | ||
32 | + | ||
33 | + @override | ||
34 | + int get hashCode => null.hashCode; | ||
35 | +} |
pdf/lib/src/pdf/format/num.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'base.dart'; | ||
18 | +import 'stream.dart'; | ||
19 | + | ||
20 | +class PdfNum extends PdfDataType { | ||
21 | + const PdfNum(this.value) | ||
22 | + : assert(value != double.infinity), | ||
23 | + assert(value != double.negativeInfinity); | ||
24 | + | ||
25 | + static const int precision = 5; | ||
26 | + | ||
27 | + final num value; | ||
28 | + | ||
29 | + @override | ||
30 | + void output(PdfStream s, [int? indent]) { | ||
31 | + assert(!value.isNaN); | ||
32 | + assert(!value.isInfinite); | ||
33 | + | ||
34 | + if (value is int) { | ||
35 | + s.putString(value.toInt().toString()); | ||
36 | + } else { | ||
37 | + var r = value.toStringAsFixed(precision); | ||
38 | + if (r.contains('.')) { | ||
39 | + var n = r.length - 1; | ||
40 | + while (r[n] == '0') { | ||
41 | + n--; | ||
42 | + } | ||
43 | + if (r[n] == '.') { | ||
44 | + n--; | ||
45 | + } | ||
46 | + r = r.substring(0, n + 1); | ||
47 | + } | ||
48 | + s.putString(r); | ||
49 | + } | ||
50 | + } | ||
51 | + | ||
52 | + @override | ||
53 | + bool operator ==(Object other) { | ||
54 | + if (other is PdfNum) { | ||
55 | + return value == other.value; | ||
56 | + } | ||
57 | + | ||
58 | + return false; | ||
59 | + } | ||
60 | + | ||
61 | + PdfNum operator |(PdfNum other) { | ||
62 | + return PdfNum(value.toInt() | other.value.toInt()); | ||
63 | + } | ||
64 | + | ||
65 | + @override | ||
66 | + int get hashCode => value.hashCode; | ||
67 | +} | ||
68 | + | ||
69 | +class PdfNumList extends PdfDataType { | ||
70 | + const PdfNumList(this.values); | ||
71 | + | ||
72 | + final List<num> values; | ||
73 | + | ||
74 | + @override | ||
75 | + void output(PdfStream s, [int? indent]) { | ||
76 | + for (var n = 0; n < values.length; n++) { | ||
77 | + if (n > 0) { | ||
78 | + s.putByte(0x20); | ||
79 | + } | ||
80 | + PdfNum(values[n]).output(s, indent); | ||
81 | + } | ||
82 | + } | ||
83 | + | ||
84 | + @override | ||
85 | + bool operator ==(Object other) { | ||
86 | + if (other is PdfNumList) { | ||
87 | + return values == other.values; | ||
88 | + } | ||
89 | + | ||
90 | + return false; | ||
91 | + } | ||
92 | + | ||
93 | + @override | ||
94 | + int get hashCode => values.hashCode; | ||
95 | +} |
pdf/lib/src/pdf/format/object_base.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'dart:typed_data'; | ||
18 | + | ||
19 | +import 'indirect.dart'; | ||
20 | + | ||
21 | +/// Callback used to compress the data | ||
22 | +typedef DeflateCallback = List<int> Function(List<int> data); | ||
23 | + | ||
24 | +/// Callback used to encrypt the value of a [PdfDictStream] or a [PdfEncStream] | ||
25 | +typedef PdfEncryptCallback = Uint8List Function( | ||
26 | + Uint8List input, PdfObjectBase object); | ||
27 | + | ||
28 | +/// PDF version to generate | ||
29 | +enum PdfVersion { | ||
30 | + /// PDF 1.4 | ||
31 | + pdf_1_4, | ||
32 | + | ||
33 | + /// PDF 1.5 to 1.7 | ||
34 | + pdf_1_5, | ||
35 | +} | ||
36 | + | ||
37 | +mixin PdfObjectBase { | ||
38 | + /// This is the unique serial number for this object. | ||
39 | + int get objser; | ||
40 | + | ||
41 | + /// This is the generation number for this object. | ||
42 | + int get objgen => 0; | ||
43 | + | ||
44 | + /// Callback used to compress the data | ||
45 | + DeflateCallback? get deflate => null; | ||
46 | + | ||
47 | + /// Callback used to encrypt the value of a [PdfDictStream] or a [PdfEncStream] | ||
48 | + PdfEncryptCallback? get encryptCallback => null; | ||
49 | + | ||
50 | + /// Output a PDF document with comments and formatted data | ||
51 | + bool get verbose => false; | ||
52 | + | ||
53 | + PdfVersion get version => PdfVersion.pdf_1_5; | ||
54 | + | ||
55 | + /// Returns the unique serial number in Pdf format | ||
56 | + PdfIndirect ref() => PdfIndirect(objser, objgen); | ||
57 | +} |
pdf/lib/src/pdf/format/string.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'dart:convert'; | ||
18 | +import 'dart:typed_data'; | ||
19 | + | ||
20 | +import 'base.dart'; | ||
21 | +import 'object_base.dart'; | ||
22 | +import 'stream.dart'; | ||
23 | + | ||
24 | +enum PdfStringFormat { binary, literal } | ||
25 | + | ||
26 | +class PdfString extends PdfDataType { | ||
27 | + const PdfString(this.value, [this.format = PdfStringFormat.literal]); | ||
28 | + | ||
29 | + factory PdfString.fromString(String value) { | ||
30 | + return PdfString(_string(value), PdfStringFormat.literal); | ||
31 | + } | ||
32 | + | ||
33 | + factory PdfString.fromStream(PdfStream value, | ||
34 | + [PdfStringFormat format = PdfStringFormat.literal]) { | ||
35 | + return PdfString(value.output(), format); | ||
36 | + } | ||
37 | + | ||
38 | + factory PdfString.fromDate(DateTime date) { | ||
39 | + return PdfString(_date(date)); | ||
40 | + } | ||
41 | + | ||
42 | + final Uint8List value; | ||
43 | + | ||
44 | + final PdfStringFormat format; | ||
45 | + | ||
46 | + static Uint8List _string(String value) { | ||
47 | + try { | ||
48 | + return latin1.encode(value); | ||
49 | + } catch (e) { | ||
50 | + return Uint8List.fromList(<int>[0xfe, 0xff] + _encodeUtf16be(value)); | ||
51 | + } | ||
52 | + } | ||
53 | + | ||
54 | + static Uint8List _date(DateTime date) { | ||
55 | + final utcDate = date.toUtc(); | ||
56 | + final year = utcDate.year.toString().padLeft(4, '0'); | ||
57 | + final month = utcDate.month.toString().padLeft(2, '0'); | ||
58 | + final day = utcDate.day.toString().padLeft(2, '0'); | ||
59 | + final hour = utcDate.hour.toString().padLeft(2, '0'); | ||
60 | + final minute = utcDate.minute.toString().padLeft(2, '0'); | ||
61 | + final second = utcDate.second.toString().padLeft(2, '0'); | ||
62 | + return _string('D:$year$month$day$hour$minute${second}Z'); | ||
63 | + } | ||
64 | + | ||
65 | + /// Produce a list of UTF-16BE encoded bytes. | ||
66 | + static List<int> _encodeUtf16be(String str) { | ||
67 | + const unicodeReplacementCharacterCodePoint = 0xfffd; | ||
68 | + const unicodeByteZeroMask = 0xff; | ||
69 | + const unicodeByteOneMask = 0xff00; | ||
70 | + const unicodeValidRangeMax = 0x10ffff; | ||
71 | + const unicodePlaneOneMax = 0xffff; | ||
72 | + const unicodeUtf16ReservedLo = 0xd800; | ||
73 | + const unicodeUtf16ReservedHi = 0xdfff; | ||
74 | + const unicodeUtf16Offset = 0x10000; | ||
75 | + const unicodeUtf16SurrogateUnit0Base = 0xd800; | ||
76 | + const unicodeUtf16SurrogateUnit1Base = 0xdc00; | ||
77 | + const unicodeUtf16HiMask = 0xffc00; | ||
78 | + const unicodeUtf16LoMask = 0x3ff; | ||
79 | + | ||
80 | + final encoding = <int>[]; | ||
81 | + | ||
82 | + void add(int unit) { | ||
83 | + encoding.add((unit & unicodeByteOneMask) >> 8); | ||
84 | + encoding.add(unit & unicodeByteZeroMask); | ||
85 | + } | ||
86 | + | ||
87 | + for (final unit in str.codeUnits) { | ||
88 | + if ((unit >= 0 && unit < unicodeUtf16ReservedLo) || | ||
89 | + (unit > unicodeUtf16ReservedHi && unit <= unicodePlaneOneMax)) { | ||
90 | + add(unit); | ||
91 | + } else if (unit > unicodePlaneOneMax && unit <= unicodeValidRangeMax) { | ||
92 | + final base = unit - unicodeUtf16Offset; | ||
93 | + add(unicodeUtf16SurrogateUnit0Base + | ||
94 | + ((base & unicodeUtf16HiMask) >> 10)); | ||
95 | + add(unicodeUtf16SurrogateUnit1Base + (base & unicodeUtf16LoMask)); | ||
96 | + } else { | ||
97 | + add(unicodeReplacementCharacterCodePoint); | ||
98 | + } | ||
99 | + } | ||
100 | + return encoding; | ||
101 | + } | ||
102 | + | ||
103 | + /// Escape special characters | ||
104 | + /// \ddd Character code ddd (octal) | ||
105 | + void _putTextBytes(PdfStream s, List<int> b) { | ||
106 | + for (final c in b) { | ||
107 | + switch (c) { | ||
108 | + case 0x0a: // \n Line feed (LF) | ||
109 | + s.putByte(0x5c); | ||
110 | + s.putByte(0x6e); | ||
111 | + break; | ||
112 | + case 0x0d: // \r Carriage return (CR) | ||
113 | + s.putByte(0x5c); | ||
114 | + s.putByte(0x72); | ||
115 | + break; | ||
116 | + case 0x09: // \t Horizontal tab (HT) | ||
117 | + s.putByte(0x5c); | ||
118 | + s.putByte(0x74); | ||
119 | + break; | ||
120 | + case 0x08: // \b Backspace (BS) | ||
121 | + s.putByte(0x5c); | ||
122 | + s.putByte(0x62); | ||
123 | + break; | ||
124 | + case 0x0c: // \f Form feed (FF) | ||
125 | + s.putByte(0x5c); | ||
126 | + s.putByte(0x66); | ||
127 | + break; | ||
128 | + case 0x28: // \( Left parenthesis | ||
129 | + s.putByte(0x5c); | ||
130 | + s.putByte(0x28); | ||
131 | + break; | ||
132 | + case 0x29: // \) Right parenthesis | ||
133 | + s.putByte(0x5c); | ||
134 | + s.putByte(0x29); | ||
135 | + break; | ||
136 | + case 0x5c: // \\ Backslash | ||
137 | + s.putByte(0x5c); | ||
138 | + s.putByte(0x5c); | ||
139 | + break; | ||
140 | + default: | ||
141 | + s.putByte(c); | ||
142 | + } | ||
143 | + } | ||
144 | + } | ||
145 | + | ||
146 | + /// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit | ||
147 | + /// [digit]. | ||
148 | + int _codeUnitForDigit(int digit) => | ||
149 | + digit < 10 ? digit + 0x30 : digit + 0x61 - 10; | ||
150 | + | ||
151 | + void _output(PdfStream s, Uint8List value) { | ||
152 | + switch (format) { | ||
153 | + case PdfStringFormat.binary: | ||
154 | + s.putByte(0x3c); | ||
155 | + for (final byte in value) { | ||
156 | + s.putByte(_codeUnitForDigit((byte & 0xF0) >> 4)); | ||
157 | + s.putByte(_codeUnitForDigit(byte & 0x0F)); | ||
158 | + } | ||
159 | + s.putByte(0x3e); | ||
160 | + break; | ||
161 | + case PdfStringFormat.literal: | ||
162 | + s.putByte(40); | ||
163 | + _putTextBytes(s, value); | ||
164 | + s.putByte(41); | ||
165 | + break; | ||
166 | + } | ||
167 | + } | ||
168 | + | ||
169 | + @override | ||
170 | + void output(PdfStream s, [int? indent]) { | ||
171 | + _output(s, value); | ||
172 | + } | ||
173 | + | ||
174 | + @override | ||
175 | + bool operator ==(Object other) { | ||
176 | + if (other is PdfString) { | ||
177 | + return value == other.value; | ||
178 | + } | ||
179 | + | ||
180 | + return false; | ||
181 | + } | ||
182 | + | ||
183 | + @override | ||
184 | + int get hashCode => value.hashCode; | ||
185 | +} | ||
186 | + | ||
187 | +class PdfSecString extends PdfString { | ||
188 | + const PdfSecString(this.object, Uint8List value, | ||
189 | + [PdfStringFormat format = PdfStringFormat.binary]) | ||
190 | + : super(value, format); | ||
191 | + | ||
192 | + factory PdfSecString.fromString( | ||
193 | + PdfObjectBase object, | ||
194 | + String value, [ | ||
195 | + PdfStringFormat format = PdfStringFormat.literal, | ||
196 | + ]) { | ||
197 | + return PdfSecString( | ||
198 | + object, | ||
199 | + PdfString._string(value), | ||
200 | + format, | ||
201 | + ); | ||
202 | + } | ||
203 | + | ||
204 | + factory PdfSecString.fromStream( | ||
205 | + PdfObjectBase object, | ||
206 | + PdfStream value, [ | ||
207 | + PdfStringFormat format = PdfStringFormat.literal, | ||
208 | + ]) { | ||
209 | + return PdfSecString( | ||
210 | + object, | ||
211 | + value.output(), | ||
212 | + format, | ||
213 | + ); | ||
214 | + } | ||
215 | + | ||
216 | + factory PdfSecString.fromDate(PdfObjectBase object, DateTime date) { | ||
217 | + return PdfSecString( | ||
218 | + object, | ||
219 | + PdfString._date(date), | ||
220 | + PdfStringFormat.literal, | ||
221 | + ); | ||
222 | + } | ||
223 | + | ||
224 | + final PdfObjectBase object; | ||
225 | + | ||
226 | + @override | ||
227 | + void output(PdfStream s, [int? indent]) { | ||
228 | + if (object.encryptCallback == null) { | ||
229 | + return super.output(s, indent); | ||
230 | + } | ||
231 | + | ||
232 | + final enc = object.encryptCallback!(value, object); | ||
233 | + _output(s, enc); | ||
234 | + } | ||
235 | +} |
@@ -17,8 +17,14 @@ | @@ -17,8 +17,14 @@ | ||
17 | import 'dart:math' as math; | 17 | import 'dart:math' as math; |
18 | import 'dart:typed_data'; | 18 | import 'dart:typed_data'; |
19 | 19 | ||
20 | -import 'data_types.dart'; | ||
21 | -import 'obj/object.dart'; | 20 | +import 'array.dart'; |
21 | +import 'base.dart'; | ||
22 | +import 'dict.dart'; | ||
23 | +import 'dict_stream.dart'; | ||
24 | +import 'indirect.dart'; | ||
25 | +import 'name.dart'; | ||
26 | +import 'num.dart'; | ||
27 | +import 'object_base.dart'; | ||
22 | import 'stream.dart'; | 28 | import 'stream.dart'; |
23 | 29 | ||
24 | enum PdfCrossRefEntryType { free, inUse, compressed } | 30 | enum PdfCrossRefEntryType { free, inUse, compressed } |
@@ -49,14 +55,14 @@ class PdfXref { | @@ -49,14 +55,14 @@ class PdfXref { | ||
49 | final PdfCrossRefEntryType type; | 55 | final PdfCrossRefEntryType type; |
50 | 56 | ||
51 | /// The xref in the format of the xref section in the Pdf file | 57 | /// The xref in the format of the xref section in the Pdf file |
52 | - String ref() { | 58 | + String _legacyRef() { |
53 | return '${offset.toString().padLeft(10, '0')} ${generation.toString().padLeft(5, '0')}${type == PdfCrossRefEntryType.inUse ? ' n ' : ' f '}'; | 59 | return '${offset.toString().padLeft(10, '0')} ${generation.toString().padLeft(5, '0')}${type == PdfCrossRefEntryType.inUse ? ' n ' : ' f '}'; |
54 | } | 60 | } |
55 | 61 | ||
56 | PdfIndirect? get container => object == null ? null : PdfIndirect(object!, 0); | 62 | PdfIndirect? get container => object == null ? null : PdfIndirect(object!, 0); |
57 | 63 | ||
58 | /// The xref in the format of the compressed xref section in the Pdf file | 64 | /// The xref in the format of the compressed xref section in the Pdf file |
59 | - int cref(ByteData o, int ofs, List<int> w) { | 65 | + int _compressedRef(ByteData o, int ofs, List<int> w) { |
60 | assert(w.length >= 3); | 66 | assert(w.length >= 3); |
61 | 67 | ||
62 | void setVal(int l, int v) { | 68 | void setVal(int l, int v) { |
@@ -105,7 +111,7 @@ class PdfXrefTable extends PdfDataType { | @@ -105,7 +111,7 @@ class PdfXrefTable extends PdfDataType { | ||
105 | s.putString('$firstId ${block.length}\n'); | 111 | s.putString('$firstId ${block.length}\n'); |
106 | 112 | ||
107 | for (final x in block) { | 113 | for (final x in block) { |
108 | - s.putString(x.ref()); | 114 | + s.putString(x._legacyRef()); |
109 | s.putByte(0x0a); | 115 | s.putByte(0x0a); |
110 | } | 116 | } |
111 | } | 117 | } |
@@ -122,15 +128,15 @@ class PdfXrefTable extends PdfDataType { | @@ -122,15 +128,15 @@ class PdfXrefTable extends PdfDataType { | ||
122 | return s.toString(); | 128 | return s.toString(); |
123 | } | 129 | } |
124 | 130 | ||
125 | - int outputLegacy(PdfObject object, PdfStream s, PdfDict params) { | 131 | + int outputLegacy(PdfObjectBase object, PdfStream s, PdfDict params) { |
126 | // Now scan through the offsets list. They should be in sequence. | 132 | // Now scan through the offsets list. They should be in sequence. |
127 | offsets.sort((a, b) => a.id.compareTo(b.id)); | 133 | offsets.sort((a, b) => a.id.compareTo(b.id)); |
128 | 134 | ||
129 | assert(() { | 135 | assert(() { |
130 | - if (object.pdfDocument.verbose) { | 136 | + if (object.verbose) { |
131 | s.putComment(''); | 137 | s.putComment(''); |
132 | s.putComment('-' * 78); | 138 | s.putComment('-' * 78); |
133 | - s.putComment('$runtimeType ${object.pdfDocument.version.name}\n$this'); | 139 | + s.putComment('$runtimeType ${object.version.name}\n$this'); |
134 | } | 140 | } |
135 | return true; | 141 | return true; |
136 | }()); | 142 | }()); |
@@ -169,20 +175,20 @@ class PdfXrefTable extends PdfDataType { | @@ -169,20 +175,20 @@ class PdfXrefTable extends PdfDataType { | ||
169 | 175 | ||
170 | // the trailer object | 176 | // the trailer object |
171 | assert(() { | 177 | assert(() { |
172 | - if (object.pdfDocument.verbose) { | 178 | + if (object.verbose) { |
173 | s.putComment(''); | 179 | s.putComment(''); |
174 | } | 180 | } |
175 | return true; | 181 | return true; |
176 | }()); | 182 | }()); |
177 | s.putString('trailer\n'); | 183 | s.putString('trailer\n'); |
178 | - params.output(s, object.pdfDocument.verbose ? 0 : null); | 184 | + params.output(s, object.verbose ? 0 : null); |
179 | s.putByte(0x0a); | 185 | s.putByte(0x0a); |
180 | 186 | ||
181 | return objOffset; | 187 | return objOffset; |
182 | } | 188 | } |
183 | 189 | ||
184 | /// Output a compressed cross-reference table | 190 | /// Output a compressed cross-reference table |
185 | - int outputCompressed(PdfObject object, PdfStream s, PdfDict params) { | 191 | + int outputCompressed(PdfObjectBase object, PdfStream s, PdfDict params) { |
186 | final offset = s.offset; | 192 | final offset = s.offset; |
187 | 193 | ||
188 | // Sort all references | 194 | // Sort all references |
@@ -229,15 +235,15 @@ class PdfXrefTable extends PdfDataType { | @@ -229,15 +235,15 @@ class PdfXrefTable extends PdfDataType { | ||
229 | ofs += wl; | 235 | ofs += wl; |
230 | 236 | ||
231 | for (final x in offsets) { | 237 | for (final x in offsets) { |
232 | - ofs = x.cref(o, ofs, w); | 238 | + ofs = x._compressedRef(o, ofs, w); |
233 | } | 239 | } |
234 | 240 | ||
235 | // Write the object | 241 | // Write the object |
236 | assert(() { | 242 | assert(() { |
237 | - if (object.pdfDocument.verbose) { | 243 | + if (object.verbose) { |
238 | s.putComment(''); | 244 | s.putComment(''); |
239 | s.putComment('-' * 78); | 245 | s.putComment('-' * 78); |
240 | - s.putComment('$runtimeType ${object.pdfDocument.version.name}\n$this'); | 246 | + s.putComment('$runtimeType ${object.version.name}\n$this'); |
241 | } | 247 | } |
242 | return true; | 248 | return true; |
243 | }()); | 249 | }()); |
@@ -252,7 +258,7 @@ class PdfXrefTable extends PdfDataType { | @@ -252,7 +258,7 @@ class PdfXrefTable extends PdfDataType { | ||
252 | isBinary: false, | 258 | isBinary: false, |
253 | encrypt: false, | 259 | encrypt: false, |
254 | values: params.values, | 260 | values: params.values, |
255 | - ).output(s, object.pdfDocument.verbose ? 0 : null); | 261 | + ).output(s, object.verbose ? 0 : null); |
256 | 262 | ||
257 | s.putString('endobj\n'); | 263 | s.putString('endobj\n'); |
258 | return objOffset; | 264 | return objOffset; |
@@ -18,8 +18,10 @@ | @@ -18,8 +18,10 @@ | ||
18 | 18 | ||
19 | import 'package:meta/meta.dart'; | 19 | import 'package:meta/meta.dart'; |
20 | 20 | ||
21 | -import 'data_types.dart'; | ||
22 | import 'document.dart'; | 21 | import 'document.dart'; |
22 | +import 'format/dict.dart'; | ||
23 | +import 'format/name.dart'; | ||
24 | +import 'format/num.dart'; | ||
23 | import 'obj/function.dart'; | 25 | import 'obj/function.dart'; |
24 | import 'obj/object_dict.dart'; | 26 | import 'obj/object_dict.dart'; |
25 | import 'obj/smask.dart'; | 27 | import 'obj/smask.dart'; |
@@ -22,7 +22,10 @@ import 'package:path_parsing/path_parsing.dart'; | @@ -22,7 +22,10 @@ import 'package:path_parsing/path_parsing.dart'; | ||
22 | import 'package:vector_math/vector_math_64.dart'; | 22 | import 'package:vector_math/vector_math_64.dart'; |
23 | 23 | ||
24 | import 'color.dart'; | 24 | import 'color.dart'; |
25 | -import 'data_types.dart'; | 25 | +import 'format/array.dart'; |
26 | +import 'format/name.dart'; | ||
27 | +import 'format/num.dart'; | ||
28 | +import 'format/stream.dart'; | ||
26 | import 'graphic_state.dart'; | 29 | import 'graphic_state.dart'; |
27 | import 'obj/font.dart'; | 30 | import 'obj/font.dart'; |
28 | import 'obj/graphic_stream.dart'; | 31 | import 'obj/graphic_stream.dart'; |
@@ -31,7 +34,6 @@ import 'obj/page.dart'; | @@ -31,7 +34,6 @@ import 'obj/page.dart'; | ||
31 | import 'obj/pattern.dart'; | 34 | import 'obj/pattern.dart'; |
32 | import 'obj/shading.dart'; | 35 | import 'obj/shading.dart'; |
33 | import 'rect.dart'; | 36 | import 'rect.dart'; |
34 | -import 'stream.dart'; | ||
35 | 37 | ||
36 | /// Shape to be used at the corners of paths that are stroked | 38 | /// Shape to be used at the corners of paths that are stroked |
37 | enum PdfLineJoin { | 39 | enum PdfLineJoin { |
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | 16 | ||
17 | import 'package:archive/archive.dart'; | 17 | import 'package:archive/archive.dart'; |
18 | 18 | ||
19 | -import '../document.dart'; | 19 | +import '../format/object_base.dart'; |
20 | 20 | ||
21 | /// Zip compression function | 21 | /// Zip compression function |
22 | DeflateCallback defaultDeflate = const ZLibEncoder().encode; | 22 | DeflateCallback defaultDeflate = const ZLibEncoder().encode; |
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | 16 | ||
17 | import 'dart:io'; | 17 | import 'dart:io'; |
18 | 18 | ||
19 | -import '../document.dart'; | 19 | +import '../format/object_base.dart'; |
20 | 20 | ||
21 | /// Zip compression function | 21 | /// Zip compression function |
22 | DeflateCallback defaultDeflate = zlib.encode; | 22 | DeflateCallback defaultDeflate = zlib.encode; |
@@ -18,12 +18,18 @@ import 'package:meta/meta.dart'; | @@ -18,12 +18,18 @@ import 'package:meta/meta.dart'; | ||
18 | import 'package:vector_math/vector_math_64.dart'; | 18 | import 'package:vector_math/vector_math_64.dart'; |
19 | 19 | ||
20 | import '../color.dart'; | 20 | import '../color.dart'; |
21 | -import '../data_types.dart'; | ||
22 | import '../document.dart'; | 21 | import '../document.dart'; |
22 | +import '../format/array.dart'; | ||
23 | +import '../format/base.dart'; | ||
24 | +import '../format/dict.dart'; | ||
25 | +import '../format/name.dart'; | ||
26 | +import '../format/null.dart'; | ||
27 | +import '../format/num.dart'; | ||
28 | +import '../format/stream.dart'; | ||
29 | +import '../format/string.dart'; | ||
23 | import '../graphics.dart'; | 30 | import '../graphics.dart'; |
24 | import '../point.dart'; | 31 | import '../point.dart'; |
25 | import '../rect.dart'; | 32 | import '../rect.dart'; |
26 | -import '../stream.dart'; | ||
27 | import 'border.dart'; | 33 | import 'border.dart'; |
28 | import 'font.dart'; | 34 | import 'font.dart'; |
29 | import 'graphic_stream.dart'; | 35 | import 'graphic_stream.dart'; |
@@ -295,7 +301,7 @@ abstract class PdfAnnotBase { | @@ -295,7 +301,7 @@ abstract class PdfAnnotBase { | ||
295 | } | 301 | } |
296 | 302 | ||
297 | if (color != null) { | 303 | if (color != null) { |
298 | - params['/C'] = PdfColorType(color!); | 304 | + params['/C'] = PdfArray.fromColor(color!); |
299 | } | 305 | } |
300 | 306 | ||
301 | if (subject != null) { | 307 | if (subject != null) { |
@@ -441,7 +447,7 @@ class PdfAnnotSquare extends PdfAnnotBase { | @@ -441,7 +447,7 @@ class PdfAnnotSquare extends PdfAnnotBase { | ||
441 | void build(PdfPage page, PdfObject object, PdfDict params) { | 447 | void build(PdfPage page, PdfObject object, PdfDict params) { |
442 | super.build(page, object, params); | 448 | super.build(page, object, params); |
443 | if (interiorColor != null) { | 449 | if (interiorColor != null) { |
444 | - params['/IC'] = PdfColorType(interiorColor!); | 450 | + params['/IC'] = PdfArray.fromColor(interiorColor!); |
445 | } | 451 | } |
446 | } | 452 | } |
447 | } | 453 | } |
@@ -474,7 +480,7 @@ class PdfAnnotCircle extends PdfAnnotBase { | @@ -474,7 +480,7 @@ class PdfAnnotCircle extends PdfAnnotBase { | ||
474 | void build(PdfPage page, PdfObject object, PdfDict params) { | 480 | void build(PdfPage page, PdfObject object, PdfDict params) { |
475 | super.build(page, object, params); | 481 | super.build(page, object, params); |
476 | if (interiorColor != null) { | 482 | if (interiorColor != null) { |
477 | - params['/IC'] = PdfColorType(interiorColor!); | 483 | + params['/IC'] = PdfArray.fromColor(interiorColor!); |
478 | } | 484 | } |
479 | } | 485 | } |
480 | } | 486 | } |
@@ -525,7 +531,7 @@ class PdfAnnotPolygon extends PdfAnnotBase { | @@ -525,7 +531,7 @@ class PdfAnnotPolygon extends PdfAnnotBase { | ||
525 | params['/Vertices'] = PdfArray.fromNum(verticies); | 531 | params['/Vertices'] = PdfArray.fromNum(verticies); |
526 | 532 | ||
527 | if (interiorColor != null) { | 533 | if (interiorColor != null) { |
528 | - params['/IC'] = PdfColorType(interiorColor!); | 534 | + params['/IC'] = PdfArray.fromColor(interiorColor!); |
529 | } | 535 | } |
530 | } | 536 | } |
531 | } | 537 | } |
@@ -631,11 +637,11 @@ abstract class PdfAnnotWidget extends PdfAnnotBase { | @@ -631,11 +637,11 @@ abstract class PdfAnnotWidget extends PdfAnnotBase { | ||
631 | 637 | ||
632 | final mk = PdfDict(); | 638 | final mk = PdfDict(); |
633 | if (color != null) { | 639 | if (color != null) { |
634 | - mk.values['/BC'] = PdfColorType(color!); | 640 | + mk.values['/BC'] = PdfArray.fromColor(color!); |
635 | } | 641 | } |
636 | 642 | ||
637 | if (backgroundColor != null) { | 643 | if (backgroundColor != null) { |
638 | - mk.values['/BG'] = PdfColorType(backgroundColor!); | 644 | + mk.values['/BG'] = PdfArray.fromColor(backgroundColor!); |
639 | } | 645 | } |
640 | 646 | ||
641 | if (mk.values.isNotEmpty) { | 647 | if (mk.values.isNotEmpty) { |
@@ -14,8 +14,8 @@ | @@ -14,8 +14,8 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | import 'object.dart'; | 19 | import 'object.dart'; |
20 | 20 | ||
21 | /// An array object | 21 | /// An array object |
@@ -14,8 +14,10 @@ | @@ -14,8 +14,10 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | +import '../format/name.dart'; | ||
20 | +import '../format/num.dart'; | ||
19 | import 'annotation.dart'; | 21 | import 'annotation.dart'; |
20 | import 'object_dict.dart'; | 22 | import 'object_dict.dart'; |
21 | 23 |
@@ -14,8 +14,11 @@ | @@ -14,8 +14,11 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | +import '../format/dict.dart'; | ||
20 | +import '../format/name.dart'; | ||
21 | +import '../format/num.dart'; | ||
19 | import 'annotation.dart'; | 22 | import 'annotation.dart'; |
20 | import 'metadata.dart'; | 23 | import 'metadata.dart'; |
21 | import 'names.dart'; | 24 | import 'names.dart'; |
@@ -2,7 +2,7 @@ import 'dart:math' as math; | @@ -2,7 +2,7 @@ import 'dart:math' as math; | ||
2 | 2 | ||
3 | import 'package:meta/meta.dart'; | 3 | import 'package:meta/meta.dart'; |
4 | 4 | ||
5 | -import '../stream.dart'; | 5 | +import '../format/stream.dart'; |
6 | 6 | ||
7 | mixin PdfDiagnostic { | 7 | mixin PdfDiagnostic { |
8 | static const _maxSize = 300; | 8 | static const _maxSize = 300; |
@@ -17,7 +17,7 @@ | @@ -17,7 +17,7 @@ | ||
17 | import 'dart:typed_data'; | 17 | import 'dart:typed_data'; |
18 | 18 | ||
19 | import '../document.dart'; | 19 | import '../document.dart'; |
20 | -import 'object.dart'; | 20 | +import '../format/object_base.dart'; |
21 | import 'object_dict.dart'; | 21 | import 'object_dict.dart'; |
22 | 22 | ||
23 | /// Encryption object | 23 | /// Encryption object |
@@ -26,5 +26,5 @@ abstract class PdfEncryption extends PdfObjectDict { | @@ -26,5 +26,5 @@ abstract class PdfEncryption extends PdfObjectDict { | ||
26 | PdfEncryption(PdfDocument pdfDocument) : super(pdfDocument); | 26 | PdfEncryption(PdfDocument pdfDocument) : super(pdfDocument); |
27 | 27 | ||
28 | /// Encrypt some data | 28 | /// Encrypt some data |
29 | - Uint8List encrypt(Uint8List input, PdfObject object); | 29 | + Uint8List encrypt(Uint8List input, PdfObjectBase object); |
30 | } | 30 | } |
@@ -16,12 +16,13 @@ | @@ -16,12 +16,13 @@ | ||
16 | 16 | ||
17 | import 'dart:convert'; | 17 | import 'dart:convert'; |
18 | 18 | ||
19 | -import '../data_types.dart'; | ||
20 | import '../document.dart'; | 19 | import '../document.dart'; |
21 | import '../font/font_metrics.dart'; | 20 | import '../font/font_metrics.dart'; |
22 | import '../font/type1_fonts.dart'; | 21 | import '../font/type1_fonts.dart'; |
22 | +import '../format/name.dart'; | ||
23 | +import '../format/stream.dart'; | ||
24 | +import '../format/string.dart'; | ||
23 | import '../point.dart'; | 25 | import '../point.dart'; |
24 | -import '../stream.dart'; | ||
25 | import 'object_dict.dart'; | 26 | import 'object_dict.dart'; |
26 | import 'type1_font.dart'; | 27 | import 'type1_font.dart'; |
27 | 28 |
@@ -14,7 +14,9 @@ | @@ -14,7 +14,9 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | 17 | +import '../format/array.dart'; |
18 | +import '../format/name.dart'; | ||
19 | +import '../format/num.dart'; | ||
18 | import 'object_dict.dart'; | 20 | import 'object_dict.dart'; |
19 | import 'object_stream.dart'; | 21 | import 'object_stream.dart'; |
20 | import 'ttffont.dart'; | 22 | import 'ttffont.dart'; |
@@ -16,8 +16,10 @@ | @@ -16,8 +16,10 @@ | ||
16 | 16 | ||
17 | import 'package:vector_math/vector_math_64.dart'; | 17 | import 'package:vector_math/vector_math_64.dart'; |
18 | 18 | ||
19 | -import '../data_types.dart'; | ||
20 | import '../document.dart'; | 19 | import '../document.dart'; |
20 | +import '../format/array.dart'; | ||
21 | +import '../format/dict.dart'; | ||
22 | +import '../format/num.dart'; | ||
21 | import 'font.dart'; | 23 | import 'font.dart'; |
22 | import 'xobject.dart'; | 24 | import 'xobject.dart'; |
23 | 25 |
@@ -15,8 +15,9 @@ | @@ -15,8 +15,9 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | import '../color.dart'; | 17 | import '../color.dart'; |
18 | -import '../data_types.dart'; | ||
19 | import '../document.dart'; | 18 | import '../document.dart'; |
19 | +import '../format/array.dart'; | ||
20 | +import '../format/num.dart'; | ||
20 | import 'object_dict.dart'; | 21 | import 'object_dict.dart'; |
21 | import 'object_stream.dart'; | 22 | import 'object_stream.dart'; |
22 | 23 |
@@ -14,8 +14,11 @@ | @@ -14,8 +14,11 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | +import '../format/bool.dart'; | ||
20 | +import '../format/dict.dart'; | ||
21 | +import '../format/name.dart'; | ||
19 | import '../graphic_state.dart'; | 22 | import '../graphic_state.dart'; |
20 | import 'font.dart'; | 23 | import 'font.dart'; |
21 | import 'object_dict.dart'; | 24 | import 'object_dict.dart'; |
@@ -18,9 +18,11 @@ import 'dart:typed_data'; | @@ -18,9 +18,11 @@ import 'dart:typed_data'; | ||
18 | 18 | ||
19 | import 'package:image/image.dart' as im; | 19 | import 'package:image/image.dart' as im; |
20 | 20 | ||
21 | -import '../data_types.dart'; | ||
22 | import '../document.dart'; | 21 | import '../document.dart'; |
23 | import '../exif.dart'; | 22 | import '../exif.dart'; |
23 | +import '../format/indirect.dart'; | ||
24 | +import '../format/name.dart'; | ||
25 | +import '../format/num.dart'; | ||
24 | import '../raster.dart'; | 26 | import '../raster.dart'; |
25 | import 'xobject.dart'; | 27 | import 'xobject.dart'; |
26 | 28 |
@@ -14,8 +14,8 @@ | @@ -14,8 +14,8 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/string.dart'; | ||
19 | import 'object_dict.dart'; | 19 | import 'object_dict.dart'; |
20 | 20 | ||
21 | /// Information object | 21 | /// Information object |
@@ -19,8 +19,9 @@ import 'dart:typed_data'; | @@ -19,8 +19,9 @@ import 'dart:typed_data'; | ||
19 | 19 | ||
20 | import 'package:xml/xml.dart'; | 20 | import 'package:xml/xml.dart'; |
21 | 21 | ||
22 | -import '../data_types.dart'; | ||
23 | import '../document.dart'; | 22 | import '../document.dart'; |
23 | +import '../format/dict_stream.dart'; | ||
24 | +import '../format/name.dart'; | ||
24 | import 'object.dart'; | 25 | import 'object.dart'; |
25 | 26 | ||
26 | /// Pdf Metadata | 27 | /// Pdf Metadata |
@@ -14,8 +14,14 @@ | @@ -14,8 +14,14 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | +import '../format/base.dart'; | ||
20 | +import '../format/dict.dart'; | ||
21 | +import '../format/name.dart'; | ||
22 | +import '../format/null.dart'; | ||
23 | +import '../format/num.dart'; | ||
24 | +import '../format/string.dart'; | ||
19 | import 'object_dict.dart'; | 25 | import 'object_dict.dart'; |
20 | import 'page.dart'; | 26 | import 'page.dart'; |
21 | 27 |
@@ -16,13 +16,15 @@ | @@ -16,13 +16,15 @@ | ||
16 | 16 | ||
17 | import 'package:meta/meta.dart'; | 17 | import 'package:meta/meta.dart'; |
18 | 18 | ||
19 | -import '../data_types.dart'; | ||
20 | import '../document.dart'; | 19 | import '../document.dart'; |
21 | -import '../stream.dart'; | 20 | +import '../format/base.dart'; |
21 | +import '../format/object_base.dart'; | ||
22 | +import '../format/stream.dart'; | ||
22 | import 'diagnostic.dart'; | 23 | import 'diagnostic.dart'; |
23 | 24 | ||
24 | /// Base Object used in the PDF file | 25 | /// Base Object used in the PDF file |
25 | -abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | 26 | +abstract class PdfObject<T extends PdfDataType> |
27 | + with PdfDiagnostic, PdfObjectBase { | ||
26 | /// This is usually called by extensors to this class, and sets the | 28 | /// This is usually called by extensors to this class, and sets the |
27 | /// Pdf Object Type | 29 | /// Pdf Object Type |
28 | PdfObject( | 30 | PdfObject( |
@@ -37,10 +39,10 @@ abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | @@ -37,10 +39,10 @@ abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | ||
37 | /// This is the object parameters. | 39 | /// This is the object parameters. |
38 | final T params; | 40 | final T params; |
39 | 41 | ||
40 | - /// This is the unique serial number for this object. | 42 | + @override |
41 | final int objser; | 43 | final int objser; |
42 | 44 | ||
43 | - /// This is the generation number for this object. | 45 | + @override |
44 | final int objgen; | 46 | final int objgen; |
45 | 47 | ||
46 | /// This allows any Pdf object to refer to the document being constructed. | 48 | /// This allows any Pdf object to refer to the document being constructed. |
@@ -48,6 +50,18 @@ abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | @@ -48,6 +50,18 @@ abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | ||
48 | 50 | ||
49 | var inUse = true; | 51 | var inUse = true; |
50 | 52 | ||
53 | + @override | ||
54 | + DeflateCallback? get deflate => pdfDocument.deflate; | ||
55 | + | ||
56 | + @override | ||
57 | + PdfEncryptCallback? get encryptCallback => pdfDocument.encryption?.encrypt; | ||
58 | + | ||
59 | + @override | ||
60 | + bool get verbose => pdfDocument.verbose; | ||
61 | + | ||
62 | + @override | ||
63 | + PdfVersion get version => pdfDocument.version; | ||
64 | + | ||
51 | /// Writes the object to the output stream. | 65 | /// Writes the object to the output stream. |
52 | void write(PdfStream os) { | 66 | void write(PdfStream os) { |
53 | prepare(); | 67 | prepare(); |
@@ -67,7 +81,7 @@ abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | @@ -67,7 +81,7 @@ abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | ||
67 | } | 81 | } |
68 | 82 | ||
69 | void writeContent(PdfStream os) { | 83 | void writeContent(PdfStream os) { |
70 | - params.output(os, pdfDocument.verbose ? 0 : null); | 84 | + params.output(os, verbose ? 0 : null); |
71 | os.putByte(0x0a); | 85 | os.putByte(0x0a); |
72 | } | 86 | } |
73 | 87 | ||
@@ -77,9 +91,6 @@ abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | @@ -77,9 +91,6 @@ abstract class PdfObject<T extends PdfDataType> with PdfDiagnostic { | ||
77 | os.putString('endobj\n'); | 91 | os.putString('endobj\n'); |
78 | } | 92 | } |
79 | 93 | ||
80 | - /// Returns the unique serial number in Pdf format | ||
81 | - PdfIndirect ref() => PdfIndirect(objser, objgen); | ||
82 | - | ||
83 | @override | 94 | @override |
84 | String toString() => '$runtimeType $params'; | 95 | String toString() => '$runtimeType $params'; |
85 | } | 96 | } |
@@ -14,9 +14,10 @@ | @@ -14,9 +14,10 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
19 | -import '../stream.dart'; | 18 | +import '../format/dict.dart'; |
19 | +import '../format/name.dart'; | ||
20 | +import '../format/stream.dart'; | ||
20 | import 'object.dart'; | 21 | import 'object.dart'; |
21 | 22 | ||
22 | /// Object with a PdfDict used in the PDF file | 23 | /// Object with a PdfDict used in the PDF file |
@@ -14,9 +14,9 @@ | @@ -14,9 +14,9 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
19 | -import '../stream.dart'; | 18 | +import '../format/dict_stream.dart'; |
19 | +import '../format/stream.dart'; | ||
20 | import 'object_dict.dart'; | 20 | import 'object_dict.dart'; |
21 | 21 | ||
22 | /// Stream Object | 22 | /// Stream Object |
@@ -15,8 +15,11 @@ | @@ -15,8 +15,11 @@ | ||
15 | */ | 15 | */ |
16 | 16 | ||
17 | import '../color.dart'; | 17 | import '../color.dart'; |
18 | -import '../data_types.dart'; | ||
19 | import '../document.dart'; | 18 | import '../document.dart'; |
19 | +import '../format/array.dart'; | ||
20 | +import '../format/name.dart'; | ||
21 | +import '../format/num.dart'; | ||
22 | +import '../format/string.dart'; | ||
20 | import '../rect.dart'; | 23 | import '../rect.dart'; |
21 | import 'object_dict.dart'; | 24 | import 'object_dict.dart'; |
22 | import 'page.dart'; | 25 | import 'page.dart'; |
@@ -125,7 +128,7 @@ class PdfOutline extends PdfObjectDict { | @@ -125,7 +128,7 @@ class PdfOutline extends PdfObjectDict { | ||
125 | params['/Title'] = PdfSecString.fromString(this, title!); | 128 | params['/Title'] = PdfSecString.fromString(this, title!); |
126 | 129 | ||
127 | if (color != null) { | 130 | if (color != null) { |
128 | - params['/C'] = PdfColorType(color!); | 131 | + params['/C'] = PdfArray.fromColor(color!); |
129 | } | 132 | } |
130 | 133 | ||
131 | if (style != PdfOutlineStyle.normal) { | 134 | if (style != PdfOutlineStyle.normal) { |
@@ -14,8 +14,10 @@ | @@ -14,8 +14,10 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | +import '../format/indirect.dart'; | ||
20 | +import '../format/num.dart'; | ||
19 | import '../graphics.dart'; | 21 | import '../graphics.dart'; |
20 | import '../page_format.dart'; | 22 | import '../page_format.dart'; |
21 | import 'annotation.dart'; | 23 | import 'annotation.dart'; |
1 | -import '../../priv.dart'; | 1 | +/* |
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
2 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | +import '../format/dict.dart'; | ||
20 | +import '../format/name.dart'; | ||
21 | +import '../format/num.dart'; | ||
22 | +import '../format/string.dart'; | ||
23 | +import 'object.dart'; | ||
3 | import 'object_dict.dart'; | 24 | import 'object_dict.dart'; |
4 | 25 | ||
5 | enum PdfPageLabelStyle { | 26 | enum PdfPageLabelStyle { |
@@ -14,8 +14,9 @@ | @@ -14,8 +14,9 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | +import '../format/num.dart'; | ||
19 | import 'object_dict.dart'; | 20 | import 'object_dict.dart'; |
20 | import 'page.dart'; | 21 | import 'page.dart'; |
21 | 22 |
@@ -16,8 +16,9 @@ | @@ -16,8 +16,9 @@ | ||
16 | 16 | ||
17 | import 'package:vector_math/vector_math_64.dart'; | 17 | import 'package:vector_math/vector_math_64.dart'; |
18 | 18 | ||
19 | -import '../data_types.dart'; | ||
20 | import '../document.dart'; | 19 | import '../document.dart'; |
20 | +import '../format/array.dart'; | ||
21 | +import '../format/num.dart'; | ||
21 | import '../graphic_state.dart'; | 22 | import '../graphic_state.dart'; |
22 | import 'object_dict.dart'; | 23 | import 'object_dict.dart'; |
23 | import 'shading.dart'; | 24 | import 'shading.dart'; |
@@ -14,8 +14,11 @@ | @@ -14,8 +14,11 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/array.dart'; | ||
19 | +import '../format/bool.dart'; | ||
20 | +import '../format/name.dart'; | ||
21 | +import '../format/num.dart'; | ||
19 | import '../point.dart'; | 22 | import '../point.dart'; |
20 | import '../rect.dart'; | 23 | import '../rect.dart'; |
21 | import 'function.dart'; | 24 | import 'function.dart'; |
@@ -16,9 +16,9 @@ | @@ -16,9 +16,9 @@ | ||
16 | 16 | ||
17 | import 'dart:typed_data'; | 17 | import 'dart:typed_data'; |
18 | 18 | ||
19 | -import '../data_types.dart'; | ||
20 | import '../document.dart'; | 19 | import '../document.dart'; |
21 | -import '../stream.dart'; | 20 | +import '../format/dict.dart'; |
21 | +import '../format/stream.dart'; | ||
22 | import 'object.dart'; | 22 | import 'object.dart'; |
23 | import 'object_dict.dart'; | 23 | import 'object_dict.dart'; |
24 | import 'object_stream.dart'; | 24 | import 'object_stream.dart'; |
@@ -16,8 +16,11 @@ | @@ -16,8 +16,11 @@ | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | -import '../data_types.dart'; | ||
20 | import '../document.dart'; | 19 | import '../document.dart'; |
20 | +import '../format/array.dart'; | ||
21 | +import '../format/bool.dart'; | ||
22 | +import '../format/dict.dart'; | ||
23 | +import '../format/name.dart'; | ||
21 | import '../graphics.dart'; | 24 | import '../graphics.dart'; |
22 | import '../rect.dart'; | 25 | import '../rect.dart'; |
23 | import 'function.dart'; | 26 | import 'function.dart'; |
@@ -17,13 +17,17 @@ | @@ -17,13 +17,17 @@ | ||
17 | import 'dart:convert'; | 17 | import 'dart:convert'; |
18 | import 'dart:typed_data'; | 18 | import 'dart:typed_data'; |
19 | 19 | ||
20 | -import '../data_types.dart'; | ||
21 | import '../document.dart'; | 20 | import '../document.dart'; |
22 | import '../font/bidi_utils.dart' as bidi; | 21 | import '../font/bidi_utils.dart' as bidi; |
23 | import '../font/font_metrics.dart'; | 22 | import '../font/font_metrics.dart'; |
24 | import '../font/ttf_parser.dart'; | 23 | import '../font/ttf_parser.dart'; |
25 | import '../font/ttf_writer.dart'; | 24 | import '../font/ttf_writer.dart'; |
26 | -import '../stream.dart'; | 25 | +import '../format/array.dart'; |
26 | +import '../format/dict.dart'; | ||
27 | +import '../format/name.dart'; | ||
28 | +import '../format/num.dart'; | ||
29 | +import '../format/stream.dart'; | ||
30 | +import '../format/string.dart'; | ||
27 | import 'array.dart'; | 31 | import 'array.dart'; |
28 | import 'font.dart'; | 32 | import 'font.dart'; |
29 | import 'font_descriptor.dart'; | 33 | import 'font_descriptor.dart'; |
@@ -14,9 +14,9 @@ | @@ -14,9 +14,9 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
19 | import '../font/font_metrics.dart'; | 18 | import '../font/font_metrics.dart'; |
19 | +import '../format/name.dart'; | ||
20 | import 'font.dart'; | 20 | import 'font.dart'; |
21 | import 'ttffont.dart'; | 21 | import 'ttffont.dart'; |
22 | 22 |
@@ -14,8 +14,8 @@ | @@ -14,8 +14,8 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import '../data_types.dart'; | ||
18 | import '../document.dart'; | 17 | import '../document.dart'; |
18 | +import '../format/name.dart'; | ||
19 | import 'object_stream.dart'; | 19 | import 'object_stream.dart'; |
20 | 20 | ||
21 | class PdfXObject extends PdfObjectStream { | 21 | class PdfXObject extends PdfObjectStream { |
@@ -14,16 +14,19 @@ | @@ -14,16 +14,19 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -import 'data_types.dart'; | ||
18 | -import 'document.dart'; | 17 | +import 'format/array.dart'; |
18 | +import 'format/dict.dart'; | ||
19 | +import 'format/num.dart'; | ||
20 | +import 'format/object_base.dart'; | ||
21 | +import 'format/stream.dart'; | ||
22 | +import 'format/string.dart'; | ||
23 | +import 'format/xref.dart'; | ||
19 | import 'obj/catalog.dart'; | 24 | import 'obj/catalog.dart'; |
20 | import 'obj/diagnostic.dart'; | 25 | import 'obj/diagnostic.dart'; |
21 | import 'obj/encryption.dart'; | 26 | import 'obj/encryption.dart'; |
22 | import 'obj/info.dart'; | 27 | import 'obj/info.dart'; |
23 | import 'obj/object.dart'; | 28 | import 'obj/object.dart'; |
24 | import 'obj/signature.dart'; | 29 | import 'obj/signature.dart'; |
25 | -import 'stream.dart'; | ||
26 | -import 'xref.dart'; | ||
27 | 30 | ||
28 | /// PDF document writer | 31 | /// PDF document writer |
29 | class PdfOutput with PdfDiagnostic { | 32 | class PdfOutput with PdfDiagnostic { |
@@ -14,8 +14,19 @@ | @@ -14,8 +14,19 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | -export 'pdf/data_types.dart'; | 17 | +export 'pdf/format/array.dart'; |
18 | +export 'pdf/format/ascii85.dart'; | ||
19 | +export 'pdf/format/base.dart'; | ||
20 | +export 'pdf/format/bool.dart'; | ||
21 | +export 'pdf/format/dict.dart'; | ||
22 | +export 'pdf/format/dict_stream.dart'; | ||
23 | +export 'pdf/format/indirect.dart'; | ||
24 | +export 'pdf/format/name.dart'; | ||
25 | +export 'pdf/format/null.dart'; | ||
26 | +export 'pdf/format/num.dart'; | ||
27 | +export 'pdf/format/object_base.dart' hide DeflateCallback, PdfVersion; | ||
28 | +export 'pdf/format/stream.dart'; | ||
29 | +export 'pdf/format/string.dart'; | ||
30 | +export 'pdf/format/xref.dart'; | ||
18 | export 'pdf/obj/object.dart'; | 31 | export 'pdf/obj/object.dart'; |
19 | export 'pdf/obj/object_stream.dart'; | 32 | export 'pdf/obj/object_stream.dart'; |
20 | -export 'pdf/stream.dart'; | ||
21 | -export 'pdf/xref.dart'; |
@@ -20,7 +20,6 @@ import 'dart:typed_data'; | @@ -20,7 +20,6 @@ import 'dart:typed_data'; | ||
20 | import 'package:vector_math/vector_math_64.dart'; | 20 | import 'package:vector_math/vector_math_64.dart'; |
21 | 21 | ||
22 | import '../../pdf.dart'; | 22 | import '../../pdf.dart'; |
23 | -import '../pdf/data_types.dart'; | ||
24 | import 'basic.dart'; | 23 | import 'basic.dart'; |
25 | import 'border_radius.dart'; | 24 | import 'border_radius.dart'; |
26 | import 'box_border.dart'; | 25 | import 'box_border.dart'; |
@@ -16,7 +16,7 @@ | @@ -16,7 +16,7 @@ | ||
16 | 16 | ||
17 | import 'dart:typed_data'; | 17 | import 'dart:typed_data'; |
18 | 18 | ||
19 | -import 'package:pdf/src/pdf/data_types.dart'; | 19 | +import 'package:pdf/src/priv.dart'; |
20 | import 'package:test/test.dart'; | 20 | import 'package:test/test.dart'; |
21 | 21 | ||
22 | void main() { | 22 | void main() { |
@@ -14,22 +14,87 @@ | @@ -14,22 +14,87 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | +import 'dart:convert'; | ||
17 | import 'dart:io'; | 18 | import 'dart:io'; |
18 | 19 | ||
19 | -import 'package:pdf/pdf.dart'; | 20 | +import 'package:pdf/src/priv.dart'; |
20 | import 'package:test/test.dart'; | 21 | import 'package:test/test.dart'; |
21 | 22 | ||
23 | +class BasicObject with PdfObjectBase { | ||
24 | + const BasicObject(this.objser); | ||
25 | + | ||
26 | + @override | ||
27 | + final int objser; | ||
28 | + | ||
29 | + @override | ||
30 | + bool get verbose => true; | ||
31 | + | ||
32 | + void write(PdfStream os, PdfDataType value) { | ||
33 | + os.putString('$objser $objgen obj\n'); | ||
34 | + value.output(os, verbose ? 0 : null); | ||
35 | + os.putByte(0x0a); | ||
36 | + os.putString('endobj\n'); | ||
37 | + } | ||
38 | +} | ||
39 | + | ||
22 | void main() { | 40 | void main() { |
23 | test('Pdf Minimal', () async { | 41 | test('Pdf Minimal', () async { |
24 | - final pdf = PdfDocument(compress: false); | ||
25 | - final page = PdfPage(pdf, pageFormat: PdfPageFormat.a4); | 42 | + final pages = PdfDict({ |
43 | + '/Type': const PdfName('/Pages'), | ||
44 | + '/Count': const PdfNum(1), | ||
45 | + }); | ||
46 | + | ||
47 | + final page = PdfDict({ | ||
48 | + '/Type': const PdfName('/Page'), | ||
49 | + '/Parent': const PdfIndirect(2, 0), | ||
50 | + '/MediaBox': PdfArray.fromNum([0, 0, 595.27559, 841.88976]), | ||
51 | + '/Resources': PdfDict({ | ||
52 | + '/ProcSet': PdfArray([ | ||
53 | + const PdfName('/PDF'), | ||
54 | + ]), | ||
55 | + }), | ||
56 | + '/Contents': const PdfIndirect(4, 0), | ||
57 | + }); | ||
58 | + | ||
59 | + final content = PdfDictStream( | ||
60 | + object: const BasicObject(1), | ||
61 | + data: latin1.encode('30 811.88976 m 200 641.88976 l S'), | ||
62 | + ); | ||
63 | + | ||
64 | + pages['/Kids'] = PdfArray([const PdfIndirect(3, 0)]); | ||
65 | + | ||
66 | + final catalog = PdfDict({ | ||
67 | + '/Type': const PdfName('/Catalog'), | ||
68 | + '/Pages': const PdfIndirect(2, 0), | ||
69 | + }); | ||
70 | + | ||
71 | + final os = PdfStream(); | ||
72 | + | ||
73 | + final xref = PdfXrefTable(); | ||
74 | + | ||
75 | + os.putString('%PDF-1.4\n'); | ||
76 | + os.putBytes(const <int>[0x25, 0xC2, 0xA5, 0xC2, 0xB1, 0xC3, 0xAB, 0x0A]); | ||
77 | + | ||
78 | + xref.add(PdfXref(1, os.offset)); | ||
79 | + final cat = const BasicObject(1)..write(os, catalog); | ||
80 | + xref.add(PdfXref(2, os.offset)); | ||
81 | + const BasicObject(2).write(os, pages); | ||
82 | + xref.add(PdfXref(3, os.offset)); | ||
83 | + const BasicObject(3).write(os, page); | ||
84 | + xref.add(PdfXref(4, os.offset)); | ||
85 | + const BasicObject(4).write(os, content); | ||
86 | + | ||
87 | + final xrefOffset = xref.outputLegacy( | ||
88 | + cat, | ||
89 | + os, | ||
90 | + PdfDict({ | ||
91 | + '/Size': PdfNum(xref.offsets.length + 1), | ||
92 | + '/Root': const PdfIndirect(1, 0), | ||
93 | + })); | ||
26 | 94 | ||
27 | - final g = page.getGraphics(); | ||
28 | - g.drawLine( | ||
29 | - 30, page.pageFormat.height - 30.0, 200, page.pageFormat.height - 200.0); | ||
30 | - g.strokePath(); | 95 | + os.putString('startxref\n$xrefOffset\n%%EOF\n'); |
31 | 96 | ||
32 | final file = File('minimal.pdf'); | 97 | final file = File('minimal.pdf'); |
33 | - await file.writeAsBytes(await pdf.save()); | 98 | + await file.writeAsBytes(os.output()); |
34 | }); | 99 | }); |
35 | } | 100 | } |
-
Please register or login to post a comment