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); }
void SWFOutput_writeGlyphShape(SWFOutput out, SWFShape shape) { unsigned char c; int styleDone = 0; int i; c = 1<<4; SWFOutput_writeUInt8(out, c); shape->nFills = 1; shape->nLines = 0; for ( i=0; i<shape->nRecords; ++i ) { if(!styleDone && shape->records[i].type == SHAPERECORD_STATECHANGE) { shape->records[i].record.stateChange->flags |= SWF_SHAPE_FILLSTYLE0FLAG; shape->records[i].record.stateChange->leftFill = 1; styleDone = 1; } if ( i < shape->nRecords-1 || shape->records[i].type != SHAPERECORD_STATECHANGE ) { SWFShape_writeShapeRecord(shape, shape->records[i], out); } } SWFOutput_writeBits(out, 0, 6); /* end tag */ SWFOutput_byteAlign(out); }
void outputTrailer (struct Movie *m) { SWFOutput out; out=newSizedSWFOutput(30); SWFOutput_writeUInt8(out,'F'); SWFOutput_writeUInt8(out,'W'); SWFOutput_writeUInt8(out,'S'); SWFOutput_writeUInt8(out,4); SWFOutput_writeUInt32(out,SWFOutput_getLength(swfout)+23 /*size of header*/); SWFOutput_writeBits(out,15,5); SWFOutput_writeSBits(out,m->frame.xMin,15); SWFOutput_writeSBits(out,m->frame.xMax,15); SWFOutput_writeSBits(out,m->frame.yMin,15); SWFOutput_writeSBits(out,m->frame.yMax,15); SWFOutput_byteAlign(out); SWFOutput_writeUInt16(out,m->rate); SWFOutput_writeUInt16(out,m->nFrames); /* Add the SWF_END tag */ SWFOutput_writeUInt16(swfout,0); SWFOutput_writeToMethod(out,fileOutputMethod,stdout); SWFOutput_writeToMethod(swfout,fileOutputMethod,stdout); destroySWFOutput(swfout); destroySWFOutput(out); }
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); }
void SWFShape_end(SWFShape shape) { int i; byte* buffer; if ( shape->isEnded ) return; shape->isEnded = TRUE; buffer = SWFOutput_getBuffer(shape->out); if (shape->isUsingNewStyles == FALSE) { buffer[0] = (SWFOutput_numBits(shape->nFills2) << 4) + SWFOutput_numBits(shape->nLines2); } for ( i=0; i<shape->nRecords; ++i ) { if ( i < shape->nRecords-1 || shape->records[i].type != SHAPERECORD_STATECHANGE ) { SWFShape_writeShapeRecord(shape, shape->records[i]); } free(shape->records[i].record.stateChange); /* all in union are pointers */ } SWFOutput_writeBits(shape->out, 0, 6); /* end tag */ SWFOutput_byteAlign(shape->out); /* addStyleHeader creates a new output and adds the existing one after itself- so even though it's called afterwards it's written before, as it should be */ if ( BLOCK(shape)->type > 0 ) /* i.e., shape with style */ SWFShape_addStyleHeader(shape); free(shape->records); shape->records = NULL; shape->nRecords = 0; shape->lines = &shape->lines2; shape->fills = &shape->fills2; shape->nLines = &shape->nLines2; shape->nFills = &shape->nFills2; }
SWFOutput outputswfSWF_SHAPE (SWF_SHAPE * shape) { SWFOutput out; int i; out=newSWFOutput(); SWFOutput_writeBits(out,shape->NumFillBits,4); SWFOutput_writeBits(out,shape->NumLineBits,4); for (i = 0; i < shape->NumShapeRecords; i++) { outputswfSWF_SHAPERECORD (&(shape->ShapeRecords[i]), out,shape->NumFillBits,shape->NumLineBits); } SWFOutput_byteAlign(out); return out; }
void SWFOutput_writeToMethod(SWFOutput out, SWFByteOutputMethod method, void *data) { int i, l; SWFOutput o = out; byte *buffer; SWFOutput_byteAlign(out); while ( o != NULL ) { buffer = o->buffer; l = o->pos - buffer; for(i=0; i<l; ++i) method(buffer[i], data); o = o->next; } }
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; }
SWFOutput outputSWF_DEFINEFONT2 (SWF_Parserstruct * pblock) { SWFOutput hdr0,hdr1,offsettbl,*glyphdata; int i,size, glyphbase; OUT_BEGIN (SWF_DEFINEFONT2); glyphdata = calloc(sblock->NumGlyphs,sizeof(SWFOutput *)); size=0; for (i = 0; i < sblock->NumGlyphs; i++) { glyphdata[i] = outputswfSWF_SHAPE (&(sblock->GlyphShapeTable[i])); size+= SWFOutput_getLength(glyphdata[i]); } if( size > 0xffff ) sblock->FontFlagsWideOffsets=1; if (sblock->FontFlagsWideOffsets) { glyphbase=(sblock->NumGlyphs*4)+4; sblock->CodeTableOffset.UI32=glyphbase; sblock->OffsetTable.UI32[0]=glyphbase; } else { glyphbase=(sblock->NumGlyphs*2)+2; sblock->CodeTableOffset.UI16=glyphbase; sblock->OffsetTable.UI16[0]=glyphbase; } for (i = 0; i < sblock->NumGlyphs; i++) { if (sblock->FontFlagsWideOffsets) { sblock->OffsetTable.UI32[i]=sblock->CodeTableOffset.UI32; sblock->CodeTableOffset.UI32=sblock->OffsetTable.UI32[i]+SWFOutput_getLength(glyphdata[i]); } else { sblock->OffsetTable.UI16[i]=sblock->CodeTableOffset.UI16; sblock->CodeTableOffset.UI16=sblock->OffsetTable.UI16[i]+SWFOutput_getLength(glyphdata[i]); } } offsettbl=newSWFOutput(); for (i = 0; i < sblock->NumGlyphs; i++) { if (sblock->FontFlagsWideOffsets) { SWFOutput_writeUInt32(offsettbl,sblock->OffsetTable.UI32[i]); } else { SWFOutput_writeUInt16(offsettbl,sblock->OffsetTable.UI16[i]); } } /* Now that we have the glyph data, and it's offset, we can start assembling this block */ size= 5 /* Initial header through FontNameLen */ +(sblock->FontNameLen) /* FontName */ +2; /* NumGlyphs */ hdr1=newSizedSWFOutput(size); SWFOutput_writeUInt16(hdr1,sblock->FontID); SWFOutput_writeBits(hdr1,sblock->FontFlagsHasLayout,1); SWFOutput_writeBits(hdr1,sblock->FontFlagsShiftJis,1); SWFOutput_writeBits(hdr1,sblock->FontFlagsSmallText,1); SWFOutput_writeBits(hdr1,sblock->FontFlagsFlagANSI,1); SWFOutput_writeBits(hdr1,sblock->FontFlagsWideOffsets,1); SWFOutput_writeBits(hdr1,sblock->FontFlagsWideCodes,1); SWFOutput_writeBits(hdr1,sblock->FontFlagsFlagsItalics,1); SWFOutput_writeBits(hdr1,sblock->FontFlagsFlagsBold,1); SWFOutput_writeUInt8(hdr1,sblock->LanguageCode); SWFOutput_writeUInt8(hdr1,sblock->FontNameLen); SWFOutput_writeBuffer(hdr1,(unsigned char *)sblock->FontName,sblock->FontNameLen); SWFOutput_writeUInt16(hdr1,sblock->NumGlyphs); /* Now, copy these parts into the hdr buffer */ SWFOutput_writeToMethod(offsettbl,SWFOutputMethod,hdr1); destroySWFOutput(offsettbl); if (sblock->FontFlagsWideOffsets) { SWFOutput_writeUInt32(hdr1,sblock->CodeTableOffset.UI32); } else { SWFOutput_writeUInt16(hdr1,sblock->CodeTableOffset.UI16); } for (i = 0; i < sblock->NumGlyphs; i++) { SWFOutput_writeToMethod(glyphdata[i],SWFOutputMethod,hdr1); destroySWFOutput(glyphdata[i]); } free(glyphdata); /* Now, resume the normal linear processing this tag */ for (i = 0; i < sblock->NumGlyphs; i++) { if( sblock->FontFlagsWideCodes ) { SWFOutput_writeUInt16(hdr1,sblock->CodeTable[i]); } else { SWFOutput_writeUInt8(hdr1,sblock->CodeTable[i]); } } if( sblock->FontFlagsHasLayout ) { SWFOutput_writeSInt16(hdr1,sblock->FontAscent); SWFOutput_writeSInt16(hdr1,sblock->FontDecent); SWFOutput_writeSInt16(hdr1,sblock->FontLeading); for (i = 0; i < sblock->NumGlyphs; i++) { SWFOutput_writeSInt16(hdr1,sblock->FontAdvanceTable[i]); } for (i = 0; i < sblock->NumGlyphs; i++) { outputswfSWF_RECT (hdr1,&(sblock->FontBoundsTable[i])); SWFOutput_byteAlign(hdr1); } SWFOutput_writeUInt16(hdr1,sblock->KerningCount); for (i = 0; i < sblock->KerningCount; i++) { if( sblock->FontFlagsWideCodes ) { SWFOutput_writeUInt16(hdr1,sblock->FontKerningTable[i].FontKerningCode1); SWFOutput_writeUInt16(hdr1,sblock->FontKerningTable[i].FontKerningCode2); SWFOutput_writeSInt16(hdr1,sblock->FontKerningTable[i].FontKerningAdjustment); } else { SWFOutput_writeUInt8(hdr1,sblock->FontKerningTable[i].FontKerningCode1); SWFOutput_writeUInt8(hdr1,sblock->FontKerningTable[i].FontKerningCode2); SWFOutput_writeSInt16(hdr1,sblock->FontKerningTable[i].FontKerningAdjustment); } } } /* This code really belongs in outputTAGHeader() */ hdr0=newSizedSWFOutput(6); if(SWFOutput_getLength(hdr1) <= 62 ) { fprintf(stderr,"TAG %x\n",(SWF_DEFINEFONT2<<6)|SWFOutput_getLength(hdr1)); SWFOutput_writeUInt16(hdr0,(SWF_DEFINEFONT2<<6)|SWFOutput_getLength(hdr1)); } else { SWFOutput_writeUInt16(hdr0,(SWF_DEFINEFONT2<<6)|0x3f); SWFOutput_writeUInt32(hdr0,SWFOutput_getLength(hdr1)); } SWFOutput_writeToMethod(hdr1,SWFOutputMethod,hdr0); destroySWFOutput(hdr1); return hdr0; }
void SWFOutput_writeMatrix(SWFOutput out, SWFMatrix matrix) { int nBits; SWFOutput_byteAlign(out); if ( (matrix->scaleX == 0 && matrix->scaleY == 0) || (matrix->scaleX == 1.0 && matrix->scaleY == 1.0) ) { SWFOutput_writeBits(out, 0, 1); } else { int xScale = (int)floor(matrix->scaleX * (1<<FIXEDBITS)); int yScale = (int)floor(matrix->scaleY * (1<<FIXEDBITS)); SWFOutput_writeBits(out, 1, 1); nBits = max(SWFOutput_numSBits(xScale), SWFOutput_numSBits(yScale)); if(nBits >= 32) SWF_error("SWFMatrix_scale: number is to big. " " Requested %i bits\n", nBits); SWFOutput_writeBits(out, nBits, 5); SWFOutput_writeSBits(out, xScale, nBits); SWFOutput_writeSBits(out, yScale, nBits); } if ( matrix->rotate0 == 0 && matrix->rotate1 == 0 ) { SWFOutput_writeBits(out, 0, 1); } else { int rot0 = (int)floor(matrix->rotate0 * (1<<FIXEDBITS)); int rot1 = (int)floor(matrix->rotate1 * (1<<FIXEDBITS)); SWFOutput_writeBits(out, 1, 1); nBits = max(SWFOutput_numSBits(rot0), SWFOutput_numSBits(rot1)); if(nBits >= 32) SWF_error("SWFMatrix_rotate: number is to big. " " Requested %i bits\n", nBits); SWFOutput_writeBits(out, nBits, 5); SWFOutput_writeSBits(out, rot0, nBits); SWFOutput_writeSBits(out, rot1, nBits); } if ( matrix->translateX != 0 || matrix->translateY != 0 ) { nBits = max(SWFOutput_numSBits(matrix->translateX), SWFOutput_numSBits(matrix->translateY)); if(nBits >= 32) SWF_error("SWFMatrix_translate: number is to big. " " Requested %i bits\n", nBits); } else nBits = 0; SWFOutput_writeBits(out, nBits, 5); SWFOutput_writeSBits(out, matrix->translateX, nBits); SWFOutput_writeSBits(out, matrix->translateY, nBits); }
SWFOutput SWFMovie_toOutput(SWFMovie movie, int level) { int swflength; #if USE_ZLIB int status; #endif SWFOutput header, tempbuffer=0, buffer, swfbuffer; SWFBlock lastBlock; unsigned long compresslength; if ( movie->nExports > 0 ) SWFMovie_writeExports(movie); if ( movie->metadata != NULL) { SWFMovie_addBlock(movie, (SWFBlock)movie->metadata); movie->metadata = NULL; // do not destroy with movie if added as block } /* Add a terminating SHOWFRAME tag if not already there */ lastBlock = SWFBlockList_getLastBlock(movie->blockList); if ( ! lastBlock || SWFBlock_getType(lastBlock) != SWF_SHOWFRAME ) { SWFMovie_nextFrame(movie); } while ( movie->nFrames < movie->totalFrames ) SWFMovie_nextFrame(movie); if(movie->symbolClass) SWFMovie_addBlock(movie, (SWFBlock)movie->symbolClass); if(movie->sceneData) SWFMovie_addBlock(movie, (SWFBlock)movie->sceneData); SWFMovie_addBlock(movie, newSWFEndBlock()); // add five for the setbackground block.. swflength = SWFBlockList_completeBlocks(movie->blockList, movie->version); /* XXX - hack */ SWFDisplayList_rewindSoundStream(movie->displayList); header = newSizedSWFOutput(23); SWFOutput_writeRect(header, movie->bounds); SWFOutput_writeUInt16(header, (int)floor(movie->rate*256)); SWFOutput_writeUInt16(header, movie->nFrames); /* SWF >= 8: first block _must_ be SWF_FILEATTRIBUTES */ if(movie->fattrs) writeSWFBlockToMethod((SWFBlock)movie->fattrs, SWFOutputMethod, header); if(movie->backgroundBlock) writeSWFBlockToMethod(movie->backgroundBlock, SWFOutputMethod, header); if(movie->limits) writeSWFBlockToMethod((SWFBlock)movie->limits, SWFOutputMethod, header); SWFOutput_byteAlign(header); swflength += 8 + SWFOutput_getLength(header); // compression level check #if USE_ZLIB if (level < -1) level = -1; if (level > 9) level = 9; #else if ( level != -1 ) { SWF_warn("No zlib support compiled in, " "cannot generate compressed output"); level = -1; } #endif // reserve output buffer if(level >= 0) { // a little bit more than the uncompressed data compresslength = swflength + (swflength/1000) + 15 + 1; swfbuffer = newSizedSWFOutput( compresslength + 8 ); } else swfbuffer = newSizedSWFOutput( swflength ); if (level >= 0) SWFOutput_writeUInt8 (swfbuffer, 'C'); else SWFOutput_writeUInt8 (swfbuffer, 'F'); SWFOutput_writeUInt8 (swfbuffer, 'W'); SWFOutput_writeUInt8 (swfbuffer, 'S'); SWFOutput_writeUInt8 (swfbuffer, movie->version); // Movie length SWFOutput_writeUInt32(swfbuffer, swflength); if(level >= 0) buffer = tempbuffer = newSizedSWFOutput( swflength - 8); else buffer = swfbuffer; SWFOutput_writeToMethod(header, SWFOutputMethod, buffer); destroySWFOutput(header); // fill swfbuffer with blocklist SWFBlockList_writeBlocksToMethod(movie->blockList, SWFOutputMethod, buffer); #if USE_ZLIB if (level >= 0) { status = compress2 ( (Bytef*) SWFOutput_getBuffer(swfbuffer)+8, &compresslength, SWFOutput_getBuffer(tempbuffer), SWFOutput_getLength(tempbuffer), level); if (status == Z_OK) { SWFOutput_truncate(swfbuffer, compresslength+8); destroySWFOutput(tempbuffer); } else SWF_error("compression failed"); } #endif // ndef USE_ZLIB return swfbuffer; }
void SWFOutput_writeCXform(SWFOutput out, SWFCXform cXform, SWFBlocktype type) { int nBits = 0; int hasAdd, hasMult; SWFOutput_byteAlign(out); hasAdd = ( cXform->rAdd != 0 || cXform->gAdd != 0 || cXform->bAdd != 0 || cXform->aAdd != 0 ); hasMult = ( cXform->rMult != 256 || cXform->gMult != 256 || cXform->bMult != 256 || cXform->aMult != 256 ); SWFOutput_writeBits(out, hasAdd ? 1 : 0, 1); SWFOutput_writeBits(out, hasMult ? 1 : 0, 1); if ( hasAdd ) { nBits = max(nBits, SWFOutput_numSBits(cXform->rAdd)); nBits = max(nBits, SWFOutput_numSBits(cXform->gAdd)); nBits = max(nBits, SWFOutput_numSBits(cXform->bAdd)); if ( type == SWF_PLACEOBJECT2 ) nBits = max(nBits, SWFOutput_numSBits(cXform->aAdd)); } if ( hasMult ) { nBits = max(nBits, SWFOutput_numSBits(cXform->rMult)); nBits = max(nBits, SWFOutput_numSBits(cXform->gMult)); nBits = max(nBits, SWFOutput_numSBits(cXform->bMult)); if ( type == SWF_PLACEOBJECT2 ) nBits = max(nBits, SWFOutput_numSBits(cXform->aMult)); } if ( nBits>=16 ) SWF_error("color transform data out of scale"); SWFOutput_writeBits(out, nBits, 4); if ( hasMult ) { SWFOutput_writeSBits(out, cXform->rMult, nBits); SWFOutput_writeSBits(out, cXform->gMult, nBits); SWFOutput_writeSBits(out, cXform->bMult, nBits); if ( type == SWF_PLACEOBJECT2 ) SWFOutput_writeSBits(out, cXform->aMult, nBits); } if ( hasAdd ) { SWFOutput_writeSBits(out, cXform->rAdd, nBits); SWFOutput_writeSBits(out, cXform->gAdd, nBits); SWFOutput_writeSBits(out, cXform->bAdd, nBits); if ( type == SWF_PLACEOBJECT2 ) SWFOutput_writeSBits(out, cXform->aAdd, nBits); } }
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; }