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 * @title: AdgLineStyle
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 #include "adg-line-style.h"
30 #include "adg-line-style-private.h"
31 #include "adg-context.h"
35 #define PARENT_CLASS ((AdgStyleClass *) adg_line_style_parent_class)
49 static void get_property (GObject
*object
,
53 static void set_property (GObject
*object
,
57 static GPtrArray
* get_pool (void);
58 static void apply (AdgStyle
*style
,
62 G_DEFINE_TYPE(AdgLineStyle
, adg_line_style
, ADG_TYPE_STYLE
)
66 adg_line_style_class_init(AdgLineStyleClass
*klass
)
68 GObjectClass
*gobject_class
;
69 AdgStyleClass
*style_class
;
72 gobject_class
= (GObjectClass
*) klass
;
73 style_class
= (AdgStyleClass
*) klass
;
75 g_type_class_add_private(klass
, sizeof(AdgLineStylePrivate
));
77 gobject_class
->get_property
= get_property
;
78 gobject_class
->set_property
= set_property
;
80 style_class
->get_pool
= get_pool
;
81 style_class
->apply
= apply
;
83 param
= g_param_spec_double("width",
85 P_("The line thickness in device unit"),
86 0., G_MAXDOUBLE
, 2., G_PARAM_READWRITE
);
87 g_object_class_install_property(gobject_class
, PROP_WIDTH
, param
);
89 param
= g_param_spec_int("cap",
91 P_("The line cap mode"),
92 G_MININT
, G_MAXINT
, CAIRO_LINE_CAP_ROUND
,
94 g_object_class_install_property(gobject_class
, PROP_CAP
, param
);
96 param
= g_param_spec_int("join",
98 P_("The line join mode"),
99 G_MININT
, G_MAXINT
, CAIRO_LINE_JOIN_MITER
,
101 g_object_class_install_property(gobject_class
, PROP_JOIN
, param
);
103 param
= g_param_spec_double("miter-limit",
106 ("Whether the lines should be joined with a bevel instead of a miter"),
107 0., G_MAXDOUBLE
, 10., G_PARAM_READWRITE
);
108 g_object_class_install_property(gobject_class
, PROP_MITER_LIMIT
,
111 param
= g_param_spec_int("antialias",
112 P_("Antialiasing Mode"),
114 ("Type of antialiasing to do when rendering lines"),
115 G_MININT
, G_MAXINT
, CAIRO_ANTIALIAS_DEFAULT
,
117 g_object_class_install_property(gobject_class
, PROP_ANTIALIAS
, param
);
119 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
123 adg_line_style_init(AdgLineStyle
*line_style
)
125 AdgLineStylePrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE(line_style
,
127 AdgLineStylePrivate
);
130 priv
->cap
= CAIRO_LINE_CAP_ROUND
;
131 priv
->join
= CAIRO_LINE_JOIN_MITER
;
132 priv
->miter_limit
= 10.;
133 priv
->antialias
= CAIRO_ANTIALIAS_DEFAULT
;
135 priv
->num_dashes
= 0;
136 priv
->dash_offset
= 0.;
138 line_style
->priv
= priv
;
142 get_property(GObject
*object
,
143 guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
145 AdgLineStyle
*line_style
= (AdgLineStyle
*) object
;
149 g_value_set_double(value
, line_style
->priv
->width
);
152 g_value_set_int(value
, line_style
->priv
->cap
);
155 g_value_set_int(value
, line_style
->priv
->join
);
157 case PROP_MITER_LIMIT
:
158 g_value_set_double(value
, line_style
->priv
->miter_limit
);
161 g_value_set_int(value
, line_style
->priv
->antialias
);
167 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
173 set_property(GObject
*object
,
174 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
176 AdgLineStyle
*line_style
= (AdgLineStyle
*) object
;
180 line_style
->priv
->width
= g_value_get_double(value
);
183 line_style
->priv
->cap
= g_value_get_int(value
);
186 line_style
->priv
->join
= g_value_get_int(value
);
188 case PROP_MITER_LIMIT
:
189 line_style
->priv
->miter_limit
= g_value_get_double(value
);
192 line_style
->priv
->antialias
= g_value_get_int(value
);
198 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
205 * adg_line_style_get_slot:
207 * Gets the slot id for this style class.
209 * Return value: the slot
212 adg_line_style_get_slot(void)
214 static AdgStyleSlot slot
= -1;
216 if (G_UNLIKELY(slot
< 0))
217 slot
= adg_context_get_slot(ADG_TYPE_LINE_STYLE
);
223 * adg_line_style_new:
225 * Constructs a new line style initialized with default params.
227 * Return value: a new line style
230 adg_line_style_new(void)
232 return g_object_new(ADG_TYPE_LINE_STYLE
, NULL
);
236 * adg_line_style_get_width:
237 * @line_style: an #AdgLineStyle object
239 * Gets the line thickness value (in paper units).
241 * Return value: the requested width
244 adg_line_style_get_width(AdgLineStyle
*line_style
)
246 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
), 0.);
248 return line_style
->priv
->width
;
252 * adg_line_style_set_width:
253 * @line_style: an #AdgLineStyle object
254 * @width: the new width
256 * Sets a new line thickness value.
259 adg_line_style_set_width(AdgLineStyle
*line_style
, gdouble width
)
261 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
263 line_style
->priv
->width
= width
;
264 g_object_notify((GObject
*) line_style
, "width");
268 * adg_line_style_get_cap:
269 * @line_style: an #AdgLineStyle object
271 * Gets the line cap mode.
273 * Return value: the requested line cap mode
276 adg_line_style_get_cap(AdgLineStyle
*line_style
)
278 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
),
279 CAIRO_LINE_CAP_BUTT
);
281 return line_style
->priv
->cap
;
285 * adg_line_style_set_cap:
286 * @line_style: an #AdgLineStyle object
287 * @cap: the new cap mode
289 * Sets a new line cap mode.
292 adg_line_style_set_cap(AdgLineStyle
*line_style
, cairo_line_cap_t cap
)
294 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
296 line_style
->priv
->cap
= cap
;
297 g_object_notify((GObject
*) line_style
, "cap");
301 * adg_line_style_get_join:
302 * @line_style: an #AdgLineStyle object
304 * Gets the line join mode.
306 * Return value: the requested line join mode
309 adg_line_style_get_join(AdgLineStyle
*line_style
)
311 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
),
312 CAIRO_LINE_JOIN_MITER
);
314 return line_style
->priv
->join
;
318 * adg_line_style_set_join:
319 * @line_style: an #AdgLineStyle object
320 * @join: the new join mode
322 * Sets a new line join mode.
325 adg_line_style_set_join(AdgLineStyle
*line_style
, cairo_line_join_t join
)
327 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
329 line_style
->priv
->join
= join
;
330 g_object_notify((GObject
*) line_style
, "join");
334 * adg_line_style_get_miter_limit:
335 * @line_style: an #AdgLineStyle object
337 * Gets the line miter limit value. The miter limit is used to determine
338 * whether the lines should be joined with a bevel instead of a miter.
340 * Return value: the requested miter limit
343 adg_line_style_get_miter_limit(AdgLineStyle
*line_style
)
345 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
), 0.);
347 return line_style
->priv
->miter_limit
;
351 * adg_line_style_set_miter_limit:
352 * @line_style: an #AdgLineStyle object
353 * @miter_limit: the new miter limit
355 * Sets a new miter limit value.
358 adg_line_style_set_miter_limit(AdgLineStyle
*line_style
,
361 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
363 line_style
->priv
->miter_limit
= miter_limit
;
364 g_object_notify((GObject
*) line_style
, "miter-limit");
368 * adg_line_style_get_antialias:
369 * @line_style: an #AdgLineStyle object
371 * Gets the antialias mode used.
373 * Return value: the requested antialias mode
376 adg_line_style_get_antialias(AdgLineStyle
*line_style
)
378 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
),
379 CAIRO_ANTIALIAS_DEFAULT
);
381 return line_style
->priv
->antialias
;
385 * adg_line_style_set_antialias:
386 * @line_style: an #AdgLineStyle object
387 * @antialias: the new antialias mode
389 * Sets a new antialias mode.
392 adg_line_style_set_antialias(AdgLineStyle
*line_style
,
393 cairo_antialias_t antialias
)
395 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
397 line_style
->priv
->antialias
= antialias
;
398 g_object_notify((GObject
*) line_style
, "antialias");
405 static GPtrArray
*pool
= NULL
;
407 if (G_UNLIKELY(pool
== NULL
)) {
408 cairo_pattern_t
*pattern
;
410 pool
= g_ptr_array_sized_new(ADG_LINE_STYLE_LAST
);
412 pool
->pdata
[ADG_LINE_STYLE_DRAW
] =
413 g_object_new(ADG_TYPE_LINE_STYLE
, "width", 2., NULL
);
415 pattern
= cairo_pattern_create_rgb(0., 1., 0.);
416 pool
->pdata
[ADG_LINE_STYLE_CENTER
] =
417 g_object_new(ADG_TYPE_LINE_STYLE
, "pattern", pattern
, "width",
419 cairo_pattern_destroy(pattern
);
421 pattern
= cairo_pattern_create_rgba(0., 0., 0., 0.5);
422 pool
->pdata
[ADG_LINE_STYLE_HIDDEN
] =
423 g_object_new(ADG_TYPE_LINE_STYLE
, "pattern", pattern
, "width",
425 cairo_pattern_destroy(pattern
);
427 pattern
= cairo_pattern_create_rgb(0., 0., 1.);
428 pool
->pdata
[ADG_LINE_STYLE_HATCH
] =
429 g_object_new(ADG_TYPE_LINE_STYLE
, "pattern", pattern
, "width",
431 cairo_pattern_destroy(pattern
);
433 pool
->pdata
[ADG_LINE_STYLE_DIM
] = g_object_new(ADG_TYPE_LINE_STYLE
,
437 pool
->len
= ADG_LINE_STYLE_LAST
;
444 apply(AdgStyle
*style
, cairo_t
*cr
)
446 AdgLineStyle
*line_style
;
447 gdouble device_width
;
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) {
464 g_return_if_fail(line_style
->priv
->dashes
!= NULL
);
466 cairo_set_dash(cr
, line_style
->priv
->dashes
,
467 line_style
->priv
->num_dashes
,
468 line_style
->priv
->dash_offset
);