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)
+static void find_best(float*_row, int width, int*_x1, int*_x2, int min_size, int from, int to, int num, char debug)
{
int x1=-1, x2=-1;
- float max1=-1,max2=-1;
+ float max1=-1e20,max2=-1e20;
int t;
float*row = malloc(sizeof(float)*(width+1));
- int filter_size = 100;
+ int filter_size = 10;
float* filter = malloc(sizeof(float)*(filter_size*2+1));
double var = filter_size/3;
for(t=-filter_size;t<=filter_size;t++) {
float r = v*v/2;
filter[filter_size+t] = exp(-r);
}
- filter[0]=1;filter_size=0;
+ //filter[0]=1;filter_size=0;
for(t=0;t<=width;t++) {
int s;
}
row[t] = sum;
}
+ free(filter);
- for(t=0;t<=width;t++) {
+ for(t=from;t<=to;t++) {
if(row[t]>max1) {
max1 = row[t];
x1 = t;
}
}
- // invalidate everything around the maximum
- for(t=-min_dist+1;t<min_dist;t++) {
- if(t+x1<0 || t+x1>width) continue;
- row[t+x1]=-1;
- }
- for(t=0;t<=width;t++) {
- if(row[t]>max2) {
- max2 = row[t];
- x2 = t;
+
+
+ if(num<=1) {
+ *_x1=x1;
+ } else {
+ /* this code is slightly wrong, in that it assumes that the glyph distortion problem
+ gets worse when the font sizes get smaller. it doesn't. in fact, the smaller
+ the font size, the more of the scaling bugs disappear (http://www.quiss.org/files/scaletest.swf)
+ A better way would probably to use the font size you need for the two alignzones
+ to come to lie in different pixels, which what I think is what makes the problems
+ appear/disappear.
+ */
+
+ double scale = min_size/1024.0;
+ for(t=from;t<=to;t++) {
+ if(t==x1) {
+ row[t]=-1e20;
+ continue;
+ }
+ double r1 = (t<x1?t:x1)*scale;
+ double r2 = (t<x1?x1:t)*scale;
+ double d1 = r2-r1;
+ double d2 = d1+2;
+ double s = d2/d1;
+ double ext1 = r1-from*scale;
+ double ext2 = to*scale-r2;
+ double add1 = ext1*s - ext1;
+ double add2 = ext2*s - ext2;
+
+ /* don't allow the char to grow more than one pixel */
+ if(add1>=1 || add2>=1) {
+ row[t]=-1e20;
+ }
+ }
+
+ for(t=from;t<=to;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;
+ 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)
+static void negate_y(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 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);
+static void draw_char(SWFFONT * f, int nr, float*row, float*column, SRECT b)
+{
+ SWFGLYPH*g = &f->glyph[nr];
SHAPE2*s = swf_ShapeToShape2(g->shape);
SHAPELINE*l = s->lines;
y = l->y;
l = l->next;
}
+ swf_Shape2Free(s);
+ free(s);
+}
- int t;
+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;
/* 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);
+
+ int nr_x = 0;
+ find_best(row, width, &x1, &x2, f->use->smallest_size,
+ char_bbox.xmin - font_bbox.xmin,
+ char_bbox.xmax - font_bbox.xmin, nr_x,
+ 0);
+ if(nr_x>0 && x1>=0) a.x = floatToF16((x1+font_bbox.xmin) / 20480.0);
+ if(nr_x>1 && x2>=0) a.dx = floatToF16((x2-x1) / 20480.0);
+
+ find_best(column, height, &y1, &y2, f->use->smallest_size,
+ char_bbox.ymin - font_bbox.ymin,
+ char_bbox.ymax - font_bbox.ymin, 2,
+ 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;
}
return;
}
-
f->alignzones = (ALIGNZONE*)rfx_calloc(sizeof(ALIGNZONE)*f->numchars);
- f->alignzone_flags = FONTALIGN_THIN;
+ f->alignzone_flags = FONTALIGN_MEDIUM;
- if(!f->layout) {
+ if(!f->layout || !f->use) {
int t;
for(t=0;t<f->numchars;t++) {
// just align the baseline
f->alignzones[t].dy = 0xffff;//floatToF16(460.80 / 1024.0);
}
} else {
+ SRECT bounds = {0,0,0,0};
int t;
for(t=0;t<f->numchars;t++) {
- f->alignzones[t] = detect_for_char(f, t);
+ SRECT b = f->layout->bounds[t];
+ negate_y(&b);
+ swf_ExpandRect2(&bounds, &b);
+ }
+
+ int width = bounds.xmax - bounds.xmin;
+ int height = bounds.ymax - bounds.ymin;
+ float*row = rfx_calloc(sizeof(float)*(width+1));
+ float*column_global = rfx_calloc(sizeof(float)*(height+1));
+ float*column = rfx_calloc(sizeof(float)*(height+1));
+
+ for(t=0;t<f->numchars;t++) {
+ draw_char(f, t, row, column_global, bounds);
}
+ for(t=0;t<=height;t++) {column_global[t]/=f->numchars/2;}
+
+ for(t=0;t<f->numchars;t++) {
+ //memcpy(column, column_global, sizeof(float)*(height+1));
+
+ memset(column, 0, sizeof(float)*(height+1));
+ int s;
+ int drawn = 0;
+ for(s=0;s<f->use->num_neighbors;s++) {
+ int char1 = f->use->neighbors[s].char1;
+ int char2 = f->use->neighbors[s].char2;
+ if(char1 == t || char2 == t) {
+ int other = t==char1?char2:char1;
+ draw_char(f, other, row, column, bounds);
+ drawn++;
+ }
+ }
+
+ for(s=0;s<=height;s++) {
+ column[t] /= drawn*2;
+ }
+
+ memset(row, 0, sizeof(float)*(width+1));
+ draw_char(f, t, row, column, bounds);
+
+ SRECT b = f->layout->bounds[t];
+ negate_y(&b);
+ f->alignzones[t] = detect_for_char(f, t, row, column, bounds, b);
+ }
+ free(row);
+ free(column_global);
+ free(column);
}
+}
-/*
- "-^_~\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_FontPostprocess(SWF*swf)
+{
+ TAG*tag = swf->firstTag;
+ while(tag) {
+ TAG*next = tag->next;
+ if(tag->id == ST_DEFINEFONT3) {
+ U16 id = swf_GetDefineID(tag);
+ SWFFONT*font = 0;
+ swf_FontExtract(swf, id, &font);
+ if(!font->alignzones) {
+ swf_FontCreateAlignZones(font);
+ tag = swf_InsertTag(tag, ST_DEFINEFONTALIGNZONES);
+ swf_FontSetAlignZones(tag, font);
+ }
+ swf_FontFree(font);
+ }
+ tag = next;
+ }
}
void swf_FontSetAlignZones(TAG*t, SWFFONT *f)
}
}
-