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 */
25 #include "gfxfilter.h"
26 #include "devices/record.h"
28 typedef struct _internal {
31 gfxdevice_t*final_out;
33 /* for two pass filters: */
37 gfxtwopassfilter_t*twopass;
40 static int filter_setparameter(gfxdevice_t*dev, const char*key, const char*value)
42 internal_t*i = (internal_t*)dev->internal;
43 return i->filter->setparameter(i->filter, key, value, i->out);
45 static void filter_startpage(gfxdevice_t*dev, int width, int height)
47 internal_t*i = (internal_t*)dev->internal;
48 i->filter->startpage(i->filter, width, height, i->out);
50 static void filter_startclip(gfxdevice_t*dev, gfxline_t*line)
52 internal_t*i = (internal_t*)dev->internal;
53 i->filter->startclip(i->filter, line, i->out);
55 static void filter_endclip(gfxdevice_t*dev)
57 internal_t*i = (internal_t*)dev->internal;
58 i->filter->endclip(i->filter, i->out);
60 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)
62 internal_t*i = (internal_t*)dev->internal;
63 i->filter->stroke(i->filter, line, width, color, cap_style, joint_style, miterLimit, i->out);
65 static void filter_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
67 internal_t*i = (internal_t*)dev->internal;
68 i->filter->fill(i->filter, line, color, i->out);
70 static void filter_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
72 internal_t*i = (internal_t*)dev->internal;
73 i->filter->fillbitmap(i->filter, line, img, matrix, cxform, i->out);
75 static void filter_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
77 internal_t*i = (internal_t*)dev->internal;
78 i->filter->fillgradient(i->filter, line, gradient, type, matrix, i->out);
80 static void filter_addfont(gfxdevice_t*dev, gfxfont_t*font)
82 internal_t*i = (internal_t*)dev->internal;
83 i->filter->addfont(i->filter, font, i->out);
85 static void filter_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
87 internal_t*i = (internal_t*)dev->internal;
88 i->filter->drawchar(i->filter, font, glyphnr, color, matrix, i->out);
90 static void filter_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
92 internal_t*i = (internal_t*)dev->internal;
93 i->filter->drawlink(i->filter, line, action, i->out);
95 static void filter_endpage(gfxdevice_t*dev)
97 internal_t*i = (internal_t*)dev->internal;
98 i->filter->endpage(i->filter, i->out);
100 static gfxresult_t* filter_finish(gfxdevice_t*dev)
102 internal_t*i = (internal_t*)dev->internal;
103 gfxresult_t*r = i->filter->finish(i->filter, i->out);
104 free(dev->internal);dev->internal=0;free(dev);
109 static int passthrough_setparameter(gfxdevice_t*dev, const char*key, const char*value)
111 internal_t*i = (internal_t*)dev->internal;
112 return i->out->setparameter(i->out, key, value);
114 static void passthrough_startpage(gfxdevice_t*dev, int width, int height)
116 internal_t*i = (internal_t*)dev->internal;
117 i->out->startpage(i->out, width, height);
119 static void passthrough_startclip(gfxdevice_t*dev, gfxline_t*line)
121 internal_t*i = (internal_t*)dev->internal;
122 i->out->startclip(i->out, line);
124 static void passthrough_endclip(gfxdevice_t*dev)
126 internal_t*i = (internal_t*)dev->internal;
127 i->out->endclip(i->out);
129 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)
131 internal_t*i = (internal_t*)dev->internal;
132 i->out->stroke(i->out, line, width, color, cap_style, joint_style, miterLimit);
134 static void passthrough_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
136 internal_t*i = (internal_t*)dev->internal;
137 i->out->fill(i->out, line, color);
139 static void passthrough_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
141 internal_t*i = (internal_t*)dev->internal;
142 i->out->fillbitmap(i->out, line, img, matrix, cxform);
144 static void passthrough_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
146 internal_t*i = (internal_t*)dev->internal;
147 i->out->fillgradient(i->out, line, gradient, type, matrix);
149 static void passthrough_addfont(gfxdevice_t*dev, gfxfont_t*font)
151 internal_t*i = (internal_t*)dev->internal;
152 i->out->addfont(i->out, font);
154 static void passthrough_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
156 internal_t*i = (internal_t*)dev->internal;
157 i->out->drawchar(i->out, font, glyphnr, color, matrix);
159 static void passthrough_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
161 internal_t*i = (internal_t*)dev->internal;
162 i->out->drawlink(i->out, line, action);
164 static void passthrough_endpage(gfxdevice_t*dev)
166 internal_t*i = (internal_t*)dev->internal;
167 i->out->endpage(i->out);
169 gfxresult_t* passthrough_finish(gfxdevice_t*dev)
171 internal_t*i = (internal_t*)dev->internal;
172 gfxdevice_t*out = i->out;
173 free(dev->internal);dev->internal=0;free(dev);
174 return out->finish(out);
177 int discard_setparameter(gfxdevice_t*dev, const char*key, const char*value)
181 static void discard_startpage(gfxdevice_t*dev, int width, int height)
184 static void discard_startclip(gfxdevice_t*dev, gfxline_t*line)
187 static void discard_endclip(gfxdevice_t*dev)
190 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)
193 static void discard_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color)
196 static void discard_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*matrix, gfxcxform_t*cxform)
199 static void discard_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*matrix)
202 static void discard_addfont(gfxdevice_t*dev, gfxfont_t*font)
205 static void discard_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix)
208 static void discard_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
211 static void discard_endpage(gfxdevice_t*dev)
214 static gfxresult_t* discard_finish(gfxdevice_t*dev)
219 gfxdevice_t*gfxfilter_apply(gfxfilter_t*filter, gfxdevice_t*out)
221 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
222 gfxdevice_t*dev = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t));
229 dev->name = filter->name?filter->name:"filter";
230 dev->setparameter = filter->setparameter?filter_setparameter:passthrough_setparameter;
231 dev->startpage = filter->startpage?filter_startpage:passthrough_startpage;
232 dev->startclip = filter->startclip?filter_startclip:passthrough_startclip;
233 dev->endclip = filter->endclip?filter_endclip:passthrough_endclip;
234 dev->stroke = filter->stroke?filter_stroke:passthrough_stroke;
235 dev->fill = filter->fill?filter_fill:passthrough_fill;
236 dev->fillbitmap = filter->fillbitmap?filter_fillbitmap:passthrough_fillbitmap;
237 dev->fillgradient = filter->fillgradient?filter_fillgradient:passthrough_fillgradient;
238 dev->addfont = filter->addfont?filter_addfont:passthrough_addfont;
239 dev->drawchar = filter->drawchar?filter_drawchar:passthrough_drawchar;
240 dev->drawlink = filter->drawlink?filter_drawlink:passthrough_drawlink;
241 dev->endpage = filter->endpage?filter_endpage:passthrough_endpage;
242 dev->finish = filter->finish?filter_finish:passthrough_finish;
246 static void setup_twopass(gfxdevice_t*, gfxfilter_t*filter, char passthrough);
248 static gfxresult_t* twopass_finish(gfxdevice_t*dev)
250 internal_t*i = (internal_t*)dev->internal;
252 assert(!strcmp(i->out->name, "record"));
255 if(i->filter->finish) {
256 r = i->filter->finish(i->filter, i->out);
258 r = i->out->finish(i->out);
261 if(i->pass == i->num_passes) {
262 /* this output device was not a record device, so we don't have
263 to do anything here (like cleanup) */
267 /* switch to next pass filter */
268 i->filter = &i->twopass->pass2;
270 if(i->pass == i->num_passes-1) {
271 /* we don't record in the final pass- we just stream out to the
272 next output device */
273 i->out = i->final_out;
275 // this only happens for 3 passes or more
276 assert(i->num_passes>2);
277 gfxdevice_record_init(&i->record, /*use tempfile*/1);
282 gfxresult_record_replay(r, i->out);
283 r = i->out->finish(i->out);
288 gfxdevice_t*gfxtwopassfilter_apply(gfxtwopassfilter_t*twopass, gfxdevice_t*out)
290 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
291 gfxdevice_t*dev = (gfxdevice_t*)rfx_calloc(sizeof(gfxdevice_t));
293 gfxdevice_record_init(&i->record, /*use tempfile*/1);
297 i->filter = &twopass->pass1;
298 i->twopass = twopass;
302 dev->setparameter = i->filter->setparameter?filter_setparameter:passthrough_setparameter;
303 dev->startpage = i->filter->startpage?filter_startpage:passthrough_startpage;
304 dev->startclip = i->filter->startclip?filter_startclip:passthrough_startclip;
305 dev->endclip = i->filter->endclip?filter_endclip:passthrough_endclip;
306 dev->stroke = i->filter->stroke?filter_stroke:passthrough_stroke;
307 dev->fill = i->filter->fill?filter_fill:passthrough_fill;
308 dev->fillbitmap = i->filter->fillbitmap?filter_fillbitmap:passthrough_fillbitmap;
309 dev->fillgradient = i->filter->fillgradient?filter_fillgradient:passthrough_fillgradient;
310 dev->addfont = i->filter->addfont?filter_addfont:passthrough_addfont;
311 dev->drawchar = i->filter->drawchar?filter_drawchar:passthrough_drawchar;
312 dev->drawlink = i->filter->drawlink?filter_drawlink:passthrough_drawlink;
313 dev->endpage = i->filter->endpage?filter_endpage:passthrough_endpage;
314 dev->finish = twopass_finish;
317 dev->name = i->filter->name?i->filter->name:"filter";
318 dev->finish = twopass_finish;