Showing
4 changed files
with
107 additions
and
100 deletions
| @@ -24,7 +24,7 @@ abstract class PdfDataType { | @@ -24,7 +24,7 @@ abstract class PdfDataType { | ||
| 24 | 24 | ||
| 25 | void output(PdfStream s); | 25 | void output(PdfStream s); |
| 26 | 26 | ||
| 27 | - PdfStream toStream() { | 27 | + PdfStream _toStream() { |
| 28 | final PdfStream s = PdfStream(); | 28 | final PdfStream s = PdfStream(); |
| 29 | output(s); | 29 | output(s); |
| 30 | return s; | 30 | return s; |
| @@ -32,11 +32,12 @@ abstract class PdfDataType { | @@ -32,11 +32,12 @@ abstract class PdfDataType { | ||
| 32 | 32 | ||
| 33 | @override | 33 | @override |
| 34 | String toString() { | 34 | String toString() { |
| 35 | - return String.fromCharCodes(toStream().output()); | 35 | + return String.fromCharCodes(_toStream().output()); |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | + @visibleForTesting | ||
| 38 | Uint8List toList() { | 39 | Uint8List toList() { |
| 39 | - return toStream().output(); | 40 | + return _toStream().output(); |
| 40 | } | 41 | } |
| 41 | } | 42 | } |
| 42 | 43 | ||
| @@ -52,7 +53,13 @@ class PdfBool extends PdfDataType { | @@ -52,7 +53,13 @@ class PdfBool extends PdfDataType { | ||
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | class PdfNum extends PdfDataType { | 55 | class PdfNum extends PdfDataType { |
| 55 | - const PdfNum(this.value); | 56 | + const PdfNum(this.value) |
| 57 | + : assert(value != null), | ||
| 58 | + assert(value != double.infinity), | ||
| 59 | + assert(value != double.nan), | ||
| 60 | + assert(value != double.negativeInfinity); | ||
| 61 | + | ||
| 62 | + static const int precision = 5; | ||
| 56 | 63 | ||
| 57 | final num value; | 64 | final num value; |
| 58 | 65 | ||
| @@ -61,7 +68,23 @@ class PdfNum extends PdfDataType { | @@ -61,7 +68,23 @@ class PdfNum extends PdfDataType { | ||
| 61 | if (value is int) { | 68 | if (value is int) { |
| 62 | s.putString(value.toInt().toString()); | 69 | s.putString(value.toInt().toString()); |
| 63 | } else { | 70 | } else { |
| 64 | - s.putNum(value); | 71 | + s.putString(value.toStringAsFixed(precision)); |
| 72 | + } | ||
| 73 | + } | ||
| 74 | +} | ||
| 75 | + | ||
| 76 | +class PdfNumList extends PdfDataType { | ||
| 77 | + PdfNumList(this.values) : assert(values != null); | ||
| 78 | + | ||
| 79 | + final List<num> values; | ||
| 80 | + | ||
| 81 | + @override | ||
| 82 | + void output(PdfStream s) { | ||
| 83 | + for (int n = 0; n < values.length; n++) { | ||
| 84 | + if (n > 0) { | ||
| 85 | + s.putByte(0x20); | ||
| 86 | + } | ||
| 87 | + PdfNum(values[n]).output(s); | ||
| 65 | } | 88 | } |
| 66 | } | 89 | } |
| 67 | } | 90 | } |
| @@ -102,6 +125,49 @@ class PdfString extends PdfDataType { | @@ -102,6 +125,49 @@ class PdfString extends PdfDataType { | ||
| 102 | return _string('D:$year$month$day$hour$minute${second}Z'); | 125 | return _string('D:$year$month$day$hour$minute${second}Z'); |
| 103 | } | 126 | } |
| 104 | 127 | ||
| 128 | + /// Escape special characters | ||
| 129 | + /// \ddd Character code ddd (octal) | ||
| 130 | + void _putTextBytes(PdfStream s, List<int> b) { | ||
| 131 | + for (int c in b) { | ||
| 132 | + switch (c) { | ||
| 133 | + case 0x0a: // \n Line feed (LF) | ||
| 134 | + s.putByte(0x5c); | ||
| 135 | + s.putByte(0x6e); | ||
| 136 | + break; | ||
| 137 | + case 0x0d: // \r Carriage return (CR) | ||
| 138 | + s.putByte(0x5c); | ||
| 139 | + s.putByte(0x72); | ||
| 140 | + break; | ||
| 141 | + case 0x09: // \t Horizontal tab (HT) | ||
| 142 | + s.putByte(0x5c); | ||
| 143 | + s.putByte(0x74); | ||
| 144 | + break; | ||
| 145 | + case 0x08: // \b Backspace (BS) | ||
| 146 | + s.putByte(0x5c); | ||
| 147 | + s.putByte(0x62); | ||
| 148 | + break; | ||
| 149 | + case 0x0c: // \f Form feed (FF) | ||
| 150 | + s.putByte(0x5c); | ||
| 151 | + s.putByte(0x66); | ||
| 152 | + break; | ||
| 153 | + case 0x28: // \( Left parenthesis | ||
| 154 | + s.putByte(0x5c); | ||
| 155 | + s.putByte(0x28); | ||
| 156 | + break; | ||
| 157 | + case 0x29: // \) Right parenthesis | ||
| 158 | + s.putByte(0x5c); | ||
| 159 | + s.putByte(0x29); | ||
| 160 | + break; | ||
| 161 | + case 0x5c: // \\ Backslash | ||
| 162 | + s.putByte(0x5c); | ||
| 163 | + s.putByte(0x5c); | ||
| 164 | + break; | ||
| 165 | + default: | ||
| 166 | + s.putByte(c); | ||
| 167 | + } | ||
| 168 | + } | ||
| 169 | + } | ||
| 170 | + | ||
| 105 | /// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit | 171 | /// Returns the ASCII/Unicode code unit corresponding to the hexadecimal digit |
| 106 | /// [digit]. | 172 | /// [digit]. |
| 107 | int _codeUnitForDigit(int digit) => | 173 | int _codeUnitForDigit(int digit) => |
| @@ -116,11 +182,10 @@ class PdfString extends PdfDataType { | @@ -116,11 +182,10 @@ class PdfString extends PdfDataType { | ||
| 116 | s.putByte(_codeUnitForDigit(byte & 0x0F)); | 182 | s.putByte(_codeUnitForDigit(byte & 0x0F)); |
| 117 | } | 183 | } |
| 118 | s.putByte(0x3e); | 184 | s.putByte(0x3e); |
| 119 | - | ||
| 120 | break; | 185 | break; |
| 121 | case PdfStringFormat.litteral: | 186 | case PdfStringFormat.litteral: |
| 122 | s.putByte(40); | 187 | s.putByte(40); |
| 123 | - s.putTextBytes(value); | 188 | + _putTextBytes(s, value); |
| 124 | s.putByte(41); | 189 | s.putByte(41); |
| 125 | break; | 190 | break; |
| 126 | } | 191 | } |
| @@ -172,10 +172,7 @@ See https://github.com/DavBfr/dart_pdf/wiki/Fonts-Management | @@ -172,10 +172,7 @@ See https://github.com/DavBfr/dart_pdf/wiki/Fonts-Management | ||
| 172 | 172 | ||
| 173 | void putText(PdfStream stream, String text) { | 173 | void putText(PdfStream stream, String text) { |
| 174 | try { | 174 | try { |
| 175 | - stream | ||
| 176 | - ..putByte(40) | ||
| 177 | - ..putTextBytes(latin1.encode(text)) | ||
| 178 | - ..putByte(41); | 175 | + PdfString(latin1.encode(text), PdfStringFormat.litteral).output(stream); |
| 179 | } catch (_) { | 176 | } catch (_) { |
| 180 | assert(() { | 177 | assert(() { |
| 181 | print(_cannotDecodeMessage); | 178 | print(_cannotDecodeMessage); |
| @@ -138,28 +138,28 @@ class PdfGraphics { | @@ -138,28 +138,28 @@ class PdfGraphics { | ||
| 138 | buf.putString('q '); | 138 | buf.putString('q '); |
| 139 | switch (img.orientation) { | 139 | switch (img.orientation) { |
| 140 | case PdfImageOrientation.topLeft: | 140 | case PdfImageOrientation.topLeft: |
| 141 | - buf.putNumList(<double>[w, 0, 0, h, x, y]); | 141 | + PdfNumList(<double>[w, 0, 0, h, x, y]).output(buf); |
| 142 | break; | 142 | break; |
| 143 | case PdfImageOrientation.topRight: | 143 | case PdfImageOrientation.topRight: |
| 144 | - buf.putNumList(<double>[-w, 0, 0, h, w + x, y]); | 144 | + PdfNumList(<double>[-w, 0, 0, h, w + x, y]).output(buf); |
| 145 | break; | 145 | break; |
| 146 | case PdfImageOrientation.bottomRight: | 146 | case PdfImageOrientation.bottomRight: |
| 147 | - buf.putNumList(<double>[-w, 0, 0, -h, w + x, h + y]); | 147 | + PdfNumList(<double>[-w, 0, 0, -h, w + x, h + y]).output(buf); |
| 148 | break; | 148 | break; |
| 149 | case PdfImageOrientation.bottomLeft: | 149 | case PdfImageOrientation.bottomLeft: |
| 150 | - buf.putNumList(<double>[w, 0, 0, -h, x, h + y]); | 150 | + PdfNumList(<double>[w, 0, 0, -h, x, h + y]).output(buf); |
| 151 | break; | 151 | break; |
| 152 | case PdfImageOrientation.leftTop: | 152 | case PdfImageOrientation.leftTop: |
| 153 | - buf.putNumList(<double>[0, -h, -w, 0, w + x, h + y]); | 153 | + PdfNumList(<double>[0, -h, -w, 0, w + x, h + y]).output(buf); |
| 154 | break; | 154 | break; |
| 155 | case PdfImageOrientation.rightTop: | 155 | case PdfImageOrientation.rightTop: |
| 156 | - buf.putNumList(<double>[0, -h, w, 0, x, h + y]); | 156 | + PdfNumList(<double>[0, -h, w, 0, x, h + y]).output(buf); |
| 157 | break; | 157 | break; |
| 158 | case PdfImageOrientation.rightBottom: | 158 | case PdfImageOrientation.rightBottom: |
| 159 | - buf.putNumList(<double>[0, h, w, 0, x, y]); | 159 | + PdfNumList(<double>[0, h, w, 0, x, y]).output(buf); |
| 160 | break; | 160 | break; |
| 161 | case PdfImageOrientation.leftBottom: | 161 | case PdfImageOrientation.leftBottom: |
| 162 | - buf.putNumList(<double>[0, h, -w, 0, w + x, y]); | 162 | + PdfNumList(<double>[0, h, -w, 0, w + x, y]).output(buf); |
| 163 | break; | 163 | break; |
| 164 | } | 164 | } |
| 165 | 165 | ||
| @@ -200,7 +200,7 @@ class PdfGraphics { | @@ -200,7 +200,7 @@ class PdfGraphics { | ||
| 200 | double w, | 200 | double w, |
| 201 | double h, | 201 | double h, |
| 202 | ) { | 202 | ) { |
| 203 | - buf.putNumList(<double>[x, y, w, h]); | 203 | + PdfNumList(<double>[x, y, w, h]).output(buf); |
| 204 | buf.putString(' re\n'); | 204 | buf.putString(' re\n'); |
| 205 | } | 205 | } |
| 206 | 206 | ||
| @@ -247,24 +247,24 @@ class PdfGraphics { | @@ -247,24 +247,24 @@ class PdfGraphics { | ||
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | buf.putString('BT '); | 249 | buf.putString('BT '); |
| 250 | - buf.putNumList(<double>[x, y]); | 250 | + PdfNumList(<double>[x, y]).output(buf); |
| 251 | buf.putString(' Td ${font.name} '); | 251 | buf.putString(' Td ${font.name} '); |
| 252 | - buf.putNum(size); | 252 | + PdfNum(size).output(buf); |
| 253 | buf.putString(' Tf '); | 253 | buf.putString(' Tf '); |
| 254 | if (charSpace != 0) { | 254 | if (charSpace != 0) { |
| 255 | - buf.putNum(charSpace); | 255 | + PdfNum(charSpace).output(buf); |
| 256 | buf.putString(' Tc '); | 256 | buf.putString(' Tc '); |
| 257 | } | 257 | } |
| 258 | if (wordSpace != 0) { | 258 | if (wordSpace != 0) { |
| 259 | - buf.putNum(wordSpace); | 259 | + PdfNum(wordSpace).output(buf); |
| 260 | buf.putString(' Tw '); | 260 | buf.putString(' Tw '); |
| 261 | } | 261 | } |
| 262 | if (scale != 1) { | 262 | if (scale != 1) { |
| 263 | - buf.putNum(scale * 100); | 263 | + PdfNum(scale * 100).output(buf); |
| 264 | buf.putString(' Tz '); | 264 | buf.putString(' Tz '); |
| 265 | } | 265 | } |
| 266 | if (rise != 0) { | 266 | if (rise != 0) { |
| 267 | - buf.putNum(rise); | 267 | + PdfNum(rise).output(buf); |
| 268 | buf.putString(' Ts '); | 268 | buf.putString(' Ts '); |
| 269 | } | 269 | } |
| 270 | if (mode != PdfTextRenderingMode.fill) { | 270 | if (mode != PdfTextRenderingMode.fill) { |
| @@ -288,11 +288,11 @@ class PdfGraphics { | @@ -288,11 +288,11 @@ class PdfGraphics { | ||
| 288 | /// @param c Color to use | 288 | /// @param c Color to use |
| 289 | void setFillColor(PdfColor color) { | 289 | void setFillColor(PdfColor color) { |
| 290 | if (color is PdfColorCmyk) { | 290 | if (color is PdfColorCmyk) { |
| 291 | - buf.putNumList( | ||
| 292 | - <double>[color.cyan, color.magenta, color.yellow, color.black]); | 291 | + PdfNumList(<double>[color.cyan, color.magenta, color.yellow, color.black]) |
| 292 | + .output(buf); | ||
| 293 | buf.putString(' k\n'); | 293 | buf.putString(' k\n'); |
| 294 | } else { | 294 | } else { |
| 295 | - buf.putNumList(<double>[color.red, color.green, color.blue]); | 295 | + PdfNumList(<double>[color.red, color.green, color.blue]).output(buf); |
| 296 | buf.putString(' rg\n'); | 296 | buf.putString(' rg\n'); |
| 297 | } | 297 | } |
| 298 | } | 298 | } |
| @@ -302,11 +302,11 @@ class PdfGraphics { | @@ -302,11 +302,11 @@ class PdfGraphics { | ||
| 302 | /// @param c Color to use | 302 | /// @param c Color to use |
| 303 | void setStrokeColor(PdfColor color) { | 303 | void setStrokeColor(PdfColor color) { |
| 304 | if (color is PdfColorCmyk) { | 304 | if (color is PdfColorCmyk) { |
| 305 | - buf.putNumList( | ||
| 306 | - <double>[color.cyan, color.magenta, color.yellow, color.black]); | 305 | + PdfNumList(<double>[color.cyan, color.magenta, color.yellow, color.black]) |
| 306 | + .output(buf); | ||
| 307 | buf.putString(' K\n'); | 307 | buf.putString(' K\n'); |
| 308 | } else { | 308 | } else { |
| 309 | - buf.putNumList(<double>[color.red, color.green, color.blue]); | 309 | + PdfNumList(<double>[color.red, color.green, color.blue]).output(buf); |
| 310 | buf.putString(' RG\n'); | 310 | buf.putString(' RG\n'); |
| 311 | } | 311 | } |
| 312 | } | 312 | } |
| @@ -320,7 +320,7 @@ class PdfGraphics { | @@ -320,7 +320,7 @@ class PdfGraphics { | ||
| 320 | /// Set the transformation Matrix | 320 | /// Set the transformation Matrix |
| 321 | void setTransform(Matrix4 t) { | 321 | void setTransform(Matrix4 t) { |
| 322 | final Float64List s = t.storage; | 322 | final Float64List s = t.storage; |
| 323 | - buf.putNumList(<double>[s[0], s[1], s[4], s[5], s[12], s[13]]); | 323 | + PdfNumList(<double>[s[0], s[1], s[4], s[5], s[12], s[13]]).output(buf); |
| 324 | buf.putString(' cm\n'); | 324 | buf.putString(' cm\n'); |
| 325 | _context.ctm.multiply(t); | 325 | _context.ctm.multiply(t); |
| 326 | } | 326 | } |
| @@ -335,7 +335,7 @@ class PdfGraphics { | @@ -335,7 +335,7 @@ class PdfGraphics { | ||
| 335 | /// @param x coordinate | 335 | /// @param x coordinate |
| 336 | /// @param y coordinate | 336 | /// @param y coordinate |
| 337 | void lineTo(double x, double y) { | 337 | void lineTo(double x, double y) { |
| 338 | - buf.putNumList(<double>[x, y]); | 338 | + PdfNumList(<double>[x, y]).output(buf); |
| 339 | buf.putString(' l\n'); | 339 | buf.putString(' l\n'); |
| 340 | } | 340 | } |
| 341 | 341 | ||
| @@ -344,7 +344,7 @@ class PdfGraphics { | @@ -344,7 +344,7 @@ class PdfGraphics { | ||
| 344 | /// @param x coordinate | 344 | /// @param x coordinate |
| 345 | /// @param y coordinate | 345 | /// @param y coordinate |
| 346 | void moveTo(double x, double y) { | 346 | void moveTo(double x, double y) { |
| 347 | - buf.putNumList(<double>[x, y]); | 347 | + PdfNumList(<double>[x, y]).output(buf); |
| 348 | buf.putString(' m\n'); | 348 | buf.putString(' m\n'); |
| 349 | } | 349 | } |
| 350 | 350 | ||
| @@ -360,7 +360,7 @@ class PdfGraphics { | @@ -360,7 +360,7 @@ class PdfGraphics { | ||
| 360 | /// @param y3 end point | 360 | /// @param y3 end point |
| 361 | void curveTo( | 361 | void curveTo( |
| 362 | double x1, double y1, double x2, double y2, double x3, double y3) { | 362 | double x1, double y1, double x2, double y2, double x3, double y3) { |
| 363 | - buf.putNumList(<double>[x1, y1, x2, y2, x3, y3]); | 363 | + PdfNumList(<double>[x1, y1, x2, y2, x3, y3]).output(buf); |
| 364 | buf.putString(' c\n'); | 364 | buf.putString(' c\n'); |
| 365 | } | 365 | } |
| 366 | 366 | ||
| @@ -685,12 +685,12 @@ class PdfGraphics { | @@ -685,12 +685,12 @@ class PdfGraphics { | ||
| 685 | } | 685 | } |
| 686 | 686 | ||
| 687 | void setLineWidth(double width) { | 687 | void setLineWidth(double width) { |
| 688 | - buf.putNum(width); | 688 | + PdfNum(width).output(buf); |
| 689 | buf.putString(' w\n'); | 689 | buf.putString(' w\n'); |
| 690 | } | 690 | } |
| 691 | 691 | ||
| 692 | void setMiterLimit(double limit) { | 692 | void setMiterLimit(double limit) { |
| 693 | - buf.putNum(limit); | 693 | + PdfNum(limit).output(buf); |
| 694 | buf.putString(' M\n'); | 694 | buf.putString(' M\n'); |
| 695 | } | 695 | } |
| 696 | } | 696 | } |
| @@ -19,8 +19,6 @@ | @@ -19,8 +19,6 @@ | ||
| 19 | part of pdf; | 19 | part of pdf; |
| 20 | 20 | ||
| 21 | class PdfStream { | 21 | class PdfStream { |
| 22 | - static const int precision = 5; | ||
| 23 | - | ||
| 24 | static const int _grow = 65536; | 22 | static const int _grow = 65536; |
| 25 | 23 | ||
| 26 | Uint8List _stream = Uint8List(_grow); | 24 | Uint8List _stream = Uint8List(_grow); |
| @@ -62,67 +60,14 @@ class PdfStream { | @@ -62,67 +60,14 @@ class PdfStream { | ||
| 62 | Uint8List output() => _stream.sublist(0, _offset); | 60 | Uint8List output() => _stream.sublist(0, _offset); |
| 63 | 61 | ||
| 64 | void putString(String s) { | 62 | void putString(String s) { |
| 65 | - for (int codeUnit in s.codeUnits) { | ||
| 66 | - if (codeUnit <= 0x7f) { | ||
| 67 | - putByte(codeUnit); | ||
| 68 | - } else { | ||
| 69 | - putByte(0x20); | ||
| 70 | - } | ||
| 71 | - } | ||
| 72 | - } | ||
| 73 | - | ||
| 74 | - void putNum(double d) { | ||
| 75 | - assert(d != double.infinity); | ||
| 76 | - putString(d.toStringAsFixed(precision)); | ||
| 77 | - } | ||
| 78 | - | ||
| 79 | - void putNumList(List<double> d) { | ||
| 80 | - putString(d.map((double v) { | ||
| 81 | - assert(v != double.infinity); | ||
| 82 | - return v.toStringAsFixed(precision); | ||
| 83 | - }).join(' ')); | ||
| 84 | - } | ||
| 85 | - | ||
| 86 | - /// Escape special characters | ||
| 87 | - /// \ddd Character code ddd (octal) | ||
| 88 | - void putTextBytes(List<int> s) { | ||
| 89 | - for (int c in s) { | ||
| 90 | - switch (c) { | ||
| 91 | - case 0x0a: // \n Line feed (LF) | ||
| 92 | - putByte(0x5c); | ||
| 93 | - putByte(0x6e); | ||
| 94 | - break; | ||
| 95 | - case 0x0d: // \r Carriage return (CR) | ||
| 96 | - putByte(0x5c); | ||
| 97 | - putByte(0x72); | ||
| 98 | - break; | ||
| 99 | - case 0x09: // \t Horizontal tab (HT) | ||
| 100 | - putByte(0x5c); | ||
| 101 | - putByte(0x74); | ||
| 102 | - break; | ||
| 103 | - case 0x08: // \b Backspace (BS) | ||
| 104 | - putByte(0x5c); | ||
| 105 | - putByte(0x62); | ||
| 106 | - break; | ||
| 107 | - case 0x0c: // \f Form feed (FF) | ||
| 108 | - putByte(0x5c); | ||
| 109 | - putByte(0x66); | ||
| 110 | - break; | ||
| 111 | - case 0x28: // \( Left parenthesis | ||
| 112 | - putByte(0x5c); | ||
| 113 | - putByte(0x28); | ||
| 114 | - break; | ||
| 115 | - case 0x29: // \) Right parenthesis | ||
| 116 | - putByte(0x5c); | ||
| 117 | - putByte(0x29); | ||
| 118 | - break; | ||
| 119 | - case 0x5c: // \\ Backslash | ||
| 120 | - putByte(0x5c); | ||
| 121 | - putByte(0x5c); | ||
| 122 | - break; | ||
| 123 | - default: | ||
| 124 | - putByte(c); | 63 | + assert(() { |
| 64 | + for (final int codeUnit in s.codeUnits) { | ||
| 65 | + if (codeUnit > 0x7f) { | ||
| 66 | + return false; | ||
| 125 | } | 67 | } |
| 126 | } | 68 | } |
| 69 | + return true; | ||
| 70 | + }()); | ||
| 71 | + putBytes(s.codeUnits); | ||
| 127 | } | 72 | } |
| 128 | } | 73 | } |
-
Please register or login to post a comment