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 "nr-arena-group.h"
17 static void nr_arena_group_class_init (NRArenaGroupClass *klass);
18 static void nr_arena_group_init (NRArenaGroup *group);
20 static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
21 static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
22 static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
23 static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
24 static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
26 static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
27 static unsigned int nr_arena_group_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
28 static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
29 static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky);
31 static NRArenaItemClass *parent_class;
33 NRType
34 nr_arena_group_get_type (void)
35 {
36 static NRType type = 0;
37 if (!type) {
38 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
39 "NRArenaGroup",
40 sizeof (NRArenaGroupClass),
41 sizeof (NRArenaGroup),
42 (void (*) (NRObjectClass *)) nr_arena_group_class_init,
43 (void (*) (NRObject *)) nr_arena_group_init);
44 }
45 return type;
46 }
48 static void
49 nr_arena_group_class_init (NRArenaGroupClass *klass)
50 {
51 NRObjectClass *object_class;
52 NRArenaItemClass *item_class;
54 object_class = (NRObjectClass *) klass;
55 item_class = (NRArenaItemClass *) klass;
57 parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
59 object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
61 item_class->children = nr_arena_group_children;
62 item_class->last_child = nr_arena_group_last_child;
63 item_class->add_child = nr_arena_group_add_child;
64 item_class->set_child_position = nr_arena_group_set_child_position;
65 item_class->remove_child = nr_arena_group_remove_child;
66 item_class->update = nr_arena_group_update;
67 item_class->render = nr_arena_group_render;
68 item_class->clip = nr_arena_group_clip;
69 item_class->pick = nr_arena_group_pick;
70 }
72 static void
73 nr_arena_group_init (NRArenaGroup *group)
74 {
75 group->transparent = FALSE;
76 group->children = NULL;
77 group->last = NULL;
78 nr_matrix_set_identity (&group->child_transform);
80 #ifdef arena_item_tile_cache
81 group->skipCaching=true;
82 #endif
84 }
86 static NRArenaItem *
87 nr_arena_group_children (NRArenaItem *item)
88 {
89 NRArenaGroup *group = NR_ARENA_GROUP (item);
91 return group->children;
92 }
94 static NRArenaItem *
95 nr_arena_group_last_child (NRArenaItem *item)
96 {
97 NRArenaGroup *group = NR_ARENA_GROUP (item);
99 return group->last;
100 }
102 static void
103 nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
104 {
105 NRArenaGroup *group = NR_ARENA_GROUP (item);
107 if (!ref) {
108 group->children = nr_arena_item_attach_ref (item, child, NULL, group->children);
109 } else {
110 ref->next = nr_arena_item_attach_ref (item, child, ref, ref->next);
111 }
113 if (ref == group->last) group->last = child;
115 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
116 }
118 static void
119 nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
120 {
121 NRArenaGroup *group = NR_ARENA_GROUP (item);
123 if (child == group->last) group->last = child->prev;
125 if (child->prev) {
126 nr_arena_item_detach_unref (item, child);
127 } else {
128 group->children = nr_arena_item_detach_unref (item, child);
129 }
131 nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
132 }
134 static void
135 nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
136 {
137 NRArenaGroup *group = NR_ARENA_GROUP (item);
139 if (child == group->last) group->last = child->prev;
141 if (child->prev) {
142 nr_arena_item_detach_unref (item, child);
143 } else {
144 group->children = nr_arena_item_detach_unref (item, child);
145 }
147 if (!ref) {
148 group->children = nr_arena_item_attach_ref (item, child, NULL, group->children);
149 } else {
150 ref->next = nr_arena_item_attach_ref (item, child, ref, ref->next);
151 }
153 if (ref == group->last) group->last = child;
155 nr_arena_item_request_render (child);
156 }
158 static unsigned int
159 nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
160 {
161 unsigned int newstate;
163 NRArenaGroup *group = NR_ARENA_GROUP (item);
165 unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
167 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
168 NRGC cgc(gc);
169 nr_matrix_multiply (&cgc.transform, &group->child_transform, &gc->transform);
170 newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
171 beststate = beststate & newstate;
172 }
174 if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
175 nr_rect_l_set_empty (&item->bbox);
176 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
177 nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
178 }
179 }
181 return beststate;
182 }
184 static unsigned int
185 nr_arena_group_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
186 {
187 NRArenaGroup *group = NR_ARENA_GROUP (item);
189 unsigned int ret = item->state;
191 /* Just compose children into parent buffer */
192 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
193 ret = nr_arena_item_invoke_render (child, area, pb, flags);
194 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
195 }
197 return ret;
198 }
200 static unsigned int
201 nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
202 {
203 NRArenaGroup *group = NR_ARENA_GROUP (item);
205 unsigned int ret = item->state;
207 /* Just compose children into parent buffer */
208 for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
209 ret = nr_arena_item_invoke_clip (child, area, pb);
210 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
211 }
213 return ret;
214 }
216 static NRArenaItem *
217 nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky)
218 {
219 NRArenaGroup *group = NR_ARENA_GROUP (item);
221 for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
222 NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
223 if (picked)
224 return (group->transparent) ? picked : item;
225 }
227 return NULL;
228 }
230 void
231 nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
232 {
233 nr_return_if_fail (group != NULL);
234 nr_return_if_fail (NR_IS_ARENA_GROUP (group));
236 group->transparent = transparent;
237 }
239 void nr_arena_group_set_child_transform(NRArenaGroup *group, NR::Matrix const &t)
240 {
241 NRMatrix nt(t);
242 nr_arena_group_set_child_transform(group, &nt);
243 }
245 void nr_arena_group_set_child_transform(NRArenaGroup *group, NRMatrix const *t)
246 {
247 if (!t) t = &NR_MATRIX_IDENTITY;
249 if (!NR_MATRIX_DF_TEST_CLOSE (t, &group->child_transform, NR_EPSILON)) {
250 nr_arena_item_request_render (NR_ARENA_ITEM (group));
251 group->child_transform = *t;
252 nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
253 }
254 }