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

graphic24.cc

Go to the documentation of this file.
00001 
00002 // Flash Plugin and Player
00003 // Copyright (C) 1998 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 "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 /* alpha = 0 : select c1, alpha = 255 select c2 */
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     /* safety test) */
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 /* FULL_AA */
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 /* FULL_AA */
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 /* FULL_AA */
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 /* FULL_AA */
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 /* FULL_AA */
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 /* FULL_AA */
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;   // Bad !!!
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     // Check again
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 /* fin macro */
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 /* fin macro */
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 }

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