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 "libnr/nr-matrix-fns.h"
26 #include "libnr/nr-matrix-ops.h"
27 #include "helper/geom.h"
29 static void nr_arena_group_class_init (NRArenaGroupClass *klass);
30 static void nr_arena_group_init (NRArenaGroup *group);
32 static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
33 static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
34 static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
35 static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
36 static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
38 static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
39 static unsigned int nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
40 static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
41 static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky);
43 static NRArenaItemClass *parent_class;
45 NRType
46 nr_arena_group_get_type (void)
47 {
48 static NRType type = 0;
49 if (!type) {
50 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
51 "NRArenaGroup",
52 sizeof (NRArenaGroupClass),
53 sizeof (NRArenaGroup),
54 (void (*) (NRObjectClass *)) nr_arena_group_class_init,
55 (void (*) (NRObject *)) nr_arena_group_init);
56 }
57 return type;
58 }
60 static void
61 nr_arena_group_class_init (NRArenaGroupClass *klass)
62 {
63 NRObjectClass *object_class;
64 NRArenaItemClass *item_class;
66 object_class = (NRObjectClass *) klass;
67 item_class = (NRArenaItemClass *) klass;
69 parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
71 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
73 item_class->children = nr_arena_group_children;
74 item_class->last_child = nr_arena_group_last_child;
75 item_class->add_child = nr_arena_group_add_child;
76 item_class->set_child_position = nr_arena_group_set_child_position;
77 item_class->remove_child = nr_arena_group_remove_child;
78 item_class->update = nr_arena_group_update;
79 item_class->render = nr_arena_group_render;
80 item_class->clip = nr_arena_group_clip;
81 item_class->pick = nr_arena_group_pick;
82 }
84 static void
85 nr_arena_group_init (NRArenaGroup *group)
86 {
87 group->transparent = FALSE;
88 group->children = NULL;
89 group->last = NULL;
90 group->style = NULL;
91 group->child_transform.setIdentity();
92 }
94 static NRArenaItem *
95 nr_arena_group_children (NRArenaItem *item)
96 {
97 NRArenaGroup *group = NR_ARENA_GROUP (item);
99 return group->children;
100 }
102 static NRArenaItem *
103 nr_arena_group_last_child (NRArenaItem *item)
104 {
105 NRArenaGroup *group = NR_ARENA_GROUP (item);
107 return group->last;
108 }
110 static void
111 nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
112 {
113 NRArenaGroup *group = NR_ARENA_GROUP (item);
115 if (!ref) {
116 group->children = nr_arena_item_attach (item, child, NULL, group->children);
117 } else {
118 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
119 }
121 if (ref == group->last) group->last = child;
123 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
124 }
126 static void
127 nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
128 {
129 NRArenaGroup *group = NR_ARENA_GROUP (item);
131 if (child == group->last) group->last = child->prev;
133 if (child->prev) {
134 nr_arena_item_detach (item, child);
135 } else {
136 group->children = nr_arena_item_detach (item, child);
137 }
139 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
140 }
142 static void
143 nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
144 {
145 NRArenaGroup *group = NR_ARENA_GROUP (item);
147 if (child == group->last) group->last = child->prev;
149 if (child->prev) {
150 nr_arena_item_detach (item, child);
151 } else {
152 group->children = nr_arena_item_detach (item, child);
153 }
155 if (!ref) {
156 group->children = nr_arena_item_attach (item, child, NULL, group->children);
157 } else {
158 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
159 }
161 if (ref == group->last) group->last = child;
163 nr_arena_item_request_render (child);
164 }
166 static unsigned int
167 nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
168 {
169 unsigned int newstate;
171 NRArenaGroup *group = NR_ARENA_GROUP (item);
173 unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
175 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
176 NRGC cgc(gc);
177 cgc.transform = group->child_transform * gc->transform;
178 newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
179 beststate = beststate & newstate;
180 }
182 if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
183 nr_rect_l_set_empty (&item->bbox);
184 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
185 if (child->visible)
186 nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
187 }
188 }
190 return beststate;
191 }
193 void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
194 {
195 g_return_if_fail(group != NULL);
196 g_return_if_fail(NR_IS_ARENA_GROUP(group));
198 if (style) sp_style_ref(style);
199 if (group->style) sp_style_unref(group->style);
200 group->style = style;
202 //if group has a filter
203 if (style->filter.set && style->getFilter()) {
204 if (!group->filter) {
205 int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
206 group->filter = new NR::Filter(primitives);
207 }
208 sp_filter_build_renderer(SP_FILTER(style->getFilter()), group->filter);
209 } else {
210 //no filter set for this group
211 delete group->filter;
212 group->filter = NULL;
213 }
215 if (style && style->enable_background.set
216 && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
217 group->background_new = true;
218 }
219 }
221 static unsigned int
222 nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
223 {
224 NRArenaGroup *group = NR_ARENA_GROUP (item);
226 unsigned int ret = item->state;
228 /* Just compose children into parent buffer */
229 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
230 ret = nr_arena_item_invoke_render (ct, child, area, pb, flags);
231 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
232 }
234 return ret;
235 }
237 static unsigned int
238 nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
239 {
240 NRArenaGroup *group = NR_ARENA_GROUP (item);
242 unsigned int ret = item->state;
244 /* Just compose children into parent buffer */
245 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
246 ret = nr_arena_item_invoke_clip (child, area, pb);
247 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
248 }
250 return ret;
251 }
253 static NRArenaItem *
254 nr_arena_group_pick (NRArenaItem *item, Geom::Point p, double delta, unsigned int sticky)
255 {
256 NRArenaGroup *group = NR_ARENA_GROUP (item);
258 for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
259 NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
260 if (picked)
261 return (group->transparent) ? picked : item;
262 }
264 return NULL;
265 }
267 void
268 nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
269 {
270 nr_return_if_fail (group != NULL);
271 nr_return_if_fail (NR_IS_ARENA_GROUP (group));
273 group->transparent = transparent;
274 }
276 void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const &t)
277 {
278 Geom::Matrix nt(t);
279 nr_arena_group_set_child_transform(group, &nt);
280 }
282 void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const *t)
283 {
284 if (!t) t = &GEOM_MATRIX_IDENTITY;
286 if (!Geom::matrix_equalp(*t, group->child_transform, NR_EPSILON)) {
287 nr_arena_item_request_render (NR_ARENA_ITEM (group));
288 group->child_transform = *t;
289 nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
290 }
291 }
294 /*
295 Local Variables:
296 mode:c++
297 c-file-style:"stroustrup"
298 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
299 indent-tabs-mode:nil
300 fill-column:99
301 End:
302 */
303 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :