summaryrefslogtreecommitdiff
path: root/core/multimedia/opieplayer/libflash/graphic.cc
Side-by-side diff
Diffstat (limited to 'core/multimedia/opieplayer/libflash/graphic.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libflash/graphic.cc632
1 files changed, 632 insertions, 0 deletions
diff --git a/core/multimedia/opieplayer/libflash/graphic.cc b/core/multimedia/opieplayer/libflash/graphic.cc
new file mode 100644
index 0000000..f65011e
--- a/dev/null
+++ b/core/multimedia/opieplayer/libflash/graphic.cc
@@ -0,0 +1,632 @@
+////////////////////////////////////////////////////////////
+// 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"
+
+#ifdef RCSID
+static char *rcsid = "$Id$";
+#endif
+
+#define PRINT 0
+
+// Public
+
+GraphicDevice::GraphicDevice(FlashDisplay *fd)
+{
+ flashDisplay = fd;
+
+ bgInitialized = 0;
+
+ // Reset flash refresh flag
+ flashDisplay->flash_refresh = 0;
+
+ /* 16 bits, RGB565 */
+ redMask = 0xF800;
+ greenMask = 0x07E0;
+ blueMask = 0x001F;
+
+ /* should be the actual window size */
+ targetWidth = fd->width;
+ targetHeight = fd->height;
+ bpl = fd->bpl;
+
+#if PRINT
+ printf("Target Width = %d\n", targetWidth);
+ printf("Target Height = %d\n", targetHeight);
+#endif
+
+ zoom = FRAC;
+ movieWidth = targetWidth;
+ movieHeight = targetHeight;
+
+ viewPort.xmin = 0;
+ viewPort.xmax = targetWidth-1;
+ viewPort.ymin = 0;
+ viewPort.ymax = targetHeight-1;
+
+ canvasBuffer = (unsigned char *) fd->pixels;
+
+ adjust = new Matrix;
+ foregroundColor.red = 0;
+ foregroundColor.green = 0;
+ foregroundColor.blue = 0;
+ foregroundColor.alpha = ALPHA_OPAQUE;
+
+ backgroundColor.red = 0;
+ backgroundColor.green = 0;
+ backgroundColor.blue = 0;
+ backgroundColor.alpha = ALPHA_OPAQUE;
+
+ showMore = 0;
+
+ setClipping(0); // Reset
+ setClipping(1);
+
+ /* polygon rasterizer : handle memory errors ! */
+
+ height = targetHeight;
+ segs = (Segment **)malloc(height * sizeof(Segment *));
+ memset(segs, 0, height * sizeof(Segment *));
+ ymin = height;
+ ymax = -1;
+
+ seg_pool = (Segment *)malloc(NB_SEGMENT_MAX * sizeof(Segment));
+ seg_pool_cur = seg_pool;
+}
+
+GraphicDevice::~GraphicDevice()
+{
+ free(segs);
+ free(seg_pool);
+
+ if (adjust) {
+ delete adjust;
+ }
+}
+
+Color *
+GraphicDevice::getColormap(Color *old, long n, Cxform *cxform)
+{
+ Color *newCmp;
+
+ newCmp = new Color[n];
+ if (newCmp == NULL) return NULL;
+
+ if (cxform) {
+ for(long i = 0; i < n; i++)
+ {
+ newCmp[i] = cxform->getColor(old[i]);
+ newCmp[i].pixel = allocColor(newCmp[i]);
+ }
+ } else {
+ for(long i = 0; i < n; i++)
+ {
+ newCmp[i] = old[i];
+ newCmp[i].pixel = allocColor(old[i]);
+ }
+ }
+
+ return newCmp;
+}
+
+long
+GraphicDevice::getHeight()
+{
+ return targetHeight;
+}
+
+long
+GraphicDevice::getWidth()
+{
+ return targetWidth;
+}
+
+Color
+GraphicDevice::getForegroundColor()
+{
+ return foregroundColor;
+}
+
+void
+GraphicDevice::setForegroundColor(Color color)
+{
+ foregroundColor = color;
+}
+
+Color
+GraphicDevice::getBackgroundColor()
+{
+ return backgroundColor;
+}
+
+int
+GraphicDevice::setBackgroundColor(Color color)
+{
+ if (bgInitialized == 0) {
+ backgroundColor = color;
+ clearCanvas();
+ bgInitialized = 1;
+ return 1;
+ }
+ return 0;
+}
+
+void
+GraphicDevice::setMovieDimension(long width, long height)
+{
+ float xAdjust, yAdjust;
+
+ movieWidth = width;
+ movieHeight = height;
+
+ xAdjust = (float)targetWidth*zoom/(float)width;
+ yAdjust = (float)targetHeight*zoom/(float)height;
+
+ if (xAdjust < yAdjust) {
+ adjust->a = xAdjust;
+ adjust->d = xAdjust;
+ adjust->ty = ((targetHeight*zoom) - (long)(height * xAdjust))/2;
+ viewPort.ymin = adjust->ty/zoom;
+ viewPort.ymax = targetHeight-viewPort.ymin-1;
+ } else {
+ adjust->a = yAdjust;
+ adjust->d = yAdjust;
+ adjust->tx = ((targetWidth*zoom) - (long)(width * yAdjust))/2;
+ viewPort.xmin = adjust->tx/zoom;
+ viewPort.xmax = targetWidth-viewPort.xmin-1;
+ }
+
+ if (viewPort.xmin < 0) viewPort.xmin = 0;
+ if (viewPort.ymin < 0) viewPort.ymin = 0;
+ if (viewPort.xmax >= targetWidth) viewPort.xmax = targetWidth-1;
+ if (viewPort.ymax >= targetHeight) viewPort.ymax = targetHeight-1;
+}
+
+void
+GraphicDevice::setMovieZoom(int z)
+{
+ z *= FRAC;
+ if (z <= 0 || z > 100) return;
+ zoom = z;
+ setMovieDimension(movieWidth,movieHeight);
+}
+
+void
+GraphicDevice::setMovieOffset(long x, long y)
+{
+ adjust->tx = -zoom*x;
+ adjust->ty = -zoom*y;
+}
+
+long
+GraphicDevice::clip(long &y, long &start, long &end)
+{
+ long xmin,xend;
+
+ if (y < clip_rect.ymin ||
+ y >= clip_rect.ymax) return 1;
+ if (end <= start)
+ return 1;
+ xmin = clip_rect.xmin * FRAC;
+ xend = clip_rect.xmax * FRAC;
+
+ if (end <= xmin || start >= xend) return 1;
+
+ if (start < xmin) start = xmin;
+ if (end > xend) end = xend;
+
+ return 0;
+}
+
+void
+GraphicDevice::drawBox(long x1, long y1, long x2, long y2)
+{
+ int i;
+
+ for(i=0;i<FRAC*2;i++) {
+ drawLine(x1+i, y1+i, x2-i, y1+i, 0);
+ drawLine(x1+i, y2-i, x2-i, y2-i, 0);
+
+ drawLine(x1+i, y1+i+1, x1+i, y2-i-1, 0);
+ drawLine(x2-i, y1+i+1, x2-i, y2-i-1, 0);
+ }
+}
+
+/* polygon rasteriser */
+
+inline Segment *
+GraphicDevice::allocSeg()
+{
+ Segment *seg;
+
+ if ( (seg_pool_cur - seg_pool) >= NB_SEGMENT_MAX )
+ return NULL;
+ seg = seg_pool_cur++;
+
+ return seg;
+}
+
+/* add a segment to the current path */
+void
+GraphicDevice::addSegment(long x1, long y1, long x2, long y2,
+ FillStyleDef *f0,
+ FillStyleDef *f1,
+ int aa)
+{
+ Segment *seg,**segs;
+ long dX, X, Y, ymin, ymax, tmp;
+ FillStyleDef *ff;
+
+ if ( y1 == y2 ) {
+ return;
+ }
+
+ if (y1 < y2) {
+ ymin = y1;
+ ymax = y2;
+ ff = f0;
+ f0 = f1;
+ f1 = ff;
+ } else {
+ ymin = y2;
+ ymax = y1;
+ tmp = x1;
+ x1 = x2;
+ x2 = tmp;
+ }
+
+ if (ymax>>FRAC_BITS < clip_rect.ymin) {
+ return;
+ }
+ if (ymin>>FRAC_BITS > clip_rect.ymax) {
+ return;
+ }
+
+ X = x1 << SEGFRAC;
+ dX = ((x2 - x1)<<SEGFRAC)/(ymax-ymin);
+
+ if (ymin < 0) {
+ X += dX * (-ymin);
+ ymin = 0;
+ }
+
+ Y = (ymin + (FRAC-1)) & ~(FRAC-1);
+ if (Y > ymax) {
+ //printf("Elimine @ y = %d ymin = %d, ymax = %d\n", Y, ymin, seg->ymax);
+ return;
+ }
+ X += dX * (Y-ymin);
+
+ Y >>= FRAC_BITS;
+ if (Y >= clip_rect.ymax) {
+ return;
+ }
+
+ seg = allocSeg();
+ if (seg == NULL) {
+ return;
+ }
+
+ seg->next = 0;
+ seg->nextValid = 0;
+ seg->aa = aa;
+ seg->ymax = ymax;
+ seg->x1 = x1;
+ seg->x2 = x2;
+ seg->X = X;
+ seg->dX = dX;
+ seg->fs[0] = f0;
+ seg->fs[1] = f1;
+
+ if (Y < this->ymin) this->ymin = Y;
+ ymax = (seg->ymax + FRAC - 1) >> FRAC_BITS;
+ if (ymax >= this->height) ymax = this->height-1;
+ if (ymax > this->ymax) this->ymax = ymax;
+
+ segs = this->segs;
+
+ if (segs[Y] == 0) {
+ segs[Y] = seg;
+ } else {
+ Segment *s,*prev;
+
+ prev = 0;
+ for(s = segs[Y]; s; prev = s, s = s->next) {
+ if (s->X > seg->X) {
+ if (prev) {
+ prev->next = seg;
+ seg->next = s;
+ } else {
+ seg->next = segs[Y];
+ segs[Y] = seg;
+ }
+ break;
+ }
+ }
+ if (s == 0) {
+ prev->next = seg;
+ seg->next = s;
+ }
+ }
+}
+
+inline Segment *
+GraphicDevice::progressSegments(Segment * curSegs, long y)
+{
+ Segment *seg,*prev;
+
+ // Update current segments
+ seg = curSegs;
+ prev = 0;
+ while(seg)
+ {
+ if ((y*FRAC) > seg->ymax) {
+ // Remove this segment, no more valid
+ if (prev) {
+ prev->nextValid = seg->nextValid;
+ } else {
+ curSegs = seg->nextValid;
+ }
+ seg = seg->nextValid;
+ } else {
+ seg->X += seg->dX * FRAC;
+ prev = seg;
+ seg = seg->nextValid;
+ }
+ }
+ return curSegs;
+}
+
+inline Segment *
+GraphicDevice::newSegments(Segment *curSegs, Segment *newSegs)
+{
+ Segment *s,*seg,*prev;
+
+ s = curSegs;
+ prev = 0;
+
+ // Check for new segments
+ for (seg = newSegs; seg; seg=seg->next)
+ {
+ // Place it at the correct position according to X
+ if (curSegs == 0) {
+ curSegs = seg;
+ seg->nextValid = 0;
+ } else {
+ for(; s; prev = s, s = s->nextValid)
+ {
+ if ( s->X > seg->X ||
+ ( (s->X == seg->X) &&
+ ( (seg->x1 == s->x1 && seg->dX < s->dX) ||
+ (seg->x2 == s->x2 && seg->dX > s->dX)
+ ))) {
+ // Insert before s
+ if (prev) {
+ seg->nextValid = s;
+ prev->nextValid = seg;
+ } else {
+ seg->nextValid = curSegs;
+ curSegs = seg;
+ }
+ break;
+ }
+ }
+ // Append at the end
+ if (s == 0) {
+ prev->nextValid = seg;
+ seg->nextValid = 0;
+ }
+ }
+
+ s = seg;
+ }
+
+ return curSegs;
+}
+
+#if 0
+static void
+printSeg(Segment *seg)
+{
+ /*
+ printf("Seg %08x : X = %5d, Ft = %d, Cl = %2x/%2x/%2x, Cr = %2x/%2x/%2x, x1=%5d, x2=%5d, ymin=%5d, ymax=%5d\n", seg,
+ seg->X>>SEGFRAC,
+ seg->right ? seg->right->type: -1,
+ seg->left ? seg->left->color.red : -1,
+ seg->left ? seg->left->color.green : -1,
+ seg->left ? seg->left->color.blue : -1,
+ seg->right ? seg->right->color.red : -1,
+ seg->right ? seg->right->color.green : -1,
+ seg->right ? seg->right->color.blue : -1,
+ seg->x1, seg->x2, seg->ymin, seg->ymax);
+ */
+}
+#endif
+
+inline void
+GraphicDevice::renderScanLine(long y, Segment *curSegs)
+{
+ Segment *seg;
+ long width;
+ int fi = 1;
+ FillStyleDef *f;
+
+ width = targetWidth * FRAC;
+
+ if (curSegs && curSegs->fs[0] && curSegs->fs[1] == 0) {
+ fi = 0;
+ }
+ for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid)
+ {
+ if (seg->nextValid->X <0) continue;
+ if ((seg->X>>SEGFRAC) > width) break;
+ f = seg->fs[fi];
+ if (f) {
+ switch (f->type) {
+ case f_Solid:
+ if (seg->aa) {
+ fillLineAA(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
+ } else {
+ fillLine(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
+ }
+ break;
+ case f_TiledBitmap:
+ case f_clippedBitmap:
+ fillLineBitmap(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
+ break;
+ case f_LinearGradient:
+ fillLineLG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
+ break;
+ case f_RadialGradient:
+ fillLineRG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
+ break;
+ case f_None:
+ break;
+ }
+ }
+ }
+}
+
+/* draw the current path */
+void
+GraphicDevice::drawPolygon(void)
+{
+ long y;
+ Segment *curSegs,*seg;
+
+ // no segments ?
+ if (this->ymax == -1)
+ return;
+
+ // Foreach scanline
+ curSegs = 0;
+ for(y=this->ymin; y <= this->ymax; y++) {
+
+ // Make X values progess and remove unuseful segments
+ curSegs = progressSegments(curSegs, y);
+
+ // Add the new segment starting at the y position.
+ curSegs = newSegments(curSegs, this->segs[y]);
+
+ // Render the scanline
+ if (this->scan_line_func == NULL) {
+ renderScanLine(y, curSegs);
+ } else {
+ for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid) {
+ if (seg->nextValid->X >= seg->X) {
+ scan_line_func(this->scan_line_func_id, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
+ }
+ }
+ }
+ }
+
+ /* free the segments */
+ memset(this->segs + this->ymin, 0,
+ (this->ymax - this->ymin + 1) * sizeof(Segment *));
+
+ this->ymax = -1;
+ this->ymin = this->height;
+
+ this->seg_pool_cur = this->seg_pool;
+}
+
+void
+GraphicDevice::updateClippingRegion(Rect *rect)
+{
+ if (!clipping) return;
+
+ transformBoundingBox(&clip_rect, adjust, rect, 1);
+ clip_rect.xmin >>= FRAC_BITS;
+ clip_rect.xmax >>= FRAC_BITS;
+ clip_rect.ymin >>= FRAC_BITS;
+ clip_rect.ymax >>= FRAC_BITS;
+
+ clip_rect.xmin-=2;
+ clip_rect.ymin-=2;
+ clip_rect.xmax+=2;
+ clip_rect.ymax+=2;
+
+ if (clip_rect.xmin < viewPort.xmin) clip_rect.xmin = viewPort.xmin;
+ if (clip_rect.xmax < viewPort.xmin) clip_rect.xmax = viewPort.xmin;
+ if (clip_rect.ymin < viewPort.ymin) clip_rect.ymin = viewPort.ymin;
+ if (clip_rect.ymax < viewPort.ymin) clip_rect.ymax = viewPort.ymin;
+
+ if (clip_rect.xmax > viewPort.xmax) clip_rect.xmax = viewPort.xmax;
+ if (clip_rect.ymax > viewPort.ymax) clip_rect.ymax = viewPort.ymax;
+ if (clip_rect.xmin > viewPort.xmax) clip_rect.xmin = viewPort.xmax;
+ if (clip_rect.ymin > viewPort.ymax) clip_rect.ymin = viewPort.ymax;
+}
+
+void
+GraphicDevice::setClipping(int value)
+{
+ clipping = value;
+ if (clipping == 0) {
+ // Reset region
+ clip_rect.xmin = viewPort.xmin;
+ clip_rect.xmax = viewPort.xmax;
+ clip_rect.ymin = viewPort.ymin;
+ clip_rect.ymax = viewPort.ymax;
+ }
+}
+
+// Virtual
+void
+GraphicDevice::clearCanvas()
+{
+}
+
+long
+GraphicDevice::allocColor(Color color)
+{
+ return 0;
+}
+
+void
+GraphicDevice::fillLineBitmap(FillStyleDef *f, long y, long start, long end)
+{
+}
+
+void
+GraphicDevice::fillLineLG(Gradient *grad, long y, long start, long end)
+{
+}
+
+void
+GraphicDevice::fillLineRG(Gradient *grad, long y, long start, long end)
+{
+}
+
+void
+GraphicDevice::fillLine(FillStyleDef *f, long y, long start, long end)
+{
+}
+
+void
+GraphicDevice::fillLineAA(FillStyleDef *f, long y, long start, long end)
+{
+}
+
+void
+GraphicDevice::drawLine(long x1, long y1, long x2, long y2, long width)
+{
+}