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

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

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