summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libflash/shape.cc
Unidiff
Diffstat (limited to 'core/multimedia/opieplayer/libflash/shape.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libflash/shape.cc1205
1 files changed, 1205 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libflash/shape.cc b/core/multimedia/opieplayer/libflash/shape.cc
new file mode 100644
index 0000000..0d8df93
--- a/dev/null
+++ b/core/multimedia/opieplayer/libflash/shape.cc
@@ -0,0 +1,1205 @@
1/////////////////////////////////////////////////////////////
2// Flash Plugin and Player
3// Copyright (C) 1998,1999 Olivier Debon
4//
5// This program is free software; you can redistribute it and/or
6// modify it under the terms of the GNU General Public License
7// as published by the Free Software Foundation; either version 2
8// of the License, or (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18//
19///////////////////////////////////////////////////////////////
20// Author : Olivier Debon <odebon@club-internet.fr>
21//
22
23#include "swf.h"
24
25#ifdef RCSID
26static char *rcsid = "$Id$";
27#endif
28
29#define PRINT 0
30
31#define ABS(v) ((v) < 0 ? -(v) : (v))
32
33static void prepareStyles(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, FillStyleDef *f, long n);
34
35static void clearStyles(GraphicDevice *gd, FillStyleDef *f, long n);
36
37static void drawShape(GraphicDevice *gd, Matrix *matrix1, Cxform *cxform, Shape *shape,
38 ShapeAction shapeAction, void *id,ScanLineFunc scan_line_func);
39
40// Constructor
41
42Shape::Shape(long id, int level) : Character(ShapeType, id)
43{
44 defLevel = level;
45
46 defaultFillStyle.type = f_Solid;
47 defaultFillStyle.color.red = 0;
48 defaultFillStyle.color.green = 0;
49 defaultFillStyle.color.blue = 0;
50 defaultFillStyle.color.alpha = ALPHA_OPAQUE;
51
52 defaultLineStyle.width = 0;
53
54 // This is to force a first update
55 lastMat.a = 0;
56 lastMat.d = 0;
57 shape_size += sizeof(Shape);
58 shape_nb ++;
59
60 file_ptr = NULL;
61 getStyles = 0;
62 getAlpha = 0;
63}
64
65Shape::~Shape()
66{
67 if (file_ptr) {
68 free(file_ptr);
69 }
70}
71
72void
73Shape::setBoundingBox(Rect rect)
74{
75 boundary = rect;
76}
77
78void
79Shape::getBoundingBox(Rect *bb, DisplayListEntry *e)
80{
81 *bb = boundary;
82}
83
84int
85Shape::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform)
86{
87 //printf("TagId = %d\n", getTagId());
88 //if (getTagId() != 220) return 0;
89
90 if (cxform) {
91 defaultFillStyle.color = cxform->getColor(gd->getForegroundColor());
92 } else {
93 defaultFillStyle.color = gd->getForegroundColor();
94 }
95 defaultFillStyle.color.pixel = gd->allocColor(defaultFillStyle.color);
96
97 drawShape(gd, matrix, cxform, this, ShapeDraw, NULL, 0);
98 return 0;
99}
100
101void
102Shape::getRegion(GraphicDevice *gd, Matrix *matrix, void *id, ScanLineFunc scan_line_func)
103{
104 gd->setClipping(0);
105 drawShape(gd,matrix,0,this,ShapeGetRegion,id,scan_line_func);
106 gd->setClipping(1);
107}
108
109/************************************************************************/
110
111/* create a new path */
112
113static void newPath(ShapeParser *shape,
114 long x, long y)
115{
116 Path *p;
117 long x1,y1;
118
119 p=&shape->curPath;
120
121 x1 = shape->matrix->getX(x, y);
122 y1 = shape->matrix->getY(x, y);
123
124 p->lastX = x1;
125 p->lastY = y1;
126
127 p->nb_edges = 0;
128 p->nb_segments = 0;
129}
130
131
132static void addSegment1(ShapeParser *shape,
133 long x, long y,
134 FillStyleDef *f0,
135 FillStyleDef *f1,
136 LineStyleDef *l)
137{
138 Path *p;
139 p=&shape->curPath;
140
141 if (l) {
142 /* a line is defined ... it will be drawn later */
143 LineSegment *ls;
144
145 ls = new LineSegment;
146 if (ls != NULL) {
147 ls->l = l;
148 ls->x1 = p->lastX;
149 ls->y1 = p->lastY;
150 ls->x2 = x;
151 ls->y2 = y;
152 ls->first = (p->nb_segments == 0);
153 ls->next = NULL;
154 if (shape->last_line == NULL) {
155 shape->first_line = ls;
156 } else {
157 shape->last_line->next = ls;
158 }
159 shape->last_line = ls;
160 }
161 }
162
163 /* anti antialiasing not needed if line */
164 if (!shape->reverse) {
165 shape->gd->addSegment(p->lastX,p->lastY,x,y,f0,f1,l ? 0 : 1);
166 } else {
167 shape->gd->addSegment(p->lastX,p->lastY,x,y,f1,f0,l ? 0 : 1);
168 }
169
170 p->lastX = x;
171 p->lastY = y;
172
173 p->nb_segments++;
174}
175
176
177static void addLine(ShapeParser *shape, long x, long y,
178 FillStyleDef *f0,
179 FillStyleDef *f1,
180 LineStyleDef *l)
181{
182 long x1,y1;
183 Path *p;
184
185 p=&shape->curPath;
186
187 x1 = shape->matrix->getX(x, y);
188 y1 = shape->matrix->getY(x, y);
189
190 addSegment1(shape,x1,y1,f0,f1,l);
191
192 p->nb_edges++;
193}
194
195
196// This is based on Divide and Conquer algorithm.
197
198#define BFRAC_BITS 0
199#define BFRAC (1 << BFRAC_BITS)
200
201static void
202bezierBuildPoints (ShapeParser *s,
203 int subdivisions,
204 long a1X, long a1Y,
205 long cX, long cY,
206 long a2X, long a2Y)
207{
208 long c1X,c1Y;
209 long c2X,c2Y;
210 long X,Y;
211 long xmin,ymin,xmax,ymax;
212
213 if (subdivisions != 0) {
214
215 /* find the bounding box */
216
217 if (a1X < cX) {
218 xmin = a1X;
219 xmax = cX;
220 } else {
221 xmin = cX;
222 xmax = a1X;
223 }
224 if (a2X < xmin) xmin = a2X;
225 if (a2X > xmax) xmax = a2X;
226
227 if (a1Y < cY) {
228 ymin = a1Y;
229 ymax = cY;
230 } else {
231 ymin = cY;
232 ymax = a1Y;
233 }
234 if (a2Y < ymin) ymin = a2Y;
235 if (a2Y > ymax) ymax = a2Y;
236
237 if (((xmax - xmin) + (ymax - ymin)) >= (BFRAC*FRAC*2)) {
238 // Control point 1
239 c1X = (a1X+cX) >> 1;
240 c1Y = (a1Y+cY) >> 1;
241
242 // Control point 2
243 c2X = (a2X+cX) >> 1;
244 c2Y = (a2Y+cY) >> 1;
245
246 // New point
247 X = (c1X+c2X) >> 1;
248 Y = (c1Y+c2Y) >> 1;
249
250 subdivisions--;
251
252 bezierBuildPoints(s, subdivisions,
253 a1X, a1Y, c1X, c1Y, X, Y);
254 bezierBuildPoints(s, subdivisions,
255 X, Y, c2X, c2Y, a2X, a2Y);
256
257 return;
258 }
259 }
260
261 addSegment1(s, (a2X+(BFRAC/2)) >> BFRAC_BITS,
262 (a2Y+(BFRAC/2)) >> BFRAC_BITS, s->f0, s->f1, s->l);
263}
264
265/* this code is broken, but useful to get something */
266static void flushPaths(ShapeParser *s)
267{
268 LineSegment *ls;
269 LineStyleDef *l;
270 long nx,ny,nn,w;
271 GraphicDevice *gd = s->gd;
272
273 /* draw the filled polygon */
274 gd->drawPolygon();
275
276 /* draw the lines */
277 ls = s->first_line;
278 if (ls != NULL) {
279 do {
280 l = ls->l;
281
282#if 0
283 printf("line %d %d %d %d width=%d\n",
284 ls->x1, ls->y1, ls->x2, ls->y2, l->width);
285#endif
286
287 /* XXX: this width is false, but it is difficult (and expensive)
288 to have the correct one */
289 w = ABS((long)(s->matrix->a * l->width));
290
291 if (w <= ((3*FRAC)/2)) {
292 w = FRAC;
293 }
294#ifdef THIN_LINES
295 if (w <= ((3*FRAC)/2)) {
296 // draw the thin lines only in shapeAction == shapeDraw
297 if (gd->scan_line_func == NULL) {
298 gd->setForegroundColor(l->fillstyle.color);
299 gd->drawLine(ls->x1, ls->y1, ls->x2, ls->y2, w);
300 }
301 } else {
302#else
303 {
304#endif
305 /* compute the normal vector */
306
307 nx = -(ls->y2 - ls->y1);
308 ny = (ls->x2 - ls->x1);
309
310 /* normalize & width */
311 nn = 2 * (long) sqrt(nx * nx + ny * ny);
312
313#define UL ls->x1 + nx -ny, ls->y1 + ny +nx
314#define UR ls->x2 + nx +ny, ls->y2 + ny -nx
315#define LL ls->x1 - nx -ny, ls->y1 - ny +nx
316#define LR ls->x2 - nx +ny, ls->y2 - ny -nx
317
318 if (nn > 0) {
319 nx = (nx * w) / nn;
320 ny = (ny * w) / nn;
321
322 /* top segment */
323 gd->addSegment(UL, UR, NULL, &l->fillstyle, 1);
324
325 /* bottom segment */
326 gd->addSegment(LL, LR, &l->fillstyle, NULL, 1);
327
328 /* right segment */
329 gd->addSegment(UR, LR, &l->fillstyle, NULL, 1);
330
331 /* left segment */
332 gd->addSegment(UL, LL, NULL, &l->fillstyle, 1);
333
334 /* draw the line polygon */
335 gd->drawPolygon();
336 }
337 }
338
339 ls = ls->next;
340 } while (ls != NULL);
341
342 /* delete the line structures */
343
344 ls = s->first_line;
345 while (ls != NULL) {
346 LineSegment *ls1;
347 ls1 = ls->next;
348 delete ls;
349 ls = ls1;
350 }
351
352 /* reset the line pointers */
353 s->first_line = NULL;
354 s->last_line = NULL;
355 }
356}
357
358
359static void addBezier(ShapeParser *shape,
360 long ctrlX1, long ctrlY1,
361 long newX1, long newY1,
362 FillStyleDef *f0,
363 FillStyleDef *f1,
364 LineStyleDef *l)
365{
366 long newX,newY,ctrlX,ctrlY;
367 Path *p;
368
369 p=&shape->curPath;
370
371 /* note: we do the matrix multiplication before calculating the
372 bezier points (faster !) */
373
374 ctrlX = shape->matrix->getX(ctrlX1, ctrlY1);
375 ctrlY = shape->matrix->getY(ctrlX1, ctrlY1);
376 newX = shape->matrix->getX(newX1, newY1);
377 newY = shape->matrix->getY(newX1, newY1);
378
379 shape->f0 = f0;
380 shape->f1 = f1;
381 shape->l = l;
382
383 bezierBuildPoints(shape, 3,
384 p->lastX<<BFRAC_BITS,p->lastY<<BFRAC_BITS,
385 ctrlX<<BFRAC_BITS,ctrlY<<BFRAC_BITS,
386 newX<<BFRAC_BITS,newY<<BFRAC_BITS);
387
388 p->nb_edges++;
389}
390
391/***********************************************************************/
392
393
394/* bit parser */
395
396static void InitBitParser(struct BitParser *b,U8 *buf)
397{
398 b->ptr = buf;
399}
400
401static void InitBits(struct BitParser *b)
402{
403 // Reset the bit position and buffer.
404 b->m_bitPos = 0;
405 b->m_bitBuf = 0;
406}
407
408
409
410static inline U8 GetByte(struct BitParser *b)
411{
412 U8 v;
413 v = *b->ptr++;
414 return v;
415}
416
417static inline U16 GetWord(struct BitParser *b)
418{
419 U8 *s;
420 U16 v;
421 s = b->ptr;
422 v = s[0] | ((U16) s[1] << 8);
423 b->ptr = s + 2;
424 return v;
425}
426
427static inline U32 GetDWord(struct BitParser *b)
428{
429 U32 v;
430 U8 * s = b->ptr;
431 v = (U32) s[0] | ((U32) s[1] << 8) |
432 ((U32) s[2] << 16) | ((U32) s [3] << 24);
433 b->ptr = s + 4;
434 return v;
435}
436
437static inline U32 GetBit (struct BitParser *b)
438{
439 U32 v;
440 S32 m_bitPos = b->m_bitPos;
441 U32 m_bitBuf = b->m_bitBuf;
442
443 if (m_bitPos == 0) {
444 m_bitBuf = (U32)(*b->ptr++) << 24;
445 m_bitPos = 8;
446 }
447
448 v = (m_bitBuf >> 31);
449
450 m_bitPos--;
451 m_bitBuf <<= 1;
452
453 b->m_bitPos = m_bitPos;
454 b->m_bitBuf = m_bitBuf;
455
456 return v;
457}
458
459static inline U32 GetBits (struct BitParser *b, int n)
460{
461 U32 v;
462 S32 m_bitPos = b->m_bitPos;
463 U32 m_bitBuf = b->m_bitBuf;
464
465 if (n == 0)
466 return 0;
467
468 while (m_bitPos < n) {
469 m_bitBuf |= (U32)(*b->ptr++) << (24 - m_bitPos);
470 m_bitPos += 8;
471 }
472
473 v = m_bitBuf >> (32 - n);
474 m_bitBuf <<= n;
475 m_bitPos -= n;
476
477 b->m_bitPos = m_bitPos;
478 b->m_bitBuf = m_bitBuf;
479 return v;
480}
481
482// Get n bits from the string with sign extension.
483static inline S32 GetSBits (struct BitParser *b,S32 n)
484{
485 // Get the number as an unsigned value.
486 S32 v = (S32) GetBits(b,n);
487
488 // Is the number negative?
489 if (v & (1L << (n - 1)))
490 {
491 // Yes. Extend the sign.
492 v |= -1L << n;
493 }
494
495 return v;
496}
497
498
499
500/************************************************************************/
501
502static void GetMatrix(BitParser *b, Matrix* mat)
503{
504 InitBits(b);
505
506 // Scale terms
507 if (GetBit(b))
508 {
509 int nBits = (int) GetBits(b,5);
510 mat->a = (float)(GetSBits(b,nBits))/(float)0x10000;
511 mat->d = (float)(GetSBits(b,nBits))/(float)0x10000;
512 }
513 else
514 {
515 mat->a = mat->d = 1.0;
516 }
517
518 // Rotate/skew terms
519 if (GetBit(b))
520 {
521 int nBits = (int)GetBits(b,5);
522 mat->c = (float)(GetSBits(b,nBits))/(float)0x10000;
523 mat->b = (float)(GetSBits(b,nBits))/(float)0x10000;
524 }
525 else
526 {
527 mat->b = mat->c = 0.0;
528 }
529
530 // Translate terms
531 int nBits = (int) GetBits(b,5);
532 mat->tx = GetSBits(b,nBits);
533 mat->ty = GetSBits(b,nBits);
534}
535
536static FillStyleDef * ParseFillStyle(ShapeParser *shape, long *n, long getAlpha)
537{
538 BitParser *b = &shape->bit_parser;
539 FillStyleDef *defs;
540 U16 i = 0;
541
542 // Get the number of fills.
543 U16 nFills = GetByte(b);
544
545 // Do we have a larger number?
546 if (nFills == 255)
547 {
548 // Get the larger number.
549 nFills = GetWord(b);
550 }
551
552 *n = nFills;
553 defs = new FillStyleDef[ nFills ];
554 if (defs == NULL) return NULL;
555
556 // Get each of the fill style.
557 for (i = 0; i < nFills; i++)
558 {
559 U16 fillStyle = GetByte(b);
560
561 defs[i].type = (FillType) fillStyle;
562
563 if (fillStyle & 0x10)
564 {
565 defs[i].type = (FillType) (fillStyle & 0x12);
566
567 // Get the gradient matrix.
568 GetMatrix(b,&(defs[i].matrix));
569
570 // Get the number of colors.
571 defs[i].gradient.nbGradients = GetByte(b);
572
573 // Get each of the colors.
574 for (U16 j = 0; j < defs[i].gradient.nbGradients; j++)
575 {
576 defs[i].gradient.ratio[j] = GetByte(b);
577 defs[i].gradient.color[j].red = GetByte(b);
578 defs[i].gradient.color[j].green = GetByte(b);
579 defs[i].gradient.color[j].blue = GetByte(b);
580 if (getAlpha) {
581 defs[i].gradient.color[j].alpha = GetByte(b);
582 } else {
583 defs[i].gradient.color[j].alpha = ALPHA_OPAQUE;
584 }
585 }
586 }
587 else if (fillStyle & 0x40)
588 {
589 defs[i].type = (FillType) (fillStyle & 0x41);
590
591 // Get the bitmapId
592 defs[i].bitmap = (Bitmap *)shape->dict->getCharacter(GetWord(b));
593 // Get the bitmap matrix.
594 GetMatrix(b,&(defs[i].matrix));
595 }
596 else
597 {
598 defs[i].type = (FillType) 0;
599
600 // A solid color
601 defs[i].color.red = GetByte(b);
602 defs[i].color.green = GetByte(b);
603 defs[i].color.blue = GetByte(b);
604 if (getAlpha) {
605 defs[i].color.alpha = GetByte(b);
606 } else {
607 defs[i].color.alpha = ALPHA_OPAQUE;
608 }
609 }
610 }
611
612 return defs;
613}
614
615static LineStyleDef * ParseLineStyle(ShapeParser *shape, long *n, long getAlpha)
616{
617 BitParser *b = &shape->bit_parser;
618 LineStyleDef *defs,*def;
619 FillStyleDef *f;
620 long i;
621
622 // Get the number of lines.
623 U16 nLines = GetByte(b);
624
625 // Do we have a larger number?
626 if (nLines == 255)
627 {
628 // Get the larger number.
629 nLines = GetWord(b);
630 }
631
632 *n = nLines;
633 defs = new LineStyleDef[ nLines ];
634 if (defs == NULL) return NULL;
635
636 // Get each of the line styles.
637 for (i = 0; i < nLines; i++)
638 {
639 def=&defs[i];
640 def->width = GetWord(b);
641 def->color.red = GetByte(b);
642 def->color.green = GetByte(b);
643 def->color.blue = GetByte(b);
644 if (getAlpha) {
645 def->color.alpha = GetByte(b);
646 } else {
647 def->color.alpha = ALPHA_OPAQUE;
648 }
649
650 f=&def->fillstyle;
651 f->type = f_Solid;
652 f->color = def->color;
653 if (shape->cxform) {
654 f->color = shape->cxform->getColor(f->color);
655 }
656 f->color.pixel = shape->gd->allocColor(f->color);
657 }
658
659 return defs;
660}
661
662/* 0 = end of shape */
663static int ParseShapeRecord(ShapeParser *shape, ShapeRecord *sr, long getAlpha)
664{
665 BitParser *b = &shape->bit_parser;
666
667 // Determine if this is an edge.
668 BOOL isEdge = (BOOL) GetBit(b);
669
670 if (!isEdge)
671 {
672 // Handle a state change
673 U16 flags = (U16) GetBits(b,5);
674
675 // Are we at the end?
676 if (flags == 0)
677 {
678 // End of shape
679 return 0;
680 }
681
682 sr->type = shapeNonEdge;
683 sr->flags = (ShapeFlags)flags;
684
685 // Process a move to.
686 if (flags & flagsMoveTo)
687 {
688 U16 nBits = (U16) GetBits(b,5);
689 sr->x = GetSBits(b,nBits);
690 sr->y = GetSBits(b,nBits);
691 }
692
693 // Get new fill info.
694 if (flags & flagsFill0)
695 {
696 sr->fillStyle0 = GetBits(b,shape->m_nFillBits);
697 }
698 if (flags & flagsFill1)
699 {
700 sr->fillStyle1 = GetBits(b,shape->m_nFillBits);
701 }
702
703 // Get new line info
704 if (flags & flagsLine)
705 {
706 sr->lineStyle = GetBits(b,shape->m_nLineBits);
707 }
708
709 // Check to get a new set of styles for a new shape layer.
710 if (flags & flagsNewStyles)
711 {
712 FillStyleDef *fillDefs;
713 LineStyleDef *lineDefs;
714 long n;
715
716 // Parse the style.
717 fillDefs = ParseFillStyle(shape, &n, getAlpha);
718 if (fillDefs == NULL) return 0;
719
720 sr->newFillStyles = fillDefs;
721 sr->nbNewFillStyles = n;
722
723 lineDefs = ParseLineStyle(shape, &n, getAlpha);
724 if (lineDefs == NULL) return 0;
725
726 sr->newLineStyles = lineDefs;
727 sr->nbNewLineStyles = n;
728
729 InitBits(b);// Bug !
730
731 // Reset.
732 shape->m_nFillBits = (U16) GetBits(b,4);
733 shape->m_nLineBits = (U16) GetBits(b,4);
734 }
735
736 //if (flags & flagsEndShape)
737 //printf("\tEnd of shape.\n\n");
738
739 return flags & flagsEndShape ? 0 : 1;
740 }
741 else
742 {
743 if (GetBit(b))
744 {
745 sr->type = shapeLine;
746
747 // Handle a line
748 U16 nBits = (U16) GetBits(b,4) + 2;// nBits is biased by 2
749
750 // Save the deltas
751 if (GetBit(b))
752 {
753 // Handle a general line.
754 sr->dX = GetSBits(b,nBits);
755 sr->dY = GetSBits(b,nBits);
756 }
757 else
758 {
759 // Handle a vert or horiz line.
760 if (GetBit(b))
761 {
762 // Vertical line
763 sr->dY = GetSBits(b,nBits);
764 sr->dX = 0;
765 }
766 else
767 {
768 // Horizontal line
769 sr->dX = GetSBits(b,nBits);
770 sr->dY = 0;
771 }
772 }
773 }
774 else
775 {
776 sr->type = shapeCurve;
777
778 // Handle a curve
779 U16 nBits = (U16) GetBits(b,4) + 2;// nBits is biased by 2
780
781 // Get the control
782 sr->ctrlX = GetSBits(b,nBits);
783 sr->ctrlY = GetSBits(b,nBits);
784
785 // Get the anchor
786 sr->anchorX = GetSBits(b,nBits);
787 sr->anchorY = GetSBits(b,nBits);
788 }
789
790 return 1;
791 }
792}
793
794static void drawShape(GraphicDevice *gd, Matrix *matrix1, Cxform *cxform, Shape *shape,
795 ShapeAction shapeAction, void *id,ScanLineFunc scan_line_func)
796{
797 LineStyleDef *l;
798 FillStyleDef *f0;
799 FillStyleDef *f1;
800 ShapeRecord sr1,*sr = &sr1;
801 int firstPoint;
802 long lastX,lastY;
803 LineStyleDef *curLineStyle;
804 long curNbLineStyles;
805 FillStyleDef *curFillStyle;
806 long curNbFillStyles;
807 StyleList *sl;
808 ShapeParser sp1,*sp=&sp1;
809 BitParser *b;
810 Matrix mat,*matrix;
811
812 mat = (*gd->adjust) * (*matrix1);
813 matrix = &mat;
814
815 sp->reverse = (mat.a * mat.d) < 0;
816
817 curLineStyle = NULL;
818 curNbLineStyles = 0;
819 curFillStyle = NULL;
820 curNbFillStyles = 0;
821 sp->style_list = NULL;
822
823 sp->shape = shape;
824 sp->gd = gd;
825 sp->matrix = matrix;
826 sp->cxform = cxform;
827 sp->dict = shape->dict;
828
829 if (shapeAction == ShapeGetRegion) {
830 gd->scan_line_func = scan_line_func;
831 gd->scan_line_func_id = id;
832 } else {
833 gd->scan_line_func = NULL;
834 }
835
836 b = &sp->bit_parser;
837 InitBitParser(b,shape->file_ptr);
838
839 if (shape->getStyles) {
840 // ShapeWithStyle
841 curFillStyle = ParseFillStyle(sp, &curNbFillStyles, shape->getAlpha);
842 if (curFillStyle == NULL) return;
843
844 curLineStyle = ParseLineStyle(sp, &curNbLineStyles, shape->getAlpha);
845 if (curLineStyle == NULL) return;
846
847 sl = new StyleList;
848 if (sl == NULL) return;
849
850 sl->next = NULL;
851 sl->newFillStyles = curFillStyle;
852 sl->nbNewFillStyles = curNbFillStyles;
853 sl->newLineStyles = curLineStyle;
854 sl->nbNewLineStyles = curNbLineStyles;
855
856 sp->style_list = sl;
857
858 if (shapeAction == ShapeDraw) {
859 prepareStyles(gd, matrix, cxform, curFillStyle, curNbFillStyles);
860 }
861 }
862
863 InitBits(b);
864 sp->m_nFillBits = (U16) GetBits(b,4);
865 sp->m_nLineBits = (U16) GetBits(b,4);
866
867 l = 0;
868 f0 = 0;
869 f1 = 0;
870 firstPoint = 1;
871 lastX = 0;
872 lastY = 0;
873 sp->curPath.nb_edges = 0;
874 sp->first_line = NULL;
875 sp->last_line = NULL;
876
877 for(;;) {
878 if (ParseShapeRecord(sp, sr, shape->getAlpha) == 0) break;
879
880 switch (sr->type)
881 {
882 case shapeNonEdge:
883 if (sr->flags & flagsNewStyles) {
884
885 curFillStyle = sr->newFillStyles;
886 curNbFillStyles = sr->nbNewFillStyles;
887 curLineStyle = sr->newLineStyles;
888 curNbLineStyles = sr->nbNewLineStyles;
889
890 sl = new StyleList;
891 sl->next = sp->style_list;
892 sl->newFillStyles = sr->newFillStyles;
893 sl->nbNewFillStyles = sr->nbNewFillStyles;
894 sl->newLineStyles = sr->newLineStyles;
895 sl->nbNewLineStyles = sr->nbNewLineStyles;
896
897 sp->style_list = sl;
898
899 if (shapeAction == ShapeDraw) {
900 prepareStyles(gd, matrix, cxform, curFillStyle, curNbFillStyles);
901 }
902 }
903 if (sr->flags & flagsFill0) {
904 if (sr->fillStyle0) {
905 if (curFillStyle) {
906 f0 = &curFillStyle[sr->fillStyle0-1];
907 } else {
908 f0 = &shape->defaultFillStyle;
909 }
910 } else {
911 f0 = 0;
912 }
913 }
914 if (sr->flags & flagsFill1) {
915 if (sr->fillStyle1) {
916 if (curFillStyle) {
917 f1 = &curFillStyle[sr->fillStyle1-1];
918 } else {
919 f1 = &shape->defaultFillStyle;
920 }
921 } else {
922 f1 = 0;
923 }
924 }
925 if (sr->flags & flagsLine) {
926 if (sr->lineStyle) {
927 l = &curLineStyle[sr->lineStyle-1];
928 } else {
929 l = 0;
930 }
931 }
932 if (sr->flags & flagsMoveTo) {
933 if (sp->curPath.nb_edges == 0) {
934 /* if no edges, draw the polygon, then the lines */
935 flushPaths(sp);
936 }
937
938 newPath(sp, sr->x, sr->y);
939 firstPoint = 0;
940
941 lastX = sr->x;
942 lastY = sr->y;
943
944#if PRINT
945 printf("---------\nX,Y = %4d,%4d\n", sr->x/20, sr->y/20);
946#endif
947 }
948 break;
949 case shapeCurve:
950 // Handle Bezier Curves !!!
951 if (firstPoint) {
952 newPath(sp, 0, 0);
953 firstPoint = 0;
954 }
955 {
956 long newX,newY,ctrlX,ctrlY;
957
958 ctrlX = lastX+sr->ctrlX;
959 ctrlY = lastY+sr->ctrlY;
960 newX = ctrlX+sr->anchorX;
961 newY = ctrlY+sr->anchorY;
962
963#if 1
964 addBezier(sp, ctrlX, ctrlY, newX, newY, f0 , f1, l);
965#else
966 addLine(sp, newX, newY, f0, f1, l);
967#endif
968
969 lastX = newX;
970 lastY = newY;
971 }
972 break;
973 case shapeLine:
974 if (firstPoint) {
975 newPath(sp, 0, 0);
976 firstPoint = 0;
977 }
978
979 lastX += sr->dX;
980 lastY += sr->dY;
981
982 addLine(sp, lastX, lastY, f0, f1, l);
983#if PRINT
984 printf(" X, Y = %4d,%4d\n", lastX/20, lastY/20);
985#endif
986 break;
987 }
988 }
989
990 /* XXX: should test if there is something to draw */
991 flushPaths(sp);
992
993 /* free the styles */
994 while (sp->style_list) {
995 StyleList *sl;
996
997 sl=sp->style_list;
998 sp->style_list = sl->next;
999
1000 if (shapeAction == ShapeDraw) {
1001 clearStyles(gd, sl->newFillStyles, sl->nbNewFillStyles);
1002 }
1003
1004 delete[] sl->newFillStyles;
1005 delete[] sl->newLineStyles;
1006
1007 delete sl;
1008 }
1009}
1010
1011static void
1012prepareStyles(GraphicDevice *gd, Matrix *matrix, Cxform *cxform,
1013 FillStyleDef *ftab, long n)
1014{
1015 long fs;
1016 FillStyleDef *f;
1017
1018 for(fs = 0; fs < n; fs++)
1019 {
1020 f = ftab + fs;
1021 switch (f->type)
1022 {
1023 case f_None:
1024 break;
1025 case f_Solid:
1026 if (cxform) {
1027 f->color = cxform->getColor(f->color);
1028 }
1029 f->color.pixel = gd->allocColor(f->color);
1030 break;
1031 case f_LinearGradient:
1032 case f_RadialGradient:
1033 {
1034 Matrix mat;
1035 int n,r,l;
1036 long red, green, blue, alpha;
1037 long dRed, dGreen, dBlue, dAlpha;
1038 long min,max;
1039 Matrix *m;
1040
1041 mat = *(matrix) * f->matrix;
1042 // Compute inverted matrix
1043 f->gradient.imat = mat.invert();
1044
1045 /* renormalize the matrix */
1046 m=&f->gradient.imat;
1047 if (f->type == f_LinearGradient) {
1048 m->a = m->a * FRAC * (1/128.0) * 65536.0;
1049 m->b = m->b * FRAC * (1/128.0) * 65536.0;
1050 m->tx = (long) ((m->tx + 16384) * (1/128.0) * 65536.0);
1051 } else {
1052 m->a = m->a * FRAC * (1/64.0) * 65536.0;
1053 m->b = m->b * FRAC * (1/64.0) * 65536.0;
1054 m->c = m->c * FRAC * (1/64.0) * 65536.0;
1055 m->d = m->d * FRAC * (1/64.0) * 65536.0;
1056 m->tx = (long) (m->tx * (1/64.0) * 65536.0);
1057 m->ty = (long) (m->ty * (1/64.0) * 65536.0);
1058 }
1059
1060 // Reset translation in inverted matrix
1061 f->gradient.has_alpha = 0;
1062
1063 // Build a 256 color ramp
1064 f->gradient.ramp = new Color[256];
1065 if (f->gradient.ramp == NULL) {
1066 // Invalidate fill style
1067 f->type = f_None;
1068 continue;
1069 }
1070
1071 // Store min and max
1072 min = f->gradient.ratio[0];
1073 max = f->gradient.ratio[f->gradient.nbGradients-1];
1074 for(r=0; r < f->gradient.nbGradients-1; r++)
1075 {
1076 Color start,end;
1077
1078 l = f->gradient.ratio[r+1]-f->gradient.ratio[r];
1079 if (l == 0) continue;
1080
1081 if (cxform) {
1082 start = cxform->getColor(f->gradient.color[r]);
1083 end = cxform->getColor(f->gradient.color[r+1]);
1084 } else {
1085 start = f->gradient.color[r];
1086 end = f->gradient.color[r+1];
1087 }
1088
1089 if (start.alpha != ALPHA_OPAQUE ||
1090 end.alpha != ALPHA_OPAQUE) {
1091 f->gradient.has_alpha = 1;
1092 }
1093
1094 dRed = end.red - start.red;
1095 dGreen = end.green - start.green;
1096 dBlue = end.blue - start.blue;
1097 dAlpha = end.alpha - start.alpha;
1098
1099 dRed = (dRed<<16)/l;
1100 dGreen = (dGreen<<16)/l;
1101 dBlue = (dBlue<<16)/l;
1102 dAlpha = (dAlpha<<16)/l;
1103
1104 red = start.red <<16;
1105 green = start.green <<16;
1106 blue = start.blue <<16;
1107 alpha = start.alpha <<16;
1108
1109 for (n=f->gradient.ratio[r]; n<=f->gradient.ratio[r+1]; n++) {
1110 f->gradient.ramp[n].red = red>>16;
1111 f->gradient.ramp[n].green = green>>16;
1112 f->gradient.ramp[n].blue = blue>>16;
1113 f->gradient.ramp[n].alpha = alpha>>16;
1114
1115 f->gradient.ramp[n].pixel = gd->allocColor(f->gradient.ramp[n]);
1116 red += dRed;
1117 green += dGreen;
1118 blue += dBlue;
1119 alpha += dAlpha;
1120 }
1121 }
1122 for(n=0; n<min; n++) {
1123 f->gradient.ramp[n] = f->gradient.ramp[min];
1124 }
1125 for(n=max; n<256; n++) {
1126 f->gradient.ramp[n] = f->gradient.ramp[max];
1127 }
1128 }
1129 break;
1130 case f_TiledBitmap:
1131 case f_clippedBitmap:
1132 if (f->bitmap) {
1133 Matrix *m;
1134
1135 f->cmap = gd->getColormap(f->bitmap->colormap,
1136 f->bitmap->nbColors, cxform);
1137 if (f->cmap == NULL) {
1138 /* Get the normal cmap anyway */
1139 f->cmap = f->bitmap->colormap;
1140 }
1141
1142 f->bitmap_matrix = *(matrix) * f->matrix;
1143
1144 f->bitmap_matrix = f->bitmap_matrix.invert();
1145
1146 m=&f->bitmap_matrix;
1147 m->a = m->a * FRAC * 65536.0;
1148 m->b = m->b * FRAC * 65536.0;
1149 m->c = m->c * FRAC * 65536.0;
1150 m->d = m->d * FRAC * 65536.0;
1151 m->tx = (long) (m->tx * 65536.0);
1152 m->ty = (long) (m->ty * 65536.0);
1153
1154 f->alpha_table = NULL;
1155
1156 if (f->bitmap->alpha_buf && cxform) {
1157 unsigned char *alpha_table;
1158 int i;
1159
1160 alpha_table = (unsigned char *)malloc (256);
1161 if (alpha_table != NULL) {
1162 for(i=0;i<256;i++) {
1163 alpha_table[i] = cxform->getAlpha(i);
1164 }
1165 }
1166 f->alpha_table = alpha_table;
1167 }
1168 }
1169 break;
1170 }
1171 }
1172}
1173
1174static void
1175clearStyles(GraphicDevice *gd, FillStyleDef *ftab, long n)
1176{
1177 long fs;
1178 FillStyleDef *f;
1179
1180 for(fs = 0; fs < n; fs++)
1181 {
1182 f = ftab + fs;
1183 switch (f->type)
1184 {
1185 case f_Solid:
1186 break;
1187 case f_LinearGradient:
1188 case f_RadialGradient:
1189 if (f->gradient.ramp) {
1190 delete f->gradient.ramp;
1191 }
1192 break;
1193 case f_TiledBitmap:
1194 case f_clippedBitmap:
1195 if (f->bitmap) {
1196 if (f->cmap && f->cmap != f->bitmap->colormap) delete f->cmap;
1197 if (f->alpha_table) free(f->alpha_table);
1198 }
1199 break;
1200 case f_None:
1201 break;
1202 }
1203 }
1204}
1205