3 Part of the swftools package.
5 Copyright (c) 2010 Matthias Kramm <kramm@quiss.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
26 #include "gfxfilter.h"
27 #include "devices/record.h"
29 typedef struct _internal {
33 /* for two pass filters: */
34 gfxdevice_t*final_out;
38 gfxtwopassfilter_t*twopass;
41 static int filter_setparameter(gfxdevice_t*dev, const char*key, const char*value)
43 internal_t*i = (internal_t*)dev->internal;
44 return i->filter->setparameter(i->filter, key, value, i->out);
46 static void filter_startpage(gfxdevice_t*dev, int width, int height)
48 internal_t*i = (internal_t*)dev->internal;
49 i->filter->startpage(i->filter, width, height, i->out);
51 static void filter_startclip(gfxdevice_t*dev, gfxline_t*line)
53 internal_t*i = (internal_t*)dev->internal;
54 i->filter->startclip(i->filter, line, i->out);
56 static void filter_endclip(gfxdevice_t*dev)
58 internal_t*i = (internal_t*)dev->internal;
59 i->filter->endclip(i->filter, i->out);
61 static void filter_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit)
63 internal_t*i = (internal_t*)dev->internal;
64 i->filter->stroke(i->filter, line, width, color, cap_style, joint_style, miterLimit, i->out);
66 static void filter_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
68 internal_t*i = (internal_t*)dev->internal;
69 i->filter->fill(i->filter, line, color, i->out);
71 static void filter_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
73 internal_t*i = (internal_t*)dev->internal;
74 i->filter->fillbitmap(i->filter, line, img, matrix, cxform, i->out);
76 static void filter_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
78 internal_t*i = (internal_t*)dev->internal;
79 i->filter->fillgradient(i->filter, line, gradient, type, matrix, i->out);
81 static void filter_addfont(gfxdevice_t*dev, gfxfont_t*font)
83 internal_t*i = (internal_t*)dev->internal;
84 i->filter->addfont(i->filter, font, i->out);
86 static void filter_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
88 internal_t*i = (internal_t*)dev->internal;
89 i->filter->drawchar(i->filter, font, glyphnr, color, matrix, i->out);
91 static void filter_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
93 internal_t*i = (internal_t*)dev->internal;
94 i->filter->drawlink(i->filter, line, action, i->out);
96 static void filter_endpage(gfxdevice_t*dev)
98 internal_t*i = (internal_t*)dev->internal;
99 i->filter->endpage(i->filter, i->out);
101 static gfxresult_t* filter_finish(gfxdevice_t*dev)
103 internal_t*i = (internal_t*)dev->internal;
105 if(i->filter->finish) {
106 r = i->filter->finish(i->filter, i->out);
108 r = i->out->finish(i->out);
110 if(i->filter->internal) {
111 free(i->filter->internal);
112 i->filter->internal = 0;
114 free(i->filter);i->filter=0;
115 free(dev->internal);dev->internal=0;free(dev);
120 static int passthrough_setparameter(gfxdevice_t*dev, const char*key, const char*value)
122 internal_t*i = (internal_t*)dev->internal;
123 return i->out->setparameter(i->out, key, value);
125 static void passthrough_startpage(gfxdevice_t*dev, int width, int height)
127 internal_t*i = (internal_t*)dev->internal;
128 i->out->startpage(i->out, width, height);
130 static void passthrough_startclip(gfxdevice_t*dev, gfxline_t*line)
132 internal_t*i = (internal_t*)dev->internal;
133 i->out->startclip(i->out, line);
135 static void passthrough_endclip(gfxdevice_t*dev)
137 internal_t*i = (internal_t*)dev->internal;
138 i->out->endclip(i->out);
140 static void passthrough_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit)
142 internal_t*i = (internal_t*)dev->internal;
143 i->out->stroke(i->out, line, width, color, cap_style, joint_style, miterLimit);
145 static void passthrough_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
147 internal_t*i = (internal_t*)dev->internal;
148 i->out->fill(i->out, line, color);
150 static void passthrough_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
152 internal_t*i = (internal_t*)dev->internal;
153 i->out->fillbitmap(i->out, line, img, matrix, cxform);
155 static void passthrough_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
157 internal_t*i = (internal_t*)dev->internal;
158 i->out->fillgradient(i->out, line, gradient, type, matrix);
160 static void passthrough_addfont(gfxdevice_t*dev, gfxfont_t*font)
162 internal_t*i = (internal_t*)dev->internal;
163 i->out->addfont(i->out, font);
165 static void passthrough_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
167 internal_t*i = (internal_t*)dev->internal;
168 i->out->drawchar(i->out, font, glyphnr, color, matrix);
170 static void passthrough_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
172 internal_t*i = (internal_t*)dev->internal;
173 i->out->drawlink(i->out, line, action);
175 static void passthrough_endpage(gfxdevice_t*dev)
177 internal_t*i = (internal_t*)dev->internal;
178 i->out->endpage(i->out);
181 int discard_setparameter(gfxdevice_t*dev, const char*key, const char*value)
185 static void discard_startpage(gfxdevice_t*dev, int width, int height)
188 static void discard_startclip(gfxdevice_t*dev, gfxline_t*line)
191 static void discard_endclip(gfxdevice_t*dev)
194 static void discard_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit)
197 static void discard_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
200 static void discard_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
203 static void discard_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
206 static void discard_addfont(gfxdevice_t*dev, gfxfont_t*font)
209 static void discard_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
212 static void discard_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
215 static void discard_endpage(gfxdevice_t*dev)
218 static gfxresult_t* discard_finish(gfxdevice_t*dev)
223 gfxdevice_t*gfxfilter_apply(gfxfilter_t*_filter, gfxdevice_t*out)
225 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
226 gfxdevice_t*dev = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t));
227 gfxfilter_t*filter = (gfxfilter_t*)rfx_alloc(sizeof(gfxfilter_t));
228 memcpy(filter, _filter, sizeof(gfxfilter_t));
235 dev->name = filter->name?filter->name:"filter";
236 dev->setparameter = filter->setparameter?filter_setparameter:passthrough_setparameter;
237 dev->startpage = filter->startpage?filter_startpage:passthrough_startpage;
238 dev->startclip = filter->startclip?filter_startclip:passthrough_startclip;
239 dev->endclip = filter->endclip?filter_endclip:passthrough_endclip;
240 dev->stroke = filter->stroke?filter_stroke:passthrough_stroke;
241 dev->fill = filter->fill?filter_fill:passthrough_fill;
242 dev->fillbitmap = filter->fillbitmap?filter_fillbitmap:passthrough_fillbitmap;
243 dev->fillgradient = filter->fillgradient?filter_fillgradient:passthrough_fillgradient;
244 dev->addfont = filter->addfont?filter_addfont:passthrough_addfont;
245 dev->drawchar = filter->drawchar?filter_drawchar:passthrough_drawchar;
246 dev->drawlink = filter->drawlink?filter_drawlink:passthrough_drawlink;
247 dev->endpage = filter->endpage?filter_endpage:passthrough_endpage;
248 dev->finish = filter_finish;
252 static void setup_twopass(gfxdevice_t*dev, gfxfilter_t*filter)
254 dev->name = filter->name?filter->name:"filter";
255 dev->setparameter = filter->setparameter?filter_setparameter:passthrough_setparameter;
256 dev->startpage = filter->startpage?filter_startpage:passthrough_startpage;
257 dev->startclip = filter->startclip?filter_startclip:passthrough_startclip;
258 dev->endclip = filter->endclip?filter_endclip:passthrough_endclip;
259 dev->stroke = filter->stroke?filter_stroke:passthrough_stroke;
260 dev->fill = filter->fill?filter_fill:passthrough_fill;
261 dev->fillbitmap = filter->fillbitmap?filter_fillbitmap:passthrough_fillbitmap;
262 dev->fillgradient = filter->fillgradient?filter_fillgradient:passthrough_fillgradient;
263 dev->addfont = filter->addfont?filter_addfont:passthrough_addfont;
264 dev->drawchar = filter->drawchar?filter_drawchar:passthrough_drawchar;
265 dev->drawlink = filter->drawlink?filter_drawlink:passthrough_drawlink;
266 dev->endpage = filter->endpage?filter_endpage:passthrough_endpage;
269 static gfxresult_t* twopass_finish(gfxdevice_t*dev)
271 internal_t*i = (internal_t*)dev->internal;
274 if(i->filter->finish) {
275 r = i->filter->finish(i->filter, i->out);
277 r = i->out->finish(i->out);
280 if(i->pass == i->num_passes) {
290 /* switch to next pass filter */
291 i->filter = &i->twopass->pass2;
292 setup_twopass(dev, i->filter);
293 dev->finish = twopass_finish;
295 if(i->pass == i->num_passes-1) {
296 /* we don't record in the final pass- we just stream out to the
297 next output device */
298 i->out = i->final_out;
300 // switch to a new tempfile- this only happens for 3 passes or more
301 assert(i->num_passes>2);
302 gfxdevice_record_init(&i->record, /*use tempfile*/1);
307 gfxresult_record_replay(r, i->out);
310 return twopass_finish(dev);
313 gfxdevice_t*gfxtwopassfilter_apply(gfxtwopassfilter_t*_twopass, gfxdevice_t*out)
315 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
316 gfxdevice_t*dev = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t));
318 gfxtwopassfilter_t*twopass = (gfxtwopassfilter_t*)rfx_alloc(sizeof(gfxtwopassfilter_t));
319 memcpy(twopass, _twopass, sizeof(gfxtwopassfilter_t));
321 gfxdevice_record_init(&i->record, /*use tempfile*/1);
325 i->twopass = twopass;
331 i->filter = &twopass->pass1;
332 setup_twopass(dev, i->filter);
333 dev->finish = twopass_finish;