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 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 * @short_description: A stroked path entity
25 * The #AdgPath object is peraphs the simplest entity.
27 * It contains a pointer to the desired #cairo_path_t structure.
31 #include "adg-path-private.h"
32 #include "adg-line-style.h"
34 #include "adg-canvas.h"
38 #define PARENT_CLASS ((AdgEntityClass *) adg_path_parent_class)
41 static void finalize (GObject
*object
);
42 static void invalidate (AdgEntity
*entity
);
43 static void render (AdgEntity
*entity
,
45 static void clear_path_cache (AdgPath
*path
);
48 G_DEFINE_TYPE(AdgPath
, adg_path
, ADG_TYPE_ENTITY
)
52 adg_path_class_init(AdgPathClass
*klass
)
54 GObjectClass
*gobject_class
;
55 AdgEntityClass
*entity_class
;
57 gobject_class
= (GObjectClass
*) klass
;
58 entity_class
= (AdgEntityClass
*) klass
;
60 g_type_class_add_private(klass
, sizeof(AdgPathPrivate
));
62 gobject_class
->finalize
= finalize
;
64 entity_class
->invalidate
= invalidate
;
65 entity_class
->render
= render
;
69 adg_path_init(AdgPath
*path
)
71 AdgPathPrivate
*priv
= G_TYPE_INSTANCE_GET_PRIVATE(path
, ADG_TYPE_PATH
,
76 priv
->cairo_path
= NULL
;
77 priv
->callback
= NULL
;
83 finalize(GObject
*object
)
85 clear_path_cache((AdgPath
*) object
);
87 ((GObjectClass
*) PARENT_CLASS
)->finalize(object
);
92 * @callback: an #AdgCallback callback
94 * Creates a new path entity. The path must be constructed in the @callback
95 * function: AdgPath will cache and reuse the cairo_copy_path() returned by
96 * the cairo context after the @callback call.
98 * Return value: the new entity
101 adg_path_new(AdgCallback callback
)
105 entity
= (AdgEntity
*) g_object_new(ADG_TYPE_PATH
, NULL
);
106 ((AdgPath
*) entity
)->priv
->callback
= callback
;
112 adg_path_get_cairo_path(AdgPath
*path
)
114 g_return_val_if_fail(ADG_IS_PATH(path
), NULL
);
116 return path
->priv
->cairo_path
;
120 adg_path_dump(AdgPath
*path
)
122 cairo_path_data_t
*data
;
123 gint n_data
, n_point
;
125 g_return_if_fail(ADG_IS_PATH(path
));
127 if (path
->priv
->cairo_path
->data
== NULL
)
130 for (n_data
= 0; n_data
< path
->priv
->cairo_path
->num_data
; ++n_data
) {
131 data
= path
->priv
->cairo_path
->data
+ n_data
;
133 switch (data
->header
.type
) {
134 case CAIRO_PATH_MOVE_TO
:
137 case CAIRO_PATH_LINE_TO
:
140 case CAIRO_PATH_CURVE_TO
:
141 g_print("Curve to ");
143 case CAIRO_PATH_CLOSE_PATH
:
144 g_print("Path close");
147 g_print("Unknown entity (%d)", data
->header
.type
);
151 for (n_point
= 1; n_point
< data
->header
.length
; ++n_point
)
152 g_print("(%lf, %lf) ", data
[n_point
].point
.x
,
153 data
[n_point
].point
.y
);
155 n_data
+= n_point
- 1;
162 invalidate(AdgEntity
*entity
)
164 clear_path_cache((AdgPath
*) entity
);
166 PARENT_CLASS
->invalidate(entity
);
170 render(AdgEntity
*entity
, cairo_t
*cr
)
172 AdgPath
*path
= (AdgPath
*) entity
;
174 if (path
->priv
->cairo_path
) {
175 /* Use cached data */
176 cairo_move_to(cr
, path
->priv
->cp
.x
, path
->priv
->cp
.y
);
177 cairo_append_path(cr
, path
->priv
->cairo_path
);
179 /* Construct and store the cache */
180 cairo_get_current_point(cr
, &path
->priv
->cp
.x
, &path
->priv
->cp
.y
);
182 if (path
->priv
->callback
)
183 path
->priv
->callback(entity
, cr
);
185 path
->priv
->cairo_path
= cairo_copy_path(cr
);
188 adg_entity_apply(entity
, ADG_SLOT_LINE_STYLE
, cr
);
191 PARENT_CLASS
->render(entity
, cr
);
195 clear_path_cache(AdgPath
*path
)
197 AdgPathPrivate
*priv
= path
->priv
;
199 if (priv
->cairo_path
!= NULL
) {
200 cairo_path_destroy(priv
->cairo_path
);
201 priv
->cairo_path
= NULL
;
204 priv
->cp
.x
= priv
->cp
.y
= 0.;