Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

shape.cc

Go to the documentation of this file.
00001 
00002 // Flash Plugin and Player
00003 // Copyright (C) 1998,1999 Olivier Debon
00004 // 
00005 // This program is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU General Public License
00007 // as published by the Free Software Foundation; either version 2
00008 // of the License, or (at your option) any later version.
00009 // 
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 // 
00020 //  Author : Olivier Debon  <odebon@club-internet.fr>
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 // Constructor
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     // This is to force a first update
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     //printf("TagId = %d\n", getTagId());
00090     //if (getTagId() != 220) return 0;
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 /* create a new path */
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         /* a line is defined ... it will be drawn later */
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     /* anti antialiasing not needed if line */
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 // This is based on Divide and Conquer algorithm.
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         /* find the bounding box */
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             // Control point 1
00241             c1X = (a1X+cX) >> 1;
00242             c1Y = (a1Y+cY) >> 1;
00243             
00244             // Control point 2
00245             c2X = (a2X+cX) >> 1;
00246             c2Y = (a2Y+cY) >> 1;
00247             
00248             // New point
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 /* this code is broken, but useful to get something */
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     /* draw the filled polygon */
00276     gd->drawPolygon();
00277     
00278     /* draw the lines */
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             /* XXX: this width is false, but it is difficult (and expensive)
00290                to have the correct one */
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                 // draw the thin lines only in shapeAction == shapeDraw
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                 /* compute the normal vector */
00308                 
00309                 nx = -(ls->y2 - ls->y1);
00310                 ny = (ls->x2 - ls->x1);
00311                 
00312                 /* normalize & width */
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                     /* top segment */
00325                     gd->addSegment(UL, UR, NULL, &l->fillstyle, 1);
00326                     
00327                     /* bottom segment */
00328                     gd->addSegment(LL, LR, &l->fillstyle, NULL, 1);
00329                 
00330                     /* right segment */
00331                     gd->addSegment(UR, LR, &l->fillstyle, NULL, 1);
00332                 
00333                     /* left segment */
00334                     gd->addSegment(UL, LL, NULL, &l->fillstyle, 1);
00335                 
00336                     /* draw the line polygon */
00337                     gd->drawPolygon();
00338                 }
00339             }
00340                 
00341             ls = ls->next;
00342         } while (ls != NULL);
00343         
00344         /* delete the line structures */
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         /* reset the line pointers */
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     /* note: we do the matrix multiplication before calculating the
00374        bezier points (faster !) */
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 /* bit parser */
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     // Reset the bit position and buffer.
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 // Get n bits from the string with sign extension.
00485 static inline S32 GetSBits (struct BitParser *b,S32 n)
00486 {
00487     // Get the number as an unsigned value.
00488     S32 v = (S32) GetBits(b,n);
00489 
00490     // Is the number negative?
00491     if (v & (1L << (n - 1)))
00492     {
00493         // Yes. Extend the sign.
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     // Scale terms
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     // Rotate/skew terms
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     // Translate terms
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         // Get the number of fills.
00545         U16 nFills = GetByte(b);
00546 
00547         // Do we have a larger number?
00548         if (nFills == 255)
00549         {
00550                 // Get the larger number.
00551                 nFills = GetWord(b);
00552         }
00553 
00554         *n = nFills;
00555         defs = new FillStyleDef[ nFills ];
00556         if (defs == NULL) return NULL;
00557 
00558         // Get each of the fill style.
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                         // Get the gradient matrix.
00570                         GetMatrix(b,&(defs[i].matrix));
00571 
00572                         // Get the number of colors.
00573                         defs[i].gradient.nbGradients = GetByte(b);
00574 
00575                         // Get each of the colors.
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                         // Get the bitmapId
00594                         defs[i].bitmap = (Bitmap *)shape->dict->getCharacter(GetWord(b));
00595                         // Get the bitmap matrix.
00596                         GetMatrix(b,&(defs[i].matrix));
00597                 }
00598                 else
00599                 {
00600                         defs[i].type = (FillType) 0;
00601 
00602                         // A solid color
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         // Get the number of lines.
00625         U16 nLines = GetByte(b);
00626 
00627         // Do we have a larger number?
00628         if (nLines == 255)
00629         {
00630                 // Get the larger number.
00631                 nLines = GetWord(b);
00632         }
00633 
00634         *n = nLines;
00635         defs = new LineStyleDef[ nLines ];
00636         if (defs == NULL) return NULL;
00637 
00638         // Get each of the line styles.
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 /* 0 = end of shape */
00665 static int ParseShapeRecord(ShapeParser *shape, ShapeRecord *sr, long getAlpha)
00666 {
00667     BitParser *b = &shape->bit_parser;
00668 
00669         // Determine if this is an edge.
00670         BOOL isEdge = (BOOL) GetBit(b);
00671 
00672         if (!isEdge)
00673         {
00674                 // Handle a state change
00675                 U16 flags = (U16) GetBits(b,5);
00676 
00677                 // Are we at the end?
00678                 if (flags == 0)
00679                 {
00680                         // End of shape
00681                         return 0;
00682                 }
00683 
00684                 sr->type = shapeNonEdge;
00685                 sr->flags = (ShapeFlags)flags;
00686 
00687                 // Process a move to.
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                 // Get new fill info.
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                 // Get new line info
00706                 if (flags & flagsLine)
00707                 {
00708                         sr->lineStyle = GetBits(b,shape->m_nLineBits);
00709                 }
00710 
00711                 // Check to get a new set of styles for a new shape layer.
00712                 if (flags & flagsNewStyles)
00713                 {
00714                         FillStyleDef *fillDefs;
00715                         LineStyleDef *lineDefs;
00716                         long n;
00717 
00718                         // Parse the style.
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);    // Bug !
00732 
00733                         // Reset.
00734                         shape->m_nFillBits = (U16) GetBits(b,4);
00735                         shape->m_nLineBits = (U16) GetBits(b,4);
00736                 }
00737 
00738                 //if (flags & flagsEndShape)
00739                         //printf("\tEnd of shape.\n\n");
00740   
00741                 return flags & flagsEndShape ? 0 : 1;
00742         }
00743         else
00744         {
00745                 if (GetBit(b))
00746                 {
00747                         sr->type = shapeLine;
00748 
00749                         // Handle a line
00750                         U16 nBits = (U16) GetBits(b,4) + 2;     // nBits is biased by 2
00751 
00752                         // Save the deltas
00753                         if (GetBit(b))
00754                         {
00755                                 // Handle a general line.
00756                                 sr->dX = GetSBits(b,nBits);
00757                                 sr->dY = GetSBits(b,nBits);
00758                         }
00759                         else
00760                         {
00761                                 // Handle a vert or horiz line.
00762                                 if (GetBit(b))
00763                                 {
00764                                         // Vertical line
00765                                         sr->dY = GetSBits(b,nBits);
00766                                         sr->dX = 0;
00767                                 }
00768                                 else
00769                                 {
00770                                         // Horizontal line
00771                                         sr->dX = GetSBits(b,nBits);
00772                                         sr->dY = 0;
00773                                 }
00774                         }
00775                 }
00776                 else
00777                 {
00778                         sr->type = shapeCurve;
00779 
00780                         // Handle a curve
00781                         U16 nBits = (U16) GetBits(b,4) + 2;     // nBits is biased by 2
00782 
00783                         // Get the control
00784                         sr->ctrlX = GetSBits(b,nBits);
00785                         sr->ctrlY = GetSBits(b,nBits);
00786 
00787                         // Get the anchor
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         // ShapeWithStyle
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                         /* if no edges, draw the polygon, then the lines */
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                 // Handle Bezier Curves !!!
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     /* XXX: should test if there is something to draw */
00993     flushPaths(sp);
00994 
00995     /* free the styles */
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                     // Compute inverted matrix
01045                     f->gradient.imat = mat.invert();
01046 
01047                     /* renormalize the matrix */
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                     // Reset translation in inverted matrix
01063                     f->gradient.has_alpha = 0;
01064 
01065                     // Build a 256 color ramp
01066                     f->gradient.ramp = new Color[256];
01067                     if (f->gradient.ramp == NULL) {
01068                         // Invalidate fill style
01069                         f->type = f_None;
01070                         continue;
01071                     }
01072 
01073                     // Store min and max
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                         /* Get the normal cmap anyway */
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 

Generated on Sat Nov 5 16:15:36 2005 for OPIE by  doxygen 1.4.2