1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2019 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(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_set_marker (AdgMarkerData
*marker_data
,
131 static void _adg_free_marker (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 g_type_class_add_private(klass
, sizeof(AdgDimStylePrivate
));
146 gobject_class
->finalize
= _adg_finalize
;
147 gobject_class
->get_property
= _adg_get_property
;
148 gobject_class
->set_property
= _adg_set_property
;
150 style_class
->clone
= _adg_clone
;
151 style_class
->apply
= _adg_apply
;
153 param
= g_param_spec_object("marker1",
155 P_("The template entity to use as first marker"),
158 g_object_class_install_property(gobject_class
, PROP_MARKER1
, param
);
160 param
= g_param_spec_object("marker2",
162 P_("The template entity to use as second marker"),
165 g_object_class_install_property(gobject_class
, PROP_MARKER2
, param
);
167 param
= adg_param_spec_dress("color-dress",
169 P_("Color dress for the whole dimension"),
170 ADG_DRESS_COLOR_DIMENSION
,
172 g_object_class_install_property(gobject_class
, PROP_COLOR_DRESS
, param
);
174 param
= adg_param_spec_dress("value-dress",
176 P_("Font dress for the nominal value of the dimension"),
177 ADG_DRESS_FONT_QUOTE_TEXT
,
179 g_object_class_install_property(gobject_class
, PROP_VALUE_DRESS
, param
);
181 param
= adg_param_spec_dress("min-dress",
182 P_("Minimum Limit Dress"),
183 P_("Font dress for the lower limit value"),
184 ADG_DRESS_FONT_QUOTE_ANNOTATION
,
186 g_object_class_install_property(gobject_class
, PROP_MIN_DRESS
, param
);
188 param
= adg_param_spec_dress("max-dress",
189 P_("Maximum Limit Dress"),
190 P_("Font dress for the upper limit value"),
191 ADG_DRESS_FONT_QUOTE_ANNOTATION
,
193 g_object_class_install_property(gobject_class
, PROP_MAX_DRESS
, param
);
195 param
= adg_param_spec_dress("line-dress",
197 P_("Line dress for the baseline and the extension lines"),
198 ADG_DRESS_LINE_DIMENSION
,
200 g_object_class_install_property(gobject_class
, PROP_LINE_DRESS
, param
);
202 param
= g_param_spec_double("from-offset",
204 P_("Offset (in global space) of the extension lines from the path to the quote"),
207 g_object_class_install_property(gobject_class
, PROP_FROM_OFFSET
, param
);
209 param
= g_param_spec_double("to-offset",
211 P_("How many extend (in global space) the extension lines after hitting the baseline"),
214 g_object_class_install_property(gobject_class
, PROP_TO_OFFSET
, param
);
216 param
= g_param_spec_double("beyond",
218 P_("How much the baseline should be extended (in global space) beyond the extension lines on dimensions with outside markers"),
221 g_object_class_install_property(gobject_class
, PROP_BEYOND
, param
);
223 param
= g_param_spec_double("baseline-spacing",
224 P_("Baseline Spacing"),
225 P_("Distance between two consecutive baselines while stacking dimensions"),
228 g_object_class_install_property(gobject_class
, PROP_BASELINE_SPACING
, param
);
230 param
= g_param_spec_double("limits-spacing",
231 P_("Limits Spacing"),
232 P_("Distance between limits/tolerances"),
233 -G_MAXDOUBLE
, G_MAXDOUBLE
, 2,
235 g_object_class_install_property(gobject_class
, PROP_LIMITS_SPACING
, param
);
237 param
= g_param_spec_boxed("quote-shift",
239 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)"),
242 g_object_class_install_property(gobject_class
, PROP_QUOTE_SHIFT
, param
);
244 param
= g_param_spec_boxed("limits-shift",
246 P_("Used to specify a smooth displacement (in global space) for the limits/tolerances by taking as reference the perfect compact position"),
249 g_object_class_install_property(gobject_class
, PROP_LIMITS_SHIFT
, param
);
251 param
= g_param_spec_string("number-format",
253 P_("The format (in printf style) of the numeric component of the basic value"),
256 g_object_class_install_property(gobject_class
, PROP_NUMBER_FORMAT
, param
);
258 param
= g_param_spec_string("number-arguments",
259 P_("Number Arguments"),
260 P_("The arguments to pass to the format function: see adg_dim_style_set_number_arguments() for further details"),
263 g_object_class_install_property(gobject_class
, PROP_NUMBER_ARGUMENTS
, param
);
265 param
= g_param_spec_string("number-tag",
267 P_("The tag to substitute inside the value template string"),
270 g_object_class_install_property(gobject_class
, PROP_NUMBER_TAG
, param
);
272 param
= g_param_spec_int("decimals",
273 P_("Rounded Value Decimals"),
274 P_("Number of significant decimals to use in the format string for rounded values (-1 to disable)"),
278 g_object_class_install_property(gobject_class
, PROP_DECIMALS
, param
);
280 param
= g_param_spec_int("rounding",
281 P_("Raw Value Decimals"),
282 P_("Number of significant decimals the raw value must be rounded to (-1 to disable)"),
286 g_object_class_install_property(gobject_class
, PROP_ROUNDING
, param
);
290 adg_dim_style_init(AdgDimStyle
*dim_style
)
292 AdgDimStylePrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(dim_style
,
296 data
->marker1
.type
= 0;
297 data
->marker1
.n_parameters
= 0;
298 data
->marker1
.parameters
= NULL
;
299 data
->marker2
.type
= 0;
300 data
->marker2
.n_parameters
= 0;
301 data
->marker2
.parameters
= NULL
;
302 data
->color_dress
= ADG_DRESS_COLOR_DIMENSION
;
303 data
->value_dress
= ADG_DRESS_FONT_QUOTE_TEXT
;
304 data
->min_dress
= ADG_DRESS_FONT_QUOTE_ANNOTATION
;
305 data
->max_dress
= ADG_DRESS_FONT_QUOTE_ANNOTATION
;
306 data
->line_dress
= ADG_DRESS_LINE_DIMENSION
;
307 data
->marker_dress
= ADG_DRESS_UNDEFINED
;
308 data
->from_offset
= 6;
311 data
->baseline_spacing
= 32;
312 data
->limits_spacing
= 0;
313 data
->quote_shift
.x
= 4;
314 data
->quote_shift
.y
= -1;
315 data
->limits_shift
.x
= +2;
316 data
->limits_shift
.y
= +2;
317 data
->number_format
= g_strdup("%-.7g");
318 data
->number_arguments
= g_strdup("d");
319 data
->number_tag
= g_strdup("<>");
323 dim_style
->data
= data
;
327 _adg_finalize(GObject
*object
)
329 AdgDimStylePrivate
*data
= ((AdgDimStyle
*) object
)->data
;
331 _adg_free_marker(&data
->marker1
);
332 _adg_free_marker(&data
->marker2
);
334 g_free(data
->number_format
);
335 data
->number_format
= NULL
;
337 g_free(data
->number_arguments
);
338 data
->number_arguments
= NULL
;
340 g_free(data
->number_tag
);
341 data
->number_tag
= NULL
;
345 _adg_get_property(GObject
*object
, guint prop_id
,
346 GValue
*value
, GParamSpec
*pspec
)
348 AdgDimStylePrivate
*data
= ((AdgDimStyle
*) object
)->data
;
351 case PROP_COLOR_DRESS
:
352 g_value_set_enum(value
, data
->color_dress
);
354 case PROP_VALUE_DRESS
:
355 g_value_set_enum(value
, data
->value_dress
);
358 g_value_set_enum(value
, data
->min_dress
);
361 g_value_set_enum(value
, data
->max_dress
);
363 case PROP_LINE_DRESS
:
364 g_value_set_enum(value
, data
->line_dress
);
366 case PROP_FROM_OFFSET
:
367 g_value_set_double(value
, data
->from_offset
);
370 g_value_set_double(value
, data
->to_offset
);
373 g_value_set_double(value
, data
->beyond
);
375 case PROP_BASELINE_SPACING
:
376 g_value_set_double(value
, data
->baseline_spacing
);
378 case PROP_LIMITS_SPACING
:
379 g_value_set_double(value
, data
->limits_spacing
);
381 case PROP_QUOTE_SHIFT
:
382 g_value_set_boxed(value
, &data
->quote_shift
);
384 case PROP_LIMITS_SHIFT
:
385 g_value_set_boxed(value
, &data
->limits_shift
);
387 case PROP_NUMBER_FORMAT
:
388 g_value_set_string(value
, data
->number_format
);
390 case PROP_NUMBER_ARGUMENTS
:
391 g_value_set_string(value
, data
->number_arguments
);
393 case PROP_NUMBER_TAG
:
394 g_value_set_string(value
, data
->number_tag
);
397 g_value_set_int(value
, data
->decimals
);
400 g_value_set_int(value
, data
->rounding
);
403 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
409 _adg_set_property(GObject
*object
, guint prop_id
,
410 const GValue
*value
, GParamSpec
*pspec
)
412 AdgDimStyle
*dim_style
;
413 AdgDimStylePrivate
*data
;
415 dim_style
= (AdgDimStyle
*) object
;
416 data
= dim_style
->data
;
420 _adg_set_marker(&data
->marker1
, g_value_get_object(value
));
423 _adg_set_marker(&data
->marker2
, g_value_get_object(value
));
425 case PROP_COLOR_DRESS
:
426 data
->color_dress
= g_value_get_enum(value
);
428 case PROP_VALUE_DRESS
:
429 data
->value_dress
= g_value_get_enum(value
);
432 data
->min_dress
= g_value_get_enum(value
);
435 data
->max_dress
= g_value_get_enum(value
);
437 case PROP_LINE_DRESS
:
438 data
->line_dress
= g_value_get_enum(value
);
440 case PROP_FROM_OFFSET
:
441 data
->from_offset
= g_value_get_double(value
);
444 data
->to_offset
= g_value_get_double(value
);
447 data
->beyond
= g_value_get_double(value
);
449 case PROP_BASELINE_SPACING
:
450 data
->baseline_spacing
= g_value_get_double(value
);
452 case PROP_LIMITS_SPACING
:
453 data
->limits_spacing
= g_value_get_double(value
);
455 case PROP_QUOTE_SHIFT
:
456 cpml_pair_copy(&data
->quote_shift
, g_value_get_boxed(value
));
458 case PROP_LIMITS_SHIFT
:
459 cpml_pair_copy(&data
->limits_shift
, g_value_get_boxed(value
));
461 case PROP_NUMBER_FORMAT
:
462 g_free(data
->number_format
);
463 data
->number_format
= g_value_dup_string(value
);
465 case PROP_NUMBER_ARGUMENTS
: {
466 const gchar
*arguments
= g_value_get_string(value
);
467 g_return_if_fail(arguments
== NULL
|| strspn(arguments
, VALID_FORMATS
) == strlen(arguments
));
468 g_free(data
->number_arguments
);
469 data
->number_arguments
= g_strdup(arguments
);
472 case PROP_NUMBER_TAG
:
473 g_free(data
->number_tag
);
474 data
->number_tag
= g_value_dup_string(value
);
477 data
->decimals
= g_value_get_int(value
);
480 data
->rounding
= g_value_get_int(value
);
483 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
492 * Constructs a new empty dimension style initialized with default params.
494 * Returns: (transfer full): a newly created dimension style.
499 adg_dim_style_new(void)
501 return g_object_new(ADG_TYPE_DIM_STYLE
, NULL
);
505 * adg_dim_style_set_marker1:
506 * @dim_style: an #AdgStyle
507 * @marker: an #AdgMarker derived entity
509 * Uses @marker as entity template to generate a new marker entity
510 * when a call to adg_dim_style_marker1_new() is made. It is allowed
511 * to pass <constant>NULL</constant> as @marker, in which case the
512 * template data of the first marker are unset.
514 * This method duplicates internally the property values of @marker,
515 * so any further change to @marker does not affect @dim_style anymore.
516 * This also means @marker could be destroyed without problems after
517 * this call because @dim_style uses only its property values and does
518 * not add any references to @marker.
523 adg_dim_style_set_marker1(AdgDimStyle
*dim_style
, AdgMarker
*marker
)
525 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
526 g_object_set(dim_style
, "marker1", marker
, NULL
);
530 * adg_dim_style_marker1_new:
531 * @dim_style: an #AdgDimStyle
533 * Creates a new marker entity by cloning the #AdgDimStyle:marker1
534 * object. The returned entity should be unreferenced with
535 * g_object_unref() when no longer needed.
537 * Returns: (transfer full): a newly created marker or <constant>NULL</constant> if the #AdgDimStyle:marker1 property is not set or on errors.
542 adg_dim_style_marker1_new(AdgDimStyle
*dim_style
)
544 AdgDimStylePrivate
*data
;
546 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
548 data
= dim_style
->data
;
550 return _adg_marker_new(&data
->marker1
);
554 * adg_dim_style_set_marker2:
555 * @dim_style: an #AdgStyle
556 * @marker: an #AdgMarker derived entity
558 * Uses @marker as entity template to generate a new marker entity
559 * when a call to adg_dim_style_marker2_new() is made. It is allowed
560 * to pass <constant>NULL</constant> as @marker, in which case the
561 * template data of the second marker are unset.
563 * This method duplicates internally the property values of @marker,
564 * so any further change to @marker does not affect @dim_style anymore.
565 * This also means @marker could be destroyed without problems after
566 * this call because @dim_style uses only its property values and does
567 * not add any references to @marker.
572 adg_dim_style_set_marker2(AdgDimStyle
*dim_style
, AdgMarker
*marker
)
574 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
575 g_object_set(dim_style
, "marker2", marker
, NULL
);
579 * adg_dim_style_marker2_new:
580 * @dim_style: an #AdgDimStyle
582 * Creates a new marker entity by cloning the #AdgDimStyle:marker2
583 * object. The returned entity should be unreferenced with
584 * g_object_unref() when no longer needed.
586 * Returns: (transfer full): a newly created marker or <constant>NULL</constant> if the #AdgDimStyle:marker2 property is not set or on errors.
591 adg_dim_style_marker2_new(AdgDimStyle
*dim_style
)
593 AdgDimStylePrivate
*data
;
595 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
597 data
= dim_style
->data
;
599 return _adg_marker_new(&data
->marker2
);
603 * adg_dim_style_set_color_dress:
604 * @dim_style: an #AdgDimStyle object
605 * @dress: the new color dress
607 * Sets a new color dress on @dim_style.
612 adg_dim_style_set_color_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
614 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
615 g_object_set(dim_style
, "color-dress", dress
, NULL
);
619 * adg_dim_style_get_color_dress:
620 * @dim_style: an #AdgDimStyle object
622 * Gets the @dim_style color dress to be used. This dress should be
623 * intended as a fallback color as it could be overriden by more
624 * specific dresses, such as a color explicitely specified on the
625 * #AdgDimStyle:value-dress.
627 * Returns: (transfer none): the color dress.
632 adg_dim_style_get_color_dress(AdgDimStyle
*dim_style
)
634 AdgDimStylePrivate
*data
;
636 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
638 data
= dim_style
->data
;
640 return data
->color_dress
;
644 * adg_dim_style_set_value_dress:
645 * @dim_style: an #AdgDimStyle object
646 * @dress: the new basic value font style
648 * Sets a new dress on @dim_style for the basic value.
653 adg_dim_style_set_value_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
655 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
656 g_object_set(dim_style
, "value-dress", dress
, NULL
);
660 * adg_dim_style_get_value_dress:
661 * @dim_style: an #AdgDimStyle object
663 * Gets the font dress to be used for the basic value of dimensions
666 * Returns: (transfer none): the font dress.
671 adg_dim_style_get_value_dress(AdgDimStyle
*dim_style
)
673 AdgDimStylePrivate
*data
;
675 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
677 data
= dim_style
->data
;
679 return data
->value_dress
;
683 * adg_dim_style_set_min_dress:
684 * @dim_style: an #AdgDimStyle object
685 * @dress: the new lower limit dress
687 * Sets a new dress on @dim_style for the lower limit value.
692 adg_dim_style_set_min_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
694 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
695 g_object_set(dim_style
, "min-dress", dress
, NULL
);
699 * adg_dim_style_get_min_dress:
700 * @dim_style: an #AdgDimStyle object
702 * Gets the @dim_style dress to be used for the lower limit.
704 * Returns: (transfer none): the lower limit dress.
709 adg_dim_style_get_min_dress(AdgDimStyle
*dim_style
)
711 AdgDimStylePrivate
*data
;
713 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
715 data
= dim_style
->data
;
717 return data
->min_dress
;
721 * adg_dim_style_set_max_dress:
722 * @dim_style: an #AdgDimStyle object
723 * @dress: the new upper limit dress
725 * Sets a new dress on @dim_style for the upper limit value.
730 adg_dim_style_set_max_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
732 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
733 g_object_set(dim_style
, "max-dress", dress
, NULL
);
737 * adg_dim_style_get_max_dress:
738 * @dim_style: an #AdgDimStyle object
740 * Gets the @dim_style dress to be used for the upper limit.
742 * Returns: (transfer none): the upper limit dress.
747 adg_dim_style_get_max_dress(AdgDimStyle
*dim_style
)
749 AdgDimStylePrivate
*data
;
751 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
753 data
= dim_style
->data
;
755 return data
->max_dress
;
759 * adg_dim_style_set_line_dress:
760 * @dim_style: an #AdgDimStyle object
761 * @dress: the new line dress
763 * Sets a new line dress on @dim_style.
768 adg_dim_style_set_line_dress(AdgDimStyle
*dim_style
, AdgDress dress
)
770 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
771 g_object_set(dim_style
, "line-dress", dress
, NULL
);
775 * adg_dim_style_get_line_dress:
776 * @dim_style: an #AdgDimStyle object
778 * Gets the line dress to be used for rendering the base and
779 * the extension lines with @dim_style.
781 * Returns: (transfer none): the line dress.
786 adg_dim_style_get_line_dress(AdgDimStyle
*dim_style
)
788 AdgDimStylePrivate
*data
;
790 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), ADG_DRESS_UNDEFINED
);
792 data
= dim_style
->data
;
794 return data
->line_dress
;
798 * adg_dim_style_set_from_offset:
799 * @dim_style: an #AdgDimStyle object
800 * @offset: the new offset
802 * Sets a new value in the #AdgDimStyle:from-offset property.
807 adg_dim_style_set_from_offset(AdgDimStyle
*dim_style
, gdouble offset
)
809 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
810 g_object_set(dim_style
, "from-offset", offset
, NULL
);
814 * adg_dim_style_get_from_offset:
815 * @dim_style: an #AdgDimStyle object
817 * Gets the distance (in global space) the extension lines must keep from the
820 * Returns: the requested distance.
825 adg_dim_style_get_from_offset(AdgDimStyle
*dim_style
)
827 AdgDimStylePrivate
*data
;
829 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
831 data
= dim_style
->data
;
833 return data
->from_offset
;
837 * adg_dim_style_set_to_offset:
838 * @dim_style: an #AdgDimStyle object
839 * @offset: the new offset
841 * Sets a new value in the #AdgDimStyle:to-offset property.
846 adg_dim_style_set_to_offset(AdgDimStyle
*dim_style
, gdouble offset
)
848 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
849 g_object_set(dim_style
, "to-offset", offset
, NULL
);
853 * adg_dim_style_get_to_offset:
854 * @dim_style: an #AdgDimStyle object
856 * Gets how much (in global space) the extension lines must extend after
857 * crossing the baseline.
859 * Returns: the requested distance.
864 adg_dim_style_get_to_offset(AdgDimStyle
*dim_style
)
866 AdgDimStylePrivate
*data
;
868 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
870 data
= dim_style
->data
;
872 return data
->to_offset
;
876 * adg_dim_style_set_beyond:
877 * @dim_style: an #AdgDimStyle object
878 * @beyond: the new length
880 * Sets a new value in the #AdgDimStyle:beyond property.
885 adg_dim_style_set_beyond(AdgDimStyle
*dim_style
, gdouble beyond
)
887 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
888 g_object_set(dim_style
, "beyond", beyond
, NULL
);
892 * adg_dim_style_get_beyond:
893 * @dim_style: an #AdgDimStyle object
895 * Gets how much (in global space) the baseline should extend beyond
896 * the extension lines on dimension with outside markers.
898 * Returns: the requested beyond length.
903 adg_dim_style_get_beyond(AdgDimStyle
*dim_style
)
905 AdgDimStylePrivate
*data
;
907 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
909 data
= dim_style
->data
;
915 * adg_dim_style_set_baseline_spacing:
916 * @dim_style: an #AdgDimStyle object
917 * @spacing: the new spacing
919 * Sets a new value in the #AdgDimStyle:baseline-spacing value.
924 adg_dim_style_set_baseline_spacing(AdgDimStyle
*dim_style
, gdouble spacing
)
926 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
927 g_object_set(dim_style
, "baseline-spacing", spacing
, NULL
);
931 * adg_dim_style_get_baseline_spacing:
932 * @dim_style: an #AdgDimStyle object
934 * Gets the distance between two consecutive baselines
935 * while stacking dimensions.
937 * Returns: the requested spacing.
942 adg_dim_style_get_baseline_spacing(AdgDimStyle
*dim_style
)
944 AdgDimStylePrivate
*data
;
946 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
948 data
= dim_style
->data
;
950 return data
->baseline_spacing
;
954 * adg_dim_style_set_limits_spacing:
955 * @dim_style: an #AdgDimStyle object
956 * @spacing: the new spacing
958 * Sets a new #AdgDimStyle:limits-spacing value.
963 adg_dim_style_set_limits_spacing(AdgDimStyle
*dim_style
, gdouble spacing
)
965 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
966 g_object_set(dim_style
, "limits-spacing", spacing
, NULL
);
970 * adg_dim_style_get_limits_spacing:
971 * @dim_style: an #AdgDimStyle object
973 * Gets the distance (in global space) between the limits/tolerances.
975 * Returns: the requested spacing.
980 adg_dim_style_get_limits_spacing(AdgDimStyle
*dim_style
)
982 AdgDimStylePrivate
*data
;
984 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), 0);
986 data
= dim_style
->data
;
988 return data
->limits_spacing
;
992 * adg_dim_style_set_quote_shift:
993 * @dim_style: an #AdgDimStyle object
994 * @shift: the new displacement
996 * Sets a new #AdgDimStyle:quote-shift value.
1001 adg_dim_style_set_quote_shift(AdgDimStyle
*dim_style
, const CpmlPair
*shift
)
1003 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1004 g_object_set(dim_style
, "quote-shift", shift
, NULL
);
1008 * adg_dim_style_get_quote_shift:
1009 * @dim_style: an #AdgDimStyle object
1011 * Gets the smooth displacement of the quote. The returned pointer refers
1012 * to an internal allocated struct and must not be modified or freed.
1014 * Returns: (transfer none): the requested shift.
1019 adg_dim_style_get_quote_shift(AdgDimStyle
*dim_style
)
1021 AdgDimStylePrivate
*data
;
1023 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1025 data
= dim_style
->data
;
1027 return &data
->quote_shift
;
1031 * adg_dim_style_set_limits_shift:
1032 * @dim_style: an #AdgDimStyle object
1033 * @shift: the new displacement
1035 * Sets a new #AdgDimStyle:limits-shift value.
1040 adg_dim_style_set_limits_shift(AdgDimStyle
*dim_style
, const CpmlPair
*shift
)
1042 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1043 g_object_set(dim_style
, "limits-shift", shift
, NULL
);
1047 * adg_dim_style_get_limits_shift:
1048 * @dim_style: an #AdgDimStyle object
1050 * Gets the smooth displacement for the limits. The returned pointer
1051 * refers to an internal allocated struct and must not be modified or freed.
1053 * Returns: (transfer none): the requested shift.
1058 adg_dim_style_get_limits_shift(AdgDimStyle
*dim_style
)
1060 AdgDimStylePrivate
*data
;
1062 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1064 data
= dim_style
->data
;
1066 return &data
->limits_shift
;
1070 * adg_dim_style_set_number_format:
1071 * @dim_style: an #AdgDimStyle object
1072 * @format: the new format to adopt
1074 * Sets a new value in the #AdgDimStyle:number-format property.
1076 * @format is similar to a printf() style format string but only 'e', 'E',
1077 * 'f', 'F', 'g' and 'G' specifiers are allowed. For reference, the
1078 * implementation leverages the g_ascii_formatd() GLib function. If you want
1079 * to use special characters (%"(", %")" and %"%") as literals you need to
1080 * escape them with a backslash.
1082 * You can use round parenthesis to group together one or more % directives
1083 * with other related literals. In that case, when the value bound to the
1084 * directive will be 0, the whole group will disappear. Some example:
1088 * AdgDimStyle *dim_style;
1091 * dim = ADG_DIM(adg_ldim_new());
1092 * dim_style = ADG_DIM_STYLE(adg_entity_style(ADG_ENTITY(dim), ADG_DRESS_DIMENSION));
1094 * adg_dim_style_set_number_arguments(dim_style, "dD");
1095 * adg_dim_style_set_number_format(dim_style, "(%g)( truncated to %g)");
1097 * text = adg_dim_get_text(dim, 1.2);
1098 * g_print("%s\n", text); // Prints "1.2 truncated to 1"
1101 * text = adg_dim_get_text(dim, 0.2);
1102 * g_print("%s\n", text); // Prints "0.2"
1105 * text = adg_dim_get_text(dim, 0);
1106 * g_print("%s\n", text); // Prints ""
1110 * Groups can be nested and can have more than one value, in which case all
1111 * the values contained in a group must be 0 in order to let it disappear.
1112 * This comes in handy for removing trailing 0 fields. A typical example is
1113 * the sexagesimal representation of angles:
1116 * adg_dim_style_set_number_arguments(dim_style, "DMs");
1117 * adg_dim_style_set_number_format(dim_style, "%g°(%g'(%g\"))");
1119 * text = adg_dim_get_text(dim, 1.5);
1120 * g_print("%s\n", text); // Prints "1°30'"
1123 * text = adg_dim_get_text(dim, 2.002777);
1124 * g_print("%s\n", text); // Prints "2°0'10\""
1131 adg_dim_style_set_number_format(AdgDimStyle
*dim_style
, const gchar
*format
)
1133 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1134 g_object_set(dim_style
, "number-format", format
, NULL
);
1138 * adg_dim_style_get_number_format:
1139 * @dim_style: an #AdgDimStyle object
1141 * Gets the number format (in printf style) of this quoting style. The
1142 * returned pointer refers to internally managed text that must not be
1143 * modified or freed.
1145 * Returns: (transfer none): the requested format.
1150 adg_dim_style_get_number_format(AdgDimStyle
*dim_style
)
1152 AdgDimStylePrivate
*data
;
1154 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1156 data
= dim_style
->data
;
1158 return data
->number_format
;
1162 * adg_dim_style_set_number_arguments:
1163 * @dim_style: an #AdgDimStyle object
1164 * @arguments: the arguments to pass to the formatting function
1166 * A string that identifies the arguments to pass to the formatting function.
1167 * See adg_dim_style_convert() to know the allowed character that can be
1168 * included into this string.
1170 * The number of arguments (i.e. the @arguments length) must match the
1171 * #AdgDimStyle:number-format property (i.e. the number of % directives
1172 * included in that property). See adg_dim_style_set_number_format() for more
1173 * technical details and some examples.
1178 adg_dim_style_set_number_arguments(AdgDimStyle
*dim_style
, const gchar
*arguments
)
1180 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1181 g_object_set(dim_style
, "number-arguments", arguments
, NULL
);
1185 * adg_dim_style_get_number_arguments:
1186 * @dim_style: an #AdgDimStyle object
1188 * Gets the arguments used by the formatting function. See
1189 * adg_dim_style_set_number_arguments() for details on what this means.
1191 * Returns: (transfer none): the requested arguments.
1196 adg_dim_style_get_number_arguments(AdgDimStyle
*dim_style
)
1198 AdgDimStylePrivate
*data
;
1200 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1202 data
= dim_style
->data
;
1204 return data
->number_arguments
;
1208 * adg_dim_style_set_number_tag:
1209 * @dim_style: an #AdgDimStyle object
1212 * Sets a new tag in the #AdgDimStyle:number-tag property.
1217 adg_dim_style_set_number_tag(AdgDimStyle
*dim_style
, const gchar
*tag
)
1219 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1220 g_object_set(dim_style
, "number-tag", tag
, NULL
);
1224 * adg_dim_style_get_number_tag:
1225 * @dim_style: an #AdgDimStyle object
1227 * Gets the number tag of @dim_style. This tag will be used while
1228 * generating the set values of the dimensions bound to this style:
1229 * check the #AdgDim:value documentation for further details.
1231 * The returned pointer refers to internally managed text that
1232 * must not be modified or freed.
1234 * Returns: (transfer none): the requested tag.
1239 adg_dim_style_get_number_tag(AdgDimStyle
*dim_style
)
1241 AdgDimStylePrivate
*data
;
1243 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), NULL
);
1245 data
= dim_style
->data
;
1247 return data
->number_tag
;
1251 * adg_dim_style_set_decimals:
1252 * @dim_style: an #AdgDimStyle object
1253 * @decimals: number of significant decimals
1255 * Sets a new value in the #AdgDimStyle:decimals property.
1260 adg_dim_style_set_decimals(AdgDimStyle
*dim_style
, gint decimals
)
1262 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1263 g_object_set(dim_style
, "decimals", decimals
, NULL
);
1267 * adg_dim_style_get_decimals:
1268 * @dim_style: an #AdgDimStyle object
1270 * Gets the decimals the value of a dimension will be rounded to before the
1273 * Returns: the number of significant decimals or -2 on errors.
1278 adg_dim_style_get_decimals(AdgDimStyle
*dim_style
)
1280 AdgDimStylePrivate
*data
;
1282 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), -2);
1284 data
= dim_style
->data
;
1286 return data
->decimals
;
1290 * adg_dim_style_set_rounding:
1291 * @dim_style: an #AdgDimStyle object
1292 * @rounding: number of significant decimals of the raw value
1294 * Sets a new value in the #AdgDimStyle:rounding property.
1299 adg_dim_style_set_rounding(AdgDimStyle
*dim_style
, gint rounding
)
1301 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style
));
1302 g_object_set(dim_style
, "rounding", rounding
, NULL
);
1306 * adg_dim_style_get_rounding:
1307 * @dim_style: an #AdgDimStyle object
1309 * Gets the number of decimals the raw value must be rounded to.
1311 * Returns: the number of significant decimals or -2 on errors.
1316 adg_dim_style_get_rounding(AdgDimStyle
*dim_style
)
1318 AdgDimStylePrivate
*data
;
1320 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), -2);
1322 data
= dim_style
->data
;
1324 return data
->rounding
;
1328 * adg_dim_style_convert:
1329 * @dim_style: an #AdgDimStyle object
1330 * @value: (inout): the value to convert
1331 * @format: the convertion to apply
1333 * Converts @value using the specific @format algorithm and store the
1334 * result in @value itself. If @value is %NULL, nothing is performed.
1336 * In the following the allowed values for @format:
1337 * - 'a': the raw @value, i.e. no conversion is performed;
1338 * - 'i': the raw number of minutes, i.e. the fractional part of @value x 60
1339 * - 'e': the raw number of seconds, i.e. the fractional part of the raw
1340 * number of minutes x 60
1341 * - 'D': the truncated value of the raw value ('a');
1342 * - 'd': the rounded value of the raw value ('a');
1343 * - 'M': the truncated value of the raw number of minutes ('i');
1344 * - 'm': the rounded value of the raw number of minutes ('i');
1345 * - 'S': the truncated value of the raw number of seconds ('e');
1346 * - 's': the rounded value of the raw number of seconds ('e');
1348 * The rounding is done according to the number of decimal specified in
1349 * #AdgDimStyle:decimals.
1351 * Returns: %TRUE if @value has been converted, %FALSE on errors.
1356 adg_dim_style_convert(AdgDimStyle
*dim_style
, gdouble
*value
, gchar format
)
1358 AdgDimStylePrivate
*data
;
1360 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style
), FALSE
);
1362 /* Inout parameter not provided: just return FALSE */
1363 if (value
== NULL
) {
1367 data
= dim_style
->data
;
1369 /* Round the raw value, if requested */
1370 if (data
->rounding
> -1) {
1371 gdouble coefficient
= pow(10, data
->rounding
);
1372 *value
= round(*value
* coefficient
) / coefficient
;
1377 case 'a': /* Raw value */
1380 case 'i': /* Raw minutes */
1381 *value
= (*value
- (gint
) *value
) * 60;
1384 case 'e': /* Raw seconds */
1385 adg_dim_style_convert(dim_style
, value
, 'i');
1386 *value
= (*value
- (gint
) *value
) * 60;
1389 case 'D': /* Truncated value */
1390 *value
= (gint
) *value
;
1393 case 'd': /* Rounded value */
1394 *value
= adg_round(*value
, data
->decimals
);
1397 case 'M': /* Truncated minutes */
1398 adg_dim_style_convert(dim_style
, value
, 'i');
1399 *value
= (gint
) *value
;
1402 case 'm': /* Rounded minutes */
1403 adg_dim_style_convert(dim_style
, value
, 'i');
1404 *value
= adg_round(*value
, data
->decimals
);
1407 case 'S': /* Truncated seconds */
1408 adg_dim_style_convert(dim_style
, value
, 'e');
1409 *value
= (gint
) *value
;
1412 case 's': /* Rounded seconds */
1413 adg_dim_style_convert(dim_style
, value
, 'e');
1414 *value
= adg_round(*value
, data
->decimals
);
1418 g_return_val_if_reached(FALSE
);
1427 _adg_clone(AdgStyle
*style
)
1429 AdgDimStyle
*dim_style
;
1432 dim_style
= (AdgDimStyle
*) adg_object_clone(G_OBJECT(style
));
1434 /* Manually clone the marker because the underlying properties are
1436 marker
= adg_dim_style_marker1_new((AdgDimStyle
*) style
);
1437 adg_dim_style_set_marker1(dim_style
, marker
);
1438 g_object_unref(marker
);
1440 marker
= adg_dim_style_marker2_new((AdgDimStyle
*) style
);
1441 adg_dim_style_set_marker2(dim_style
, marker
);
1442 g_object_unref(marker
);
1444 return (AdgStyle
*) dim_style
;
1448 _adg_apply(AdgStyle
*style
, AdgEntity
*entity
, cairo_t
*cr
)
1450 AdgDimStylePrivate
*data
= ((AdgDimStyle
*) style
)->data
;
1451 adg_entity_apply_dress(entity
, data
->color_dress
, cr
);
1455 _adg_marker_new(const AdgMarkerData
*marker_data
)
1457 if (marker_data
->type
== 0)
1460 return g_object_newv(marker_data
->type
,
1461 marker_data
->n_parameters
,
1462 marker_data
->parameters
);
1466 _adg_set_marker(AdgMarkerData
*marker_data
, AdgMarker
*marker
)
1468 g_return_if_fail(marker
== NULL
|| ADG_IS_MARKER(marker
));
1470 /* Free the previous marker data, if any */
1471 _adg_free_marker(marker_data
);
1477 GParameter
*parameter
;
1480 object
= (GObject
*) marker
;
1481 specs
= g_object_class_list_properties(G_OBJECT_GET_CLASS(marker
),
1482 &marker_data
->n_parameters
);
1484 marker_data
->type
= G_TYPE_FROM_INSTANCE(marker
);
1485 marker_data
->parameters
= g_new0(GParameter
, marker_data
->n_parameters
);
1487 for (n
= 0; n
< marker_data
->n_parameters
; ++n
) {
1489 parameter
= &marker_data
->parameters
[n
];
1491 /* Using intern strings because GParameter:name is const.
1492 * GObject properties are internally managed using non-static
1493 * GQuark, so g_intern_string() is the way to go */
1494 parameter
->name
= g_intern_string(spec
->name
);
1496 g_value_init(¶meter
->value
, spec
->value_type
);
1497 g_object_get_property(object
, spec
->name
, ¶meter
->value
);
1505 _adg_free_marker(AdgMarkerData
*marker_data
)
1509 for (n
= 0; n
< marker_data
->n_parameters
; ++n
)
1510 g_value_unset(&marker_data
->parameters
[n
].value
);
1512 marker_data
->type
= 0;
1513 marker_data
->n_parameters
= 0;
1514 marker_data
->parameters
= NULL
;