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 "style.h"
19 static void nr_arena_group_class_init (NRArenaGroupClass *klass);
20 static void nr_arena_group_init (NRArenaGroup *group);
22 static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
23 static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
24 static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
25 static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
26 static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
28 static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
29 static unsigned int nr_arena_group_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
30 static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
31 static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky);
33 static NRArenaItemClass *parent_class;
35 NRType
36 nr_arena_group_get_type (void)
37 {
38 static NRType type = 0;
39 if (!type) {
40 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
41 "NRArenaGroup",
42 sizeof (NRArenaGroupClass),
43 sizeof (NRArenaGroup),
44 (void (*) (NRObjectClass *)) nr_arena_group_class_init,
45 (void (*) (NRObject *)) nr_arena_group_init);
46 }
47 return type;
48 }
50 static void
51 nr_arena_group_class_init (NRArenaGroupClass *klass)
52 {
53 NRObjectClass *object_class;
54 NRArenaItemClass *item_class;
56 object_class = (NRObjectClass *) klass;
57 item_class = (NRArenaItemClass *) klass;
59 parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
61 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
63 item_class->children = nr_arena_group_children;
64 item_class->last_child = nr_arena_group_last_child;
65 item_class->add_child = nr_arena_group_add_child;
66 item_class->set_child_position = nr_arena_group_set_child_position;
67 item_class->remove_child = nr_arena_group_remove_child;
68 item_class->update = nr_arena_group_update;
69 item_class->render = nr_arena_group_render;
70 item_class->clip = nr_arena_group_clip;
71 item_class->pick = nr_arena_group_pick;
72 }
74 static void
75 nr_arena_group_init (NRArenaGroup *group)
76 {
77 group->transparent = FALSE;
78 group->children = NULL;
79 group->last = NULL;
80 group->style = NULL;
81 nr_matrix_set_identity (&group->child_transform);
83 #ifdef arena_item_tile_cache
84 group->skipCaching=true;
85 #endif
87 }
89 static NRArenaItem *
90 nr_arena_group_children (NRArenaItem *item)
91 {
92 NRArenaGroup *group = NR_ARENA_GROUP (item);
94 return group->children;
95 }
97 static NRArenaItem *
98 nr_arena_group_last_child (NRArenaItem *item)
99 {
100 NRArenaGroup *group = NR_ARENA_GROUP (item);
102 return group->last;
103 }
105 static void
106 nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
107 {
108 NRArenaGroup *group = NR_ARENA_GROUP (item);
110 if (!ref) {
111 group->children = nr_arena_item_attach (item, child, NULL, group->children);
112 } else {
113 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
114 }
116 if (ref == group->last) group->last = child;
118 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
119 }
121 static void
122 nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
123 {
124 NRArenaGroup *group = NR_ARENA_GROUP (item);
126 if (child == group->last) group->last = child->prev;
128 if (child->prev) {
129 nr_arena_item_detach (item, child);
130 } else {
131 group->children = nr_arena_item_detach (item, child);
132 }
134 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
135 }
137 static void
138 nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
139 {
140 NRArenaGroup *group = NR_ARENA_GROUP (item);
142 if (child == group->last) group->last = child->prev;
144 if (child->prev) {
145 nr_arena_item_detach (item, child);
146 } else {
147 group->children = nr_arena_item_detach (item, child);
148 }
150 if (!ref) {
151 group->children = nr_arena_item_attach (item, child, NULL, group->children);
152 } else {
153 ref->next = nr_arena_item_attach (item, child, ref, ref->next);
154 }
156 if (ref == group->last) group->last = child;
158 nr_arena_item_request_render (child);
159 }
161 static unsigned int
162 nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
163 {
164 unsigned int newstate;
166 NRArenaGroup *group = NR_ARENA_GROUP (item);
168 unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
170 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
171 NRGC cgc(gc);
172 nr_matrix_multiply (&cgc.transform, &group->child_transform, &gc->transform);
173 newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
174 beststate = beststate & newstate;
175 }
177 if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
178 nr_rect_l_set_empty (&item->bbox);
179 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
180 nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
181 }
182 }
184 return beststate;
185 }
187 void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
188 {
189 g_return_if_fail(group != NULL);
190 g_return_if_fail(NR_IS_ARENA_GROUP(group));
192 if (style) sp_style_ref(style);
193 if (group->style) sp_style_unref(group->style);
194 group->style = style;
196 if (style && style->filter.set && style->filter.filter) {
197 group->filter = new NR::Filter();
198 }
199 }
201 static unsigned int
202 nr_arena_group_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
203 {
204 NRArenaGroup *group = NR_ARENA_GROUP (item);
206 unsigned int ret = item->state;
208 /* Just compose children into parent buffer */
209 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
210 ret = nr_arena_item_invoke_render (child, area, pb, flags);
211 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
212 }
214 return ret;
215 }
217 static unsigned int
218 nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
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_clip (child, area, pb);
227 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
228 }
230 return ret;
231 }
233 static NRArenaItem *
234 nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky)
235 {
236 NRArenaGroup *group = NR_ARENA_GROUP (item);
238 for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
239 NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
240 if (picked)
241 return (group->transparent) ? picked : item;
242 }
244 return NULL;
245 }
247 void
248 nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
249 {
250 nr_return_if_fail (group != NULL);
251 nr_return_if_fail (NR_IS_ARENA_GROUP (group));
253 group->transparent = transparent;
254 }
256 void nr_arena_group_set_child_transform(NRArenaGroup *group, NR::Matrix const &t)
257 {
258 NRMatrix nt(t);
259 nr_arena_group_set_child_transform(group, &nt);
260 }
262 void nr_arena_group_set_child_transform(NRArenaGroup *group, NRMatrix const *t)
263 {
264 if (!t) t = &NR_MATRIX_IDENTITY;
266 if (!NR_MATRIX_DF_TEST_CLOSE (t, &group->child_transform, NR_EPSILON)) {
267 nr_arena_item_request_render (NR_ARENA_ITEM (group));
268 group->child_transform = *t;
269 nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
270 }
271 }