[AdgLDim] Using the new entity transformation APIs
[adg.git] / adg / adg-ldim.c
blobe2b702684755e5c564007352f72f12bd16ad7787
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:adg-ldim
23 * @short_description: Linear dimensions
25 * The #AdgLDim entity represents a linear dimension.
26 **/
28 /**
29 * AdgLDim:
31 * All fields are private and should not be used directly.
32 * Use its public methods instead.
33 **/
36 #include "adg-ldim.h"
37 #include "adg-ldim-private.h"
38 #include "adg-dim-style.h"
39 #include "adg-intl.h"
41 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_ldim_parent_class)
42 #define PARENT_ENTITY_CLASS ((AdgEntityClass *) adg_ldim_parent_class)
45 enum {
46 PROP_0,
47 PROP_DIRECTION,
48 PROP_HAS_EXTENSION1,
49 PROP_HAS_EXTENSION2
53 static void dispose (GObject *object);
54 static void get_property (GObject *object,
55 guint param_id,
56 GValue *value,
57 GParamSpec *pspec);
58 static void set_property (GObject *object,
59 guint param_id,
60 const GValue *value,
61 GParamSpec *pspec);
62 static void invalidate (AdgEntity *entity);
63 static void arrange (AdgEntity *entity);
64 static void render (AdgEntity *entity,
65 cairo_t *cr);
66 static gchar * default_value (AdgDim *dim);
67 static gdouble get_distance (AdgLDim *ldim);
68 static void update_shift (AdgLDim *ldim);
69 static void update_entities (AdgLDim *ldim);
70 static gboolean choose_outside (AdgLDim *ldim);
71 static void dispose_markers (AdgLDim *ldim);
72 static CpmlPath * trail_callback (AdgTrail *trail,
73 gpointer user_data);
76 G_DEFINE_TYPE(AdgLDim, adg_ldim, ADG_TYPE_DIM);
79 static void
80 adg_ldim_class_init(AdgLDimClass *klass)
82 GObjectClass *gobject_class;
83 AdgEntityClass *entity_class;
84 AdgDimClass *dim_class;
85 GParamSpec *param;
87 gobject_class = (GObjectClass *) klass;
88 entity_class = (AdgEntityClass *) klass;
89 dim_class = (AdgDimClass *) klass;
91 g_type_class_add_private(klass, sizeof(AdgLDimPrivate));
93 gobject_class->dispose = dispose;
94 gobject_class->get_property = get_property;
95 gobject_class->set_property = set_property;
97 entity_class->invalidate = invalidate;
98 entity_class->arrange = arrange;
99 entity_class->render = render;
101 dim_class->default_value = default_value;
103 param = g_param_spec_double("direction",
104 P_("Direction"),
105 P_("The inclination angle of the extension lines"),
106 -G_MAXDOUBLE, G_MAXDOUBLE, ADG_DIR_RIGHT,
107 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
108 g_object_class_install_property(gobject_class, PROP_DIRECTION, param);
110 param = g_param_spec_boolean("has-extension1",
111 P_("Has First Extension Line flag"),
112 P_("Show (TRUE) or hide (FALSE) the first extension line"),
113 TRUE, G_PARAM_READWRITE);
114 g_object_class_install_property(gobject_class, PROP_HAS_EXTENSION1, param);
116 param = g_param_spec_boolean("has-extension2",
117 P_("Has Second Extension Line flag"),
118 P_("Show (TRUE) or hide (FALSE) the second extension line"),
119 TRUE, G_PARAM_READWRITE);
120 g_object_class_install_property(gobject_class, PROP_HAS_EXTENSION2, param);
123 static void
124 adg_ldim_init(AdgLDim *ldim)
126 AdgLDimPrivate *data;
127 cairo_path_data_t move_to, line_to;
129 data = G_TYPE_INSTANCE_GET_PRIVATE(ldim, ADG_TYPE_LDIM, AdgLDimPrivate);
130 move_to.header.type = CAIRO_PATH_MOVE_TO;
131 move_to.header.length = 2;
132 line_to.header.type = CAIRO_PATH_LINE_TO;
133 line_to.header.length = 2;
135 data->distance = -1;
136 data->direction = 0;
137 data->has_extension1 = TRUE;
138 data->has_extension2 = TRUE;
140 data->cpml.path.status = CAIRO_STATUS_INVALID_PATH_DATA;
141 data->cpml.path.data = data->cpml.data;
142 data->cpml.path.num_data = G_N_ELEMENTS(data->cpml.data);
143 data->cpml.path.data[0] = move_to;
144 data->cpml.path.data[2] = line_to;
145 data->cpml.path.data[4] = move_to;
146 data->cpml.path.data[6] = line_to;
147 data->cpml.path.data[8] = move_to;
148 data->cpml.path.data[10] = line_to;
149 data->cpml.path.data[12] = move_to;
150 data->cpml.path.data[14] = line_to;
151 data->cpml.path.data[16] = move_to;
152 data->cpml.path.data[18] = line_to;
154 data->trail = NULL;
155 data->marker1 = NULL;
156 data->marker2 = NULL;
158 data->shift.is_arranged = FALSE;
160 ldim->data = data;
163 static void
164 dispose(GObject *object)
166 dispose_markers((AdgLDim *) object);
168 if (PARENT_OBJECT_CLASS->dispose != NULL)
169 PARENT_OBJECT_CLASS->dispose(object);
172 static void
173 get_property(GObject *object,
174 guint prop_id, GValue *value, GParamSpec *pspec)
176 AdgLDimPrivate *data = ((AdgLDim *) object)->data;
178 switch (prop_id) {
179 case PROP_DIRECTION:
180 g_value_set_double(value, data->direction);
181 break;
182 case PROP_HAS_EXTENSION1:
183 g_value_set_boolean(value, data->has_extension1);
184 break;
185 case PROP_HAS_EXTENSION2:
186 g_value_set_boolean(value, data->has_extension2);
187 break;
188 default:
189 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
190 break;
194 static void
195 set_property(GObject *object,
196 guint prop_id, const GValue *value, GParamSpec *pspec)
198 AdgLDimPrivate *data = ((AdgLDim *) object)->data;
200 switch (prop_id) {
201 case PROP_DIRECTION:
202 data->direction = g_value_get_double(value);
203 break;
204 case PROP_HAS_EXTENSION1:
205 data->has_extension1 = g_value_get_boolean(value);
206 break;
207 case PROP_HAS_EXTENSION2:
208 data->has_extension2 = g_value_get_boolean(value);
209 break;
210 default:
211 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
212 break;
218 * adg_ldim_new:
220 * Creates a new - unreferenced - linear dimension. You must, at least, define
221 * the reference points with adg_dim_set_ref(), the dimension direction with
222 * adg_ldim_set_direction() and the position reference using adg_dim_set_pos()
223 * or, better, adg_ldim_set_pos().
225 * Returns: the newly created linear dimension entity
227 AdgLDim *
228 adg_ldim_new(void)
230 return g_object_new(ADG_TYPE_LDIM, NULL);
234 * adg_ldim_new_full:
235 * @ref1: the first reference point
236 * @ref2: the second reference point
237 * @direction: angle where to extend the dimension
238 * @pos: the position reference
240 * Creates a new linear dimension, specifing all the needed properties in
241 * one shot.
243 * Returns: the newly created linear dimension entity
245 AdgLDim *
246 adg_ldim_new_full(const AdgPair *ref1, const AdgPair *ref2,
247 gdouble direction, const AdgPair *pos)
249 AdgLDim *ldim = g_object_new(ADG_TYPE_LDIM, "ref1", ref1, "ref2", ref2,
250 "direction", direction, NULL);
251 adg_ldim_set_pos(ldim, pos);
252 return ldim;
256 * adg_ldim_new_full_explicit:
257 * @ref1_x: the x coordinate of the first reference point
258 * @ref1_y: the y coordinate of the first reference point
259 * @ref2_x: the x coordinate of the second reference point
260 * @ref2_y: the y coordinate of the second reference point
261 * @direction: angle where to extend the dimension
262 * @pos_x: the x coordinate of the position reference
263 * @pos_y: the y coordinate of the position reference
265 * Wrappes adg_ldim_new_full() with explicit values.
267 * Returns: the newly created linear dimension entity
269 AdgLDim *
270 adg_ldim_new_full_explicit(gdouble ref1_x, gdouble ref1_y,
271 gdouble ref2_x, gdouble ref2_y,
272 gdouble direction, gdouble pos_x, gdouble pos_y)
274 AdgPair ref1;
275 AdgPair ref2;
276 AdgPair pos;
278 ref1.x = ref1_x;
279 ref1.y = ref1_y;
280 ref2.x = ref2_x;
281 ref2.y = ref2_y;
282 pos.x = pos_x;
283 pos.y = pos_y;
285 return adg_ldim_new_full(&ref1, &ref2, direction, &pos);
289 * adg_ldim_set_pos:
290 * @ldim: an #AdgLDim entity
291 * @pos: an #AdgPair structure
293 * Sets the position references (pos1 and pos2 properties) of @ldim using a
294 * single @pos point. Before this call, @ldim MUST HAVE defined the reference
295 * points and the direction. If these conditions are not met, an error message
296 * is logged and the position references will not be set.
298 void
299 adg_ldim_set_pos(AdgLDim *ldim, const AdgPair *pos)
301 AdgLDimPrivate *data;
302 const AdgPair *ref1, *ref2;
303 AdgPair pos1, pos2;
304 CpmlPair baseline_vector, extension_vector;
305 gdouble d, k;
307 g_return_if_fail(ADG_IS_LDIM(ldim));
309 data = ldim->data;
310 ref1 = adg_dim_get_ref1((AdgDim *) ldim);
311 ref2 = adg_dim_get_ref2((AdgDim *) ldim);
313 cpml_vector_from_angle(&extension_vector, data->direction, 1);
315 baseline_vector.x = -extension_vector.y;
316 baseline_vector.y = extension_vector.x;
318 d = extension_vector.y * baseline_vector.x -
319 extension_vector.x * baseline_vector.y;
320 g_return_if_fail(d != 0);
322 k = ((pos->y - ref1->y) * baseline_vector.x -
323 (pos->x - ref1->x) * baseline_vector.y) / d;
324 pos1.x = ref1->x + k * extension_vector.x;
325 pos1.y = ref1->y + k * extension_vector.y;
327 k = ((pos->y - ref2->y) * baseline_vector.x -
328 (pos->x - ref2->x) * baseline_vector.y) / d;
329 pos2.x = ref2->x + k * extension_vector.x;
330 pos2.y = ref2->y + k * extension_vector.y;
332 data->distance = -1;
334 adg_dim_set_pos((AdgDim *) ldim, &pos1, &pos2);
338 * adg_ldim_set_pos_explicit:
339 * @ldim: an #AdgLDim entity
340 * @pos_x: the new x coordinate position reference
341 * @pos_y: the new y coordinate position reference
343 * Wrappers adg_ldim_set_pos() with explicit coordinates.
345 void
346 adg_ldim_set_pos_explicit(AdgLDim *ldim, gdouble pos_x, gdouble pos_y)
348 AdgPair pos;
350 pos.x = pos_x;
351 pos.y = pos_y;
353 adg_ldim_set_pos(ldim, &pos);
357 * adg_ldim_get_direction:
358 * @ldim: an #AdgLDim entity
360 * Gets the direction where @ldim will extend.
362 * Returns: the direction angle in radians
364 gdouble
365 adg_ldim_get_direction(AdgLDim *ldim)
367 AdgLDimPrivate *data;
369 g_return_val_if_fail(ADG_IS_LDIM(ldim), 0);
371 data = ldim->data;
373 return data->direction;
377 * adg_ldim_set_direction:
378 * @ldim: an #AdgLDim entity
379 * @direction: an angle value, in radians
381 * Sets the direction angle where to extend @ldim.
383 void
384 adg_ldim_set_direction(AdgLDim *ldim, gdouble direction)
386 AdgLDimPrivate *data;
388 g_return_if_fail(ADG_IS_LDIM(ldim));
390 data = ldim->data;
391 data->direction = direction;
393 g_object_notify((GObject *) ldim, "direction");
397 * adg_ldim_has_extension1:
398 * @ldim: an #AdgLDim entity
400 * Checks if @ldim should render also the first extension line.
402 * Returns: %TRUE on first extension line presents, %FALSE otherwise
404 gboolean
405 adg_ldim_has_extension1(AdgLDim *ldim)
407 AdgLDimPrivate *data;
409 g_return_val_if_fail(ADG_IS_LDIM(ldim), FALSE);
411 data = ldim->data;
413 return data->has_extension1;
417 * adg_ldim_switch_extension1:
418 * @ldim: an #AdgLDim entity
419 * @state: the new state
421 * Shows (if @state is %TRUE) or hide (if @state is %FALSE) the first
422 * extension line of @ldim.
424 void
425 adg_ldim_switch_extension1(AdgLDim *ldim, gboolean state)
427 AdgLDimPrivate *data;
429 g_return_if_fail(ADG_IS_LDIM(ldim));
431 data = ldim->data;
433 data->has_extension1 = state;
434 g_object_notify((GObject *) ldim, "has-extension1");
438 * adg_ldim_has_extension2:
439 * @ldim: an #AdgLDim entity
441 * Checks if @ldim should render also the second extension line.
443 * Returns: %TRUE on first extension line presents, %FALSE otherwise
445 gboolean
446 adg_ldim_has_extension2(AdgLDim *ldim)
448 AdgLDimPrivate *data;
450 g_return_val_if_fail(ADG_IS_LDIM(ldim), FALSE);
452 data = ldim->data;
454 return data->has_extension2;
458 * adg_ldim_switch_extension2:
459 * @ldim: an #AdgLDim entity
460 * @state: the new state
462 * Shows (if @state is %TRUE) or hide (if @state is %FALSE) the second
463 * extension line of @ldim.
465 void
466 adg_ldim_switch_extension2(AdgLDim *ldim, gboolean state)
468 AdgLDimPrivate *data;
470 g_return_if_fail(ADG_IS_LDIM(ldim));
472 data = ldim->data;
474 data->has_extension2 = state;
475 g_object_notify((GObject *) ldim, "has-extension2");
479 static void
480 invalidate(AdgEntity *entity)
482 AdgLDim *ldim;
483 AdgLDimPrivate *data;
485 ldim = (AdgLDim *) entity;
486 data = ldim->data;
488 dispose_markers(ldim);
489 data->shift.is_arranged = FALSE;
491 if (PARENT_ENTITY_CLASS->invalidate != NULL)
492 PARENT_ENTITY_CLASS->invalidate(entity);
495 static void
496 arrange(AdgEntity *entity)
498 AdgLDim *ldim;
499 AdgDim *dim;
500 AdgLDimPrivate *data;
501 AdgDimStyle *dim_style;
502 AdgContainer *quote;
503 gboolean outside;
504 AdgMatrix local;
505 AdgPair ref1, ref2, pos1, pos2;
506 AdgPair pair;
507 gint n;
509 PARENT_ENTITY_CLASS->arrange(entity);
511 ldim = (AdgLDim *) entity;
512 dim = (AdgDim *) ldim;
513 data = ldim->data;
514 dim_style = adg_dim_get_dim_style(dim);
515 quote = adg_dim_get_quote(dim);
517 update_shift(ldim);
518 update_entities(ldim);
520 switch (adg_dim_get_outside(dim)) {
521 case ADG_THREE_STATE_OFF:
522 outside = FALSE;
523 break;
524 case ADG_THREE_STATE_ON:
525 outside = TRUE;
526 break;
527 case ADG_THREE_STATE_UNKNOWN:
528 default:
529 outside = choose_outside(ldim);
530 break;
533 adg_entity_get_local_matrix((AdgEntity *) ldim, &local);
534 cpml_pair_copy(&ref1, adg_dim_get_ref1(dim));
535 cpml_pair_copy(&ref2, adg_dim_get_ref2(dim));
536 cpml_pair_copy(&pos1, adg_dim_get_pos1(dim));
537 cpml_pair_copy(&pos2, adg_dim_get_pos2(dim));
539 cpml_pair_transform(&ref1, &local);
540 cpml_pair_transform(&ref2, &local);
541 cpml_pair_transform(&pos1, &local);
542 cpml_pair_transform(&pos2, &local);
544 cpml_pair_add(cpml_pair_copy(&pair, &ref1), &data->shift.from);
545 cpml_pair_to_cairo(&pair, &data->cpml.data[13]);
547 cpml_pair_add(cpml_pair_copy(&pair, &pos1), &data->shift.marker);
548 cpml_pair_to_cairo(&pair, &data->cpml.data[1]);
550 cpml_pair_add(&pair, &data->shift.to);
551 cpml_pair_to_cairo(&pair, &data->cpml.data[15]);
553 cpml_pair_add(cpml_pair_copy(&pair, &ref2), &data->shift.from);
554 cpml_pair_to_cairo(&pair, &data->cpml.data[17]);
556 cpml_pair_add(cpml_pair_copy(&pair, &pos2), &data->shift.marker);
557 cpml_pair_to_cairo(&pair, &data->cpml.data[3]);
559 cpml_pair_add(&pair, &data->shift.to);
560 cpml_pair_to_cairo(&pair, &data->cpml.data[19]);
562 /* Calculate the outside segments */
563 if (outside) {
564 gdouble beyond;
565 CpmlVector vector;
567 beyond = adg_dim_style_get_beyond(dim_style);
568 cpml_pair_from_cairo(&pair, &data->cpml.data[1]);
570 cpml_pair_from_cairo(&vector, &data->cpml.data[3]);
571 cpml_pair_sub(&vector, &pair);
572 cpml_vector_set_length(&vector, beyond);
574 cpml_pair_from_cairo(&pair, &data->cpml.data[1]);
575 cpml_pair_to_cairo(&pair, &data->cpml.data[5]);
577 cpml_pair_sub(&pair, &vector);
578 cpml_pair_to_cairo(&pair, &data->cpml.data[7]);
580 cpml_pair_from_cairo(&pair, &data->cpml.data[3]);
581 cpml_pair_to_cairo(&pair, &data->cpml.data[11]);
583 cpml_pair_add(&pair, &vector);
584 cpml_pair_to_cairo(&pair, &data->cpml.data[9]);
586 data->cpml.data[2].header.length = 2;
587 data->cpml.data[10].header.length = 2;
588 n = 10;
589 } else {
590 data->cpml.data[2].header.length = 10;
591 n = 2;
594 /* Play with header lengths to show or hide the extension lines */
595 if (data->has_extension1) {
596 data->cpml.data[14].header.length = data->has_extension2 ? 2 : 6;
597 } else {
598 data->cpml.data[n].header.length += 4;
599 if (!data->has_extension2)
600 data->cpml.data[n].header.length += 4;
603 data->cpml.path.status = CAIRO_STATUS_SUCCESS;
605 if (quote != NULL) {
606 /* Update global and local map of the quote container */
607 AdgEntity *quote_entity;
608 gdouble angle;
609 AdgMatrix matrix;
611 quote_entity = (AdgEntity *) quote;
612 angle = adg_dim_quote_angle(dim, data->direction + G_PI_2);
613 adg_matrix_copy(&matrix, &local);
614 cairo_matrix_invert(&matrix);
616 pair.x = (data->cpml.data[1].point.x + data->cpml.data[3].point.x) / 2;
617 pair.y = (data->cpml.data[1].point.y + data->cpml.data[3].point.y) / 2;
618 cairo_matrix_transform_point(&matrix, &pair.x, &pair.y);
619 cairo_matrix_init_translate(&matrix, pair.x, pair.y);
620 adg_entity_set_local_map(quote_entity, &matrix);
622 cairo_matrix_init_rotate(&matrix, angle);
623 adg_entity_transform_global_map(quote_entity, &matrix, ADG_TRANSFORM_BEFORE);
626 if (data->marker1 != NULL) {
627 adg_marker_set_segment(data->marker1, data->trail, outside ? 2 : 1);
628 adg_entity_local_changed((AdgEntity *) data->marker1);
631 if (data->marker2 != NULL) {
632 adg_marker_set_segment(data->marker2, data->trail, outside ? 3 : 1);
633 adg_entity_local_changed((AdgEntity *) data->marker2);
636 /* TODO: compute the extents */
639 static void
640 render(AdgEntity *entity, cairo_t *cr)
642 AdgLDim *ldim;
643 AdgDim *dim;
644 AdgLDimPrivate *data;
645 AdgDimStyle *dim_style;
646 AdgDress dress;
648 ldim = (AdgLDim *) entity;
649 dim = (AdgDim *) entity;
650 data = ldim->data;
651 dim_style = adg_dim_get_dim_style(dim);
653 dress = adg_dim_style_get_color_dress(dim_style);
654 adg_entity_apply_dress(entity, dress, cr);
656 if (data->marker1 != NULL)
657 adg_entity_render((AdgEntity *) data->marker1, cr);
659 if (data->marker2 != NULL)
660 adg_entity_render((AdgEntity *) data->marker2, cr);
662 adg_entity_render((AdgEntity *) adg_dim_get_quote(dim), cr);
664 /* This CpmlPath has no arcs, so it can be fed directly into cairo */
665 dress = adg_dim_style_get_line_dress(dim_style);
666 adg_entity_apply_dress(entity, dress, cr);
667 cairo_append_path(cr, &data->cpml.path);
668 cairo_stroke(cr);
671 static gchar *
672 default_value(AdgDim *dim)
674 AdgDimStyle *dim_style;
675 const gchar *format;
676 gdouble distance;
678 dim_style = adg_dim_get_dim_style(dim);
679 format = adg_dim_style_get_number_format(dim_style);
680 distance = get_distance((AdgLDim *) dim);
682 return g_strdup_printf(format, distance);
685 static gdouble
686 get_distance(AdgLDim *ldim)
688 AdgLDimPrivate *data = ldim->data;
690 if (data->distance < 0) {
691 AdgDim *dim;
692 const AdgPair *pos1;
693 const AdgPair *pos2;
695 dim = (AdgDim *) ldim;
696 pos1 = adg_dim_get_pos1(dim);
697 pos2 = adg_dim_get_pos2(dim);
699 data->distance = cpml_pair_distance(pos1, pos2);
702 return data->distance;
705 static void
706 update_shift(AdgLDim *ldim)
708 AdgLDimPrivate *data;
709 AdgDimStyle *dim_style;
710 AdgMatrix matrix;
711 gdouble from_offset;
712 gdouble to_offset;
713 gdouble baseline_spacing;
714 gdouble level;
716 data = ldim->data;
717 dim_style = adg_dim_get_dim_style((AdgDim *) ldim);
719 if (data->shift.is_arranged)
720 return;
722 from_offset = adg_dim_style_get_from_offset(dim_style);
723 to_offset = adg_dim_style_get_to_offset(dim_style);
724 baseline_spacing = adg_dim_style_get_baseline_spacing(dim_style);
725 level = adg_dim_get_level((AdgDim *) ldim);
727 cairo_matrix_init_rotate(&matrix, data->direction);
729 data->shift.from.x = data->shift.from.y = 0;
730 data->shift.marker.x = data->shift.marker.y = 0;
731 data->shift.to.x = data->shift.to.y = 0;
733 cairo_matrix_translate(&matrix, from_offset, 0);
734 cpml_pair_transform(&data->shift.from, &matrix);
735 cairo_matrix_translate(&matrix, to_offset-from_offset, 0);
736 cpml_pair_transform(&data->shift.to, &matrix);
737 cairo_matrix_translate(&matrix, level*baseline_spacing-to_offset, 0);
738 cpml_pair_transform(&data->shift.marker, &matrix);
740 data->shift.is_arranged = TRUE;
743 static void
744 update_entities(AdgLDim *ldim)
746 AdgLDimPrivate *data;
747 AdgDimStyle *dim_style;
749 data = ldim->data;
750 dim_style = adg_dim_get_dim_style((AdgDim *) ldim);
752 if (data->trail == NULL)
753 data->trail = adg_trail_new(trail_callback, ldim);
755 if (data->marker1 == NULL)
756 data->marker1 = adg_dim_style_marker1_new(dim_style);
758 if (data->marker2 == NULL)
759 data->marker2 = adg_dim_style_marker2_new(dim_style);
762 static gboolean
763 choose_outside(AdgLDim *ldim)
765 AdgLDimPrivate *data;
766 AdgContainer *quote;
767 CpmlExtents extents;
768 AdgMatrix local;
769 gdouble marker1, marker2;
770 gdouble needed, available;
772 data = ldim->data;
773 quote = adg_dim_get_quote((AdgDim *) ldim);
774 adg_entity_get_extents((AdgEntity *) quote, &extents);
775 adg_entity_get_local_matrix((AdgEntity *) ldim, &local);
776 marker1 = data->marker1 == NULL ? 0 : adg_marker_get_size(data->marker1);
777 marker2 = data->marker2 == NULL ? 0 : adg_marker_get_size(data->marker2);
779 needed = extents.size.x + marker1 + marker2;
780 available = get_distance(ldim) * local.xx;
782 return needed > available;
785 static void
786 dispose_markers(AdgLDim *ldim)
788 AdgLDimPrivate *data = ldim->data;
790 if (data->trail != NULL) {
791 g_object_unref(data->trail);
792 data->trail = NULL;
795 if (data->marker1 != NULL) {
796 g_object_unref(data->marker1);
797 data->marker1 = NULL;
800 if (data->marker2 != NULL) {
801 g_object_unref(data->marker2);
802 data->marker2 = NULL;
806 static CpmlPath *
807 trail_callback(AdgTrail *trail, gpointer user_data)
809 AdgLDim *ldim;
810 AdgLDimPrivate *data;
812 ldim = (AdgLDim *) user_data;
813 data = ldim->data;
815 adg_trail_clear_cairo_path(trail);
817 return &data->cpml.path;