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