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.
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.
32 * All fields are private and should not be used directly.
33 * Use its public methods instead.
38 * ADG_SLOT_LINE_STYLE:
40 * Gets the slot id for this style class.
42 * Return value: the requested slot id
46 #include "adg-line-style.h"
47 #include "adg-line-style-private.h"
48 #include "adg-context.h"
52 #define PARENT_STYLE_CLASS ((AdgStyleClass *) adg_line_style_parent_class)
66 static void get_property (GObject
*object
,
70 static void set_property (GObject
*object
,
74 static GPtrArray
* get_pool (void);
75 static void apply (AdgStyle
*style
,
79 G_DEFINE_TYPE(AdgLineStyle
, adg_line_style
, ADG_TYPE_STYLE
);
83 adg_line_style_class_init(AdgLineStyleClass
*klass
)
85 GObjectClass
*gobject_class
;
86 AdgStyleClass
*style_class
;
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",
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",
108 P_("The line cap mode"),
109 G_MININT
, G_MAXINT
, CAIRO_LINE_CAP_ROUND
,
111 g_object_class_install_property(gobject_class
, PROP_CAP
, param
);
113 param
= g_param_spec_int("join",
115 P_("The line join mode"),
116 G_MININT
, G_MAXINT
, CAIRO_LINE_JOIN_MITER
,
118 g_object_class_install_property(gobject_class
, PROP_JOIN
, param
);
120 param
= g_param_spec_double("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
,
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
,
132 g_object_class_install_property(gobject_class
, PROP_ANTIALIAS
, param
);
134 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
138 adg_line_style_init(AdgLineStyle
*line_style
)
140 AdgLineStylePrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(line_style
,
142 AdgLineStylePrivate
);
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
;
150 data
->num_dashes
= 0;
151 data
->dash_offset
= 0.;
153 line_style
->data
= data
;
157 get_property(GObject
*object
,
158 guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
160 AdgLineStylePrivate
*data
= ((AdgLineStyle
*) object
)->data
;
164 g_value_set_double(value
, data
->width
);
167 g_value_set_int(value
, data
->cap
);
170 g_value_set_int(value
, data
->join
);
172 case PROP_MITER_LIMIT
:
173 g_value_set_double(value
, data
->miter_limit
);
176 g_value_set_int(value
, data
->antialias
);
182 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
188 set_property(GObject
*object
,
189 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
191 AdgLineStylePrivate
*data
= ((AdgLineStyle
*) object
)->data
;
195 data
->width
= g_value_get_double(value
);
198 data
->cap
= g_value_get_int(value
);
201 data
->join
= g_value_get_int(value
);
203 case PROP_MITER_LIMIT
:
204 data
->miter_limit
= g_value_get_double(value
);
207 data
->antialias
= g_value_get_int(value
);
213 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
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
);
231 * adg_line_style_new:
233 * Constructs a new line style initialized with default params.
235 * Return value: a new line style
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 * Return value: the requested width
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
;
264 * adg_line_style_set_width:
265 * @line_style: an #AdgLineStyle object
266 * @width: the new width
268 * Sets a new line thickness value.
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
;
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 * Return value: the requested line cap mode
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
;
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.
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
;
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 * Return value: the requested line join mode
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
;
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.
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
));
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 * Return value: the requested miter limit
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.
394 adg_line_style_set_miter_limit(AdgLineStyle
*line_style
,
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 * Return value: the requested antialias mode
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.
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");
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",
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",
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",
479 cairo_pattern_destroy(pattern
);
481 pool
->pdata
[ADG_LINE_STYLE_DIM
] = g_object_new(ADG_TYPE_LINE_STYLE
,
485 pool
->len
= ADG_LINE_STYLE_LAST
;
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
);