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"
47 static void get_property (GObject
*object
,
51 static void set_property (GObject
*object
,
55 static GPtrArray
* get_pool (void);
56 static void apply (AdgStyle
*style
,
60 G_DEFINE_TYPE(AdgLineStyle
, adg_line_style
, ADG_TYPE_STYLE
)
64 adg_line_style_class_init(AdgLineStyleClass
*klass
)
66 GObjectClass
*gobject_class
;
67 AdgStyleClass
*style_class
;
70 gobject_class
= (GObjectClass
*) klass
;
71 style_class
= (AdgStyleClass
*) klass
;
73 g_type_class_add_private(klass
, sizeof(AdgLineStylePrivate
));
75 gobject_class
->get_property
= get_property
;
76 gobject_class
->set_property
= set_property
;
78 style_class
->get_pool
= get_pool
;
79 style_class
->apply
= apply
;
81 param
= g_param_spec_double("width",
83 P_("The line thickness in device unit"),
84 0., G_MAXDOUBLE
, 2., G_PARAM_READWRITE
);
85 g_object_class_install_property(gobject_class
, PROP_WIDTH
, param
);
87 param
= g_param_spec_int("cap",
89 P_("The line cap mode"),
90 G_MININT
, G_MAXINT
, CAIRO_LINE_CAP_ROUND
,
92 g_object_class_install_property(gobject_class
, PROP_CAP
, param
);
94 param
= g_param_spec_int("join",
96 P_("The line join mode"),
97 G_MININT
, G_MAXINT
, CAIRO_LINE_JOIN_MITER
,
99 g_object_class_install_property(gobject_class
, PROP_JOIN
, param
);
101 param
= g_param_spec_double("miter-limit",
104 ("Whether the lines should be joined with a bevel instead of a miter"),
105 0., G_MAXDOUBLE
, 10., G_PARAM_READWRITE
);
106 g_object_class_install_property(gobject_class
, PROP_MITER_LIMIT
,
109 param
= g_param_spec_int("antialias",
110 P_("Antialiasing Mode"),
112 ("Type of antialiasing to do when rendering lines"),
113 G_MININT
, G_MAXINT
, CAIRO_ANTIALIAS_DEFAULT
,
115 g_object_class_install_property(gobject_class
, PROP_ANTIALIAS
, param
);
117 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
121 adg_line_style_init(AdgLineStyle
*line_style
)
123 AdgLineStylePrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE(line_style
,
125 AdgLineStylePrivate
);
128 priv
->cap
= CAIRO_LINE_CAP_ROUND
;
129 priv
->join
= CAIRO_LINE_JOIN_MITER
;
130 priv
->miter_limit
= 10.;
131 priv
->antialias
= CAIRO_ANTIALIAS_DEFAULT
;
133 priv
->num_dashes
= 0;
134 priv
->dash_offset
= 0.;
136 line_style
->priv
= priv
;
140 get_property(GObject
*object
,
141 guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
143 AdgLineStyle
*line_style
= (AdgLineStyle
*) object
;
147 g_value_set_double(value
, line_style
->priv
->width
);
150 g_value_set_int(value
, line_style
->priv
->cap
);
153 g_value_set_int(value
, line_style
->priv
->join
);
155 case PROP_MITER_LIMIT
:
156 g_value_set_double(value
, line_style
->priv
->miter_limit
);
159 g_value_set_int(value
, line_style
->priv
->antialias
);
165 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
171 set_property(GObject
*object
,
172 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
174 AdgLineStyle
*line_style
= (AdgLineStyle
*) object
;
178 line_style
->priv
->width
= g_value_get_double(value
);
181 line_style
->priv
->cap
= g_value_get_int(value
);
184 line_style
->priv
->join
= g_value_get_int(value
);
186 case PROP_MITER_LIMIT
:
187 line_style
->priv
->miter_limit
= g_value_get_double(value
);
190 line_style
->priv
->antialias
= g_value_get_int(value
);
196 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
203 * adg_line_style_get_slot:
205 * Gets the slot id for this style class.
207 * Return value: the slot
210 adg_line_style_get_slot(void)
212 static AdgStyleSlot slot
= -1;
214 if (G_UNLIKELY(slot
< 0))
215 slot
= adg_context_get_slot(ADG_TYPE_LINE_STYLE
);
221 * adg_line_style_new:
223 * Constructs a new line style initialized with default params.
225 * Return value: a new line style
228 adg_line_style_new(void)
230 return g_object_new(ADG_TYPE_LINE_STYLE
, NULL
);
234 * adg_line_style_get_width:
235 * @line_style: an #AdgLineStyle object
237 * Gets the line thickness value (in paper units).
239 * Return value: the requested width
242 adg_line_style_get_width(AdgLineStyle
*line_style
)
244 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
), 0.);
246 return line_style
->priv
->width
;
250 * adg_line_style_set_width:
251 * @line_style: an #AdgLineStyle object
252 * @width: the new width
254 * Sets a new line thickness value.
257 adg_line_style_set_width(AdgLineStyle
*line_style
, gdouble width
)
259 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
261 line_style
->priv
->width
= width
;
262 g_object_notify((GObject
*) line_style
, "width");
266 * adg_line_style_get_cap:
267 * @line_style: an #AdgLineStyle object
269 * Gets the line cap mode.
271 * Return value: the requested line cap mode
274 adg_line_style_get_cap(AdgLineStyle
*line_style
)
276 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
),
277 CAIRO_LINE_CAP_BUTT
);
279 return line_style
->priv
->cap
;
283 * adg_line_style_set_cap:
284 * @line_style: an #AdgLineStyle object
285 * @cap: the new cap mode
287 * Sets a new line cap mode.
290 adg_line_style_set_cap(AdgLineStyle
*line_style
, cairo_line_cap_t cap
)
292 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
294 line_style
->priv
->cap
= cap
;
295 g_object_notify((GObject
*) line_style
, "cap");
299 * adg_line_style_get_join:
300 * @line_style: an #AdgLineStyle object
302 * Gets the line join mode.
304 * Return value: the requested line join mode
307 adg_line_style_get_join(AdgLineStyle
*line_style
)
309 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
),
310 CAIRO_LINE_JOIN_MITER
);
312 return line_style
->priv
->join
;
316 * adg_line_style_set_join:
317 * @line_style: an #AdgLineStyle object
318 * @join: the new join mode
320 * Sets a new line join mode.
323 adg_line_style_set_join(AdgLineStyle
*line_style
, cairo_line_join_t join
)
325 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
327 line_style
->priv
->join
= join
;
328 g_object_notify((GObject
*) line_style
, "join");
332 * adg_line_style_get_miter_limit:
333 * @line_style: an #AdgLineStyle object
335 * Gets the line miter limit value. The miter limit is used to determine
336 * whether the lines should be joined with a bevel instead of a miter.
338 * Return value: the requested miter limit
341 adg_line_style_get_miter_limit(AdgLineStyle
*line_style
)
343 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
), 0.);
345 return line_style
->priv
->miter_limit
;
349 * adg_line_style_set_miter_limit:
350 * @line_style: an #AdgLineStyle object
351 * @miter_limit: the new miter limit
353 * Sets a new miter limit value.
356 adg_line_style_set_miter_limit(AdgLineStyle
*line_style
,
359 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
361 line_style
->priv
->miter_limit
= miter_limit
;
362 g_object_notify((GObject
*) line_style
, "miter-limit");
366 * adg_line_style_get_antialias:
367 * @line_style: an #AdgLineStyle object
369 * Gets the antialias mode used.
371 * Return value: the requested antialias mode
374 adg_line_style_get_antialias(AdgLineStyle
*line_style
)
376 g_return_val_if_fail(ADG_IS_LINE_STYLE(line_style
),
377 CAIRO_ANTIALIAS_DEFAULT
);
379 return line_style
->priv
->antialias
;
383 * adg_line_style_set_antialias:
384 * @line_style: an #AdgLineStyle object
385 * @antialias: the new antialias mode
387 * Sets a new antialias mode.
390 adg_line_style_set_antialias(AdgLineStyle
*line_style
,
391 cairo_antialias_t antialias
)
393 g_return_if_fail(ADG_IS_LINE_STYLE(line_style
));
395 line_style
->priv
->antialias
= antialias
;
396 g_object_notify((GObject
*) line_style
, "antialias");
403 static GPtrArray
*pool
= NULL
;
405 if (G_UNLIKELY(pool
== NULL
)) {
406 cairo_pattern_t
*pattern
;
408 pool
= g_ptr_array_sized_new(ADG_LINE_STYLE_LAST
);
410 pool
->pdata
[ADG_LINE_STYLE_DRAW
] =
411 g_object_new(ADG_TYPE_LINE_STYLE
, "width", 2., NULL
);
413 pattern
= cairo_pattern_create_rgb(0., 1., 0.);
414 pool
->pdata
[ADG_LINE_STYLE_CENTER
] =
415 g_object_new(ADG_TYPE_LINE_STYLE
, "pattern", pattern
, "width",
417 cairo_pattern_destroy(pattern
);
419 pattern
= cairo_pattern_create_rgba(0., 0., 0., 0.5);
420 pool
->pdata
[ADG_LINE_STYLE_HIDDEN
] =
421 g_object_new(ADG_TYPE_LINE_STYLE
, "pattern", pattern
, "width",
423 cairo_pattern_destroy(pattern
);
425 pattern
= cairo_pattern_create_rgb(0., 0., 1.);
426 pool
->pdata
[ADG_LINE_STYLE_HATCH
] =
427 g_object_new(ADG_TYPE_LINE_STYLE
, "pattern", pattern
, "width",
429 cairo_pattern_destroy(pattern
);
431 pool
->pdata
[ADG_LINE_STYLE_DIM
] = g_object_new(ADG_TYPE_LINE_STYLE
,
435 pool
->len
= ADG_LINE_STYLE_LAST
;
442 apply(AdgStyle
*style
, cairo_t
*cr
)
444 AdgLineStyle
*line_style
;
445 AdgStyleClass
*style_class
;
446 gdouble device_width
;
449 line_style
= (AdgLineStyle
*) style
;
450 style_class
= (AdgStyleClass
*) adg_line_style_parent_class
;
452 if (style_class
->apply
!= NULL
)
453 style_class
->apply(style
, cr
);
455 device_width
= line_style
->priv
->width
;
456 cairo_device_to_user_distance(cr
, &device_width
, &dummy
);
457 cairo_set_line_width(cr
, device_width
);
459 cairo_set_line_cap(cr
, line_style
->priv
->cap
);
460 cairo_set_line_join(cr
, line_style
->priv
->join
);
461 cairo_set_miter_limit(cr
, line_style
->priv
->miter_limit
);
462 cairo_set_antialias(cr
, line_style
->priv
->antialias
);
464 if (line_style
->priv
->num_dashes
> 0) {
465 g_return_if_fail(line_style
->priv
->dashes
!= NULL
);
467 cairo_set_dash(cr
, line_style
->priv
->dashes
,
468 line_style
->priv
->num_dashes
,
469 line_style
->priv
->dash_offset
);