home *** CD-ROM | disk | FTP | other *** search
Wrap
//////////////////////////////////////////////////////////// // Flash Plugin and Player // Copyright (C) 1998 Olivier Debon // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // /////////////////////////////////////////////////////////////// // Author : Olivier Debon <odebon@club-internet.fr> // #include "swf.h" #include "graphic8.h" #ifdef RCSID static char *rcsid = "$Id: graphic.cc,v 1.5 1999/09/03 15:17:40 ode Exp $"; #endif #include "sqrt.h" #define FULL_AA #define PRINT 0 typedef unsigned char TYPE; #define HBP #ifdef HBP extern "C" { extern long mix_alpha8(long c1, long c2, int alpha); extern void fill_line_flat_opaque8(unsigned char *line, long pixels, long col); extern void fill_line_flat8(unsigned char *line, long pixels, long col, int alpha); extern void fill_line_flat_bitmap8(unsigned char *p, long n, Color *cmap, unsigned char *pixels, int pixbpl, long x1, long y1, long dx, long dy, long width, long height, int tiled); extern void fill_line_alpha_chn_bitmap8(unsigned char *p, long n, Color *cmap, unsigned char *pixels, int pixbpl, long x1, long y1, long dx, long dy, unsigned char *alphatable, unsigned char *alphachannel, long width, long height, int tiled); extern void fill_line_alpha_bitmap8(unsigned char *p, long n, Color *cmap, unsigned char *pixels, int pixbpl, long x1, long y1, long dx, long dy, unsigned char *alphachannel, long width, long height, int tiled); extern int fill_line_ramp_opaque8(unsigned char *point, long n, Color *ramp, long r, long dr); extern int fill_line_ramp8(unsigned char *point, long n, Color *ramp, long r, long dr); extern int fill_line_ramp_2_opaque8(unsigned char *point, long n, Color *ramp, long r, long dr); extern int fill_line_ramp_2_8(unsigned char *point, long n, Color *ramp, long r, long dr); extern void fill_line_radial_ramp_2_8(unsigned char *point, long n, long *X, long *Y, long dx, long dy, Color *ramp, unsigned char *SQRT); extern void fill_line_radial_ramp8(unsigned char *point, long n, long *X, long *Y, long dx, long dy, Color *ramp, unsigned char *SQRT); extern Color *get_colour8(long c, Color *c); extern long alloc_colour8(Color *c); } #else #define mix_alpha8 mix_alpha #endif // Public GraphicDevice8::GraphicDevice8(FlashDisplay *fd) : GraphicDevice(fd) { } GraphicDevice8::~GraphicDevice8() { } long GraphicDevice8::allocColor(Color color) { #ifdef HBP return alloc_colour8(&color); #else // colour number tables static long redtable [16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17}; static long greentable [16] = {0x00, 0x01, 0x02, 0x03, 0x20, 0x21, 0x22, 0x23, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61, 0x62, 0x63}; static long bluetable [16] = {0x00, 0x01, 0x02, 0x03, 0x08, 0x09, 0x0a, 0x0b, 0x80, 0x81, 0x82, 0x83, 0x88, 0x89, 0x8a, 0x8b}; return redtable[color.red >> 4] | greentable[color.green >> 4] | bluetable[color.blue >> 4]; #endif } Color GraphicDevice8::getColor(unsigned long c) { Color color; #ifdef HBP get_colour8(c, &color); #else color.red = ((c & 7) | ((c & 0x10) >> 1)) << 4; color.green = ((c & 3) | ((c & 0x60) >> 3)) << 4; color.blue = ((c & 3) | ((c & 0x08) >> 1) | ((c & 0x80) >> 4)) << 4; #endif return color; } void GraphicDevice8::clearCanvas() { #ifdef HBP long pixel; #else TYPE pixel; #endif TYPE *point,*p; long h, w,n; if (!bgInitialized) return; pixel = allocColor(backgroundColor); // The following allows to test clipping //for(point = (TYPE *)canvasBuffer,n=0; n<targetHeight*bpl/2; point++,n++) *point = 0xfe00; point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin; w = clip_rect.xmax - clip_rect.xmin; h = clip_rect.ymax - clip_rect.ymin; while (h--) { p = point; n = w; #ifdef HBP if (h &1) pixel = ((pixel>>8) & ~0xff000000) | (pixel<<24); fill_line_flat_opaque8(point, n, pixel); #else while (n--) { *p++ = pixel; } #endif point = (TYPE *)((char *)point + bpl); } flashDisplay->flash_refresh = 1; flashDisplay->clip_x = clip_rect.xmin; flashDisplay->clip_y = clip_rect.ymin; flashDisplay->clip_width = clip_rect.xmax-clip_rect.xmin; flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin; } void GraphicDevice8::fillLineAA(FillStyleDef *f, long y, long start, long end) { register long n; TYPE *line; TYPE *point; #ifdef HBP long pixel; #else TYPE pixel; #endif unsigned int alpha, start_alpha,end_alpha; if (clip(y,start,end)) return; line = (TYPE *)(canvasBuffer + bpl*y); alpha = f->color.alpha; pixel = f->color.pixel; #ifdef HBP if (y &1) pixel = ((pixel>>8) & ~0xff000000) | (pixel<<24); #endif if (alpha == ALPHA_OPAQUE) { start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); start >>= FRAC_BITS; end >>= FRAC_BITS; point = &line[start]; if (start == end) { *point = (TYPE)mix_alpha8(*point, pixel, start_alpha + end_alpha - 255); } else { n = end-start; if (start_alpha < 255) { *point = (TYPE)mix_alpha8(*point, pixel, start_alpha); point++; n--; } #ifdef HBP fill_line_flat_opaque8(point, n, pixel); point += n; #else while (n > 0) { *point = pixel; point++; n--; } #endif if (end_alpha > 0) { *point = mix_alpha8(*point, pixel, end_alpha); } } } else { start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); start >>= FRAC_BITS; end >>= FRAC_BITS; point = &line[start]; if (start == end) { *point = (TYPE)mix_alpha8(*point, pixel, ((start_alpha + end_alpha - 255) * alpha) >> 8); } else { n = end-start; if (start_alpha < 255) { *point = mix_alpha8(*point, pixel, (start_alpha * alpha) >> 8); point++; n--; } #ifdef HBP fill_line_flat8(point, n, pixel, alpha); point += n; #else while (n > 0) { *point = mix_alpha8(*point, pixel, alpha); point++; n--; } #endif if (end_alpha > 0) { *point = mix_alpha8(*point, pixel, (end_alpha * alpha) >> 8); } } } } void GraphicDevice8::fillLine(FillStyleDef *f, long y, long start, long end) { register long n; TYPE *line,*point; #ifdef HBP long pixel; #else TYPE pixel; #endif unsigned int alpha; if (clip(y,start,end)) return; start >>= FRAC_BITS; end >>= FRAC_BITS; line = (TYPE *)(canvasBuffer + bpl*y); point = &line[start]; n = end-start; pixel = f->color.pixel; #ifdef HBP if (y &1) pixel = ((pixel>>8) & ~0xff000000) | (pixel<<24); #endif alpha = f->color.alpha; if (alpha == ALPHA_OPAQUE) { #ifdef HBP fill_line_flat_opaque8(point, n, pixel); #else while (n--) { *point = pixel; point++; } #endif } else { #ifdef HBP fill_line_flat8(point, n, pixel, alpha); #else while (n--) { *point = mix_alpha8(*point, pixel, alpha); point++; } #endif } } /* 16 bit assumed... easy to change */ void GraphicDevice8::fillLineBitmap(FillStyleDef *f, long y, long start, long end) { int n; long x1,y1,dx,dy; Matrix *m = &f->bitmap_matrix; Bitmap *b = f->bitmap; unsigned char *pixels; // unsigned short *p; unsigned char *p; Color *cmap; long pixbpl; TYPE pixel; int offset; unsigned char *alpha_table; /* safety test) */ if (!b) return; if (clip(y,start,end)) return; start /= FRAC; end /= FRAC; n = end - start; // p = (unsigned short *) (this->canvasBuffer + this->bpl*y + start * 2); p = (unsigned char *) (this->canvasBuffer + this->bpl*y + start); /* the coordinates in the image are normalized to 16 bits */ #ifdef HBP x1 = start*f->bm_a + y*f->bm_b + f->bm_tx; y1 = start*f->bm_c + y*f->bm_d + f->bm_ty; dx = f->bm_a; dy = f->bm_c; #else x1 = (long) (m->a * start + m->b * y + m->tx); y1 = (long) (m->c * start + m->d * y + m->ty); dx = (long) (m->a); dy = (long) (m->c); #endif pixels = b->pixels; pixbpl = b->bpl; cmap = f->cmap; if (b->alpha_buf == NULL) { #ifdef HBP if (f->type == f_TiledBitmap) { // step values may not be larger than the bitmap width or height if ((dx>>16 > b->width) || (dy>>16 > b->height)) dx = dy = 0; // make sure start point is within bitmap x1 = x1 % (b->width<<16); if (x1 < 0) x1 += b->width<<16; y1 = y1 % (b->height<<16); if (y1 < 0) y1 += b->height<<16; fill_line_flat_bitmap8(p, n, cmap, pixels, pixbpl, x1, y1, dx, dy, b->width, b->height, 1); } else { fill_line_flat_bitmap8(p, n, cmap, pixels, pixbpl, x1, y1, dx, dy, b->width, b->height, 0); } #else while (n) { if (x1 >= 0 && y1 >= 0 && (x1 >> 16) < b->width && (y1 >> 16) < b->height) { pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]].pixel; *p = pixel; } x1 += dx; y1 += dy; p++; n--; } #endif } else if (f->alpha_table) { #ifdef HBP if (f->type == f_TiledBitmap) { // step values may not be larger than the bitmap width or height if ((dx>>16 > b->width) || (dy>>16 > b->height)) dx = dy = 0; // make sure start point is within bitmap x1 = x1 % (b->width<<16); if (x1 < 0) x1 += b->width<<16; y1 = y1 % (b->height<<16); if (y1 < 0) y1 += b->height<<16; fill_line_alpha_chn_bitmap8(p, n, cmap, pixels, pixbpl, x1, y1, dx, dy, f->alpha_table, b->alpha_buf, b->width, b->height, 1); } else { fill_line_alpha_chn_bitmap8(p, n, cmap, pixels, pixbpl, x1, y1, dx, dy, f->alpha_table, b->alpha_buf, b->width, b->height, 0); } #else alpha_table = f->alpha_table; while (n) { if (x1 >= 0 && y1 >= 0 && (x1 >> 16) < b->width && (y1 >> 16) < b->height) { offset = (y1 >> 16) * pixbpl + (x1 >> 16); pixel = cmap[pixels[offset]].pixel; *p = mix_alpha8(*p, pixel, alpha_table[b->alpha_buf[offset]]); } x1 += dx; y1 += dy; p++; n--; } #endif } else { #ifdef HBP if (f->type == f_TiledBitmap) { // step values may not be larger than the bitmap width or height if ((dx>>16 > b->width) || (dy>>16 > b->height)) dx = dy = 0; // make sure start point is within bitmap x1 = x1 % (b->width<<16); if (x1 < 0) x1 += b->width<<16; y1 = y1 % (b->height<<16); if (y1 < 0) y1 += b->height<<16; fill_line_alpha_bitmap8(p, n, cmap, pixels, pixbpl, x1, y1, dx, dy, b->alpha_buf, b->width, b->height, 1); } else { fill_line_alpha_bitmap8(p, n, cmap, pixels, pixbpl, x1, y1, dx, dy, b->alpha_buf, b->width, b->height, 0); } #else while (n) { if (x1 >= 0 && y1 >= 0 && (x1 >> 16) < b->width && (y1 >> 16) < b->height) { offset = (y1 >> 16) * pixbpl + (x1 >> 16); pixel = cmap[pixels[offset]].pixel; *p = mix_alpha8(*p, pixel, b->alpha_buf[offset]); } x1 += dx; y1 += dy; p++; n--; } #endif } } /* XXX: clipping should be better handled */ void GraphicDevice8::fillLineLG(Gradient *grad, long y, long start, long end) { long dr,r,v,r2; register long n; TYPE *line; TYPE *point; Color *cp,*ramp; Matrix *m = &grad->imat; unsigned int start_alpha,end_alpha; if (clip(y,start,end)) return; start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); start /= FRAC; end /= FRAC; n = end-start; #if 1 #define SHIFTIT 10 r = (((long)m->a) >> 6) * start + (((long)m->b) >> 6) * y + (m->tx >> 6); dr = ((long)(m->a)) >> 6; #else #define SHIFTIT 16 r = (long) (m->a * start + m->b * y + m->tx); dr = (long) (m->a); #endif ramp = grad->ramp; line = (TYPE *)(canvasBuffer + bpl*y); point = &line[start]; r2 = r + n * dr; if ( ((r | r2) & ~255) == 0 ) { if (!grad->has_alpha) { #ifdef FULL_AA if (start_alpha < 255) { v = r>>SHIFTIT; *point = mix_alpha8(*point, (TYPE)ramp[v].pixel, start_alpha); point++; r += dr; n--; } #endif /* FULL_AA */ #ifdef HBP r = fill_line_ramp_opaque8(point, n, ramp, r, dr); point += n; #else while (n>0) { v = r>>SHIFTIT; *point = (TYPE)ramp[v].pixel; point++; r += dr; n--; } #endif #ifdef FULL_AA if (end_alpha > 0) { v = r>>SHIFTIT; *point = mix_alpha8(*point, (TYPE)ramp[v].pixel, end_alpha); } #endif /* FULL_AA */ } else { #ifdef HBP fill_line_ramp8(point, n, ramp, r, dr); #else while (n--) { v = r>>SHIFTIT; cp = &ramp[v]; *point = mix_alpha8(*point, cp->pixel, cp->alpha); point++; r += dr; } #endif } } else { if (!grad->has_alpha) { #ifdef FULL_AA if (start_alpha < 255) { v = r>>SHIFTIT; if (v < 0) v = 0; else if (v > 255) v = 255; *point = mix_alpha8(*point, (TYPE)ramp[v].pixel, start_alpha); point++; r += dr; n--; } #endif /* FULL_AA */ #ifdef HBP r = fill_line_ramp_2_opaque8(point, n, ramp, r, dr); point += n; #else while (n>0) { v = r>>SHIFTIT; if (v < 0) v = 0; else if (v > 255) v = 255; *point = (TYPE)ramp[v].pixel; point++; r += dr; n--; } #endif #ifdef FULL_AA if (end_alpha > 0) { v = r>>SHIFTIT; if (v < 0) v = 0; else if (v > 255) v = 255; *point = mix_alpha8(*point, (TYPE)ramp[v].pixel, end_alpha); } #endif /* FULL_AA */ } else { #ifdef HBP fill_line_ramp_2_8(point, n, ramp, r, dr); #else while (n--) { v = r>>SHIFTIT; if (v < 0) v = 0; else if (v > 255) v = 255; cp = &ramp[v]; *point = mix_alpha8(*point, cp->pixel, cp->alpha); point++; r += dr; } #endif } } } ///////////// PLATFORM INDEPENDENT void GraphicDevice8::fillLineRG(Gradient *grad, long y, long start, long end) { long X,dx,r,Y,dy; long dist2; register long n; Color *cp,*ramp; TYPE *line; TYPE *point; Matrix *m = &grad->imat; unsigned int start_alpha,end_alpha; if (clip(y,start,end)) return; start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS)); end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS); start /= FRAC; end /= FRAC; n = end-start; #if 1 X = ((((long)m->a >> 10 ) * start + (((long)m->b) >> 10) * y) << 10) + m->tx; Y = ((((long)m->c >> 10 ) * start + (((long)m->d) >> 10) * y) << 10) + m->ty; #else X = (long) (m->a * start + m->b * y + m->tx); Y = (long) (m->c * start + m->d * y + m->ty); #endif dx = (long) (m->a); dy = (long) (m->c); ramp = grad->ramp; line = (TYPE *)(canvasBuffer + bpl*y); point = &line[start]; if (!grad->has_alpha) { #ifdef FULL_AA if (start == end) { dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); if ((unsigned long)dist2 >= 65536) { r = 255; } else { r= SQRT[dist2]; } *point = mix_alpha8(*point, (TYPE)ramp[r].pixel, start_alpha + end_alpha - 255); } else { if (start_alpha < 255) { dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); if ((unsigned long)dist2 >= 65536) { r = 255; } else { r= SQRT[dist2]; } *point = mix_alpha8(*point, (TYPE)ramp[r].pixel, start_alpha); point++; X += dx; Y += dy; n--; } #endif /* FULL_AA */ #ifdef HBP fill_line_radial_ramp8(point, n, &X, &Y, dx, dy, ramp, SQRT); point += n; #else while (n>0) { dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); if ((unsigned long)dist2 >= 65536) { r = 255; } else { r= SQRT[dist2]; } *point = (TYPE)ramp[r].pixel; point++; X += dx; Y += dy; n--; } #endif #ifdef FULL_AA if (end_alpha > 0) { dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); if ((unsigned long)dist2 >= 65536) { r = 255; } else { r= SQRT[dist2]; } *point = mix_alpha8(*point, (TYPE)ramp[r].pixel, end_alpha); } } #endif /* FULL_AA */ } else { #ifdef HBP fill_line_radial_ramp_2_8(point, n, &X, &Y, dx, dy, ramp, SQRT); point += n; #else while (n--) { dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16)); if ((unsigned long)dist2 >= 65536) { r = 255; } else { r= SQRT[dist2]; } cp = &ramp[r]; *point = mix_alpha8(*point, cp->pixel, cp->alpha); point++; X += dx; Y += dy; } #endif } } /* XXX: should use polygon rasterizer to handle width */ /* XXX: handle only 16 bit case */ /* XXX: must be clipped */ void GraphicDevice8::drawLine(long x1, long y1, long x2, long y2, long width) { int n,adr,dx,dy,sx,color; register int a; register unsigned short *pp; int alpha; #if 0 x1 = (x1 + (FRAC/2)) >> FRAC_BITS; y1 = (y1 + (FRAC/2)) >> FRAC_BITS; x2 = (x2 + (FRAC/2)) >> FRAC_BITS; y2 = (y2 + (FRAC/2)) >> FRAC_BITS; #else x1 = (x1) >> FRAC_BITS; y1 = (y1) >> FRAC_BITS; x2 = (x2) >> FRAC_BITS; y2 = (y2) >> FRAC_BITS; #endif if (y1 > y2 || (y1 == y2 && x1 > x2)) { long tmp; tmp=x1; x1=x2; x2=tmp; tmp=y1; y1=y2; y2=tmp; } if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return; if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return; if (x1 == x2 && y1 == y2) return; // Bad !!! if (y1 < clip_rect.ymin && y1 != y2) { x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1); y1 = clip_rect.ymin; } if (y2 > clip_rect.ymax && y1 != y2) { x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1); y2 = clip_rect.ymax; } if (x1 < x2) { if (x1 < clip_rect.xmin && x1 != x2) { y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1); x1 = clip_rect.xmin; } if (x2 > clip_rect.xmax && x1 != x2) { y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1); x2 = clip_rect.xmax; } } if (x1 > x2) { if (x2 < clip_rect.xmin && x2 != x1) { y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2); x2 = clip_rect.xmin; } if (x1 > clip_rect.xmax && x2 != x1) { y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2); x1 = clip_rect.xmax; } } // Check again if (x1 == x2 && y1 == y2) return; if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return; if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return; if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return; if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return; sx=bpl >> 1; adr=(y1 * sx + x1); pp = (unsigned short *)canvasBuffer + adr; dx = x2 - x1; dy = y2 - y1; #if defined(RISCOS) color = allocColor(foregroundColor); #else color = allocColor16_565(foregroundColor); #endif alpha = foregroundColor.alpha; if (alpha == ALPHA_OPAQUE) { #define PUTPIXEL() \ { \ *pp=color; \ } #define DRAWLINE(dx,dy,inc_1,inc_2) \ n=dx;\ a=2*dy-dx;\ dy=2*dy;\ dx=2*dx-dy;\ do {\ PUTPIXEL();\ if (a>0) { pp+=(inc_1); a-=dx; }\ else { pp+=(inc_2); a+=dy; }\ } while (--n >= 0); /* fin macro */ if (dx == 0 && dy == 0) { PUTPIXEL(); } else if (dx > 0) { if (dx >= dy) { DRAWLINE(dx, dy, sx + 1, 1); } else { DRAWLINE(dy, dx, sx + 1, sx); } } else { dx = -dx; if (dx >= dy) { DRAWLINE(dx, dy, sx - 1, -1); } else { DRAWLINE(dy, dx, sx - 1, sx); } } #undef DRAWLINE #undef PUTPIXEL } else { #define PUTPIXEL() \ { \ *pp=mix_alpha8(*pp,color,alpha); \ } #define DRAWLINE(dx,dy,inc_1,inc_2) \ n=dx;\ a=2*dy-dx;\ dy=2*dy;\ dx=2*dx-dy;\ do {\ PUTPIXEL();\ if (a>0) { pp+=(inc_1); a-=dx; }\ else { pp+=(inc_2); a+=dy; }\ } while (--n >= 0); /* fin macro */ if (dx == 0 && dy == 0) { PUTPIXEL(); } else if (dx > 0) { if (dx >= dy) { DRAWLINE(dx, dy, sx + 1, 1); } else { DRAWLINE(dy, dx, sx + 1, sx); } } else { dx = -dx; if (dx >= dy) { DRAWLINE(dx, dy, sx - 1, -1); } else { DRAWLINE(dy, dx, sx - 1, sx); } } #undef DRAWLINE #undef PUTPIXEL } }