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];
108 }
110 void FilterSlot::set(int slot_nr, NRPixBlock *pb)
111 {
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;
122 }
124 int FilterSlot::get_slot_count()
125 {
126 int seek = _slot_count;
127 do {
128 seek--;
129 } while (_slot[seek] == NULL);
131 return seek + 1;
132 }
134 int FilterSlot::_get_index(int slot_nr)
135 {
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;
186 }
188 }
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 :