X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswftext.c;h=41207bfc06dcbae22cddd1da20f2957234018fdf;hb=922f9285d96ff230c5c6a7017ac7246a0cdf6163;hp=b5d74f00d42c2617a30db52509fb89a6ac34bc4f;hpb=9b57fcd7feaf69fd54447174b19f5f377706bb15;p=swftools.git diff --git a/lib/modules/swftext.c b/lib/modules/swftext.c index b5d74f0..41207bf 100644 --- a/lib/modules/swftext.c +++ b/lib/modules/swftext.c @@ -6,7 +6,7 @@ Part of the swftools package. Copyright (c) 2001 Rainer Böhme - Copyright (c) 2003,2004 Matthias Kramm + Copyright (c) 2003,2004,2005,2006,2007,2008,2009 Matthias Kramm This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -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;tu->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: @@ -625,6 +674,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; } } @@ -777,6 +832,12 @@ int swf_FontReduce(SWFFONT * f) return 0; } +static SWFFONT* font_to_sort; +int cmp_chars(const void*a, const void*b) +{ + int x = *(const int*)a; + int y = *(const int*)b; +} void swf_FontSort(SWFFONT * font) { int i, j; @@ -790,6 +851,8 @@ void swf_FontSort(SWFFONT * font) for (i = 0; i < font->numchars; i++) { newplace[i] = i; } + //qsort(newplace, sizeof(newplace[0]), font->numchars, cmp_chars); + for (i = 0; i < font->numchars; i++) for (j = 0; j < i; j++) { if (font->glyph2ascii[i] < font->glyph2ascii[j]) { @@ -832,8 +895,8 @@ void swf_FontSort(SWFFONT * font) font->ascii2glyph[i] = newpos[font->ascii2glyph[i]]; } - rfx_free(newpos); rfx_free(newplace); + font->glyph2glyph = newpos; } void swf_FontPrepareForEditText(SWFFONT * font) @@ -851,11 +914,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; } @@ -873,22 +934,22 @@ 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, const U8 * s, U16 size) { if( (!s)) return -1; int ascii; while (*s) { - ascii = readUTF8char(&s); + ascii = readUTF8char((U8**)&s); if(ascii < f->maxascii && f->ascii2glyph[ascii]>=0) - swf_FontUseGlyph(f, f->ascii2glyph[ascii]); + swf_FontUseGlyph(f, f->ascii2glyph[ascii], size); } return 0; } @@ -905,7 +966,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;tnum_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); @@ -914,6 +1049,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; } @@ -1059,12 +1196,15 @@ int swf_FontSetDefine2(TAG * tag, SWFFONT * f) if (f->layout) { swf_SetU16(tag, f->layout->ascent); swf_SetU16(tag, f->layout->descent); - swf_SetU16(tag, f->layout->leading); + swf_SetU16(tag, 0); // flash ignores leading + for (t = 0; t < f->numchars; t++) swf_SetU16(tag, f->glyph[t].advance); for (t = 0; t < f->numchars; t++) { swf_ResetWriteBits(tag); - swf_SetRect(tag, &f->layout->bounds[t]); + /* not used by flash, so leave this empty */ + SRECT b = {0,0,0,0}; + swf_SetRect(tag, &b); } swf_SetU16(tag, f->layout->kerningcount); for (t = 0; t < f->layout->kerningcount; t++) { @@ -1170,6 +1310,10 @@ void swf_FontFree(SWFFONT * f) rfx_free(f->glyph2ascii); f->glyph2ascii = NULL; } + if (f->glyph2glyph) { + rfx_free(f->glyph2glyph); + f->glyph2glyph = NULL; + } font_freename(f); font_freelayout(f); font_freeglyphnames(f);