00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020
00021
00022
00023 #include "swf.h"
00024
00025 #include "math.h"
00026
00027 #ifdef RCSID
00028 static char *rcsid = "$Id: shape.cc,v 1.2 2004/03/14 18:16:15 zecke Exp $";
00029 #endif
00030
00031 #define PRINT 0
00032
00033 #define ABS(v) ((v) < 0 ? -(v) : (v))
00034
00035 static void prepareStyles(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, FillStyleDef *f, long n);
00036
00037 static void clearStyles(GraphicDevice *gd, FillStyleDef *f, long n);
00038
00039 static void drawShape(GraphicDevice *gd, Matrix *matrix1, Cxform *cxform, Shape *shape,
00040 ShapeAction shapeAction, void *id,ScanLineFunc scan_line_func);
00041
00042
00043
00044 Shape::Shape(long id, int level) : Character(ShapeType, id)
00045 {
00046 defLevel = level;
00047
00048 defaultFillStyle.type = f_Solid;
00049 defaultFillStyle.color.red = 0;
00050 defaultFillStyle.color.green = 0;
00051 defaultFillStyle.color.blue = 0;
00052 defaultFillStyle.color.alpha = ALPHA_OPAQUE;
00053
00054 defaultLineStyle.width = 0;
00055
00056
00057 lastMat.a = 0;
00058 lastMat.d = 0;
00059 shape_size += sizeof(Shape);
00060 shape_nb ++;
00061
00062 file_ptr = NULL;
00063 getStyles = 0;
00064 getAlpha = 0;
00065 }
00066
00067 Shape::~Shape()
00068 {
00069 if (file_ptr) {
00070 free(file_ptr);
00071 }
00072 }
00073
00074 void
00075 Shape::setBoundingBox(Rect rect)
00076 {
00077 boundary = rect;
00078 }
00079
00080 void
00081 Shape::getBoundingBox(Rect *bb, DisplayListEntry *e)
00082 {
00083 *bb = boundary;
00084 }
00085
00086 int
00087 Shape::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform)
00088 {
00089
00090
00091
00092 if (cxform) {
00093 defaultFillStyle.color = cxform->getColor(gd->getForegroundColor());
00094 } else {
00095 defaultFillStyle.color = gd->getForegroundColor();
00096 }
00097 defaultFillStyle.color.pixel = gd->allocColor(defaultFillStyle.color);
00098
00099 drawShape(gd, matrix, cxform, this, ShapeDraw, NULL, 0);
00100 return 0;
00101 }
00102
00103 void
00104 Shape::getRegion(GraphicDevice *gd, Matrix *matrix, void *id, ScanLineFunc scan_line_func)
00105 {
00106 gd->setClipping(0);
00107 drawShape(gd,matrix,0,this,ShapeGetRegion,id,scan_line_func);
00108 gd->setClipping(1);
00109 }
00110
00111
00112
00113
00114
00115 static void newPath(ShapeParser *shape,
00116 long x, long y)
00117 {
00118 Path *p;
00119 long x1,y1;
00120
00121 p=&shape->curPath;
00122
00123 x1 = shape->matrix->getX(x, y);
00124 y1 = shape->matrix->getY(x, y);
00125
00126 p->lastX = x1;
00127 p->lastY = y1;
00128
00129 p->nb_edges = 0;
00130 p->nb_segments = 0;
00131 }
00132
00133
00134 static void addSegment1(ShapeParser *shape,
00135 long x, long y,
00136 FillStyleDef *f0,
00137 FillStyleDef *f1,
00138 LineStyleDef *l)
00139 {
00140 Path *p;
00141 p=&shape->curPath;
00142
00143 if (l) {
00144
00145 LineSegment *ls;
00146
00147 ls = new LineSegment;
00148 if (ls != NULL) {
00149 ls->l = l;
00150 ls->x1 = p->lastX;
00151 ls->y1 = p->lastY;
00152 ls->x2 = x;
00153 ls->y2 = y;
00154 ls->first = (p->nb_segments == 0);
00155 ls->next = NULL;
00156 if (shape->last_line == NULL) {
00157 shape->first_line = ls;
00158 } else {
00159 shape->last_line->next = ls;
00160 }
00161 shape->last_line = ls;
00162 }
00163 }
00164
00165
00166 if (!shape->reverse) {
00167 shape->gd->addSegment(p->lastX,p->lastY,x,y,f0,f1,l ? 0 : 1);
00168 } else {
00169 shape->gd->addSegment(p->lastX,p->lastY,x,y,f1,f0,l ? 0 : 1);
00170 }
00171
00172 p->lastX = x;
00173 p->lastY = y;
00174
00175 p->nb_segments++;
00176 }
00177
00178
00179 static void addLine(ShapeParser *shape, long x, long y,
00180 FillStyleDef *f0,
00181 FillStyleDef *f1,
00182 LineStyleDef *l)
00183 {
00184 long x1,y1;
00185 Path *p;
00186
00187 p=&shape->curPath;
00188
00189 x1 = shape->matrix->getX(x, y);
00190 y1 = shape->matrix->getY(x, y);
00191
00192 addSegment1(shape,x1,y1,f0,f1,l);
00193
00194 p->nb_edges++;
00195 }
00196
00197
00198
00199
00200 #define BFRAC_BITS 0
00201 #define BFRAC (1 << BFRAC_BITS)
00202
00203 static void
00204 bezierBuildPoints (ShapeParser *s,
00205 int subdivisions,
00206 long a1X, long a1Y,
00207 long cX, long cY,
00208 long a2X, long a2Y)
00209 {
00210 long c1X,c1Y;
00211 long c2X,c2Y;
00212 long X,Y;
00213 long xmin,ymin,xmax,ymax;
00214
00215 if (subdivisions != 0) {
00216
00217
00218
00219 if (a1X < cX) {
00220 xmin = a1X;
00221 xmax = cX;
00222 } else {
00223 xmin = cX;
00224 xmax = a1X;
00225 }
00226 if (a2X < xmin) xmin = a2X;
00227 if (a2X > xmax) xmax = a2X;
00228
00229 if (a1Y < cY) {
00230 ymin = a1Y;
00231 ymax = cY;
00232 } else {
00233 ymin = cY;
00234 ymax = a1Y;
00235 }
00236 if (a2Y < ymin) ymin = a2Y;
00237 if (a2Y > ymax) ymax = a2Y;
00238
00239 if (((xmax - xmin) + (ymax - ymin)) >= (BFRAC*FRAC*2)) {
00240
00241 c1X = (a1X+cX) >> 1;
00242 c1Y = (a1Y+cY) >> 1;
00243
00244
00245 c2X = (a2X+cX) >> 1;
00246 c2Y = (a2Y+cY) >> 1;
00247
00248
00249 X = (c1X+c2X) >> 1;
00250 Y = (c1Y+c2Y) >> 1;
00251
00252 subdivisions--;
00253
00254 bezierBuildPoints(s, subdivisions,
00255 a1X, a1Y, c1X, c1Y, X, Y);
00256 bezierBuildPoints(s, subdivisions,
00257 X, Y, c2X, c2Y, a2X, a2Y);
00258
00259 return;
00260 }
00261 }
00262
00263 addSegment1(s, (a2X+(BFRAC/2)) >> BFRAC_BITS,
00264 (a2Y+(BFRAC/2)) >> BFRAC_BITS, s->f0, s->f1, s->l);
00265 }
00266
00267
00268 static void flushPaths(ShapeParser *s)
00269 {
00270 LineSegment *ls;
00271 LineStyleDef *l;
00272 long nx,ny,nn,w;
00273 GraphicDevice *gd = s->gd;
00274
00275
00276 gd->drawPolygon();
00277
00278
00279 ls = s->first_line;
00280 if (ls != NULL) {
00281 do {
00282 l = ls->l;
00283
00284 #if 0
00285 printf("line %d %d %d %d width=%d\n",
00286 ls->x1, ls->y1, ls->x2, ls->y2, l->width);
00287 #endif
00288
00289
00290
00291 w = ABS((long)(s->matrix->a * l->width));
00292
00293 if (w <= ((3*FRAC)/2)) {
00294 w = FRAC;
00295 }
00296 #ifdef THIN_LINES
00297 if (w <= ((3*FRAC)/2)) {
00298
00299 if (gd->scan_line_func == NULL) {
00300 gd->setForegroundColor(l->fillstyle.color);
00301 gd->drawLine(ls->x1, ls->y1, ls->x2, ls->y2, w);
00302 }
00303 } else {
00304 #else
00305 {
00306 #endif
00307
00308
00309 nx = -(ls->y2 - ls->y1);
00310 ny = (ls->x2 - ls->x1);
00311
00312
00313 nn = 2 * (long) sqrt(nx * nx + ny * ny);
00314
00315 #define UL ls->x1 + nx -ny, ls->y1 + ny +nx
00316 #define UR ls->x2 + nx +ny, ls->y2 + ny -nx
00317 #define LL ls->x1 - nx -ny, ls->y1 - ny +nx
00318 #define LR ls->x2 - nx +ny, ls->y2 - ny -nx
00319
00320 if (nn > 0) {
00321 nx = (nx * w) / nn;
00322 ny = (ny * w) / nn;
00323
00324
00325 gd->addSegment(UL, UR, NULL, &l->fillstyle, 1);
00326
00327
00328 gd->addSegment(LL, LR, &l->fillstyle, NULL, 1);
00329
00330
00331 gd->addSegment(UR, LR, &l->fillstyle, NULL, 1);
00332
00333
00334 gd->addSegment(UL, LL, NULL, &l->fillstyle, 1);
00335
00336
00337 gd->drawPolygon();
00338 }
00339 }
00340
00341 ls = ls->next;
00342 } while (ls != NULL);
00343
00344
00345
00346 ls = s->first_line;
00347 while (ls != NULL) {
00348 LineSegment *ls1;
00349 ls1 = ls->next;
00350 delete ls;
00351 ls = ls1;
00352 }
00353
00354
00355 s->first_line = NULL;
00356 s->last_line = NULL;
00357 }
00358 }
00359
00360
00361 static void addBezier(ShapeParser *shape,
00362 long ctrlX1, long ctrlY1,
00363 long newX1, long newY1,
00364 FillStyleDef *f0,
00365 FillStyleDef *f1,
00366 LineStyleDef *l)
00367 {
00368 long newX,newY,ctrlX,ctrlY;
00369 Path *p;
00370
00371 p=&shape->curPath;
00372
00373
00374
00375
00376 ctrlX = shape->matrix->getX(ctrlX1, ctrlY1);
00377 ctrlY = shape->matrix->getY(ctrlX1, ctrlY1);
00378 newX = shape->matrix->getX(newX1, newY1);
00379 newY = shape->matrix->getY(newX1, newY1);
00380
00381 shape->f0 = f0;
00382 shape->f1 = f1;
00383 shape->l = l;
00384
00385 bezierBuildPoints(shape, 3,
00386 p->lastX<<BFRAC_BITS,p->lastY<<BFRAC_BITS,
00387 ctrlX<<BFRAC_BITS,ctrlY<<BFRAC_BITS,
00388 newX<<BFRAC_BITS,newY<<BFRAC_BITS);
00389
00390 p->nb_edges++;
00391 }
00392
00393
00394
00395
00396
00397
00398 static void InitBitParser(struct BitParser *b,U8 *buf)
00399 {
00400 b->ptr = buf;
00401 }
00402
00403 static void InitBits(struct BitParser *b)
00404 {
00405
00406 b->m_bitPos = 0;
00407 b->m_bitBuf = 0;
00408 }
00409
00410
00411
00412 static inline U8 GetByte(struct BitParser *b)
00413 {
00414 U8 v;
00415 v = *b->ptr++;
00416 return v;
00417 }
00418
00419 static inline U16 GetWord(struct BitParser *b)
00420 {
00421 U8 *s;
00422 U16 v;
00423 s = b->ptr;
00424 v = s[0] | ((U16) s[1] << 8);
00425 b->ptr = s + 2;
00426 return v;
00427 }
00428
00429 static inline U32 GetDWord(struct BitParser *b)
00430 {
00431 U32 v;
00432 U8 * s = b->ptr;
00433 v = (U32) s[0] | ((U32) s[1] << 8) |
00434 ((U32) s[2] << 16) | ((U32) s [3] << 24);
00435 b->ptr = s + 4;
00436 return v;
00437 }
00438
00439 static inline U32 GetBit (struct BitParser *b)
00440 {
00441 U32 v;
00442 S32 m_bitPos = b->m_bitPos;
00443 U32 m_bitBuf = b->m_bitBuf;
00444
00445 if (m_bitPos == 0) {
00446 m_bitBuf = (U32)(*b->ptr++) << 24;
00447 m_bitPos = 8;
00448 }
00449
00450 v = (m_bitBuf >> 31);
00451
00452 m_bitPos--;
00453 m_bitBuf <<= 1;
00454
00455 b->m_bitPos = m_bitPos;
00456 b->m_bitBuf = m_bitBuf;
00457
00458 return v;
00459 }
00460
00461 static inline U32 GetBits (struct BitParser *b, int n)
00462 {
00463 U32 v;
00464 S32 m_bitPos = b->m_bitPos;
00465 U32 m_bitBuf = b->m_bitBuf;
00466
00467 if (n == 0)
00468 return 0;
00469
00470 while (m_bitPos < n) {
00471 m_bitBuf |= (U32)(*b->ptr++) << (24 - m_bitPos);
00472 m_bitPos += 8;
00473 }
00474
00475 v = m_bitBuf >> (32 - n);
00476 m_bitBuf <<= n;
00477 m_bitPos -= n;
00478
00479 b->m_bitPos = m_bitPos;
00480 b->m_bitBuf = m_bitBuf;
00481 return v;
00482 }
00483
00484
00485 static inline S32 GetSBits (struct BitParser *b,S32 n)
00486 {
00487
00488 S32 v = (S32) GetBits(b,n);
00489
00490
00491 if (v & (1L << (n - 1)))
00492 {
00493
00494 v |= -1L << n;
00495 }
00496
00497 return v;
00498 }
00499
00500
00501
00502
00503
00504 static void GetMatrix(BitParser *b, Matrix* mat)
00505 {
00506 InitBits(b);
00507
00508
00509 if (GetBit(b))
00510 {
00511 int nBits = (int) GetBits(b,5);
00512 mat->a = (float)(GetSBits(b,nBits))/(float)0x10000;
00513 mat->d = (float)(GetSBits(b,nBits))/(float)0x10000;
00514 }
00515 else
00516 {
00517 mat->a = mat->d = 1.0;
00518 }
00519
00520
00521 if (GetBit(b))
00522 {
00523 int nBits = (int)GetBits(b,5);
00524 mat->c = (float)(GetSBits(b,nBits))/(float)0x10000;
00525 mat->b = (float)(GetSBits(b,nBits))/(float)0x10000;
00526 }
00527 else
00528 {
00529 mat->b = mat->c = 0.0;
00530 }
00531
00532
00533 int nBits = (int) GetBits(b,5);
00534 mat->tx = GetSBits(b,nBits);
00535 mat->ty = GetSBits(b,nBits);
00536 }
00537
00538 static FillStyleDef * ParseFillStyle(ShapeParser *shape, long *n, long getAlpha)
00539 {
00540 BitParser *b = &shape->bit_parser;
00541 FillStyleDef *defs;
00542 U16 i = 0;
00543
00544
00545 U16 nFills = GetByte(b);
00546
00547
00548 if (nFills == 255)
00549 {
00550
00551 nFills = GetWord(b);
00552 }
00553
00554 *n = nFills;
00555 defs = new FillStyleDef[ nFills ];
00556 if (defs == NULL) return NULL;
00557
00558
00559 for (i = 0; i < nFills; i++)
00560 {
00561 U16 fillStyle = GetByte(b);
00562
00563 defs[i].type = (FillType) fillStyle;
00564
00565 if (fillStyle & 0x10)
00566 {
00567 defs[i].type = (FillType) (fillStyle & 0x12);
00568
00569
00570 GetMatrix(b,&(defs[i].matrix));
00571
00572
00573 defs[i].gradient.nbGradients = GetByte(b);
00574
00575
00576 for (U16 j = 0; j < defs[i].gradient.nbGradients; j++)
00577 {
00578 defs[i].gradient.ratio[j] = GetByte(b);
00579 defs[i].gradient.color[j].red = GetByte(b);
00580 defs[i].gradient.color[j].green = GetByte(b);
00581 defs[i].gradient.color[j].blue = GetByte(b);
00582 if (getAlpha) {
00583 defs[i].gradient.color[j].alpha = GetByte(b);
00584 } else {
00585 defs[i].gradient.color[j].alpha = ALPHA_OPAQUE;
00586 }
00587 }
00588 }
00589 else if (fillStyle & 0x40)
00590 {
00591 defs[i].type = (FillType) (fillStyle & 0x41);
00592
00593
00594 defs[i].bitmap = (Bitmap *)shape->dict->getCharacter(GetWord(b));
00595
00596 GetMatrix(b,&(defs[i].matrix));
00597 }
00598 else
00599 {
00600 defs[i].type = (FillType) 0;
00601
00602
00603 defs[i].color.red = GetByte(b);
00604 defs[i].color.green = GetByte(b);
00605 defs[i].color.blue = GetByte(b);
00606 if (getAlpha) {
00607 defs[i].color.alpha = GetByte(b);
00608 } else {
00609 defs[i].color.alpha = ALPHA_OPAQUE;
00610 }
00611 }
00612 }
00613
00614 return defs;
00615 }
00616
00617 static LineStyleDef * ParseLineStyle(ShapeParser *shape, long *n, long getAlpha)
00618 {
00619 BitParser *b = &shape->bit_parser;
00620 LineStyleDef *defs,*def;
00621 FillStyleDef *f;
00622 long i;
00623
00624
00625 U16 nLines = GetByte(b);
00626
00627
00628 if (nLines == 255)
00629 {
00630
00631 nLines = GetWord(b);
00632 }
00633
00634 *n = nLines;
00635 defs = new LineStyleDef[ nLines ];
00636 if (defs == NULL) return NULL;
00637
00638
00639 for (i = 0; i < nLines; i++)
00640 {
00641 def=&defs[i];
00642 def->width = GetWord(b);
00643 def->color.red = GetByte(b);
00644 def->color.green = GetByte(b);
00645 def->color.blue = GetByte(b);
00646 if (getAlpha) {
00647 def->color.alpha = GetByte(b);
00648 } else {
00649 def->color.alpha = ALPHA_OPAQUE;
00650 }
00651
00652 f=&def->fillstyle;
00653 f->type = f_Solid;
00654 f->color = def->color;
00655 if (shape->cxform) {
00656 f->color = shape->cxform->getColor(f->color);
00657 }
00658 f->color.pixel = shape->gd->allocColor(f->color);
00659 }
00660
00661 return defs;
00662 }
00663
00664
00665 static int ParseShapeRecord(ShapeParser *shape, ShapeRecord *sr, long getAlpha)
00666 {
00667 BitParser *b = &shape->bit_parser;
00668
00669
00670 BOOL isEdge = (BOOL) GetBit(b);
00671
00672 if (!isEdge)
00673 {
00674
00675 U16 flags = (U16) GetBits(b,5);
00676
00677
00678 if (flags == 0)
00679 {
00680
00681 return 0;
00682 }
00683
00684 sr->type = shapeNonEdge;
00685 sr->flags = (ShapeFlags)flags;
00686
00687
00688 if (flags & flagsMoveTo)
00689 {
00690 U16 nBits = (U16) GetBits(b,5);
00691 sr->x = GetSBits(b,nBits);
00692 sr->y = GetSBits(b,nBits);
00693 }
00694
00695
00696 if (flags & flagsFill0)
00697 {
00698 sr->fillStyle0 = GetBits(b,shape->m_nFillBits);
00699 }
00700 if (flags & flagsFill1)
00701 {
00702 sr->fillStyle1 = GetBits(b,shape->m_nFillBits);
00703 }
00704
00705
00706 if (flags & flagsLine)
00707 {
00708 sr->lineStyle = GetBits(b,shape->m_nLineBits);
00709 }
00710
00711
00712 if (flags & flagsNewStyles)
00713 {
00714 FillStyleDef *fillDefs;
00715 LineStyleDef *lineDefs;
00716 long n;
00717
00718
00719 fillDefs = ParseFillStyle(shape, &n, getAlpha);
00720 if (fillDefs == NULL) return 0;
00721
00722 sr->newFillStyles = fillDefs;
00723 sr->nbNewFillStyles = n;
00724
00725 lineDefs = ParseLineStyle(shape, &n, getAlpha);
00726 if (lineDefs == NULL) return 0;
00727
00728 sr->newLineStyles = lineDefs;
00729 sr->nbNewLineStyles = n;
00730
00731 InitBits(b);
00732
00733
00734 shape->m_nFillBits = (U16) GetBits(b,4);
00735 shape->m_nLineBits = (U16) GetBits(b,4);
00736 }
00737
00738
00739
00740
00741 return flags & flagsEndShape ? 0 : 1;
00742 }
00743 else
00744 {
00745 if (GetBit(b))
00746 {
00747 sr->type = shapeLine;
00748
00749
00750 U16 nBits = (U16) GetBits(b,4) + 2;
00751
00752
00753 if (GetBit(b))
00754 {
00755
00756 sr->dX = GetSBits(b,nBits);
00757 sr->dY = GetSBits(b,nBits);
00758 }
00759 else
00760 {
00761
00762 if (GetBit(b))
00763 {
00764
00765 sr->dY = GetSBits(b,nBits);
00766 sr->dX = 0;
00767 }
00768 else
00769 {
00770
00771 sr->dX = GetSBits(b,nBits);
00772 sr->dY = 0;
00773 }
00774 }
00775 }
00776 else
00777 {
00778 sr->type = shapeCurve;
00779
00780
00781 U16 nBits = (U16) GetBits(b,4) + 2;
00782
00783
00784 sr->ctrlX = GetSBits(b,nBits);
00785 sr->ctrlY = GetSBits(b,nBits);
00786
00787
00788 sr->anchorX = GetSBits(b,nBits);
00789 sr->anchorY = GetSBits(b,nBits);
00790 }
00791
00792 return 1;
00793 }
00794 }
00795
00796 static void drawShape(GraphicDevice *gd, Matrix *matrix1, Cxform *cxform, Shape *shape,
00797 ShapeAction shapeAction, void *id,ScanLineFunc scan_line_func)
00798 {
00799 LineStyleDef *l;
00800 FillStyleDef *f0;
00801 FillStyleDef *f1;
00802 ShapeRecord sr1,*sr = &sr1;
00803 int firstPoint;
00804 long lastX,lastY;
00805 LineStyleDef *curLineStyle;
00806 long curNbLineStyles;
00807 FillStyleDef *curFillStyle;
00808 long curNbFillStyles;
00809 StyleList *sl;
00810 ShapeParser sp1,*sp=&sp1;
00811 BitParser *b;
00812 Matrix mat,*matrix;
00813
00814 mat = (*gd->adjust) * (*matrix1);
00815 matrix = &mat;
00816
00817 sp->reverse = (mat.a * mat.d) < 0;
00818
00819 curLineStyle = NULL;
00820 curNbLineStyles = 0;
00821 curFillStyle = NULL;
00822 curNbFillStyles = 0;
00823 sp->style_list = NULL;
00824
00825 sp->shape = shape;
00826 sp->gd = gd;
00827 sp->matrix = matrix;
00828 sp->cxform = cxform;
00829 sp->dict = shape->dict;
00830
00831 if (shapeAction == ShapeGetRegion) {
00832 gd->scan_line_func = scan_line_func;
00833 gd->scan_line_func_id = id;
00834 } else {
00835 gd->scan_line_func = NULL;
00836 }
00837
00838 b = &sp->bit_parser;
00839 InitBitParser(b,shape->file_ptr);
00840
00841 if (shape->getStyles) {
00842
00843 curFillStyle = ParseFillStyle(sp, &curNbFillStyles, shape->getAlpha);
00844 if (curFillStyle == NULL) return;
00845
00846 curLineStyle = ParseLineStyle(sp, &curNbLineStyles, shape->getAlpha);
00847 if (curLineStyle == NULL) return;
00848
00849 sl = new StyleList;
00850 if (sl == NULL) return;
00851
00852 sl->next = NULL;
00853 sl->newFillStyles = curFillStyle;
00854 sl->nbNewFillStyles = curNbFillStyles;
00855 sl->newLineStyles = curLineStyle;
00856 sl->nbNewLineStyles = curNbLineStyles;
00857
00858 sp->style_list = sl;
00859
00860 if (shapeAction == ShapeDraw) {
00861 prepareStyles(gd, matrix, cxform, curFillStyle, curNbFillStyles);
00862 }
00863 }
00864
00865 InitBits(b);
00866 sp->m_nFillBits = (U16) GetBits(b,4);
00867 sp->m_nLineBits = (U16) GetBits(b,4);
00868
00869 l = 0;
00870 f0 = 0;
00871 f1 = 0;
00872 firstPoint = 1;
00873 lastX = 0;
00874 lastY = 0;
00875 sp->curPath.nb_edges = 0;
00876 sp->first_line = NULL;
00877 sp->last_line = NULL;
00878
00879 for(;;) {
00880 if (ParseShapeRecord(sp, sr, shape->getAlpha) == 0) break;
00881
00882 switch (sr->type)
00883 {
00884 case shapeNonEdge:
00885 if (sr->flags & flagsNewStyles) {
00886
00887 curFillStyle = sr->newFillStyles;
00888 curNbFillStyles = sr->nbNewFillStyles;
00889 curLineStyle = sr->newLineStyles;
00890 curNbLineStyles = sr->nbNewLineStyles;
00891
00892 sl = new StyleList;
00893 sl->next = sp->style_list;
00894 sl->newFillStyles = sr->newFillStyles;
00895 sl->nbNewFillStyles = sr->nbNewFillStyles;
00896 sl->newLineStyles = sr->newLineStyles;
00897 sl->nbNewLineStyles = sr->nbNewLineStyles;
00898
00899 sp->style_list = sl;
00900
00901 if (shapeAction == ShapeDraw) {
00902 prepareStyles(gd, matrix, cxform, curFillStyle, curNbFillStyles);
00903 }
00904 }
00905 if (sr->flags & flagsFill0) {
00906 if (sr->fillStyle0) {
00907 if (curFillStyle) {
00908 f0 = &curFillStyle[sr->fillStyle0-1];
00909 } else {
00910 f0 = &shape->defaultFillStyle;
00911 }
00912 } else {
00913 f0 = 0;
00914 }
00915 }
00916 if (sr->flags & flagsFill1) {
00917 if (sr->fillStyle1) {
00918 if (curFillStyle) {
00919 f1 = &curFillStyle[sr->fillStyle1-1];
00920 } else {
00921 f1 = &shape->defaultFillStyle;
00922 }
00923 } else {
00924 f1 = 0;
00925 }
00926 }
00927 if (sr->flags & flagsLine) {
00928 if (sr->lineStyle) {
00929 l = &curLineStyle[sr->lineStyle-1];
00930 } else {
00931 l = 0;
00932 }
00933 }
00934 if (sr->flags & flagsMoveTo) {
00935 if (sp->curPath.nb_edges == 0) {
00936
00937 flushPaths(sp);
00938 }
00939
00940 newPath(sp, sr->x, sr->y);
00941 firstPoint = 0;
00942
00943 lastX = sr->x;
00944 lastY = sr->y;
00945
00946 #if PRINT
00947 printf("---------\nX,Y = %4d,%4d\n", sr->x/20, sr->y/20);
00948 #endif
00949 }
00950 break;
00951 case shapeCurve:
00952
00953 if (firstPoint) {
00954 newPath(sp, 0, 0);
00955 firstPoint = 0;
00956 }
00957 {
00958 long newX,newY,ctrlX,ctrlY;
00959
00960 ctrlX = lastX+sr->ctrlX;
00961 ctrlY = lastY+sr->ctrlY;
00962 newX = ctrlX+sr->anchorX;
00963 newY = ctrlY+sr->anchorY;
00964
00965 #if 1
00966 addBezier(sp, ctrlX, ctrlY, newX, newY, f0 , f1, l);
00967 #else
00968 addLine(sp, newX, newY, f0, f1, l);
00969 #endif
00970
00971 lastX = newX;
00972 lastY = newY;
00973 }
00974 break;
00975 case shapeLine:
00976 if (firstPoint) {
00977 newPath(sp, 0, 0);
00978 firstPoint = 0;
00979 }
00980
00981 lastX += sr->dX;
00982 lastY += sr->dY;
00983
00984 addLine(sp, lastX, lastY, f0, f1, l);
00985 #if PRINT
00986 printf(" X, Y = %4d,%4d\n", lastX/20, lastY/20);
00987 #endif
00988 break;
00989 }
00990 }
00991
00992
00993 flushPaths(sp);
00994
00995
00996 while (sp->style_list) {
00997 StyleList *sl;
00998
00999 sl=sp->style_list;
01000 sp->style_list = sl->next;
01001
01002 if (shapeAction == ShapeDraw) {
01003 clearStyles(gd, sl->newFillStyles, sl->nbNewFillStyles);
01004 }
01005
01006 delete[] sl->newFillStyles;
01007 delete[] sl->newLineStyles;
01008
01009 delete sl;
01010 }
01011 }
01012
01013 static void
01014 prepareStyles(GraphicDevice *gd, Matrix *matrix, Cxform *cxform,
01015 FillStyleDef *ftab, long n)
01016 {
01017 long fs;
01018 FillStyleDef *f;
01019
01020 for(fs = 0; fs < n; fs++)
01021 {
01022 f = ftab + fs;
01023 switch (f->type)
01024 {
01025 case f_None:
01026 break;
01027 case f_Solid:
01028 if (cxform) {
01029 f->color = cxform->getColor(f->color);
01030 }
01031 f->color.pixel = gd->allocColor(f->color);
01032 break;
01033 case f_LinearGradient:
01034 case f_RadialGradient:
01035 {
01036 Matrix mat;
01037 int n,r,l;
01038 long red, green, blue, alpha;
01039 long dRed, dGreen, dBlue, dAlpha;
01040 long min,max;
01041 Matrix *m;
01042
01043 mat = *(matrix) * f->matrix;
01044
01045 f->gradient.imat = mat.invert();
01046
01047
01048 m=&f->gradient.imat;
01049 if (f->type == f_LinearGradient) {
01050 m->a = m->a * FRAC * (1/128.0) * 65536.0;
01051 m->b = m->b * FRAC * (1/128.0) * 65536.0;
01052 m->tx = (long) ((m->tx + 16384) * (1/128.0) * 65536.0);
01053 } else {
01054 m->a = m->a * FRAC * (1/64.0) * 65536.0;
01055 m->b = m->b * FRAC * (1/64.0) * 65536.0;
01056 m->c = m->c * FRAC * (1/64.0) * 65536.0;
01057 m->d = m->d * FRAC * (1/64.0) * 65536.0;
01058 m->tx = (long) (m->tx * (1/64.0) * 65536.0);
01059 m->ty = (long) (m->ty * (1/64.0) * 65536.0);
01060 }
01061
01062
01063 f->gradient.has_alpha = 0;
01064
01065
01066 f->gradient.ramp = new Color[256];
01067 if (f->gradient.ramp == NULL) {
01068
01069 f->type = f_None;
01070 continue;
01071 }
01072
01073
01074 min = f->gradient.ratio[0];
01075 max = f->gradient.ratio[f->gradient.nbGradients-1];
01076 for(r=0; r < f->gradient.nbGradients-1; r++)
01077 {
01078 Color start,end;
01079
01080 l = f->gradient.ratio[r+1]-f->gradient.ratio[r];
01081 if (l == 0) continue;
01082
01083 if (cxform) {
01084 start = cxform->getColor(f->gradient.color[r]);
01085 end = cxform->getColor(f->gradient.color[r+1]);
01086 } else {
01087 start = f->gradient.color[r];
01088 end = f->gradient.color[r+1];
01089 }
01090
01091 if (start.alpha != ALPHA_OPAQUE ||
01092 end.alpha != ALPHA_OPAQUE) {
01093 f->gradient.has_alpha = 1;
01094 }
01095
01096 dRed = end.red - start.red;
01097 dGreen = end.green - start.green;
01098 dBlue = end.blue - start.blue;
01099 dAlpha = end.alpha - start.alpha;
01100
01101 dRed = (dRed<<16)/l;
01102 dGreen = (dGreen<<16)/l;
01103 dBlue = (dBlue<<16)/l;
01104 dAlpha = (dAlpha<<16)/l;
01105
01106 red = start.red <<16;
01107 green = start.green <<16;
01108 blue = start.blue <<16;
01109 alpha = start.alpha <<16;
01110
01111 for (n=f->gradient.ratio[r]; n<=f->gradient.ratio[r+1]; n++) {
01112 f->gradient.ramp[n].red = red>>16;
01113 f->gradient.ramp[n].green = green>>16;
01114 f->gradient.ramp[n].blue = blue>>16;
01115 f->gradient.ramp[n].alpha = alpha>>16;
01116
01117 f->gradient.ramp[n].pixel = gd->allocColor(f->gradient.ramp[n]);
01118 red += dRed;
01119 green += dGreen;
01120 blue += dBlue;
01121 alpha += dAlpha;
01122 }
01123 }
01124 for(n=0; n<min; n++) {
01125 f->gradient.ramp[n] = f->gradient.ramp[min];
01126 }
01127 for(n=max; n<256; n++) {
01128 f->gradient.ramp[n] = f->gradient.ramp[max];
01129 }
01130 }
01131 break;
01132 case f_TiledBitmap:
01133 case f_clippedBitmap:
01134 if (f->bitmap) {
01135 Matrix *m;
01136
01137 f->cmap = gd->getColormap(f->bitmap->colormap,
01138 f->bitmap->nbColors, cxform);
01139 if (f->cmap == NULL) {
01140
01141 f->cmap = f->bitmap->colormap;
01142 }
01143
01144 f->bitmap_matrix = *(matrix) * f->matrix;
01145
01146 f->bitmap_matrix = f->bitmap_matrix.invert();
01147
01148 m=&f->bitmap_matrix;
01149 m->a = m->a * FRAC * 65536.0;
01150 m->b = m->b * FRAC * 65536.0;
01151 m->c = m->c * FRAC * 65536.0;
01152 m->d = m->d * FRAC * 65536.0;
01153 m->tx = (long) (m->tx * 65536.0);
01154 m->ty = (long) (m->ty * 65536.0);
01155
01156 f->alpha_table = NULL;
01157
01158 if (f->bitmap->alpha_buf && cxform) {
01159 unsigned char *alpha_table;
01160 int i;
01161
01162 alpha_table = (unsigned char *)malloc (256);
01163 if (alpha_table != NULL) {
01164 for(i=0;i<256;i++) {
01165 alpha_table[i] = cxform->getAlpha(i);
01166 }
01167 }
01168 f->alpha_table = alpha_table;
01169 }
01170 }
01171 break;
01172 }
01173 }
01174 }
01175
01176 static void
01177 clearStyles(GraphicDevice *gd, FillStyleDef *ftab, long n)
01178 {
01179 long fs;
01180 FillStyleDef *f;
01181
01182 for(fs = 0; fs < n; fs++)
01183 {
01184 f = ftab + fs;
01185 switch (f->type)
01186 {
01187 case f_Solid:
01188 break;
01189 case f_LinearGradient:
01190 case f_RadialGradient:
01191 if (f->gradient.ramp) {
01192 delete f->gradient.ramp;
01193 }
01194 break;
01195 case f_TiledBitmap:
01196 case f_clippedBitmap:
01197 if (f->bitmap) {
01198 if (f->cmap && f->cmap != f->bitmap->colormap) delete f->cmap;
01199 if (f->alpha_table) free(f->alpha_table);
01200 }
01201 break;
01202 case f_None:
01203 break;
01204 }
01205 }
01206 }
01207