diff --git a/src/adg/adg-dim-style-private.h b/src/adg/adg-dim-style-private.h index 8197bf68..4f4001c0 100644 --- a/src/adg/adg-dim-style-private.h +++ b/src/adg/adg-dim-style-private.h @@ -1,61 +1,62 @@ /* ADG - Automatic Drawing Generation * Copyright (C) 2007-2017 Nicola Fontana * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef __ADG_DIM_STYLE_PRIVATE_H__ #define __ADG_DIM_STYLE_PRIVATE_H__ G_BEGIN_DECLS typedef struct _AdgMarkerData AdgMarkerData; typedef struct _AdgDimStylePrivate AdgDimStylePrivate; struct _AdgMarkerData { GType type; guint n_parameters; GParameter *parameters; }; struct _AdgDimStylePrivate { AdgMarkerData marker1; AdgMarkerData marker2; AdgDress color_dress; AdgDress value_dress; AdgDress min_dress; AdgDress max_dress; AdgDress line_dress; AdgDress marker_dress; gdouble from_offset; gdouble to_offset; gdouble beyond; gdouble baseline_spacing; gdouble limits_spacing; CpmlPair quote_shift; CpmlPair limits_shift; gchar *number_format; gchar *number_arguments; gchar *number_tag; gint decimals; + gint rounding; }; G_END_DECLS #endif /* __ADG_DIM_STYLE_PRIVATE_H__ */ diff --git a/src/adg/adg-dim-style.c b/src/adg/adg-dim-style.c index 5766e9f4..d81c196d 100644 --- a/src/adg/adg-dim-style.c +++ b/src/adg/adg-dim-style.c @@ -1,1403 +1,1466 @@ /* ADG - Automatic Drawing Generation * Copyright (C) 2007-2017 Nicola Fontana * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** * SECTION:adg-dim-style * @short_description: Dimension style related stuff * * Contains parameters on how to build dimensions such as the different font * styles (for value and limits), line style, offsets of the various * dimension components etc... * * Since: 1.0 */ /** * AdgDimStyle: * * All fields are private and should not be used directly. * Use its public methods instead. * * Since: 1.0 **/ #include "adg-internal.h" #include "adg-style.h" #include "adg-font-style.h" #include "adg-dash.h" #include "adg-line-style.h" #include "adg-model.h" #include "adg-trail.h" #include "adg-marker.h" #include "adg-dress.h" #include "adg-param-dress.h" #include "adg-dim-style.h" #include "adg-dim-style-private.h" #include +#include #define VALID_FORMATS "aieDdMmSs" G_DEFINE_TYPE(AdgDimStyle, adg_dim_style, ADG_TYPE_STYLE) enum { PROP_0, PROP_MARKER1, PROP_MARKER2, PROP_COLOR_DRESS, PROP_VALUE_DRESS, PROP_MIN_DRESS, PROP_MAX_DRESS, PROP_LINE_DRESS, PROP_FROM_OFFSET, PROP_TO_OFFSET, PROP_BEYOND, PROP_BASELINE_SPACING, PROP_LIMITS_SPACING, PROP_QUOTE_SHIFT, PROP_LIMITS_SHIFT, PROP_NUMBER_FORMAT, PROP_NUMBER_ARGUMENTS, PROP_NUMBER_TAG, - PROP_DECIMALS + PROP_DECIMALS, + PROP_ROUNDING, }; static void _adg_finalize (GObject *object); static void _adg_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void _adg_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static void _adg_apply (AdgStyle *style, AdgEntity *entity, cairo_t *cr); static AdgMarker * _adg_marker_new (const AdgMarkerData *marker_data); static void _adg_set_marker (AdgMarkerData *marker_data, AdgMarker *marker); static void _adg_free_marker (AdgMarkerData *marker_data); static void adg_dim_style_class_init(AdgDimStyleClass *klass) { GObjectClass *gobject_class; AdgStyleClass *style_class; GParamSpec *param; gobject_class = (GObjectClass *) klass; style_class = (AdgStyleClass *) klass; g_type_class_add_private(klass, sizeof(AdgDimStylePrivate)); gobject_class->finalize = _adg_finalize; gobject_class->get_property = _adg_get_property; gobject_class->set_property = _adg_set_property; style_class->apply = _adg_apply; param = g_param_spec_object("marker1", P_("First Marker"), P_("The template entity to use as first marker"), ADG_TYPE_MARKER, G_PARAM_WRITABLE); g_object_class_install_property(gobject_class, PROP_MARKER1, param); param = g_param_spec_object("marker2", P_("Second Marker"), P_("The template entity to use as second marker"), ADG_TYPE_MARKER, G_PARAM_WRITABLE); g_object_class_install_property(gobject_class, PROP_MARKER2, param); param = adg_param_spec_dress("color-dress", P_("Color Dress"), P_("Color dress for the whole dimension"), ADG_DRESS_COLOR_DIMENSION, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_COLOR_DRESS, param); param = adg_param_spec_dress("value-dress", P_("Value Dress"), P_("Font dress for the nominal value of the dimension"), ADG_DRESS_FONT_QUOTE_TEXT, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_VALUE_DRESS, param); param = adg_param_spec_dress("min-dress", P_("Minimum Limit Dress"), P_("Font dress for the lower limit value"), ADG_DRESS_FONT_QUOTE_ANNOTATION, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_MIN_DRESS, param); param = adg_param_spec_dress("max-dress", P_("Maximum Limit Dress"), P_("Font dress for the upper limit value"), ADG_DRESS_FONT_QUOTE_ANNOTATION, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_MAX_DRESS, param); param = adg_param_spec_dress("line-dress", P_("Line Dress"), P_("Line dress for the baseline and the extension lines"), ADG_DRESS_LINE_DIMENSION, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_LINE_DRESS, param); param = g_param_spec_double("from-offset", P_("From Offset"), P_("Offset (in global space) of the extension lines from the path to the quote"), 0, G_MAXDOUBLE, 5, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_FROM_OFFSET, param); param = g_param_spec_double("to-offset", P_("To Offset"), P_("How many extend (in global space) the extension lines after hitting the baseline"), 0, G_MAXDOUBLE, 5, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_TO_OFFSET, param); param = g_param_spec_double("beyond", P_("Beyond Length"), P_("How much the baseline should be extended (in global space) beyond the extension lines on dimensions with outside markers"), 0, G_MAXDOUBLE, 20, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_BEYOND, param); param = g_param_spec_double("baseline-spacing", P_("Baseline Spacing"), P_("Distance between two consecutive baselines while stacking dimensions"), 0, G_MAXDOUBLE, 32, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_BASELINE_SPACING, param); param = g_param_spec_double("limits-spacing", P_("Limits Spacing"), P_("Distance between limits/tolerances"), 0, G_MAXDOUBLE, 2, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_LIMITS_SPACING, param); param = g_param_spec_boxed("quote-shift", P_("Quote Shift"), 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)"), CPML_TYPE_PAIR, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_QUOTE_SHIFT, param); param = g_param_spec_boxed("limits-shift", P_("Limits Shift"), P_("Used to specify a smooth displacement (in global space) for the limits/tolerances by taking as reference the perfect compact position"), CPML_TYPE_PAIR, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_LIMITS_SHIFT, param); param = g_param_spec_string("number-format", P_("Number Format"), P_("The format (in printf style) of the numeric component of the basic value"), "%-.7g", G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_NUMBER_FORMAT, param); param = g_param_spec_string("number-arguments", P_("Number Arguments"), P_("The arguments to pass to the format function: see adg_dim_style_set_number_arguments() for further details"), "d", G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_NUMBER_ARGUMENTS, param); param = g_param_spec_string("number-tag", P_("Number Tag"), P_("The tag to substitute inside the value template string"), "<>", G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_NUMBER_TAG, param); param = g_param_spec_int("decimals", - P_("decimals"), - P_("Number of significant decimals to round the value to (-1 to disable)"), + P_("Rounded Value Decimals"), + P_("Number of significant decimals to use in the format string for rounded values (-1 to disable)"), -1, G_MAXINT, 2, G_PARAM_READWRITE); g_object_class_install_property(gobject_class, PROP_DECIMALS, param); + + param = g_param_spec_int("rounding", + P_("Raw Value Decimals"), + P_("Number of significant decimals the raw value must be rounded to (-1 to disable)"), + -1, G_MAXINT, + 6, + G_PARAM_READWRITE); + g_object_class_install_property(gobject_class, PROP_ROUNDING, param); } static void adg_dim_style_init(AdgDimStyle *dim_style) { AdgDimStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(dim_style, ADG_TYPE_DIM_STYLE, AdgDimStylePrivate); data->marker1.type = 0; data->marker1.n_parameters = 0; data->marker1.parameters = NULL; data->marker2.type = 0; data->marker2.n_parameters = 0; data->marker2.parameters = NULL; data->color_dress = ADG_DRESS_COLOR_DIMENSION; data->value_dress = ADG_DRESS_FONT_QUOTE_TEXT; data->min_dress = ADG_DRESS_FONT_QUOTE_ANNOTATION; data->max_dress = ADG_DRESS_FONT_QUOTE_ANNOTATION; data->line_dress = ADG_DRESS_LINE_DIMENSION; data->marker_dress = ADG_DRESS_UNDEFINED; data->from_offset = 6; data->to_offset = 6; data->beyond = 20; data->baseline_spacing = 32; data->limits_spacing = 0; data->quote_shift.x = 4; data->quote_shift.y = -1; data->limits_shift.x = +2; data->limits_shift.y = +2; data->number_format = g_strdup("%-.7g"); data->number_arguments = g_strdup("d"); data->number_tag = g_strdup("<>"); data->decimals = 2; + data->rounding = 6; dim_style->data = data; } static void _adg_finalize(GObject *object) { AdgDimStylePrivate *data = ((AdgDimStyle *) object)->data; _adg_free_marker(&data->marker1); _adg_free_marker(&data->marker2); g_free(data->number_format); data->number_format = NULL; g_free(data->number_arguments); data->number_arguments = NULL; g_free(data->number_tag); data->number_tag = NULL; } static void _adg_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { AdgDimStylePrivate *data = ((AdgDimStyle *) object)->data; switch (prop_id) { case PROP_COLOR_DRESS: g_value_set_enum(value, data->color_dress); break; case PROP_VALUE_DRESS: g_value_set_enum(value, data->value_dress); break; case PROP_MIN_DRESS: g_value_set_enum(value, data->min_dress); break; case PROP_MAX_DRESS: g_value_set_enum(value, data->max_dress); break; case PROP_LINE_DRESS: g_value_set_enum(value, data->line_dress); break; case PROP_FROM_OFFSET: g_value_set_double(value, data->from_offset); break; case PROP_TO_OFFSET: g_value_set_double(value, data->to_offset); break; case PROP_BEYOND: g_value_set_double(value, data->beyond); break; case PROP_BASELINE_SPACING: g_value_set_double(value, data->baseline_spacing); break; case PROP_LIMITS_SPACING: g_value_set_double(value, data->limits_spacing); break; case PROP_QUOTE_SHIFT: g_value_set_boxed(value, &data->quote_shift); break; case PROP_LIMITS_SHIFT: g_value_set_boxed(value, &data->limits_shift); break; case PROP_NUMBER_FORMAT: g_value_set_string(value, data->number_format); break; case PROP_NUMBER_ARGUMENTS: g_value_set_string(value, data->number_arguments); break; case PROP_NUMBER_TAG: g_value_set_string(value, data->number_tag); break; case PROP_DECIMALS: g_value_set_int(value, data->decimals); break; + case PROP_ROUNDING: + g_value_set_int(value, data->rounding); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } static void _adg_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { AdgDimStyle *dim_style; AdgDimStylePrivate *data; dim_style = (AdgDimStyle *) object; data = dim_style->data; switch (prop_id) { case PROP_MARKER1: _adg_set_marker(&data->marker1, g_value_get_object(value)); break; case PROP_MARKER2: _adg_set_marker(&data->marker2, g_value_get_object(value)); break; case PROP_COLOR_DRESS: data->color_dress = g_value_get_enum(value); break; case PROP_VALUE_DRESS: data->value_dress = g_value_get_enum(value); break; case PROP_MIN_DRESS: data->min_dress = g_value_get_enum(value); break; case PROP_MAX_DRESS: data->max_dress = g_value_get_enum(value); break; case PROP_LINE_DRESS: data->line_dress = g_value_get_enum(value); break; case PROP_FROM_OFFSET: data->from_offset = g_value_get_double(value); break; case PROP_TO_OFFSET: data->to_offset = g_value_get_double(value); break; case PROP_BEYOND: data->beyond = g_value_get_double(value); break; case PROP_BASELINE_SPACING: data->baseline_spacing = g_value_get_double(value); break; case PROP_LIMITS_SPACING: data->limits_spacing = g_value_get_double(value); break; case PROP_QUOTE_SHIFT: cpml_pair_copy(&data->quote_shift, g_value_get_boxed(value)); break; case PROP_LIMITS_SHIFT: cpml_pair_copy(&data->limits_shift, g_value_get_boxed(value)); break; case PROP_NUMBER_FORMAT: g_free(data->number_format); data->number_format = g_value_dup_string(value); break; case PROP_NUMBER_ARGUMENTS: { const gchar *arguments = g_value_get_string(value); g_return_if_fail(arguments == NULL || strspn(arguments, VALID_FORMATS) == strlen(arguments)); g_free(data->number_arguments); data->number_arguments = g_strdup(arguments); break; } case PROP_NUMBER_TAG: g_free(data->number_tag); data->number_tag = g_value_dup_string(value); break; case PROP_DECIMALS: data->decimals = g_value_get_int(value); break; + case PROP_ROUNDING: + data->rounding = g_value_get_int(value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); break; } } /** * adg_dim_style_new: * * Constructs a new empty dimension style initialized with default params. * * Returns: (transfer full): a newly created dimension style. * * Since: 1.0 **/ AdgDimStyle * adg_dim_style_new(void) { return g_object_new(ADG_TYPE_DIM_STYLE, NULL); } /** * adg_dim_style_set_marker1: * @dim_style: an #AdgStyle * @marker: an #AdgMarker derived entity * * Uses @marker as entity template to generate a new marker entity * when a call to adg_dim_style_marker1_new() is made. It is allowed * to pass NULL as @marker, in which case the * template data of the first marker are unset. * * This method duplicates internally the property values of @marker, * so any further change to @marker does not affect @dim_style anymore. * This also means @marker could be destroyed without problems after * this call because @dim_style uses only its property values and does * not add any references to @marker. * * Since: 1.0 **/ void adg_dim_style_set_marker1(AdgDimStyle *dim_style, AdgMarker *marker) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "marker1", marker, NULL); } /** * adg_dim_style_marker1_new: * @dim_style: an #AdgDimStyle * * Creates a new marker entity by cloning the #AdgDimStyle:marker1 * object. The returned entity should be unreferenced with * g_object_unref() when no longer needed. * * Returns: (transfer full): a newly created marker or NULL if the #AdgDimStyle:marker1 property is not set or on errors. * * Since: 1.0 **/ AdgMarker * adg_dim_style_marker1_new(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL); data = dim_style->data; return _adg_marker_new(&data->marker1); } /** * adg_dim_style_set_marker2: * @dim_style: an #AdgStyle * @marker: an #AdgMarker derived entity * * Uses @marker as entity template to generate a new marker entity * when a call to adg_dim_style_marker2_new() is made. It is allowed * to pass NULL as @marker, in which case the * template data of the second marker are unset. * * This method duplicates internally the property values of @marker, * so any further change to @marker does not affect @dim_style anymore. * This also means @marker could be destroyed without problems after * this call because @dim_style uses only its property values and does * not add any references to @marker. * * Since: 1.0 **/ void adg_dim_style_set_marker2(AdgDimStyle *dim_style, AdgMarker *marker) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "marker2", marker, NULL); } /** * adg_dim_style_marker2_new: * @dim_style: an #AdgDimStyle * * Creates a new marker entity by cloning the #AdgDimStyle:marker2 * object. The returned entity should be unreferenced with * g_object_unref() when no longer needed. * * Returns: (transfer full): a newly created marker or NULL if the #AdgDimStyle:marker2 property is not set or on errors. * * Since: 1.0 **/ AdgMarker * adg_dim_style_marker2_new(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL); data = dim_style->data; return _adg_marker_new(&data->marker2); } /** * adg_dim_style_set_color_dress: * @dim_style: an #AdgDimStyle object * @dress: the new color dress * * Sets a new color dress on @dim_style. * * Since: 1.0 **/ void adg_dim_style_set_color_dress(AdgDimStyle *dim_style, AdgDress dress) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "color-dress", dress, NULL); } /** * adg_dim_style_get_color_dress: * @dim_style: an #AdgDimStyle object * * Gets the @dim_style color dress to be used. This dress should be * intended as a fallback color as it could be overriden by more * specific dresses, such as a color explicitely specified on the * #AdgDimStyle:value-dress. * * Returns: (transfer none): the color dress. * * Since: 1.0 **/ AdgDress adg_dim_style_get_color_dress(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED); data = dim_style->data; return data->color_dress; } /** * adg_dim_style_set_value_dress: * @dim_style: an #AdgDimStyle object * @dress: the new basic value font style * * Sets a new dress on @dim_style for the basic value. * * Since: 1.0 **/ void adg_dim_style_set_value_dress(AdgDimStyle *dim_style, AdgDress dress) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "value-dress", dress, NULL); } /** * adg_dim_style_get_value_dress: * @dim_style: an #AdgDimStyle object * * Gets the font dress to be used for the basic value of dimensions * with @dim_style. * * Returns: (transfer none): the font dress. * * Since: 1.0 **/ AdgDress adg_dim_style_get_value_dress(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED); data = dim_style->data; return data->value_dress; } /** * adg_dim_style_set_min_dress: * @dim_style: an #AdgDimStyle object * @dress: the new lower limit dress * * Sets a new dress on @dim_style for the lower limit value. * * Since: 1.0 **/ void adg_dim_style_set_min_dress(AdgDimStyle *dim_style, AdgDress dress) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "min-dress", dress, NULL); } /** * adg_dim_style_get_min_dress: * @dim_style: an #AdgDimStyle object * * Gets the @dim_style dress to be used for the lower limit. * * Returns: (transfer none): the lower limit dress. * * Since: 1.0 **/ AdgDress adg_dim_style_get_min_dress(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED); data = dim_style->data; return data->min_dress; } /** * adg_dim_style_set_max_dress: * @dim_style: an #AdgDimStyle object * @dress: the new upper limit dress * * Sets a new dress on @dim_style for the upper limit value. * * Since: 1.0 **/ void adg_dim_style_set_max_dress(AdgDimStyle *dim_style, AdgDress dress) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "max-dress", dress, NULL); } /** * adg_dim_style_get_max_dress: * @dim_style: an #AdgDimStyle object * * Gets the @dim_style dress to be used for the upper limit. * * Returns: (transfer none): the upper limit dress. * * Since: 1.0 **/ AdgDress adg_dim_style_get_max_dress(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED); data = dim_style->data; return data->max_dress; } /** * adg_dim_style_set_line_dress: * @dim_style: an #AdgDimStyle object * @dress: the new line dress * * Sets a new line dress on @dim_style. * * Since: 1.0 **/ void adg_dim_style_set_line_dress(AdgDimStyle *dim_style, AdgDress dress) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "line-dress", dress, NULL); } /** * adg_dim_style_get_line_dress: * @dim_style: an #AdgDimStyle object * * Gets the line dress to be used for rendering the base and * the extension lines with @dim_style. * * Returns: (transfer none): the line dress. * * Since: 1.0 **/ AdgDress adg_dim_style_get_line_dress(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED); data = dim_style->data; return data->line_dress; } /** * adg_dim_style_set_from_offset: * @dim_style: an #AdgDimStyle object * @offset: the new offset * * Sets a new value in the #AdgDimStyle:from-offset property. * * Since: 1.0 **/ void adg_dim_style_set_from_offset(AdgDimStyle *dim_style, gdouble offset) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "from-offset", offset, NULL); } /** * adg_dim_style_get_from_offset: * @dim_style: an #AdgDimStyle object * * Gets the distance (in global space) the extension lines must keep from the * sensed points. * * Returns: the requested distance. * * Since: 1.0 **/ gdouble adg_dim_style_get_from_offset(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0); data = dim_style->data; return data->from_offset; } /** * adg_dim_style_set_to_offset: * @dim_style: an #AdgDimStyle object * @offset: the new offset * * Sets a new value in the #AdgDimStyle:to-offset property. * * Since: 1.0 **/ void adg_dim_style_set_to_offset(AdgDimStyle *dim_style, gdouble offset) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "to-offset", offset, NULL); } /** * adg_dim_style_get_to_offset: * @dim_style: an #AdgDimStyle object * * Gets how much (in global space) the extension lines must extend after * crossing the baseline. * * Returns: the requested distance. * * Since: 1.0 **/ gdouble adg_dim_style_get_to_offset(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0); data = dim_style->data; return data->to_offset; } /** * adg_dim_style_set_beyond: * @dim_style: an #AdgDimStyle object * @beyond: the new length * * Sets a new value in the #AdgDimStyle:beyond property. * * Since: 1.0 **/ void adg_dim_style_set_beyond(AdgDimStyle *dim_style, gdouble beyond) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "beyond", beyond, NULL); } /** * adg_dim_style_get_beyond: * @dim_style: an #AdgDimStyle object * * Gets how much (in global space) the baseline should extend beyond * the extension lines on dimension with outside markers. * * Returns: the requested beyond length. * * Since: 1.0 **/ gdouble adg_dim_style_get_beyond(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0); data = dim_style->data; return data->beyond; } /** * adg_dim_style_set_baseline_spacing: * @dim_style: an #AdgDimStyle object * @spacing: the new spacing * * Sets a new value in the #AdgDimStyle:baseline-spacing value. * * Since: 1.0 **/ void adg_dim_style_set_baseline_spacing(AdgDimStyle *dim_style, gdouble spacing) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "baseline-spacing", spacing, NULL); } /** * adg_dim_style_get_baseline_spacing: * @dim_style: an #AdgDimStyle object * * Gets the distance between two consecutive baselines * while stacking dimensions. * * Returns: the requested spacing. * * Since: 1.0 **/ gdouble adg_dim_style_get_baseline_spacing(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0); data = dim_style->data; return data->baseline_spacing; } /** * adg_dim_style_set_limits_spacing: * @dim_style: an #AdgDimStyle object * @spacing: the new spacing * * Sets a new #AdgDimStyle:limits-spacing value. * * Since: 1.0 **/ void adg_dim_style_set_limits_spacing(AdgDimStyle *dim_style, gdouble spacing) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "limits-spacing", spacing, NULL); } /** * adg_dim_style_get_limits_spacing: * @dim_style: an #AdgDimStyle object * * Gets the distance (in global space) between the limits/tolerances. * * Returns: the requested spacing. * * Since: 1.0 **/ gdouble adg_dim_style_get_limits_spacing(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0); data = dim_style->data; return data->limits_spacing; } /** * adg_dim_style_set_quote_shift: * @dim_style: an #AdgDimStyle object * @shift: the new displacement * * Sets a new #AdgDimStyle:quote-shift value. * * Since: 1.0 **/ void adg_dim_style_set_quote_shift(AdgDimStyle *dim_style, const CpmlPair *shift) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "quote-shift", shift, NULL); } /** * adg_dim_style_get_quote_shift: * @dim_style: an #AdgDimStyle object * * Gets the smooth displacement of the quote. The returned pointer refers * to an internal allocated struct and must not be modified or freed. * * Returns: (transfer none): the requested shift. * * Since: 1.0 **/ const CpmlPair * adg_dim_style_get_quote_shift(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL); data = dim_style->data; return &data->quote_shift; } /** * adg_dim_style_set_limits_shift: * @dim_style: an #AdgDimStyle object * @shift: the new displacement * * Sets a new #AdgDimStyle:limits-shift value. * * Since: 1.0 **/ void adg_dim_style_set_limits_shift(AdgDimStyle *dim_style, const CpmlPair *shift) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "limits-shift", shift, NULL); } /** * adg_dim_style_get_limits_shift: * @dim_style: an #AdgDimStyle object * * Gets the smooth displacement for the limits. The returned pointer * refers to an internal allocated struct and must not be modified or freed. * * Returns: (transfer none): the requested shift. * * Since: 1.0 **/ const CpmlPair * adg_dim_style_get_limits_shift(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL); data = dim_style->data; return &data->limits_shift; } /** * adg_dim_style_set_number_format: * @dim_style: an #AdgDimStyle object * @format: the new format to adopt * * Sets a new value in the #AdgDimStyle:number-format property. * * @format is similar to a printf() style format string but only 'e', 'E', * 'f', 'F', 'g' and 'G' specifiers are allowed. For reference, the * implementation leverages the g_ascii_formatd() GLib function. If you want * to use special characters (%"(", %")" and %"%") as literals you need to * escape them with a backslash. * * You can use round parenthesis to group together one or more % directives * with other related literals. In that case, when the value bound to the * directive will be 0, the whole group will disappear. Some example: * * |[ * AdgDim *dim; * gchar *text; * * dim = ADG_DIM(adg_ldim_new()); * dim_style = ADG_DIM_STYLE(adg_entity_style(ADG_ENTITY(dim), ADG_DRESS_DIMENSION)); * * adg_dim_style_set_number_arguments(dim_style, "dD"); * adg_dim_style_set_number_format(dim_style, "(%g)( truncated to %g)"); * * text = adg_dim_get_text(dim, 1.2); * g_print("%s\n", text); // Prints "1.2 truncated to 1" * g_free(text); * * text = adg_dim_get_text(dim, 0.2); * g_print("%s\n", text); // Prints "0.2" * g_free(text); * * text = adg_dim_get_text(dim, 0); * g_print("%s\n", text); // Prints "" * g_free(text); * ]| * * Groups can be nested and can have more than one value, in which case all * the values contained in a group must be 0 in order to let it disappear. * This comes in handy for removing trailing 0 fields. A typical example is * the sexagesimal representation of angles: * * |[ * adg_dim_style_set_number_arguments(dim_style, "DMs"); * adg_dim_style_set_number_format(dim_style, "%g°(%g'(%g\"))"); * * text = adg_dim_get_text(dim, 1.5); * g_print("%s\n", text); // Prints "1°30'" * g_free(text); * * text = adg_dim_get_text(dim, 2.002777); * g_print("%s\n", text); // Prints "2°0'10\"" * g_free(text); * ]| * * Since: 1.0 **/ void adg_dim_style_set_number_format(AdgDimStyle *dim_style, const gchar *format) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "number-format", format, NULL); } /** * adg_dim_style_get_number_format: * @dim_style: an #AdgDimStyle object * * Gets the number format (in printf style) of this quoting style. The * returned pointer refers to internally managed text that must not be * modified or freed. * * Returns: (transfer none): the requested format. * * Since: 1.0 **/ const gchar * adg_dim_style_get_number_format(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL); data = dim_style->data; return data->number_format; } /** * adg_dim_style_set_number_arguments: * @dim_style: an #AdgDimStyle object * @arguments: the arguments to pass to the formatting function * * A string that identifies the arguments to pass to the formatting function. * See adg_dim_style_convert() to know the allowed character that can be * included into this string. * * The number of arguments (i.e. the @arguments length) must match the * #AdgDimStyle:number-format property (i.e. the number of % directives * included in that property). See adg_dim_style_set_number_format() for more * technical details and some examples. * * Since: 1.0 **/ void adg_dim_style_set_number_arguments(AdgDimStyle *dim_style, const gchar *arguments) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "number-arguments", arguments, NULL); } /** * adg_dim_style_get_number_arguments: * @dim_style: an #AdgDimStyle object * * Gets the arguments used by the formatting function. See * adg_dim_style_set_number_arguments() for details on what this means. * * Returns: (transfer none): the requested arguments. * * Since: 1.0 **/ const gchar * adg_dim_style_get_number_arguments(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL); data = dim_style->data; return data->number_arguments; } /** * adg_dim_style_set_number_tag: * @dim_style: an #AdgDimStyle object * @tag: the new tag * * Sets a new tag in the #AdgDimStyle:number-tag property. * * Since: 1.0 **/ void adg_dim_style_set_number_tag(AdgDimStyle *dim_style, const gchar *tag) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "number-tag", tag, NULL); } /** * adg_dim_style_get_number_tag: * @dim_style: an #AdgDimStyle object * * Gets the number tag of @dim_style. This tag will be used while * generating the set values of the dimensions bound to this style: * check the #AdgDim:value documentation for further details. * * The returned pointer refers to internally managed text that * must not be modified or freed. * * Returns: (transfer none): the requested tag. * * Since: 1.0 **/ const gchar * adg_dim_style_get_number_tag(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL); data = dim_style->data; return data->number_tag; } /** * adg_dim_style_set_decimals: * @dim_style: an #AdgDimStyle object * @decimals: number of significant decimals * * Sets a new value in the #AdgDimStyle:decimals property. * * Since: 1.0 **/ void adg_dim_style_set_decimals(AdgDimStyle *dim_style, gint decimals) { g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); g_object_set(dim_style, "decimals", decimals, NULL); } /** * adg_dim_style_get_decimals: * @dim_style: an #AdgDimStyle object * * Gets the decimals the value of a dimension will be rounded to before the * rendering. * * Returns: the number of significant decimals or -2 on errors. * * Since: 1.0 **/ gint adg_dim_style_get_decimals(AdgDimStyle *dim_style) { AdgDimStylePrivate *data; g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), -2); data = dim_style->data; return data->decimals; } /** + * adg_dim_style_set_rounding: + * @dim_style: an #AdgDimStyle object + * @rounding: number of significant decimals of the raw value + * + * Sets a new value in the #AdgDimStyle:rounding property. + * + * Since: 1.0 + **/ +void +adg_dim_style_set_rounding(AdgDimStyle *dim_style, gint rounding) +{ + g_return_if_fail(ADG_IS_DIM_STYLE(dim_style)); + g_object_set(dim_style, "rounding", rounding, NULL); +} + +/** + * adg_dim_style_get_rounding: + * @dim_style: an #AdgDimStyle object + * + * Gets the number of decimals the raw value must be rounded to. + * + * Returns: the number of significant decimals or -2 on errors. + * + * Since: 1.0 + **/ +gint +adg_dim_style_get_rounding(AdgDimStyle *dim_style) +{ + AdgDimStylePrivate *data; + + g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), -2); + + data = dim_style->data; + + return data->rounding; +} + +/** * adg_dim_style_convert: * @dim_style: an #AdgDimStyle object * @value: (inout): the value to convert * @format: the convertion to apply * * Converts @value using the specific @format algorithm and store the * result in @value itself. If @value is %NULL, nothing is performed. * * In the following the allowed values for @format: * - 'a': the raw @value, i.e. no conversion is performed; * - 'i': the raw number of minutes, i.e. the fractional part of @value x 60 * - 'e': the raw number of seconds, i.e. the fractional part of the raw * number of minutes x 60 * - 'D': the truncated value of the raw value ('a'); * - 'd': the rounded value of the raw value ('a'); * - 'M': the truncated value of the raw number of minutes ('i'); * - 'm': the rounded value of the raw number of minutes ('i'); * - 'S': the truncated value of the raw number of seconds ('e'); * - 's': the rounded value of the raw number of seconds ('e'); * * The rounding is done according to the number of decimal specified in * #AdgDimStyle:decimals. * * Returns: %TRUE if @value has been converted, %FALSE on errors. * * Since: 1.0 **/ gboolean adg_dim_style_convert(AdgDimStyle *dim_style, gdouble *value, gchar format) { + AdgDimStylePrivate *data; + g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), FALSE); /* Inout parameter not provided: just return FALSE */ if (value == NULL) { return FALSE; } - g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), FALSE); + data = dim_style->data; + + /* Round the raw value, if requested */ + if (data->rounding > -1) { + gdouble coefficient = pow(10, data->rounding); + *value = round(*value * coefficient) / coefficient; + } switch (format) { case 'a': /* Raw value */ break; case 'i': /* Raw minutes */ *value = (*value - (gint) *value) * 60; break; case 'e': /* Raw seconds */ adg_dim_style_convert(dim_style, value, 'i'); *value = (*value - (gint) *value) * 60; break; case 'D': /* Truncated value */ *value = (gint) *value; break; case 'd': /* Rounded value */ - *value = adg_round(*value, adg_dim_style_get_decimals(dim_style)); + *value = adg_round(*value, data->decimals); break; case 'M': /* Truncated minutes */ adg_dim_style_convert(dim_style, value, 'i'); *value = (gint) *value; break; case 'm': /* Rounded minutes */ adg_dim_style_convert(dim_style, value, 'i'); - *value = adg_round(*value, adg_dim_style_get_decimals(dim_style)); + *value = adg_round(*value, data->decimals); break; case 'S': /* Truncated seconds */ adg_dim_style_convert(dim_style, value, 'e'); *value = (gint) *value; break; case 's': /* Rounded seconds */ adg_dim_style_convert(dim_style, value, 'e'); - *value = adg_round(*value, adg_dim_style_get_decimals(dim_style)); + *value = adg_round(*value, data->decimals); break; default: g_return_val_if_reached(FALSE); return FALSE; } return TRUE; } static void _adg_apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr) { AdgDimStylePrivate *data = ((AdgDimStyle *) style)->data; adg_entity_apply_dress(entity, data->color_dress, cr); } static AdgMarker * _adg_marker_new(const AdgMarkerData *marker_data) { if (marker_data->type == 0) return NULL; return g_object_newv(marker_data->type, marker_data->n_parameters, marker_data->parameters); } static void _adg_set_marker(AdgMarkerData *marker_data, AdgMarker *marker) { g_return_if_fail(marker == NULL || ADG_IS_MARKER(marker)); /* Free the previous marker data, if any */ _adg_free_marker(marker_data); if (marker) { GObject *object; GParamSpec **specs; GParamSpec *spec; GParameter *parameter; guint n; object = (GObject *) marker; specs = g_object_class_list_properties(G_OBJECT_GET_CLASS(marker), &marker_data->n_parameters); marker_data->type = G_TYPE_FROM_INSTANCE(marker); marker_data->parameters = g_new0(GParameter, marker_data->n_parameters); for (n = 0; n < marker_data->n_parameters; ++n) { spec = specs[n]; parameter = &marker_data->parameters[n]; /* Using intern strings because GParameter:name is const. * GObject properties are internally managed using non-static * GQuark, so g_intern_string() is the way to go */ parameter->name = g_intern_string(spec->name); g_value_init(¶meter->value, spec->value_type); g_object_get_property(object, spec->name, ¶meter->value); } g_free(specs); } } static void _adg_free_marker(AdgMarkerData *marker_data) { guint n; for (n = 0; n < marker_data->n_parameters; ++n) g_value_unset(&marker_data->parameters[n].value); marker_data->type = 0; marker_data->n_parameters = 0; marker_data->parameters = NULL; } diff --git a/src/adg/adg-dim-style.h b/src/adg/adg-dim-style.h index 9e881d22..e551dadd 100644 --- a/src/adg/adg-dim-style.h +++ b/src/adg/adg-dim-style.h @@ -1,122 +1,125 @@ /* ADG - Automatic Drawing Generation * Copyright (C) 2007-2017 Nicola Fontana * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #if !defined(__ADG_H__) #error "Only can be included directly." #endif #ifndef __ADG_DIM_STYLE_H__ #define __ADG_DIM_STYLE_H__ G_BEGIN_DECLS #define ADG_TYPE_DIM_STYLE (adg_dim_style_get_type()) #define ADG_DIM_STYLE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), ADG_TYPE_DIM_STYLE, AdgDimStyle)) #define ADG_DIM_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), ADG_TYPE_DIM_STYLE, AdgDimStyleClass)) #define ADG_IS_DIM_STYLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), ADG_TYPE_DIM_STYLE)) #define ADG_IS_DIM_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), ADG_TYPE_DIM_STYLE)) #define ADG_DIM_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), ADG_TYPE_DIM_STYLE, AdgDimStyleClass)) typedef struct _AdgDimStyle AdgDimStyle; typedef struct _AdgDimStyleClass AdgDimStyleClass; struct _AdgDimStyle { /*< private >*/ AdgStyle parent; gpointer data; }; struct _AdgDimStyleClass { /*< private >*/ AdgStyleClass parent_class; }; GType adg_dim_style_get_type (void); AdgDimStyle * adg_dim_style_new (void); void adg_dim_style_set_marker1 (AdgDimStyle *dim_style, AdgMarker *marker); AdgMarker * adg_dim_style_marker1_new (AdgDimStyle *dim_style); void adg_dim_style_set_marker2 (AdgDimStyle *dim_style, AdgMarker *marker); AdgMarker * adg_dim_style_marker2_new (AdgDimStyle *dim_style); void adg_dim_style_set_color_dress (AdgDimStyle *dim_style, AdgDress dress); AdgDress adg_dim_style_get_color_dress (AdgDimStyle *dim_style); void adg_dim_style_set_value_dress (AdgDimStyle *dim_style, AdgDress dress); AdgDress adg_dim_style_get_value_dress (AdgDimStyle *dim_style); void adg_dim_style_set_min_dress (AdgDimStyle *dim_style, AdgDress dress); AdgDress adg_dim_style_get_min_dress (AdgDimStyle *dim_style); void adg_dim_style_set_max_dress (AdgDimStyle *dim_style, AdgDress dress); AdgDress adg_dim_style_get_max_dress (AdgDimStyle *dim_style); void adg_dim_style_set_line_dress (AdgDimStyle *dim_style, AdgDress dress); AdgDress adg_dim_style_get_line_dress (AdgDimStyle *dim_style); void adg_dim_style_set_from_offset (AdgDimStyle *dim_style, gdouble offset); gdouble adg_dim_style_get_from_offset (AdgDimStyle *dim_style); void adg_dim_style_set_to_offset (AdgDimStyle *dim_style, gdouble offset); gdouble adg_dim_style_get_to_offset (AdgDimStyle *dim_style); void adg_dim_style_set_beyond (AdgDimStyle *dim_style, gdouble beyond); gdouble adg_dim_style_get_beyond (AdgDimStyle *dim_style); void adg_dim_style_set_baseline_spacing (AdgDimStyle *dim_style, gdouble spacing); gdouble adg_dim_style_get_baseline_spacing (AdgDimStyle *dim_style); void adg_dim_style_set_limits_spacing(AdgDimStyle *dim_style, gdouble spacing); gdouble adg_dim_style_get_limits_spacing(AdgDimStyle *dim_style); void adg_dim_style_set_quote_shift (AdgDimStyle *dim_style, const CpmlPair *shift); const CpmlPair *adg_dim_style_get_quote_shift (AdgDimStyle *dim_style); void adg_dim_style_set_limits_shift (AdgDimStyle *dim_style, const CpmlPair *shift); const CpmlPair *adg_dim_style_get_limits_shift (AdgDimStyle *dim_style); void adg_dim_style_set_number_format (AdgDimStyle *dim_style, const gchar *format); const gchar * adg_dim_style_get_number_format (AdgDimStyle *dim_style); void adg_dim_style_set_number_arguments (AdgDimStyle *dim_style, const gchar *arguments); const gchar * adg_dim_style_get_number_arguments (AdgDimStyle *dim_style); void adg_dim_style_set_number_tag (AdgDimStyle *dim_style, const gchar *tag); const gchar * adg_dim_style_get_number_tag (AdgDimStyle *dim_style); void adg_dim_style_set_decimals (AdgDimStyle *dim_style, gint decimals); gint adg_dim_style_get_decimals (AdgDimStyle *dim_style); +void adg_dim_style_set_rounding (AdgDimStyle *dim_style, + gint rounding); +gint adg_dim_style_get_rounding (AdgDimStyle *dim_style); gboolean adg_dim_style_convert (AdgDimStyle *dim_style, gdouble *value, gchar format); G_END_DECLS #endif /* __ADG_DIM_STYLE_H__ */ diff --git a/src/adg/tests/test-dim-style.c b/src/adg/tests/test-dim-style.c index 4a0ae587..a0f9c5e5 100644 --- a/src/adg/tests/test-dim-style.c +++ b/src/adg/tests/test-dim-style.c @@ -1,913 +1,974 @@ /* ADG - Automatic Drawing Generation * Copyright (C) 2007-2017 Nicola Fontana * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include #include static void _adg_property_baseline_spacing(void) { AdgDimStyle *dim_style; gdouble valid_baseline_spacing_1, valid_baseline_spacing_2, invalid_baseline_spacing; gdouble baseline_spacing; dim_style = adg_dim_style_new(); valid_baseline_spacing_1 = 0; valid_baseline_spacing_2 = 999; invalid_baseline_spacing = -1; /* Using the public APIs */ adg_dim_style_set_baseline_spacing(dim_style, valid_baseline_spacing_1); baseline_spacing = adg_dim_style_get_baseline_spacing(dim_style); adg_assert_isapprox(baseline_spacing, valid_baseline_spacing_1); adg_dim_style_set_baseline_spacing(dim_style, invalid_baseline_spacing); baseline_spacing = adg_dim_style_get_baseline_spacing(dim_style); adg_assert_isapprox(baseline_spacing, valid_baseline_spacing_1); adg_dim_style_set_baseline_spacing(dim_style, valid_baseline_spacing_2); baseline_spacing = adg_dim_style_get_baseline_spacing(dim_style); adg_assert_isapprox(baseline_spacing, valid_baseline_spacing_2); /* Using GObject property methods */ g_object_set(dim_style, "baseline-spacing", valid_baseline_spacing_1, NULL); g_object_get(dim_style, "baseline-spacing", &baseline_spacing, NULL); adg_assert_isapprox(baseline_spacing, valid_baseline_spacing_1); g_object_set(dim_style, "baseline-spacing", invalid_baseline_spacing, NULL); g_object_get(dim_style, "baseline-spacing", &baseline_spacing, NULL); adg_assert_isapprox(baseline_spacing, valid_baseline_spacing_1); g_object_set(dim_style, "baseline-spacing", valid_baseline_spacing_2, NULL); g_object_get(dim_style, "baseline-spacing", &baseline_spacing, NULL); adg_assert_isapprox(baseline_spacing, valid_baseline_spacing_2); g_object_unref(dim_style); } static void _adg_property_beyond(void) { AdgDimStyle *dim_style; gdouble valid_beyond_1, valid_beyond_2, invalid_beyond; gdouble beyond; dim_style = adg_dim_style_new(); valid_beyond_1 = 0; valid_beyond_2 = 999; invalid_beyond = -1; /* Using the public APIs */ adg_dim_style_set_beyond(dim_style, valid_beyond_1); beyond = adg_dim_style_get_beyond(dim_style); adg_assert_isapprox(beyond, valid_beyond_1); adg_dim_style_set_beyond(dim_style, invalid_beyond); beyond = adg_dim_style_get_beyond(dim_style); adg_assert_isapprox(beyond, valid_beyond_1); adg_dim_style_set_beyond(dim_style, valid_beyond_2); beyond = adg_dim_style_get_beyond(dim_style); adg_assert_isapprox(beyond, valid_beyond_2); /* Using GObject property methods */ g_object_set(dim_style, "beyond", valid_beyond_1, NULL); g_object_get(dim_style, "beyond", &beyond, NULL); adg_assert_isapprox(beyond, valid_beyond_1); g_object_set(dim_style, "beyond", invalid_beyond, NULL); g_object_get(dim_style, "beyond", &beyond, NULL); adg_assert_isapprox(beyond, valid_beyond_1); g_object_set(dim_style, "beyond", valid_beyond_2, NULL); g_object_get(dim_style, "beyond", &beyond, NULL); adg_assert_isapprox(beyond, valid_beyond_2); g_object_unref(dim_style); } static void _adg_property_color_dress(void) { AdgDimStyle *dim_style; AdgDress valid_dress_1, valid_dress_2, incompatible_dress; AdgDress color_dress; dim_style = adg_dim_style_new(); valid_dress_1 = ADG_DRESS_COLOR_ANNOTATION; valid_dress_2 = ADG_DRESS_COLOR; incompatible_dress = ADG_DRESS_FONT; /* Using the public APIs */ adg_dim_style_set_color_dress(dim_style, valid_dress_1); color_dress = adg_dim_style_get_color_dress(dim_style); g_assert_cmpint(color_dress, ==, valid_dress_1); adg_dim_style_set_color_dress(dim_style, incompatible_dress); color_dress = adg_dim_style_get_color_dress(dim_style); g_assert_cmpint(color_dress, ==, valid_dress_1); adg_dim_style_set_color_dress(dim_style, valid_dress_2); color_dress = adg_dim_style_get_color_dress(dim_style); g_assert_cmpint(color_dress, ==, valid_dress_2); /* Using GObject property methods */ g_object_set(dim_style, "color-dress", valid_dress_1, NULL); g_object_get(dim_style, "color-dress", &color_dress, NULL); g_assert_cmpint(color_dress, ==, valid_dress_1); g_object_set(dim_style, "color-dress", incompatible_dress, NULL); g_object_get(dim_style, "color-dress", &color_dress, NULL); g_assert_cmpint(color_dress, ==, valid_dress_1); g_object_set(dim_style, "color-dress", valid_dress_2, NULL); g_object_get(dim_style, "color-dress", &color_dress, NULL); g_assert_cmpint(color_dress, ==, valid_dress_2); g_object_unref(dim_style); } static void _adg_property_from_offset(void) { AdgDimStyle *dim_style; gdouble valid_from_offset_1, valid_from_offset_2, invalid_from_offset; gdouble from_offset; dim_style = adg_dim_style_new(); valid_from_offset_1 = 0; valid_from_offset_2 = 999; invalid_from_offset = -1; /* Using the public APIs */ adg_dim_style_set_from_offset(dim_style, valid_from_offset_1); from_offset = adg_dim_style_get_from_offset(dim_style); adg_assert_isapprox(from_offset, valid_from_offset_1); adg_dim_style_set_from_offset(dim_style, invalid_from_offset); from_offset = adg_dim_style_get_from_offset(dim_style); adg_assert_isapprox(from_offset, valid_from_offset_1); adg_dim_style_set_from_offset(dim_style, valid_from_offset_2); from_offset = adg_dim_style_get_from_offset(dim_style); adg_assert_isapprox(from_offset, valid_from_offset_2); /* Using GObject property methods */ g_object_set(dim_style, "from-offset", valid_from_offset_1, NULL); g_object_get(dim_style, "from-offset", &from_offset, NULL); adg_assert_isapprox(from_offset, valid_from_offset_1); g_object_set(dim_style, "from-offset", invalid_from_offset, NULL); g_object_get(dim_style, "from-offset", &from_offset, NULL); adg_assert_isapprox(from_offset, valid_from_offset_1); g_object_set(dim_style, "from-offset", valid_from_offset_2, NULL); g_object_get(dim_style, "from-offset", &from_offset, NULL); adg_assert_isapprox(from_offset, valid_from_offset_2); g_object_unref(dim_style); } static void _adg_property_limits_shift(void) { AdgDimStyle *dim_style; CpmlPair null_shift, identity_shift; const CpmlPair *shift; CpmlPair *shift_dup; dim_style = adg_dim_style_new(); null_shift.x = 0; null_shift.y = 0; identity_shift.x = 1; identity_shift.y = 1; /* Using the public APIs */ adg_dim_style_set_limits_shift(dim_style, &identity_shift); shift = adg_dim_style_get_limits_shift(dim_style); g_assert_true(cpml_pair_equal(shift, &identity_shift)); adg_dim_style_set_limits_shift(dim_style, &null_shift); shift = adg_dim_style_get_limits_shift(dim_style); g_assert_true(cpml_pair_equal(shift, &null_shift)); adg_dim_style_set_limits_shift(dim_style, NULL); shift = adg_dim_style_get_limits_shift(dim_style); g_assert_true(cpml_pair_equal(shift, &null_shift)); /* Using GObject property methods */ g_object_set(dim_style, "limits-shift", &identity_shift, NULL); g_object_get(dim_style, "limits-shift", &shift_dup, NULL); g_assert_true(cpml_pair_equal(shift_dup, &identity_shift)); g_free(shift_dup); g_object_set(dim_style, "limits-shift", NULL, NULL); g_object_get(dim_style, "limits-shift", &shift_dup, NULL); g_assert_true(cpml_pair_equal(shift_dup, &identity_shift)); g_free(shift_dup); g_object_set(dim_style, "limits-shift", &null_shift, NULL); g_object_get(dim_style, "limits-shift", &shift_dup, NULL); g_assert_true(cpml_pair_equal(shift_dup, &null_shift)); g_free(shift_dup); g_object_unref(dim_style); } static void _adg_property_limits_spacing(void) { AdgDimStyle *dim_style; gdouble valid_limits_spacing_1, valid_limits_spacing_2, invalid_limits_spacing; gdouble limits_spacing; dim_style = adg_dim_style_new(); valid_limits_spacing_1 = 0; valid_limits_spacing_2 = 999; invalid_limits_spacing = -1; /* Using the public APIs */ adg_dim_style_set_limits_spacing(dim_style, valid_limits_spacing_1); limits_spacing = adg_dim_style_get_limits_spacing(dim_style); adg_assert_isapprox(limits_spacing, valid_limits_spacing_1); adg_dim_style_set_limits_spacing(dim_style, invalid_limits_spacing); limits_spacing = adg_dim_style_get_limits_spacing(dim_style); adg_assert_isapprox(limits_spacing, valid_limits_spacing_1); adg_dim_style_set_limits_spacing(dim_style, valid_limits_spacing_2); limits_spacing = adg_dim_style_get_limits_spacing(dim_style); adg_assert_isapprox(limits_spacing, valid_limits_spacing_2); /* Using GObject property methods */ g_object_set(dim_style, "limits-spacing", valid_limits_spacing_1, NULL); g_object_get(dim_style, "limits-spacing", &limits_spacing, NULL); adg_assert_isapprox(limits_spacing, valid_limits_spacing_1); g_object_set(dim_style, "limits-spacing", invalid_limits_spacing, NULL); g_object_get(dim_style, "limits-spacing", &limits_spacing, NULL); adg_assert_isapprox(limits_spacing, valid_limits_spacing_1); g_object_set(dim_style, "limits-spacing", valid_limits_spacing_2, NULL); g_object_get(dim_style, "limits-spacing", &limits_spacing, NULL); adg_assert_isapprox(limits_spacing, valid_limits_spacing_2); g_object_unref(dim_style); } static void _adg_property_line_dress(void) { AdgDimStyle *dim_style; AdgDress valid_dress_1, valid_dress_2, incompatible_dress; AdgDress line_dress; dim_style = adg_dim_style_new(); valid_dress_1 = ADG_DRESS_LINE_FILL; valid_dress_2 = ADG_DRESS_LINE; incompatible_dress = ADG_DRESS_COLOR; /* Using the public APIs */ adg_dim_style_set_line_dress(dim_style, valid_dress_1); line_dress = adg_dim_style_get_line_dress(dim_style); g_assert_cmpint(line_dress, ==, valid_dress_1); adg_dim_style_set_line_dress(dim_style, incompatible_dress); line_dress = adg_dim_style_get_line_dress(dim_style); g_assert_cmpint(line_dress, ==, valid_dress_1); adg_dim_style_set_line_dress(dim_style, valid_dress_2); line_dress = adg_dim_style_get_line_dress(dim_style); g_assert_cmpint(line_dress, ==, valid_dress_2); /* Using GObject property methods */ g_object_set(dim_style, "line-dress", valid_dress_1, NULL); g_object_get(dim_style, "line-dress", &line_dress, NULL); g_assert_cmpint(line_dress, ==, valid_dress_1); g_object_set(dim_style, "line-dress", incompatible_dress, NULL); g_object_get(dim_style, "line-dress", &line_dress, NULL); g_assert_cmpint(line_dress, ==, valid_dress_1); g_object_set(dim_style, "line-dress", valid_dress_2, NULL); g_object_get(dim_style, "line-dress", &line_dress, NULL); g_assert_cmpint(line_dress, ==, valid_dress_2); g_object_unref(dim_style); } static void _adg_property_marker1(void) { AdgDimStyle *dim_style; AdgMarker *valid_marker, *invalid_marker, *marker; dim_style = adg_dim_style_new(); valid_marker = ADG_MARKER(adg_arrow_new()); invalid_marker = adg_test_invalid_pointer(); /* Using the public APIs */ adg_dim_style_set_marker1(dim_style, valid_marker); marker = adg_dim_style_marker1_new(dim_style); g_assert_nonnull(marker); adg_entity_destroy(ADG_ENTITY(marker)); adg_dim_style_set_marker1(dim_style, invalid_marker); marker = adg_dim_style_marker1_new(dim_style); g_assert_nonnull(marker); adg_entity_destroy(ADG_ENTITY(marker)); adg_dim_style_set_marker1(dim_style, NULL); marker = adg_dim_style_marker1_new(dim_style); g_assert_null(marker); /* Using GObject property methods */ g_object_set(dim_style, "marker1", valid_marker, NULL); marker = adg_dim_style_marker1_new(dim_style); g_assert_nonnull(marker); adg_entity_destroy(ADG_ENTITY(marker)); g_object_set(dim_style, "marker1", invalid_marker, NULL); marker = adg_dim_style_marker1_new(dim_style); g_assert_nonnull(marker); adg_entity_destroy(ADG_ENTITY(marker)); g_object_set(dim_style, "marker1", NULL, NULL); marker = adg_dim_style_marker1_new(dim_style); g_assert_null(marker); g_object_unref(dim_style); adg_entity_destroy(ADG_ENTITY(valid_marker)); } static void _adg_property_marker2(void) { AdgDimStyle *dim_style; AdgMarker *valid_marker, *invalid_marker, *marker; dim_style = adg_dim_style_new(); valid_marker = ADG_MARKER(adg_arrow_new()); invalid_marker = adg_test_invalid_pointer(); /* Using the public APIs */ adg_dim_style_set_marker2(dim_style, valid_marker); marker = adg_dim_style_marker2_new(dim_style); g_assert_nonnull(marker); adg_entity_destroy(ADG_ENTITY(marker)); adg_dim_style_set_marker2(dim_style, invalid_marker); marker = adg_dim_style_marker2_new(dim_style); g_assert_nonnull(marker); adg_entity_destroy(ADG_ENTITY(marker)); adg_dim_style_set_marker2(dim_style, NULL); marker = adg_dim_style_marker2_new(dim_style); g_assert_null(marker); /* Using GObject property methods */ g_object_set(dim_style, "marker2", valid_marker, NULL); marker = adg_dim_style_marker2_new(dim_style); g_assert_nonnull(marker); adg_entity_destroy(ADG_ENTITY(marker)); g_object_set(dim_style, "marker2", invalid_marker, NULL); marker = adg_dim_style_marker2_new(dim_style); g_assert_nonnull(marker); adg_entity_destroy(ADG_ENTITY(marker)); g_object_set(dim_style, "marker2", NULL, NULL); marker = adg_dim_style_marker2_new(dim_style); g_assert_null(marker); g_object_unref(dim_style); adg_entity_destroy(ADG_ENTITY(valid_marker)); } static void _adg_property_max_dress(void) { AdgDimStyle *dim_style; AdgDress valid_dress_1, valid_dress_2, incompatible_dress; AdgDress max_dress; dim_style = adg_dim_style_new(); valid_dress_1 = ADG_DRESS_FONT_QUOTE_ANNOTATION; valid_dress_2 = ADG_DRESS_FONT_ANNOTATION; incompatible_dress = ADG_DRESS_FILL_HATCH; /* Using the public APIs */ adg_dim_style_set_max_dress(dim_style, valid_dress_1); max_dress = adg_dim_style_get_max_dress(dim_style); g_assert_cmpint(max_dress, ==, valid_dress_1); adg_dim_style_set_max_dress(dim_style, incompatible_dress); max_dress = adg_dim_style_get_max_dress(dim_style); g_assert_cmpint(max_dress, ==, valid_dress_1); adg_dim_style_set_max_dress(dim_style, valid_dress_2); max_dress = adg_dim_style_get_max_dress(dim_style); g_assert_cmpint(max_dress, ==, valid_dress_2); /* Using GObject property methods */ g_object_set(dim_style, "max-dress", valid_dress_1, NULL); g_object_get(dim_style, "max-dress", &max_dress, NULL); g_assert_cmpint(max_dress, ==, valid_dress_1); g_object_set(dim_style, "max-dress", incompatible_dress, NULL); g_object_get(dim_style, "max-dress", &max_dress, NULL); g_assert_cmpint(max_dress, ==, valid_dress_1); g_object_set(dim_style, "max-dress", valid_dress_2, NULL); g_object_get(dim_style, "max-dress", &max_dress, NULL); g_assert_cmpint(max_dress, ==, valid_dress_2); g_object_unref(dim_style); } static void _adg_property_min_dress(void) { AdgDimStyle *dim_style; AdgDress valid_dress_1, valid_dress_2, incompatible_dress; AdgDress min_dress; dim_style = adg_dim_style_new(); valid_dress_1 = ADG_DRESS_FONT_QUOTE_TEXT; valid_dress_2 = ADG_DRESS_FONT_QUOTE_ANNOTATION; incompatible_dress = ADG_DRESS_FILL_HATCH; /* Using the public APIs */ adg_dim_style_set_min_dress(dim_style, valid_dress_1); min_dress = adg_dim_style_get_min_dress(dim_style); g_assert_cmpint(min_dress, ==, valid_dress_1); adg_dim_style_set_min_dress(dim_style, incompatible_dress); min_dress = adg_dim_style_get_min_dress(dim_style); g_assert_cmpint(min_dress, ==, valid_dress_1); adg_dim_style_set_min_dress(dim_style, valid_dress_2); min_dress = adg_dim_style_get_min_dress(dim_style); g_assert_cmpint(min_dress, ==, valid_dress_2); /* Using GObject property methods */ g_object_set(dim_style, "min-dress", valid_dress_1, NULL); g_object_get(dim_style, "min-dress", &min_dress, NULL); g_assert_cmpint(min_dress, ==, valid_dress_1); g_object_set(dim_style, "min-dress", incompatible_dress, NULL); g_object_get(dim_style, "min-dress", &min_dress, NULL); g_assert_cmpint(min_dress, ==, valid_dress_1); g_object_set(dim_style, "min-dress", valid_dress_2, NULL); g_object_get(dim_style, "min-dress", &min_dress, NULL); g_assert_cmpint(min_dress, ==, valid_dress_2); g_object_unref(dim_style); } static void _adg_property_number_format(void) { AdgDimStyle *dim_style; const gchar *valid_text_1, *valid_text_2; const gchar *number_format; gchar *number_format_dup; dim_style = adg_dim_style_new(); valid_text_1 = "%lf"; valid_text_2 = "%abc%"; /* Check default value */ number_format = adg_dim_style_get_number_format(dim_style); g_assert_cmpstr(number_format, ==, "%-.7g"); /* Using the public APIs */ adg_dim_style_set_number_format(dim_style, valid_text_1); number_format = adg_dim_style_get_number_format(dim_style); g_assert_cmpstr(number_format, ==, valid_text_1); adg_dim_style_set_number_format(dim_style, valid_text_2); number_format = adg_dim_style_get_number_format(dim_style); g_assert_cmpstr(number_format, ==, valid_text_2); adg_dim_style_set_number_format(dim_style, NULL); number_format = adg_dim_style_get_number_format(dim_style); g_assert_null(number_format); /* Using GObject property methods */ g_object_set(dim_style, "number-format", valid_text_1, NULL); g_object_get(dim_style, "number-format", &number_format_dup, NULL); g_assert_cmpstr(number_format_dup, ==, valid_text_1); g_free(number_format_dup); g_object_set(dim_style, "number-format", valid_text_2, NULL); g_object_get(dim_style, "number-format", &number_format_dup, NULL); g_assert_cmpstr(number_format_dup, ==, valid_text_2); g_free(number_format_dup); g_object_set(dim_style, "number-format", NULL, NULL); g_object_get(dim_style, "number-format", &number_format_dup, NULL); g_assert_null(number_format_dup); g_object_unref(dim_style); } static void _adg_property_number_arguments(void) { AdgDimStyle *dim_style; const gchar *valid_text_1, *valid_text_2; const gchar *number_arguments; gchar *number_arguments_dup; dim_style = adg_dim_style_new(); valid_text_1 = "aieDdMmSs"; valid_text_2 = ""; /* Check default value */ number_arguments = adg_dim_style_get_number_arguments(dim_style); g_assert_cmpstr(number_arguments, ==, "d"); /* Using the public APIs */ adg_dim_style_set_number_arguments(dim_style, valid_text_1); number_arguments = adg_dim_style_get_number_arguments(dim_style); g_assert_cmpstr(number_arguments, ==, valid_text_1); adg_dim_style_set_number_arguments(dim_style, "invalid"); number_arguments = adg_dim_style_get_number_arguments(dim_style); g_assert_cmpstr(number_arguments, ==, valid_text_1); adg_dim_style_set_number_arguments(dim_style, " "); number_arguments = adg_dim_style_get_number_arguments(dim_style); g_assert_cmpstr(number_arguments, ==, valid_text_1); adg_dim_style_set_number_arguments(dim_style, valid_text_2); number_arguments = adg_dim_style_get_number_arguments(dim_style); g_assert_cmpstr(number_arguments, ==, valid_text_2); adg_dim_style_set_number_arguments(dim_style, NULL); number_arguments = adg_dim_style_get_number_arguments(dim_style); g_assert_null(number_arguments); /* Using GObject property methods */ g_object_set(dim_style, "number-arguments", valid_text_1, NULL); g_object_get(dim_style, "number-arguments", &number_arguments_dup, NULL); g_assert_cmpstr(number_arguments_dup, ==, valid_text_1); g_free(number_arguments_dup); g_object_set(dim_style, "number-arguments", "invalid", NULL); g_object_get(dim_style, "number-arguments", &number_arguments_dup, NULL); g_assert_cmpstr(number_arguments_dup, ==, valid_text_1); g_free(number_arguments_dup); g_object_set(dim_style, "number-arguments", " ", NULL); g_object_get(dim_style, "number-arguments", &number_arguments_dup, NULL); g_assert_cmpstr(number_arguments_dup, ==, valid_text_1); g_free(number_arguments_dup); g_object_set(dim_style, "number-arguments", valid_text_2, NULL); g_object_get(dim_style, "number-arguments", &number_arguments_dup, NULL); g_assert_cmpstr(number_arguments_dup, ==, valid_text_2); g_free(number_arguments_dup); g_object_set(dim_style, "number-arguments", NULL, NULL); g_object_get(dim_style, "number-arguments", &number_arguments_dup, NULL); g_assert_null(number_arguments_dup); g_object_unref(dim_style); } static void _adg_property_number_tag(void) { AdgDimStyle *dim_style; const gchar *valid_text_1, *valid_text_2; const gchar *number_tag; gchar *number_tag_dup; dim_style = adg_dim_style_new(); valid_text_1 = ""; valid_text_2 = "<è>"; /* Check default value */ number_tag = adg_dim_style_get_number_tag(dim_style); g_assert_cmpstr(number_tag, ==, "<>"); /* Using the public APIs */ adg_dim_style_set_number_tag(dim_style, valid_text_1); number_tag = adg_dim_style_get_number_tag(dim_style); g_assert_cmpstr(number_tag, ==, valid_text_1); adg_dim_style_set_number_tag(dim_style, valid_text_2); number_tag = adg_dim_style_get_number_tag(dim_style); g_assert_cmpstr(number_tag, ==, valid_text_2); adg_dim_style_set_number_tag(dim_style, NULL); number_tag = adg_dim_style_get_number_tag(dim_style); g_assert_null(number_tag); /* Using GObject property methods */ g_object_set(dim_style, "number-tag", valid_text_1, NULL); g_object_get(dim_style, "number-tag", &number_tag_dup, NULL); g_assert_cmpstr(number_tag_dup, ==, valid_text_1); g_free(number_tag_dup); g_object_set(dim_style, "number-tag", valid_text_2, NULL); g_object_get(dim_style, "number-tag", &number_tag_dup, NULL); g_assert_cmpstr(number_tag_dup, ==, valid_text_2); g_free(number_tag_dup); g_object_set(dim_style, "number-tag", NULL, NULL); g_object_get(dim_style, "number-tag", &number_tag_dup, NULL); g_assert_null(number_tag_dup); g_object_unref(dim_style); } static void _adg_property_decimals(void) { AdgDimStyle *dim_style; gint decimals; dim_style = adg_dim_style_new(); /* Check default value */ decimals = adg_dim_style_get_decimals(dim_style); g_assert_cmpint(decimals, ==, 2); /* Using the public APIs */ adg_dim_style_set_decimals(dim_style, 4); decimals = adg_dim_style_get_decimals(dim_style); g_assert_cmpint(decimals, ==, 4); adg_dim_style_set_decimals(dim_style, -2); decimals = adg_dim_style_get_decimals(dim_style); g_assert_cmpint(decimals, ==, 4); decimals = adg_dim_style_get_decimals(NULL); g_assert_cmpint(decimals, ==, -2); adg_dim_style_set_decimals(dim_style, -1); decimals = adg_dim_style_get_decimals(dim_style); g_assert_cmpint(decimals, ==, -1); /* Using GObject property methods */ g_object_set(dim_style, "decimals", 2, NULL); g_object_get(dim_style, "decimals", &decimals, NULL); g_assert_cmpint(decimals, ==, 2); g_object_set(dim_style, "decimals", -2, NULL); g_object_get(dim_style, "decimals", &decimals, NULL); g_assert_cmpint(decimals, ==, 2); g_object_set(dim_style, "decimals", -1, NULL); g_object_get(dim_style, "decimals", &decimals, NULL); g_assert_cmpint(decimals, ==, -1); g_object_unref(dim_style); } static void +_adg_property_rounding(void) +{ + AdgDimStyle *dim_style; + gint rounding; + + dim_style = adg_dim_style_new(); + + /* Check default value */ + rounding = adg_dim_style_get_rounding(dim_style); + g_assert_cmpint(rounding, ==, 6); + + /* Using the public APIs */ + adg_dim_style_set_rounding(dim_style, 4); + rounding = adg_dim_style_get_rounding(dim_style); + g_assert_cmpint(rounding, ==, 4); + + adg_dim_style_set_rounding(dim_style, -2); + rounding = adg_dim_style_get_rounding(dim_style); + g_assert_cmpint(rounding, ==, 4); + + rounding = adg_dim_style_get_rounding(NULL); + g_assert_cmpint(rounding, ==, -2); + + adg_dim_style_set_rounding(dim_style, -1); + rounding = adg_dim_style_get_rounding(dim_style); + g_assert_cmpint(rounding, ==, -1); + + /* Using GObject property methods */ + g_object_set(dim_style, "rounding", 2, NULL); + g_object_get(dim_style, "rounding", &rounding, NULL); + g_assert_cmpint(rounding, ==, 2); + + g_object_set(dim_style, "rounding", -2, NULL); + g_object_get(dim_style, "rounding", &rounding, NULL); + g_assert_cmpint(rounding, ==, 2); + + g_object_set(dim_style, "rounding", -1, NULL); + g_object_get(dim_style, "rounding", &rounding, NULL); + g_assert_cmpint(rounding, ==, -1); + + g_object_unref(dim_style); +} + +static void _adg_property_quote_shift(void) { AdgDimStyle *dim_style; CpmlPair null_shift, identity_shift; const CpmlPair *shift; CpmlPair *shift_dup; dim_style = adg_dim_style_new(); null_shift.x = 0; null_shift.y = 0; identity_shift.x = 1; identity_shift.y = 1; /* Using the public APIs */ adg_dim_style_set_quote_shift(dim_style, &identity_shift); shift = adg_dim_style_get_quote_shift(dim_style); g_assert_true(cpml_pair_equal(shift, &identity_shift)); adg_dim_style_set_quote_shift(dim_style, &null_shift); shift = adg_dim_style_get_quote_shift(dim_style); g_assert_true(cpml_pair_equal(shift, &null_shift)); adg_dim_style_set_quote_shift(dim_style, NULL); shift = adg_dim_style_get_quote_shift(dim_style); g_assert_true(cpml_pair_equal(shift, &null_shift)); /* Using GObject property methods */ g_object_set(dim_style, "quote-shift", &identity_shift, NULL); g_object_get(dim_style, "quote-shift", &shift_dup, NULL); g_assert_true(cpml_pair_equal(shift_dup, &identity_shift)); g_free(shift_dup); g_object_set(dim_style, "quote-shift", NULL, NULL); g_object_get(dim_style, "quote-shift", &shift_dup, NULL); g_assert_true(cpml_pair_equal(shift_dup, &identity_shift)); g_free(shift_dup); g_object_set(dim_style, "quote-shift", &null_shift, NULL); g_object_get(dim_style, "quote-shift", &shift_dup, NULL); g_assert_true(cpml_pair_equal(shift_dup, &null_shift)); g_free(shift_dup); g_object_unref(dim_style); } static void _adg_property_to_offset(void) { AdgDimStyle *dim_style; gdouble valid_to_offset_1, valid_to_offset_2, invalid_to_offset; gdouble to_offset; dim_style = adg_dim_style_new(); valid_to_offset_1 = 0; valid_to_offset_2 = 999; invalid_to_offset = -1; /* Using the public APIs */ adg_dim_style_set_to_offset(dim_style, valid_to_offset_1); to_offset = adg_dim_style_get_to_offset(dim_style); adg_assert_isapprox(to_offset, valid_to_offset_1); adg_dim_style_set_to_offset(dim_style, invalid_to_offset); to_offset = adg_dim_style_get_to_offset(dim_style); adg_assert_isapprox(to_offset, valid_to_offset_1); adg_dim_style_set_to_offset(dim_style, valid_to_offset_2); to_offset = adg_dim_style_get_to_offset(dim_style); adg_assert_isapprox(to_offset, valid_to_offset_2); /* Using GObject property methods */ g_object_set(dim_style, "to-offset", valid_to_offset_1, NULL); g_object_get(dim_style, "to-offset", &to_offset, NULL); adg_assert_isapprox(to_offset, valid_to_offset_1); g_object_set(dim_style, "to-offset", invalid_to_offset, NULL); g_object_get(dim_style, "to-offset", &to_offset, NULL); adg_assert_isapprox(to_offset, valid_to_offset_1); g_object_set(dim_style, "to-offset", valid_to_offset_2, NULL); g_object_get(dim_style, "to-offset", &to_offset, NULL); adg_assert_isapprox(to_offset, valid_to_offset_2); g_object_unref(dim_style); } static void _adg_property_value_dress(void) { AdgDimStyle *dim_style; AdgDress valid_dress_1, valid_dress_2, incompatible_dress; AdgDress value_dress; dim_style = adg_dim_style_new(); valid_dress_1 = ADG_DRESS_FONT; valid_dress_2 = ADG_DRESS_FONT_QUOTE_ANNOTATION; incompatible_dress = ADG_DRESS_FILL_HATCH; /* Using the public APIs */ adg_dim_style_set_value_dress(dim_style, valid_dress_1); value_dress = adg_dim_style_get_value_dress(dim_style); g_assert_cmpint(value_dress, ==, valid_dress_1); adg_dim_style_set_value_dress(dim_style, incompatible_dress); value_dress = adg_dim_style_get_value_dress(dim_style); g_assert_cmpint(value_dress, ==, valid_dress_1); adg_dim_style_set_value_dress(dim_style, valid_dress_2); value_dress = adg_dim_style_get_value_dress(dim_style); g_assert_cmpint(value_dress, ==, valid_dress_2); /* Using GObject property methods */ g_object_set(dim_style, "value-dress", valid_dress_1, NULL); g_object_get(dim_style, "value-dress", &value_dress, NULL); g_assert_cmpint(value_dress, ==, valid_dress_1); g_object_set(dim_style, "value-dress", incompatible_dress, NULL); g_object_get(dim_style, "value-dress", &value_dress, NULL); g_assert_cmpint(value_dress, ==, valid_dress_1); g_object_set(dim_style, "value-dress", valid_dress_2, NULL); g_object_get(dim_style, "value-dress", &value_dress, NULL); g_assert_cmpint(value_dress, ==, valid_dress_2); g_object_unref(dim_style); } static void _adg_method_convert(void) { AdgDimStyle *dim_style; gdouble value; dim_style = adg_dim_style_new(); adg_dim_style_set_decimals(dim_style, 0); /* Sanity check */ g_assert_false(adg_dim_style_convert(NULL, &value, 'a')); g_assert_false(adg_dim_style_convert(dim_style, NULL, 'a')); g_assert_false(adg_dim_style_convert(NULL, NULL, 'a')); /* Checking the various conversions. For reference: * - 'a': the raw @value, i.e. no conversion is performed; * - 'i': the raw number of minutes, i.e. the fractional part of @value x 60 * - 'e': the raw number of seconds, i.e. the fractional part of the raw * number of minutes x 60 * - 'D': the truncated value of the raw value ('a'); * - 'd': the rounded value of the raw value ('a'); * - 'M': the truncated value of the raw number of minutes ('i'); * - 'm': the rounded value of the raw number of minutes ('i'); * - 'S': the truncated value of the raw number of seconds ('e'); * - 's': the rounded value of the raw number of seconds ('e'); */ value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 'a')); adg_assert_isapprox(value, 5.678); value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 'i')); adg_assert_isapprox(value, 40.68); value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 'e')); adg_assert_isapprox(value, 40.8); value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 'D')); adg_assert_isapprox(value, 5); value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 'd')); adg_assert_isapprox(value, 6); value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 'M')); adg_assert_isapprox(value, 40); value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 'm')); adg_assert_isapprox(value, 41); value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 'S')); adg_assert_isapprox(value, 40); value = 5.678; g_assert_true(adg_dim_style_convert(dim_style, &value, 's')); adg_assert_isapprox(value, 41); + /* Checking that the round property rounds */ + value = 59.999; + g_assert_true(adg_dim_style_convert(dim_style, &value, 'D')); + adg_assert_isapprox(value, 59); + + adg_dim_style_set_rounding(dim_style, 3); + + value = 59.999; + g_assert_true(adg_dim_style_convert(dim_style, &value, 'D')); + adg_assert_isapprox(value, 59); + + adg_dim_style_set_rounding(dim_style, 2); + + value = 59.999; + g_assert_true(adg_dim_style_convert(dim_style, &value, 'D')); + adg_assert_isapprox(value, 60); g_object_unref(dim_style); } int main(int argc, char *argv[]) { adg_test_init(&argc, &argv); adg_test_add_object_checks("/adg/dim-style/type/object", ADG_TYPE_DIM_STYLE); g_test_add_func("/adg/dim-style/property/baseline-spacing", _adg_property_baseline_spacing); g_test_add_func("/adg/dim-style/property/beyond", _adg_property_beyond); g_test_add_func("/adg/dim-style/property/color-dress", _adg_property_color_dress); g_test_add_func("/adg/dim-style/property/from-offset", _adg_property_from_offset); g_test_add_func("/adg/dim-style/property/limits-shift", _adg_property_limits_shift); g_test_add_func("/adg/dim-style/property/limits-spacing", _adg_property_limits_spacing); g_test_add_func("/adg/dim-style/property/line-dress", _adg_property_line_dress); g_test_add_func("/adg/dim-style/property/marker1", _adg_property_marker1); g_test_add_func("/adg/dim-style/property/marker2", _adg_property_marker2); g_test_add_func("/adg/dim-style/property/max-dress", _adg_property_max_dress); g_test_add_func("/adg/dim-style/property/min-dress", _adg_property_min_dress); g_test_add_func("/adg/dim-style/property/number-format", _adg_property_number_format); g_test_add_func("/adg/dim-style/property/number-arguments", _adg_property_number_arguments); g_test_add_func("/adg/dim-style/property/number-tag", _adg_property_number_tag); g_test_add_func("/adg/dim-style/property/decimals", _adg_property_decimals); + g_test_add_func("/adg/dim-style/property/rounding", _adg_property_rounding); g_test_add_func("/adg/dim-style/property/quote-shift", _adg_property_quote_shift); g_test_add_func("/adg/dim-style/property/to-offset", _adg_property_to_offset); g_test_add_func("/adg/dim-style/property/value-dress", _adg_property_value_dress); g_test_add_func("/adg/dim-style/method/convert", _adg_method_convert); return g_test_run(); }