[docs] Improved the ADG docs
[adg.git] / adg / adg-line-style.c
blob5ad9e3164934137da33d2967b68a58234e9f28b1
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 * Return value: 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"
53 enum {
54 PROP_0,
55 PROP_WIDTH,
56 PROP_CAP,
57 PROP_JOIN,
58 PROP_MITER_LIMIT,
59 PROP_ANTIALIAS,
60 PROP_DASH
64 static void get_property (GObject *object,
65 guint prop_id,
66 GValue *value,
67 GParamSpec *pspec);
68 static void set_property (GObject *object,
69 guint prop_id,
70 const GValue *value,
71 GParamSpec *pspec);
72 static GPtrArray * get_pool (void);
73 static void apply (AdgStyle *style,
74 cairo_t *cr);
77 G_DEFINE_TYPE(AdgLineStyle, adg_line_style, ADG_TYPE_STYLE);
80 static void
81 adg_line_style_class_init(AdgLineStyleClass *klass)
83 GObjectClass *gobject_class;
84 AdgStyleClass *style_class;
85 GParamSpec *param;
87 gobject_class = (GObjectClass *) klass;
88 style_class = (AdgStyleClass *) klass;
90 g_type_class_add_private(klass, sizeof(AdgLineStylePrivate));
92 gobject_class->get_property = get_property;
93 gobject_class->set_property = set_property;
95 style_class->get_pool = get_pool;
96 style_class->apply = apply;
98 param = g_param_spec_double("width",
99 P_("Line Width"),
100 P_("The line thickness in device unit"),
101 0., G_MAXDOUBLE, 2., G_PARAM_READWRITE);
102 g_object_class_install_property(gobject_class, PROP_WIDTH, param);
104 param = g_param_spec_int("cap",
105 P_("Line Cap"),
106 P_("The line cap mode"),
107 G_MININT, G_MAXINT, CAIRO_LINE_CAP_ROUND,
108 G_PARAM_READWRITE);
109 g_object_class_install_property(gobject_class, PROP_CAP, param);
111 param = g_param_spec_int("join",
112 P_("Line Join"),
113 P_("The line join mode"),
114 G_MININT, G_MAXINT, CAIRO_LINE_JOIN_MITER,
115 G_PARAM_READWRITE);
116 g_object_class_install_property(gobject_class, PROP_JOIN, param);
118 param = g_param_spec_double("miter-limit",
119 P_("Miter Limit"),
120 P_("Whether the lines should be joined with a bevel instead of a miter"),
121 0., G_MAXDOUBLE, 10., G_PARAM_READWRITE);
122 g_object_class_install_property(gobject_class, PROP_MITER_LIMIT,
123 param);
125 param = g_param_spec_int("antialias",
126 P_("Antialiasing Mode"),
127 P_("Type of antialiasing to do when rendering lines"),
128 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
129 G_PARAM_READWRITE);
130 g_object_class_install_property(gobject_class, PROP_ANTIALIAS, param);
132 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
135 static void
136 adg_line_style_init(AdgLineStyle *line_style)
138 AdgLineStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(line_style,
139 ADG_TYPE_LINE_STYLE,
140 AdgLineStylePrivate);
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,
156 guint prop_id, GValue *value, GParamSpec *pspec)
158 AdgLineStylePrivate *data = ((AdgLineStyle *) object)->data;
160 switch (prop_id) {
161 case PROP_WIDTH:
162 g_value_set_double(value, data->width);
163 break;
164 case PROP_CAP:
165 g_value_set_int(value, data->cap);
166 break;
167 case PROP_JOIN:
168 g_value_set_int(value, data->join);
169 break;
170 case PROP_MITER_LIMIT:
171 g_value_set_double(value, data->miter_limit);
172 break;
173 case PROP_ANTIALIAS:
174 g_value_set_int(value, data->antialias);
175 break;
176 case PROP_DASH:
177 /* TODO */
178 break;
179 default:
180 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
181 break;
185 static void
186 set_property(GObject *object,
187 guint prop_id, const GValue *value, GParamSpec *pspec)
189 AdgLineStylePrivate *data = ((AdgLineStyle *) object)->data;
191 switch (prop_id) {
192 case PROP_WIDTH:
193 data->width = g_value_get_double(value);
194 break;
195 case PROP_CAP:
196 data->cap = g_value_get_int(value);
197 break;
198 case PROP_JOIN:
199 data->join = g_value_get_int(value);
200 break;
201 case PROP_MITER_LIMIT:
202 data->miter_limit = g_value_get_double(value);
203 break;
204 case PROP_ANTIALIAS:
205 data->antialias = g_value_get_int(value);
206 break;
207 case PROP_DASH:
208 /* TODO */
209 break;
210 default:
211 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
212 break;
217 AdgStyleSlot
218 _adg_line_style_get_slot(void)
220 static AdgStyleSlot slot = -1;
222 if (G_UNLIKELY(slot < 0))
223 slot = adg_context_get_slot(ADG_TYPE_LINE_STYLE);
225 return slot;
229 * adg_line_style_new:
231 * Constructs a new line style initialized with default params.
233 * Return value: a new line style
235 AdgStyle *
236 adg_line_style_new(void)
238 return g_object_new(ADG_TYPE_LINE_STYLE, NULL);
242 * adg_line_style_get_width:
243 * @line_style: an #AdgLineStyle object
245 * Gets the line thickness value (in paper units).
247 * Return value: the requested width
249 gdouble
250 adg_line_style_get_width(AdgLineStyle *line_style)
252 AdgLineStylePrivate *data;
254 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), 0.);
256 data = line_style->data;
258 return data->width;
262 * adg_line_style_set_width:
263 * @line_style: an #AdgLineStyle object
264 * @width: the new width
266 * Sets a new line thickness value.
268 void
269 adg_line_style_set_width(AdgLineStyle *line_style, gdouble width)
271 AdgLineStylePrivate *data;
273 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
275 data = line_style->data;
276 data->width = width;
278 g_object_notify((GObject *) line_style, "width");
282 * adg_line_style_get_cap:
283 * @line_style: an #AdgLineStyle object
285 * Gets the line cap mode.
287 * Return value: the requested line cap mode
289 cairo_line_cap_t
290 adg_line_style_get_cap(AdgLineStyle *line_style)
292 AdgLineStylePrivate *data;
294 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
295 CAIRO_LINE_CAP_BUTT);
297 data = line_style->data;
299 return data->cap;
303 * adg_line_style_set_cap:
304 * @line_style: an #AdgLineStyle object
305 * @cap: the new cap mode
307 * Sets a new line cap mode.
309 void
310 adg_line_style_set_cap(AdgLineStyle *line_style, cairo_line_cap_t cap)
312 AdgLineStylePrivate *data;
314 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
316 data = line_style->data;
317 data->cap = cap;
319 g_object_notify((GObject *) line_style, "cap");
323 * adg_line_style_get_join:
324 * @line_style: an #AdgLineStyle object
326 * Gets the line join mode.
328 * Return value: the requested line join mode
330 cairo_line_join_t
331 adg_line_style_get_join(AdgLineStyle *line_style)
333 AdgLineStylePrivate *data;
335 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
336 CAIRO_LINE_JOIN_MITER);
338 data = line_style->data;
340 return data->join;
344 * adg_line_style_set_join:
345 * @line_style: an #AdgLineStyle object
346 * @join: the new join mode
348 * Sets a new line join mode.
350 void
351 adg_line_style_set_join(AdgLineStyle *line_style, cairo_line_join_t join)
353 AdgLineStylePrivate *data;
355 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
357 data->join = join;
358 data = line_style->data;
360 g_object_notify((GObject *) line_style, "join");
364 * adg_line_style_get_miter_limit:
365 * @line_style: an #AdgLineStyle object
367 * Gets the line miter limit value. The miter limit is used to determine
368 * whether the lines should be joined with a bevel instead of a miter.
370 * Return value: the requested miter limit
372 gdouble
373 adg_line_style_get_miter_limit(AdgLineStyle *line_style)
375 AdgLineStylePrivate *data;
377 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), 0.);
379 data = line_style->data;
381 return data->miter_limit;
385 * adg_line_style_set_miter_limit:
386 * @line_style: an #AdgLineStyle object
387 * @miter_limit: the new miter limit
389 * Sets a new miter limit value.
391 void
392 adg_line_style_set_miter_limit(AdgLineStyle *line_style,
393 gdouble miter_limit)
395 AdgLineStylePrivate *data;
397 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
399 data = line_style->data;
400 data->miter_limit = miter_limit;
402 g_object_notify((GObject *) line_style, "miter-limit");
406 * adg_line_style_get_antialias:
407 * @line_style: an #AdgLineStyle object
409 * Gets the antialias mode used.
411 * Return value: the requested antialias mode
413 cairo_antialias_t
414 adg_line_style_get_antialias(AdgLineStyle *line_style)
416 AdgLineStylePrivate *data;
418 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
419 CAIRO_ANTIALIAS_DEFAULT);
421 data = line_style->data;
423 return data->antialias;
427 * adg_line_style_set_antialias:
428 * @line_style: an #AdgLineStyle object
429 * @antialias: the new antialias mode
431 * Sets a new antialias mode.
433 void
434 adg_line_style_set_antialias(AdgLineStyle *line_style,
435 cairo_antialias_t antialias)
437 AdgLineStylePrivate *data;
439 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
441 data = line_style->data;
442 data->antialias = antialias;
444 g_object_notify((GObject *) line_style, "antialias");
448 static GPtrArray *
449 get_pool(void)
451 static GPtrArray *pool = NULL;
453 if (G_UNLIKELY(pool == NULL)) {
454 cairo_pattern_t *pattern;
456 pool = g_ptr_array_sized_new(ADG_LINE_STYLE_LAST);
458 pool->pdata[ADG_LINE_STYLE_DRAW] =
459 g_object_new(ADG_TYPE_LINE_STYLE, "width", 2., NULL);
461 pattern = cairo_pattern_create_rgb(0., 1., 0.);
462 pool->pdata[ADG_LINE_STYLE_CENTER] =
463 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
464 0.75, NULL);
465 cairo_pattern_destroy(pattern);
467 pattern = cairo_pattern_create_rgba(0., 0., 0., 0.5);
468 pool->pdata[ADG_LINE_STYLE_HIDDEN] =
469 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
470 0.75, NULL);
471 cairo_pattern_destroy(pattern);
473 pattern = cairo_pattern_create_rgb(0., 0., 1.);
474 pool->pdata[ADG_LINE_STYLE_HATCH] =
475 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
476 1.25, NULL);
477 cairo_pattern_destroy(pattern);
479 pool->pdata[ADG_LINE_STYLE_DIM] = g_object_new(ADG_TYPE_LINE_STYLE,
480 "width", 0.75,
481 NULL);
483 pool->len = ADG_LINE_STYLE_LAST;
486 return pool;
489 static void
490 apply(AdgStyle *style, cairo_t *cr)
492 AdgLineStyle *line_style;
493 AdgLineStylePrivate *data;
494 AdgStyleClass *style_class;
495 gdouble device_width;
496 gdouble dummy = 0.;
498 line_style = (AdgLineStyle *) style;
499 data = line_style->data;
500 style_class = (AdgStyleClass *) adg_line_style_parent_class;
502 if (style_class->apply != NULL)
503 style_class->apply(style, cr);
505 device_width = data->width;
506 cairo_device_to_user_distance(cr, &device_width, &dummy);
507 cairo_set_line_width(cr, device_width);
509 cairo_set_line_cap(cr, data->cap);
510 cairo_set_line_join(cr, data->join);
511 cairo_set_miter_limit(cr, data->miter_limit);
512 cairo_set_antialias(cr, data->antialias);
514 if (data->num_dashes > 0) {
515 g_return_if_fail(data->dashes != NULL);
517 cairo_set_dash(cr, data->dashes, data->num_dashes, data->dash_offset);