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