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 "sp-feblend.h"
24 #include "display/nr-filter-blend.h"
25 #include "libnr/nr-matrix-fns.h"
26 #include "libnr/nr-matrix-ops.h"
28 static void nr_arena_group_class_init (NRArenaGroupClass *klass);
29 static void nr_arena_group_init (NRArenaGroup *group);
31 static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
32 static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
33 static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
34 static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
35 static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
37 static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
38 static unsigned int nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
39 static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
40 static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky);
42 static NRArenaItemClass *parent_class;
44 NRType
45 nr_arena_group_get_type (void)
46 {
47 static NRType type = 0;
48 if (!type) {
49 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
50 "NRArenaGroup",
51 sizeof (NRArenaGroupClass),
52 sizeof (NRArenaGroup),
53 (void (*) (NRObjectClass *)) nr_arena_group_class_init,
54 (void (*) (NRObject *)) nr_arena_group_init);
55 }
56 return type;
57 }
59 static void
60 nr_arena_group_class_init (NRArenaGroupClass *klass)
61 {
62 NRObjectClass *object_class;
63 NRArenaItemClass *item_class;
65 object_class = (NRObjectClass *) klass;
66 item_class = (NRArenaItemClass *) klass;
68 parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
70 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
72 item_class->children = nr_arena_group_children;
73 item_class->last_child = nr_arena_group_last_child;
74 item_class->add_child = nr_arena_group_add_child;
75 item_class->set_child_position = nr_arena_group_set_child_position;
76 item_class->remove_child = nr_arena_group_remove_child;
77 item_class->update = nr_arena_group_update;
78 item_class->render = nr_arena_group_render;
79 item_class->clip = nr_arena_group_clip;
80 item_class->pick = nr_arena_group_pick;
81 }
83 static void
84 nr_arena_group_init (NRArenaGroup *group)
85 {
86 group->transparent = FALSE;
87 group->children = NULL;
88 group->last = NULL;
89 group->style = NULL;
90 group->child_transform.set_identity();
91 }
93 static NRArenaItem *
94 nr_arena_group_children (NRArenaItem *item)
95 {
96 NRArenaGroup *group = NR_ARENA_GROUP (item);
98 return group->children;
99 }
101 static NRArenaItem *
102 nr_arena_group_last_child (NRArenaItem *item)
103 {
104 NRArenaGroup *group = NR_ARENA_GROUP (item);
106 return group->last;
107 }
109 static void
110 nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
111 {
112 NRArenaGroup *group = NR_ARENA_GROUP (item);
114 if (!ref) {
115 group->children = nr_arena_item_attach (item, child, NULL, group->children);
116 } else {
117 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
118 }
120 if (ref == group->last) group->last = child;
122 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
123 }
125 static void
126 nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
127 {
128 NRArenaGroup *group = NR_ARENA_GROUP (item);
130 if (child == group->last) group->last = child->prev;
132 if (child->prev) {
133 nr_arena_item_detach (item, child);
134 } else {
135 group->children = nr_arena_item_detach (item, child);
136 }
138 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
139 }
141 static void
142 nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
143 {
144 NRArenaGroup *group = NR_ARENA_GROUP (item);
146 if (child == group->last) group->last = child->prev;
148 if (child->prev) {
149 nr_arena_item_detach (item, child);
150 } else {
151 group->children = nr_arena_item_detach (item, child);
152 }
154 if (!ref) {
155 group->children = nr_arena_item_attach (item, child, NULL, group->children);
156 } else {
157 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
158 }
160 if (ref == group->last) group->last = child;
162 nr_arena_item_request_render (child);
163 }
165 static unsigned int
166 nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
167 {
168 unsigned int newstate;
170 NRArenaGroup *group = NR_ARENA_GROUP (item);
172 unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
174 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
175 NRGC cgc(gc);
176 cgc.transform = group->child_transform * gc->transform;
177 newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
178 beststate = beststate & newstate;
179 }
181 if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
182 nr_rect_l_set_empty (&item->bbox);
183 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
184 if (child->visible)
185 nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
186 }
187 }
189 return beststate;
190 }
192 void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
193 {
194 g_return_if_fail(group != NULL);
195 g_return_if_fail(NR_IS_ARENA_GROUP(group));
197 if (style) sp_style_ref(style);
198 if (group->style) sp_style_unref(group->style);
199 group->style = style;
201 //if group has a filter
202 if (style->filter.set && style->getFilter()) {
203 if (!group->filter) {
204 int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
205 group->filter = new NR::Filter(primitives);
206 }
207 sp_filter_build_renderer(SP_FILTER(style->getFilter()), group->filter);
208 } else {
209 //no filter set for this group
210 delete group->filter;
211 group->filter = NULL;
212 }
214 if (style && style->enable_background.set
215 && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
216 group->background_new = true;
217 }
218 }
220 static unsigned int
221 nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
222 {
223 NRArenaGroup *group = NR_ARENA_GROUP (item);
225 unsigned int ret = item->state;
227 /* Just compose children into parent buffer */
228 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
229 ret = nr_arena_item_invoke_render (ct, child, area, pb, flags);
230 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
231 }
233 return ret;
234 }
236 static unsigned int
237 nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
238 {
239 NRArenaGroup *group = NR_ARENA_GROUP (item);
241 unsigned int ret = item->state;
243 /* Just compose children into parent buffer */
244 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
245 ret = nr_arena_item_invoke_clip (child, area, pb);
246 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
247 }
249 return ret;
250 }
252 static NRArenaItem *
253 nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky)
254 {
255 NRArenaGroup *group = NR_ARENA_GROUP (item);
257 for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
258 NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
259 if (picked)
260 return (group->transparent) ? picked : item;
261 }
263 return NULL;
264 }
266 void
267 nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
268 {
269 nr_return_if_fail (group != NULL);
270 nr_return_if_fail (NR_IS_ARENA_GROUP (group));
272 group->transparent = transparent;
273 }
275 void nr_arena_group_set_child_transform(NRArenaGroup *group, NR::Matrix const &t)
276 {
277 NR::Matrix nt(t);
278 nr_arena_group_set_child_transform(group, &nt);
279 }
281 void nr_arena_group_set_child_transform(NRArenaGroup *group, NR::Matrix const *t)
282 {
283 if (!t) t = &NR_MATRIX_IDENTITY;
285 if (!NR::matrix_equalp(*t, group->child_transform, NR_EPSILON)) {
286 nr_arena_item_request_render (NR_ARENA_ITEM (group));
287 group->child_transform = *t;
288 nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
289 }
290 }
293 /*
294 Local Variables:
295 mode:c++
296 c-file-style:"stroustrup"
297 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
298 indent-tabs-mode:nil
299 fill-column:99
300 End:
301 */
302 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :