added occurence counting to glyph pair tracker
[swftools.git] / lib / modules / swftext.c
index 912e8fa..c473211 100644 (file)
@@ -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;
@@ -647,6 +625,12 @@ static void font_freeusage(SWFFONT*f)
        if(f->use->chars) {
            rfx_free(f->use->chars);f->use->chars = 0;
        }
+       if(f->use->neighbors) {
+           rfx_free(f->use->neighbors);f->use->neighbors = 0;
+       }
+       if(f->use->neighbors_hash) {
+           rfx_free(f->use->neighbors_hash);f->use->neighbors_hash = 0;
+       }
        rfx_free(f->use); f->use = 0;
     }
 }
@@ -873,11 +857,9 @@ int swf_FontInitUsage(SWFFONT * f)
        fprintf(stderr, "Usage initialized twice");
        return -1;
     }
-    f->use = (FONTUSAGE*)rfx_alloc(sizeof(FONTUSAGE));
-    f->use->is_reduced = 0;
-    f->use->used_glyphs = 0;
+    f->use = (FONTUSAGE*)rfx_calloc(sizeof(FONTUSAGE));
+    f->use->smallest_size = 0xffff;
     f->use->chars = (int*)rfx_calloc(sizeof(f->use->chars[0]) * f->numchars);
-    f->use->glyphs_specified = 0;
     return 0;
 }
 
@@ -895,13 +877,13 @@ int swf_FontUse(SWFFONT * f, U8 * s)
        return -1;
     while (*s) {
        if(*s < f->maxascii && f->ascii2glyph[*s]>=0)
-           swf_FontUseGlyph(f, f->ascii2glyph[*s]);
+           swf_FontUseGlyph(f, f->ascii2glyph[*s], /*FIXME*/0xffff);
        s++;
     }
     return 0;
 }
 
-int swf_FontUseUTF8(SWFFONT * f, U8 * s)
+int swf_FontUseUTF8(SWFFONT * f, U8 * s, U16 size)
 {
     if( (!s))
        return -1;
@@ -910,7 +892,7 @@ int swf_FontUseUTF8(SWFFONT * f, U8 * s)
     {
        ascii = readUTF8char(&s);
        if(ascii < f->maxascii && f->ascii2glyph[ascii]>=0)
-           swf_FontUseGlyph(f, f->ascii2glyph[ascii]);
+           swf_FontUseGlyph(f, f->ascii2glyph[ascii], size);
     }
     return 0;
 }
@@ -927,7 +909,81 @@ int swf_FontUseAll(SWFFONT* f)
     return 0;
 }
 
-int swf_FontUseGlyph(SWFFONT * f, int glyph)
+static unsigned hash2(int char1, int char2)
+{
+    unsigned hash = char1^(char2<<8);
+    hash += (hash << 3);
+    hash ^= (hash >> 11);
+    hash += (hash << 15);
+    return hash;
+}
+static void hashadd(FONTUSAGE*u, int char1, int char2, int nr)
+{
+    unsigned hash = hash2(char1, char2);
+    while(1) {
+       hash = hash%u->neighbors_hash_size;
+       if(!u->neighbors_hash[hash]) {
+          u->neighbors_hash[hash] = nr+1;
+          return;
+       }
+       hash++;
+    }
+}
+int swf_FontUseGetPair(SWFFONT * f, int char1, int char2)
+{
+    FONTUSAGE*u = f->use;
+    if(!u || !u->neighbors_hash_size) 
+       return 0;
+    unsigned hash = hash2(char1, char2);
+    while(1) {
+       hash = hash%u->neighbors_hash_size;
+       int pos = u->neighbors_hash[hash];
+       if(!pos)
+           return 0;
+       if(pos && 
+          u->neighbors[pos-1].char1 == char1 &&
+          u->neighbors[pos-1].char2 == char2) {
+           return pos;
+       }
+       hash++;
+    }
+
+}
+void swf_FontUsePair(SWFFONT * f, int char1, int char2)
+{
+    if (!f->use)
+       swf_FontInitUsage(f);
+    FONTUSAGE*u = f->use;
+
+    if(u->num_neighbors*3 >= u->neighbors_hash_size*2) {
+       if(u->neighbors_hash) {
+           free(u->neighbors_hash);
+       }
+       u->neighbors_hash_size = u->neighbors_hash_size?u->neighbors_hash_size*2:1024;
+       u->neighbors_hash = rfx_calloc(u->neighbors_hash_size*sizeof(int));
+       int t;
+       for(t=0;t<u->num_neighbors;t++) {
+           hashadd(u, u->neighbors[t].char1, u->neighbors[t].char2, t);
+       }
+    }
+
+    int nr = swf_FontUseGetPair(f, char1, char2);
+    if(!nr) {
+       if(u->num_neighbors == u->neighbors_size) {
+           u->neighbors_size += 4096;
+           u->neighbors = rfx_realloc(u->neighbors, sizeof(SWFGLYPHPAIR)*u->neighbors_size);
+       }
+       u->neighbors[u->num_neighbors].char1 = char1;
+       u->neighbors[u->num_neighbors].char2 = char2;
+       u->neighbors[u->num_neighbors].num = 1;
+       hashadd(u, char1, char2, u->num_neighbors);
+       u->num_neighbors++;
+    } else {
+       u->neighbors[nr-1].num++;
+    }
+}
+
+int swf_FontUseGlyph(SWFFONT * f, int glyph, U16 size)
 {
     if (!f->use)
        swf_FontInitUsage(f);
@@ -936,6 +992,8 @@ int swf_FontUseGlyph(SWFFONT * f, int glyph)
     if(!f->use->chars[glyph])
        f->use->used_glyphs++;
     f->use->chars[glyph] = 1;
+    if(size && size < f->use->smallest_size)
+       f->use->smallest_size = size;
     return 0;
 }
 
@@ -1103,27 +1161,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;i<f->numchars;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 +1645,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;t<f->numchars;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;t<f->numchars;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 +2079,3 @@ char*data =
     swf_SaveSWF(&swf, filename);
     swf_FreeTags(&swf);
 }
-