[docs] Removed useless tracked files from adg
[adg.git] / adg / adg-arrow-style.c
blob098ad316196b64cf410a632473aeacfd0e271876
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:arrow-style
23 * @title: AdgArrowStyle
24 * @short_description: Arrow rendering related stuff
26 * Contains parameters on how to draw arrows, providing a way to register a
27 * custom rendering callback.
30 /**
31 * AdgArrowStyle:
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
35 **/
38 #include "adg-arrow-style.h"
39 #include "adg-arrow-style-private.h"
40 #include "adg-context.h"
41 #include "adg-intl.h"
42 #include "adg-util.h"
43 #include <math.h>
46 enum {
47 PROP_0,
48 PROP_SIZE,
49 PROP_ANGLE,
50 PROP_MARGIN,
51 PROP_RENDERER
55 static void get_property (GObject *object,
56 guint prop_id,
57 GValue *value,
58 GParamSpec *pspec);
59 static void set_property (GObject *object,
60 guint prop_id,
61 const GValue *value,
62 GParamSpec *pspec);
63 static GPtrArray * get_pool (void);
64 static void arrow_renderer (AdgArrowStyle *arrow_style,
65 cairo_t *cr,
66 CpmlSegment *segment);
67 static void triangle_renderer (AdgArrowStyle *arrow_style,
68 cairo_t *cr,
69 CpmlSegment *segment);
70 static void dot_renderer (AdgArrowStyle *arrow_style,
71 cairo_t *cr,
72 CpmlSegment *segment);
73 static void circle_renderer (AdgArrowStyle *arrow_style,
74 cairo_t *cr,
75 CpmlSegment *segment);
76 static void block_renderer (AdgArrowStyle *arrow_style,
77 cairo_t *cr,
78 CpmlSegment *segment);
79 static void square_renderer (AdgArrowStyle *arrow_style,
80 cairo_t *cr,
81 CpmlSegment *segment);
82 static void tick_renderer (AdgArrowStyle *arrow_style,
83 cairo_t *cr,
84 CpmlSegment *segment);
85 static void draw_triangle (cairo_t *cr,
86 AdgArrowStyle *arrow_style,
87 CpmlSegment *segment);
88 static void draw_circle (cairo_t *cr,
89 AdgArrowStyle *arrow_style,
90 CpmlSegment *segment);
93 G_DEFINE_TYPE(AdgArrowStyle, adg_arrow_style, ADG_TYPE_STYLE)
96 static void
97 adg_arrow_style_class_init(AdgArrowStyleClass *klass)
99 GObjectClass *gobject_class;
100 AdgStyleClass *style_class;
101 GParamSpec *param;
103 gobject_class = (GObjectClass *) klass;
104 style_class = (AdgStyleClass *) klass;
106 g_type_class_add_private(klass, sizeof(AdgArrowStylePrivate));
108 gobject_class->get_property = get_property;
109 gobject_class->set_property = set_property;
111 style_class->get_pool = get_pool;
113 param = g_param_spec_double("size",
114 P_("Arrow Size"),
116 ("The size of the arrow, a renderer dependent parameter"),
117 -G_MAXDOUBLE, G_MAXDOUBLE, 14.,
118 G_PARAM_READWRITE);
119 g_object_class_install_property(gobject_class, PROP_SIZE, param);
121 param = g_param_spec_double("angle",
122 P_("Arrow Angle"),
124 ("The angle of the arrow, a renderer dependent parameter"),
125 -G_MAXDOUBLE, G_MAXDOUBLE, G_PI / 6.,
126 G_PARAM_READWRITE);
127 g_object_class_install_property(gobject_class, PROP_ANGLE, param);
129 param = g_param_spec_double("margin",
130 P_("Arrow Margin"),
132 ("The margin of the arrow, a renderer dependent parameter"),
133 -G_MAXDOUBLE, G_MAXDOUBLE, 14.,
134 G_PARAM_READWRITE);
135 g_object_class_install_property(gobject_class, PROP_MARGIN, param);
137 param = g_param_spec_pointer("renderer",
138 P_("Renderer Callback"),
140 ("The callback to call to renderer this arrow type"),
141 G_PARAM_READWRITE);
142 g_object_class_install_property(gobject_class, PROP_RENDERER, param);
145 static void
146 adg_arrow_style_init(AdgArrowStyle *arrow_style)
148 AdgArrowStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(arrow_style,
149 ADG_TYPE_ARROW_STYLE,
150 AdgArrowStylePrivate);
152 data->size = 14.;
153 data->angle = G_PI / 6.;
154 data->margin = 14.;
155 data->renderer = NULL;
157 arrow_style->data = data;
160 static void
161 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
163 AdgArrowStylePrivate *data = ((AdgArrowStyle *) object)->data;
165 switch (prop_id) {
166 case PROP_SIZE:
167 g_value_set_double(value, data->size);
168 break;
169 case PROP_ANGLE:
170 g_value_set_double(value, data->angle);
171 break;
172 case PROP_MARGIN:
173 g_value_set_double(value, data->margin);
174 break;
175 case PROP_RENDERER:
176 g_value_set_pointer(value, data->renderer);
177 break;
178 default:
179 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
180 break;
184 static void
185 set_property(GObject *object,
186 guint prop_id, const GValue *value, GParamSpec *pspec)
188 AdgArrowStylePrivate *data = ((AdgArrowStyle *) object)->data;
190 switch (prop_id) {
191 case PROP_SIZE:
192 data->size = g_value_get_double(value);
193 break;
194 case PROP_ANGLE:
195 data->angle = g_value_get_double(value);
196 break;
197 case PROP_MARGIN:
198 data->margin = g_value_get_double(value);
199 break;
200 case PROP_RENDERER:
201 data->renderer = g_value_get_pointer(value);
202 break;
203 default:
204 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
205 break;
211 * adg_arrow_style_get_slot:
213 * Gets the slot id for this style class.
215 * Return value: the slot
217 AdgStyleSlot
218 adg_arrow_style_get_slot(void)
220 static AdgStyleSlot slot = -1;
222 if (G_UNLIKELY(slot < 0))
223 slot = adg_context_get_slot(ADG_TYPE_ARROW_STYLE);
225 return slot;
229 * adg_arrow_style_new:
231 * Constructs a new arrow style initialized with default params.
233 * Return value: a new arrow style
235 AdgStyle *
236 adg_arrow_style_new(void)
238 return g_object_new(ADG_TYPE_ARROW_STYLE, NULL);
242 * adg_arrow_style_render:
243 * @arrow_style: an #AdgArrowStyle instance
244 * @cr: the cairo context to use
245 * @segment: the #CpmlSegment where the arrow must be rendered
247 * Renders an arrow on @cr at the beginning of @segment in the way
248 * specified by @arrow_style.
250 void
251 adg_arrow_style_render(AdgArrowStyle *arrow_style,
252 cairo_t *cr, CpmlSegment *segment)
254 AdgStyleClass *style_class;
255 AdgArrowStylePrivate *data;
257 g_return_if_fail(arrow_style != NULL);
258 g_return_if_fail(cr != NULL);
259 g_return_if_fail(segment != NULL);
261 data = arrow_style->data;
263 /* NULL renderer */
264 if (data->renderer == NULL)
265 return;
267 style_class = (AdgStyleClass *) adg_arrow_style_parent_class;
269 if (style_class->apply != NULL)
270 style_class->apply((AdgStyle *) arrow_style, cr);
272 data->renderer(arrow_style, cr, segment);
276 * adg_arrow_style_get_size:
277 * @arrow_style: an #AdgArrowStyle object
279 * Gets the size (in paper units) of the arrow (renderer dependent value).
281 * Return value: the size value
283 gdouble
284 adg_arrow_style_get_size(AdgArrowStyle *arrow_style)
286 AdgArrowStylePrivate *data;
288 g_return_val_if_fail(ADG_IS_ARROW_STYLE(arrow_style), 0.);
290 data = arrow_style->data;
292 return data->size;
296 * adg_arrow_style_set_size:
297 * @arrow_style: an #AdgArrowStyle object
298 * @size: the new size
300 * Sets a new size.
302 void
303 adg_arrow_style_set_size(AdgArrowStyle *arrow_style, gdouble size)
305 AdgArrowStylePrivate *data;
307 g_return_if_fail(ADG_IS_ARROW_STYLE(arrow_style));
309 data = arrow_style->data;
310 data->size = size;
312 g_object_notify((GObject *) arrow_style, "size");
316 * adg_arrow_style_get_angle:
317 * @arrow_style: an #AdgArrowStyle object
319 * Gets the angle (in degree) of the arrow (renderer dependent value).
321 * Return value: the angle value
323 gdouble
324 adg_arrow_style_get_angle(AdgArrowStyle *arrow_style)
326 AdgArrowStylePrivate *data;
328 g_return_val_if_fail(ADG_IS_ARROW_STYLE(arrow_style), 0.);
330 data = arrow_style->data;
332 return data->angle;
336 * adg_arrow_style_set_angle:
337 * @arrow_style: an #AdgArrowStyle object
338 * @angle: the new angle
340 * Sets a new angle.
342 void
343 adg_arrow_style_set_angle(AdgArrowStyle *arrow_style, gdouble angle)
345 AdgArrowStylePrivate *data;
347 g_return_if_fail(ADG_IS_ARROW_STYLE(arrow_style));
349 data = arrow_style->data;
350 data->angle = angle;
352 g_object_notify((GObject *) arrow_style, "angle");
356 * adg_arrow_style_get_margin:
357 * @arrow_style: an #AdgArrowStyle object
359 * Gets the margin (in paper units) of this arrow (renderer dependent value).
360 * The margin is also used to trim the baseline of this amount.
362 * Return value: the margin value
364 gdouble
365 adg_arrow_style_get_margin(AdgArrowStyle *arrow_style)
367 AdgArrowStylePrivate *data;
369 g_return_val_if_fail(ADG_IS_ARROW_STYLE(arrow_style), 0.);
371 data = arrow_style->data;
373 return data->margin;
377 * adg_arrow_style_set_margin:
378 * @arrow_style: an #AdgArrowStyle object
379 * @margin: the new margin
381 * Sets a new margin.
383 void
384 adg_arrow_style_set_margin(AdgArrowStyle *arrow_style, gdouble margin)
386 AdgArrowStylePrivate *data;
388 g_return_if_fail(ADG_IS_ARROW_STYLE(arrow_style));
390 data = arrow_style->data;
391 data->margin = margin;
393 g_object_notify((GObject *) arrow_style, "margin");
397 * adg_arrow_style_get_renderer:
398 * @arrow_style: an #AdgArrowStyle object
400 * Gets the renderer of @arrow_style.
402 * Return value: the renderer value
404 AdgArrowRenderer
405 adg_arrow_style_get_renderer(AdgArrowStyle *arrow_style)
407 AdgArrowStylePrivate *data;
409 g_return_val_if_fail(ADG_IS_ARROW_STYLE(arrow_style), NULL);
411 data = arrow_style->data;
413 return data->renderer;
417 * adg_arrow_style_set_renderer:
418 * @arrow_style: an #AdgArrowStyle object
419 * @renderer: the new renderer
421 * Sets a new renderer.
423 void
424 adg_arrow_style_set_renderer(AdgArrowStyle *arrow_style,
425 AdgArrowRenderer renderer)
427 AdgArrowStylePrivate *data;
429 g_return_if_fail(ADG_IS_ARROW_STYLE(arrow_style));
431 data = arrow_style->data;
432 data->renderer = renderer;
434 g_object_notify((GObject *) arrow_style, "renderer");
438 static GPtrArray *
439 get_pool(void)
441 static GPtrArray *pool = NULL;
443 if (G_UNLIKELY(pool == NULL)) {
444 pool = g_ptr_array_sized_new(ADG_ARROW_STYLE_LAST);
446 pool->pdata[ADG_ARROW_STYLE_ARROW] =
447 g_object_new(ADG_TYPE_ARROW_STYLE, "renderer", arrow_renderer,
448 NULL);
449 pool->pdata[ADG_ARROW_STYLE_TRIANGLE] =
450 g_object_new(ADG_TYPE_ARROW_STYLE, "renderer",
451 triangle_renderer, NULL);
452 pool->pdata[ADG_ARROW_STYLE_DOT] =
453 g_object_new(ADG_TYPE_ARROW_STYLE, "size", 5., "angle", 0.,
454 "margin", 2.5, "renderer", dot_renderer, NULL);
455 pool->pdata[ADG_ARROW_STYLE_CIRCLE] =
456 g_object_new(ADG_TYPE_ARROW_STYLE, "size", 10., "angle", 0.,
457 "margin", 5., "renderer", circle_renderer, NULL);
458 pool->pdata[ADG_ARROW_STYLE_BLOCK] =
459 g_object_new(ADG_TYPE_ARROW_STYLE, "size", 10., "angle", 0.,
460 "margin", 5., "renderer", block_renderer, NULL);
461 pool->pdata[ADG_ARROW_STYLE_SQUARE] =
462 g_object_new(ADG_TYPE_ARROW_STYLE, "size", 10., "angle", 0.,
463 "margin", -0.1, "renderer", square_renderer,
464 NULL);
465 pool->pdata[ADG_ARROW_STYLE_TICK] =
466 g_object_new(ADG_TYPE_ARROW_STYLE, "size", 20., "angle",
467 G_PI / 3., "margin", 0., "renderer",
468 tick_renderer, NULL);
470 pool->len = ADG_ARROW_STYLE_LAST;
473 return pool;
476 static void
477 arrow_renderer(AdgArrowStyle *arrow_style, cairo_t *cr, CpmlSegment *segment)
479 draw_triangle(cr, arrow_style, segment);
480 cairo_fill(cr);
483 static void
484 triangle_renderer(AdgArrowStyle *arrow_style, cairo_t *cr, CpmlSegment *segment)
486 draw_triangle(cr, arrow_style, segment);
487 cairo_stroke(cr);
490 static void
491 dot_renderer(AdgArrowStyle *arrow_style, cairo_t *cr, CpmlSegment *segment)
493 draw_circle(cr, arrow_style, segment);
494 cairo_fill(cr);
497 static void
498 circle_renderer(AdgArrowStyle *arrow_style, cairo_t *cr, CpmlSegment *segment)
500 draw_circle(cr, arrow_style, segment);
501 cairo_stroke(cr);
504 static void
505 block_renderer(AdgArrowStyle *arrow_style, cairo_t *cr, CpmlSegment *segment)
507 ADG_STUB();
510 static void
511 square_renderer(AdgArrowStyle *arrow_style, cairo_t *cr, CpmlSegment *segment)
513 ADG_STUB();
516 static void
517 tick_renderer(AdgArrowStyle *arrow_style, cairo_t *cr, CpmlSegment *segment)
519 ADG_STUB();
522 static void
523 draw_triangle(cairo_t *cr, AdgArrowStyle *arrow_style, CpmlSegment *segment)
525 AdgArrowStylePrivate *data;
526 double length, height_2;
527 double org_x, org_y;
528 double tmp;
529 CpmlPair tail, tail1, tail2;
530 CpmlPair vector;
532 data = arrow_style->data;
533 length = data->size;
534 height_2 = tan(data->angle / 2.0) * length;
535 cairo_device_to_user_distance(cr, &length, &height_2);
536 org_x = segment->data[1].point.x;
537 org_y = segment->data[1].point.y;
539 switch (segment->data[2].header.type) {
540 case CAIRO_PATH_LINE_TO:
541 vector.x = segment->data[3].point.x - org_x;
542 vector.y = segment->data[3].point.y - org_y;
543 cpml_vector_set_length(&vector, 1.);
545 tail.x = vector.x * length + org_x;
546 tail.y = vector.y * length + org_y;
548 tmp = vector.x;
549 vector.x = -vector.y * height_2;
550 vector.y = tmp * height_2;
552 tail1.x = tail.x + vector.x;
553 tail1.y = tail.y + vector.y;
555 tail2.x = tail.x - vector.x;
556 tail2.y = tail.y - vector.y;
558 cairo_move_to(cr, org_x, org_y);
559 cairo_line_to(cr, tail1.x, tail1.y);
560 cairo_line_to(cr, tail2.x, tail2.y);
561 cairo_close_path(cr);
563 break;
564 case CAIRO_PATH_CURVE_TO:
565 ADG_STUB();
566 break;
567 default:
568 g_assert_not_reached();
572 static void
573 draw_circle(cairo_t *cr, AdgArrowStyle *arrow_style, CpmlSegment *segment)
575 AdgArrowStylePrivate *data;
576 double radius;
577 double dummy;
579 data = arrow_style->data;
580 radius = data->size / 2.;
581 dummy = 0;
583 cairo_device_to_user_distance(cr, &radius, &dummy);
584 cairo_new_path(cr);
585 cairo_arc(cr,
586 segment->data[1].point.x, segment->data[1].point.y,
587 radius, 0., M_PI);