From: Matthias Kramm Date: Fri, 30 Oct 2009 20:37:29 +0000 (-0700) Subject: added fontalign polygon detector X-Git-Tag: version-0-9-1~252 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=9b57fcd7feaf69fd54447174b19f5f377706bb15 added fontalign polygon detector --- diff --git a/lib/Makefile.in b/lib/Makefile.in index ef5a16c..27aeec3 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in @@ -16,12 +16,12 @@ as12compiler_in_source = $(as12compiler_objects) as3compiler_objects = as3/abc.$(O) as3/pool.$(O) as3/files.$(O) as3/opcodes.$(O) as3/code.$(O) as3/registry.$(O) as3/builtin.$(O) as3/parser.tab.$(O) as3/tokenizer.yy.$(O) as3/scripts.$(O) as3/compiler.$(O) as3/import.$(O) as3/expr.$(O) as3/common.$(O) as3/initcode.$(O) gfxpoly_objects = gfxpoly/active.$(O) gfxpoly/convert.$(O) gfxpoly/poly.$(O) gfxpoly/renderpoly.$(O) gfxpoly/stroke.$(O) gfxpoly/wind.$(O) gfxpoly/xrow.$(O) -rfxswf_modules = modules/swfbits.c modules/swfaction.c modules/swfdump.c modules/swfcgi.c modules/swfbutton.c modules/swftext.c modules/swffont.c modules/swftools.c modules/swfsound.c modules/swfshape.c modules/swfobject.c modules/swfdraw.c modules/swffilter.c modules/swfrender.c h.263/swfvideo.c +rfxswf_modules = modules/swfbits.c modules/swfaction.c modules/swfdump.c modules/swfcgi.c modules/swfbutton.c modules/swftext.c modules/swffont.c modules/swftools.c modules/swfsound.c modules/swfshape.c modules/swfobject.c modules/swfdraw.c modules/swffilter.c modules/swfrender.c h.263/swfvideo.c modules/swfalignzones.c base_objects=q.$(O) utf8.$(O) png.$(O) jpeg.$(O) wav.$(O) mp3.$(O) os.$(O) bitio.$(O) log.$(O) mem.$(O) gfx_objects=gfxtools.$(O) gfxfont.$(O) 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@ -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) +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) ocr_objects=gocr/box.$(O) gocr/database.$(O) gocr/detect.$(O) gocr/job.$(O) gocr/lines.$(O) gocr/list.$(O) gocr/ocr0.$(O) gocr/ocr0n.$(O) gocr/ocr1.$(O) gocr/otsu.$(O) gocr/output.$(O) gocr/pgm2asc.$(O) gocr/pixel.$(O) gocr/progress.$(O) gocr/remove.$(O) gocr/unicode.$(O) %.$(O): %.c diff --git a/lib/devices/swf.c b/lib/devices/swf.c index 6d66409..121d49c 100644 --- a/lib/devices/swf.c +++ b/lib/devices/swf.c @@ -1465,25 +1465,26 @@ void swfoutput_finalize(gfxdevice_t*dev) endpage(dev); fontlist_t *iterator = i->fontlist; + char use_font3 = i->config_flashversion>=8 && !NO_FONT3; while(iterator) { TAG*mtag = i->swf->firstTag; if(iterator->swffont) { + if(use_font3) { + // needs to be done before the reduce + swf_FontCreateAlignZones(iterator->swffont); + } if(!i->config_storeallcharacters) { msg(" Reducing font %s", iterator->swffont->name); swf_FontReduce(iterator->swffont); } int used = iterator->swffont->use && iterator->swffont->use->used_glyphs; if(used) { - if(i->config_flashversion<8 || NO_FONT3) { + if(!use_font3) { mtag = swf_InsertTag(mtag, ST_DEFINEFONT2); swf_FontSetDefine2(mtag, iterator->swffont); } else { mtag = swf_InsertTag(mtag, ST_DEFINEFONT3); swf_FontSetDefine2(mtag, iterator->swffont); - - if(i->config_flashversion>=10) - swf_FontCreateAlignZones(iterator->swffont); - if(iterator->swffont->alignzones) { mtag = swf_InsertTag(mtag, ST_DEFINEFONTALIGNZONES); swf_FontSetAlignZones(mtag, iterator->swffont); diff --git a/lib/modules/swfalignzones.c b/lib/modules/swfalignzones.c new file mode 100644 index 0000000..0c5f663 --- /dev/null +++ b/lib/modules/swfalignzones.c @@ -0,0 +1,212 @@ +#include "../rfxswf.h" + +static inline double sqr(double x) {return x*x;} + +static void draw_line(float*row, float x1, float x2, float y1, float y2, int min, int max) +{ + if(x2max) { + fprintf(stderr, "error: glyph x stroke out of bounds\n"); + return; + } + x1 -= min; + x2 -= min; + + double d = sqrt(sqr(y2-y1)+sqr(x2-x1)); + if(floor(x1)==floor(x2)) { + row[(int)floor(x1)] += d; + } else { + double i = d/(x2-x1); + int x; + int xx1 = ceil(x1); + int xx2 = floor(x2); + row[xx1] += i*(xx1-x1); + row[xx2] += i*(x2-xx2); + for(x=xx1;xxmin, area->xmax); + draw_line(column, y1, y2, x1, x2, area->ymin, area->ymax); +} + +static void find_best(float*_row, int width, int*_x1, int*_x2, int min_dist) +{ + int x1=-1, x2=-1; + float max1=-1,max2=-1; + int t; + float*row = malloc(sizeof(float)*(width+1)); + int filter_size = 100; + float* filter = malloc(sizeof(float)*(filter_size*2+1)); + double var = filter_size/3; + for(t=-filter_size;t<=filter_size;t++) { + double v = t/var; + float r = v*v/2; + filter[filter_size+t] = exp(-r); + } + filter[0]=1;filter_size=0; + + for(t=0;t<=width;t++) { + int s; + double sum = 0; + for(s=-filter_size;s<=filter_size;s++) { + if(t+s<0) continue; + if(t+s>width) continue; + sum += _row[t+s]*filter[s+filter_size]; + } + row[t] = sum; + } + + for(t=0;t<=width;t++) { + if(row[t]>max1) { + max1 = row[t]; + x1 = t; + } + } + // invalidate everything around the maximum + for(t=-min_dist+1;twidth) continue; + row[t+x1]=-1; + } + for(t=0;t<=width;t++) { + if(row[t]>max2) { + max2 = row[t]; + x2 = t; + } + } + + if(x1>0 && x2>0 && x1>x2) {int x=x1;x1=x2;x2=x;} + *_x1=x1; + *_x2=x2; + free(row); +} + +static ALIGNZONE detect_for_char(SWFFONT * f, int nr) +{ + SWFGLYPH*g = &f->glyph[nr]; + SRECT b = f->layout->bounds[nr]; + ALIGNZONE a = {0xffff,0xffff,0xffff,0xffff}; + + // negate y + int by1=b.ymin,by2=b.ymax; + b.ymin = -by2; + b.ymax = -by1; + + int width = b.xmax - b.xmin + 1; + int height = b.ymax - b.ymin + 1; + if(!width || !height) + return a; + + float*row = rfx_calloc(sizeof(float)*width); + float*column = rfx_calloc(sizeof(float)*height); + + SHAPE2*s = swf_ShapeToShape2(g->shape); + SHAPELINE*l = s->lines; + int x=0,y=0; + while(l) { + if(l->type == lineTo) { + draw_line_xy(row,column,x,-y,l->x,-l->y,&b); + } else if(l->type == splineTo) { + double x1=x,x2=l->sx,x3=l->x; + double y1=y,y2=l->sy,y3=l->y; + double c = fabs(x3-2*x2+x1) + fabs(y3-2*y2+y1); + int parts = ((int)(sqrt(c)/6))*2+1; + float xx=x1,yy=y1; + int t; + for(t=1;t<=parts;t++) { + float nx = ((t*t*x3 + 2*t*(parts-t)*x2 + (parts-t)*(parts-t)*x1)/(double)(parts*parts)); + float ny = ((t*t*y3 + 2*t*(parts-t)*y2 + (parts-t)*(parts-t)*y1)/(double)(parts*parts)); + draw_line_xy(row,column,xx,-yy,nx,-ny,&b); + xx = nx; + yy = ny; + } + } + x = l->x; + y = l->y; + l = l->next; + } + + int t; + + /* find two best x values */ + int x1=-1,y1=-1,x2=-1,y2=-1; + //int min_dist = 4000; + int min_dist = 1; + find_best(row,width,&x1,&x2,min_dist); + find_best(column,height,&y1,&y2,min_dist); + + if(x1>=0) a.x = floatToF16((x1+b.xmin) / 20480.0); + if(x2>=0) a.dx = floatToF16((x2-x1) / 20480.0); + if(y1>=0) a.y = floatToF16((y1+b.ymin) / 20480.0); + if(y2>=0) a.dy = floatToF16((y2-y1) / 20480.0); + return a; +} + +void swf_FontCreateAlignZones(SWFFONT * f) +{ + if(f->alignzones) + return; + + if(!f->layout) { + fprintf(stderr, "Error: font needs a layout for alignzones to be detected."); + return; + } + + + f->alignzones = (ALIGNZONE*)rfx_calloc(sizeof(ALIGNZONE)*f->numchars); + f->alignzone_flags = FONTALIGN_THIN; + + if(!f->layout) { + int t; + for(t=0;tnumchars;t++) { + // just align the baseline + f->alignzones[t].x = 0xffff; + f->alignzones[t].y = 0; + f->alignzones[t].dx = 0xffff; + f->alignzones[t].dy = 0xffff;//floatToF16(460.80 / 1024.0); + } + } else { + int t; + for(t=0;tnumchars;t++) { + f->alignzones[t] = detect_for_char(f, t); + } + } + +/* + "-^_~\xad\xaf+`\xac\xb7\xf7" //chars for which to detect one y value + "#=:;\xb1" //chars for which to detect two y values + "\"\xa8" //chars for which to detect two x values +*/ +} + +void swf_FontSetAlignZones(TAG*t, SWFFONT *f) +{ + swf_SetU16(t, f->id); + swf_SetU8(t, f->alignzone_flags); + int i; + for(i=0;inumchars;i++) { + ALIGNZONE*a = &f->alignzones[i]; + U8 flags = 0; + if((a->x & a->dx)!=0xffff) + flags |= 1; + if((a->y & a->dy)!=0xffff) + flags |= 2; + int num = 1; + if(a->dx != 0xffff || a->dy != 0xffff) + num++; + swf_SetU8(t, num); + if(flags&1) swf_SetU16(t, a->x); else swf_SetU16(t, 0); + if(flags&2) swf_SetU16(t, a->y); else swf_SetU16(t, 0); + if(num==2) { + if((flags&1) && a->dx!=0xffff) swf_SetU16(t, a->dx); else swf_SetU16(t, 0); + if((flags&2) && a->dy!=0xffff) swf_SetU16(t, a->dy); else swf_SetU16(t, 0); + } + swf_SetU8(t, flags); + } +} + + diff --git a/lib/modules/swftext.c b/lib/modules/swftext.c index 912e8fa..b5d74f0 100644 --- a/lib/modules/swftext.c +++ b/lib/modules/swftext.c @@ -373,28 +373,6 @@ int swf_FontExtract_DefineFont2(int id, SWFFONT * font, TAG * tag) return font->id; } -static float F16toFloat(U16 x) -{ - TAG t; - t.data = (void*)&x; - t.readBit = 0; - t.pos = 0; - t.len = 2; - return swf_GetF16(&t); -} - -static float floatToF16(float f) -{ - U16 u = 0; - TAG t; - t.data = (void*)&u; - t.len = 0; - t.memsize = 2; - t.writeBit = 0; - swf_SetF16(&t, f); - return u; -} - int swf_FontExtract_DefineFontAlignZones(int id, SWFFONT * font, TAG * tag) { U16 fid; @@ -1103,27 +1081,6 @@ int swf_FontSetDefine2(TAG * tag, SWFFONT * f) return 0; } -void swf_FontSetAlignZones(TAG*t, SWFFONT *f) -{ - swf_SetU16(t, f->id); - swf_SetU8(t, f->alignzone_flags); - int i; - for(i=0;inumchars;i++) { - ALIGNZONE*a = &f->alignzones[i]; - U8 flags = 0; - if((a->x & a->dx)!=0xffff) - flags |= 1; - if((a->y & a->dy)!=0xffff) - flags |= 2; - swf_SetU8(t, 2); - if(flags&1) swf_SetU16(t, a->x); else swf_SetU16(t, 0); - if(flags&2) swf_SetU16(t, a->y); else swf_SetU16(t, 0); - if((flags&1) && a->dx!=0xffff) swf_SetU16(t, a->dx); else swf_SetU16(t, 0); - if((flags&2) && a->dy!=0xffff) swf_SetU16(t, a->dy); else swf_SetU16(t, 0); - swf_SetU8(t, flags); - } -} - void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading) { f->layout = (SWFLAYOUT *) rfx_alloc(sizeof(SWFLAYOUT)); @@ -1608,46 +1565,6 @@ void swf_FontCreateLayout(SWFFONT * f) } } -#define FONTALIGN_THIN -#define FONTALIGN_MEDIUM -#define FONTALIGN_THICK - -void swf_FontCreateAlignZones(SWFFONT * f) -{ - if(f->alignzones) - return; - - f->alignzones = (ALIGNZONE*)rfx_calloc(sizeof(ALIGNZONE)*f->numchars); - f->alignzone_flags = 0; // thin - - if(!f->layout) { - int t; - for(t=0;tnumchars;t++) { - // just align the baseline - f->alignzones[t].x = 0xffff; - f->alignzones[t].y = 0; - f->alignzones[t].dx = 0xffff; - f->alignzones[t].dy = 0xffff;//floatToF16(460.80 / 1024.0); - } - } else { - int t; - for(t=0;tnumchars;t++) { - // just align the baseline - f->alignzones[t].x = 0xffff; - f->alignzones[t].y = 0; - f->alignzones[t].dx = 0xffff; - f->alignzones[t].dy = 0xffff;//floatToF16(460.80 / 1024.0); - } - } - -/* - "-^_~\xad\xaf+`\xac\xb7\xf7" //chars for which to detect one y value - "#=:;\xb1" //chars for which to detect two y values - "\"\xa8" //chars for which to detect two x values -*/ -} - - void swf_DrawText(drawer_t * draw, SWFFONT * font, int size, const char *text) { U8 *s = (U8 *) text; @@ -2082,4 +1999,3 @@ char*data = swf_SaveSWF(&swf, filename); swf_FreeTags(&swf); } - diff --git a/lib/rfxswf.c b/lib/rfxswf.c index 025bcaf..c9006c1 100644 --- a/lib/rfxswf.c +++ b/lib/rfxswf.c @@ -474,6 +474,28 @@ void swf_SetF16(TAG * t, float f) swf_SetU16(t, result); } +float F16toFloat(U16 x) +{ + TAG t; + t.data = (void*)&x; + t.readBit = 0; + t.pos = 0; + t.len = 2; + return swf_GetF16(&t); +} + +float floatToF16(float f) +{ + U16 u = 0; + TAG t; + t.data = (void*)&u; + t.len = 0; + t.memsize = 2; + t.writeBit = 0; + swf_SetF16(&t, f); + return u; +} + double swf_GetD64(TAG*tag) { /* FIXME: this is not big-endian compatible */ diff --git a/lib/rfxswf.h b/lib/rfxswf.h index f586849..8c102c9 100644 --- a/lib/rfxswf.h +++ b/lib/rfxswf.h @@ -245,6 +245,9 @@ int swf_SetU32(TAG * t,U32 v); void swf_SetF16(TAG * t,float f); void swf_SetString(TAG*t,const char*s); +float floatToF16(float f); +float F16toFloat(U16 x); + /* abc datatypes */ U32 swf_GetU30(TAG*tag); int swf_SetU30(TAG*tag, U32 u); @@ -540,6 +543,10 @@ typedef struct _FONTUSAGE #define FONT_ENCODING_ANSI 2 #define FONT_ENCODING_SHIFTJIS 4 +#define FONTALIGN_THIN 0 +#define FONTALIGN_MEDIUM 1 +#define FONTALIGN_THICK 2 + typedef struct _ALIGNZONE { U16 x,y; diff --git a/src/Makefile.in b/src/Makefile.in index 86cf573..463b8d9 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -53,7 +53,7 @@ swfc-interpolation.$(O): swfc-interpolation.c swfc-interpolation.h ../lib/q.h parser.$(O): parser.yy.c parser.h ../lib/q.h $(C) parser.yy.c -o $@ -../lib/librfxswf$(A): ../lib/modules/swfrender.c ../lib/modules/swfshape.c ../lib/modules/swftext.c ../lib/modules/swffont.c ../lib/modules/swfbits.c ../lib/rfxswf.c ../lib/devices/swf.c +../lib/librfxswf$(A): ../lib/modules/swfrender.c ../lib/modules/swfshape.c ../lib/modules/swftext.c ../lib/modules/swffont.c ../lib/modules/swfbits.c ../lib/rfxswf.c ../lib/devices/swf.c ../lib/modules/swfalignzones.c cd ../lib;$(MAKE) librfxswf$(A);cd - # TODO: include the following rule only if lex is available diff --git a/src/font2swf.c b/src/font2swf.c index cd30118..55c06cd 100644 --- a/src/font2swf.c +++ b/src/font2swf.c @@ -98,6 +98,7 @@ static void convertFont(char*infile, char*outfile) SWFFONT * font; font = swf_LoadFont(infile); + swf_FontCreateAlignZones(font); if(fontname) font->name = strdup(fontname); diff --git a/src/swfdump.c b/src/swfdump.c index acc1806..f903aa7 100644 --- a/src/swfdump.c +++ b/src/swfdump.c @@ -1016,15 +1016,18 @@ static void handleFontAlign2(TAG*tag, char*prefix) printf("%sglyph %d) ", prefix, num); int nr = swf_GetU8(tag); // should be 2 int t; - for(t=0;t