1 /* remove_font_transform.c
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 */
24 #include "../gfxfilter.h"
25 #include "../gfxtools.h"
26 #include "../gfxfont.h"
31 typedef struct _mymatrix {
32 float m00,m01,m10,m11;
34 double size; // not hashed
37 static void* mymatrix_clone(const void*_m) {
40 const mymatrix_t*m1=_m;
41 mymatrix_t*m2 = malloc(sizeof(mymatrix_t));
43 m2->id = strdup(m1->id);
46 static unsigned int mymatrix_hash(const void*_m) {
49 const mymatrix_t*m = (mymatrix_t*)_m;
51 h = crc32_add_bytes(h, (char*)&m->m00, sizeof(m->m00));
52 h = crc32_add_bytes(h, (char*)&m->m01, sizeof(m->m01));
53 h = crc32_add_bytes(h, (char*)&m->m10, sizeof(m->m10));
54 h = crc32_add_bytes(h, (char*)&m->m11, sizeof(m->m11));
57 static void mymatrix_destroy(void*_m) {
58 mymatrix_t*m = (mymatrix_t*)_m;
62 static char mymatrix_equals(const void*_m1, const void*_m2) {
63 const mymatrix_t*m1=_m1;
64 const mymatrix_t*m2=_m2;
68 /* we do a binary comparison of the float32
69 bits here instead of a numerical comparison
70 to prevent the compiler from e.g. removing the
71 (float) cast during optimization, which would break
72 the equivalence between equals() and hash() (as
73 the hash is derived from the float32 values) */
74 return *(U32*)&m1->m00 == *(U32*)&m2->m00 &&
75 *(U32*)&m1->m01 == *(U32*)&m2->m01 &&
76 *(U32*)&m1->m10 == *(U32*)&m2->m10 &&
77 *(U32*)&m1->m11 == *(U32*)&m2->m11;
79 type_t mymatrix_type = {
82 free: mymatrix_destroy,
83 equals: mymatrix_equals
86 typedef struct _internal {
93 void __attribute__((noinline))
94 matrix_convert(gfxmatrix_t*in, const char*id, mymatrix_t*out)
96 void matrix_convert(gfxmatrix_t*in, const char*id, mymatrix_t*out)
99 double l1 = sqrt(in->m00 * in->m00 + in->m01 * in->m01);
100 double l2 = sqrt(in->m10 * in->m10 + in->m11 * in->m11);
103 memset(out, 0, sizeof(*out));
106 out->m00 = in->m00 / l;
107 out->m01 = in->m01 / l;
108 out->m10 = in->m10 / l;
109 out->m11 = in->m11 / l;
114 typedef struct _matrixdata {
118 typedef struct _transformedfont {
125 static transformedfont_t* transformedfont_new(gfxfont_t*orig, mymatrix_t*m)
127 transformedfont_t*f = rfx_calloc(sizeof(transformedfont_t));
130 f->used = malloc(sizeof(f->used[0])*orig->num_glyphs);
134 static void pass1_drawchar(gfxfilter_t*f, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix, gfxdevice_t*out)
136 internal_t*i = (internal_t*)f->internal;
138 matrix_convert(matrix, font->id, &m);
139 transformedfont_t*fd = dict_lookup(i->matrices, &m);
141 fd = transformedfont_new(font, &m);
142 dict_put(i->matrices, &m, fd);
145 out->drawchar(out, font, glyphnr, color, matrix);
148 static gfxresult_t* pass1_finish(gfxfilter_t*f, gfxdevice_t*out)
150 internal_t*i = (internal_t*)f->internal;
151 DICT_ITERATE_DATA(i->matrices, transformedfont_t*, fd) {
152 gfxfont_t*font = fd->font = rfx_calloc(sizeof(gfxfont_t));
154 static int fontcount=0;
155 sprintf(id, "font%d", fontcount++);
156 font->id = strdup(id);
159 for(t=0;t<fd->orig->num_glyphs;t++) {
160 if(fd->used[t]) count++;
162 font->num_glyphs = count;
163 font->glyphs = rfx_calloc(sizeof(gfxglyph_t)*font->num_glyphs);
165 for(t=0;t<fd->orig->num_glyphs;t++) {
167 font->glyphs[count] = fd->orig->glyphs[t];
172 gfxfont_fix_unicode(font);
174 return out->finish(out);
177 static void pass2_drawchar(gfxfilter_t*f, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix, gfxdevice_t*out)
179 internal_t*i = (internal_t*)f->internal;
183 DICT_ITERATE_DATA(i->matrices, transformedfont_t*, fd) {
184 out->addfont(out, fd->font);
189 matrix_convert(matrix, font->id, &m);
190 transformedfont_t*d = dict_lookup(i->matrices, &m);
191 out->drawchar(out, d->font, d->used[glyphnr], color, matrix);
194 void gfxtwopassfilter_remove_font_transforms_init(gfxtwopassfilter_t*f)
196 internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
198 memset(f, 0, sizeof(gfxtwopassfilter_t));
199 f->type = gfxfilter_twopass;
201 f->pass1.name = "remove font transforms pass 1";
202 f->pass1.drawchar = pass1_drawchar;
203 f->pass1.finish = pass1_finish;
204 f->pass1.internal = i;
206 f->pass2.name = "remove font transforms pass 2";
207 f->pass2.drawchar = pass2_drawchar;
208 f->pass2.internal = i;
210 i->matrices = dict_new2(&mymatrix_type);