added vectors_to_glyphs filter
authorMatthias Kramm <kramm@quiss.org>
Thu, 1 Apr 2010 02:23:16 +0000 (19:23 -0700)
committerMatthias Kramm <kramm@quiss.org>
Thu, 1 Apr 2010 02:23:16 +0000 (19:23 -0700)
lib/Makefile.in
lib/devices/record.c
lib/filters/vectors_to_glyphs.c [new file with mode: 0644]
lib/gfxfilter.c
lib/gfxfilter.h
lib/gfxpoly.h
lib/gfxpoly/convert.c
lib/gfxpoly/convert.h
lib/ruby/gfx.c

index 2a34e89..28a9aba 100644 (file)
@@ -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)
index 165e4c5..8f7b40a 100644 (file)
@@ -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("<trace> 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("<trace> 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 (file)
index 0000000..a1eb7ee
--- /dev/null
@@ -0,0 +1,165 @@
+/* vectors_to_fonts.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 <math.h>
+#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;
+}
+
+
index 24b969e..f1a341a 100644 (file)
@@ -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);
index 6de443e..0b341f7 100644 (file)
@@ -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
index c1e3a38..b8329c8 100644 (file)
@@ -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
index f67699e..0a2cc93 100644 (file)
@@ -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);
 }
index 7c18958..c02e385 100644 (file)
@@ -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);
index 3a5f60c..3227449 100644 (file)
@@ -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");
 }