David PHAM-VAN

Improve verbose output

@@ -107,6 +107,10 @@ class PdfGraphics { @@ -107,6 +107,10 @@ class PdfGraphics {
107 /// Ellipse 4-spline magic number 107 /// Ellipse 4-spline magic number
108 static const double _m4 = 0.551784; 108 static const double _m4 = 0.551784;
109 109
  110 + static const int _commentIndent = 35;
  111 + static const int _indentAmount = 2;
  112 + int _indent = _indentAmount;
  113 +
110 /// Graphic context 114 /// Graphic context
111 late _PdfGraphicsContext _context; 115 late _PdfGraphicsContext _context;
112 final Queue<_PdfGraphicsContext> _contextQueue = Queue<_PdfGraphicsContext>(); 116 final Queue<_PdfGraphicsContext> _contextQueue = Queue<_PdfGraphicsContext>();
@@ -122,78 +126,136 @@ class PdfGraphics { @@ -122,78 +126,136 @@ class PdfGraphics {
122 /// Draw a surface on the previously defined shape 126 /// Draw a surface on the previously defined shape
123 /// set evenOdd to false to use the nonzero winding number rule to determine the region to fill and to true to use the even-odd rule to determine the region to fill 127 /// set evenOdd to false to use the nonzero winding number rule to determine the region to fill and to true to use the even-odd rule to determine the region to fill
124 void fillPath({bool evenOdd = false}) { 128 void fillPath({bool evenOdd = false}) {
  129 + var o = 0;
125 assert(() { 130 assert(() {
126 if (_page.pdfDocument.verbose) { 131 if (_page.pdfDocument.verbose) {
127 - _buf.putComment('fillPath evenOdd:$evenOdd'); 132 + o = _buf.offset;
  133 + _buf.putString(' ' * (_indent));
128 } 134 }
129 return true; 135 return true;
130 }()); 136 }());
131 137
132 - _buf.putString('f${evenOdd ? '*' : ''}\n'); 138 + _buf.putString('f${evenOdd ? '*' : ''} ');
  139 +
  140 + assert(() {
  141 + if (_page.pdfDocument.verbose) {
  142 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  143 + _buf.putComment('fillPath(evenOdd: $evenOdd)');
  144 + }
  145 + return true;
  146 + }());
133 } 147 }
134 148
135 /// Draw the contour of the previously defined shape 149 /// Draw the contour of the previously defined shape
136 void strokePath({bool close = false}) { 150 void strokePath({bool close = false}) {
  151 + var o = 0;
137 assert(() { 152 assert(() {
138 if (_page.pdfDocument.verbose) { 153 if (_page.pdfDocument.verbose) {
139 - _buf.putComment('strokePath close:$close'); 154 + o = _buf.offset;
  155 + _buf.putString(' ' * (_indent));
140 } 156 }
141 return true; 157 return true;
142 }()); 158 }());
143 159
144 - _buf.putString('${close ? 's' : 'S'}\n'); 160 + _buf.putString('${close ? 's' : 'S'} ');
  161 +
  162 + assert(() {
  163 + if (_page.pdfDocument.verbose) {
  164 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  165 + _buf.putComment('strokePath(close: $close)');
  166 + }
  167 + return true;
  168 + }());
145 } 169 }
146 170
147 /// Close the path with a line 171 /// Close the path with a line
148 void closePath() { 172 void closePath() {
149 assert(() { 173 assert(() {
150 if (_page.pdfDocument.verbose) { 174 if (_page.pdfDocument.verbose) {
151 - _buf.putComment('closePath'); 175 + _buf.putString(' ' * (_indent));
152 } 176 }
153 return true; 177 return true;
154 }()); 178 }());
155 179
156 - _buf.putString('h\n'); 180 + _buf.putString('h ');
  181 +
  182 + assert(() {
  183 + if (_page.pdfDocument.verbose) {
  184 + _buf.putString(' ' * (_commentIndent - 2 - _indent));
  185 + _buf.putComment('closePath()');
  186 + }
  187 + return true;
  188 + }());
157 } 189 }
158 190
159 /// Create a clipping surface from the previously defined shape, 191 /// Create a clipping surface from the previously defined shape,
160 /// to prevent any further drawing outside 192 /// to prevent any further drawing outside
161 void clipPath({bool evenOdd = false, bool end = true}) { 193 void clipPath({bool evenOdd = false, bool end = true}) {
  194 + var o = 0;
162 assert(() { 195 assert(() {
163 if (_page.pdfDocument.verbose) { 196 if (_page.pdfDocument.verbose) {
164 - _buf.putComment('clipPath evenOdd:$evenOdd end:$end'); 197 + o = _buf.offset;
  198 + _buf.putString(' ' * (_indent));
165 } 199 }
166 return true; 200 return true;
167 }()); 201 }());
168 202
169 - _buf.putString('W${evenOdd ? '*' : ''}${end ? ' n' : ''}\n'); 203 + _buf.putString('W${evenOdd ? '*' : ''}${end ? ' n' : ''} ');
  204 +
  205 + assert(() {
  206 + if (_page.pdfDocument.verbose) {
  207 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  208 + _buf.putComment('clipPath(evenOdd: $evenOdd, end: $end)');
  209 + }
  210 + return true;
  211 + }());
170 } 212 }
171 213
172 /// Draw a surface on the previously defined shape and then draw the contour 214 /// Draw a surface on the previously defined shape and then draw the contour
173 /// set evenOdd to false to use the nonzero winding number rule to determine the region to fill and to true to use the even-odd rule to determine the region to fill 215 /// set evenOdd to false to use the nonzero winding number rule to determine the region to fill and to true to use the even-odd rule to determine the region to fill
174 void fillAndStrokePath({bool evenOdd = false, bool close = false}) { 216 void fillAndStrokePath({bool evenOdd = false, bool close = false}) {
  217 + var o = 0;
175 assert(() { 218 assert(() {
176 if (_page.pdfDocument.verbose) { 219 if (_page.pdfDocument.verbose) {
177 - _buf.putComment('fillAndStrokePath evenOdd:$evenOdd close:$close'); 220 + o = _buf.offset;
  221 + _buf.putString(' ' * (_indent));
178 } 222 }
179 return true; 223 return true;
180 }()); 224 }());
181 225
182 - _buf.putString('${close ? 'b' : 'B'}${evenOdd ? '*' : ''}\n'); 226 + _buf.putString('${close ? 'b' : 'B'}${evenOdd ? '*' : ''} ');
  227 +
  228 + assert(() {
  229 + if (_page.pdfDocument.verbose) {
  230 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  231 + _buf.putComment('fillAndStrokePath(evenOdd:$evenOdd, close:$close)');
  232 + }
  233 + return true;
  234 + }());
183 } 235 }
184 236
185 /// Apply a shader 237 /// Apply a shader
186 void applyShader(PdfShading shader) { 238 void applyShader(PdfShading shader) {
  239 + var o = 0;
187 assert(() { 240 assert(() {
188 if (_page.pdfDocument.verbose) { 241 if (_page.pdfDocument.verbose) {
189 - _buf.putComment('applyShader'); 242 + o = _buf.offset;
  243 + _buf.putString(' ' * (_indent));
190 } 244 }
191 return true; 245 return true;
192 }()); 246 }());
193 247
194 // The shader needs to be registered in the page resources 248 // The shader needs to be registered in the page resources
195 _page.addShader(shader); 249 _page.addShader(shader);
196 - _buf.putString('${shader.name} sh\n'); 250 + _buf.putString('${shader.name} sh ');
  251 +
  252 + assert(() {
  253 + if (_page.pdfDocument.verbose) {
  254 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  255 + _buf.putComment('applyShader(${shader.ref()})');
  256 + }
  257 + return true;
  258 + }());
197 } 259 }
198 260
199 /// This releases any resources used by this Graphics object. You must use 261 /// This releases any resources used by this Graphics object. You must use
@@ -202,17 +264,26 @@ class PdfGraphics { @@ -202,17 +264,26 @@ class PdfGraphics {
202 /// When using [PdfPage], you can create another fresh Graphics instance, 264 /// When using [PdfPage], you can create another fresh Graphics instance,
203 /// which will draw over this one. 265 /// which will draw over this one.
204 void restoreContext() { 266 void restoreContext() {
  267 + if (_contextQueue.isNotEmpty) {
205 assert(() { 268 assert(() {
  269 + _indent -= _indentAmount;
206 if (_page.pdfDocument.verbose) { 270 if (_page.pdfDocument.verbose) {
207 - _buf.putComment('restoreContext'); 271 + _buf.putString(' ' * (_indent));
208 } 272 }
209 return true; 273 return true;
210 }()); 274 }());
211 275
212 - if (_contextQueue.isNotEmpty) {  
213 // restore graphics context 276 // restore graphics context
214 - _buf.putString('Q\n'); 277 + _buf.putString('Q ');
215 _context = _contextQueue.removeLast(); 278 _context = _contextQueue.removeLast();
  279 +
  280 + assert(() {
  281 + if (_page.pdfDocument.verbose) {
  282 + _buf.putString(' ' * (_commentIndent - 2 - _indent));
  283 + _buf.putComment('restoreContext()');
  284 + }
  285 + return true;
  286 + }());
216 } 287 }
217 } 288 }
218 289
@@ -220,20 +291,29 @@ class PdfGraphics { @@ -220,20 +291,29 @@ class PdfGraphics {
220 void saveContext() { 291 void saveContext() {
221 assert(() { 292 assert(() {
222 if (_page.pdfDocument.verbose) { 293 if (_page.pdfDocument.verbose) {
223 - _buf.putComment('saveContext'); 294 + _buf.putString(' ' * (_indent));
224 } 295 }
225 return true; 296 return true;
226 }()); 297 }());
227 -  
228 - _buf.putString('q\n'); 298 + _buf.putString('q ');
229 _contextQueue.addLast(_context.copy()); 299 _contextQueue.addLast(_context.copy());
  300 + assert(() {
  301 + if (_page.pdfDocument.verbose) {
  302 + _buf.putString(' ' * (_commentIndent - 2 - _indent));
  303 + _buf.putComment('saveContext()');
  304 + }
  305 + _indent += _indentAmount;
  306 + return true;
  307 + }());
230 } 308 }
231 309
232 /// Draws an image onto the page. 310 /// Draws an image onto the page.
233 void drawImage(PdfImage img, double x, double y, [double? w, double? h]) { 311 void drawImage(PdfImage img, double x, double y, [double? w, double? h]) {
  312 + var o = 0;
234 assert(() { 313 assert(() {
235 if (_page.pdfDocument.verbose) { 314 if (_page.pdfDocument.verbose) {
236 - _buf.putComment('drawImage x:$x y:$y'); 315 + o = _buf.offset;
  316 + _buf.putString(' ' * (_indent));
237 } 317 }
238 return true; 318 return true;
239 }()); 319 }());
@@ -273,18 +353,20 @@ class PdfGraphics { @@ -273,18 +353,20 @@ class PdfGraphics {
273 break; 353 break;
274 } 354 }
275 355
276 - _buf.putString(' cm ${img.name} Do Q\n'); 356 + _buf.putString(' cm ${img.name} Do Q ');
277 } 357 }
278 358
279 - /// Draws a line between two coordinates.  
280 - void drawLine(double x1, double y1, double x2, double y2) {  
281 assert(() { 359 assert(() {
282 if (_page.pdfDocument.verbose) { 360 if (_page.pdfDocument.verbose) {
283 - _buf.putComment('drawLine x1:$x1 y1:$y1 x2:$x2 y2:$y2'); 361 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  362 + _buf.putComment('drawImage(${img.ref()}, x: $x, y: $y, w: $w, h: $h)');
284 } 363 }
285 return true; 364 return true;
286 }()); 365 }());
  366 + }
287 367
  368 + /// Draws a line between two coordinates.
  369 + void drawLine(double x1, double y1, double x2, double y2) {
288 moveTo(x1, y1); 370 moveTo(x1, y1);
289 lineTo(x2, y2); 371 lineTo(x2, y2);
290 } 372 }
@@ -294,13 +376,6 @@ class PdfGraphics { @@ -294,13 +376,6 @@ class PdfGraphics {
294 /// Use clockwise=false to draw the inside of a donut 376 /// Use clockwise=false to draw the inside of a donut
295 void drawEllipse(double x, double y, double r1, double r2, 377 void drawEllipse(double x, double y, double r1, double r2,
296 {bool clockwise = true}) { 378 {bool clockwise = true}) {
297 - assert(() {  
298 - if (_page.pdfDocument.verbose) {  
299 - _buf.putComment('drawEllipse x:$x y:$y r1:$r1 r2:$r2');  
300 - }  
301 - return true;  
302 - }());  
303 -  
304 moveTo(x, y - r2); 379 moveTo(x, y - r2);
305 if (clockwise) { 380 if (clockwise) {
306 curveTo(x + _m4 * r1, y - r2, x + r1, y - _m4 * r2, x + r1, y); 381 curveTo(x + _m4 * r1, y - r2, x + r1, y - _m4 * r2, x + r1, y);
@@ -316,21 +391,26 @@ class PdfGraphics { @@ -316,21 +391,26 @@ class PdfGraphics {
316 } 391 }
317 392
318 /// Draws a Rectangle 393 /// Draws a Rectangle
319 - void drawRect(  
320 - double x,  
321 - double y,  
322 - double w,  
323 - double h,  
324 - ) { 394 + void drawRect(double x, double y, double w, double h) {
  395 + var o = 0;
325 assert(() { 396 assert(() {
326 if (_page.pdfDocument.verbose) { 397 if (_page.pdfDocument.verbose) {
327 - _buf.putComment('drawRect x:$x y:$y w:$w h:$h'); 398 + o = _buf.offset;
  399 + _buf.putString(' ' * (_indent));
328 } 400 }
329 return true; 401 return true;
330 }()); 402 }());
331 403
332 PdfNumList([x, y, w, h]).output(_buf); 404 PdfNumList([x, y, w, h]).output(_buf);
333 - _buf.putString(' re\n'); 405 + _buf.putString(' re ');
  406 +
  407 + assert(() {
  408 + if (_page.pdfDocument.verbose) {
  409 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  410 + _buf.putComment('drawRect(x: $x, y: $y, w: $w, h: $h)');
  411 + }
  412 + return true;
  413 + }());
334 } 414 }
335 415
336 /// Draws a Rectangle 416 /// Draws a Rectangle
@@ -340,13 +420,6 @@ class PdfGraphics { @@ -340,13 +420,6 @@ class PdfGraphics {
340 420
341 /// Draws a Rounded Rectangle 421 /// Draws a Rounded Rectangle
342 void drawRRect(double x, double y, double w, double h, double rv, double rh) { 422 void drawRRect(double x, double y, double w, double h, double rv, double rh) {
343 - assert(() {  
344 - if (_page.pdfDocument.verbose) {  
345 - _buf.putComment('drawRRect x:$x y:$y w:$w h:$h rv:$rv rh:$rh');  
346 - }  
347 - return true;  
348 - }());  
349 -  
350 moveTo(x, y + rv); 423 moveTo(x, y + rv);
351 curveTo(x, y - _m4 * rv + rv, x - _m4 * rh + rh, y, x + rh, y); 424 curveTo(x, y - _m4 * rv + rv, x - _m4 * rh + rh, y, x + rh, y);
352 lineTo(x + w - rh, y); 425 lineTo(x + w - rh, y);
@@ -366,38 +439,51 @@ class PdfGraphics { @@ -366,38 +439,51 @@ class PdfGraphics {
366 double? charSpace, 439 double? charSpace,
367 double? wordSpace, 440 double? wordSpace,
368 double? scale, 441 double? scale,
369 - PdfTextRenderingMode? mode = PdfTextRenderingMode.fill, 442 + PdfTextRenderingMode mode = PdfTextRenderingMode.fill,
370 double? rise, 443 double? rise,
371 }) { 444 }) {
  445 + var o = 0;
372 assert(() { 446 assert(() {
373 if (_page.pdfDocument.verbose) { 447 if (_page.pdfDocument.verbose) {
374 - _buf.putComment('setFont'); 448 + o = _buf.offset;
  449 + _buf.putString(' ' * (_indent));
375 } 450 }
376 return true; 451 return true;
377 }()); 452 }());
378 453
  454 + _page.addFont(font);
  455 +
379 _buf.putString('${font.name} '); 456 _buf.putString('${font.name} ');
380 PdfNum(size).output(_buf); 457 PdfNum(size).output(_buf);
381 - _buf.putString(' Tf\n'); 458 + _buf.putString(' Tf ');
382 if (charSpace != null) { 459 if (charSpace != null) {
383 PdfNum(charSpace).output(_buf); 460 PdfNum(charSpace).output(_buf);
384 - _buf.putString(' Tc\n'); 461 + _buf.putString(' Tc ');
385 } 462 }
386 if (wordSpace != null) { 463 if (wordSpace != null) {
387 PdfNum(wordSpace).output(_buf); 464 PdfNum(wordSpace).output(_buf);
388 - _buf.putString(' Tw\n'); 465 + _buf.putString(' Tw ');
389 } 466 }
390 if (scale != null) { 467 if (scale != null) {
391 PdfNum(scale * 100).output(_buf); 468 PdfNum(scale * 100).output(_buf);
392 - _buf.putString(' Tz\n'); 469 + _buf.putString(' Tz ');
393 } 470 }
394 if (rise != null) { 471 if (rise != null) {
395 PdfNum(rise).output(_buf); 472 PdfNum(rise).output(_buf);
396 - _buf.putString(' Ts\n'); 473 + _buf.putString(' Ts ');
397 } 474 }
398 if (mode != PdfTextRenderingMode.fill) { 475 if (mode != PdfTextRenderingMode.fill) {
399 - _buf.putString('${mode!.index} Tr\n'); 476 + _buf.putString('${mode.index} Tr ');
  477 + }
  478 +
  479 + assert(() {
  480 + if (_page.pdfDocument.verbose) {
  481 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  482 + _buf.putComment(
  483 + 'setFont(${font.ref()}, size: $size, charSpace: $charSpace, wordSpace: $wordSpace, scale: $scale, mode: ${mode.name}, rise: $rise)');
400 } 484 }
  485 + return true;
  486 + }());
401 } 487 }
402 488
403 /// This draws a string. 489 /// This draws a string.
@@ -407,44 +493,103 @@ class PdfGraphics { @@ -407,44 +493,103 @@ class PdfGraphics {
407 String s, 493 String s,
408 double x, 494 double x,
409 double y, { 495 double y, {
410 - double charSpace = 0,  
411 - double wordSpace = 0,  
412 - double scale = 1, 496 + double? charSpace,
  497 + double? wordSpace,
  498 + double? scale,
413 PdfTextRenderingMode mode = PdfTextRenderingMode.fill, 499 PdfTextRenderingMode mode = PdfTextRenderingMode.fill,
414 - double rise = 0, 500 + double? rise,
415 }) { 501 }) {
416 assert(() { 502 assert(() {
417 if (_page.pdfDocument.verbose) { 503 if (_page.pdfDocument.verbose) {
418 - _buf.putComment('drawString x:$x y:$y size:$size "$s"'); 504 + _buf.putString(' ' * (_indent));
419 } 505 }
420 return true; 506 return true;
421 }()); 507 }());
422 508
423 - _page.addFont(font);  
424 -  
425 _buf.putString('BT '); 509 _buf.putString('BT ');
426 - PdfNumList([x, y]).output(_buf);  
427 - _buf.putString(' Td '); 510 +
  511 + assert(() {
  512 + if (_page.pdfDocument.verbose) {
  513 + _buf.putString(' ' * (_commentIndent - 3 - _indent));
  514 + _buf.putComment('beginText()');
  515 + _indent += _indentAmount;
  516 + }
  517 + return true;
  518 + }());
  519 +
428 setFont(font, size, 520 setFont(font, size,
429 charSpace: charSpace, 521 charSpace: charSpace,
430 mode: mode, 522 mode: mode,
431 rise: rise, 523 rise: rise,
432 scale: scale, 524 scale: scale,
433 wordSpace: wordSpace); 525 wordSpace: wordSpace);
  526 +
  527 + var o = 0;
  528 + assert(() {
  529 + if (_page.pdfDocument.verbose) {
  530 + o = _buf.offset;
  531 + _buf.putString(' ' * (_indent));
  532 + }
  533 + return true;
  534 + }());
  535 +
  536 + PdfNumList([x, y]).output(_buf);
  537 + _buf.putString(' Td ');
  538 +
  539 + assert(() {
  540 + if (_page.pdfDocument.verbose) {
  541 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  542 + _buf.putComment('moveCursor($x, $y)');
  543 + o = _buf.offset;
  544 + _buf.putString(' ' * (_indent));
  545 + }
  546 + return true;
  547 + }());
  548 +
434 _buf.putString('['); 549 _buf.putString('[');
435 font.putText(_buf, s); 550 font.putText(_buf, s);
436 - _buf.putString(']TJ ET\n'); 551 + _buf.putString(']TJ ');
  552 +
  553 + assert(() {
  554 + if (_page.pdfDocument.verbose) {
  555 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  556 + _buf.putComment('drawString("$s")');
  557 + o = _buf.offset;
  558 + _indent -= _indentAmount;
  559 + _buf.putString(' ' * (_indent));
  560 + }
  561 + return true;
  562 + }());
  563 +
  564 + _buf.putString('ET ');
  565 +
  566 + assert(() {
  567 + if (_page.pdfDocument.verbose) {
  568 + _buf.putString(' ' * (_commentIndent - 3 - _indent));
  569 + _buf.putComment('endText()');
  570 + }
  571 + return true;
  572 + }());
  573 +
437 } 574 }
438 575
439 void reset() { 576 void reset() {
440 assert(() { 577 assert(() {
441 if (_page.pdfDocument.verbose) { 578 if (_page.pdfDocument.verbose) {
442 - _buf.putComment('reset'); 579 + _buf.putString(' ' * (_indent));
443 } 580 }
444 return true; 581 return true;
445 }()); 582 }());
446 583
447 - _buf.putString('0 Tr\n'); 584 + _buf.putString('0 Tr ');
  585 +
  586 + assert(() {
  587 + if (_page.pdfDocument.verbose) {
  588 + _buf.putString(' ' * (_commentIndent - 5 - _indent));
  589 + _buf.putComment('reset()');
  590 + }
  591 + return true;
  592 + }());
448 } 593 }
449 594
450 /// Sets the color for drawing 595 /// Sets the color for drawing
@@ -455,9 +600,11 @@ class PdfGraphics { @@ -455,9 +600,11 @@ class PdfGraphics {
455 600
456 /// Sets the fill color for drawing 601 /// Sets the fill color for drawing
457 void setFillColor(PdfColor? color) { 602 void setFillColor(PdfColor? color) {
  603 + var o = 0;
458 assert(() { 604 assert(() {
459 if (_page.pdfDocument.verbose) { 605 if (_page.pdfDocument.verbose) {
460 - _buf.putComment('setFillColor ${color?.toHex()}'); 606 + o = _buf.offset;
  607 + _buf.putString(' ' * (_indent));
461 } 608 }
462 return true; 609 return true;
463 }()); 610 }());
@@ -465,18 +612,28 @@ class PdfGraphics { @@ -465,18 +612,28 @@ class PdfGraphics {
465 if (color is PdfColorCmyk) { 612 if (color is PdfColorCmyk) {
466 PdfNumList(<double>[color.cyan, color.magenta, color.yellow, color.black]) 613 PdfNumList(<double>[color.cyan, color.magenta, color.yellow, color.black])
467 .output(_buf); 614 .output(_buf);
468 - _buf.putString(' k\n'); 615 + _buf.putString(' k ');
469 } else { 616 } else {
470 PdfNumList(<double>[color!.red, color.green, color.blue]).output(_buf); 617 PdfNumList(<double>[color!.red, color.green, color.blue]).output(_buf);
471 - _buf.putString(' rg\n'); 618 + _buf.putString(' rg ');
  619 + }
  620 +
  621 + assert(() {
  622 + if (_page.pdfDocument.verbose) {
  623 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  624 + _buf.putComment('setFillColor(${color?.toHex()})');
472 } 625 }
  626 + return true;
  627 + }());
473 } 628 }
474 629
475 /// Sets the stroke color for drawing 630 /// Sets the stroke color for drawing
476 void setStrokeColor(PdfColor? color) { 631 void setStrokeColor(PdfColor? color) {
  632 + var o = 0;
477 assert(() { 633 assert(() {
478 if (_page.pdfDocument.verbose) { 634 if (_page.pdfDocument.verbose) {
479 - _buf.putComment('setStrokeColor ${color?.toHex()}'); 635 + o = _buf.offset;
  636 + _buf.putString(' ' * (_indent));
480 } 637 }
481 return true; 638 return true;
482 }()); 639 }());
@@ -484,67 +641,116 @@ class PdfGraphics { @@ -484,67 +641,116 @@ class PdfGraphics {
484 if (color is PdfColorCmyk) { 641 if (color is PdfColorCmyk) {
485 PdfNumList(<double>[color.cyan, color.magenta, color.yellow, color.black]) 642 PdfNumList(<double>[color.cyan, color.magenta, color.yellow, color.black])
486 .output(_buf); 643 .output(_buf);
487 - _buf.putString(' K\n'); 644 + _buf.putString(' K ');
488 } else { 645 } else {
489 PdfNumList(<double>[color!.red, color.green, color.blue]).output(_buf); 646 PdfNumList(<double>[color!.red, color.green, color.blue]).output(_buf);
490 - _buf.putString(' RG\n'); 647 + _buf.putString(' RG ');
  648 + }
  649 +
  650 + assert(() {
  651 + if (_page.pdfDocument.verbose) {
  652 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  653 + _buf.putComment('setStrokeColor(${color?.toHex()})');
491 } 654 }
  655 + return true;
  656 + }());
492 } 657 }
493 658
494 /// Sets the fill pattern for drawing 659 /// Sets the fill pattern for drawing
495 void setFillPattern(PdfPattern pattern) { 660 void setFillPattern(PdfPattern pattern) {
  661 + var o = 0;
496 assert(() { 662 assert(() {
497 if (_page.pdfDocument.verbose) { 663 if (_page.pdfDocument.verbose) {
498 - _buf.putComment('setFillPattern'); 664 + o = _buf.offset;
  665 + _buf.putString(' ' * (_indent));
499 } 666 }
500 return true; 667 return true;
501 }()); 668 }());
502 669
503 // The shader needs to be registered in the page resources 670 // The shader needs to be registered in the page resources
504 _page.addPattern(pattern); 671 _page.addPattern(pattern);
505 - _buf.putString('/Pattern cs${pattern.name} scn\n'); 672 + _buf.putString('/Pattern cs${pattern.name} scn ');
  673 +
  674 + assert(() {
  675 + if (_page.pdfDocument.verbose) {
  676 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  677 + _buf.putComment('setFillPattern(${pattern.ref()})');
  678 + }
  679 + return true;
  680 + }());
506 } 681 }
507 682
508 /// Sets the stroke pattern for drawing 683 /// Sets the stroke pattern for drawing
509 void setStrokePattern(PdfPattern pattern) { 684 void setStrokePattern(PdfPattern pattern) {
  685 + var o = 0;
510 assert(() { 686 assert(() {
511 if (_page.pdfDocument.verbose) { 687 if (_page.pdfDocument.verbose) {
512 - _buf.putComment('setStrokePattern'); 688 + o = _buf.offset;
  689 + _buf.putString(' ' * (_indent));
513 } 690 }
514 return true; 691 return true;
515 }()); 692 }());
516 693
517 // The shader needs to be registered in the page resources 694 // The shader needs to be registered in the page resources
518 _page.addPattern(pattern); 695 _page.addPattern(pattern);
519 - _buf.putString('/Pattern CS${pattern.name} SCN\n'); 696 + _buf.putString('/Pattern CS${pattern.name} SCN ');
  697 +
  698 + assert(() {
  699 + if (_page.pdfDocument.verbose) {
  700 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  701 + _buf.putComment('setStrokePattern(${pattern.ref()})');
  702 + }
  703 + return true;
  704 + }());
520 } 705 }
521 706
522 /// Set the graphic state for drawing 707 /// Set the graphic state for drawing
523 void setGraphicState(PdfGraphicState state) { 708 void setGraphicState(PdfGraphicState state) {
  709 + var o = 0;
524 assert(() { 710 assert(() {
525 if (_page.pdfDocument.verbose) { 711 if (_page.pdfDocument.verbose) {
526 - _buf.putComment('setGraphicState $state'); 712 + o = _buf.offset;
  713 + _buf.putString(' ' * (_indent));
527 } 714 }
528 return true; 715 return true;
529 }()); 716 }());
530 717
531 final name = _page.stateName(state); 718 final name = _page.stateName(state);
532 - _buf.putString('$name gs\n'); 719 + _buf.putString('$name gs ');
  720 +
  721 + assert(() {
  722 + if (_page.pdfDocument.verbose) {
  723 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  724 + _buf.putComment('setGraphicState($state)');
  725 + }
  726 + return true;
  727 + }());
533 } 728 }
534 729
535 /// Set the transformation Matrix 730 /// Set the transformation Matrix
536 void setTransform(Matrix4 t) { 731 void setTransform(Matrix4 t) {
  732 + var o = 0;
537 assert(() { 733 assert(() {
538 if (_page.pdfDocument.verbose) { 734 if (_page.pdfDocument.verbose) {
539 - _buf.putComment('setTransform\n$t'); 735 + o = _buf.offset;
  736 + _buf.putString(' ' * (_indent));
540 } 737 }
541 return true; 738 return true;
542 }()); 739 }());
543 740
544 final s = t.storage; 741 final s = t.storage;
545 PdfNumList(<double>[s[0], s[1], s[4], s[5], s[12], s[13]]).output(_buf); 742 PdfNumList(<double>[s[0], s[1], s[4], s[5], s[12], s[13]]).output(_buf);
546 - _buf.putString(' cm\n'); 743 + _buf.putString(' cm ');
547 _context.ctm.multiply(t); 744 _context.ctm.multiply(t);
  745 +
  746 + assert(() {
  747 + if (_page.pdfDocument.verbose) {
  748 + final n = math.max(0, _commentIndent - _buf.offset + o);
  749 + _buf.putString(' ' * n);
  750 + _buf.putComment('setTransform($s)');
  751 + }
  752 + return true;
  753 + }());
548 } 754 }
549 755
550 /// Get the transformation Matrix 756 /// Get the transformation Matrix
@@ -554,28 +760,48 @@ class PdfGraphics { @@ -554,28 +760,48 @@ class PdfGraphics {
554 760
555 /// This adds a line segment to the current path 761 /// This adds a line segment to the current path
556 void lineTo(double x, double y) { 762 void lineTo(double x, double y) {
  763 + var o = 0;
557 assert(() { 764 assert(() {
558 if (_page.pdfDocument.verbose) { 765 if (_page.pdfDocument.verbose) {
559 - _buf.putComment('lineTo x:$x y:$y'); 766 + o = _buf.offset;
  767 + _buf.putString(' ' * (_indent));
560 } 768 }
561 return true; 769 return true;
562 }()); 770 }());
563 771
564 PdfNumList([x, y]).output(_buf); 772 PdfNumList([x, y]).output(_buf);
565 - _buf.putString(' l\n'); 773 + _buf.putString(' l ');
  774 +
  775 + assert(() {
  776 + if (_page.pdfDocument.verbose) {
  777 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  778 + _buf.putComment('lineTo($x, $y)');
  779 + }
  780 + return true;
  781 + }());
566 } 782 }
567 783
568 /// This moves the current drawing point. 784 /// This moves the current drawing point.
569 void moveTo(double x, double y) { 785 void moveTo(double x, double y) {
  786 + var o = 0;
570 assert(() { 787 assert(() {
571 if (_page.pdfDocument.verbose) { 788 if (_page.pdfDocument.verbose) {
572 - _buf.putComment('moveTo x:$x y:$y'); 789 + o = _buf.offset;
  790 + _buf.putString(' ' * (_indent));
573 } 791 }
574 return true; 792 return true;
575 }()); 793 }());
576 794
577 PdfNumList([x, y]).output(_buf); 795 PdfNumList([x, y]).output(_buf);
578 - _buf.putString(' m\n'); 796 + _buf.putString(' m ');
  797 +
  798 + assert(() {
  799 + if (_page.pdfDocument.verbose) {
  800 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  801 + _buf.putComment('moveTo($x, $y)');
  802 + }
  803 + return true;
  804 + }());
579 } 805 }
580 806
581 /// Draw a cubic bézier curve from the current point to (x3,y3) 807 /// Draw a cubic bézier curve from the current point to (x3,y3)
@@ -583,15 +809,25 @@ class PdfGraphics { @@ -583,15 +809,25 @@ class PdfGraphics {
583 /// and (x2,y2) as the control point at the end of the curve. 809 /// and (x2,y2) as the control point at the end of the curve.
584 void curveTo( 810 void curveTo(
585 double x1, double y1, double x2, double y2, double x3, double y3) { 811 double x1, double y1, double x2, double y2, double x3, double y3) {
  812 + var o = 0;
586 assert(() { 813 assert(() {
587 if (_page.pdfDocument.verbose) { 814 if (_page.pdfDocument.verbose) {
588 - _buf.putComment('curveTo x1:$x1 y1:$y1 x2:$x2 y2:$y2 x3:$x3 y3:$y3'); 815 + o = _buf.offset;
  816 + _buf.putString(' ' * (_indent));
589 } 817 }
590 return true; 818 return true;
591 }()); 819 }());
592 820
593 PdfNumList([x1, y1, x2, y2, x3, y3]).output(_buf); 821 PdfNumList([x1, y1, x2, y2, x3, y3]).output(_buf);
594 - _buf.putString(' c\n'); 822 + _buf.putString(' c ');
  823 +
  824 + assert(() {
  825 + if (_page.pdfDocument.verbose) {
  826 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  827 + _buf.putComment('curveTo($x1, $y1, $x2, $y2, $x3, $y3)');
  828 + }
  829 + return true;
  830 + }());
595 } 831 }
596 832
597 double _vectorAngle(double ux, double uy, double vx, double vy) { 833 double _vectorAngle(double ux, double uy, double vx, double vy) {
@@ -753,51 +989,87 @@ class PdfGraphics { @@ -753,51 +989,87 @@ class PdfGraphics {
753 void setLineCap(PdfLineCap cap) { 989 void setLineCap(PdfLineCap cap) {
754 assert(() { 990 assert(() {
755 if (_page.pdfDocument.verbose) { 991 if (_page.pdfDocument.verbose) {
756 - _buf.putComment('setLineCap $cap'); 992 + _buf.putString(' ' * (_indent));
757 } 993 }
758 return true; 994 return true;
759 }()); 995 }());
760 996
761 - _buf.putString('${cap.index} J\n'); 997 + _buf.putString('${cap.index} J ');
  998 +
  999 + assert(() {
  1000 + if (_page.pdfDocument.verbose) {
  1001 + _buf.putString(' ' * (_commentIndent - 4 - _indent));
  1002 + _buf.putComment('setLineCap(${cap.name})');
  1003 + }
  1004 + return true;
  1005 + }());
762 } 1006 }
763 1007
764 /// Set line join type 1008 /// Set line join type
765 void setLineJoin(PdfLineJoin join) { 1009 void setLineJoin(PdfLineJoin join) {
766 assert(() { 1010 assert(() {
767 if (_page.pdfDocument.verbose) { 1011 if (_page.pdfDocument.verbose) {
768 - _buf.putComment('setLineJoin $join'); 1012 + _buf.putString(' ' * (_indent));
769 } 1013 }
770 return true; 1014 return true;
771 }()); 1015 }());
772 1016
773 - _buf.putString('${join.index} j\n'); 1017 + _buf.putString('${join.index} j ');
  1018 +
  1019 + assert(() {
  1020 + if (_page.pdfDocument.verbose) {
  1021 + _buf.putString(' ' * (_commentIndent - 4 - _indent));
  1022 + _buf.putComment('setLineJoin(${join.name})');
  1023 + }
  1024 + return true;
  1025 + }());
774 } 1026 }
775 1027
776 /// Set line width 1028 /// Set line width
777 void setLineWidth(double width) { 1029 void setLineWidth(double width) {
  1030 + var o = 0;
778 assert(() { 1031 assert(() {
779 if (_page.pdfDocument.verbose) { 1032 if (_page.pdfDocument.verbose) {
780 - _buf.putComment('setLineWidth $width'); 1033 + o = _buf.offset;
  1034 + _buf.putString(' ' * (_indent));
781 } 1035 }
782 return true; 1036 return true;
783 }()); 1037 }());
784 1038
785 PdfNum(width).output(_buf); 1039 PdfNum(width).output(_buf);
786 - _buf.putString(' w\n'); 1040 + _buf.putString(' w ');
  1041 +
  1042 + assert(() {
  1043 + if (_page.pdfDocument.verbose) {
  1044 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  1045 + _buf.putComment('setLineWidth($width)');
  1046 + }
  1047 + return true;
  1048 + }());
787 } 1049 }
788 1050
789 /// Set line joint miter limit, applies if the 1051 /// Set line joint miter limit, applies if the
790 void setMiterLimit(double limit) { 1052 void setMiterLimit(double limit) {
  1053 + var o = 0;
791 assert(() { 1054 assert(() {
792 if (_page.pdfDocument.verbose) { 1055 if (_page.pdfDocument.verbose) {
793 - _buf.putComment('setMiterLimit $limit'); 1056 + o = _buf.offset;
  1057 + _buf.putString(' ' * (_indent));
794 } 1058 }
795 return true; 1059 return true;
796 }()); 1060 }());
797 1061
798 assert(limit >= 1.0); 1062 assert(limit >= 1.0);
799 PdfNum(limit).output(_buf); 1063 PdfNum(limit).output(_buf);
800 - _buf.putString(' M\n'); 1064 + _buf.putString(' M ');
  1065 +
  1066 + assert(() {
  1067 + if (_page.pdfDocument.verbose) {
  1068 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  1069 + _buf.putComment('setMiterLimit($limit)');
  1070 + }
  1071 + return true;
  1072 + }());
801 } 1073 }
802 1074
803 /// The dash array shall be cycled through, adding up the lengths of dashes and gaps. 1075 /// The dash array shall be cycled through, adding up the lengths of dashes and gaps.
@@ -805,38 +1077,66 @@ class PdfGraphics { @@ -805,38 +1077,66 @@ class PdfGraphics {
805 /// 1077 ///
806 /// Example: [2 1] will create a dash pattern with 2 on, 1 off, 2 on, 1 off, ... 1078 /// Example: [2 1] will create a dash pattern with 2 on, 1 off, 2 on, 1 off, ...
807 void setLineDashPattern([List<num> array = const <num>[], int phase = 0]) { 1079 void setLineDashPattern([List<num> array = const <num>[], int phase = 0]) {
  1080 + var o = 0;
808 assert(() { 1081 assert(() {
809 if (_page.pdfDocument.verbose) { 1082 if (_page.pdfDocument.verbose) {
810 - _buf.putComment('setLineDashPattern $array phase:$phase'); 1083 + o = _buf.offset;
  1084 + _buf.putString(' ' * (_indent));
811 } 1085 }
812 return true; 1086 return true;
813 }()); 1087 }());
814 1088
815 PdfArray.fromNum(array).output(_buf); 1089 PdfArray.fromNum(array).output(_buf);
816 - _buf.putString(' $phase d\n'); 1090 + _buf.putString(' $phase d ');
  1091 +
  1092 + assert(() {
  1093 + if (_page.pdfDocument.verbose) {
  1094 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  1095 + _buf.putComment('setLineDashPattern($array, $phase)');
  1096 + }
  1097 + return true;
  1098 + }());
817 } 1099 }
818 1100
819 void markContentBegin(PdfName tag) { 1101 void markContentBegin(PdfName tag) {
  1102 + var o = 0;
820 assert(() { 1103 assert(() {
821 if (_page.pdfDocument.verbose) { 1104 if (_page.pdfDocument.verbose) {
822 - _buf.putComment('markContentBegin'); 1105 + o = _buf.offset;
  1106 + _buf.putString(' ' * (_indent));
823 } 1107 }
824 return true; 1108 return true;
825 }()); 1109 }());
826 1110
827 tag.output(_buf); 1111 tag.output(_buf);
828 - _buf.putString(' BMC\n'); 1112 + _buf.putString(' BMC ');
  1113 +
  1114 + assert(() {
  1115 + if (_page.pdfDocument.verbose) {
  1116 + _buf.putString(' ' * math.max(0, _commentIndent - _buf.offset + o));
  1117 + _buf.putComment('markContentBegin($tag)');
  1118 + }
  1119 + return true;
  1120 + }());
829 } 1121 }
830 1122
831 void markContentEnd() { 1123 void markContentEnd() {
832 assert(() { 1124 assert(() {
833 if (_page.pdfDocument.verbose) { 1125 if (_page.pdfDocument.verbose) {
834 - _buf.putComment('markContentEnd'); 1126 + _buf.putString(' ' * (_indent));
835 } 1127 }
836 return true; 1128 return true;
837 }()); 1129 }());
838 1130
839 - _buf.putString('EMC\n'); 1131 + _buf.putString('EMC ');
  1132 +
  1133 + assert(() {
  1134 + if (_page.pdfDocument.verbose) {
  1135 + _buf.putString(' ' * (_commentIndent - 4 - _indent));
  1136 + _buf.putComment('markContentEnd()');
  1137 + }
  1138 + return true;
  1139 + }());
840 } 1140 }
841 } 1141 }
842 1142
@@ -891,8 +1191,8 @@ class _PathBBProxy extends PathProxy { @@ -891,8 +1191,8 @@ class _PathBBProxy extends PathProxy {
891 @override 1191 @override
892 void cubicTo( 1192 void cubicTo(
893 double x1, double y1, double x2, double y2, double x3, double y3) { 1193 double x1, double y1, double x2, double y2, double x3, double y3) {
894 - final tvalues = <double>[];  
895 - double a, b, c, t, t1, t2, b2ac, sqrtb2ac; 1194 + final tValues = <double>[];
  1195 + double a, b, c, t, t1, t2, b2ac, sqrtB2ac;
896 1196
897 for (var i = 0; i < 2; ++i) { 1197 for (var i = 0; i < 2; ++i) {
898 if (i == 0) { 1198 if (i == 0) {
@@ -910,7 +1210,7 @@ class _PathBBProxy extends PathProxy { @@ -910,7 +1210,7 @@ class _PathBBProxy extends PathProxy {
910 } 1210 }
911 t = -c / b; 1211 t = -c / b;
912 if (0 < t && t < 1) { 1212 if (0 < t && t < 1) {
913 - tvalues.add(t); 1213 + tValues.add(t);
914 } 1214 }
915 continue; 1215 continue;
916 } 1216 }
@@ -919,23 +1219,23 @@ class _PathBBProxy extends PathProxy { @@ -919,23 +1219,23 @@ class _PathBBProxy extends PathProxy {
919 if (b2ac.abs() < 1e-12) { 1219 if (b2ac.abs() < 1e-12) {
920 t = -b / (2 * a); 1220 t = -b / (2 * a);
921 if (0 < t && t < 1) { 1221 if (0 < t && t < 1) {
922 - tvalues.add(t); 1222 + tValues.add(t);
923 } 1223 }
924 } 1224 }
925 continue; 1225 continue;
926 } 1226 }
927 - sqrtb2ac = math.sqrt(b2ac);  
928 - t1 = (-b + sqrtb2ac) / (2 * a); 1227 + sqrtB2ac = math.sqrt(b2ac);
  1228 + t1 = (-b + sqrtB2ac) / (2 * a);
929 if (0 < t1 && t1 < 1) { 1229 if (0 < t1 && t1 < 1) {
930 - tvalues.add(t1); 1230 + tValues.add(t1);
931 } 1231 }
932 - t2 = (-b - sqrtb2ac) / (2 * a); 1232 + t2 = (-b - sqrtB2ac) / (2 * a);
933 if (0 < t2 && t2 < 1) { 1233 if (0 < t2 && t2 < 1) {
934 - tvalues.add(t2); 1234 + tValues.add(t2);
935 } 1235 }
936 } 1236 }
937 1237
938 - for (final t in tvalues) { 1238 + for (final t in tValues) {
939 final mt = 1 - t; 1239 final mt = 1 - t;
940 _updateMinMax( 1240 _updateMinMax(
941 (mt * mt * mt * _pX) + 1241 (mt * mt * mt * _pX) +
@@ -94,7 +94,6 @@ class PdfOutput with PdfDiagnostic { @@ -94,7 +94,6 @@ class PdfOutput with PdfDiagnostic {
94 signatureID = ob; 94 signatureID = ob;
95 } 95 }
96 96
97 - xref.add(PdfXref(ob.objser, os.offset));  
98 assert(() { 97 assert(() {
99 if (verbose) { 98 if (verbose) {
100 ob.setInsertion(os); 99 ob.setInsertion(os);
@@ -102,6 +101,7 @@ class PdfOutput with PdfDiagnostic { @@ -102,6 +101,7 @@ class PdfOutput with PdfDiagnostic {
102 } 101 }
103 return true; 102 return true;
104 }()); 103 }());
  104 + xref.add(PdfXref(ob.objser, os.offset, generation: ob.objgen));
105 ob.write(os); 105 ob.write(os);
106 assert(() { 106 assert(() {
107 if (verbose) { 107 if (verbose) {
@@ -145,36 +145,15 @@ class PdfOutput with PdfDiagnostic { @@ -145,36 +145,15 @@ class PdfOutput with PdfDiagnostic {
145 params['/Prev'] = PdfNum(rootID!.pdfDocument.prev!.xrefOffset); 145 params['/Prev'] = PdfNum(rootID!.pdfDocument.prev!.xrefOffset);
146 } 146 }
147 147
148 - final _xref = os.offset;  
149 - if (isCompressed) {  
150 - xref.outputCompressed(rootID!, os, params);  
151 - } else {  
152 - assert(() {  
153 - if (verbose) {  
154 - os.putComment('');  
155 - os.putComment('-' * 78);  
156 - }  
157 - return true;  
158 - }());  
159 - xref.output(os);  
160 -  
161 - // the trailer object  
162 - assert(() {  
163 - if (verbose) {  
164 - os.putComment('');  
165 - os.putComment('-' * 78);  
166 - }  
167 - return true;  
168 - }());  
169 - os.putString('trailer\n');  
170 - params.output(os, verbose ? 0 : null);  
171 - os.putByte(0x0a);  
172 - } 148 + final _xref = isCompressed
  149 + ? xref.outputCompressed(rootID!, os, params)
  150 + : xref.outputLegacy(rootID!, os, params);
173 151
174 assert(() { 152 assert(() {
175 if (verbose) { 153 if (verbose) {
176 os.putComment(''); 154 os.putComment('');
177 os.putComment('-' * 78); 155 os.putComment('-' * 78);
  156 + os.putComment('$runtimeType');
178 } 157 }
179 return true; 158 return true;
180 }()); 159 }());
@@ -83,7 +83,7 @@ class PdfXref { @@ -83,7 +83,7 @@ class PdfXref {
83 } 83 }
84 84
85 @override 85 @override
86 - String toString() => '$runtimeType $id $generation $offset $type'; 86 + String toString() => '$id $generation obj ${type.name} $offset';
87 87
88 @override 88 @override
89 int get hashCode => offset; 89 int get hashCode => offset;
@@ -101,8 +101,8 @@ class PdfXrefTable extends PdfDataType { @@ -101,8 +101,8 @@ class PdfXrefTable extends PdfDataType {
101 } 101 }
102 102
103 /// Writes a block of references to the Pdf file 103 /// Writes a block of references to the Pdf file
104 - void _writeblock(PdfStream s, int firstid, List<PdfXref> block) {  
105 - s.putString('$firstid ${block.length}\n'); 104 + void _writeBlock(PdfStream s, int firstId, List<PdfXref> block) {
  105 + s.putString('$firstId ${block.length}\n');
106 106
107 for (final x in block) { 107 for (final x in block) {
108 s.putString(x.ref()); 108 s.putString(x.ref());
@@ -111,14 +111,32 @@ class PdfXrefTable extends PdfDataType { @@ -111,14 +111,32 @@ class PdfXrefTable extends PdfDataType {
111 } 111 }
112 112
113 @override 113 @override
114 - void output(PdfStream s, [int? indent]) {  
115 - s.putString('xref\n'); 114 + void output(PdfStream s, [int? indent]) {}
116 115
  116 + @override
  117 + String toString() {
  118 + final s = StringBuffer();
  119 + for (final x in offsets) {
  120 + s.writeln(' $x');
  121 + }
  122 + return s.toString();
  123 + }
  124 +
  125 + int outputLegacy(PdfObject object, PdfStream s, PdfDict params) {
117 // Now scan through the offsets list. They should be in sequence. 126 // Now scan through the offsets list. They should be in sequence.
118 offsets.sort((a, b) => a.id.compareTo(b.id)); 127 offsets.sort((a, b) => a.id.compareTo(b.id));
119 128
120 - var firstid = 0; // First id in block  
121 - var lastid = 0; // The last id used 129 + assert(() {
  130 + if (object.pdfDocument.verbose) {
  131 + s.putComment('');
  132 + s.putComment('-' * 78);
  133 + s.putComment('$runtimeType ${object.pdfDocument.version.name}\n$this');
  134 + }
  135 + return true;
  136 + }());
  137 +
  138 + var firstId = 0; // First id in block
  139 + var lastId = 0; // The last id used
122 final block = <PdfXref>[]; // xrefs in this block 140 final block = <PdfXref>[]; // xrefs in this block
123 141
124 // We need block 0 to exist 142 // We need block 0 to exist
@@ -129,26 +147,42 @@ class PdfXrefTable extends PdfDataType { @@ -129,26 +147,42 @@ class PdfXrefTable extends PdfDataType {
129 type: PdfCrossRefEntryType.free, 147 type: PdfCrossRefEntryType.free,
130 )); 148 ));
131 149
  150 + final objOffset = s.offset;
  151 + s.putString('xref\n');
  152 +
132 for (final x in offsets) { 153 for (final x in offsets) {
133 // check to see if block is in range 154 // check to see if block is in range
134 - if (x.id != (lastid + 1)) { 155 + if (x.id != (lastId + 1)) {
135 // no, so write this block, and reset 156 // no, so write this block, and reset
136 - _writeblock(s, firstid, block); 157 + _writeBlock(s, firstId, block);
137 block.clear(); 158 block.clear();
138 - firstid = x.id; 159 + firstId = x.id;
139 } 160 }
140 161
141 // now add to block 162 // now add to block
142 block.add(x); 163 block.add(x);
143 - lastid = x.id; 164 + lastId = x.id;
144 } 165 }
145 166
146 // now write the last block 167 // now write the last block
147 - _writeblock(s, firstid, block); 168 + _writeBlock(s, firstId, block);
  169 +
  170 + // the trailer object
  171 + assert(() {
  172 + if (object.pdfDocument.verbose) {
  173 + s.putComment('');
  174 + }
  175 + return true;
  176 + }());
  177 + s.putString('trailer\n');
  178 + params.output(s, object.pdfDocument.verbose ? 0 : null);
  179 + s.putByte(0x0a);
  180 +
  181 + return objOffset;
148 } 182 }
149 183
150 /// Output a compressed cross-reference table 184 /// Output a compressed cross-reference table
151 - void outputCompressed(PdfObject object, PdfStream s, PdfDict params) { 185 + int outputCompressed(PdfObject object, PdfStream s, PdfDict params) {
152 final offset = s.offset; 186 final offset = s.offset;
153 187
154 // Sort all references 188 // Sort all references
@@ -161,24 +195,24 @@ class PdfXrefTable extends PdfDataType { @@ -161,24 +195,24 @@ class PdfXrefTable extends PdfDataType {
161 params['/Type'] = const PdfName('/XRef'); 195 params['/Type'] = const PdfName('/XRef');
162 params['/Size'] = PdfNum(id + 1); 196 params['/Size'] = PdfNum(id + 1);
163 197
164 - var firstid = 0; // First id in block  
165 - var lastid = 0; // The last id used 198 + var firstId = 0; // First id in block
  199 + var lastId = 0; // The last id used
166 final blocks = <int>[]; // xrefs in this block first, count 200 final blocks = <int>[]; // xrefs in this block first, count
167 201
168 // We need block 0 to exist 202 // We need block 0 to exist
169 - blocks.add(firstid); 203 + blocks.add(firstId);
170 204
171 for (final x in offsets) { 205 for (final x in offsets) {
172 // check to see if block is in range 206 // check to see if block is in range
173 - if (x.id != (lastid + 1)) { 207 + if (x.id != (lastId + 1)) {
174 // no, so store this block, and reset 208 // no, so store this block, and reset
175 - blocks.add(lastid - firstid + 1);  
176 - firstid = x.id;  
177 - blocks.add(firstid); 209 + blocks.add(lastId - firstId + 1);
  210 + firstId = x.id;
  211 + blocks.add(firstId);
178 } 212 }
179 - lastid = x.id; 213 + lastId = x.id;
180 } 214 }
181 - blocks.add(lastid - firstid + 1); 215 + blocks.add(lastId - firstId + 1);
182 216
183 if (!(blocks.length == 2 && blocks[0] == 0 && blocks[1] == id + 1)) { 217 if (!(blocks.length == 2 && blocks[0] == 0 && blocks[1] == id + 1)) {
184 params['/Index'] = PdfArray.fromNum(blocks); 218 params['/Index'] = PdfArray.fromNum(blocks);
@@ -203,10 +237,13 @@ class PdfXrefTable extends PdfDataType { @@ -203,10 +237,13 @@ class PdfXrefTable extends PdfDataType {
203 if (object.pdfDocument.verbose) { 237 if (object.pdfDocument.verbose) {
204 s.putComment(''); 238 s.putComment('');
205 s.putComment('-' * 78); 239 s.putComment('-' * 78);
206 - s.putComment('$runtimeType $this'); 240 + s.putComment('$runtimeType ${object.pdfDocument.version.name}\n$this');
207 } 241 }
208 return true; 242 return true;
209 }()); 243 }());
  244 +
  245 + final objOffset = s.offset;
  246 +
210 s.putString('$id 0 obj\n'); 247 s.putString('$id 0 obj\n');
211 248
212 PdfDictStream( 249 PdfDictStream(
@@ -218,5 +255,6 @@ class PdfXrefTable extends PdfDataType { @@ -218,5 +255,6 @@ class PdfXrefTable extends PdfDataType {
218 ).output(s, object.pdfDocument.verbose ? 0 : null); 255 ).output(s, object.pdfDocument.verbose ? 0 : null);
219 256
220 s.putString('endobj\n'); 257 s.putString('endobj\n');
  258 + return objOffset;
221 } 259 }
222 } 260 }