Now resets arrow sizes for illegal arrows.
[dia.git] / lib / arrows.c
blobcf15155690152c8d89277377a563b0c5965a1277
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include <config.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <glib.h>
24 #include <math.h>
25 #include "message.h"
27 #ifdef G_OS_WIN32
28 #include <float.h>
29 #define finite(d) _finite(d)
30 #endif
32 #ifdef __EMX__
33 #define finite(d) isfinite(d)
34 #endif
36 #include "arrows.h"
37 #include "diarenderer.h"
38 #include "intl.h"
40 struct menudesc arrow_types[] =
41 {{N_("None"),ARROW_NONE},
42 {N_("Lines"),ARROW_LINES},
43 {N_("Hollow Triangle"),ARROW_HOLLOW_TRIANGLE},
44 {N_("Filled Triangle"),ARROW_FILLED_TRIANGLE},
45 {N_("Unfilled Triangle"),ARROW_UNFILLED_TRIANGLE},
46 {N_("Hollow Diamond"),ARROW_HOLLOW_DIAMOND},
47 {N_("Filled Diamond"),ARROW_FILLED_DIAMOND},
48 {N_("Half Diamond"), ARROW_HALF_DIAMOND},
49 {N_("Half Head"),ARROW_HALF_HEAD},
50 {N_("Slashed Cross"),ARROW_SLASHED_CROSS},
51 {N_("Filled Ellipse"),ARROW_FILLED_ELLIPSE},
52 {N_("Hollow Ellipse"),ARROW_HOLLOW_ELLIPSE},
53 {N_("Filled Dot"),ARROW_FILLED_DOT},
54 {N_("Dimension Origin"),ARROW_DIMENSION_ORIGIN},
55 {N_("Blanked Dot"),ARROW_BLANKED_DOT},
56 {N_("Double Hollow Triangle"),ARROW_DOUBLE_HOLLOW_TRIANGLE},
57 {N_("Double Filled Triangle"),ARROW_DOUBLE_FILLED_TRIANGLE},
58 {N_("Filled Dot and Triangle"), ARROW_FILLED_DOT_N_TRIANGLE},
59 {N_("Filled Box"),ARROW_FILLED_BOX},
60 {N_("Blanked Box"),ARROW_BLANKED_BOX},
61 {N_("Slashed"),ARROW_SLASH_ARROW},
62 {N_("Integral Symbol"),ARROW_INTEGRAL_SYMBOL},
63 {N_("Crow Foot"),ARROW_CROW_FOOT},
64 {N_("Cross"),ARROW_CROSS},
65 {N_("1-or-many"),ARROW_ONE_OR_MANY},
66 {N_("0-or-many"),ARROW_NONE_OR_MANY},
67 {N_("1-or-0"),ARROW_ONE_OR_NONE},
68 {N_("1 exactly"),ARROW_ONE_EXACTLY},
69 {N_("Filled Concave"),ARROW_FILLED_CONCAVE},
70 {N_("Blanked Concave"),ARROW_BLANKED_CONCAVE},
71 {N_("Round"), ARROW_ROUNDED},
72 {N_("Open Round"), ARROW_OPEN_ROUNDED},
73 {N_("Backslash"),ARROW_BACKSLASH},
74 {N_("Infinite Line"),ARROW_THREE_DOTS},
75 {NULL,0}};
77 /**** prototypes ****/
78 static void
79 draw_empty_ellipse(DiaRenderer *renderer, Point *to, Point *from,
80 real length, real width, real linewidth,
81 Color *fg_color);
82 static void
83 calculate_double_arrow(Point *second_to, Point *second_from,
84 Point *to, Point *from, real length);
86 static void
87 draw_crow_foot(DiaRenderer *renderer, Point *to, Point *from,
88 real length, real width, real linewidth,
89 Color *fg_color,Color *bg_color);
90 static void
91 calculate_diamond(Point *poly/*[4]*/, Point *to, Point *from,
92 real length, real width);
94 /** The function calculate_arrow_point adjusts the placement of the line and
95 * the arrow, so that the arrow doesn't overshoot the connectionpoint and the
96 * line doesn't stick out the other end of the arrow.
97 * @param arrow An arrow to calculate adjustments for. The arrow type
98 * determins what adjustments are done..
99 * @param to Where the arrow points to (e.g. connection point)
100 * @param from Where the arrow points from (e.g. bezier control line end)
101 * @param move_arrow A place to return the new end point of the arrow head
102 * (i.e. where 'to' should be to render the arrow head well)
103 * @param move_line A place to return the new end point of the line (i.e.
104 * where 'to' should be to render the connecting line without
105 * leaving bits of its linewidth outside the arrow).
106 * @param linewidth The linewidth used for drawing both arrow and line.
108 void
109 calculate_arrow_point(const Arrow *arrow, const Point *to, const Point *from,
110 Point *move_arrow, Point *move_line,
111 real linewidth)
113 real add_len;
114 real angle;
115 Point tmp;
117 /* Otherwise line is drawn through arrow
118 * head for some hollow arrow heads
119 * */
120 if (linewidth == 0.0)
121 linewidth = 0.0001;
123 /* First, we move the arrow head backwards.
124 * This in most cases just accounts for the linewidth of the arrow.
125 * In pointy arrows, this means we must look at the angle of the
126 * arrowhead.
127 * */
128 switch (arrow->type) {
129 case ARROW_LINES:
130 case ARROW_HOLLOW_TRIANGLE:
131 case ARROW_UNFILLED_TRIANGLE:
132 case ARROW_FILLED_CONCAVE:
133 case ARROW_BLANKED_CONCAVE:
134 case ARROW_DOUBLE_HOLLOW_TRIANGLE:
135 if (arrow->width < 0.0000001) return;
136 angle = atan(arrow->length/(arrow->width/2));
137 if (angle < 75*2*G_PI/360.0) {
138 add_len = .5*linewidth/cos(angle);
139 } else {
140 add_len = 0;
143 *move_arrow = *to;
144 point_sub(move_arrow, from);
145 point_normalize(move_arrow);
146 point_scale(move_arrow, add_len);
147 break;
148 case ARROW_HALF_HEAD:
149 if (arrow->width < 0.0000001) return;
150 angle = atan(arrow->length/(arrow->width/2));
151 if (angle < 60*2*G_PI/360.0) {
152 add_len = linewidth/cos(angle);
153 } else {
154 add_len = 0;
157 *move_arrow = *to;
158 point_sub(move_arrow, from);
159 point_normalize(move_arrow);
160 point_scale(move_arrow, add_len);
161 break;
162 case ARROW_FILLED_TRIANGLE:
163 case ARROW_HOLLOW_ELLIPSE:
164 case ARROW_ROUNDED:
165 case ARROW_DIMENSION_ORIGIN:
166 case ARROW_BLANKED_DOT:
167 case ARROW_BLANKED_BOX:
168 add_len = .5*linewidth;
170 *move_arrow = *to;
171 point_sub(move_arrow, from);
172 point_normalize(move_arrow);
173 point_scale(move_arrow, add_len);
174 break;
175 case ARROW_ONE_EXACTLY:
176 case ARROW_ONE_OR_NONE:
177 case ARROW_ONE_OR_MANY:
178 case ARROW_NONE_OR_MANY:
179 default:
180 move_arrow->x = 0.0;
181 move_arrow->y = 0.0;
182 break;
185 /* Now move the line to be behind the arrowhead. */
186 switch (arrow->type) {
187 case ARROW_LINES:
188 case ARROW_HALF_HEAD:
189 *move_line = *move_arrow;
190 point_scale(move_line, 2.0);
191 return;
192 case ARROW_HOLLOW_TRIANGLE:
193 case ARROW_UNFILLED_TRIANGLE:
194 case ARROW_FILLED_TRIANGLE:
195 case ARROW_FILLED_ELLIPSE:
196 case ARROW_HOLLOW_ELLIPSE:
197 case ARROW_ROUNDED:
198 *move_line = *move_arrow;
199 point_normalize(move_line);
200 point_scale(move_line, arrow->length);
201 point_add(move_line, move_arrow);
202 return;
203 case ARROW_HALF_DIAMOND:
204 case ARROW_OPEN_ROUNDED:
205 /* These don't move the arrow, so *move_arrow can't be used. */
206 *move_line = *to;
207 point_sub(move_line, from);
208 point_normalize(move_line);
209 point_scale(move_line, arrow->length);
210 point_add(move_line, move_arrow);
211 return;
212 case ARROW_HOLLOW_DIAMOND:
213 case ARROW_FILLED_DIAMOND:
214 /* Make move_line be a unit vector in direction of line */
215 *move_line = *to;
216 point_sub(move_line, from);
217 point_normalize(move_line);
219 /* Set the length to arrow_length - \/2*linewidth */
220 tmp = *move_line;
221 point_scale(move_line, arrow->length);
222 point_scale(&tmp, G_SQRT2*linewidth);
223 point_sub(move_line, &tmp);
224 return;
225 case ARROW_DIMENSION_ORIGIN:
226 case ARROW_BLANKED_DOT:
227 case ARROW_BLANKED_BOX:
228 *move_line = *move_arrow;
229 point_normalize(move_line);
230 point_scale(move_line, .5*arrow->length);
231 return;
232 case ARROW_FILLED_DOT:
233 case ARROW_FILLED_BOX:
234 *move_line = *to;
235 point_sub(move_line, from);
236 point_normalize(move_line);
237 point_scale(move_line, .5*arrow->length);
238 return;
239 case ARROW_FILLED_CONCAVE:
240 case ARROW_BLANKED_CONCAVE:
241 *move_line = *move_arrow;
242 point_normalize(move_line);
243 point_scale(move_line, .75*arrow->length);
244 point_add(move_line, move_arrow);
245 return;
246 case ARROW_DOUBLE_HOLLOW_TRIANGLE:
247 *move_line = *move_arrow;
248 point_normalize(move_line);
249 tmp = *move_line;
250 point_scale(move_line, 2.0*arrow->length);
251 point_add(move_line, move_arrow);
252 point_scale(&tmp, linewidth);
253 point_add(move_line, &tmp);
254 return;
255 case ARROW_DOUBLE_FILLED_TRIANGLE:
256 *move_line = *to;
257 point_sub(move_line, from);
258 point_normalize(move_line);
259 point_scale(move_line, 2*arrow->length);
260 return;
261 case ARROW_FILLED_DOT_N_TRIANGLE:
262 *move_line = *to;
263 point_sub(move_line, from);
264 point_normalize(move_line);
265 point_scale(move_line, arrow->length + arrow->width);
266 return;
267 case ARROW_THREE_DOTS:
268 *move_line = *to;
269 point_sub(move_line, from);
270 add_len = point_len(move_line);
271 point_normalize(move_line);
272 if (add_len > 4*arrow->length)
273 point_scale(move_line, 2*arrow->length);
274 else
275 point_scale(move_line, arrow->length);
276 return;
277 case ARROW_SLASH_ARROW:
278 case ARROW_INTEGRAL_SYMBOL:
279 *move_line = *to;
280 point_sub(move_line, from);
281 add_len = point_len(move_line);
282 point_normalize(move_line);
283 point_scale(move_line, arrow->length / 2);
284 return;
285 case ARROW_ONE_EXACTLY:
286 case ARROW_ONE_OR_NONE:
287 case ARROW_ONE_OR_MANY:
288 case ARROW_NONE_OR_MANY:
289 default:
290 move_arrow->x = 0.0;
291 move_arrow->y = 0.0;
292 move_line->x = 0.0;
293 move_line->y = 0.0;
294 return;
298 /** Calculate the corners of a normal arrow.
299 * @param poly A three-element array in which to return the three points
300 * involved in making a simple arrow: poly[0] is the right-
301 * hand point, poly[1] is the tip, and poly[2] is the left-hand
302 * point.
303 * @param to Where the arrow is pointing to
304 * @param from Where the arrow is pointing from (e.g. the end of the stem)
305 * @param length How long the arrowhead should be.
306 * @param width How wide the arrowhead should be.
308 static void
309 calculate_arrow(Point *poly, Point *to, Point *from,
310 real length, real width)
312 Point delta;
313 Point orth_delta;
314 real len;
316 delta = *to;
317 point_sub(&delta, from);
318 len = point_len(&delta);
319 if (len <= 0.0001) {
320 delta.x=1.0;
321 delta.y=0.0;
322 } else {
323 delta.x/=len;
324 delta.y/=len;
327 orth_delta.x = delta.y;
328 orth_delta.y = -delta.x;
330 point_scale(&delta, length);
331 point_scale(&orth_delta, width/2.0);
333 poly[0] = *to;
334 point_sub(&poly[0], &delta);
335 point_sub(&poly[0], &orth_delta);
336 poly[1] = *to;
337 poly[2] = *to;
338 point_sub(&poly[2], &delta);
339 point_add(&poly[2], &orth_delta);
342 /** Calculate the actual point of a crows-foot arrow.
343 * @param poly A three-element array in which to return the three points
344 * involved in making a simple arrow: poly[0] is the tip, poly[1]
345 * is the right-hand point, and poly[2] is the left-hand point.
346 * @param to Where the arrow is pointing to
347 * @param from Where the arrow is pointing from (e.g. the end of the stem)
348 * @param length How long the arrowhead should be.
349 * @param width How wide the arrowhead should be.
351 static void
352 calculate_crow(Point *poly, Point *to, Point *from,
353 real length, real width)
355 Point delta;
356 Point orth_delta;
357 real len;
359 delta = *to;
360 point_sub(&delta, from);
361 len = point_len(&delta);
362 if (len <= 0.0001) {
363 delta.x=1.0;
364 delta.y=0.0;
365 } else {
366 delta.x/=len;
367 delta.y/=len;
370 orth_delta.x = delta.y;
371 orth_delta.y = -delta.x;
373 point_scale(&delta, length);
374 point_scale(&orth_delta, width/2.0);
376 poly[0] = *to;
377 point_sub(&poly[0], &delta);
378 poly[1] = *to;
379 point_sub(&poly[1], &orth_delta);
380 poly[2] = *to;
381 point_add(&poly[2], &orth_delta);
384 /** Draw ER arrow for 0..N according to Modern database management,
385 * McFadden/Hoffer/Prescott, Addison-Wessley, 1999
386 * @param renderer A renderer instance to draw into
387 * @param to The point that the arrow points to.
388 * @param from Where the arrow points from (e.g. end of stem)
389 * @param length The length of the arrow
390 * @param width The width of the arrow
391 * @param linewidth The thickness of the lines used to draw the arrow.
392 * @param fg_color The color used for drawing the arrow lines.
393 * @param bg_color Ignored.
394 * @todo The ER-drawing methods are ripe for some refactoring.
396 static void
397 draw_none_or_many(DiaRenderer *renderer, Point *to, Point *from,
398 real length, real width, real linewidth,
399 Color *fg_color,Color *bg_color)
401 Point second_from, second_to;
403 draw_crow_foot(renderer, to, from, length, width,
404 linewidth, fg_color, bg_color);
406 calculate_double_arrow(&second_to, &second_from, to, from, length);
407 /* use the middle of the arrow */
409 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
410 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
411 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
412 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
414 draw_empty_ellipse(renderer, &second_to, &second_from, length/2,
415 width, linewidth, fg_color);
418 /** ER arrow for exactly-one relations according to Modern database management,
419 * McFadden/Hoffer/Prescott, Addison-Wessley, 1999
420 * @param renderer A renderer instance to draw into
421 * @param to The point that the arrow points to.
422 * @param from Where the arrow points from (e.g. end of stem)
423 * @param length The length of the arrow
424 * @param width The width of the arrow
425 * @param linewidth The thickness of the lines used to draw the arrow.
426 * @param fg_color The color used for drawing the arrow lines.
427 * @param bg_color Ignored.
429 static void
430 draw_one_exactly(DiaRenderer *renderer, Point *to, Point *from,
431 real length, real width, real linewidth,
432 Color *fg_color,Color *bg_color)
434 Point vl,vt;
435 Point bs,be;
437 /* the first line */
438 point_copy(&vl,from); point_sub(&vl,to);
439 if (point_len(&vl) > 0)
440 point_normalize(&vl);
441 else {
442 vl.x = 1.0; vl.y = 0.0;
444 if (!finite(vl.x)) {
445 vl.x = 1.0; vl.y = 0.0;
447 point_get_perp(&vt,&vl);
448 point_copy_add_scaled(&bs,to,&vl,length/2);
449 point_copy_add_scaled(&be,&bs,&vt,-width/2.0);
450 point_add_scaled(&bs,&vt,width/2.0);
452 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer,&bs,&be,fg_color);
454 point_copy_add_scaled(&bs,to,&vl,length);
456 point_copy_add_scaled(&be,&bs,&vt,-width/2.0);
457 point_add_scaled(&bs,&vt,width/2.0);
459 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer,&bs,&be,fg_color);
462 /* ER arrow for 1..N according to Modern database management,
463 * McFadden/Hoffer/Prescott, Addison-Wessley, 1999
464 * @param renderer A renderer instance to draw into
465 * @param to The point that the arrow points to.
466 * @param from Where the arrow points from (e.g. end of stem)
467 * @param length The length of the arrow
468 * @param width The width of the arrow
469 * @param linewidth The thickness of the lines used to draw the arrow.
470 * @param fg_color The color used for drawing the arrow lines.
471 * @param bg_color Ignored.
473 static void
474 draw_one_or_many(DiaRenderer *renderer, Point *to, Point *from,
475 real length, real width, real linewidth,
476 Color *fg_color,Color *bg_color)
479 Point poly[6];
481 draw_crow_foot(renderer, to, from, length, width,
482 linewidth, fg_color, bg_color);
484 calculate_arrow(poly, to, from, length, width);
486 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
487 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
488 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
489 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
491 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &poly[0],&poly[2], fg_color);
494 /* ER arrow for 0,1 according to Modern database management,
495 * McFadden/Hoffer/Prescott, Addison-Wessley, 1999
496 * @param renderer A renderer instance to draw into
497 * @param to The point that the arrow points to.
498 * @param from Where the arrow points from (e.g. end of stem)
499 * @param length The length of the arrow
500 * @param width The width of the arrow
501 * @param linewidth The thickness of the lines used to draw the arrow.
502 * @param fg_color The color used for drawing the arrow lines.
503 * @param bg_color Ignored.
505 static void
506 draw_one_or_none(DiaRenderer *renderer, Point *to, Point *from,
507 real length, real width, real linewidth,
508 Color *fg_color,Color *bg_color)
510 Point vl,vt;
511 Point bs,be;
512 Point second_from, second_to;
514 /* the line */
515 point_copy(&vl,from); point_sub(&vl,to);
516 if (point_len(&vl) > 0)
517 point_normalize(&vl);
518 else {
519 vl.x = 1.0; vl.y = 0.0;
521 if (!finite(vl.x)) {
522 vl.x = 1.0; vl.y = 0.0;
524 point_get_perp(&vt,&vl);
525 point_copy_add_scaled(&bs,to,&vl,length/2);
526 point_copy_add_scaled(&be,&bs,&vt,-width/2.0);
527 point_add_scaled(&bs,&vt,width/2.0);
529 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer,&bs,&be,fg_color);
530 /* the ellipse */
531 calculate_double_arrow(&second_to, &second_from, to, from, length);
532 draw_empty_ellipse(renderer, &second_to, &second_from, length/2, width, linewidth, fg_color);
535 /** Draw a crow's foot arrowhead.
536 * @param renderer A renderer instance to draw into
537 * @param to The point that the arrow points to.
538 * @param from Where the arrow points from (e.g. end of stem)
539 * @param length The length of the arrow
540 * @param width The width of the arrow
541 * @param linewidth The thickness of the lines used to draw the arrow.
542 * @param fg_color The color used for drawing the arrow lines.
543 * @param bg_color Ignored.
545 static void
546 draw_crow_foot(DiaRenderer *renderer, Point *to, Point *from,
547 real length, real width, real linewidth,
548 Color *fg_color,Color *bg_color)
551 Point poly[3];
553 calculate_crow(poly, to, from, length, width);
555 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
556 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
557 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
559 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer,&poly[0],&poly[1],fg_color);
560 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer,&poly[0],&poly[2],fg_color);
563 /** Draw a simple open line arrow.
564 * @param renderer A renderer instance to draw into
565 * @param to The point that the arrow points to.
566 * @param from Where the arrow points from (e.g. end of stem)
567 * @param length The length of the arrow
568 * @param width The width of the arrow
569 * @param linewidth The thickness of the lines used to draw the arrow.
570 * @param fg_color The color used for drawing the arrow lines.
572 static void
573 draw_lines(DiaRenderer *renderer, Point *to, Point *from,
574 real length, real width, real linewidth,
575 Color *color)
577 Point poly[3];
579 calculate_arrow(poly, to, from, length, width);
581 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
582 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
583 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
584 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
586 DIA_RENDERER_GET_CLASS(renderer)->draw_polyline(renderer, poly, 3, color);
589 /** Draw an arrowhead that is a filled ellipse.
590 * @param renderer A renderer instance to draw into
591 * @param to The point that the arrow points to.
592 * @param from Where the arrow points from (e.g. end of stem)
593 * @param length The length of the arrow
594 * @param width The width of the arrow
595 * @param linewidth The thickness of the lines used to draw the arrow.
596 * @param fg_color The color used for drawing the arrow lines.
597 * @param bg_color Used to fill the ellipse, usually white and non-settable.
598 * If null, the ellipse is filled with fg_color and slightly
599 * smaller (by linewidth/2).
601 static void
602 draw_fill_ellipse(DiaRenderer *renderer, Point *to, Point *from,
603 real length, real width, real linewidth,
604 Color *fg_color,Color *bg_color)
606 BezPoint bp[5];
607 Point vl,vt;
609 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
610 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
611 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
612 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
614 if (!bg_color) {
615 /* no bg_color means filled ellipse ; we then compensate for the line width
617 length += linewidth;
618 width += linewidth;
620 point_copy(&vl,from); point_sub(&vl,to);
621 if (point_len(&vl) > 0)
622 point_normalize(&vl);
623 else {
624 vl.x = 1.0; vl.y = 0.0;
626 if (!finite(vl.x)) {
627 vl.x = 1.0; vl.y = 0.0;
629 point_get_perp(&vt,&vl);
632 /* This pile of crap is quite well handled by gcc. */
633 bp[0].type = BEZ_MOVE_TO;
634 point_copy(&bp[0].p1,to);
635 bp[1].type = bp[2].type = bp[3].type = bp[4].type = BEZ_CURVE_TO;
636 point_copy(&bp[4].p3,&bp[0].p1);
638 point_copy_add_scaled(&bp[2].p3,&bp[0].p1,&vl,length);
639 point_copy_add_scaled(&bp[2].p2,&bp[2].p3,&vt,-width / 4.0);
640 point_copy_add_scaled(&bp[3].p1,&bp[2].p3,&vt,width / 4.0);
641 point_copy_add_scaled(&bp[1].p1,&bp[0].p1,&vt,-width / 4.0);
642 point_copy_add_scaled(&bp[4].p2,&bp[0].p1,&vt,width / 4.0);
643 point_copy_add_scaled(&bp[1].p3,&bp[0].p1,&vl,length / 2.0); /* temp */
644 point_copy_add_scaled(&bp[3].p3,&bp[1].p3,&vt,width / 2.0);
645 point_add_scaled(&bp[1].p3,&vt,-width / 2.0);
646 point_copy_add_scaled(&bp[1].p2,&bp[1].p3,&vl,-length / 4.0);
647 point_copy_add_scaled(&bp[4].p1,&bp[3].p3,&vl,-length / 4.0);
648 point_copy_add_scaled(&bp[2].p1,&bp[1].p3,&vl,length / 4.0);
649 point_copy_add_scaled(&bp[3].p2,&bp[3].p3,&vl,length / 4.0);
650 if (bg_color) {
651 DIA_RENDERER_GET_CLASS(renderer)->fill_bezier(renderer,bp,sizeof(bp)/sizeof(bp[0]),bg_color);
652 DIA_RENDERER_GET_CLASS(renderer)->draw_bezier(renderer,bp,sizeof(bp)/sizeof(bp[0]),fg_color);
653 } else {
654 DIA_RENDERER_GET_CLASS(renderer)->fill_bezier(renderer,bp,sizeof(bp)/sizeof(bp[0]),fg_color);
658 /** Draw an arrowhead that is an ellipse with empty interior.
659 * @param renderer A renderer instance to draw into
660 * @param to The point that the arrow points to.
661 * @param from Where the arrow points from (e.g. end of stem)
662 * @param length The length of the arrow
663 * @param width The width of the arrow
664 * @param linewidth The thickness of the lines used to draw the arrow.
665 * @param fg_color The color used for drawing the arrow lines.
667 static void
668 draw_empty_ellipse(DiaRenderer *renderer, Point *to, Point *from,
669 real length, real width, real linewidth,
670 Color *fg_color)
672 BezPoint bp[5];
673 Point vl,vt;
674 Point disp;
676 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
677 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
678 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
679 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
681 point_copy(&vl,from);
682 point_sub(&vl,to);
683 if (point_len(&vl) > 0)
684 point_normalize(&vl);
685 else {
686 vl.x = 1.0; vl.y = 0.0;
688 if (!finite(vl.x)) {
689 vl.x = 1.0; vl.y = 0.0;
692 point_get_perp(&vt,&vl);
694 point_copy(&disp, &vl);
695 disp.x *= length/2;
696 disp.y *= length/2;
698 /* This pile of crap is quite well handled by gcc. */
699 bp[0].type = BEZ_MOVE_TO;
700 point_copy(&bp[0].p1,to);
701 point_add(&bp[0].p1,&disp);
702 bp[1].type = bp[2].type = bp[3].type = bp[4].type = BEZ_CURVE_TO;
703 point_copy(&bp[4].p3,&bp[0].p1);
705 point_copy_add_scaled(&bp[2].p3,&bp[0].p1,&vl,length);
706 point_copy_add_scaled(&bp[2].p2,&bp[2].p3,&vt,-width / 4.0);
707 point_copy_add_scaled(&bp[3].p1,&bp[2].p3,&vt,width / 4.0);
708 point_copy_add_scaled(&bp[1].p1,&bp[0].p1,&vt,-width / 4.0);
709 point_copy_add_scaled(&bp[4].p2,&bp[0].p1,&vt,width / 4.0);
710 point_copy_add_scaled(&bp[1].p3,&bp[0].p1,&vl,length / 2.0); /* temp */
711 point_copy_add_scaled(&bp[3].p3,&bp[1].p3,&vt,width / 2.0);
712 point_add_scaled(&bp[1].p3,&vt,-width / 2.0);
713 point_copy_add_scaled(&bp[1].p2,&bp[1].p3,&vl,-length / 4.0);
714 point_copy_add_scaled(&bp[4].p1,&bp[3].p3,&vl,-length / 4.0);
715 point_copy_add_scaled(&bp[2].p1,&bp[1].p3,&vl,length / 4.0);
716 point_copy_add_scaled(&bp[3].p2,&bp[3].p3,&vl,length / 4.0);
718 DIA_RENDERER_GET_CLASS(renderer)->draw_bezier(renderer,bp,sizeof(bp)/sizeof(bp[0]),fg_color);
721 /** Draw an arrow head that is an (optionall) filled box.
722 * @param renderer A renderer instance to draw into
723 * @param to The point that the arrow points to.
724 * @param from Where the arrow points from (e.g. end of stem)
725 * @param length The length of the arrow
726 * @param width The width of the arrow
727 * @param linewidth The thickness of the lines used to draw the arrow.
728 * @param fg_color The color used for drawing the arrow lines.
729 * @param bg_color The color used for the interior of the box. If
730 * fg_color == bg_color, the box is rendered slightly smaller.
732 static void
733 draw_fill_box(DiaRenderer *renderer, Point *to, Point *from,
734 real length, real width, real linewidth,
735 Color *fg_color,Color *bg_color)
737 Point vl,vt;
738 Point bs,be;
739 Point poly[4];
740 real lw_factor,clength,cwidth;
742 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
743 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
744 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
745 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
747 if (fg_color == bg_color) {
748 /* Filled dot */
749 lw_factor = linewidth;
750 } else {
751 /* Hollow dot or dimension origin */
752 lw_factor = 0.0;
754 clength = length + lw_factor;
755 cwidth = width + lw_factor;
757 point_copy(&vl,from); point_sub(&vl,to);
758 if (point_len(&vl) > 0)
759 point_normalize(&vl);
760 else {
761 vl.x = 1.0; vl.y = 0.0;
763 if (!finite(vl.x)) {
764 vl.x = 1.0; vl.y = 0.0;
766 point_get_perp(&vt,&vl);
768 point_copy_add_scaled(&bs,to,&vl,length/4);
769 point_copy_add_scaled(&be,&bs,&vt,-width/2.0);
770 point_add_scaled(&bs,&vt,width/2.0);
772 point_copy(&poly[0],to);
773 point_copy(&poly[1],&poly[0]);
774 point_add_scaled(&poly[0],&vt,cwidth/4.0);
775 point_add_scaled(&poly[1],&vt,-cwidth/4.0);
776 point_copy_add_scaled(&poly[2],&poly[1],&vl,clength/2.0);
777 point_copy_add_scaled(&poly[3],&poly[0],&vl,clength/2.0);
779 if (fg_color == bg_color) {
780 DIA_RENDERER_GET_CLASS(renderer)->fill_polygon(renderer, poly, 4, fg_color);
781 } else {
782 DIA_RENDERER_GET_CLASS(renderer)->fill_polygon(renderer, poly, 4, bg_color);
783 DIA_RENDERER_GET_CLASS(renderer)->draw_polygon(renderer, poly, 4, fg_color);
785 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer,&bs,&be,fg_color);
788 /** Draw a "filled dot" arrow.
789 * @param renderer A renderer instance to draw into
790 * @param to The point that the arrow points to.
791 * @param from Where the arrow points from (e.g. end of stem)
792 * @param length The length of the arrow
793 * @param width The width of the arrow
794 * @param linewidth The thickness of the lines used to draw the arrow.
795 * @param fg_color The color used for drawing the arrow lines.
796 * @param bg_color The collor used for the interior of the dot.
797 * @bug Need to describe the diff between this and ellipse arrow.
799 static void
800 draw_fill_dot(DiaRenderer *renderer, Point *to, Point *from,
801 real length, real width, real linewidth,
802 Color *fg_color,Color *bg_color)
804 BezPoint bp[5];
805 Point vl,vt;
806 Point bs,be;
807 real lw_factor,clength,cwidth;
809 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
810 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
811 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
812 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
814 if (fg_color == bg_color) {
815 /* Filled dot */
816 lw_factor = linewidth;
817 } else {
818 /* Hollow dot or dimension origin */
819 lw_factor = 0.0;
821 clength = length + lw_factor;
822 cwidth = width + lw_factor;
824 point_copy(&vl,from); point_sub(&vl,to);
825 if (point_len(&vl) > 0)
826 point_normalize(&vl);
827 else {
828 vl.x = 1.0; vl.y = 0.0;
830 if (!finite(vl.x)) {
831 vl.x = 1.0; vl.y = 0.0;
833 point_get_perp(&vt,&vl);
835 point_copy_add_scaled(&bs,to,&vl,length/4);
836 point_copy_add_scaled(&be,&bs,&vt,-width/2.0);
837 point_add_scaled(&bs,&vt,width/2.0);
839 /* This pile of crap is quite well handled by gcc. */
840 bp[0].type = BEZ_MOVE_TO;
841 point_copy(&bp[0].p1,to);
842 bp[1].type = bp[2].type = bp[3].type = bp[4].type = BEZ_CURVE_TO;
843 point_copy(&bp[4].p3,&bp[0].p1);
845 point_copy_add_scaled(&bp[2].p3,&bp[0].p1,&vl,clength/2);
846 point_copy_add_scaled(&bp[2].p2,&bp[2].p3,&vt,-cwidth / 8.0);
847 point_copy_add_scaled(&bp[3].p1,&bp[2].p3,&vt,cwidth / 8.0);
848 point_copy_add_scaled(&bp[1].p1,&bp[0].p1,&vt,-cwidth / 8.0);
849 point_copy_add_scaled(&bp[4].p2,&bp[0].p1,&vt,cwidth / 8.0);
850 point_copy_add_scaled(&bp[1].p3,&bp[0].p1,&vl,clength / 4.0); /* temp */
851 point_copy_add_scaled(&bp[3].p3,&bp[1].p3,&vt,cwidth / 4.0);
852 point_add_scaled(&bp[1].p3,&vt,-cwidth / 4.0);
853 point_copy_add_scaled(&bp[1].p2,&bp[1].p3,&vl,-clength / 8.0);
854 point_copy_add_scaled(&bp[4].p1,&bp[3].p3,&vl,-clength / 8.0);
855 point_copy_add_scaled(&bp[2].p1,&bp[1].p3,&vl,clength / 8.0);
856 point_copy_add_scaled(&bp[3].p2,&bp[3].p3,&vl,clength / 8.0);
858 if (!bg_color) {
859 /* Means dimension origin */
860 Point dos,doe;
862 point_copy_add_scaled(&doe,to,&vl,length);
863 point_copy_add_scaled(&dos,to,&vl,length/2);
865 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer,&dos,&doe,fg_color);
866 } else {
867 DIA_RENDERER_GET_CLASS(renderer)->fill_bezier(renderer,bp,sizeof(bp)/sizeof(bp[0]),bg_color);
869 if (fg_color != bg_color) {
870 DIA_RENDERER_GET_CLASS(renderer)->draw_bezier(renderer,bp,sizeof(bp)/sizeof(bp[0]),fg_color);
872 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer,&bs,&be,fg_color);
875 /** Draw the integral-sign arrow head.
876 * @param renderer A renderer instance to draw into
877 * @param to The point that the arrow points to.
878 * @param from Where the arrow points from (e.g. end of stem)
879 * @param length The length of the arrow
880 * @param width The width of the arrow
881 * @param linewidth The thickness of the lines used to draw the arrow.
882 * @param fg_color The color used for drawing the arrow lines.
883 * @param bg_color The color used to kludge around the longer stem of this
884 * arrow.
885 * @bug The bg_color kludge should not be necessary, arrow pos is adjustable.
887 static void
888 draw_integral(DiaRenderer *renderer, Point *to, Point *from,
889 real length, real width, real linewidth,
890 Color *fg_color)
892 BezPoint bp[2];
893 Point vl,vt;
894 Point bs,be, bs2,be2;
895 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
896 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
897 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
898 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
900 point_copy(&vl,from); point_sub(&vl,to);
901 if (point_len(&vl) > 0)
902 point_normalize(&vl);
903 else {
904 vl.x = 1.0; vl.y = 0.0;
906 if (!finite(vl.x)) {
907 vl.x = 1.0; vl.y = 0.0;
909 point_get_perp(&vt,&vl);
911 point_copy_add_scaled(&bs,to,&vl,length/2);
912 point_copy_add_scaled(&be,&bs,&vt,-width/2.0);
913 point_add_scaled(&bs,&vt,width/2.0);
915 point_copy_add_scaled(&bs2,to,&vl,length/2);
916 point_copy_add_scaled(&be2,&bs2,&vl,length/2);
918 bp[0].type = BEZ_MOVE_TO;
919 bp[1].type = BEZ_CURVE_TO;
920 point_copy_add_scaled(&bp[0].p1,to,&vl,.1*length);
921 point_add_scaled(&bp[0].p1,&vt,.4*width);
922 point_copy_add_scaled(&bp[1].p3,to,&vl,.9*length);
923 point_add_scaled(&bp[1].p3,&vt,-.4*width);
924 point_copy_add_scaled(&bp[1].p1,&bp[0].p1,&vl,.35*length);
925 point_copy_add_scaled(&bp[1].p2,&bp[1].p3,&vl,-.35*length);
927 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &bs2, &be2, fg_color);
928 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &bs, &be, fg_color);
929 DIA_RENDERER_GET_CLASS(renderer)->draw_bezier(renderer,bp,sizeof(bp)/sizeof(bp[0]),fg_color);
932 /** Draw the arrowhead that is a line with a slash through it.
933 * @param renderer A renderer instance to draw into
934 * @param to The point that the arrow points to.
935 * @param from Where the arrow points from (e.g. end of stem)
936 * @param length The length of the arrow
937 * @param width The width of the arrow
938 * @param linewidth The thickness of the lines used to draw the arrow.
939 * @param fg_color The color used for drawing the arrow lines.
940 * @param bg_color Used for a kludge of "erasing" the line tip instead of
941 * figuring out the correct way to do this.
942 * @bug Figure out the right way to do this, avoid kludge.
944 static void
945 draw_slashed(DiaRenderer *renderer, Point *to, Point *from,
946 real length, real width, real linewidth,
947 Color *fg_color)
949 Point vl,vt;
950 Point bs,be, bs2,be2, bs3,be3;
952 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
953 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
954 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
955 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
957 point_copy(&vl,from); point_sub(&vl,to);
958 if (point_len(&vl) > 0)
959 point_normalize(&vl);
960 else {
961 vl.x = 1.0; vl.y = 0.0;
963 if (!finite(vl.x)) {
964 vl.x = 1.0; vl.y = 0.0;
966 point_get_perp(&vt,&vl);
968 point_copy_add_scaled(&bs,to,&vl,length/2);
969 point_copy_add_scaled(&be,&bs,&vt,-width/2.0);
970 point_add_scaled(&bs,&vt,width/2.0);
972 point_copy_add_scaled(&bs2,to,&vl,length/2);
973 point_copy_add_scaled(&be2,&bs2,&vl,length/2);
975 point_copy_add_scaled(&bs3,to,&vl,.1*length);
976 point_add_scaled(&bs3,&vt,.4*width);
977 point_copy_add_scaled(&be3,to,&vl,.9*length);
978 point_add_scaled(&be3,&vt,-.4*width);
980 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &bs2, &be2, fg_color);
981 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &bs, &be, fg_color);
982 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &bs3, &be3, fg_color);
985 /** Calculate positions for the half-head arrow (only left-hand(?) line drawn)
986 * @param poly The three-element array to store the result in.
987 * @param to Where the arrow points to
988 * @param from Where the arrow points from (e.g. end of stem)
989 * @param length The length of the arrowhead
990 * @param width The width of the arrowhead
991 * @param linewidth The width of the lines used to draw the arrow
992 * @bug Describe better what is put into poly.
994 static void
995 calculate_halfhead(Point *poly, Point *to, Point *from,
996 real length, real width, real linewidth)
998 Point delta;
999 Point orth_delta;
1000 real len;
1001 real angle, add_len;
1003 if (width > 0.0000001) {
1004 angle = atan(length/(width/2));
1005 add_len = linewidth/cos(angle);
1006 } else {
1007 add_len = 0;
1010 delta = *to;
1011 point_sub(&delta, from);
1012 len = point_len(&delta);
1013 if (len <= 0.0001) {
1014 delta.x=1.0;
1015 delta.y=0.0;
1016 } else {
1017 delta.x/=len;
1018 delta.y/=len;
1021 orth_delta.x = delta.y;
1022 orth_delta.y = -delta.x;
1024 point_scale(&delta, length);
1025 point_scale(&orth_delta, width/2.0);
1027 poly[0] = *to;
1028 point_sub(&poly[0], &delta);
1029 point_sub(&poly[0], &orth_delta);
1030 poly[1] = *to;
1031 poly[2] = *to;
1032 point_normalize(&delta);
1033 point_scale(&delta, add_len);
1034 point_sub(&poly[2], &delta);
1035 /* point_add(&poly[2], &orth_delta);*/
1038 /** Draw a halfhead arrow.
1039 * @param renderer A renderer instance to draw into
1040 * @param to The point that the arrow points to.
1041 * @param from Where the arrow points from (e.g. end of stem)
1042 * @param length The length of the arrow
1043 * @param width The width of the arrow
1044 * @param linewidth The thickness of the lines used to draw the arrow.
1045 * @param color The color used for drawing the arrow lines.
1047 static void
1048 draw_halfhead(DiaRenderer *renderer, Point *to, Point *from,
1049 real length, real width, real linewidth,
1050 Color *color)
1052 Point poly[3];
1054 calculate_halfhead(poly, to, from, length, width, linewidth);
1056 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1057 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1058 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1059 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1061 DIA_RENDERER_GET_CLASS(renderer)->draw_polyline(renderer, poly, 3, color);
1064 /** Draw a basic triangular arrow.
1065 * @param renderer A renderer instance to draw into
1066 * @param to The point that the arrow points to.
1067 * @param from Where the arrow points from (e.g. end of stem)
1068 * @param length The length of the arrow
1069 * @param width The width of the arrow
1070 * @param linewidth The thickness of the lines used to draw the arrow.
1071 * @param color The color used for drawing the arrow lines.
1073 static void
1074 draw_triangle(DiaRenderer *renderer, Point *to, Point *from,
1075 real length, real width, real linewidth,
1076 Color *color)
1078 Point poly[3];
1080 calculate_arrow(poly, to, from, length, width);
1082 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1083 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1084 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1086 DIA_RENDERER_GET_CLASS(renderer)->draw_polygon(renderer, poly, 3, color);
1089 /** Draw a simple triangular arrow, with filled head.
1090 * @param renderer A renderer instance to draw into
1091 * @param to The point that the arrow points to.
1092 * @param from Where the arrow points from (e.g. end of stem)
1093 * @param length The length of the arrow
1094 * @param width The width of the arrow
1095 * @param linewidth The thickness of the lines used to draw the arrow.
1096 * @param color The color used for drawing the arrowhead.
1098 static void
1099 fill_triangle(DiaRenderer *renderer, Point *to, Point *from,
1100 real length, real width, Color *color)
1102 Point poly[3];
1104 calculate_arrow(poly, to, from, length, width);
1106 DIA_RENDERER_GET_CLASS(renderer)->set_fillstyle(renderer, FILLSTYLE_SOLID);
1107 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1109 DIA_RENDERER_GET_CLASS(renderer)->fill_polygon(renderer, poly, 3, color);
1112 /** Calculate the points needed to draw a diamon arrowhead.
1113 * @param poly A 4-element arrow to hold the return values:
1114 * poly[0] holds the tip of the diamond.
1115 * poly[1] holds the right-side tip of the diamond.
1116 * poly[2] holds the back end of the diamond.
1117 * poly[3] holds the left-side tip of the diamond.
1118 * @param to The point the arrow points to.
1119 * @param from The point the arrow points away from (e.g. bezier control line)
1120 * @param length The length of the arrowhead
1121 * @param width The width of the arrowhead
1122 * @bug Take linewidth into account.
1124 static void
1125 calculate_diamond(Point *poly, Point *to, Point *from,
1126 real length, real width)
1128 Point delta;
1129 Point orth_delta;
1130 real len;
1132 delta = *to;
1133 point_sub(&delta, from);
1134 len = sqrt(point_dot(&delta, &delta));
1135 if (len <= 0.0001) {
1136 delta.x=1.0;
1137 delta.y=0.0;
1138 } else {
1139 delta.x/=len;
1140 delta.y/=len;
1143 orth_delta.x = delta.y;
1144 orth_delta.y = -delta.x;
1146 point_scale(&delta, length/2.0);
1147 point_scale(&orth_delta, width/2.0);
1149 poly[0] = *to;
1150 poly[1] = *to;
1151 point_sub(&poly[1], &delta);
1152 point_sub(&poly[1], &orth_delta);
1153 poly[2] = *to;
1154 point_sub(&poly[2], &delta);
1155 point_sub(&poly[2], &delta);
1156 poly[3] = *to;
1157 point_sub(&poly[3], &delta);
1158 point_add(&poly[3], &orth_delta);
1161 /** Draw a diamond-shaped arrow head.
1162 * @param renderer A renderer instance to draw into
1163 * @param to The point that the arrow points to.
1164 * @param from Where the arrow points from (e.g. end of stem)
1165 * @param length The length of the arrow
1166 * @param width The width of the arrow
1167 * @param linewidth The thickness of the lines used to draw the arrow.
1168 * @param color The color used for drawing the arrowhead.
1170 static void
1171 draw_diamond(DiaRenderer *renderer, Point *to, Point *from,
1172 real length, real width, real linewidth,
1173 Color *color)
1175 Point poly[4];
1177 calculate_diamond(poly, to, from, length, width);
1179 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1180 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1181 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1182 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1184 DIA_RENDERER_GET_CLASS(renderer)->draw_polygon(renderer, poly, 4, color);
1187 /** Draw a right-hand part of a diamond arrowhead.
1188 * @param renderer A renderer instance to draw into
1189 * @param to The point that the arrow points to.
1190 * @param from Where the arrow points from (e.g. end of stem)
1191 * @param length The length of the arrow
1192 * @param width The width of the arrow
1193 * @param linewidth The thickness of the lines used to draw the arrow.
1194 * @param color The color used for drawing the arrowhead.
1196 static void
1197 draw_half_diamond(DiaRenderer *renderer, Point *to, Point *from,
1198 real length, real width, real linewidth,
1199 Color *color)
1201 Point poly[4];
1203 calculate_diamond(poly, to, from, length, width);
1205 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1206 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1207 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1208 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1210 DIA_RENDERER_GET_CLASS(renderer)->draw_polyline(renderer, poly+1, 3, color);
1213 /** Draw a filled diamond arrow head.
1214 * @param renderer A renderer instance to draw into
1215 * @param to The point that the arrow points to.
1216 * @param from Where the arrow points from (e.g. end of stem)
1217 * @param length The length of the arrow
1218 * @param width The width of the arrow
1219 * @param color The color used for drawing the arrowhead.
1221 static void
1222 fill_diamond(DiaRenderer *renderer, Point *to, Point *from,
1223 real length, real width,
1224 Color *color)
1226 Point poly[4];
1228 calculate_diamond(poly, to, from, length, width);
1230 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1231 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1232 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1234 DIA_RENDERER_GET_CLASS(renderer)->fill_polygon(renderer, poly, 4, color);
1237 /** Calculate the points needed to draw a slashed-cross arrowhead.
1238 * @param poly A 6-element array to hold the points calculated:
1239 * @param to Where the arrow points to.
1240 * @param from Where the arrow points from (e.g. other end of stem).
1241 * @param length The length of the arrowhead.
1242 * @param width The width of the arrowhead.
1243 * @bug Describe what is where in the poly array.
1245 static void
1246 calculate_slashed_cross(Point *poly, Point *to, Point *from,
1247 real length, real width)
1249 Point delta;
1250 Point orth_delta;
1251 real len;
1252 int i;
1254 delta = *to;
1255 point_sub(&delta, from);
1256 len = sqrt(point_dot(&delta, &delta));
1257 if (len <= 0.0001) {
1258 delta.x=1.0;
1259 delta.y=0.0;
1260 } else {
1261 delta.x/=len;
1262 delta.y/=len;
1265 orth_delta.x = delta.y;
1266 orth_delta.y = -delta.x;
1268 point_scale(&delta, length/2.0);
1269 point_scale(&orth_delta, width/2.0);
1271 for(i=0; i<6;i++)poly[i] = *to;
1273 point_add(&poly[1], &delta);
1275 point_add(&poly[2], &delta);
1276 point_add(&poly[2], &orth_delta);
1278 point_sub(&poly[3], &delta);
1279 point_sub(&poly[3], &orth_delta);
1281 point_add(&poly[4], &orth_delta);
1282 point_sub(&poly[5], &orth_delta);
1285 /** Draw a slashed cross arrowhead.
1286 * @param renderer A renderer instance to draw into
1287 * @param to The point that the arrow points to.
1288 * @param from Where the arrow points from (e.g. end of stem)
1289 * @param length The length of the arrow
1290 * @param width The width of the arrow
1291 * @param linewidth The thickness of the lines used to draw the arrow.
1292 * @param color The color used for drawing the arrowhead.
1294 static void
1295 draw_slashed_cross(DiaRenderer *renderer, Point *to, Point *from,
1296 real length, real width, real linewidth, Color *color)
1298 Point poly[6];
1300 calculate_slashed_cross(poly, to, from, length, width);
1302 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1303 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1304 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1305 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1307 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &poly[0],&poly[1], color);
1308 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &poly[2],&poly[3], color);
1309 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &poly[4],&poly[5], color);
1312 /** Draw a backslash arrowhead.
1313 * @param renderer A renderer instance to draw into
1314 * @param to The point that the arrow points to.
1315 * @param from Where the arrow points from (e.g. end of stem)
1316 * @param length The length of the arrow
1317 * @param width The width of the arrow
1318 * @param linewidth The thickness of the lines used to draw the arrow.
1319 * @param color The color used for drawing the arrowhead.
1320 * @todo refactor into calculate and draw.
1322 static void
1323 draw_backslash(DiaRenderer *renderer, Point *to, Point *from,
1324 real length, real width, real linewidth, Color *color)
1326 Point point1;
1327 Point point2;
1328 Point delta;
1329 Point orth_delta;
1330 real len;
1332 delta = *to;
1333 point_sub(&delta, from);
1334 len = sqrt(point_dot(&delta, &delta));
1335 if (len <= 0.0001) {
1336 delta.x=1.0;
1337 delta.y=0.0;
1338 } else {
1339 delta.x/=len;
1340 delta.y/=len;
1343 orth_delta.x = delta.y;
1344 orth_delta.y = -delta.x;
1346 point_scale(&delta, length/2.0);
1347 point_scale(&orth_delta, width/2.0);
1349 point1 = *to;
1350 point_sub(&point1, &delta);
1351 point_sub(&point1, &delta);
1352 point_sub(&point1, &delta);
1353 point_add(&point1, &orth_delta);
1355 point2 = *to;
1356 point_sub(&point2, &delta);
1357 point_sub(&point2, &orth_delta);
1359 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1360 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1361 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1362 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1364 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &point1,&point2, color);
1367 /** Draw a cross-like arrowhead.
1368 * @param renderer A renderer instance to draw into
1369 * @param to The point that the arrow points to.
1370 * @param from Where the arrow points from (e.g. end of stem)
1371 * @param length The length of the arrow
1372 * @param width The width of the arrow
1373 * @param linewidth The thickness of the lines used to draw the arrow.
1374 * @param color The color used for drawing the arrowhead.
1376 static void
1377 draw_cross(DiaRenderer *renderer, Point *to, Point *from,
1378 real length, real width, real linewidth, Color *color)
1380 Point poly[6];
1382 calculate_arrow(poly, to, from, length, width);
1384 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1385 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1386 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1387 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1389 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &poly[0],&poly[2], color);
1390 /*DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &poly[4],&poly[5], color); */
1393 /** Calculate where to put the second arrowhead of a double arrow
1394 * @param second_to Return value for the point where the second arrowhead
1395 * should point to.
1396 * @param second_from Return value for the point where the second arrowhead
1397 * should point from.
1398 * @param to Where the first arrowhead should point to.
1399 * @param from Where the whole arrow points from (e.g. end of stem)
1400 * @param length The length of each arrowhead.
1402 static void
1403 calculate_double_arrow(Point *second_to, Point *second_from,
1404 Point *to, Point *from, real length)
1406 Point delta;
1407 real len;
1409 delta = *to;
1410 point_sub(&delta, from);
1411 len = sqrt(point_dot(&delta, &delta));
1412 if (len <= 0.0001) {
1413 delta.x=1.0;
1414 delta.y=0.0;
1415 } else {
1416 delta.x/=len;
1417 delta.y/=len;
1420 point_scale(&delta, length/2);
1422 *second_to = *to;
1423 point_sub(second_to, &delta);
1424 point_sub(second_to, &delta);
1425 *second_from = *from;
1426 point_add(second_from, &delta);
1427 point_add(second_from, &delta);
1430 /** Draw a double-triangle arrowhead.
1431 * @param renderer A renderer instance to draw into
1432 * @param to The point that the arrow points to.
1433 * @param from Where the arrow points from (e.g. end of stem)
1434 * @param length The length of the arrow
1435 * @param width The width of the arrow
1436 * @param linewidth The thickness of the lines used to draw the arrow.
1437 * @param color The color used for drawing the arrowhead.
1439 static void
1440 draw_double_triangle(DiaRenderer *renderer, Point *to, Point *from,
1441 real length, real width, real linewidth, Color *color)
1443 Point second_from, second_to;
1445 draw_triangle(renderer, to, from, length, width, linewidth, color);
1446 calculate_double_arrow(&second_to, &second_from, to, from, length+linewidth);
1447 draw_triangle(renderer, &second_to, &second_from, length, width, linewidth, color);
1450 /** Draw a filled double-triangle arrowhead.
1451 * @param renderer A renderer instance to draw into
1452 * @param to The point that the arrow points to.
1453 * @param from Where the arrow points from (e.g. end of stem)
1454 * @param length The length of the arrow
1455 * @param width The width of the arrow
1456 * @param linewidth The thickness of the lines used to draw the arrow.
1457 * @param color The color used for drawing the arrowhead.
1459 static void
1460 fill_double_triangle(DiaRenderer *renderer, Point *to, Point *from,
1461 real length, real width, Color *color)
1463 Point second_from, second_to;
1465 fill_triangle(renderer, to, from, length, width, color);
1466 calculate_double_arrow(&second_to, &second_from, to, from, length);
1467 fill_triangle(renderer, &second_to, &second_from, length, width, color);
1470 /** Calculate the points needed to draw a concave arrowhead.
1471 * @param poly A 4-element array of return points:
1472 * poly[0] is the tip of the arrow.
1473 * poly[1] is the right-hand point of the arrow.
1474 * poly[2] is the rear indent point of the arrow.
1475 * poly[3] is the left-hand point of the arrow.
1476 * @param to Where the arrow points to.
1477 * @param from Where the arrow points from (e.g. bezier control point)
1478 * @param length The length of the arrow.
1479 * @param width The width of the arrow.
1481 static void
1482 calculate_concave(Point *poly, Point *to, Point *from,
1483 real length, real width)
1485 Point delta;
1486 Point orth_delta;
1487 real len;
1489 delta = *to;
1490 point_sub(&delta, from);
1491 len = sqrt(point_dot(&delta, &delta));
1492 if (len <= 0.0001) {
1493 delta.x=1.0;
1494 delta.y=0.0;
1495 } else {
1496 delta.x/=len;
1497 delta.y/=len;
1500 orth_delta.x = delta.y;
1501 orth_delta.y = -delta.x;
1503 point_scale(&delta, length/4.0);
1504 point_scale(&orth_delta, width/2.0);
1506 poly[0] = *to;
1507 poly[1] = *to;
1508 point_sub(&poly[1], &delta);
1509 point_sub(&poly[1], &delta);
1510 point_sub(&poly[1], &delta);
1511 point_sub(&poly[1], &delta);
1512 point_sub(&poly[1], &orth_delta);
1513 poly[2] = *to;
1514 point_sub(&poly[2], &delta);
1515 point_sub(&poly[2], &delta);
1516 point_sub(&poly[2], &delta);
1517 poly[3] = *to;
1518 point_add(&poly[3], &orth_delta);
1519 point_sub(&poly[3], &delta);
1520 point_sub(&poly[3], &delta);
1521 point_sub(&poly[3], &delta);
1522 point_sub(&poly[3], &delta);
1525 /** Draw a concave triangle arrowhead.
1526 * @param renderer A renderer instance to draw into
1527 * @param to The point that the arrow points to.
1528 * @param from Where the arrow points from (e.g. end of stem)
1529 * @param length The length of the arrow
1530 * @param width The width of the arrow
1531 * @param linewidth The thickness of the lines used to draw the arrow.
1532 * @param fg_color The color used for drawing the arrowhead lines
1533 * @param bg_color The color used for drawing the arrowhead interior.
1535 static void
1536 draw_concave_triangle(DiaRenderer *renderer, Point *to, Point *from,
1537 real length, real width, real linewidth,
1538 Color *fg_color, Color *bg_color)
1540 Point poly[4];
1542 calculate_concave(poly, to, from, length, width);
1544 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1545 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1546 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1548 if (fg_color == bg_color)
1549 DIA_RENDERER_GET_CLASS(renderer)->fill_polygon(renderer, poly, 4, bg_color);
1550 DIA_RENDERER_GET_CLASS(renderer)->draw_polygon(renderer, poly, 4, fg_color);
1553 /** Draw a rounded (half-circle) arrowhead.
1554 * @param renderer A renderer instance to draw into
1555 * @param to The point that the arrow points to.
1556 * @param from Where the arrow points from (e.g. end of stem)
1557 * @param length The length of the arrow
1558 * @param width The width of the arrow
1559 * @param linewidth The thickness of the lines used to draw the arrow.
1560 * @param fg_color The color used for drawing the arrowhead lines
1561 * @param bg_color Ignored.
1563 static void
1564 draw_rounded(DiaRenderer *renderer, Point *to, Point *from,
1565 real length, real width, real linewidth,
1566 Color *fg_color, Color *bg_color)
1568 Point p = *to;
1569 Point delta;
1570 real len, rayon;
1571 real rapport;
1572 real angle_start;
1574 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1575 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1576 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1577 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1579 delta = *from;
1581 point_sub(&delta, to);
1583 len = sqrt(point_dot(&delta, &delta)); /* line length */
1584 rayon = (length / 2.0);
1585 rapport = rayon / len;
1587 p.x += delta.x * rapport;
1588 p.y += delta.y * rapport;
1590 angle_start = 90.0 - asin((p.y - to->y) / rayon) * (180.0 / 3.14);
1591 if (p.x - to->x < 0) { angle_start = 360.0 - angle_start; }
1593 DIA_RENDERER_GET_CLASS(renderer)->draw_arc(renderer, &p, width, length, angle_start, angle_start - 180.0, fg_color);
1595 p.x += delta.x * rapport;
1596 p.y += delta.y * rapport;
1597 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &p, to, fg_color);
1600 /** Draw an open rounded arrowhead.
1601 * @param renderer A renderer instance to draw into
1602 * @param to The point that the arrow points to.
1603 * @param from Where the arrow points from (e.g. end of stem)
1604 * @param length The length of the arrow
1605 * @param width The width of the arrow
1606 * @param linewidth The thickness of the lines used to draw the arrow.
1607 * @param fg_color The color used for drawing the arrowhead lines
1608 * @param bg_color Ignored.
1609 * @todo Describe the arrowhead better.
1611 static void
1612 draw_open_rounded(DiaRenderer *renderer, Point *to, Point *from,
1613 real length, real width, real linewidth,
1614 Color *fg_color, Color *bg_color)
1616 Point p = *to;
1617 Point delta;
1618 real len, rayon;
1619 real rapport;
1620 real angle_start;
1621 Point p_line;
1623 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1624 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1625 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1627 delta = *from;
1629 point_sub(&delta, to);
1631 len = sqrt(point_dot(&delta, &delta)); /* line length */
1632 rayon = (length / 2.0);
1633 rapport = rayon / len;
1635 p.x += delta.x * rapport;
1636 p.y += delta.y * rapport;
1638 angle_start = 90.0 - asin((p.y - to->y) / rayon) * (180.0 / 3.14);
1639 if (p.x - to->x < 0) { angle_start = 360.0 - angle_start; }
1641 p_line = p;
1642 p_line.x += delta.x * rapport;
1643 p_line.y += delta.y * rapport;
1645 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth * 2.0);
1646 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &p_line, to, bg_color);
1648 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1649 DIA_RENDERER_GET_CLASS(renderer)->draw_arc(renderer, &p, width, length, angle_start - 180.0, angle_start, fg_color);
1652 /** Draw an arrowhead with a circle in front of a triangle, filled.
1653 * @param renderer A renderer instance to draw into
1654 * @param to The point that the arrow points to.
1655 * @param from Where the arrow points from (e.g. end of stem)
1656 * @param length The length of the arrow
1657 * @param width The width of the arrow
1658 * @param linewidth The thickness of the lines used to draw the arrow.
1659 * @param fg_color The color used for drawing the arrowhead lines
1660 * @param bg_color Ignored.
1662 static void
1663 draw_filled_dot_n_triangle(DiaRenderer *renderer, Point *to, Point *from,
1664 real length, real width, real linewidth,
1665 Color *fg_color, Color *bg_color)
1667 Point p_dot = *to, p_tri = *to, delta;
1668 real len, rayon;
1669 real rapport;
1670 Point poly[3];
1672 DIA_RENDERER_GET_CLASS(renderer)->set_linecaps(renderer, LINECAPS_BUTT);
1673 DIA_RENDERER_GET_CLASS(renderer)->set_linejoin(renderer, LINEJOIN_MITER);
1674 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1675 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1677 delta = *from;
1679 point_sub(&delta, to);
1681 len = sqrt(point_dot(&delta, &delta)); /* line length */
1683 /* dot */
1684 rayon = (width / 2.0);
1685 rapport = rayon / len;
1686 p_dot.x += delta.x * rapport;
1687 p_dot.y += delta.y * rapport;
1688 DIA_RENDERER_GET_CLASS(renderer)->fill_ellipse(renderer, &p_dot,
1689 width, width, fg_color);
1690 /* triangle */
1691 rapport = width / len;
1692 p_tri.x += delta.x * rapport;
1693 p_tri.y += delta.y * rapport;
1694 calculate_arrow(poly, &p_tri, from, length, width);
1695 DIA_RENDERER_GET_CLASS(renderer)->fill_polygon(renderer, poly, 3, fg_color);
1698 /** Draw an arrowhead that is simply three dots (ellipsis)
1699 * @param renderer A renderer instance to draw into
1700 * @param to The point that the arrow points to.
1701 * @param from Where the arrow points from (e.g. end of stem)
1702 * @param length The length of the arrow
1703 * @param width The width of the arrow
1704 * @param linewidth The thickness of the lines used to draw the arrow.
1705 * @param fg_color The color used for drawing the arrowhead lines
1707 static void
1708 draw_three_dots(DiaRenderer *renderer, Point *to, Point *from,
1709 real length, real width, real linewidth, Color *fg_color)
1712 gdouble dot_width;
1713 gdouble hole_width;
1714 gdouble len;
1715 gint i;
1716 Point delta, dot_from, dot_to;
1718 delta = *to;
1719 point_sub(&delta, from);
1720 len = point_len(&delta);
1721 point_normalize(&delta);
1723 if (len > 4 * width)
1724 width *= 2;
1725 dot_width = width * 0.2;
1726 hole_width = width / 3 - dot_width;
1728 DIA_RENDERER_GET_CLASS(renderer)->set_linewidth(renderer, linewidth);
1729 DIA_RENDERER_GET_CLASS(renderer)->set_linestyle(renderer, LINESTYLE_SOLID);
1731 for (i = 0; i < 3; i++) {
1732 dot_from.x = to->x - i * (dot_width + hole_width) * delta.x;
1733 dot_from.y = to->y - i * (dot_width + hole_width) * delta.y;
1734 dot_to.x = to->x - ((i + 1) * dot_width + i * hole_width) * delta.x;
1735 dot_to.y = to->y - ((i + 1) * dot_width + i * hole_width) * delta.y;
1736 DIA_RENDERER_GET_CLASS(renderer)->draw_line(renderer, &dot_from, &dot_to, fg_color);
1740 /** Draw any arrowhead.
1741 * @param renderer A renderer instance to draw into
1742 * @param type Which kind of arrowhead to draw.
1743 * @param to The point that the arrow points to.
1744 * @param from Where the arrow points from (e.g. end of stem)
1745 * @param length The length of the arrow
1746 * @param width The width of the arrow
1747 * @param linewidth The thickness of the lines used to draw the arrow.
1748 * @param fg_color The color used for drawing the arrowhead lines
1749 * @param bg_color The color used for drawing the arrowhead interior.
1751 void
1752 arrow_draw(DiaRenderer *renderer, ArrowType type,
1753 Point *to, Point *from,
1754 real length, real width, real linewidth,
1755 Color *fg_color, Color *bg_color)
1757 switch(type) {
1758 case ARROW_NONE:
1759 break;
1760 case ARROW_LINES:
1761 draw_lines(renderer, to, from, length, width, linewidth, fg_color);
1762 break;
1763 case ARROW_HALF_HEAD:
1764 draw_halfhead(renderer, to, from, length, width, linewidth, fg_color);
1765 break;
1766 case ARROW_HOLLOW_TRIANGLE:
1767 fill_triangle(renderer, to, from, length, width, bg_color);
1768 draw_triangle(renderer, to, from, length, width, linewidth, fg_color);
1769 break;
1770 case ARROW_UNFILLED_TRIANGLE:
1771 draw_triangle(renderer, to, from, length, width, linewidth, fg_color);
1772 break;
1773 case ARROW_FILLED_TRIANGLE:
1774 fill_triangle(renderer, to, from, length, width, fg_color);
1775 break;
1776 case ARROW_HOLLOW_DIAMOND:
1777 fill_diamond(renderer, to, from, length, width, bg_color);
1778 draw_diamond(renderer, to, from, length, width, linewidth, fg_color);
1779 break;
1780 case ARROW_FILLED_DIAMOND:
1781 fill_diamond(renderer, to, from, length, width, fg_color);
1782 break;
1783 case ARROW_HALF_DIAMOND:
1784 /* fill_diamond(renderer, to, from, length, width, bg_color);*/
1785 draw_half_diamond(renderer, to, from, length, width, linewidth, fg_color);
1786 break;
1787 case ARROW_SLASHED_CROSS:
1788 draw_slashed_cross(renderer, to, from, length, width, linewidth, fg_color);
1789 break;
1790 case ARROW_FILLED_ELLIPSE:
1791 draw_fill_ellipse(renderer,to,from,length,width,linewidth,
1792 fg_color,NULL);
1793 break;
1794 case ARROW_HOLLOW_ELLIPSE:
1795 draw_fill_ellipse(renderer,to,from,length,width,linewidth,
1796 fg_color,bg_color);
1797 break;
1798 case ARROW_DOUBLE_HOLLOW_TRIANGLE:
1799 fill_double_triangle(renderer, to, from, length+(linewidth/2), width, bg_color);
1800 draw_double_triangle(renderer, to, from, length, width, linewidth, fg_color);
1801 break;
1802 case ARROW_DOUBLE_FILLED_TRIANGLE:
1803 fill_double_triangle(renderer, to, from, length, width, fg_color);
1804 break;
1805 case ARROW_FILLED_DOT:
1806 draw_fill_dot(renderer,to,from,length,width,linewidth,fg_color,fg_color);
1807 break;
1808 case ARROW_BLANKED_DOT:
1809 draw_fill_dot(renderer,to,from,length,width,linewidth,fg_color,bg_color);
1810 break;
1811 case ARROW_FILLED_BOX:
1812 draw_fill_box(renderer,to,from,length,width,linewidth,fg_color,fg_color);
1813 break;
1814 case ARROW_BLANKED_BOX:
1815 draw_fill_box(renderer,to,from,length,width,linewidth,fg_color,bg_color);
1816 break;
1817 case ARROW_DIMENSION_ORIGIN:
1818 draw_fill_dot(renderer,to,from,length,width,linewidth,fg_color,NULL);
1819 break;
1820 case ARROW_INTEGRAL_SYMBOL:
1821 draw_integral(renderer,to,from,length,width,linewidth,fg_color);
1822 break;
1823 case ARROW_SLASH_ARROW:
1824 draw_slashed(renderer,to,from,length,width,linewidth,fg_color);
1825 break;
1826 case ARROW_ONE_OR_MANY:
1827 draw_one_or_many(renderer,to,from,length,width,linewidth,fg_color,bg_color);
1828 break;
1829 case ARROW_NONE_OR_MANY:
1830 draw_none_or_many(renderer,to,from,length,width,linewidth,fg_color,bg_color);
1831 break;
1832 case ARROW_ONE_EXACTLY:
1833 draw_one_exactly(renderer,to,from,length,width,linewidth,fg_color,bg_color);
1834 break;
1835 case ARROW_ONE_OR_NONE:
1836 draw_one_or_none(renderer,to,from,length,width,linewidth,fg_color,bg_color);
1837 break;
1838 case ARROW_CROW_FOOT:
1839 draw_crow_foot(renderer,to,from,length,width,linewidth,fg_color,bg_color);
1840 break;
1841 case ARROW_CROSS:
1842 draw_cross(renderer, to, from, length, width, linewidth, fg_color);
1843 break;
1844 case ARROW_FILLED_CONCAVE:
1845 draw_concave_triangle(renderer, to, from, length, width, linewidth, fg_color, fg_color);
1846 break;
1847 case ARROW_BLANKED_CONCAVE:
1848 draw_concave_triangle(renderer, to, from, length, width, linewidth, fg_color, bg_color);
1849 break;
1850 case ARROW_ROUNDED:
1851 draw_rounded(renderer, to, from, length, width, linewidth, fg_color, bg_color);
1852 break;
1853 case ARROW_OPEN_ROUNDED:
1854 draw_open_rounded(renderer, to, from, length, width, linewidth,
1855 fg_color, bg_color);
1856 break;
1857 case ARROW_FILLED_DOT_N_TRIANGLE:
1858 draw_filled_dot_n_triangle(renderer, to, from, length, width, linewidth,
1859 fg_color, bg_color);
1860 break;
1861 case ARROW_BACKSLASH:
1862 draw_backslash(renderer,to,from,length,width,linewidth,fg_color);
1863 break;
1864 case ARROW_THREE_DOTS:
1865 draw_three_dots(renderer,to,from,length,width,linewidth,fg_color);
1866 break;
1867 case MAX_ARROW_TYPE:
1868 break;
1872 /* *** Loading and saving arrows. *** */
1873 /** Makes sure an arrow object is within reasonable limits
1874 * @param arrow An arrow object. This object may be modified to comply with
1875 * restrictions of MIN_ARROW_DIMENSION on its length and width and to have a
1876 * legal head type.
1878 static void
1879 sanitize_arrow(Arrow *arrow)
1881 if (arrow->length < MIN_ARROW_DIMENSION ||
1882 arrow->width < MIN_ARROW_DIMENSION ||
1883 arrow->type < 0 || arrow->type > MAX_ARROW_TYPE) {
1884 arrow->type = ARROW_NONE;
1885 arrow->width = DEFAULT_ARROW_WIDTH;
1886 arrow->length = DEFAULT_ARROW_LENGTH;
1890 /** Save the arrow information into three attributes.
1891 * @param obj_node The XML node to save to.
1892 * @param arrow the arrow to save.
1893 * @param type_attribute the name of the attribute of the arrow type.
1894 * @param length_attribute the name of the attribute of the arrow length.
1895 * @param width_attribute the name of the attribte of the arrow width.
1897 void
1898 save_arrow(ObjectNode obj_node, Arrow *arrow, gchar *type_attribute,
1899 gchar *length_attribute, gchar *width_attribute)
1901 data_add_enum(new_attribute(obj_node, type_attribute),
1902 arrow->type);
1903 data_add_real(new_attribute(obj_node, length_attribute),
1904 arrow->length);
1905 data_add_real(new_attribute(obj_node, width_attribute),
1906 arrow->width);
1909 /** Load arrow information from three attributes.
1910 * @param obj_node The XML node to load from.
1911 * @param arrow the arrow to store the data info.
1912 * @param type_attribute the name of the attribute of the arrow type.
1913 * @param length_attribute the name of the attribute of the arrow length.
1914 * @param width_attribute the name of the attribte of the arrow width.
1916 void
1917 load_arrow(ObjectNode obj_node, Arrow *arrow, gchar *type_attribute,
1918 gchar *length_attribute, gchar *width_attribute)
1920 AttributeNode *attr;
1922 arrow->type = ARROW_NONE;
1923 arrow->length = DEFAULT_ARROW_LENGTH;
1924 arrow->width = DEFAULT_ARROW_WIDTH;
1925 attr = object_find_attribute(obj_node, type_attribute);
1926 if (attr != NULL)
1927 arrow->type = data_enum(attribute_first_data(attr));
1928 attr = object_find_attribute(obj_node, length_attribute);
1929 if (attr != NULL)
1930 arrow->length = data_real(attribute_first_data(attr));
1931 attr = object_find_attribute(obj_node, width_attribute);
1932 if (attr != NULL)
1933 arrow->width = data_real(attribute_first_data(attr));
1935 sanitize_arrow(arrow);
1938 /** Returns the arrow type that corresponds to a given name.
1939 * @param name The name of an arrow type (case sensitive)
1940 * @returns The arrow type (@see ArrowType enum in arrows.h). Returns
1941 * ARROW_NONE if the name doesn't match any known arrow head type.
1943 ArrowType
1944 arrow_type_from_name(gchar *name)
1946 int i;
1947 for (i = 0; arrow_types[i].name != NULL; i++) {
1948 if (!strcmp(arrow_types[i].name, name)) {
1949 return arrow_types[i].enum_value;
1952 printf("Unknown arrow type %s\n", name);
1953 return 0;
1956 /** Return the index into the arrow_types array (which is sorted by an
1957 * arbitrary order that we like) for a given arrow type.
1958 * @param atype An arrow type as defined in arrows.h
1959 * @returns An index into the arrow_types array.
1961 gint
1962 arrow_index_from_type(ArrowType atype)
1964 int i = 0;
1966 for (i = 0; arrow_types[i].name != NULL; i++) {
1967 if (arrow_types[i].enum_value == atype) {
1968 return i;
1971 printf("Can't find arrow index for type %d\n", atype);
1972 return 0;
1975 /** Get a list of all known arrow head names, in arrow_types order.
1976 * @returns A newly allocated list of the names. The list should be
1977 * freed after use, but the strings are owned by arrow_types.
1979 GList *
1980 get_arrow_names(void)
1982 int i = 0;
1983 GList *arrows = NULL;
1985 for (i = 0; arrow_types[i].name != NULL; i++) {
1986 arrows = g_list_append(arrows, arrow_types[i].name);
1988 return arrows;