📄 shape.c
字号:
/* Ming, an SWF output library Copyright (C) 2002 Opaque Industries - http://www.opaque.net/ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*//* $Id: shape.c,v 1.20 2003/11/08 18:30:21 whamann Exp $ */#include <stdlib.h>#include "shape.h"#include "character.h"#include "matrix.h"#include "fillstyle.h"#include "linestyle.h"#include "font.h"struct stateChangeRecord{ int flags; int moveToX; int moveToY; int leftFill; int rightFill; int line; /* newstyle not used.. */};typedef struct stateChangeRecord *StateChangeRecord;struct lineToRecord{ int dx; int dy;};typedef struct lineToRecord *LineToRecord;struct curveToRecord{ int controlx; int controly; int anchorx; int anchory;};typedef struct curveToRecord *CurveToRecord;typedef enum{ SHAPERECORD_STATECHANGE, SHAPERECORD_LINETO, SHAPERECORD_CURVETO} shapeRecordType;struct shapeRecord{ shapeRecordType type; union { StateChangeRecord stateChange; LineToRecord lineTo; CurveToRecord curveTo; } record;};typedef struct shapeRecord ShapeRecord;struct SWFShape_s{ struct SWFCharacter_s character; ShapeRecord *records; int nRecords; SWFOutput out; int xpos; /* cursor for using abs. coords in lineTo, curveTo */ int ypos; SWFLineStyle *lines; SWFFillStyle *fills; byte nLines; byte nFills; short lineWidth; BOOL isMorph; BOOL isEnded;};static voidSWFShape_writeShapeRecord(SWFShape shape, ShapeRecord record);static voidwriteSWFShapeBlockToMethod(SWFBlock block, SWFByteOutputMethod method, void* data){ SWFOutput out = ((SWFShape)block)->out; SWFOutput_writeToMethod(out, method, data);}static intcompleteSWFShapeBlock(SWFBlock block){ SWFShape shape = (SWFShape)block; SWFShape_end(shape); return SWFOutput_getLength(shape->out);}voiddestroySWFShape(SWFShape shape){ int i; 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); destroySWFOutput(shape->out); destroySWFCharacter((SWFCharacter) shape);}SWFShapenewSWFShape(){ SWFShape shape = (SWFShape)malloc(sizeof(struct SWFShape_s)); 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->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; SWFOutput_writeUInt8(shape->out, 0); /* space for nFillBits, nLineBits */ return shape;}SWFShapenewSWFShapeFromBitmap(SWFBitmap bitmap){ SWFShape shape = newSWFShape(); SWFFillStyle fill = SWFShape_addBitmapFillStyle(shape, bitmap, SWFFILL_TILED_BITMAP); int width = SWFBitmap_getWidth(bitmap); int 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;}voidSWFShape_end(SWFShape shape){ int i; byte* buffer; if ( shape->isEnded ) return; shape->isEnded = TRUE; buffer = SWFOutput_getBuffer(shape->out); buffer[0] = (SWFOutput_numBits(shape->nFills) << 4) + SWFOutput_numBits(shape->nLines); 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;}SWFOutputSWFShape_getOutput(SWFShape shape){ return shape->out;}voidSWFShape_getFills(SWFShape shape, SWFFillStyle** fills, int* nFills){ *fills = shape->fills; *nFills = shape->nFills;}voidSWFShape_getLines(SWFShape shape, SWFLineStyle** lines, int* nLines){ *lines = shape->lines; *nLines = shape->nLines;}voidSWFShape_setMorphFlag(SWFShape shape){ shape->isMorph = TRUE;}voidSWFShape_addStyleHeader(SWFShape shape){ SWFOutput out = newSWFOutput(); SWFOutput_writeUInt16(out, CHARACTERID(shape)); SWFOutput_writeRect(out, SWFCharacter_getBounds(CHARACTER(shape))); SWFOutput_writeFillStyles(out, shape->fills, shape->nFills, BLOCK(shape)->type); SWFOutput_writeLineStyles(out, shape->lines, shape->nLines, BLOCK(shape)->type); /* prepend shape->out w/ shape header */ SWFOutput_setNext(out, shape->out); shape->out = out;}/* ShapeRecords are an intermediate storage so that we don't have to specify fill/line types in advance.*/#define SHAPERECORD_INCREMENT 32static ShapeRecordnewShapeRecord(SWFShape shape, shapeRecordType type){ if ( shape->nRecords % SHAPERECORD_INCREMENT == 0 ) { shape->records = (ShapeRecord*) realloc(shape->records, sizeof(ShapeRecord) * (shape->nRecords + SHAPERECORD_INCREMENT)); } switch ( type ) { case SHAPERECORD_STATECHANGE: { StateChangeRecord change = (StateChangeRecord)calloc(1,sizeof(struct stateChangeRecord)); shape->records[shape->nRecords].record.stateChange = change; break; } case SHAPERECORD_LINETO: { LineToRecord lineTo = (LineToRecord) calloc(1,sizeof(struct lineToRecord)); shape->records[shape->nRecords].record.lineTo = lineTo; break; } case SHAPERECORD_CURVETO: { CurveToRecord curveTo = (CurveToRecord) calloc(1,sizeof(struct curveToRecord)); shape->records[shape->nRecords].record.curveTo = curveTo; break; } } shape->records[shape->nRecords].type = type; return shape->records[shape->nRecords++];}voidSWFShape_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->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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -