generate align zones during postprocessing
authorMatthias Kramm <kramm@quiss.org>
Sat, 28 Nov 2009 03:35:34 +0000 (19:35 -0800)
committerMatthias Kramm <kramm@quiss.org>
Sat, 28 Nov 2009 03:35:34 +0000 (19:35 -0800)
lib/devices/swf.c
lib/modules/swfalignzones.c
lib/modules/swffont.c
lib/modules/swfobject.c
lib/modules/swfshape.c
lib/modules/swftext.c
lib/rfxswf.h

index 8d557da..1db6b38 100644 (file)
@@ -739,12 +739,6 @@ static void chararray_writetotag(chararray_t*_chardata, TAG*tag)
                    lastx = chr->x;
                    lasty = chr->y;
                    lastsize = chr->size;
-               } else {
-                   assert(lastchar>=0);
-                   if(pass==1 && lastchar!=chr->charid) {
-                       swf_FontUsePair(chr->font, lastchar, chr->charid);
-                       swf_FontUsePair(chr->font, chr->charid, lastchar);
-                   }
                }
 
                if(islast)
@@ -1477,6 +1471,7 @@ 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) {
@@ -1496,19 +1491,19 @@ void swfoutput_finalize(gfxdevice_t*dev)
                } else {
                    mtag = swf_InsertTag(mtag, ST_DEFINEFONT3);
                    swf_FontSetDefine2(mtag, iterator->swffont);
-                   if(iterator->swffont->alignzones) {
-                       mtag = swf_InsertTag(mtag, ST_DEFINEFONTALIGNZONES);
-                       swf_FontSetAlignZones(mtag, iterator->swffont);
-                   }
                }
            }
        }
 
         iterator = iterator->next;
     }
-       
+
     i->tag = swf_InsertTag(i->tag,ST_END);
     TAG* tag = i->tag->prev;
+   
+    if(i->config_storeallcharacters) {
+       swf_FontPostprocess(i->swf); // generate alignment information
+    }
 
     /* remove the removeobject2 tags between the last ST_SHOWFRAME
        and the ST_END- they confuse the flash player  */
index 21780d3..027585f 100644 (file)
@@ -235,15 +235,15 @@ void swf_FontCreateAlignZones(SWFFONT * f)
            memset(column, 0, sizeof(float)*(height+1));
            int s;
            int drawn = 0;
-           printf("[font %d] pairing %c with ", f->id, f->glyph2ascii[t]);
            for(s=0;s<f->use->num_neighbors;s++) {
-               if(f->use->neighbors[s].char2 == t) {
-                   printf("%c (%d) ", f->glyph2ascii[f->use->neighbors[s].char1], f->use->neighbors[s].num);
-                   draw_char(f, f->use->neighbors[s].char1, row, column, bounds);
+               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++;
                }
            }
-           printf("\n");
 
            for(s=0;s<=height;s++) {
                column[t] /= drawn*2;
@@ -262,6 +262,26 @@ void swf_FontCreateAlignZones(SWFFONT * f)
     }
 }
 
+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)
 {
     swf_SetU16(t, f->id);
@@ -288,4 +308,3 @@ void swf_FontSetAlignZones(TAG*t, SWFFONT *f)
     }
 }
 
-
index cd553b8..aee2fae 100644 (file)
@@ -347,12 +347,16 @@ SWFFONT* swf_LoadTrueTypeFont(const char*filename)
     //font->layout->descent = abs(face->descender)*FT_SCALE*loadfont_scale*20/FT_SUBPIXELS/2; //face->bbox.xMax;
     //font->layout->leading = font->layout->ascent + font->layout->descent;
 
-    font->layout->ascent = -fontbbox.ymin;
-    if(font->layout->ascent < 0)
+    if(-fontbbox.ymin < 0)
         font->layout->ascent = 0;
-    font->layout->descent = fontbbox.ymax;
-    if(font->layout->descent < 0)
+    else
+       font->layout->ascent = -fontbbox.ymin;
+
+    if(-fontbbox.ymax < 0)
         font->layout->descent = 0;
+    else
+       font->layout->descent = -fontbbox.ymax;
+
     font->layout->leading = fontbbox.ymax - fontbbox.ymin;
 
     /* notice: if skip_unused is true, font->glyph2ascii, font->glyphnames and font->layout->bounds will 
index 36b66d4..349824d 100644 (file)
@@ -57,7 +57,7 @@ int isUnitCXForm(CXFORM* cx)
     return 0;
 }
 
-static int objectplace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const U8 * name, U16 clipaction, U8 blendmode, FILTERLIST*filters)
+static int objectplace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const char * name, U16 clipaction, U8 blendmode, FILTERLIST*filters)
 { U8 flags,flags2;
   if (!t) return -1;
 
@@ -87,15 +87,15 @@ static int objectplace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const U8
     swf_SetU8(t,blendmode);
   return 0; 
 }
-int swf_ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const U8 * name)
+int swf_ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const char * name)
 {
     return objectplace(t,id,depth,m,cx,name,0,0,0);
 }
-int swf_ObjectPlaceClip(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const U8 * name, U16 clipaction)
+int swf_ObjectPlaceClip(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const char * name, U16 clipaction)
 { 
     return objectplace(t,id,depth,m,cx,name,clipaction,0,0);
 }
-int swf_ObjectPlaceBlend(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const U8 * name, U8 blend)
+int swf_ObjectPlaceBlend(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const char * name, U8 blend)
 { 
     if(t->id != ST_PLACEOBJECT3)
        fprintf(stderr, "wrong tag- ignoring blend mode\n");
@@ -198,7 +198,7 @@ void swf_GetPlaceObject(TAG * tag,SWFPLACEOBJECT* obj)
             l = strlen((const char *)&tag->data[tag->pos]);
             t = 0;
             data = (U8*)rfx_alloc(l+1);
-            obj->name = data;
+            obj->name = (char*)data;
             while((data[t++] = swf_GetU8(tag))); 
         }
        if(flags2&PF2_BLENDMODE) {
index afa069c..bc972d4 100644 (file)
@@ -616,6 +616,35 @@ static int parseFillStyleArray(TAG*tag, SHAPE2*shape)
     return 1;
 }
 
+char swf_ShapeIsEmpty(SHAPE*s)
+{
+    if(!s || !s->data) return 1;
+    TAG _tag;
+    TAG* tag = &_tag;
+    memset(tag, 0, sizeof(TAG));
+    tag->data = s->data;
+    tag->len = tag->memsize = (s->bitlen+7)/8;
+    tag->pos = 0;
+    
+    while(1) {
+       if(!swf_GetBits(tag, 1)) {
+           U16 flags = swf_GetBits(tag, 5);
+           if(!flags) break;
+           if(flags&1) { //move
+               int n = swf_GetBits(tag, 5); 
+               swf_GetSBits(tag, n); //x
+               swf_GetSBits(tag, n); //y
+           }
+           if(flags&2) swf_GetBits(tag, s->bits.fill);
+           if(flags&4) swf_GetBits(tag, s->bits.fill);
+           if(flags&8) swf_GetBits(tag, s->bits.line);
+           if(flags&16) {return 0;}
+       } else {
+           return 0;
+       }
+    }
+    return 1;
+}
 
 /* todo: merge this with swf_GetSimpleShape */
 static SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits, int version, SHAPE2*shape2)
index c473211..888f74a 100644 (file)
@@ -255,7 +255,7 @@ int swf_FontExtract_DefineFont2(int id, SWFFONT * font, TAG * tag)
     U32 *offset;
     U8 flags1, langcode, namelen;
     swf_SetTagPos(tag, 0);
-    font->version = 2;
+    font->version = tag->id==ST_DEFINEFONT3?3:2;
     fid = swf_GetU16(tag);
     if (id && id != fid)
        return id;
@@ -278,7 +278,6 @@ int swf_FontExtract_DefineFont2(int id, SWFFONT * font, TAG * tag)
     font->name = (U8 *) rfx_alloc(namelen + 1);
     font->name[namelen] = 0;
     swf_GetBlock(tag, font->name, namelen);
-    font->version = 2;
     glyphcount = swf_GetU16(tag);
     font->numchars = glyphcount;
 
@@ -516,7 +515,7 @@ swf_FontExtract_DefineTextCallback(int id, SWFFONT * f, TAG * t, int jobs,
 }
 
 int swf_ParseDefineText(TAG * tag,
-                   void (*callback) (void *self, int *chars, int *ypos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA * color), void *self)
+                   void (*callback) (void *self, int *chars, int *xpos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA * color), void *self)
 {
     return swf_FontExtract_DefineTextCallback(-1, 0, tag, FEDTJ_CALLBACK, callback, self);
 }
@@ -526,6 +525,52 @@ int swf_FontExtract_DefineText(int id, SWFFONT * f, TAG * t, int jobs)
     return swf_FontExtract_DefineTextCallback(id, f, t, jobs, 0, 0);
 }
 
+typedef struct _usagetmp {
+    SWFFONT*font;
+    int lastx,lasty;
+    int last;
+} usagetmp_t;
+static void updateusage(void *self, int *chars, int *xpos, int nr, 
+                       int fontid, int fontsize, int xstart, int ystart, RGBA * color)
+{
+    usagetmp_t*u = (usagetmp_t*)self;
+    if(!u->font->use) {
+       swf_FontInitUsage(u->font);
+    }
+    if(fontid!=u->font->id)
+       return;
+
+    int t;
+    for(t=0;t<nr;t++) {
+       int x=xpos[t];
+       int y=ystart;
+       int c = chars[t];
+       if(c<0 || c>u->font->numchars)
+           continue;
+       swf_FontUseGlyph(u->font, c, fontsize);
+       if(u->lasty == y && x>=u->lastx-200 && abs(u->lastx-x)<200 &&
+          u->last!=c && !swf_ShapeIsEmpty(u->font->glyph[u->last].shape) && 
+          !swf_ShapeIsEmpty(u->font->glyph[c].shape)) 
+       {
+           swf_FontUsePair(u->font, u->last, c);
+       }
+       u->lasty = y;
+       /* FIXME: do we still need to divide advance by 20 for definefont3? */
+       u->lastx = x + (u->font->glyph[c].advance*fontsize/20480);
+       u->last = c;
+    }
+}
+
+void swf_FontUpdateUsage(SWFFONT*f, TAG* tag)
+{
+    usagetmp_t u;
+    u.font = f;
+    u.lastx = -0x80000000;
+    u.lasty = -0x80000000;
+    u.last = 0;
+    swf_ParseDefineText(tag, updateusage, &u);
+}
+
 int swf_FontExtract(SWF * swf, int id, SWFFONT * *font)
 {
     TAG *t;
@@ -561,7 +606,11 @@ int swf_FontExtract(SWF * swf, int id, SWFFONT * *font)
 
        case ST_DEFINETEXT:
        case ST_DEFINETEXT2:
-           nid = swf_FontExtract_DefineText(id, f, t, f->layout ? 0 : FEDTJ_MODIFY);
+           if(!f->layout) {
+               nid = swf_FontExtract_DefineText(id, f, t, FEDTJ_MODIFY);
+           }
+           if(f->version>=3 && f->layout) 
+               swf_FontUpdateUsage(f, t);
            break;
 
        case ST_GLYPHNAMES:
index 7f8eb1c..5bfeb5d 100644 (file)
@@ -449,6 +449,7 @@ typedef struct _SHAPELINE
 
 int   swf_ShapeNew(SHAPE ** s);
 void  swf_ShapeFree(SHAPE * s);
+char  swf_ShapeIsEmpty(SHAPE*s);
 
 int   swf_GetSimpleShape(TAG * t,SHAPE ** s); // without Linestyle/Fillstyle Record
 int   swf_SetSimpleShape(TAG * t,SHAPE * s);   // without Linestyle/Fillstyle Record
@@ -658,6 +659,7 @@ void swf_FontSetAlignZones(TAG*t, SWFFONT *f);
 void swf_FontCreateLayout(SWFFONT*f);
 void swf_FontCreateAlignZones(SWFFONT * f);
 void swf_FontAddLayout(SWFFONT * f, int ascent, int descent, int leading);
+void swf_FontPostprocess(SWF*swf);
 
 int swf_ParseDefineText(TAG * t, void(*callback)(void*self, int*chars, int*xpos, int nr, int fontid, int fontsize, int xstart, int ystart, RGBA* color), void*self);
 
@@ -935,9 +937,9 @@ void action_fixjump(ActionMarker m1, ActionMarker m2);
 
 extern char*blendModeNames[];
 
-int swf_ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const U8 * name);
-int swf_ObjectPlaceClip(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const U8 * name, U16 clipaction);
-int swf_ObjectPlaceBlend(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const U8 * name, U8 blendmode);
+int swf_ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const char* name);
+int swf_ObjectPlaceClip(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const char* name, U16 clipaction);
+int swf_ObjectPlaceBlend(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,const char* name, U8 blendmode);
 int swf_ObjectMove(TAG * t,U16 depth,MATRIX * m,CXFORM * cx);
 
 #define PF_MOVE         0x01
@@ -977,7 +979,7 @@ typedef struct _SWFPLACEOBJECT {
     MATRIX matrix;
     CXFORM cxform;
     U16 ratio;
-    U8*name;
+    char*name;
     U16 clipdepth;
     ActionTAG* actions;
     U8 blendmode;