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