📄 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.55 2008/09/12 09:13:36 krechert Exp $ */#include <stdlib.h>#include <stdio.h> #include <stdarg.h>#include "shape.h"#include "character.h"#include "matrix.h"#include "fillstyle.h"#include "linestyle.h"#include "font.h"#include "libming.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; int useVersion; // SWF_DEFINESHAPE4 extensions unsigned char flags; SWFRect edgeBounds;#if TRACK_ALLOCS /* memory node for garbage collection */ mem_node *gcnode;#endif};static voidSWFShape_writeShapeRecord(SWFShape shape, ShapeRecord record, SWFOutput out);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; if(shape->fills != NULL) { // Fills have to be destroyed by users. /* for ( i=0; i<shape->nFills; ++i ) destroySWFFillStyle(shape->fills[i]); */ free(shape->fills); } if(shape->records != NULL) { for(i = 0; i < shape->nRecords; i++) { free(shape->records[i].record.stateChange); } free(shape->records); } if(shape->edgeBounds != NULL) free(shape->edgeBounds); for ( i=0; i<shape->nLines; ++i ) free(shape->lines[i]); if ( shape->lines != NULL ) free(shape->lines); destroySWFOutput(shape->out);#if TRACK_ALLOCS ming_gc_remove_node(shape->gcnode);#endif destroySWFCharacter((SWFCharacter) shape);}SWFShape newSWFGlyphShape(){ 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 = NULL; BLOCK(shape)->complete = NULL; BLOCK(shape)->dtor = NULL; BLOCK(shape)->type = SWF_UNUSEDBLOCK; 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 = 0; SWFOutput_writeUInt8(shape->out, 0); /* space for nFillBits, nLineBits */#if TRACK_ALLOCS shape->gcnode = ming_gc_add_node(shape, (dtorfunctype) destroySWFShape);#endif return shape;}SWFShapenewSWFShape(){ 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 shape filled with bitmap */SWFShapenewSWFShapeFromBitmap(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;}voidSWFOutput_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);}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], shape->out); } 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 ) { if(shape->useVersion == SWF_SHAPE4) BLOCK(shape)->type = SWF_DEFINESHAPE4; 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))); 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;}/* ShapeRecords are an intermediate storage so that we don't have to specify fill/line types in advance.*/#define SHAPERECORD_INCREMENT 32/* 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -