1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2021 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.
22 * SECTION:adg-dim-style
23 * @short_description: Dimension style related stuff
25 * Contains parameters on how to build dimensions such as the format of the
26 * label, the different font styles (for value and limits), line style,
27 * offsets of the various dimension components etc.
29 * A typical use case is to set the quote of angular dimensions in sexagesimal
30 * units. To do this, use something similar to the following code:
33 * AdgDimStyle *dim_style = ADG_DIM_STYLE(adg_style_clone(adg_dress_get_fallback(adg_dress_dimension)));
35 * // Set the decimals and rounding properties
36 * adg_dim_style_set_decimals(dim_style, 0);
37 * adg_dim_style_set_rounding(dim_style, 3);
39 * // Set the arguments and the format of the quote number
40 * adg_dim_style_set_number_arguments(dim_style, "Dm");
41 * adg_dim_style_set_number_format(dim_style, "%g°(%g')");
44 * After that you can apply the new style to the
45 * <constant>ADG_DRESS_DIMENSION</constant> of the entity you want to change,
49 * adg_entity_set_style(my_angular_dimension,
50 * ADG_DRESS_DIMENSION,
51 * ADG_STYLE(dim_style));
60 * All fields are private and should not be used directly.
61 * Use its public methods instead.
67 #include "adg-internal.h"
68 #include "adg-style.h"
69 #include "adg-font-style.h"
71 #include "adg-line-style.h"
72 #include "adg-model.h"
73 #include "adg-trail.h"
74 #include "adg-marker.h"
75 #include "adg-dress.h"
76 #include "adg-param-dress.h"
78 #include "adg-dim-style.h"
79 #include "adg-dim-style-private.h"
85 #define VALID_FORMATS "aieDdMmSs"
88 G_DEFINE_TYPE_WITH_PRIVATE(AdgDimStyle
, adg_dim_style
, ADG_TYPE_STYLE
)
102 PROP_BASELINE_SPACING
,
107 PROP_NUMBER_ARGUMENTS
,
114 static void _adg_finalize (GObject
*object
);
115 static void _adg_get_property (GObject
*object
,
119 static void _adg_set_property (GObject
*object
,
123 static AdgStyle
* _adg_clone (AdgStyle
*style
);
124 static void _adg_apply (AdgStyle
*style
,
127 static AdgMarker
* _adg_marker_new (const AdgMarkerData
129 static void _adg_marker_data_set (AdgMarkerData
*marker_data
,
131 static void _adg_marker_data_unset (AdgMarkerData
*marker_data
);
135 adg_dim_style_class_init(AdgDimStyleClass
*klass
)
137 GObjectClass
*gobject_class
;
138 AdgStyleClass
*style_class
;
141 gobject_class
= (GObjectClass
*) klass
;
142 style_class
= (AdgStyleClass
*) klass
;
144 gobject_class
->finalize
= _adg_finalize
;
145 gobject_class
->get_property
= _adg_get_property
;
146 gobject_class
->set_property
= _adg_set_property
;
148 style_class
->clone
= _adg_clone
;
149 style_class
->apply
= _adg_apply
;
151 param
= g_param_spec_object("marker1",
153 P_("The template entity to use as first marker"),
156 g_object_class_install_property(gobject_class
, PROP_MARKER1
, param
);
158 param
= g_param_spec_object("marker2",
160 P_("The template entity to use as second marker"),
163 g_object_class_install_property(gobject_class
, PROP_MARKER2
, param
);
165 param
= adg_param_spec_dress("color-dress",
167 P_("Color dress for the whole dimension"),
168 ADG_DRESS_COLOR_DIMENSION
,
170 g_object_class_install_property(gobject_class
, PROP_COLOR_DRESS
, param
);
172 param
= adg_param_spec_dress("value-dress",
174 P_("Font dress for the nominal value of the dimension"),
175 ADG_DRESS_FONT_QUOTE_TEXT
,
177 g_object_class_install_property(gobject_class
, PROP_VALUE_DRESS
, param
);
179 param
= adg_param_spec_dress("min-dress",
180 P_("Minimum Limit Dress"),
181 P_("Font dress for the lower limit value"),
182 ADG_DRESS_FONT_QUOTE_ANNOTATION
,
184 g_object_class_install_property(gobject_class
, PROP_MIN_DRESS
, param
);
186 param
= adg_param_spec_dress("max-dress",
187 P_("Maximum Limit Dress"),
188 P_("Font dress for the upper limit value"),
189 ADG_DRESS_FONT_QUOTE_ANNOTATION
,
191 g_object_class_install_property(gobject_class
, PROP_MAX_DRESS
, param
);
193 param
= adg_param_spec_dress("line-dress",
195 P_("Line dress for the baseline and the extension lines"),
196 ADG_DRESS_LINE_DIMENSION
,
198 g_object_class_install_property(gobject_class
, PROP_LINE_DRESS
, param
);
200 param
= g_param_spec_double("from-offset",
202 P_("Offset (in global space) of the extension lines from the path to the quote"),
205 g_object_class_install_property(gobject_class
, PROP_FROM_OFFSET
, param
);
207 param
= g_param_spec_double("to-offset",
209 P_("How many extend (in global space) the extension lines after hitting the baseline"),
212 g_object_class_install_property(gobject_class
, PROP_TO_OFFSET
, param
);
214 param
= g_param_spec_double("beyond",
216 P_("How much the baseline should be extended (in global space) beyond the extension lines on dimensions with outside markers"),
219 g_object_class_install_property(gobject_class
, PROP_BEYOND
, param
);
221 param
= g_param_spec_double("baseline-spacing",
222 P_("Baseline Spacing"),
223 P_("Distance between two consecutive baselines while stacking dimensions"),
226 g_object_class_install_property(gobject_class
, PROP_BASELINE_SPACING
, param
);
228 param
= g_param_spec_double("limits-spacing",
229 P_("Limits Spacing"),
230 P_("Distance between limits/tolerances"),
231 -G_MAXDOUBLE
, G_MAXDOUBLE
, 2,
233 g_object_class_install_property(gobject_class
, PROP_LIMITS_SPACING
, param
);
235 param
= g_param_spec_boxed("quote-shift",
237 P_("Used to specify a smooth displacement (in global space) of the quote by taking as reference the perfect compact position (the middle of the baseline on common linear dimension, for instance)"),
240 g_object_class_install_property(gobject_class
, PROP_QUOTE_SHIFT
, param
);
242 param
= g_param_spec_boxed("limits-shift",
244 P_("Used to specify a smooth displacement (in global space) for the limits/tolerances by taking as reference the perfect compact position"),
247 g_object_class_install_property(gobject_class
, PROP_LIMITS_SHIFT
, param
);
249 param
= g_param_spec_string("number-format",
251 P_("The format (in printf style) of the numeric component of the basic value"),
254 g_object_class_install_property(gobject_class
, PROP_NUMBER_FORMAT
, param
);
256 param
= g_param_spec_string("number-arguments",
257 P_("Number Arguments"),
258 P_("The arguments to pass to the format function: see adg_dim_style_set_number_arguments() for further details"),
261 g_object_class_install_property(gobject_class
, PROP_NUMBER_ARGUMENTS
, param
);
263 param
= g_param_spec_string("number-tag",
265 P_("The tag to substitute inside the value template string"),
268 g_object_class_install_property(gobject_class
, PROP_NUMBER_TAG
, param
);
270 param
= g_param_spec_int("decimals",
271 P_("Rounded Value Decimals"),
272 P_("Number of significant decimals to use in the format string for rounded values (-1 to disable)"),
276 g_object_class_install_property(gobject_class
, PROP_DECIMALS
, param
);
278 param
= g_param_spec_int("rounding",
279 P_("Raw Value Decimals"),
280 P_("Number of significant decimals the raw value must be rounded to (-1 to disable)"),
284 g_object_class_install_property(gobject_class
, PROP_ROUNDING
, param
);
288 adg_dim_style_init(AdgDimStyle
*dim_style
)
290 AdgDimStylePrivate
*data
= adg_dim_style_get_instance_private(dim_style
);
291 data
->marker1
.type
= 0;
292 data
->marker1
.n_properties
= 0;
293 data
->marker1
.names
= NULL
;
294 data
->marker1
.values
= NULL
;
295 data
->marker2
.type
= 0;
296 data
->marker2
.n_properties
= 0;
297 data
->marker2
.names
= NULL
;
298 data
->marker2
.values
= NULL
;
299 data
->color_dress
= ADG_DRESS_COLOR_DIMENSION
;
300 data
->value_dress
= ADG_DRESS_FONT_QUOTE_TEXT
;
301 data
->min_dress
= ADG_DRESS_FONT_QUOTE_ANNOTATION
;
302 data
->max_dress
= ADG_DRESS_FONT_QUOTE_ANNOTATION
;
303 data
->line_dress
= ADG_DRESS_LINE_DIMENSION
;
304 data
->marker_dress
= ADG_DRESS_UNDEFINED
;
305 data
->from_offset
= 6;
308 data
->baseline_spacing
= 32;
309 data
->limits_spacing
= 0;
310 data
->quote_shift
.x
= 4;
311 data
->quote_shift
.y
= -1;
312 data
->limits_shift
.x
= +2;
313 data
->limits_shift
.y
= +2;
314 data
->number_format
= g_strdup("%-.7g");
315 data
->number_arguments
= g_strdup("d");
316 data
->number_tag
= g_strdup("<>");
322 _adg_finalize(GObject
*object
)
324 AdgDimStylePrivate
*data
= adg_dim_style_get_instance_private((AdgDimStyle
*) object
);
326 _adg_marker_data_unset(&data
->marker1
);
327 _adg_marker_data_unset(&data
->marker2
);
329 g_free(data
->number_format
);
330 data
->number_format
= NULL
;
332 g_free(data
->number_arguments
);
333 data
->number_arguments
= NULL
;
335 g_free(data
->number_tag
);
336 data
->number_tag
= NULL
;
340 _adg_get_property(GObject
*object
, guint prop_id
,
341 GValue
*value
, GParamSpec
*pspec
)
343 AdgDimStylePrivate
*data
= adg_dim_style_get_instance_private((AdgDimStyle
*) object
);
346 case PROP_COLOR_DRESS
:
347 g_value_set_enum(value
, data
->color_dress
);
349 case PROP_VALUE_DRESS
:
350 g_value_set_enum(value
, data
->value_dress
);
353 g_value_set_enum(value
, data
->min_dress
);
356 g_value_set_enum(value
, data
->max_dress
);
358 case PROP_LINE_DRESS
:
359 g_value_set_enum(value
, data
->line_dress
);
361 case PROP_FROM_OFFSET
:
362 g_value_set_double(value
, data
->from_offset
);
365 g_value_set_double(value
, data
->to_offset
);
368 g_value_set_double(value
, data
->beyond
);
370 case PROP_BASELINE_SPACING
:
371 g_value_set_double(value
, data
->baseline_spacing
);
373 case PROP_LIMITS_SPACING
:
374 g_value_set_double(value
, data
->limits_spacing
);
376 case PROP_QUOTE_SHIFT
:
377 g_value_set_boxed(value
, &data
->quote_shift
);
379 case PROP_LIMITS_SHIFT
:
380 g_value_set_boxed(value
, &data
->limits_shift
);
382 case PROP_NUMBER_FORMAT
:
383 g_value_set_string(value
, data
->number_format
);
385 case PROP_NUMBER_ARGUMENTS
:
386 g_value_set_string(value
, data
->number_arguments
);
388 case PROP_NUMBER_TAG
:
389 g_value_set_string(value
, data
->number_tag
);
392 g_value_set_int(value
, data
->decimals
);
395 g_value_set_int(value
, data
->rounding
);
398 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
404 _adg_set_property(GObject
*object
, guint prop_id
,
405 const GValue
*value
, GParamSpec
*pspec
)
407 AdgDimStyle
*dim_style
= (AdgDimStyle
*) object
;
408 AdgDimStylePrivate
*data
= adg_dim_style_get_instance_private(dim_style
);
412 _adg_marker_data_set(&data
->marker1
, g_value_get_object(value
));
415 _adg_marker_data_set(&data
->marker2
, g_value_get_object(value
));
417 case PROP_COLOR_DRESS
:
418 data
->color_dress
= g_value_get_enum(value
);
420 case PROP_VALUE_DRESS
:
421 data
->value_dress
= g_value_get_enum(value
);
424 data
->min_dress
= g_value_get_enum(value
);
427 data
->max_dress
= g_value_get_enum(value
);
429 case PROP_LINE_DRESS
:
430 data
->line_dress
= g_value_get_enum(value
);
432 case PROP_FROM_OFFSET
:
433 data
->from_offset
= g_value_get_double(value
);
436 data
->to_offset
= g_value_get_double(value
);
439 data
->beyond
= g_value_get_double(value
);
441 case PROP_BASELINE_SPACING
:
442 data
->baseline_spacing
= g_value_get_double(value
);
444 case PROP_LIMITS_SPACING
:
445 data
->limits_spacing
= g_value_get_double(value
);
447 case PROP_QUOTE_SHIFT
:
448 cpml_pair_copy(&data
->quote_shift
, g_value_get_boxed(value
));
450 case PROP_LIMITS_SHIFT
:
451 cpml_pair_copy(&data
->limits_shift
, g_value_get_boxed(value
));
453 case PROP_NUMBER_FORMAT
:
454 g_free(data
->number_format
);
455 data
->number_format
= g_value_dup_string(value
);
457 case PROP_NUMBER_ARGUMENTS
: {
458 const gchar
*arguments
= g_value_get_string(value
);
459 g_return_if_fail(arguments
== NULL
|| strspn(arguments
, VALID_FORMATS
) == strlen(arguments
));
460 g_free(data
->number_arguments
);
461 data
->number_arguments
= g_strdup(arguments
);
464 case PROP_NUMBER_TAG
:
465 g_free(data
->number_tag
);
466 data
->number_tag
= g_value_dup_string(value
);
469 data
->decimals
= g_value_get_int(value
);
472 data
->rounding
= g_value_get_int(value
);
475 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
484 * Constructs a new empty dimension style initialized with default params.
486 * Returns: (transfer full): a newly created dimension style.
491 adg_dim_style_new(void)
493 return g_object_new(ADG_TYPE_DIM_STYLE
, NULL
);
497 * adg_dim_style_set_marker1:
498 * @dim_style: an #AdgStyle
499 * @marker: an #AdgMarker derived entity
501 * Uses @marker as entity template to generate a new marker entity
502 * when a call to adg_dim_style_marker1_new() is made. It is allowed
503 * to pass <constant>NULL</constant> as @marker, in which case the
504 * template data of the first marker are unset.
506 * This method duplicates internally the property values of @marker,
507 * so any further change to @marker does not affect @dim_style anymore.
508 * This also means @marker could be destroyed without problems after
509 * this call because @dim_style uses only its property values and does
510 * not add any references to @marker.
515 adg_dim_style_set_marker1(AdgDimStyle
*dim_style
, AdgMarker
*marker
)
517 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
518 g_object_set(dim_style
, "marker1", marker
, NULL
);
522 * adg_dim_style_marker1_new:
523 * @dim_style: an #AdgDimStyle
525 * Creates a new marker entity by cloning the #AdgDimStyle:marker1
526 * object. The returned entity should be unreferenced with
527 * g_object_unref() when no longer needed.
529 * Returns: (transfer full): a newly created marker or <constant>NULL</constant> if the #AdgDimStyle:marker1 property is not set or on errors.
534 adg_dim_style_marker1_new(AdgDimStyle
*dim_style
)
536 AdgDimStylePrivate
*data
;
538 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
540 data
= adg_dim_style_get_instance_private(dim_style
);
541 return _adg_marker_new(&data
->marker1
);
545 * adg_dim_style_set_marker2:
546 * @dim_style: an #AdgStyle
547 * @marker: an #AdgMarker derived entity
549 * Uses @marker as entity template to generate a new marker entity
550 * when a call to adg_dim_style_marker2_new() is made. It is allowed
551 * to pass <constant>NULL</constant> as @marker, in which case the
552 * template data of the second marker are unset.
554 * This method duplicates internally the property values of @marker,
555 * so any further change to @marker does not affect @dim_style anymore.
556 * This also means @marker could be destroyed without problems after
557 * this call because @dim_style uses only its property values and does
558 * not add any references to @marker.
563 adg_dim_style_set_marker2(AdgDimStyle
*dim_style
, AdgMarker
*marker
)
565 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
566 g_object_set(dim_style
, "marker2", marker
, NULL
);
570 * adg_dim_style_marker2_new:
571 * @dim_style: an #AdgDimStyle
573 * Creates a new marker entity by cloning the #AdgDimStyle:marker2
574 * object. The returned entity should be unreferenced with
575 * g_object_unref() when no longer needed.
577 * Returns: (transfer full): a newly created marker or <constant>NULL</constant> if the #AdgDimStyle:marker2 property is not set or on errors.
582 adg_dim_style_marker2_new(AdgDimStyle
*dim_style
)
584 AdgDimStylePrivate
*data
;
586 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
588 data
= adg_dim_style_get_instance_private(dim_style
);
589 return _adg_marker_new(&data
->marker2
);
593 * adg_dim_style_set_color_dress:
594 * @dim_style: an #AdgDimStyle object
595 * @dress: the new color dress
597 * Sets a new color dress on @dim_style.
602 adg_dim_style_set_color_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
604 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
605 g_object_set(dim_style
, "color-dress", dress
, NULL
);
609 * adg_dim_style_get_color_dress:
610 * @dim_style: an #AdgDimStyle object
612 * Gets the @dim_style color dress to be used. This dress should be
613 * intended as a fallback color as it could be overriden by more
614 * specific dresses, such as a color explicitely specified on the
615 * #AdgDimStyle:value-dress.
617 * Returns: (transfer none): the color dress.
622 adg_dim_style_get_color_dress(AdgDimStyle
*dim_style
)
624 AdgDimStylePrivate
*data
;
626 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
628 data
= adg_dim_style_get_instance_private(dim_style
);
629 return data
->color_dress
;
633 * adg_dim_style_set_value_dress:
634 * @dim_style: an #AdgDimStyle object
635 * @dress: the new basic value font style
637 * Sets a new dress on @dim_style for the basic value.
642 adg_dim_style_set_value_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
644 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
645 g_object_set(dim_style
, "value-dress", dress
, NULL
);
649 * adg_dim_style_get_value_dress:
650 * @dim_style: an #AdgDimStyle object
652 * Gets the font dress to be used for the basic value of dimensions
655 * Returns: (transfer none): the font dress.
660 adg_dim_style_get_value_dress(AdgDimStyle
*dim_style
)
662 AdgDimStylePrivate
*data
;
664 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
666 data
= adg_dim_style_get_instance_private(dim_style
);
667 return data
->value_dress
;
671 * adg_dim_style_set_min_dress:
672 * @dim_style: an #AdgDimStyle object
673 * @dress: the new lower limit dress
675 * Sets a new dress on @dim_style for the lower limit value.
680 adg_dim_style_set_min_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
682 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
683 g_object_set(dim_style
, "min-dress", dress
, NULL
);
687 * adg_dim_style_get_min_dress:
688 * @dim_style: an #AdgDimStyle object
690 * Gets the @dim_style dress to be used for the lower limit.
692 * Returns: (transfer none): the lower limit dress.
697 adg_dim_style_get_min_dress(AdgDimStyle
*dim_style
)
699 AdgDimStylePrivate
*data
;
701 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
703 data
= adg_dim_style_get_instance_private(dim_style
);
704 return data
->min_dress
;
708 * adg_dim_style_set_max_dress:
709 * @dim_style: an #AdgDimStyle object
710 * @dress: the new upper limit dress
712 * Sets a new dress on @dim_style for the upper limit value.
717 adg_dim_style_set_max_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
719 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
720 g_object_set(dim_style
, "max-dress", dress
, NULL
);
724 * adg_dim_style_get_max_dress:
725 * @dim_style: an #AdgDimStyle object
727 * Gets the @dim_style dress to be used for the upper limit.
729 * Returns: (transfer none): the upper limit dress.
734 adg_dim_style_get_max_dress(AdgDimStyle
*dim_style
)
736 AdgDimStylePrivate
*data
;
738 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
740 data
= adg_dim_style_get_instance_private(dim_style
);
741 return data
->max_dress
;
745 * adg_dim_style_set_line_dress:
746 * @dim_style: an #AdgDimStyle object
747 * @dress: the new line dress
749 * Sets a new line dress on @dim_style.
754 adg_dim_style_set_line_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
756 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
757 g_object_set(dim_style
, "line-dress", dress
, NULL
);
761 * adg_dim_style_get_line_dress:
762 * @dim_style: an #AdgDimStyle object
764 * Gets the line dress to be used for rendering the base and
765 * the extension lines with @dim_style.
767 * Returns: (transfer none): the line dress.
772 adg_dim_style_get_line_dress(AdgDimStyle
*dim_style
)
774 AdgDimStylePrivate
*data
;
776 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
778 data
= adg_dim_style_get_instance_private(dim_style
);
779 return data
->line_dress
;
783 * adg_dim_style_set_from_offset:
784 * @dim_style: an #AdgDimStyle object
785 * @offset: the new offset
787 * Sets a new value in the #AdgDimStyle:from-offset property.
792 adg_dim_style_set_from_offset(AdgDimStyle
*dim_style
, gdouble offset
)
794 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
795 g_object_set(dim_style
, "from-offset", offset
, NULL
);
799 * adg_dim_style_get_from_offset:
800 * @dim_style: an #AdgDimStyle object
802 * Gets the distance (in global space) the extension lines must keep from the
805 * Returns: the requested distance.
810 adg_dim_style_get_from_offset(AdgDimStyle
*dim_style
)
812 AdgDimStylePrivate
*data
;
814 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
816 data
= adg_dim_style_get_instance_private(dim_style
);
817 return data
->from_offset
;
821 * adg_dim_style_set_to_offset:
822 * @dim_style: an #AdgDimStyle object
823 * @offset: the new offset
825 * Sets a new value in the #AdgDimStyle:to-offset property.
830 adg_dim_style_set_to_offset(AdgDimStyle
*dim_style
, gdouble offset
)
832 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
833 g_object_set(dim_style
, "to-offset", offset
, NULL
);
837 * adg_dim_style_get_to_offset:
838 * @dim_style: an #AdgDimStyle object
840 * Gets how much (in global space) the extension lines must extend after
841 * crossing the baseline.
843 * Returns: the requested distance.
848 adg_dim_style_get_to_offset(AdgDimStyle
*dim_style
)
850 AdgDimStylePrivate
*data
;
852 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
854 data
= adg_dim_style_get_instance_private(dim_style
);
855 return data
->to_offset
;
859 * adg_dim_style_set_beyond:
860 * @dim_style: an #AdgDimStyle object
861 * @beyond: the new length
863 * Sets a new value in the #AdgDimStyle:beyond property.
868 adg_dim_style_set_beyond(AdgDimStyle
*dim_style
, gdouble beyond
)
870 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
871 g_object_set(dim_style
, "beyond", beyond
, NULL
);
875 * adg_dim_style_get_beyond:
876 * @dim_style: an #AdgDimStyle object
878 * Gets how much (in global space) the baseline should extend beyond
879 * the extension lines on dimension with outside markers.
881 * Returns: the requested beyond length.
886 adg_dim_style_get_beyond(AdgDimStyle
*dim_style
)
888 AdgDimStylePrivate
*data
;
890 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
892 data
= adg_dim_style_get_instance_private(dim_style
);
897 * adg_dim_style_set_baseline_spacing:
898 * @dim_style: an #AdgDimStyle object
899 * @spacing: the new spacing
901 * Sets a new value in the #AdgDimStyle:baseline-spacing value.
906 adg_dim_style_set_baseline_spacing(AdgDimStyle
*dim_style
, gdouble spacing
)
908 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
909 g_object_set(dim_style
, "baseline-spacing", spacing
, NULL
);
913 * adg_dim_style_get_baseline_spacing:
914 * @dim_style: an #AdgDimStyle object
916 * Gets the distance between two consecutive baselines
917 * while stacking dimensions.
919 * Returns: the requested spacing.
924 adg_dim_style_get_baseline_spacing(AdgDimStyle
*dim_style
)
926 AdgDimStylePrivate
*data
;
928 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
930 data
= adg_dim_style_get_instance_private(dim_style
);
931 return data
->baseline_spacing
;
935 * adg_dim_style_set_limits_spacing:
936 * @dim_style: an #AdgDimStyle object
937 * @spacing: the new spacing
939 * Sets a new #AdgDimStyle:limits-spacing value.
944 adg_dim_style_set_limits_spacing(AdgDimStyle
*dim_style
, gdouble spacing
)
946 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
947 g_object_set(dim_style
, "limits-spacing", spacing
, NULL
);
951 * adg_dim_style_get_limits_spacing:
952 * @dim_style: an #AdgDimStyle object
954 * Gets the distance (in global space) between the limits/tolerances.
956 * Returns: the requested spacing.
961 adg_dim_style_get_limits_spacing(AdgDimStyle
*dim_style
)
963 AdgDimStylePrivate
*data
;
965 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
967 data
= adg_dim_style_get_instance_private(dim_style
);
968 return data
->limits_spacing
;
972 * adg_dim_style_set_quote_shift:
973 * @dim_style: an #AdgDimStyle object
974 * @shift: the new displacement
976 * Sets a new #AdgDimStyle:quote-shift value.
981 adg_dim_style_set_quote_shift(AdgDimStyle
*dim_style
, const CpmlPair
*shift
)
983 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
984 g_object_set(dim_style
, "quote-shift", shift
, NULL
);
988 * adg_dim_style_get_quote_shift:
989 * @dim_style: an #AdgDimStyle object
991 * Gets the smooth displacement of the quote. The returned pointer refers
992 * to an internal allocated struct and must not be modified or freed.
994 * Returns: (transfer none): the requested shift.
999 adg_dim_style_get_quote_shift(AdgDimStyle
*dim_style
)
1001 AdgDimStylePrivate
*data
;
1003 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1005 data
= adg_dim_style_get_instance_private(dim_style
);
1006 return &data
->quote_shift
;
1010 * adg_dim_style_set_limits_shift:
1011 * @dim_style: an #AdgDimStyle object
1012 * @shift: the new displacement
1014 * Sets a new #AdgDimStyle:limits-shift value.
1019 adg_dim_style_set_limits_shift(AdgDimStyle
*dim_style
, const CpmlPair
*shift
)
1021 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1022 g_object_set(dim_style
, "limits-shift", shift
, NULL
);
1026 * adg_dim_style_get_limits_shift:
1027 * @dim_style: an #AdgDimStyle object
1029 * Gets the smooth displacement for the limits. The returned pointer
1030 * refers to an internal allocated struct and must not be modified or freed.
1032 * Returns: (transfer none): the requested shift.
1037 adg_dim_style_get_limits_shift(AdgDimStyle
*dim_style
)
1039 AdgDimStylePrivate
*data
;
1041 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1043 data
= adg_dim_style_get_instance_private(dim_style
);
1044 return &data
->limits_shift
;
1048 * adg_dim_style_set_number_format:
1049 * @dim_style: an #AdgDimStyle object
1050 * @format: the new format to adopt
1052 * Sets a new value in the #AdgDimStyle:number-format property.
1054 * @format is similar to a printf() style format string but only 'e', 'E',
1055 * 'f', 'F', 'g' and 'G' specifiers are allowed. For reference, the
1056 * implementation leverages the g_ascii_formatd() GLib function. If you want
1057 * to use special characters (%"(", %")" and %"%") as literals you need to
1058 * escape them with a backslash.
1060 * You can use round parenthesis to group together one or more % directives
1061 * with other related literals. In that case, when the value bound to the
1062 * directive will be 0, the whole group will disappear. Some example:
1066 * AdgDimStyle *dim_style;
1069 * dim = ADG_DIM(adg_ldim_new());
1070 * dim_style = ADG_DIM_STYLE(adg_entity_style(ADG_ENTITY(dim), ADG_DRESS_DIMENSION));
1072 * adg_dim_style_set_number_arguments(dim_style, "dD");
1073 * adg_dim_style_set_number_format(dim_style, "(%g)( truncated to %g)");
1075 * text = adg_dim_get_text(dim, 1.2);
1076 * g_print("%s\n", text); // Prints "1.2 truncated to 1"
1079 * text = adg_dim_get_text(dim, 0.2);
1080 * g_print("%s\n", text); // Prints "0.2"
1083 * text = adg_dim_get_text(dim, 0);
1084 * g_print("%s\n", text); // Prints ""
1088 * Groups can be nested and can have more than one value, in which case all
1089 * the values contained in a group must be 0 in order to let it disappear.
1090 * This comes in handy for removing trailing 0 fields. A typical example is
1091 * the sexagesimal representation of angles:
1094 * adg_dim_style_set_number_arguments(dim_style, "DMs");
1095 * adg_dim_style_set_number_format(dim_style, "%g°(%g'(%g\"))");
1097 * text = adg_dim_get_text(dim, 1.5);
1098 * g_print("%s\n", text); // Prints "1°30'"
1101 * text = adg_dim_get_text(dim, 2.002777);
1102 * g_print("%s\n", text); // Prints "2°0'10\""
1109 adg_dim_style_set_number_format(AdgDimStyle
*dim_style
, const gchar
*format
)
1111 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1112 g_object_set(dim_style
, "number-format", format
, NULL
);
1116 * adg_dim_style_get_number_format:
1117 * @dim_style: an #AdgDimStyle object
1119 * Gets the number format (in printf style) of this quoting style. The
1120 * returned pointer refers to internally managed text that must not be
1121 * modified or freed.
1123 * Returns: (transfer none): the requested format.
1128 adg_dim_style_get_number_format(AdgDimStyle
*dim_style
)
1130 AdgDimStylePrivate
*data
;
1132 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1134 data
= adg_dim_style_get_instance_private(dim_style
);
1135 return data
->number_format
;
1139 * adg_dim_style_set_number_arguments:
1140 * @dim_style: an #AdgDimStyle object
1141 * @arguments: the arguments to pass to the formatting function
1143 * A string that identifies the arguments to pass to the formatting function.
1144 * See adg_dim_style_convert() to know the allowed character that can be
1145 * included into this string.
1147 * The number of arguments (i.e. the @arguments length) must match the
1148 * #AdgDimStyle:number-format property (i.e. the number of % directives
1149 * included in that property). See adg_dim_style_set_number_format() for more
1150 * technical details and some examples.
1155 adg_dim_style_set_number_arguments(AdgDimStyle
*dim_style
, const gchar
*arguments
)
1157 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1158 g_object_set(dim_style
, "number-arguments", arguments
, NULL
);
1162 * adg_dim_style_get_number_arguments:
1163 * @dim_style: an #AdgDimStyle object
1165 * Gets the arguments used by the formatting function. See
1166 * adg_dim_style_set_number_arguments() for details on what this means.
1168 * Returns: (transfer none): the requested arguments.
1173 adg_dim_style_get_number_arguments(AdgDimStyle
*dim_style
)
1175 AdgDimStylePrivate
*data
;
1177 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1179 data
= adg_dim_style_get_instance_private(dim_style
);
1180 return data
->number_arguments
;
1184 * adg_dim_style_set_number_tag:
1185 * @dim_style: an #AdgDimStyle object
1188 * Sets a new tag in the #AdgDimStyle:number-tag property.
1193 adg_dim_style_set_number_tag(AdgDimStyle
*dim_style
, const gchar
*tag
)
1195 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1196 g_object_set(dim_style
, "number-tag", tag
, NULL
);
1200 * adg_dim_style_get_number_tag:
1201 * @dim_style: an #AdgDimStyle object
1203 * Gets the number tag of @dim_style. This tag will be used while
1204 * generating the set values of the dimensions bound to this style:
1205 * check the #AdgDim:value documentation for further details.
1207 * The returned pointer refers to internally managed text that
1208 * must not be modified or freed.
1210 * Returns: (transfer none): the requested tag.
1215 adg_dim_style_get_number_tag(AdgDimStyle
*dim_style
)
1217 AdgDimStylePrivate
*data
;
1219 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1221 data
= adg_dim_style_get_instance_private(dim_style
);
1222 return data
->number_tag
;
1226 * adg_dim_style_set_decimals:
1227 * @dim_style: an #AdgDimStyle object
1228 * @decimals: number of significant decimals
1230 * Sets a new value in the #AdgDimStyle:decimals property.
1235 adg_dim_style_set_decimals(AdgDimStyle
*dim_style
, gint decimals
)
1237 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1238 g_object_set(dim_style
, "decimals", decimals
, NULL
);
1242 * adg_dim_style_get_decimals:
1243 * @dim_style: an #AdgDimStyle object
1245 * Gets the decimals the value of a dimension will be rounded to before the
1248 * Returns: the number of significant decimals or -2 on errors.
1253 adg_dim_style_get_decimals(AdgDimStyle
*dim_style
)
1255 AdgDimStylePrivate
*data
;
1257 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), -2);
1259 data
= adg_dim_style_get_instance_private(dim_style
);
1260 return data
->decimals
;
1264 * adg_dim_style_set_rounding:
1265 * @dim_style: an #AdgDimStyle object
1266 * @rounding: number of significant decimals of the raw value
1268 * Sets a new value in the #AdgDimStyle:rounding property.
1273 adg_dim_style_set_rounding(AdgDimStyle
*dim_style
, gint rounding
)
1275 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1276 g_object_set(dim_style
, "rounding", rounding
, NULL
);
1280 * adg_dim_style_get_rounding:
1281 * @dim_style: an #AdgDimStyle object
1283 * Gets the number of decimals the raw value must be rounded to.
1285 * Returns: the number of significant decimals or -2 on errors.
1290 adg_dim_style_get_rounding(AdgDimStyle
*dim_style
)
1292 AdgDimStylePrivate
*data
;
1294 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), -2);
1296 data
= adg_dim_style_get_instance_private(dim_style
);
1297 return data
->rounding
;
1301 * adg_dim_style_convert:
1302 * @dim_style: an #AdgDimStyle object
1303 * @value: (inout): the value to convert
1304 * @format: the convertion to apply
1306 * Converts @value using the specific @format algorithm and store the
1307 * result in @value itself. If @value is %NULL, nothing is performed.
1309 * In the following the allowed values for @format:
1310 * - 'a': the raw @value, i.e. no conversion is performed;
1311 * - 'i': the raw number of minutes, i.e. the fractional part of @value x 60
1312 * - 'e': the raw number of seconds, i.e. the fractional part of the raw
1313 * number of minutes x 60
1314 * - 'D': the truncated value of the raw value ('a');
1315 * - 'd': the rounded value of the raw value ('a');
1316 * - 'M': the truncated value of the raw number of minutes ('i');
1317 * - 'm': the rounded value of the raw number of minutes ('i');
1318 * - 'S': the truncated value of the raw number of seconds ('e');
1319 * - 's': the rounded value of the raw number of seconds ('e');
1321 * The rounding is done according to the number of decimal specified in
1322 * #AdgDimStyle:decimals.
1324 * Returns: %TRUE if @value has been converted, %FALSE on errors.
1329 adg_dim_style_convert(AdgDimStyle
*dim_style
, gdouble
*value
, gchar format
)
1331 AdgDimStylePrivate
*data
;
1333 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), FALSE
);
1335 /* Inout parameter not provided: just return FALSE */
1336 if (value
== NULL
) {
1340 data
= adg_dim_style_get_instance_private(dim_style
);
1342 /* Round the raw value, if requested */
1343 if (data
->rounding
> -1) {
1344 gdouble coefficient
= pow(10, data
->rounding
);
1345 *value
= round(*value
* coefficient
) / coefficient
;
1350 case 'a': /* Raw value */
1353 case 'i': /* Raw minutes */
1354 *value
= (*value
- (gint
) *value
) * 60;
1357 case 'e': /* Raw seconds */
1358 adg_dim_style_convert(dim_style
, value
, 'i');
1359 *value
= (*value
- (gint
) *value
) * 60;
1362 case 'D': /* Truncated value */
1363 *value
= (gint
) *value
;
1366 case 'd': /* Rounded value */
1367 *value
= adg_round(*value
, data
->decimals
);
1370 case 'M': /* Truncated minutes */
1371 adg_dim_style_convert(dim_style
, value
, 'i');
1372 *value
= (gint
) *value
;
1375 case 'm': /* Rounded minutes */
1376 adg_dim_style_convert(dim_style
, value
, 'i');
1377 *value
= adg_round(*value
, data
->decimals
);
1380 case 'S': /* Truncated seconds */
1381 adg_dim_style_convert(dim_style
, value
, 'e');
1382 *value
= (gint
) *value
;
1385 case 's': /* Rounded seconds */
1386 adg_dim_style_convert(dim_style
, value
, 'e');
1387 *value
= adg_round(*value
, data
->decimals
);
1391 g_return_val_if_reached(FALSE
);
1400 _adg_clone(AdgStyle
*style
)
1402 AdgDimStyle
*dim_style
;
1405 dim_style
= (AdgDimStyle
*) adg_object_clone(G_OBJECT(style
));
1407 /* Manually clone the marker because the underlying properties are
1409 marker
= adg_dim_style_marker1_new((AdgDimStyle
*) style
);
1410 adg_dim_style_set_marker1(dim_style
, marker
);
1411 g_object_unref(marker
);
1413 marker
= adg_dim_style_marker2_new((AdgDimStyle
*) style
);
1414 adg_dim_style_set_marker2(dim_style
, marker
);
1415 g_object_unref(marker
);
1417 return (AdgStyle
*) dim_style
;
1421 _adg_apply(AdgStyle
*style
, AdgEntity
*entity
, cairo_t
*cr
)
1423 AdgDimStylePrivate
*data
= adg_dim_style_get_instance_private((AdgDimStyle
*) style
);
1424 adg_entity_apply_dress(entity
, data
->color_dress
, cr
);
1428 _adg_marker_new(const AdgMarkerData
*marker_data
)
1430 if (marker_data
->type
== 0)
1433 return (AdgMarker
*) g_object_new_with_properties(marker_data
->type
,
1434 marker_data
->n_properties
,
1436 marker_data
->values
);
1440 _adg_marker_data_set(AdgMarkerData
*marker_data
, AdgMarker
*marker
)
1442 g_return_if_fail(marker
== NULL
|| ADG_IS_MARKER(marker
));
1444 /* Free the previous marker data, if any */
1445 _adg_marker_data_unset(marker_data
);
1454 object
= (GObject
*) marker
;
1455 specs
= g_object_class_list_properties(G_OBJECT_GET_CLASS(marker
),
1456 &marker_data
->n_properties
);
1458 marker_data
->type
= G_TYPE_FROM_INSTANCE(marker
);
1459 marker_data
->names
= g_new0(const gchar
*, marker_data
->n_properties
);
1460 marker_data
->values
= g_new0(GValue
, marker_data
->n_properties
);
1462 for (n
= 0; n
< marker_data
->n_properties
; ++n
) {
1465 /* Using intern strings because `name` is const.
1466 * GObject properties are internally managed using non-static
1467 * GQuark, so g_intern_string() is the way to go */
1468 marker_data
->names
[n
] = g_intern_string(spec
->name
);
1470 value
= &marker_data
->values
[n
];
1471 g_value_init(value
, spec
->value_type
);
1472 g_object_get_property(object
, spec
->name
, value
);
1480 _adg_marker_data_unset(AdgMarkerData
*marker_data
)
1484 for (n
= 0; n
< marker_data
->n_properties
; ++n
) {
1485 g_value_unset(&marker_data
->values
[n
]);
1488 g_free(marker_data
->names
);
1489 g_free(marker_data
->values
);
1491 marker_data
->type
= 0;
1492 marker_data
->n_properties
= 0;
1493 marker_data
->names
= NULL
;
1494 marker_data
->values
= NULL
;