7e558dd6ce306d021d95dbd267e95eab5cc85a7d
1 #define __NR_FILTER_CPP__
3 /*
4 * SVG filters rendering
5 *
6 * Author:
7 * Niko Kiirala <niko@kiirala.com>
8 *
9 * Copyright (C) 2006 Niko Kiirala
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #include "display/nr-filter.h"
15 #include "display/nr-filter-primitive.h"
16 #include "display/nr-filter-gaussian.h"
17 #include "display/nr-filter-slot.h"
18 #include "display/nr-filter-types.h"
20 #include "display/nr-arena-item.h"
21 #include "libnr/nr-pixblock.h"
22 #include "libnr/nr-blit.h"
23 #include "svg/svg-length.h"
24 #include "sp-filter-units.h"
26 //#include "display/nr-arena-shape.h"
28 namespace NR {
30 Filter::Filter()
31 {
32 _primitive_count = 1;
33 _primitive_table_size = 1;
34 _primitive = new FilterPrimitive*[1];
35 _primitive[0] = new FilterGaussian;
36 _common_init();
37 }
39 Filter::Filter(int n)
40 {
41 _primitive_count = 0;
42 _primitive_table_size = n;
43 _primitive = new FilterPrimitive*[n];
44 for ( int i = 0 ; i < n ; i++ ) {
45 _primitive[i] = NULL;
46 }
47 _common_init();
48 }
50 void Filter::_common_init() {
51 _slot_count = 1;
52 _output_slot = NR_FILTER_SLOT_NOT_SET;
54 _region_x.set(SVGLength::PERCENT, -10, 0);
55 _region_y.set(SVGLength::PERCENT, -10, 0);
56 _region_width.set(SVGLength::PERCENT, 120, 0);
57 _region_height.set(SVGLength::PERCENT, 120, 0);
59 _x_pixels = -1.0;
60 _y_pixels = -1.0;
62 _filter_units = SP_FILTER_UNITS_OBJECTBOUNDINGBOX;
63 _primitive_units = SP_FILTER_UNITS_USERSPACEONUSE;
64 }
66 Filter::~Filter()
67 {
68 clear_primitives();
69 delete[] _primitive;
70 }
73 int Filter::render(NRArenaItem const *item, NRPixBlock *pb)
74 {
75 FilterSlot slot(_slot_count);
76 NRPixBlock *in = new NRPixBlock;
77 nr_pixblock_setup_fast(in, pb->mode,
78 pb->area.x0, pb->area.y0,
79 pb->area.x1, pb->area.y1, true);
80 nr_blit_pixblock_pixblock(in, pb);
81 slot.set(NR_FILTER_SOURCEGRAPHIC, in);
82 in = NULL; // in is now handled by FilterSlot, we should not touch it
84 _primitive[0]->render(slot, *item->ctm);
86 NRPixBlock *out = slot.get(_output_slot);
88 int size = (pb->area.x1 - pb->area.x0)
89 * (pb->area.y1 - pb->area.y0)
90 * NR_PIXBLOCK_BPP(pb);
91 memset(NR_PIXBLOCK_PX(pb), 0, size);
93 nr_blit_pixblock_pixblock(pb, out);
95 _slot_count = slot.get_slot_count();
96 return 0;
97 }
99 int Filter::get_enlarge(Matrix const &m)
100 {
101 int enlarge = 0;
102 for ( int i = 0 ; i < _primitive_count ; i++ ) {
103 if(_primitive[i]) enlarge += _primitive[i]->get_enlarge(m);
104 }
105 return enlarge;
106 }
108 void Filter::bbox_enlarge(NRRectL &bbox)
109 {
110 int len_x = bbox.x1 - bbox.x0;
111 int len_y = bbox.y1 - bbox.y0;
112 int enlarge_x = (int)std::ceil(len_x / 10.0);
113 int enlarge_y = (int)std::ceil(len_y / 10.0);
114 bbox.x0 -= enlarge_x;
115 bbox.x1 += enlarge_x;
116 bbox.y0 -= enlarge_y;
117 bbox.y1 += enlarge_y;
118 }
120 typedef FilterPrimitive*(*FilterConstructor)();
121 static FilterConstructor _constructor[NR_FILTER_ENDPRIMITIVETYPE];
123 void Filter::_create_constructor_table()
124 {
125 static bool created = false;
126 if(created) return;
128 /* Filter effects not yet implemented are set to NULL */
129 _constructor[NR_FILTER_BLEND] = NULL;
130 _constructor[NR_FILTER_COLORMATRIX] = NULL;
131 _constructor[NR_FILTER_COMPONENTTRANSFER] = NULL;
132 _constructor[NR_FILTER_COMPOSITE] = NULL;
133 _constructor[NR_FILTER_CONVOLVEMATRIX] = NULL;
134 _constructor[NR_FILTER_DIFFUSELIGHTING] = NULL;
135 _constructor[NR_FILTER_DISPLACEMENTMAP] = NULL;
136 _constructor[NR_FILTER_FLOOD] = NULL;
137 _constructor[NR_FILTER_GAUSSIANBLUR] = &FilterGaussian::create;
138 _constructor[NR_FILTER_IMAGE] = NULL;
139 _constructor[NR_FILTER_MERGE] = NULL;
140 _constructor[NR_FILTER_MORPHOLOGY] = NULL;
141 _constructor[NR_FILTER_OFFSET] = NULL;
142 _constructor[NR_FILTER_SPECULARLIGHTING] = NULL;
143 _constructor[NR_FILTER_TILE] = NULL;
144 _constructor[NR_FILTER_TURBULENCE] = NULL;
145 }
147 void Filter::_enlarge_primitive_table() {
148 FilterPrimitive **new_tbl = new FilterPrimitive*[_primitive_table_size * 2];
149 for (int i = 0 ; i < _primitive_count ; i++) {
150 new_tbl[i] = _primitive[i];
151 }
152 _primitive_table_size *= 2;
153 for (int i = _primitive_count ; i < _primitive_table_size ; i++) {
154 new_tbl[i] = NULL;
155 }
156 delete[] _primitive;
157 _primitive = new_tbl;
158 }
160 FilterPrimitive *Filter::add_primitive(FilterPrimitiveType type)
161 {
162 _create_constructor_table();
164 // Check that we can create a new filter of specified type
165 if (type < 0 || type >= NR_FILTER_ENDPRIMITIVETYPE)
166 return NULL;
167 if (!_constructor[type]) return NULL;
168 FilterPrimitive *created = _constructor[type]();
170 // If there is no space for new filter primitive, enlarge the table
171 if (_primitive_count >= _primitive_table_size) {
172 _enlarge_primitive_table();
173 }
175 _primitive[_primitive_count] = created;
176 return created;
177 }
179 FilterPrimitive *Filter::replace_primitive(FilterPrimitive *target, FilterPrimitiveType type)
180 {
181 _create_constructor_table();
183 // Check that target is valid primitive inside this filter
184 int place = -1;
185 for (int i = 0 ; i < _primitive_count ; i++) {
186 if (target == _primitive[i]) {
187 place = i;
188 break;
189 }
190 }
191 if (place < 0) return NULL;
193 // Check that we can create a new filter of specified type
194 if (type < 0 || type >= NR_FILTER_ENDPRIMITIVETYPE)
195 return NULL;
196 if (!_constructor[type]) return NULL;
197 FilterPrimitive *created = _constructor[type]();
199 // If there is no space for new filter primitive, enlarge the table
200 if (_primitive_count >= _primitive_table_size) {
201 _enlarge_primitive_table();
202 }
204 delete target;
205 _primitive[place] = created;
206 return created;
207 }
209 void Filter::clear_primitives()
210 {
211 for (int i = 0 ; i < _primitive_count ; i++) {
212 if (_primitive[i]) delete _primitive[i];
213 }
214 _primitive_count = 0;
215 }
217 } /* namespace NR */
219 /*
220 Local Variables:
221 mode:c++
222 c-file-style:"stroustrup"
223 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
224 indent-tabs-mode:nil
225 fill-column:99
226 End:
227 */
228 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :