int SWFText_getScaledStringWidth(SWFText text, const char *string) { SWFFont font; int height; unsigned short* widestr; int len = strlen(string); int n, ret; if(text->currentRecord == NULL) return -1; height = text->currentRecord->height; widestr = (unsigned short *)malloc(2 * len); /* If malloc failed, return -1 to signify this */ if (NULL == text) return -1; for(n = 0 ; n < len ; n++) widestr[n] = (unsigned char)string[n]; if ( text->currentRecord->isResolved ) font = SWFFontCharacter_getFont(text->currentRecord->font.fontchar); else font = text->currentRecord->font.font; ret = SWFFont_getScaledWideStringWidth(font, widestr, len) * height / 1024; free(widestr); return ret; }
static inline int checkSWFFontCharacter(SWFFontCharacter fc) { int font_flags; int nGlyphs; SWFFont font = SWFFontCharacter_getFont(fc); font_flags = SWFFont_getFlags(font); nGlyphs = SWFFontCharacter_getNGlyphs(fc); if((font_flags & SWF_FONT_HASLAYOUT) == 0 && nGlyphs == 0) return -1; return 0; }
static void SWFTextRecord_computeAdvances(SWFTextRecord textRecord) { int i; int len = textRecord->strlen; unsigned short* widestring = textRecord->string; unsigned short glyph; SWFFontCharacter fontchar = textRecord->font.fontchar; SWFFont font = SWFFontCharacter_getFont(fontchar); if(!len) return; // do not try to calculate 1st char of null string /* compute advances (spacing) from spacing, advance and kern table */ if ( textRecord->advance == NULL ) { textRecord->advance = (int*)malloc(sizeof(int) * len); memset(textRecord->advance, 0, sizeof(int) * len); } glyph = SWFFontCharacter_getGlyphCode(fontchar, widestring[0]); for ( i=0; i<len; ++i ) { int adv; unsigned short nextglyph; adv = SWFFont_getCharacterAdvance(font, (unsigned short)glyph); adv += textRecord->spacing; /* get kerning from font's kern table */ if ( i < len-1 ) { nextglyph = SWFFontCharacter_getGlyphCode(fontchar, widestring[i+1]); adv += SWFFont_getCharacterKern(font, glyph, nextglyph); glyph = nextglyph; } if ( textRecord->advance != NULL ) adv += textRecord->advance[i]; textRecord->advance[i] = adv * textRecord->height / 1024; textRecord->nAdvanceBits = max(textRecord->nAdvanceBits, SWFOutput_numSBits(textRecord->advance[i])); } }
/* * Adds a font to a movie. * retursn a SWFFontCharacter object */ SWFFontCharacter SWFMovie_addFont(SWFMovie movie, SWFFont font) { SWFFontCharacter fontchar; int i; for( i = 0 ; i < movie->nFonts ; i++ ) { fontchar = movie->fonts[i]; if ( SWFFontCharacter_getFont(fontchar) == font ) return fontchar; } movie->fonts = (SWFFontCharacter*)realloc(movie->fonts, sizeof(SWFFontCharacter) * (movie->nFonts + 1)); fontchar = newSWFFontCharacter(font); movie->fonts[movie->nFonts++] = fontchar; SWFMovie_addBlock(movie, (SWFBlock)fontchar); return fontchar; }
int SWFText_getScaledWideStringWidth(SWFText text, const unsigned short *string) { SWFFont font; int height = text->currentRecord->height; int len; for(len = 0 ; *string ; len++) ; if ( text->currentRecord->isResolved ) font = SWFFontCharacter_getFont(text->currentRecord->font.fontchar); else font = text->currentRecord->font.font; if ( text->currentRecord->isBrowserFont ) return 0; else return SWFFont_getScaledWideStringWidth(font, string, len) * height / 1024; }
int SWFText_getScaledUTF8StringWidth(SWFText text, const char *string) { SWFFont font; int height = text->currentRecord->height; unsigned short* widestr; int len, ret; len = UTF8ExpandString(string, &widestr); if ( text->currentRecord->isResolved ) font = SWFFontCharacter_getFont(text->currentRecord->font.fontchar); else font = text->currentRecord->font.font; if ( text->currentRecord->isBrowserFont ) ret = 0; else ret = SWFFont_getScaledWideStringWidth(font, widestr, len) * height / 1024; free(widestr); return ret; }
void SWFText_resolveCodes(SWFText text) { SWFTextRecord textRecord, oldRecord; SWFOutput out = text->out; int nGlyphBits = 0; int len, i; int curX = 0, curY = 0, curH = 0; textRecord = text->initialRecord; while ( textRecord != NULL ) { SWFTextRecord_computeAdvances(textRecord); text->nAdvanceBits = max(text->nAdvanceBits, textRecord->nAdvanceBits); if ( textRecord->flags & SWF_TEXT_HAS_FONT ) { int fontGlyphs = SWFFontCharacter_getNGlyphs(textRecord->font.fontchar); nGlyphBits = max(nGlyphBits, SWFOutput_numBits(fontGlyphs-1)); } textRecord = textRecord->next; } textRecord = text->initialRecord; while ( textRecord != NULL ) { SWFFontCharacter fontchar = NULL; SWFFont font = NULL; oldRecord = textRecord; if ( textRecord->string == NULL || textRecord->strlen == 0 ) { textRecord = textRecord->next; destroySWFTextRecord(oldRecord); continue; } SWFOutput_byteAlign(out); /* Raff says the spec lies- there's always a change record, even if it's empty, and the string record length is the full 8 bits. */ SWFOutput_writeUInt8(out, textRecord->flags | SWF_TEXT_STATE_CHANGE); if ( textRecord->flags & SWF_TEXT_HAS_FONT ) SWFOutput_writeUInt16(out, CHARACTERID(textRecord->font.fontchar)); if ( textRecord->flags & SWF_TEXT_HAS_COLOR ) { SWFOutput_writeUInt8(out, textRecord->r); SWFOutput_writeUInt8(out, textRecord->g); SWFOutput_writeUInt8(out, textRecord->b); if ( BLOCK(text)->type == SWF_DEFINETEXT2 ) SWFOutput_writeUInt8(out, textRecord->a); } if ( textRecord->flags & SWF_TEXT_HAS_X ) { SWFOutput_writeUInt16(out, textRecord->x); curX = textRecord->x; } if ( textRecord->flags & SWF_TEXT_HAS_Y ) { SWFOutput_writeUInt16(out, textRecord->y); curY = textRecord->y; } if ( textRecord->flags & SWF_TEXT_HAS_FONT ) { SWFOutput_writeUInt16(out, textRecord->height); curH = textRecord->height; } /* record type 0: string data */ len = textRecord->strlen; if ( len >= 256 ) SWF_error("Found text record >= 256 characters!"); SWFOutput_writeUInt8(out, len); fontchar = textRecord->font.fontchar; font = SWFFontCharacter_getFont(fontchar); if ( font == NULL ) SWF_error("Couldn't find font"); for ( i=0; i<len; ++i ) { SWFRect glyphBounds; int minX, maxX, minY, maxY; unsigned short font_glyphcode = SWFFont_findGlyphCode(font, textRecord->string[i]); glyphBounds = SWFFont_getGlyphBounds(font,font_glyphcode); SWFRect_getBounds(glyphBounds, &minX, &maxX, &minY, &maxY); int fontchar_glyphcode = SWFFontCharacter_findGlyphCode(fontchar, textRecord->string[i]); if (fontchar_glyphcode < 0) { SWF_error("SWFText_resolveCodes: no suitable glyph available (in dumped font)"); } SWFOutput_writeBits(out, (unsigned short) fontchar_glyphcode, nGlyphBits); SWFOutput_writeBits(out, textRecord->advance[i], text->nAdvanceBits); if ( CHARACTER(text)->bounds ) { SWFRect_includePoint(CHARACTER(text)->bounds, curX + minX * curH / 1024, curY + minY * curH / 1024, 0); SWFRect_includePoint(CHARACTER(text)->bounds, curX + maxX * curH / 1024, curY + maxY * curH / 1024, 0); } else { CHARACTER(text)->bounds = newSWFRect(curX + minX * curH /1024, curX + maxX * curH /1024, curY + minY * curH /1024, curY + maxY * curH /1024); } if ( textRecord->advance != NULL ) curX += textRecord->advance[i]; } textRecord = textRecord->next; destroySWFTextRecord(oldRecord); } SWFOutput_writeUInt8(out, 0); /* end text records */ text->nGlyphBits = nGlyphBits; text->initialRecord = NULL; text->currentRecord = NULL; }
void SWFText_resolveCodes(SWFText text) { SWFTextRecord textRecord, oldRecord; SWFOutput out = text->out; int nGlyphBits = 0; int len, i; int curX = 0, curY = 0, curH = 0; textRecord = text->initialRecord; while ( textRecord != NULL ) { SWFTextRecord_computeAdvances(textRecord); text->nAdvanceBits = max(text->nAdvanceBits, textRecord->nAdvanceBits); if ( textRecord->flags & SWF_TEXT_HAS_FONT ) { if ( textRecord->isBrowserFont ) { /* XXX - assume browser fonts have 8bit glyph table? */ nGlyphBits = max(nGlyphBits, 8); } else { int fontGlyphs = SWFFontCharacter_getNGlyphs(textRecord->font.fontchar); nGlyphBits = max(nGlyphBits, SWFOutput_numBits(fontGlyphs-1)); } } textRecord = textRecord->next; } textRecord = text->initialRecord; while ( textRecord != NULL ) { oldRecord = textRecord; if ( textRecord->string == NULL || textRecord->strlen == 0 ) { textRecord = textRecord->next; destroySWFTextRecord(oldRecord); continue; } SWFOutput_byteAlign(out); /* Raff says the spec lies- there's always a change record, even if it's empty, and the string record length is the full 8 bits. */ SWFOutput_writeUInt8(out, textRecord->flags | SWF_TEXT_STATE_CHANGE); if ( textRecord->flags & SWF_TEXT_HAS_FONT ) { if ( textRecord->isBrowserFont ) SWFOutput_writeUInt16(out, CHARACTERID(textRecord->font.browserFont)); else SWFOutput_writeUInt16(out, CHARACTERID(textRecord->font.fontchar)); } if ( textRecord->flags & SWF_TEXT_HAS_COLOR ) { SWFOutput_writeUInt8(out, textRecord->r); SWFOutput_writeUInt8(out, textRecord->g); SWFOutput_writeUInt8(out, textRecord->b); if ( BLOCK(text)->type == SWF_DEFINETEXT2 ) SWFOutput_writeUInt8(out, textRecord->a); } if ( textRecord->flags & SWF_TEXT_HAS_X ) { SWFOutput_writeUInt16(out, textRecord->x); curX = textRecord->x; } if ( textRecord->flags & SWF_TEXT_HAS_Y ) { SWFOutput_writeUInt16(out, textRecord->y); curY = textRecord->y; } if ( textRecord->flags & SWF_TEXT_HAS_FONT ) { SWFOutput_writeUInt16(out, textRecord->height); curH = textRecord->height; } /* record type 0: string data */ len = textRecord->strlen; if ( len >= 256 ) SWF_error("Found text record >= 256 characters!"); SWFOutput_writeUInt8(out, len); /* XXX - er, browser fonts in text objects crash the player.. Maybe because there's no definefontinfo block? */ if ( textRecord->isBrowserFont ) { for ( i=0; i<len; ++i ) { SWFOutput_writeBits(out, textRecord->string[i], nGlyphBits); SWFOutput_writeBits(out, textRecord->advance[i], text->nAdvanceBits); /* XXX - fudging the text character bounds since we don't have font metrics */ if ( CHARACTER(text)->bounds ) { SWFRect_includePoint(CHARACTER(text)->bounds, curX, curY, 0); SWFRect_includePoint(CHARACTER(text)->bounds, curX + curH, curY + curH, 0); } else { CHARACTER(text)->bounds = newSWFRect(curX, curX + curH, curY, curY + curH); } curX += curH; } } else { SWFFontCharacter fontchar = textRecord->font.fontchar; SWFFont font = SWFFontCharacter_getFont(fontchar); if ( font == NULL ) SWF_error("Couldn't find font"); for ( i=0; i<len; ++i ) { SWFRect glyphBounds; int minX, maxX, minY, maxY; unsigned short code = SWFFontCharacter_getGlyphCode(fontchar, textRecord->string[i]); glyphBounds = SWFFont_getGlyphBounds(font, code); SWFRect_getBounds(glyphBounds, &minX, &maxX, &minY, &maxY); SWFOutput_writeBits(out, textRecord->string[i], nGlyphBits); SWFOutput_writeBits(out, textRecord->advance[i], text->nAdvanceBits); if ( CHARACTER(text)->bounds ) { SWFRect_includePoint(CHARACTER(text)->bounds, curX + minX * curH / 1024, curY + minY * curH / 1024, 0); SWFRect_includePoint(CHARACTER(text)->bounds, curX + maxX * curH / 1024, curY + maxY * curH / 1024, 0); } else { CHARACTER(text)->bounds = newSWFRect(curX + minX * curH /1024, curX + maxX * curH /1024, curY + minY * curH /1024, curY + maxY * curH /1024); } if ( textRecord->advance != NULL ) curX += textRecord->advance[i]; } } textRecord = textRecord->next; destroySWFTextRecord(oldRecord); } SWFOutput_writeUInt8(out, 0); /* end text records */ text->nGlyphBits = nGlyphBits; text->initialRecord = NULL; text->currentRecord = NULL; }