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: dk4grat.ctr
12 */
13 
14 /**	@file dk4grat.c The dk4grat module.
15 */
16 
17 
18 #include "dk4conf.h"
19 
20 #if	DK4_HAVE_MATH_H
21 #ifndef	MATH_H_INCLUDED
22 #if	DK4_ON_WINDOWS
23 #ifndef	_USE_MATH_DEFINES
24 #define	_USE_MATH_DEFINES 1
25 #endif
26 #endif
27 #include <math.h>
28 #define	MATH_H_INCLUDED 1
29 #endif
30 #endif
31 
32 #ifndef	DK4MEM_H_INCLUDED
33 #include <libdk4base/dk4mem.h>
34 #endif
35 
36 #ifndef	DK4STR8_H_INCLUDED
37 #include <libdk4base/dk4str8.h>
38 #endif
39 
40 #ifndef	DK4STRD_H_INCLUDED
41 #include <libdk4base/dk4strd.h>
42 #endif
43 
44 #ifndef	DK4GRA_H_INCLUDED
45 #include <libdk4gra/dk4gra.h>
46 #endif
47 
48 #ifndef	DK4GRAT_H_INCLUDED
49 #include <libdk4gra/dk4grat.h>
50 #endif
51 
52 #ifndef	GRA_H_INCLUDED
53 #include <libdk4gra/gra.h>
54 #endif
55 
56 #ifndef	DK4STRM_H_INCLUDED
57 #include <libdk4c/dk4strm.h>
58 #endif
59 
60 #ifndef	DK4MAO8D_H_INCLUDED
61 #include <libdk4maio8d/dk4mao8d.h>
62 #endif
63 
64 #ifndef	DK4MAO8DNS_H_INCLUDED
65 #include <libdk4c/dk4mao8dns.h>
66 #endif
67 
68 #ifndef	DK4MATH_H_INCLUDED
69 #include <libdk4c/dk4math.h>
70 #endif
71 
72 #ifndef	DK4ITER_H_INCLUDED
73 #include <libdk4c/dk4iter.h>
74 #endif
75 
76 #ifndef	DK4BITSH_H_INCLUDED
77 #include <libdk4c/dk4bitsh.h>
78 #endif
79 
80 #ifndef	DK4EDSTM_H_INCLUDED
81 #include <libdk4c/dk4edstm.h>
82 #endif
83 
84 #ifndef	DK4FONTC_H_INCLUDED
85 #include <libdk4gra/dk4fontc.h>
86 #endif
87 
88 #ifndef	DK4UNUSED_H_INCLUDED
89 #include <libdk4base/dk4unused.h>
90 #endif
91 
92 #if DK4_HAVE_ASSERT_H
93 #ifndef	ASSERT_H_INCLUDED
94 #include <assert.h>
95 #define	ASSERT_H_INCLUDED 1
96 #endif
97 #endif
98 
99 
100 
101 
102 
103 
104 /**	Masks to request a single bit from a dk4_px_t value.
105 */
106 static const dk4_px_t dk4gratool_bit_values[] = {
107 	0x0001, 0x0002, 0x0004, 0x0008,
108 	0x0010, 0x0020, 0x0040, 0x0080,
109 	0x0100, 0x0200, 0x0400, 0x0800
110 };
111 
112 
113 
114 /**	Start of standalone document, part 1.
115 */
116 static const char * const	dk4gratool_text1[] = {
117 /* 0 */
118 "% PPPT_FONT_SETUP_BEGIN\n",
119 
120 /* 1 */
121 "\\usepackage[T1]{fontenc}\n",
122 
123 /* 2 */
124 "\\usepackage{mathptmx}\n",
125 
126 /* 3 */
127 "\\usepackage[scaled=.92]{helvet}\n",
128 
129 /* 4 */
130 "\\usepackage{courier}\n",
131 
132 /* 5 */
133 "% PPPT_FONT_SETUP_END\n",
134 
135 NULL
136 
137 };
138 
139 
140 
141 /**	Start of standalone document, part 1.
142 */
143 static const char * const	dk4gratool_text3[] = {
144 /* 0 */
145 "% PPPT_PACKAGES_BEGIN\n",
146 
147 /* 1 */
148 "\\usepackage{textcomp}\n",
149 
150 /* 2 */
151 "\\usepackage[intlimits]{amsmath}\n",
152 
153 /* 3 */
154 "\\usepackage{fancybox}\n",
155 
156 /* 4 */
157 "\\usepackage{graphicx}\n",
158 
159 /* 5 */
160 "\\usepackage{xcolor}\n",
161 
162 /* 6 */
163 "% PPPT_PACKAGES_END\n",
164 
165 NULL
166 
167 };
168 
169 
170 
171 /**	Start of standalone document, part 1.
172 */
173 static const char * const	dk4gratool_text4[] = {
174 /* 0 */
175 "% PPPT_PDF_INFO_BEGIN\n",
176 
177 /* 1 */
178 "% \\usepackage{hyperref}\n",
179 
180 /* 2 */
181 "% \\hypersetup{\n",
182 
183 /* 3 */
184 "%   pdfauthor={Anonymous author},\n",
185 
186 /* 4 */
187 "%   pdftitle={Document title},\n",
188 
189 /* 5 */
190 "%   pdfsubject={Document subject},\n",
191 
192 /* 6 */
193 "%   pdfkeywords={Key,word,another}\n",
194 
195 /* 7 */
196 "% }\n",
197 
198 /* 8 */
199 "% PPPT_PDF_INFO_END\n",
200 
201 NULL
202 
203 };
204 
205 
206 /**	Start of standalone document, part 2.
207 */
208 static const char * const	dk4gratool_text2[] = {
209 /* 0 */
210 "\\pagestyle{empty}\n",
211 
212 /* 1 */
213 "\\setlength{\\voffset}{-1in}\n",
214 
215 /* 2 */
216 "\\setlength{\\topmargin}{0bp}\n",
217 
218 /* 3 */
219 "\\setlength{\\headheight}{0bp}\n",
220 
221 /* 4 */
222 "\\setlength{\\headsep}{0bp}\n",
223 
224 /* 5 */
225 "\\setlength{\\topskip}{0bp}\n",
226 
227 /* 6 */
228 "\\setlength{\\hoffset}{-1in}\n",
229 
230 /* 7 */
231 "\\setlength{\\oddsidemargin}{0bp}\n",
232 
233 /* 8 */
234 "\\setlength{\\evensidemargin}{0bp}\n",
235 
236 /* 9 */
237 "\\setlength{\\marginparwidth}{0bp}\n",
238 
239 /* 10 */
240 "\\setlength{\\marginparsep}{0bp}\n",
241 
242 /* 11 */
243 "\\setlength{\\textwidth}{\\paperwidth}\n",
244 
245 /* 12 */
246 "\\setlength{\\textheight}{\\paperheight}\n",
247 
248 /* 13 */
249 "\\setlength{\\parskip}{0bp}\n",
250 
251 /* 14 */
252 "\\setlength{\\parindent}{0bp}\n",
253 
254 /* 15 */
255 "\\setlength{\\pdfpagewidth}{\\paperwidth}\n",
256 
257 /* 16 */
258 "\\setlength{\\pdfpageheight}{\\paperheight}\n",
259 
260 NULL
261 
262 };
263 
264 
265 
266 /**	Constant text fragments.
267 */
268 static const char * const dk4gratool_kw[] = {
269 /*  0 */	"\n",
270 /*  1 */	"\\setlength{\\paperwidth}{",
271 /*  2 */	"\\setlength{\\paperheight}{",
272 /*  3 */	"bp}\n",
273 /*  4 */	"\\end{document}\n",
274 /*  5 */	"\\usepackage{pgfcore}\n",
275 /*  6 */	"\\color[cmyk]{",
276 /*  7 */	"\\color[gray]{",
277 /*  8 */	"\\color[rgb]{",
278 /*  9 */	"}",
279 /* 10 */	",",
280 /* 11 */	"\\newfont{\\PPPTfo",
281 /* 12 */	"}{",
282 /* 13 */	"pt}%\n",
283 /* 14 */	" at ",
284 /* 15 */	"\\providecommand{\\PPPTfo",
285 /* 16 */	"}{}%\n",
286 /* 17 */	"\\renewcommand{\\PPPTfo",
287 /* 18 */	"}{\\normalfont",
288 /* 19 */	"\\selectfont}%\n",
289 /* 20 */	"\\fontfamily{",
290 /* 21 */	"}",
291 /* 22 */	"\\ttdefault",
292 /* 23 */	"\\sfdefault",
293 /* 24 */	"\\rmdefault",
294 /* 25 */	"\\fontseries{\\bfdefault}",
295 /* 26 */	"\\fontseries{\\mddefault}",
296 /* 27 */	"\\fontshape{\\itdefault}",
297 /* 28 */	"\\fontshape{\\updefault}",
298 /* 29 */	"\\fontsize{",
299 /* 30 */	"pt}{",
300 /* 31 */	"pt}",
301 /* 32 */	"\\begin{document}%\n",
302 /* 33 */	"\\documentclass[12pt]{article}\n",
303 /* 34 */	"\\documentclass[",
304 /* 35 */	"pt]{article}\n",
305 /* 36 */	"% PPPT_FONT_SETUP_BEGIN\n",
306 /* 37 */	"% PPPT_FONT_SETUP_END\n",
307 /* 38 */	"% PPPT_PACKAGES_BEGIN\n",
308 /* 39 */	"% PPPT_PACKAGES_END\n",
309 NULL
310 };
311 
312 
313 
314 /**	Alphabet used to translate numbers to uniqe names.
315 */
316 static const char dk4gratool_alphabet[] = {
317 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
318 };
319 
320 
321 dk4_gra_t *
dk4gratool_open(const dkChar * fn,size_t w,size_t h,int docfl,dk4_er_t * erp)322 dk4gratool_open(
323 	const dkChar	*fn,
324 	size_t			 w,
325 	size_t			 h,
326 	int				 docfl,
327 	dk4_er_t		*erp
328 )
329 {
330 	dk4_gra_t	*back	= NULL;
331 
332 #if	DK4_USE_ASSERT
333 	assert(NULL != fn);
334 	assert(0 < w);
335 	assert(0 < h);
336 #endif
337 	back = dk4mem_new(dk4_gra_t,1,erp);
338 	if (NULL != back) {
339 		/*
340 			Initialize all components to defaults
341 		*/
342 		dk4cs_context_init(&(back->cscctx), erp);
343 		back->s_pages	= NULL;
344 		back->i_pages	= NULL;
345 		back->fn		= NULL;
346 		back->curpg		= NULL;
347 		back->pages		= 0;
348 		back->dr		= DK4_GRA_DRIVER_PDF;
349 		back->gscp		= 0;
350 		back->eor		= 1;
351 		back->w			= w;
352 		back->h			= h;
353 		back->cur_x		= 0.0;
354 		back->cur_y		= 0.0;
355 		back->patlw		= 0.9;
356 		back->le		= 0;
357 		back->lec		= 0;
358 		back->len		= 0;
359 		back->docfl		= docfl;
360 
361 		/*
362 			Allocate memory for data copies
363 		*/
364 		if (NULL != fn) {
365 			back->fn = dk4str_dup(fn, erp);
366 			if (NULL == back->fn) {
367 				dk4mem_free(back);
368 				back = NULL;
369 			}
370 		}
371 	}
372 
373 	return back;
374 }
375 
376 
377 
378 void
dk4gratool_close(dk4_gra_t * gptr)379 dk4gratool_close(
380 	dk4_gra_t *gptr
381 )
382 {
383 
384 #if	DK4_USE_ASSERT
385 	assert(NULL != gptr);
386 #endif
387 	if (NULL != gptr) {
388 		if (NULL != gptr->fn) {
389 			dk4mem_free(gptr->fn);
390 			gptr->fn = NULL;
391 		}
392 		dk4mem_free(gptr);
393 	}
394 
395 }
396 
397 
398 
399 int
dk4gratool_points_for_circle(dk4_gra_point_t * ptr,size_t sz,double r,dk4_er_t * erp)400 dk4gratool_points_for_circle(
401 	dk4_gra_point_t	*ptr,
402 	size_t			 sz,
403 	double			 r,
404 	dk4_er_t		*erp
405 )
406 {
407 	double	 kr;		/* Product of kappa and radius */
408 	double	 krsq2;		/* Product of kappa and radius divided by sqrt(2) */
409 	int		 back	= 0;
410 
411 #if	DK4_USE_ASSERT
412 	assert(NULL != ptr);
413 	assert((24 == sz) || (12 == sz));
414 	assert(0.0 < r);
415 #endif
416 	if ((NULL == ptr) || ((24 != sz) && (12 != sz)) || (0.0 >= r)) {
417 		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
418 		goto finished;
419 	}
420 	ptr[0].x = r;
421 	ptr[0].y = 0.0;
422 	if (24 == sz) {
423 		kr = KAPPA_8 * r;
424 		krsq2 = kr / M_SQRT2;
425 		ptr[ 1].x =	r;
426 		ptr[ 1].y =	kr;
427 		ptr[ 3].x = r / M_SQRT2;
428 		ptr[ 3].y = r / M_SQRT2;
429 		ptr[ 2].x = ptr[3].x + krsq2;
430 		ptr[ 2].y = ptr[3].y - krsq2;
431 		ptr[ 4].x = ptr[3].x - krsq2;
432 		ptr[ 4].y = ptr[3].y + krsq2;
433 		ptr[ 5].x = kr;
434 		ptr[ 5].y = r;
435 		ptr[ 6].x = 0.0;
436 		ptr[ 6].y = r;
437 		ptr[ 7].x = 0.0 - kr;
438 		ptr[ 7].y = r;
439 		ptr[ 9].x =	0.0 - ptr[3].x;
440 		ptr[ 9].y = ptr[3].y;
441 		ptr[ 8].x = ptr[9].x + krsq2;
442 		ptr[ 8].y = ptr[9].y + krsq2;
443 		ptr[10].x = ptr[9].x - krsq2;
444 		ptr[10].y = ptr[9].y - krsq2;
445 		ptr[11].x = 0.0 - r;
446 		ptr[11].y = kr;
447 		ptr[12].x = 0.0 - r;
448 		ptr[12].y = 0.0;
449 		ptr[13].x = 0.0 - r;
450 		ptr[13].y = 0.0 - kr;
451 		ptr[15].x = ptr[9].x;
452 		ptr[15].y = 0.0 - ptr[3].x;
453 		ptr[14].x = ptr[15].x - krsq2;
454 		ptr[14].y = ptr[15].y + krsq2;
455 		ptr[16].x = ptr[15].x + krsq2;
456 		ptr[16].y = ptr[15].y - krsq2;
457 		ptr[17].x = 0.0 - kr;
458 		ptr[17].y = 0.0 - r;
459 		ptr[18].x = 0.0;
460 		ptr[18].y = 0.0 - r;
461 		ptr[19].x = kr;
462 		ptr[19].y = 0.0 - r;
463 		ptr[21].x =	ptr[3].x;
464 		ptr[21].y = 0.0 - ptr[3].y;
465 		ptr[20].x = ptr[21].x - krsq2;
466 		ptr[20].y = ptr[21].y - krsq2;
467 		ptr[22].x = ptr[21].x + krsq2;
468 		ptr[22].y = ptr[21].y + krsq2;
469 		ptr[23].x = r;
470 		ptr[23].y = 0.0 - kr;
471 	}
472 	else {
473 		kr = KAPPA_4 * r;
474 		ptr[ 1].x = r;
475 		ptr[ 1].y = kr;
476 		ptr[ 2].x = kr;
477 		ptr[ 2].y = r;
478 		ptr[ 3].x = 0.0;
479 		ptr[ 3].y = r;
480 		ptr[ 4].x = 0.0 - kr;
481 		ptr[ 4].y = r;
482 		ptr[ 5].x = 0.0 - r;
483 		ptr[ 5].y = kr;
484 		ptr[ 6].x = 0.0 - r;
485 		ptr[ 6].y = 0.0;
486 		ptr[ 7].x = 0.0 - r;
487 		ptr[ 7].y = 0.0 - kr;
488 		ptr[ 8].x = 0.0 - kr;
489 		ptr[ 8].y = 0.0 - r;
490 		ptr[ 9].x = 0.0;
491 		ptr[ 9].y = 0.0 - r;
492 		ptr[10].x = kr;
493 		ptr[10].y = 0.0 - r;
494 		ptr[11].x = r;
495 		ptr[11].y = 0.0 - kr;
496 	}
497 	back = 1;
498 
499 	finished:
500 
501 	return back;
502 }
503 
504 
505 
506 int
dk4gratool_points_for_ellipse(dk4_gra_point_t * ptr,size_t sz,double xc,double yc,double rx,double ry,double alpha,dk4_er_t * erp)507 dk4gratool_points_for_ellipse(
508 	dk4_gra_point_t	*ptr,
509 	size_t			 sz,
510 	double			 xc,
511 	double			 yc,
512 	double			 rx,
513 	double			 ry,
514 	double			 alpha,
515 	dk4_er_t		*erp
516 )
517 {
518 	double	coeff;			/* Coefficient ry/rx */
519 	size_t	i;				/* Index to traverse all points */
520 	int		back = 0;		/* Result */
521 
522 #if	DK4_USE_ASSERT
523 	assert(NULL != ptr);
524 	assert((24 == sz) || (12 == sz));
525 	assert(0.0 < rx);
526 	assert(0.0 < ry);
527 #endif
528 	/*
529 		Check arguments
530 	*/
531 	if (
532 		(NULL == ptr) || ((24 != sz) && (12 != sz))
533 		|| (0.0 >= rx) || (0.0 >= ry)
534 	) {
535 		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
536 		goto finished;
537 	}
538 	/*
539 		Create circle data
540 	*/
541 	back = dk4gratool_points_for_circle(ptr, sz, rx, erp);
542 	if (0 == back) { goto finished; }
543 	/*
544 		Scale y values for radius ry
545 	*/
546 	coeff = ry / rx;
547 	for (i = 0; i < sz; i++) {
548 		ptr[i].y *= coeff;
549 	}
550 	/*	Rotate the points if necessary
551 	*/
552 	if (DK4_GRA_EPSILON_COORDINATES < fabs(alpha)) {
553 		for (i = 0; i < sz; i++) {
554 			dk4gratool_rotate_point(&(ptr[i]), alpha);
555 		}
556 	}
557 	/*	Shift to specified center point
558 	*/
559 	for (i = 0; i < sz; i++) {
560 		ptr[i].x += xc;
561 		ptr[i].y += yc;
562 	}
563 	/*	Check all coordinates for finite values.
564 	*/
565 	for (i = 0; i < sz; i++) {
566 #if	DK4_HAVE_ISFINITE
567 	if ((!(isfinite(ptr[i].x))) || (!(isfinite(ptr[i].y)))) {
568 		dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
569 		back = 0;
570 	}
571 #else
572 #if	DK4_HAVE__FINITE
573 	if ((!(_finite(ptr[i].x))) || (!(_finite(ptr[i].y)))) {
574 		dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
575 		back = 0;
576 	}
577 #else
578 
579 #endif
580 #endif
581 	}
582 
583 	finished:
584 	return back;
585 }
586 
587 
588 
589 void
dk4gratool_rotate_point(dk4_gra_point_t * pt,double rot)590 dk4gratool_rotate_point(dk4_gra_point_t *pt, double rot)
591 {
592 	double	r;		/* Point radius */
593 	double	a;		/* Point angle */
594 
595 #if	DK4_USE_ASSERT
596 	assert(NULL != pt);
597 #endif
598 	r = sqrt(pt->x * pt->x + pt->y * pt->y);
599 	a = atan2(pt->y, pt->x);
600 	a += rot;
601 	pt->x = r * cos(a);
602 	pt->y = r * sin(a);
603 
604 }
605 
606 
607 
608 void
dk4gratool_initialize_attributes(dk4gra_attributes_t * pattr)609 dk4gratool_initialize_attributes(
610 	dk4gra_attributes_t *pattr
611 )
612 {
613 
614 #if	DK4_USE_ASSERT
615 	assert(NULL != pattr);
616 #endif
617 	if (NULL != pattr) {
618 		pattr->lc_active		= -1;
619 		pattr->lc_requested		= DK4_GRA_LC_BUTTED;
620 		pattr->lj_active		= -1;
621 		pattr->lj_requested		= DK4_GRA_LJ_MITERED;
622 		pattr->ls_active		= -1;
623 		pattr->ls_requested		= DK4_GRA_LS_SOLID;
624 		pattr->lw_active		= -1.0;
625 		pattr->lw_requested		= 0.9;
626 		pattr->sv_active		= -1.0;
627 		pattr->sv_requested		= 4.0;
628 		pattr->ml_active		= 10.0;
629 		pattr->ml_requested		= 10.0;
630 		pattr->eor_active		= -1;
631 		pattr->eor_requested	= 0;
632 		dk4mem_reset(&(pattr->col_stroke_active), sizeof(dk4gra_col_t), NULL);
633 		pattr->col_stroke_active.what = DK4_GRA_COL_SPEC_NONE;
634 		dk4mem_cpy(
635 			&(pattr->col_fill_active), &(pattr->col_stroke_active),
636 			sizeof(dk4gra_col_t), NULL
637 		);
638 		dk4mem_cpy(
639 			&(pattr->col_stroke_requested), &(pattr->col_stroke_active),
640 			sizeof(dk4gra_col_t), NULL
641 		);
642 		pattr->col_stroke_requested.what = DK4_GRA_COL_SPEC_GRAY;
643 		pattr->col_stroke_requested.data.gray = 0.0;
644 		dk4mem_cpy(
645 			&(pattr->col_fill_requested), &(pattr->col_stroke_requested),
646 			sizeof(dk4gra_col_t), NULL
647 		);
648 
649 	}
650 
651 }
652 
653 
654 
655 void
dk4gratool_reset_active_attributes(dk4gra_attributes_t * pattr)656 dk4gratool_reset_active_attributes(
657 	dk4gra_attributes_t *pattr
658 )
659 {
660 #if	DK4_USE_ASSERT
661 	assert(NULL != pattr);
662 #endif
663 	pattr->col_stroke_active.what	= DK4_GRA_COL_SPEC_NONE;
664 	pattr->col_fill_active.what		= DK4_GRA_COL_SPEC_NONE;
665 	pattr->lw_active				= -1.0;
666 	pattr->sv_active				= -1.0;
667 	pattr->ml_active				= -1.0;
668 	pattr->lc_active				= -1;
669 	pattr->lj_active				= -1;
670 	pattr->ls_active				= -1;
671 	pattr->eor_active				= -1;
672 }
673 
674 
675 
676 void
dk4gratool_set_color_requested(dk4gra_col_t * pcol,int colsp,double c1,double c2,double c3,double c4)677 dk4gratool_set_color_requested(
678 	dk4gra_col_t	*pcol,
679 	int				 colsp,
680 	double			 c1,
681 	double			 c2,
682 	double			 c3,
683 	double			 c4
684 )
685 {
686 #if	DK4_USE_ASSERT
687 	assert(NULL != pcol);
688 #endif
689 	pcol->what = colsp;
690 	switch (colsp) {
691 		case DK4_GRA_COL_SPEC_CMYK : {
692 			pcol->data.cmyk.c = c1;
693 			pcol->data.cmyk.m = c2;
694 			pcol->data.cmyk.y = c3;
695 			pcol->data.cmyk.k = c4;
696 		} break;
697 		case DK4_GRA_COL_SPEC_RGB : {
698 			pcol->data.rgb.r = c1;
699 			pcol->data.rgb.g = c2;
700 			pcol->data.rgb.b = c3;
701 		} break;
702 		case DK4_GRA_COL_SPEC_GRAY : {
703 			pcol->data.gray = c1;
704 		} break;
705 	}
706 }
707 
708 
709 
710 int
dk4gratool_colors_differ(dk4gra_col_t * p1,dk4gra_col_t * p2)711 dk4gratool_colors_differ(
712 	dk4gra_col_t	*p1,
713 	dk4gra_col_t	*p2
714 )
715 {
716 	int		back	= 1;
717 #if	DK4_USE_ASSERT
718 	assert(NULL != p1);
719 	assert(NULL != p2);
720 #endif
721 	if (p1->what == p2->what) {
722 		switch (p1->what) {
723 			case DK4_GRA_COL_SPEC_CMYK : {
724 				back = 0;
725 				if (1.0e-3 < fabs(p1->data.cmyk.c - p2->data.cmyk.c)) {
726 					back = 1;
727 				}
728 				if (1.0e-3 < fabs(p1->data.cmyk.m - p2->data.cmyk.m)) {
729 					back = 1;
730 				}
731 				if (1.0e-3 < fabs(p1->data.cmyk.y - p2->data.cmyk.y)) {
732 					back = 1;
733 				}
734 				if (1.0e-3 < fabs(p1->data.cmyk.k - p2->data.cmyk.k)) {
735 					back = 1;
736 				}
737 			} break;
738 			case DK4_GRA_COL_SPEC_RGB : {
739 				back = 0;
740 				if (1.0e-3 < fabs(p1->data.rgb.r - p2->data.rgb.r)) {
741 					back = 1;
742 				}
743 				if (1.0e-3 < fabs(p1->data.rgb.g - p2->data.rgb.g)) {
744 					back = 1;
745 				}
746 				if (1.0e-3 < fabs(p1->data.rgb.b - p2->data.rgb.b)) {
747 					back = 1;
748 				}
749 			} break;
750 			case DK4_GRA_COL_SPEC_GRAY : {
751 				if (1.0e-3 >= fabs(p1->data.gray - p2->data.gray)) {
752 					back = 0;
753 				}
754 			} break;
755 		}
756 	}
757 	return back;
758 }
759 
760 
761 
762 int
dk4gratool_line_style_differs(int ls_a,int ls_r,double sv_a,double sv_r,int lwc)763 dk4gratool_line_style_differs(
764 	int		ls_a,
765 	int		ls_r,
766 	double	sv_a,
767 	double	sv_r,
768 	int		lwc
769 )
770 {
771 	int		 back = 1;
772 
773 	if (ls_a == ls_r) {
774 		back = 0;
775 		if (DK4_GRA_LS_SOLID != ls_a) {
776 			if (0 != lwc) {
777 				back = 1;
778 			}
779 			else {
780 				if (1.0e-3 < fabs(sv_a - sv_r)) {
781 					back = 1;
782 				}
783 			}
784 		}
785 	}
786 
787 	return back;
788 }
789 
790 
791 
792 int
dk4gratool_calculate_transformations(double * dst,double xl,double xr,double yb,double yt,double w,double h,int kar,int pos,dk4_er_t * erp)793 dk4gratool_calculate_transformations(
794 	double		*dst,
795 	double		 xl,
796 	double		 xr,
797 	double		 yb,
798 	double		 yt,
799 	double		 w,
800 	double		 h,
801 	int			 kar,
802 	int			 pos,
803 	dk4_er_t	*erp
804 )
805 {
806 	double	 dx;		/* Available X space */
807 	double	 dy;		/* Available Y space */
808 	size_t	 i;			/* Traverse transformation values */
809 	int		 back	= 0;
810 
811 #if	DK4_USE_ASSERT
812 	assert(NULL != dst);
813 	assert(xr > xl);
814 	assert(yt > yb);
815 	assert(0.0 < w);
816 	assert(0.0 < h);
817 #endif
818 	if ((xr <= xl) || (yt <= yb) || (0.0 >= w) || (0.0 >= h)) {
819 		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
820 		goto finished;
821 	}
822 	for (i = 0; i < 5; i++) { dst[i] = 0.0; }
823 	dx = xr - xl;
824 	dy = yt - yb;
825 	switch (pos) {
826 		case 1: {
827 			dst[2] = 90.0;
828 			if (0 != kar) {
829 				if ((w * dx) > (h * dy)) {	/* Y fully used, space in X */
830 					dx = (h * dy) / w;
831 					dst[0] = xr - (xr - xl - dx) / 2.0;
832 					dst[1] = yb;
833 				}
834 				else {						/* X fully used, space in Y */
835 					dy = (w * dx) / h;
836 					dst[0] = xr;
837 					dst[1] = yb + (yt - yb - dy) / 2.0;
838 				}
839 				dst[3] = dy;
840 				dst[4] = dx;
841 			}
842 			else {
843 				dst[0] = xr;
844 				dst[1] = yb;
845 				dst[3] = yt - yb;
846 				dst[4] = xr - xl;
847 			}
848 		} break;
849 		case 2: {
850 			dst[2] = 180.0;
851 			if (0 != kar) {
852 				if ((w * dy) > (h * dx)) {  /* X fully used, space in Y */
853 					dy = (h * dx) / w;
854 					dst[0] = xr;
855 					dst[1] = yt - (yt - yb - dy) / 2.0;
856 				}
857 				else {
858 					dx = (w * dy) / h;
859 					dst[0] = xr - (xr - xl - dx) / 2.0;
860 					dst[1] = yt;
861 				}
862 				dst[3] = dx;
863 				dst[4] = dy;
864 			}
865 			else {
866 				dst[0] = xr;
867 				dst[1] = yt;
868 				dst[3] = xr - xl;
869 				dst[4] = yt - yb;
870 			}
871 		} break;
872 		case 3: {
873 			dst[2] = 270.0;
874 			if (0 != kar) {
875 				if ((w * dx) > (h * dy)) {	/* Y fully used, space in X */
876 					dx = (h * dy) / w;
877 					dst[0] = xl + (xr - xl - dx) / 2.0;
878 					dst[1] = yt;
879 				}
880 				else {						/* X fully used, space in Y */
881 					dy = (w * dx) / h;
882 					dst[0] = xl;
883 					dst[1] = yt - (yt - yb - dy) / 2.0;
884 				}
885 				dst[3] = dy;
886 				dst[4] = dx;
887 			}
888 			else {
889 				dst[0] = xl;
890 				dst[1] = yt;
891 				dst[3] = yt - yb;
892 				dst[4] = xr - xl;
893 
894 			}
895 		} break;
896 		case 4: {
897 			dst[2] = 90.0;
898 			if (0 != kar) {
899 				if ((w * dx) > (h * dy)) {	/* Y fully used, space in X */
900 					dx = (h * dy) / w;
901 					dst[0] = xr - (xr - xl - dx) / 2.0;
902 					dst[1] = yt;
903 				}
904 				else {						/* X fully used, space in Y */
905 					dy = (w * dx) / h;
906 					dst[0] = xr;
907 					dst[1] = yt - (yt - yb - dy) / 2.0;
908 				}
909 				dst[3] = 0.0 - dy;
910 				dst[4] = dx;
911 			}
912 			else {
913 				dst[0] = xr;
914 				dst[1] = yt;
915 				dst[3] = yb - yt;
916 				dst[4] = xr - xl;
917 			}
918 		} break;
919 		case 5: {
920 			if (0 != kar) {
921 				if ((w * dy) > (h * dx)) {	/* X fully used, space in Y */
922 					dy = (h * dx) / w;
923 					dst[0] = xr;
924 					dst[1] = yb + (yt - yb - dy) / 2.0;
925 				}
926 				else {						/* Y fully used, space in X */
927 					dx = (w * dy) / h;
928 					dst[0] = xr - (xr - xl - dx) / 2.0;
929 					dst[1] = yb;
930 				}
931 				dst[3] = 0.0 - dx;
932 				dst[4] = dy;
933 
934 			}
935 			else {
936 				dst[0] = xr;
937 				dst[1] = yb;
938 				dst[3] = xl - xr;
939 				dst[4] = yt - yb;
940 			}
941 		} break;
942 		case 6: {
943 			dst[2] = 90.0;
944 			if (0 != kar) {
945 				if ((w * dx) > (h * dy)) {	/* Y fully used, space in X */
946 					dx = (h * dy) / w;
947 					dst[0] = xl + (xr - xl - dx) / 2.0;
948 					dst[1] = yb;
949 				}
950 				else {						/* X fully used, space in Y */
951 					dy = (w * dx) / h;
952 					dst[0] = xl;
953 					dst[1] = yb + (yt - yb - dy) / 2.0;
954 				}
955 				dst[3] = dy;
956 				dst[4] = 0.0 - dx;
957 			}
958 			else {
959 				dst[0] = xl;
960 				dst[1] = yb;
961 				dst[3] = yt - yb;
962 				dst[4] = xl - xr;
963 			}
964 		} break;
965 		case 7: {
966 			if (0 != kar) {
967 				if ((w * dy) > (h * dx)) {	/* X fully used, space in Y */
968 					dy = (h * dx) / w;
969 					dst[0] = xl;
970 					dst[1] = yt - (yt - yb - dy) / 2.0;
971 				}
972 				else {						/* Y fully used, space in X */
973 					dx = (w * dy) / h;
974 					dst[0] = xl + (xr - xl - dx) / 2.0;
975 					dst[1] = yt;
976 				}
977 				dst[3] = dx;
978 				dst[4] = 0.0 - dy;
979 
980 			}
981 			else {
982 				dst[0] = xl;
983 				dst[1] = yt;
984 				dst[3] = xr - xl;
985 				dst[4] = yb - yt;
986 			}
987 		} break;
988 		default : {	/* 0 */
989 			if (0 != kar) {
990 				if ((w * dy) > (h * dx)) {	/* X fully used, space in Y */
991 					dy = (h * dx) / w;
992 					dst[0] = xl;
993 					dst[1] = yb + (yt - yb - dy) / 2.0;
994 				}
995 				else {						/* Y fully used, space in X */
996 					dx = (w * dy) / h;
997 					dst[0] = xl + (xr - xl - dx) / 2.0;
998 					dst[1] = yb;
999 				}
1000 				dst[3] = dx;
1001 				dst[4] = dy;
1002 			}
1003 			else {
1004 				dst[0] = xl;
1005 				dst[1] = yb;
1006 				dst[3] = (xr - xl);
1007 				dst[4] = (yt - yb);
1008 			}
1009 		} break;
1010 	}
1011 
1012 	back = 1;
1013 	for (i = 0; i < 5; i++) {
1014 #if DK4_HAVE_ISFINITE
1015 	  	if (!(isfinite(dst[i]))) {
1016 			dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
1017 			back = 0;
1018 		}
1019 #else
1020 #if	DK4_HAVE__FINITE
1021 		if (!(_finite(dst[i]))) {
1022 			dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
1023 			back = 0;
1024 		}
1025 #endif
1026 #endif
1027 	}
1028 
1029 	finished:
1030 
1031 	return back;
1032 }
1033 
1034 
1035 
1036 void
dk4gratool_stream_string(dk4_stream_t * os,const char * str,int * backptr,dk4_er_t * erp)1037 dk4gratool_stream_string(
1038 	dk4_stream_t	*os,
1039 	const char		*str,
1040 	int				*backptr,
1041 	dk4_er_t		*erp
1042 )
1043 {
1044 #if	DK4_USE_ASSERT
1045 	assert(NULL != os);
1046 	assert(NULL != str);
1047 #endif
1048 	if (0 == dk4stream_write_char_string(os, str, erp)) {
1049 		if (NULL != backptr) { *backptr = 0; }
1050 	}
1051 }
1052 
1053 
1054 
1055 void
dk4gratool_stream_double(dk4_stream_t * os,double val,int * backptr,dk4_er_t * erp)1056 dk4gratool_stream_double(
1057 	dk4_stream_t	*os,
1058 	double			 val,
1059 	int				*backptr,
1060 	dk4_er_t		*erp
1061 )
1062 {
1063 #if	DK4_USE_ASSERT
1064 	assert(NULL != os);
1065 #endif
1066 	if (0 == dk4ma_write_c8_double_no_sci_to_stream(os,val,1.0e-8,0,1,erp)) {
1067 		if (NULL != backptr) { *backptr = 0; }
1068 	}
1069 }
1070 
1071 
1072 
1073 void
dk4gratool_stream_uint(dk4_stream_t * os,dk4_um_t val,size_t padsz,int * backptr,dk4_er_t * erp)1074 dk4gratool_stream_uint(
1075 	dk4_stream_t	*os,
1076 	dk4_um_t		 val,
1077 	size_t			 padsz,
1078 	int				*backptr,
1079 	dk4_er_t		*erp
1080 )
1081 {
1082 	char	buf[16*sizeof(dk4_um_t)];	/* Buffer for val as text */
1083 #if	DK4_USE_ASSERT
1084 	assert(NULL != os);
1085 #endif
1086 	if (0 != dk4ma_write_c8_decimal_unsigned(buf,sizeof(buf),val,padsz,erp)) {
1087 		dk4gratool_stream_string(os, buf, backptr, erp);
1088 	}
1089 	else {
1090 		if (NULL != backptr) { *backptr = 0; }
1091 	}
1092 }
1093 
1094 
1095 
1096 void
dk4gratool_stream_num_alpha(dk4_stream_t * os,size_t val,int * backptr,dk4_er_t * erp)1097 dk4gratool_stream_num_alpha(
1098 	dk4_stream_t	*os,
1099 	size_t			 val,
1100 	int				*backptr,
1101 	dk4_er_t		*erp
1102 )
1103 {
1104 	size_t		kwi;	/* Index of number in alphabet */
1105 #if	DK4_USE_ASSERT
1106 	assert(NULL != os);
1107 #endif
1108 	do {
1109 		kwi = val % (size_t)26U;
1110 		val = val / (size_t)26U;
1111 		if (0 == dk4stream_write_byte(os, dk4gratool_alphabet[kwi], erp)) {
1112 			if (NULL != backptr) { *backptr = 0; }
1113 		}
1114 	} while (0 < val);
1115 }
1116 
1117 
1118 
1119 void
dk4gratool_stream_color(dk4_stream_t * os,dk4gra_col_t const * col,int * backptr,dk4_er_t * erp)1120 dk4gratool_stream_color(
1121 	dk4_stream_t		*os,
1122 	dk4gra_col_t const	*col,
1123 	int					*backptr,
1124 	dk4_er_t			*erp
1125 )
1126 {
1127 #if	DK4_USE_ASSERT
1128 	assert(NULL != os);
1129 	assert(NULL != col);
1130 #endif
1131 	switch (col->what) {
1132 		case DK4_GRA_COL_SPEC_CMYK : {
1133 			dk4gratool_stream_string(os, dk4gratool_kw[6], backptr, erp);
1134 			dk4gratool_stream_double(os, col->data.cmyk.c, backptr, erp);
1135 			dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
1136 			dk4gratool_stream_double(os, col->data.cmyk.m, backptr, erp);
1137 			dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
1138 			dk4gratool_stream_double(os, col->data.cmyk.y, backptr, erp);
1139 			dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
1140 			dk4gratool_stream_double(os, col->data.cmyk.k, backptr, erp);
1141 			dk4gratool_stream_string(os, dk4gratool_kw[9], backptr, erp);
1142 		} break;
1143 		case DK4_GRA_COL_SPEC_GRAY : {
1144 			dk4gratool_stream_string(os, dk4gratool_kw[7], backptr, erp);
1145 			dk4gratool_stream_double(os, col->data.gray, backptr, erp);
1146 			dk4gratool_stream_string(os, dk4gratool_kw[9], backptr, erp);
1147 		} break;
1148 		default : {		/* RGB */
1149 			dk4gratool_stream_string(os, dk4gratool_kw[8], backptr, erp);
1150 			dk4gratool_stream_double(os, col->data.rgb.r, backptr, erp);
1151 			dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
1152 			dk4gratool_stream_double(os, col->data.rgb.g, backptr, erp);
1153 			dk4gratool_stream_string(os, dk4gratool_kw[10], backptr, erp);
1154 			dk4gratool_stream_double(os, col->data.rgb.b, backptr, erp);
1155 			dk4gratool_stream_string(os, dk4gratool_kw[9], backptr, erp);
1156 		} break;
1157 	}
1158 }
1159 
1160 
1161 
1162 double
dk4gratool_kappa_for_angle(double alpha)1163 dk4gratool_kappa_for_angle(double alpha)
1164 {
1165 	double back;
1166 
1167 	alpha = fabs(alpha);
1168 	back =	(2.0 * sqrt(8.0 * (1.0 - cos(alpha))) - 4.0 * sin(alpha))
1169 		/ (3.0 * alpha * (1.0 - cos(alpha)));
1170 
1171 	return back;
1172 }
1173 
1174 
1175 
1176 dk4_px_t
dk4gratool_bit(size_t i)1177 dk4gratool_bit(
1178 	size_t	i
1179 )
1180 {
1181 	return (dk4gratool_bit_values[i]);
1182 }
1183 
1184 
1185 
1186 void
dk4gratool_put_pixel_value(dk4_stream_t * strm,dk4_bit_shift_t * bs,dk4_px_t pixval,dk4_px_bit_depth_t bpc,int * backptr,dk4_er_t * erp)1187 dk4gratool_put_pixel_value(
1188 	dk4_stream_t		*strm,
1189 	dk4_bit_shift_t		*bs,
1190 	dk4_px_t			 pixval,
1191 	dk4_px_bit_depth_t	 bpc,
1192 	int					*backptr,
1193 	dk4_er_t			*erp
1194 )
1195 {
1196 	int					 res;
1197 	dk4_px_bit_depth_t	 i;
1198 
1199 #if	DK4_USE_ASSERT
1200 	assert(NULL != strm);
1201 	assert(NULL != bs);
1202 #endif
1203 	for (i = 0; i < bpc; i++) {
1204 		res = dk4bit_shift_add(
1205 			bs,
1206 			(
1207 				(0 != (pixval & (dk4gratool_bit((size_t)(bpc - 1 - i)))))
1208 				? (1) : (0)
1209 			),
1210 			NULL
1211 		);
1212 		if (DK4_EDSTM_FINISHED == res) {
1213 			res = dk4stream_write_byte(
1214 				strm, (char)dk4bit_shift_output(bs, NULL), erp
1215 			);
1216 			if (0 == res) {
1217 				if (NULL != backptr) { *backptr = 0; }
1218 			}
1219 		}
1220 	}
1221 
1222 }
1223 
1224 
1225 
1226 /**	Write paragraph of text to output.
1227 	@param	ostrm	Output stream.
1228 	@param	strar	String array.
1229 	@param	bptr	Address of success variable to reset on error.
1230 	@param	erp		Error report, may be NULL.
1231 */
1232 static
1233 void
dk4gratool_paragraph_to_stream(dk4_stream_t * ostrm,const char * const * strar,int * bptr,dk4_er_t * erp)1234 dk4gratool_paragraph_to_stream(
1235 	dk4_stream_t		*ostrm,
1236 	const char * const	*strar,
1237 	int					*bptr,
1238 	dk4_er_t			*erp
1239 )
1240 {
1241 #if	DK4_USE_ASSERT
1242 	assert(NULL != ostrm);
1243 	assert(NULL != strar);
1244 #endif
1245 	if ((NULL != ostrm) && (NULL != strar)) {
1246 		while (NULL != *strar) {
1247 			dk4gratool_stream_string(ostrm, *(strar++), bptr, erp);
1248 		}
1249 	}
1250 }
1251 
1252 
1253 
1254 void
dk4gratool_start_standalone_document(dk4_stream_t * ostrm,dk4_gra_t * gra,int pgf,double dfs,dk4_sto_t * s_f,dk4_sto_it_t * i_f,dk4_sto_t * s_p,dk4_sto_it_t * i_p,dk4_sto_t * s_o,dk4_sto_it_t * i_o,int * bptr,dk4_er_t * erp)1255 dk4gratool_start_standalone_document(
1256 	dk4_stream_t		*ostrm,
1257 	dk4_gra_t			*gra,
1258 	int					 pgf,
1259 	double				 dfs,
1260 	dk4_sto_t			*s_f,
1261 	dk4_sto_it_t		*i_f,
1262 	dk4_sto_t			*s_p,
1263 	dk4_sto_it_t		*i_p,
1264 	dk4_sto_t			*s_o,
1265 	dk4_sto_it_t		*i_o,
1266 	int					*bptr,
1267 	dk4_er_t			*erp
1268 )
1269 {
1270 	dk4_gra_preamble_line_t	*pl;
1271 	int						 res;
1272 
1273 #if	DK4_USE_ASSERT
1274 	assert(NULL != ostrm);
1275 	assert(NULL != gra);
1276 	assert(0.0 < dfs);
1277 #endif
1278 	/*
1279 		Document class
1280 	*/
1281 
1282 	if (0.0 < dfs) {
1283 		dk4gratool_stream_string(ostrm, dk4gratool_kw[34], bptr, erp);
1284 		res = dk4ma_write_c8_double_no_sci_to_stream(
1285 			ostrm, dfs, 1.0e-1, 0, 0, erp
1286 		);
1287 		if (0 == res) { if (NULL != bptr) { *bptr = 0; } }
1288 		dk4gratool_stream_string(ostrm, dk4gratool_kw[35], bptr, erp);
1289 	}
1290 	else {
1291 		dk4gratool_stream_string(ostrm, dk4gratool_kw[33], bptr, erp);
1292 	}
1293 	/*
1294 		Font setup
1295 	*/
1296 	if ((NULL != s_f) && (NULL != i_f)) {
1297 		dk4gratool_stream_string(ostrm, dk4gratool_kw[36], bptr, erp);
1298 		dk4sto_it_reset(i_f);
1299 		do {
1300 			pl = (dk4_gra_preamble_line_t *)dk4sto_it_next(i_f);
1301 			if (NULL != pl) {
1302 				dk4gratool_stream_string(ostrm, pl->text, bptr, erp);
1303 				dk4gratool_stream_string(ostrm, dk4gratool_kw[0], bptr, erp);
1304 			}
1305 		} while (NULL != pl);
1306 		dk4gratool_stream_string(ostrm, dk4gratool_kw[37], bptr, erp);
1307 	}
1308 	else {
1309 		dk4gratool_paragraph_to_stream(ostrm, dk4gratool_text1, bptr, erp);
1310 	}
1311 	/*
1312 		Additional packages
1313 	*/
1314 	if ((NULL != s_p) && (NULL != i_p)) {
1315 		dk4gratool_stream_string(ostrm, dk4gratool_kw[38], bptr, erp);
1316 		dk4sto_it_reset(i_p);
1317 		do {
1318 			pl = (dk4_gra_preamble_line_t *)dk4sto_it_next(i_p);
1319 			if (NULL != pl) {
1320 				dk4gratool_stream_string(ostrm, pl->text, bptr, erp);
1321 				dk4gratool_stream_string(ostrm, dk4gratool_kw[0], bptr, erp);
1322 			}
1323 		} while (NULL != pl);
1324 		dk4gratool_stream_string(ostrm, dk4gratool_kw[39], bptr, erp);
1325 	}
1326 	else {
1327 		dk4gratool_paragraph_to_stream(ostrm, dk4gratool_text3, bptr, erp);
1328 	}
1329 	dk4gratool_paragraph_to_stream(ostrm, dk4gratool_text4, bptr, erp);
1330 	/*
1331 		/setlength{/paperwidth{xxxbp}
1332 	*/
1333 	dk4gratool_stream_string(ostrm, dk4gratool_kw[1], bptr, erp);
1334 	dk4gratool_stream_uint(ostrm, gra->w, 0, bptr, erp);
1335 	dk4gratool_stream_string(ostrm, dk4gratool_kw[3], bptr, erp);
1336 	/*
1337 		/setlength{/paperheight{xxxbp}
1338 	*/
1339 	dk4gratool_stream_string(ostrm, dk4gratool_kw[2], bptr, erp);
1340 	dk4gratool_stream_uint(ostrm, gra->h, 0, bptr, erp);
1341 	dk4gratool_stream_string(ostrm, dk4gratool_kw[3], bptr, erp);
1342 	/*
1343 		/usepackage{pgfcore}
1344 	*/
1345 	if (0 != pgf) {
1346 		dk4gratool_stream_string(ostrm, dk4gratool_kw[5], bptr, erp);
1347 	}
1348 	/*
1349 		Instructions for setup
1350 	*/
1351 	dk4gratool_paragraph_to_stream(ostrm, dk4gratool_text2, bptr, erp);
1352 	/*
1353 		Additional other setup lines
1354 	*/
1355 	if ((NULL != s_o) && (NULL != i_o)) {
1356 		dk4sto_it_reset(i_o);
1357 		do {
1358 			pl = (dk4_gra_preamble_line_t *)dk4sto_it_next(i_o);
1359 			if (NULL != pl) {
1360 				dk4gratool_stream_string(ostrm, pl->text, bptr, erp);
1361 				dk4gratool_stream_string(ostrm, dk4gratool_kw[0], bptr, erp);
1362 			}
1363 		} while (NULL != pl);
1364 	}
1365 	/*
1366 		/begin{document}
1367 	*/
1368 	dk4gratool_stream_string(ostrm, dk4gratool_kw[32], bptr, erp);
1369 
1370 }
1371 
1372 
1373 
1374 void
dk4gratool_end_standalone_document(dk4_stream_t * ostrm,int * bptr,dk4_er_t * erp)1375 dk4gratool_end_standalone_document(
1376 	dk4_stream_t		*ostrm,
1377 	int					*bptr,
1378 	dk4_er_t			*erp
1379 )
1380 {
1381 #if	DK4_USE_ASSERT
1382 	assert(NULL != ostrm);
1383 #endif
1384 	dk4gratool_stream_string(ostrm, dk4gratool_kw[4], bptr, erp);
1385 }
1386 
1387 
1388 
1389 /**	Write definition for one font from collector to output stream.
1390 	@param	ostrm	Output stream.
1391 	@param	foi		Font item to write.
1392 	@param	bptr	Address of success variable to reset on error.
1393 	@param	erp		Error report, may be NULL.
1394 */
1395 static
1396 void
dk4gratool_font_one_definition(dk4_stream_t * ostrm,dk4_font_item_t const * foi,int * bptr,dk4_er_t * erp)1397 dk4gratool_font_one_definition(
1398 	dk4_stream_t			*ostrm,
1399 	dk4_font_item_t const	*foi,
1400 	int						*bptr,
1401 	dk4_er_t				*erp
1402 )
1403 {
1404 	const char		*lfn	= NULL;		/* LaTeX font name */
1405 	int				 ffl	= 0;		/* Font number or font features */
1406 	int				 ff		= 0;		/* Font features mask */
1407 #if	DK4_USE_ASSERT
1408 	assert(NULL != ostrm);
1409 	assert(NULL != foi);
1410 #endif
1411 	if (DK4_GRA_TF_EXACT_SIZE == foi->fex) {
1412 		lfn = dk4font_get_latex_font_name(dk4font_number_from_int(foi->fno));
1413 		dk4gratool_stream_string(ostrm, dk4gratool_kw[11], bptr, erp);
1414 		dk4gratool_stream_num_alpha(ostrm, foi->nf, bptr, erp);
1415 		dk4gratool_stream_string(ostrm, dk4gratool_kw[12], bptr, erp);
1416 		dk4gratool_stream_string(ostrm, lfn, bptr, erp);
1417 		dk4gratool_stream_string(ostrm, dk4gratool_kw[14], bptr, erp);
1418 		dk4gratool_stream_double(ostrm, foi->fsz, bptr, erp);
1419 		dk4gratool_stream_string(ostrm, dk4gratool_kw[13], bptr, erp);
1420 	}
1421 	else {
1422 		/* providecommand */
1423 		dk4gratool_stream_string(ostrm, dk4gratool_kw[15], bptr, erp);
1424 		dk4gratool_stream_num_alpha(ostrm, foi->nf, bptr, erp);
1425 		dk4gratool_stream_string(ostrm, dk4gratool_kw[16], bptr, erp);
1426 		/* renewcommand */
1427 		dk4gratool_stream_string(ostrm, dk4gratool_kw[17], bptr, erp);
1428 		dk4gratool_stream_num_alpha(ostrm, foi->nf, bptr, erp);
1429 		dk4gratool_stream_string(ostrm, dk4gratool_kw[18], bptr, erp);
1430 		/* Font size */
1431 		switch (foi->fex) {
1432 			case DK4_GRA_TF_SIMILAR_SIZE : case DK4_GRA_TF_NONE_SIZE : {
1433 				dk4gratool_stream_string(ostrm, dk4gratool_kw[29], bptr, erp);
1434 				dk4gratool_stream_double(ostrm, foi->fsz, bptr, erp);
1435 				dk4gratool_stream_string(ostrm, dk4gratool_kw[30], bptr, erp);
1436 				dk4gratool_stream_double(ostrm, (1.2 * foi->fsz), bptr, erp);
1437 				dk4gratool_stream_string(ostrm, dk4gratool_kw[31], bptr, erp);
1438 			} break;
1439 			default : {
1440 				/* Intentionally empty to avoid compiler warnings. */
1441 			} break;
1442 		}
1443 		/* Font family, series and shape */
1444 		switch (foi->fex) {
1445 			case DK4_GRA_TF_EXACT_NONE :
1446 			case DK4_GRA_TF_SIMILAR_SIZE :
1447 			case DK4_GRA_TF_SIMILAR_NONE : {
1448 				dk4gratool_stream_string(ostrm, dk4gratool_kw[20], bptr, erp);
1449 				if (DK4_GRA_TF_EXACT_NONE == foi->fex) {
1450 					dk4gratool_stream_string(
1451 						ostrm,
1452 						dk4font_get_latex_family_name(
1453 							dk4font_number_from_int(foi->fno)
1454 						),
1455 						bptr,
1456 						erp
1457 					);
1458 				}
1459 				else {
1460 					switch (DK4_FONT_FEATURE_FT_MASK & (foi->fno)) {
1461 						case DK4_FONT_FEATURE_SYMBOL : {
1462 							dk4gratool_stream_string(
1463 								ostrm, dk4gratool_kw[24], bptr, erp
1464 							);
1465 						} break;
1466 						case DK4_FONT_FEATURE_TTY : {
1467 							dk4gratool_stream_string(
1468 								ostrm, dk4gratool_kw[22], bptr, erp
1469 							);
1470 						} break;
1471 						case DK4_FONT_FEATURE_SANS_SERIF : {
1472 							dk4gratool_stream_string(
1473 								ostrm, dk4gratool_kw[23], bptr, erp
1474 							);
1475 						} break;
1476 						default : {	/* roman */
1477 							dk4gratool_stream_string(
1478 								ostrm, dk4gratool_kw[24], bptr, erp
1479 							);
1480 						} break;
1481 					}
1482 					/*	2019-05-14	Bugfix
1483 						To find the type we must and-combine the font
1484 						features with the mask bit as above.
1485 					*/
1486 #if	0
1487 					if (0 != (DK4_FONT_FEATURE_TTY & (foi->fno))) {
1488 						dk4gratool_stream_string(
1489 							ostrm, dk4gratool_kw[22], bptr, erp
1490 						);
1491 					}
1492 					else {
1493 						if (0 != (DK4_FONT_FEATURE_SANS_SERIF & (foi->fno))) {
1494 							dk4gratool_stream_string(
1495 								ostrm, dk4gratool_kw[23], bptr, erp
1496 							);
1497 						}
1498 						else {
1499 							dk4gratool_stream_string(
1500 								ostrm, dk4gratool_kw[24], bptr, erp
1501 							);
1502 						}
1503 					}
1504 #endif
1505 				}
1506 				dk4gratool_stream_string(ostrm, dk4gratool_kw[21], bptr, erp);
1507 				ffl = foi->fno;
1508 				if (DK4_GRA_TF_EXACT_NONE == foi->fex) {
1509 					ffl = dk4font_get_features(
1510 						dk4font_number_from_int(foi->fno)
1511 					);
1512 				}
1513 				if (0 != (DK4_FONT_FEATURE_BOLD & ffl)) {
1514 					dk4gratool_stream_string(ostrm,dk4gratool_kw[25],bptr,erp);
1515 				}
1516 				else {
1517 					dk4gratool_stream_string(ostrm,dk4gratool_kw[26],bptr,erp);
1518 				}
1519 				ff = DK4_FONT_FEATURE_ITALIC | DK4_FONT_FEATURE_OBLIQUE;
1520 				if (0 != (ff & ffl)) {
1521 					dk4gratool_stream_string(ostrm,dk4gratool_kw[27],bptr,erp);
1522 				}
1523 				else {
1524 					dk4gratool_stream_string(ostrm,dk4gratool_kw[28],bptr,erp);
1525 				}
1526 			} break;
1527 			default : {
1528 				/* Intentionally empty to avoid compiler warnings. */
1529 			} break;
1530 		}
1531 		dk4gratool_stream_string(ostrm, dk4gratool_kw[19], bptr, erp);
1532 	}
1533 }
1534 
1535 
1536 
1537 void
dk4gratool_font_definitions(dk4_stream_t * ostrm,dk4_font_collector_t * fontc,int * bptr,dk4_er_t * erp)1538 dk4gratool_font_definitions(
1539 	dk4_stream_t			*ostrm,
1540 	dk4_font_collector_t	*fontc,
1541 	int						*bptr,
1542 	dk4_er_t				*erp
1543 )
1544 {
1545 	dk4_font_item_t	*foi;	/* Current font item to write */
1546 #if	DK4_USE_ASSERT
1547 	assert(NULL != ostrm);
1548 	assert(NULL != fontc);
1549 #endif
1550 	dk4sto_it_reset(fontc->i_fn);
1551 	do {
1552 		foi = (dk4_font_item_t *)dk4sto_it_next(fontc->i_fn);
1553 		if (NULL != foi) {
1554 			dk4gratool_font_one_definition(ostrm, foi, bptr, erp);
1555 		}
1556 	} while (NULL != foi);
1557 }
1558 
1559 
1560 
1561 int
dk4gratool_compare_preamble_lines(void const * l,void const * r,int DK4_ARG_UNUSED (cr))1562 dk4gratool_compare_preamble_lines(
1563 	void const	*l,
1564 	void const	*r,
1565 	int			 DK4_ARG_UNUSED(cr)
1566 )
1567 {
1568 	dk4_gra_preamble_line_t const	*pl;
1569 	dk4_gra_preamble_line_t const	*pr;
1570 	int		 back	= 0;
1571 
1572 	DK4_UNUSED_ARG(cr)
1573 	if (NULL != l) {
1574 		if (NULL != r) {
1575 			pl = (dk4_gra_preamble_line_t const *)l;
1576 			pr = (dk4_gra_preamble_line_t const *)r;
1577 			if (pl->lineno > pr->lineno) {
1578 				back = 1;
1579 			}
1580 			else {
1581 				if (pl->lineno < pr->lineno) {
1582 					back = -1;
1583 				}
1584 			}
1585 		}
1586 		else {
1587 			back = 1;
1588 		}
1589 	}
1590 	else {
1591 		if (NULL != r) {
1592 			back = -1;
1593 		}
1594 	}
1595 	return back;
1596 }
1597 
1598 
1599 
1600 void
dk4gratool_preamble_delete(dk4_gra_preamble_line_t * ptr)1601 dk4gratool_preamble_delete(
1602 	dk4_gra_preamble_line_t	*ptr
1603 )
1604 {
1605 
1606 #if	DK4_USE_ASSERT
1607 	assert(NULL != ptr);
1608 #endif
1609 	if (NULL != ptr) {
1610 		if (NULL != ptr->text) {
1611 			dk4mem_free(ptr->text);
1612 		}
1613 		dk4mem_free(ptr);
1614 	}
1615 
1616 }
1617 
1618 
1619 
1620 dk4_gra_preamble_line_t *
dk4gratool_preamble_new(char const * textline,size_t lineno,dk4_er_t * erp)1621 dk4gratool_preamble_new(
1622 	char const	*textline,
1623 	size_t		 lineno,
1624 	dk4_er_t	*erp
1625 )
1626 {
1627 	dk4_gra_preamble_line_t	*back	= NULL;
1628 
1629 #if	DK4_USE_ASSERT
1630 	assert(NULL != textline);
1631 #endif
1632 	if (NULL != textline) {
1633 		back = dk4mem_new(dk4_gra_preamble_line_t,1,erp);
1634 		if (NULL != back) {
1635 			back->lineno = lineno;
1636 			back->text = dk4str8_dup(textline, erp);
1637 			if (NULL == back->text) {
1638 				dk4mem_free(back);
1639 				back = NULL;
1640 			}
1641 		}
1642 #if	TRACE_DEBUG
1643 		else {
1644 		}
1645 #endif
1646 	}
1647 	else {
1648 		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1649 	}
1650 
1651 	return back;
1652 }
1653 
1654 
1655 
1656 double
dk4gratool_dist_point_point(dk4_gra_point_t const * a,dk4_gra_point_t const * b,dk4_er_t * erp)1657 dk4gratool_dist_point_point(
1658 	dk4_gra_point_t const	*a,
1659 	dk4_gra_point_t	const	*b,
1660 	dk4_er_t				*erp
1661 )
1662 {
1663 	double		back = -1;
1664 	double		dx;
1665 	double		dy;
1666 #if	DK4_USE_ASSERT
1667 	assert(NULL != a);
1668 	assert(NULL != b);
1669 #endif
1670 	if ((NULL != a) && (NULL != b)) {
1671 		dx = b->x - a->x;
1672 		dy = b->y - a->y;
1673 		back = sqrt(dx * dx + dy * dy);
1674 	}
1675 	else {
1676 		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1677 	}
1678 	return back;
1679 }
1680 
1681 
1682 
1683 /**	Calculate square value.
1684 	@param	x	Original value.
1685 	@return	Square value.
1686 */
1687 
1688 static
1689 double
dbl_sq(double x)1690 dbl_sq(double x)
1691 {
1692 	return (x * x);
1693 }
1694 
1695 
1696 double
dk4gratool_dist_point_track(dk4_gra_point_t const * a,dk4_gra_point_t const * b,dk4_gra_point_t const * p,dk4_er_t * erp)1697 dk4gratool_dist_point_track(
1698 	dk4_gra_point_t const	*a,
1699 	dk4_gra_point_t const	*b,
1700 	dk4_gra_point_t const	*p,
1701 	dk4_er_t				*erp
1702 )
1703 {
1704 	dk4_gra_point_t		q;
1705 	double				back = -1.0;
1706 	double				z;
1707 	double				n;
1708 	double				t;
1709 #if	DK4_USE_ASSERT
1710 	assert(NULL != a);
1711 	assert(NULL != b);
1712 	assert(NULL != p);
1713 #endif
1714 	if ((NULL != a) && (NULL != b) && (NULL != p)) {
1715 		z =		(b->y - a->y) * p->y - a->y * b->y + dbl_sq(a->y);
1716 		z +=	(b->x - a->x) * p->x - a->x * b->x + dbl_sq(a->x);
1717 		n =		dbl_sq(b->y) - 2.0 * a->y * b->y + dbl_sq(a->y);
1718 		n +=	dbl_sq(b->x) - 2.0 * a->x * b->x + dbl_sq(a->x);
1719 		t =		z / n;
1720 		if ((0 != dk4ma_is_finite(t)) && (0.0 <= t) && (1.0 >= t)) {
1721 			q.x = a->x + t * (b->x - a->x);
1722 			q.y = a->y + t * (b->y - a->y);
1723 			back = dk4gratool_dist_point_point(&q, p, erp);
1724 		}
1725 		else {
1726 			z = dk4gratool_dist_point_point(a, p, erp);
1727 			n = dk4gratool_dist_point_point(b, p, erp);
1728 			back = ((z <= n) ? (z) : (n));
1729 		}
1730 	}
1731 	else {
1732 		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1733 	}
1734 	return back;
1735 }
1736 
1737 
1738 
1739 double
dk4gratool_dist_point_ellipse_simple(double rx,double ry,dk4_gra_point_t const * p)1740 dk4gratool_dist_point_ellipse_simple(
1741 	double					 rx,
1742 	double					 ry,
1743 	dk4_gra_point_t const	*p
1744 )
1745 {
1746 	double				px;
1747 	double				back	= -1.0;
1748 
1749 #if	DK4_USE_ASSERT
1750 	assert(NULL != p);
1751 	assert(0.0 < rx);
1752 	assert(0.0 < ry);
1753 #endif
1754 	px = (ry * p->x) / rx;
1755 	back = sqrt((px * px) + (p->y * p->y));
1756 	back = fabs(back - ry);
1757 	back = (back * rx) / ry;
1758 
1759 	return back;
1760 }
1761 
1762 
1763 
1764 double
dk4gratool_dist_point_ellipse(dk4_gra_point_t const * c,double rx,double ry,double rot,dk4_gra_point_t const * p,dk4_er_t * erp)1765 dk4gratool_dist_point_ellipse(
1766 	dk4_gra_point_t	const	*c,
1767 	double					 rx,
1768 	double					 ry,
1769 	double					 rot,
1770 	dk4_gra_point_t	const	*p,
1771 	dk4_er_t				*erp
1772 )
1773 {
1774 	dk4_gra_point_t	 myp;
1775 	double			 back	= -1.0;
1776 #if	DK4_USE_ASSERT
1777 	assert(NULL != c);
1778 	assert(NULL != p);
1779 	assert(0.0 < rx);
1780 	assert(0.0 < ry);
1781 #endif
1782 	if ((NULL != c) && (NULL != p) && (0.0 < rx) && (0.0 < ry)) {
1783 		DK4_MEMCPY(&myp,p,sizeof(dk4_gra_point_t));
1784 		myp.x -= c->x;
1785 		myp.y -= c->y;
1786 		if (1.0e-8 <= fabs(rot)) {
1787 			dk4gratool_rotate_point(&myp, (0.0 - rot));
1788 		}
1789 		back = dk4gratool_dist_point_ellipse_simple(rx, ry, &myp);
1790 	}
1791 	else {
1792 		dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
1793 	}
1794 	return back;
1795 }
1796 
1797 
1798 
1799 /* vim: set ai sw=4 ts=4 : */
1800 
1801