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