[build] Autogenerating all the <bookinfo> tag
[adg.git] / adg / adg-line-style.c
blob250c0310bde2fcb35e67bf9b1a2170bca4267aaa
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 * @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 /**
31 * AdgLineStyle:
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
35 **/
38 #include "adg-line-style.h"
39 #include "adg-line-style-private.h"
40 #include "adg-context.h"
41 #include "adg-intl.h"
42 #include "adg-util.h"
45 enum {
46 PROP_0,
47 PROP_WIDTH,
48 PROP_CAP,
49 PROP_JOIN,
50 PROP_MITER_LIMIT,
51 PROP_ANTIALIAS,
52 PROP_DASH
56 static void get_property (GObject *object,
57 guint prop_id,
58 GValue *value,
59 GParamSpec *pspec);
60 static void set_property (GObject *object,
61 guint prop_id,
62 const GValue *value,
63 GParamSpec *pspec);
64 static GPtrArray * get_pool (void);
65 static void apply (AdgStyle *style,
66 cairo_t *cr);
69 G_DEFINE_TYPE(AdgLineStyle, adg_line_style, ADG_TYPE_STYLE)
72 static void
73 adg_line_style_class_init(AdgLineStyleClass *klass)
75 GObjectClass *gobject_class;
76 AdgStyleClass *style_class;
77 GParamSpec *param;
79 gobject_class = (GObjectClass *) klass;
80 style_class = (AdgStyleClass *) klass;
82 g_type_class_add_private(klass, sizeof(AdgLineStylePrivate));
84 gobject_class->get_property = get_property;
85 gobject_class->set_property = set_property;
87 style_class->get_pool = get_pool;
88 style_class->apply = apply;
90 param = g_param_spec_double("width",
91 P_("Line Width"),
92 P_("The line thickness in device unit"),
93 0., G_MAXDOUBLE, 2., G_PARAM_READWRITE);
94 g_object_class_install_property(gobject_class, PROP_WIDTH, param);
96 param = g_param_spec_int("cap",
97 P_("Line Cap"),
98 P_("The line cap mode"),
99 G_MININT, G_MAXINT, CAIRO_LINE_CAP_ROUND,
100 G_PARAM_READWRITE);
101 g_object_class_install_property(gobject_class, PROP_CAP, param);
103 param = g_param_spec_int("join",
104 P_("Line Join"),
105 P_("The line join mode"),
106 G_MININT, G_MAXINT, CAIRO_LINE_JOIN_MITER,
107 G_PARAM_READWRITE);
108 g_object_class_install_property(gobject_class, PROP_JOIN, param);
110 param = g_param_spec_double("miter-limit",
111 P_("Miter Limit"),
113 ("Whether the lines should be joined with a bevel instead of a miter"),
114 0., G_MAXDOUBLE, 10., G_PARAM_READWRITE);
115 g_object_class_install_property(gobject_class, PROP_MITER_LIMIT,
116 param);
118 param = g_param_spec_int("antialias",
119 P_("Antialiasing Mode"),
121 ("Type of antialiasing to do when rendering lines"),
122 G_MININT, G_MAXINT, CAIRO_ANTIALIAS_DEFAULT,
123 G_PARAM_READWRITE);
124 g_object_class_install_property(gobject_class, PROP_ANTIALIAS, param);
126 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
129 static void
130 adg_line_style_init(AdgLineStyle *line_style)
132 AdgLineStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(line_style,
133 ADG_TYPE_LINE_STYLE,
134 AdgLineStylePrivate);
136 data->width = 2.;
137 data->cap = CAIRO_LINE_CAP_ROUND;
138 data->join = CAIRO_LINE_JOIN_MITER;
139 data->miter_limit = 10.;
140 data->antialias = CAIRO_ANTIALIAS_DEFAULT;
141 data->dashes = NULL;
142 data->num_dashes = 0;
143 data->dash_offset = 0.;
145 line_style->data = data;
148 static void
149 get_property(GObject *object,
150 guint prop_id, GValue *value, GParamSpec *pspec)
152 AdgLineStylePrivate *data = ((AdgLineStyle *) object)->data;
154 switch (prop_id) {
155 case PROP_WIDTH:
156 g_value_set_double(value, data->width);
157 break;
158 case PROP_CAP:
159 g_value_set_int(value, data->cap);
160 break;
161 case PROP_JOIN:
162 g_value_set_int(value, data->join);
163 break;
164 case PROP_MITER_LIMIT:
165 g_value_set_double(value, data->miter_limit);
166 break;
167 case PROP_ANTIALIAS:
168 g_value_set_int(value, data->antialias);
169 break;
170 case PROP_DASH:
171 /* TODO */
172 break;
173 default:
174 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
175 break;
179 static void
180 set_property(GObject *object,
181 guint prop_id, const GValue *value, GParamSpec *pspec)
183 AdgLineStylePrivate *data = ((AdgLineStyle *) object)->data;
185 switch (prop_id) {
186 case PROP_WIDTH:
187 data->width = g_value_get_double(value);
188 break;
189 case PROP_CAP:
190 data->cap = g_value_get_int(value);
191 break;
192 case PROP_JOIN:
193 data->join = g_value_get_int(value);
194 break;
195 case PROP_MITER_LIMIT:
196 data->miter_limit = g_value_get_double(value);
197 break;
198 case PROP_ANTIALIAS:
199 data->antialias = g_value_get_int(value);
200 break;
201 case PROP_DASH:
202 /* TODO */
203 break;
204 default:
205 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
206 break;
212 * adg_line_style_get_slot:
214 * Gets the slot id for this style class.
216 * Return value: the slot
218 AdgStyleSlot
219 adg_line_style_get_slot(void)
221 static AdgStyleSlot slot = -1;
223 if (G_UNLIKELY(slot < 0))
224 slot = adg_context_get_slot(ADG_TYPE_LINE_STYLE);
226 return slot;
230 * adg_line_style_new:
232 * Constructs a new line style initialized with default params.
234 * Return value: a new line style
236 AdgStyle *
237 adg_line_style_new(void)
239 return g_object_new(ADG_TYPE_LINE_STYLE, NULL);
243 * adg_line_style_get_width:
244 * @line_style: an #AdgLineStyle object
246 * Gets the line thickness value (in paper units).
248 * Return value: the requested width
250 gdouble
251 adg_line_style_get_width(AdgLineStyle *line_style)
253 AdgLineStylePrivate *data;
255 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), 0.);
257 data = line_style->data;
259 return data->width;
263 * adg_line_style_set_width:
264 * @line_style: an #AdgLineStyle object
265 * @width: the new width
267 * Sets a new line thickness value.
269 void
270 adg_line_style_set_width(AdgLineStyle *line_style, gdouble width)
272 AdgLineStylePrivate *data;
274 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
276 data = line_style->data;
277 data->width = width;
279 g_object_notify((GObject *) line_style, "width");
283 * adg_line_style_get_cap:
284 * @line_style: an #AdgLineStyle object
286 * Gets the line cap mode.
288 * Return value: the requested line cap mode
290 cairo_line_cap_t
291 adg_line_style_get_cap(AdgLineStyle *line_style)
293 AdgLineStylePrivate *data;
295 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
296 CAIRO_LINE_CAP_BUTT);
298 data = line_style->data;
300 return data->cap;
304 * adg_line_style_set_cap:
305 * @line_style: an #AdgLineStyle object
306 * @cap: the new cap mode
308 * Sets a new line cap mode.
310 void
311 adg_line_style_set_cap(AdgLineStyle *line_style, cairo_line_cap_t cap)
313 AdgLineStylePrivate *data;
315 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
317 data = line_style->data;
318 data->cap = cap;
320 g_object_notify((GObject *) line_style, "cap");
324 * adg_line_style_get_join:
325 * @line_style: an #AdgLineStyle object
327 * Gets the line join mode.
329 * Return value: the requested line join mode
331 cairo_line_join_t
332 adg_line_style_get_join(AdgLineStyle *line_style)
334 AdgLineStylePrivate *data;
336 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
337 CAIRO_LINE_JOIN_MITER);
339 data = line_style->data;
341 return data->join;
345 * adg_line_style_set_join:
346 * @line_style: an #AdgLineStyle object
347 * @join: the new join mode
349 * Sets a new line join mode.
351 void
352 adg_line_style_set_join(AdgLineStyle *line_style, cairo_line_join_t join)
354 AdgLineStylePrivate *data;
356 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
358 data->join = join;
359 data = line_style->data;
361 g_object_notify((GObject *) line_style, "join");
365 * adg_line_style_get_miter_limit:
366 * @line_style: an #AdgLineStyle object
368 * Gets the line miter limit value. The miter limit is used to determine
369 * whether the lines should be joined with a bevel instead of a miter.
371 * Return value: the requested miter limit
373 gdouble
374 adg_line_style_get_miter_limit(AdgLineStyle *line_style)
376 AdgLineStylePrivate *data;
378 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style), 0.);
380 data = line_style->data;
382 return data->miter_limit;
386 * adg_line_style_set_miter_limit:
387 * @line_style: an #AdgLineStyle object
388 * @miter_limit: the new miter limit
390 * Sets a new miter limit value.
392 void
393 adg_line_style_set_miter_limit(AdgLineStyle *line_style,
394 gdouble miter_limit)
396 AdgLineStylePrivate *data;
398 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
400 data = line_style->data;
401 data->miter_limit = miter_limit;
403 g_object_notify((GObject *) line_style, "miter-limit");
407 * adg_line_style_get_antialias:
408 * @line_style: an #AdgLineStyle object
410 * Gets the antialias mode used.
412 * Return value: the requested antialias mode
414 cairo_antialias_t
415 adg_line_style_get_antialias(AdgLineStyle *line_style)
417 AdgLineStylePrivate *data;
419 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style),
420 CAIRO_ANTIALIAS_DEFAULT);
422 data = line_style->data;
424 return data->antialias;
428 * adg_line_style_set_antialias:
429 * @line_style: an #AdgLineStyle object
430 * @antialias: the new antialias mode
432 * Sets a new antialias mode.
434 void
435 adg_line_style_set_antialias(AdgLineStyle *line_style,
436 cairo_antialias_t antialias)
438 AdgLineStylePrivate *data;
440 g_return_if_fail(ADG_IS_LINE_STYLE(line_style));
442 data = line_style->data;
443 data->antialias = antialias;
445 g_object_notify((GObject *) line_style, "antialias");
449 static GPtrArray *
450 get_pool(void)
452 static GPtrArray *pool = NULL;
454 if (G_UNLIKELY(pool == NULL)) {
455 cairo_pattern_t *pattern;
457 pool = g_ptr_array_sized_new(ADG_LINE_STYLE_LAST);
459 pool->pdata[ADG_LINE_STYLE_DRAW] =
460 g_object_new(ADG_TYPE_LINE_STYLE, "width", 2., NULL);
462 pattern = cairo_pattern_create_rgb(0., 1., 0.);
463 pool->pdata[ADG_LINE_STYLE_CENTER] =
464 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
465 0.75, NULL);
466 cairo_pattern_destroy(pattern);
468 pattern = cairo_pattern_create_rgba(0., 0., 0., 0.5);
469 pool->pdata[ADG_LINE_STYLE_HIDDEN] =
470 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
471 0.75, NULL);
472 cairo_pattern_destroy(pattern);
474 pattern = cairo_pattern_create_rgb(0., 0., 1.);
475 pool->pdata[ADG_LINE_STYLE_HATCH] =
476 g_object_new(ADG_TYPE_LINE_STYLE, "pattern", pattern, "width",
477 1.25, NULL);
478 cairo_pattern_destroy(pattern);
480 pool->pdata[ADG_LINE_STYLE_DIM] = g_object_new(ADG_TYPE_LINE_STYLE,
481 "width", 0.75,
482 NULL);
484 pool->len = ADG_LINE_STYLE_LAST;
487 return pool;
490 static void
491 apply(AdgStyle *style, cairo_t *cr)
493 AdgLineStyle *line_style;
494 AdgLineStylePrivate *data;
495 AdgStyleClass *style_class;
496 gdouble device_width;
497 gdouble dummy = 0.;
499 line_style = (AdgLineStyle *) style;
500 data = line_style->data;
501 style_class = (AdgStyleClass *) adg_line_style_parent_class;
503 if (style_class->apply != NULL)
504 style_class->apply(style, cr);
506 device_width = data->width;
507 cairo_device_to_user_distance(cr, &device_width, &dummy);
508 cairo_set_line_width(cr, device_width);
510 cairo_set_line_cap(cr, data->cap);
511 cairo_set_line_join(cr, data->join);
512 cairo_set_miter_limit(cr, data->miter_limit);
513 cairo_set_antialias(cr, data->antialias);
515 if (data->num_dashes > 0) {
516 g_return_if_fail(data->dashes != NULL);
518 cairo_set_dash(cr, data->dashes, data->num_dashes, data->dash_offset);