📄 shape.cc
字号:
/////////////////////////////////////////////////////////////// Flash Plugin and Player// Copyright (C) 1998,1999 Olivier Debon// // This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; either version 2// of the License, or (at your option) any later version.// // This program 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 General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// ///////////////////////////////////////////////////////////////// Author : Olivier Debon <odebon@club-internet.fr>//#include "swf.h"#include <math.h>#ifdef RCSIDstatic char *rcsid = "$Id: shape.cc,v 1.1 2003/09/08 19:41:59 jasonk Exp $";#endif#define PRINT 0#define ABS(v) ((v) < 0 ? -(v) : (v))static void prepareStyles(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, FillStyleDef *f, long n);static void clearStyles(GraphicDevice *gd, FillStyleDef *f, long n);static void drawShape(GraphicDevice *gd, Matrix *matrix1, Cxform *cxform, Shape *shape, ShapeAction shapeAction, void *id,ScanLineFunc scan_line_func);// ConstructorShape::Shape(long id, int level) : Character(ShapeType, id){ defLevel = level; defaultFillStyle.type = f_Solid; defaultFillStyle.color.red = 0; defaultFillStyle.color.green = 0; defaultFillStyle.color.blue = 0; defaultFillStyle.color.alpha = ALPHA_OPAQUE; defaultLineStyle.width = 0; // This is to force a first update lastMat.a = 0; lastMat.d = 0; shape_size += sizeof(Shape); shape_nb ++; file_ptr = NULL; getStyles = 0; getAlpha = 0;}Shape::~Shape(){ if (file_ptr) { free(file_ptr); }}voidShape::setBoundingBox(Rect rect){ boundary = rect;}voidShape::getBoundingBox(Rect *bb, DisplayListEntry *e){ *bb = boundary;}intShape::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform){ //printf("TagId = %d\n", getTagId()); //if (getTagId() != 220) return 0; if (cxform) { defaultFillStyle.color = cxform->getColor(gd->getForegroundColor()); } else { defaultFillStyle.color = gd->getForegroundColor(); } defaultFillStyle.color.pixel = gd->allocColor(defaultFillStyle.color); drawShape(gd, matrix, cxform, this, ShapeDraw, NULL, 0); return 0;}voidShape::getRegion(GraphicDevice *gd, Matrix *matrix, void *id, ScanLineFunc scan_line_func){ gd->setClipping(0); drawShape(gd,matrix,0,this,ShapeGetRegion,id,scan_line_func); gd->setClipping(1);}/************************************************************************//* create a new path */static void newPath(ShapeParser *shape, long x, long y){ Path *p; long x1,y1; p=&shape->curPath; x1 = shape->matrix->getX(x, y); y1 = shape->matrix->getY(x, y); p->lastX = x1; p->lastY = y1; p->nb_edges = 0; p->nb_segments = 0;}static void addSegment1(ShapeParser *shape, long x, long y, FillStyleDef *f0, FillStyleDef *f1, LineStyleDef *l){ Path *p; p=&shape->curPath; if (l) { /* a line is defined ... it will be drawn later */ LineSegment *ls; ls = new LineSegment; if (ls != NULL) { ls->l = l; ls->x1 = p->lastX; ls->y1 = p->lastY; ls->x2 = x; ls->y2 = y; ls->first = (p->nb_segments == 0); ls->next = NULL; if (shape->last_line == NULL) { shape->first_line = ls; } else { shape->last_line->next = ls; } shape->last_line = ls; } } /* anti antialiasing not needed if line */ if (!shape->reverse) { shape->gd->addSegment(p->lastX,p->lastY,x,y,f0,f1,l ? 0 : 1); } else { shape->gd->addSegment(p->lastX,p->lastY,x,y,f1,f0,l ? 0 : 1); } p->lastX = x; p->lastY = y; p->nb_segments++;}static void addLine(ShapeParser *shape, long x, long y, FillStyleDef *f0, FillStyleDef *f1, LineStyleDef *l){ long x1,y1; Path *p; p=&shape->curPath; x1 = shape->matrix->getX(x, y); y1 = shape->matrix->getY(x, y); addSegment1(shape,x1,y1,f0,f1,l); p->nb_edges++;}// This is based on Divide and Conquer algorithm.#define BFRAC_BITS 0#define BFRAC (1 << BFRAC_BITS)static voidbezierBuildPoints (ShapeParser *s, int subdivisions, long a1X, long a1Y, long cX, long cY, long a2X, long a2Y){ long c1X,c1Y; long c2X,c2Y; long X,Y; long xmin,ymin,xmax,ymax; if (subdivisions != 0) { /* find the bounding box */ if (a1X < cX) { xmin = a1X; xmax = cX; } else { xmin = cX; xmax = a1X; } if (a2X < xmin) xmin = a2X; if (a2X > xmax) xmax = a2X; if (a1Y < cY) { ymin = a1Y; ymax = cY; } else { ymin = cY; ymax = a1Y; } if (a2Y < ymin) ymin = a2Y; if (a2Y > ymax) ymax = a2Y; if (((xmax - xmin) + (ymax - ymin)) >= (BFRAC*FRAC*2)) { // Control point 1 c1X = (a1X+cX) >> 1; c1Y = (a1Y+cY) >> 1; // Control point 2 c2X = (a2X+cX) >> 1; c2Y = (a2Y+cY) >> 1; // New point X = (c1X+c2X) >> 1; Y = (c1Y+c2Y) >> 1; subdivisions--; bezierBuildPoints(s, subdivisions, a1X, a1Y, c1X, c1Y, X, Y); bezierBuildPoints(s, subdivisions, X, Y, c2X, c2Y, a2X, a2Y); return; } } addSegment1(s, (a2X+(BFRAC/2)) >> BFRAC_BITS, (a2Y+(BFRAC/2)) >> BFRAC_BITS, s->f0, s->f1, s->l);}/* this code is broken, but useful to get something */static void flushPaths(ShapeParser *s){ LineSegment *ls; LineStyleDef *l; long nx,ny,nn,w; GraphicDevice *gd = s->gd; /* draw the filled polygon */ gd->drawPolygon(); /* draw the lines */ ls = s->first_line; if (ls != NULL) { do { l = ls->l;#if 0 printf("line %d %d %d %d width=%d\n", ls->x1, ls->y1, ls->x2, ls->y2, l->width);#endif /* XXX: this width is false, but it is difficult (and expensive) to have the correct one */ w = ABS((long)(s->matrix->a * l->width)); if (w <= ((3*FRAC)/2)) { w = FRAC; }#ifdef THIN_LINES if (w <= ((3*FRAC)/2)) { // draw the thin lines only in shapeAction == shapeDraw if (gd->scan_line_func == NULL) { gd->setForegroundColor(l->fillstyle.color); gd->drawLine(ls->x1, ls->y1, ls->x2, ls->y2, w); } } else {#else {#endif /* compute the normal vector */ nx = -(ls->y2 - ls->y1); ny = (ls->x2 - ls->x1); /* normalize & width */ nn = 2 * (long) sqrt(nx * nx + ny * ny); #define UL ls->x1 + nx -ny, ls->y1 + ny +nx#define UR ls->x2 + nx +ny, ls->y2 + ny -nx#define LL ls->x1 - nx -ny, ls->y1 - ny +nx#define LR ls->x2 - nx +ny, ls->y2 - ny -nx if (nn > 0) { nx = (nx * w) / nn; ny = (ny * w) / nn; /* top segment */ gd->addSegment(UL, UR, NULL, &l->fillstyle, 1); /* bottom segment */ gd->addSegment(LL, LR, &l->fillstyle, NULL, 1); /* right segment */ gd->addSegment(UR, LR, &l->fillstyle, NULL, 1); /* left segment */ gd->addSegment(UL, LL, NULL, &l->fillstyle, 1); /* draw the line polygon */ gd->drawPolygon(); } } ls = ls->next; } while (ls != NULL); /* delete the line structures */ ls = s->first_line; while (ls != NULL) { LineSegment *ls1; ls1 = ls->next; delete ls; ls = ls1; } /* reset the line pointers */ s->first_line = NULL; s->last_line = NULL; }}static void addBezier(ShapeParser *shape, long ctrlX1, long ctrlY1, long newX1, long newY1, FillStyleDef *f0, FillStyleDef *f1, LineStyleDef *l){ long newX,newY,ctrlX,ctrlY; Path *p; p=&shape->curPath; /* note: we do the matrix multiplication before calculating the bezier points (faster !) */ ctrlX = shape->matrix->getX(ctrlX1, ctrlY1); ctrlY = shape->matrix->getY(ctrlX1, ctrlY1); newX = shape->matrix->getX(newX1, newY1); newY = shape->matrix->getY(newX1, newY1); shape->f0 = f0; shape->f1 = f1; shape->l = l; bezierBuildPoints(shape, 3, p->lastX<<BFRAC_BITS,p->lastY<<BFRAC_BITS, ctrlX<<BFRAC_BITS,ctrlY<<BFRAC_BITS, newX<<BFRAC_BITS,newY<<BFRAC_BITS); p->nb_edges++;}/***********************************************************************//* bit parser */static void InitBitParser(struct BitParser *b,U8 *buf) { b->ptr = buf;}static void InitBits(struct BitParser *b){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -