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

graphic32.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 "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 /* alpha = 0 : select c1, alpha = 255 select c2 */
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     /* safety test) */
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     /* the coordinates in the image are normalized to 16 bits */
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 /* FULL_AA */
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 /* FULL_AA */
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 /* FULL_AA */
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 /* FULL_AA */
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 /* FULL_AA */
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 /* FULL_AA */
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;   // Bad !!!
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     // Check again
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 /* fin macro */
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 /* fin macro */
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 }

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