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"
26 static void nr_arena_group_class_init (NRArenaGroupClass *klass);
27 static void nr_arena_group_init (NRArenaGroup *group);
29 static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
30 static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
31 static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
32 static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
33 static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
35 static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
36 static unsigned int nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
37 static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
38 static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky);
40 static NRArenaItemClass *parent_class;
42 NRType
43 nr_arena_group_get_type (void)
44 {
45 static NRType type = 0;
46 if (!type) {
47 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
48 "NRArenaGroup",
49 sizeof (NRArenaGroupClass),
50 sizeof (NRArenaGroup),
51 (void (*) (NRObjectClass *)) nr_arena_group_class_init,
52 (void (*) (NRObject *)) nr_arena_group_init);
53 }
54 return type;
55 }
57 static void
58 nr_arena_group_class_init (NRArenaGroupClass *klass)
59 {
60 NRObjectClass *object_class;
61 NRArenaItemClass *item_class;
63 object_class = (NRObjectClass *) klass;
64 item_class = (NRArenaItemClass *) klass;
66 parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
68 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
70 item_class->children = nr_arena_group_children;
71 item_class->last_child = nr_arena_group_last_child;
72 item_class->add_child = nr_arena_group_add_child;
73 item_class->set_child_position = nr_arena_group_set_child_position;
74 item_class->remove_child = nr_arena_group_remove_child;
75 item_class->update = nr_arena_group_update;
76 item_class->render = nr_arena_group_render;
77 item_class->clip = nr_arena_group_clip;
78 item_class->pick = nr_arena_group_pick;
79 }
81 static void
82 nr_arena_group_init (NRArenaGroup *group)
83 {
84 group->transparent = FALSE;
85 group->children = NULL;
86 group->last = NULL;
87 group->style = NULL;
88 nr_matrix_set_identity (&group->child_transform);
89 }
91 static NRArenaItem *
92 nr_arena_group_children (NRArenaItem *item)
93 {
94 NRArenaGroup *group = NR_ARENA_GROUP (item);
96 return group->children;
97 }
99 static NRArenaItem *
100 nr_arena_group_last_child (NRArenaItem *item)
101 {
102 NRArenaGroup *group = NR_ARENA_GROUP (item);
104 return group->last;
105 }
107 static void
108 nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
109 {
110 NRArenaGroup *group = NR_ARENA_GROUP (item);
112 if (!ref) {
113 group->children = nr_arena_item_attach (item, child, NULL, group->children);
114 } else {
115 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
116 }
118 if (ref == group->last) group->last = child;
120 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
121 }
123 static void
124 nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
125 {
126 NRArenaGroup *group = NR_ARENA_GROUP (item);
128 if (child == group->last) group->last = child->prev;
130 if (child->prev) {
131 nr_arena_item_detach (item, child);
132 } else {
133 group->children = nr_arena_item_detach (item, child);
134 }
136 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
137 }
139 static void
140 nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
141 {
142 NRArenaGroup *group = NR_ARENA_GROUP (item);
144 if (child == group->last) group->last = child->prev;
146 if (child->prev) {
147 nr_arena_item_detach (item, child);
148 } else {
149 group->children = nr_arena_item_detach (item, child);
150 }
152 if (!ref) {
153 group->children = nr_arena_item_attach (item, child, NULL, group->children);
154 } else {
155 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
156 }
158 if (ref == group->last) group->last = child;
160 nr_arena_item_request_render (child);
161 }
163 static unsigned int
164 nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
165 {
166 unsigned int newstate;
168 NRArenaGroup *group = NR_ARENA_GROUP (item);
170 unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
172 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
173 NRGC cgc(gc);
174 nr_matrix_multiply (&cgc.transform, &group->child_transform, &gc->transform);
175 newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
176 beststate = beststate & newstate;
177 }
179 if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
180 nr_rect_l_set_empty (&item->bbox);
181 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
182 nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
183 }
184 }
186 return beststate;
187 }
189 void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
190 {
191 g_return_if_fail(group != NULL);
192 g_return_if_fail(NR_IS_ARENA_GROUP(group));
194 if (style) sp_style_ref(style);
195 if (group->style) sp_style_unref(group->style);
196 group->style = style;
198 //if group has a filter
199 if (style->filter.set && style->getFilter()) {
200 if (!group->filter) {
201 int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
202 group->filter = new NR::Filter(primitives);
203 }
204 sp_filter_build_renderer(SP_FILTER(style->getFilter()), group->filter);
205 } else {
206 //no filter set for this group
207 delete group->filter;
208 group->filter = NULL;
209 }
211 if (style && style->enable_background.set
212 && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
213 group->background_new = true;
214 }
215 }
217 static unsigned int
218 nr_arena_group_render (cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
219 {
220 NRArenaGroup *group = NR_ARENA_GROUP (item);
222 unsigned int ret = item->state;
224 /* Just compose children into parent buffer */
225 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
226 ret = nr_arena_item_invoke_render (ct, child, area, pb, flags);
227 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
228 }
230 return ret;
231 }
233 static unsigned int
234 nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
235 {
236 NRArenaGroup *group = NR_ARENA_GROUP (item);
238 unsigned int ret = item->state;
240 /* Just compose children into parent buffer */
241 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
242 ret = nr_arena_item_invoke_clip (child, area, pb);
243 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
244 }
246 return ret;
247 }
249 static NRArenaItem *
250 nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky)
251 {
252 NRArenaGroup *group = NR_ARENA_GROUP (item);
254 for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
255 NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
256 if (picked)
257 return (group->transparent) ? picked : item;
258 }
260 return NULL;
261 }
263 void
264 nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
265 {
266 nr_return_if_fail (group != NULL);
267 nr_return_if_fail (NR_IS_ARENA_GROUP (group));
269 group->transparent = transparent;
270 }
272 void nr_arena_group_set_child_transform(NRArenaGroup *group, NR::Matrix const &t)
273 {
274 NRMatrix nt(t);
275 nr_arena_group_set_child_transform(group, &nt);
276 }
278 void nr_arena_group_set_child_transform(NRArenaGroup *group, NRMatrix const *t)
279 {
280 if (!t) t = &NR_MATRIX_IDENTITY;
282 if (!NR_MATRIX_DF_TEST_CLOSE (t, &group->child_transform, NR_EPSILON)) {
283 nr_arena_item_request_render (NR_ARENA_ITEM (group));
284 group->child_transform = *t;
285 nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
286 }
287 }
289 /*
290 Local Variables:
291 mode:c++
292 c-file-style:"stroustrup"
293 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
294 indent-tabs-mode:nil
295 fill-column:99
296 End:
297 */
298 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :