fix crashes reported by Debian Cylab Mayhem Team
[swftools.git] / lib / filters / remove_invisible_characters.c
blob2d1df9c2b19c89644b0ee0fca68a610fa923e403
1 /* remove_invisible_characters.c
3 Part of the swftools package.
5 Copyright (c) 2011 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 */
21 #include <stdlib.h>
22 #include <stdint.h>
23 #include <memory.h>
24 #include "../gfxfilter.h"
25 #include "../gfxtools.h"
26 #include "../gfxfont.h"
27 #include "../gfxpoly.h"
28 #include "../gfximage.h"
29 #include "../types.h"
30 #include "../mem.h"
31 #include "../devices/render.h"
33 typedef struct _page {
34 uint8_t* visible;
35 int size8;
36 int size;
37 struct _page*next;
38 } page_t;
40 typedef struct _internal {
41 gfxdevice_t render;
42 int count;
44 double area;
46 page_t*first_page;
47 page_t*last_page;
49 page_t*current_page;
50 } internal_t;
52 static gfxcolor_t black = {255,0,0,0};
54 static void pass1_startpage(gfxfilter_t*f, int width, int height, gfxdevice_t*out)
56 internal_t*i = (internal_t*)f->internal;
57 gfxdevice_render_init(&i->render);
58 i->render.startpage(&i->render, width, height);
59 out->startpage(out, width, height);
60 i->count = 0;
62 static void pass1_endpage(gfxfilter_t*f, gfxdevice_t*out)
64 internal_t*i = (internal_t*)f->internal;
65 i->render.endpage(&i->render);
66 out->endpage(out);
67 gfxresult_t*result = i->render.finish(&i->render);
69 page_t*page = (page_t*)rfx_calloc(sizeof(page_t));
70 if(!i->first_page) {
71 i->first_page = i->last_page = i->current_page = page;
72 } else {
73 i->last_page->next = page;
74 i->last_page = page;
76 page->size = i->count + 1;
77 page->size8 = (page->size+7) >> 3;
78 page->visible = (uint8_t*)rfx_calloc(page->size8);
80 gfximage_t*img = (gfximage_t*)result->get(result, "page0");
81 int size = img->width*img->height;
82 int t;
83 for(t=0;t<size;t++) {
84 int index = ((*(uint32_t*)&img->data[t])>>8);
85 page->visible[index>>3] |= (1<<(index&7));
87 result->destroy(result);
89 static void pass1_fill(gfxfilter_t*f, gfxline_t*line, gfxcolor_t*color, gfxdevice_t*out)
91 internal_t*i = (internal_t*)f->internal;
92 if(color->a == 255) {
93 i->render.fill(&i->render, line, &black);
95 out->fill(out, line, color);
97 static void pass1_stroke(gfxfilter_t*f, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit, gfxdevice_t*out)
99 internal_t*i = (internal_t*)f->internal;
100 if(color->a == 255) {
101 i->render.stroke(&i->render, line, width, &black, cap_style, joint_style, miterLimit);
103 out->stroke(out, line, width, color, cap_style, joint_style, miterLimit);
105 static void pass1_fillbitmap(gfxfilter_t*f, gfxline_t*line, gfximage_t* bitmap, gfxmatrix_t*imgcoord2devcoord, gfxcxform_t*cxform, gfxdevice_t*out)
107 internal_t*i = (internal_t*)f->internal;
108 gfximage_t*img = gfximage_new(bitmap->width, bitmap->height);
109 int size = img->width*img->height;
110 memset(img->data, 0, size*sizeof(gfxcolor_t));
111 int t;
112 for(t=0;t<size;t++) {
113 img->data[t].a = bitmap->data[t].a == 255 ? 255 : 0;
115 i->render.fillbitmap(&i->render, line, img, imgcoord2devcoord, 0);
116 gfximage_free(img);
117 out->fillbitmap(out, line, bitmap, imgcoord2devcoord, cxform);
119 static void pass1_fillgradient(gfxfilter_t*f, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*gradcoord2devcoord, gfxdevice_t*out)
121 internal_t*i = (internal_t*)f->internal;
122 i->render.fill(&i->render, line, &black);
123 out->fillgradient(out, line, gradient, type, gradcoord2devcoord);
125 static void pass1_startclip(gfxfilter_t*f, gfxline_t*line, gfxdevice_t*out)
127 internal_t*i = (internal_t*)f->internal;
128 i->render.startclip(&i->render, line);
129 out->startclip(out, line);
131 static void pass1_endclip(gfxfilter_t*f, gfxdevice_t*out)
133 internal_t*i = (internal_t*)f->internal;
134 i->render.endclip(&i->render);
135 out->endclip(out);
137 static void pass1_addfont(gfxfilter_t*f, gfxfont_t*font, gfxdevice_t*out)
139 internal_t*i = (internal_t*)f->internal;
140 /* Don't pass this to device->render(). We're not in a page
141 yet, and the render device doesn't need addfont() */
142 //i->render.addfont(&i->render, font);
143 out->addfont(out, font);
145 static void pass1_drawchar(gfxfilter_t*f, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix, gfxdevice_t*out)
147 internal_t*i = (internal_t*)f->internal;
148 i->count++;
149 gfxcolor_t c;
150 *(uint32_t*)&c = i->count<<8|0xff;
152 double advance = font->glyphs[glyphnr].advance;
153 gfxline_t*box = gfxline_makerectangle(0,0,advance,font->ascent);
154 gfxline_transform(box, matrix);
155 i->render.fill(&i->render, box, &c);
156 if(font->ascent < 512) {
157 i->render.drawchar(&i->render, font, glyphnr, &c, matrix);
159 gfxline_free(box);
161 out->drawchar(out, font, glyphnr, color, matrix);
163 static gfxresult_t*pass1_finish(gfxfilter_t*f, gfxdevice_t*out)
165 internal_t*i = (internal_t*)f->internal;
166 return out->finish(out);
169 static void pass2_startpage(gfxfilter_t*f, int width, int height, gfxdevice_t*out)
171 internal_t*i = (internal_t*)f->internal;
172 out->startpage(out, width, height);
173 i->count = 0;
175 static void pass2_endpage(gfxfilter_t*f, gfxdevice_t*out)
177 internal_t*i = (internal_t*)f->internal;
178 i->current_page = i->current_page->next;
179 out->endpage(out);
181 static void pass2_addfont(gfxfilter_t*f, gfxfont_t*font, gfxdevice_t*out)
183 internal_t*i = (internal_t*)f->internal;
184 out->addfont(out, font);
186 static void pass2_drawchar(gfxfilter_t*f, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix, gfxdevice_t*out)
188 internal_t*i = (internal_t*)f->internal;
189 i->count++;
190 if(i->current_page->visible[i->count>>3]&(1<<(i->count&7))) {
191 out->drawchar(out, font, glyphnr, color, matrix);
192 } else {
193 #ifdef DEBUG_AREA
194 gfxline_t*line = gfxline_clone(font->glyphs[glyphnr].line);
195 gfxline_transform(line, matrix);
196 gfxpoly_t*poly = gfxpoly_from_fill(line, 0.05);
197 double area = gfxpoly_area(poly);
198 gfxpoly_destroy(poly);
199 gfxline_free(line);
200 i->area += area;
201 #endif
204 static gfxresult_t*pass2_finish(gfxfilter_t*f, gfxdevice_t*out)
206 internal_t*i = (internal_t*)f->internal;
207 #ifdef DEBUG_AREA
208 printf("%f\n", i->area);
209 #endif
210 return out->finish(out);
213 void gfxtwopassfilter_remove_invisible_characters_init(gfxtwopassfilter_t*f)
215 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
217 memset(f, 0, sizeof(gfxtwopassfilter_t));
218 f->type = gfxfilter_twopass;
220 f->pass1.name = "filter \"remove invisible characters\" pass 1";
221 f->pass1.addfont = pass1_addfont;
222 f->pass1.drawchar = pass1_drawchar;
223 f->pass1.fill = pass1_fill;
224 f->pass1.fillbitmap = pass1_fillbitmap;
225 f->pass1.fillgradient = pass1_fillgradient;
226 f->pass1.stroke = pass1_stroke;
227 f->pass1.startclip= pass1_startclip;
228 f->pass1.endclip = pass1_endclip;
229 f->pass1.startpage = pass1_startpage;
230 f->pass1.endpage = pass1_endpage;
231 f->pass1.finish = pass1_finish;
232 f->pass1.internal = i;
234 f->pass2.name = "filter \"remove invisible characters\" pass 2";
235 f->pass2.addfont = pass2_addfont;
236 f->pass2.drawchar = pass2_drawchar;
237 f->pass2.startpage = pass2_startpage;
238 f->pass2.endpage = pass2_endpage;
239 f->pass2.finish = pass2_finish;
240 f->pass2.internal = i;