3 static inline double sqr(double x) {return x*x;}
5 static void draw_line(float*row, float x1, float x2, float y1, float y2, int min, int max)
7 if(x2<x1) {int x=x1;x1=x2;x2=x;}
9 fprintf(stderr, "error: glyph x stroke out of bounds\n");
15 double d = sqrt(sqr(y2-y1)+sqr(x2-x1));
16 if(floor(x1)==floor(x2)) {
17 row[(int)floor(x1)] += d;
23 row[xx1] += i*(xx1-x1);
24 row[xx2] += i*(x2-xx2);
25 for(x=xx1;x<xx2;x++) {
31 static void draw_line_xy(float*row,float*column, float x1, float y1, float x2, float y2,SRECT* area)
33 draw_line(row, x1, x2, y1, y2, area->xmin, area->xmax);
34 draw_line(column, y1, y2, x1, x2, area->ymin, area->ymax);
39 static void find_best(float*_row, int width, int*_x1, int*_x2, int min_size, int from, int to, char debug)
44 float max1=-1e20,max2=-1e20;
46 float*row = malloc(sizeof(float)*(width+1));
48 float* filter = malloc(sizeof(float)*(filter_size*2+1));
49 double var = filter_size/3;
50 for(t=-filter_size;t<=filter_size;t++) {
53 filter[filter_size+t] = exp(-r);
55 //filter[0]=1;filter_size=0;
57 for(t=0;t<=width;t++) {
60 for(s=-filter_size;s<=filter_size;s++) {
62 if(t+s>width) continue;
63 sum += _row[t+s]*filter[s+filter_size];
68 for(t=from;t<=to;t++) {
75 double scale = min_size/1024.0;
76 for(t=from;t<=to;t++) {
81 double r1 = (t<x1?t:x1)*scale;
82 double r2 = (t<x1?x1:t)*scale;
86 double ext1 = r1-from*scale;
87 double ext2 = to*scale-r2;
88 double add1 = ext1*s - ext1;
89 double add2 = ext2*s - ext2;
91 /* don't allow the char to grow more than one pixel */
92 if(add1>=1 || add2>=1) {
97 for(t=from;t<=to;t++) {
104 if(x1>=0 && x2>=0 && x1>x2) {int x=x1;x1=x2;x2=x;}
110 static void negate_y(SRECT* b)
113 int by1=b->ymin,by2=b->ymax;
118 static void draw_char(SWFFONT * f, int nr, float*row, float*column, SRECT b)
120 SWFGLYPH*g = &f->glyph[nr];
122 SHAPE2*s = swf_ShapeToShape2(g->shape);
123 SHAPELINE*l = s->lines;
126 if(l->type == lineTo) {
127 draw_line_xy(row,column,x,-y,l->x,-l->y,&b);
128 } else if(l->type == splineTo) {
129 double x1=x,x2=l->sx,x3=l->x;
130 double y1=y,y2=l->sy,y3=l->y;
131 double c = fabs(x3-2*x2+x1) + fabs(y3-2*y2+y1);
132 int parts = ((int)(sqrt(c)/6))*2+1;
135 for(t=1;t<=parts;t++) {
136 float nx = ((t*t*x3 + 2*t*(parts-t)*x2 + (parts-t)*(parts-t)*x1)/(double)(parts*parts));
137 float ny = ((t*t*y3 + 2*t*(parts-t)*y2 + (parts-t)*(parts-t)*y1)/(double)(parts*parts));
138 draw_line_xy(row,column,xx,-yy,nx,-ny,&b);
149 static ALIGNZONE detect_for_char(SWFFONT * f, int nr, float*row, float*column, SRECT font_bbox, SRECT char_bbox)
151 ALIGNZONE a = {0xffff,0xffff,0xffff,0xffff};
152 int width = font_bbox.xmax - font_bbox.xmin;
153 int height = font_bbox.ymax - font_bbox.ymin;
154 if(!width || !height)
157 /* find two best x values */
158 int x1=-1,y1=-1,x2=-1,y2=-1;
159 find_best(row, width, &x1, &x2, f->use->smallest_size,
160 char_bbox.xmin - font_bbox.xmin,
161 char_bbox.xmax - font_bbox.xmin,
163 find_best(column, height, &y1, &y2, f->use->smallest_size,
164 char_bbox.ymin - font_bbox.ymin,
165 char_bbox.ymax - font_bbox.ymin,
168 //if(x1>=0) a.x = floatToF16((x1+b.xmin) / 20480.0);
169 //if(x2>=0) a.dx = floatToF16((x2-x1) / 20480.0);
170 if(y1>=0) a.y = floatToF16((y1+font_bbox.ymin) / 20480.0);
171 if(y2>=0) a.dy = floatToF16((y2-y1) / 20480.0);
175 void swf_FontCreateAlignZones(SWFFONT * f)
181 fprintf(stderr, "Error: font needs a layout for alignzones to be detected.");
185 f->alignzones = (ALIGNZONE*)rfx_calloc(sizeof(ALIGNZONE)*f->numchars);
186 f->alignzone_flags = FONTALIGN_MEDIUM;
190 for(t=0;t<f->numchars;t++) {
191 // just align the baseline
192 f->alignzones[t].x = 0xffff;
193 f->alignzones[t].y = 0;
194 f->alignzones[t].dx = 0xffff;
195 f->alignzones[t].dy = 0xffff;//floatToF16(460.80 / 1024.0);
199 SRECT bounds = {0,0,0,0};
201 for(t=0;t<f->numchars;t++) {
202 SRECT b = f->layout->bounds[t];
204 swf_ExpandRect2(&bounds, &b);
207 int width = bounds.xmax - bounds.xmin;
208 int height = bounds.ymax - bounds.ymin;
209 float*row = rfx_calloc(sizeof(float)*(width+1));
210 float*column = rfx_calloc(sizeof(float)*(height+1));
211 float*row2 = rfx_calloc(sizeof(float)*(width+1));
212 float*column2 = rfx_calloc(sizeof(float)*(height+1));
214 for(t=0;t<f->numchars;t++) {
215 draw_char(f, t, row, column, bounds);
217 for(t=0;t<=width;t++) {row[t]/=f->numchars/2;}
218 for(t=0;t<=height;t++) {column[t]/=f->numchars/2;}
220 for(t=0;t<f->numchars;t++) {
221 memcpy(row2, row, sizeof(float)*(width+1));
222 memcpy(column2, column, sizeof(float)*(height+1));
223 //draw_char(f, t, row2, column2, bounds);
225 SRECT b = f->layout->bounds[t];
227 f->alignzones[t] = detect_for_char(f, t, row2, column2, bounds, b);
232 void swf_FontSetAlignZones(TAG*t, SWFFONT *f)
234 swf_SetU16(t, f->id);
235 swf_SetU8(t, f->alignzone_flags);
237 for(i=0;i<f->numchars;i++) {
238 ALIGNZONE*a = &f->alignzones[i];
240 if((a->x & a->dx)!=0xffff)
242 if((a->y & a->dy)!=0xffff)
245 if(a->dx != 0xffff || a->dy != 0xffff)
248 if(flags&1) swf_SetU16(t, a->x); else swf_SetU16(t, 0);
249 if(flags&2) swf_SetU16(t, a->y); else swf_SetU16(t, 0);
251 if((flags&1) && a->dx!=0xffff) swf_SetU16(t, a->dx); else swf_SetU16(t, 0);
252 if((flags&2) && a->dy!=0xffff) swf_SetU16(t, a->dy); else swf_SetU16(t, 0);