From 215363119a65a76176428f37c9eb89af91f3469b Mon Sep 17 00:00:00 2001 From: Matthias Kramm Date: Fri, 6 Nov 2009 14:27:40 -0800 Subject: [PATCH] incorporate global font information into alignzones for individual chars --- lib/modules/swfalignzones.c | 108 +++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/lib/modules/swfalignzones.c b/lib/modules/swfalignzones.c index a102a9b..6c8190f 100644 --- a/lib/modules/swfalignzones.c +++ b/lib/modules/swfalignzones.c @@ -34,8 +34,12 @@ static void draw_line_xy(float*row,float*column, float x1, float y1, float x2, f 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_size, int min, int max, char debug) +#include + +static void find_best(float*_row, int width, int*_x1, int*_x2, int min_size, int from, int to, char debug) { + assert(from>=0); + assert(to>=0); int x1=-1, x2=-1; float max1=-1e20,max2=-1e20; int t; @@ -61,7 +65,7 @@ static void find_best(float*_row, int width, int*_x1, int*_x2, int min_size, int row[t] = sum; } - for(t=0;t<=width;t++) { + for(t=from;t<=to;t++) { if(row[t]>max1) { max1 = row[t]; x1 = t; @@ -69,7 +73,7 @@ static void find_best(float*_row, int width, int*_x1, int*_x2, int min_size, int } double scale = min_size/1024.0; - for(t=0;t<=width;t++) { + for(t=from;t<=to;t++) { if(t==x1) { row[t]=-1e20; continue; @@ -79,8 +83,8 @@ static void find_best(float*_row, int width, int*_x1, int*_x2, int min_size, int double d1 = r2-r1; double d2 = d1+2; double s = d2/d1; - double ext1 = r1; - double ext2 = width*scale-r2; + double ext1 = r1-from*scale; + double ext2 = to*scale-r2; double add1 = ext1*s - ext1; double add2 = ext2*s - ext2; @@ -90,7 +94,7 @@ static void find_best(float*_row, int width, int*_x1, int*_x2, int min_size, int } } - for(t=0;t<=width;t++) { + for(t=from;t<=to;t++) { if(row[t]>max2) { max2 = row[t]; x2 = t; @@ -103,37 +107,17 @@ static void find_best(float*_row, int width, int*_x1, int*_x2, int min_size, int free(row); } -static int find_min_distance(int min_size, int height) +static void negate_y(SRECT* b) { - /* find a minimum distance between two alignzones so - that when they both, due to pixel snapping, move - into opposite directions, the subsequent character - scaling doesn't cause the upper/lower end of the char - to move outwards more than m pixels */ - int m = 4; - double scale = min_size / 1024.0; - double max_move = (2 * 1.0 / scale)/m; - return (int)(height*max_move); + // negate y + int by1=b->ymin,by2=b->ymax; + b->ymin = -by2; + b->ymax = -by1; } -static ALIGNZONE detect_for_char(SWFFONT * f, int nr) +static void draw_char(SWFFONT * f, int nr, float*row, float*column, SRECT b) { 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; @@ -160,18 +144,30 @@ static ALIGNZONE detect_for_char(SWFFONT * f, int nr) y = l->y; l = l->next; } +} + +static ALIGNZONE detect_for_char(SWFFONT * f, int nr, float*row, float*column, SRECT font_bbox, SRECT char_bbox) +{ + ALIGNZONE a = {0xffff,0xffff,0xffff,0xffff}; + int width = font_bbox.xmax - font_bbox.xmin; + int height = font_bbox.ymax - font_bbox.ymin; + if(!width || !height) + return a; - int t; - /* find two best x values */ int x1=-1,y1=-1,x2=-1,y2=-1; - find_best(row,width,&x1,&x2,f->use->smallest_size,b.xmin,b.xmax,0); - char debug = f->glyph2ascii[nr]=='o' && f->id==7; - find_best(column,height,&y1,&y2,f->use->smallest_size,b.ymin,b.ymax,debug); + find_best(row, width, &x1, &x2, f->use->smallest_size, + char_bbox.xmin - font_bbox.xmin, + char_bbox.xmax - font_bbox.xmin, + 0); + find_best(column, height, &y1, &y2, f->use->smallest_size, + char_bbox.ymin - font_bbox.ymin, + char_bbox.ymax - font_bbox.ymin, + 0); //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(y1>=0) a.y = floatToF16((y1+font_bbox.ymin) / 20480.0); if(y2>=0) a.dy = floatToF16((y2-y1) / 20480.0); return a; } @@ -186,7 +182,6 @@ void swf_FontCreateAlignZones(SWFFONT * f) return; } - f->alignzones = (ALIGNZONE*)rfx_calloc(sizeof(ALIGNZONE)*f->numchars); f->alignzone_flags = FONTALIGN_MEDIUM; @@ -201,16 +196,37 @@ void swf_FontCreateAlignZones(SWFFONT * f) } } else { int t; + SRECT bounds = {0,0,0,0}; + for(t=0;tnumchars;t++) { - f->alignzones[t] = detect_for_char(f, t); + SRECT b = f->layout->bounds[t]; + negate_y(&b); + swf_ExpandRect2(&bounds, &b); } - } -/* - "-^_~\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 -*/ + int width = bounds.xmax - bounds.xmin; + int height = bounds.ymax - bounds.ymin; + float*row = rfx_calloc(sizeof(float)*(width+1)); + float*column = rfx_calloc(sizeof(float)*(height+1)); + float*row2 = rfx_calloc(sizeof(float)*(width+1)); + float*column2 = rfx_calloc(sizeof(float)*(height+1)); + + for(t=0;tnumchars;t++) { + draw_char(f, t, row, column, bounds); + } + for(t=0;t<=width;t++) {row[t]/=f->numchars/2;} + for(t=0;t<=height;t++) {column[t]/=f->numchars/2;} + + for(t=0;tnumchars;t++) { + memcpy(row2, row, sizeof(float)*(width+1)); + memcpy(column2, column, sizeof(float)*(height+1)); + //draw_char(f, t, row2, column2, bounds); + + SRECT b = f->layout->bounds[t]; + negate_y(&b); + f->alignzones[t] = detect_for_char(f, t, row2, column2, bounds, b); + } + } } void swf_FontSetAlignZones(TAG*t, SWFFONT *f) -- 1.7.10.4