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 "graphic32.h"
00026
00027 extern unsigned char SQRT[];
00028
00029 #define FULL_AA
00030
00031 #define PRINT 0
00032
00033 typedef unsigned long TYPE;
00034
00035 GraphicDevice32::GraphicDevice32(FlashDisplay *fd) : GraphicDevice(fd)
00036 {
00037 }
00038
00039 long
00040 GraphicDevice32::allocColor(Color color)
00041 {
00042 return (color.red)<<16 | (color.green)<<8 | (color.blue);
00043 }
00044
00045 void
00046 GraphicDevice32::clearCanvas()
00047 {
00048 TYPE pixel;
00049 TYPE *point,*p;
00050 long h, w,n;
00051
00052 if (!bgInitialized) return;
00053
00054 pixel = allocColor(backgroundColor);
00055
00056 point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin;
00057 w = clip_rect.xmax - clip_rect.xmin;
00058 h = clip_rect.ymax - clip_rect.ymin;
00059
00060 while (h--) {
00061 p = point;
00062 n = w;
00063 while (n--) {
00064 *p++ = pixel;
00065 }
00066
00067 point = (TYPE *)((char *)point + bpl);
00068 }
00069
00070 flashDisplay->flash_refresh = 1;
00071 flashDisplay->clip_x = clip_rect.xmin;
00072 flashDisplay->clip_y = clip_rect.ymin;
00073 flashDisplay->clip_width = clip_rect.xmax-clip_rect.xmin;
00074 flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin;
00075 }
00076
00077 #define RED_MASK 0xFF0000
00078 #define GREEN_MASK 0x00FF00
00079 #define BLUE_MASK 0x0000FF
00080
00081
00082 static inline unsigned long
00083 mix_alpha(unsigned long c1, unsigned long c2, int alpha)
00084 {
00085 long r1,r2,r;
00086 long g1,g2,g;
00087 long b1,b2,b;
00088
00089 r1 = c1 & RED_MASK;
00090 r2 = c2 & RED_MASK;
00091 r = (((r2-r1)*alpha + r1 * 256) >> 8) & RED_MASK;
00092
00093 g1 = c1 & GREEN_MASK;
00094 g2 = c2 & GREEN_MASK;
00095 g = (((g2-g1)*alpha + g1 * 256) >> 8) & GREEN_MASK;
00096
00097 b1 = c1 & BLUE_MASK;
00098 b2 = c2 & BLUE_MASK;
00099 b = (((b2-b1)*alpha + b1 * 256) >> 8) & BLUE_MASK;
00100
00101 return (r|g|b);
00102 }
00103
00104 void
00105 GraphicDevice32::fillLineAA(FillStyleDef *f, long y, long start, long end)
00106 {
00107 register long n;
00108 TYPE *line;
00109 TYPE *point,pixel;
00110 unsigned int alpha, start_alpha,end_alpha;
00111
00112 if (clip(y,start,end)) return;
00113
00114 line = (TYPE *)(canvasBuffer + bpl*y);
00115
00116 alpha = f->color.alpha;
00117 pixel = f->color.pixel;
00118
00119 if (alpha == ALPHA_OPAQUE) {
00120
00121 start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
00122 end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
00123
00124 start >>= FRAC_BITS;
00125 end >>= FRAC_BITS;
00126
00127 point = &line[start];
00128
00129 if (start == end) {
00130 *point = mix_alpha(*point, pixel, start_alpha + end_alpha - 255);
00131 } else {
00132 n = end-start;
00133 if (start_alpha < 255) {
00134 *point = mix_alpha(*point, pixel, start_alpha);
00135 point++;
00136 n--;
00137 }
00138 while (n > 0) {
00139 *point = pixel;
00140 point++;
00141 n--;
00142 }
00143 if (end_alpha > 0) {
00144 *point = mix_alpha(*point, pixel, end_alpha);
00145 }
00146 }
00147 } else {
00148
00149 start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
00150 end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
00151
00152 start >>= FRAC_BITS;
00153 end >>= FRAC_BITS;
00154
00155 point = &line[start];
00156
00157 if (start == end) {
00158 *point = mix_alpha(*point, pixel,
00159 ((start_alpha + end_alpha - 255) * alpha) >> 8);
00160 } else {
00161 n = end-start;
00162 if (start_alpha < 255) {
00163 *point = mix_alpha(*point, pixel, (start_alpha * alpha) >> 8);
00164 point++;
00165 n--;
00166 }
00167 while (n > 0) {
00168 *point = mix_alpha(*point, pixel, alpha);
00169 point++;
00170 n--;
00171 }
00172 if (end_alpha > 0) {
00173 *point = mix_alpha(*point, pixel, (end_alpha * alpha) >> 8);
00174 }
00175 }
00176 }
00177 }
00178
00179 void
00180 GraphicDevice32::fillLine(FillStyleDef *f, long y, long start, long end)
00181 {
00182 register long n;
00183 TYPE *line,*point;
00184 TYPE pixel;
00185 unsigned int alpha;
00186
00187 if (clip(y,start,end)) return;
00188
00189 start >>= FRAC_BITS;
00190 end >>= FRAC_BITS;
00191
00192 line = (TYPE *)(canvasBuffer + bpl*y);
00193 point = &line[start];
00194 n = end-start;
00195 pixel = f->color.pixel;
00196 alpha = f->color.alpha;
00197 if (alpha == ALPHA_OPAQUE) {
00198 while (n--) {
00199 *point = pixel;
00200 point++;
00201 }
00202 } else {
00203 while (n--) {
00204 *point = mix_alpha(*point, pixel, alpha);
00205 point++;
00206 }
00207 }
00208 }
00209
00210 void
00211 GraphicDevice32::fillLineBitmap(FillStyleDef *f, long y, long start, long end)
00212 {
00213 int n;
00214 long x1,y1,dx,dy;
00215 Matrix *m = &f->bitmap_matrix;
00216 Bitmap *b = f->bitmap;
00217 unsigned char *pixels;
00218 TYPE *p;
00219 Color *cmap;
00220 long pixbpl;
00221 TYPE pixel;
00222 int offset;
00223 unsigned char *alpha_table;
00224
00225
00226 if (!b) return;
00227
00228 if (clip(y,start,end)) return;
00229
00230 start /= FRAC;
00231 end /= FRAC;
00232 n = end - start;
00233 p = (TYPE *) (this->canvasBuffer + this->bpl*y + start * sizeof(TYPE));
00234
00235
00236 x1 = (long) (m->a * start + m->b * y + m->tx);
00237 y1 = (long) (m->c * start + m->d * y + m->ty);
00238 dx = (long) (m->a);
00239 dy = (long) (m->c);
00240
00241 pixels = b->pixels;
00242 pixbpl = b->bpl;
00243 cmap = f->cmap;
00244
00245 if (b->alpha_buf == NULL) {
00246 while (n) {
00247 if (x1 >= 0 && y1 >= 0 &&
00248 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
00249
00250 pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]].pixel;
00251 *p = pixel;
00252 }
00253 x1 += dx;
00254 y1 += dy;
00255 p++;
00256 n--;
00257 }
00258 } else if (f->alpha_table) {
00259 alpha_table = f->alpha_table;
00260 while (n) {
00261 if (x1 >= 0 && y1 >= 0 &&
00262 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
00263
00264 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
00265 pixel = cmap[pixels[offset]].pixel;
00266 *p = mix_alpha(*p, pixel, alpha_table[b->alpha_buf[offset]]);
00267 }
00268 x1 += dx;
00269 y1 += dy;
00270 p++;
00271 n--;
00272 }
00273 } else {
00274 while (n) {
00275 if (x1 >= 0 && y1 >= 0 &&
00276 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
00277
00278 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
00279 pixel = cmap[pixels[offset]].pixel;
00280 *p = mix_alpha(*p, pixel, b->alpha_buf[offset]);
00281 }
00282 x1 += dx;
00283 y1 += dy;
00284 p++;
00285 n--;
00286 }
00287 }
00288 }
00289
00290 void
00291 GraphicDevice32::fillLineLG(Gradient *grad, long y, long start, long end)
00292 {
00293 long dr,r,v,r2;
00294 register long n;
00295 TYPE *line;
00296 TYPE *point;
00297 Color *cp,*ramp;
00298 Matrix *m = &grad->imat;
00299 unsigned int start_alpha,end_alpha;
00300
00301 if (clip(y,start,end)) return;
00302
00303 start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
00304 end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
00305
00306 start /= FRAC;
00307 end /= FRAC;
00308
00309 n = end-start;
00310
00311 r = (long) (m->a * start + m->b * y + m->tx);
00312 dr = (long) (m->a);
00313
00314 ramp = grad->ramp;
00315
00316 line = (TYPE *)(canvasBuffer + bpl*y);
00317 point = &line[start];
00318
00319 r2 = r + n * dr;
00320 if ( ((r | r2) & ~255) == 0 ) {
00321 if (!grad->has_alpha) {
00322 #ifdef FULL_AA
00323 if (start_alpha < 255) {
00324 v = r>>16;
00325 *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
00326 point++;
00327 r += dr;
00328 n--;
00329 }
00330 #endif
00331 while (n>0) {
00332 v = r>>16;
00333 *point = (TYPE)ramp[v].pixel;
00334 point++;
00335 r += dr;
00336 n--;
00337 }
00338 #ifdef FULL_AA
00339 if (end_alpha > 0) {
00340 v = r>>16;
00341 *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
00342 }
00343 #endif
00344 } else {
00345 while (n--) {
00346 v = r>>16;
00347 cp = &ramp[v];
00348 *point = mix_alpha(*point, cp->pixel, cp->alpha);
00349 point++;
00350 r += dr;
00351 }
00352 }
00353 } else {
00354 if (!grad->has_alpha) {
00355 #ifdef FULL_AA
00356 if (start_alpha < 255) {
00357 v = r>>16;
00358 if (v < 0) v = 0;
00359 else if (v > 255) v = 255;
00360 *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
00361 point++;
00362 r += dr;
00363 n--;
00364 }
00365 #endif
00366 while (n>0) {
00367 v = r>>16;
00368 if (v < 0) v = 0;
00369 else if (v > 255) v = 255;
00370 *point = (TYPE)ramp[v].pixel;
00371 point++;
00372 r += dr;
00373 n--;
00374 }
00375 #ifdef FULL_AA
00376 if (end_alpha > 0) {
00377 v = r>>16;
00378 if (v < 0) v = 0;
00379 else if (v > 255) v = 255;
00380 *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
00381 }
00382 #endif
00383 } else {
00384 while (n--) {
00385 v = r>>16;
00386 if (v < 0) v = 0;
00387 else if (v > 255) v = 255;
00388 cp = &ramp[v];
00389 *point = mix_alpha(*point, cp->pixel, cp->alpha);
00390 point++;
00391 r += dr;
00392 }
00393 }
00394 }
00395 }
00396
00397 void
00398 GraphicDevice32::fillLineRG(Gradient *grad, long y, long start, long end)
00399 {
00400 long X,dx,r,Y,dy;
00401 long dist2;
00402 register long n;
00403 Color *cp,*ramp;
00404 TYPE *line;
00405 TYPE *point;
00406 Matrix *m = &grad->imat;
00407 unsigned int start_alpha,end_alpha;
00408
00409 if (clip(y,start,end)) return;
00410
00411 start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
00412 end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
00413
00414 start /= FRAC;
00415 end /= FRAC;
00416
00417 n = end-start;
00418
00419 X = (long) (m->a * start + m->b * y + m->tx);
00420 Y = (long) (m->c * start + m->d * y + m->ty);
00421 dx = (long) (m->a);
00422 dy = (long) (m->c);
00423
00424 ramp = grad->ramp;
00425
00426 line = (TYPE *)(canvasBuffer + bpl*y);
00427 point = &line[start];
00428
00429 if (!grad->has_alpha) {
00430 #ifdef FULL_AA
00431 if (start == end) {
00432 dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
00433 if ((unsigned long)dist2 >= 65536) {
00434 r = 255;
00435 } else {
00436 r = SQRT[dist2];
00437 }
00438 *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha + end_alpha - 255);
00439 } else {
00440 if (start_alpha < 255) {
00441 dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
00442 if ((unsigned long)dist2 >= 65536) {
00443 r = 255;
00444 } else {
00445 r = SQRT[dist2];
00446 }
00447 *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha);
00448 point++;
00449 X += dx;
00450 Y += dy;
00451 n--;
00452 }
00453 #endif
00454 while (n>0) {
00455 dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
00456 if ((unsigned long)dist2 >= 65536) {
00457 r = 255;
00458 } else {
00459 r= SQRT[dist2];
00460 }
00461 *point = (TYPE)ramp[r].pixel;
00462 point++;
00463 X += dx;
00464 Y += dy;
00465 n--;
00466 }
00467 #ifdef FULL_AA
00468 if (end_alpha > 0) {
00469 dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
00470 if ((unsigned long)dist2 >= 65536) {
00471 r = 255;
00472 } else {
00473 r= SQRT[dist2];
00474 }
00475 *point = mix_alpha(*point, (TYPE)ramp[r].pixel, end_alpha);
00476 }
00477 }
00478 #endif
00479
00480 } else {
00481 while (n--) {
00482 dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
00483 if ((unsigned long)dist2 >= 65536) {
00484 r = 255;
00485 } else {
00486 r= SQRT[dist2];
00487 }
00488 cp = &ramp[r];
00489 *point = mix_alpha(*point, cp->pixel, cp->alpha);
00490 point++;
00491 X += dx;
00492 Y += dy;
00493 }
00494 }
00495 }
00496
00497 void
00498 GraphicDevice32::drawLine(long x1, long y1, long x2, long y2, long width)
00499 {
00500 int n,adr,dx,dy,sx,color;
00501 register int a;
00502 register TYPE *pp;
00503 int alpha;
00504
00505 x1 = (x1) >> FRAC_BITS;
00506 y1 = (y1) >> FRAC_BITS;
00507 x2 = (x2) >> FRAC_BITS;
00508 y2 = (y2) >> FRAC_BITS;
00509
00510 if (y1 > y2 || (y1 == y2 && x1 > x2)) {
00511 long tmp;
00512
00513 tmp=x1;
00514 x1=x2;
00515 x2=tmp;
00516
00517 tmp=y1;
00518 y1=y2;
00519 y2=tmp;
00520 }
00521
00522 if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return;
00523 if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return;
00524 if (x1 == x2 && y1 == y2) return;
00525
00526 if (y1 < clip_rect.ymin && y1 != y2) {
00527 x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1);
00528 y1 = clip_rect.ymin;
00529 }
00530
00531 if (y2 > clip_rect.ymax && y1 != y2) {
00532 x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1);
00533 y2 = clip_rect.ymax;
00534 }
00535
00536 if (x1 < x2) {
00537 if (x1 < clip_rect.xmin && x1 != x2) {
00538 y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1);
00539 x1 = clip_rect.xmin;
00540 }
00541
00542 if (x2 > clip_rect.xmax && x1 != x2) {
00543 y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1);
00544 x2 = clip_rect.xmax;
00545 }
00546 }
00547
00548 if (x1 > x2) {
00549 if (x2 < clip_rect.xmin && x2 != x1) {
00550 y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2);
00551 x2 = clip_rect.xmin;
00552 }
00553
00554 if (x1 > clip_rect.xmax && x2 != x1) {
00555 y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2);
00556 x1 = clip_rect.xmax;
00557 }
00558 }
00559
00560
00561 if (x1 == x2 && y1 == y2) return;
00562 if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return;
00563 if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return;
00564 if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return;
00565 if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return;
00566
00567 sx=bpl >> 1;
00568 adr=(y1 * sx + x1);
00569 pp = (TYPE *)canvasBuffer + adr;
00570
00571 dx = x2 - x1;
00572 dy = y2 - y1;
00573
00574 color = allocColor(foregroundColor);
00575 alpha = foregroundColor.alpha;
00576
00577 if (alpha == ALPHA_OPAQUE) {
00578
00579 #define PUTPIXEL() \
00580 { \
00581 *pp=color; \
00582 }
00583
00584 #define DRAWLINE(dx,dy,inc_1,inc_2) \
00585 n=dx;\
00586 a=2*dy-dx;\
00587 dy=2*dy;\
00588 dx=2*dx-dy;\
00589 do {\
00590 PUTPIXEL();\
00591 if (a>0) { pp+=(inc_1); a-=dx; }\
00592 else { pp+=(inc_2); a+=dy; }\
00593 } while (--n >= 0);
00594
00595
00596
00597 if (dx == 0 && dy == 0) {
00598 PUTPIXEL();
00599 } else if (dx > 0) {
00600 if (dx >= dy) {
00601 DRAWLINE(dx, dy, sx + 1, 1);
00602 } else {
00603 DRAWLINE(dy, dx, sx + 1, sx);
00604 }
00605 } else {
00606 dx = -dx;
00607 if (dx >= dy) {
00608 DRAWLINE(dx, dy, sx - 1, -1);
00609 } else {
00610 DRAWLINE(dy, dx, sx - 1, sx);
00611 }
00612 }
00613
00614
00615 #undef DRAWLINE
00616 #undef PUTPIXEL
00617 } else {
00618 #define PUTPIXEL() \
00619 { \
00620 *pp=mix_alpha(*pp,color,alpha); \
00621 }
00622
00623 #define DRAWLINE(dx,dy,inc_1,inc_2) \
00624 n=dx;\
00625 a=2*dy-dx;\
00626 dy=2*dy;\
00627 dx=2*dx-dy;\
00628 do {\
00629 PUTPIXEL();\
00630 if (a>0) { pp+=(inc_1); a-=dx; }\
00631 else { pp+=(inc_2); a+=dy; }\
00632 } while (--n >= 0);
00633
00634
00635
00636 if (dx == 0 && dy == 0) {
00637 PUTPIXEL();
00638 } else if (dx > 0) {
00639 if (dx >= dy) {
00640 DRAWLINE(dx, dy, sx + 1, 1);
00641 } else {
00642 DRAWLINE(dy, dx, sx + 1, sx);
00643 }
00644 } else {
00645 dx = -dx;
00646 if (dx >= dy) {
00647 DRAWLINE(dx, dy, sx - 1, -1);
00648 } else {
00649 DRAWLINE(dy, dx, sx - 1, sx);
00650 }
00651 }
00652
00653
00654 #undef DRAWLINE
00655 #undef PUTPIXEL
00656 }
00657 }