int completeSWFTextField(SWFBlock block) { SWFTextField field = (SWFTextField)block; /* we're guessing how big the block's going to be.. */ SWFOutput out = newSizedSWFOutput(42 + ((field->varName)?strlen(field->varName):0) + ((field->string)?strlen(field->string):0)); field->out = out; resetBounds(field); SWFOutput_writeUInt16(out, CHARACTERID(field)); SWFOutput_writeRect(out, CHARACTER(field)->bounds); SWFOutput_writeUInt16(out, field->flags); if(field->flags & SWFTEXTFIELD_HASFONT) { SWFOutput_writeUInt16(out, CHARACTERID(field->font.fontchar)); SWFOutput_writeUInt16(out, field->fontHeight); } if(field->flags & SWFTEXTFIELD_HASCOLOR) { SWFOutput_writeUInt8(out, field->r); SWFOutput_writeUInt8(out, field->g); SWFOutput_writeUInt8(out, field->b); SWFOutput_writeUInt8(out, field->a); } if ( field->flags & SWFTEXTFIELD_HASLENGTH ) SWFOutput_writeUInt16(out, field->length); if(field->flags & SWFTEXTFIELD_HASLAYOUT) { SWFOutput_writeUInt8(out, field->alignment); SWFOutput_writeUInt16(out, field->leftMargin); SWFOutput_writeUInt16(out, field->rightMargin); SWFOutput_writeUInt16(out, field->indentation); SWFOutput_writeUInt16(out, field->lineSpacing); } SWFOutput_writeString(out, (byte*) field->varName); if ( field->flags & SWFTEXTFIELD_HASTEXT ) SWFOutput_writeString(out, (byte*)field->string); /* XXX - if font is a real font, do we need to talk to it? flash 4 just makes a browser font for (editable) textfields for all fonts */ SWFOutput_byteAlign(out); return SWFOutput_getLength(out); }
static void writeSWFTextToMethod(SWFBlock block, SWFByteOutputMethod method, void *data) { SWFText text = (SWFText)block; int length = 0; SWFOutput out; if ( text->matrix == NULL ) text->matrix = newSWFMatrix(1.0, 0, 0, 1.0, 0, 0); length += (SWFMatrix_numBits(text->matrix)+7)/8; length += (SWFRect_numBits(CHARACTER(text)->bounds)+7)/8; length += 4; out = newSizedSWFOutput(length); SWFOutput_writeUInt16(out, CHARACTERID(text)); SWFOutput_writeRect(out, CHARACTER(text)->bounds); SWFOutput_writeMatrix(out, text->matrix); SWFOutput_writeUInt8(out, text->nGlyphBits); SWFOutput_writeUInt8(out, text->nAdvanceBits); SWFOutput_writeToMethod(out, method, data); SWFOutput_writeToMethod(text->out, method, data); destroySWFOutput(out); }
void writeSWFFontToMethod(SWFBlock block, SWFByteOutputMethod method, void *data) { SWFFont font = (SWFFont)block; int offset, i; byte *p, *s; methodWriteUInt16(CHARACTERID(font), method, data); offset = font->nGlyphs*2; /* write offset table for glyphs */ for(i=0; i<font->nGlyphs; ++i) { methodWriteUInt16(offset, method, data); offset += glyphLength(font, font->codeToGlyph[i]); } /* write shape records for glyphs */ for(i=0; i<font->nGlyphs; ++i) { p = font->glyphOffset[font->codeToGlyph[i]]; s = font->glyphOffset[font->codeToGlyph[i]+1]; SWF_assert(p < s); while(p < s) method(*(p++), data); } }
SWFText newSWFText() { SWFText text = (SWFText)malloc(sizeof(struct SWFText_s)); SWFCharacterInit((SWFCharacter)text); CHARACTERID(text) = ++SWF_gNumCharacters; BLOCK(text)->type = SWF_DEFINETEXT; BLOCK(text)->writeBlock = writeSWFTextToMethod; BLOCK(text)->complete = completeSWFText; BLOCK(text)->dtor = (destroySWFBlockMethod) destroySWFText; CHARACTER(text)->bounds = newSWFRect(0,0,0,0); text->out = newSWFOutput(); text->currentRecord = NULL; text->initialRecord = NULL; text->matrix = NULL; text->nAdvanceBits = 0; #if TRACK_ALLOCS text->gcnode = ming_gc_add_node(text, (dtorfunctype) destroySWFBitmap); #endif return text; }
static void finishBrowserFont(SWFBrowserFont font) { unsigned int i; SWFOutput out; SWF_assert(BLOCK(font)->swfVersion); out = newSWFOutput(); font->out = out; SWFOutput_writeUInt16(out, CHARACTERID(font)); if(BLOCK(font)->swfVersion > 5) /* maybe italic or bold flag? */ SWFOutput_writeUInt8(out, SWF_FONT_WIDECODES); else SWFOutput_writeUInt8(out, 0); SWFOutput_writeUInt8(out, 0); /* reserved flags */ SWFOutput_writeUInt8(out, strlen(font->name)); for ( i=0; i<strlen(font->name); ++i ) SWFOutput_writeUInt8(out, font->name[i]); SWFOutput_writeUInt16(out, 0); /* number of glyphs */ SWFOutput_writeSInt16(out, 2); /* offset */ SWFOutput_byteAlign(out); }
static void writeSWFPrebuiltClipToMethod(SWFBlock block, SWFByteOutputMethod method, void *data) { SWFPrebuiltClip clip = (SWFPrebuiltClip) block; methodWriteUInt16(CHARACTERID(clip), method, data); methodWriteUInt16(clip->frames, method, data); SWFOutput_writeToMethod(clip->display, method, data); }
int completeSWFPlaceObject2Block(SWFBlock block) { SWFPlaceObject2Block place = (SWFPlaceObject2Block)block; SWFOutput out = newSizedSWFOutput(42); int flags = ((place->name != NULL) ? SWF_PLACE_HAS_NAME : 0) | ((place->ratio != -1) ? SWF_PLACE_HAS_RATIO : 0) | ((place->masklevel != -1) ? SWF_PLACE_HAS_MASK : 0) | ((place->cXform != NULL) ? SWF_PLACE_HAS_CXFORM : 0) | ((place->matrix != NULL) ? SWF_PLACE_HAS_MATRIX : 0) | ((place->character != NULL) ? SWF_PLACE_HAS_CHARACTER : 0) | ((place->move != 0) ? SWF_PLACE_MOVE : 0) | ((place->nActions != 0) ? SWF_PLACE_HAS_ACTIONS : 0); SWFOutput_writeUInt8(out, flags); if(place->version == 3) { flags = 0; if(place->hasCacheFlag) flags |= SWF_PLACE_CACHE; if(place->hasBlendFlag) flags |= SWF_PLACE_HAS_BLEND; if(place->hasFilterFlag) flags |= SWF_PLACE_HAS_FILTER; SWFOutput_writeUInt8(out, flags); } SWFOutput_writeUInt16(out, place->depth); if ( place->character != NULL ) SWFOutput_writeUInt16(out, CHARACTERID(place->character)); if ( place->matrix != NULL ) SWFOutput_writeMatrix(out, place->matrix); if ( place->cXform != NULL ) SWFOutput_writeCXform(out, place->cXform, SWF_PLACEOBJECT2); if ( place->ratio != -1 ) SWFOutput_writeUInt16(out, place->ratio); if ( place->name != NULL ) SWFOutput_writeString(out, (byte*)place->name); if ( place->masklevel != -1 ) SWFOutput_writeUInt16(out, place->masklevel); if( place->version == 3 && place->hasFilterFlag) SWFOutput_writeFilterList(out, place->filterList); if( place->version == 3 && place->hasBlendFlag) SWFOutput_writeUInt8(out, place->blendMode); place->out = out; writeActions(place); return SWFOutput_getLength(out); }
int completeSWFButton(SWFBlock block) { SWFButton button = (SWFButton)block; SWFButtonRecord record; SWFOutput out = newSWFOutput(); int i, length = 0, layer; byte *offset; SWFOutput_writeUInt16(out, CHARACTERID(button)); SWFOutput_writeUInt8(out, button->menuflag); /* fill in offset later */ offset = SWFOutput_getCurPos(out); SWFOutput_writeUInt16(out, 0); for(i=0; i<button->nRecords; ++i) { record = button->records[i]; SWFOutput_writeUInt8(out, record->flags); SWFOutput_writeUInt16(out, CHARACTERID(record->character)); layer = record->layer; if(layer == 0 && block->swfVersion >= 5) layer = i+1; SWFOutput_writeUInt16(out, layer); SWFOutput_writeMatrix(out, SWFPosition_getMatrix(record->position)); SWFOutput_writeUInt8(out, 0); /* blank CXForm */ if(record->flags & RECORD_HASFILTER) SWFOutput_writeFilterList(out, record->filterList); if(record->flags & RECORD_HASBLEND) SWFOutput_writeUInt8(out, record->blendMode); } SWFOutput_writeUInt8(out, 0); /* end buttons */ length = SWFOutput_getLength(out) - 3; if(button->nActions > 0) { *offset = length&0xff; *(offset+1) = (length>>8)&0xff; }
SWFText newSWFText() { SWFRect temp_rect; SWFText text = (SWFText)malloc(sizeof(struct SWFText_s)); /* If malloc failed, return NULL to signify this */ if (NULL == text) return NULL; SWFCharacterInit((SWFCharacter)text); CHARACTERID(text) = ++SWF_gNumCharacters; BLOCK(text)->type = SWF_DEFINETEXT; BLOCK(text)->writeBlock = writeSWFTextToMethod; BLOCK(text)->complete = completeSWFText; BLOCK(text)->dtor = (destroySWFBlockMethod) destroySWFText; temp_rect = newSWFRect(0,0,0,0); /* If newSWFRect() failed, return NULL to signify this */ if (NULL == temp_rect) { free(text); return NULL; } CHARACTER(text)->bounds = temp_rect; text->out = newSWFOutput(); /* If newSWFOutput() failed, return NULL to signify this */ if (NULL == text->out) { destroySWFRect(temp_rect); free(text); return NULL; } text->currentRecord = NULL; text->initialRecord = NULL; text->matrix = NULL; text->nAdvanceBits = 0; #if TRACK_ALLOCS text->gcnode = ming_gc_add_node(text, (dtorfunctype) destroySWFText); #endif return text; }
/* * Import a font from an other SWFFile * see also SWFMovie_importCharacter * returns a SWFFontCharacter object */ SWFFontCharacter SWFMovie_importFont(SWFMovie movie, const char *filename, const char *name) { SWFFontCharacter res; SWFImportBlock importer; int id; res = newSWFDummyFontCharacter(); id = CHARACTERID(res); importer = SWFMovie_addImport(movie, filename, name, id); SWFCharacter_addDependency((SWFCharacter) res, (SWFCharacter) importer); return res; }
static void writeSWFDBLBitmapToMethod(SWFBlock block, SWFByteOutputMethod method, void *data) { SWFDBLBitmap dbl = (SWFDBLBitmap)block; int i; methodWriteUInt16(CHARACTERID(dbl), method, data); /* just dump the rest of the file */ for ( i=block->length-2; i>0; --i ) method((unsigned char)SWFInput_getChar(dbl->input), data); }
void writeSWFSoundInstanceToMethod(SWFBlock block, SWFByteOutputMethod method, void *data) { SWFSoundInstance sound; byte flags; int i; // block may be null if we're calling from button.c: if ( block == NULL ) { method(0, data); method(0, data); method(0, data); return; } sound = (SWFSoundInstance)block; flags = sound->flags; if ( sound->sound ) methodWriteUInt16(CHARACTERID(sound->sound), method, data); else methodWriteUInt16(0, method, data); /* 0 means NULL character */ method(flags, data); if ( flags & SWF_SOUNDINFO_HASINPOINT ) methodWriteUInt32(sound->inPoint, method, data); if ( flags & SWF_SOUNDINFO_HASOUTPOINT ) methodWriteUInt32(sound->outPoint, method, data); if ( flags & SWF_SOUNDINFO_HASLOOPS ) methodWriteUInt16(sound->numLoops, method, data); if ( flags & SWF_SOUNDINFO_HASENVELOPE ) { method(sound->numEnvPoints, data); for ( i=0; i<sound->numEnvPoints; ++i ) { methodWriteUInt32((sound->envPoints[i]).mark44, method, data); methodWriteUInt16((sound->envPoints[i]).level0, method, data); methodWriteUInt16((sound->envPoints[i]).level1, method, data); } } }
SWFShape newSWFShape() { SWFShape shape = (SWFShape)malloc(sizeof(struct SWFShape_s)); /* If malloc failed, return NULL to signify this */ if (NULL == shape) return NULL; SWFCharacterInit((SWFCharacter)shape); BLOCK(shape)->writeBlock = writeSWFShapeBlockToMethod; BLOCK(shape)->complete = completeSWFShapeBlock; BLOCK(shape)->dtor = (destroySWFBlockMethod) destroySWFShape; BLOCK(shape)->type = SWF_DEFINESHAPE3; CHARACTERID(shape) = ++SWF_gNumCharacters; shape->out = newSWFOutput(); CHARACTER(shape)->bounds = newSWFRect(0,0,0,0); shape->edgeBounds = newSWFRect(0,0,0,0); shape->records = NULL; shape->lines = NULL; shape->fills = NULL; shape->nRecords = 0; shape->xpos = 0; shape->ypos = 0; shape->nLines = 0; shape->nFills = 0; shape->lineWidth = 0; shape->isMorph = FALSE; shape->isEnded = FALSE; shape->flags = 0; shape->useVersion = SWF_SHAPE3; SWFOutput_writeUInt8(shape->out, 0); /* space for nFillBits, nLineBits */ #if TRACK_ALLOCS shape->gcnode = ming_gc_add_node(shape, (dtorfunctype) destroySWFShape); #endif return shape; }
/** * creates a browser font instance * This Function allows the usage of built in fonts like "_sans". * Takes the name of the font as an argument. */ SWFBrowserFont newSWFBrowserFont(const char *name) { SWFBrowserFont font = (SWFBrowserFont) malloc(sizeof(struct SWFBrowserFont_s)); SWFCharacterInit((SWFCharacter)font); BLOCK(font)->writeBlock = writeSWFBrowserFontToMethod; BLOCK(font)->complete = completeSWFBrowserFont; BLOCK(font)->dtor = (destroySWFBlockMethod) destroySWFBrowserFont; BLOCK(font)->type = SWF_BROWSERFONT; CHARACTERID(font) = ++SWF_gNumCharacters; font->out = NULL; font->name = strdup(name); return font; }
SWFDBLBitmapData newSWFDBLBitmapData_fromData(dblData data) { SWFDBLBitmapData dbl; dbl = (SWFDBLBitmapData)malloc(sizeof(struct SWFDBLBitmapData_s)); /* If malloc failed, return NULL to signify this */ if (NULL == dbl) return NULL; SWFCharacterInit((SWFCharacter)dbl); CHARACTERID(dbl) = ++SWF_gNumCharacters; BLOCK(dbl)->writeBlock = writeSWFDBLBitmapDataToMethod; BLOCK(dbl)->complete = completeSWFDBLBitmap; BLOCK(dbl)->dtor = (destroySWFBlockMethod) destroySWFDBLBitmapData; dbl->width = data->width; dbl->height = data->height; dbl->format = data->format; dbl->format2 = data->format2; dbl->data = data->data; if(data->hasalpha) BLOCK(dbl)->type = SWF_DEFINELOSSLESS2; else BLOCK(dbl)->type = SWF_DEFINELOSSLESS; BLOCK(dbl)->length = data->length; BLOCK(dbl)->length += 7; /* character id, format, width, height */ if(dbl->format == 3) BLOCK(dbl)->length++; CHARACTER(dbl)->bounds = newSWFRect(0, dbl->width, 0, dbl->height); #if TRACK_ALLOCS dbl->gcnode = ming_gc_add_node(dbl, (dtorfunctype)destroySWFDBLBitmapData); #endif return dbl; }
/* * Import a character to the movie * Imports characters from an other movie. filename (URL) points to a SWF * file with exported characters. * * returns a SWFCharacter object */ SWFCharacter SWFMovie_importCharacter(SWFMovie movie, const char *filename /* URL to movie */, const char *name /* idetifier of character */) { SWFCharacter res; SWFImportBlock importer; int id; res = (SWFCharacter) malloc(sizeof(struct SWFCharacter_s)); SWFCharacterInit(res); CHARACTERID(res) = id = ++SWF_gNumCharacters; BLOCK(res)->type = SWF_DEFINESPRITE; BLOCK(res)->writeBlock = NULL; BLOCK(res)->complete = completeSWFImportCharacter; BLOCK(res)->dtor = (destroySWFBlockMethod) destroySWFCharacter; importer = SWFMovie_addImport(movie, filename, name, id); SWFCharacter_addDependency(res, (SWFCharacter) importer); return res; }
void SWFShape_addStyleHeader(SWFShape shape) { SWFOutput out = newSWFOutput(); SWFOutput_writeUInt16(out, CHARACTERID(shape)); SWFOutput_writeRect(out, SWFCharacter_getBounds(CHARACTER(shape))); if (shape->isUsingNewStyles) { shape->nFills2 = 0; shape->nLines2 = 0; } SWFOutput_writeFillStyles(out, shape->fills2, shape->nFills2, BLOCK(shape)->type); SWFOutput_writeLineStyles(out, shape->lines2, shape->nLines2, BLOCK(shape)->type); /* prepend shape->out w/ shape header */ SWFOutput_setNext(out, shape->out); shape->out = out; }
void SWFShape_addStyleHeader(SWFShape shape) { SWFOutput out = newSWFOutput(); SWFOutput_writeUInt16(out, CHARACTERID(shape)); SWFOutput_writeRect(out, SWFCharacter_getBounds(CHARACTER(shape))); if(shape->useVersion == SWF_SHAPE4) { SWFOutput_writeRect(out, shape->edgeBounds); SWFOutput_writeUInt8(out, shape->flags); } SWFOutput_writeFillStyles(out, shape->fills, shape->nFills, BLOCK(shape)->type, shape->edgeBounds); SWFOutput_writeLineStyles(out, shape->lines, shape->nLines, BLOCK(shape)->type); /* prepend shape->out w/ shape header */ SWFOutput_setNext(out, shape->out); shape->out = out; }
static void writeSWFDBLBitmapDataToMethod(SWFBlock block, SWFByteOutputMethod method, void *data) { SWFDBLBitmapData dbl = (SWFDBLBitmapData)block; int i; unsigned char *ptr; methodWriteUInt16(CHARACTERID(dbl), method, data); method(dbl->format, data); methodWriteUInt16(dbl->width, method, data); methodWriteUInt16(dbl->height, method, data); i=block->length-8; if(dbl->format == 3) // palette image method(dbl->format2, data); else i++; /* just dump the rest of the file */ for (ptr = dbl->data; i>0; --i ) method(*ptr++, data); }
SWFTextField newSWFTextField() { SWFRect temp_rect; SWFTextField field = (SWFTextField)malloc(sizeof(struct SWFTextField_s)); /* If malloc failed, return NULL to signify this */ if (NULL == field) return NULL; SWFCharacterInit((SWFCharacter)field); BLOCK(field)->writeBlock = writeSWFTextFieldToMethod; BLOCK(field)->complete = completeSWFTextField; BLOCK(field)->dtor = (destroySWFBlockMethod) destroySWFTextField; BLOCK(field)->type = SWF_DEFINEEDITTEXT; CHARACTERID(field) = ++SWF_gNumCharacters; temp_rect = newSWFRect(-40, 280, -40, 280); /* If newSWFRect() failed, return NULL to signify this */ if (NULL == temp_rect) { free(field); return NULL; } CHARACTER(field)->bounds = temp_rect; field->out = NULL; field->lineSpacing = 40; field->padding = 40; field->fontHeight = 240; field->fieldHeight = 0; field->width = 0; field->a = 0xff; field->nLines = 1; field->flags = 0; field->font.font = NULL; field->fonttype = Unresolved; field->varName = NULL; field->string = NULL; field->r = 0; field->g = 0; field->b = 0; field->a = 0xff; field->length = 0; field->alignment = SWFTEXTFIELD_ALIGN_LEFT; field->leftMargin = 0; field->rightMargin = 0; field->indentation = 0; field->embeds = NULL; field->embedlen = 0; return field; }
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; }
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; }
SWFDBLBitmap newSWFDBLBitmap_fromInput(SWFInput input) { SWFDBLBitmap dbl; int version; int width, height; dbl = (SWFDBLBitmap)malloc(sizeof(struct SWFDBLBitmap_s)); SWFCharacterInit((SWFCharacter)dbl); CHARACTERID(dbl) = ++SWF_gNumCharacters; BLOCK(dbl)->writeBlock = writeSWFDBLBitmapToMethod; BLOCK(dbl)->complete = completeSWFDBLBitmap; BLOCK(dbl)->dtor = (destroySWFBlockMethod) destroySWFCharacter; dbl->input = input; if ( SWFInput_getChar(input) != 'D' || SWFInput_getChar(input) != 'B' ) { SWF_error("File is not a DBL file!"); } version = SWFInput_getChar(input); if ( version != 'L' && version != 'l' ) SWF_error("File is not a DBL file!"); switch ( SWFInput_getChar(input) ) { case 1: BLOCK(dbl)->type = SWF_DEFINELOSSLESS; break; case 2: BLOCK(dbl)->type = SWF_DEFINELOSSLESS2; break; default: SWF_error("Unexpected DBL type byte!"); } if ( version == 'l' ) { BLOCK(dbl)->length = SWFInput_getUInt32_BE(input); BLOCK(dbl)->length += 2; /* character id */ } else { /* first version used a 2-byte file length.. brilliant, eh? */ BLOCK(dbl)->length = SWFInput_getUInt16_BE(input); BLOCK(dbl)->length += 2; /* character id */ } SWFInput_getChar(input); /* format */ width = SWFInput_getUInt16(input); height = SWFInput_getUInt16(input); /* roll back to beginning of dbl data */ SWFInput_seek(input, -5, SEEK_CUR); CHARACTER(dbl)->bounds = newSWFRect(0, width, 0, height); return dbl; }