Code

Added support for in-parameter in filter primitives
[inkscape.git] / src / display / nr-filter-slot.cpp
1 #define __NR_FILTER_SLOT_CPP__
3 /*
4  * A container class for filter slots. Allows for simple getting and
5  * setting images in filter slots without having to bother with
6  * table indexes and such.
7  *
8  * Author:
9  *   Niko Kiirala <niko@kiirala.com>
10  *
11  * Copyright (C) 2006 Niko Kiirala
12  *
13  * Released under GNU GPL, read the file 'COPYING' for more information
14  */
16 #include <assert.h>
18 #include "display/nr-arena-item.h"
19 #include "libnr/nr-pixblock.h"
20 #include "display/nr-filter-types.h"
21 #include "display/nr-filter-slot.h"
23 namespace NR {
25 FilterSlot::FilterSlot(int slots, NRArenaItem const *item)
26 {
27     _slot_count = ((slots > 0) ? slots : 2);
28     _slot = new NRPixBlock*[_slot_count];
29     _slot_number = new int[_slot_count];
31     for (int i = 0 ; i < _slot_count ; i++) {
32         _slot[i] = NULL;
33         _slot_number[i] = NR_FILTER_SLOT_NOT_SET;
34     }
36     _last_out = -1;
38     _arena_item = item;
39 }
41 FilterSlot::~FilterSlot()
42 {
43     for (int i = 0 ; i < _slot_count ; i++) {
44         if (_slot[i]) {
45             nr_pixblock_release(_slot[i]);
46             delete _slot[i];
47         }
48     }
49     delete[] _slot;
50     delete[] _slot_number;
51 }
53 NRPixBlock *FilterSlot::get(int slot_nr)
54 {
55     int index = _get_index(slot_nr);
56     assert(index >= 0);
58     /* If we didn't have the specified image, but we could create it
59      * from the other information we have, let's do that */
60     if (_slot[index] == NULL
61         && (slot_nr == NR_FILTER_SOURCEALPHA
62             || slot_nr == NR_FILTER_BACKGROUNDIMAGE
63             || slot_nr == NR_FILTER_BACKGROUNDALPHA
64             || slot_nr == NR_FILTER_FILLPAINT
65             || slot_nr == NR_FILTER_STROKEPAINT))
66     {
67         /* If needed, fetch background */
68         if (slot_nr == NR_FILTER_BACKGROUNDIMAGE
69             || slot_nr == NR_FILTER_BACKGROUNDALPHA)
70         {
71             NRPixBlock *pb;
72             pb = nr_arena_item_get_background(_arena_item);
73             if (pb) {
74                 this->set(NR_FILTER_BACKGROUNDIMAGE, pb);
75             } else {
76                 NRPixBlock *source = this->get(NR_FILTER_SOURCEGRAPHIC);
77                 pb = new NRPixBlock();
78                 if (!pb) return NULL; // Allocation failed
79                 nr_pixblock_setup_fast(pb, source->mode,
80                                        source->area.x0, source->area.y0,
81                                        source->area.x1, source->area.y1, true);
82                 if (pb->size != NR_PIXBLOCK_SIZE_TINY && pb->data.px == NULL) {
83                     // allocation failed
84                     delete pb;
85                     return NULL;
86                 }
87                 this->set(NR_FILTER_BACKGROUNDIMAGE, pb);
88             }
89         }
90         /* If only a alpha channel is needed, strip it from full image */
91         if (slot_nr == NR_FILTER_SOURCEALPHA) {
92             // TODO
93         }
94         if (slot_nr == NR_FILTER_BACKGROUNDALPHA) {
95             // TODO
96         }
97         /* When a paint is needed, fetch it from arena item */
98         if (slot_nr == NR_FILTER_FILLPAINT) {
99             // TODO
100         }
101         if (slot_nr == NR_FILTER_STROKEPAINT) {
102             // TODO
103         }
104     }
106     assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slot_number[index] == slot_nr);
107     return _slot[index];
110 void FilterSlot::set(int slot_nr, NRPixBlock *pb)
112     int index = _get_index(slot_nr);
113     assert(index >= 0);
114     assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slot_number[index] == slot_nr);
116     if(_slot[index]) {
117         nr_pixblock_release(_slot[index]);
118         delete _slot[index];
119     }
120     _slot[index] = pb;
121     _last_out = index;
124 int FilterSlot::get_slot_count()
126     int seek = _slot_count;
127     do {
128         seek--;
129     } while (_slot[seek] == NULL);
130     
131     return seek + 1;
134 int FilterSlot::_get_index(int slot_nr)
136     assert(slot_nr >= 0 ||
137            slot_nr == NR_FILTER_SLOT_NOT_SET ||
138            slot_nr == NR_FILTER_SOURCEGRAPHIC ||
139            slot_nr == NR_FILTER_SOURCEALPHA ||
140            slot_nr == NR_FILTER_BACKGROUNDIMAGE ||
141            slot_nr == NR_FILTER_BACKGROUNDALPHA ||
142            slot_nr == NR_FILTER_FILLPAINT ||
143            slot_nr == NR_FILTER_STROKEPAINT);
145     int index = -1;
146     if (slot_nr == NR_FILTER_SLOT_NOT_SET) {
147         return _last_out;
148     }
149     /* Search, if the slot already exists */
150     for (int i = 0 ; i < _slot_count ; i++) {
151         if (_slot_number[i] == slot_nr) {
152             index = i;
153             break;
154         }
155     }
157     /* If the slot doesn't already exist, create it */
158     if (index == -1) {
159         int seek = _slot_count;
160         do {
161             seek--;
162         } while (_slot[seek] == NULL && seek > 0);
163         /* If there is no space for more slots, create more space */
164         if (seek == _slot_count - 1) {
165             NRPixBlock **new_slot = new NRPixBlock*[_slot_count * 2];
166             int *new_number = new int[_slot_count * 2];
167             for (int i = 0 ; i < _slot_count ; i++) {
168                 new_slot[i] = _slot[i];
169                 new_number[i] = _slot_number[i];
170             }
171             for (int i = _slot_count ; i < _slot_count * 2 ; i++) {
172                 new_slot[i] = NULL;
173                 new_number[i] = NR_FILTER_SLOT_NOT_SET;
174             }
175             delete[] _slot;
176             delete[] _slot_number;
177             _slot = new_slot;
178             _slot_number = new_number;
179             _slot_count *= 2;
180         }
181         /* Now that there is space, create the slot */
182         _slot_number[seek + 1] = slot_nr;
183         index = seek + 1;
184     }
185     return index;
190 /*
191   Local Variables:
192   mode:c++
193   c-file-style:"stroustrup"
194   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
195   indent-tabs-mode:nil
196   fill-column:99
197   End:
198 */
199 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :