[CpmlArc] Fixed issue 7: arc extents bug
[adg.git] / adg / adg-line-style.c
blob415e4d37c9f52397ce8a1c81b8415b897bd37ba0
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:adg-line-style
23 * @short_description: Line style related stuff
25 * Contains parameters on how to draw lines such as width, cap mode, join mode
26 * and dash composition, if used.
27 **/
29 /**
30 * AdgLineStyle:
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
34 **/
37 #include "adg-line-style.h"
38 #include "adg-line-style-private.h"
39 #include "adg-dress-builtins.h"
40 #include "adg-intl.h"
42 #define PARENT_STYLE_CLASS ((AdgStyleClass *) adg_line_style_parent_class)
45 enum {
46 PROP_0,
47 PROP_COLOR_DRESS,
48 PROP_WIDTH,
49 PROP_CAP,
50 PROP_JOIN,
51 PROP_MITER_LIMIT,
52 PROP_ANTIALIAS,
53 PROP_DASH
57 static void get_property (GObject *object,
58 guint prop_id,
59 GValue *value,
60 GParamSpec *pspec);
61 static void set_property (GObject *object,
62 guint prop_id,
63 const GValue *value,
64 GParamSpec *pspec);
65 static void apply (AdgStyle *style,
66 AdgEntity *entity,
67 cairo_t *cr);
70 G_DEFINE_TYPE(AdgLineStyle, adg_line_style, ADG_TYPE_STYLE);
73 static void
74 adg_line_style_class_init(AdgLineStyleClass *klass)
76 GObjectClass *gobject_class;
77 AdgStyleClass *style_class;
78 GParamSpec *param;
80 gobject_class = (GObjectClass *) klass;
81 style_class = (AdgStyleClass *) klass;
83 g_type_class_add_private(klass, sizeof(AdgLineStylePrivate));
85 gobject_class->get_property = get_property;
86 gobject_class->set_property = set_property;
88 style_class->apply = apply;
90 param = adg_param_spec_dress("color-dress",
91 P_("Color Dress"),
92 P_("The color dress to bind to this line style"),
93 ADG_DRESS_COLOR,
94 G_PARAM_READWRITE);
95 g_object_class_install_property(gobject_class, PROP_COLOR_DRESS, param);
97 param = g_param_spec_double("width",
98 P_("Line Width"),
99 P_("The line thickness in device unit"),
100 0., G_MAXDOUBLE, 2., G_PARAM_READWRITE);
101 g_object_class_install_property(gobject_class, PROP_WIDTH, param);
103 param = g_param_spec_int("cap",
104 P_("Line Cap"),
105 P_("The line cap mode"),
106 G_MININT, G_MAXINT, CAIRO_LINE_CAP_ROUND,
107 G_PARAM_READWRITE);
108 g_object_class_install_property(gobject_class, PROP_CAP, param);
110 param = g_param_spec_int("join",
111 P_("Line Join"),
112 P_("The line join mode"),
113 G_MININT, G_MAXINT, CAIRO_LINE_JOIN_MITER,
114 G_PARAM_READWRITE);
115 g_object_class_install_property(gobject_class, PROP_JOIN, param);
117 param = g_param_spec_double("miter-limit",
118 P_("Miter Limit"),
119 P_("Whether the lines should be joined with a bevel instead of a miter"),
120 0., G_MAXDOUBLE, 10., G_PARAM_READWRITE);
121 g_object_class_install_property(gobject_class, PROP_MITER_LIMIT,
122 param);
124 param = g_param_spec_int("antialias",
125 P_("Antialiasing Mode"),
126 P_("Type of antialiasing to do when rendering lines"),
127 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
128 G_PARAM_READWRITE);
129 g_object_class_install_property(gobject_class, PROP_ANTIALIAS, param);
131 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
134 static void
135 adg_line_style_init(AdgLineStyle *line_style)
137 AdgLineStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(line_style,
138 ADG_TYPE_LINE_STYLE,
139 AdgLineStylePrivate);
141 data->color_dress = ADG_DRESS_COLOR;
142 data->width = 2.;
143 data->cap = CAIRO_LINE_CAP_ROUND;
144 data->join = CAIRO_LINE_JOIN_MITER;
145 data->miter_limit = 10.;
146 data->antialias = CAIRO_ANTIALIAS_DEFAULT;
147 data->dashes = NULL;
148 data->num_dashes = 0;
149 data->dash_offset = 0.;
151 line_style->data = data;
154 static void
155 get_property(GObject *object, guint prop_id,
156 GValue *value, GParamSpec *pspec)
158 AdgLineStylePrivate *data = ((AdgLineStyle *) object)->data;
160 switch (prop_id) {
161 case PROP_COLOR_DRESS:
162 g_value_set_int(value, data->color_dress);
163 break;
164 case PROP_WIDTH:
165 g_value_set_double(value, data->width);
166 break;
167 case PROP_CAP:
168 g_value_set_int(value, data->cap);
169 break;
170 case PROP_JOIN:
171 g_value_set_int(value, data->join);
172 break;
173 case PROP_MITER_LIMIT:
174 g_value_set_double(value, data->miter_limit);
175 break;
176 case PROP_ANTIALIAS:
177 g_value_set_int(value, data->antialias);
178 break;
179 case PROP_DASH:
180 /* TODO */
181 break;
182 default:
183 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
184 break;
188 static void
189 set_property(GObject *object, guint prop_id,
190 const GValue *value, GParamSpec *pspec)
192 AdgLineStylePrivate *data = ((AdgLineStyle *) object)->data;
194 switch (prop_id) {
195 case PROP_COLOR_DRESS:
196 adg_dress_set(&data->color_dress, g_value_get_int(value));
197 break;
198 case PROP_WIDTH:
199 data->width = g_value_get_double(value);
200 break;
201 case PROP_CAP:
202 data->cap = g_value_get_int(value);
203 break;
204 case PROP_JOIN:
205 data->join = g_value_get_int(value);
206 break;
207 case PROP_MITER_LIMIT:
208 data->miter_limit = g_value_get_double(value);
209 break;
210 case PROP_ANTIALIAS:
211 data->antialias = g_value_get_int(value);
212 break;
213 case PROP_DASH:
214 /* TODO */
215 break;
216 default:
217 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
218 break;
224 * adg_line_style_new:
226 * Constructs a new line style initialized with default params.
228 * Returns: a new line style
230 AdgLineStyle *
231 adg_line_style_new(void)
233 return g_object_new(ADG_TYPE_LINE_STYLE, NULL);
237 * adg_line_style_get_color_dress:
238 * @line_style: an #AdgLineStyle
240 * Gets the color dress used by @line_style.
242 * Returns: the current color dress
244 AdgDress
245 adg_line_style_get_color_dress(AdgLineStyle *line_style)
247 AdgLineStylePrivate *data;
249 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), ADG_DRESS_UNDEFINED);
251 data = line_style->data;
253 return data->color_dress;
257 * adg_line_style_set_color_dress:
258 * @line_style: an #AdgLineStyle
259 * @dress: the new color dress to use
261 * Sets a new color dress on @line_style. The new dress
262 * should be related to the original dress: you cannot
263 * set a dress used for line styles to a dress managing
264 * fonts.
266 * The validation of the new dress is done by calling
267 * adg_dress_are_related() with @dress and the previous
268 * dress as arguments: check out its documentation for
269 * details on what is a related dress.
271 void
272 adg_line_style_set_color_dress(AdgLineStyle *line_style, AdgDress dress)
274 AdgLineStylePrivate *data;
276 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
278 data = line_style->data;
280 if (adg_dress_set(&data->color_dress, dress))
281 g_object_notify((GObject *) line_style, "color-dress");
285 * adg_line_style_get_width:
286 * @line_style: an #AdgLineStyle object
288 * Gets the line thickness value (in global space).
290 * Returns: the requested width
292 gdouble
293 adg_line_style_get_width(AdgLineStyle *line_style)
295 AdgLineStylePrivate *data;
297 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), 0.);
299 data = line_style->data;
301 return data->width;
305 * adg_line_style_set_width:
306 * @line_style: an #AdgLineStyle object
307 * @width: the new width
309 * Sets a new line thickness value.
311 void
312 adg_line_style_set_width(AdgLineStyle *line_style, gdouble width)
314 AdgLineStylePrivate *data;
316 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
318 data = line_style->data;
319 data->width = width;
321 g_object_notify((GObject *) line_style, "width");
325 * adg_line_style_get_cap:
326 * @line_style: an #AdgLineStyle object
328 * Gets the line cap mode.
330 * Returns: the requested line cap mode
332 cairo_line_cap_t
333 adg_line_style_get_cap(AdgLineStyle *line_style)
335 AdgLineStylePrivate *data;
337 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
338 CAIRO_LINE_CAP_BUTT);
340 data = line_style->data;
342 return data->cap;
346 * adg_line_style_set_cap:
347 * @line_style: an #AdgLineStyle object
348 * @cap: the new cap mode
350 * Sets a new line cap mode.
352 void
353 adg_line_style_set_cap(AdgLineStyle *line_style, cairo_line_cap_t cap)
355 AdgLineStylePrivate *data;
357 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
359 data = line_style->data;
360 data->cap = cap;
362 g_object_notify((GObject *) line_style, "cap");
366 * adg_line_style_get_join:
367 * @line_style: an #AdgLineStyle object
369 * Gets the line join mode.
371 * Returns: the requested line join mode
373 cairo_line_join_t
374 adg_line_style_get_join(AdgLineStyle *line_style)
376 AdgLineStylePrivate *data;
378 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
379 CAIRO_LINE_JOIN_MITER);
381 data = line_style->data;
383 return data->join;
387 * adg_line_style_set_join:
388 * @line_style: an #AdgLineStyle object
389 * @join: the new join mode
391 * Sets a new line join mode.
393 void
394 adg_line_style_set_join(AdgLineStyle *line_style, cairo_line_join_t join)
396 AdgLineStylePrivate *data;
398 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
400 data = line_style->data;
401 data->join = join;
403 g_object_notify((GObject *) line_style, "join");
407 * adg_line_style_get_miter_limit:
408 * @line_style: an #AdgLineStyle object
410 * Gets the line miter limit value. The miter limit is used to determine
411 * whether the lines should be joined with a bevel instead of a miter.
413 * Returns: the requested miter limit
415 gdouble
416 adg_line_style_get_miter_limit(AdgLineStyle *line_style)
418 AdgLineStylePrivate *data;
420 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), 0.);
422 data = line_style->data;
424 return data->miter_limit;
428 * adg_line_style_set_miter_limit:
429 * @line_style: an #AdgLineStyle object
430 * @miter_limit: the new miter limit
432 * Sets a new miter limit value.
434 void
435 adg_line_style_set_miter_limit(AdgLineStyle *line_style,
436 gdouble miter_limit)
438 AdgLineStylePrivate *data;
440 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
442 data = line_style->data;
443 data->miter_limit = miter_limit;
445 g_object_notify((GObject *) line_style, "miter-limit");
449 * adg_line_style_get_antialias:
450 * @line_style: an #AdgLineStyle object
452 * Gets the antialias mode used.
454 * Returns: the requested antialias mode
456 cairo_antialias_t
457 adg_line_style_get_antialias(AdgLineStyle *line_style)
459 AdgLineStylePrivate *data;
461 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
462 CAIRO_ANTIALIAS_DEFAULT);
464 data = line_style->data;
466 return data->antialias;
470 * adg_line_style_set_antialias:
471 * @line_style: an #AdgLineStyle object
472 * @antialias: the new antialias mode
474 * Sets a new antialias mode.
476 void
477 adg_line_style_set_antialias(AdgLineStyle *line_style,
478 cairo_antialias_t antialias)
480 AdgLineStylePrivate *data;
482 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
484 data = line_style->data;
485 data->antialias = antialias;
487 g_object_notify((GObject *) line_style, "antialias");
490 static void
491 apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr)
493 AdgLineStylePrivate *data = ((AdgLineStyle *) style)->data;
495 adg_entity_apply_dress(entity, data->color_dress, cr);
496 cairo_set_line_width(cr, data->width);
497 cairo_set_line_cap(cr, data->cap);
498 cairo_set_line_join(cr, data->join);
499 cairo_set_miter_limit(cr, data->miter_limit);
500 cairo_set_antialias(cr, data->antialias);
502 if (data->num_dashes > 0) {
503 g_return_if_fail(data->dashes != NULL);
505 cairo_set_dash(cr, data->dashes, data->num_dashes, data->dash_offset);