void SWFShape_drawScaledLine(SWFShape shape, int dx, int dy) { ShapeRecord record; if ( shape->isEnded ) return; if ( dx == 0 && dy == 0 ) return; record = newShapeRecord(shape, SHAPERECORD_LINETO); SWF_assert(SWFOutput_numSBits(dx) < 18); SWF_assert(SWFOutput_numSBits(dy) < 18); record.record.lineTo->dx = dx; record.record.lineTo->dy = dy; shape->xpos += dx; shape->ypos += dy; SWFRect_includePoint(SWFCharacter_getBounds(CHARACTER(shape)), shape->xpos, shape->ypos, shape->lineWidth); SWFRect_includePoint(shape->edgeBounds, shape->xpos, shape->ypos, 0); }
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_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; }
/* copy shaperecord from other shape */ static ShapeRecord addShapeRecord(SWFShape shape, ShapeRecord record, int *vx, int *vy, float scale) { if ( shape->nRecords % SHAPERECORD_INCREMENT == 0 ) { shape->records = (ShapeRecord*) realloc(shape->records, sizeof(ShapeRecord) * (shape->nRecords + SHAPERECORD_INCREMENT)); } switch ( record.type ) { case SHAPERECORD_STATECHANGE: { StateChangeRecord change = (StateChangeRecord) calloc(1,sizeof(struct stateChangeRecord)); *change = *record.record.stateChange; shape->records[shape->nRecords].record.stateChange = change; change->moveToX += shape->xpos; change->moveToY += shape->ypos; change->moveToX *= scale; change->moveToY *= scale; *vx = change->moveToX; *vy = change->moveToY; break; } case SHAPERECORD_LINETO: { LineToRecord lineTo = (LineToRecord) calloc(1,sizeof(struct lineToRecord)); *lineTo = *record.record.lineTo; lineTo->dx *= scale; lineTo->dy *= scale; shape->records[shape->nRecords].record.lineTo = lineTo; *vx += lineTo->dx; *vy += lineTo->dy; SWFRect_includePoint(SWFCharacter_getBounds(CHARACTER(shape)), *vx, *vy, shape->lineWidth); SWFRect_includePoint(shape->edgeBounds, *vx, *vy, 0); break; } case SHAPERECORD_CURVETO: { CurveToRecord curveTo = (CurveToRecord) calloc(1,sizeof(struct curveToRecord)); *curveTo = *record.record.curveTo; curveTo->controlx *= scale; curveTo->controly *= scale; curveTo->anchorx *= scale; curveTo->anchory *= scale; shape->records[shape->nRecords].record.curveTo = curveTo; *vx += curveTo->controlx; *vy += curveTo->controly; SWFRect_includePoint(SWFCharacter_getBounds(CHARACTER(shape)), *vx, *vy, shape->lineWidth); SWFRect_includePoint(shape->edgeBounds, *vx, *vy, 0); *vx += curveTo->anchorx; *vy += curveTo->anchory; SWFRect_includePoint(SWFCharacter_getBounds(CHARACTER(shape)), *vx, *vy, shape->lineWidth); SWFRect_includePoint(shape->edgeBounds, *vx, *vy, 0); break; } } shape->records[shape->nRecords].type = record.type; shape->nRecords++; return shape->records[shape->nRecords-1]; }
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; }