1 #define __NR_ARENA_GROUP_C__
3 /*
4 * RGBA display list system for inkscape
5 *
6 * Author:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 *
9 * Copyright (C) 2001-2002 Lauris Kaplinski
10 * Copyright (C) 2001 Ximian, Inc.
11 *
12 * Released under GNU GPL, read the file 'COPYING' for more information
13 */
15 #include "display/nr-arena-group.h"
16 #include "display/nr-filter.h"
17 #include "display/nr-filter-gaussian.h"
18 #include "display/nr-filter-types.h"
19 #include "style.h"
20 #include "sp-filter.h"
21 #include "sp-filter-reference.h"
22 #include "sp-gaussian-blur.h"
23 #include "filters/blend.h"
24 #include "display/nr-filter-blend.h"
25 #include "helper/geom.h"
27 static void nr_arena_group_class_init (NRArenaGroupClass *klass);
28 static void nr_arena_group_init (NRArenaGroup *group);
30 static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
31 static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
32 static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
33 static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
34 static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
36 static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
37 static unsigned int nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
38 static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
39 static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
41 static NRArenaItemClass *parent_class;
43 NRType
44 nr_arena_group_get_type (void)
45 {
46 static NRType type = 0;
47 if (!type) {
48 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
49 "NRArenaGroup",
50 sizeof (NRArenaGroupClass),
51 sizeof (NRArenaGroup),
52 (void (*) (NRObjectClass *)) nr_arena_group_class_init,
53 (void (*) (NRObject *)) nr_arena_group_init);
54 }
55 return type;
56 }
58 static void
59 nr_arena_group_class_init (NRArenaGroupClass *klass)
60 {
61 NRObjectClass *object_class;
62 NRArenaItemClass *item_class;
64 object_class = (NRObjectClass *) klass;
65 item_class = (NRArenaItemClass *) klass;
67 parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
69 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
71 item_class->children = nr_arena_group_children;
72 item_class->last_child = nr_arena_group_last_child;
73 item_class->add_child = nr_arena_group_add_child;
74 item_class->set_child_position = nr_arena_group_set_child_position;
75 item_class->remove_child = nr_arena_group_remove_child;
76 item_class->update = nr_arena_group_update;
77 item_class->render = nr_arena_group_render;
78 item_class->clip = nr_arena_group_clip;
79 item_class->pick = nr_arena_group_pick;
80 }
82 static void
83 nr_arena_group_init (NRArenaGroup *group)
84 {
85 group->transparent = FALSE;
86 group->children = NULL;
87 group->last = NULL;
88 group->style = NULL;
89 group->child_transform.setIdentity();
90 }
92 static NRArenaItem *
93 nr_arena_group_children (NRArenaItem *item)
94 {
95 NRArenaGroup *group = NR_ARENA_GROUP (item);
97 return group->children;
98 }
100 static NRArenaItem *
101 nr_arena_group_last_child (NRArenaItem *item)
102 {
103 NRArenaGroup *group = NR_ARENA_GROUP (item);
105 return group->last;
106 }
108 static void
109 nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
110 {
111 NRArenaGroup *group = NR_ARENA_GROUP (item);
113 if (!ref) {
114 group->children = nr_arena_item_attach (item, child, NULL, group->children);
115 } else {
116 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
117 }
119 if (ref == group->last) group->last = child;
121 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
122 }
124 static void
125 nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
126 {
127 NRArenaGroup *group = NR_ARENA_GROUP (item);
129 if (child == group->last) group->last = child->prev;
131 if (child->prev) {
132 nr_arena_item_detach (item, child);
133 } else {
134 group->children = nr_arena_item_detach (item, child);
135 }
137 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
138 }
140 static void
141 nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
142 {
143 NRArenaGroup *group = NR_ARENA_GROUP (item);
145 if (child == group->last) group->last = child->prev;
147 if (child->prev) {
148 nr_arena_item_detach (item, child);
149 } else {
150 group->children = nr_arena_item_detach (item, child);
151 }
153 if (!ref) {
154 group->children = nr_arena_item_attach (item, child, NULL, group->children);
155 } else {
156 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
157 }
159 if (ref == group->last) group->last = child;
161 nr_arena_item_request_render (child);
162 }
164 static unsigned int
165 nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
166 {
167 unsigned int newstate;
169 NRArenaGroup *group = NR_ARENA_GROUP (item);
171 unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
173 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
174 NRGC cgc(gc);
175 cgc.transform = group->child_transform * gc->transform;
176 newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
177 beststate = beststate & newstate;
178 }
180 if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
181 nr_rect_l_set_empty (&item->bbox);
182 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
183 if (child->visible)
184 nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
185 }
186 }
188 return beststate;
189 }
191 void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
192 {
193 g_return_if_fail(group != NULL);
194 g_return_if_fail(NR_IS_ARENA_GROUP(group));
196 if (style) sp_style_ref(style);
197 if (group->style) sp_style_unref(group->style);
198 group->style = style;
200 //if group has a filter
201 if (style->filter.set && style->getFilter()) {
202 if (!group->filter) {
203 int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
204 group->filter = new Inkscape::Filters::Filter(primitives);
205 }
206 sp_filter_build_renderer(SP_FILTER(style->getFilter()), group->filter);
207 } else {
208 //no filter set for this group
209 delete group->filter;
210 group->filter = NULL;
211 }
213 if (style && style->enable_background.set
214 && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
215 group->background_new = true;
216 }
217 }
219 static unsigned int
220 nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
221 {
222 NRArenaGroup *group = NR_ARENA_GROUP (item);
224 unsigned int ret = item->state;
226 /* Just compose children into parent buffer */
227 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
228 ret = nr_arena_item_invoke_render (ct, child, area, pb, flags);
229 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
230 }
232 return ret;
233 }
235 static unsigned int
236 nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
237 {
238 NRArenaGroup *group = NR_ARENA_GROUP (item);
240 unsigned int ret = item->state;
242 /* Just compose children into parent buffer */
243 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
244 ret = nr_arena_item_invoke_clip (child, area, pb);
245 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
246 }
248 return ret;
249 }
251 static NRArenaItem *
252 nr_arena_group_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky)
253 {
254 NRArenaGroup *group = NR_ARENA_GROUP (item);
256 for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
257 NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
258 if (picked)
259 return (group->transparent) ? picked : item;
260 }
262 return NULL;
263 }
265 void
266 nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
267 {
268 nr_return_if_fail (group != NULL);
269 nr_return_if_fail (NR_IS_ARENA_GROUP (group));
271 group->transparent = transparent;
272 }
274 void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const &t)
275 {
276 Geom::Matrix nt(t);
277 nr_arena_group_set_child_transform(group, &nt);
278 }
280 void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const *t)
281 {
282 if (!t) t = &GEOM_MATRIX_IDENTITY;
284 if (!Geom::matrix_equalp(*t, group->child_transform, NR_EPSILON)) {
285 nr_arena_item_request_render (NR_ARENA_ITEM (group));
286 group->child_transform = *t;
287 nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
288 }
289 }
292 /*
293 Local Variables:
294 mode:c++
295 c-file-style:"stroustrup"
296 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
297 indent-tabs-mode:nil
298 fill-column:99
299 End:
300 */
301 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :