[AdgLDim] Avoid arrange() on the same data
[adg.git] / adg / adg-ldim.c
blob335859ec27eb0558ee6f8b0616cb243c1ba171af
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 local_changed (AdgEntity *entity);
63 static void invalidate (AdgEntity *entity);
64 static void arrange (AdgEntity *entity);
65 static void render (AdgEntity *entity,
66 cairo_t *cr);
67 static gchar * default_value (AdgDim *dim);
68 static void update_geometry (AdgLDim *ldim);
69 static void update_shift (AdgLDim *ldim);
70 static void update_entities (AdgLDim *ldim);
71 static gboolean choose_outside (AdgLDim *ldim);
72 static void dispose_markers (AdgLDim *ldim);
73 static CpmlPath * trail_callback (AdgTrail *trail,
74 gpointer user_data);
77 G_DEFINE_TYPE(AdgLDim, adg_ldim, ADG_TYPE_DIM);
80 static void
81 adg_ldim_class_init(AdgLDimClass *klass)
83 GObjectClass *gobject_class;
84 AdgEntityClass *entity_class;
85 AdgDimClass *dim_class;
86 GParamSpec *param;
88 gobject_class = (GObjectClass *) klass;
89 entity_class = (AdgEntityClass *) klass;
90 dim_class = (AdgDimClass *) klass;
92 g_type_class_add_private(klass, sizeof(AdgLDimPrivate));
94 gobject_class->dispose = dispose;
95 gobject_class->get_property = get_property;
96 gobject_class->set_property = set_property;
98 entity_class->local_changed = local_changed;
99 entity_class->invalidate = invalidate;
100 entity_class->arrange = arrange;
101 entity_class->render = render;
103 dim_class->default_value = default_value;
105 param = g_param_spec_double("direction",
106 P_("Direction"),
107 P_("The inclination angle of the extension lines"),
108 -G_MAXDOUBLE, G_MAXDOUBLE, ADG_DIR_RIGHT,
109 G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
110 g_object_class_install_property(gobject_class, PROP_DIRECTION, param);
112 param = g_param_spec_boolean("has-extension1",
113 P_("Has First Extension Line flag"),
114 P_("Show (TRUE) or hide (FALSE) the first extension line"),
115 TRUE, G_PARAM_READWRITE);
116 g_object_class_install_property(gobject_class, PROP_HAS_EXTENSION1, param);
118 param = g_param_spec_boolean("has-extension2",
119 P_("Has Second Extension Line flag"),
120 P_("Show (TRUE) or hide (FALSE) the second extension line"),
121 TRUE, G_PARAM_READWRITE);
122 g_object_class_install_property(gobject_class, PROP_HAS_EXTENSION2, param);
125 static void
126 adg_ldim_init(AdgLDim *ldim)
128 AdgLDimPrivate *data;
129 cairo_path_data_t move_to, line_to;
131 data = G_TYPE_INSTANCE_GET_PRIVATE(ldim, ADG_TYPE_LDIM, AdgLDimPrivate);
132 move_to.header.type = CAIRO_PATH_MOVE_TO;
133 move_to.header.length = 2;
134 line_to.header.type = CAIRO_PATH_LINE_TO;
135 line_to.header.length = 2;
137 data->direction = 0;
138 data->has_extension1 = TRUE;
139 data->has_extension2 = TRUE;
141 data->cpml.path.status = CAIRO_STATUS_INVALID_PATH_DATA;
142 data->cpml.path.data = data->cpml.data;
143 data->cpml.path.num_data = G_N_ELEMENTS(data->cpml.data);
144 data->cpml.path.data[0] = move_to;
145 data->cpml.path.data[2] = line_to;
146 data->cpml.path.data[4] = move_to;
147 data->cpml.path.data[6] = line_to;
148 data->cpml.path.data[8] = move_to;
149 data->cpml.path.data[10] = line_to;
150 data->cpml.path.data[12] = move_to;
151 data->cpml.path.data[14] = line_to;
152 data->cpml.path.data[16] = move_to;
153 data->cpml.path.data[18] = line_to;
155 data->trail = NULL;
156 data->marker1 = NULL;
157 data->marker2 = NULL;
159 data->geometry.is_arranged = FALSE;
160 data->shift.is_arranged = FALSE;
162 ldim->data = data;
165 static void
166 dispose(GObject *object)
168 dispose_markers((AdgLDim *) object);
170 if (PARENT_OBJECT_CLASS->dispose != NULL)
171 PARENT_OBJECT_CLASS->dispose(object);
174 static void
175 get_property(GObject *object,
176 guint prop_id, GValue *value, GParamSpec *pspec)
178 AdgLDimPrivate *data = ((AdgLDim *) object)->data;
180 switch (prop_id) {
181 case PROP_DIRECTION:
182 g_value_set_double(value, data->direction);
183 break;
184 case PROP_HAS_EXTENSION1:
185 g_value_set_boolean(value, data->has_extension1);
186 break;
187 case PROP_HAS_EXTENSION2:
188 g_value_set_boolean(value, data->has_extension2);
189 break;
190 default:
191 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
192 break;
196 static void
197 set_property(GObject *object,
198 guint prop_id, const GValue *value, GParamSpec *pspec)
200 AdgLDimPrivate *data = ((AdgLDim *) object)->data;
202 switch (prop_id) {
203 case PROP_DIRECTION:
204 data->direction = g_value_get_double(value);
205 break;
206 case PROP_HAS_EXTENSION1:
207 data->has_extension1 = g_value_get_boolean(value);
208 break;
209 case PROP_HAS_EXTENSION2:
210 data->has_extension2 = g_value_get_boolean(value);
211 break;
212 default:
213 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
214 break;
220 * adg_ldim_new:
222 * Creates a new - undefined - linear dimension. You must, at least,
223 * define the reference points with adg_dim_set_ref(), the dimension
224 * direction with adg_ldim_set_direction() and the position reference
225 * using adg_dim_set_pos().
227 * Returns: the newly created linear dimension entity
229 AdgLDim *
230 adg_ldim_new(void)
232 return g_object_new(ADG_TYPE_LDIM, NULL);
236 * adg_ldim_new_full:
237 * @ref1: the first reference point
238 * @ref2: the second reference point
239 * @direction: angle where to extend the dimension
240 * @pos: the position reference
242 * Creates a new linear dimension, specifing all the needed properties in
243 * one shot.
245 * Returns: the newly created linear dimension entity
247 AdgLDim *
248 adg_ldim_new_full(const AdgPair *ref1, const AdgPair *ref2,
249 gdouble direction, const AdgPair *pos)
251 return g_object_new(ADG_TYPE_LDIM, "ref1", ref1, "ref2", ref2,
252 "direction", direction, "pos", pos, NULL);
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_get_direction:
290 * @ldim: an #AdgLDim entity
292 * Gets the direction where @ldim will extend.
294 * Returns: the direction angle in radians
296 gdouble
297 adg_ldim_get_direction(AdgLDim *ldim)
299 AdgLDimPrivate *data;
301 g_return_val_if_fail(ADG_IS_LDIM(ldim), 0);
303 data = ldim->data;
305 return data->direction;
309 * adg_ldim_set_direction:
310 * @ldim: an #AdgLDim entity
311 * @direction: an angle value, in radians
313 * Sets the direction angle where to extend @ldim.
315 void
316 adg_ldim_set_direction(AdgLDim *ldim, gdouble direction)
318 AdgLDimPrivate *data;
320 g_return_if_fail(ADG_IS_LDIM(ldim));
322 data = ldim->data;
323 data->direction = direction;
325 g_object_notify((GObject *) ldim, "direction");
329 * adg_ldim_has_extension1:
330 * @ldim: an #AdgLDim entity
332 * Checks if @ldim should render also the first extension line.
334 * Returns: %TRUE on first extension line presents, %FALSE otherwise
336 gboolean
337 adg_ldim_has_extension1(AdgLDim *ldim)
339 AdgLDimPrivate *data;
341 g_return_val_if_fail(ADG_IS_LDIM(ldim), FALSE);
343 data = ldim->data;
345 return data->has_extension1;
349 * adg_ldim_switch_extension1:
350 * @ldim: an #AdgLDim entity
351 * @state: the new state
353 * Shows (if @state is %TRUE) or hide (if @state is %FALSE) the first
354 * extension line of @ldim.
356 void
357 adg_ldim_switch_extension1(AdgLDim *ldim, gboolean state)
359 AdgLDimPrivate *data;
361 g_return_if_fail(ADG_IS_LDIM(ldim));
363 data = ldim->data;
365 data->has_extension1 = state;
366 g_object_notify((GObject *) ldim, "has-extension1");
370 * adg_ldim_has_extension2:
371 * @ldim: an #AdgLDim entity
373 * Checks if @ldim should render also the second extension line.
375 * Returns: %TRUE on first extension line presents, %FALSE otherwise
377 gboolean
378 adg_ldim_has_extension2(AdgLDim *ldim)
380 AdgLDimPrivate *data;
382 g_return_val_if_fail(ADG_IS_LDIM(ldim), FALSE);
384 data = ldim->data;
386 return data->has_extension2;
390 * adg_ldim_switch_extension2:
391 * @ldim: an #AdgLDim entity
392 * @state: the new state
394 * Shows (if @state is %TRUE) or hide (if @state is %FALSE) the second
395 * extension line of @ldim.
397 void
398 adg_ldim_switch_extension2(AdgLDim *ldim, gboolean state)
400 AdgLDimPrivate *data;
402 g_return_if_fail(ADG_IS_LDIM(ldim));
404 data = ldim->data;
406 data->has_extension2 = state;
407 g_object_notify((GObject *) ldim, "has-extension2");
411 static void
412 local_changed(AdgEntity *entity)
414 AdgLDimPrivate *data = ((AdgLDim *) entity)->data;
416 if (data->trail != NULL)
417 adg_trail_clear_cairo_path(data->trail);
419 data->cpml.path.status = CAIRO_STATUS_INVALID_PATH_DATA;
421 PARENT_ENTITY_CLASS->local_changed(entity);
424 static void
425 invalidate(AdgEntity *entity)
427 AdgLDim *ldim;
428 AdgLDimPrivate *data;
430 ldim = (AdgLDim *) entity;
431 data = ldim->data;
433 dispose_markers(ldim);
434 data->geometry.is_arranged = FALSE;
435 data->shift.is_arranged = FALSE;
436 adg_trail_clear_cairo_path(data->trail);
437 data->cpml.path.status = CAIRO_STATUS_INVALID_PATH_DATA;
439 if (PARENT_ENTITY_CLASS->invalidate != NULL)
440 PARENT_ENTITY_CLASS->invalidate(entity);
443 static void
444 arrange(AdgEntity *entity)
446 AdgLDim *ldim;
447 AdgDim *dim;
448 AdgLDimPrivate *data;
449 AdgContainer *quote;
450 AdgDimStyle *dim_style;
451 gboolean outside;
452 const AdgMatrix *local;
453 AdgPair ref1, ref2, base1, base2;
454 AdgPair pair;
455 gint n;
457 PARENT_ENTITY_CLASS->arrange(entity);
459 ldim = (AdgLDim *) entity;
460 dim = (AdgDim *) ldim;
461 data = ldim->data;
462 quote = adg_dim_get_quote(dim);
464 update_geometry(ldim);
465 update_shift(ldim);
466 update_entities(ldim);
468 if (data->cpml.path.status == CAIRO_STATUS_SUCCESS) {
469 AdgEntity *quote_entity = (AdgEntity *) quote;
470 adg_entity_set_global_map(quote_entity, &data->quote.global_map);
471 adg_entity_set_local_map(quote_entity, &data->quote.local_map);
472 return;
475 dim_style = adg_dim_get_dim_style(dim);
477 switch (adg_dim_get_outside(dim)) {
478 case ADG_THREE_STATE_OFF:
479 outside = FALSE;
480 break;
481 case ADG_THREE_STATE_ON:
482 outside = TRUE;
483 break;
484 case ADG_THREE_STATE_UNKNOWN:
485 default:
486 outside = choose_outside(ldim);
487 break;
490 local = adg_entity_local_matrix(entity);
491 cpml_pair_copy(&ref1, adg_dim_get_ref1(dim));
492 cpml_pair_copy(&ref2, adg_dim_get_ref2(dim));
493 cpml_pair_copy(&base1, &data->geometry.base1);
494 cpml_pair_copy(&base2, &data->geometry.base2);
496 cpml_pair_transform(&ref1, local);
497 cpml_pair_transform(&ref2, local);
498 cpml_pair_transform(&base1, local);
499 cpml_pair_transform(&base2, local);
501 cpml_pair_add(cpml_pair_copy(&pair, &ref1), &data->shift.from);
502 cpml_pair_to_cairo(&pair, &data->cpml.data[13]);
504 cpml_pair_copy(&pair, &base1);
505 cpml_pair_add(&pair, &data->shift.base);
506 cpml_pair_to_cairo(&pair, &data->cpml.data[1]);
508 cpml_pair_add(&pair, &data->shift.to);
509 cpml_pair_to_cairo(&pair, &data->cpml.data[15]);
511 cpml_pair_add(cpml_pair_copy(&pair, &ref2), &data->shift.from);
512 cpml_pair_to_cairo(&pair, &data->cpml.data[17]);
514 cpml_pair_copy(&pair, &base2);
515 cpml_pair_add(&pair, &data->shift.base);
516 cpml_pair_to_cairo(&pair, &data->cpml.data[3]);
518 cpml_pair_add(&pair, &data->shift.to);
519 cpml_pair_to_cairo(&pair, &data->cpml.data[19]);
521 /* Calculate the outside segments */
522 if (outside) {
523 gdouble beyond;
524 CpmlVector vector;
526 beyond = adg_dim_style_get_beyond(dim_style);
527 cpml_pair_from_cairo(&pair, &data->cpml.data[1]);
529 cpml_pair_from_cairo(&vector, &data->cpml.data[3]);
530 cpml_pair_sub(&vector, &pair);
531 cpml_vector_set_length(&vector, beyond);
533 cpml_pair_from_cairo(&pair, &data->cpml.data[1]);
534 cpml_pair_to_cairo(&pair, &data->cpml.data[5]);
536 cpml_pair_sub(&pair, &vector);
537 cpml_pair_to_cairo(&pair, &data->cpml.data[7]);
539 cpml_pair_from_cairo(&pair, &data->cpml.data[3]);
540 cpml_pair_to_cairo(&pair, &data->cpml.data[11]);
542 cpml_pair_add(&pair, &vector);
543 cpml_pair_to_cairo(&pair, &data->cpml.data[9]);
545 data->cpml.data[2].header.length = 2;
546 data->cpml.data[10].header.length = 2;
547 n = 10;
548 } else {
549 data->cpml.data[2].header.length = 10;
550 n = 2;
553 /* Play with header lengths to show or hide the extension lines */
554 if (data->has_extension1) {
555 data->cpml.data[14].header.length = data->has_extension2 ? 2 : 6;
556 } else {
557 data->cpml.data[n].header.length += 4;
558 if (!data->has_extension2)
559 data->cpml.data[n].header.length += 4;
562 data->cpml.path.status = CAIRO_STATUS_SUCCESS;
564 if (quote != NULL) {
565 /* Update global and local map of the quote container */
566 AdgEntity *quote_entity;
567 gdouble angle;
568 AdgMatrix matrix;
570 quote_entity = (AdgEntity *) quote;
571 angle = adg_dim_quote_angle(dim, data->direction + G_PI_2);
572 adg_matrix_copy(&matrix, local);
573 cairo_matrix_invert(&matrix);
575 pair.x = (data->cpml.data[1].point.x + data->cpml.data[3].point.x) / 2;
576 pair.y = (data->cpml.data[1].point.y + data->cpml.data[3].point.y) / 2;
577 cairo_matrix_transform_point(&matrix, &pair.x, &pair.y);
578 cairo_matrix_init_translate(&matrix, pair.x, pair.y);
579 adg_entity_set_local_map(quote_entity, &matrix);
581 cairo_matrix_init_rotate(&matrix, angle);
582 adg_entity_transform_global_map(quote_entity, &matrix, ADG_TRANSFORM_BEFORE);
584 adg_entity_get_global_map(quote_entity, &data->quote.global_map);
585 adg_entity_get_local_map(quote_entity, &data->quote.local_map);
588 if (data->marker1 != NULL) {
589 adg_marker_set_segment(data->marker1, data->trail, outside ? 2 : 1);
590 adg_entity_local_changed((AdgEntity *) data->marker1);
593 if (data->marker2 != NULL) {
594 adg_marker_set_segment(data->marker2, data->trail, outside ? 3 : 1);
595 adg_entity_local_changed((AdgEntity *) data->marker2);
598 /* TODO: compute the extents */
601 static void
602 render(AdgEntity *entity, cairo_t *cr)
604 AdgLDim *ldim;
605 AdgDim *dim;
606 AdgLDimPrivate *data;
607 AdgDimStyle *dim_style;
608 AdgDress dress;
609 const cairo_path_t *cairo_path;
611 ldim = (AdgLDim *) entity;
612 dim = (AdgDim *) entity;
613 data = ldim->data;
614 dim_style = adg_dim_get_dim_style(dim);
616 dress = adg_dim_style_get_color_dress(dim_style);
617 adg_entity_apply_dress(entity, dress, cr);
619 if (data->marker1 != NULL)
620 adg_entity_render((AdgEntity *) data->marker1, cr);
622 if (data->marker2 != NULL)
623 adg_entity_render((AdgEntity *) data->marker2, cr);
625 adg_entity_render((AdgEntity *) adg_dim_get_quote(dim), cr);
627 dress = adg_dim_style_get_line_dress(dim_style);
628 adg_entity_apply_dress(entity, dress, cr);
630 cairo_path = adg_trail_get_cairo_path(data->trail);
631 cairo_append_path(cr, cairo_path);
632 cairo_stroke(cr);
635 static gchar *
636 default_value(AdgDim *dim)
638 AdgLDim *ldim;
639 AdgLDimPrivate *data;
640 AdgDimStyle *dim_style;
641 const gchar *format;
643 ldim = (AdgLDim *) dim;
644 data = ldim->data;
645 dim_style = adg_dim_get_dim_style(dim);
646 format = adg_dim_style_get_number_format(dim_style);
648 update_geometry(ldim);
650 return g_strdup_printf(format, data->geometry.distance);
653 static void
654 update_geometry(AdgLDim *ldim)
656 AdgLDimPrivate *data;
657 AdgDim *dim;
658 const AdgPair *ref1, *ref2;
659 const AdgPair *pos;
660 CpmlVector baseline, extension;
661 gdouble d, k;
663 data = ldim->data;
665 if (data->geometry.is_arranged)
666 return;
668 dim = (AdgDim *) ldim;
669 ref1 = adg_dim_get_ref1(dim);
670 ref2 = adg_dim_get_ref2(dim);
671 pos = adg_dim_get_pos(dim);
672 cpml_vector_from_angle(&extension, data->direction);
673 cpml_pair_copy(&baseline, &extension);
674 cpml_vector_normal(&baseline);
676 d = extension.y * baseline.x -
677 extension.x * baseline.y;
678 g_return_if_fail(d != 0);
680 k = ((pos->y - ref1->y) * baseline.x -
681 (pos->x - ref1->x) * baseline.y) / d;
682 data->geometry.base1.x = ref1->x + k * extension.x;
683 data->geometry.base1.y = ref1->y + k * extension.y;
685 k = ((pos->y - ref2->y) * baseline.x -
686 (pos->x - ref2->x) * baseline.y) / d;
687 data->geometry.base2.x = ref2->x + k * extension.x;
688 data->geometry.base2.y = ref2->y + k * extension.y;
690 data->geometry.distance = cpml_pair_distance(&data->geometry.base1,
691 &data->geometry.base2);
693 data->geometry.is_arranged = TRUE;
696 static void
697 update_shift(AdgLDim *ldim)
699 AdgLDimPrivate *data;
700 AdgDimStyle *dim_style;
701 gdouble from_offset, to_offset;
702 gdouble baseline_spacing, level;
703 CpmlVector vector;
705 data = ldim->data;
707 if (data->shift.is_arranged)
708 return;
710 dim_style = adg_dim_get_dim_style((AdgDim *) ldim);
711 from_offset = adg_dim_style_get_from_offset(dim_style);
712 to_offset = adg_dim_style_get_to_offset(dim_style);
713 baseline_spacing = adg_dim_style_get_baseline_spacing(dim_style);
714 level = adg_dim_get_level((AdgDim *) ldim);
716 cpml_vector_from_angle(&vector, data->direction);
718 cpml_vector_set_length(&vector, from_offset);
719 cpml_pair_copy(&data->shift.from, &vector);
721 cpml_vector_set_length(&vector, to_offset);
722 cpml_pair_copy(&data->shift.to, &vector);
724 cpml_vector_set_length(&vector, level * baseline_spacing);
725 cpml_pair_copy(&data->shift.base, &vector);
727 data->shift.is_arranged = TRUE;
730 static void
731 update_entities(AdgLDim *ldim)
733 AdgLDimPrivate *data;
734 AdgDimStyle *dim_style;
736 data = ldim->data;
737 dim_style = adg_dim_get_dim_style((AdgDim *) ldim);
739 if (data->trail == NULL)
740 data->trail = adg_trail_new(trail_callback, ldim);
742 if (data->marker1 == NULL)
743 data->marker1 = adg_dim_style_marker1_new(dim_style);
745 if (data->marker2 == NULL)
746 data->marker2 = adg_dim_style_marker2_new(dim_style);
749 static gboolean
750 choose_outside(AdgLDim *ldim)
752 AdgLDimPrivate *data;
753 AdgContainer *quote;
754 const AdgMatrix *local;
755 CpmlExtents extents;
756 gdouble marker1, marker2;
757 gdouble needed, available;
759 data = ldim->data;
760 quote = adg_dim_get_quote((AdgDim *) ldim);
761 local = adg_entity_local_matrix((AdgEntity *) ldim);
762 adg_entity_get_extents((AdgEntity *) quote, &extents);
763 marker1 = data->marker1 == NULL ? 0 : adg_marker_get_size(data->marker1);
764 marker2 = data->marker2 == NULL ? 0 : adg_marker_get_size(data->marker2);
766 needed = extents.size.x + marker1 + marker2;
767 available = data->geometry.distance * local->xx;
769 return needed > available;
772 static void
773 dispose_markers(AdgLDim *ldim)
775 AdgLDimPrivate *data = ldim->data;
777 if (data->trail != NULL) {
778 g_object_unref(data->trail);
779 data->trail = NULL;
782 if (data->marker1 != NULL) {
783 g_object_unref(data->marker1);
784 data->marker1 = NULL;
787 if (data->marker2 != NULL) {
788 g_object_unref(data->marker2);
789 data->marker2 = NULL;
793 static CpmlPath *
794 trail_callback(AdgTrail *trail, gpointer user_data)
796 AdgLDim *ldim;
797 AdgLDimPrivate *data;
799 ldim = (AdgLDim *) user_data;
800 data = ldim->data;
802 return &data->cpml.path;