Implemented adg_line_style_new()
[adg.git] / adg / adg-line-style.c
blob6bec7528ba9f51bfc71c96c8dfe867b56ef1740f
1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2008, 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 Library 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 * Library 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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 /**
22 * SECTION:line-style
23 * @title: AdgLineStyle
24 * @short_description: Line style related stuff
26 * Contains parameters on how to draw lines such as width, cap mode, join mode
27 * and dash composition, if used.
30 #include "adg-line-style.h"
31 #include "adg-line-style-private.h"
32 #include "adg-intl.h"
33 #include "adg-util.h"
35 #define PARENT_CLASS ((AdgStyleClass *) adg_line_style_parent_class)
38 enum
40 PROP_0,
41 PROP_WIDTH,
42 PROP_CAP,
43 PROP_JOIN,
44 PROP_MITER_LIMIT,
45 PROP_ANTIALIAS,
46 PROP_DASH
50 static void get_property (GObject *object,
51 guint prop_id,
52 GValue *value,
53 GParamSpec *pspec);
54 static void set_property (GObject *object,
55 guint prop_id,
56 const GValue *value,
57 GParamSpec *pspec);
59 static void apply (AdgStyle *style,
60 cairo_t *cr);
63 G_DEFINE_TYPE (AdgLineStyle, adg_line_style, ADG_TYPE_STYLE)
66 static void
67 adg_line_style_class_init (AdgLineStyleClass *klass)
69 GObjectClass *gobject_class;
70 AdgStyleClass *style_class;
71 GParamSpec *param;
73 gobject_class = (GObjectClass *) klass;
74 style_class = (AdgStyleClass *) klass;
76 g_type_class_add_private (klass, sizeof (AdgLineStylePrivate));
78 gobject_class->get_property = get_property;
79 gobject_class->set_property = set_property;
81 style_class->apply = apply;
83 param = g_param_spec_double ("width",
84 P_("Line Width"),
85 P_("The line thickness in device unit"),
86 0., G_MAXDOUBLE, 2.,
87 G_PARAM_READWRITE);
88 g_object_class_install_property (gobject_class, PROP_WIDTH, param);
90 param = g_param_spec_int ("cap",
91 P_("Line Cap"),
92 P_("The line cap mode"),
93 G_MININT, G_MAXINT, CAIRO_LINE_CAP_ROUND,
94 G_PARAM_READWRITE);
95 g_object_class_install_property (gobject_class, PROP_CAP, param);
97 param = g_param_spec_int ("join",
98 P_("Line Join"),
99 P_("The line join mode"),
100 G_MININT, G_MAXINT, CAIRO_LINE_JOIN_MITER,
101 G_PARAM_READWRITE);
102 g_object_class_install_property (gobject_class, PROP_JOIN, param);
104 param = g_param_spec_double ("miter-limit",
105 P_("Miter Limit"),
106 P_("Whether the lines should be joined with a bevel instead of a miter"),
107 0., G_MAXDOUBLE, 10.,
108 G_PARAM_READWRITE);
109 g_object_class_install_property (gobject_class, PROP_MITER_LIMIT, param);
111 param = g_param_spec_int ("antialias",
112 P_("Antialiasing Mode"),
113 P_("Type of antialiasing to do when rendering lines"),
114 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
115 G_PARAM_READWRITE);
116 g_object_class_install_property (gobject_class, PROP_ANTIALIAS, param);
118 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
121 static void
122 adg_line_style_init (AdgLineStyle *line_style)
124 AdgLineStylePrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (line_style,
125 ADG_TYPE_LINE_STYLE,
126 AdgLineStylePrivate);
128 priv->width = 2.;
129 priv->cap = CAIRO_LINE_CAP_ROUND;
130 priv->join = CAIRO_LINE_JOIN_MITER;
131 priv->miter_limit = 10.;
132 priv->antialias = CAIRO_ANTIALIAS_DEFAULT;
133 priv->dashes = NULL;
134 priv->num_dashes = 0;
135 priv->dash_offset = 0.;
137 line_style->priv = priv;
140 static void
141 get_property (GObject *object,
142 guint prop_id,
143 GValue *value,
144 GParamSpec *pspec)
146 AdgLineStyle *line_style = (AdgLineStyle *) object;
148 switch (prop_id)
150 case PROP_WIDTH:
151 g_value_set_double (value, line_style->priv->width);
152 break;
153 case PROP_CAP:
154 g_value_set_int (value, line_style->priv->cap);
155 break;
156 case PROP_JOIN:
157 g_value_set_int (value, line_style->priv->join);
158 break;
159 case PROP_MITER_LIMIT:
160 g_value_set_double (value, line_style->priv->miter_limit);
161 break;
162 case PROP_ANTIALIAS:
163 g_value_set_int (value, line_style->priv->antialias);
164 break;
165 case PROP_DASH:
166 /* TODO */
167 break;
168 default:
169 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
170 break;
174 static void
175 set_property (GObject *object,
176 guint prop_id,
177 const GValue *value,
178 GParamSpec *pspec)
180 AdgLineStyle *line_style = (AdgLineStyle *) object;
182 switch (prop_id)
184 case PROP_WIDTH:
185 line_style->priv->width = g_value_get_double (value);
186 break;
187 case PROP_CAP:
188 line_style->priv->cap = g_value_get_int (value);
189 break;
190 case PROP_JOIN:
191 line_style->priv->join = g_value_get_int (value);
192 break;
193 case PROP_MITER_LIMIT:
194 line_style->priv->miter_limit = g_value_get_double (value);
195 break;
196 case PROP_ANTIALIAS:
197 line_style->priv->antialias = g_value_get_int (value);
198 break;
199 case PROP_DASH:
200 /* TODO */
201 break;
202 default:
203 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
204 break;
210 * adg_line_style_new:
212 * Constructs a new line style initialized with default params.
214 * Return value: a new line style
216 AdgStyle *
217 adg_line_style_new (void)
219 return g_object_new (ADG_TYPE_LINE_STYLE, NULL);
223 * adg_line_style_from_id:
224 * @id: a line style identifier
226 * Gets a predefined style from an #AdgLineStyleId identifier.
228 * Return value: the requested style or %NULL if not found
230 AdgStyle *
231 adg_line_style_from_id (AdgLineStyleId id)
233 static AdgStyle **builtins = NULL;
235 if G_UNLIKELY (builtins == NULL)
237 cairo_pattern_t *pattern;
239 builtins = g_new (AdgStyle *, ADG_LINE_STYLE_LAST);
241 builtins[ADG_LINE_STYLE_DRAW] = g_object_new (ADG_TYPE_LINE_STYLE,
242 "width", 2.,
243 NULL);
245 pattern = cairo_pattern_create_rgb (0., 1., 0.);
246 builtins[ADG_LINE_STYLE_CENTER] = g_object_new (ADG_TYPE_LINE_STYLE,
247 "pattern", pattern,
248 "width", 0.75,
249 NULL);
250 cairo_pattern_destroy (pattern);
252 pattern = cairo_pattern_create_rgba (0., 0., 0., 0.5);
253 builtins[ADG_LINE_STYLE_HIDDEN] = g_object_new (ADG_TYPE_LINE_STYLE,
254 "pattern", pattern,
255 "width", 0.75,
256 NULL);
257 cairo_pattern_destroy (pattern);
259 pattern = cairo_pattern_create_rgb (0., 0., 1.);
260 builtins[ADG_LINE_STYLE_XATCH] = g_object_new (ADG_TYPE_LINE_STYLE,
261 "pattern", pattern,
262 "width", 1.25,
263 NULL);
264 cairo_pattern_destroy (pattern);
266 builtins[ADG_LINE_STYLE_DIM] = g_object_new (ADG_TYPE_LINE_STYLE,
267 "width", 0.75,
268 NULL);
271 g_return_val_if_fail (id < ADG_LINE_STYLE_LAST, NULL);
272 return builtins[id];
276 * adg_line_style_get_width:
277 * @line_style: an #AdgLineStyle object
279 * Gets the line thickness value (in paper units).
281 * Return value: the requested width
283 gdouble
284 adg_line_style_get_width (AdgLineStyle *line_style)
286 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style), 0.);
288 return line_style->priv->width;
292 * adg_line_style_set_width:
293 * @line_style: an #AdgLineStyle object
294 * @width: the new width
296 * Sets a new line thickness value.
298 void
299 adg_line_style_set_width (AdgLineStyle *line_style,
300 gdouble width)
302 g_return_if_fail (ADG_IS_LINE_STYLE (line_style));
304 line_style->priv->width = width;
305 g_object_notify ((GObject *) line_style, "width");
309 * adg_line_style_get_cap:
310 * @line_style: an #AdgLineStyle object
312 * Gets the line cap mode.
314 * Return value: the requested line cap mode
316 cairo_line_cap_t
317 adg_line_style_get_cap (AdgLineStyle *line_style)
319 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style), CAIRO_LINE_CAP_BUTT);
321 return line_style->priv->cap;
325 * adg_line_style_set_cap:
326 * @line_style: an #AdgLineStyle object
327 * @cap: the new cap mode
329 * Sets a new line cap mode.
331 void
332 adg_line_style_set_cap (AdgLineStyle *line_style,
333 cairo_line_cap_t cap)
335 g_return_if_fail (ADG_IS_LINE_STYLE (line_style));
337 line_style->priv->cap = cap;
338 g_object_notify ((GObject *) line_style, "cap");
342 * adg_line_style_get_join:
343 * @line_style: an #AdgLineStyle object
345 * Gets the line join mode.
347 * Return value: the requested line join mode
349 cairo_line_join_t
350 adg_line_style_get_join (AdgLineStyle *line_style)
352 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style), CAIRO_LINE_JOIN_MITER);
354 return line_style->priv->join;
358 * adg_line_style_set_join:
359 * @line_style: an #AdgLineStyle object
360 * @join: the new join mode
362 * Sets a new line join mode.
364 void
365 adg_line_style_set_join (AdgLineStyle *line_style,
366 cairo_line_join_t join)
368 g_return_if_fail (ADG_IS_LINE_STYLE (line_style));
370 line_style->priv->join = join;
371 g_object_notify ((GObject *) line_style, "join");
375 * adg_line_style_get_miter_limit:
376 * @line_style: an #AdgLineStyle object
378 * Gets the line miter limit value. The miter limit is used to determine
379 * whether the lines should be joined with a bevel instead of a miter.
381 * Return value: the requested miter limit
383 gdouble
384 adg_line_style_get_miter_limit (AdgLineStyle *line_style)
386 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style), 0.);
388 return line_style->priv->miter_limit;
392 * adg_line_style_set_miter_limit:
393 * @line_style: an #AdgLineStyle object
394 * @miter_limit: the new miter limit
396 * Sets a new miter limit value.
398 void
399 adg_line_style_set_miter_limit (AdgLineStyle *line_style,
400 gdouble miter_limit)
402 g_return_if_fail (ADG_IS_LINE_STYLE (line_style));
404 line_style->priv->miter_limit = miter_limit;
405 g_object_notify ((GObject *) line_style, "miter-limit");
409 * adg_line_style_get_antialias:
410 * @line_style: an #AdgLineStyle object
412 * Gets the antialias mode used.
414 * Return value: the requested antialias mode
416 cairo_antialias_t
417 adg_line_style_get_antialias (AdgLineStyle *line_style)
419 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style), CAIRO_ANTIALIAS_DEFAULT);
421 return line_style->priv->antialias;
425 * adg_line_style_set_antialias:
426 * @line_style: an #AdgLineStyle object
427 * @antialias: the new antialias mode
429 * Sets a new antialias mode.
431 void
432 adg_line_style_set_antialias (AdgLineStyle *line_style,
433 cairo_antialias_t antialias)
435 g_return_if_fail (ADG_IS_LINE_STYLE (line_style));
437 line_style->priv->antialias = antialias;
438 g_object_notify ((GObject *) line_style, "antialias");
442 static void
443 apply (AdgStyle *style,
444 cairo_t *cr)
446 AdgLineStyle *line_style;
447 gdouble device_width;
448 gdouble dummy = 0.;
450 line_style = (AdgLineStyle *) style;
452 PARENT_CLASS->apply (style, cr);
454 device_width = line_style->priv->width;
455 cairo_device_to_user_distance (cr, &device_width, &dummy);
456 cairo_set_line_width (cr, device_width);
458 cairo_set_line_cap (cr, line_style->priv->cap);
459 cairo_set_line_join (cr, line_style->priv->join);
460 cairo_set_miter_limit (cr, line_style->priv->miter_limit);
461 cairo_set_antialias (cr, line_style->priv->antialias);
463 if (line_style->priv->num_dashes > 0)
465 g_return_if_fail (line_style->priv->dashes != NULL);
467 cairo_set_dash (cr, line_style->priv->dashes, line_style->priv->num_dashes,
468 line_style->priv->dash_offset);