1 /*
2 Copyright (C) 2018-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: wxd2lout.ctr
12 */
13
14 /** @file wxd2lout.c The wxd2lout module.
15 */
16
17
18 #ifndef WXD2LAT_H_INCLUDED
19 #include <wxd2lat/wxd2lat.h>
20 #endif
21
22
23
24
25
26
27
28 static const dkChar *kwnl[] = {
29 /* 0 */
30 dkT(".tex"),
31
32 NULL
33
34 };
35
36
37
38 double
wxd2lout_convert_x(wxd_drawing_t * drw,wxd2lat_job_t * job,double x)39 wxd2lout_convert_x(wxd_drawing_t *drw, wxd2lat_job_t *job, double x)
40 {
41 #if TRACE_DEBUG
42 double back;
43
44 back = ((9.0 * (x - drw->bbxl)) / 2032000.0) + job->shiftx;
45
46 return back;
47 #else
48 return (((9.0 * (x - drw->bbxl)) / 2032000.0) + job->shiftx);
49 #endif
50 }
51
52
53
54 double
wxd2lout_convert_y(wxd_drawing_t * drw,wxd2lat_job_t * job,double y)55 wxd2lout_convert_y(wxd_drawing_t *drw, wxd2lat_job_t *job, double y)
56 {
57 #if TRACE_DEBUG
58 double back;
59
60 back = ((9.0 * (y - drw->bbyb)) / 2032000.0) + job->shifty;
61
62 return back;
63 #else
64 return (((9.0 * (y - drw->bbyb)) / 2032000.0) + job->shifty);
65 #endif
66 }
67
68
69
70 /** Convert distance value from WXD coordinates to bp.
71 @param r Distance to convert
72 @return Conversion result.
73 */
74 double
wxd2lout_convert_r(double r)75 wxd2lout_convert_r(double r)
76 {
77 #if TRACE_DEBUG
78 double back;
79
80 back = ((9.0 * r) / 2032000.0);
81
82 return back;
83 #else
84 return ((9.0 * r) / 2032000.0);
85 #endif
86 }
87
88
89
90
91 /** Prepare job structure, calculate coordinates transformations
92 and create output file name.
93 @param drw Drawing to convert.
94 @param job Job structure.
95 @param fn File name.
96 @return 1 on success (output possible), 0 on error.
97 */
98 static
99 int
wxd2lout_prepare_job(wxd_drawing_t * drw,wxd2lat_job_t * job,const dkChar * fn)100 wxd2lout_prepare_job(wxd_drawing_t *drw, wxd2lat_job_t *job, const dkChar *fn)
101 {
102 dkChar *ptr;
103 double dwidth;
104 double dheight;
105 double cwidth;
106 double cheight;
107 int back = 1;
108
109 dwidth = (9.0 * (drw->bbxr - drw->bbxl)) / 2032000.0;
110 dheight = (9.0 * (drw->bbyt - drw->bbyb)) / 2032000.0;
111 cwidth = ceil(dwidth);
112 cheight = ceil(dheight);
113 if (cwidth > dwidth) {
114 job->shiftx = (cwidth - dwidth) / 2.0;
115
116 }
117 if (cheight > dheight) {
118 job->shifty = (cheight - dheight) / 2.0;
119
120 }
121 if ((0 == dk4ma_is_finite(dwidth)) || (0 == dk4ma_is_finite(cwidth))) {
122 back = 0;
123 /* ERROR: Numeric overflow in width calculation */
124 dk4app_log_1(
125 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 36
126 );
127 }
128 if ((0 == dk4ma_is_finite(dheight)) || (0 == dk4ma_is_finite(cheight))) {
129 back = 0;
130 /* ERROR: Numeric overflow in height calculation */
131 dk4app_log_1(
132 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 36
133 );
134 }
135 if ((double)(SIZE_MAX) < cwidth) {
136 back = 0;
137 /* ERROR: Numeric overflow in width calculation */
138 dk4app_log_1(
139 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 36
140 );
141 }
142 else {
143 job->szwidth = (size_t)cwidth;
144
145 }
146 if ((double)(SIZE_MAX) < cheight) {
147 back = 0;
148 /* ERROR: Numeric overflow in height calculation */
149 dk4app_log_1(
150 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 36
151 );
152 }
153 else {
154 job->szheight = (size_t)cheight;
155
156 }
157 if (0 != dk4str_cpy_s(job->fno1, job->szfnb, fn, NULL)) {
158 ptr = dk4path_get_suffix(job->fno1, NULL);
159 if (NULL != ptr) { *ptr = dkT('\0'); }
160 if (0 == dk4str_cat_s(job->fno1, job->szfnb, kwnl[0], NULL)) {
161 back = 0;
162 /* ERROR: File name too long */
163 dk4app_log_1(
164 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 37
165 );
166 }
167 }
168 else {
169 /* ERROR: File name too long */
170 dk4app_log_1(
171 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 37
172 );
173 back = 0;
174 }
175
176 return back;
177 }
178
179
180
181 /** Set clip region to used coordinates ranges.
182 @param drw Drawing to convert.
183 @param job Job structure.
184 @return 1 on success, 0 on error.
185 */
186 static
187 int
wxd2lout_clip_to_used_region(wxd2lat_job_t * job)188 wxd2lout_clip_to_used_region(wxd2lat_job_t *job)
189 {
190 dk4_er_t er;
191 int back = 1;
192 double xl;
193 double xr;
194 double yb;
195 double yt;
196
197 if ((0.0 < job->shiftx) || (0.0 < job->shifty)) {
198 xl = job->shiftx;
199 if (0.0 > xl) { xl = 0.0; }
200 xr = (double)(job->szwidth) - job->shiftx;
201 yb = job->shifty;
202 if (0.0 > yb) { yb = 0.0; }
203 yt = (double)(job->szheight) - job->shifty;
204 dk4error_init(&er);
205 dk4pppt_newpath_moveto(job->ppp, xl, yb, NULL, &back, &er);
206 dk4pppt_lineto(job->ppp, xr, yb, NULL, &back, &er);
207 dk4pppt_lineto(job->ppp, xr, yt, NULL, &back, &er);
208 dk4pppt_lineto(job->ppp, xl, yt, NULL, &back, &er);
209 dk4pppt_lineto(job->ppp, xl, yb, NULL, &back, &er);
210 dk4pppt_closepath(job->ppp, &back, &er);
211 dk4pppt_clip(job->ppp, &back, &er);
212 if (0 == back) {
213 /* ERROR: Failed to clip region */
214 dk4app_log_1(
215 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 38
216 );
217 }
218 }
219
220 return back;
221 }
222
223
224
225 /** Set stroke RGB colour.
226 @param job Job structure.
227 @param pobj Current object.
228 @param backptr Address of success variable to reset on errors.
229 @param erp Error report, may be NULL.
230 @return 1 on success, 0 on error.
231 */
232 static
233 void
wxd2lout_stroke_rgb(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_er_t * erp)234 wxd2lout_stroke_rgb(
235 wxd2lat_job_t *job,
236 wxd_object_t *pobj,
237 int *backptr,
238 dk4_er_t *erp
239 )
240 {
241
242 dk4pppt_set_stroke_rgb(
243 job->ppp,
244 (((double)(pobj->sc[0])) / 255.0),
245 (((double)(pobj->sc[1])) / 255.0),
246 (((double)(pobj->sc[2])) / 255.0),
247 backptr, erp
248 );
249
250
251 }
252
253
254
255 /** Set stroke line width.
256 @param drw Drawing structure.
257 @param job Job structure.
258 @param pobj Current object.
259 @param backptr Address of success variable to reset on errors.
260 @param erp Error report, may be NULL.
261 @return 1 on success, 0 on error.
262 */
263 static
264 void
wxd2lout_line_width(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_er_t * erp)265 wxd2lout_line_width(
266 wxd_drawing_t *drw,
267 wxd2lat_job_t *job,
268 wxd_object_t *pobj,
269 int *backptr,
270 dk4_er_t *erp
271 )
272 {
273
274 dk4pppt_set_line_width(
275 job->ppp, wxd2lat_object_linewidth(pobj, drw, job),
276 backptr, erp
277 );
278
279
280 }
281
282
283
284 /** Set stroke line style.
285 @param drw Drawing structure.
286 @param job Job structure.
287 @param pobj Current object.
288 @param backptr Address of success variable to reset on errors.
289 @param erp Error report, may be NULL.
290 @return 1 on success, 0 on error.
291 */
292 static
293 void
wxd2lout_line_style(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_er_t * erp)294 wxd2lout_line_style(
295 wxd_drawing_t *drw,
296 wxd2lat_job_t *job,
297 wxd_object_t *pobj,
298 int *backptr,
299 dk4_er_t *erp
300 )
301 {
302 double sv;
303 dk4_gra_ls_t ls = DK4_GRA_LS_SOLID;
304
305 switch (pobj->ls) {
306 case WXD_LS_SOLID : {
307 ls = DK4_GRA_LS_SOLID;
308 } break;
309 case WXD_LS_DASH : {
310 ls = DK4_GRA_LS_DASH;
311 } break;
312 case WXD_LS_DOT : {
313 ls = DK4_GRA_LS_DOT;
314 } break;
315 case WXD_LS_DASH_DOT : {
316 ls = DK4_GRA_LS_DASH_DOT;
317 } break;
318 case WXD_LS_DASH_DOT_DOT : {
319 ls = DK4_GRA_LS_DASH_DOT_DOT;
320 } break;
321 case WXD_LS_DASH_DOT_DOT_DOT : {
322 ls = DK4_GRA_LS_DASH_DOT_DOT_DOT;
323 } break;
324 }
325 sv = (double)(pobj->sl) * wxd2lat_object_linewidth(pobj, drw, job);
326 dk4pppt_set_line_style(job->ppp, ls, sv, backptr, erp);
327
328
329 }
330
331
332
333 /** Set stroke line cap.
334 @param job Job structure.
335 @param pobj Current object.
336 @param backptr Address of success variable to reset on errors.
337 @param erp Error report, may be NULL.
338 @return 1 on success, 0 on error.
339 */
340 static
341 void
wxd2lout_line_cap(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_er_t * erp)342 wxd2lout_line_cap(
343 wxd2lat_job_t *job,
344 wxd_object_t *pobj,
345 int *backptr,
346 dk4_er_t *erp
347 )
348 {
349 dk4_gra_lc_t lc = DK4_GRA_LC_BUTTED;
350
351 switch (pobj->csfs) {
352 case WXD_LC_BUTTED : {
353 lc = DK4_GRA_LC_BUTTED;
354 } break;
355 case WXD_LC_ROUNDED : {
356 lc = DK4_GRA_LC_ROUNDED;
357 } break;
358 case WXD_LC_PROJECTING : {
359 lc = DK4_GRA_LC_PROJECTING;
360 } break;
361 }
362 dk4pppt_set_line_cap(job->ppp, lc, backptr, erp);
363
364
365 }
366
367
368
369 /** Set stroke line join.
370 @param job Job structure.
371 @param pobj Current object.
372 @param backptr Address of success variable to reset on errors.
373 @param erp Error report, may be NULL.
374 @return 1 on success, 0 on error.
375 */
376 static
377 void
wxd2lout_line_join(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_er_t * erp)378 wxd2lout_line_join(
379 wxd2lat_job_t *job,
380 wxd_object_t *pobj,
381 int *backptr,
382 dk4_er_t *erp
383 )
384 {
385 dk4_gra_lj_t lj = DK4_GRA_LJ_MITERED;
386
387 switch ( (int)(pobj->ot) ) {
388 case WXD_OT_O_ARC : case WXD_OT_C_ARC :
389 case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : {
390 lj = DK4_GRA_LJ_ROUNDED;
391 } break;
392 default : {
393 switch (pobj->js) {
394 case WXD_LJ_MITERED : {
395 lj = DK4_GRA_LJ_MITERED;
396 } break;
397 case WXD_LJ_ROUNDED : {
398 lj = DK4_GRA_LJ_ROUNDED;
399 } break;
400 case WXD_LJ_BEVELED : {
401 lj = DK4_GRA_LJ_BEVELED;
402 } break;
403 }
404 } break;
405 }
406
407
408
409 if ((uint8_t)0U == pobj->ml) { pobj->ml = (uint8_t)1U; }
410 dk4pppt_set_line_join(job->ppp, lj, (double)(pobj->ml), backptr, erp);
411
412
413 }
414
415
416
417 /** Set fill RGB colour.
418 @param job Job structure.
419 @param pobj Current object.
420 @param backptr Address of success variable to reset on errors.
421 @param erp Error report, may be NULL.
422 @return 1 on success, 0 on error.
423 */
424 static
425 void
wxd2lout_fill_rgb(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_er_t * erp)426 wxd2lout_fill_rgb(
427 wxd2lat_job_t *job,
428 wxd_object_t *pobj,
429 int *backptr,
430 dk4_er_t *erp
431 )
432 {
433
434
435
436
437
438
439
440
441
442 dk4pppt_set_fill_rgb(
443 job->ppp,
444 (((double)(pobj->fc[0])) / 255.0),
445 (((double)(pobj->fc[1])) / 255.0),
446 (((double)(pobj->fc[2])) / 255.0),
447 backptr, erp
448 );
449
450
451 }
452
453
454
455 /** Set fill attributes.
456 @param job Job structure.
457 @param pobj Current object.
458 @param backptr Address of success variable to reset on errors.
459 @param erp Error report, may be NULL.
460 @return 1 on success, 0 on error.
461 */
462 static
463 void
wxd2lout_attributes_fill(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_er_t * erp)464 wxd2lout_attributes_fill(
465 wxd2lat_job_t *job,
466 wxd_object_t *pobj,
467 int *backptr,
468 dk4_er_t *erp
469 )
470 {
471 /* Fill colour
472 */
473
474 wxd2lout_fill_rgb(job, pobj, backptr, erp);
475
476
477 }
478
479
480
481 /** Return pattern for object.
482 @param pobj Object to pattern.
483 @return Pattern number as dk4_gra_pattern_t.
484 */
485 static
486 dk4_gra_pattern_t
wxd2lout_find_pattern(wxd_object_t * pobj)487 wxd2lout_find_pattern(wxd_object_t *pobj)
488 {
489 dk4_gra_pattern_t back = DK4_GRA_PATTERN_30_DEGREE_LEFT;
490
491 switch (pobj->csfs) {
492 case WXD_FS_30_DEGREE_LEFT : {
493 back = DK4_GRA_PATTERN_30_DEGREE_LEFT;
494 } break;
495 case WXD_FS_30_DEGREE_RIGHT : {
496 back = DK4_GRA_PATTERN_30_DEGREE_RIGHT;
497 } break;
498 case WXD_FS_30_DEGREE_SIEVE : {
499 back = DK4_GRA_PATTERN_30_DEGREE_SIEVE;
500 } break;
501 case WXD_FS_45_DEGREE_LEFT : {
502 back = DK4_GRA_PATTERN_45_DEGREE_LEFT;
503 } break;
504 case WXD_FS_45_DEGREE_RIGHT : {
505 back = DK4_GRA_PATTERN_45_DEGREE_RIGHT;
506 } break;
507 case WXD_FS_45_DEGREE_SIEVE : {
508 back = DK4_GRA_PATTERN_45_DEGREE_SIEVE;
509 } break;
510 case WXD_FS_HORIZONTAL_BRICKS : {
511 back = DK4_GRA_PATTERN_HORIZONTAL_BRICKS;
512 } break;
513 case WXD_FS_VERTICAL_BRICKS : {
514 back = DK4_GRA_PATTERN_VERTICAL_BRICKS;
515 } break;
516 case WXD_FS_HORIZONTAL_LINES : {
517 back = DK4_GRA_PATTERN_HORIZONTAL_LINES;
518 } break;
519 case WXD_FS_VERTICAL_LINES : {
520 back = DK4_GRA_PATTERN_VERTICAL_LINES;
521 } break;
522 case WXD_FS_HORIZONTAL_VERTICAL_SIEVE : {
523 back = DK4_GRA_PATTERN_HORIZONTAL_VERTICAL_SIEVE;
524 } break;
525 case WXD_FS_HORIZONTAL_SHINGLES_LEFT : {
526 back = DK4_GRA_PATTERN_HORIZONTAL_SHINGLES_LEFT;
527 } break;
528 case WXD_FS_HORIZONTAL_SHINGLES_RIGHT : {
529 back = DK4_GRA_PATTERN_HORIZONTAL_SHINGLES_RIGHT;
530 } break;
531 case WXD_FS_VERTICAL_SHINGLES_1 : {
532 back = DK4_GRA_PATTERN_VERTICAL_SHINGLES_1;
533 } break;
534 case WXD_FS_VERTICAL_SHINGLES_2 : {
535 back = DK4_GRA_PATTERN_VERTICAL_SHINGLES_2;
536 } break;
537 case WXD_FS_LARGE_FISH_SCALES : {
538 back = DK4_GRA_PATTERN_LARGE_FISH_SCALES;
539 } break;
540 case WXD_FS_SMALL_FISH_SCALES : {
541 back = DK4_GRA_PATTERN_SMALL_FISH_SCALES;
542 } break;
543 case WXD_FS_CIRCLES : {
544 back = DK4_GRA_PATTERN_CIRCLES;
545 } break;
546 case WXD_FS_HEXAGONS : {
547 back = DK4_GRA_PATTERN_HEXAGONS;
548 } break;
549 case WXD_FS_OCTAGONS : {
550 back = DK4_GRA_PATTERN_OCTAGONS;
551 } break;
552 case WXD_FS_HORIZONTAL_TIRES : {
553 back = DK4_GRA_PATTERN_HORIZONTAL_TIRES;
554 } break;
555 case WXD_FS_VERTICAL_TIRES : {
556 back = DK4_GRA_PATTERN_VERTICAL_TIRES;
557 } break;
558
559 }
560
561 return back;
562 }
563
564
565
566 /** Set stroke attributes.
567 @param drw Drawing structure.
568 @param job Job structure.
569 @param pobj Current object.
570 @param backptr Address of success variable to reset on errors.
571 @param use_lc Flag: Also set line cap.
572 @param use_lj Flag: Use join style and miter limit.
573 @param erp Error report, may be NULL.
574 @return 1 on success, 0 on error.
575 */
576 static
577 void
wxd2lout_attributes_stroke(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,int use_lc,dk4_er_t * erp)578 wxd2lout_attributes_stroke(
579 wxd_drawing_t *drw,
580 wxd2lat_job_t *job,
581 wxd_object_t *pobj,
582 int *backptr,
583 int use_lc,
584 dk4_er_t *erp
585 )
586 {
587
588 /* Stroke colour
589 */
590 wxd2lout_stroke_rgb(job, pobj, backptr, erp);
591
592 /*
593 Line width
594 */
595 wxd2lout_line_width(drw, job, pobj, backptr, erp);
596
597 /*
598 Line style and dash length
599 */
600 wxd2lout_line_style(drw, job, pobj, backptr, erp);
601
602 /*
603 Line cap
604 */
605 if (0 != use_lc) {
606 wxd2lout_line_cap(job, pobj, backptr, erp);
607
608 }
609 /*
610 Line join
611 */
612 switch (pobj->ot) {
613 case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE :
614 case WXD_OT_POLYGON : case WXD_OT_C_SPLINE :
615 case WXD_OT_C_ARC: case WXD_OT_BOX : {
616 wxd2lout_line_join(job, pobj, backptr, erp);
617 } break;
618 }
619
620
621 }
622
623
624
625 /** Create polygon or polyline without arrowheads path.
626 @param job Job structure.
627 @param pobj Object to create path for.
628 @param backptr Address of success variable to reset on error.
629 @param pbb Bounding box for path, may be NULL.
630 @param erp Error report, may be NULL.
631 @param iscl Flag: Closed path.
632 */
633 static
634 void
wxd2lout_path_pl_no_arrows(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp,int iscl)635 wxd2lout_path_pl_no_arrows(
636 wxd2lat_job_t *job,
637 wxd_object_t *pobj,
638 int *backptr,
639 dk4_bb_t *pbb,
640 dk4_er_t *erp,
641 int iscl
642 )
643 {
644 uint16_t i;
645
646 dk4pppt_newpath_moveto(
647 job->ppp, ((pobj->det).p.p)[0].x, ((pobj->det).p.p)[0].y,
648 pbb, backptr, erp
649 );
650 for (i = 1; i < (pobj->det).p.n; i++) {
651 dk4pppt_lineto(
652 job->ppp, ((pobj->det).p.p)[i].x, ((pobj->det).p.p)[i].y,
653 pbb, backptr, erp
654 );
655 }
656 if (0 != iscl) {
657 dk4pppt_lineto(
658 job->ppp, ((pobj->det).p.p)[0].x, ((pobj->det).p.p)[0].y,
659 pbb, backptr, erp
660 );
661 dk4pppt_closepath(job->ppp, backptr, erp);
662 }
663
664 }
665
666
667
668 /** Create Bezier segments for one X-spline segment.
669 The X-spline segment is drawn completely, 8 Bezier segments
670 are used per X-spline segment.
671 @param job Job structure.
672 @param xs X-spline structure, control points are set up.
673 @param ib Index of point B (0 for first segment).
674 @param backptr Address of success variable to reset on error.
675 @param pbb Bounding box for path, may be NULL.
676 @param erp Error report, may be NULL.
677 */
678 static
679 void
wxd2lout_path_spline_segment_normal(wxd2lat_job_t * job,dk4_xsp_2d_t * xs,uint16_t ib,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)680 wxd2lout_path_spline_segment_normal(
681 wxd2lat_job_t *job,
682 dk4_xsp_2d_t *xs,
683 uint16_t ib,
684 int *backptr,
685 dk4_bb_t *pbb,
686 dk4_er_t *erp
687 )
688 {
689 double v0[4];
690 double v1[4];
691 double t;
692 double divisor;
693 unsigned i;
694
695 divisor = 3.0 * (double)((job->grco).xsss);
696 if (0 != dk4xsp2d_calculate_value_derivative(v0, xs, 0.0, erp)) {
697 v0[1] = v0[1] / divisor;
698 v0[3] = v0[3] / divisor;
699 if ((uint16_t)0U == ib) {
700 dk4pppt_newpath_moveto(job->ppp, v0[0], v0[2], pbb, backptr, erp);
701 }
702 for (i = 1; i <= (job->grco).xsss; i++) {
703 t = (double)i / (double)((job->grco).xsss);
704 if ((job->grco).xsss == i) { t = 1.0; }
705 if (0 != dk4xsp2d_calculate_value_derivative(v1, xs, t, erp)) {
706 v1[1] = v1[1] / divisor;
707 v1[3] = v1[3] / divisor;
708 dk4pppt_curveto(
709 job->ppp,
710 (v0[0]+v0[1]), (v0[2]+v0[3]),
711 (v1[0]-v1[1]), (v1[2]-v1[3]),
712 v1[0], v1[2],
713 pbb, backptr, erp
714 );
715 DK4_MEMCPY(v0,v1,sizeof(v0));
716 }
717 else {
718 if (NULL != backptr) { *backptr = 0; }
719 /* ERROR: X-spline calculation failed */
720 dk4app_log_1(
721 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 39
722 );
723 }
724 }
725 }
726 else {
727 if (NULL != backptr) { *backptr = 0; }
728 /* ERROR: X-spline calculation failed */
729 dk4app_log_1(
730 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 39
731 );
732 }
733
734 }
735
736
737
738 /** Create spline path for closed spline or open spline without arrowheads.
739 @param job Job structure.
740 @param pobj Object to create path for.
741 @param backptr Address of success variable to reset on error.
742 @param pbb Bounding box for path, may be NULL.
743 @param erp Error report, may be NULL.
744 @param iscl Flag: Closed path.
745 */
746 static
747 void
wxd2lout_path_spline_no_arrows(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp,int iscl)748 wxd2lout_path_spline_no_arrows(
749 wxd2lat_job_t *job,
750 wxd_object_t *pobj,
751 int *backptr,
752 dk4_bb_t *pbb,
753 dk4_er_t *erp,
754 int iscl
755 )
756 {
757 dk4_xsp_2d_t xs; /* X-spline */
758 uint16_t sgn; /* Current segment to process */
759 #if VERSION_BEFORE_20190110
760 uint16_t ia; /* Index of point A */
761 uint16_t id; /* Index of point D */
762 #endif
763 uint16_t ib; /* Index of point B */
764 uint16_t ic; /* Index of point C */
765
766 dk4xsp2d_reset(&xs);
767 for (sgn = 0; sgn < (pobj->det).s.n - 1; sgn++) {
768 ib = sgn;
769 ic = (uint16_t)(ib + 1U);
770 if (
771 (1.0e-8 > fabs(((pobj->det).s.p)[ib].s))
772 && (1.0e-8 > fabs(((pobj->det).s.p)[ic].s))
773 ) {
774 if (0 == sgn) {
775 dk4pppt_newpath_moveto(
776 job->ppp,
777 ((pobj->det).s.p)[ib].x, ((pobj->det).s.p)[ib].y,
778 pbb, backptr, erp
779 );
780 }
781 dk4pppt_lineto(
782 job->ppp,
783 ((pobj->det).s.p)[ic].x, ((pobj->det).s.p)[ic].y,
784 pbb, backptr, erp
785 );
786 }
787 else {
788 #if VERSION_BEFORE_20190110
789 id = ib + (uint16_t)2U;
790 ia = ib - (uint16_t)1U;
791 dk4xsp2d_reset_points(&xs);
792 dk4xsp2d_set_point(
793 &xs,
794 ((pobj->det).s.p)[ib].x, ((pobj->det).s.p)[ib].y,
795 ((pobj->det).s.p)[ib].s, 1
796 );
797 dk4xsp2d_set_point(
798 &xs,
799 ((pobj->det).s.p)[ic].x, ((pobj->det).s.p)[ic].y,
800 ((pobj->det).s.p)[ic].s, 2
801 );
802 if ((uint16_t)0U != ib) {
803 dk4xsp2d_set_point(
804 &xs,
805 ((pobj->det).s.p)[ia].x, ((pobj->det).s.p)[ia].y,
806 ((pobj->det).s.p)[ia].s, 0
807 );
808 }
809 else {
810 if (0 != iscl) {
811 ia = (pobj->det).s.n - (uint16_t)1U;
812 dk4xsp2d_set_point(
813 &xs,
814 ((pobj->det).s.p)[ia].x, ((pobj->det).s.p)[ia].y,
815 ((pobj->det).s.p)[ia].s, 0
816 );
817 }
818 }
819 if (id < (pobj->det).s.n) {
820 dk4xsp2d_set_point(
821 &xs,
822 ((pobj->det).s.p)[id].x, ((pobj->det).s.p)[id].y,
823 ((pobj->det).s.p)[id].s, 3
824 );
825 }
826 else {
827 if (0 != iscl) {
828 id = (uint16_t)0U;
829 dk4xsp2d_set_point(
830 &xs,
831 ((pobj->det).s.p)[id].x, ((pobj->det).s.p)[id].y,
832 ((pobj->det).s.p)[id].s, 3
833 );
834 }
835 }
836 #else
837 wxd2lxs_set_xspline(&xs, pobj, ib);
838 #endif
839 wxd2lout_path_spline_segment_normal(
840 job, &xs, sgn, backptr, pbb, erp
841 );
842 }
843 }
844 if (0 != iscl) {
845 ib = (uint16_t)((pobj->det).s.n - 1U);
846 ic = (uint16_t)0U;
847 if (
848 (1.0e-8 > fabs(((pobj->det).s.p)[ib].s))
849 && (1.0e-8 > fabs(((pobj->det).s.p)[ic].s))
850 ) {
851 dk4pppt_lineto(
852 job->ppp,
853 ((pobj->det).s.p)[ic].x, ((pobj->det).s.p)[ic].y,
854 pbb, backptr, erp
855 );
856 }
857 else {
858 #if VERSION_BEFORE_20190110
859 ia = (pobj->det).s.n - (uint16_t)2U;
860 id = (uint16_t)1U;
861 dk4xsp2d_reset_points(&xs);
862 dk4xsp2d_set_point(
863 &xs,
864 ((pobj->det).s.p)[ia].x, ((pobj->det).s.p)[ia].y,
865 ((pobj->det).s.p)[ia].s, 0
866 );
867 dk4xsp2d_set_point(
868 &xs,
869 ((pobj->det).s.p)[ib].x, ((pobj->det).s.p)[ib].y,
870 ((pobj->det).s.p)[ib].s, 1
871 );
872 dk4xsp2d_set_point(
873 &xs,
874 ((pobj->det).s.p)[ic].x, ((pobj->det).s.p)[ic].y,
875 ((pobj->det).s.p)[ic].s, 2
876 );
877 dk4xsp2d_set_point(
878 &xs,
879 ((pobj->det).s.p)[id].x, ((pobj->det).s.p)[id].y,
880 ((pobj->det).s.p)[id].s, 3
881 );
882 #else
883 wxd2lxs_set_xspline(&xs, pobj, ib);
884 #endif
885 wxd2lout_path_spline_segment_normal(
886 job, &xs, ib, backptr, pbb, erp
887 );
888 }
889 dk4pppt_closepath(job->ppp, backptr, erp);
890 }
891
892 }
893
894
895
896 /** Create arc path for given start and end angle.
897 @param drw Drawing structure.
898 @param job Job structure.
899 @param pobj Object to create path for.
900 @param alpha Start angle in radians.
901 @param beta End angle in radians.
902 @param backptr Address of success variable to reset on error.
903 @param pbb Bounding box for path, may be NULL.
904 @param erp Error report, may be NULL.
905 @param iscl Flag: Closed path.
906 */
907 static
908 void
wxd2lout_path_arc_angles(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj,double alpha,double beta,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp,int iscl)909 wxd2lout_path_arc_angles(
910 wxd_drawing_t *drw,
911 wxd2lat_job_t *job,
912 wxd_object_t *pobj,
913 double alpha,
914 double beta,
915 int *backptr,
916 dk4_bb_t *pbb,
917 dk4_er_t *erp,
918 int iscl
919 )
920 {
921 double v0[4]; /* Start point of current segment */
922 double v1[4]; /* End point of current segment */
923 double angle; /* Complete arc angle */
924 double pos; /* Angle position at end of current segment */
925 double kappa; /* Kappa value */
926 double segan; /* Segment angle */
927 size_t nsegs; /* Number of segments */
928 size_t i; /* Current segment */
929
930 if (0 != (pobj->det).a.d) {
931 /*
932 Real arc.
933 */
934 angle = beta - alpha;
935
936 nsegs = (size_t)ceil(4.0 * fabs(angle) / M_PI);
937 if (1 > nsegs) { nsegs = 1; }
938
939 segan = angle / (double)nsegs;
940
941 kappa = dk4gratool_kappa_for_angle(fabs(segan));
942
943 v0[0] = (pobj->det).a.x + (pobj->det).a.r * cos(alpha);
944 v0[1] = (pobj->det).a.y + (pobj->det).a.r * sin(alpha);
945 v0[2] = -1.0 * kappa * segan * (pobj->det).a.r * sin(alpha);
946 v0[3] = kappa * segan * (pobj->det).a.r * cos(alpha);
947 for (i = 0; i < nsegs; i++) {
948 if (0 == i) {
949 dk4pppt_newpath_moveto(
950 job->ppp, v0[0], v0[1], NULL, backptr, erp
951 );
952 }
953 if (i < (nsegs - 1)) {
954 pos = alpha
955 + ((angle * (double)(i + (size_t)1U)) / (double)nsegs);
956 }
957 else {
958 pos = beta;
959 }
960 v1[0] = (pobj->det).a.x + (pobj->det).a.r * cos(pos);
961 v1[1] = (pobj->det).a.y + (pobj->det).a.r * sin(pos);
962 v1[2] = -1.0 * kappa * segan * (pobj->det).a.r * sin(pos);
963 v1[3] = kappa * segan * (pobj->det).a.r * cos(pos);
964 dk4pppt_curveto(
965 job->ppp,
966 (v0[0] + v0[2]), (v0[1] + v0[3]),
967 (v1[0] - v1[2]), (v1[1] - v1[3]),
968 v1[0], v1[1],
969 pbb, backptr, erp
970 );
971 DK4_MEMCPY(v0,v1,sizeof(v0));
972 }
973 if (0 != iscl) {
974 dk4pppt_lineto(
975 job->ppp, (pobj->det).a.x, (pobj->det).a.y, pbb, backptr, erp
976 );
977 v0[0] = (pobj->det).a.x + (pobj->det).a.r * cos(alpha);
978 v0[1] = (pobj->det).a.y + (pobj->det).a.r * sin(alpha);
979 dk4pppt_lineto(
980 job->ppp, v0[0], v0[1], pbb, backptr, erp
981 );
982 }
983 }
984 else {
985 /* Malformed arc, points either on one line or equal.
986 */
987 dk4pppt_newpath_moveto(
988 job->ppp,
989 wxd2lout_convert_x(drw, job, (double)((pobj->det).a.x1)),
990 wxd2lout_convert_y(drw, job, (double)((pobj->det).a.y1)),
991 NULL, backptr, erp
992 );
993 dk4pppt_lineto(
994 job->ppp,
995 wxd2lout_convert_x(drw, job, (double)((pobj->det).a.x2)),
996 wxd2lout_convert_y(drw, job, (double)((pobj->det).a.y2)),
997 NULL, backptr, erp
998 );
999 dk4pppt_lineto(
1000 job->ppp,
1001 wxd2lout_convert_x(drw, job, (double)((pobj->det).a.x3)),
1002 wxd2lout_convert_y(drw, job, (double)((pobj->det).a.y3)),
1003 NULL, backptr, erp
1004 );
1005 if (0 != iscl) {
1006 dk4pppt_lineto(
1007 job->ppp,
1008 wxd2lout_convert_x(drw, job, (double)((pobj->det).a.x1)),
1009 wxd2lout_convert_y(drw, job, (double)((pobj->det).a.y1)),
1010 NULL, backptr, erp
1011 );
1012 dk4pppt_closepath(job->ppp, backptr, erp);
1013 }
1014 }
1015
1016 }
1017
1018
1019
1020 /** Create arc path for closed arcs or open arcs without arrowheads.
1021 @param drw Drawing structure.
1022 @param job Job structure.
1023 @param pobj Object to create path for.
1024 @param backptr Address of success variable to reset on error.
1025 @param pbb Bounding box for path, may be NULL.
1026 @param erp Error report, may be NULL.
1027 @param iscl Flag: Closed path.
1028 */
1029 static
1030 void
wxd2lout_path_arc_no_arrows(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp,int iscl)1031 wxd2lout_path_arc_no_arrows(
1032 wxd_drawing_t *drw,
1033 wxd2lat_job_t *job,
1034 wxd_object_t *pobj,
1035 int *backptr,
1036 dk4_bb_t *pbb,
1037 dk4_er_t *erp,
1038 int iscl
1039 )
1040 {
1041
1042 wxd2lout_path_arc_angles(
1043 drw, job, pobj, (pobj->det).a.a, (pobj->det).a.b,
1044 backptr, pbb, erp, iscl
1045 );
1046
1047 }
1048
1049
1050
1051 /** Create polyline with arrowheads path.
1052 @param job Job structure.
1053 @param pobj Object to create path for.
1054 @param backptr Address of success variable to reset on error.
1055 @param pbb Bounding box for path, may be NULL.
1056 @param erp Error report, may be NULL.
1057 */
1058 static
1059 void
wxd2lout_path_pl_with_arrows(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)1060 wxd2lout_path_pl_with_arrows(
1061 wxd2lat_job_t *job,
1062 wxd_object_t *pobj,
1063 int *backptr,
1064 dk4_bb_t *pbb,
1065 dk4_er_t *erp
1066 )
1067 {
1068 double x0; /* X coordinate first/last point */
1069 double y0; /* Y coordinate first/last point */
1070 double x1; /* X coordinate second/penultimate point */
1071 double y1; /* Y coordinate second/penultimate point */
1072 double sl; /* Segment length */
1073 double cl; /* Cut length */
1074 double nl; /* Non-cut length */
1075 uint16_t i; /* Current inner point */
1076
1077 /*
1078 Move to first point
1079 */
1080 x0 = ((pobj->det).p.p)[0].x;
1081 y0 = ((pobj->det).p.p)[0].y;
1082
1083 if (0 != (pobj->ab).type) {
1084 x1 = ((pobj->det).p.p)[1].x;
1085 y1 = ((pobj->det).p.p)[1].y;
1086 sl = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
1087 cl = (pobj->ab).cut;
1088 nl = sl - cl;
1089 x0 = ((x0 * nl) + (x1 * cl)) / sl;
1090 y0 = ((y0 * nl) + (y1 * cl)) / sl;
1091 }
1092
1093 dk4pppt_newpath_moveto(job->ppp, x0, y0, pbb, backptr, erp);
1094 /*
1095 Lines to inner points
1096 */
1097 if ((uint16_t)2U < (pobj->det).p.n) {
1098 for (i = (uint16_t)1U; i < ((pobj->det).p.n) - (uint16_t)1U; i++) {
1099
1100 dk4pppt_lineto(
1101 job->ppp, ((pobj->det).p.p)[i].x, ((pobj->det).p.p)[i].y,
1102 pbb, backptr, erp
1103 );
1104 }
1105 }
1106 /* Line to last point
1107 */
1108 x0 = ((pobj->det).p.p)[(pobj->det).p.n - (uint16_t)1U].x;
1109 y0 = ((pobj->det).p.p)[(pobj->det).p.n - (uint16_t)1U].y;
1110
1111 if (0 != (pobj->af).type) {
1112 x1 = ((pobj->det).p.p)[(pobj->det).p.n - (uint16_t)2U].x;
1113 y1 = ((pobj->det).p.p)[(pobj->det).p.n - (uint16_t)2U].y;
1114 sl = sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
1115 cl = (pobj->af).cut;
1116 nl = sl - cl;
1117 x0 = (x0 * nl + x1 * cl) / sl;
1118 y0 = (y0 * nl + y1 * cl) / sl;
1119 }
1120
1121 dk4pppt_lineto(job->ppp, x0, y0, pbb, backptr, erp);
1122
1123 }
1124
1125
1126
1127 /** Create spline path for open spline with arrowheads.
1128 @param job Job structure.
1129 @param pobj Object to create path for.
1130 @param ts Start parameter t.
1131 @param te End parameter t.
1132 @param npmoveto Flag: Start new path and move to first point.
1133 @param fullseg Flag: This is a full segment.
1134 @param backptr Address of success variable to reset on error.
1135 @param pbb Bounding box for path, may be NULL.
1136 @param erp Error report, may be NULL.
1137 @param iscl Flag: Closed path.
1138 */
1139 static
1140 void
wxd2lout_spline_seg(wxd2lat_job_t * job,wxd_object_t * pobj,double ts,double te,int npmoveto,int fullseg,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)1141 wxd2lout_spline_seg(
1142 wxd2lat_job_t *job,
1143 wxd_object_t *pobj,
1144 double ts,
1145 double te,
1146 int npmoveto,
1147 int fullseg,
1148 int *backptr,
1149 dk4_bb_t *pbb,
1150 dk4_er_t *erp
1151 )
1152 {
1153 double v0[4]; /* Start of segment */
1154 double v1[4]; /* End of segment */
1155 dk4_xsp_2d_t xs; /* X-spline structure */
1156 double diff; /* Parameter t difference start to end */
1157 double coeff; /* Coefficient for derivatives */
1158 double t; /* Current parameter t in range 0 to 1 */
1159 unsigned nsubs; /* Number of sub segments */
1160 unsigned i; /* Current sub segment */
1161 int res; /* Step calculation result */
1162 uint16_t ib; /* X-spline segment index */
1163
1164 ib = (uint16_t)floor(ts);
1165 wxd2lxs_set_xspline(&xs, pobj, ib);
1166 diff = te - ts;
1167 nsubs = (job->grco).xsss;
1168 if (0 != fullseg) {
1169 nsubs = (unsigned)ceil(fabs(diff * (double)nsubs));
1170 if (0U == nsubs) { nsubs = 1U; }
1171 }
1172 coeff = diff / (3.0 * (double)nsubs);
1173 t = ts - (double)ib;
1174 res = dk4xsp2d_calculate_value_derivative(v0, &xs, t, erp);
1175 if (0 != res) {
1176 v0[1] *= coeff; v0[3] *= coeff;
1177 for (i = 0U; i < nsubs; i++) {
1178 if ((nsubs - 1U) == i) {
1179 t = te;
1180 }
1181 else {
1182 t = ts + ((diff * (double)(i + 1U)) / (double)nsubs);
1183 }
1184 t = t - (double)ib;
1185 res = dk4xsp2d_calculate_value_derivative(v1, &xs, t, erp);
1186 if (0 != res) {
1187 v1[1] *= coeff; v1[3] *= coeff;
1188 if ((0U == i) && (0 != npmoveto)) {
1189 dk4pppt_newpath_moveto(
1190 job->ppp, v0[0], v0[2], pbb, backptr, erp
1191 );
1192 }
1193 dk4pppt_curveto(
1194 job->ppp, (v0[0]+v0[1]), (v0[2]+v0[3]), (v1[0]-v1[1]),
1195 (v1[2]-v1[3]), v1[0], v1[2], pbb, backptr, erp
1196 );
1197 }
1198 else {
1199 *backptr = 0;
1200 /* ERROR: Calculation failed */
1201 dk4app_log_1(
1202 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 39
1203 );
1204 }
1205 DK4_MEMCPY(v0,v1,sizeof(v0));
1206 }
1207 }
1208 else {
1209 *backptr = 0;
1210 /* ERROR: Calculation failed */
1211 dk4app_log_1(
1212 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 39
1213 );
1214 }
1215
1216 }
1217
1218
1219 /** Create spline path for open spline with arrowheads.
1220 @param drw Drawing structure.
1221 @param job Job structure.
1222 @param pobj Object to create path for.
1223 @param backptr Address of success variable to reset on error.
1224 @param pbb Bounding box for path, may be NULL.
1225 @param erp Error report, may be NULL.
1226 @param iscl Flag: Closed path.
1227 */
1228 static
1229 void
wxd2lout_path_spline_with_arrows(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)1230 wxd2lout_path_spline_with_arrows(
1231 wxd2lat_job_t *job,
1232 wxd_object_t *pobj,
1233 int *backptr,
1234 dk4_bb_t *pbb,
1235 dk4_er_t *erp
1236 )
1237 {
1238 uint16_t ss;
1239 uint16_t se;
1240 uint16_t i;
1241
1242 ss = (uint16_t)floor((pobj->det).s.ts);
1243 se = (uint16_t)floor((pobj->det).s.te);
1244 if (0 != (pobj->ab).type) {
1245 if (0 != (pobj->af).type) {
1246 if (se > ss) {
1247 wxd2lout_spline_seg(
1248 job, pobj, (pobj->det).s.ts, (double)(ss + 1), 1, 0,
1249 backptr, pbb, erp
1250 );
1251 for (i = (uint16_t)(ss + 1U); i < se; i++) {
1252 wxd2lout_spline_seg(
1253 job, pobj, (double)i, (double)(i + 1), 0, 1,
1254 backptr, pbb, erp
1255 );
1256 }
1257 if ((pobj->det).s.te > floor((pobj->det).s.te)) {
1258 wxd2lout_spline_seg(
1259 job, pobj, (double)se, (pobj->det).s.te, 0, 0,
1260 backptr, pbb, erp
1261 );
1262 }
1263 }
1264 else {
1265 wxd2lout_spline_seg(
1266 job, pobj, (pobj->det).s.ts, (pobj->det).s.te, 1, 0,
1267 backptr, pbb, erp
1268 );
1269 }
1270 }
1271 else {
1272 wxd2lout_spline_seg(
1273 job, pobj, (pobj->det).s.ts, (double)(ss + 1), 1, 0,
1274 backptr, pbb, erp
1275 );
1276 for (i = (uint16_t)(ss + 1U); i < (pobj->det).s.n - 1; i++) {
1277 wxd2lout_spline_seg(
1278 job, pobj, (double)i, (double)(i + 1), 0, 1,
1279 backptr, pbb, erp
1280 );
1281 }
1282 }
1283 }
1284 else {
1285 if (0 != (pobj->af).type) {
1286 for (i = 0; i < se; i++) {
1287 wxd2lout_spline_seg(
1288 job, pobj, (double)i, (double)(i + 1),
1289 ((0 == i) ? 1 : 0), 1, backptr, pbb, erp
1290 );
1291 }
1292 if ((pobj->det).s.te > floor((pobj->det).s.te)) {
1293 wxd2lout_spline_seg(
1294 job, pobj, (double)se, (pobj->det).s.te, 0, 0,
1295 backptr, pbb, erp
1296 );
1297 }
1298 }
1299 else {
1300 wxd2lout_path_spline_no_arrows(job, pobj, backptr, pbb, erp, 0);
1301 }
1302 }
1303
1304 }
1305
1306
1307
1308 /** Create arc path for open arcs with at least one arrowhead.
1309 @param drw Drawing structure.
1310 @param job Job structure.
1311 @param pobj Object to create path for.
1312 @param backptr Address of success variable to reset on error.
1313 @param pbb Bounding box for path, may be NULL.
1314 @param erp Error report, may be NULL.
1315 @param iscl Flag: Closed path.
1316 */
1317 static
1318 void
wxd2lout_path_arc_with_arrows(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp,int iscl)1319 wxd2lout_path_arc_with_arrows(
1320 wxd_drawing_t *drw,
1321 wxd2lat_job_t *job,
1322 wxd_object_t *pobj,
1323 int *backptr,
1324 dk4_bb_t *pbb,
1325 dk4_er_t *erp,
1326 int iscl
1327 )
1328 {
1329 double alpha; /* Start angle */
1330 double beta; /* End angle */
1331 double x1; /* X coordinate point 1 */
1332 double y1; /* Y coordinate point 1 */
1333 double x2; /* X coordinate point 2 */
1334 double y2; /* Y coordinate point 2 */
1335 double x3; /* X coordinate point 3 */
1336 double y3; /* Y coordinate point 3 */
1337 double sl; /* Segment length */
1338 double cl; /* Cut length */
1339 double nl; /* Non-cut length */
1340
1341 if (0 != (pobj->det).a.d) {
1342 alpha = (pobj->det).a.a;
1343 beta = (pobj->det).a.b;
1344
1345
1346 if (0 < (pobj->det).a.d) {
1347 if (0 != (pobj->ab).type) {
1348
1349 alpha += (pobj->ab).cut / (pobj->det).a.r;
1350
1351 }
1352 if (0 != (pobj->af).type) {
1353
1354 beta -= (pobj->af).cut / (pobj->det).a.r;
1355
1356 }
1357 }
1358 else {
1359 if (0 != (pobj->ab).type) {
1360
1361 alpha -= (pobj->ab).cut / (pobj->det).a.r;
1362
1363 }
1364 if (0 != (pobj->af).type) {
1365
1366 beta += (pobj->af).cut / (pobj->det).a.r;
1367
1368 }
1369 }
1370 wxd2lout_path_arc_angles(
1371 drw, job, pobj, alpha, beta, backptr, pbb, erp, iscl
1372 );
1373 }
1374 else {
1375 /* Malformed arc as polygon, cut ends for arrows.
1376 */
1377 x1 = wxd2lout_convert_x(drw, job, (double)((pobj->det).a.x1));
1378 x2 = wxd2lout_convert_x(drw, job, (double)((pobj->det).a.x2));
1379 x3 = wxd2lout_convert_x(drw, job, (double)((pobj->det).a.x3));
1380 y1 = wxd2lout_convert_y(drw, job, (double)((pobj->det).a.y1));
1381 y2 = wxd2lout_convert_y(drw, job, (double)((pobj->det).a.y2));
1382 y3 = wxd2lout_convert_y(drw, job, (double)((pobj->det).a.y3));
1383 if (0 != (pobj->ab).type) {
1384 sl = sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
1385 cl = (pobj->ab).cut;
1386 nl = sl - cl;
1387 x1 = (x1 * nl + x2 * cl) / sl;
1388 y1 = (y1 * nl + y2 * cl) / sl;
1389 }
1390 dk4pppt_newpath_moveto(job->ppp, x1, y1, pbb, backptr, erp);
1391 dk4pppt_lineto(job->ppp, x2, y2, pbb, backptr, erp);
1392 if (0 != (pobj->af).type) {
1393 sl = sqrt((x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3));
1394 cl = (pobj->af).cut;
1395 nl = sl - cl;
1396 x3 = (x3 * nl + x2 * cl) / sl;
1397 y3 = (y3 * nl + y2 * cl) / sl;
1398 }
1399 dk4pppt_lineto(job->ppp, x3, y3, pbb, backptr, erp);
1400 }
1401
1402 }
1403
1404
1405
1406 /** Create polyline or polygon path.
1407 @param job Job structure.
1408 @param pobj Object to create path for.
1409 @param backptr Address of success variable to reset on error.
1410 @param pbb Bounding box for path, may be NULL.
1411 @param erp Error report, may be NULL.
1412 @param iscl Flag: Closed path.
1413 */
1414 static
1415 void
wxd2lout_path_polyline(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp,int iscl)1416 wxd2lout_path_polyline(
1417 wxd2lat_job_t *job,
1418 wxd_object_t *pobj,
1419 int *backptr,
1420 dk4_bb_t *pbb,
1421 dk4_er_t *erp,
1422 int iscl
1423 )
1424 {
1425
1426 if (
1427 (0 != iscl)
1428 || (((uint8_t)0U == pobj->af.type) && ((uint8_t)0U == pobj->ab.type))
1429 ) {
1430 /* Closed polygon or polyline without arrows.
1431 */
1432 wxd2lout_path_pl_no_arrows(job, pobj, backptr, pbb, erp, iscl);
1433 }
1434 else {
1435 /* Polyline with at least one arrow.
1436 */
1437 wxd2lout_path_pl_with_arrows(job, pobj, backptr, pbb, erp);
1438 }
1439
1440 }
1441
1442
1443
1444 /** Create spline path.
1445 @param job Job structure.
1446 @param pobj Object to create path for.
1447 @param backptr Address of success variable to reset on error.
1448 @param pbb Bounding box for path, may be NULL.
1449 @param erp Error report, may be NULL.
1450 @param iscl Flag: Closed path.
1451 */
1452 static
1453 void
wxd2lout_path_spline(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp,int iscl)1454 wxd2lout_path_spline(
1455 wxd2lat_job_t *job,
1456 wxd_object_t *pobj,
1457 int *backptr,
1458 dk4_bb_t *pbb,
1459 dk4_er_t *erp,
1460 int iscl
1461 )
1462 {
1463
1464 if (
1465 (0 != iscl)
1466 || (((uint8_t)0U == pobj->af.type) && ((uint8_t)0U == pobj->ab.type))
1467 ) {
1468 /* Closed spline or open spline without arrowheads.
1469 */
1470 wxd2lout_path_spline_no_arrows(job, pobj, backptr, pbb, erp, iscl);
1471 }
1472 else {
1473 /* Open spline with at least one arrowhead.
1474 */
1475 wxd2lout_path_spline_with_arrows(job, pobj, backptr, pbb, erp);
1476 }
1477
1478 }
1479
1480
1481
1482 /** Create arc path.
1483 @param drw Drawing structure.
1484 @param job Job structure.
1485 @param pobj Object to create path for.
1486 @param backptr Address of success variable to reset on error.
1487 @param pbb Bounding box for path, may be NULL.
1488 @param erp Error report, may be NULL.
1489 @param iscl Flag: Closed path.
1490 */
1491 static
1492 void
wxd2lout_path_arc(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp,int iscl)1493 wxd2lout_path_arc(
1494 wxd_drawing_t *drw,
1495 wxd2lat_job_t *job,
1496 wxd_object_t *pobj,
1497 int *backptr,
1498 dk4_bb_t *pbb,
1499 dk4_er_t *erp,
1500 int iscl
1501 )
1502 {
1503
1504 if (
1505 (0 != iscl)
1506 || (((uint8_t)0U == pobj->af.type) && ((uint8_t)0U == pobj->ab.type))
1507 ) {
1508 /* Closed arc or open arc without arrowheads.
1509 */
1510 wxd2lout_path_arc_no_arrows(drw,job,pobj,backptr,pbb,erp,iscl);
1511 }
1512 else {
1513 /* Open arc with at least one arrowhead.
1514 */
1515 wxd2lout_path_arc_with_arrows(drw,job,pobj,backptr,pbb,erp,iscl);
1516 }
1517
1518 }
1519
1520
1521
1522 /** Create circle path.
1523 @param job Job structure.
1524 @param pobj Object to create path for.
1525 @param backptr Address of success variable to reset on error.
1526 @param pbb Bounding box for path, may be NULL.
1527 @param erp Error report, may be NULL.
1528 */
1529 static
1530 void
wxd2lout_path_circle(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)1531 wxd2lout_path_circle(
1532 wxd2lat_job_t *job,
1533 wxd_object_t *pobj,
1534 int *backptr,
1535 dk4_bb_t *pbb,
1536 dk4_er_t *erp
1537 )
1538 {
1539
1540
1541
1542
1543 dk4pppt_circle(
1544 job->ppp,
1545 (pobj->det).e.x, (pobj->det).e.y, (pobj->det).e.rx,
1546 pbb, backptr, erp
1547 );
1548
1549 }
1550
1551
1552
1553 /** Create ellipse path.
1554 @param job Job structure.
1555 @param pobj Object to create path for.
1556 @param backptr Address of success variable to reset on error.
1557 @param pbb Bounding box for path, may be NULL.
1558 @param erp Error report, may be NULL.
1559 */
1560 static
1561 void
wxd2lout_path_ellipse(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)1562 wxd2lout_path_ellipse(
1563 wxd2lat_job_t *job,
1564 wxd_object_t *pobj,
1565 int *backptr,
1566 dk4_bb_t *pbb,
1567 dk4_er_t *erp
1568 )
1569 {
1570
1571 dk4pppt_ellipse(
1572 job->ppp,
1573 (pobj->det).e.x, (pobj->det).e.y, (pobj->det).e.rx, (pobj->det).e.ry,
1574 (pobj->det).e.a, pbb, backptr, erp
1575 );
1576
1577 }
1578
1579
1580
1581 /** Create box path.
1582 @param job Job structure.
1583 @param pobj Object to create path for.
1584 @param backptr Address of success variable to reset on error.
1585 @param pbb Bounding box for path, may be NULL.
1586 @param erp Error report, may be NULL.
1587 */
1588 static
1589 void
wxd2lout_path_box(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)1590 wxd2lout_path_box(
1591 wxd2lat_job_t *job,
1592 wxd_object_t *pobj,
1593 int *backptr,
1594 dk4_bb_t *pbb,
1595 dk4_er_t *erp
1596 )
1597 {
1598
1599 dk4pppt_rectangle(
1600 job->ppp,
1601 (pobj->det).b.xl, (pobj->det).b.xr,
1602 (pobj->det).b.yb, (pobj->det).b.yt,
1603 ((0.0 < (pobj->det).b.r) ? ((pobj->det).b.r) : (-1.0)),
1604 pbb, backptr, erp
1605 );
1606
1607 }
1608
1609
1610
1611 /** Create dot path.
1612 @param job Job structure.
1613 @param pobj Object to create path for.
1614 @param backptr Address of success variable to reset on error.
1615 @param pbb Bounding box for path, may be NULL.
1616 @param erp Error report, may be NULL.
1617 */
1618 static
1619 void
wxd2lout_path_dot(wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)1620 wxd2lout_path_dot(
1621 wxd2lat_job_t *job,
1622 wxd_object_t *pobj,
1623 int *backptr,
1624 dk4_bb_t *pbb,
1625 dk4_er_t *erp
1626 )
1627 {
1628
1629 dk4pppt_circle(
1630 job->ppp, (pobj->det).d.x, (pobj->det).d.y, ((pobj->det).d.d / 2.0),
1631 pbb, backptr, erp
1632 );
1633
1634 }
1635
1636
1637
1638
1639 /** Create object path.
1640 @param drw Drawing structure.
1641 @param job Job structure.
1642 @param pobj Object to create path for.
1643 @param backptr Address of success variable to reset on error.
1644 @param pbb Bounding box for path, may be NULL.
1645 @param erp Error report, may be NULL.
1646 */
1647 static
1648 void
wxd2lout_object_path(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj,int * backptr,dk4_bb_t * pbb,dk4_er_t * erp)1649 wxd2lout_object_path(
1650 wxd_drawing_t *drw,
1651 wxd2lat_job_t *job,
1652 wxd_object_t *pobj,
1653 int *backptr,
1654 dk4_bb_t *pbb,
1655 dk4_er_t *erp
1656 )
1657 {
1658
1659 switch (pobj->ot) {
1660 case WXD_OT_POLYLINE : {
1661 wxd2lout_path_polyline(job, pobj, backptr, pbb, erp, 0);
1662 } break;
1663 case WXD_OT_O_SPLINE : {
1664 wxd2lout_path_spline(job, pobj, backptr, pbb, erp, 0);
1665 } break;
1666 case WXD_OT_O_ARC : {
1667 wxd2lout_path_arc(drw, job, pobj, backptr, pbb, erp, 0);
1668 } break;
1669 case WXD_OT_POLYGON : {
1670 wxd2lout_path_polyline(job, pobj, backptr, pbb, erp, 1);
1671 } break;
1672 case WXD_OT_C_SPLINE : {
1673 wxd2lout_path_spline(job, pobj, backptr, pbb, erp, 1);
1674 } break;
1675 case WXD_OT_C_ARC : {
1676 wxd2lout_path_arc(drw, job, pobj, backptr, pbb, erp, 1);
1677 } break;
1678 case WXD_OT_CIRCLE : {
1679 wxd2lout_path_circle(job, pobj, backptr, pbb, erp);
1680 } break;
1681 case WXD_OT_ELLIPSE : {
1682 wxd2lout_path_ellipse(job, pobj, backptr, pbb, erp);
1683 } break;
1684 case WXD_OT_BOX : {
1685 wxd2lout_path_box(job, pobj, backptr, pbb, erp);
1686 } break;
1687 case WXD_OT_DOT_FILLED : {
1688 wxd2lout_path_dot(job, pobj, backptr, pbb, erp);
1689 } break;
1690 case WXD_OT_DOT_WHITE : {
1691 wxd2lout_path_dot(job, pobj, backptr, pbb, erp);
1692 } break;
1693 }
1694
1695 }
1696
1697
1698
1699 static
1700 dk4_text_align_h_t
wxd2lout_h_text_align(uint8_t a)1701 wxd2lout_h_text_align(uint8_t a)
1702 {
1703 dk4_text_align_h_t back = DK4_TEXT_ALIGN_H_LEFT;
1704 switch ((int)a) {
1705 case 1: {
1706 back = DK4_TEXT_ALIGN_H_CENTERED;
1707 } break;
1708 case 2: {
1709 back = DK4_TEXT_ALIGN_H_RIGHT;
1710 } break;
1711 }
1712 return back;
1713 }
1714
1715
1716
1717 /** Create output for one text object.
1718 @param job Job structure containing the output structure.
1719 @param pobj Object to process.
1720 @return 1 on success, 0 on error.
1721 */
1722 static
1723 int
wxd2lout_text_object(wxd2lat_job_t * job,wxd_object_t * pobj)1724 wxd2lout_text_object(
1725 wxd2lat_job_t *job,
1726 wxd_object_t *pobj
1727 )
1728 {
1729 dkChar buf[2048];
1730 dk4_er_t er;
1731 int back = 1;
1732 int res;
1733 dk4_gra_tf_t fonttype = DK4_GRA_TF_SIMILAR_SIZE;
1734
1735 if (DK4_GRA_PURPOSE_DOCUMENT == (job->grco).purpose) {
1736 fonttype = DK4_GRA_TF_EXACT_SIZE;
1737 }
1738 dk4error_init(&er);
1739 res = dk4recode_c8_to_dk(
1740 buf, DK4_SIZEOF(buf,dkChar), dk4app_get_encoding(job->app),
1741 (pobj->det).t.t, DK4_ENCODING_UTF8, &er
1742 );
1743 if (0 != res) {
1744 wxd2lout_fill_rgb(job, pobj, &back, &er);
1745 if (0 != back) {
1746 if (0x00 != (0x01 & ((pobj->det).t.fl))) {
1747 /*
1748 Special text
1749 */
1750 fonttype = DK4_GRA_TF_NONE_NONE;
1751 dk4pppt_special_text(
1752 job->ppp, (pobj->det).t.x, (pobj->det).t.y, (pobj->det).t.a,
1753 (pobj->det).t.t, NULL,
1754 wxd2lout_h_text_align((pobj->det).t.al),
1755 DK4_TEXT_ALIGN_V_BASELINE, (int)((pobj->det).t.find),
1756 (double)((pobj->det).t.fsz), fonttype, 0, &back, &er
1757 );
1758 }
1759 else {
1760 /* Normal text
1761 */
1762 dk4pppt_simple_utf8_text(
1763 job->ppp, (pobj->det).t.x, (pobj->det).t.y, (pobj->det).t.a,
1764 (pobj->det).t.t, NULL,
1765 wxd2lout_h_text_align((pobj->det).t.al),
1766 DK4_TEXT_ALIGN_V_BASELINE,
1767 (int)((pobj->det).t.find), (double)((pobj->det).t.fsz),
1768 fonttype, job->uc2l, 0, &back, &er
1769 );
1770 }
1771 if (0 == back) {
1772 /* ERROR: Failed to write text */
1773 dk4app_log_1(
1774 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 40
1775 );
1776 }
1777 }
1778 else {
1779 /* ERROR: Failed to set fill colour */
1780 dk4app_log_1(
1781 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 41
1782 );
1783 }
1784 }
1785 else {
1786 back = 0;
1787 /* ERROR: UTF-8 decoding failed */
1788 dk4app_log_1(
1789 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 42
1790 );
1791 }
1792
1793 return back;
1794 }
1795
1796
1797
1798 /** Create output for one open path object probably with arrowheads attached.
1799 @param drw Original drawing.
1800 @param job Job structure containing the output structure.
1801 @param pobj Object to process.
1802 @return 1 on success, 0 on error.
1803 */
1804 static
1805 int
wxd2lout_open_path_object(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)1806 wxd2lout_open_path_object(
1807 wxd_drawing_t *drw,
1808 wxd2lat_job_t *job,
1809 wxd_object_t *pobj
1810 )
1811 {
1812 dk4_er_t er;
1813 int myback;
1814 int back = 1;
1815
1816 dk4error_init(&er);
1817 if (0.0 < pobj->lw) {
1818 wxd2lout_attributes_stroke(drw, job, pobj, &back, 1, &er);
1819
1820 dk4pppt_prepare_stroke(job->ppp, &back, &er);
1821
1822 wxd2lout_object_path(drw, job, pobj, &back, NULL, &er);
1823
1824 dk4pppt_stroke(job->ppp, &back, &er);
1825
1826 if (0 == back) {
1827 /* ERROR: Failed to create graphics object */
1828 dk4app_log_1(
1829 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 43
1830 );
1831 }
1832 if ((uint8_t)0U != (pobj->af).type) {
1833 myback = 1;
1834 wxd2lah_arrowhead(&(pobj->af), drw, job, pobj, 0, &myback, &er);
1835 if (0 == myback) {
1836 back = 0;
1837 /* ERROR: Failed to create forward arrowhead */
1838 dk4app_log_1(
1839 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 44
1840 );
1841 }
1842
1843 }
1844 if ((uint8_t)0U != (pobj->ab).type) {
1845 myback = 1;
1846 wxd2lah_arrowhead(&(pobj->ab), drw, job, pobj, 1, &myback, &er);
1847 if (0 == myback) {
1848 back = 0;
1849 /* ERROR: Failed to create backward arrowhead */
1850 dk4app_log_1(
1851 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 45
1852 );
1853 }
1854
1855 }
1856 }
1857 else {
1858 /* Object skipped */
1859 /* INFO: Skipping object due to non-positive line-width */
1860 dk4app_log_1(
1861 job->app, job->msg, job->sz_msg, DK4_LL_INFO, 46
1862 );
1863 }
1864
1865 return back;
1866 }
1867
1868
1869
1870 /** Create output for one closed path object, probably filled or pattern filled.
1871 @param drw Original drawing.
1872 @param job Job structure containing the output structure.
1873 @param pobj Object to process.
1874 @return 1 on success, 0 on error.
1875 */
1876 static
1877 int
wxd2lout_closed_path_object(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)1878 wxd2lout_closed_path_object(
1879 wxd_drawing_t *drw,
1880 wxd2lat_job_t *job,
1881 wxd_object_t *pobj
1882 )
1883 {
1884 dk4_bb_t pbb;
1885 dk4_er_t er;
1886 int back = 1;
1887 int must_stroke = 0;
1888 int must_fill = 0;
1889 int must_pattern = 0;
1890 int combined = 0;
1891
1892 dk4bb_init(&pbb);
1893 dk4error_init(&er);
1894 if (0.0 < pobj->lw) {
1895 must_stroke = 1;
1896 }
1897 if ((uint8_t)(WXD_FS_NONE) != pobj->csfs) {
1898 must_fill = 1;
1899 }
1900 if ((uint8_t)(WXD_FS_PURE) < pobj->csfs) {
1901 must_pattern = 1;
1902 }
1903 if ((0 != must_stroke) && (0 != must_fill)) {
1904 if (0 != dk4pppt_can_fill_and_stroke(job->ppp)) {
1905 combined = 1;
1906 }
1907 }
1908 if (0 != combined) {
1909 wxd2lout_attributes_fill(job, pobj, &back, &er);
1910
1911 wxd2lout_attributes_stroke(drw, job, pobj, &back, 0, &er);
1912
1913 dk4pppt_prepare_fill_and_stroke(job->ppp, &back, &er);
1914
1915 wxd2lout_object_path(drw, job, pobj, &back, NULL, &er);
1916
1917 dk4pppt_fill_and_stroke(job->ppp, &back, &er);
1918
1919 if (0 != must_pattern) {
1920 dk4pppt_gsave(job->ppp, &back, &er);
1921
1922 wxd2lout_object_path(drw, job, pobj, &back, &pbb, &er);
1923
1924 dk4pppt_clip(job->ppp, &back, &er);
1925
1926 dk4pppt_pattern(
1927 job->ppp, pbb.xmin, pbb.xmax, pbb.ymin, pbb.ymax,
1928 wxd2lout_find_pattern(pobj), &back, &er
1929 );
1930
1931 dk4pppt_grestore(job->ppp, &back, &er);
1932
1933 }
1934 }
1935 else {
1936 if (0 != must_fill) {
1937 wxd2lout_attributes_fill(job, pobj, &back, &er);
1938
1939 dk4pppt_prepare_fill(job->ppp, &back, &er);
1940
1941 wxd2lout_object_path(drw, job, pobj, &back, NULL, &er);
1942
1943 dk4pppt_fill(job->ppp, &back, &er);
1944
1945 }
1946 if (0 != must_pattern) {
1947 dk4pppt_gsave(job->ppp, &back, &er);
1948
1949 wxd2lout_object_path(drw, job, pobj, &back, &pbb, &er);
1950
1951 dk4pppt_clip(job->ppp, &back, &er);
1952
1953 dk4pppt_pattern(
1954 job->ppp, pbb.xmin, pbb.xmax, pbb.ymin, pbb.ymax,
1955 wxd2lout_find_pattern(pobj), &back, &er
1956 );
1957
1958 dk4pppt_grestore(job->ppp, &back, &er);
1959
1960 }
1961 if (0 != must_stroke) {
1962 wxd2lout_attributes_stroke(drw, job, pobj, &back, 0, &er);
1963
1964 dk4pppt_prepare_stroke(job->ppp, &back, &er);
1965
1966 wxd2lout_object_path(drw, job, pobj, &back, NULL, &er);
1967
1968 dk4pppt_stroke(job->ppp, &back, &er);
1969
1970 }
1971 }
1972 if (0 == back) {
1973 /* ERROR: Failed to create graphics object */
1974 dk4app_log_1(
1975 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 43
1976 );
1977 }
1978
1979 return back;
1980 }
1981
1982
1983
1984 /** Create output for one dot object.
1985 @param drw Original drawing.
1986 @param job Job structure containing the output structure.
1987 @param pobj Object to process.
1988 @return 1 on success, 0 on error.
1989 */
1990 static
1991 int
wxd2lout_dot_object(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)1992 wxd2lout_dot_object(
1993 wxd_drawing_t *drw,
1994 wxd2lat_job_t *job,
1995 wxd_object_t *pobj
1996 )
1997 {
1998 dk4_er_t er;
1999 double lw;
2000 int back = 1;
2001
2002 dk4error_init(&er);
2003
2004 switch (pobj->ot) {
2005 case WXD_OT_DOT_FILLED : {
2006 wxd2lout_attributes_fill(job, pobj, &back, &er);
2007 if (1 == back) {
2008 dk4pppt_prepare_fill(job->ppp, &back, &er);
2009 if (1 == back) {
2010 dk4pppt_circle(
2011 job->ppp, (pobj->det).d.x, (pobj->det).d.y,
2012 ((pobj->det).d.d / 2.0), NULL, &back, &er
2013 );
2014 dk4pppt_fill(job->ppp, &back, &er);
2015 if (0 == back) {
2016 /* ERROR: Failed to create filled circle */
2017 dk4app_log_1(
2018 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 47
2019 );
2020 }
2021 }
2022 else {
2023 /* ERROR: Failed to set up filling */
2024 dk4app_log_1(
2025 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 48
2026 );
2027 }
2028 }
2029 else {
2030 /* ERROR: Failed to set up filling */
2031 dk4app_log_1(
2032 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 48
2033 );
2034 }
2035 } break;
2036 case WXD_OT_DOT_WHITE : {
2037 lw = wxd2lat_object_linewidth(pobj, drw, job);
2038 if (lw >= (pobj->det).d.d) {
2039 dk4pppt_set_fill_rgb(
2040 job->ppp,
2041 (((double)(pobj->sc[0])) / 255.0),
2042 (((double)(pobj->sc[1])) / 255.0),
2043 (((double)(pobj->sc[2])) / 255.0),
2044 &back, &er
2045 );
2046 dk4pppt_prepare_fill(job->ppp, &back, &er);
2047 dk4pppt_circle(
2048 job->ppp, (pobj->det).d.x, (pobj->det).d.y,
2049 ((lw + (pobj->det).d.d) / 2.0), NULL, &back, &er
2050 );
2051 dk4pppt_fill(job->ppp, &back, &er);
2052 }
2053 else {
2054 if (0 != dk4pppt_can_fill_and_stroke(job->ppp)) {
2055 wxd2lout_attributes_fill(job, pobj, &back, &er);
2056 wxd2lout_attributes_stroke(drw, job, pobj, &back, 0, &er);
2057 dk4pppt_prepare_fill_and_stroke(job->ppp, &back, &er);
2058 if (1 == back) {
2059 dk4pppt_circle(
2060 job->ppp, (pobj->det).d.x, (pobj->det).d.y,
2061 ((pobj->det).d.d / 2.0), NULL, &back, &er
2062 );
2063 dk4pppt_fill_and_stroke(job->ppp, &back, &er);
2064 if (0 == back) {
2065 /* ERROR: Failed to create filled circle */
2066 dk4app_log_1(
2067 job->app,job->msg,job->sz_msg,DK4_LL_ERROR,47
2068 );
2069 }
2070
2071 }
2072 else {
2073 /* ERROR: Failed to set up fill and stroke */
2074 dk4app_log_1(
2075 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 49
2076 );
2077 }
2078 }
2079 else {
2080 wxd2lout_attributes_fill(job, pobj, &back, &er);
2081 dk4pppt_prepare_fill(job->ppp, &back, &er);
2082 if (0 != back) {
2083 dk4pppt_circle(
2084 job->ppp, (pobj->det).d.x, (pobj->det).d.y,
2085 ((pobj->det).d.d / 2.0), NULL, &back, &er
2086 );
2087 dk4pppt_fill(job->ppp, &back, &er);
2088 if (0 != back) {
2089 wxd2lout_attributes_stroke(
2090 drw, job, pobj, &back, 0, &er
2091 );
2092 dk4pppt_prepare_stroke(job->ppp, &back, &er);
2093 if (0 != back) {
2094 dk4pppt_circle(
2095 job->ppp, (pobj->det).d.x, (pobj->det).d.y,
2096 ((pobj->det).d.d / 2.0), NULL, &back, &er
2097 );
2098 dk4pppt_stroke(job->ppp, &back, &er);
2099 if (0 == back) {
2100 /* ERROR: Failed to stroke circle */
2101 dk4app_log_1(
2102 job->app, job->msg, job->sz_msg,
2103 DK4_LL_ERROR, 36
2104 );
2105
2106 }
2107 }
2108 else {
2109 /* ERROR: Failed to set up stroke */
2110 dk4app_log_1(
2111 job->app, job->msg, job->sz_msg,
2112 DK4_LL_ERROR, 51
2113 );
2114 }
2115 }
2116 else {
2117 /* Failed to create filled circle */
2118 dk4app_log_1(
2119 job->app,job->msg,job->sz_msg,DK4_LL_ERROR,47
2120 );
2121 }
2122 }
2123 else {
2124 /* ERROR: Failed to set up fill */
2125 dk4app_log_1(
2126 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 48
2127 );
2128 }
2129 }
2130 }
2131 } break;
2132 }
2133
2134 return back;
2135 }
2136
2137
2138
2139 /** Create output for one image object.
2140 @param job Job structure containing the output structure.
2141 @param pobj Object to process.
2142 @return 1 on success, 0 on error.
2143 */
2144 static
2145 int
wxd2lout_image_object(wxd2lat_job_t * job,wxd_object_t * pobj)2146 wxd2lout_image_object(
2147 wxd2lat_job_t *job,
2148 wxd_object_t *pobj
2149 )
2150 {
2151 dkChar fnb[DK4_MAX_PATH]; /* File name buffer */
2152 dk4_px_t bg[4]; /* Background colour */
2153 dk4_cs_conv_ctx_t ctx; /* RGB to gray conv context */
2154 dk4_er_t er; /* Error report */
2155 dk4_bif_t *pbif = NULL; /* Bitmap image */
2156 int back = 1; /* Function result */
2157 int ifl = 0; /* Image flags */
2158 int fbg = 0; /* Flag: Force background */
2159 int res = 0; /* Step result */
2160
2161 DK4_MEMCPY(&ctx,&((job->grco).ctx),sizeof(dk4_cs_conv_ctx_t));
2162 bg[0] = (dk4_px_t)(pobj->fc[0]);
2163 bg[1] = (dk4_px_t)(pobj->fc[1]);
2164 bg[2] = (dk4_px_t)(pobj->fc[2]);
2165 if (DK4_CS_CONV_RGB_TO_GRAY_MIN <= (pobj->det).i.r2g) {
2166 if (DK4_CS_CONV_RGB_TO_GRAY_MAX >= (pobj->det).i.r2g) {
2167 ctx.rgb_to_gray = (dk4_cs_conv_rgb_to_gray_t)((pobj->det).i.r2g);
2168 }
2169 }
2170 if (0x00 != (0x20 & ((pobj->det).i.fl))) {
2171 fbg = 1;
2172 }
2173 if (0x00 != (0x02 & ((pobj->det).i.fl))) {
2174 /* Alpha mix */
2175 ctx.alpha = DK4_CS_CONV_ALPHA_MIX;
2176 }
2177 else {
2178 /* Alpha ignore */
2179 ctx.alpha = DK4_CS_CONV_ALPHA_FOREGROUND;
2180 }
2181 if (0 != (job->grco).color) {
2182 ifl |= DK4_GRA_IMG_FLAG_COLOR;
2183 }
2184 if (0 != (job->grco).ps_lzw) {
2185 ifl |= DK4_GRA_IMG_FLAG_LZW;
2186 }
2187 if (0x00 != (0x08 & ((pobj->det).i.fl))) {
2188 ifl |= DK4_GRA_IMG_FLAG_DCT;
2189 }
2190 if (0x00 != (0x04 & ((pobj->det).i.fl))) {
2191 ifl |= DK4_GRA_IMG_FLAG_INTERPOLATION;
2192 }
2193 if (0x00 != (0x10 & ((pobj->det).i.fl))) {
2194 ifl |= DK4_GRA_IMG_FLAG_DCT_INTERPOLATION;
2195 }
2196 ifl |= DK4_GRA_IMG_FLAG_ANALYZE_BPC;
2197 ifl |= DK4_GRA_IMG_FLAG_ANALYZE_COLOR;
2198 ifl |= DK4_GRA_IMG_FLAG_ANALYZE_ALPHA;
2199 if (0x00 == (0x01 & ((pobj->det).i.fl))) {
2200 ifl |= DK4_GRA_IMG_FLAG_IGNORE_ASPECT_RATIO;
2201 }
2202 res = dk4recode_c8_to_dk(
2203 fnb, DK4_SIZEOF(fnb,dkChar), dk4app_get_encoding(job->app),
2204 (pobj->det).i.fn, DK4_ENCODING_UTF8, &er
2205 );
2206 if (0 != res) {
2207 if (0 <= dk4bif_type_for_suffix(fnb)) {
2208 pbif = dk4bif_open_app(fnb, 0, &ctx, job->app);
2209 if (NULL != pbif) {
2210 dk4error_init(&er);
2211 dk4bif_set_background(pbif, bg, 3, 8, fbg);
2212 dk4pppt_bif_image(
2213 job->ppp, (pobj->det).i.x,
2214 ((pobj->det).i.x + (pobj->det).i.w),
2215 (pobj->det).i.y,
2216 ((pobj->det).i.y + (pobj->det).i.h), pbif, fnb,
2217 (size_t)0U, ifl, NULL, &back, &er
2218 );
2219 dk4bif_close(pbif);
2220 if (0 == back) {
2221 /* ERROR: Failed to add bitmap image */
2222 dk4app_log_1(
2223 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 52
2224 );
2225 }
2226 }
2227 else {
2228 back = 0;
2229 /* ERROR: Failed to open file */
2230 }
2231 }
2232 else {
2233 back = 0;
2234 /* ERROR: Not a supported bitmap type */
2235 dk4app_log_1(
2236 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 53
2237 );
2238 }
2239 }
2240 else {
2241 back = 0;
2242 /* ERROR: Failed to decode file name! */
2243 dk4app_log_1(
2244 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 54
2245 );
2246 }
2247
2248 return back;
2249 }
2250
2251
2252
2253 /** Check one text object if information is complete and object
2254 can be drawn.
2255 @param job Job structure.
2256 @param pobj Object to check.
2257 @return 1 on success (further handling possible), 0 otherwise.
2258 */
2259 static
2260 int
wxd2lout_check_one_text_object(wxd2lat_job_t * job,wxd_object_t * pobj)2261 wxd2lout_check_one_text_object(
2262 wxd2lat_job_t *job,
2263 wxd_object_t *pobj
2264 )
2265 {
2266 int back = 0;
2267
2268 if (NULL != (pobj->det).t.t) {
2269 if ((uint16_t)0U != (pobj->det).t.fsz) {
2270 back = 1;
2271 }
2272 else {
2273 if ((uint8_t)0x00 != ((uint8_t)0x01 & (pobj->det).t.fl)) {
2274 back = 1;
2275 }
2276 else {
2277 /* ERROR: Font size 0 */
2278 dk4app_log_1(
2279 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 55
2280 );
2281 }
2282 }
2283 }
2284 else {
2285 /* ERROR: No text on object */
2286 dk4app_log_1(
2287 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 56
2288 );
2289 }
2290
2291 return back;
2292 }
2293
2294
2295
2296 /** Check one polyline/polygon object if information is complete and object
2297 can be drawn.
2298 @param job Job structure.
2299 @param pobj Object to check.
2300 @return 1 on success (further handling possible), 0 otherwise.
2301 */
2302 static
2303 int
wxd2lout_check_one_polyline_object(wxd2lat_job_t * job,wxd_object_t * pobj)2304 wxd2lout_check_one_polyline_object(
2305 wxd2lat_job_t *job,
2306 wxd_object_t *pobj
2307 )
2308 {
2309 double x0; /* Coordinate of first point */
2310 double y0; /* Coordinate of first point */
2311 double x1; /* Coordinate of second point */
2312 double y1; /* Coordinate of second point */
2313 double lseg; /* Segment length */
2314 size_t lp; /* Index of last point */
2315 int back = 0;
2316
2317 if (NULL != (pobj->det).p.p) {
2318 if ((uint16_t)1U < (pobj->det).p.n) {
2319 back = 1;
2320 /*
2321 For polyline check whether first and last segment
2322 are long enough for arrowhead cuts.
2323 */
2324 if (WXD_OT_POLYLINE == pobj->ot) {
2325 lseg = 0.0;
2326 if (0 != (pobj->ab).type) {
2327 x0 = ((pobj->det).p.p)[0].x;
2328 x1 = ((pobj->det).p.p)[1].x;
2329 y0 = ((pobj->det).p.p)[0].y;
2330 y1 = ((pobj->det).p.p)[1].y;
2331 x1 = x1 - x0;
2332 y1 = y1 - y0;
2333 lseg = sqrt(x1 * x1 + y1 * y1);
2334 if (lseg <= (pobj->ab).cut) {
2335 back = 0;
2336 /* ERROR: First segment too short */
2337 dk4app_log_1(
2338 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 57
2339 );
2340 }
2341 }
2342 if (0 != (pobj->af).type) {
2343 lp = (pobj->det).p.n - 1U;
2344 x0 = ((pobj->det).p.p)[lp].x;
2345 x1 = ((pobj->det).p.p)[lp - 1].x;
2346 y0 = ((pobj->det).p.p)[lp].y;
2347 y1 = ((pobj->det).p.p)[lp - 1].y;
2348 x1 = x1 - x0;
2349 y1 = y1 - y0;
2350 /*
2351 Just one segment or multiple segments?
2352 */
2353 if ((uint16_t)2U == (pobj->det).p.n) {
2354 /*
2355 If the polyline has just one segment (only
2356 2 points) the cuts for forward and backward
2357 arrow are both applied to the same segment.
2358 So the segment must be longer than the summary
2359 of the two cuts.
2360 */
2361 lseg += sqrt(x1 * x1 + y1 * y1);
2362 }
2363 else {
2364 /* Polyline has more than one segments, the
2365 final segment is cutted for the forward
2366 arrowhead only.
2367 */
2368 lseg = sqrt(x1 * x1 + y1 * y1);
2369 }
2370 if (lseg <= (pobj->af).cut) {
2371 back = 0;
2372 /* ERROR: Last segment too short */
2373 dk4app_log_1(
2374 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 58
2375 );
2376 }
2377 }
2378 }
2379 }
2380 else {
2381 /* ERROR: Too few points */
2382 dk4app_log_1(
2383 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 59
2384 );
2385 }
2386 }
2387 else {
2388 /* ERROR: No points for object */
2389 dk4app_log_1(
2390 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 60
2391 );
2392 }
2393
2394 return back;
2395 }
2396
2397
2398 /** Check one spline object if information is complete and object
2399 can be drawn.
2400 @param drw Drawing structure.
2401 @param job Job structure.
2402 @param pobj Object to check.
2403 @return 1 on success (further handling possible), 0 otherwise.
2404 */
2405 static
2406 int
wxd2lout_check_one_spline_object(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2407 wxd2lout_check_one_spline_object(
2408 wxd_drawing_t *drw,
2409 wxd2lat_job_t *job,
2410 wxd_object_t *pobj
2411 )
2412 {
2413 double cutl; /* Length to cut, length of arrowhead */
2414 int back = 0;
2415
2416 if (NULL != (pobj->det).s.p) {
2417 if ((uint16_t)1U < (pobj->det).s.n) {
2418 back = 1;
2419 /*
2420 For open spline object check whether spline
2421 is long enough for arrowhead cuts.
2422 */
2423 if (WXD_OT_O_SPLINE == pobj->ot) {
2424 if (
2425 (0 != (pobj->af).type)
2426 || (0 != (pobj->ab).type)
2427 ) {
2428 cutl = 0.0;
2429 if (0 != (pobj->af).type) {
2430 cutl += ((pobj->af).cut + (pobj->af).cuttol);
2431 }
2432 if (0 != (pobj->ab).type) {
2433 cutl += ((pobj->ab).cut + (pobj->ab).cuttol);
2434 }
2435 if (cutl >= (pobj->det).s.suml) {
2436 back = 0;
2437 /* ERROR: Spline too short */
2438 dk4app_log_1(
2439 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 61
2440 );
2441 }
2442 if (0 != (pobj->af).type) {
2443 cutl = (pobj->af).offset
2444 + (double)((pobj->af).length)
2445 * wxd2lat_object_linewidth(pobj, drw, job);
2446 if (cutl >= (pobj->det).s.suml) {
2447 back = 0;
2448 /* ERROR: Forward arrow too long */
2449 dk4app_log_1(
2450 job->app, job->msg, job->sz_msg,
2451 DK4_LL_ERROR, 62
2452 );
2453 }
2454 }
2455 if (0 != (pobj->ab).type) {
2456 cutl = (pobj->ab).offset
2457 + (double)((pobj->ab).length)
2458 * wxd2lat_object_linewidth(pobj, drw, job);
2459 if (cutl >= (pobj->det).s.suml) {
2460 back = 0;
2461 /* ERROR: Backward arrow too long */
2462 dk4app_log_1(
2463 job->app, job->msg, job->sz_msg,
2464 DK4_LL_ERROR, 63
2465 );
2466 }
2467 }
2468 }
2469 }
2470 }
2471 else {
2472 /* ERROR: Too few points */
2473 dk4app_log_1(
2474 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 59
2475 );
2476 }
2477 }
2478 else {
2479 /* ERROR: No points for object */
2480 dk4app_log_1(
2481 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 60
2482 );
2483 }
2484
2485 return back;
2486 }
2487
2488
2489
2490 /** Check one arc object if information is complete and object
2491 can be drawn.
2492 @param drw Drawing structure.
2493 @param job Job structure.
2494 @param pobj Object to check.
2495 @return 1 on success (further handling possible), 0 otherwise.
2496 */
2497 static
2498 int
wxd2lout_check_one_arc_object(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2499 wxd2lout_check_one_arc_object(
2500 wxd_drawing_t *drw,
2501 wxd2lat_job_t *job,
2502 wxd_object_t *pobj
2503 )
2504 {
2505
2506 double x0; /* Coordinate of first point */
2507 double y0; /* Coordinate of first point */
2508 double x1; /* Coordinate of second point */
2509 double y1; /* Coordinate of second point */
2510 double cutl; /* Length to cut, length of arrowhead */
2511 double lseg; /* Segment length */
2512 int back = 0;
2513
2514 /*
2515 For open arc object check whether arc is long enough
2516 for arrowhead cuts.
2517 For malformed arc check whether segments are long enough
2518 for the arrowhead cuts.
2519 */
2520 back = 1;
2521 if (WXD_OT_O_ARC == pobj->ot) {
2522 if ((0 != (pobj->af).type) || (0 != (pobj->ab).type)) {
2523 if (0 != (pobj->det).a.d) {
2524 /*
2525 Real arc
2526 */
2527 lseg = fabs(
2528 (pobj->det).a.r
2529 * ((pobj->det).a.b - (pobj->det).a.a)
2530 );
2531 cutl = 0.0;
2532 if (0 != (pobj->af).type) {
2533 cutl = (pobj->af).cut;
2534 }
2535 if (0 != (pobj->ab).type) {
2536 cutl += (pobj->ab).cut;
2537 }
2538 if (cutl > lseg) {
2539 back = 0;
2540 /* ERROR: Arc too short for arrows */
2541 dk4app_log_1(
2542 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 64
2543 );
2544 }
2545 if (0 != (pobj->af).type) {
2546 cutl = (pobj->af).offset
2547 + (double)((pobj->af).length)
2548 * wxd2lat_object_linewidth(pobj, drw, job);
2549 if (cutl > lseg) {
2550 back = 0;
2551 /* ERROR: Forward arrow too long */
2552 dk4app_log_1(
2553 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 62
2554 );
2555 }
2556 }
2557 if (0 != (pobj->ab).type) {
2558 cutl = (pobj->ab).offset
2559 + (double)((pobj->ab).length)
2560 * wxd2lat_object_linewidth(pobj, drw, job);
2561 if (cutl > lseg) {
2562 back = 0;
2563 /* ERROR: Backward arrow too long */
2564 dk4app_log_1(
2565 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 63
2566 );
2567 }
2568 }
2569 }
2570 else {
2571 /* Malformed arc drawn as polyline
2572 */
2573 if (0 != (pobj->af).type) {
2574 x0 = wxd2lout_convert_x(drw,job,(double)((pobj->det).a.x2));
2575 y0 = wxd2lout_convert_y(drw,job,(double)((pobj->det).a.y2));
2576 x1 = wxd2lout_convert_x(drw,job,(double)((pobj->det).a.x3));
2577 y1 = wxd2lout_convert_y(drw,job,(double)((pobj->det).a.y3));
2578 x1 = x1 - x0;
2579 y1 = y1 - y0;
2580 lseg = sqrt(x1 * x1 + y1 * y1);
2581 if (lseg <= (pobj->af).cut) {
2582 back = 0;
2583 /* ERROR: Forward arrow too long */
2584 dk4app_log_1(
2585 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 62
2586 );
2587 }
2588 }
2589 if (0 != (pobj->ab).type) {
2590 x0 = wxd2lout_convert_x(drw,job,(double)((pobj->det).a.x2));
2591 y0 = wxd2lout_convert_y(drw,job,(double)((pobj->det).a.y2));
2592 x1 = wxd2lout_convert_x(drw,job,(double)((pobj->det).a.x1));
2593 y1 = wxd2lout_convert_y(drw,job,(double)((pobj->det).a.y1));
2594 x1 = x1 - x0;
2595 y1 = y1 - y0;
2596 lseg = sqrt(x1 * x1 + y1 * y1);
2597 if (lseg <= (pobj->ab).cut) {
2598 back = 0;
2599 /* ERROR: Backward arrow too long */
2600 dk4app_log_1(
2601 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 63
2602 );
2603 }
2604 }
2605 }
2606 }
2607 }
2608
2609 return back;
2610 }
2611
2612
2613
2614 /** Check one circle object if information is complete and object
2615 can be drawn.
2616 @param job Job structure.
2617 @param pobj Object to check.
2618 @return 1 on success (further handling possible), 0 otherwise.
2619 */
2620 static
2621 int
wxd2lout_check_one_circle_object(wxd2lat_job_t * job,wxd_object_t * pobj)2622 wxd2lout_check_one_circle_object(
2623 wxd2lat_job_t *job,
2624 wxd_object_t *pobj
2625 )
2626 {
2627 int back = 0;
2628
2629 if (0.0 < (pobj->det).e.rx) {
2630 back = 1;
2631 }
2632 else {
2633 /* ERROR: Radius 0 */
2634 dk4app_log_1(
2635 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 65
2636 );
2637 }
2638
2639 return back;
2640 }
2641
2642
2643
2644 /** Check one ellipse object if information is complete and object
2645 can be drawn.
2646 @param job Job structure.
2647 @param pobj Object to check.
2648 @return 1 on success (further handling possible), 0 otherwise.
2649 */
2650 static
2651 int
wxd2lout_check_one_ellipse_object(wxd2lat_job_t * job,wxd_object_t * pobj)2652 wxd2lout_check_one_ellipse_object(
2653 wxd2lat_job_t *job,
2654 wxd_object_t *pobj
2655 )
2656 {
2657 int back = 0;
2658
2659 if ((0.0 < (pobj->det).e.rx) && (0.0 < (pobj->det).e.ry)) {
2660 back = 1;
2661 }
2662 else {
2663 /* ERROR: Radius 0 */
2664 dk4app_log_1(
2665 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 65
2666 );
2667 }
2668
2669 return back;
2670 }
2671
2672
2673
2674 /** Check one box object if information is complete and object
2675 can be drawn.
2676 @param job Job structure.
2677 @param pobj Object to check.
2678 @return 1 on success (further handling possible), 0 otherwise.
2679 */
2680 static
2681 int
wxd2lout_check_one_box_object(wxd2lat_job_t * job,wxd_object_t * pobj)2682 wxd2lout_check_one_box_object(
2683 wxd2lat_job_t *job,
2684 wxd_object_t *pobj
2685 )
2686 {
2687 double w;
2688 double h;
2689 int back = 1;
2690
2691 w = fabs((pobj->det).b.xr - (pobj->det).b.xl);
2692 h = fabs((pobj->det).b.yt - (pobj->det).b.yb);
2693 if (h < w) {
2694 w = h;
2695 }
2696 if ((pobj->det).b.r > (w / 2.0)) {
2697 back = 0;
2698 /* ERROR: Box radius too large */
2699 dk4app_log_1(
2700 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 66
2701 );
2702 }
2703
2704 return back;
2705 }
2706
2707
2708
2709 /** Check one dot object if information is complete and object
2710 can be drawn.
2711 @param job Job structure.
2712 @param pobj Object to check.
2713 @return 1 on success (further handling possible), 0 otherwise.
2714 */
2715 static
2716 int
wxd2lout_check_one_dot_object(wxd2lat_job_t * job,wxd_object_t * pobj)2717 wxd2lout_check_one_dot_object(
2718 wxd2lat_job_t *job,
2719 wxd_object_t *pobj
2720 )
2721 {
2722 int back = 0;
2723
2724 if (0.0 < (pobj->det).d.d) {
2725 back = 1;
2726 }
2727 else {
2728 /* ERROR: Diameter 0 */
2729 dk4app_log_1(
2730 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 67
2731 );
2732 }
2733
2734 return back;
2735 }
2736
2737
2738
2739 /** Check one image object if information is complete and object
2740 can be drawn.
2741 @param job Job structure.
2742 @param pobj Object to check.
2743 @return 1 on success (further handling possible), 0 otherwise.
2744 */
2745 static
2746 int
wxd2lout_check_one_image_object(wxd2lat_job_t * job,wxd_object_t * pobj)2747 wxd2lout_check_one_image_object(
2748 wxd2lat_job_t *job,
2749 wxd_object_t *pobj
2750 )
2751 {
2752 int back = 0;
2753
2754 if (NULL != (pobj->det).i.fn) {
2755 if ((0.0 < (pobj->det).i.w) && (0.0 < (pobj->det).i.h)) {
2756 back = 1;
2757 }
2758 else {
2759 /* ERROR: Width and height must be positive */
2760 dk4app_log_1(
2761 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 68
2762 );
2763 }
2764 }
2765 else {
2766 /* ERROR: No file name */
2767 dk4app_log_1(
2768 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 69
2769 );
2770 }
2771
2772 return back;
2773 }
2774
2775
2776
2777 /** Check one graphics object if information is complete and object
2778 can be drawn.
2779 @param drw Drawing structure.
2780 @param job Job structure.
2781 @param pobj Object to check.
2782 @return 1 on success (further handling possible), 0 otherwise.
2783 */
2784 static
2785 int
wxd2lout_check_one_graphics_object(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2786 wxd2lout_check_one_graphics_object(
2787 wxd_drawing_t *drw,
2788 wxd2lat_job_t *job,
2789 wxd_object_t *pobj
2790 )
2791 {
2792 int back = 0;
2793
2794 switch (pobj->ot) {
2795 case WXD_OT_TEXT : {
2796 back = wxd2lout_check_one_text_object(job, pobj);
2797 } break;
2798 case WXD_OT_POLYLINE : case WXD_OT_POLYGON : {
2799 back = wxd2lout_check_one_polyline_object(job, pobj);
2800 } break;
2801 case WXD_OT_O_SPLINE : case WXD_OT_C_SPLINE : {
2802 back = wxd2lout_check_one_spline_object(drw, job, pobj);
2803 } break;
2804 case WXD_OT_O_ARC : case WXD_OT_C_ARC : {
2805 back = wxd2lout_check_one_arc_object(drw, job, pobj);
2806 } break;
2807 case WXD_OT_CIRCLE : {
2808 back = wxd2lout_check_one_circle_object(job, pobj);
2809 } break;
2810 case WXD_OT_ELLIPSE : {
2811 back = wxd2lout_check_one_ellipse_object(job, pobj);
2812 } break;
2813 case WXD_OT_BOX : {
2814 back = wxd2lout_check_one_box_object(job, pobj);
2815 } break;
2816 case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : {
2817 back = wxd2lout_check_one_dot_object(job, pobj);
2818 } break;
2819 case WXD_OT_IMAGE : {
2820 back = wxd2lout_check_one_image_object(job, pobj);
2821 } break;
2822 default : {
2823 /* ERROR: Illegal object type */
2824 dk4app_log_1(
2825 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 70
2826 );
2827 } break;
2828 }
2829 if (0 == back) {
2830 /* ERROR: Object check failed */
2831 dk4app_log_1(
2832 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 71
2833 );
2834 }
2835
2836 return back;
2837 }
2838
2839
2840
2841 static
2842 int
wxd2lout_is_abnormal_circle(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2843 wxd2lout_is_abnormal_circle(
2844 wxd_drawing_t *drw,
2845 wxd2lat_job_t *job,
2846 wxd_object_t *pobj
2847 )
2848 {
2849 double lw;
2850 int back = 0;
2851
2852 lw = wxd2lat_object_linewidth(pobj, drw, job);
2853 if ((pobj->det).e.rx <= (lw / 2.0)) {
2854 back = 1;
2855 }
2856
2857 return back;
2858 }
2859
2860
2861
2862 /** Check whether circle is abnormal (diameter smaller than line width).
2863 @param drw Drawing structure.
2864 @param job Job structure.
2865 @param pobj Object to check.
2866 @return 1 for abnormal circle, 0 for normal circle.
2867 */
2868 static
2869 int
wxd2lout_abnormal_circle(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2870 wxd2lout_abnormal_circle(
2871 wxd_drawing_t *drw,
2872 wxd2lat_job_t *job,
2873 wxd_object_t *pobj
2874 )
2875 {
2876 dk4_er_t er;
2877 double lw;
2878 int back = 1;
2879
2880 lw = wxd2lat_object_linewidth(pobj, drw, job);
2881 dk4error_init(&er);
2882 dk4pppt_set_fill_rgb(
2883 job->ppp,
2884 (((double)(pobj->sc[0])) / 255.0),
2885 (((double)(pobj->sc[1])) / 255.0),
2886 (((double)(pobj->sc[2])) / 255.0),
2887 &back, &er
2888 );
2889 dk4pppt_prepare_fill(job->ppp, &back, &er);
2890 dk4pppt_circle(
2891 job->ppp, (pobj->det).e.x, (pobj->det).e.y,
2892 ((pobj->det).e.rx + lw / 2.0), NULL, &back, &er
2893 );
2894 dk4pppt_fill(job->ppp, &back, &er);
2895
2896 return back;
2897 }
2898
2899
2900
2901 /** Draw abnormal stroked circle as filled circle.
2902 @param drw Drawing structure.
2903 @param job Job structure.
2904 @param pobj Circle object to draw.
2905 @return 1 on success, 0 on error.
2906 */
2907 static
2908 int
wxd2lout_is_abnormal_ellipse(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2909 wxd2lout_is_abnormal_ellipse(
2910 wxd_drawing_t *drw,
2911 wxd2lat_job_t *job,
2912 wxd_object_t *pobj
2913 )
2914 {
2915 double lw;
2916 int back = 0;
2917
2918 lw = wxd2lat_object_linewidth(pobj, drw, job) / 2.0;
2919 if (((pobj->det).e.rx <= lw) || ((pobj->det).e.ry <= lw)) {
2920 back = 1;
2921 }
2922
2923 return back;
2924 }
2925
2926
2927
2928 /** Check whether ellipse is abnormal (one diameter smaller than line width).
2929 @param drw Drawing structure.
2930 @param job Job structure.
2931 @param pobj Ellipse object to check.
2932 @return 1 for abnormal ellipse, 0 for normal ellipse.
2933 */
2934 static
2935 int
wxd2lout_abnormal_ellipse(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2936 wxd2lout_abnormal_ellipse(
2937 wxd_drawing_t *drw,
2938 wxd2lat_job_t *job,
2939 wxd_object_t *pobj
2940 )
2941 {
2942 dk4_er_t er;
2943 double lw;
2944 int back = 1;
2945
2946 lw = wxd2lat_object_linewidth(pobj, drw, job);
2947 dk4error_init(&er);
2948 dk4pppt_set_fill_rgb(
2949 job->ppp,
2950 (((double)(pobj->sc[0])) / 255.0),
2951 (((double)(pobj->sc[1])) / 255.0),
2952 (((double)(pobj->sc[2])) / 255.0),
2953 &back, &er
2954 );
2955 dk4pppt_prepare_fill(job->ppp, &back, &er);
2956 dk4pppt_ellipse(
2957 job->ppp, (pobj->det).e.x, (pobj->det).e.y,
2958 ((pobj->det).e.rx + lw / 2.0), ((pobj->det).e.ry + lw / 2.0),
2959 (pobj->det).e.a, NULL, &back, &er
2960 );
2961 dk4pppt_fill(job->ppp, &back, &er);
2962
2963 return back;
2964 }
2965
2966
2967
2968 static
2969 int
wxd2lout_is_abnormal_box(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2970 wxd2lout_is_abnormal_box(
2971 wxd_drawing_t *drw,
2972 wxd2lat_job_t *job,
2973 wxd_object_t *pobj
2974 )
2975 {
2976 double lw;
2977 int back = 0;
2978
2979 lw = wxd2lat_object_linewidth(pobj, drw, job);
2980 if (
2981 (lw >= fabs((pobj->det).b.xr - (pobj->det).b.xl))
2982 || (lw >= fabs((pobj->det).b.yt - (pobj->det).b.yb))
2983 ) {
2984 back = 1;
2985 }
2986
2987 return back;
2988 }
2989
2990
2991
2992 static
2993 int
wxd2lout_abnormal_box(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)2994 wxd2lout_abnormal_box(
2995 wxd_drawing_t *drw,
2996 wxd2lat_job_t *job,
2997 wxd_object_t *pobj
2998 )
2999 {
3000 dk4_er_t er;
3001 double lw;
3002 double xl;
3003 double xr;
3004 double yt;
3005 double yb;
3006 double ra;
3007 double dx;
3008 double dy;
3009 int back = 1;
3010
3011 lw = wxd2lat_object_linewidth(pobj, drw, job) / 2.0;
3012 dk4error_init(&er);
3013 dk4pppt_set_fill_rgb(
3014 job->ppp,
3015 (((double)(pobj->sc[0])) / 255.0),
3016 (((double)(pobj->sc[1])) / 255.0),
3017 (((double)(pobj->sc[2])) / 255.0),
3018 &back, &er
3019 );
3020
3021 dk4pppt_prepare_fill(job->ppp, &back, &er);
3022
3023 if ((pobj->det).b.xr >= (pobj->det).b.xl) {
3024 xl = (pobj->det).b.xl - lw;
3025 xr = (pobj->det).b.xr + lw;
3026 }
3027 else {
3028 xl = (pobj->det).b.xr - lw;
3029 xr = (pobj->det).b.xl + lw;
3030 }
3031 if ((pobj->det).b.yt >= (pobj->det).b.yb) {
3032 yb = (pobj->det).b.yb - lw;
3033 yt = (pobj->det).b.yt + lw;
3034 }
3035 else {
3036 yb = (pobj->det).b.yt - lw;
3037 yt = (pobj->det).b.yb + lw;
3038 }
3039 if (0.0 < (pobj->det).b.r) {
3040 ra = (pobj->det).b.r + lw;
3041 dx = fabs(xr - xl);
3042 dy = fabs(yb - yt);
3043 if (dy < dx) { dx = dy; }
3044 dx *= 0.4998;
3045 if (dx < ra) {
3046 ra = dx;
3047 }
3048 }
3049 else {
3050 ra = -1.0;
3051 }
3052 dk4pppt_rectangle(job->ppp, xl, xr, yb, yt, ra, NULL, &back, &er);
3053
3054 dk4pppt_fill(job->ppp, &back, &er);
3055
3056 return back;
3057 }
3058
3059
3060
3061
3062 /** Draw one graphics object.
3063 @param drw Drawing structure.
3064 @param job Job structure.
3065 @param pobj Graphics object to draw.
3066 @return 1 on success, 0 on error.
3067 */
3068 static
3069 int
wxd2lout_one_graphics_object(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)3070 wxd2lout_one_graphics_object(
3071 wxd_drawing_t *drw,
3072 wxd2lat_job_t *job,
3073 wxd_object_t *pobj
3074 )
3075 {
3076 int back = 1;
3077
3078
3079 if (0 != wxd2lout_check_one_graphics_object(drw, job, pobj)) {
3080 switch (pobj->ot) {
3081 case WXD_OT_TEXT : {
3082 back = wxd2lout_text_object(job, pobj);
3083 } break;
3084 case WXD_OT_POLYLINE : case WXD_OT_O_SPLINE : case WXD_OT_O_ARC : {
3085 back = wxd2lout_open_path_object(drw, job, pobj);
3086 } break;
3087 case WXD_OT_POLYGON : case WXD_OT_C_SPLINE : case WXD_OT_C_ARC : {
3088 back = wxd2lout_closed_path_object(drw, job, pobj);
3089 } break;
3090 case WXD_OT_CIRCLE : {
3091 if (0 != wxd2lout_is_abnormal_circle(drw, job, pobj)) {
3092 back = wxd2lout_abnormal_circle(drw, job, pobj);
3093 }
3094 else {
3095 back = wxd2lout_closed_path_object(drw, job, pobj);
3096 }
3097 } break;
3098 case WXD_OT_ELLIPSE : {
3099 if (0 != wxd2lout_is_abnormal_ellipse(drw, job, pobj)) {
3100 back = wxd2lout_abnormal_ellipse(drw, job, pobj);
3101 }
3102 else {
3103 back = wxd2lout_closed_path_object(drw, job, pobj);
3104 }
3105 } break;
3106 case WXD_OT_BOX : {
3107 if (0 != wxd2lout_is_abnormal_box(drw, job, pobj)) {
3108 back = wxd2lout_abnormal_box(drw, job, pobj);
3109 }
3110 else {
3111 back = wxd2lout_closed_path_object(drw, job, pobj);
3112 }
3113 } break;
3114 case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : {
3115
3116 back = wxd2lout_dot_object(drw, job, pobj);
3117 } break;
3118 case WXD_OT_IMAGE : {
3119 back = wxd2lout_image_object(job, pobj);
3120 } break;
3121 }
3122 if (0 == back) {
3123 /* ERROR: Failed to write graphics object */
3124 dk4app_log_1(
3125 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 72
3126 );
3127 }
3128 }
3129 else {
3130 back = 0;
3131 }
3132
3133 return back;
3134 }
3135
3136
3137
3138 /** Create output for all graphics objects in a drawing.
3139 @param drw Original drawing.
3140 @param job Job structure containing the output structure.
3141 @return 1 on success, 0 on error.
3142 */
3143 static
3144 int
wxd2lout_all_graphics_objects(wxd_drawing_t * drw,wxd2lat_job_t * job)3145 wxd2lout_all_graphics_objects(
3146 wxd_drawing_t *drw,
3147 wxd2lat_job_t *job
3148 )
3149 {
3150 wxd_object_t *pobj;
3151 dk4_um_t oldline;
3152 int back = 1;
3153
3154
3155 oldline = dk4app_get_log_source_line(job->app);
3156 dk4sto_it_reset(drw->i_flat);
3157 do {
3158 pobj = (wxd_object_t *)dk4sto_it_next(drw->i_flat);
3159 if (NULL != pobj) {
3160 dk4app_set_log_source_line(job->app, pobj->lino);
3161 if (0 == wxd2lout_one_graphics_object(drw, job, pobj)) {
3162 back = 0;
3163 }
3164 }
3165 } while (NULL != pobj);
3166 dk4app_set_log_source_line(job->app, oldline);
3167
3168 return back;
3169 }
3170
3171
3172
3173 static
3174 int
wxd2lout_check_arrows(wxd_drawing_t * drw,wxd2lat_job_t * job,wxd_object_t * pobj)3175 wxd2lout_check_arrows(
3176 wxd_drawing_t *drw,
3177 wxd2lat_job_t *job,
3178 wxd_object_t *pobj
3179 )
3180 {
3181 int back = 1;
3182
3183 if ((uint8_t)0U != (pobj->af).type) {
3184 if (0 == wxd2lah_one_arrowhead(&(pobj->af), pobj, drw, job)) {
3185 back = 0;
3186 /* ERROR: Forward arrow calculation failed */
3187 dk4app_log_1(
3188 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 73
3189 );
3190 }
3191 }
3192 if ((uint8_t)0U != (pobj->ab).type) {
3193 if (0 == wxd2lah_one_arrowhead(&(pobj->ab), pobj, drw, job)) {
3194 back = 0;
3195 /* ERROR: Backward arrow calculation failed */
3196 dk4app_log_1(
3197 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 74
3198 );
3199 }
3200 }
3201
3202 return back;
3203 }
3204
3205
3206
3207 static
3208 int
wxd2out_all_calculations(wxd_drawing_t * drw,wxd2lat_job_t * job)3209 wxd2out_all_calculations(wxd_drawing_t *drw, wxd2lat_job_t *job)
3210 {
3211 wxd_object_t *pobj;
3212 dk4_um_t oldline;
3213 int back = 1;
3214 int myback = 0;
3215 uint16_t u16;
3216
3217 oldline = dk4app_get_log_source_line(job->app);
3218 dk4sto_it_reset(drw->i_flat);
3219 do {
3220 pobj = (wxd_object_t *)dk4sto_it_next(drw->i_flat);
3221 if (NULL != pobj) {
3222 dk4app_set_log_source_line(job->app, pobj->lino);
3223 switch (pobj->ot) {
3224 case WXD_OT_TEXT : {
3225 (pobj->det).t.x =
3226 wxd2lout_convert_x(drw, job, (pobj->det).t.x);
3227 (pobj->det).t.y =
3228 wxd2lout_convert_y(drw, job, (pobj->det).t.y);
3229 #if 0
3230 (pobj->det).t.a = (M_PI * (pobj->det).t.a) / 180.0;
3231 #endif
3232 } break;
3233 case WXD_OT_POLYLINE : {
3234 u16 = (uint16_t)0U;
3235 if ((NULL != (pobj->det).p.p) && (u16 < (pobj->det).p.n)) {
3236 for (u16 = (uint16_t)0U; u16 < (pobj->det).p.n; u16++) {
3237 ((pobj->det).p.p)[u16].x =
3238 wxd2lout_convert_x(
3239 drw, job, ((pobj->det).p.p)[u16].x
3240 );
3241 ((pobj->det).p.p)[u16].y =
3242 wxd2lout_convert_y(
3243 drw, job, ((pobj->det).p.p)[u16].y
3244 );
3245 }
3246 }
3247 if (0 == wxd2lout_check_arrows(drw, job, pobj)) {
3248 /* Errors already reported */
3249 back = 0;
3250 }
3251 } break;
3252 case WXD_OT_O_SPLINE : {
3253 u16 = (uint16_t)0U;
3254 if ((NULL != (pobj->det).s.p) && (u16 < (pobj->det).s.n)) {
3255 for (u16 = (uint16_t)0U; u16 < (pobj->det).s.n; u16++) {
3256 ((pobj->det).s.p)[u16].x =
3257 wxd2lout_convert_x(
3258 drw, job, ((pobj->det).s.p)[u16].x
3259 );
3260 ((pobj->det).s.p)[u16].y =
3261 wxd2lout_convert_y(
3262 drw, job, ((pobj->det).s.p)[u16].y
3263 );
3264 }
3265 }
3266 if (0 == wxd2lout_check_arrows(drw, job, pobj)) {
3267 /* Errors already reported */
3268 back = 0;
3269 }
3270 if (
3271 ((uint8_t)0U != (pobj->af).type)
3272 || ((uint8_t)0U != (pobj->ab).type)
3273 ) {
3274 (pobj->det).s.ts = -1.0;
3275 (pobj->det).s.te = -1.0;
3276 myback = 1;
3277 wxd2lxs_calculate_spline_segments(job, pobj, &myback);
3278 if (0 == myback) {
3279 back = 0;
3280 /* ERROR: Spline segment calculation failed */
3281 dk4app_log_1(
3282 job->app, job->msg, job->sz_msg,
3283 DK4_LL_ERROR, 75
3284 );
3285 }
3286 }
3287 } break;
3288 case WXD_OT_O_ARC : {
3289 (pobj->det).a.x =
3290 wxd2lout_convert_x(drw, job, (pobj->det).a.x);
3291 (pobj->det).a.y =
3292 wxd2lout_convert_y(drw, job, (pobj->det).a.y);
3293
3294 (pobj->det).a.r =
3295 wxd2lout_convert_r((pobj->det).a.r);
3296 if (0 == wxd2lout_check_arrows(drw, job, pobj)) {
3297 /* Errors already reported */
3298 back = 0;
3299 }
3300 } break;
3301 case WXD_OT_POLYGON : {
3302 u16 = (uint16_t)0U;
3303 if ((NULL != (pobj->det).p.p) && (u16 < (pobj->det).p.n)) {
3304 for (u16 = (uint16_t)0U; u16 < (pobj->det).p.n; u16++) {
3305 ((pobj->det).p.p)[u16].x =
3306 wxd2lout_convert_x(
3307 drw, job, ((pobj->det).p.p)[u16].x
3308 );
3309 ((pobj->det).p.p)[u16].y =
3310 wxd2lout_convert_y(
3311 drw, job, ((pobj->det).p.p)[u16].y
3312 );
3313 }
3314 }
3315 } break;
3316 case WXD_OT_C_SPLINE : {
3317 u16 = (uint16_t)0U;
3318 if ((NULL != (pobj->det).s.p) && (u16 < (pobj->det).s.n)) {
3319 for (u16 = (uint16_t)0U; u16 < (pobj->det).s.n; u16++) {
3320 ((pobj->det).s.p)[u16].x =
3321 wxd2lout_convert_x(
3322 drw, job, ((pobj->det).s.p)[u16].x
3323 );
3324 ((pobj->det).s.p)[u16].y =
3325 wxd2lout_convert_y(
3326 drw, job, ((pobj->det).s.p)[u16].y
3327 );
3328 }
3329 }
3330 } break;
3331 case WXD_OT_C_ARC : {
3332 (pobj->det).a.x =
3333 wxd2lout_convert_x(drw, job, (pobj->det).a.x);
3334 (pobj->det).a.y =
3335 wxd2lout_convert_y(drw, job, (pobj->det).a.y);
3336
3337 (pobj->det).a.r =
3338 wxd2lout_convert_r((pobj->det).a.r);
3339 } break;
3340 case WXD_OT_CIRCLE : case WXD_OT_ELLIPSE : {
3341 (pobj->det).e.x =
3342 wxd2lout_convert_x(drw, job, (pobj->det).e.x);
3343 (pobj->det).e.y =
3344 wxd2lout_convert_y(drw, job, (pobj->det).e.y);
3345
3346 (pobj->det).e.rx =
3347 wxd2lout_convert_r((pobj->det).e.rx);
3348
3349
3350 (pobj->det).e.ry =
3351 wxd2lout_convert_r((pobj->det).e.ry);
3352
3353 } break;
3354 case WXD_OT_BOX : {
3355
3356
3357
3358
3359
3360 (pobj->det).b.xl =
3361 wxd2lout_convert_x(drw, job, (pobj->det).b.xl);
3362 (pobj->det).b.xr =
3363 wxd2lout_convert_x(drw, job, (pobj->det).b.xr);
3364 (pobj->det).b.yb =
3365 wxd2lout_convert_y(drw, job, (pobj->det).b.yb);
3366 (pobj->det).b.yt =
3367 wxd2lout_convert_y(drw, job, (pobj->det).b.yt);
3368 if (0.0 < (pobj->det).b.r) {
3369
3370 (pobj->det).b.r = wxd2lout_convert_r((pobj->det).b.r);
3371 }
3372
3373
3374
3375
3376
3377 } break;
3378 case WXD_OT_IMAGE : {
3379 (pobj->det).i.x =
3380 wxd2lout_convert_x(drw, job, (pobj->det).i.x);
3381 (pobj->det).i.y =
3382 wxd2lout_convert_y(drw, job, (pobj->det).i.y);
3383
3384
3385 (pobj->det).i.w = wxd2lout_convert_r((pobj->det).i.w);
3386 (pobj->det).i.h = wxd2lout_convert_r((pobj->det).i.h);
3387
3388 } break;
3389 case WXD_OT_DOT_FILLED : case WXD_OT_DOT_WHITE : {
3390 (pobj->det).d.x =
3391 wxd2lout_convert_x(drw, job, (pobj->det).d.x);
3392 (pobj->det).d.y =
3393 wxd2lout_convert_y(drw, job, (pobj->det).d.y);
3394
3395 if (0.0 < job->baselw) {
3396 (pobj->det).d.d *= job->baselw;
3397 }
3398 else {
3399 (pobj->det).d.d *= drw->baselw;
3400 }
3401
3402 } break;
3403 }
3404 }
3405 } while (NULL != pobj);
3406 dk4app_set_log_source_line(job->app, oldline);
3407
3408 return back;
3409 }
3410
3411
3412
3413 void
wxd2lat_output(wxd_drawing_t * drw,wxd2lat_job_t * job,const dkChar * fn)3414 wxd2lat_output(wxd_drawing_t *drw, wxd2lat_job_t *job, const dkChar *fn)
3415 {
3416 dk4_er_t er;
3417 dk4_pppt_driver_t dr;
3418 int flags = 0;
3419 int ok = 0;
3420
3421
3422 /*
3423 Calculate image width and coordinates shift values.
3424 */
3425 if (0 == wxd2lout_prepare_job(drw, job, fn)) {
3426 /* All errors already reported */
3427 job->exval = EXIT_FAILURE;
3428 goto finished;
3429 }
3430 /* Convert coordinates to bp, pre-calculate arrowhead data.
3431 */
3432 if (0 == wxd2out_all_calculations(drw, job)) {
3433 /* All errors already reported */
3434 job->exval = EXIT_FAILURE;
3435 goto finished;
3436 }
3437 /* Open output structure
3438 */
3439 dr = DK4_PPPT_DR_PDF_TEX;
3440 switch ((job->grco).driver) {
3441 #if 0
3442 case DK4_GRA_DRIVER_PDF : {
3443 dr = DK4_PPPT_DR_PDF_TEX;
3444 } break;
3445 #endif
3446 case DK4_GRA_DRIVER_PS : case DK4_GRA_DRIVER_EPS : {
3447 dr = DK4_PPPT_DR_EPS_TEX;
3448 } break;
3449 case DK4_GRA_DRIVER_PGF : {
3450 dr = DK4_PPPT_DR_PGF;
3451 } break;
3452 }
3453 if (0 == job->whitebg) {
3454 flags |= DK4_GRA_PAGE_FLAG_NO_BG;
3455 }
3456 if (0 == (job->grco).color) {
3457 flags |= DK4_GRA_DOC_FLAG_FORCE_GRAY;
3458 }
3459 if (DK4_PPPT_DR_EPS_TEX == dr) {
3460 if (2 == (job->grco).ps_level) {
3461 flags |= DK4_GRA_DOC_FLAG_PS2;
3462 }
3463 if (0 != (job->grco).ps_dsc) {
3464 flags |= DK4_GRA_DOC_FLAG_PS_DSC;
3465 }
3466 if (DK4_GRA_DRIVER_EPS == (job->grco).driver) {
3467 flags |= DK4_GRA_DOC_FLAG_EPS;
3468 }
3469 }
3470 dk4error_init(&er);
3471 job->ppp = dk4pppt_open(
3472 job->fno1, dr,
3473 ((DK4_GRA_PURPOSE_DOCUMENT == (job->grco).purpose) ? (1) : (0)),
3474 flags, job->szwidth, job->szheight, &er
3475 );
3476 if (NULL == job->ppp) {
3477 /* ERROR: Failed to open output structure */
3478 dk4app_log_1(
3479 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 76
3480 );
3481 job->exval = EXIT_FAILURE;
3482 goto finished;
3483 }
3484 dk4pppt_set_gs_for_pattern_only(job->ppp, 1, NULL);
3485 if (0.0 < job->patlw) {
3486 dk4pppt_set_pattern_line_width(job->ppp, job->patlw);
3487 }
3488 else {
3489 dk4pppt_set_pattern_line_width(job->ppp, 0.45);
3490 }
3491 /*
3492 Clip if shiftx and/or shifty is used
3493 */
3494 if (0 == wxd2lout_clip_to_used_region(job)) {
3495 /* All errors already reported */
3496 job->exval = EXIT_FAILURE;
3497 goto finished;
3498 }
3499 /* Draw all graphics objects
3500 */
3501 if (0 == wxd2lout_all_graphics_objects(drw, job)) {
3502 /* All errors already reported */
3503 job->exval = EXIT_FAILURE;
3504 goto finished;
3505 }
3506
3507 /* Finally indicate success
3508 */
3509 ok = 1;
3510
3511 /* Produce output files if success so far, clean up
3512 */
3513 finished:
3514 if (NULL != job->ppp) {
3515 if (0 != ok) {
3516 dk4error_init(&er);
3517 ok = dk4pppt_write_and_close(job->ppp, &er);
3518 if (0 == ok) {
3519 /* ERROR: Failed to write output */
3520 dk4app_log_1(
3521 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 77
3522 );
3523 job->exval = EXIT_FAILURE;
3524 }
3525 }
3526 else {
3527 dk4pppt_close(job->ppp);
3528 /* ERROR: Skipping output due to previous errors */
3529 dk4app_log_1(
3530 job->app, job->msg, job->sz_msg, DK4_LL_ERROR, 78
3531 );
3532 job->exval = EXIT_FAILURE;
3533 }
3534 }
3535 job->ppp = NULL;
3536
3537 }
3538
3539
3540
3541 /* vim: set ai sw=4 ts=4 : */
3542
3543