1 /*
2 Copyright (C) 2011-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: dk3fig.ctr
12 */
13
14 /** @file dk3fig.c The dk3fig module.
15 */
16
17
18
19 #include <libdk3c/dk3all.h>
20 #include <libdk3fig/dk3fig.h>
21 #include <libdk3c/dk3unused.h>
22
23
24
25
26
27
28
29 /** Localized message texts.
30 */
31 static dkChar const * const dk3fig_messages[] = {
32 /* 0 */
33 dkT("dk3fig.str"),
34
35 /* 1 */
36 dkT("Syntax error in Fig input!"),
37
38 /* 2 */
39 dkT("Color redefined!"),
40
41 /* 3 */
42 dkT("Mathematical problem in arc calculation!"),
43
44 /* 4 */
45 dkT("Object processing failed!"),
46
47 /* 5 */
48 dkT("Arrowhead calculation failed!"),
49
50 /* 6 */
51 dkT("Error while reading input file!"),
52
53 /* 7 */
54 dkT("Color not found, using black as default color!"),
55
56 /* 8 */
57 dkT("Unknown object type!"),
58
59 /* 9 */
60 dkT("Can not fill open graphics path!"),
61
62 /* 10 */
63 dkT("Converted to closed graphics path for filling."),
64
65 NULL
66
67 };
68
69
70
71
72 dkChar const * const *
dk3fig_get_localized_messages(dk3_app_t * app)73 dk3fig_get_localized_messages(dk3_app_t *app)
74 {
75 dkChar const * const *back = NULL;
76 if(app) {
77 back = dk3app_messages(
78 app, dk3fig_messages[0], (dkChar const **)dk3fig_messages
79 );
80 }
81 return back;
82 }
83
84
85
86 /** Compare two text objects.
87 This function is used to sort text objects.
88 @param pl Left text object.
89 @param pr Right text object.
90 @return Comparison result.
91 */
92 static
93 int
dk3fig_obj_text_compare(dk3_fig_obj_t const * pl,dk3_fig_obj_t const * pr)94 dk3fig_obj_text_compare(dk3_fig_obj_t const *pl, dk3_fig_obj_t const *pr)
95 {
96 int back = 0;
97 /*
98 Non-special texts before special texts.
99 */
100 if(((pl->dt).txt.ff) & DK3_FIG_FONT_FLAG_SPECIAL) {
101 if(!(((pr->dt).txt.ff) & DK3_FIG_FONT_FLAG_SPECIAL)) {
102 back = 1;
103 }
104 } else {
105 if(((pr->dt).txt.ff) & DK3_FIG_FONT_FLAG_SPECIAL) {
106 back = -1;
107 }
108 }
109 /*
110 Font selection type.
111 */
112 if(0 == back) {
113 if(((pl->dt).txt.ff) & DK3_FIG_FONT_FLAG_PS) {
114 if(!(((pr->dt).txt.ff) & DK3_FIG_FONT_FLAG_PS)) {
115 back = 1;
116 }
117 } else {
118 if(((pr->dt).txt.ff) & DK3_FIG_FONT_FLAG_PS) {
119 back = -1;
120 }
121 }
122 }
123 /*
124 Font number.
125 */
126 if(0 == back) {
127 if((pl->dt).txt.fo > (pr->dt).txt.fo) {
128 back = 1;
129 } else {
130 if((pl->dt).txt.fo < (pr->dt).txt.fo) {
131 back = -1;
132 }
133 }
134 }
135 /*
136 Font size.
137 */
138 if(0 == back) {
139 if((pl->dt).txt.fs > (pr->dt).txt.fs) {
140 back = 1;
141 } else {
142 if((pl->dt).txt.fs < (pr->dt).txt.fs) {
143 back = -1;
144 }
145 }
146 }
147 /*
148 Text string.
149 */
150 if(0 == back) {
151 back = dk3str_c8_cmp((pl->dt).txt.st, (pr->dt).txt.st);
152 if(back < -1) back = -1;
153 if(back > 1) back = 1;
154 }
155 return back;
156 }
157
158
159
160 /** Compare two non-text objects.
161 @param pl Left object.
162 @param pr Right object.
163 @return Comparison result.
164 */
165 static
166 int
dk3fig_obj_path_compare(dk3_fig_obj_t const * pl,dk3_fig_obj_t const * pr)167 dk3fig_obj_path_compare(dk3_fig_obj_t const *pl, dk3_fig_obj_t const *pr)
168 {
169 int back = 0;
170 /*
171 Line width.
172 */
173 if(0 == back) {
174 if(pl->lw > pr->lw) { back = 1; }
175 else { if(pl->lw < pr->lw) { back = -1; } }
176 }
177 /*
178 Pen color.
179 */
180 if(0 == back) {
181 if(pl->pc > pr->pc) { back = 1; }
182 else { if(pl->pc < pr->pc) { back = -1; } }
183 }
184 /*
185 Line cap.
186 */
187 if(0 == back) {
188 if(pl->cs > pr->cs) { back = 1; }
189 else { if(pl->cs < pr->cs) { back = -1; } }
190 }
191 /*
192 Line join.
193 */
194 if(0 == back) {
195 if(pl->js > pr->js) { back = 1; }
196 else { if(pl->js < pr->js) { back = -1; } }
197 }
198 /*
199 Line style, style value for equal line style.
200 */
201 if(0 == back) {
202 if(pl->ls > pr->ls) { back = 1; }
203 else { if(pl->ls < pr->ls) { back = -1; } }
204 if(0 == back) {
205 if(pl->sv > pr->sv) { back = 1; }
206 else { if(pl->sv < pr->sv) { back = -1; } }
207 }
208 }
209 /*
210 Non-closed before closed.
211 */
212 if(0 == back) {
213 if(pl->cl) {
214 if(pr->cl) {
215 /*
216 Fill color.
217 */
218 if(pl->fc > pr->fc) { back = 1; }
219 else { if(pl->fc < pr->fc) { back = -1; } }
220 /*
221 Fill style.
222 */
223 if(0 == back) {
224 if(pl->fi > pr->fi) { back = 1; }
225 else { if(pl->fi < pr->fi) { back = -1; } }
226 }
227 } else {
228 back = 1;
229 }
230 } else {
231 if(pr->cl) {
232 back = -1;
233 }
234 }
235 }
236 /*
237 Object type.
238 */
239 if(0 == back) {
240 if(pl->ot > pr->ot) { back = 1; }
241 else { if(pl->ot < pr->ot) { back = -1; } }
242 }
243 /*
244 Sub type.
245 */
246 if(0 == back) {
247 if(pl->st > pr->st) { back = 1; }
248 else { if(pl->st < pr->st) { back = -1; } }
249 }
250 return back;
251 }
252
253
254
255 /** Compare two Fig objects for sorted storing.
256 We must draw the deepest layer elements first (by definition).
257 Additionally we sort elements by multiple attributes
258 (non-text elements before texts, pen color, fill color and type,
259 line style, line width, cap style, join style) to group elements
260 with equal attributes. This is done to minimize instructions
261 for writing colors, line style, line width...
262 @param l Left Fig object.
263 @param r Right Fig object.
264 @param cr Comparison criteria (ignored).
265 @return Comparison result.
266 */
267 static
268 int
dk3fig_obj_compare(void const * l,void const * r,int DK3_ARG_UNUSED (cr))269 dk3fig_obj_compare(void const *l, void const *r, int DK3_ARG_UNUSED(cr) )
270 {
271 int back = 0;
272 dk3_fig_obj_t const *pl;
273 dk3_fig_obj_t const *pr;
274
275 DK3_UNUSED_ARG(cr)
276 if(l) {
277 if(r) {
278 pl = (dk3_fig_obj_t const *)l;
279 pr = (dk3_fig_obj_t const *)r;
280 /*
281 Deepest layers first.
282 */
283 if(pl->la > pr->la) { back = -1; }
284 else { if(pl->la < pr->la) { back = 1; } }
285 /*
286 Non-texts before texts.
287 */
288 if(0 == back) {
289 if(DK3_FIG_OBJ_TEXT == pl->ot) {
290 if(!(DK3_FIG_OBJ_TEXT == pr->ot)) {
291 back = 1;
292 } else {
293 back = dk3fig_obj_text_compare(pl, pr);
294 }
295 } else {
296 if(DK3_FIG_OBJ_TEXT == pr->ot) {
297 back = -1;
298 } else {
299 back = dk3fig_obj_path_compare(pl, pr);
300 }
301 }
302 }
303 /*
304 Line number of definition.
305 */
306 if(0 == back) {
307 if(pl->li > pr->li) { back = 1; }
308 else { if(pl->li < pr->li) { back = -1; } }
309 }
310 } else back = 1;
311 } else {
312 if(r) back = -1;
313 }
314 return back;
315 }
316
317
318
319 /** Destroy arrowhead, release memory.
320 @param ah Arrowhead to destroy.
321 */
322 static
323 void
dk3fig_ah_delete(dk3_fig_ah_t * ah)324 dk3fig_ah_delete(dk3_fig_ah_t *ah)
325 {
326
327 if(ah) {
328 if(ah->o1) {
329 dk3fig_obj_delete((dk3_fig_obj_t *)(ah->o1));
330 }
331 if(ah->o2) {
332 dk3fig_obj_delete((dk3_fig_obj_t *)(ah->o2));
333 }
334 dk3_delete(ah);
335 }
336 }
337
338
339
340 /** Create new arrowhead structure.
341 @param app Application structure for diagnostics.
342 @return Pointer to new structure on success, NULL on error.
343 */
344 static
345 dk3_fig_ah_t *
dk3fig_ah_new(dk3_app_t * app)346 dk3fig_ah_new(dk3_app_t *app)
347 {
348 dk3_fig_ah_t *back = NULL;
349 back = dk3_new_app(dk3_fig_ah_t,1,app);
350 if(back) {
351 back->o1 = NULL;
352 back->o2 = NULL;
353 back->wi = 0.0;
354 back->he = 0.0;
355 back->as = 0;
356 back->af = 0;
357 }
358 return back;
359 }
360
361
362
363 void
dk3fig_obj_delete(dk3_fig_obj_t * obj)364 dk3fig_obj_delete(dk3_fig_obj_t *obj)
365 {
366
367 if(obj) {
368 if(obj->af) {
369 dk3fig_ah_delete(obj->af);
370 }
371 if(obj->ab) {
372 dk3fig_ah_delete(obj->ab);
373 }
374 switch(obj->ot) {
375 case DK3_FIG_OBJ_TEXT: {
376 if((obj->dt).txt.st) {
377 dk3_release((obj->dt).txt.st);
378 }
379 } break;
380 case DK3_FIG_OBJ_SPLINE: {
381 if((obj->dt).spl.po) {
382 dk3_release((obj->dt).spl.po);
383 }
384 if((obj->dt).spl.fslc) {
385 dk3_release((obj->dt).spl.fslc);
386 }
387 } break;
388 case DK3_FIG_OBJ_POLYLINE: {
389 if((obj->dt).pol.po) {
390 dk3_release((obj->dt).pol.po);
391 }
392 if((obj->dt).pol.fn) {
393 dk3_release((obj->dt).pol.fn);
394 }
395 } break;
396 }
397 obj->af = NULL;
398 obj->ab = NULL;
399 dk3_delete(obj);
400 }
401 }
402
403
404
405 /** Reset all members of a drawing object.
406 @param drw Drawing object to reset.
407 */
408 static
409 void
dk3fig_initialize_empty_drawing(dk3_fig_drawing_t * drw)410 dk3fig_initialize_empty_drawing(dk3_fig_drawing_t *drw)
411 {
412
413 dk3bb_reset(&(drw->bb));
414 drw->msg = NULL;
415 drw->app = NULL;
416 drw->sobj = NULL;
417 drw->iobj = NULL;
418 drw->scol = NULL;
419 drw->icol = NULL;
420 drw->cobj = NULL;
421 drw->dsd = NULL;
422 drw->res = 1200.0;
423 drw->lineno = 0UL;
424 drw->lres = 0;
425 drw->cind = 0;
426 drw->cxy = 0;
427 drw->state = 0;
428 drw->ec = 0;
429 drw->srctype = DK3_FIG_SRCTYPE_UNKNOWN;
430 drw->xssbs = 8;
431 drw->qbs = 4;
432 drw->transcol = -2;
433 drw->coah = 0;
434 drw->xsah = 0;
435 drw->cosp = 0;
436 drw->cofop = 1;
437 drw->ahbs = 0;
438 drw->bbts = 0;
439 drw->arcspp = 8.0;
440 drw->splspp = 8.0;
441 drw->minspp = 4;
442 drw->codi = 3;
443 drw->xsprec = 0.04; /* originally 1200.0 / 25400.0 */
444 drw->lwbp = 0.9; /* 1/80 inch */
445
446 }
447
448
449
450 /** Compare two Fig colors.
451 @param l Left object.
452 @param r Right color object or number.
453 @param cr Comparison criteria (0=color/color, 1=color/number).
454 @return Comparison result.
455 */
456 static
457 int
dk3fig_color_compare(void const * l,void const * r,int cr)458 dk3fig_color_compare(void const *l, void const *r, int cr)
459 {
460 int back = 0;
461 dk3_fig_color_t const *pl;
462 dk3_fig_color_t const *pr;
463 int *ip;
464 if(l) {
465 if(r) {
466 pl = (dk3_fig_color_t const *)l;
467 pr = (dk3_fig_color_t const *)r;
468 ip = (int *)r;
469 switch(cr) {
470 case 1: {
471 if(pl->i > (*ip)) {
472 back = 1;
473 } else {
474 if(pl->i < (*ip)) {
475 back = -1;
476 }
477 }
478 } break;
479 default: {
480 if(pl->i > pr->i) {
481 back = 1;
482 } else {
483 if(pl->i < pr->i) {
484 back = -1;
485 }
486 }
487 } break;
488 }
489 } else back = 1;
490 } else {
491 if(r) back = -1;
492 }
493 return back;
494 }
495
496
497 dk3_fig_drawing_t *
dk3fig_drawing_new(dk3_app_t * app,dkChar const * const * msg)498 dk3fig_drawing_new(dk3_app_t *app, dkChar const * const *msg)
499 {
500 dk3_fig_drawing_t *back = NULL;
501
502 if(app) {
503 back = dk3_new_app(dk3_fig_drawing_t,1,app);
504 if(back) {
505 dk3fig_initialize_empty_drawing(back);
506 back->app = app;
507 back->msg = msg;
508 back->sobj = dk3sto_open_app(app);
509 if(back->sobj) {
510 dk3sto_set_comp(back->sobj, dk3fig_obj_compare, 0);
511 back->iobj = dk3sto_it_open(back->sobj);
512 if(back->iobj) {
513 back->scol = dk3sto_open_app(app);
514 if(back->scol) {
515 dk3sto_set_comp(back->scol, dk3fig_color_compare, 0);
516 back->icol = dk3sto_it_open(back->scol);
517 if(back->icol) {
518 /* Place for further initialization here */
519 } else {
520 dk3fig_drawing_delete(back);
521 back = NULL;
522 }
523 } else {
524 dk3fig_drawing_delete(back);
525 back = NULL;
526 }
527 } else {
528 dk3fig_drawing_delete(back);
529 back = NULL;
530 }
531 } else {
532 dk3fig_drawing_delete(back);
533 back = NULL;
534 }
535 } else {
536 }
537 }
538 return back;
539 }
540
541
542
543 void
dk3fig_drawing_delete(dk3_fig_drawing_t * drw)544 dk3fig_drawing_delete(dk3_fig_drawing_t *drw)
545 {
546 dk3_fig_color_t *co; /* Current color to release. */
547 dk3_fig_obj_t *po; /* Current Fig object to release. */
548
549 if(drw) {
550 /*
551 Remove all objects.
552 */
553 if(drw->sobj) {
554 if(drw->iobj) {
555 dk3sto_it_reset(drw->iobj);
556 while(NULL != (po = (dk3_fig_obj_t *)dk3sto_it_next(drw->iobj))) {
557 dk3fig_obj_delete(po);
558 }
559 dk3sto_it_close(drw->iobj);
560 }
561 dk3sto_close(drw->sobj);
562 }
563 /*
564 Remove all colors.
565 */
566 if(drw->scol) {
567 if(drw->icol) {
568 dk3sto_it_reset(drw->icol);
569 while(NULL != (co = (dk3_fig_color_t *)dk3sto_it_next(drw->icol))) {
570
571 dk3_delete(co);
572 }
573 dk3sto_it_close(drw->icol);
574 }
575 dk3sto_close(drw->scol);
576 }
577 /*
578 Reset all members.
579 */
580 dk3fig_initialize_empty_drawing(drw);
581 /*
582 Release memory.
583 */
584 drw->app = NULL;
585 drw->msg = NULL;
586 dk3_delete(drw);
587 }
588 }
589
590
591
592 /** Internal function to create Fig object and initialize it.
593 @param li Line number of object definition in file.
594 @param la Layer number.
595 @param ot Object type.
596 @param st Object subtype.
597 @param lw Line width.
598 @param pc Pen color.
599 @param fc Fill color.
600 @param fi Fill type.
601 @param cs Cap style.
602 @param js Join style.
603 @param ls Line style.
604 @param sv Style value.
605 @param af Flag: Arrowhead forward.
606 @param ab Flag: Arrowhead backward.
607 @param po Flag: Path object (non-text object).
608 @param cl Flag: Closed path object.
609 @param app Application structure for diagnostics, may be NULL.
610 @return Pointer to new object on success, NULL on error.
611 */
612 static
613 dk3_fig_obj_t *
dk3fig_obj_internal_new(unsigned long li,int la,int ot,int st,int lw,int pc,int fc,int fi,int cs,int js,int ls,double sv,int af,int ab,int po,int cl,dk3_app_t * app)614 dk3fig_obj_internal_new(
615 unsigned long li,
616 int la,
617 int ot,
618 int st,
619 int lw,
620 int pc,
621 int fc,
622 int fi,
623 int cs,
624 int js,
625 int ls,
626 double sv,
627 int af,
628 int ab,
629 int po,
630 int cl,
631 dk3_app_t *app
632 )
633 {
634 dk3_fig_obj_t *back = NULL;
635
636 back = dk3_new_app(dk3_fig_obj_t,1,app);
637 if(back) {
638 back->af = NULL;
639 back->ab = NULL;
640 back->dsd = NULL;
641 back->sv = sv;
642 back->li = li;
643 back->la = la;
644 back->ot = ot;
645 back->st = st;
646 back->lw = lw;
647 back->pc = pc;
648 back->fc = fc;
649 back->fi = fi;
650 back->cs = cs;
651 back->js = js;
652 back->ls = ls;
653 back->cl = ((cl) ? 0x01 : 0x00);
654 if(back->lw < 0) {
655 back->lw = 0;
656 if(po) {
657 /* +++++ Warning: Illegal line width corrected! */
658 }
659 }
660 if(back->pc < -1) {
661 back->pc = -1;
662 /* +++++ Warning: Illegal pen color definition corrected! */
663 }
664 if(back->fc < DK3_FIG_COLOR_DEFAULT) {
665 back->fc = DK3_FIG_COLOR_DEFAULT;
666 if((po) && (cl)) {
667 /* +++++ Warning: Illegal fill color definition corrected! */
668 }
669 }
670 if(back->fi < DK3_FIG_COLOR_DEFAULT) {
671 back->fi = DK3_FIG_COLOR_DEFAULT;
672 if((po) && (cl)) {
673 /* +++++ Warning: Illegal fill style corrected! */
674 }
675 } else {
676 if(back->fi > 62) {
677 back->fi = 62;
678 if((po) && (cl)) {
679 /* +++++ Warning: Illegal fill style corrected! */
680 }
681 } else {
682 if((DK3_FIG_COLOR_BLACK == fc) || (DK3_FIG_COLOR_WHITE == fc)) {
683 if((back->fi >= 21) && (back->fi <= 40)) {
684 back->fi = 20;
685 if((po) && (cl)) {
686 /* +++++ Warning: Illegal fill style corrected! */
687 }
688 }
689 }
690 }
691 }
692 if(DK3_FIG_LC_BUTT != back->cs) {
693 if(DK3_FIG_LC_ROUND != back->cs) {
694 if(DK3_FIG_LC_PROJECTING != back->cs) {
695 back->cs = DK3_FIG_LC_BUTT;
696 if(po) {
697 /* +++++ Warning: Illegal line cap style corrected! */
698 }
699 }
700 }
701 }
702 if(DK3_FIG_LJ_MITER != back->js) {
703 if(DK3_FIG_LJ_ROUND != back->js) {
704 if(DK3_FIG_LJ_BEVEL != back->js) {
705 back->js = DK3_FIG_LJ_MITER;
706 if(po) {
707 /* +++++ Warning: Illegal line join style corrected! */
708 }
709 }
710 }
711 }
712 if(back->ls < DK3_FIG_LS_SOLID) {
713 back->ls = DK3_FIG_LS_SOLID;
714 if(ls < DK3_FIG_LS_DEFAULT) {
715 if(po) {
716 /* +++++ Warning: Illegal line style corrected! */
717 }
718 }
719 } else {
720 if(back->ls > DK3_FIG_LS_DASH_TRIPLE_DOTTED) {
721 back->ls = DK3_FIG_LS_SOLID;
722 if(po) {
723 /* +++++ Warning: Illegal line style corrected! */
724 }
725 }
726 }
727 } else {
728 }
729 if((po) && (!(cl))) {
730 if(NULL != back) {
731 if(af) {
732 back->af = dk3fig_ah_new(app);
733 if(!(back->af)) {
734 dk3fig_obj_delete(back);
735 back = NULL;
736 }
737 }
738 }
739 if (NULL != back) {
740 if(ab) {
741 back->ab = dk3fig_ah_new(app);
742 if(!(back->ab)) {
743 dk3fig_obj_delete(back);
744 back = NULL;
745 }
746 }
747 }
748 } else {
749 if((af) || (ab)) {
750 /* +++++ Warning: Arrowhead ignored for closed path! */
751 }
752 }
753 return back;
754 }
755
756
757
758 /** Initialize details for arc.
759 @param obj Object to initialize.
760 */
761 static
762 void
dk3fig_initialize_arc_details(dk3_fig_obj_t * obj)763 dk3fig_initialize_arc_details(dk3_fig_obj_t *obj)
764 {
765 (obj->dt).arc.xc = 0.0;
766 (obj->dt).arc.yc = 0.0;
767 (obj->dt).arc.ra = 0.0;
768 (obj->dt).arc.x1 = 0.0;
769 (obj->dt).arc.y1 = 0.0;
770 (obj->dt).arc.x2 = 0.0;
771 (obj->dt).arc.y2 = 0.0;
772 (obj->dt).arc.x3 = 0.0;
773 (obj->dt).arc.y3 = 0.0;
774 (obj->dt).arc.as = 0.0;
775 (obj->dt).arc.ae = 0.0;
776 (obj->dt).arc.di = 0x00;
777 }
778
779
780
781 /** Initialize ellipse details.
782 @param obj Object to initialize.
783 */
784 static
785 void
dk3fig_initialize_ellipse_details(dk3_fig_obj_t * obj)786 dk3fig_initialize_ellipse_details(dk3_fig_obj_t *obj)
787 {
788 (obj->dt).ell.an = 0.0;
789 (obj->dt).ell.cx = 0.0;
790 (obj->dt).ell.cy = 0.0;
791 (obj->dt).ell.rx = 0.0;
792 (obj->dt).ell.ry = 0.0;
793 }
794
795
796
797 /** Initialize polyline details.
798 @param obj Object to initialize.
799 @param np Number of points.
800 @param app Application structure for diagnostics.
801 @return 1 on success, 0 on error (not enough memory).
802 */
803 static
804 int
dk3fig_initialize_polyline_details(dk3_fig_obj_t * obj,size_t np,dk3_app_t * app)805 dk3fig_initialize_polyline_details(dk3_fig_obj_t *obj,size_t np,dk3_app_t *app)
806 {
807 int back = 0;
808 (obj->dt).pol.fn = NULL;
809 (obj->dt).pol.po = NULL;
810 (obj->dt).pol.ra = 0.0;
811 (obj->dt).pol.xs = 0.0;
812 (obj->dt).pol.ys = 0.0;
813 (obj->dt).pol.xe = 0.0;
814 (obj->dt).pol.ye = 0.0;
815 (obj->dt).pol.np = np;
816 (obj->dt).pol.flf = 0;
817 (obj->dt).pol.po = dk3_new_app(dk3_fig_poly_point_t,np,app);
818 if((obj->dt).pol.po) {
819 back = 1;
820 }
821 return back;
822 }
823
824
825
826 /** Initialize spline details.
827 @param obj Object to initialize.
828 @param np Number of spline points.
829 @param app Application structure for diagnostics.
830 @return 1 on success, 0 on error (not enough memory).
831 */
832 static
833 int
dk3fig_initialize_spline_details(dk3_fig_obj_t * obj,size_t np,dk3_app_t * app)834 dk3fig_initialize_spline_details(dk3_fig_obj_t *obj,size_t np,dk3_app_t *app)
835 {
836 double *xptr;
837 size_t i;
838 int back = 0;
839 (obj->dt).spl.po = NULL;
840 (obj->dt).spl.fslc = NULL;
841 (obj->dt).spl.ts = -1.0;
842 (obj->dt).spl.te = -1.0;
843 (obj->dt).spl.np = np;
844 (obj->dt).spl.po = dk3_new_app(dk3_fig_spline_point_t, np, app);
845 if((obj->dt).spl.po) {
846 back = 1;
847 switch(obj->st) {
848 case 0: case 2: case 4: {
849 if(((obj->af) || (obj->ab)) && (2 <= np)) {
850 (obj->dt).spl.fslc = dk3_new_app(double, (np-1), app);
851 if((obj->dt).spl.fslc) {
852 /* Initialize cache to -1 */
853 xptr = (obj->dt).spl.fslc;
854 i = np - 1;
855 while(i--) { *(xptr++) = -1.0; }
856 } else {
857 back = 0;
858 }
859 }
860 } break;
861 }
862 }
863 return back;
864 }
865
866
867
868 /** Initialize text details.
869 @param obj Object to initialize.
870 @param tx Text for text object.
871 @param app Application structure for diagnostics.
872 @return 1 on success, 0 on error (not enough memory).
873 */
874 static
875 int
dk3fig_initialize_text_details(dk3_fig_obj_t * obj,char const * tx,dk3_app_t * app)876 dk3fig_initialize_text_details(dk3_fig_obj_t *obj,char const *tx,dk3_app_t *app)
877 {
878 int back = 0;
879 (obj->dt).txt.st = NULL;
880 (obj->dt).txt.x = 0.0;
881 (obj->dt).txt.y = 0.0;
882 (obj->dt).txt.an = 0.0;
883 (obj->dt).txt.fs = 0.0;
884 (obj->dt).txt.he = 0.0;
885 (obj->dt).txt.wi = 0.0;
886 (obj->dt).txt.fo = 0;
887 (obj->dt).txt.ff = 0;
888 (obj->dt).txt.st = dk3str_c8_dup_app(tx, app);
889 if((obj->dt).txt.st) {
890 back = 1;
891 }
892 return back;
893 }
894
895
896
897 dk3_fig_obj_t *
dk3fig_obj_new(unsigned long li,int la,int ot,int st,int lw,int pc,int fc,int fi,int cs,int js,int ls,double sv,int af,int ab,size_t np,char const * txt,dk3_app_t * app)898 dk3fig_obj_new(
899 unsigned long li,
900 int la,
901 int ot,
902 int st,
903 int lw,
904 int pc,
905 int fc,
906 int fi,
907 int cs,
908 int js,
909 int ls,
910 double sv,
911 int af,
912 int ab,
913 size_t np,
914 char const *txt,
915 dk3_app_t *app
916 )
917 {
918 dk3_fig_obj_t *back = NULL;
919
920 if((la < 0) || (la > 999)) {
921 /* +++++ Warning: Illegal layer number! */
922 }
923 switch(ot) {
924 case DK3_FIG_OBJ_ARC: {
925 switch(st) {
926 case DK3_FIG_OBJ_SUB_ARC_OPEN: {
927 back = dk3fig_obj_internal_new(
928 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
929 );
930 } break;
931 case DK3_FIG_OBJ_SUB_ARC_CLOSED: {
932 back = dk3fig_obj_internal_new(
933 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
934 );
935 } break;
936 case 0: {
937 /* +++++ Warning: jFig closed arc bug. */
938 back = dk3fig_obj_internal_new(
939 li, la, ot, DK3_FIG_OBJ_SUB_ARC_CLOSED,
940 lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
941 );
942 } break;
943 default: {
944 /* +++++ Warning: Illegal sub type corrected! */
945 back = dk3fig_obj_internal_new(
946 li, la, ot, DK3_FIG_OBJ_SUB_ARC_CLOSED,
947 lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
948 );
949 } break;
950 }
951 if(back) {
952 dk3fig_initialize_arc_details(back);
953 }
954 } break;
955 case DK3_FIG_OBJ_ELLIPSE: {
956 switch(st) {
957 case DK3_FIG_OBJ_SUB_ELL_RADII: {
958 back = dk3fig_obj_internal_new(
959 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
960 );
961 } break;
962 case DK3_FIG_OBJ_SUB_ELL_DIAMETERS: {
963 back = dk3fig_obj_internal_new(
964 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
965 );
966 } break;
967 case DK3_FIG_OBJ_SUB_CIR_RADIUS: {
968 back = dk3fig_obj_internal_new(
969 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
970 );
971 } break;
972 case DK3_FIG_OBJ_SUB_CIR_DIAMETER: {
973 back = dk3fig_obj_internal_new(
974 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
975 );
976 } break;
977 default: {
978 /* +++++ Warning: Illegal sub type corrected! */
979 back = dk3fig_obj_internal_new(
980 li, la, ot, DK3_FIG_OBJ_SUB_ELL_RADII,
981 lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
982 );
983 } break;
984 }
985 if(back) {
986 dk3fig_initialize_ellipse_details(back);
987 }
988 } break;
989 case DK3_FIG_OBJ_POLYLINE: {
990 switch(st) {
991 case DK3_FIG_OBJ_SUB_POLYLINE: {
992 back = dk3fig_obj_internal_new(
993 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
994 );
995 } break;
996 case DK3_FIG_OBJ_SUB_BOX: {
997 back = dk3fig_obj_internal_new(
998 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
999 );
1000 } break;
1001 case DK3_FIG_OBJ_SUB_POLYGON: {
1002 back = dk3fig_obj_internal_new(
1003 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
1004 );
1005 } break;
1006 case DK3_FIG_OBJ_SUB_ARCBOX: {
1007 back = dk3fig_obj_internal_new(
1008 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
1009 );
1010 } break;
1011 case DK3_FIG_OBJ_SUB_IMAGE: {
1012 back = dk3fig_obj_internal_new(
1013 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
1014 );
1015 } break;
1016 default: {
1017 /* +++++ Warning: Illegal sub type corrected! */
1018 back = dk3fig_obj_internal_new(
1019 li, la, ot, DK3_FIG_OBJ_SUB_POLYLINE,
1020 lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
1021 );
1022 } break;
1023 }
1024 if(back) {
1025 if(!dk3fig_initialize_polyline_details(back, np, app)) {
1026 dk3fig_obj_delete(back);
1027 back = NULL;
1028 }
1029 }
1030 } break;
1031 case DK3_FIG_OBJ_SPLINE: {
1032 switch(st) {
1033 case DK3_FIG_OBJ_SUB_OPEN_APPRO: {
1034 back = dk3fig_obj_internal_new(
1035 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
1036 );
1037 } break;
1038 case DK3_FIG_OBJ_SUB_CLOSED_APPRO: {
1039 back = dk3fig_obj_internal_new(
1040 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
1041 );
1042 } break;
1043 case DK3_FIG_OBJ_SUB_OPEN_INT: {
1044 back = dk3fig_obj_internal_new(
1045 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
1046 );
1047 } break;
1048 case DK3_FIG_OBJ_SUB_CLOSED_INT: {
1049 back = dk3fig_obj_internal_new(
1050 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
1051 );
1052 } break;
1053 case DK3_FIG_OBJ_SUB_OPEN_X: {
1054 back = dk3fig_obj_internal_new(
1055 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
1056 );
1057 } break;
1058 case DK3_FIG_OBJ_SUB_CLOSED_X: {
1059 back = dk3fig_obj_internal_new(
1060 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 1, app
1061 );
1062 } break;
1063 default: {
1064 /* +++++ Warning: Illegal sub type corrected! */
1065 back = dk3fig_obj_internal_new(
1066 li, la, ot, DK3_FIG_OBJ_SUB_OPEN_X,
1067 lw, pc, fc, fi, cs, js, ls, sv, af, ab, 1, 0, app
1068 );
1069 } break;
1070 }
1071 if(back) {
1072 if(!dk3fig_initialize_spline_details(back, np, app)) {
1073 dk3fig_obj_delete(back);
1074 back = NULL;
1075 }
1076 }
1077 } break;
1078 case DK3_FIG_OBJ_TEXT: {
1079 if(txt) {
1080 back = dk3fig_obj_internal_new(
1081 li, la, ot, st, lw, pc, fc, fi, cs, js, ls, sv, af, ab, 0, 0, app
1082 );
1083 if(back) {
1084 if(!dk3fig_initialize_text_details(back, txt, app)) {
1085 dk3fig_obj_delete(back);
1086 back = NULL;
1087 }
1088 }
1089 } else {
1090 /* +++++ ERROR: No text specified! */
1091 }
1092 } break;
1093 case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: {
1094 back = dk3fig_obj_internal_new(
1095 li, la, ot, ((st) ? 1 : 0),
1096 lw, pc, fc, fi, cs, js, ls, sv, af, ab, 0,
1097 ((st) ? 1 : 0),
1098 app
1099 );
1100 } break;
1101 default: {
1102 /* +++++ ERROR: Can not create object! */
1103 } break;
1104 }
1105 return back;
1106 }
1107
1108
1109 void
dk3fig_obj_init(dk3_fig_obj_t * obj)1110 dk3fig_obj_init(dk3_fig_obj_t *obj)
1111 {
1112 if(obj) {
1113 dk3mem_res((void *)obj, sizeof(dk3_fig_obj_t));
1114 obj->af = NULL;
1115 obj->ab = NULL;
1116 obj->dsd = NULL;
1117 obj->sv = 0.0;
1118 }
1119 }
1120
1121
1122
1123 void
dk3fig_set_options_bsegs(dk3_fig_drawing_t * drw,size_t xssbs,size_t qbs)1124 dk3fig_set_options_bsegs(dk3_fig_drawing_t *drw, size_t xssbs, size_t qbs)
1125 {
1126 if(drw) {
1127 drw->xssbs = xssbs;
1128 drw->qbs = qbs;
1129 if(xssbs < 2) drw->xssbs = 2;
1130 if(qbs < 2) drw->qbs = 2;
1131 }
1132 }
1133
1134
1135
1136 void
dk3fig_set_options_lwbp(dk3_fig_drawing_t * drw,double val)1137 dk3fig_set_options_lwbp(dk3_fig_drawing_t *drw, double val)
1138 {
1139 if (drw) {
1140 drw->lwbp = val;
1141 }
1142 }
1143
1144
1145
1146 void
dk3fig_set_options_coah(dk3_fig_drawing_t * drw,int val)1147 dk3fig_set_options_coah(dk3_fig_drawing_t *drw, int val)
1148 {
1149 if(drw) {
1150 drw->coah = ((val) ? 1 : 0);
1151 }
1152 }
1153
1154
1155
1156 void
dk3fig_set_options_xsah(dk3_fig_drawing_t * drw,int val)1157 dk3fig_set_options_xsah(dk3_fig_drawing_t *drw, int val)
1158 {
1159 if (drw) {
1160 drw->xsah = ((val) ? 1 : 0);
1161 }
1162 }
1163
1164
1165
1166 void
dk3fig_set_options_cosp(dk3_fig_drawing_t * drw,int val)1167 dk3fig_set_options_cosp(dk3_fig_drawing_t *drw, int val)
1168 {
1169 if(drw) {
1170 drw->cosp = ((val) ? 1 : 0);
1171 }
1172 }
1173
1174
1175
1176 void
dk3fig_set_options_bbts(dk3_fig_drawing_t * drw,int val)1177 dk3fig_set_options_bbts(dk3_fig_drawing_t *drw, int val)
1178 {
1179 if(drw) {
1180 drw->bbts = ((val) ? 1 : 0);
1181 }
1182 }
1183
1184
1185
1186 void
dk3fig_set_options_cofop(dk3_fig_drawing_t * drw,int val)1187 dk3fig_set_options_cofop(dk3_fig_drawing_t *drw, int val)
1188 {
1189 if(drw) {
1190 drw->cofop = ((val) ? 1 : 0);
1191 }
1192 }
1193
1194
1195
1196 void
dk3fig_set_options_ah_bisection(dk3_fig_drawing_t * drw,int val)1197 dk3fig_set_options_ah_bisection(dk3_fig_drawing_t *drw, int val)
1198 {
1199 if(drw) {
1200 drw->ahbs = ((val) ? 1 : 0);
1201 }
1202 }
1203
1204
1205
1206 void
dk3fig_set_options_srctype(dk3_fig_drawing_t * drw,int val)1207 dk3fig_set_options_srctype(dk3_fig_drawing_t *drw, int val)
1208 {
1209 if(drw) {
1210 drw->srctype = val;
1211 }
1212 }
1213
1214
1215
1216 void
dk3fig_set_options_arrows(dk3_fig_drawing_t * drw,double arcspp,double splspp,size_t minspp)1217 dk3fig_set_options_arrows(
1218 dk3_fig_drawing_t *drw,
1219 double arcspp,
1220 double splspp,
1221 size_t minspp
1222 )
1223 {
1224 if(drw) {
1225 drw->arcspp = arcspp;
1226 if(drw->arcspp < 2.0) { drw->arcspp = 2.0; }
1227 drw->splspp = splspp;
1228 if(drw->splspp < 2.0) { drw->splspp = 2.0; }
1229 drw->minspp = minspp;
1230 if(drw->minspp < 2) { drw->minspp = 2; }
1231 }
1232 }
1233
1234
1235
1236 void
dk3fig_set_options_iteration_precision(dk3_fig_drawing_t * drw,double prec)1237 dk3fig_set_options_iteration_precision(
1238 dk3_fig_drawing_t *drw,
1239 double prec
1240 )
1241 {
1242 if(drw) {
1243 drw->xsprec = fabs(prec);
1244 if(drw->xsprec < 1.0e-24) {
1245 drw->xsprec = 1.0e-24;
1246 }
1247 }
1248 }
1249
1250
1251 void
dk3fig_gs_init(dk3_graphics_state_t * gs)1252 dk3fig_gs_init(dk3_graphics_state_t *gs)
1253 {
1254 if(gs) {
1255 (gs->c1).r = (gs->c1).g = (gs->c1).b = 0.0;
1256 (gs->c2).r = (gs->c2).g = (gs->c2).b = 0.0;
1257 gs->lw = -1.0;
1258 gs->sv = -1.0;
1259 gs->slw = -1.0;
1260 gs->lc = gs->lj = gs->ls = 0;
1261 gs->hc1 = gs->hc2 = gs->hlc = gs->hlj = gs->hlw = gs->hls = 0;
1262 gs->hfn = 0; gs->fs = -1.0; gs->fn = -1;
1263 }
1264 }
1265
1266
1267
1268 void
dk3fig_set_options_codi(dk3_fig_drawing_t * drw,size_t codi)1269 dk3fig_set_options_codi(
1270 dk3_fig_drawing_t *drw,
1271 size_t codi
1272 )
1273 {
1274 if(drw) {
1275 drw->codi = codi;
1276 }
1277 }
1278
1279
1280
1281 void
dk3fig_set_ec(dk3_fig_drawing_t * drw,int ec)1282 dk3fig_set_ec(dk3_fig_drawing_t *drw, int ec)
1283 {
1284 if(drw) {
1285 if(0 == drw->ec) {
1286 drw->ec = ec;
1287 }
1288 }
1289 }
1290
1291
1292