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