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