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-gaussian-blur.h"
22 #include "sp-feblend.h"
23 #include "display/nr-filter-blend.h"
25 static void nr_arena_group_class_init (NRArenaGroupClass *klass);
26 static void nr_arena_group_init (NRArenaGroup *group);
28 static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
29 static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
30 static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
31 static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
32 static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
34 static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
35 static unsigned int nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
36 static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
37 static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky);
39 static NRArenaItemClass *parent_class;
41 NRType
42 nr_arena_group_get_type (void)
43 {
44 static NRType type = 0;
45 if (!type) {
46 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
47 "NRArenaGroup",
48 sizeof (NRArenaGroupClass),
49 sizeof (NRArenaGroup),
50 (void (*) (NRObjectClass *)) nr_arena_group_class_init,
51 (void (*) (NRObject *)) nr_arena_group_init);
52 }
53 return type;
54 }
56 static void
57 nr_arena_group_class_init (NRArenaGroupClass *klass)
58 {
59 NRObjectClass *object_class;
60 NRArenaItemClass *item_class;
62 object_class = (NRObjectClass *) klass;
63 item_class = (NRArenaItemClass *) klass;
65 parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
67 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
69 item_class->children = nr_arena_group_children;
70 item_class->last_child = nr_arena_group_last_child;
71 item_class->add_child = nr_arena_group_add_child;
72 item_class->set_child_position = nr_arena_group_set_child_position;
73 item_class->remove_child = nr_arena_group_remove_child;
74 item_class->update = nr_arena_group_update;
75 item_class->render = nr_arena_group_render;
76 item_class->clip = nr_arena_group_clip;
77 item_class->pick = nr_arena_group_pick;
78 }
80 static void
81 nr_arena_group_init (NRArenaGroup *group)
82 {
83 group->transparent = FALSE;
84 group->children = NULL;
85 group->last = NULL;
86 group->style = NULL;
87 nr_matrix_set_identity (&group->child_transform);
88 }
90 static NRArenaItem *
91 nr_arena_group_children (NRArenaItem *item)
92 {
93 NRArenaGroup *group = NR_ARENA_GROUP (item);
95 return group->children;
96 }
98 static NRArenaItem *
99 nr_arena_group_last_child (NRArenaItem *item)
100 {
101 NRArenaGroup *group = NR_ARENA_GROUP (item);
103 return group->last;
104 }
106 static void
107 nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
108 {
109 NRArenaGroup *group = NR_ARENA_GROUP (item);
111 if (!ref) {
112 group->children = nr_arena_item_attach (item, child, NULL, group->children);
113 } else {
114 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
115 }
117 if (ref == group->last) group->last = child;
119 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
120 }
122 static void
123 nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
124 {
125 NRArenaGroup *group = NR_ARENA_GROUP (item);
127 if (child == group->last) group->last = child->prev;
129 if (child->prev) {
130 nr_arena_item_detach (item, child);
131 } else {
132 group->children = nr_arena_item_detach (item, child);
133 }
135 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
136 }
138 static void
139 nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
140 {
141 NRArenaGroup *group = NR_ARENA_GROUP (item);
143 if (child == group->last) group->last = child->prev;
145 if (child->prev) {
146 nr_arena_item_detach (item, child);
147 } else {
148 group->children = nr_arena_item_detach (item, child);
149 }
151 if (!ref) {
152 group->children = nr_arena_item_attach (item, child, NULL, group->children);
153 } else {
154 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
155 }
157 if (ref == group->last) group->last = child;
159 nr_arena_item_request_render (child);
160 }
162 static unsigned int
163 nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
164 {
165 unsigned int newstate;
167 NRArenaGroup *group = NR_ARENA_GROUP (item);
169 unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
171 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
172 NRGC cgc(gc);
173 nr_matrix_multiply (&cgc.transform, &group->child_transform, &gc->transform);
174 newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
175 beststate = beststate & newstate;
176 }
178 if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
179 nr_rect_l_set_empty (&item->bbox);
180 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
181 nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
182 }
183 }
185 return beststate;
186 }
188 void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
189 {
190 g_return_if_fail(group != NULL);
191 g_return_if_fail(NR_IS_ARENA_GROUP(group));
193 if (style) sp_style_ref(style);
194 if (group->style) sp_style_unref(group->style);
195 group->style = style;
197 //if group has a filter
198 if (style->filter.set && style->filter.filter) {
199 if (!group->filter) {
200 int primitives = sp_filter_primitive_count(style->filter.filter);
201 group->filter = new NR::Filter(primitives);
202 }
203 sp_filter_build_renderer(style->filter.filter, group->filter);
204 } else {
205 //no filter set for this group
206 delete group->filter;
207 group->filter = NULL;
208 }
210 if (style && style->enable_background.set
211 && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
212 group->background_new = true;
213 }
214 }
216 static unsigned int
217 nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
218 {
219 NRArenaGroup *group = NR_ARENA_GROUP (item);
221 unsigned int ret = item->state;
223 /* Just compose children into parent buffer */
224 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
225 ret = nr_arena_item_invoke_render (ct, child, area, pb, flags);
226 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
227 }
229 return ret;
230 }
232 static unsigned int
233 nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
234 {
235 NRArenaGroup *group = NR_ARENA_GROUP (item);
237 unsigned int ret = item->state;
239 /* Just compose children into parent buffer */
240 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
241 ret = nr_arena_item_invoke_clip (child, area, pb);
242 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
243 }
245 return ret;
246 }
248 static NRArenaItem *
249 nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky)
250 {
251 NRArenaGroup *group = NR_ARENA_GROUP (item);
253 for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
254 NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
255 if (picked)
256 return (group->transparent) ? picked : item;
257 }
259 return NULL;
260 }
262 void
263 nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
264 {
265 nr_return_if_fail (group != NULL);
266 nr_return_if_fail (NR_IS_ARENA_GROUP (group));
268 group->transparent = transparent;
269 }
271 void nr_arena_group_set_child_transform(NRArenaGroup *group, NR::Matrix const &t)
272 {
273 NRMatrix nt(t);
274 nr_arena_group_set_child_transform(group, &nt);
275 }
277 void nr_arena_group_set_child_transform(NRArenaGroup *group, NRMatrix const *t)
278 {
279 if (!t) t = &NR_MATRIX_IDENTITY;
281 if (!NR_MATRIX_DF_TEST_CLOSE (t, &group->child_transform, NR_EPSILON)) {
282 nr_arena_item_request_render (NR_ARENA_ITEM (group));
283 group->child_transform = *t;
284 nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
285 }
286 }
288 /*
289 Local Variables:
290 mode:c++
291 c-file-style:"stroustrup"
292 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
293 indent-tabs-mode:nil
294 fill-column:99
295 End:
296 */
297 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :