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 * @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.
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
38 #include "adg-line-style.h"
39 #include "adg-line-style-private.h"
40 #include "adg-context.h"
56 static void get_property (GObject
*object
,
60 static void set_property (GObject
*object
,
64 static GPtrArray
* get_pool (void);
65 static void apply (AdgStyle
*style
,
69 G_DEFINE_TYPE(AdgLineStyle
, adg_line_style
, ADG_TYPE_STYLE
)
73 adg_line_style_class_init(AdgLineStyleClass
*klass
)
75 GObjectClass
*gobject_class
;
76 AdgStyleClass
*style_class
;
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",
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",
98 P_("The line cap mode"),
99 G_MININT
, G_MAXINT
, CAIRO_LINE_CAP_ROUND
,
101 g_object_class_install_property(gobject_class
, PROP_CAP
, param
);
103 param
= g_param_spec_int("join",
105 P_("The line join mode"),
106 G_MININT
, G_MAXINT
, CAIRO_LINE_JOIN_MITER
,
108 g_object_class_install_property(gobject_class
, PROP_JOIN
, param
);
110 param
= g_param_spec_double("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
,
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
,
124 g_object_class_install_property(gobject_class
, PROP_ANTIALIAS
, param
);
126 /* TODO: PROP_DASH (PROP_DASHES, PROP_NUM_DASHES, PROP_DASH_OFFSET) */
130 adg_line_style_init(AdgLineStyle
*line_style
)
132 AdgLineStylePrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(line_style
,
134 AdgLineStylePrivate
);
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
;
142 data
->num_dashes
= 0;
143 data
->dash_offset
= 0.;
145 line_style
->data
= data
;
149 get_property(GObject
*object
,
150 guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
152 AdgLineStylePrivate
*data
= ((AdgLineStyle
*) object
)->data
;
156 g_value_set_double(value
, data
->width
);
159 g_value_set_int(value
, data
->cap
);
162 g_value_set_int(value
, data
->join
);
164 case PROP_MITER_LIMIT
:
165 g_value_set_double(value
, data
->miter_limit
);
168 g_value_set_int(value
, data
->antialias
);
174 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
180 set_property(GObject
*object
,
181 guint prop_id
, const GValue
*value
, GParamSpec
*pspec
)
183 AdgLineStylePrivate
*data
= ((AdgLineStyle
*) object
)->data
;
187 data
->width
= g_value_get_double(value
);
190 data
->cap
= g_value_get_int(value
);
193 data
->join
= g_value_get_int(value
);
195 case PROP_MITER_LIMIT
:
196 data
->miter_limit
= g_value_get_double(value
);
199 data
->antialias
= g_value_get_int(value
);
205 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
212 * adg_line_style_get_slot:
214 * Gets the slot id for this style class.
216 * Return value: the slot
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
);
230 * adg_line_style_new:
232 * Constructs a new line style initialized with default params.
234 * Return value: a new line style
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
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
;
263 * adg_line_style_set_width:
264 * @line_style: an #AdgLineStyle object
265 * @width: the new width
267 * Sets a new line thickness value.
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
;
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
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
;
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.
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
;
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
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
;
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.
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
));
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
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.
393 adg_line_style_set_miter_limit(AdgLineStyle
*line_style
,
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
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.
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");
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",
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",
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",
478 cairo_pattern_destroy(pattern
);
480 pool
->pdata
[ADG_LINE_STYLE_DIM
] = g_object_new(ADG_TYPE_LINE_STYLE
,
484 pool
->len
= ADG_LINE_STYLE_LAST
;
491 apply(AdgStyle
*style
, cairo_t
*cr
)
493 AdgLineStyle
*line_style
;
494 AdgLineStylePrivate
*data
;
495 AdgStyleClass
*style_class
;
496 gdouble device_width
;
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
);