base_objects=q.$(O) utf8.$(O) png.$(O) jpeg.$(O) wav.$(O) mp3.$(O) os.$(O) bitio.$(O) log.$(O) mem.$(O) MD5.$(O) xml.$(O) ttf.$(O)
devices=devices/dummy.$(O) devices/file.$(O) devices/render.$(O) devices/text.$(O) devices/record.$(O) devices/ops.$(O) devices/polyops.$(O) devices/bbox.$(O) devices/rescale.$(O) @DEVICE_OPENGL@ @DEVICE_PDF@
-filters=filters/alpha.$(O) filters/remove_font_transforms.$(O)
+filters=filters/alpha.$(O) filters/remove_font_transforms.$(O) filters/one_big_font.$(O)
gfx_objects=gfximage.$(O) gfxtools.$(O) gfxfont.$(O) gfxfilter.$(O) $(devices) $(filters)
rfxswf_objects=modules/swfaction.$(O) modules/swfbits.$(O) modules/swfbutton.$(O) modules/swfcgi.$(O) modules/swfdraw.$(O) modules/swfdump.$(O) modules/swffilter.$(O) modules/swffont.$(O) modules/swfobject.$(O) modules/swfrender.$(O) modules/swfshape.$(O) modules/swfsound.$(O) modules/swftext.$(O) modules/swftools.$(O) modules/swfalignzones.$(O)
i->alpha = alpha;
memset(f, 0, sizeof(gfxfilter_t));
+ f->type = gfxfilter_onepass;
f->name = "maketransparent";
f->internal = i;
f->stroke = maketransparent_stroke;
--- /dev/null
+/* remove_font_transform.c
+
+ Part of the swftools package.
+
+ Copyright (c) 2010 Matthias Kramm <kramm@quiss.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <stdlib.h>
+#include <memory.h>
+#include "../gfxfilter.h"
+#include "../gfxtools.h"
+#include "../gfxfont.h"
+#include "../types.h"
+#include "../mem.h"
+
+typedef struct _internal {
+ gfxfontlist_t*fonts;
+ gfxfont_t*font;
+ int num_glyphs;
+} internal_t;
+
+typedef struct _fontdata {
+ gfxfont_t*font;
+ int start;
+} fontdata_t;
+
+static void pass1_drawchar(gfxfilter_t*f, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix, gfxdevice_t*out)
+{
+ internal_t*i = (internal_t*)f->internal;
+ fontdata_t*d = gfxfontlist_getuserdata(i->fonts, font->id);
+ if(!d) {
+ d = rfx_calloc(sizeof(fontdata_t));
+ d->font = font;
+ d->start = i->num_glyphs;
+ i->num_glyphs += font->num_glyphs;
+ i->fonts = gfxfontlist_addfont2(i->fonts, font, d);
+ }
+ out->drawchar(out, font, glyphnr, color, matrix);
+}
+static gfxresult_t*pass1_finish(gfxfilter_t*f, gfxdevice_t*out)
+{
+ internal_t*i = (internal_t*)f->internal;
+ gfxfont_t*font = i->font = rfx_calloc(sizeof(gfxfont_t));
+ font->id = strdup("onebigfont");
+ font->num_glyphs = i->num_glyphs;
+ font->glyphs = rfx_calloc(sizeof(gfxglyph_t)*i->num_glyphs);
+ gfxfontlist_t*l = i->fonts;
+ while(l) {
+ gfxfont_t*old = l->font;
+ fontdata_t*d = l->user;
+ memcpy(font->glyphs + d->start, old->glyphs, sizeof(gfxglyph_t)*old->num_glyphs);
+ if(old->ascent > font->ascent)
+ font->ascent = old->ascent;
+ if(old->descent > font->descent)
+ font->descent = old->descent;
+ l = l->next;
+ }
+ gfxfont_fix_unicode(font);
+ return out->finish(out);
+}
+
+static void pass2_addfont(gfxfilter_t*f, gfxfont_t*font, gfxdevice_t*out)
+{
+ internal_t*i = (internal_t*)f->internal;
+ out->addfont(out, i->font);
+}
+static void pass2_drawchar(gfxfilter_t*f, gfxfont_t*font, int glyphnr, gfxcolor_t*color, gfxmatrix_t*matrix, gfxdevice_t*out)
+{
+ internal_t*i = (internal_t*)f->internal;
+ fontdata_t*d = gfxfontlist_getuserdata(i->fonts, font->id);
+ out->drawchar(out, i->font, glyphnr + d->start, color, matrix);
+}
+static gfxresult_t*pass2_finish(gfxfilter_t*f, gfxdevice_t*out)
+{
+ internal_t*i = (internal_t*)f->internal;
+ // clean up
+ gfxfontlist_t*l = i->fonts;
+ while(l) {
+ free(l->user);l->user=0;
+ l=l->next;
+ }
+ gfxfontlist_free(i->fonts, 0);i->fonts=0;
+ return out->finish(out);
+}
+
+void gfxtwopassfilter_one_big_font_init(gfxtwopassfilter_t*f)
+{
+ internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
+
+ memset(f, 0, sizeof(gfxtwopassfilter_t));
+ f->type = gfxfilter_twopass;
+
+ f->pass1.name = "filter \"one big font\" pass 1";
+ f->pass1.drawchar = pass1_drawchar;
+ f->pass1.finish = pass1_finish;
+ f->pass1.internal = i;
+
+ f->pass2.name = "filter \"one big font\" pass 2";
+ f->pass2.addfont = pass2_addfont;
+ f->pass2.drawchar = pass2_drawchar;
+ f->pass2.finish = pass2_finish;
+ f->pass2.internal = i;
+}
+
{
internal_t*i = (internal_t*)rfx_calloc(sizeof(internal_t));
memset(f, 0, sizeof(gfxtwopassfilter_t));
+ f->type = gfxfilter_twopass;
f->pass1.name = "remove font transforms pass 1";
f->pass1.drawchar = pass1_drawchar;
f->pass1.internal = i;
#include "mem.h"
#include "gfxfilter.h"
#include "devices/record.h"
+#include "q.h"
typedef struct _internal {
gfxfilter_t*filter;
}
i->pass++;
- gfxresult_record_replay(r, i->out);
+ gfxresult_record_replay(r, dev);
r->destroy(r);
return twopass_finish(dev);
return dev;
}
+gfxfilterchain_t* gfxfilterchain_parse(const char*_filterexpr)
+{
+ char*filterexpr = strdup(_filterexpr);
+ char*f = filterexpr;
+ char*end = filterexpr+strlen(filterexpr);
+ dict_t* params = dict_new2(&charptr_type);
+ char*cmd = 0;
+
+ gfxfilterchain_t*chain = 0;
+ gfxfilterchain_t*next = 0;
+
+ if(!*f)
+ return 0;
+
+ while(1) {
+ char* eq = strchr(f, '=');
+ char* colon = strchr(f, ':');
+ char lastitem = 0;
+ if(!colon) {
+ colon = end;
+ lastitem = 1;
+ }
+ *colon = 0;
+ char*newcmd = 0;
+ char param = 0;
+
+ /* fixme: change this from a dict_t to gfxparams_t? */
+ if(eq && eq < colon) { // parameter
+ *eq = 0;
+ if(!cmd) {
+ fprintf(stderr, "Error: need a filter before specifying parameters (%s=%s)\n", f, eq+1);
+ return 0;
+ }
+ dict_put(params, f, strdup(eq+1));
+ param = 1;
+ } else {
+ newcmd = f;
+ }
+ if(!param || lastitem) {
+ if(!cmd && lastitem)
+ cmd = newcmd;
+ gfxfilterbase_t*f = 0;
+ if(!strcmp(cmd, "maketransparent")) {
+ char*alphastr = dict_lookup(params, "alpha");
+ int alpha = 255;
+ if(alphastr) alpha=atoi(alphastr);
+ f = malloc(sizeof(gfxfilter_t));
+ gfxfilter_maketransparent_init((gfxfilter_t*)f, alpha);
+ } else if(!strcmp(cmd, "remove_font_transforms")) {
+ f = malloc(sizeof(gfxtwopassfilter_t));
+ gfxtwopassfilter_remove_font_transforms_init((gfxtwopassfilter_t*)f);
+ } else if(!strcmp(cmd, "one_big_font")) {
+ f = malloc(sizeof(gfxtwopassfilter_t));
+ gfxtwopassfilter_one_big_font_init((gfxtwopassfilter_t*)f);
+ } else {
+ fprintf(stderr, "Unknown filter: %s\n", cmd);
+ return 0;
+ }
+ dict_clear(params);
+ gfxfilterchain_t*n = rfx_calloc(sizeof(gfxfilterchain_t));
+ if(!chain) {
+ chain = next = n;
+ } else {
+ next->next = n;
+ next = n;
+ }
+ n->filter = f;
+
+ cmd = newcmd;
+ if(lastitem) break;
+ }
+ f = colon+1;
+ }
+ dict_destroy(params);
+ return chain;
+}
+
+gfxdevice_t* gfxfilterchain_apply(gfxfilterchain_t*chain, gfxdevice_t*dev)
+{
+ while(chain) {
+ if(chain->filter->type == gfxfilter_onepass) {
+ dev = gfxfilter_apply((gfxfilter_t*)chain->filter, dev);
+ } else if(chain->filter->type == gfxfilter_twopass) {
+ dev = gfxtwopassfilter_apply((gfxtwopassfilter_t*)chain->filter, dev);
+ } else {
+ fprintf(stderr, "Internal error in gfxfilterchain_apply- unknown filter type %d\n", chain->filter->type);
+ }
+ chain = chain->next;
+ }
+ return dev;
+}
+
+void gfxfilterchain_destroy(gfxfilterchain_t*chain)
+{
+ while(chain) {
+ gfxfilterchain_t*next = chain->next;
+ free(chain);
+ chain = next;
+ }
+}
extern "C" {
#endif
+typedef enum {gfxfilter_none, gfxfilter_onepass, gfxfilter_twopass} gfxfiltertype_t;
+
+typedef struct _gfxfilterbase
+{
+ gfxfiltertype_t type;
+} gfxfilterbase_t;
+
typedef struct _gfxfilter
{
+ gfxfiltertype_t type;
int num_passes;
const char*name;
+
int pass;
int (*setparameter)(struct _gfxfilter*in, const char*key, const char*value, struct _gfxdevice*out);
typedef struct _gfxtwopassfilter
{
+ gfxfiltertype_t type;
gfxfilter_t pass1;
gfxfilter_t pass2;
} gfxtwopassfilter_t;
gfxdevice_t*gfxfilter_apply(gfxfilter_t*filter, gfxdevice_t*dev);
gfxdevice_t*gfxtwopassfilter_apply(gfxtwopassfilter_t*filter, gfxdevice_t*dev);
+typedef struct _gfxfilterchain {
+ gfxfilterbase_t*filter;
+ struct _gfxfilterchain*next;
+} gfxfilterchain_t;
+
+gfxfilterchain_t* gfxfilterchain_parse(const char*filterexpr);
+gfxdevice_t* gfxfilterchain_apply(gfxfilterchain_t*chain, gfxdevice_t*dev);
+void gfxfilterchain_destroy(gfxfilterchain_t*chain);
+
#define wrap_filter(dev, name, args...) \
{gfxfilter_t f_##name; \
gfxfilter_##name##_init(&f_##name, ## args); \
/* known filters */
void gfxfilter_maketransparent_init(gfxfilter_t*f, U8 alpha);
void gfxtwopassfilter_remove_font_transforms_init(gfxtwopassfilter_t*f);
+void gfxtwopassfilter_one_big_font_init(gfxtwopassfilter_t*f);
-void check_filter();
#ifdef __cplusplus
}
static int flatten = 0;
+static char* filters = 0;
+
char* fontpaths[256];
int fontpathpos = 0;
store_parameter("extrafontdata", "1");
return 0;
}
+ else if (!strcmp(name, "ff"))
+ {
+ if(filters) {
+ // append this to the current filter expression (we allow more than one --filter)
+ int l = strlen(filters);
+ int new_len = l + strlen(val) + 2;
+ filters = (char*)realloc(filters, new_len);
+ filters[l] = ':';
+ strcpy(filters+l+1, val);
+ } else {
+ filters = strdup(val);
+ }
+ return 1;
+ }
else if (!strcmp(name, "w"))
{
store_parameter("linksopennewwindow", "0");
{"t", "stop"},
{"T", "flashversion"},
{"F", "fontdir"},
+{"ff", "filter"},
{"b", "defaultviewer"},
{"l", "defaultloader"},
{"B", "viewer"},
out = &rescale;
}
+ if(filters) {
+ gfxfilterchain_t*chain = gfxfilterchain_parse(filters);
+ if(!chain) {
+ fprintf(stderr, "Unable to parse filters: %s\n", filters);
+ exit(1);
+ }
+ out = gfxfilterchain_apply(chain, out);
+ gfxfilterchain_destroy(chain);
+ }
+
/* pass global parameters to output device */
parameter_t*p = device_config;
while(p) {
p->next = 0;free(p);
p = next;
}
+ if(filters) {
+ free(filters);
+ }
return 0;
}