[AdgModel] Enhanced docs
[adg.git] / adg / adg-line-style.c
blobaa9c178104b58c27a6d5cc36fa16a33ec63d674e
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.
29 /**
30 * AdgLineStyle:
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
34 **/
37 /**
38 * ADG_SLOT_LINE_STYLE:
40 * Gets the slot id for this style class.
42 * Returns: the requested slot id
43 **/
46 #include "adg-line-style.h"
47 #include "adg-line-style-private.h"
48 #include "adg-context.h"
49 #include "adg-intl.h"
50 #include "adg-util.h"
52 #define PARENT_STYLE_CLASS ((AdgStyleClass *) adg_line_style_parent_class)
55 enum {
56 PROP_0,
57 PROP_WIDTH,
58 PROP_CAP,
59 PROP_JOIN,
60 PROP_MITER_LIMIT,
61 PROP_ANTIALIAS,
62 PROP_DASH
66 static void get_property (GObject *object,
67 guint prop_id,
68 GValue *value,
69 GParamSpec *pspec);
70 static void set_property (GObject *object,
71 guint prop_id,
72 const GValue *value,
73 GParamSpec *pspec);
74 static GPtrArray * get_pool (void);
75 static void apply (AdgStyle *style,
76 cairo_t *cr);
79 G_DEFINE_TYPE(AdgLineStyle, adg_line_style, ADG_TYPE_STYLE);
82 static void
83 adg_line_style_class_init(AdgLineStyleClass *klass)
85 GObjectClass *gobject_class;
86 AdgStyleClass *style_class;
87 GParamSpec *param;
89 gobject_class = (GObjectClass *) klass;
90 style_class = (AdgStyleClass *) klass;
92 g_type_class_add_private(klass, sizeof(AdgLineStylePrivate));
94 gobject_class->get_property = get_property;
95 gobject_class->set_property = set_property;
97 style_class->get_pool = get_pool;
98 style_class->apply = apply;
100 param = g_param_spec_double("width",
101 P_("Line Width"),
102 P_("The line thickness in device unit"),
103 0., G_MAXDOUBLE, 2., G_PARAM_READWRITE);
104 g_object_class_install_property(gobject_class, PROP_WIDTH, param);
106 param = g_param_spec_int("cap",
107 P_("Line Cap"),
108 P_("The line cap mode"),
109 G_MININT, G_MAXINT, CAIRO_LINE_CAP_ROUND,
110 G_PARAM_READWRITE);
111 g_object_class_install_property(gobject_class, PROP_CAP, param);
113 param = g_param_spec_int("join",
114 P_("Line Join"),
115 P_("The line join mode"),
116 G_MININT, G_MAXINT, CAIRO_LINE_JOIN_MITER,
117 G_PARAM_READWRITE);
118 g_object_class_install_property(gobject_class, PROP_JOIN, param);
120 param = g_param_spec_double("miter-limit",
121 P_("Miter Limit"),
122 P_("Whether the lines should be joined with a bevel instead of a miter"),
123 0., G_MAXDOUBLE, 10., G_PARAM_READWRITE);
124 g_object_class_install_property(gobject_class, PROP_MITER_LIMIT,
125 param);
127 param = g_param_spec_int("antialias",
128 P_("Antialiasing Mode"),
129 P_("Type of antialiasing to do when rendering lines"),
130 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
131 G_PARAM_READWRITE);
132 g_object_class_install_property(gobject_class, PROP_ANTIALIAS, param);
134 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
137 static void
138 adg_line_style_init(AdgLineStyle *line_style)
140 AdgLineStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(line_style,
141 ADG_TYPE_LINE_STYLE,
142 AdgLineStylePrivate);
144 data->width = 2.;
145 data->cap = CAIRO_LINE_CAP_ROUND;
146 data->join = CAIRO_LINE_JOIN_MITER;
147 data->miter_limit = 10.;
148 data->antialias = CAIRO_ANTIALIAS_DEFAULT;
149 data->dashes = NULL;
150 data->num_dashes = 0;
151 data->dash_offset = 0.;
153 line_style->data = data;
156 static void
157 get_property(GObject *object,
158 guint prop_id, GValue *value, GParamSpec *pspec)
160 AdgLineStylePrivate *data = ((AdgLineStyle *) object)->data;
162 switch (prop_id) {
163 case PROP_WIDTH:
164 g_value_set_double(value, data->width);
165 break;
166 case PROP_CAP:
167 g_value_set_int(value, data->cap);
168 break;
169 case PROP_JOIN:
170 g_value_set_int(value, data->join);
171 break;
172 case PROP_MITER_LIMIT:
173 g_value_set_double(value, data->miter_limit);
174 break;
175 case PROP_ANTIALIAS:
176 g_value_set_int(value, data->antialias);
177 break;
178 case PROP_DASH:
179 /* TODO */
180 break;
181 default:
182 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
183 break;
187 static void
188 set_property(GObject *object,
189 guint prop_id, const GValue *value, GParamSpec *pspec)
191 AdgLineStylePrivate *data = ((AdgLineStyle *) object)->data;
193 switch (prop_id) {
194 case PROP_WIDTH:
195 data->width = g_value_get_double(value);
196 break;
197 case PROP_CAP:
198 data->cap = g_value_get_int(value);
199 break;
200 case PROP_JOIN:
201 data->join = g_value_get_int(value);
202 break;
203 case PROP_MITER_LIMIT:
204 data->miter_limit = g_value_get_double(value);
205 break;
206 case PROP_ANTIALIAS:
207 data->antialias = g_value_get_int(value);
208 break;
209 case PROP_DASH:
210 /* TODO */
211 break;
212 default:
213 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
214 break;
219 AdgStyleSlot
220 _adg_line_style_get_slot(void)
222 static AdgStyleSlot slot = -1;
224 if (G_UNLIKELY(slot < 0))
225 slot = adg_context_get_slot(ADG_TYPE_LINE_STYLE);
227 return slot;
231 * adg_line_style_new:
233 * Constructs a new line style initialized with default params.
235 * Returns: a new line style
237 AdgStyle *
238 adg_line_style_new(void)
240 return g_object_new(ADG_TYPE_LINE_STYLE, NULL);
244 * adg_line_style_get_width:
245 * @line_style: an #AdgLineStyle object
247 * Gets the line thickness value (in global space).
249 * Returns: the requested width
251 gdouble
252 adg_line_style_get_width(AdgLineStyle *line_style)
254 AdgLineStylePrivate *data;
256 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), 0.);
258 data = line_style->data;
260 return data->width;
264 * adg_line_style_set_width:
265 * @line_style: an #AdgLineStyle object
266 * @width: the new width
268 * Sets a new line thickness value.
270 void
271 adg_line_style_set_width(AdgLineStyle *line_style, gdouble width)
273 AdgLineStylePrivate *data;
275 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
277 data = line_style->data;
278 data->width = width;
280 g_object_notify((GObject *) line_style, "width");
284 * adg_line_style_get_cap:
285 * @line_style: an #AdgLineStyle object
287 * Gets the line cap mode.
289 * Returns: the requested line cap mode
291 cairo_line_cap_t
292 adg_line_style_get_cap(AdgLineStyle *line_style)
294 AdgLineStylePrivate *data;
296 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
297 CAIRO_LINE_CAP_BUTT);
299 data = line_style->data;
301 return data->cap;
305 * adg_line_style_set_cap:
306 * @line_style: an #AdgLineStyle object
307 * @cap: the new cap mode
309 * Sets a new line cap mode.
311 void
312 adg_line_style_set_cap(AdgLineStyle *line_style, cairo_line_cap_t cap)
314 AdgLineStylePrivate *data;
316 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
318 data = line_style->data;
319 data->cap = cap;
321 g_object_notify((GObject *) line_style, "cap");
325 * adg_line_style_get_join:
326 * @line_style: an #AdgLineStyle object
328 * Gets the line join mode.
330 * Returns: the requested line join mode
332 cairo_line_join_t
333 adg_line_style_get_join(AdgLineStyle *line_style)
335 AdgLineStylePrivate *data;
337 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
338 CAIRO_LINE_JOIN_MITER);
340 data = line_style->data;
342 return data->join;
346 * adg_line_style_set_join:
347 * @line_style: an #AdgLineStyle object
348 * @join: the new join mode
350 * Sets a new line join mode.
352 void
353 adg_line_style_set_join(AdgLineStyle *line_style, cairo_line_join_t join)
355 AdgLineStylePrivate *data;
357 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
359 data->join = join;
360 data = line_style->data;
362 g_object_notify((GObject *) line_style, "join");
366 * adg_line_style_get_miter_limit:
367 * @line_style: an #AdgLineStyle object
369 * Gets the line miter limit value. The miter limit is used to determine
370 * whether the lines should be joined with a bevel instead of a miter.
372 * Returns: the requested miter limit
374 gdouble
375 adg_line_style_get_miter_limit(AdgLineStyle *line_style)
377 AdgLineStylePrivate *data;
379 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), 0.);
381 data = line_style->data;
383 return data->miter_limit;
387 * adg_line_style_set_miter_limit:
388 * @line_style: an #AdgLineStyle object
389 * @miter_limit: the new miter limit
391 * Sets a new miter limit value.
393 void
394 adg_line_style_set_miter_limit(AdgLineStyle *line_style,
395 gdouble miter_limit)
397 AdgLineStylePrivate *data;
399 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
401 data = line_style->data;
402 data->miter_limit = miter_limit;
404 g_object_notify((GObject *) line_style, "miter-limit");
408 * adg_line_style_get_antialias:
409 * @line_style: an #AdgLineStyle object
411 * Gets the antialias mode used.
413 * Returns: the requested antialias mode
415 cairo_antialias_t
416 adg_line_style_get_antialias(AdgLineStyle *line_style)
418 AdgLineStylePrivate *data;
420 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
421 CAIRO_ANTIALIAS_DEFAULT);
423 data = line_style->data;
425 return data->antialias;
429 * adg_line_style_set_antialias:
430 * @line_style: an #AdgLineStyle object
431 * @antialias: the new antialias mode
433 * Sets a new antialias mode.
435 void
436 adg_line_style_set_antialias(AdgLineStyle *line_style,
437 cairo_antialias_t antialias)
439 AdgLineStylePrivate *data;
441 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
443 data = line_style->data;
444 data->antialias = antialias;
446 g_object_notify((GObject *) line_style, "antialias");
450 static GPtrArray *
451 get_pool(void)
453 static GPtrArray *pool = NULL;
455 if (G_UNLIKELY(pool == NULL)) {
456 cairo_pattern_t *pattern;
458 pool = g_ptr_array_sized_new(ADG_LINE_STYLE_LAST);
460 pool->pdata[ADG_LINE_STYLE_DRAW] =
461 g_object_new(ADG_TYPE_LINE_STYLE, "width", 2., NULL);
463 pattern = cairo_pattern_create_rgb(0., 1., 0.);
464 pool->pdata[ADG_LINE_STYLE_CENTER] =
465 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
466 0.75, NULL);
467 cairo_pattern_destroy(pattern);
469 pattern = cairo_pattern_create_rgba(0., 0., 0., 0.5);
470 pool->pdata[ADG_LINE_STYLE_HIDDEN] =
471 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
472 0.75, NULL);
473 cairo_pattern_destroy(pattern);
475 pattern = cairo_pattern_create_rgb(0., 0., 1.);
476 pool->pdata[ADG_LINE_STYLE_HATCH] =
477 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
478 1.25, NULL);
479 cairo_pattern_destroy(pattern);
481 pool->pdata[ADG_LINE_STYLE_DIM] = g_object_new(ADG_TYPE_LINE_STYLE,
482 "width", 0.75,
483 NULL);
485 pool->len = ADG_LINE_STYLE_LAST;
488 return pool;
491 static void
492 apply(AdgStyle *style, cairo_t *cr)
494 AdgLineStyle *line_style;
495 AdgLineStylePrivate *data;
497 line_style = (AdgLineStyle *) style;
498 data = line_style->data;
500 if (PARENT_STYLE_CLASS->apply != NULL)
501 PARENT_STYLE_CLASS->apply(style, cr);
503 cairo_set_line_width(cr, data->width);
504 cairo_set_line_cap(cr, data->cap);
505 cairo_set_line_join(cr, data->join);
506 cairo_set_miter_limit(cr, data->miter_limit);
507 cairo_set_antialias(cr, data->antialias);
509 if (data->num_dashes > 0) {
510 g_return_if_fail(data->dashes != NULL);
512 cairo_set_dash(cr, data->dashes, data->num_dashes, data->dash_offset);