From: Matthias Kramm Date: Thu, 1 Apr 2010 02:23:16 +0000 (-0700) Subject: added vectors_to_glyphs filter X-Git-Tag: version-0-9-1~59 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=3116692a2512f2bfae346a1074d1fdfa00ea9d2c added vectors_to_glyphs filter --- diff --git a/lib/Makefile.in b/lib/Makefile.in index 2a34e89..28a9aba 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -20,7 +20,7 @@ rfxswf_modules = modules/swfbits.c modules/swfaction.c modules/swfdump.c module 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/one_big_font.$(O) +filters=filters/alpha.$(O) filters/remove_font_transforms.$(O) filters/one_big_font.$(O) filters/vectors_to_glyphs.$(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) diff --git a/lib/devices/record.c b/lib/devices/record.c index 165e4c5..8f7b40a 100644 --- a/lib/devices/record.c +++ b/lib/devices/record.c @@ -97,6 +97,7 @@ typedef struct _internal_result { #define OP_FINISH 0x0d #define FLAG_SAME_AS_LAST 0x10 +#define FLAG_ZERO_FONT 0x20 #define LINE_MOVETO 0x0e #define LINE_LINETO 0x0f @@ -579,14 +580,18 @@ static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr, } msg(" record: %08x DRAWCHAR %d\n", glyphnr, dev); - const char*font_id = font->id?font->id:"*NULL*"; + const char*font_id = (font&&font->id)?font->id:"*NULL*"; gfxmatrix_t*l = &i->state.last_matrix[OP_DRAWCHAR]; + U8 flags = 0; + if(!font) + flags |= FLAG_ZERO_FONT; + char same_font = i->state.last_string[OP_DRAWCHAR] && !strcmp(i->state.last_string[OP_DRAWCHAR], font_id); char same_matrix = (l->m00 == matrix->m00) && (l->m01 == matrix->m01) && (l->m10 == matrix->m10) && (l->m11 == matrix->m11); char same_color = !memcmp(color, &i->state.last_color[OP_DRAWCHAR], sizeof(gfxcolor_t)); - U8 flags = 0; + if(same_font && same_matrix && same_color) flags |= FLAG_SAME_AS_LAST; @@ -597,7 +602,8 @@ static void record_drawchar(struct _gfxdevice*dev, gfxfont_t*font, int glyphnr, #endif if(!(flags&FLAG_SAME_AS_LAST)) { - writer_writeString(&i->w, font_id); + if(!(flags&FLAG_ZERO_FONT)) + writer_writeString(&i->w, font_id); dumpColor(&i->w, &i->state, color); dumpMatrix(&i->w, &i->state, matrix); i->state.last_string[OP_DRAWCHAR] = strdup(font_id); @@ -776,7 +782,9 @@ static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r) case OP_DRAWCHAR: { U32 glyph = reader_readU32(r); gfxmatrix_t m = {1,0,0, 0,1,0}; - char* id = read_string(r, &state, op, flags); + char* id = 0; + if(!(flags&FLAG_ZERO_FONT)) + id = read_string(r, &state, op, flags); gfxcolor_t color = read_color(r, &state, op, flags); gfxmatrix_t matrix = read_matrix(r, &state, op, flags); @@ -786,7 +794,8 @@ static void replay(struct _gfxdevice*dev, gfxdevice_t*out, reader_t*r) } msg(" replay: DRAWCHAR font=%s glyph=%d", id, glyph); out->drawchar(out, font, glyph, &color, &matrix); - free(id); + if(id) + free(id); break; } } diff --git a/lib/filters/vectors_to_glyphs.c b/lib/filters/vectors_to_glyphs.c new file mode 100644 index 0000000..a1eb7ee --- /dev/null +++ b/lib/filters/vectors_to_glyphs.c @@ -0,0 +1,165 @@ +/* vectors_to_fonts.c + + Part of the swftools package. + + Copyright (c) 2010 Matthias Kramm + + 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 +#include +#include +#include "../gfxfilter.h" +#include "../gfxtools.h" +#include "../gfxpoly.h" +#include "../gfxfont.h" +#include "../types.h" +#include "../mem.h" +#include "../q.h" + +typedef struct _vglyph { + gfxglyph_t glyph; + struct _vglyph*next; +} vglyph_t; + +typedef struct _internal { + vglyph_t*first_glyph; + vglyph_t*last_glyph; + gfxfont_t*font; + char first; + int glyph_nr; +} internal_t; + +#define FONT_SIZE 1024.0 + +static void pass1_fill(gfxfilter_t*f, gfxline_t*line, gfxcolor_t*color, gfxdevice_t*out) +{ + internal_t*i = (internal_t*)f->internal; + gfxbbox_t bbox = gfxline_getbbox(line); + double height = bbox.ymax - bbox.ymin; + double width = bbox.xmax - bbox.xmin; + double size = fmax(width,height); + if(fabs(size) < 1e-3) return; + double scale = FONT_SIZE/size; + gfxmatrix_t m = {scale, 0, -bbox.xmin*scale, + 0, scale, -bbox.ymax*scale}; + line = gfxline_clone(line); + gfxline_transform(line, &m); + line = gfxline_restitch(line); + vglyph_t*v = rfx_calloc(sizeof(vglyph_t)); + v->glyph.line = line; + v->glyph.advance = width*scale; + v->glyph.unicode = 32+i->glyph_nr; + + i->last_glyph->next = v; + i->last_glyph = v; + + gfxmatrix_t m2 = {1.0/scale, 0, bbox.xmin, + 0, 1.0/scale, bbox.ymax}; + out->drawchar(out, 0, i->glyph_nr, color, &m2); + + i->glyph_nr++; +} +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) +{ + return; + internal_t*i = (internal_t*)f->internal; + gfxpoly_t*poly = gfxpoly_from_stroke(line, width, cap_style, joint_style, miterLimit, DEFAULT_GRID); + gfxline_t*line2 = gfxline_from_gfxpoly_with_direction(poly); + pass1_fill(f, line2, color, out); + gfxline_free(line2); + gfxpoly_destroy(poly); +} + +static void make_font(internal_t*i) +{ + i->font = rfx_calloc(sizeof(gfxfont_t)); + i->font->id = "SWFTools-Vector-Magic"; + i->font->num_glyphs = i->glyph_nr; + i->font->glyphs = malloc(sizeof(gfxglyph_t)*i->font->num_glyphs); + i->font->ascent = FONT_SIZE; + i->font->descent = 0; + int pos = 0; + vglyph_t*g = i->first_glyph; + while(g) { + i->font->glyphs[pos] = g->glyph; + pos++; + g = g->next; + } + gfxfont_fix_unicode(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; + if(i->first) { + make_font(i); + out->addfont(out, i->font); + i->first = 0; + } + if(!font) { + font = i->font; + + gfxcolor_t red = {255,254,1,1}; + int x; + gfxmatrix_t m = {1.0, 0,0, + 0, 1.0,0}; + out->drawchar(out, font, 1, &red, &m); + + /*gfxmatrix_t m2 = {1.0, 0,600, + 0, 1.0,600}; + out->drawchar(out, font, 1, &red, &m2);*/ + gfxline_t*line = gfxline_makerectangle(0, 0, 1, 1); + gfximage_t img; + img.data = color; + img.width = 1; + img.height = 1; + out->fillbitmap(out, line, &img, &m, 0); + } + out->drawchar(out, font, glyphnr, color, matrix); +} + +void gfxtwopassfilter_vectors_to_glyphs_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 = "vectors to glyphs pass 1"; + f->pass1.fill = pass1_fill; + f->pass1.stroke = pass1_stroke; + f->pass1.internal = i; + + f->pass2.name = "vectors to glyphs pass 2"; + f->pass2.drawchar = pass2_drawchar; + f->pass2.internal = i; + + i->first = 1; + + i->first_glyph = rfx_calloc(sizeof(vglyph_t)); + i->first_glyph->glyph.line = 0; + i->first_glyph->glyph.advance = FONT_SIZE; + i->first_glyph->glyph.unicode = 32; + i->last_glyph = rfx_calloc(sizeof(vglyph_t)); + // dummy char + i->first_glyph->next = i->last_glyph; + i->last_glyph->glyph.line = 0; + i->last_glyph->glyph.advance = FONT_SIZE/8; + i->last_glyph->glyph.unicode = 33; + i->glyph_nr = 2; +} + + diff --git a/lib/gfxfilter.c b/lib/gfxfilter.c index 24b969e..f1a341a 100644 --- a/lib/gfxfilter.c +++ b/lib/gfxfilter.c @@ -361,7 +361,7 @@ gfxfilterchain_t* gfxfilterchain_parse(const char*_filterexpr) *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; @@ -377,6 +377,7 @@ gfxfilterchain_t* gfxfilterchain_parse(const char*_filterexpr) if(!param || lastitem) { if(!cmd && lastitem) cmd = newcmd; + assert(cmd); gfxfilterbase_t*f = 0; if(!strcmp(cmd, "maketransparent")) { char*alphastr = dict_lookup(params, "alpha"); @@ -387,6 +388,9 @@ gfxfilterchain_t* gfxfilterchain_parse(const char*_filterexpr) } else if(!strcmp(cmd, "remove_font_transforms")) { f = malloc(sizeof(gfxtwopassfilter_t)); gfxtwopassfilter_remove_font_transforms_init((gfxtwopassfilter_t*)f); + } else if(!strcmp(cmd, "vectors_to_glyphs")) { + f = malloc(sizeof(gfxtwopassfilter_t)); + gfxtwopassfilter_vectors_to_glyphs_init((gfxtwopassfilter_t*)f); } else if(!strcmp(cmd, "one_big_font")) { f = malloc(sizeof(gfxtwopassfilter_t)); gfxtwopassfilter_one_big_font_init((gfxtwopassfilter_t*)f); diff --git a/lib/gfxfilter.h b/lib/gfxfilter.h index 6de443e..0b341f7 100644 --- a/lib/gfxfilter.h +++ b/lib/gfxfilter.h @@ -97,6 +97,7 @@ void gfxfilterchain_destroy(gfxfilterchain_t*chain); 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 gfxtwopassfilter_vectors_to_glyphs_init(gfxtwopassfilter_t*f); #ifdef __cplusplus diff --git a/lib/gfxpoly.h b/lib/gfxpoly.h index c1e3a38..b8329c8 100644 --- a/lib/gfxpoly.h +++ b/lib/gfxpoly.h @@ -53,6 +53,7 @@ gfxpoly_t* gfxpoly_union(gfxpoly_t*p1, gfxpoly_t*p2); /* conversion functions */ gfxpoly_t* gfxpoly_createbox(double x1, double y1,double x2, double y2, double gridsize); gfxline_t* gfxline_from_gfxpoly(gfxpoly_t*poly); +gfxline_t* gfxline_from_gfxpoly_with_direction(gfxpoly_t*poly); gfxline_t* gfxpoly_circular_to_evenodd(gfxline_t*line, double gridsize); #ifdef __cplusplus diff --git a/lib/gfxpoly/convert.c b/lib/gfxpoly/convert.c index f67699e..0a2cc93 100644 --- a/lib/gfxpoly/convert.c +++ b/lib/gfxpoly/convert.c @@ -513,7 +513,7 @@ gfxline_t*gfxline_from_gfxpoly(gfxpoly_t*poly) return mkgfxline(poly, 0); } -gfxline_t*gfxline_from_gfxpoly_updown(gfxpoly_t*poly) +gfxline_t*gfxline_from_gfxpoly_with_direction(gfxpoly_t*poly) { return mkgfxline(poly, 1); } diff --git a/lib/gfxpoly/convert.h b/lib/gfxpoly/convert.h index 7c18958..c02e385 100644 --- a/lib/gfxpoly/convert.h +++ b/lib/gfxpoly/convert.h @@ -22,7 +22,7 @@ gfxpoly_t* gfxpoly_from_file(const char*filename, double gridsize); void gfxpoly_destroy(gfxpoly_t*poly); gfxline_t*gfxline_from_gfxpoly(gfxpoly_t*poly); -gfxline_t*gfxline_from_gfxpoly_updown(gfxpoly_t*poly); // preserves up/down +gfxline_t*gfxline_from_gfxpoly_with_direction(gfxpoly_t*poly); // preserves up/down gfxline_t* gfxpoly_circular_to_evenodd(gfxline_t*line, double gridsize); gfxpoly_t* gfxpoly_createbox(double x1, double y1,double x2, double y2, double gridsize); diff --git a/lib/ruby/gfx.c b/lib/ruby/gfx.c index 3a5f60c..3227449 100644 --- a/lib/ruby/gfx.c +++ b/lib/ruby/gfx.c @@ -437,6 +437,7 @@ static ID id_radial = 0; static ID id_linear = 0; static ID id_remove_font_transforms = 0; static ID id_maketransparent = 0; +static ID id_vectors_to_glyphs = 0; static VALUE noop(int argc, VALUE *argv, VALUE obj) {return obj;} @@ -707,6 +708,8 @@ static VALUE doc_render(VALUE cls, VALUE device, VALUE _range, VALUE filters) else x = RARRAY(filters)->ptr[t++]; if(id == id_remove_font_transforms) { wrap_filter2(dev, remove_font_transforms); + } else if(id == id_vectors_to_glyphs) { + wrap_filter2(dev, vectors_to_glyphs); } else if(id == id_maketransparent) { PARAM(alpha); wrap_filter(dev, maketransparent, FIX2INT(alpha)); @@ -856,5 +859,6 @@ void Init_gfx() id_linear = rb_intern("linear"); id_remove_font_transforms = rb_intern("remove_font_transforms"); id_maketransparent = rb_intern("maketransparent"); + id_vectors_to_glyphs = rb_intern("vectors_to_glyphs"); }