1 /*
2 Copyright (C) 2012-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: f2lud.ctr
12 */
13 
14 /**	@file f2lud.c The f2lud module.
15 */
16 
17 
18 #include <libdk3c/dk3all.h>
19 #include <libdk3c/dk3bezcu.h>
20 #include <fig2lat/fig2lat.h>
21 #include <libdk3c/dk3xsp.h>
22 #include <fig2lat/f2lud.h>
23 #include <fig2lat/f2lsvg.h>
24 #include <fig2lat/f2lpgf.h>
25 #include <fig2lat/f2lpdf.h>
26 #include <fig2lat/f2leps.h>
27 #include <libdk3fig/dk3figto.h>
28 #if 0
29 #include <libdk3c/dkt-version.h>
30 #endif
31 #include <libdk4base/dk4vers.h>
32 #include <fig2lat/f2ludpat.h>
33 #include <fig2lat/f2lpara.h>
34 #include <libdk3c/dk3unused.h>
35 
36 
37 
38 
39 
40 
41 
42 /**	Keywords used by the module.
43 */
44 static char const * const	f2lud_c8_kw[] = {
45 /* 0 */
46 "fig object begin %lu, line %lu, type %ld %ld, layer %d",
47 
48 /* 1 */
49 "fig object end %lu",
50 
51 /* 2 */
52 "arrowhead forward begin, type=%d, fill=%d, length=%lg, width=%lg",
53 
54 /* 3 */
55 "arrowhead forward end",
56 
57 /* 4 */
58 "arrowhead backward begin, type=%d, fill=%d, length=%lg, width=%lg",
59 
60 /* 5 */
61 "arrowhead backward end",
62 
63 /* 6 */
64 "path object begin, type %ld %ld",
65 
66 /* 7 */
67 "path object end",
68 
69 NULL
70 
71 };
72 
73 
74 
75 /**	Write debug line to output file.
76 	@param	job	Job structure.
77 	@param	msg	Text line without newline at end.
78 */
79 static
80 void
f2lud_debug(f2l_job_t * job,char const * msg)81 f2lud_debug(
82   f2l_job_t	*job,
83   char const	*msg
84 )
85 {
86   switch(job->dr) {
87     case FIG2LAT_DRIVER_EPS_STANDALONE: {
88       f2leps_eps_pure_debug(job, msg);
89     } break;
90     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
91       f2lpgf_tex_debug(job, msg);
92     } break;
93     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
94       f2lpdf_tex_with_pdf_debug(job, msg);
95     } break;
96     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
97       f2lpdf_pdf_with_tex_debug(job, msg);
98     } break;
99     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
100       f2leps_eps_with_tex_debug(job, msg);
101     } break;
102     /* @DRIVER@ universal */
103     default: {	/* PGF */
104       f2lpgf_pgf_debug(job, msg);
105     } break;
106   }
107 }
108 
109 
110 
111 /**	Calculate factors for coordinates transformations.
112 	@param	job	Job structure.
113 	@param	drw	Drawing structure.
114 	@return	1 on success, 0 on error.
115 */
116 static
117 int
f2lud_coordinates_transformation(f2l_job_t * job,dk3_fig_drawing_t * drw)118 f2lud_coordinates_transformation(f2l_job_t *job, dk3_fig_drawing_t *drw)
119 {
120   double	 xmin;		/* Minimum x in output space. */
121   double	 xmax;		/* Maximum x in output space. */
122   double	 ymin;		/* Minimum y in output space. */
123   double	 ymax;		/* Maximum y in output space. */
124   double	 xdelta;	/* Used width in output space. */
125   double	 ydelta;	/* Used height in output space. */
126   double	 width;		/* Bounding box width in output space. */
127   double	 height;	/* Bounding box height in output space. */
128   int		 mec = 0;	/* Mathematical error code. */
129   int		 back = 1;
130 
131   (job->ct2d).mx = dk3ma_d_div_ok( 72.0, drw->res, &mec);
132   (job->ct2d).my = dk3ma_d_div_ok(-72.0, drw->res, &mec);
133   xmin = dk3ma_d_mul_ok((job->ct2d).mx, (drw->bb).xmin, &mec);
134   xmax = dk3ma_d_mul_ok((job->ct2d).mx, (drw->bb).xmax, &mec);
135   ymax = dk3ma_d_mul_ok((job->ct2d).my, (drw->bb).ymin, &mec);
136   ymin = dk3ma_d_mul_ok((job->ct2d).my, (drw->bb).ymax, &mec);
137   xdelta = dk3ma_d_sub_ok(xmax, xmin, &mec);
138   ydelta = dk3ma_d_sub_ok(ymax, ymin, &mec);
139   job->width = width = ceil(xdelta);
140   job->height = height = ceil(ydelta);
141   job->lwidth = dk3ma_d_to_l_ok(width, &mec);
142   job->lheight = dk3ma_d_to_l_ok(height, &mec);
143   (job->ct2d).nx = 0.5 * dk3ma_d_sub_ok(width, xdelta, &mec);
144   (job->ct2d).ny = 0.5 * dk3ma_d_sub_ok(height, ydelta, &mec);
145   (job->ct2d).nx = dk3ma_d_sub_ok((job->ct2d).nx, xmin, &mec);
146   (job->ct2d).ny = dk3ma_d_sub_ok((job->ct2d).ny, ymin, &mec);
147 
148 
149   if(mec) {
150     back = 0;
151     /* ERROR: Math problem */
152     dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 35);
153     f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
154   }
155   return back;
156 }
157 
158 
159 
160 /**	Driver-specific initialization.
161 	@param	job	Job structure.
162 	@param	drw	Drawing structure.
163 	@return	1 on success, 0 on error.
164 */
165 static
166 int
f2lud_driver_initialize(f2l_job_t * job,dk3_fig_drawing_t * drw)167 f2lud_driver_initialize(f2l_job_t *job, dk3_fig_drawing_t *drw)
168 {
169   int		 back;
170 
171   back = f2lud_coordinates_transformation(job, drw);
172   if(back) {
173     switch(job->dr) {
174       case FIG2LAT_DRIVER_TEX_FULL_PGF: {
175         back = f2lpgf_tex_initialize(job, drw);
176       } break;
177       case FIG2LAT_DRIVER_TEX_FULL_PDF: {
178         back = f2lpdf_tex_with_pdf_initialize(job, drw);
179       } break;
180       case FIG2LAT_DRIVER_PDF_WITH_TEX: {
181         back = f2lpdf_pdf_with_tex_initialize(job, drw);
182       } break;
183       case FIG2LAT_DRIVER_EPS_WITH_TEX: {
184         back = f2leps_eps_with_tex_initialize(job, drw);
185       } break;
186       case FIG2LAT_DRIVER_EPS_STANDALONE: {
187         back = f2leps_eps_pure_initialize(job, drw);
188       } break;
189       /* @DRIVER@ universal */
190       default: {	/* PGF */
191         back = f2lpgf_pgf_initialize(job, drw);
192       } break;
193     }
194   }
195   return back;
196 }
197 
198 
199 
200 /**	Release resources allocated by f2lud_driver_initialize().
201 	@param	job	Job structure.
202 	@param	drw	Drawing structure.
203 */
204 static
205 void
f2lud_driver_end(f2l_job_t * job,dk3_fig_drawing_t * drw)206 f2lud_driver_end(f2l_job_t *job, dk3_fig_drawing_t *drw)
207 {
208 
209   switch(job->dr) {
210     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
211       f2lpgf_tex_end(job, drw);
212     } break;
213     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
214       f2lpdf_tex_with_pdf_end(job, drw);
215     } break;
216     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
217       f2lpdf_pdf_with_tex_end(job, drw);
218     } break;
219     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
220       f2leps_eps_with_tex_end(job, drw);
221     } break;
222     case FIG2LAT_DRIVER_EPS_STANDALONE: {
223       f2leps_eps_pure_end(job, drw);
224     } break;
225     /* @DRIVER@ universal */
226     default: {	/* PGF */
227       f2lpgf_pgf_end(job, drw);
228     } break;
229   }
230 
231 }
232 
233 
234 
235 /**	Open output files.
236 	@param	job	Job structure.
237 	@return	1 on success, 0 on error.
238 */
239 static
240 int
f2lud_open_output_files(f2l_job_t * job)241 f2lud_open_output_files(f2l_job_t *job)
242 {
243   int		 back = 0;
244 
245   switch(job->dr) {
246     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
247       back = f2lpgf_tex_open_output_files(job);
248     } break;
249     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
250       back = f2lpdf_tex_with_pdf_open_output_files(job);
251     } break;
252     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
253       back = f2lpdf_pdf_with_tex_open_output_files(job);
254     } break;
255     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
256       back = f2leps_eps_with_tex_open_output_files(job);
257     } break;
258     case FIG2LAT_DRIVER_EPS_STANDALONE: {
259       back = f2leps_eps_pure_open_output_files(job);
260     } break;
261     /* @DRIVER@ universal */
262     default: {	/* PGF */
263       back = f2lpgf_pgf_open_output_files(job);
264     } break;
265   }
266   return back;
267 }
268 
269 
270 
271 /**	Close output files.
272 	@param	job	Job structure.
273 */
274 static
275 void
f2lud_close_output_files(f2l_job_t * job)276 f2lud_close_output_files(f2l_job_t *job)
277 {
278 
279   switch(job->dr) {
280     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
281       f2lpgf_tex_close_output_files(job);
282     } break;
283     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
284       f2lpdf_tex_with_pdf_close_output_files(job);
285     } break;
286     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
287       f2lpdf_pdf_with_tex_close_output_files(job);
288     } break;
289     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
290       f2leps_eps_with_tex_close_output_files(job);
291     } break;
292     case FIG2LAT_DRIVER_EPS_STANDALONE: {
293       f2leps_eps_pure_close_output_files(job);
294     } break;
295     /* @DRIVER@ universal */
296     default: {	/* PGF */
297       f2lpgf_pgf_close_output_files(job);
298     } break;
299   }
300 }
301 
302 
303 
304 /**	Write start of output.
305 	@param	job	Job structure.
306 	@param	drw	Drawing structure.
307 	@return	1 on success, 0 on error.
308 */
309 static
310 int
f2lud_start_processing(f2l_job_t * job,dk3_fig_drawing_t * drw)311 f2lud_start_processing(f2l_job_t *job, dk3_fig_drawing_t *drw)
312 {
313   int		 back = 0;
314 
315   switch(job->dr) {
316     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
317       back = f2lpgf_tex_start_processing(job, drw);
318     } break;
319     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
320       back = f2lpdf_tex_with_pdf_start_processing(job, drw);
321     } break;
322     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
323       back = f2lpdf_pdf_with_tex_start_processing(job, drw);
324     } break;
325     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
326       back = f2leps_eps_with_tex_start_processing(job, drw);
327     } break;
328     case FIG2LAT_DRIVER_EPS_STANDALONE: {
329       back = f2leps_eps_pure_start_processing(job, drw);
330     } break;
331     /* @DRIVER@ universal */
332     default: {	/* PGF */
333       back = f2lpgf_pgf_start_processing(job, drw);
334     } break;
335   }
336   return back;
337 }
338 
339 
340 
341 /**	Write end of output.
342 	@param	job	Job structure.
343 	@param	drw	Drawing structure.
344 */
345 static
346 void
f2lud_end_processing(f2l_job_t * job,dk3_fig_drawing_t * drw)347 f2lud_end_processing(f2l_job_t *job, dk3_fig_drawing_t *drw)
348 {
349 
350   switch(job->dr) {
351     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
352       f2lpgf_tex_end_processing(job, drw);
353     } break;
354     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
355       f2lpdf_tex_with_pdf_end_processing(job, drw);
356     } break;
357     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
358       f2lpdf_pdf_with_tex_end_processing(job, drw);
359     } break;
360     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
361       f2leps_eps_with_tex_end_processing(job, drw);
362     } break;
363     case FIG2LAT_DRIVER_EPS_STANDALONE: {
364       f2leps_eps_pure_end_processing(job, drw);
365     } break;
366     /* @DRIVER@ universal */
367     default: {	/* PGF */
368       f2lpgf_pgf_end_processing(job, drw);
369     } break;
370   }
371 }
372 
373 
374 
375 /**	Process one text object.
376 	@param	job	Job structure.
377 	@param	drw	Drawing structure.
378 	@param	obj	Current object to process.
379 */
380 static
381 void
f2lud_text_object(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)382 f2lud_text_object(
383   f2l_job_t		*job,
384   dk3_fig_drawing_t	*drw,
385   dk3_fig_obj_t		*obj
386 )
387 {
388   double		x;	/* X position of text object. */
389   double		y;	/* Y position of text object. */
390   int			ec = 0;	/* Mathematical error code. */
391 
392   if(!(DK3_FIG_FONT_FLAG_HIDDEN & ((obj->dt).txt.ff))) {
393     x = dk3ct_2d_x(&(job->ct2d), (obj->dt).txt.x, &ec);
394     y = dk3ct_2d_y(&(job->ct2d), (obj->dt).txt.y, &ec);
395     switch(job->dr) {
396       case FIG2LAT_DRIVER_TEX_FULL_PGF: {
397         f2lpgf_tex_text_object(job, drw, obj, x, y);
398       } break;
399       case FIG2LAT_DRIVER_TEX_FULL_PDF: {
400         f2lpdf_tex_with_pdf_text_object(job, drw, obj, x, y);
401       } break;
402       case FIG2LAT_DRIVER_PDF_WITH_TEX: {
403         f2lpdf_pdf_with_tex_text_object(job, drw, obj, x, y);
404       } break;
405       case FIG2LAT_DRIVER_EPS_WITH_TEX: {
406         f2leps_eps_with_tex_text_object(job, drw, obj, x, y);
407       } break;
408       case FIG2LAT_DRIVER_EPS_STANDALONE: {
409         f2leps_eps_pure_text_object(job, drw, obj, x, y);
410       } break;
411       /* @DRIVER@ universal */
412       default: {	/* PGF */
413         f2lpgf_pgf_text_object(job, drw, obj, x, y);
414       } break;
415     }
416   }
417   if(ec) {
418     /* ERROR: Math problem! */
419     dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 35);
420     f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
421   }
422 
423 }
424 
425 
426 
427 /**	Find bounding box for output coordinates.
428 	@param	bb	Bounding box to set up.
429 	@param	job	Job structure.
430 	@param	drw	Drawing structure.
431 	@param	obj	Polygon/polyline object.
432 	@param	ec	Pointer to error code variable.
433 */
434 static
435 void
f2lud_find_bounding_box(dk3_bb_t * bb,f2l_job_t * job,dk3_fig_drawing_t * DK3_SILENCE_ARG_UNUSED (drw),dk3_fig_obj_t * obj,int * ec)436 f2lud_find_bounding_box(
437   dk3_bb_t		*bb,
438   f2l_job_t		*job,
439   dk3_fig_drawing_t	* DK3_SILENCE_ARG_UNUSED(drw),
440   dk3_fig_obj_t		*obj,
441   int			*ec
442 )
443 {
444   dk3_fig_poly_point_t		*po;	/* Current point. */
445   size_t			 np;	/* Number of points. */
446   size_t			 i;	/* Index of current point. */
447 
448   DK3_UNUSED_ARG(drw)
449   po = (obj->dt).pol.po;
450   np = (obj->dt).pol.np;
451   dk3bb_reset(bb);
452   for(i = 0; i < np; i++) {
453     dk3bb_add_x(bb, dk3ct_2d_x(&(job->ct2d), po->x, ec));
454     dk3bb_add_y(bb, dk3ct_2d_y(&(job->ct2d), po->y, ec));
455     po++;
456   }
457 }
458 
459 
460 
461 /**	Process one image object.
462 	@param	job	Job structure.
463 	@param	drw	Drawing structure.
464 	@param	obj	Current object to process.
465 */
466 static
467 void
f2lud_image_object(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)468 f2lud_image_object(
469   f2l_job_t		*job,
470   dk3_fig_drawing_t	*drw,
471   dk3_fig_obj_t		*obj
472 )
473 {
474   dk3_bb_t	outbb;		/* Image bounding box in output space. */
475   int		ec	= 0;	/* Error code variable. */
476   int		drawdir	= 0;	/* Drawing direction for embedded image. */
477 
478   dk3bb_reset(&outbb);
479   f2lud_find_bounding_box(&outbb, job, drw, obj, &ec);
480   drawdir = f2lto_find_draw_direction(drw, obj, &ec);
481   switch(job->dr) {
482     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
483       f2lpgf_tex_image_object(job, drw, obj, &outbb, drawdir, &ec);
484     } break;
485     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
486       f2lpdf_tex_with_pdf_image_object(job, drw, obj, &outbb, drawdir, &ec);
487     } break;
488     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
489       f2lpdf_pdf_with_tex_image_object(job, drw, obj, &outbb, drawdir, &ec);
490     } break;
491     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
492       f2leps_eps_with_tex_image_object(job, drw, obj, &outbb, drawdir, &ec);
493     } break;
494     case FIG2LAT_DRIVER_EPS_STANDALONE: {
495       f2leps_eps_pure_image_object(job, drw, obj, &outbb, drawdir, &ec);
496     } break;
497     /* @DRIVER@ universal */
498     default: {	/* PGF */
499       f2lpgf_pgf_image_object(job, drw, obj, &outbb, drawdir, &ec);
500     } break;
501   }
502   if(ec) {
503     /* ERROR: Math error! */
504     dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 35);
505     f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
506   }
507 }
508 
509 
510 
511 void
f2lud_newpath(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)512 f2lud_newpath(
513   f2l_job_t		*job,
514   dk3_fig_drawing_t	*drw,
515   dk3_fig_obj_t		*obj
516 )
517 {
518 
519   switch(job->dr) {
520     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
521       f2lpgf_tex_newpath(job, drw, obj);
522     } break;
523     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
524       f2lpdf_tex_with_pdf_newpath(job, drw, obj);
525     } break;
526     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
527       f2lpdf_pdf_with_tex_newpath(job, drw, obj);
528     } break;
529     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
530       f2leps_eps_with_tex_newpath(job, drw, obj);
531     } break;
532     case FIG2LAT_DRIVER_EPS_STANDALONE: {
533       f2leps_eps_pure_newpath(job, drw, obj);
534     } break;
535     /* @DRIVER@ universal */
536     default: {	/* PGF */
537       f2lpgf_pgf_newpath(job, drw, obj);
538     } break;
539   }
540 }
541 
542 
543 
544 void
f2lud_moveto(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,double x,double y)545 f2lud_moveto(
546   f2l_job_t		*job,
547   dk3_fig_drawing_t	*drw,
548   dk3_fig_obj_t		*obj,
549   double		 x,
550   double		 y
551 )
552 {
553 
554   switch(job->dr) {
555     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
556       f2lpgf_tex_moveto(job, drw, obj, x, y);
557     } break;
558     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
559       f2lpdf_tex_with_pdf_moveto(job, drw, obj, x, y);
560     } break;
561     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
562       f2lpdf_pdf_with_tex_moveto(job, drw, obj, x, y);
563     } break;
564     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
565       f2leps_eps_with_tex_moveto(job, drw, obj, x, y);
566     } break;
567     case FIG2LAT_DRIVER_EPS_STANDALONE: {
568       f2leps_eps_pure_moveto(job, drw, obj, x, y);
569     } break;
570     /* @DRIVER@ universal */
571     default: {	/* PGF */
572       f2lpgf_pgf_moveto(job, drw, obj, x, y);
573     } break;
574   }
575 }
576 
577 
578 
579 void
f2lud_lineto(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,double x,double y)580 f2lud_lineto(
581   f2l_job_t		*job,
582   dk3_fig_drawing_t	*drw,
583   dk3_fig_obj_t		*obj,
584   double		 x,
585   double		 y
586 )
587 {
588 
589   switch(job->dr) {
590     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
591       f2lpgf_tex_lineto(job, drw, obj, x, y);
592     } break;
593     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
594       f2lpdf_tex_with_pdf_lineto(job, drw, obj, x, y);
595     } break;
596     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
597       f2lpdf_pdf_with_tex_lineto(job, drw, obj, x, y);
598     } break;
599     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
600       f2leps_eps_with_tex_lineto(job, drw, obj, x, y);
601     } break;
602     case FIG2LAT_DRIVER_EPS_STANDALONE: {
603       f2leps_eps_pure_lineto(job, drw, obj, x, y);
604     } break;
605     /* @DRIVER@ universal */
606     default: {	/* PGF */
607       f2lpgf_pgf_lineto(job, drw, obj, x, y);
608     } break;
609   }
610 }
611 
612 
613 
614 void
f2lud_curveto(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,double xcs,double ycs,double xce,double yce,double xe,double ye)615 f2lud_curveto(
616   f2l_job_t		*job,
617   dk3_fig_drawing_t	*drw,
618   dk3_fig_obj_t		*obj,
619   double		 xcs,
620   double		 ycs,
621   double		 xce,
622   double		 yce,
623   double		 xe,
624   double		 ye
625 )
626 {
627 
628   switch(job->dr) {
629     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
630       f2lpgf_tex_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye);
631     } break;
632     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
633       f2lpdf_tex_with_pdf_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye);
634     } break;
635     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
636       f2lpdf_pdf_with_tex_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye);
637     } break;
638     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
639       f2leps_eps_with_tex_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye);
640     } break;
641     case FIG2LAT_DRIVER_EPS_STANDALONE: {
642       f2leps_eps_pure_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye);
643     } break;
644     /* @DRIVER@ universal */
645     default: {	/* PGF */
646       f2lpgf_pgf_curveto(job, drw, obj, xcs, ycs, xce, yce, xe, ye);
647     } break;
648   }
649 }
650 
651 
652 
653 void
f2lud_fig_moveto(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,double x,double y,int * ec)654 f2lud_fig_moveto(
655   f2l_job_t		*job,
656   dk3_fig_drawing_t	*drw,
657   dk3_fig_obj_t		*obj,
658   double		 x,
659   double		 y,
660   int			*ec
661 )
662 {
663   double	nx;	/* Destination x in output space. */
664   double	ny;	/* Destination y in output space. */
665 
666   nx = dk3ct_2d_x(&(job->ct2d), x, ec);
667   ny = dk3ct_2d_y(&(job->ct2d), y, ec);
668   f2lud_moveto(job, drw, obj, nx, ny);
669 
670 }
671 
672 
673 
674 void
f2lud_fig_lineto(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,double x,double y,int * ec)675 f2lud_fig_lineto(
676   f2l_job_t		*job,
677   dk3_fig_drawing_t	*drw,
678   dk3_fig_obj_t		*obj,
679   double		 x,
680   double		 y,
681   int			*ec
682 )
683 {
684   double	nx;	/* Destination x in output space. */
685   double	ny;	/* Destination y in output space. */
686 
687   nx = dk3ct_2d_x(&(job->ct2d), x, ec);
688   ny = dk3ct_2d_y(&(job->ct2d), y, ec);
689   f2lud_lineto(job, drw, obj, nx, ny);
690 
691 }
692 
693 
694 
695 void
f2lud_fig_curveto(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,double xcs,double ycs,double xce,double yce,double xe,double ye,int * ec)696 f2lud_fig_curveto(
697   f2l_job_t		*job,
698   dk3_fig_drawing_t	*drw,
699   dk3_fig_obj_t		*obj,
700   double		 xcs,
701   double		 ycs,
702   double		 xce,
703   double		 yce,
704   double		 xe,
705   double		 ye,
706   int			*ec
707 )
708 {
709   double	nxcs;	/* First control point x in output space. */
710   double	nycs;	/* First control point y in output space. */
711   double	nxce;	/* Second control point x in output space. */
712   double	nyce;	/* Second control point y in output space. */
713   double	nxe;	/* End point x in output space. */
714   double	nye;	/* End point y in output space. */
715 
716   nxcs = dk3ct_2d_x(&(job->ct2d), xcs, ec);
717   nycs = dk3ct_2d_y(&(job->ct2d), ycs, ec);
718   nxce = dk3ct_2d_x(&(job->ct2d), xce, ec);
719   nyce = dk3ct_2d_y(&(job->ct2d), yce, ec);
720   nxe  = dk3ct_2d_x(&(job->ct2d), xe,  ec);
721   nye  = dk3ct_2d_y(&(job->ct2d), ye,  ec);
722   f2lud_curveto(job, drw, obj, nxcs, nycs, nxce, nyce, nxe, nye);
723 
724 }
725 
726 
727 
728 void
f2lud_closepath(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)729 f2lud_closepath(
730   f2l_job_t		*job,
731   dk3_fig_drawing_t	*drw,
732   dk3_fig_obj_t		*obj
733 )
734 {
735 
736   switch(job->dr) {
737     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
738       f2lpgf_tex_closepath(job, drw, obj);
739     } break;
740     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
741       f2lpdf_tex_with_pdf_closepath(job, drw, obj);
742     } break;
743     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
744       f2lpdf_pdf_with_tex_closepath(job, drw, obj);
745     } break;
746     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
747       f2leps_eps_with_tex_closepath(job, drw, obj);
748     } break;
749     case FIG2LAT_DRIVER_EPS_STANDALONE: {
750       f2leps_eps_pure_closepath(job, drw, obj);
751     } break;
752     /* @DRIVER@ universal */
753     default: {	/* PGF */
754       f2lpgf_pgf_closepath(job, drw, obj);
755     } break;
756   }
757 }
758 
759 
760 
761 /**	Issue "fill" command.
762 	@param	job	Job structure.
763 	@param	drw	Drawing structure.
764 	@param	obj	Current object to process.
765 */
766 void
f2lud_fill(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)767 f2lud_fill(
768   f2l_job_t		*job,
769   dk3_fig_drawing_t	*drw,
770   dk3_fig_obj_t		*obj
771 )
772 {
773 
774   switch(job->dr) {
775     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
776       f2lpgf_tex_fill(job, drw, obj);
777     } break;
778     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
779       f2lpdf_tex_with_pdf_fill(job, drw, obj);
780     } break;
781     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
782       f2lpdf_pdf_with_tex_fill(job, drw, obj);
783     } break;
784     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
785       f2leps_eps_with_tex_fill(job, drw, obj);
786     } break;
787     case FIG2LAT_DRIVER_EPS_STANDALONE: {
788       f2leps_eps_pure_fill(job, drw, obj);
789     } break;
790     /* @DRIVER@ universal */
791     default: {	/* PGF */
792       f2lpgf_pgf_fill(job, drw, obj);
793     } break;
794   }
795 }
796 
797 
798 
799 /**	Issue combined "fill" and "clip" command.
800 	@param	job	Job structure.
801 	@param	drw	Drawing structure.
802 	@param	obj	Current object to process.
803 */
804 static
805 void
f2lud_fill_clip(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)806 f2lud_fill_clip(
807   f2l_job_t		*job,
808   dk3_fig_drawing_t	*drw,
809   dk3_fig_obj_t		*obj
810 )
811 {
812 
813   switch(job->dr) {
814     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
815       f2lpgf_tex_fill_clip(job, drw, obj);
816     } break;
817     case FIG2LAT_DRIVER_PGF: {
818       f2lpgf_pgf_fill_clip(job, drw, obj);
819     } break;
820     /* @DRIVER@ universal */
821   }
822 }
823 
824 
825 
826 /**	Issue combined "fill", "stroke",  and "clip" command.
827 	@param	job	Job structure.
828 	@param	drw	Drawing structure.
829 	@param	obj	Current object to process.
830 */
831 static
832 void
f2lud_fill_stroke_clip(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)833 f2lud_fill_stroke_clip(
834   f2l_job_t		*job,
835   dk3_fig_drawing_t	*drw,
836   dk3_fig_obj_t		*obj
837 )
838 {
839 
840   switch(job->dr) {
841     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
842       f2lpgf_tex_fill_stroke_clip(job, drw, obj);
843     } break;
844     case FIG2LAT_DRIVER_PGF: {
845       f2lpgf_pgf_fill_stroke_clip(job, drw, obj);
846     } break;
847     /* @DRIVER@ universal */
848   }
849 }
850 
851 
852 
853 /**	Issue combined "fill" and "stroke" command.
854 	@param	job	Job structure.
855 	@param	drw	Drawing structure.
856 	@param	obj	Current object to process.
857 */
858 static
859 void
f2lud_fill_stroke(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)860 f2lud_fill_stroke(
861   f2l_job_t		*job,
862   dk3_fig_drawing_t	*drw,
863   dk3_fig_obj_t		*obj
864 )
865 {
866 
867   switch(job->dr) {
868     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
869       f2lpgf_tex_fill_stroke(job, drw, obj);
870     } break;
871     case FIG2LAT_DRIVER_PGF: {
872       f2lpgf_pgf_fill_stroke(job, drw, obj);
873     } break;
874     /* @DRIVER@ universal */
875   }
876 }
877 
878 
879 
880 void
f2lud_stroke(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)881 f2lud_stroke(
882   f2l_job_t		*job,
883   dk3_fig_drawing_t	*drw,
884   dk3_fig_obj_t		*obj
885 )
886 {
887 
888   switch(job->dr) {
889     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
890       f2lpgf_tex_stroke(job, drw, obj);
891     } break;
892     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
893       f2lpdf_tex_with_pdf_stroke(job, drw, obj);
894     } break;
895     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
896       f2lpdf_pdf_with_tex_stroke(job, drw, obj);
897     } break;
898     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
899       f2leps_eps_with_tex_stroke(job, drw, obj);
900     } break;
901     case FIG2LAT_DRIVER_EPS_STANDALONE: {
902       f2leps_eps_pure_stroke(job, drw, obj);
903     } break;
904     /* @DRIVER@ universal */
905     default: {	/* PGF */
906       f2lpgf_pgf_stroke(job, drw, obj);
907     } break;
908   }
909 }
910 
911 
912 
913 /**	Issue "clip" command.
914 	@param	job	Job structure.
915 	@param	drw	Drawing structure.
916 	@param	obj	Current object to process.
917 */
918 static
919 void
f2lud_clip(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)920 f2lud_clip(
921   f2l_job_t		*job,
922   dk3_fig_drawing_t	*drw,
923   dk3_fig_obj_t		*obj
924 )
925 {
926 
927   switch(job->dr) {
928     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
929       f2lpgf_tex_clip(job, drw, obj);
930     } break;
931     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
932       f2lpdf_tex_with_pdf_clip(job, drw, obj);
933     } break;
934     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
935       f2lpdf_pdf_with_tex_clip(job, drw, obj);
936     } break;
937     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
938       f2leps_eps_with_tex_clip(job, drw, obj);
939     } break;
940     case FIG2LAT_DRIVER_EPS_STANDALONE: {
941       f2leps_eps_pure_clip(job, drw, obj);
942     } break;
943     /* @DRIVER@ universal */
944     default: {	/* PGF */
945       f2lpgf_pgf_clip(job, drw, obj);
946     } break;
947   }
948 }
949 
950 
951 
952 /**	Issue "gsave" command.
953 	@param	job	Job structure.
954 	@param	drw	Drawing structure.
955 	@param	obj	Current object to process.
956 */
957 static
958 void
f2lud_gsave(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)959 f2lud_gsave(
960   f2l_job_t		*job,
961   dk3_fig_drawing_t	*drw,
962   dk3_fig_obj_t		*obj
963 )
964 {
965 
966   switch(job->dr) {
967     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
968       f2lpgf_tex_gsave(job, drw, obj);
969     } break;
970     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
971       f2lpdf_tex_with_pdf_gsave(job, drw, obj);
972     } break;
973     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
974       f2lpdf_pdf_with_tex_gsave(job, drw, obj);
975     } break;
976     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
977       f2leps_eps_with_tex_gsave(job, drw, obj);
978     } break;
979     case FIG2LAT_DRIVER_EPS_STANDALONE: {
980       f2leps_eps_pure_gsave(job, drw, obj);
981     } break;
982     /* @DRIVER@ universal */
983     default: {	/* PGF */
984       f2lpgf_pgf_gsave(job, drw, obj);
985     } break;
986   }
987 }
988 
989 
990 
991 /**	Issue "grestore" command.
992 	@param	job	Job structure.
993 	@param	drw	Drawing structure.
994 	@param	obj	Current object to process.
995 */
996 static
997 void
f2lud_grestore(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)998 f2lud_grestore(
999   f2l_job_t		*job,
1000   dk3_fig_drawing_t	*drw,
1001   dk3_fig_obj_t		*obj
1002 )
1003 {
1004 
1005   switch(job->dr) {
1006     case FIG2LAT_DRIVER_TEX_FULL_PGF: {
1007       f2lpgf_tex_grestore(job, drw, obj);
1008     } break;
1009     case FIG2LAT_DRIVER_TEX_FULL_PDF: {
1010       f2lpdf_tex_with_pdf_grestore(job, drw, obj);
1011     } break;
1012     case FIG2LAT_DRIVER_PDF_WITH_TEX: {
1013       f2lpdf_pdf_with_tex_grestore(job, drw, obj);
1014     } break;
1015     case FIG2LAT_DRIVER_EPS_WITH_TEX: {
1016       f2leps_eps_with_tex_grestore(job, drw, obj);
1017     } break;
1018     case FIG2LAT_DRIVER_EPS_STANDALONE: {
1019       f2leps_eps_pure_grestore(job, drw, obj);
1020     } break;
1021     /* @DRIVER@ universal */
1022     default: {	/* PGF */
1023       f2lpgf_pgf_grestore(job, drw, obj);
1024     } break;
1025   }
1026 }
1027 
1028 
1029 
1030 /**	Create path for ellipse object.
1031 	@param	job	Job structure.
1032 	@param	drw	Drawing structure.
1033 	@param	obj	Current object to process.
1034 	@param	ec	Pointe to error code variable, may be NULL.
1035 */
1036 static
1037 void
f2lud_create_ellipse_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int * ec)1038 f2lud_create_ellipse_path(
1039   f2l_job_t		*job,
1040   dk3_fig_drawing_t	*drw,
1041   dk3_fig_obj_t		*obj,
1042   int			*ec
1043 )
1044 {
1045   dk3_fig_poly_point_t	 po[12];	/* Points in Fig space. */
1046   double		 myan;		/* Rotation angle in Fig space. */
1047   size_t		 i;		/* Index of current point to modify. */
1048 
1049   po[0].x = (obj->dt).ell.rx;
1050   po[0].y = 0.0;
1051   po[1].x = (obj->dt).ell.rx;
1052   po[1].y = FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).ell.ry;
1053   po[2].x = FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).ell.rx;
1054   po[2].y = (obj->dt).ell.ry;
1055   po[3].x = 0.0;
1056   po[3].y = (obj->dt).ell.ry;
1057   po[4].x = 0.0 - po[2].x;
1058   po[4].y = po[2].y;
1059   po[5].x = 0.0 - po[1].x;
1060   po[5].y = po[1].y;
1061   po[6].x = 0.0 - po[0].x;
1062   po[6].y = 0.0;
1063   po[7].x = po[6].x;
1064   po[7].y = 0.0 - po[5].y;
1065   po[8].x = po[4].x;
1066   po[8].y = 0.0 - po[2].y;
1067   po[9].x = 0.0;
1068   po[9].y = 0.0 - po[3].y;
1069   po[10].x = po[2].x;
1070   po[10].y = po[9].y;
1071   po[11].x = po[1].x;
1072   po[11].y = po[7].y;
1073   switch(obj->st) {
1074     case 1: case 2: {
1075       if(1.0e-6 < fabs((obj->dt).ell.an)) {
1076         if(1.0e-6 < fabs(dk3ma_d_sub_ok((obj->dt).ell.rx,(obj->dt).ell.ry,ec)))
1077 	{
1078 	  myan = -1.0 * (obj->dt).ell.an;
1079 	  for(i = 0; i < 12; i++) {
1080 	    dk3fig_tool_rotate_point(&(po[i]), myan, ec);
1081 	  }
1082 	}
1083       }
1084     } break;
1085   }
1086   for(i = 0; i < 12; i++) {
1087     dk3fig_tool_shift_point(&(po[i]), (obj->dt).ell.cx, (obj->dt).ell.cy, ec);
1088   }
1089   f2lud_fig_moveto(job, drw, obj, po[0].x, po[0].y, ec);
1090   f2lud_fig_curveto(
1091     job, drw, obj,
1092     po[1].x, po[1].y, po[2].x, po[2].y, po[3].x, po[3].y,
1093     ec
1094   );
1095   f2lud_fig_curveto(
1096     job, drw, obj,
1097     po[4].x, po[4].y, po[5].x, po[5].y, po[6].x, po[6].y,
1098     ec
1099   );
1100   f2lud_fig_curveto(
1101     job, drw, obj,
1102     po[7].x, po[7].y, po[8].x, po[8].y, po[9].x, po[9].y,
1103     ec
1104   );
1105   f2lud_fig_curveto(
1106     job, drw, obj,
1107     po[10].x, po[10].y, po[11].x, po[11].y, po[0].x, po[0].y,
1108     ec
1109   );
1110 
1111 }
1112 
1113 
1114 
1115 /**	Create path for polygon object.
1116 	@param	job	Job structure.
1117 	@param	drw	Drawing structure.
1118 	@param	obj	Current object to process.
1119 	@param	ec	Pointe to error code variable, may be NULL.
1120 */
1121 static
1122 void
f2lud_create_polygon_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int * ec)1123 f2lud_create_polygon_path(
1124   f2l_job_t		*job,
1125   dk3_fig_drawing_t	*drw,
1126   dk3_fig_obj_t		*obj,
1127   int			*ec
1128 )
1129 {
1130   dk3_fig_poly_point_t	*po;	/* Current point to process. */
1131   size_t		 np;	/* Number of points. */
1132   size_t		 i;	/* Index of current point. */
1133 
1134   po = (obj->dt).pol.po;
1135   np = (obj->dt).pol.np;
1136   for(i = 0; i < np; i++) {
1137     if(0 == i) {
1138       f2lud_fig_moveto(job, drw, obj, po->x, po->y, ec);
1139     } else {
1140       f2lud_fig_lineto(job, drw, obj, po->x, po->y, ec);
1141     }
1142     po++;
1143   }
1144   if(obj->cl) {
1145     po = (obj->dt).pol.po;
1146     f2lud_fig_lineto(job, drw, obj, po->x, po->y, ec);
1147   }
1148 }
1149 
1150 
1151 
1152 /**	Create path for box object.
1153 	@param	job	Job structure.
1154 	@param	drw	Drawing structure.
1155 	@param	obj	Current object to process.
1156 	@param	ec	Pointe to error code variable, may be NULL.
1157 */
1158 static
1159 void
f2lud_create_box_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int * ec)1160 f2lud_create_box_path(
1161   f2l_job_t		*job,
1162   dk3_fig_drawing_t	*drw,
1163   dk3_fig_obj_t		*obj,
1164   int			*ec
1165 )
1166 {
1167   dk3_bb_t		 outbb;	/* Box coordinates in output space. */
1168 
1169   dk3bb_reset(&outbb);
1170   f2lud_find_bounding_box(&outbb, job, drw, obj, ec);
1171   f2lud_moveto(job, drw, obj, outbb.xmin, outbb.ymin);
1172   f2lud_lineto(job, drw, obj, outbb.xmax, outbb.ymin);
1173   f2lud_lineto(job, drw, obj, outbb.xmax, outbb.ymax);
1174   f2lud_lineto(job, drw, obj, outbb.xmin, outbb.ymax);
1175   f2lud_lineto(job, drw, obj, outbb.xmin, outbb.ymin);
1176 
1177 }
1178 
1179 
1180 
1181 /**	Create path for arc box object.
1182 	@param	job	Job structure.
1183 	@param	drw	Drawing structure.
1184 	@param	obj	Current object to process.
1185 	@param	ec	Pointe to error code variable, may be NULL.
1186 */
1187 static
1188 void
f2lud_create_arc_box_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int * ec)1189 f2lud_create_arc_box_path(
1190   f2l_job_t		*job,
1191   dk3_fig_drawing_t	*drw,
1192   dk3_fig_obj_t		*obj,
1193   int			*ec
1194 )
1195 {
1196   dk3_fig_poly_point_t	po[16];	/* Box points in output space. */
1197   dk3_bb_t		outbb;	/* Box coordinates in output space. */
1198   double		r;	/* Corner radius in output space. */
1199   double		maxr;	/* Maximum value for corner radius. */
1200   double		corner;	/* Factor control to end. */
1201   double		rc;	/* Dist of control to end in output space. */
1202 
1203   dk3bb_reset(&outbb);
1204   f2lud_find_bounding_box(&outbb, job, drw, obj, ec);
1205 #if VERSION_BEFORE_20140808
1206   r = dk3ct_2d_r(&(job->ct2d), (obj->dt).pol.ra, ec);
1207 #else
1208   r = 0.9 * (obj->dt).pol.ra;
1209 #endif
1210   maxr = 0.49 * fabs(dk3ma_d_sub_ok(outbb.xmax, outbb.xmin, ec));
1211   if(r > maxr) r = maxr;
1212   maxr = 0.49 * fabs(dk3ma_d_sub_ok(outbb.ymax, outbb.ymin, ec));
1213   if(r > maxr) r = maxr;
1214   corner = 1.0 - FIG2LAT_CIRCLE_QUADRANT_BEZIER;
1215   rc = r * corner;
1216   /* Bottom line */
1217   po[0].x = dk3ma_d_add_ok(outbb.xmin, r, ec);
1218   po[0].y = outbb.ymin;
1219   po[1].x = dk3ma_d_sub_ok(outbb.xmax, r, ec);
1220   po[1].y = po[0].y;
1221   /* Lower right corner control points */
1222   po[2].x = dk3ma_d_sub_ok(outbb.xmax, rc, ec);
1223   po[2].y = po[0].y;
1224   po[3].x = outbb.xmax;
1225   po[3].y = dk3ma_d_add_ok(outbb.ymin, rc, ec);
1226   /* Right line */
1227   po[4].x = outbb.xmax;
1228   po[4].y = dk3ma_d_add_ok(outbb.ymin, r, ec);
1229   po[5].x = outbb.xmax;
1230   po[5].y = dk3ma_d_sub_ok(outbb.ymax, r, ec);
1231   /* Upper right corner control points */
1232   po[6].x = outbb.xmax;
1233   po[6].y = dk3ma_d_sub_ok(outbb.ymax, rc, ec);
1234   po[7].x = dk3ma_d_sub_ok(outbb.xmax, rc, ec);
1235   po[7].y = outbb.ymax;
1236   /* Top line */
1237   po[8].x = dk3ma_d_sub_ok(outbb.xmax, r, ec);
1238   po[8].y = outbb.ymax;
1239   po[9].x = dk3ma_d_add_ok(outbb.xmin, r, ec);
1240   po[9].y = outbb.ymax;
1241   /* Upper left corner control points */
1242   po[10].x = dk3ma_d_add_ok(outbb.xmin, rc, ec);
1243   po[10].y = outbb.ymax;
1244   po[11].x = outbb.xmin;
1245   po[11].y = dk3ma_d_sub_ok(outbb.ymax, rc, ec);
1246   /* Left line */
1247   po[12].x = outbb.xmin;
1248   po[12].y = dk3ma_d_sub_ok(outbb.ymax, r, ec);
1249   po[13].x = outbb.xmin;
1250   po[13].y = dk3ma_d_add_ok(outbb.ymin, r, ec);
1251   /* Lower left corner control points */
1252   po[14].x = outbb.xmin;
1253   po[14].y = dk3ma_d_add_ok(outbb.ymin, rc, ec);
1254   po[15].x = dk3ma_d_add_ok(outbb.xmin, rc, ec);
1255   po[15].y = outbb.ymin;
1256   f2lud_moveto(job, drw, obj, po[0].x, po[0].y);
1257   f2lud_lineto(job, drw, obj, po[1].x, po[1].y);
1258   f2lud_curveto(
1259     job, drw, obj,
1260     po[2].x, po[2].y, po[3].x, po[3].y, po[4].x, po[4].y
1261   );
1262   f2lud_lineto(job, drw, obj, po[5].x, po[5].y);
1263   f2lud_curveto(
1264     job, drw, obj,
1265     po[6].x, po[6].y, po[7].x, po[7].y, po[8].x, po[8].y
1266   );
1267   f2lud_lineto(job, drw, obj, po[9].x, po[9].y);
1268   f2lud_curveto(
1269     job, drw, obj,
1270     po[10].x, po[10].y, po[11].x, po[11].y, po[12].x, po[12].y
1271   );
1272   f2lud_lineto(job, drw, obj, po[13].x, po[13].y);
1273   f2lud_curveto(
1274     job, drw, obj,
1275     po[14].x, po[14].y, po[15].x, po[15].y, po[0].x, po[0].y
1276   );
1277 
1278 }
1279 
1280 
1281 
1282 /**	Create path for the last partial X-spline segment from closed X-spline.
1283 	@param	job	Job structure.
1284 	@param	drw	Fig drawing.
1285 	@param	obj	Fig object.
1286 	@param	sp	Spline points array.
1287 	@param	np	Number of spline points.
1288 	@param	i	Current segment index.
1289 	@param	te	Parameter t for end point.
1290 	@param	isfirst	Flag: First segment.
1291 	@param	iscl	Flag: Closed spline.
1292 	@param	primary	Flag: Primary (1=primary object, 0=arrowhead).
1293 	@param	ec	Pointer to error code variable, may be NULL.
1294 */
1295 static
1296 void
f2lud_final_spline_segment(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,dk3_fig_spline_point_t * sp,size_t np,size_t i,double te,int isfirst,int DK3_SILENCE_ARG_UNUSED (iscl),int primary,int * ec)1297 f2lud_final_spline_segment(
1298   f2l_job_t			*job,
1299   dk3_fig_drawing_t		*drw,
1300   dk3_fig_obj_t			*obj,
1301   dk3_fig_spline_point_t	*sp,
1302   size_t			 np,
1303   size_t			 i,
1304   double			 te,
1305   int				 isfirst,
1306   int				 DK3_SILENCE_ARG_UNUSED(iscl),
1307   int				 primary,
1308   int				*ec
1309 )
1310 {
1311   dk3_xspline_segment_t		 seg;		/* Segment for caluclation. */
1312   dk3_fig_spline_point_t	*pa = NULL;	/* Left neighbour. */
1313   dk3_fig_spline_point_t	*pb = NULL;	/* Start. */
1314   dk3_fig_spline_point_t	*pc = NULL;	/* End. */
1315   dk3_fig_spline_point_t	*pd = NULL;	/* Right neighbour. */
1316   double			 myte;		/* t for end. */
1317   double			 dnumsegs;	/* Number of segments. */
1318   double			 factor;	/* Scale factor for deriv. */
1319   double			 t;		/* Current t. */
1320   double			 x;		/* Bezier end x. */
1321   double			 y;		/* Bezier end y. */
1322   double			 dxdt;		/* Bezier dx/dt at end. */
1323   double			 dydt;		/* Bezier dy/dt at end. */
1324   double			 lastx = 0.0;	/* Bezier start x. */
1325   double			 lasty = 0.0;	/* Bezier start y. */
1326   double			 lastdxdt = 0.0;	/* dx/dt at start. */
1327   double			 lastdydt = 0.0;	/* dy/dt at end. */
1328   size_t			 nsegs;		/* Number of segments. */
1329   size_t			 iseg;		/* Current segment. */
1330   int				 res;		/* Calculation result. */
1331 
1332   DK3_UNUSED_ARG(iscl)
1333   myte = dk3ma_d_sub_ok(te, floor(te), ec);
1334   dnumsegs = myte * (double)dk3fig_tool_xssbs(drw, primary);
1335   dnumsegs = ceil(dnumsegs);
1336   nsegs = dk3ma_d_to_sz_ok(dnumsegs, ec);
1337   pb = &(sp[i]);
1338   pc = &(sp[i + 1]);
1339   if(0 < i) {
1340     pa = &(sp[i - 1]);
1341   }
1342   if(i < (np - 2)) {
1343     pd = &(sp[i + 2]);
1344   }
1345   factor = myte / (double)nsegs;
1346   dk3xsp_reset(&seg);
1347   if(job->cosp) { dk3xsp_set_cb(&seg, 1); }
1348   dk3xsp_set(&seg, pa, pb, pc, pd);
1349   if(dk3xsp_calculate(&seg, 0.0, 1)) {
1350     lastx = dk3xsp_get_x(&seg);
1351     lasty = dk3xsp_get_y(&seg);
1352     lastdxdt = dk3xsp_get_dxdt(&seg);
1353     lastdydt = dk3xsp_get_dydt(&seg);
1354     lastdxdt = (factor * lastdxdt) / 3.0;
1355     lastdydt = (factor * lastdydt) / 3.0;
1356     /*	Move to start point.
1357     */
1358     if(isfirst) {
1359 	f2lud_fig_moveto(job, drw, obj, lastx, lasty, ec);
1360     }
1361     /*	Further curve only if te > 1.0e-6.
1362     	For smaller te draw straight line.
1363     */
1364     if(1.0e-6 < myte) {
1365       for(iseg = 0; iseg < nsegs; iseg++) {
1366         if(iseg < (nsegs - 1)) {
1367           t = (double)(iseg + 1) / (double)nsegs;
1368 	  t = t * myte;
1369         } else {
1370           t = myte;
1371         }
1372         res = dk3xsp_calculate(&seg, t, 1);
1373         if(!(res)) {
1374 	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1375         }
1376         x = dk3xsp_get_x(&seg);
1377         y = dk3xsp_get_y(&seg);
1378         dxdt = dk3xsp_get_dxdt(&seg);
1379         dydt = dk3xsp_get_dydt(&seg);
1380         dxdt = (factor * dxdt) / 3.0;
1381         dydt = (factor * dydt) / 3.0;
1382         f2lud_fig_curveto(
1383           job, drw, obj,
1384 	  dk3ma_d_add_ok(lastx, lastdxdt, ec),
1385 	  dk3ma_d_add_ok(lasty, lastdydt, ec),
1386 	  dk3ma_d_sub_ok(x, dxdt, ec),
1387 	  dk3ma_d_sub_ok(y, dydt, ec),
1388 	  x, y,
1389 	  ec
1390         );
1391         lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt;
1392       }
1393     } else {
1394       res = dk3xsp_calculate(&seg, myte, 0);
1395       if(!(res)) {
1396 	if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1397 	/* ERROR: Math */
1398         dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 36);
1399 	f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
1400       }
1401       x = dk3xsp_get_x(&seg);
1402       y = dk3xsp_get_y(&seg);
1403       f2lud_fig_lineto(job, drw, obj, x, y, ec);
1404     }
1405   } else {
1406     if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1407     f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
1408   }
1409 
1410 }
1411 
1412 
1413 
1414 /**	Create path for the first partial X-spline segment from closed X-spline.
1415 	@param	job	Job structure.
1416 	@param	drw	Fig drawing.
1417 	@param	obj	Fig object.
1418 	@param	sp	Spline points array.
1419 	@param	np	Number of spline points.
1420 	@param	i	Current segment index.
1421 	@param	ts	Parameter t for start point.
1422 	@param	isfirst	Flag: First segment.
1423 	@param	iscl	Flag: Closed spline.
1424 	@param	primary	Flag: Primary (1=primary object, 0=arrowhead).
1425 	@param	ec	Pointer to error code variable, may be NULL.
1426 */
1427 static
1428 void
f2lud_first_spline_segment(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,dk3_fig_spline_point_t * sp,size_t np,size_t i,double ts,int isfirst,int DK3_SILENCE_ARG_UNUSED (iscl),int primary,int * ec)1429 f2lud_first_spline_segment(
1430   f2l_job_t			*job,
1431   dk3_fig_drawing_t		*drw,
1432   dk3_fig_obj_t			*obj,
1433   dk3_fig_spline_point_t	*sp,
1434   size_t			 np,
1435   size_t			 i,
1436   double			 ts,
1437   int				 isfirst,
1438   int				 DK3_SILENCE_ARG_UNUSED(iscl),
1439   int				 primary,
1440   int				*ec
1441 )
1442 {
1443   dk3_xspline_segment_t		 seg;		/* Segment for caluclation. */
1444   dk3_fig_spline_point_t	*pa = NULL;	/* Left neighbour. */
1445   dk3_fig_spline_point_t	*pb = NULL;	/* Start. */
1446   dk3_fig_spline_point_t	*pc = NULL;	/* End. */
1447   dk3_fig_spline_point_t	*pd = NULL;	/* Right neighbour. */
1448   double			 myts;		/* t for start. */
1449   double			 dnumsegs;	/* Number of segments. */
1450   double			 factor;	/* Scale factor for deriv. */
1451   double			 t;		/* Current t. */
1452   double			 x;		/* Bezier end x. */
1453   double			 y;		/* Bezier end y. */
1454   double			 dxdt;		/* Bezier dx/dt at end. */
1455   double			 dydt;		/* Bezier dy/dt at end. */
1456   double			 lastx = 0.0;	/* Bezier start x. */
1457   double			 lasty = 0.0;	/* Bezier start y. */
1458   double			 lastdxdt = 0.0;	/* dx/dt at start. */
1459   double			 lastdydt = 0.0;	/* dy/dt at end. */
1460   size_t			 nsegs;		/* Number of segments. */
1461   size_t			 iseg;		/* Current segment. */
1462   int				 res;		/* Calculation result. */
1463 
1464   DK3_UNUSED_ARG(iscl)
1465   myts = dk3ma_d_sub_ok(ts, floor(ts), ec);
1466   dnumsegs = (1.0 - myts) * (double)dk3fig_tool_xssbs(drw, primary);
1467   dnumsegs = ceil(dnumsegs);
1468   nsegs = dk3ma_d_to_sz_ok(dnumsegs, ec);
1469   pb = &(sp[i]);
1470   pc = &(sp[i + 1]);
1471   if(0 < i) {
1472     pa = &(sp[i - 1]);
1473   }
1474   if(i < (np - 2)) {
1475     pd = &(sp[i + 2]);
1476   }
1477   factor = (1.0 - myts) / (double)nsegs;
1478   dk3xsp_reset(&seg);
1479   if(job->cosp) { dk3xsp_set_cb(&seg, 1); }
1480   dk3xsp_set(&seg, pa, pb, pc, pd);
1481   if(dk3xsp_calculate(&seg, myts, 1)) {
1482     /*	If necessary move to the start point.
1483     */
1484     lastx = dk3xsp_get_x(&seg);
1485     lasty = dk3xsp_get_y(&seg);
1486     lastdxdt = dk3xsp_get_dxdt(&seg);
1487     lastdydt = dk3xsp_get_dydt(&seg);
1488     lastdxdt = (factor * lastdxdt) / 3.0;
1489     lastdydt = (factor * lastdydt) / 3.0;
1490     if(isfirst) {
1491 	f2lud_fig_moveto(job, drw, obj, lastx, lasty, ec);
1492     }
1493     if(1.0e-6 < (1.0 - myts)) {
1494       for(iseg = 0; iseg < nsegs; iseg++) {
1495         if(iseg < (nsegs - 1)) {
1496 	  t = myts + (((1.0 - myts) * ((double)(iseg + 1))) / ((double)nsegs));
1497 	} else {
1498 	  t = 1.0;
1499 	}
1500 	res = dk3xsp_calculate(&seg, t, 1);
1501 	if(!(res)) {
1502 	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1503 	}
1504 	x = dk3xsp_get_x(&seg);
1505 	y = dk3xsp_get_y(&seg);
1506 	dxdt = dk3xsp_get_dxdt(&seg);
1507 	dydt = dk3xsp_get_dydt(&seg);
1508 	dxdt = (factor * dxdt) / 3.0;
1509 	dydt = (factor * dydt) / 3.0;
1510 	f2lud_fig_curveto(
1511 	  job, drw, obj,
1512 	  dk3ma_d_add_ok(lastx, lastdxdt, ec),
1513 	  dk3ma_d_add_ok(lasty, lastdydt, ec),
1514 	  dk3ma_d_sub_ok(x, dxdt, ec),
1515 	  dk3ma_d_sub_ok(y, dydt, ec),
1516 	  x, y,
1517 	  ec
1518 	);
1519 	lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt;
1520       }
1521     } else {
1522       res = dk3xsp_calculate(&seg, 1.0, 0);
1523       if(!(res)) {
1524 	if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1525 	/* ERROR: Math */
1526         dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 36);
1527 	f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
1528       }
1529       x = dk3xsp_get_x(&seg);
1530       y = dk3xsp_get_y(&seg);
1531       f2lud_fig_lineto(job, drw, obj, x, y, ec);
1532     }
1533   } else {
1534     if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1535     f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
1536   }
1537 
1538 }
1539 
1540 
1541 
1542 
1543 /**	Create path for the single partial X-spline segment cutted on both ends
1544 	from closed X-spline.
1545 	@param	job	Job structure.
1546 	@param	drw	Fig drawing.
1547 	@param	obj	Fig object.
1548 	@param	sp	Spline points array.
1549 	@param	np	Number of spline points.
1550 	@param	i	Current segment index.
1551 	@param	ts	Parameter t for start point.
1552 	@param	te	Parameter t for end point.
1553 	@param	isfirst	Flag: First segment.
1554 	@param	iscl	Flag: Closed spline.
1555 	@param	primary	Flag: Primary (1=primary object, 0=arrowhead).
1556 	@param	ec	Pointer to error code variable, may be NULL.
1557 */
1558 static
1559 void
f2lud_single_spline_segment(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,dk3_fig_spline_point_t * sp,size_t np,size_t i,double ts,double te,int isfirst,int DK3_SILENCE_ARG_UNUSED (iscl),int primary,int * ec)1560 f2lud_single_spline_segment(
1561   f2l_job_t			*job,
1562   dk3_fig_drawing_t		*drw,
1563   dk3_fig_obj_t			*obj,
1564   dk3_fig_spline_point_t	*sp,
1565   size_t			 np,
1566   size_t			 i,
1567   double			 ts,
1568   double			 te,
1569   int				 isfirst,
1570   int				 DK3_SILENCE_ARG_UNUSED(iscl),
1571   int				 primary,
1572   int				*ec
1573 )
1574 {
1575   dk3_xspline_segment_t		 seg;		/* Segment for caluclation. */
1576   dk3_fig_spline_point_t	*pa = NULL;	/* Left neighbour. */
1577   dk3_fig_spline_point_t	*pb = NULL;	/* Start. */
1578   dk3_fig_spline_point_t	*pc = NULL;	/* End. */
1579   dk3_fig_spline_point_t	*pd = NULL;	/* Right neighbour. */
1580   double			 myte;		/* t for end. */
1581   double			 myts;		/* t for start. */
1582   double			 dnumsegs;	/* Number of segments. */
1583   double			 factor;	/* Scale factor for deriv. */
1584   double			 t;		/* Current t. */
1585   double			 x;		/* Bezier end x. */
1586   double			 y;		/* Bezier end y. */
1587   double			 dxdt;		/* Bezier dx/dt at end. */
1588   double			 dydt;		/* Bezier dy/dt at end. */
1589   double			 lastx = 0.0;	/* Bezier start x. */
1590   double			 lasty = 0.0;	/* Bezier start y. */
1591   double			 lastdxdt = 0.0;	/* dx/dt at start. */
1592   double			 lastdydt = 0.0;	/* dy/dt at end. */
1593   size_t			 nsegs;		/* Number of segments. */
1594   size_t			 iseg;		/* Current segment. */
1595   int				 res;		/* Calculation result. */
1596 
1597   DK3_UNUSED_ARG(iscl)
1598   myte = dk3ma_d_sub_ok(te, floor(te), ec);
1599   myts = dk3ma_d_sub_ok(ts, floor(ts), ec);
1600   dnumsegs = (myte - myts) * (double)dk3fig_tool_xssbs(drw, primary);
1601   dnumsegs = ceil(dnumsegs);
1602   nsegs = dk3ma_d_to_sz_ok(dnumsegs, ec);
1603   pb = &(sp[i]);
1604   pc = &(sp[i + 1]);
1605   if(0 < i) {
1606     pa = &(sp[i - 1]);
1607   }
1608   if(i < (np - 2)) {
1609     pd = &(sp[i + 2]);
1610   }
1611   factor = (myte - myts) / ((double)nsegs);
1612   dk3xsp_reset(&seg);
1613   if(job->cosp) { dk3xsp_set_cb(&seg, 1); }
1614   dk3xsp_set(&seg, pa, pb, pc, pd);
1615   if(dk3xsp_calculate(&seg, myts, 1)) {
1616     lastx = dk3xsp_get_x(&seg);
1617     lasty = dk3xsp_get_y(&seg);
1618     lastdxdt = dk3xsp_get_dxdt(&seg);
1619     lastdydt = dk3xsp_get_dydt(&seg);
1620     lastdxdt = (factor * lastdxdt) / 3.0;
1621     lastdydt = (factor * lastdydt) / 3.0;
1622     if(isfirst) {
1623       f2lud_fig_moveto(job, drw, obj, lastx, lasty, ec);
1624     }
1625     if(1.0e-6 < (myte - myts)) {
1626       for(iseg = 0; iseg < nsegs; iseg++) {
1627         if(iseg < (nsegs - 1)) {
1628 	  t = myts + (((myte - myts) * ((double)(iseg + 1))) / ((double)nsegs));
1629 	} else {
1630 	  t = myte;
1631 	}
1632 	res = dk3xsp_calculate(&seg, t, 1);
1633 	if(!(res)) {
1634 	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1635 	}
1636 	x = dk3xsp_get_x(&seg);
1637 	y = dk3xsp_get_y(&seg);
1638 	dxdt = dk3xsp_get_dxdt(&seg);
1639 	dydt = dk3xsp_get_dydt(&seg);
1640 	dxdt = (factor * dxdt) / 3.0;
1641 	dydt = (factor * dydt) / 3.0;
1642 	f2lud_fig_curveto(
1643 	  job, drw, obj,
1644 	  dk3ma_d_add_ok(lastx, lastdxdt, ec),
1645 	  dk3ma_d_add_ok(lasty, lastdydt, ec),
1646 	  dk3ma_d_sub_ok(x, dxdt, ec),
1647 	  dk3ma_d_sub_ok(y, dydt, ec),
1648 	  x, y,
1649 	  ec
1650 	);
1651 	lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt;
1652       }
1653     } else {
1654       res = dk3xsp_calculate(&seg, myte, 0);
1655       if(!(res)) {
1656 	if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1657 	/* ERROR: Calculation failed! */
1658         dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 36);
1659 	f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
1660       }
1661       x = dk3xsp_get_x(&seg);
1662       y = dk3xsp_get_y(&seg);
1663       f2lud_fig_lineto(job, drw, obj, x, y, ec);
1664     }
1665   } else {
1666     if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1667     /* ERROR: Calculation failed! */
1668     dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 36);
1669     f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
1670   }
1671 
1672 }
1673 
1674 
1675 
1676 
1677 /**	Create path for one complete X-spline segment from closed X-spline.
1678 	@param	job	Job structure.
1679 	@param	drw	Fig drawing.
1680 	@param	obj	Fig object.
1681 	@param	sp	Spline points array.
1682 	@param	np	Number of spline points.
1683 	@param	i	Current segment index.
1684 	@param	isfirst	Flag: First segment.
1685 	@param	iscl	Flag: Closed spline.
1686 	@param	primary	Flag: Primary (1=primary object, 0=arrowhead).
1687 	@param	ec	Pointer to error code variable, may be NULL.
1688 */
1689 static
1690 void
f2lud_full_spline_segment(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,dk3_fig_spline_point_t * sp,size_t np,size_t i,int isfirst,int iscl,int primary,int * ec)1691 f2lud_full_spline_segment(
1692   f2l_job_t			*job,
1693   dk3_fig_drawing_t		*drw,
1694   dk3_fig_obj_t			*obj,
1695   dk3_fig_spline_point_t	*sp,
1696   size_t			 np,
1697   size_t			 i,
1698   int				 isfirst,
1699   int				 iscl,
1700   int				 primary,
1701   int				*ec
1702 )
1703 {
1704   dk3_xspline_segment_t		 seg;		/* Segment for caluclation. */
1705   dk3_fig_spline_point_t	*pa = NULL;	/* Left neighbour. */
1706   dk3_fig_spline_point_t	*pb = NULL;	/* Start. */
1707   dk3_fig_spline_point_t	*pc = NULL;	/* End. */
1708   dk3_fig_spline_point_t	*pd = NULL;	/* Right neighbour. */
1709   double			 factor;	/* Scale factor for deriv. */
1710   double			 t;		/* Current t. */
1711   double			 x;		/* Bezier end x. */
1712   double			 y;		/* Bezier end y. */
1713   double			 dxdt;		/* Bezier dx/dt at end. */
1714   double			 dydt;		/* Bezier dy/dt at end. */
1715   double			 lastx = 0.0;	/* Bezier start x. */
1716   double			 lasty = 0.0;	/* Bezier start y. */
1717   double			 lastdxdt = 0.0;	/* dx/dt at start. */
1718   double			 lastdydt = 0.0;	/* dy/dt at end. */
1719   size_t			 xsss;		/* Number of segments. */
1720   size_t			 iseg;		/* Current segment. */
1721   size_t			 ic;
1722   size_t			 id;
1723   int				 res;		/* Calculation result. */
1724 
1725   if(i < ((iscl) ? np : (np - 1))) {
1726     pb = &(sp[i]);
1727     ic = i + 1; while(ic >= np) { ic = ic - np; }
1728     pc = &(sp[ic]);
1729     if(i > 0) {
1730       pa = &(sp[i - 1]);
1731     } else {
1732       if(iscl) {
1733         pa = &(sp[np - 1]);
1734       }
1735     }
1736     if(i < (np - 2)) {
1737       pd = &(sp[i + 2]);
1738     } else {
1739       if(iscl) {
1740         id = i + 2; while(id >= np) { id = id - np; }
1741 	pd = &(sp[id]);
1742       }
1743     }
1744     xsss = dk3fig_tool_xssbs(drw, primary);
1745     factor = 1.0 / (double)xsss;
1746     dk3xsp_reset(&seg);
1747     if(job->cosp) { dk3xsp_set_cb(&seg, 1); }
1748     dk3xsp_set(&seg, pa, pb, pc, pd);
1749     if(dk3xsp_calculate(&seg, 0.0, 1)) {
1750       lastx = dk3xsp_get_x(&seg);
1751       lasty = dk3xsp_get_y(&seg);
1752       lastdxdt = dk3xsp_get_dxdt(&seg);
1753       lastdydt = dk3xsp_get_dydt(&seg);
1754       lastdxdt = (factor * lastdxdt) / 3.0;
1755       lastdydt = (factor * lastdydt) / 3.0;
1756       if(isfirst) {
1757 	f2lud_fig_moveto(job, drw, obj, lastx, lasty, ec);
1758       }
1759       for(iseg = 0; iseg < xsss; iseg++) {
1760         if(iseg < (xsss - 1)) {
1761 	  t = (double)(iseg + 1) / (double)xsss;
1762 	} else {
1763 	  t = 1.0;
1764 	}
1765 	res = dk3xsp_calculate(&seg, t, 1);
1766 	if(!(res)) {
1767 	  if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1768 	}
1769 	x = dk3xsp_get_x(&seg);
1770 	y = dk3xsp_get_y(&seg);
1771 	dxdt = dk3xsp_get_dxdt(&seg);
1772 	dydt = dk3xsp_get_dydt(&seg);
1773 	dxdt = (factor * dxdt) / 3.0;
1774 	dydt = (factor * dydt) / 3.0;
1775 	f2lud_fig_curveto(
1776 	  job, drw, obj,
1777 	  dk3ma_d_add_ok(lastx, lastdxdt, ec),
1778 	  dk3ma_d_add_ok(lasty, lastdydt, ec),
1779 	  dk3ma_d_sub_ok(x, dxdt, ec),
1780 	  dk3ma_d_sub_ok(y, dydt, ec),
1781 	  x,
1782 	  y,
1783 	  ec
1784 	);
1785 	lastx = x; lasty = y; lastdxdt = dxdt; lastdydt = dydt;
1786       }
1787     } else {
1788       if(ec) { *ec = DK3_ERROR_MATH_OVERFLOW; }
1789     }
1790   } else {
1791     /* ERROR: BUG: Wrong i */
1792   }
1793 }
1794 
1795 
1796 
1797 /**	Create path for open spline object.
1798 	@param	job	Job structure.
1799 	@param	drw	Drawing structure.
1800 	@param	obj	Current object to process.
1801 	@param	primary	Flag: Primary object (1=object, 0=arrowhead).
1802 	@param	ec	Pointe to error code variable, may be NULL.
1803 */
1804 static
1805 void
f2lud_create_open_spline_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)1806 f2lud_create_open_spline_path(
1807   f2l_job_t		*job,
1808   dk3_fig_drawing_t	*drw,
1809   dk3_fig_obj_t		*obj,
1810   int			 primary,
1811   int			*ec
1812 )
1813 {
1814   dk3_fig_spline_point_t	*sp;	/* Spline points. */
1815   size_t			 np;	/* Number of points. */
1816   size_t			 i;	/* Current segment index. */
1817   size_t			 min;	/* Minimum t value. */
1818   size_t			 max;	/* Maximum t value. */
1819 
1820   sp = (obj->dt).spl.po;
1821   np = (obj->dt).spl.np;
1822 
1823   if(job->coah) {
1824     for(i = 0; i < (np - 1); i++) {
1825       f2lud_full_spline_segment(
1826         job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec
1827       );
1828     }
1829   } else {
1830     if(obj->ab) {
1831       /*	2013-11-23
1832       		ROUNDING DOWNWARDS INTENDED.
1833 		We want to find the start segment.
1834       */
1835       min = dk3ma_d_to_sz_ok(floor((obj->dt).spl.ts), ec);
1836       if(obj->af) {
1837         if((obj->dt).spl.te >= (obj->dt).spl.ts) {
1838 	  /*	2013-11-23
1839 	  	ROUNDING DOWNWARDS INTENDED.
1840 		We want to find the last full segment to draw.
1841 	  */
1842           max = dk3ma_d_to_sz_ok(floor((obj->dt).spl.te), ec);
1843           if(max > min) {
1844             f2lud_first_spline_segment(
1845               job, drw, obj, sp, np, min, (obj->dt).spl.ts, 1, 0, primary, ec
1846             );
1847 	    /*	2012-12-04 Bugfix: Only to max.
1848 	    */
1849 #if VERSION_BEFORE_20121204
1850             for(i = (min + 1); i < (np - 1); i++) {
1851               f2lud_full_spline_segment(
1852 	        job, drw, obj, sp, np, i, 0, 0, primary, ec
1853 	      );
1854             }
1855 #else
1856             for(i = (min + 1); i < max; i++) {
1857               f2lud_full_spline_segment(
1858 	        job, drw, obj, sp, np, i, 0, 0, primary, ec
1859 	      );
1860             }
1861 #endif
1862 	    f2lud_final_spline_segment(
1863 	      job, drw, obj, sp, np, max, (obj->dt).spl.te, 0, 0, primary, ec
1864 	    );
1865           } else {
1866             f2lud_single_spline_segment(
1867 	      job, drw, obj, sp, np, min, (obj->dt).spl.ts, (obj->dt).spl.te,
1868 	      1, 0, primary, ec
1869 	    );
1870           }
1871         } else {
1872           /* ERROR: Arrowheads too long for spline! */
1873           dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 37);
1874 	  f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_SYNTAX);
1875         }
1876       } else {
1877         f2lud_first_spline_segment(
1878           job, drw, obj, sp, np, min, (obj->dt).spl.ts, 1, 0, primary, ec
1879         );
1880         for(i = (min + 1); i < (np - 1); i++) {
1881           f2lud_full_spline_segment(
1882 	    job, drw, obj, sp, np, i, 0, 0, primary, ec
1883 	  );
1884         }
1885       }
1886     } else {
1887       if(obj->af) {
1888         /*	2013-11-23
1889 		ROUNDING DOWNWARDS INTENDED.
1890 		We want to find the last full segment.
1891 	*/
1892         max = dk3ma_d_to_sz_ok(floor((obj->dt).spl.te), ec);
1893         if(max < (np - 1)) {
1894           if(max > 0) {
1895             for(i = 0; i < max; i++) {
1896 	      f2lud_full_spline_segment(
1897 	        job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec
1898 	      );
1899 	    }
1900 	    f2lud_final_spline_segment(
1901 	      job, drw, obj, sp, np, max, (obj->dt).spl.te, 0, 0, primary, ec
1902 	    );
1903           } else {
1904 	    f2lud_final_spline_segment(
1905 	      job, drw, obj, sp, np, max, (obj->dt).spl.te, 1, 0, primary, ec
1906 	    );
1907           }
1908         } else {
1909           /* ERROR: Illegal max value! */
1910           dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 39);
1911 	  f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN);
1912         }
1913       } else {
1914         for(i = 0; i < (np - 1); i++) {
1915           f2lud_full_spline_segment(
1916 	    job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 0, primary, ec
1917 	  );
1918         }
1919       }
1920     }
1921   }
1922 
1923 }
1924 
1925 
1926 
1927 /**	Create path for open spline object.
1928 	@param	job	Job structure.
1929 	@param	drw	Drawing structure.
1930 	@param	obj	Current object to process.
1931 	@param	primary	Flag: Primary object (1=object, 0=arrowhead).
1932 	@param	ec	Pointe to error code variable, may be NULL.
1933 */
1934 static
1935 void
f2lud_create_open_fast_spline_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int DK3_SILENCE_ARG_UNUSED (primary),int * ec)1936 f2lud_create_open_fast_spline_path(
1937   f2l_job_t		*job,
1938   dk3_fig_drawing_t	*drw,
1939   dk3_fig_obj_t		*obj,
1940   int			 DK3_SILENCE_ARG_UNUSED(primary),
1941   int			*ec
1942 )
1943 {
1944   dk3_fig_spline_point_t	*po;
1945   size_t			 np;
1946   size_t			 ib;
1947   size_t			 ic;
1948   double			 dxdtb;
1949   double			 dydtb;
1950   double			 dxdtc;
1951   double			 dydtc;
1952 
1953   DK3_UNUSED_ARG(primary)
1954   po = (obj->dt).spl.po;
1955   np = (obj->dt).spl.np;
1956   if (np > 1) {
1957     for (ib = 0; ib < (np - 1); ib++) {
1958       ic = ib + 1;
1959       if (0 == ib) {
1960         /* MOVETO */
1961 	f2lud_fig_moveto(job, drw, obj, po[ib].x, po[ib].y, ec);
1962       }
1963       if ((fabs(po[ib].s) < 1.0e-6) && (fabs(po[ic].s) < 1.0e-6)) {
1964         /* LINETO */
1965 	f2lud_fig_lineto(job, drw, obj, po[ic].x, po[ic].y, ec);
1966       } else {
1967         dxdtb = dxdtc = dk3ma_d_sub_ok(po[ic].x, po[ib].x, ec);
1968 	dydtb = dydtc = dk3ma_d_sub_ok(po[ic].y, po[ib].y, ec);
1969 	if ((0 < ib) && (fabs(1.0 + po[ib].s) < 1.0e-6)) {
1970 	  dxdtb = f2lpara_derived_center(po[ib-1].x, po[ib].x, po[ic].x, ec);
1971 	  dydtb = f2lpara_derived_center(po[ib-1].y, po[ib].y, po[ic].y, ec);
1972 	} else {
1973 	  if ((ic < (np - 1)) && (fabs(1.0 + po[ic].s) < 1.0e-6)) {
1974 	    dxdtb = f2lpara_derived_left(po[ib].x, po[ic].x, po[ic+1].x, ec);
1975 	    dydtb = f2lpara_derived_left(po[ib].y, po[ic].y, po[ic+1].y, ec);
1976 	  }
1977 	}
1978 	if ((ic < (np - 1)) && (1.0 + fabs(po[ic].s) < 1.0e-6)) {
1979 	  dxdtc = f2lpara_derived_center(po[ib].x, po[ic].x, po[ic+1].x, ec);
1980 	  dydtc = f2lpara_derived_center(po[ib].y, po[ic].y, po[ic+1].y, ec);
1981 	} else {
1982 	  if ((0 < ib) && (fabs(1.0 + po[ib].s) < 1.0e-6)) {
1983 	    dxdtc = f2lpara_derived_right(po[ib-1].x, po[ib].x, po[ic].x, ec);
1984 	    dydtc = f2lpara_derived_right(po[ib-1].y, po[ib].y, po[ic].y, ec);
1985 	  }
1986 	}
1987 	/* CURVETO */
1988 	f2lud_fig_curveto(
1989 	  job, drw, obj,
1990 	  dk3ma_d_add_ok(po[ib].x, (dxdtb / 3.0), ec),
1991 	  dk3ma_d_add_ok(po[ib].y, (dydtb / 3.0), ec),
1992 	  dk3ma_d_sub_ok(po[ic].x, (dxdtc / 3.0), ec),
1993 	  dk3ma_d_sub_ok(po[ic].y, (dydtc / 3.0), ec),
1994 	  po[ic].x,
1995 	  po[ic].y,
1996 	  ec
1997 	);
1998       }
1999     }
2000   }
2001 }
2002 
2003 
2004 
2005 /**	Create path for closed spline object.
2006 	@param	job	Job structure.
2007 	@param	drw	Drawing structure.
2008 	@param	obj	Current object to process.
2009 	@param	primary	Flag: Primary object (1=object, 0=arrowhead).
2010 	@param	ec	Pointe to error code variable, may be NULL.
2011 */
2012 static
2013 void
f2lud_create_closed_spline_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)2014 f2lud_create_closed_spline_path(
2015   f2l_job_t		*job,
2016   dk3_fig_drawing_t	*drw,
2017   dk3_fig_obj_t		*obj,
2018   int			 primary,
2019   int			*ec
2020 )
2021 {
2022   dk3_fig_spline_point_t	*sp;	/* Spline points. */
2023   size_t			 np;	/* Number of points. */
2024   size_t			 i;	/* Current segment index. */
2025 
2026   sp = (obj->dt).spl.po;
2027   np = (obj->dt).spl.np;
2028   for(i = 0; i < np; i++) {
2029     f2lud_full_spline_segment(
2030       job, drw, obj, sp, np, i, ((0 == i) ? 1 : 0), 1, primary, ec
2031     );
2032   }
2033 
2034 }
2035 
2036 /**	Create path for closed spline object.
2037 	@param	job	Job structure.
2038 	@param	drw	Drawing structure.
2039 	@param	obj	Current object to process.
2040 	@param	primary	Flag: Primary object (1=object, 0=arrowhead).
2041 	@param	ec	Pointe to error code variable, may be NULL.
2042 */
2043 static
2044 void
f2lud_create_closed_fast_spline_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int DK3_SILENCE_ARG_UNUSED (primary),int * ec)2045 f2lud_create_closed_fast_spline_path(
2046   f2l_job_t		*job,
2047   dk3_fig_drawing_t	*drw,
2048   dk3_fig_obj_t		*obj,
2049   int			 DK3_SILENCE_ARG_UNUSED(primary),
2050   int			*ec
2051 )
2052 {
2053   dk3_fig_spline_point_t	*po;
2054   size_t			 np;
2055   size_t			 ib;
2056   size_t			 ic;
2057   size_t			 ia;
2058   size_t			 id;
2059   double			 dxdtb;
2060   double			 dydtb;
2061   double			 dxdtc;
2062   double			 dydtc;
2063 
2064   DK3_UNUSED_ARG(primary)
2065   po = (obj->dt).spl.po;
2066   np = (obj->dt).spl.np;
2067   if (2 < np) {
2068     for (ib = 0; ib < np; ib++) {
2069       ic = ib + 1;
2070       id = ib + 2;
2071       if (ic >= np) { ic = ic - np; }
2072       if (id >= np) { id = id - np; }
2073       if (0 < ib) {
2074         ia = ib - 1;
2075       } else {
2076         ia = np - 1;
2077       }
2078       if (0 == ib) {
2079         /* MOVETO */
2080 	f2lud_fig_moveto(job, drw, obj, po[ib].x, po[ib].y, ec);
2081       }
2082       if ((fabs(po[ib].s) < 1.0e-6) && (fabs(po[ic].s) < 1.0e-6)) {
2083         /* LINETO */
2084 	f2lud_fig_lineto(job, drw, obj, po[ic].x, po[ic].y, ec);
2085       } else {
2086         dxdtb = dxdtc = dk3ma_d_sub_ok(po[ic].x, po[ib].x, ec);
2087 	dydtb = dydtc = dk3ma_d_sub_ok(po[ic].y, po[ib].y, ec);
2088 	if (fabs(1.0 + po[ib].s) < 1.0e-6) {
2089 	  dxdtb = f2lpara_derived_center(po[ia].x, po[ib].x, po[ic].x, ec);
2090 	  dydtb = f2lpara_derived_center(po[ia].y, po[ib].y, po[ic].y, ec);
2091 	} else {
2092 	  if (fabs(1.0 + po[ic].s) < 1.0e-6) {
2093 	    dxdtb = f2lpara_derived_left(po[ib].x, po[ic].x, po[id].x, ec);
2094 	    dydtb = f2lpara_derived_left(po[ib].y, po[ic].y, po[id].y, ec);
2095 	  }
2096 	}
2097 	if (fabs(1.0 + po[ic].s) < 1.0e-6) {
2098 	  dxdtc = f2lpara_derived_center(po[ib].x, po[ic].x, po[id].x, ec);
2099 	  dydtc = f2lpara_derived_center(po[ib].y, po[ic].y, po[id].y, ec);
2100 	} else {
2101 	  if (fabs(1.0 + po[ib].s) < 1.0e-6) {
2102 	    dxdtc = f2lpara_derived_right(po[ia].x, po[ib].x, po[ic].x, ec);
2103 	    dydtc = f2lpara_derived_right(po[ia].y, po[ib].y, po[ic].y, ec);
2104 	  }
2105 	}
2106         /* CURVETO */
2107 	f2lud_fig_curveto(
2108 	  job, drw, obj,
2109 	  dk3ma_d_add_ok(po[ib].x, (dxdtb / 3.0), ec),
2110 	  dk3ma_d_add_ok(po[ib].y, (dydtb / 3.0), ec),
2111 	  dk3ma_d_sub_ok(po[ic].x, (dxdtc / 3.0), ec),
2112 	  dk3ma_d_sub_ok(po[ic].y, (dydtc / 3.0), ec),
2113 	  po[ic].x,
2114 	  po[ic].y,
2115 	  ec
2116 	);
2117       }
2118     }
2119   }
2120 
2121 }
2122 
2123 
2124 
2125 /**	Create path for open arc object.
2126 	@param	job	Job structure.
2127 	@param	drw	Drawing structure.
2128 	@param	obj	Current object to process.
2129 	@param	iscl	Flag: Closed arc.
2130 	@param	ec	Pointe to error code variable, may be NULL.
2131 */
2132 static
2133 void
f2lud_create_arc_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int iscl,int * ec)2134 f2lud_create_arc_path(
2135   f2l_job_t		*job,
2136   dk3_fig_drawing_t	*drw,
2137   dk3_fig_obj_t		*obj,
2138   int			 iscl,
2139   int			*ec
2140 )
2141 {
2142   double		sx;		/* Start x. */
2143   double		sy;		/* Start y. */
2144   double		cx;		/* Center x. */
2145   double		cy;		/* Center y. */
2146   double		r;		/* Radius. */
2147   double		as;		/* Arc start angle in radians. */
2148   double		ae;		/* Arc end angle in radians. */
2149   double		lastx;		/* Segment start x. */
2150   double		lasty;		/* Segment start y. */
2151   double		lastkdxdt;	/* X difference to first control. */
2152   double		lastkdydt;	/* Y difference to first control. */
2153   double		x;		/* Segment end x. */
2154   double		y;		/* Segment end y. */
2155   double		kdxdt;		/* X difference to last control. */
2156   double		kdydt;		/* Y difference to last control. */
2157   double		dnumsegs;	/* Number of segments. */
2158   double		alpha;		/* Arc angle in radians. */
2159   double		alphaseg;	/* Segment angle in radians. */
2160   double		kappa;		/* Factor for derivative. */
2161   double		alphaend;	/* Segment end angle in radians. */
2162   size_t		nsegs;		/* Number of segments. */
2163   size_t		i;		/* Index of current segment. */
2164 
2165   cx = (obj->dt).arc.xc;
2166   cy = (obj->dt).arc.yc;
2167   r  = (obj->dt).arc.ra;
2168   if((obj->dt).arc.as < (obj->dt).arc.ae) {
2169     as = (obj->dt).arc.as;
2170     ae = (obj->dt).arc.ae;
2171   } else {
2172     as = (obj->dt).arc.ae;
2173     ae = (obj->dt).arc.as;
2174   }
2175   alpha = dk3ma_d_sub_ok(ae, as, ec);
2176   dnumsegs = ceil(dk3ma_d_mul_ok(4.0, (alpha / M_PI), ec));
2177 
2178   nsegs = dk3ma_d_to_sz_ok(dnumsegs, ec);
2179   alphaseg = alpha / ((double)nsegs);
2180   kappa = dk3fig_tool_arc_kappa(alphaseg, ec);
2181   sx = lastx = dk3ma_d_add_ok(cx, (r * cos(as)), ec);
2182   sy = lasty = dk3ma_d_add_ok(cy, (r * sin(as)), ec);
2183   f2lud_fig_moveto(job, drw, obj, lastx, lasty, ec);
2184   lastkdxdt = dk3ma_d_mul_ok(
2185     kappa,
2186     (-1.0 * dk3ma_d_mul_ok(r, alphaseg, ec) * sin(as)),
2187     ec
2188   );
2189   lastkdydt = dk3ma_d_mul_ok(
2190     kappa,
2191     (dk3ma_d_mul_ok(r, alphaseg, ec) * cos(as)),
2192     ec
2193   );
2194   for(i = 0; i < nsegs; i++) {
2195     if(i < (nsegs - 1)) {
2196       alphaend = dk3ma_d_add_ok(
2197         as,
2198 	dk3ma_d_mul_ok(dk3ma_d_add_ok(1.0, (double)i, ec), alphaseg, ec),
2199 	ec
2200       );
2201     } else {
2202       alphaend = ae;
2203     }
2204     x = dk3ma_d_add_ok(cx, (r * cos(alphaend)), ec);
2205     y = dk3ma_d_add_ok(cy, (r * sin(alphaend)), ec);
2206     kdxdt = dk3ma_d_mul_ok(
2207       kappa,
2208       (-1.0 * dk3ma_d_mul_ok(r, alphaseg, ec) * sin(alphaend)),
2209       ec
2210     );
2211     kdydt = dk3ma_d_mul_ok(
2212       kappa,
2213       (dk3ma_d_mul_ok(r, alphaseg, ec) * cos(alphaend)),
2214       ec
2215     );
2216     f2lud_fig_curveto(
2217       job, drw, obj,
2218       dk3ma_d_add_ok(lastx, lastkdxdt, ec),
2219       dk3ma_d_add_ok(lasty, lastkdydt, ec),
2220       dk3ma_d_sub_ok(x, kdxdt, ec),
2221       dk3ma_d_sub_ok(y, kdydt, ec),
2222       x, y,
2223       ec
2224     );
2225     lastx = x; lasty = y; lastkdxdt = kdxdt; lastkdydt = kdydt;
2226   }
2227   /*	For closed arc draw the lines.
2228   */
2229   if(iscl) {
2230     f2lud_fig_lineto(job, drw, obj, cx, cy, ec);
2231     f2lud_fig_lineto(job, drw, obj, sx, sy, ec);
2232   }
2233 
2234 }
2235 
2236 
2237 
2238 /**	Create path for half circle object.
2239 	@param	job	Job structure.
2240 	@param	drw	Drawing structure.
2241 	@param	obj	Current object to process.
2242 	@param	ec	Pointe to error code variable, may be NULL.
2243 */
2244 static
2245 void
f2lud_create_half_circle_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int * ec)2246 f2lud_create_half_circle_path(
2247   f2l_job_t		*job,
2248   dk3_fig_drawing_t	*drw,
2249   dk3_fig_obj_t		*obj,
2250   int			*ec
2251 )
2252 {
2253   dk3_fig_poly_point_t	po[7];	/* Points to construct path. */
2254   size_t		i;	/* Current point index */
2255 
2256   po[0].x = 0.0;
2257   po[0].y = (obj->dt).hci.ra;
2258   po[1].x = -1.0 * FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).hci.ra;
2259   po[1].y = (obj->dt).hci.ra;
2260   po[2].x = -1.0 * (obj->dt).hci.ra;
2261   po[2].y = FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).hci.ra;
2262   po[3].x = -1.0 * (obj->dt).hci.ra;
2263   po[3].y = 0.0;
2264   po[4].x = -1.0 * (obj->dt).hci.ra;
2265   po[4].y = -1.0 * FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).hci.ra;
2266   po[5].x = -1.0 * FIG2LAT_CIRCLE_QUADRANT_BEZIER * (obj->dt).hci.ra;
2267   po[5].y = -1.0 * (obj->dt).hci.ra;
2268   po[6].x = 0.0;
2269   po[6].y = -1.0 * (obj->dt).hci.ra;
2270   if(1.0e-6 < fabs((obj->dt).hci.an)) {
2271     for(i = 0; i < 7; i++) {
2272       dk3fig_tool_rotate_point(&(po[i]), (obj->dt).hci.an, ec);
2273     }
2274   }
2275   for(i = 0; i < 7; i++) {
2276     dk3fig_tool_shift_point(&(po[i]), (obj->dt).hci.cx, (obj->dt).hci.cy, ec);
2277   }
2278   f2lud_fig_moveto(job, drw, obj, po[0].x, po[0].y, ec);
2279   f2lud_fig_curveto(
2280     job, drw, obj, po[1].x, po[1].y, po[2].x, po[2].y, po[3].x, po[3].y, ec
2281   );
2282   f2lud_fig_curveto(
2283     job, drw, obj, po[4].x, po[4].y, po[5].x, po[5].y, po[6].x, po[6].y, ec
2284   );
2285   if(obj->st) {
2286     f2lud_fig_lineto(job, drw, obj, po[0].x, po[0].y, ec);
2287   }
2288 
2289 }
2290 
2291 
2292 
2293 /**	Create path for object.
2294 	@param	job	Job structure.
2295 	@param	drw	Drawing structure.
2296 	@param	obj	Current object to process.
2297 	@param	ec	Pointe to error code variable, may be NULL.
2298 	@param	primary	Flag: Primary object (1=object, 0=arrowhead).
2299 */
2300 static
2301 void
f2lud_create_path(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)2302 f2lud_create_path(
2303   f2l_job_t		*job,
2304   dk3_fig_drawing_t	*drw,
2305   dk3_fig_obj_t		*obj,
2306   int			 primary,
2307   int			*ec
2308 )
2309 {
2310 
2311   switch(obj->ot) {
2312     case DK3_FIG_OBJ_ELLIPSE: {
2313       f2lud_create_ellipse_path(job, drw, obj, ec);
2314     } break;
2315     case DK3_FIG_OBJ_POLYLINE: {
2316       switch(obj->st) {
2317         case 1: {	/* Polyline */
2318 	  f2lud_create_polygon_path(job, drw, obj, ec);
2319 	} break;
2320 	case 2: {	/* Box */
2321 	  f2lud_create_box_path(job, drw, obj, ec);
2322 	} break;
2323 	case 3: {	/* Polygon */
2324 	  f2lud_create_polygon_path(job, drw, obj, ec);
2325 	} break;
2326 	case 4: {	/* Arc-box */
2327 	  f2lud_create_arc_box_path(job, drw, obj, ec);
2328 	} break;
2329       }
2330     } break;
2331     case DK3_FIG_OBJ_SPLINE: {
2332       switch(obj->st) {
2333         case 0: case 2: case 4: {	/* open spline */
2334 	  f2lud_create_open_spline_path(job, drw, obj, primary, ec);
2335 	} break;
2336 	case 1: case 3: case 5: {	/* closed spline */
2337 	  f2lud_create_closed_spline_path(job, drw, obj, primary, ec);
2338 	} break;
2339       }
2340     } break;
2341     case DK3_FIG_OBJ_ARC: {
2342       switch(obj->st) {
2343         case 1: {			/* open arc */
2344 	  f2lud_create_arc_path(job, drw, obj, 0, ec);
2345 	} break;
2346 	default: {			/* closed arc */
2347 	  f2lud_create_arc_path(job, drw, obj, 1, ec);
2348 	} break;
2349       }
2350     } break;
2351     case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE: {
2352       f2lud_create_half_circle_path(job, drw, obj, ec);
2353     } break;
2354     case DK3_FIG_OBJ_PSEUDO_FAST_SPLINE: {
2355       switch(obj->st) {
2356         case 0: case 2: case 4: {	/* open spline */
2357 	  f2lud_create_open_fast_spline_path(job, drw, obj, primary, ec);
2358 	} break;
2359 	case 1: case 3: case 5: {	/* closed spline */
2360 	  f2lud_create_closed_fast_spline_path(job, drw, obj, primary, ec);
2361 	} break;
2362       }
2363     } break;
2364   }
2365 }
2366 
2367 
2368 
2369 /**	Set color (stroke color for pdf/pgf).
2370 	If we already have a color 1 equal to the new color
2371 	the operation is skipped.
2372 	@param	job		Conversion job structure.
2373 	@param	drw		Drawing structure.
2374 	@param	colno		Color number.
2375 	@param	fillstyle	Fill style used in the object.
2376 	Depending on the fillstyle it might be necessary
2377 	to create a shade of the color.
2378 */
2379 static
2380 void
f2lud_set_color_1(f2l_job_t * job,dk3_fig_drawing_t * drw,int colno,int fillstyle)2381 f2lud_set_color_1(
2382   f2l_job_t		*job,
2383   dk3_fig_drawing_t	*drw,
2384   int			 colno,
2385   int			 fillstyle
2386 )
2387 {
2388   dk3_rgb_color_t	rgb;		/* Color structure to fill. */
2389   int			muc = 1;	/* Flag: Must configure. */
2390 #if 0
2391   int			ec = 0;		/* Error code variable. */
2392 #endif
2393 
2394   dk3fig_tool_find_color(&rgb, drw, colno, fillstyle);
2395 #if 0
2396   if((job->gs).hc1) {
2397     if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.r, (job->gs).c1.r, &ec))) {
2398       if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.g, (job->gs).c1.g, &ec))) {
2399         if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.b, (job->gs).c1.b, &ec))) {
2400 	  if(0 == ec) {
2401 	    muc = 0;
2402 	  }
2403         }
2404       }
2405     }
2406   }
2407 #else
2408   muc = dk3fig_tool_must_set_color(
2409     (job->gs).hc1, (job->gs).c1.r, (job->gs).c1.g, (job->gs).c1.b,
2410     rgb.r, rgb.g, rgb.b
2411   );
2412 #endif
2413   if(muc) {
2414     switch(job->dr) {
2415       case FIG2LAT_DRIVER_TEX_FULL_PGF: {
2416         f2lpgf_tex_set_color_1(job, drw, &rgb);
2417       } break;
2418       case FIG2LAT_DRIVER_TEX_FULL_PDF: {
2419         f2lpdf_tex_with_pdf_set_color_1(job, drw, &rgb);
2420       } break;
2421       case FIG2LAT_DRIVER_EPS_WITH_TEX: {
2422         f2leps_eps_with_tex_set_color_1(job, drw, &rgb);
2423       } break;
2424       case FIG2LAT_DRIVER_PDF_WITH_TEX: {
2425         f2lpdf_pdf_with_tex_set_color_1(job, drw, &rgb);
2426       } break;
2427       case FIG2LAT_DRIVER_EPS_STANDALONE: {
2428         f2leps_eps_pure_set_color_1(job, drw, &rgb);
2429       } break;
2430       /* @DRIVER@ universal */
2431       default: {
2432         f2lpgf_pgf_set_color_1(job, drw, &rgb);
2433       } break;
2434     }
2435     (job->gs).c1.r = rgb.r;
2436     (job->gs).c1.g = rgb.g;
2437     (job->gs).c1.b = rgb.b;
2438     (job->gs).hc1  = 1;
2439   }
2440 
2441 }
2442 
2443 
2444 
2445 /**	Set non-stroking color for pdf/pgf.
2446 	If we already have a color 2 equal to the new color
2447 	the operation is skipped.
2448 	@param	job		Job structure.
2449 	@param	drw		Drawing structure.
2450 	@param	colno		Color number.
2451 	@param	fillstyle	Fill style used in the object.
2452 	Depending on the fillstyle it might be necessary
2453 	to create a shade of the color.
2454 */
2455 static
2456 void
f2lud_set_color_2(f2l_job_t * job,dk3_fig_drawing_t * drw,int colno,int fillstyle)2457 f2lud_set_color_2(
2458   f2l_job_t		*job,
2459   dk3_fig_drawing_t	*drw,
2460   int			 colno,
2461   int			 fillstyle
2462 )
2463 {
2464   dk3_rgb_color_t	 rgb;		/* Color structure to fill. */
2465 #if 0
2466   int			 ec = 0;	/* Error code variable. */
2467 #endif
2468   int			 muc = 1;	/* Flag: Must configure. */
2469 
2470 
2471   dk3fig_tool_find_color(&rgb, drw, colno, fillstyle);
2472 #if 0
2473   if((job->gs).hc2) {
2474     if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.r, (job->gs).c2.r, &ec))) {
2475       if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.g, (job->gs).c2.g, &ec))) {
2476         if(1.0e-6 > fabs(dk3ma_d_sub_ok(rgb.b, (job->gs).c2.b, &ec))) {
2477 	  if(0 == ec) {
2478 	    muc = 0;
2479 	  }
2480         }
2481       }
2482     }
2483   }
2484 #else
2485   muc = dk3fig_tool_must_set_color(
2486     (job->gs).hc2, (job->gs).c2.r, (job->gs).c2.g, (job->gs).c2.b,
2487     rgb.r, rgb.g, rgb.b
2488   );
2489 #endif
2490   if(muc) {
2491     switch(job->dr) {
2492       case FIG2LAT_DRIVER_TEX_FULL_PGF: {
2493         f2lpgf_tex_set_color_2(job, drw, &rgb);
2494       } break;
2495       case FIG2LAT_DRIVER_TEX_FULL_PDF: {
2496         f2lpdf_tex_with_pdf_set_color_2(job, drw, &rgb);
2497       } break;
2498       case FIG2LAT_DRIVER_EPS_WITH_TEX: {
2499         f2leps_eps_with_tex_set_color_2(job, drw, &rgb);
2500       } break;
2501       case FIG2LAT_DRIVER_PDF_WITH_TEX: {
2502         f2lpdf_pdf_with_tex_set_color_2(job, drw, &rgb);
2503       } break;
2504       case FIG2LAT_DRIVER_EPS_STANDALONE: {
2505         f2leps_eps_pure_set_color_2(job, drw, &rgb);
2506       } break;
2507       /* @DRIVER@ universal */
2508       default: {
2509         f2lpgf_pgf_set_color_2(job, drw, &rgb);
2510       } break;
2511     }
2512     (job->gs).c2.r = rgb.r;
2513     (job->gs).c2.g = rgb.g;
2514     (job->gs).c2.b = rgb.b;
2515     (job->gs).hc2  = 1;
2516   }
2517 
2518 }
2519 
2520 
2521 
2522 /**	Internal function to set line width.
2523 	The line width is not set again if we already
2524 	have a current line width equal to the new line width.
2525 	@param	job	Job structure.
2526 	@param	drw	Drawing structure.
2527 	@param	obj	Current object.
2528 	@param	lw	New line width in output coordinates.
2529 */
2530 static
2531 void
f2lud_internal_set_line_width(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,double lw)2532 f2lud_internal_set_line_width(
2533   f2l_job_t		*job,
2534   dk3_fig_drawing_t	*drw,
2535   dk3_fig_obj_t		*obj,
2536   double		 lw
2537 )
2538 {
2539   int		mc = 1;		/* Flag: Must configure. */
2540   int		ec = 0;		/* Error code variable. */
2541 
2542   if((job->gs).hlw) {
2543     if(1.0e-6 > fabs(dk3ma_d_sub_ok(lw, (job->gs).lw, &ec))) {
2544       if(0 == ec) {
2545         mc = 0;
2546       }
2547     }
2548   }
2549   if(mc) {
2550     switch(job->dr) {
2551       case FIG2LAT_DRIVER_TEX_FULL_PGF: {
2552         f2lpgf_tex_set_line_width(job, drw, obj, lw);
2553       } break;
2554       case FIG2LAT_DRIVER_TEX_FULL_PDF: {
2555         f2lpdf_tex_with_pdf_set_line_width(job, drw, obj, lw);
2556       } break;
2557       case FIG2LAT_DRIVER_EPS_WITH_TEX: {
2558         f2leps_eps_with_tex_set_line_width(job, drw, obj, lw);
2559       } break;
2560       case FIG2LAT_DRIVER_PDF_WITH_TEX: {
2561         f2lpdf_pdf_with_tex_set_line_width(job, drw, obj, lw);
2562       } break;
2563       case FIG2LAT_DRIVER_EPS_STANDALONE: {
2564         f2leps_eps_pure_set_line_width(job, drw, obj, lw);
2565       } break;
2566       /* @DRIVER@ universal */
2567       default: {
2568         f2lpgf_pgf_set_line_width(job, drw, obj, lw);
2569       } break;
2570     }
2571     (job->gs).lw = lw;
2572     (job->gs).hlw = 1;
2573   }
2574 
2575 }
2576 
2577 
2578 
2579 /**	Set line dash (line style and dash/gap length).
2580 	The operation is skipped if the current line style and style
2581 	value is equal to the new one.
2582 	@param	job	Job structure.
2583 	@param	drw	Drawing structure.
2584 	@param	obj	Fig object.
2585 	@param	ls	Line style.
2586 	@param	sv	Style value (dash/gap) length in output units.
2587 */
2588 static
2589 void
f2lud_internal_set_line_dash(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int ls,double sv)2590 f2lud_internal_set_line_dash(
2591   f2l_job_t		*job,
2592   dk3_fig_drawing_t	*drw,
2593   dk3_fig_obj_t		*obj,
2594   int			 ls,
2595   double		 sv
2596 )
2597 {
2598   double	mysv;		/* Style value converted to output space. */
2599   double	mylw;		/* Line width in Fig and output space. */
2600   int		mc = 1;		/* Flag: Must configure. */
2601   int		ec = 0;		/* Error code variable. */
2602 
2603   mysv = 0.9 * sv;
2604   mylw = dk3fig_tool_get_lw(drw, obj, &ec);
2605   /*	Convert line width to output space.
2606   */
2607   mylw = dk3ct_2d_r(&(job->ct2d), mylw, &ec);
2608   if((job->gs).hls) {
2609     if((job->gs).ls == ls) {
2610       if(DK3_FIG_LS_SOLID == ls) {
2611         mc = 0;
2612       } else {
2613         if(1.0e-6 > fabs(dk3ma_d_sub_ok((job->gs).sv, mysv, &ec))) {
2614 	  if(0 == ec) {
2615 	    if(DK3_FIG_LS_DASHED == ls) {
2616 	      mc = 0;
2617 	    } else {
2618 	      if(1.0e-6 > fabs(dk3ma_d_sub_ok((job->gs).slw, mylw, &ec))) {
2619 	        if(0 == ec) {
2620 	          mc = 0;
2621 	        }
2622 	      }
2623 	    }
2624 	  }
2625 	}
2626       }
2627     }
2628   }
2629   if(mc) {
2630     switch(job->dr) {
2631       case FIG2LAT_DRIVER_TEX_FULL_PGF: {
2632         f2lpgf_tex_set_line_style(job, drw, obj, ls, mysv, mylw);
2633       } break;
2634       case FIG2LAT_DRIVER_TEX_FULL_PDF: {
2635         f2lpdf_tex_with_pdf_set_line_style(job, drw, obj, ls, mysv, mylw);
2636       } break;
2637       case FIG2LAT_DRIVER_EPS_WITH_TEX: {
2638         f2leps_eps_with_tex_set_line_style(job, drw, obj, ls, mysv, mylw);
2639       } break;
2640       case FIG2LAT_DRIVER_PDF_WITH_TEX: {
2641         f2lpdf_pdf_with_tex_set_line_style(job, drw, obj, ls, mysv, mylw);
2642       } break;
2643       case FIG2LAT_DRIVER_EPS_STANDALONE: {
2644         f2leps_eps_pure_set_line_style(job, drw, obj, ls, mysv, mylw);
2645       } break;
2646       /* @DRIVER@ universal */
2647       default: {
2648         f2lpgf_pgf_set_line_style(job, drw, obj, ls, mysv, mylw);
2649       } break;
2650     }
2651     (job->gs).ls = ls; (job->gs).sv = mysv; (job->gs).slw = mylw;
2652     (job->gs).hls = 1;
2653   }
2654 
2655 }
2656 
2657 
2658 
2659 /**	Set line ends.
2660 	The operation is skipped if the current line end is equal
2661 	to the new one.
2662 	@param	job	Job structure.
2663 	@param	drw	Drawing structure.
2664 	@param	obj	Current object.
2665 	@param	le	Line end style.
2666 */
2667 static
2668 void
f2lud_set_line_end(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int le)2669 f2lud_set_line_end(
2670   f2l_job_t		*job,
2671   dk3_fig_drawing_t	*drw,
2672   dk3_fig_obj_t		*obj,
2673   int			 le
2674 )
2675 {
2676   int		mc = 1;		/* Flag: Must configure. */
2677 
2678   if((job->gs).hlc) {
2679     if((job->gs).lc == le) {
2680       mc = 0;
2681     }
2682   }
2683   if(mc) {
2684     switch(job->dr) {
2685       case FIG2LAT_DRIVER_TEX_FULL_PGF: {
2686         f2lpgf_tex_set_line_end(job, drw, obj, le);
2687       } break;
2688       case FIG2LAT_DRIVER_TEX_FULL_PDF: {
2689         f2lpdf_tex_with_pdf_set_line_end(job, drw, obj, le);
2690       } break;
2691       case FIG2LAT_DRIVER_EPS_WITH_TEX: {
2692         f2leps_eps_with_tex_set_line_end(job, drw, obj, le);
2693       } break;
2694       case FIG2LAT_DRIVER_PDF_WITH_TEX: {
2695         f2lpdf_pdf_with_tex_set_line_end(job, drw, obj, le);
2696       } break;
2697       case FIG2LAT_DRIVER_EPS_STANDALONE: {
2698         f2leps_eps_pure_set_line_end(job, drw, obj, le);
2699       } break;
2700       /* @DRIVER@ universal */
2701       default: {
2702         f2lpgf_pgf_set_line_end(job, drw, obj, le);
2703       } break;
2704     }
2705     (job->gs).lc = le; (job->gs).hlc = 1;
2706   }
2707 
2708 }
2709 
2710 
2711 
2712 /**	Set line join.
2713 	The operation is skipped if the current line join is equal
2714 	to the new one.
2715 	@param	job	Job structure.
2716 	@param	drw	Drawing structure.
2717 	@param	obj	Current object.
2718 	@param	lj	Line end style.
2719 */
2720 static
2721 void
f2lud_set_line_join(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int lj)2722 f2lud_set_line_join(
2723   f2l_job_t		*job,
2724   dk3_fig_drawing_t	*drw,
2725   dk3_fig_obj_t		*obj,
2726   int			 lj
2727 )
2728 {
2729   int		mc = 1;		/* Flag: Must configure. */
2730 
2731   if((job->gs).hlj) {
2732     if((job->gs).lj == lj) {
2733       mc = 0;
2734     }
2735   }
2736   if(mc) {
2737     switch(job->dr) {
2738       case FIG2LAT_DRIVER_TEX_FULL_PGF: {
2739         f2lpgf_tex_set_line_join(job, drw, obj, lj);
2740       } break;
2741       case FIG2LAT_DRIVER_TEX_FULL_PDF: {
2742         f2lpdf_tex_with_pdf_set_line_join(job, drw, obj, lj);
2743       } break;
2744       case FIG2LAT_DRIVER_EPS_WITH_TEX: {
2745         f2leps_eps_with_tex_set_line_join(job, drw, obj, lj);
2746       } break;
2747       case FIG2LAT_DRIVER_PDF_WITH_TEX: {
2748         f2lpdf_pdf_with_tex_set_line_join(job, drw, obj, lj);
2749       } break;
2750       case FIG2LAT_DRIVER_EPS_STANDALONE: {
2751         f2leps_eps_pure_set_line_join(job, drw, obj, lj);
2752       } break;
2753       /* @DRIVER@ universal */
2754       default: {
2755         f2lpgf_pgf_set_line_join(job, drw, obj, lj);
2756       } break;
2757     }
2758     (job->gs).lj = lj; (job->gs).hlj = 1;
2759   }
2760 
2761 }
2762 
2763 
2764 
2765 /**	Set up line style, line width, line ends and line join for pattern.
2766 	@param	job	Job structure.
2767 	@param	drw	Drawing structure.
2768 	@param	obj	Current object to process.
2769 */
2770 static
2771 void
f2lud_set_pattern_line_style(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)2772 f2lud_set_pattern_line_style(
2773   f2l_job_t		*job,
2774   dk3_fig_drawing_t	*drw,
2775   dk3_fig_obj_t		*obj
2776 )
2777 {
2778 
2779 #if VERSION_BEFORE_20140330
2780   f2lud_internal_set_line_width(job, drw, obj, ((job->lighten) ? 0.45 : 0.9));
2781 #else
2782   f2lud_internal_set_line_width(job, drw, obj, job->lwbp);
2783 #endif
2784   f2lud_internal_set_line_dash(job, drw, obj, DK3_FIG_LS_SOLID, -1.0);
2785   f2lud_set_line_end(job, drw, obj, DK3_FIG_LC_BUTT);
2786   f2lud_set_line_join(job, drw, obj, DK3_FIG_LJ_MITER);
2787 #if 0
2788   /*	2012/11/18
2789   	In fishscale patterns we draw arc by arc, not a sequence
2790 	of arcs. So we do not need to care about line join
2791 	of arcs.
2792   */
2793   switch(obj->fi) {
2794     case 56: case 57: {
2795       f2lud_set_line_join(job, drw, obj, DK3_FIG_LJ_BEVEL);
2796     } break;
2797     default: {
2798       f2lud_set_line_join(job, drw, obj, DK3_FIG_LJ_MITER);
2799     } break;
2800   }
2801 #endif
2802 
2803 }
2804 
2805 
2806 
2807 /**	Set line width.
2808 	@param	job	Job structure.
2809 	@param	drw	Drawing structure.
2810 	@param	obj	Current object to process.
2811 */
2812 static
2813 void
f2lud_set_line_width(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)2814 f2lud_set_line_width(
2815   f2l_job_t		*job,
2816   dk3_fig_drawing_t	*drw,
2817   dk3_fig_obj_t		*obj
2818 )
2819 {
2820   double 	 lw;		/* Line width in Fig space. */
2821   int		 ec = 0;	/* Error code variable. */
2822 
2823   lw = dk3fig_tool_get_lw(drw, obj, &ec);
2824   lw = dk3ct_2d_r(&(job->ct2d), lw, &ec);
2825   if(0 == ec) {
2826     f2lud_internal_set_line_width(job, drw, obj, lw);
2827   }
2828 }
2829 
2830 
2831 
2832 /**	Set line dash (line style and dash/gap length).
2833 	@param	job	Job structure.
2834 	@param	drw	Drawing structure.
2835 	@param	obj	Fig object.
2836 */
2837 static
2838 void
f2lud_set_line_dash(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)2839 f2lud_set_line_dash(
2840   f2l_job_t		*job,
2841   dk3_fig_drawing_t	*drw,
2842   dk3_fig_obj_t		*obj
2843 )
2844 {
2845 
2846   f2lud_internal_set_line_dash(job, drw, obj, obj->ls, (0.9 * obj->sv));
2847 
2848 }
2849 
2850 
2851 
2852 /**	Draw operations for object: stroke.
2853 	@param	job	Job structure.
2854 	@param	drw	Drawing structure.
2855 	@param	obj	Current object to process.
2856 	@param	ec	Pointe to error code variable, may be NULL.
2857 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
2858 */
2859 static
2860 void
f2lud_path_stroke(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)2861 f2lud_path_stroke(
2862   f2l_job_t		*job,
2863   dk3_fig_drawing_t	*drw,
2864   dk3_fig_obj_t		*obj,
2865   int			 primary,
2866   int			*ec
2867 )
2868 {
2869 
2870   f2lud_set_color_1(job, drw, obj->pc, 20);
2871   f2lud_set_line_width(job, drw, obj);
2872   f2lud_set_line_dash(job, drw, obj);
2873   f2lud_set_line_end(job, drw, obj, obj->cs);
2874   f2lud_set_line_join(job, drw, obj, obj->js);
2875   f2lud_newpath(job, drw, obj);
2876   f2lud_create_path(job, drw, obj, primary, ec);
2877   if(obj->cl) {
2878     f2lud_closepath(job, drw, obj);
2879   }
2880   f2lud_stroke(job, drw, obj);
2881 
2882 }
2883 
2884 
2885 
2886 /**	Draw operations for object: fill.
2887 	@param	job	Job structure.
2888 	@param	drw	Drawing structure.
2889 	@param	obj	Current object to process.
2890 	@param	ec	Pointe to error code variable, may be NULL.
2891 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
2892 */
2893 static
2894 void
f2lud_path_fill(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)2895 f2lud_path_fill(
2896   f2l_job_t		*job,
2897   dk3_fig_drawing_t	*drw,
2898   dk3_fig_obj_t		*obj,
2899   int			 primary,
2900   int			*ec
2901 )
2902 {
2903 
2904   switch(job->dr) {
2905     case FIG2LAT_DRIVER_PGF:
2906     case FIG2LAT_DRIVER_TEX_FULL_PGF:
2907     case FIG2LAT_DRIVER_TEX_FULL_PDF:
2908     case FIG2LAT_DRIVER_PDF_WITH_TEX:
2909     {
2910       f2lud_set_color_2(job, drw, obj->fc, obj->fi);
2911     } break;
2912     default: {
2913       f2lud_set_color_1(job, drw, obj->fc, obj->fi);
2914     } break;
2915   }
2916   f2lud_newpath(job, drw, obj);
2917   f2lud_create_path(job, drw, obj, primary, ec);
2918   f2lud_closepath(job, drw, obj);
2919   f2lud_fill(job, drw, obj);
2920 
2921 }
2922 
2923 
2924 
2925 /**	Draw operations for object: fill and stroke.
2926 	@param	job	Job structure.
2927 	@param	drw	Drawing structure.
2928 	@param	obj	Current object to process.
2929 	@param	ec	Pointe to error code variable, may be NULL.
2930 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
2931 */
2932 static
2933 void
f2lud_path_fill_stroke(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)2934 f2lud_path_fill_stroke(
2935   f2l_job_t		*job,
2936   dk3_fig_drawing_t	*drw,
2937   dk3_fig_obj_t		*obj,
2938   int			 primary,
2939   int			*ec
2940 )
2941 {
2942 
2943   switch(job->dr) {
2944     case FIG2LAT_DRIVER_PGF:
2945     case FIG2LAT_DRIVER_TEX_FULL_PGF:
2946     {
2947       f2lud_set_color_2(job, drw, obj->fc, obj->fi);
2948       f2lud_set_color_1(job, drw, obj->pc, 20);
2949       f2lud_set_line_width(job, drw, obj);
2950       f2lud_set_line_dash(job, drw, obj);
2951       f2lud_set_line_end(job, drw, obj, obj->cs);
2952       f2lud_set_line_join(job, drw, obj, obj->js);
2953       f2lud_newpath(job, drw, obj);
2954       f2lud_create_path(job, drw, obj, primary, ec);
2955       f2lud_closepath(job, drw, obj);
2956       f2lud_fill_stroke(job, drw, obj);
2957     } break;
2958     case FIG2LAT_DRIVER_TEX_FULL_PDF:
2959     case FIG2LAT_DRIVER_PDF_WITH_TEX:
2960     {
2961       f2lud_set_color_2(job, drw, obj->fc, obj->fi);
2962       f2lud_set_color_1(job, drw, obj->pc, 20);
2963       f2lud_set_line_width(job, drw, obj);
2964       f2lud_set_line_dash(job, drw, obj);
2965       f2lud_set_line_end(job, drw, obj, obj->cs);
2966       f2lud_set_line_join(job, drw, obj, obj->js);
2967       f2lud_newpath(job, drw, obj);
2968       f2lud_create_path(job, drw, obj, primary, ec);
2969       f2lud_closepath(job, drw, obj);
2970       f2lud_fill(job, drw, obj);
2971       f2lud_newpath(job, drw, obj);
2972       f2lud_create_path(job, drw, obj, primary, ec);
2973       f2lud_closepath(job, drw, obj);
2974       f2lud_stroke(job, drw, obj);
2975     } break;
2976     default: {
2977       f2lud_set_line_width(job, drw, obj);
2978       f2lud_set_line_dash(job, drw, obj);
2979       f2lud_set_line_end(job, drw, obj, obj->cs);
2980       f2lud_set_line_join(job, drw, obj, obj->js);
2981       f2lud_set_color_1(job, drw, obj->fc, obj->fi);
2982       f2lud_newpath(job, drw, obj);
2983       f2lud_create_path(job, drw, obj, primary, ec);
2984       f2lud_closepath(job, drw, obj);
2985       f2lud_fill(job, drw, obj);
2986       f2lud_set_color_1(job, drw, obj->pc, obj->fi);
2987       f2lud_newpath(job, drw, obj);
2988       f2lud_create_path(job, drw, obj, primary, ec);
2989       f2lud_closepath(job, drw, obj);
2990       f2lud_stroke(job, drw, obj);
2991     } break;
2992   }
2993 }
2994 
2995 
2996 
2997 /**	Draw operations for object: pattern.
2998 	@param	job	Job structure.
2999 	@param	drw	Drawing structure.
3000 	@param	obj	Current object to process.
3001 	@param	ec	Pointe to error code variable, may be NULL.
3002 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
3003 */
3004 static
3005 void
f2lud_path_pattern(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)3006 f2lud_path_pattern(
3007   f2l_job_t		*job,
3008   dk3_fig_drawing_t	*drw,
3009   dk3_fig_obj_t		*obj,
3010   int			 primary,
3011   int			*ec
3012 )
3013 {
3014 
3015   f2lud_set_pattern_line_style(job, drw, obj);
3016   f2lud_set_color_1(job, drw, obj->pc, 20);
3017   f2lud_gsave(job, drw, obj);
3018   f2lud_newpath(job, drw, obj);
3019   f2lud_create_path(job, drw, obj, primary, ec);
3020   f2lud_closepath(job, drw, obj);
3021   f2lud_clip(job, drw, obj);
3022   f2lud_pattern(job, drw, obj, ec);
3023   f2lud_grestore(job, drw, obj);
3024 
3025 }
3026 
3027 
3028 
3029 /**	Draw operations for object: pattern and stroke.
3030 	@param	job	Job structure.
3031 	@param	drw	Drawing structure.
3032 	@param	obj	Current object to process.
3033 	@param	ec	Pointe to error code variable, may be NULL.
3034 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
3035 */
3036 static
3037 void
f2lud_path_pattern_stroke(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)3038 f2lud_path_pattern_stroke(
3039   f2l_job_t		*job,
3040   dk3_fig_drawing_t	*drw,
3041   dk3_fig_obj_t		*obj,
3042   int			 primary,
3043   int			*ec
3044 )
3045 {
3046 
3047   f2lud_set_color_1(job, drw, obj->pc, 20);
3048   f2lud_set_pattern_line_style(job, drw, obj);
3049   f2lud_gsave(job, drw, obj);
3050   f2lud_newpath(job, drw, obj);
3051   f2lud_create_path(job, drw, obj, primary, ec);
3052   f2lud_closepath(job, drw, obj);
3053   f2lud_clip(job, drw, obj);
3054   f2lud_pattern(job, drw, obj, ec);
3055   f2lud_grestore(job, drw, obj);
3056   f2lud_set_line_width(job, drw, obj);
3057   f2lud_set_line_dash(job, drw, obj);
3058   f2lud_set_line_end(job, drw, obj, obj->cs);
3059   f2lud_set_line_join(job, drw, obj, obj->js);
3060   f2lud_newpath(job, drw, obj);
3061   f2lud_create_path(job, drw, obj, primary, ec);
3062   f2lud_closepath(job, drw, obj);
3063   f2lud_stroke(job, drw, obj);
3064 
3065 }
3066 
3067 
3068 
3069 /**	Draw operations for object: fill and pattern.
3070 	@param	job	Job structure.
3071 	@param	drw	Drawing structure.
3072 	@param	obj	Current object to process.
3073 	@param	ec	Pointe to error code variable, may be NULL.
3074 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
3075 */
3076 static
3077 void
f2lud_path_fill_pattern(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)3078 f2lud_path_fill_pattern(
3079   f2l_job_t		*job,
3080   dk3_fig_drawing_t	*drw,
3081   dk3_fig_obj_t		*obj,
3082   int			 primary,
3083   int			*ec
3084 )
3085 {
3086 
3087   switch(job->dr) {
3088     case FIG2LAT_DRIVER_PGF:
3089     case FIG2LAT_DRIVER_TEX_FULL_PGF:
3090     {
3091       f2lud_set_color_2(job, drw, obj->fc, obj->fi);
3092       f2lud_set_color_1(job, drw, obj->pc, 20);
3093       f2lud_set_pattern_line_style(job, drw, obj);
3094       f2lud_gsave(job, drw, obj);
3095       f2lud_newpath(job, drw, obj);
3096       f2lud_create_path(job, drw, obj, primary, ec);
3097       f2lud_closepath(job, drw, obj);
3098       f2lud_fill_clip(job, drw, obj);
3099       f2lud_pattern(job, drw, obj, ec);
3100       f2lud_grestore(job, drw, obj);
3101     } break;
3102     default: {
3103       switch(job->dr) {
3104         case FIG2LAT_DRIVER_TEX_FULL_PDF:
3105         case FIG2LAT_DRIVER_PDF_WITH_TEX:
3106         {
3107           f2lud_set_color_2(job, drw, obj->fc, obj->fi);
3108           f2lud_set_color_1(job, drw, obj->pc, 20);
3109 	  f2lud_set_pattern_line_style(job, drw, obj);
3110           f2lud_newpath(job, drw, obj);
3111           f2lud_create_path(job, drw, obj, primary, ec);
3112 	  f2lud_closepath(job, drw, obj);
3113           f2lud_fill(job, drw, obj);
3114           f2lud_gsave(job, drw, obj);
3115           f2lud_newpath(job, drw, obj);
3116           f2lud_create_path(job, drw, obj, primary, ec);
3117           f2lud_closepath(job, drw, obj);
3118           f2lud_clip(job, drw, obj);
3119           f2lud_pattern(job, drw, obj, ec);
3120           f2lud_grestore(job, drw, obj);
3121         } break;
3122         default: {
3123 	  f2lud_set_color_1(job, drw, obj->fc, obj->fi);
3124 	  f2lud_set_pattern_line_style(job, drw, obj);
3125           f2lud_newpath(job, drw, obj);
3126           f2lud_create_path(job, drw, obj, primary, ec);
3127 	  f2lud_closepath(job, drw, obj);
3128           f2lud_fill(job, drw, obj);
3129           f2lud_set_color_1(job, drw, obj->pc, 20);
3130           f2lud_gsave(job, drw, obj);
3131           f2lud_newpath(job, drw, obj);
3132           f2lud_create_path(job, drw, obj, primary, ec);
3133           f2lud_closepath(job, drw, obj);
3134           f2lud_clip(job, drw, obj);
3135           f2lud_pattern(job, drw, obj, ec);
3136           f2lud_grestore(job, drw, obj);
3137         } break;
3138       }
3139     } break;
3140   }
3141 }
3142 
3143 
3144 
3145 /**	Check whether on object line style and line width
3146 	matches style and width configured in a dk3_graphics_state_t.
3147 	@param	gs	dk3_graphics_state_t to test.
3148 	@param	ct2d	Coordinates transformation data.
3149 	@param	drw	Drawing containing the Fig object.
3150 	@param	obj	Fig object.
3151 	@return	1 for equal line width and style, 0 otherwise.
3152 */
3153 static
3154 int
f2lud_style_equal(dk3_graphics_state_t * gs,dk3_ct_2d_t * ct2d,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)3155 f2lud_style_equal(
3156   dk3_graphics_state_t	*gs,
3157   dk3_ct_2d_t		*ct2d,
3158   dk3_fig_drawing_t	*drw,
3159   dk3_fig_obj_t		*obj
3160 )
3161 {
3162   double	 lw;		/* Line width in Fig space. */
3163   int		 back	= 0;
3164   int		 ec	= 0;	/* Error code variable. */
3165 #if 0
3166   if((gs->hlw) && (gs->hls) && (gs->hlc) && (gs->hlj)) {
3167     if((gs->ls = obj->ls) && (gs->lc == obj->cs) && (gs->lj == obj->js)) {
3168       lw = dk3fig_tool_get_lw(drw, obj, &ec);
3169       if(1.0e-6 > fabs(dk3ma_d_sub_ok(gs->lw, lw, &ec))) {
3170         if(0 == ec) {
3171 	  if(DK3_FIG_LS_SOLID == obj->ls) {
3172 	    back = 1;
3173 	  } else {
3174 	    sv = 0.9 * obj->sv;
3175 	    if(1.0e-6 > fabs(dk3ma_d_sub_ok(gs->sv, sv, &ec))) {
3176 	      if(0 == ec) {
3177 	        back = 1;
3178 	      }
3179 	    }
3180 	  }
3181 	}
3182       }
3183     }
3184   }
3185 #else
3186   /*	2012/11/15 As this operation is applied to closed path objects
3187   	only, there is no need to check line ends.
3188 	As fill patterns are drawn as solid lines, we only have
3189 	to check the object line style, whether it is solid.
3190 	For solid lines the style value is ignored.
3191   */
3192   if((gs->hlw) && (gs->hls) && (gs->hlj)) {
3193     if(DK3_FIG_LS_SOLID == obj->ls) {
3194       if(gs->lj == obj->js) {
3195         lw = dk3fig_tool_get_lw(drw, obj, &ec);
3196 	lw = dk3ct_2d_r(ct2d, lw, &ec);
3197 	if(1.0e-6 > fabs(dk3ma_d_sub_ok(gs->lw, lw, &ec))) {
3198 	  if(0 == ec) {
3199 	    back = 1;
3200 	  }
3201 	}
3202       }
3203     }
3204   }
3205 #endif
3206   return back;
3207 }
3208 
3209 
3210 
3211 /**	Draw operations for object: fill, pattern and stroke.
3212 	@param	job	Job structure.
3213 	@param	drw	Drawing structure.
3214 	@param	obj	Current object to process.
3215 	@param	ec	Pointe to error code variable, may be NULL.
3216 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
3217 */
3218 static
3219 void
f2lud_path_fill_pattern_stroke(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary,int * ec)3220 f2lud_path_fill_pattern_stroke(
3221   f2l_job_t		*job,
3222   dk3_fig_drawing_t	*drw,
3223   dk3_fig_obj_t		*obj,
3224   int			 primary,
3225   int			*ec
3226 )
3227 {
3228 
3229   switch(job->dr) {
3230     case FIG2LAT_DRIVER_PGF:
3231     case FIG2LAT_DRIVER_TEX_FULL_PGF:
3232     {
3233       f2lud_set_color_2(job, drw, obj->fc, obj->fi);
3234       f2lud_set_color_1(job, drw, obj->pc, 20);
3235       f2lud_set_pattern_line_style(job, drw, obj);
3236       if(f2lud_style_equal(&(job->gs), &(job->ct2d), drw, obj)) {
3237         f2lud_gsave(job, drw, obj);
3238         f2lud_newpath(job, drw, obj);
3239         f2lud_create_path(job, drw, obj, primary, ec);
3240         f2lud_closepath(job, drw, obj);
3241         f2lud_fill_stroke_clip(job, drw, obj);
3242         f2lud_pattern(job, drw, obj, ec);
3243         f2lud_grestore(job, drw, obj);
3244       } else {
3245         f2lud_gsave(job, drw, obj);
3246         f2lud_newpath(job, drw, obj);
3247         f2lud_create_path(job, drw, obj, primary, ec);
3248         f2lud_closepath(job, drw, obj);
3249         f2lud_fill_clip(job, drw, obj);
3250         f2lud_pattern(job, drw, obj, ec);
3251         f2lud_grestore(job, drw, obj);
3252         f2lud_set_line_width(job, drw, obj);
3253         f2lud_set_line_dash(job, drw, obj);
3254         f2lud_set_line_end(job, drw, obj, obj->cs);
3255         f2lud_set_line_join(job, drw, obj, obj->js);
3256         f2lud_newpath(job, drw, obj);
3257         f2lud_create_path(job, drw, obj, primary, ec);
3258         f2lud_closepath(job, drw, obj);
3259         f2lud_stroke(job, drw, obj);
3260       }
3261     } break;
3262     case FIG2LAT_DRIVER_TEX_FULL_PDF:
3263     case FIG2LAT_DRIVER_PDF_WITH_TEX:
3264     {
3265       f2lud_set_color_2(job, drw, obj->fc, obj->fi);
3266       f2lud_set_color_1(job, drw, obj->pc, 20);
3267       f2lud_set_pattern_line_style(job, drw, obj);
3268       f2lud_newpath(job, drw, obj);
3269       f2lud_create_path(job, drw, obj, primary, ec);
3270       f2lud_closepath(job, drw, obj);
3271       f2lud_fill(job, drw, obj);
3272       f2lud_gsave(job, drw, obj);
3273       f2lud_newpath(job, drw, obj);
3274       f2lud_create_path(job, drw, obj, primary, ec);
3275       f2lud_closepath(job, drw, obj);
3276       f2lud_clip(job, drw, obj);
3277       f2lud_pattern(job, drw, obj, ec);
3278       f2lud_grestore(job, drw, obj);
3279       f2lud_set_line_width(job, drw, obj);
3280       f2lud_set_line_dash(job, drw, obj);
3281       f2lud_set_line_end(job, drw, obj, obj->cs);
3282       f2lud_set_line_join(job, drw, obj, obj->js);
3283       f2lud_newpath(job, drw, obj);
3284       f2lud_create_path(job, drw, obj, primary, ec);
3285       f2lud_closepath(job, drw, obj);
3286       f2lud_stroke(job, drw, obj);
3287     } break;
3288     default: {
3289       f2lud_set_color_1(job, drw, obj->fc, obj->fi);
3290       f2lud_set_pattern_line_style(job, drw, obj);
3291       f2lud_newpath(job, drw, obj);
3292       f2lud_create_path(job, drw, obj, primary, ec);
3293       f2lud_closepath(job, drw, obj);
3294       f2lud_fill(job, drw, obj);
3295       f2lud_set_color_1(job, drw, obj->pc, 20);
3296       f2lud_gsave(job, drw, obj);
3297       f2lud_newpath(job, drw, obj);
3298       f2lud_create_path(job, drw, obj, primary, ec);
3299       f2lud_closepath(job, drw, obj);
3300       f2lud_clip(job, drw, obj);
3301       f2lud_pattern(job, drw, obj, ec);
3302       f2lud_grestore(job, drw, obj);
3303       f2lud_set_line_width(job, drw, obj);
3304       f2lud_set_line_dash(job, drw, obj);
3305       f2lud_set_line_end(job, drw, obj, obj->cs);
3306       f2lud_set_line_join(job, drw, obj, obj->js);
3307       f2lud_newpath(job, drw, obj);
3308       f2lud_create_path(job, drw, obj, primary, ec);
3309       f2lud_closepath(job, drw, obj);
3310       f2lud_stroke(job, drw, obj);
3311     } break;
3312   }
3313 }
3314 
3315 
3316 
3317 /**	Process path object.
3318 	@param	job	Job structure.
3319 	@param	drw	Drawing structure.
3320 	@param	obj	Current object to process.
3321 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
3322 */
3323 static
3324 void
f2lud_path_object(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary)3325 f2lud_path_object(
3326   f2l_job_t		*job,
3327   dk3_fig_drawing_t	*drw,
3328   dk3_fig_obj_t		*obj,
3329   int			 primary
3330 )
3331 {
3332   int		drawop;		/* Operations to perform. */
3333   int		ec = 0;		/* Error code variable. */
3334 
3335   drawop = dk3fig_tool_get_operation(drw, obj);
3336   if(obj->cl) {
3337     switch(drawop) {
3338       case DK3_FIG_OP_STROKE: {
3339         f2lud_path_stroke(job, drw, obj, primary, &ec);
3340       } break;
3341       case DK3_FIG_OP_FILL: {
3342         f2lud_path_fill(job, drw, obj, primary, &ec);
3343       } break;
3344       case (DK3_FIG_OP_FILL | DK3_FIG_OP_STROKE): {
3345         f2lud_path_fill_stroke(job, drw, obj, primary, &ec);
3346       } break;
3347       case DK3_FIG_OP_PATTERN: {
3348         f2lud_path_pattern(job, drw, obj, primary, &ec);
3349       } break;
3350       case (DK3_FIG_OP_PATTERN | DK3_FIG_OP_STROKE): {
3351         f2lud_path_pattern_stroke(job, drw, obj, primary, &ec);
3352       } break;
3353       case (DK3_FIG_OP_PATTERN | DK3_FIG_OP_FILL): {
3354         f2lud_path_fill_pattern(job, drw, obj, primary, &ec);
3355       } break;
3356       case (DK3_FIG_OP_PATTERN | DK3_FIG_OP_FILL | DK3_FIG_OP_STROKE): {
3357         f2lud_path_fill_pattern_stroke(job, drw, obj, primary, &ec);
3358       } break;
3359     }
3360   } else {
3361     if(DK3_FIG_OP_STROKE & drawop) {
3362       f2lud_path_stroke(job, drw, obj, primary, &ec);
3363     }
3364   }
3365   if(ec) {
3366     /* ERROR: Math error in object! */
3367     dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 38);
3368     f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_MATH);
3369   }
3370 }
3371 
3372 
3373 
3374 /**	Process one object.
3375 	@param	job	Job structure.
3376 	@param	drw	Drawing structure.
3377 	@param	obj	Current object to process.
3378 	@param	primary	Flag: primary (1=primary object, 0=arrowhead).
3379 */
3380 static
3381 void
f2lud_process_one(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,int primary)3382 f2lud_process_one(
3383   f2l_job_t		*job,
3384   dk3_fig_drawing_t	*drw,
3385   dk3_fig_obj_t		*obj,
3386   int			 primary
3387 )
3388 {
3389   char		debbuf[256];	/* Buffer for debug messages. */
3390 
3391   if(job->debug) {
3392     sprintf(debbuf, f2lud_c8_kw[6], obj->ot, obj->st);
3393     f2lud_debug(job, debbuf);
3394   }
3395   switch(obj->ot) {
3396     case DK3_FIG_OBJ_TEXT: {
3397       f2lud_text_object(job, drw, obj);
3398     } break;
3399     case DK3_FIG_OBJ_ELLIPSE:
3400     case DK3_FIG_OBJ_SPLINE:
3401     case DK3_FIG_OBJ_ARC:
3402     case DK3_FIG_OBJ_PSEUDO_HALF_CIRCLE:
3403     case DK3_FIG_OBJ_PSEUDO_FAST_SPLINE:
3404     {
3405       f2lud_path_object(job, drw, obj, primary);
3406     } break;
3407     case DK3_FIG_OBJ_POLYLINE: {
3408       switch(obj->st) {
3409         case 5: {
3410 	  f2lud_image_object(job, drw, obj);
3411 	} break;
3412 	default: {
3413 	  f2lud_path_object(job, drw, obj, primary);
3414 	} break;
3415       }
3416     } break;
3417   }
3418   if(job->debug) {
3419     f2lud_debug(job, f2lud_c8_kw[7]);
3420   }
3421 }
3422 
3423 
3424 
3425 int
f2lud_is_interpolated_spline(dk3_fig_obj_t * obj)3426 f2lud_is_interpolated_spline(dk3_fig_obj_t *obj)
3427 {
3428   dk3_fig_spline_point_t	*po;	/* Points to test */
3429   size_t			 np;	/* Number of points */
3430   size_t			 i;	/* Traverse all points */
3431   int				 back = 1;
3432 
3433   po = (obj->dt).spl.po;
3434   np = (obj->dt).spl.np;
3435   for (i = 0; ((i < np) && (1 == back)); i++) {
3436 
3437     if (fabs(po->s) > 1.0e-6) {
3438       if (fabs(1.0 + po->s) > 1.0e-6) {
3439         back = 0;
3440       }
3441     }
3442     po++;
3443   }
3444   return back;
3445 }
3446 
3447 
3448 
3449 /**	Process one arrowhead object.
3450 	@param	job	Job structure.
3451 	@param	drw	Drawing structure.
3452 	@param	obj	Current object to process.
3453 */
3454 static
3455 void
f2lud_process_ah_one(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj)3456 f2lud_process_ah_one(
3457   f2l_job_t		*job,
3458   dk3_fig_drawing_t	*drw,
3459   dk3_fig_obj_t		*obj
3460 )
3461 {
3462   switch (obj->ot) {
3463     case DK3_FIG_OBJ_SPLINE: {
3464       if ((!(job->xsah)) && (f2lud_is_interpolated_spline(obj))) {
3465         obj->ot = DK3_FIG_OBJ_PSEUDO_FAST_SPLINE;
3466         f2lud_process_one(job, drw, obj, 0);
3467         obj->ot = DK3_FIG_OBJ_SPLINE;
3468       } else {
3469         f2lud_process_one(job, drw, obj, 0);
3470       }
3471     } break;
3472     default: {
3473       f2lud_process_one(job, drw, obj, 0);
3474     } break;
3475   }
3476 }
3477 
3478 
3479 
3480 /**	Process object and arrowheads.
3481 	@param	job	Job structure.
3482 	@param	drw	Drawing structure.
3483 	@param	obj	Current object to process.
3484 	@param	objno	Number of current object.
3485 */
3486 static
3487 void
f2lud_process_object(f2l_job_t * job,dk3_fig_drawing_t * drw,dk3_fig_obj_t * obj,unsigned long objno)3488 f2lud_process_object(
3489   f2l_job_t		*job,
3490   dk3_fig_drawing_t	*drw,
3491   dk3_fig_obj_t		*obj,
3492   unsigned long		 objno
3493 )
3494 {
3495   char		debbuf[256];	/* Buffer for debug messages. */
3496 
3497   /*
3498   	Process object itself.
3499   */
3500 
3501   if(job->debug) {
3502     sprintf(debbuf, f2lud_c8_kw[0], objno, obj->li, obj->ot, obj->st, obj->la);
3503     f2lud_debug(job, debbuf);
3504   }
3505   f2lud_process_one(job, drw, obj, 1);
3506 
3507   /*
3508   	For primary objects process the arrowheads.
3509   */
3510   if(obj->af) {
3511 
3512     if(job->debug) {
3513       sprintf(
3514         debbuf, f2lud_c8_kw[2],
3515 	(obj->af)->as,
3516 	(obj->af)->af,
3517 	(obj->af)->he,
3518 	(obj->af)->wi
3519       );
3520       f2lud_debug(job, debbuf);
3521     }
3522     if((obj->af)->o1) {
3523 #if VERSION_BEFORE_20140329
3524       f2lud_process_one(job,drw,(dk3_fig_obj_t *)((obj->af)->o1),0);
3525 #else
3526       f2lud_process_ah_one(job, drw, (dk3_fig_obj_t *)((obj->af)->o1));
3527 #endif
3528     }
3529     if((obj->af)->o2) {
3530 #if VERSION_BEFORE_20140329
3531       f2lud_process_one(job,drw,(dk3_fig_obj_t *)((obj->af)->o2),0);
3532 #else
3533       f2lud_process_ah_one(job, drw, (dk3_fig_obj_t *)((obj->af)->o2));
3534 #endif
3535     }
3536     if(job->debug) {
3537       f2lud_debug(job, f2lud_c8_kw[3]);
3538     }
3539 
3540   }
3541   if(obj->ab) {
3542 
3543     if(job->debug) {
3544       sprintf(
3545         debbuf, f2lud_c8_kw[4],
3546 	(obj->ab)->as,
3547 	(obj->ab)->af,
3548 	(obj->ab)->he,
3549 	(obj->ab)->wi
3550       );
3551       f2lud_debug(job, debbuf);
3552     }
3553     if((obj->ab)->o1) {
3554 #if VERSION_BEFORE_20140329
3555       f2lud_process_one(job,drw,(dk3_fig_obj_t *)((obj->ab)->o1),0);
3556 #else
3557       f2lud_process_ah_one(job, drw, (dk3_fig_obj_t *)((obj->ab)->o1));
3558 #endif
3559     }
3560     if((obj->ab)->o2) {
3561 #if VERSION_BEFORE_20140329
3562       f2lud_process_one(job,drw,(dk3_fig_obj_t *)((obj->ab)->o2),0);
3563 #else
3564       f2lud_process_ah_one(job, drw, (dk3_fig_obj_t *)((obj->ab)->o2));
3565 #endif
3566     }
3567     if(job->debug) {
3568       f2lud_debug(job, f2lud_c8_kw[5]);
3569     }
3570 
3571   }
3572   if(job->debug) {
3573     sprintf(debbuf, f2lud_c8_kw[1], objno);
3574     f2lud_debug(job, debbuf);
3575   }
3576 
3577 }
3578 
3579 
3580 
3581 void
f2lud_output(f2l_job_t * job)3582 f2lud_output(f2l_job_t *job)
3583 {
3584   dk3_fig_obj_t		*obj;	/* Current object to process. */
3585   dk3_fig_drawing_t	*drw;	/* Drawing to process. */
3586   unsigned long		 objno;	/* Current object number. */
3587 
3588   drw = job->drw;
3589   objno = 0UL;
3590   if(f2lud_driver_initialize(job, drw)) {
3591     if(f2lud_open_output_files(job)) {
3592       if(f2lud_start_processing(job, drw)) {
3593 	dk3sto_it_reset(drw->iobj);
3594 	while(NULL != (obj = (dk3_fig_obj_t *)dk3sto_it_next(drw->iobj))) {
3595 	  if(!dk3fig_tool_is_bgrect(obj, objno)) {
3596 	    f2lud_process_object(job, drw, obj, objno);
3597 	  }
3598 	  objno++;
3599 	}
3600       } else {
3601         f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN);
3602       }
3603       f2lud_end_processing(job, drw);
3604     } else {
3605       f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN);
3606     }
3607     f2lud_close_output_files(job);
3608   } else {
3609     f2l_tool_set_exit_status(job, FIG2LAT_EXIT_ERROR_UNKNOWN);
3610   }
3611   f2lud_driver_end(job, drw);
3612 }
3613 
3614