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