/* * Assigns a name to a SWFBlock object. * Creates an exportlibrary with named symbols to be imported by other * SWF movies. * Call SWFMovie_writeExports() when you're done with the exports * to actually write the tag. If you don't the tag will be added * at the END of the SWF. * see also SWFMovie_importCharacter, SWFMovie_importFont */ void SWFMovie_addExport(SWFMovie movie, SWFBlock block, const char *name) { switch( SWFBlock_getType(block)) { case SWF_DEFINESHAPE: case SWF_DEFINESHAPE2: case SWF_DEFINESHAPE3: case SWF_DEFINESHAPE4: case SWF_DEFINEBUTTON: case SWF_DEFINEBUTTON2: case SWF_DEFINESPRITE: case SWF_DEFINEFONT2: case SWF_DEFINESOUND: case SWF_DEFINELOSSLESS: case SWF_DEFINELOSSLESS2: case SWF_DEFINEBITS: case SWF_DEFINEBITSJPEG2: case SWF_DEFINEBITSJPEG3: movie->exports = (struct SWFExport_s*)realloc(movie->exports, (movie->nExports+1) * sizeof(struct SWFExport_s)); movie->exports[movie->nExports].block = block; movie->exports[movie->nExports].name = strdup(name); ++movie->nExports; break; default: SWF_error("Exporting a character of type %d is not supported", SWFBlock_getType(block)); break; } }
void SWFText_addUTF8String(SWFText text, const char* string, int* advance) { unsigned short* widestring; int len = UTF8ExpandString(string, &widestring); SWFTextRecord textRecord = text->currentRecord; /* marginally sloppy to tack on a new record, but I don't want to deal with concats */ if ( textRecord == NULL || textRecord->string != NULL ) textRecord = SWFText_addTextRecord(text); /* If SWFText_addTextRecord() failed, return early */ if (NULL == textRecord) return; if ( textRecord->font.font == NULL ) SWF_error("font must be set before calling addString"); textRecord->advance = advance; textRecord->strlen = len; textRecord->string = widestring; }
/* * Creates a shape filled with bitmap */ SWFShape newSWFShapeFromBitmap(SWFBitmap bitmap, int flag) { SWFShape shape = newSWFShape(); SWFFillStyle fill; int width, height; if ( flag != SWFFILL_TILED_BITMAP && flag != SWFFILL_CLIPPED_BITMAP) { SWF_error("Invalid bitmap fill flag"); } fill = SWFShape_addBitmapFillStyle(shape, bitmap, flag); width = SWFBitmap_getWidth(bitmap); height = SWFBitmap_getHeight(bitmap); SWFShape_setRightFillStyle(shape, fill); // XXX - scale shouldn't be hardcoded! (here, or in newSWFBitmapFillStyle) SWFShape_drawScaledLine(shape, width * 20, 0); SWFShape_drawScaledLine(shape, 0, height * 20); SWFShape_drawScaledLine(shape, -width * 20, 0); SWFShape_drawScaledLine(shape, 0, -height * 20); return shape; }
void SWFText_addWideString(SWFText text, const unsigned short* widestring, int len, int* advance) { SWFTextRecord textRecord = text->currentRecord; /* marginally sloppy to tack on a new record, but I don't want to deal with concats */ if ( textRecord == NULL || textRecord->string != NULL ) textRecord = SWFText_addTextRecord(text); /* If SWFText_addTextRecord() failed, return early */ if (NULL == textRecord) return; if ( textRecord->font.font == NULL ) SWF_error("font must be set before calling addString"); textRecord->advance = advance; textRecord->strlen = len; textRecord->string = (unsigned short*)malloc(sizeof(unsigned short) * len); /* If malloc failed, return early */ if (NULL == textRecord->string) { destroySWFTextRecord(textRecord); return; } memcpy(textRecord->string, widestring, sizeof(unsigned short) * len); }
/* note: replaces action, doesn't append.. */ void SWFButton_addAction(SWFButton button, SWFAction action, int flags) { if ( SWFCharacter_isFinished((SWFCharacter)button) ) SWF_error("Can't alter a button after it's been added to another character"); if ( button->nActions % BUTTONRECORD_INCREMENT == 0 ) { button->actions = (struct actionRecord*) realloc(button->actions, (button->nActions + BUTTONRECORD_INCREMENT) * sizeof(struct actionRecord)); } button->actions[button->nActions].action = action; button->actions[button->nActions].flags = flags; ++button->nActions; }
void SWFOutput_writeRect(SWFOutput out, SWFRect rect) { int nBits = max(max(SWFOutput_numSBits(rect->minX), SWFOutput_numSBits(rect->maxX)), max(SWFOutput_numSBits(rect->minY), SWFOutput_numSBits(rect->maxY))); if(nBits>=32) SWF_error("SWFRect too large for file format"); SWFOutput_writeBits(out, nBits, 5); SWFOutput_writeSBits(out, rect->minX, nBits); SWFOutput_writeSBits(out, rect->maxX, nBits); SWFOutput_writeSBits(out, rect->minY, nBits); SWFOutput_writeSBits(out, rect->maxY, nBits); }
static void setPlaceObjectVersion(SWFPlaceObject2Block block, int version) { switch(version) { case 2: block->version = version; BLOCK(block)->type = SWF_PLACEOBJECT2; break; case 3: block->version = version; BLOCK(block)->type = SWF_PLACEOBJECT3; break; default: SWF_error("setPlaceObjectVersion: invalid version %i\n", version); } }
/* adds a shape character * Add a shape character to a button for given states * possible states: * SWFBUTTON_HIT * SWFBUTTON_DOWN * SWFBUTTON_OVER * SWFBUTTON_UP * states can be combined using the binary or operator * deprecated! use SWFButton_addCharacter instead */ void SWFButton_addShape(SWFButton button, SWFCharacter character, byte flags) { SWFMatrix m; SWF_warnOnce("SWFButton_addShape is deprecated\nUse SWFButton_addCharacter instead\n"); if ( SWFCharacter_isFinished((SWFCharacter)button) ) SWF_error("Can't alter a button after it's been added to another character"); m = newSWFMatrix(1.0, 0, 0, 1.0, 0, 0); SWFCharacter_getDependencies((SWFCharacter)character, &CHARACTER(button)->dependencies, &CHARACTER(button)->nDependencies); SWFCharacter_addDependency((SWFCharacter)button, (SWFCharacter)character); SWFCharacter_setFinished(character); SWFButton_addRecord(button, newSWFButtonRecord(flags, character, 0, m)); }
void SWFShape_drawScaledCurve(SWFShape shape, int controldx, int controldy, int anchordx, int anchordy) { ShapeRecord record; if ( shape->isEnded ) return; if ( controldx == 0 && controldy == 0 && anchordx == 0 && anchordy == 0 ) return; // printf("curve %i,%i, %i, %i\n", controldx, controldy, anchordx, anchordy); record = newShapeRecord(shape, SHAPERECORD_CURVETO); record.record.curveTo->controlx = controldx; record.record.curveTo->controly = controldy; record.record.curveTo->anchorx = anchordx; record.record.curveTo->anchory = anchordy; if ( SWFOutput_numSBits(controldx) >= 18 || SWFOutput_numSBits(controldy) >= 18 || SWFOutput_numSBits(anchordx) >= 18 || SWFOutput_numSBits(anchordy) >= 18 ) SWF_error("Curve parameters too large"); /* including the control point is sloppy, but safe.. */ shape->xpos += controldx; shape->ypos += controldy; SWFRect_includePoint(SWFCharacter_getBounds(CHARACTER(shape)), shape->xpos, shape->ypos, shape->lineWidth); SWFRect_includePoint(shape->edgeBounds, shape->xpos, shape->ypos, 0); shape->xpos += anchordx; shape->ypos += anchordy; SWFRect_includePoint(SWFCharacter_getBounds(CHARACTER(shape)), shape->xpos, shape->ypos, shape->lineWidth); SWFRect_includePoint(shape->edgeBounds, shape->xpos, shape->ypos, 0); }
void SWFText_setFont(SWFText text, void* font) { SWFTextRecord textRecord = text->currentRecord; if ( textRecord == NULL || textRecord->string != NULL ) textRecord = SWFText_addTextRecord(text); textRecord->flags |= SWF_TEXT_HAS_FONT; /* XXX */ textRecord->isBrowserFont = (BLOCK(font)->type == SWF_DEFINEEDITTEXT); if ( textRecord->isBrowserFont ) SWF_error("cannot use browser font for SWFText"); // textRecord->font.browserFont = (SWFBrowserFont)font; else textRecord->font.font = (SWFFont)font; }
void SWFShape_setRightFillStyle(SWFShape shape, SWFFillStyle fill) { ShapeRecord record; if ( shape->isEnded || shape->isMorph ) return; record = addStyleRecord(shape); if ( fill != NOFILL ) { if ( SWFFill_getIdx(fill) > *shape->nFills ) SWF_error("Invalid fill idx"); record.record.stateChange->rightFill = SWFFill_getIdx(fill); } else record.record.stateChange->rightFill = 0; record.record.stateChange->flags |= SWF_SHAPE_FILLSTYLE1FLAG; }
/* * Assigns a name to a SWFBlock object. * Creates an exportlibrary with named symbols to be imported by other * SWF movies. * Call SWFMovie_writeExports() when you're done with the exports * to actually write the tag. If you don't the tag will be added * at the END of the SWF. * see also SWFMovie_importCharacter, SWFMovie_importFont */ void SWFMovie_addExport(SWFMovie movie, SWFBlock block, const char *name) { switch( SWFBlock_getType(block)) { case SWF_DEFINESHAPE: case SWF_DEFINESHAPE2: case SWF_DEFINESHAPE3: /*SWF_warn("Exporting a shape character is not ensured to work");*/ case SWF_DEFINESPRITE: case SWF_DEFINEFONT2: movie->exports = (struct SWFExport_s*)realloc(movie->exports, (movie->nExports+1) * sizeof(struct SWFExport_s)); movie->exports[movie->nExports].block = block; movie->exports[movie->nExports].name = strdup(name); ++movie->nExports; break; default: SWF_error("Exporting a character of type %d is not supported", SWFBlock_getType(block)); break; } }
SWFDBLBitmapData newSWFDBLBitmapData_fromGifInput(SWFInput input) { SWF_error("newSWFDBLBitmapData_fromGifInput can't be used (no gif compiled into this build of Ming).\n"); return 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; }
void SWFShape_writeShapeRecord(SWFShape shape, ShapeRecord record, SWFOutput out) { switch(record.type) { case SHAPERECORD_STATECHANGE: { int flags = record.record.stateChange->flags; if(flags == 0) return; SWFOutput_writeBits(out, flags, 6); if(flags & SWF_SHAPE_MOVETOFLAG) { int x = record.record.stateChange->moveToX; int y = record.record.stateChange->moveToY; int nBits = max(SWFOutput_numSBits(x), SWFOutput_numSBits(y)); SWF_assert(nBits<32); SWFOutput_writeBits(out, nBits, 5); SWFOutput_writeSBits(out, x, nBits); SWFOutput_writeSBits(out, y, nBits); } if(flags & SWF_SHAPE_FILLSTYLE0FLAG) { SWFOutput_writeBits(out, record.record.stateChange->leftFill, SWFOutput_numBits(shape->nFills)); } if(flags & SWF_SHAPE_FILLSTYLE1FLAG) { SWFOutput_writeBits(out, record.record.stateChange->rightFill, SWFOutput_numBits(shape->nFills)); } if(flags & SWF_SHAPE_LINESTYLEFLAG) { SWFOutput_writeBits(out, record.record.stateChange->line, SWFOutput_numBits(shape->nLines)); } /* newstyle's never used. But this is what it looks like: if ( flags & SWF_SHAPE_NEWSTYLEFLAG ) { SWFOutput_writeFillStyles(shape->out, shape->fills, shape->nFills, BLOCK(shape)->type); SWFOutput_writeLineStyles(shape->out, shape->lines, shape->nLines, BLOCK(shape)->type); SWFOutput_writeBits(shape->out, SWFOutput_numBits(shape->nFills), 4); SWFOutput_writeBits(shape->out, SWFOutput_numBits(shape->nLines), 4); } */ break; } case SHAPERECORD_LINETO: { int nBits; int dx = record.record.lineTo->dx; int dy = record.record.lineTo->dy; SWFOutput_writeBits(out, 3, 2); /* straight edge */ if(dx==0) { nBits = SWFOutput_numSBits(dy); SWF_assert(nBits<18); SWFOutput_writeBits(out, nBits-2, 4); SWFOutput_writeBits(out, 1, 2); /* vertical line */ SWFOutput_writeSBits(out, dy, nBits); } else if(dy==0) { nBits = SWFOutput_numSBits(dx); SWF_assert(nBits<18); SWFOutput_writeBits(out, nBits-2, 4); SWFOutput_writeBits(out, 0, 2); /* horizontal line */ SWFOutput_writeSBits(out, dx, nBits); } else { nBits = max(SWFOutput_numSBits(dx), SWFOutput_numSBits(dy)); SWF_assert(nBits<18); SWFOutput_writeBits(out, nBits-2, 4); SWFOutput_writeBits(out, 1, 1); /* general line */ SWFOutput_writeSBits(out, dx, nBits); SWFOutput_writeSBits(out, dy, nBits); } break; } case SHAPERECORD_CURVETO: { int controlx = record.record.curveTo->controlx; int controly = record.record.curveTo->controly; int anchorx = record.record.curveTo->anchorx; int anchory = record.record.curveTo->anchory; int nBits = max(max(SWFOutput_numSBits(controlx), SWFOutput_numSBits(controly)), max(SWFOutput_numSBits(anchorx), SWFOutput_numSBits(anchory))); if ( nBits < 2 ) nBits = 2; SWF_assert(nBits < 18); SWFOutput_writeBits(out, 2, 2); /* curved edge */ SWFOutput_writeBits(out, nBits-2, 4); SWFOutput_writeSBits(out, controlx, nBits); SWFOutput_writeSBits(out, controly, nBits); SWFOutput_writeSBits(out, anchorx, nBits); SWFOutput_writeSBits(out, anchory, nBits); break; } default: SWF_error("Unknown shapeRecordType"); } }
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 SWFShape_drawScaledGlyph(SWFShape shape, SWFFont font, unsigned short c, int size) { byte *p = SWFFont_findGlyph(font, c); byte **f = &p; int moveBits, x=0, y=0; int straight, numBits; int numFillBits, numLineBits; /* moveTos in the record are absolute, but we want to draw from the current location. grr. */ int startX = shape->xpos; int startY = shape->ypos; int style; byteAlign(); if ( (numFillBits = readBitsP(f, 4)) != 1 ) /* fill bits */ SWF_error("SWFShape_drawGlyph: bad file format (was expecting fill bits = 1)"); if ( (numLineBits = readBitsP(f, 4)) > 1 ) /* line bits */ SWF_error("SWFShape_drawGlyph: bad file format (was expecting line bits = 0)"); /* now we get to parse the shape commands. Oh boy. the first one will be a non-edge block- grab the moveto loc */ readBitsP(f, 2); /* type 0, newstyles */ style = readBitsP(f, 3); if(readBitsP(f, 1)) { moveBits = readBitsP(f, 5); x = startX + readSBitsP(f, moveBits); y = startY + readSBitsP(f, moveBits); } else if(style == 0) /* no style, no move => space character */ return; SWFShape_moveScaledPenTo(shape, x*size/1024, y*size/1024); if ( style & 1 ) if ( readBitsP(f, numFillBits) != 0 ) /* fill0 = 0 */ SWF_error("SWFFont_getShape: bad file format (was expecting fill0 = 0)"); if ( style & 2 ) if ( readBitsP(f, numFillBits) != 1 ) /* fill1 = 1 */ SWF_error("SWFFont_getShape: bad file format (was expecting fill1 = 1)"); if ( style & 4 ) if ( readBitsP(f, numLineBits) != 0 ) /* line = 1 */ SWF_error("SWFFont_getShape: bad file format (was expecting line = 0)"); /* translate the glyph's shape records into drawing commands */ for ( ;; ) { if ( readBitsP(f, 1) == 0 ) { /* it's a moveTo or a shape end */ if ( readBitsP(f, 5) == 0 ) break; moveBits = readBitsP(f, 5); x = startX + readSBitsP(f, moveBits); y = startY + readSBitsP(f, moveBits); SWFShape_moveScaledPenTo(shape, x*size/1024, y*size/1024); continue; } straight = readBitsP(f, 1); numBits = readBitsP(f, 4)+2; if ( straight==1 ) { if ( readBitsP(f, 1) ) /* general line */ { x += readSBitsP(f, numBits); y += readSBitsP(f, numBits); } else { if ( readBitsP(f, 1) ) /* vert = 1 */ y += readSBitsP(f, numBits); else x += readSBitsP(f, numBits); } SWFShape_drawScaledLineTo(shape, x*size/1024, y*size/1024); } else { int controlX = readSBitsP(f, numBits); int controlY = readSBitsP(f, numBits); int anchorX = readSBitsP(f, numBits); int anchorY = readSBitsP(f, numBits); SWFShape_drawScaledCurveTo(shape, (x+controlX)*size/1024, (y+controlY)*size/1024, (x+controlX+anchorX)*size/1024, (y+controlY+anchorY)*size/1024); x += controlX + anchorX; y += controlY + anchorY; } } /* no idea where the pen was left */ SWFShape_moveScaledPenTo(shape, startX, startY); }
void SWFShape_writeShapeRecord(SWFShape shape, ShapeRecord record) { SWFOutput out = shape->out; switch(record.type) { case SHAPERECORD_STATECHANGE: { int flags = record.record.stateChange->flags; if(flags == 0) return; SWFOutput_writeBits(out, flags, 6); if(flags & SWF_SHAPE_MOVETOFLAG) { int x = record.record.stateChange->moveToX; int y = record.record.stateChange->moveToY; int nBits = max(SWFOutput_numSBits(x), SWFOutput_numSBits(y)); SWF_assert(nBits<32); SWFOutput_writeBits(out, nBits, 5); SWFOutput_writeSBits(out, x, nBits); SWFOutput_writeSBits(out, y, nBits); } if(flags & SWF_SHAPE_FILLSTYLE0FLAG) { SWFOutput_writeBits(out, record.record.stateChange->leftFill, SWFOutput_numBits(shape->nFills2)); } if(flags & SWF_SHAPE_FILLSTYLE1FLAG) { SWFOutput_writeBits(out, record.record.stateChange->rightFill, SWFOutput_numBits(shape->nFills2)); } if(flags & SWF_SHAPE_LINESTYLEFLAG) { SWFOutput_writeBits(out, record.record.stateChange->line, SWFOutput_numBits(shape->nLines2)); } /* newstyle's never used. But this is what it looks like: */ if ( flags & SWF_SHAPE_NEWSTYLEFLAG ) { int i; shape->lines = &record.record.stateChange->lines; shape->fills = &record.record.stateChange->fills; shape->nLines = &record.record.stateChange->nLines; shape->nFills = &record.record.stateChange->nFills; shape->nFills2 = *shape->nFills; shape->nLines2 = *shape->nLines; SWFOutput_writeFillStyles(shape->out, *shape->fills, *shape->nFills, BLOCK(shape)->type); SWFOutput_writeLineStyles(shape->out, *shape->lines, *shape->nLines, BLOCK(shape)->type); SWFOutput_writeBits(shape->out, SWFOutput_numBits(*shape->nFills), 4); SWFOutput_writeBits(shape->out, SWFOutput_numBits(*shape->nLines), 4); for ( i=0; i<*shape->nFills; ++i ) { SWFMatrix matrix = SWFFillStyle_getMatrix((*shape->fills)[i]); if ( matrix != NULL ) destroySWFMatrix(matrix); /* gradients and bitmaps are destroyed separately */ free((*shape->fills)[i]); } if ( *shape->fills != NULL ) free(*shape->fills); for ( i=0; i<*shape->nLines; ++i ) free((*shape->lines)[i]); if ( *shape->lines != NULL ) free(*shape->lines); } break; } case SHAPERECORD_LINETO: { int nBits; int dx = record.record.lineTo->dx; int dy = record.record.lineTo->dy; SWFOutput_writeBits(out, 3, 2); /* straight edge */ if(dx==0 && dy!=0) { nBits = SWFOutput_numSBits(dy); SWF_assert(nBits<18); SWFOutput_writeBits(out, nBits-2, 4); SWFOutput_writeBits(out, 1, 2); /* vertical line */ SWFOutput_writeSBits(out, dy, nBits); } else if(dy==0 && dx!=0) { nBits = SWFOutput_numSBits(dx); SWF_assert(nBits<18); SWFOutput_writeBits(out, nBits-2, 4); SWFOutput_writeBits(out, 0, 2); /* horizontal line */ SWFOutput_writeSBits(out, dx, nBits); } else { nBits = max(SWFOutput_numSBits(dx), SWFOutput_numSBits(dy)); nBits = max(nBits, 2); SWF_assert(nBits<18); SWFOutput_writeBits(out, nBits-2, 4); SWFOutput_writeBits(out, 1, 1); /* general line */ SWFOutput_writeSBits(out, dx, nBits); SWFOutput_writeSBits(out, dy, nBits); } break; } case SHAPERECORD_CURVETO: { int controlx = record.record.curveTo->controlx; int controly = record.record.curveTo->controly; int anchorx = record.record.curveTo->anchorx; int anchory = record.record.curveTo->anchory; int nBits = max(max(SWFOutput_numSBits(controlx), SWFOutput_numSBits(controly)), max(SWFOutput_numSBits(anchorx), SWFOutput_numSBits(anchory))); if ( nBits < 2 ) nBits = 2; SWF_assert(nBits < 18); SWFOutput_writeBits(out, 2, 2); /* curved edge */ SWFOutput_writeBits(out, nBits-2, 4); SWFOutput_writeSBits(out, controlx, nBits); SWFOutput_writeSBits(out, controly, nBits); SWFOutput_writeSBits(out, anchorx, nBits); SWFOutput_writeSBits(out, anchory, nBits); break; } default: SWF_error("Unknown shapeRecordType"); } }
SWFDBLBitmapData newSWFDBLBitmapData_fromGifFile(const char * fileName) { SWF_error("newSWFDBLBitmapData_fromGifFile can't be used (no gif compiled into this build of Ming).\n"); return NULL; }
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 ) { 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 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); }