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