1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007-2008, 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 Library 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 * Library 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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
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 #include "adg-line-style.h"
31 #include "adg-line-style-private.h"
35 #define PARENT_CLASS ((AdgStyleClass *) adg_line_style_parent_class)
50 static void get_property (GObject
*object
,
54 static void set_property (GObject
*object
,
59 static AdgStyle
*from_id (gint id
);
60 static void apply (AdgStyle
*style
,
63 static GPtrArray
*pool
= NULL
;
66 G_DEFINE_TYPE (AdgLineStyle
, adg_line_style
, ADG_TYPE_STYLE
)
70 adg_line_style_class_init (AdgLineStyleClass
*klass
)
72 GObjectClass
*gobject_class
;
73 AdgStyleClass
*style_class
;
76 gobject_class
= (GObjectClass
*) klass
;
77 style_class
= (AdgStyleClass
*) klass
;
79 g_type_class_add_private (klass
, sizeof (AdgLineStylePrivate
));
81 gobject_class
->get_property
= get_property
;
82 gobject_class
->set_property
= set_property
;
84 style_class
->from_id
= from_id
;
85 style_class
->apply
= apply
;
87 param
= g_param_spec_double ("width",
89 P_("The line thickness in device unit"),
92 g_object_class_install_property (gobject_class
, PROP_WIDTH
, param
);
94 param
= g_param_spec_int ("cap",
96 P_("The line cap mode"),
97 G_MININT
, G_MAXINT
, CAIRO_LINE_CAP_ROUND
,
99 g_object_class_install_property (gobject_class
, PROP_CAP
, param
);
101 param
= g_param_spec_int ("join",
103 P_("The line join mode"),
104 G_MININT
, G_MAXINT
, CAIRO_LINE_JOIN_MITER
,
106 g_object_class_install_property (gobject_class
, PROP_JOIN
, param
);
108 param
= g_param_spec_double ("miter-limit",
110 P_("Whether the lines should be joined with a bevel instead of a miter"),
111 0., G_MAXDOUBLE
, 10.,
113 g_object_class_install_property (gobject_class
, PROP_MITER_LIMIT
, param
);
115 param
= g_param_spec_int ("antialias",
116 P_("Antialiasing Mode"),
117 P_("Type of antialiasing to do when rendering lines"),
118 G_MININT
, G_MAXINT
, CAIRO_ANTIALIAS_DEFAULT
,
120 g_object_class_install_property (gobject_class
, PROP_ANTIALIAS
, param
);
122 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
126 adg_line_style_init (AdgLineStyle
*line_style
)
128 AdgLineStylePrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (line_style
,
130 AdgLineStylePrivate
);
133 priv
->cap
= CAIRO_LINE_CAP_ROUND
;
134 priv
->join
= CAIRO_LINE_JOIN_MITER
;
135 priv
->miter_limit
= 10.;
136 priv
->antialias
= CAIRO_ANTIALIAS_DEFAULT
;
138 priv
->num_dashes
= 0;
139 priv
->dash_offset
= 0.;
141 line_style
->priv
= priv
;
145 get_property (GObject
*object
,
150 AdgLineStyle
*line_style
= (AdgLineStyle
*) object
;
155 g_value_set_double (value
, line_style
->priv
->width
);
158 g_value_set_int (value
, line_style
->priv
->cap
);
161 g_value_set_int (value
, line_style
->priv
->join
);
163 case PROP_MITER_LIMIT
:
164 g_value_set_double (value
, line_style
->priv
->miter_limit
);
167 g_value_set_int (value
, line_style
->priv
->antialias
);
173 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
179 set_property (GObject
*object
,
184 AdgLineStyle
*line_style
= (AdgLineStyle
*) object
;
189 line_style
->priv
->width
= g_value_get_double (value
);
192 line_style
->priv
->cap
= g_value_get_int (value
);
195 line_style
->priv
->join
= g_value_get_int (value
);
197 case PROP_MITER_LIMIT
:
198 line_style
->priv
->miter_limit
= g_value_get_double (value
);
201 line_style
->priv
->antialias
= g_value_get_int (value
);
207 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
214 * adg_line_style_new:
216 * Constructs a new line style initialized with default params.
218 * Return value: a new line style
221 adg_line_style_new (void)
223 return g_object_new (ADG_TYPE_LINE_STYLE
, NULL
);
227 * adg_line_style_get_width:
228 * @line_style: an #AdgLineStyle object
230 * Gets the line thickness value (in paper units).
232 * Return value: the requested width
235 adg_line_style_get_width (AdgLineStyle
*line_style
)
237 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style
), 0.);
239 return line_style
->priv
->width
;
243 * adg_line_style_set_width:
244 * @line_style: an #AdgLineStyle object
245 * @width: the new width
247 * Sets a new line thickness value.
250 adg_line_style_set_width (AdgLineStyle
*line_style
,
253 g_return_if_fail (ADG_IS_LINE_STYLE (line_style
));
255 line_style
->priv
->width
= width
;
256 g_object_notify ((GObject
*) line_style
, "width");
260 * adg_line_style_get_cap:
261 * @line_style: an #AdgLineStyle object
263 * Gets the line cap mode.
265 * Return value: the requested line cap mode
268 adg_line_style_get_cap (AdgLineStyle
*line_style
)
270 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style
), CAIRO_LINE_CAP_BUTT
);
272 return line_style
->priv
->cap
;
276 * adg_line_style_set_cap:
277 * @line_style: an #AdgLineStyle object
278 * @cap: the new cap mode
280 * Sets a new line cap mode.
283 adg_line_style_set_cap (AdgLineStyle
*line_style
,
284 cairo_line_cap_t cap
)
286 g_return_if_fail (ADG_IS_LINE_STYLE (line_style
));
288 line_style
->priv
->cap
= cap
;
289 g_object_notify ((GObject
*) line_style
, "cap");
293 * adg_line_style_get_join:
294 * @line_style: an #AdgLineStyle object
296 * Gets the line join mode.
298 * Return value: the requested line join mode
301 adg_line_style_get_join (AdgLineStyle
*line_style
)
303 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style
), CAIRO_LINE_JOIN_MITER
);
305 return line_style
->priv
->join
;
309 * adg_line_style_set_join:
310 * @line_style: an #AdgLineStyle object
311 * @join: the new join mode
313 * Sets a new line join mode.
316 adg_line_style_set_join (AdgLineStyle
*line_style
,
317 cairo_line_join_t join
)
319 g_return_if_fail (ADG_IS_LINE_STYLE (line_style
));
321 line_style
->priv
->join
= join
;
322 g_object_notify ((GObject
*) line_style
, "join");
326 * adg_line_style_get_miter_limit:
327 * @line_style: an #AdgLineStyle object
329 * Gets the line miter limit value. The miter limit is used to determine
330 * whether the lines should be joined with a bevel instead of a miter.
332 * Return value: the requested miter limit
335 adg_line_style_get_miter_limit (AdgLineStyle
*line_style
)
337 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style
), 0.);
339 return line_style
->priv
->miter_limit
;
343 * adg_line_style_set_miter_limit:
344 * @line_style: an #AdgLineStyle object
345 * @miter_limit: the new miter limit
347 * Sets a new miter limit value.
350 adg_line_style_set_miter_limit (AdgLineStyle
*line_style
,
353 g_return_if_fail (ADG_IS_LINE_STYLE (line_style
));
355 line_style
->priv
->miter_limit
= miter_limit
;
356 g_object_notify ((GObject
*) line_style
, "miter-limit");
360 * adg_line_style_get_antialias:
361 * @line_style: an #AdgLineStyle object
363 * Gets the antialias mode used.
365 * Return value: the requested antialias mode
368 adg_line_style_get_antialias (AdgLineStyle
*line_style
)
370 g_return_val_if_fail (ADG_IS_LINE_STYLE (line_style
), CAIRO_ANTIALIAS_DEFAULT
);
372 return line_style
->priv
->antialias
;
376 * adg_line_style_set_antialias:
377 * @line_style: an #AdgLineStyle object
378 * @antialias: the new antialias mode
380 * Sets a new antialias mode.
383 adg_line_style_set_antialias (AdgLineStyle
*line_style
,
384 cairo_antialias_t antialias
)
386 g_return_if_fail (ADG_IS_LINE_STYLE (line_style
));
388 line_style
->priv
->antialias
= antialias
;
389 g_object_notify ((GObject
*) line_style
, "antialias");
396 if G_UNLIKELY (pool
== NULL
)
398 cairo_pattern_t
*pattern
;
400 pool
= g_ptr_array_sized_new (ADG_LINE_STYLE_LAST
);
402 pool
->pdata
[ADG_LINE_STYLE_DRAW
] = g_object_new (ADG_TYPE_LINE_STYLE
,
406 pattern
= cairo_pattern_create_rgb (0., 1., 0.);
407 pool
->pdata
[ADG_LINE_STYLE_CENTER
] = g_object_new (ADG_TYPE_LINE_STYLE
,
411 cairo_pattern_destroy (pattern
);
413 pattern
= cairo_pattern_create_rgba (0., 0., 0., 0.5);
414 pool
->pdata
[ADG_LINE_STYLE_HIDDEN
] = g_object_new (ADG_TYPE_LINE_STYLE
,
418 cairo_pattern_destroy (pattern
);
420 pattern
= cairo_pattern_create_rgb (0., 0., 1.);
421 pool
->pdata
[ADG_LINE_STYLE_XATCH
] = g_object_new (ADG_TYPE_LINE_STYLE
,
425 cairo_pattern_destroy (pattern
);
427 pool
->pdata
[ADG_LINE_STYLE_DIM
] = g_object_new (ADG_TYPE_LINE_STYLE
,
431 pool
->len
= ADG_LINE_STYLE_LAST
;
434 g_return_val_if_fail (id
< pool
->len
, NULL
);
435 return (AdgStyle
*) g_ptr_array_index (pool
, id
);
439 apply (AdgStyle
*style
,
442 AdgLineStyle
*line_style
;
443 gdouble device_width
;
446 line_style
= (AdgLineStyle
*) style
;
448 PARENT_CLASS
->apply (style
, cr
);
450 device_width
= line_style
->priv
->width
;
451 cairo_device_to_user_distance (cr
, &device_width
, &dummy
);
452 cairo_set_line_width (cr
, device_width
);
454 cairo_set_line_cap (cr
, line_style
->priv
->cap
);
455 cairo_set_line_join (cr
, line_style
->priv
->join
);
456 cairo_set_miter_limit (cr
, line_style
->priv
->miter_limit
);
457 cairo_set_antialias (cr
, line_style
->priv
->antialias
);
459 if (line_style
->priv
->num_dashes
> 0)
461 g_return_if_fail (line_style
->priv
->dashes
!= NULL
);
463 cairo_set_dash (cr
, line_style
->priv
->dashes
, line_style
->priv
->num_dashes
,
464 line_style
->priv
->dash_offset
);