Code

8df0453327492b04ad65f4bef1d711ead3198542
[inkscape.git] / src / display / nr-arena-group.cpp
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-gaussian-blur.h"
23 static void nr_arena_group_class_init (NRArenaGroupClass *klass);
24 static void nr_arena_group_init (NRArenaGroup *group);
26 static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
27 static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
28 static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
29 static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
30 static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
32 static unsigned int nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset);
33 static unsigned int nr_arena_group_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags);
34 static unsigned int nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb);
35 static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky);
37 static NRArenaItemClass *parent_class;
39 NRType
40 nr_arena_group_get_type (void)
41 {
42         static NRType type = 0;
43         if (!type) {
44                 type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
45                                                 "NRArenaGroup",
46                                                 sizeof (NRArenaGroupClass),
47                                                 sizeof (NRArenaGroup),
48                                                 (void (*) (NRObjectClass *)) nr_arena_group_class_init,
49                                                 (void (*) (NRObject *)) nr_arena_group_init);
50         }
51         return type;
52 }
54 static void
55 nr_arena_group_class_init (NRArenaGroupClass *klass)
56 {
57         NRObjectClass *object_class;
58         NRArenaItemClass *item_class;
60         object_class = (NRObjectClass *) klass;
61         item_class = (NRArenaItemClass *) klass;
63         parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
65         object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
67         item_class->children = nr_arena_group_children;
68         item_class->last_child = nr_arena_group_last_child;
69         item_class->add_child = nr_arena_group_add_child;
70         item_class->set_child_position = nr_arena_group_set_child_position;
71         item_class->remove_child = nr_arena_group_remove_child;
72         item_class->update = nr_arena_group_update;
73         item_class->render = nr_arena_group_render;
74         item_class->clip = nr_arena_group_clip;
75         item_class->pick = nr_arena_group_pick;
76 }
78 static void
79 nr_arena_group_init (NRArenaGroup *group)
80 {
81         group->transparent = FALSE;
82         group->children = NULL;
83         group->last = NULL;
84         group->style = NULL;
85         nr_matrix_set_identity (&group->child_transform);
86   
87 #ifdef arena_item_tile_cache
88   group->skipCaching=true;
89 #endif
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)
104         NRArenaGroup *group = NR_ARENA_GROUP (item);
106         return group->last;
109 static void
110 nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
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);
125 static void
126 nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
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);
141 static void
142 nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
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);
165 static unsigned int
166 nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
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                 nr_matrix_multiply (&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                         nr_rect_l_union (&item->bbox, &item->bbox, &child->bbox);
185                 }
186         }
188         return beststate;
191 void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
193   g_return_if_fail(group != NULL);
194   g_return_if_fail(NR_IS_ARENA_GROUP(group));
196   if (style) sp_style_ref(style);
197   if (group->style) sp_style_unref(group->style);
198   group->style = style;
200   //if there is a filter set for this group
201   if (style && style->filter.set && style->filter.filter) {
202   
203         group->filter = new NR::Filter();
204         group->filter->set_x(style->filter.filter->x);
205         group->filter->set_y(style->filter.filter->y);
206         group->filter->set_width(style->filter.filter->width);
207         group->filter->set_height(style->filter.filter->height);
208         
209         //go through all SP filter primitives
210         for(int i=0; i<style->filter.filter->_primitive_count; i++)
211         {
212             SPFilterPrimitive *primitive = style->filter.filter->_primitives[i];
213             //if primitive is gaussianblur
214 //            if(SP_IS_GAUSSIANBLUR(primitive))
215             {
216                 NR::FilterGaussian * gaussian = (NR::FilterGaussian *) group->filter->add_primitive(NR::NR_FILTER_GAUSSIANBLUR);
217                 SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive);
218                 float num = spblur->stdDeviation.getNumber();
219                 if( num>=0.0 )
220                 {
221                     float optnum = spblur->stdDeviation.getOptNumber();
222                     if( optnum>=0.0 )
223                         gaussian->set_deviation((double) num, (double) optnum);
224                     else
225                         gaussian->set_deviation((double) num);
226                 }
227             }
228         }
229     }
230     else
231     {
232         //no filter set for this group
233         group->filter = NULL;
234     }
236   if (style && style->enable_background.set
237       && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
238     group->background_new = true;
239   }
242 static unsigned int
243 nr_arena_group_render (NRArenaItem *item, NRRectL *area, NRPixBlock *pb, unsigned int flags)
245         NRArenaGroup *group = NR_ARENA_GROUP (item);
247         unsigned int ret = item->state;
249         /* Just compose children into parent buffer */
250         for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
251                 ret = nr_arena_item_invoke_render (child, area, pb, flags);
252                 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
253         }
255         return ret;
258 static unsigned int
259 nr_arena_group_clip (NRArenaItem *item, NRRectL *area, NRPixBlock *pb)
261         NRArenaGroup *group = NR_ARENA_GROUP (item);
263         unsigned int ret = item->state;
265         /* Just compose children into parent buffer */
266         for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
267                 ret = nr_arena_item_invoke_clip (child, area, pb);
268                 if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
269         }
271         return ret;
274 static NRArenaItem *
275 nr_arena_group_pick (NRArenaItem *item, NR::Point p, double delta, unsigned int sticky)
277         NRArenaGroup *group = NR_ARENA_GROUP (item);
279         for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
280                 NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
281                 if (picked)
282                         return (group->transparent) ? picked : item;
283         }
285         return NULL;
288 void
289 nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
291         nr_return_if_fail (group != NULL);
292         nr_return_if_fail (NR_IS_ARENA_GROUP (group));
294         group->transparent = transparent;
297 void nr_arena_group_set_child_transform(NRArenaGroup *group, NR::Matrix const &t)
299         NRMatrix nt(t);
300         nr_arena_group_set_child_transform(group, &nt);
303 void nr_arena_group_set_child_transform(NRArenaGroup *group, NRMatrix const *t)
305         if (!t) t = &NR_MATRIX_IDENTITY;
307         if (!NR_MATRIX_DF_TEST_CLOSE (t, &group->child_transform, NR_EPSILON)) {
308                 nr_arena_item_request_render (NR_ARENA_ITEM (group));
309                 group->child_transform = *t;
310                 nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
311         }