1 /*
2 Copyright (C) 2017-2021, Dirk Krause
3 SPDX-License-Identifier: BSD-3-Clause
4 */
5
6 /*
7 WARNING: This file was generated by the dkct program (see
8 http://dktools.sourceforge.net/ for details).
9 Changes you make here will be lost if dkct is run again!
10 You should modify the original source and run dkct on it.
11 Original source: dk4grpdf.ctr
12 */
13
14 /** @file dk4grpdf.c The dk4grpdf module.
15 */
16
17
18
19 #ifdef DK4GRA_PDF_FORCE_UNCOMPRESSED
20 #undef DK4GRA_PDF_FORCE_UNCOMPRESSED
21 #endif
22
23 /** Use for debugging purposes only to produce
24 an uncompresse page contents data stream.
25 Normally this should be defined to 0.
26 */
27 #define DK4GRA_PDF_FORCE_UNCOMPRESSED 0
28
29
30
31 #include "dk4conf.h"
32
33 #if DK4_HAVE_MATH_H
34 #ifndef MATH_H_INCLUDED
35 #if DK4_ON_WINDOWS
36 #ifndef _USE_MATH_DEFINES
37 #define _USE_MATH_DEFINES 1
38 #endif
39 #endif
40 #include <math.h>
41 #define MATH_H_INCLUDED 1
42 #endif
43 #endif
44
45 #ifndef DK4GRA_H_INCLUDED
46 #include <libdk4gra/dk4gra.h>
47 #endif
48
49 #ifndef GRA_H_INCLUDED
50 #include <libdk4gra/gra.h>
51 #endif
52
53 #ifndef DK4MAO8D_H_INCLUDED
54 #include <libdk4maio8d/dk4mao8d.h>
55 #endif
56
57 #ifndef DK4MAO8DNS_H_INCLUDED
58 #include <libdk4c/dk4mao8dns.h>
59 #endif
60
61 #ifndef DK4UFIC_H_INCLUDED
62 #include <libdk4c/dk4ufic.h>
63 #endif
64
65 #ifndef DK4STRD_H_INCLUDED
66 #include <libdk4base/dk4strd.h>
67 #endif
68
69 #ifndef DK4STRM_H_INCLUDED
70 #include <libdk4c/dk4strm.h>
71 #endif
72
73 #ifndef DK4STRMF_H_INCLUDED
74 #include <libdk4c/dk4strmf.h>
75 #endif
76
77 #ifndef DK4STRMCO_H_INCLUDED
78 #include <libdk4c/dk4strmco.h>
79 #endif
80
81 #ifndef DK4MEM_H_INCLUDED
82 #include <libdk4base/dk4mem.h>
83 #endif
84
85 #if DK4_HAVE_ASSERT_H
86 #ifndef ASSERT_H_INCLUDED
87 #include <assert.h>
88 #define ASSERT_H_INCLUDED 1
89 #endif
90 #endif
91
92
93
94
95
96 /** PDF object position.
97 */
98 typedef struct {
99 size_t num; /**< Object number. */
100 dk4_um_t pos; /**< Start position in output stream. */
101 } dk4_gra_pdf_objpos_t;
102
103
104
105 /** Constant text fragments used by module.
106 */
107 static const char * const dk4_gra_pdf_c8_kw[] = {
108 /* 0 */
109 "\n",
110
111 /* 1 */
112 " ",
113
114 /* 2 */
115 "q\n",
116
117 /* 3 */
118 "Q\n",
119
120 /* 4 */
121 " m\n",
122
123 /* 5 */
124 " l\n",
125
126 /* 6 */
127 " c\n",
128
129 /* 7 */
130 "h\n",
131
132 /* 8 */
133 "S\n",
134
135 /* 9 */
136 "f\n",
137
138 /* 10 */
139 "f*\n",
140
141 /* 11 */
142 "B\n",
143
144 /* 12 */
145 "B*\n",
146
147 /* 13 */
148 "W n\n",
149
150 /* 14 */
151 "W* n\n",
152
153 /* 15 */
154 "1 g\n",
155
156 /* 16 */
157 "0 ",
158
159 /* 17 */
160 "0",
161
162 /* 18 */
163 " 0",
164
165 /* 19 */
166 " g\n",
167
168 /* 20 */
169 " G\n",
170
171 /* 21 */
172 " k\n",
173
174 /* 22 */
175 " K\n",
176
177 /* 23 */
178 " rg\n",
179
180 /* 24 */
181 " RG\n",
182
183 /* 25 */
184 " w\n",
185
186 /* 26 */
187 "0 J\n",
188
189 /* 27 */
190 "1 J\n",
191
192 /* 28 */
193 "2 J\n",
194
195 /* 29 */
196 "0 j\n",
197
198 /* 30 */
199 "1 j\n",
200
201 /* 31 */
202 "2 j\n",
203
204 /* 32 */
205 "[] 0 d\n",
206
207 /* 33 */
208 "[",
209
210 /* 34 */
211 "] ",
212
213 /* 35 */
214 " d\n",
215
216 /* 36 */
217 "%PDF-1.4\n",
218
219 /* 37 */
220 " 0 obj\n",
221
222 /* 38 */
223 "endobj\n",
224
225 /* 39 */
226 "<<\n",
227
228 /* 40 */
229 ">>\n",
230
231 /* 41 */
232 "/Producer (libdk4gra, see http://sourceforge.net/p/dktools/wiki/Home/)\n",
233
234 /* 42 */
235 "/CreationDate (D:",
236
237 /* 43 */
238 "/ModDate (D:",
239
240 /* 44 */
241 ")\n",
242
243 /* 45 */
244 "xref 0 ",
245
246 /* 46 */
247 "0000000000 65535 f\n",
248
249 /* 47 */
250 " 00000 n\n",
251
252 /* 48 */
253 "trailer\n<< /Size ",
254
255 /* 49 */
256 " /Info 1 0 R /Root 2 0 R >>\nstartxref\n",
257
258 /* 50 */
259 "\n%%EOF\n",
260
261 /* 51 */
262 "/Type /Catalog\n",
263
264 /* 52 */
265 "/Pages 3 0 R\n",
266
267 /* 53 */
268 "/Type /Pages\n",
269
270 /* 54 */
271 "/Count ",
272
273 /* 55 */
274 "/Kids [\n",
275
276 /* 56 */
277 "]\n",
278
279 /* 57 */
280 " 0 R\n",
281
282 /* 58 */
283 "/Type /Page\n",
284
285 /* 59 */
286 "/Parent 3 0 R\n",
287
288 /* 60 */
289 "/MediaBox [0 0 ",
290
291 /* 61 */
292 "/CropBox [0 0 ",
293
294 /* 62 */
295 "/Resources <<\n",
296
297 /* 63 */
298 "/ProcSet [/PDF /ImageB /ImageC]\n",
299
300 /* 64 */
301 "/XObject <<\n",
302
303 /* 65 */
304 "/Contents ",
305
306 /* 66 */
307 "/Length ",
308
309 /* 67 */
310 "/Filter /FlateDecode\n",
311
312 /* 68 */
313 "stream\n",
314
315 /* 69 */
316 "\nendstream\n",
317
318 /* 70 */
319 " cm\n",
320
321 /* 71 */
322 "/X",
323
324 /* 72 */
325 " Do\n",
326
327 /* 73 */
328 "/Type /XObject\n",
329
330 /* 74 */
331 "/Subtype /Image\n",
332
333 /* 75 */
334 "/Width ",
335
336 /* 76 */
337 "/Height ",
338
339 /* 77 */
340 "/BitsPerComponent ",
341
342 /* 78 */
343 "/ColorSpace /DeviceRGB\n",
344
345 /* 79 */
346 "/ColorSpace /DeviceGray\n",
347
348 /* 80 */
349 "/ColorSpace /DeviceCMYK\n",
350
351 /* 81 */
352 "/SMask ",
353
354 /* 82 */
355 "/Interpolate true\n",
356
357 /* 83 */
358 "/Filter /DCTDecode\n",
359
360 /* 84 */
361 " M\n",
362
363 /* 85 */
364 "/Decode [1 0 1 0 1 0 1 0]\n",
365
366 /* 86 */
367 "/Decode [1 0 1 0 1 0] \n",
368
369 /* 87 */
370 "/Decode [1 0 1 0] \n",
371
372 /* 88 */
373 "/Decode [1 0]\n",
374
375 NULL
376
377 };
378
379
380
381 void
dk4gra_pdf_i_outstream_kw(dk4_stream_t * os,size_t kwi,int * backptr,dk4_er_t * erp)382 dk4gra_pdf_i_outstream_kw(
383 dk4_stream_t *os,
384 size_t kwi,
385 int *backptr,
386 dk4_er_t *erp
387 )
388 {
389
390 #if DK4_USE_ASSERT
391 assert(NULL != os);
392 #endif
393 dk4gratool_stream_string(os, dk4_gra_pdf_c8_kw[kwi], backptr, erp);
394 }
395
396
397
398 void
dk4gra_pdf_i_values_and_kw(dk4_stream_t * os,double * da,size_t szda,size_t kwi,int * backptr,dk4_er_t * erp)399 dk4gra_pdf_i_values_and_kw(
400 dk4_stream_t *os,
401 double *da,
402 size_t szda,
403 size_t kwi,
404 int *backptr,
405 dk4_er_t *erp
406 )
407 {
408 size_t i;
409 #if DK4_USE_ASSERT
410 assert(NULL != os);
411 assert(NULL != da);
412 assert(0 < szda);
413 #endif
414 for (i = 0; i < szda; i++) {
415 if (0 < i) {
416 dk4gratool_stream_string(os, dk4_gra_pdf_c8_kw[1], backptr, erp);
417 }
418 if (0 == dk4ma_write_c8_double_no_sci_to_stream(
419 os, da[i], DK4_GRA_EPSILON_COORDINATES, 0, 1, erp
420 )
421 ) {
422 if (NULL != backptr) { *backptr = 0; }
423 }
424 }
425 dk4gratool_stream_string(os, dk4_gra_pdf_c8_kw[kwi], backptr, erp);
426 }
427
428
429
430 /** Compare page structures by number or a page against a number.
431 @param l Left page object.
432 @param r Right page object or page number.
433 @param cr Comparison criteria (0=page/page, 1=page/number).
434 @return Comparison result.
435 */
436 static
437 int
dk4gra_pdf_compare_pages_by_number(const void * l,const void * r,int cr)438 dk4gra_pdf_compare_pages_by_number(const void *l, const void *r, int cr)
439 {
440 const dk4_gra_pdf_page_t *pl;
441 const dk4_gra_pdf_page_t *pr;
442 const size_t *ppno;
443
444 int back = 0;
445 if (NULL != l) {
446 if (NULL != r) {
447 pl = (const dk4_gra_pdf_page_t *)l;
448 switch (cr) {
449 case 1: {
450 ppno = (const size_t *)r;
451 if (pl->pageno > *ppno) {
452 back = 1;
453 }
454 else {
455 if (pl->pageno < *ppno) {
456 back = -1;
457 }
458 }
459 } break;
460 default : {
461 pr = (const dk4_gra_pdf_page_t *)r;
462 if (pl->pageno > pr->pageno) {
463 back = 1;
464 }
465 else {
466 if (pl->pageno < pr->pageno) {
467 back = -1;
468 }
469 }
470 } break;
471 }
472 }
473 else {
474 back = 1;
475 }
476 }
477 else {
478 if (NULL != r) {
479 back = -1;
480 }
481 }
482 return back;
483 }
484
485
486
487 int
dk4gra_pdf_compare_used_xo(const void * l,const void * r,int cr)488 dk4gra_pdf_compare_used_xo(
489 const void *l,
490 const void *r,
491 int cr
492 #if DK4_HAVE_ATTRIBUTE_UNUSED
493 __attribute__((unused))
494 #endif
495 )
496 {
497 const dk4_gra_pdf_img_xo_t *pl;
498 const dk4_gra_pdf_img_xo_t *pr;
499 int back = 0;
500
501 #if !DK4_HAVE_ATTRIBUTE_UNUSED
502 (void)cr;
503 #endif
504 if (NULL != l) {
505 if (NULL != r) {
506 pl = (const dk4_gra_pdf_img_xo_t *)l;
507 pr = (const dk4_gra_pdf_img_xo_t *)r;
508 if (pl->objno > pr->objno) {
509 back = 1;
510 }
511 else {
512 if (pl->objno < pr->objno) {
513 back = -1;
514 }
515 }
516 }
517 else { back = 1; }
518 }
519 else {
520 if (NULL != r) { back = -1; }
521 }
522 return back;
523 }
524
525
526
527 /** Compare two object positions by number.
528 @param l Left object.
529 @param r Right object.
530 @param cr Comparison criteria (0=objpos/objpos, 1=objpos/number).
531 @return Comparison result.
532 */
533 static
534 int
dk4gra_pdf_compare_objpos(const void * l,const void * r,int cr)535 dk4gra_pdf_compare_objpos(
536 const void *l,
537 const void *r,
538 int cr
539 )
540 {
541 const dk4_gra_pdf_objpos_t *pl;
542 const dk4_gra_pdf_objpos_t *pr;
543 const size_t *psz;
544 int back = 0;
545
546 if (NULL != l) {
547 if (NULL != r) {
548 pl = (const dk4_gra_pdf_objpos_t *)l;
549 switch (cr) {
550 case 1 : {
551 psz = (const size_t *)r;
552 if (pl->num > *psz) {
553 back = 1;
554 }
555 else {
556 if (pl->num < *psz) {
557 back = -1;
558 }
559 }
560 } break;
561 default : {
562 pr = (const dk4_gra_pdf_objpos_t *)r;
563 if (pl->num > pr->num) {
564 back = 1;
565 }
566 else {
567 if (pl->num < pr->num) {
568 back = -1;
569 }
570 }
571 } break;
572 }
573 }
574 else {
575 back = 1;
576 }
577 }
578 else {
579 if (NULL != r) {
580 back = -1;
581 }
582 }
583 return back;
584 }
585
586
587
588 /** Check whether two XObjects are generated from the same file.
589 @param pl Left object.
590 @param pr Right object.
591 @return Comparison result (0 for equality).
592 */
593 static
594 int
dk4gra_pdf_xo_check_same_file(const dk4_gra_pdf_img_xo_t * pl,const dk4_gra_pdf_img_xo_t * pr)595 dk4gra_pdf_xo_check_same_file(
596 const dk4_gra_pdf_img_xo_t *pl,
597 const dk4_gra_pdf_img_xo_t *pr
598 )
599 {
600 int back = 0;
601
602
603 if (0 != pl->hufi) {
604 if (0 != pr->hufi) {
605 back = dk4ufi_compare(&(pl->ufi), &(pr->ufi));
606
607 }
608 else {
609 back = 1;
610 }
611 }
612 else {
613 if (0 != pr->hufi) {
614 back = -1;
615 }
616 else {
617 if (NULL != pl->fn) {
618 if (NULL != pr->fn) {
619 back = dk4str_pathcmp(pl->fn, pr->fn);
620
621 }
622 else {
623 back = 1;
624 }
625 }
626 else {
627 if (NULL != pr->fn) {
628 back = -1;
629 }
630 else {
631 if (pl->objno > pr->objno) {
632 back = 1;
633 }
634 else {
635 if (pl->objno < pr->objno) {
636 back = -1;
637 }
638 }
639 }
640 }
641 }
642 }
643
644 return back;
645 }
646
647
648
649 /** Compare two integer values.
650 @param l Left value.
651 @param r Right value.
652 @return Comparison result.
653 */
654 static
655 int
dk4gra_pdf_compare_int(int l,int r)656 dk4gra_pdf_compare_int(int l, int r)
657 {
658 int back = 0;
659 if (l > r) {
660 back = 1;
661 }
662 else {
663 if (l < r) { back = -1; }
664 }
665 return back;
666 }
667
668
669
670 /** Compare two XObjects whether or not they contain the same file
671 and frame number using same conversion settings.
672 @param l Left object.
673 @param r Right object.
674 @param cr Comparison criteria (ignored).
675 @return Comparison result.
676 */
677 static
678 int
dk4gra_pdf_compare_xo(const void * l,const void * r,int cr)679 dk4gra_pdf_compare_xo(
680 const void *l,
681 const void *r,
682 int cr
683 #if DK4_HAVE_ATTRIBUTE_UNUSED
684 __attribute__((unused))
685 #endif
686 )
687 {
688 const dk4_gra_pdf_img_xo_t *pl;
689 const dk4_gra_pdf_img_xo_t *pr;
690 int back = 0;
691
692 #if !DK4_HAVE_ATTRIBUTE_UNUSED
693 (void)cr;
694 #endif
695
696 if (NULL != l) {
697 if (NULL != r) {
698 pl = (const dk4_gra_pdf_img_xo_t *)l;
699 pr = (const dk4_gra_pdf_img_xo_t *)r;
700 /*
701 Check whether or not both XObjects use the same file
702 */
703 back = dk4gra_pdf_xo_check_same_file(pl, pr);
704 /*
705 If the same file is used for both XObjects, check
706 whether the same settings are used
707 */
708 if (0 == back) {
709 if (pl->fno > pr->fno) {
710 back = 1;
711 }
712 else {
713 if (pl->fno < pr->fno) {
714 back = -1;
715 }
716 }
717 }
718 if (0 == back) {
719 back = dk4gra_pdf_compare_int(pl->dct, pr->dct);
720
721 }
722 if (0 == back) {
723 back = dk4gra_pdf_compare_int(pl->ipol, pr->ipol);
724
725 }
726 if (0 == back) {
727 back = dk4gra_pdf_compare_int(pl->cs, pr->cs);
728
729 }
730 if (0 == back) {
731 back = dk4gra_pdf_compare_int(pl->bpc, pr->bpc);
732
733 }
734 if (0 == back) {
735 back = dk4gra_pdf_compare_int(pl->deci, pr->deci);
736
737 }
738 }
739 else {
740 back = 1;
741 }
742 }
743 else {
744 if (NULL != r) {
745 back = -1;
746 }
747 }
748
749 return back;
750 }
751
752
753
754 /** Destroy XObject structure, release resources.
755 @param puxo XObject structure to destroy.
756 */
757 void
dk4gra_pdf_xo_delete(dk4_gra_pdf_img_xo_t * puxo)758 dk4gra_pdf_xo_delete(
759 dk4_gra_pdf_img_xo_t *puxo
760 )
761 {
762
763 #if DK4_USE_ASSERT
764 assert(NULL != puxo);
765 #endif
766 if (NULL != puxo) {
767
768 if (NULL != puxo->i_mb) {
769
770 dk4membuf_close(puxo->i_mb);
771
772 } puxo->i_mb = NULL;
773
774 if (NULL != puxo->m_mb) {
775
776 dk4membuf_close(puxo->m_mb);
777
778 } puxo->m_mb = NULL;
779
780 if (NULL != puxo->fn) {
781
782 dk4mem_free((void *)(puxo->fn));
783
784 } puxo->fn = NULL;
785
786 dk4mem_free(puxo);
787
788 }
789
790 }
791
792
793
794 /** Destroy page structure, release resources.
795 @param pptr Page to destroy.
796 */
797 static
798 void
dk4gra_pgf_page_delete(dk4_gra_pdf_page_t * pptr)799 dk4gra_pgf_page_delete(
800 dk4_gra_pdf_page_t *pptr
801 )
802 {
803
804 #if DK4_USE_ASSERT
805 assert(NULL != pptr);
806 #endif
807 if (NULL != pptr) {
808 if (NULL != pptr->s_uxo) {
809 if (NULL != pptr->i_uxo) {
810 dk4sto_it_close(pptr->i_uxo);
811 }
812 dk4sto_close(pptr->s_uxo);
813 } pptr->s_uxo = NULL; pptr->i_uxo = NULL;
814 if (NULL != pptr->costrm) {
815
816 dk4stream_close(pptr->costrm, NULL);
817
818 } pptr->costrm = NULL;
819 if (NULL != pptr->memstrm) {
820
821 dk4stream_close(pptr->memstrm, NULL);
822
823 } pptr->memstrm = NULL;
824 if (NULL != pptr->membuf) {
825
826 dk4membuf_close(pptr->membuf);
827
828 } pptr->membuf = NULL;
829 pptr->outstrm = NULL;
830 dk4mem_free(pptr);
831 }
832
833 }
834
835
836
837 /** Write path construction commands to output stream.
838 @param os Output stream.
839 @param gra Output structure.
840 @param backptr Address of success variable to reset on errors.
841 @param erp Error report, may be NULL.
842 */
843 static
844 void
dk4gra_pdf_page_box_path(dk4_stream_t * os,dk4_gra_t * gra,int * backptr,dk4_er_t * erp)845 dk4gra_pdf_page_box_path(
846 dk4_stream_t *os,
847 dk4_gra_t *gra,
848 int *backptr,
849 dk4_er_t *erp
850 )
851 {
852 #if DK4_USE_ASSERT
853 assert(NULL != gra);
854 assert(NULL != os);
855 #endif
856 /* 0 0 newpathmoveto
857 */
858 dk4gra_pdf_i_outstream_kw(os, 16, backptr, erp);
859 dk4gra_pdf_i_outstream_kw(os, 17, backptr, erp);
860 dk4gra_pdf_i_outstream_kw(os, 4, backptr, erp);
861
862 /* w 0 lineto */
863 dk4gratool_stream_uint(os, gra->w, 0, backptr, erp);
864 dk4gra_pdf_i_outstream_kw(os, 18, backptr, erp);
865 dk4gra_pdf_i_outstream_kw(os, 5, backptr, erp);
866
867 /* w h lineto
868 */
869 dk4gratool_stream_uint(os, gra->w, 0, backptr, erp);
870 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
871 dk4gratool_stream_uint(os, gra->h, 0, backptr, erp);
872 dk4gra_pdf_i_outstream_kw(os, 5, backptr, erp);
873
874 /* 0 h lineto
875 */
876 dk4gra_pdf_i_outstream_kw(os, 16, backptr, erp);
877 dk4gratool_stream_uint(os, gra->h, 0, backptr, erp);
878 dk4gra_pdf_i_outstream_kw(os, 5, backptr, erp);
879
880 /* closepath
881 */
882 dk4gra_pdf_i_outstream_kw(os, 7, backptr, erp);
883 }
884
885
886
887 /** Create new page, allocate resources.
888 @param pageno Page number of new page.
889 @param flags Flags to open new page.
890 @param erp Error report, may be NULL.
891 @return Valid pointer on success, NULL on error.
892 */
893 static
894 dk4_gra_pdf_page_t *
dk4gra_pdf_page_new(size_t pageno,dk4_gra_t * gra,int flags,dk4_er_t * erp)895 dk4gra_pdf_page_new(
896 size_t pageno,
897 dk4_gra_t *gra,
898 int flags,
899 dk4_er_t *erp
900 )
901 {
902 dk4_gra_pdf_page_t *back = NULL;
903 int ok = 0;
904
905 #if DK4_USE_ASSERT
906 assert(NULL != gra);
907 #endif
908 #if DK4GRA_PDF_FORCE_UNCOMPRESSED
909 flags |= DK4_GRA_PAGE_FLAG_NOT_COMPRESSED;
910 #endif
911
912 back = dk4mem_new(dk4_gra_pdf_page_t,1,erp);
913 if (NULL == back) {
914 goto finished;
915 }
916 back->membuf = NULL;
917 back->memstrm = NULL;
918 back->costrm = NULL;
919 back->outstrm = NULL;
920 back->s_uxo = NULL;
921 back->i_uxo = NULL;
922 back->pageno = pageno;
923 back->objno = 0;
924 back->flags = flags;
925 dk4gratool_initialize_attributes(&(back->attr));
926 back->membuf = dk4membuf_open(erp);
927 if (NULL == back->membuf) {
928 goto finished;
929 }
930 back->memstrm = dk4stream_open_membuf_writer(back->membuf, erp);
931 if (NULL == back->membuf) {
932 goto finished;
933 }
934 if (0 != (flags & DK4_GRA_PAGE_FLAG_NOT_COMPRESSED)) {
935 back->outstrm = back->memstrm;
936 ok = 1;
937 }
938 else {
939 back->costrm = dk4strmco_open(
940 back->memstrm,
941 DK4_STRMCO_PP_NONE, DK4_STRMCO_CO_FLATE, DK4_STRMCO_OE_NONE,
942 0, erp
943 );
944 if (NULL != back->costrm) {
945 back->outstrm = back->costrm;
946 ok = 1;
947 }
948 }
949 if (1 == ok) {
950 /* TODO: gsave */
951 dk4gra_pdf_i_outstream_kw(back->outstrm, 2, &ok, erp);
952 /* clip */
953 if (0 == (flags & DK4_GRA_PAGE_FLAG_NO_CLIP)) {
954 dk4gra_pdf_page_box_path(back->outstrm, gra, &ok, erp);
955 dk4gra_pdf_i_outstream_kw(back->outstrm, 13, &ok, erp);
956 }
957 /* fill */
958 if (0 == (flags & DK4_GRA_PAGE_FLAG_NO_BG)) {
959 dk4gra_pdf_i_outstream_kw(back->outstrm, 15, &ok, erp);
960 dk4gra_pdf_page_box_path(back->outstrm, gra, &ok, erp);
961 dk4gra_pdf_i_outstream_kw(back->outstrm, 9, &ok, erp);
962 }
963 }
964
965 finished:
966 if ((NULL != back) && (0 == ok)) {
967 dk4gra_pgf_page_delete(back);
968 back = NULL;
969 }
970
971
972 return back;
973 }
974
975
976
977 /** Change current fill or stroke color if necessary.
978 @param os Output stream.
979 @param cpactive Active color.
980 @param cprequested Requested color.
981 @param fill Flag: Fill color (0=stroke color).
982 @param backptr Address of success variable to reset on errors.
983 @param erp Error report, may be NULL.
984 */
985 static
986 void
dk4gra_pdf_set_color_if_necessary(dk4_stream_t * os,dk4gra_col_t * cpactive,dk4gra_col_t * cprequested,int fill,int * backptr,dk4_er_t * erp)987 dk4gra_pdf_set_color_if_necessary(
988 dk4_stream_t *os,
989 dk4gra_col_t *cpactive,
990 dk4gra_col_t *cprequested,
991 int fill,
992 int *backptr,
993 dk4_er_t *erp
994 )
995 {
996 #if DK4_USE_ASSERT
997 assert(NULL != os);
998 assert(NULL != cpactive);
999 assert(NULL != cprequested);
1000 #endif
1001 if (dk4gratool_colors_differ(cpactive, cprequested)) {
1002 switch (cprequested->what) {
1003 case DK4_GRA_COL_SPEC_GRAY : {
1004 dk4gratool_stream_double(
1005 os, cprequested->data.gray, backptr, erp
1006 );
1007 dk4gra_pdf_i_outstream_kw(
1008 os, ((0 != fill) ? (19) : (20)), backptr, erp
1009 );
1010 } break;
1011 case DK4_GRA_COL_SPEC_CMYK : {
1012 dk4gratool_stream_double(
1013 os, cprequested->data.cmyk.c, backptr, erp
1014 );
1015 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1016 dk4gratool_stream_double(
1017 os, cprequested->data.cmyk.m, backptr, erp
1018 );
1019 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1020 dk4gratool_stream_double(
1021 os, cprequested->data.cmyk.y, backptr, erp
1022 );
1023 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1024 dk4gratool_stream_double(
1025 os, cprequested->data.cmyk.k, backptr, erp
1026 );
1027 dk4gra_pdf_i_outstream_kw(
1028 os, ((0 != fill) ? (21) : (22)), backptr, erp
1029 );
1030 } break;
1031 default : { /* RGB */
1032 dk4gratool_stream_double(
1033 os, cprequested->data.rgb.r, backptr, erp
1034 );
1035 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1036 dk4gratool_stream_double(
1037 os, cprequested->data.rgb.g, backptr, erp
1038 );
1039 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1040 dk4gratool_stream_double(
1041 os, cprequested->data.rgb.b, backptr, erp
1042 );
1043 dk4gra_pdf_i_outstream_kw(
1044 os, ((0 != fill) ? (23) : (24)), backptr, erp
1045 );
1046 } break;
1047 }
1048 dk4mem_cpy(cpactive, cprequested, sizeof(dk4gra_col_t), erp);
1049 }
1050 }
1051
1052
1053
1054 /** Write dash setup to output stream.
1055 @param os Output stream.
1056 @param da Dash length array.
1057 @param szda Size of dash length array (number of elements).
1058 @param phase Phase for dash pattern.
1059 @param backptr Address of success variable to reset on errors.
1060 @param erp Error report, may be NULL.
1061 */
1062 static
1063 void
dk4gra_pdf_dash_out(dk4_stream_t * os,double * da,size_t szda,double phase,int * backptr,dk4_er_t * erp)1064 dk4gra_pdf_dash_out(
1065 dk4_stream_t *os,
1066 double *da,
1067 size_t szda,
1068 double phase,
1069 int *backptr,
1070 dk4_er_t *erp
1071 )
1072 {
1073 size_t i;
1074 #if DK4_USE_ASSERT
1075 assert(NULL != os);
1076 assert(NULL != da);
1077 assert(0 < szda);
1078 #endif
1079 dk4gra_pdf_i_outstream_kw(os, 33, backptr, erp);
1080 for (i = 0; i < szda; i++) {
1081 if (0 < i) {
1082 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1083 }
1084 dk4gratool_stream_double(os, da[i], backptr, erp);
1085 }
1086 dk4gra_pdf_i_outstream_kw(os, 34, backptr, erp);
1087 dk4gratool_stream_double(os, phase, backptr, erp);
1088 dk4gra_pdf_i_outstream_kw(os, 35, backptr, erp);
1089 }
1090
1091
1092
1093 /** Begin a new object, save start position.
1094 @param os Output stream.
1095 @param gra Output structure.
1096 @param objno Number of new object.
1097 @param backptr Address of success variable to reset on errors.
1098 @param erp Error report, may be NULL.
1099 */
1100 static
1101 void
dk4gra_pdf_begin_object(dk4_stream_t * os,dk4_gra_t * gra,size_t objno,int * backptr,dk4_er_t * erp)1102 dk4gra_pdf_begin_object(
1103 dk4_stream_t *os,
1104 dk4_gra_t *gra,
1105 size_t objno,
1106 int *backptr,
1107 dk4_er_t *erp
1108 )
1109 {
1110 dk4_gra_pdf_objpos_t *ppos = NULL;
1111 dk4_um_t position;
1112 #if DK4_USE_ASSERT
1113 assert(NULL != gra);
1114 assert(NULL != os);
1115 #endif
1116 position = dk4stream_bytes_written(os);
1117 dk4gratool_stream_uint(os, objno, 0, backptr, erp);
1118 dk4gra_pdf_i_outstream_kw(os, 37, backptr, erp);
1119 ppos = dk4mem_new(dk4_gra_pdf_objpos_t,1,erp);
1120 if (NULL != ppos) {
1121 ppos->pos = position;
1122 ppos->num = objno;
1123 if (0 == dk4sto_add(gra->out.pdf.s_objpos, ppos, erp)) {
1124 dk4mem_free(ppos);
1125 if (NULL != backptr) { *backptr = 0; }
1126 }
1127 }
1128 else {
1129 if (NULL != backptr) { *backptr = 0; }
1130 }
1131 }
1132
1133
1134
1135 /** End current object.
1136 @param os Output stream.
1137 @param backptr Address of success variable to reset on errors.
1138 @param erp Error report, may be NULL.
1139 */
1140 static
1141 void
dk4gra_pdf_end_object(dk4_stream_t * os,int * backptr,dk4_er_t * erp)1142 dk4gra_pdf_end_object(
1143 dk4_stream_t *os,
1144 int *backptr,
1145 dk4_er_t *erp
1146 )
1147 {
1148 #if DK4_USE_ASSERT
1149 assert(NULL != os);
1150 #endif
1151 dk4gra_pdf_i_outstream_kw(os, 38, backptr, erp);
1152 }
1153
1154
1155
1156 /** Enumerate pages (assign object numbers to pages).
1157 @param gra Output structure.
1158 @param erp Error report, may be NULL.
1159 @return 1 on success, 0 on error.
1160 */
1161 static
1162 int
dk4gra_pdf_enumerate_pages(dk4_gra_t * gra,dk4_er_t * erp)1163 dk4gra_pdf_enumerate_pages(
1164 dk4_gra_t *gra,
1165 dk4_er_t *erp
1166 )
1167 {
1168 dk4_gra_pdf_page_t *bptr;
1169 int back = 1;
1170 #if DK4_USE_ASSERT
1171 assert(NULL != gra);
1172 #endif
1173 dk4sto_it_reset(gra->i_pages);
1174 do {
1175 bptr = (dk4_gra_pdf_page_t *)dk4sto_it_next(gra->i_pages);
1176 if (NULL != bptr) {
1177 /*
1178 If gsave was issued at start of stream, issue grestore now
1179 */
1180 if (0 == ((bptr->flags) & DK4_GRA_PAGE_FLAG_NO_CLIP)) {
1181 if (NULL != bptr->outstrm) {
1182 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 3, &back, erp);
1183 }
1184 }
1185 bptr->outstrm = NULL;
1186 /*
1187 Close compressed stream
1188 */
1189 if (NULL != bptr->costrm) {
1190 if (0 == dk4stream_close(bptr->costrm, erp)) { back = 0; }
1191 }
1192 bptr->costrm = NULL;
1193 /*
1194 Close memory stream
1195 */
1196 if (NULL != bptr->memstrm) {
1197 if (0 == dk4stream_close(bptr->memstrm, erp)) { back = 0; }
1198 }
1199 bptr->memstrm = NULL;
1200 /*
1201 Assign object number
1202 */
1203 if ((SIZE_MAX - 1) > gra->out.pdf.nextobj) {
1204 bptr->objno = gra->out.pdf.nextobj;
1205 gra->out.pdf.nextobj += 2;
1206 }
1207 else {
1208 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
1209 back = 0;
1210 }
1211 }
1212 } while ((1 == back) && (NULL != bptr));
1213 if (SIZE_MAX <= gra->out.pdf.nextobj) {
1214 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
1215 back = 0;
1216 }
1217 return back;
1218 }
1219
1220
1221
1222 static
1223 void
dk4gra_pdf_one_xobject(dk4_stream_t * os,dk4_gra_t * gra,dk4_gra_pdf_img_xo_t * puxo,int * backptr,dk4_er_t * erp)1224 dk4gra_pdf_one_xobject(
1225 dk4_stream_t *os,
1226 dk4_gra_t *gra,
1227 dk4_gra_pdf_img_xo_t *puxo,
1228 int *backptr,
1229 dk4_er_t *erp
1230 )
1231 {
1232 size_t szmb;
1233
1234 #if DK4_USE_ASSERT
1235 assert(NULL != gra);
1236 assert(NULL != os);
1237 assert(NULL != puxo);
1238 #endif
1239 /* Image object
1240 */
1241 dk4gra_pdf_begin_object(os, gra, puxo->objno, backptr, erp);
1242 /* << */
1243 dk4gra_pdf_i_outstream_kw(os, 39, backptr, erp);
1244 /* /Type /XObject */
1245 dk4gra_pdf_i_outstream_kw(os, 73, backptr, erp);
1246 /* /Subtype /Image */
1247 dk4gra_pdf_i_outstream_kw(os, 74, backptr, erp);
1248 /* /Width ... */
1249 dk4gra_pdf_i_outstream_kw(os, 75, backptr, erp);
1250 dk4gratool_stream_uint(os, (dk4_um_t)(puxo->width), 0, backptr, erp);
1251 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1252 /* /Height ... */
1253 dk4gra_pdf_i_outstream_kw(os, 76, backptr, erp);
1254 dk4gratool_stream_uint(os, (dk4_um_t)(puxo->height), 0, backptr, erp);
1255 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1256 /* /BitsPerComponent ... */
1257 dk4gra_pdf_i_outstream_kw(os, 77, backptr, erp);
1258 dk4gratool_stream_uint(os, puxo->bpc, 0, backptr, erp);
1259 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1260 /* /ColorSpace ... */
1261 switch (puxo->cs) {
1262 case DK4_CS_CMYK : {
1263 dk4gra_pdf_i_outstream_kw(os, 80, backptr, erp);
1264 } break;
1265 case DK4_CS_GRAY : case DK4_CS_GRAY_ALPHA : {
1266 dk4gra_pdf_i_outstream_kw(os, 79, backptr, erp);
1267 } break;
1268 default : {
1269 dk4gra_pdf_i_outstream_kw(os, 78, backptr, erp);
1270 } break;
1271 }
1272 if ((0 != puxo->mobjno) && (NULL != puxo->m_mb)) {
1273 /* /SMask ... */
1274 dk4gra_pdf_i_outstream_kw(os, 81, backptr, erp);
1275 dk4gratool_stream_uint(os, puxo->mobjno, 0, backptr, erp);
1276 dk4gra_pdf_i_outstream_kw(os, 57, backptr, erp);
1277 }
1278 /* /Interpolate ... */
1279 if (0 != puxo->ipol) {
1280 dk4gra_pdf_i_outstream_kw(os, 82, backptr, erp);
1281 }
1282 /* /Filter ... */
1283 dk4gra_pdf_i_outstream_kw(os,((0 != puxo->dct) ? (83) : (67)),backptr,erp);
1284 /* /Length ... */
1285 dk4gra_pdf_i_outstream_kw(os, 66, backptr, erp);
1286
1287 if (0 == dk4membuf_size(&szmb, puxo->i_mb, erp)) {
1288 szmb = 0;
1289 }
1290 dk4gratool_stream_uint(os, szmb, 0, backptr, erp);
1291 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1292 if (0 != puxo->deci) {
1293 switch (puxo->cs) {
1294 case DK4_CS_CMYK : {
1295 dk4gra_pdf_i_outstream_kw(os, 85, backptr, erp);
1296 } break;
1297 case DK4_CS_RGB_ALPHA : {
1298 dk4gra_pdf_i_outstream_kw(os, 85, backptr, erp);
1299 } break;
1300 case DK4_CS_RGB : {
1301 dk4gra_pdf_i_outstream_kw(os, 86, backptr, erp);
1302 } break;
1303 case DK4_CS_GRAY_ALPHA : {
1304 dk4gra_pdf_i_outstream_kw(os, 87, backptr, erp);
1305 } break;
1306 case DK4_CS_GRAY : {
1307 dk4gra_pdf_i_outstream_kw(os, 88, backptr, erp);
1308 } break;
1309 }
1310 }
1311 /* >> */
1312 dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp);
1313 /* stream */
1314 dk4gra_pdf_i_outstream_kw(os, 68, backptr, erp);
1315 /* Memory buffer contents */
1316 if (0 == dk4membuf_to_stream(os, puxo->i_mb, erp)) {
1317 if (NULL != backptr) { *backptr = 0; }
1318 }
1319 /* endstream */
1320 dk4gra_pdf_i_outstream_kw(os, 69, backptr, erp);
1321 dk4gra_pdf_end_object(os, backptr, erp);
1322 /*
1323 Mask object, if available
1324 */
1325 if ((0 != puxo->mobjno) && (NULL != puxo->m_mb)) {
1326 dk4gra_pdf_begin_object(os, gra, puxo->mobjno, backptr, erp);
1327 /* << */
1328 dk4gra_pdf_i_outstream_kw(os, 39, backptr, erp);
1329
1330 /* /Type /XObject */
1331 dk4gra_pdf_i_outstream_kw(os, 73, backptr, erp);
1332 /* /Subtype /Image */
1333 dk4gra_pdf_i_outstream_kw(os, 74, backptr, erp);
1334 /* /Width ... */
1335 dk4gra_pdf_i_outstream_kw(os, 75, backptr, erp);
1336 dk4gratool_stream_uint(os, (dk4_um_t)(puxo->width), 0, backptr, erp);
1337 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1338 /* /Height ... */
1339 dk4gra_pdf_i_outstream_kw(os, 76, backptr, erp);
1340 dk4gratool_stream_uint(os, (dk4_um_t)(puxo->height), 0, backptr, erp);
1341 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1342 /* /BitsPerComponent ... */
1343 dk4gra_pdf_i_outstream_kw(os, 77, backptr, erp);
1344 dk4gratool_stream_uint(os, puxo->bpc, 0, backptr, erp);
1345 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1346 /* /ColorSpace /DeviceGray */
1347 dk4gra_pdf_i_outstream_kw(os, 79, backptr, erp);
1348 /* /Filter /FlateDecode */
1349 dk4gra_pdf_i_outstream_kw(os, 67, backptr, erp);
1350 /* /Length ... */
1351
1352 if (0 == dk4membuf_size(&szmb, puxo->m_mb, erp)) {
1353 szmb = 0;
1354 }
1355 dk4gra_pdf_i_outstream_kw(os, 66, backptr, erp);
1356 dk4gratool_stream_uint(os, szmb, 0, backptr, erp);
1357 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1358 /* >> */
1359 dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp);
1360 /* stream */
1361 dk4gra_pdf_i_outstream_kw(os, 68, backptr, erp);
1362 /* Memory buffer contents */
1363 if (0 == dk4membuf_to_stream(os, puxo->m_mb, erp)) {
1364 if (NULL != backptr) { *backptr = 0; }
1365 }
1366 /* endstream */
1367 dk4gra_pdf_i_outstream_kw(os, 69, backptr, erp);
1368 dk4gra_pdf_end_object(os, backptr, erp);
1369 }
1370 }
1371
1372
1373
1374 static
1375 void
dk4gra_pdf_one_page(dk4_stream_t * os,dk4_gra_t * gra,dk4_gra_pdf_page_t * bptr,int * backptr,dk4_er_t * erp)1376 dk4gra_pdf_one_page(
1377 dk4_stream_t *os,
1378 dk4_gra_t *gra,
1379 dk4_gra_pdf_page_t *bptr,
1380 int *backptr,
1381 dk4_er_t *erp
1382 )
1383 {
1384 dk4_gra_pdf_img_xo_t *xo;
1385 size_t mbs = 0;
1386
1387 #if DK4_USE_ASSERT
1388 assert(NULL != gra);
1389 assert(NULL != os);
1390 #endif
1391 dk4gra_pdf_begin_object(os, gra, bptr->objno, backptr, erp);
1392 /* << */
1393 dk4gra_pdf_i_outstream_kw(os, 39, backptr, erp);
1394 /* /Type /Page */
1395 dk4gra_pdf_i_outstream_kw(os, 58, backptr, erp);
1396 /* /Parent 3 0 R */
1397 dk4gra_pdf_i_outstream_kw(os, 59, backptr, erp);
1398 /* /MediaBox [ 0 0 595 842 ] */
1399 dk4gra_pdf_i_outstream_kw(os, 60, backptr, erp);
1400 dk4gratool_stream_uint(os, gra->w, 0, backptr, erp);
1401 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1402 dk4gratool_stream_uint(os, gra->h, 0, backptr, erp);
1403 dk4gra_pdf_i_outstream_kw(os, 56, backptr, erp);
1404 /* /CropBox [ 0 0 595 842 ] */
1405 dk4gra_pdf_i_outstream_kw(os, 61, backptr, erp);
1406 dk4gratool_stream_uint(os, gra->w, 0, backptr, erp);
1407 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1408 dk4gratool_stream_uint(os, gra->h, 0, backptr, erp);
1409 dk4gra_pdf_i_outstream_kw(os, 56, backptr, erp);
1410 /* /Resources << */
1411 dk4gra_pdf_i_outstream_kw(os, 62, backptr, erp);
1412 /* /ProcSet [ /PDF /ImageB /ImageC ] */
1413 dk4gra_pdf_i_outstream_kw(os, 63, backptr, erp);
1414 if ((NULL != bptr->s_uxo) && (NULL != bptr->i_uxo)) {
1415 dk4gra_pdf_i_outstream_kw(os, 64, backptr, erp);
1416 dk4sto_it_reset(bptr->i_uxo);
1417 do {
1418 xo = (dk4_gra_pdf_img_xo_t *)dk4sto_it_next(bptr->i_uxo);
1419 if (NULL != xo) {
1420 dk4gra_pdf_i_outstream_kw(os, 71, backptr, erp);
1421 dk4gratool_stream_uint(os, xo->objno, 0, backptr, erp);
1422 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
1423 dk4gratool_stream_uint(os, xo->objno, 0, backptr, erp);
1424 dk4gra_pdf_i_outstream_kw(os, 57, backptr, erp);
1425 }
1426 } while (NULL != xo);
1427 dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp);
1428 }
1429 /* >> */
1430 dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp);
1431 /* /Contents 12 0 R */
1432 dk4gra_pdf_i_outstream_kw(os, 65, backptr, erp);
1433 dk4gratool_stream_uint(os, (bptr->objno + 1), 0, backptr, erp);
1434 dk4gra_pdf_i_outstream_kw(os, 57, backptr, erp);
1435 /* >> */
1436 dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp);
1437 dk4gra_pdf_end_object(os, backptr, erp);
1438
1439 dk4gra_pdf_begin_object(os, gra, (bptr->objno + 1), backptr, erp);
1440 /* << */
1441 dk4gra_pdf_i_outstream_kw(os, 39, backptr, erp);
1442 /* /Length ... */
1443
1444 if (0 == dk4membuf_size(&mbs, bptr->membuf, erp)) {
1445
1446 if (NULL != backptr) { *backptr = 0; }
1447 }
1448 dk4gra_pdf_i_outstream_kw(os, 66, backptr, erp);
1449 dk4gratool_stream_uint(os, mbs, 0, backptr, erp);
1450 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1451 /* /Filter ... */
1452
1453 if (0 == ((bptr->flags) & DK4_GRA_PAGE_FLAG_NOT_COMPRESSED)) {
1454 dk4gra_pdf_i_outstream_kw(os, 67, backptr, erp);
1455 }
1456 /* >> */
1457 dk4gra_pdf_i_outstream_kw(os, 40, backptr, erp);
1458 /* stream */
1459 dk4gra_pdf_i_outstream_kw(os, 68, backptr, erp);
1460 /* data */
1461 if (0 == dk4membuf_to_stream(os, bptr->membuf, erp)) {
1462 if (NULL != backptr) { *backptr = 0; }
1463 }
1464 /* endstream */
1465 dk4gra_pdf_i_outstream_kw(os, 69, backptr, erp);
1466 dk4gra_pdf_end_object(os, backptr, erp);
1467
1468 }
1469
1470
1471
1472 static
1473 void
dk4gra_pdf_xref_section(dk4_stream_t * os,dk4_gra_t * gra,int * backptr,dk4_er_t * erp)1474 dk4gra_pdf_xref_section(
1475 dk4_stream_t *os,
1476 dk4_gra_t *gra,
1477 int *backptr,
1478 dk4_er_t *erp
1479 )
1480 {
1481 dk4_gra_pdf_objpos_t *objpos;
1482 dk4_um_t startxrefpos;
1483 #if DK4_USE_ASSERT
1484 assert(NULL != gra);
1485 assert(NULL != os);
1486 #endif
1487 startxrefpos = dk4stream_bytes_written(os);
1488 dk4gra_pdf_i_outstream_kw(os, 45, backptr, erp);
1489 dk4gratool_stream_uint(os, gra->out.pdf.nextobj, 0, backptr, erp);
1490 dk4gra_pdf_i_outstream_kw(os, 0, backptr, erp);
1491 dk4gra_pdf_i_outstream_kw(os, 46, backptr, erp);
1492 dk4sto_it_reset(gra->out.pdf.i_objpos);
1493 do {
1494 objpos = (dk4_gra_pdf_objpos_t *)dk4sto_it_next(gra->out.pdf.i_objpos);
1495 if (NULL != objpos) {
1496 dk4gratool_stream_uint(os, objpos->pos, 10, backptr, erp);
1497 dk4gra_pdf_i_outstream_kw(os, 47, backptr, erp);
1498 }
1499 } while (NULL != objpos);
1500 dk4gra_pdf_i_outstream_kw(os, 48, backptr, erp);
1501 dk4gratool_stream_uint(os, gra->out.pdf.nextobj, 0, backptr, erp);
1502 dk4gra_pdf_i_outstream_kw(os, 49, backptr, erp);
1503 dk4gratool_stream_uint(os, startxrefpos, 0, backptr, erp);
1504 dk4gra_pdf_i_outstream_kw(os, 50, backptr, erp);
1505 }
1506
1507
1508 /** Write PDF file.
1509 @param fout Output file, opened for binary write operations.
1510 @param gra Output structure.
1511 @param erp Error report, may be NULL.
1512 @return 1 on success, 0 on error.
1513 */
1514 static
1515 int
dk4gra_pdf_file(FILE * fout,dk4_gra_t * gra,dk4_er_t * erp)1516 dk4gra_pdf_file(
1517 FILE *fout,
1518 dk4_gra_t *gra,
1519 dk4_er_t *erp
1520 )
1521 {
1522 char timestamp[64];
1523 dk4_gra_pdf_img_xo_t *puxo;
1524 dk4_gra_pdf_page_t *bptr;
1525 dk4_stream_t *os = NULL;
1526 int back = 0;
1527
1528 #if DK4_USE_ASSERT
1529 assert(NULL != gra);
1530 assert(NULL != fout);
1531 #endif
1532 if (0 == dk4gra_pdf_timestamp(timestamp, sizeof(timestamp), erp)) {
1533 goto finished;
1534 }
1535 os = dk4stream_open_for_file(fout, DK4_STREAM_WRITE, 4096, 4096, erp);
1536 if (NULL == os) { goto finished; }
1537 back = dk4gra_pdf_enumerate_pages(gra, erp);
1538
1539 /* PDF line at start of file
1540 */
1541 dk4gra_pdf_i_outstream_kw(os, 36, &back, erp);
1542
1543 /* Object 1 is Info object.
1544 */
1545 dk4gra_pdf_begin_object(os, gra, 1, &back, erp);
1546 /* << */
1547 dk4gra_pdf_i_outstream_kw(os, 39, &back, erp);
1548 /* /Producer (http://sourceforge.net/p/dktools/wiki/Home/) */
1549 dk4gra_pdf_i_outstream_kw(os, 41, &back, erp);
1550 /* /CreationDate (D:20170324235818) */
1551 dk4gra_pdf_i_outstream_kw(os, 42, &back, erp);
1552 if (0 == dk4stream_write_char_string(os, timestamp, erp)) { back = 0; }
1553 dk4gra_pdf_i_outstream_kw(os, 44, &back, erp);
1554 /* /ModDate (D:20170324235818) */
1555 dk4gra_pdf_i_outstream_kw(os, 43, &back, erp);
1556 if (0 == dk4stream_write_char_string(os, timestamp, erp)) { back = 0; }
1557 dk4gra_pdf_i_outstream_kw(os, 44, &back, erp);
1558 /* >> */
1559 dk4gra_pdf_i_outstream_kw(os, 40, &back, erp);
1560 dk4gra_pdf_end_object(os, &back, erp);
1561
1562 /* Object 2 is Root object.
1563 */
1564 dk4gra_pdf_begin_object(os, gra, 2, &back, erp);
1565 /* << */
1566 dk4gra_pdf_i_outstream_kw(os, 39, &back, erp);
1567 /* /Type /Catalog */
1568 dk4gra_pdf_i_outstream_kw(os, 51, &back, erp);
1569 /* /Pages 3 0 R */
1570 dk4gra_pdf_i_outstream_kw(os, 52, &back, erp);
1571 /* >> */
1572 dk4gra_pdf_i_outstream_kw(os, 40, &back, erp);
1573 dk4gra_pdf_end_object(os, &back, erp);
1574
1575 /* Object 3 is Pages object.
1576 */
1577 dk4gra_pdf_begin_object(os, gra, 3, &back, erp);
1578 /* << */
1579 dk4gra_pdf_i_outstream_kw(os, 39, &back, erp);
1580 /* /Type /Pages */
1581 dk4gra_pdf_i_outstream_kw(os, 53, &back, erp);
1582 /* /Count ... */
1583 dk4gra_pdf_i_outstream_kw(os, 54, &back, erp);
1584 dk4gratool_stream_uint(os, gra->pages, 0, &back, erp);
1585 dk4gra_pdf_i_outstream_kw(os, 0, &back, erp);
1586 /* /Kids [ */
1587 dk4gra_pdf_i_outstream_kw(os, 55, &back, erp);
1588 dk4sto_it_reset(gra->i_pages);
1589 do {
1590 bptr = (dk4_gra_pdf_page_t *)dk4sto_it_next(gra->i_pages);
1591 if (NULL != bptr) {
1592 dk4gratool_stream_uint(os, bptr->objno, 0, &back, erp);
1593 dk4gra_pdf_i_outstream_kw(os, 57, &back, erp);
1594 }
1595 } while (NULL != bptr);
1596 /* ] */
1597 dk4gra_pdf_i_outstream_kw(os, 56, &back, erp);
1598 /* >> */
1599 dk4gra_pdf_i_outstream_kw(os, 40, &back, erp);
1600 dk4gra_pdf_end_object(os, &back, erp);
1601
1602 /* XOjects for images
1603 */
1604
1605 dk4sto_it_reset(gra->out.pdf.i_imagno);
1606 do {
1607 puxo = (dk4_gra_pdf_img_xo_t *)dk4sto_it_next(gra->out.pdf.i_imagno);
1608 if (NULL != puxo) {
1609
1610 dk4gra_pdf_one_xobject(os, gra, puxo, &back, erp);
1611 }
1612 } while (NULL != puxo);
1613
1614
1615 /* Pages and content streams
1616 */
1617 dk4sto_it_reset(gra->i_pages);
1618 do {
1619 bptr = (dk4_gra_pdf_page_t *)dk4sto_it_next(gra->i_pages);
1620 if (NULL != bptr) {
1621 dk4gra_pdf_one_page(os, gra, bptr, &back, erp);
1622 }
1623 } while (NULL != bptr);
1624
1625 /* Finishing section (xref)
1626 */
1627 dk4gra_pdf_xref_section(os, gra, &back, erp);
1628
1629 finished:
1630 if (NULL != os) { if (0 == dk4stream_close(os, erp)) { back = 0; } }
1631
1632 return back;
1633 }
1634
1635
1636
1637 void
dk4gra_pdf_close(dk4_gra_t * gra)1638 dk4gra_pdf_close(
1639 dk4_gra_t *gra
1640 )
1641 {
1642 dk4_gra_pdf_page_t *bptr;
1643 dk4_gra_pdf_img_xo_t *puxo;
1644 void *vptr;
1645
1646 #if DK4_USE_ASSERT
1647 assert(NULL != gra);
1648 #endif
1649 if (NULL == gra) {
1650 goto finished;
1651 }
1652
1653 /* Release object positions
1654 */
1655 if (NULL != gra->out.pdf.s_objpos) {
1656 if (NULL != gra->out.pdf.i_objpos) {
1657 dk4sto_it_reset(gra->out.pdf.i_objpos);
1658 do {
1659 vptr = dk4sto_it_next(gra->out.pdf.i_objpos);
1660 if (NULL != vptr) {
1661 dk4mem_free(vptr);
1662 }
1663 } while (NULL != vptr);
1664 dk4sto_it_close(gra->out.pdf.i_objpos);
1665 }
1666 dk4sto_close(gra->out.pdf.s_objpos);
1667 }
1668 gra->out.pdf.s_objpos = NULL;
1669 gra->out.pdf.i_objpos = NULL;
1670
1671 /* Release storage and iterator sorted by XObject object number
1672 */
1673 if (NULL != gra->out.pdf.s_imagno) {
1674 if (NULL != gra->out.pdf.i_imagno) {
1675 dk4sto_it_close(gra->out.pdf.i_imagno);
1676 }
1677 dk4sto_close(gra->out.pdf.s_imagno);
1678 }
1679 gra->out.pdf.s_imagno = NULL;
1680 gra->out.pdf.i_imagno = NULL;
1681
1682 /* Release pages
1683 */
1684
1685 if (NULL != gra->s_pages) {
1686 if (NULL != gra->i_pages) {
1687 dk4sto_it_reset(gra->i_pages);
1688 do {
1689 bptr = (dk4_gra_pdf_page_t *)dk4sto_it_next(gra->i_pages);
1690 if (NULL != bptr) {
1691 dk4gra_pgf_page_delete(bptr);
1692 }
1693 } while(NULL != bptr);
1694 dk4sto_it_close(gra->i_pages);
1695 }
1696 dk4sto_close(gra->s_pages);
1697 }
1698 gra->s_pages = NULL;
1699 gra->i_pages = NULL;
1700 gra->curpg = NULL;
1701
1702
1703 /* Release records for embedded images
1704 */
1705
1706 if (NULL != gra->out.pdf.s_images) {
1707 if (NULL != gra->out.pdf.i_images) {
1708 dk4sto_it_reset(gra->out.pdf.i_images);
1709 do {
1710 puxo = (dk4_gra_pdf_img_xo_t *)dk4sto_it_next(
1711 gra->out.pdf.i_images
1712 );
1713 if (NULL != puxo) {
1714
1715 dk4gra_pdf_xo_delete(puxo);
1716 }
1717 } while(NULL != puxo);
1718 dk4sto_it_close(gra->out.pdf.i_images);
1719 }
1720 dk4sto_close(gra->out.pdf.s_images);
1721 }
1722 gra->out.pdf.s_images = NULL;
1723 gra->out.pdf.i_images = NULL;
1724
1725
1726 /* Release file name and output structure itself
1727 */
1728 dk4gratool_close(gra);
1729
1730 finished:
1731
1732 return;
1733 }
1734
1735
1736
1737 dk4_gra_t *
dk4gra_pdf_open(const dkChar * fn,size_t w,size_t h,int docfl,dk4_er_t * erp)1738 dk4gra_pdf_open(
1739 const dkChar *fn,
1740 size_t w,
1741 size_t h,
1742 int docfl,
1743 dk4_er_t *erp
1744 )
1745 {
1746 dk4_gra_t *back = NULL;
1747 int ok = 0;
1748
1749 #if DK4_USE_ASSERT
1750 assert(NULL != fn);
1751 #endif
1752 /*
1753 Generic initialization
1754 */
1755 back = dk4gratool_open(fn, w, h, docfl, erp);
1756 if (NULL == back) {
1757 goto finished;
1758 }
1759 /* PDF specific initialization
1760 */
1761 back->out.pdf.s_imagno = NULL;
1762 back->out.pdf.i_imagno = NULL;
1763 back->out.pdf.s_images = NULL;
1764 back->out.pdf.i_images = NULL;
1765 back->out.pdf.s_objpos = NULL;
1766 back->out.pdf.i_objpos = NULL;
1767 back->out.pdf.nextobj = 4;
1768 back->out.pdf.unxo = 0;
1769 /*
1770 Pages container and iterator
1771 */
1772 back->s_pages = dk4sto_open(erp);
1773 if (NULL == back->s_pages) {
1774 goto finished;
1775 }
1776 (void)dk4sto_set_comp(back->s_pages, dk4gra_pdf_compare_pages_by_number, 0);
1777 back->i_pages = dk4sto_it_open(back->s_pages, erp);
1778 if (NULL == back->i_pages) {
1779 goto finished;
1780 }
1781 /*
1782 PDF XObject container and iterator for embedded images
1783 */
1784 back->out.pdf.s_images = dk4sto_open(erp);
1785 if (NULL == back->out.pdf.s_images) {
1786 goto finished;
1787 }
1788 (void)dk4sto_set_comp(back->out.pdf.s_images, dk4gra_pdf_compare_xo, 0);
1789 back->out.pdf.i_images = dk4sto_it_open(back->out.pdf.s_images, erp);
1790 if (NULL == back->out.pdf.i_images) {
1791 goto finished;
1792 }
1793 /* PDF XObject container and iterator sorted by object number
1794 */
1795 back->out.pdf.s_imagno = dk4sto_open(erp);
1796 if (NULL == back->out.pdf.s_imagno) {
1797 goto finished;
1798 }
1799 (void)dk4sto_set_comp(back->out.pdf.s_imagno,dk4gra_pdf_compare_used_xo,0);
1800 back->out.pdf.i_imagno = dk4sto_it_open(back->out.pdf.s_imagno, erp);
1801 if (NULL == back->out.pdf.i_imagno) {
1802 goto finished;
1803 }
1804 /* Storage and iterator for object start positions
1805 */
1806 back->out.pdf.s_objpos = dk4sto_open(erp);
1807 if (NULL == back->out.pdf.s_objpos) {
1808 goto finished;
1809 }
1810 (void)dk4sto_set_comp(back->out.pdf.s_objpos, dk4gra_pdf_compare_objpos, 0);
1811 back->out.pdf.i_objpos = dk4sto_it_open(back->out.pdf.s_objpos, erp);
1812 if (NULL == back->out.pdf.i_objpos) {
1813 goto finished;
1814 }
1815 /* Finally indicate success
1816 */
1817 ok = 1;
1818
1819 /* Cleanup section, destroy object if errors occured
1820 */
1821 finished:
1822 if ((NULL != back) && (0 == ok)) {
1823 dk4gra_pdf_close(back);
1824 back = NULL;
1825 }
1826
1827 return back;
1828 }
1829
1830
1831
1832 int
dk4gra_pdf_write_file_and_close(FILE * fout,dk4_gra_t * gra,dk4_er_t * erp)1833 dk4gra_pdf_write_file_and_close(
1834 FILE *fout,
1835 dk4_gra_t *gra,
1836 dk4_er_t *erp
1837 )
1838 {
1839 int back = 0;
1840 #if DK4_USE_ASSERT
1841 assert(NULL != gra);
1842 assert(NULL != fout);
1843 #endif
1844 back = dk4gra_pdf_file(fout, gra, erp);
1845 dk4gra_pdf_close(gra);
1846 return back;
1847 }
1848
1849
1850
1851 int
dk4gra_pdf_page(dk4_gra_t * gra,int flags,dk4_er_t * erp)1852 dk4gra_pdf_page(
1853 dk4_gra_t *gra,
1854 int flags,
1855 dk4_er_t *erp
1856 )
1857 {
1858 dk4_gra_pdf_page_t *curpg = NULL;
1859 int back = 0;
1860
1861 #if DK4_USE_ASSERT
1862 assert(NULL != gra);
1863 #endif
1864 /*
1865 Check number of pages already defined
1866 */
1867 if (SIZE_MAX == gra->pages) {
1868 dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
1869 goto finished;
1870 }
1871 curpg = dk4gra_pdf_page_new(gra->pages, gra, flags, erp);
1872 if (NULL == curpg) {
1873 goto finished;
1874 }
1875 if (0 == dk4sto_add(gra->s_pages, curpg, erp)) {
1876 dk4gra_pgf_page_delete(curpg);
1877 goto finished;
1878 }
1879 gra->curpg = curpg;
1880 gra->pages += 1;
1881 back = 1;
1882
1883 finished:
1884
1885 return back;
1886 }
1887
1888
1889
1890 int
dk4gra_pdf_gsave(dk4_gra_t * gra,dk4_er_t * erp)1891 dk4gra_pdf_gsave(
1892 dk4_gra_t *gra,
1893 dk4_er_t *erp
1894 )
1895 {
1896 dk4_gra_pdf_page_t *bptr;
1897 int back = 0;
1898 #if DK4_USE_ASSERT
1899 assert(NULL != gra);
1900 #endif
1901 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
1902 if (NULL == bptr->outstrm) {
1903 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1904 goto finished;
1905 }
1906 back = 1;
1907 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 2, &back, erp);
1908
1909 finished:
1910 return back;
1911 }
1912
1913
1914
1915 void
dk4gra_pdf_i_gsave(dk4_gra_t * gra,int * backptr,dk4_er_t * erp)1916 dk4gra_pdf_i_gsave(
1917 dk4_gra_t *gra,
1918 int *backptr,
1919 dk4_er_t *erp
1920 )
1921 {
1922 #if DK4_USE_ASSERT
1923 assert(NULL != gra);
1924 #endif
1925 if (0 == dk4gra_pdf_gsave(gra, erp)) {
1926 if (NULL != backptr) { *backptr = 0; }
1927 }
1928 }
1929
1930
1931
1932 int
dk4gra_pdf_grestore(dk4_gra_t * gra,dk4_er_t * erp)1933 dk4gra_pdf_grestore(
1934 dk4_gra_t *gra,
1935 dk4_er_t *erp
1936 )
1937 {
1938 dk4_gra_pdf_page_t *bptr;
1939 int back = 0;
1940 #if DK4_USE_ASSERT
1941 assert(NULL != gra);
1942 #endif
1943 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
1944 if (NULL == bptr->outstrm) {
1945 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1946 goto finished;
1947 }
1948 back = 1;
1949 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 3, &back, erp);
1950
1951 finished:
1952 return back;
1953 }
1954
1955
1956
1957 void
dk4gra_pdf_i_grestore(dk4_gra_t * gra,int * backptr,dk4_er_t * erp)1958 dk4gra_pdf_i_grestore(
1959 dk4_gra_t *gra,
1960 int *backptr,
1961 dk4_er_t *erp
1962 )
1963 {
1964 #if DK4_USE_ASSERT
1965 assert(NULL != gra);
1966 #endif
1967 if (0 == dk4gra_pdf_grestore(gra, erp)) {
1968 if (NULL != backptr) { *backptr = 0; }
1969 }
1970 }
1971
1972
1973 int
dk4gra_pdf_set_line_width(dk4_gra_t * gra,double lw,dk4_er_t * erp)1974 dk4gra_pdf_set_line_width(
1975 dk4_gra_t *gra,
1976 double lw,
1977 dk4_er_t *erp
1978 )
1979 {
1980
1981 dk4_gra_pdf_page_t *bptr;
1982 int back = 0;
1983 #if DK4_USE_ASSERT
1984 assert(NULL != gra);
1985 #endif
1986 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
1987 if (NULL == bptr->outstrm) {
1988 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1989 goto finished;
1990 }
1991 back = 1;
1992 bptr->attr.lw_requested = lw;
1993
1994 finished:
1995 return back;
1996 }
1997
1998
1999
2000 int
dk4gra_pdf_set_line_style(dk4_gra_t * gra,int ls,double sv,dk4_er_t * erp)2001 dk4gra_pdf_set_line_style(
2002 dk4_gra_t *gra,
2003 int ls,
2004 double sv,
2005 dk4_er_t *erp
2006 )
2007 {
2008 dk4_gra_pdf_page_t *bptr;
2009 int back = 0;
2010 #if DK4_USE_ASSERT
2011 assert(NULL != gra);
2012 #endif
2013 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2014 if (NULL == bptr->outstrm) {
2015 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2016 goto finished;
2017 }
2018 back = 1;
2019 bptr->attr.ls_requested = ls;
2020 bptr->attr.sv_requested = sv;
2021
2022 finished:
2023 return back;
2024 }
2025
2026
2027
2028 int
dk4gra_pdf_set_line_cap(dk4_gra_t * gra,int lc,dk4_er_t * erp)2029 dk4gra_pdf_set_line_cap(
2030 dk4_gra_t *gra,
2031 int lc,
2032 dk4_er_t *erp
2033 )
2034 {
2035 dk4_gra_pdf_page_t *bptr;
2036 int back = 0;
2037 #if DK4_USE_ASSERT
2038 assert(NULL != gra);
2039 #endif
2040 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2041 if (NULL == bptr->outstrm) {
2042 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2043 goto finished;
2044 }
2045 back = 1;
2046 bptr->attr.lc_requested = lc;
2047
2048 finished:
2049 return back;
2050 }
2051
2052
2053
2054 int
dk4gra_pdf_set_line_join(dk4_gra_t * gra,int lj,double ml,dk4_er_t * erp)2055 dk4gra_pdf_set_line_join(
2056 dk4_gra_t *gra,
2057 int lj,
2058 double ml,
2059 dk4_er_t *erp
2060 )
2061 {
2062 dk4_gra_pdf_page_t *bptr;
2063 int back = 0;
2064
2065 #if DK4_USE_ASSERT
2066 assert(NULL != gra);
2067 #endif
2068 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2069 if (NULL == bptr->outstrm) {
2070 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2071 goto finished;
2072 }
2073 back = 1;
2074 bptr->attr.lj_requested = lj;
2075 bptr->attr.ml_requested = ml;
2076 if (1.0 > bptr->attr.ml_requested) {
2077 bptr->attr.ml_requested = 1.0;
2078 back = 0;
2079 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2080 }
2081
2082 finished:
2083
2084 return back;
2085 }
2086
2087
2088
2089 int
dk4gra_pdf_set_fill_gray(dk4_gra_t * gra,double g,dk4_er_t * erp)2090 dk4gra_pdf_set_fill_gray(
2091 dk4_gra_t *gra,
2092 double g,
2093 dk4_er_t *erp
2094 )
2095 {
2096 dk4_gra_pdf_page_t *bptr;
2097 int back = 0;
2098 #if DK4_USE_ASSERT
2099 assert(NULL != gra);
2100 #endif
2101 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2102 if (NULL == bptr->outstrm) {
2103 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2104 goto finished;
2105 }
2106 back = 1;
2107 bptr->attr.col_fill_requested.what = DK4_GRA_COL_SPEC_GRAY;
2108 bptr->attr.col_fill_requested.data.gray = g;
2109
2110 finished:
2111 return back;
2112 }
2113
2114
2115
2116 int
dk4gra_pdf_set_fill_rgb(dk4_gra_t * gra,double r,double g,double b,dk4_er_t * erp)2117 dk4gra_pdf_set_fill_rgb(
2118 dk4_gra_t *gra,
2119 double r,
2120 double g,
2121 double b,
2122 dk4_er_t *erp
2123 )
2124 {
2125 dk4_gra_pdf_page_t *bptr;
2126 int back = 0;
2127 #if DK4_USE_ASSERT
2128 assert(NULL != gra);
2129 #endif
2130 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2131 if (NULL == bptr->outstrm) {
2132 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2133 goto finished;
2134 }
2135 back = 1;
2136 bptr->attr.col_fill_requested.what = DK4_GRA_COL_SPEC_RGB;
2137 bptr->attr.col_fill_requested.data.rgb.r = r;
2138 bptr->attr.col_fill_requested.data.rgb.g = g;
2139 bptr->attr.col_fill_requested.data.rgb.b = b;
2140
2141 finished:
2142 return back;
2143 }
2144
2145
2146
2147 int
dk4gra_pdf_set_fill_cmyk(dk4_gra_t * gra,double c,double m,double y,double k,dk4_er_t * erp)2148 dk4gra_pdf_set_fill_cmyk(
2149 dk4_gra_t *gra,
2150 double c,
2151 double m,
2152 double y,
2153 double k,
2154 dk4_er_t *erp
2155 )
2156 {
2157 dk4_gra_pdf_page_t *bptr;
2158 int back = 0;
2159 #if DK4_USE_ASSERT
2160 assert(NULL != gra);
2161 #endif
2162 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2163 if (NULL == bptr->outstrm) {
2164 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2165 goto finished;
2166 }
2167 back = 1;
2168 bptr->attr.col_fill_requested.what = DK4_GRA_COL_SPEC_CMYK;
2169 bptr->attr.col_fill_requested.data.cmyk.c = c;
2170 bptr->attr.col_fill_requested.data.cmyk.m = m;
2171 bptr->attr.col_fill_requested.data.cmyk.y = y;
2172 bptr->attr.col_fill_requested.data.cmyk.k = k;
2173
2174 finished:
2175 return back;
2176 }
2177
2178
2179
2180 int
dk4gra_pdf_set_stroke_gray(dk4_gra_t * gra,double g,dk4_er_t * erp)2181 dk4gra_pdf_set_stroke_gray(
2182 dk4_gra_t *gra,
2183 double g,
2184 dk4_er_t *erp
2185 )
2186 {
2187 dk4_gra_pdf_page_t *bptr;
2188 int back = 0;
2189 #if DK4_USE_ASSERT
2190 assert(NULL != gra);
2191 #endif
2192 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2193 if (NULL == bptr->outstrm) {
2194 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2195 goto finished;
2196 }
2197 back = 1;
2198 bptr->attr.col_stroke_requested.what = DK4_GRA_COL_SPEC_GRAY;
2199 bptr->attr.col_stroke_requested.data.gray = g;
2200
2201 finished:
2202 return back;
2203 }
2204
2205
2206
2207 int
dk4gra_pdf_set_stroke_rgb(dk4_gra_t * gra,double r,double g,double b,dk4_er_t * erp)2208 dk4gra_pdf_set_stroke_rgb(
2209 dk4_gra_t *gra,
2210 double r,
2211 double g,
2212 double b,
2213 dk4_er_t *erp
2214 )
2215 {
2216 dk4_gra_pdf_page_t *bptr;
2217 int back = 0;
2218 #if DK4_USE_ASSERT
2219 assert(NULL != gra);
2220 #endif
2221 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2222 if (NULL == bptr->outstrm) {
2223 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2224 goto finished;
2225 }
2226 back = 1;
2227 bptr->attr.col_stroke_requested.what = DK4_GRA_COL_SPEC_RGB;
2228 bptr->attr.col_stroke_requested.data.rgb.r = r;
2229 bptr->attr.col_stroke_requested.data.rgb.g = g;
2230 bptr->attr.col_stroke_requested.data.rgb.b = b;
2231
2232 finished:
2233 return back;
2234 }
2235
2236
2237
2238 int
dk4gra_pdf_set_stroke_cmyk(dk4_gra_t * gra,double c,double m,double y,double k,dk4_er_t * erp)2239 dk4gra_pdf_set_stroke_cmyk(
2240 dk4_gra_t *gra,
2241 double c,
2242 double m,
2243 double y,
2244 double k,
2245 dk4_er_t *erp
2246 )
2247 {
2248 dk4_gra_pdf_page_t *bptr;
2249 int back = 0;
2250 #if DK4_USE_ASSERT
2251 assert(NULL != gra);
2252 #endif
2253 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2254 if (NULL == bptr->outstrm) {
2255 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2256 goto finished;
2257 }
2258 back = 1;
2259 bptr->attr.col_stroke_requested.what = DK4_GRA_COL_SPEC_CMYK;
2260 bptr->attr.col_stroke_requested.data.cmyk.c = c;
2261 bptr->attr.col_stroke_requested.data.cmyk.m = m;
2262 bptr->attr.col_stroke_requested.data.cmyk.y = y;
2263 bptr->attr.col_stroke_requested.data.cmyk.k = k;
2264
2265 finished:
2266 return back;
2267 }
2268
2269
2270
2271 int
dk4gra_pdf_prepare_fill(dk4_gra_t * gra,dk4_er_t * erp)2272 dk4gra_pdf_prepare_fill(
2273 dk4_gra_t *gra,
2274 dk4_er_t *erp
2275 )
2276 {
2277 dk4_gra_pdf_page_t *bptr;
2278 int back = 0;
2279 #if DK4_USE_ASSERT
2280 assert(NULL != gra);
2281 #endif
2282 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2283 if (NULL == bptr->outstrm) {
2284 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2285 goto finished;
2286 }
2287 back = 1;
2288 dk4gra_pdf_set_color_if_necessary(
2289 bptr->outstrm,
2290 &(bptr->attr.col_fill_active), &(bptr->attr.col_fill_requested),
2291 1, &back, erp
2292 );
2293
2294 finished:
2295 return back;
2296 }
2297
2298
2299
2300
2301
2302 int
dk4gra_pdf_prepare_stroke(dk4_gra_t * gra,dk4_er_t * erp)2303 dk4gra_pdf_prepare_stroke(
2304 dk4_gra_t *gra,
2305 dk4_er_t *erp
2306 )
2307 {
2308 double da[16];
2309 dk4_gra_pdf_page_t *bptr;
2310 double gw;
2311 int back = 0;
2312 int lwc = 0;
2313 #if DK4_USE_ASSERT
2314 assert(NULL != gra);
2315 #endif
2316 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2317 if (NULL == bptr->outstrm) {
2318 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2319 goto finished;
2320 }
2321 back = 1;
2322
2323 /* Stroke color
2324 */
2325 dk4gra_pdf_set_color_if_necessary(
2326 bptr->outstrm,
2327 &(bptr->attr.col_stroke_active), &(bptr->attr.col_stroke_requested),
2328 0, &back, erp
2329 );
2330
2331 /* Line width
2332 */
2333 if (
2334 DK4_GRA_EPSILON_LINEWIDTH
2335 < fabs(bptr->attr.lw_active - bptr->attr.lw_requested)
2336 ) {
2337 dk4gratool_stream_double(
2338 bptr->outstrm, bptr->attr.lw_requested, &back, erp
2339 );
2340 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 25, &back, erp);
2341 bptr->attr.lw_active = bptr->attr.lw_requested;
2342 lwc = 1;
2343 }
2344 /* Line style
2345 */
2346 lwc = dk4gratool_line_style_differs(
2347 bptr->attr.ls_active, bptr->attr.ls_requested,
2348 bptr->attr.sv_active, bptr->attr.sv_requested,
2349 lwc
2350 );
2351 if (0 != lwc) {
2352 gw = (bptr->attr.sv_requested + bptr->attr.lw_requested) / 2.0;
2353 if ((2.0 * bptr->attr.lw_requested) < gw) {
2354 gw = 2.0 * bptr->attr.lw_requested;
2355 }
2356 switch (bptr->attr.lc_requested) {
2357 case DK4_GRA_LC_ROUNDED : case DK4_GRA_LC_PROJECTING : {
2358 gw += bptr->attr.lw_requested;
2359 } break;
2360 }
2361 switch (bptr->attr.ls_requested) {
2362 case DK4_GRA_LS_DASH : {
2363 da[0] = bptr->attr.sv_requested;
2364 da[1] = gw;
2365 dk4gra_pdf_dash_out(
2366 bptr->outstrm, da, 2, (da[0] / 2.0), &back, erp
2367 );
2368 } break;
2369 case DK4_GRA_LS_DOT : {
2370 da[0] = da[1] = bptr->attr.lw_requested;
2371 dk4gra_pdf_dash_out(
2372 bptr->outstrm, da, 2, (da[0] / 2.0), &back, erp
2373 );
2374 } break;
2375 case DK4_GRA_LS_DASH_DOT : {
2376 da[0] = bptr->attr.sv_requested;
2377 da[1] = gw;
2378 da[2] = bptr->attr.lw_requested;
2379 da[3] = gw;
2380 dk4gra_pdf_dash_out(
2381 bptr->outstrm, da, 4, (da[0] / 2.0), &back, erp
2382 );
2383 } break;
2384 case DK4_GRA_LS_DASH_DOT_DOT : {
2385 da[0] = bptr->attr.sv_requested;
2386 da[1] = gw;
2387 da[2] = bptr->attr.lw_requested;
2388 da[3] = gw;
2389 da[4] = bptr->attr.lw_requested;
2390 da[5] = gw;
2391 dk4gra_pdf_dash_out(
2392 bptr->outstrm, da, 6, (da[0] / 2.0), &back, erp
2393 );
2394 } break;
2395 case DK4_GRA_LS_DASH_DOT_DOT_DOT : {
2396 da[0] = bptr->attr.sv_requested;
2397 da[1] = gw;
2398 da[2] = bptr->attr.lw_requested;
2399 da[3] = gw;
2400 da[4] = bptr->attr.lw_requested;
2401 da[5] = gw;
2402 da[6] = bptr->attr.lw_requested;
2403 da[7] = gw;
2404 dk4gra_pdf_dash_out(
2405 bptr->outstrm, da, 8, (da[0] / 2.0), &back, erp
2406 );
2407 } break;
2408 default : { /* solid */
2409 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 32, &back, erp);
2410 } break;
2411 }
2412 bptr->attr.ls_active = bptr->attr.ls_requested;
2413 bptr->attr.sv_active = bptr->attr.sv_requested;
2414 }
2415 /* Line cap
2416 */
2417 if (bptr->attr.lc_active != bptr->attr.lc_requested) {
2418 switch (bptr->attr.lc_requested) {
2419 case DK4_GRA_LC_ROUNDED : { /* 1 */
2420 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 27, &back, erp);
2421 } break;
2422 case DK4_GRA_LC_PROJECTING : { /* 2 */
2423 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 28, &back, erp);
2424 } break;
2425 default : { /* 0 */
2426 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 26, &back, erp);
2427 } break;
2428 }
2429 bptr->attr.lc_active = bptr->attr.lc_requested;
2430 }
2431 /* Line join
2432 */
2433 if (bptr->attr.lj_active != bptr->attr.lj_requested) {
2434 switch (bptr->attr.lj_requested) {
2435 case DK4_GRA_LJ_ROUNDED : { /* 1 */
2436 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 30, &back, erp);
2437 } break;
2438 case DK4_GRA_LJ_BEVELED : { /* 2 */
2439 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 31, &back, erp);
2440 } break;
2441 default : { /* 0 */
2442 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 29, &back, erp);
2443 } break;
2444 }
2445 bptr->attr.lj_active = bptr->attr.lj_requested;
2446 }
2447 if (DK4_GRA_LJ_MITERED == bptr->attr.lj_active) {
2448 if (
2449 DK4_GRA_EPSILON_MITERLIMIT
2450 < fabs(bptr->attr.ml_active - bptr->attr.ml_requested)
2451 ) {
2452 dk4gra_pdf_i_values_and_kw(
2453 bptr->outstrm, &(bptr->attr.ml_requested), 1, 84, &back, erp
2454 );
2455 bptr->attr.ml_active = bptr->attr.ml_requested;
2456 }
2457 }
2458
2459 finished:
2460 return back;
2461 }
2462
2463
2464
2465 int
dk4gra_pdf_prepare_fill_and_stroke(dk4_gra_t * gra,dk4_er_t * erp)2466 dk4gra_pdf_prepare_fill_and_stroke(
2467 dk4_gra_t *gra,
2468 dk4_er_t *erp
2469 )
2470 {
2471 int back = 0;
2472 #if DK4_USE_ASSERT
2473 assert(NULL != gra);
2474 #endif
2475 back = dk4gra_pdf_prepare_fill(gra, erp);
2476 if (0 == dk4gra_pdf_prepare_stroke(gra, erp)) {
2477 back = 0;
2478 }
2479 return back;
2480 }
2481
2482
2483
2484 int
dk4gra_pdf_fill(dk4_gra_t * gra,dk4_er_t * erp)2485 dk4gra_pdf_fill(
2486 dk4_gra_t *gra,
2487 dk4_er_t *erp
2488 )
2489 {
2490 dk4_gra_pdf_page_t *bptr;
2491 int back = 0;
2492 #if DK4_USE_ASSERT
2493 assert(NULL != gra);
2494 #endif
2495 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2496 if (NULL == bptr->outstrm) {
2497 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2498 goto finished;
2499 }
2500 back = 1;
2501 dk4gra_pdf_i_outstream_kw(
2502 bptr->outstrm, ((0 != gra->eor) ? (10) : (9)), &back, erp
2503 );
2504
2505 finished:
2506 return back;
2507 }
2508
2509
2510
2511 int
dk4gra_pdf_stroke(dk4_gra_t * gra,dk4_er_t * erp)2512 dk4gra_pdf_stroke(
2513 dk4_gra_t *gra,
2514 dk4_er_t *erp
2515 )
2516 {
2517 dk4_gra_pdf_page_t *bptr;
2518 int back = 0;
2519 #if DK4_USE_ASSERT
2520 assert(NULL != gra);
2521 #endif
2522 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2523 if (NULL == bptr->outstrm) {
2524 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2525 goto finished;
2526 }
2527 back = 1;
2528 dk4gra_pdf_i_outstream_kw(bptr->outstrm, 8, &back, erp);
2529
2530 finished:
2531 return back;
2532 }
2533
2534
2535
2536 int
dk4gra_pdf_fill_and_stroke(dk4_gra_t * gra,dk4_er_t * erp)2537 dk4gra_pdf_fill_and_stroke(
2538 dk4_gra_t *gra,
2539 dk4_er_t *erp
2540 )
2541 {
2542 dk4_gra_pdf_page_t *bptr;
2543 int back = 0;
2544 #if DK4_USE_ASSERT
2545 assert(NULL != gra);
2546 #endif
2547 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2548 if (NULL == bptr->outstrm) {
2549 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2550 goto finished;
2551 }
2552 back = 1;
2553 dk4gra_pdf_i_outstream_kw(
2554 bptr->outstrm, ((0 != gra->eor) ? (12) : (11)), &back, erp
2555 );
2556
2557 finished:
2558 return back;
2559 }
2560
2561
2562
2563 int
dk4gra_pdf_clip(dk4_gra_t * gra,dk4_er_t * erp)2564 dk4gra_pdf_clip(
2565 dk4_gra_t *gra,
2566 dk4_er_t *erp
2567 )
2568 {
2569 dk4_gra_pdf_page_t *bptr;
2570 int back = 0;
2571 #if DK4_USE_ASSERT
2572 assert(NULL != gra);
2573 #endif
2574 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2575 if (NULL == bptr->outstrm) {
2576 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2577 goto finished;
2578 }
2579 back = 1;
2580 dk4gra_pdf_i_outstream_kw(
2581 bptr->outstrm, ((0 != gra->eor) ? (14) : (13)), &back, erp
2582 );
2583
2584 finished:
2585 return back;
2586 }
2587
2588
2589
2590 static
2591 void
dk4gra_pdf_i_newpath_moveto(dk4_stream_t * os,double x,double y,int * backptr,dk4_er_t * erp)2592 dk4gra_pdf_i_newpath_moveto(
2593 dk4_stream_t *os,
2594 double x,
2595 double y,
2596 int *backptr,
2597 dk4_er_t *erp
2598 )
2599 {
2600
2601 #if DK4_USE_ASSERT
2602 assert(NULL != os);
2603 #endif
2604 dk4gratool_stream_double(os, x, backptr, erp);
2605 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
2606 dk4gratool_stream_double(os, y, backptr, erp);
2607 dk4gra_pdf_i_outstream_kw(os, 4, backptr, erp);
2608
2609 }
2610
2611
2612
2613 static
2614 void
dk4gra_pdf_i_lineto(dk4_stream_t * os,double x,double y,int * backptr,dk4_er_t * erp)2615 dk4gra_pdf_i_lineto(
2616 dk4_stream_t *os,
2617 double x,
2618 double y,
2619 int *backptr,
2620 dk4_er_t *erp
2621 )
2622 {
2623 #if DK4_USE_ASSERT
2624 assert(NULL != os);
2625 #endif
2626 dk4gratool_stream_double(os, x, backptr, erp);
2627 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
2628 dk4gratool_stream_double(os, y, backptr, erp);
2629 dk4gra_pdf_i_outstream_kw(os, 5, backptr, erp);
2630 }
2631
2632
2633
2634 static
2635 void
dk4gra_pdf_i_curveto(dk4_stream_t * os,double xc1,double yc1,double xc2,double yc2,double x,double y,int * backptr,dk4_er_t * erp)2636 dk4gra_pdf_i_curveto(
2637 dk4_stream_t *os,
2638 double xc1,
2639 double yc1,
2640 double xc2,
2641 double yc2,
2642 double x,
2643 double y,
2644 int *backptr,
2645 dk4_er_t *erp
2646 )
2647 {
2648 #if DK4_USE_ASSERT
2649 assert(NULL != os);
2650 #endif
2651 dk4gratool_stream_double(os, xc1, backptr, erp);
2652 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
2653 dk4gratool_stream_double(os, yc1, backptr, erp);
2654 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
2655 dk4gratool_stream_double(os, xc2, backptr, erp);
2656 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
2657 dk4gratool_stream_double(os, yc2, backptr, erp);
2658 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
2659 dk4gratool_stream_double(os, x, backptr, erp);
2660 dk4gra_pdf_i_outstream_kw(os, 1, backptr, erp);
2661 dk4gratool_stream_double(os, y, backptr, erp);
2662 dk4gra_pdf_i_outstream_kw(os, 6, backptr, erp);
2663 }
2664
2665
2666
2667 static
2668 void
dk4gra_pdf_i_closepath(dk4_stream_t * os,int * backptr,dk4_er_t * erp)2669 dk4gra_pdf_i_closepath(
2670 dk4_stream_t *os,
2671 int *backptr,
2672 dk4_er_t *erp
2673 )
2674 {
2675 #if DK4_USE_ASSERT
2676 assert(NULL != os);
2677 #endif
2678 dk4gra_pdf_i_outstream_kw(os, 7, backptr, erp);
2679 }
2680
2681
2682
2683 int
dk4gra_pdf_newpath_moveto(dk4_gra_t * gra,double x,double y,dk4_er_t * erp)2684 dk4gra_pdf_newpath_moveto(
2685 dk4_gra_t *gra,
2686 double x,
2687 double y,
2688 dk4_er_t *erp
2689 )
2690 {
2691 dk4_gra_pdf_page_t *bptr;
2692 int back = 0;
2693
2694 #if DK4_USE_ASSERT
2695 assert(NULL != gra);
2696 #endif
2697 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2698
2699 if (NULL == bptr->outstrm) {
2700
2701 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2702 goto finished;
2703 }
2704 back = 1;
2705
2706 dk4gra_pdf_i_newpath_moveto(bptr->outstrm, x, y, &back, erp);
2707
2708 finished:
2709
2710 return back;
2711 }
2712
2713
2714
2715 int
dk4gra_pdf_lineto(dk4_gra_t * gra,double x,double y,dk4_er_t * erp)2716 dk4gra_pdf_lineto(
2717 dk4_gra_t *gra,
2718 double x,
2719 double y,
2720 dk4_er_t *erp
2721 )
2722 {
2723 dk4_gra_pdf_page_t *bptr;
2724 int back = 0;
2725 #if DK4_USE_ASSERT
2726 assert(NULL != gra);
2727 #endif
2728 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2729 if (NULL == bptr->outstrm) {
2730 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2731 goto finished;
2732 }
2733 back = 1;
2734 dk4gra_pdf_i_lineto(bptr->outstrm, x, y, &back, erp);
2735
2736 finished:
2737 return back;
2738 }
2739
2740
2741
2742 int
dk4gra_pdf_curveto(dk4_gra_t * gra,double xc1,double yc1,double xc2,double yc2,double x,double y,dk4_er_t * erp)2743 dk4gra_pdf_curveto(
2744 dk4_gra_t *gra,
2745 double xc1,
2746 double yc1,
2747 double xc2,
2748 double yc2,
2749 double x,
2750 double y,
2751 dk4_er_t *erp
2752 )
2753 {
2754 dk4_gra_pdf_page_t *bptr;
2755 int back = 0;
2756 #if DK4_USE_ASSERT
2757 assert(NULL != gra);
2758 #endif
2759 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2760 if (NULL == bptr->outstrm) {
2761 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2762 goto finished;
2763 }
2764 back = 1;
2765 dk4gra_pdf_i_curveto(
2766 bptr->outstrm, xc1, yc1, xc2, yc2, x, y, &back, erp
2767 );
2768
2769 finished:
2770 return back;
2771 }
2772
2773
2774
2775 int
dk4gra_pdf_closepath(dk4_gra_t * gra,dk4_er_t * erp)2776 dk4gra_pdf_closepath(
2777 dk4_gra_t *gra,
2778 dk4_er_t *erp
2779 )
2780 {
2781 dk4_gra_pdf_page_t *bptr;
2782 int back = 0;
2783 #if DK4_USE_ASSERT
2784 assert(NULL != gra);
2785 #endif
2786 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2787 if (NULL == bptr->outstrm) {
2788 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
2789 goto finished;
2790 }
2791 back = 1;
2792 dk4gra_pdf_i_closepath(
2793 bptr->outstrm, &back, erp
2794 );
2795
2796 finished:
2797 return back;
2798 }
2799
2800
2801
2802 void
dk4gra_pdf_save_attributes(dk4_gra_t * gra)2803 dk4gra_pdf_save_attributes(
2804 dk4_gra_t *gra
2805 )
2806 {
2807 dk4_gra_pdf_page_t *bptr;
2808 #if DK4_USE_ASSERT
2809 assert(NULL != gra);
2810 #endif
2811 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2812 dk4mem_cpy(
2813 &(bptr->catt),
2814 &(bptr->attr),
2815 sizeof(dk4gra_attributes_t),
2816 NULL
2817 );
2818 }
2819
2820
2821
2822 void
dk4gra_pdf_restore_attributes(dk4_gra_t * gra)2823 dk4gra_pdf_restore_attributes(
2824 dk4_gra_t *gra
2825 )
2826 {
2827 dk4_gra_pdf_page_t *bptr;
2828 #if DK4_USE_ASSERT
2829 assert(NULL != gra);
2830 #endif
2831 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2832 dk4mem_cpy(
2833 &(bptr->attr),
2834 &(bptr->catt),
2835 sizeof(dk4gra_attributes_t),
2836 NULL
2837 );
2838 }
2839
2840
2841
2842 void
dk4gra_pdf_reset_attributes(dk4_gra_t * gra)2843 dk4gra_pdf_reset_attributes(
2844 dk4_gra_t *gra
2845 )
2846 {
2847 dk4_gra_pdf_page_t *bptr;
2848 #if DK4_USE_ASSERT
2849 assert(NULL != gra);
2850 #endif
2851 bptr = (dk4_gra_pdf_page_t *)(gra->curpg);
2852 dk4gratool_reset_active_attributes(&(bptr->attr));
2853 }
2854
2855
2856 /* vim: set ai sw=4 ts=4 : */
2857