dslinux/user/pixil/packages/flash/flash/Lib Makefile adpcm.cc adpcm.h bitmap.cc bitmap.h button.cc button.h character.cc character.h cxform.cc cxform.h displaylist.cc displaylist.h flash.cc flash.h font.cc font.h graphic.cc graphic.h graphic16.cc graphic16.h graphic24.cc graphic24.h graphic32.cc graphic32.h graphic_generic.cc matrix.cc matrix.h movie.cc movie.h mp3.cc mp3.h program.cc program.h rect.h script.cc script.h shape.cc shape.h sound.cc sound.h sprite.cc sprite.h sqrt.cc sqrt.h swf.h text.cc text.h

amadeus dslinux_amadeus at user.in-berlin.de
Tue Oct 3 13:26:12 CEST 2006


Update of /cvsroot/dslinux/dslinux/user/pixil/packages/flash/flash/Lib
In directory antilope:/tmp/cvs-serv11916/packages/flash/flash/Lib

Added Files:
	Makefile adpcm.cc adpcm.h bitmap.cc bitmap.h button.cc 
	button.h character.cc character.h cxform.cc cxform.h 
	displaylist.cc displaylist.h flash.cc flash.h font.cc font.h 
	graphic.cc graphic.h graphic16.cc graphic16.h graphic24.cc 
	graphic24.h graphic32.cc graphic32.h graphic_generic.cc 
	matrix.cc matrix.h movie.cc movie.h mp3.cc mp3.h program.cc 
	program.h rect.h script.cc script.h shape.cc shape.h sound.cc 
	sound.h sprite.cc sprite.h sqrt.cc sqrt.h swf.h text.cc text.h 
Log Message:
adding pristine copy of pixil to HEAD so I can branch from it

--- NEW FILE: flash.h ---
/*///////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////// */
#ifndef _FLASH_H_
#define _FLASH_H_

#define PLUGIN_NAME "Shockwave Flash"
#define FLASH_VERSION_STRING "Version 0.4.10"

/* Flags to pass to FlashExec */
#define FLASH_WAKEUP 0x01
#define FLASH_EVENT  0x02
#define FLASH_CMD    0x04

/* Mask to extract commands */
#define FLASH_CMD_MASK 0xf0
/* Commands */
#define FLASH_STOP     0x10	/* Pause the movie */
#define FLASH_CONT     0x20	/* Continue the movie after pause */
#define FLASH_REWIND   0x30	/* Rewind the movie and pause */
#define FLASH_STEP     0x40	/* Frame by frame operation */

/* return codes of FlashExec */
#define FLASH_STATUS_WAKEUP   0x01    /* FlashExec must be called again after a given time */

struct FlashInfo {
	long frameRate;
	long frameCount;
	long frameWidth;
	long frameHeight;
	long version;
};

/* Player settings */
#define PLAYER_LOOP	(1<<0)
#define PLAYER_QUALITY	(1<<1)
#define PLAYER_MENU	(1<<2)

/* Parser status */
#define FLASH_PARSE_ERROR     0
#define FLASH_PARSE_START     1
#define FLASH_PARSE_NEED_DATA 2
#define FLASH_PARSE_EOM       4
#define FLASH_PARSE_WAKEUP    8
#define FLASH_PARSE_OOM       16      /* Out Of Memory */

typedef void *FlashHandle;

#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif

enum FlashEventType {
    FeNone,
    FeMouseMove,
    FeButtonPress,
    FeButtonRelease,
    FeRefresh,
    FeKeyPress,
    /* internal events */
    FeKeyRelease
};

enum FlashKey {
    FeKeyUp = 1,
    FeKeyDown,
    FeKeyLeft,
    FeKeyRight,
    FeKeyEnter,
    FeKeyNext
};



typedef struct FlashEvent {
    enum FlashEventType type;
    int		 x,y;		/* Mouse coordinates, 
                                   relative to upper-left window corner */
    enum FlashKey key;
} FlashEvent;

typedef struct FlashDisplay {
    void *pixels;
    int bpl;      /* bytes per line */
    int width;
    int height;
    int depth;
    int bpp;
    int flash_refresh;
    /* Clipping region */
    int clip_x, clip_y;
    int clip_width, clip_height;
} FlashDisplay;

extern FlashHandle FlashNew();
extern void FlashGetInfo(FlashHandle fh, struct FlashInfo *fi);
extern long FlashGraphicInit(FlashHandle fh, FlashDisplay *fd);
extern void FlashSoundInit(FlashHandle fh, char *device);
extern int  FlashParse(FlashHandle fh, int level, char *data, long size);
extern long FlashExec(FlashHandle fh, long flag, FlashEvent *fe, struct timeval *wakeDate);
extern void FlashClose(FlashHandle fh);
extern void FlashSetGetUrlMethod(FlashHandle flashHandle, void (*getUrl)(char *, char *, void *), void *);
extern void FlashSetGetSwfMethod(FlashHandle flashHandle, void (*getSwf)(char *url, int level, void *clientData), void *clientData);
extern void FlashSetCursorOnOffMethod(FlashHandle flashHandle, void (*cursorOnOff)(int , void *), void *clientData);
extern void FlashZoom(FlashHandle fh, int zoom);
extern void FlashOffset(FlashHandle fh, int x, int y);
extern void FlashSettings(FlashHandle fh, long settings);

#if defined(__cplusplus) || defined(c_plusplus)
};
#endif

#endif /* _FLASH_H_ */

--- NEW FILE: graphic16.h ---
////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

class GraphicDevice16: public GraphicDevice {
private:
	long GraphicDevice16::allocColor(Color color);

public:
	GraphicDevice16(FlashDisplay *fd);

	void clearCanvas();
	void fillLineAA(FillStyleDef *f, long y, long start, long end);
	void fillLine(FillStyleDef *f, long y, long start, long end);
	void fillLineBitmap(FillStyleDef *f, long y, long start, long end);
	void fillLineLG(Gradient *grad, long y, long start, long end);
	void fillLineRG(Gradient *grad, long y, long start, long end);
	void drawLine(long x1, long y1, long x2, long y2, long width);
};

--- NEW FILE: graphic.cc ---
////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: graphic.cc,v 1.1 2006-10-03 11:26:09 dslinux_amadeus Exp $";
#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)
{
}

--- NEW FILE: script.h ---
#ifndef _SCRIPT_H_
#define _SCRIPT_H_

// SWF file parser.
//
//////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////
// Input script object definition.
//////////////////////////////////////////////////////////////////////

// An input script object.  This object represents a script created from 
// an external file that is meant to be inserted into an output script.
struct CInputScript  : public Dict
{
    int level;
    struct CInputScript *next;

    Program *program;	// Current parsed program

        // Memory fences
	int  outOfMemory;

	//Flash info
	long frameRate;
	long frameCount;
	Rect frameRect;

	// Pointer to file contents buffer.
	U8 *m_fileBuf;

	// File state information.
	U32 m_filePos;
	U32 m_fileSize;
	U32 m_actualSize;
	U32 m_fileStart;
	U16 m_fileVersion;

	int needHeader;

	// Bit Handling
	S32 m_bitPos;
	U32 m_bitBuf;

	// Tag parsing information.
	U32 m_tagStart;
	U32 m_tagEnd;
	U32 m_tagLen;

	// Parsing information.
	S32 m_nFillBits;
	S32 m_nLineBits;
	S32 m_nGlyphBits;
	S32 m_nAdvanceBits;

	// Set to true if we wish to dump all contents long form
	U32 m_dumpAll;

	// if set to true will dump image guts (i.e. jpeg, zlib, etc. data)
	U32 m_dumpGuts;

	// Handle to output file.
	FILE *m_outputFile;

	// Constructor/destructor.
	CInputScript(int level = 0);
	~CInputScript();

	// Tag scanning methods.
	U16 GetTag(void);
	U8 GetByte(void);
	U16 GetWord(void);
	U32 GetDWord(void);
	void GetRect(Rect *r);
	void GetMatrix(Matrix *matrix);

	void GetCxform(Cxform *cxform, BOOL hasAlpha);
	char *GetString(void);

	// Routines for reading arbitrary sized bit fields from the stream.
	// Always call start bits before gettings bits and do not intermix 
	// these calls with GetByte, etc...	
	void InitBits();
	S32 GetSBits(S32 n);
	U32 GetBits(S32 n);

	// Tag subcomponent parsing methods
	void ParseFillStyle(long getAlpha = 0);
	void ParseLineStyle(long getAlpha = 0);
	int  ParseShapeRecord(long getAlpha = 0);
	ButtonRecord *  ParseButtonRecord(long getCxform = 0);
	ActionRecord *  ParseActionRecord();
	TextRecord   *  ParseTextRecord(int hasAlpha = 0);
        void ParseShapeData(int getAlpha, int getStyles);

	// Parsing methods.
	void ParseEnd();				// 00: stagEnd
	void ParseShowFrame(U32 frame, U32 offset);	// 01: stagShowFrame
	void ParseDefineShape(int level);		// 02: stagDefineShape
	void ParseFreeCharacter();                     	// 03: stagFreeCharacter
	void ParsePlaceObject();			// 04: stagPlaceObject
	void ParseRemoveObject();                      	// 05: stagRemoveObject
	void ParseDefineBits();                        	// 06: stagDefineBits
	void ParseDefineButton();       		//x 07: stagDefineButton
	void ParseJPEGTables();		                // 08: stagJPEGTables
	void ParseSetBackgroundColor();                	// 09: stagSetBackgroundColor
	void ParseDefineFont();         		//x 10: stagDefineFont
	void ParseDefineText(int hasAplha);    		//x 11: stagDefineText    33: stagDefineText2
	void ParseDoAction();                          	// 12: stagDoAction	
	void ParseDefineFontInfo();     		//x 13: stagDefineFontInfo
	void ParseDefineSound();                       	// 14: stagDefineSound
	void ParseStartSound();                        	// 15: stagStartSound
	void ParseStopSound();                         	// 16: stagStopSound
	void ParseDefineButtonSound();                 	// 17: stagDefineButtonSound
	void ParseSoundStreamHead(); 	               	// 18: stagSoundStreamHead
	void ParseSoundStreamBlock();                  	// 19: stagSoundStreamBlock
	void ParseDefineBitsLossless(int level);       	// 20: stagDefineBitsLossless 36: stagDefineBitsLossless2
	void ParseDefineBitsJPEG2();                   	// 21: stagDefineBitsJPEG2
	void ParseDefineButtonCxform();	            	// 23: stagDefineButtonCxform
	void ParseProtect();           	            	// 24: stagProtect
	void ParsePlaceObject2();                      	// 26: stagPlaceObject2
	void ParseRemoveObject2();                     	// 28: stagRemoveObject2
	void ParseDefineButton2();      		//x 34: stagDefineButton2
	void ParseDefineBitsJPEG3();                   	// 35: stagDefineBitsJPEG3
	void ParseDefineMouseTarget();                 	// 38: stagDefineMouseTarget
	void ParseDefineSprite();       		//x 39: stagDefineSprite
	void ParseNameCharacter();                     	// 40: stagNameCharacter
	void ParseFrameLabel();                        	// 43: stagFrameLabel
	void ParseSoundStreamHead2(); 	               	// 45: stagSoundStreamHead2
	void ParseDefineMorphShape();   		//x 46: stagDefineMorphShape
	void ParseDefineFont2();        		//x 48: stagDefineFont2
	void ParseUnknown(long,long);

	void ParseTags(int *);
	int  ParseData(FlashMovie *movie, char * data, long size);
	void S_DumpImageGuts();

#ifdef DUMP
	long save(char *filenam);
#endif
};


#endif /* _SCRIPT_H_ */

--- NEW FILE: graphic32.h ---
////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

class GraphicDevice32: public GraphicDevice {
private:
	long GraphicDevice32::allocColor(Color color);

public:
	GraphicDevice32(FlashDisplay *fd);

	void clearCanvas();
	void fillLineAA(FillStyleDef *f, long y, long start, long end);
	void fillLine(FillStyleDef *f, long y, long start, long end);
	void fillLineBitmap(FillStyleDef *f, long y, long start, long end);
	void fillLineLG(Gradient *grad, long y, long start, long end);
	void fillLineRG(Gradient *grad, long y, long start, long end);
	void drawLine(long x1, long y1, long x2, long y2, long width);
};

--- NEW FILE: text.cc ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: text.cc,v 1.1 2006-10-03 11:26:10 dslinux_amadeus Exp $";
#endif

Text::Text(long id) : Character(TextType, id)
{
	textRecords = 0;
}

Text::~Text()
{
	TextRecord     *cur,*del;

	for(cur = textRecords; cur;)
	{
		del = cur;
		cur = cur->next;
		delete del;
	}
}

void
Text::setTextBoundary(Rect rect)
{
	boundary = rect;
}

void
Text::setTextMatrix(Matrix m)
{
	textMatrix = m;
}

void
Text::addTextRecord(TextRecord *tr)
{
	SwfFont *font = 0;
	long n;

	tr->next = 0;

	if (textRecords == 0) {
		textRecords = tr;
		font = tr->font;
	} else {
		TextRecord *current;
		long fontHeight = 0;

		for(current = textRecords; current->next; current = current->next) {
			if (current->flags & textHasFont) {
				font = current->font;
				fontHeight = current->fontHeight;
			}
		}

		current->next = tr;
		if (current->flags & textHasFont) {
			font = current->font;
			fontHeight = current->fontHeight;
		}

		if (tr->flags & textHasFont) {
			font = tr->font;
		} else {
			tr->font = font;
			tr->fontHeight = fontHeight;
		}
	}

	if (tr->nbGlyphs) {
		for(n=0; n < tr->nbGlyphs; n++) {
			tr->glyphs[n].code = font->getGlyphCode(tr->glyphs[n].index);
		}
	}
}

int
Text::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform)
{
	return doText(gd, matrix, cxform, ShapeDraw, NULL, NULL);
}

void
Text::getRegion(GraphicDevice *gd, Matrix *matrix, 
                               void *id, ScanLineFunc scan_line_func)
{
	doText(gd, matrix, 0, ShapeGetRegion, id, scan_line_func);
}

void
Text::getBoundingBox(Rect *bb, DisplayListEntry *e)
{
    *bb =  boundary;
}

TextRecord *
Text::getTextRecords()
{
	return textRecords;
}

int
Text::doText(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, ShapeAction action,
             void *id, ScanLineFunc scan_line_func)
{
	TextRecord	*tr;
	long		 x,y;		// Current position
	SwfFont		*font = 0;	// Current font
	long		 fontHeight;
	Matrix		 tmat,fmat;
	long		 g;

	x = y = 0;
	fontHeight = 0;

	// Compute final text matrix
	tmat = (*matrix) * textMatrix;

	for(tr = textRecords; tr; tr = tr ->next)
	{
		if (tr->flags & isTextControl) {
			if (tr->flags & textHasXOffset) {
				x = tr->xOffset;
			}
			if (tr->flags & textHasYOffset) {
				y = tr->yOffset;
			}
			if (tr->flags & textHasColor) {
				if (action == ShapeDraw) {
					if (cxform) {
						gd->setForegroundColor(cxform->getColor(tr->color));
					} else {
						gd->setForegroundColor(tr->color);
					}
				}
			}
		}

		font = tr->font;
		fontHeight = tr->fontHeight;
		// Update font matrix
		fmat.a = fontHeight/1000.0;
		fmat.d = fontHeight/1000.0;

		assert(font != 0);
		for (g = 0; g < tr->nbGlyphs; g++)
		{
			Shape *shape;
			Matrix cmat;

			shape = font->getGlyph( tr->glyphs[g].index );

#ifdef PRINT
			printf("%c", font->getGlyphCode(tr->glyphs[g].index));
#endif

			// Update font matrix
			fmat.tx = x;
			fmat.ty = y;

			// Compute Character matrix
			cmat = tmat * fmat;

			if (action == ShapeDraw) {
				shape->execute(gd, &cmat, cxform);
			} else {
				shape->getRegion(gd, &cmat, id, scan_line_func);
			}

			// Advance
			x += tr->glyphs[g].xAdvance;
		}
#ifdef PRINT
		printf("\n");
#endif
	}

	if (gd->showMore) {
		tmat = (*gd->adjust) * (*matrix);

		long x1,x2,y1,y2;

		x1 = boundary.xmin;
		y1 = boundary.ymin;
		x2 = boundary.xmax;
		y2 = boundary.ymax;
		gd->drawLine(tmat.getX(x1,y1),tmat.getY(x1,y1),tmat.getX(x2,y1),tmat.getY(x2,y1),FRAC);
		gd->drawLine(tmat.getX(x2,y1),tmat.getY(x2,y1),tmat.getX(x2,y2),tmat.getY(x2,y2),FRAC);
		gd->drawLine(tmat.getX(x2,y2),tmat.getY(x2,y2),tmat.getX(x1,y2),tmat.getY(x1,y2),FRAC);
		gd->drawLine(tmat.getX(x1,y2),tmat.getY(x1,y2),tmat.getX(x1,y1),tmat.getY(x1,y1),FRAC);
	}

	return 0;
}

////////// TextRecord Methods
TextRecord::TextRecord() {
	flags = (TextFlags)0;
	font = 0;
	fontHeight = 0;
	nbGlyphs = 0;
	glyphs = 0;
	xOffset = 0;
	yOffset = 0;
}

TextRecord::~TextRecord() {
	if (nbGlyphs) delete glyphs;
}

char *
TextRecord::getText() {
	static char text[256];
	long g;

	for(g=0; g < nbGlyphs; g++) {
		text[g] = glyphs[g].code;
	}
	text[g] = 0;

	return text;
}

--- NEW FILE: shape.cc ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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.
// 
///////////////////////////////////////////////////////////////
[...1167 lines suppressed...]
                break;
            case f_LinearGradient:
            case f_RadialGradient:
                if (f->gradient.ramp) {
                    delete f->gradient.ramp;
                }
                break;
            case f_TiledBitmap:
            case f_clippedBitmap:
                if (f->bitmap) {
                    if (f->cmap && f->cmap != f->bitmap->colormap) delete f->cmap;
                    if (f->alpha_table) free(f->alpha_table);
                }
                break;
	    case f_None:
	    	break;
        }
    }
}


--- NEW FILE: rect.h ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _RECT_H_
#define _RECT_H_

struct Rect
{
	long xmin;
	long xmax;
	long ymin;
	long ymax;

	long getWidth() {
		return xmax-xmin;
	};

	long getHeight() {
		return ymax-ymin;
	};

	void print() {
		printf("Xmin = %d   Xmax = %d  Ymin = %d  Ymax = %d\n",
				(int)xmin,(int)xmax,(int)ymin,(int)ymax);
	};

	void reset() {
		xmin = LONG_MAX;
		ymin = LONG_MAX;
		xmax = LONG_MIN;
		ymax = LONG_MIN;
	};

#ifdef DUMP
	void dump(BitStream *bs);
#endif
};

#endif /* _RECT_H_ */

--- NEW FILE: character.cc ---
/////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: character.cc,v 1.1 2006-10-03 11:26:08 dslinux_amadeus Exp $";
#endif

///// Character member definitions

Character::Character(ObjectType objectType, long tagid)
{
	type = objectType;
	tagId = tagid;
	name = NULL;
}

Character::~Character()
{
	delete name;
}

int
Character::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform)
{
	printf("Cannot be executed\n");
	return 0;
}

ActionRecord *
Character::eventHandler(GraphicDevice *gd, FlashEvent *ev)
{
	fprintf(stderr,"Unable to handle event !!!\n");
	return 0;
}

int
Character::isButton()
{
	return 0;
}

int
Character::isSprite(void)
{
    return 0;
}

char *
Character::getName()
{
	return name;
}

void
Character::getBoundingBox(Rect *bb, DisplayListEntry *e)
{
    //fprintf(stderr,"Unable to handle getBoundingBox !!!\n");
    bb->xmin = LONG_MAX;
    bb->ymin = LONG_MAX;
    bb->ymax = LONG_MIN;
    bb->ymax = LONG_MIN;
    return;
}

void
Character::getRegion(GraphicDevice *gd, Matrix *matrix, 
                               void *id, ScanLineFunc scan_line_func)
{
	fprintf(stderr,"Unable to handle getRegion !!!\n");
	return;
}

long
Character::getTagId()
{
	return tagId;
}

void
Character::reset()
{
}

ObjectType
Character::getType()
{
	return type;
}

char *
Character::getTypeString()
{
	switch (type) {
		case BitmapType:
			return "Bitmap";
		case FontType:
			return "Font";
		case ButtonType:
			return "Button";
		case SpriteType:
			return "Sprite";
		case ShapeType:
			return "Shape";
		case SoundType:
			return "Sound";
		case TextType:
			return "Text";
		default:
			return "Unknown";
	}
}

void
Character::setName(char* string)
{
	name = strdup(string);
}

///// Dict methods definitions

Dict::Dict()
{
	head = 0;
}

Dict::~Dict()
{
	struct sCharCell *cell,*del;
	
	for(cell = head; cell;)
	{
		del = cell;
		cell = cell->next;
                delete del->elt;
		delete del;
	}
}

void
Dict::addCharacter(Character *character)
{
	struct sCharCell *cell;

	cell = new sCharCell;
	if (cell == NULL) {
		delete character;
		return;
	}
	cell->elt = character;
	cell->next = head;

	head = cell;
}

Character *
Dict::getCharacter(long id)
{
	struct sCharCell *cell;
	
	for(cell = head; cell; cell = cell->next)
	{
		if (id == cell->elt->getTagId()) return cell->elt;
	}
	return 0;
}

void
Dict::dictRewind()
{
	currentCell = head;
}

Character *
Dict::dictNextCharacter()
{
	if (currentCell) {
		struct sCharCell *cell;

		cell = currentCell;
		currentCell = currentCell->next;
		return cell->elt;
	} else {
		return 0;
	}
}

void
Dict::nameCharacter(long id, char *string)
{
        struct sCharCell *cell;

        for(cell = head; cell; cell = cell->next)
        {
                if (cell->elt->getTagId() == id) {
                        cell->elt->setName(string);
                        break;
                }
        }
}

#ifdef DUMP
void
Dict::dictSetUnsaved()
{
	struct sCharCell *cell;
	
	for(cell = head; cell; cell = cell->next)
	{
		cell->elt->saved = 0;
	}
}
#endif

--- NEW FILE: movie.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _MOVIE_H_
#define _MOVIE_H_

#include "swf.h"

struct FlashMovie {
	/* true if a button has been moved */
	int buttons_updated;

	/* current keyboard focus */
	DisplayListEntry 	*cur_focus;

	/* mouse state */
	long mouse_active;
	long mouse_x;
	long mouse_y;
	int button_pressed;

	Button *lost_over;

	/* a button can return to a given state after some time */
	FlashEvent           scheduledEvent;
	struct timeval       scheduledTime;

	int		 refresh;

	CInputScript 	*main;
	long		 msPerFrame;
	GraphicDevice	*gd;
	SoundMixer   	*sm;

	void		(*getUrl)(char *,char *, void *);
	void		*getUrlClientData;

	void		(*getSwf)(char *url, int level, void *clientData);
	void		*getSwfClientData;

	void		(*cursorOnOff)(int , void *);
	void		*cursorOnOffClientData;

	FlashMovie();
	~FlashMovie();
	int		 processMovie(GraphicDevice *gd, SoundMixer *sm);
	int		 handleEvent(GraphicDevice *gd, SoundMixer *sm, FlashEvent *event);
	void 		 renderMovie();
	void 		 renderFocus();
};

#endif /* _MOVIE_H_ */

--- NEW FILE: swf.h ---
#ifndef _SWF_H_
#define _SWF_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <assert.h>
#include <limits.h>

#ifdef DUMP
#include "bitstream.h"
#endif

#include "flash.h"

extern int debug;

// Global Types
typedef unsigned long U32, *P_U32, **PP_U32;
typedef signed long S32, *P_S32, **PP_S32;
typedef unsigned short U16, *P_U16, **PP_U16;
typedef signed short S16, *P_S16, **PP_S16;
typedef unsigned char U8, *P_U8, **PP_U8;
typedef signed char S8, *P_S8, **PP_S8;
typedef signed long SFIXED, *P_SFIXED;
typedef signed long SCOORD, *P_SCOORD;
typedef unsigned long BOOL;

#define ZOOM(v,f) ((v)/(f))

#include "matrix.h"
#include "cxform.h"
#include "rect.h"

#include <sys/time.h>
#define ST struct timeval t1,t2;
#define START gettimeofday(&t1,0)
#define STOP(msg) gettimeofday(&t2,0); printf("%s Delta = %d ms\n", msg, (t2.tv_sec-t1.tv_sec)*1000+(t2.tv_usec-t1.tv_usec)/1000); fflush(stdout);

// Start Sound Flags
enum {
	soundHasInPoint		= 0x01,
	soundHasOutPoint	= 0x02,
	soundHasLoops		= 0x04,
	soundHasEnvelope	= 0x08

	// the upper 4 bits are reserved for synchronization flags
};

// Flags for Sound Format
enum SoundFlags {
	soundIsStereo		   = 0x01,
	soundIs16bit		   = 0x02,
	soundFormatMask		   = 0xf0,
	soundFormatRaw		   = 0x00,
	soundFormatADPCMCompressed = 0x10,
	soundFormatMP3Compressed   = 0x20
};

// Flags for defining Button States
enum ButtonState {
	stateHitTest = 0x08,
	stateDown    = 0x04,
	stateOver    = 0x02,
	stateUp      = 0x01
};

// Actions
enum Action {
		// Internal actions
		ActionRefresh		= 0x00,
		ActionPlaySound		= 0x01,
		// Normal actions
		ActionGotoFrame		= 0x81,
		ActionGetURL		= 0x83,
		ActionNextFrame		= 0x04,
		ActionPrevFrame		= 0x05,
		ActionPlay		= 0x06,
		ActionStop		= 0x07,
		ActionToggleQuality	= 0x08,
		ActionStopSounds	= 0x09,
		ActionWaitForFrame	= 0x8a,
		ActionSetTarget		= 0x8b,
		ActionGoToLabel		= 0x8c
};

class Sound;

struct ActionRecord {
	Action			 action;

	// GotoFrame  & WaitForFrame
	long			 frameIndex;

	// GetURL
	char			*url;
	char			*target;

	// GotoLabel
	char			*frameLabel;

	// WaitForFrame
	long			 skipCount;

	// Sound
	Sound			*sound;

	struct ActionRecord	*next;
	
	ActionRecord() {
		frameLabel = 0;
		url = 0;
		target = 0;
		sound = 0;
	};

	~ActionRecord() {
		if (frameLabel) free(frameLabel);
		if (url) free(url);
		if (target) free(target);
	};
};

enum FontFlags {
	fontUnicode   = 0x20,
	fontShiftJIS  = 0x10,
	fontANSI      = 0x08,
	fontItalic    = 0x04,
	fontBold      = 0x02,
	fontWideCodes = 0x01
};

enum TextFlags {
	isTextControl = 0x80,

	textIsLarge   = 0x70,
	textHasFont   = 0x08,
	textHasColor  = 0x04,
	textHasYOffset= 0x02,
	textHasXOffset= 0x01
};

#ifndef NULL
#define NULL 0
#endif

// Tag values that represent actions or data in a Flash script.
enum
{ 
    stagEnd 			= 0,
    stagShowFrame 		= 1,
    stagDefineShape		= 2,
    stagFreeCharacter 		= 3,
    stagPlaceObject 		= 4,
    stagRemoveObject 		= 5,
    stagDefineBits 		= 6,
    stagDefineButton 		= 7,
    stagJPEGTables 		= 8,
    stagSetBackgroundColor	= 9,
    stagDefineFont		= 10,
    stagDefineText		= 11,
    stagDoAction		= 12,
    stagDefineFontInfo		= 13,
    stagDefineSound		= 14,	// Event sound tags.
    stagStartSound		= 15,
    stagStopSound		= 16,
    stagDefineButtonSound	= 17,
    stagSoundStreamHead		= 18,
    stagSoundStreamBlock	= 19,
    stagDefineBitsLossless	= 20,	// A bitmap using lossless zlib compression.
    stagDefineBitsJPEG2		= 21,	// A bitmap using an internal JPEG compression table.
    stagDefineShape2		= 22,
    stagDefineButtonCxform	= 23,
    stagProtect			= 24,	// This file should not be importable for editing.

    // These are the new tags for Flash 3.
    stagPlaceObject2		= 26,	// The new style place w/ alpha color transform and name.
    stagRemoveObject2		= 28,	// A more compact remove object that omits the character tag (just depth).
    stagDefineShape3		= 32,	// A shape V3 includes alpha values.
    stagDefineText2		= 33,	// A text V2 includes alpha values.
    stagDefineButton2		= 34,	// A button V2 includes color transform, alpha and multiple actions
    stagDefineBitsJPEG3		= 35,	// A JPEG bitmap with alpha info.
    stagDefineBitsLossless2 	= 36,	// A lossless bitmap with alpha info.
    stagDefineSprite		= 39,	// Define a sequence of tags that describe the behavior of a sprite.
    stagNameCharacter		= 40,	// Name a character definition, character id and a string, (used for buttons, bitmaps, sprites and sounds).
    stagFrameLabel			= 43,	// A string label for the current frame.
    stagSoundStreamHead2	= 45,	// For lossless streaming sound, should not have needed this...
    stagDefineMorphShape	= 46,	// A morph shape definition
    stagDefineFont2		= 48,

    notEnoughData		= 0xffff	// Special code
};

#ifndef false
#define false 0
#endif
#ifndef true
#define true 1
#endif

extern int shape_size,shape_nb,shaperecord_size,shaperecord_nb,style_size,style_nb;

typedef void (*ScanLineFunc)(void *id, long y, long start, long end);

class Bitmap;
struct FlashMovie;


extern "C" {
#include "jpeglib.h"
};
extern "C" {
#include "zlib.h"
};

#include "graphic.h"
#include "character.h"
#include "bitmap.h"
#include "shape.h"
#include "displaylist.h"
#include "sound.h"
#include "button.h"
#include "font.h"
#include "text.h"
#include "adpcm.h"
#include "mp3.h"
#include "program.h"
#include "sprite.h"
#include "script.h"
#include "movie.h"

#endif /* _SWF_H_ */

--- NEW FILE: sqrt.cc ---
unsigned char SQRT[] = {

0,1,1,1,2,2,2,2,2,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,
5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,
6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,
10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,
11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,
13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14,
14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,
16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
[...4060 lines suppressed...]
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
};

--- NEW FILE: sqrt.h ---

--- NEW FILE: adpcm.cc ---

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: adpcm.cc,v 1.1 2006-10-03 11:26:08 dslinux_amadeus Exp $";
#endif

// This file has been rearranged from the code posted
// on news:forums.macromedia.com by Jonathan Gay.
// Courtesy of Macromedia

//
// ADPCM tables
//

static const int indexTable2[2] = {
    -1, 2,
};

// Is this ok?
static const int indexTable3[4] = {
    -1, -1, 2, 4,
};

static const int indexTable4[8] = {
    -1, -1, -1, -1, 2, 4, 6, 8,
};

static const int indexTable5[16] = {
 -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 4, 6, 8, 10, 13, 16,
};

static const int* indexTables[] = {
 indexTable2,
 indexTable3,
 indexTable4,
 indexTable5
};

static const int stepsizeTable[89] = {
    7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
    19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
    50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
    130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
    337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
    876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
    2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
    5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
    15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
};

long
Adpcm::GetBits(int n)
{
	if ( bitPos < n ) FillBuffer();

	assert(bitPos >= n);

	long v = ((unsigned long)bitBuf << (32-bitPos)) >> (32-n);
	bitPos -= n;

	return v;
}

long
Adpcm::GetSBits(int n)
{
	if ( bitPos < n ) FillBuffer();

	assert(bitPos >= n);

	long v = ((long)bitBuf << (32-bitPos)) >> (32-n);
	bitPos -= n;

	return v;
}

//
// The Decompressor
//

// Constructor
Adpcm::Adpcm(unsigned char *buffer, long isStereo)
{
	stereo = isStereo;
	src = buffer;

	nBits = 0; // flag that it is not inited
	nSamples = 0;

	bitPos = 0;
	bitBuf = 0;
}

void
Adpcm::FillBuffer()
{
	while ( bitPos <= 24 /*&& srcSize > 0*/ ) {
		bitBuf = (bitBuf<<8) | *src++;
		bitPos += 8;
	}
}

void
Adpcm::Decompress(short *dst, long n)
{
	if ( nBits == 0 ) {
		// Get the compression header
		nBits = (int)GetBits(2)+2;
	}

	const int* indexTable = indexTables[nBits-2];
	int k0 = 1 << (nBits-2);
	int signmask = 1 << (nBits-1);

	if ( !stereo ) {
		// Optimize for mono
		long		vp = valpred[0]; // maybe these can get into registers...
		int		ind = index[0];
		long		ns = nSamples;

		while ( n-- > 0 ) {
			ns++;

			if ( (ns & 0xFFF) == 1 ) {
				// Get a new block header
				*dst++ = (short)(vp = GetSBits(16));

				ind = (int)GetBits(6); // The first sample in a block does not have a delta
			} else {
				// Process a delta value
				int delta = (int)GetBits(nBits);

				// Compute difference and new predicted value
				// Computes 'vpdiff = (delta+0.5)*step/4'
				int step = stepsizeTable[ind];
				long vpdiff = 0;
				int k = k0;

				do {
					if ( delta & k )
					vpdiff += step;
					step >>= 1;
					k >>= 1;
				} while ( k );

				vpdiff += step; // add 0.5

				if ( delta & signmask ) // the sign bit
					vp -= vpdiff;
				else
					vp += vpdiff;

				// Find new index value
				ind += indexTable[delta&(~signmask)];

				if ( ind < 0 )
					ind = 0;
				else if ( ind > 88 )
					ind = 88;

				// clamp output value
				if ( vp != (short)vp )
					vp = vp < 0 ? -32768 : 32767;

				/* Step 7 - Output value */
				*dst++ = (short)vp;
			}
		}

		valpred[0] = vp;
		index[0] = ind;
		nSamples = ns;

	} else {
		int sn = stereo ? 2 : 1;

		// Stereo
		while ( n-- > 0 ) {

			nSamples++;

			if ( (nSamples & 0xFFF) == 1 ) {
				// Get a new block header
				for ( int i = 0; i < sn; i++ ) {

					*dst++ = (short)(valpred[i] = GetSBits(16));

					// The first sample in a block does not have a delta
					index[i] = (int)GetBits(6);
				}
			} else {
				// Process a delta value
				for ( int i = 0; i < sn; i++ ) {
					int delta = (int)GetBits(nBits);

					// Compute difference and new predicted value
					// Computes 'vpdiff = (delta+0.5)*step/4'

					int step = stepsizeTable[index[i]];
					long vpdiff = 0;
					int k = k0;

					do {
						if ( delta & k ) vpdiff += step;
						step >>= 1;
						k >>= 1;
					} while ( k );
					vpdiff += step; // add 0.5


					if ( delta & signmask ) // the sign bit
						valpred[i] -= vpdiff;
					else
						valpred[i] += vpdiff;

					// Find new index value
					index[i] += indexTable[delta&(~signmask)];

					if ( index[i] < 0 )
						index[i] = 0;
					else if ( index[i] > 88 )
						index[i] = 88;

					// clamp output value
					if ( valpred[i] != (short)valpred[i] )
						valpred[i] = valpred[i] < 0 ? -32768 : 32767;

					/* Step 7 - Output value */
					*dst++ = (short)valpred[i];
				}
			}
		}
	}
}

--- NEW FILE: character.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _CHARACTER_H_
#define _CHARACTER_H_

enum ObjectType {
	ShapeType,
	TextType,
	FontType,
	SoundType,
	BitmapType,
	SpriteType,
	ButtonType
};

class DisplayListEntry;

// Character definition

class Character {
	long			 tagId;
	ObjectType		 type;
	char			*name;

public:
	Character(ObjectType type, long tagId);
        virtual ~Character();

	virtual int		 execute(GraphicDevice *, Matrix *, Cxform *);	// Display, play or whatever
	virtual int		 isButton(void);	// True if Character is a button
        virtual int              isSprite(void);
	virtual ActionRecord	*eventHandler(GraphicDevice *, FlashEvent *);
        virtual void		 getRegion(GraphicDevice *gd, Matrix *matrix, void *id, ScanLineFunc scan_line_func);
	virtual void		 reset();	// Reset internal state of object
	virtual void		 getBoundingBox(Rect *bb, DisplayListEntry *de);
#ifdef DUMP
	virtual void		 dump(BitStream *main);

	int			 saved;
#endif

	long			 getTagId();	// Return tagId
	ObjectType		 getType();
	char			*getTypeString();
	char			*getName();
	void			 setName(char *);
};

struct sCharCell {
	Character *elt;
	struct sCharCell *next;
};

class Dict {
	struct sCharCell *head;
	struct sCharCell *currentCell;	// Iteration variable for dictNextCharacter

public:
	Dict();
	~Dict();

	void		 addCharacter(Character *character);
	void		 nameCharacter(long id, char *string);
	Character	*getCharacter(long id);
	void		 dictRewind();
	Character	*dictNextCharacter();

#ifdef DUMP
	void		 dictSetUnsaved();
#endif
};

#endif /* _CHARACTER_H_ */

--- NEW FILE: adpcm.h ---
#ifndef _ADPCM_H_
#define _ADPCM_H_

class Adpcm {

	// Destination format - note we always decompress to 16 bit
	long		 stereo;
	int		 nBits;  // number of bits in each sample

	long		 valpred[2]; // Current state
	int		 index[2];

	long 		 nSamples; // number of samples decompressed so far

	// Parsing Info
	unsigned char 	*src;
	long		 bitBuf; // this should always contain at least 24 bits of data
	int		 bitPos;

	void FillBuffer();

	long GetBits(int n);

	long GetSBits(int n);

public:
	Adpcm(unsigned char *buffer, long isStereo);

	void Decompress(short * dst, long n); // return number of good samples
#ifdef DUMP
	void dump(BitStream *bs);
	void Compress(short *pcm, long n, int bits);
#endif
};

#endif /* _ADPCM_H_ */

--- NEW FILE: flash.cc ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//  

#include "swf.h"
#include "graphic16.h"
#include "graphic24.h"
#include "graphic32.h"

#ifdef RCSID
static char *rcsid = "$Id: flash.cc,v 1.1 2006-10-03 11:26:09 dslinux_amadeus Exp $";
#endif

// Interface with standard C
extern "C" {

FlashHandle
FlashNew()
{
	FlashMovie *fh;

	fh = new FlashMovie;

        fh->main = new CInputScript;

	return (FlashHandle)fh;
}

int
FlashParse(FlashHandle flashHandle, int level, char *data, long size)
{
	FlashMovie *fh;
	CInputScript *script;
	int status = FLASH_PARSE_ERROR;

	fh = (FlashMovie *)flashHandle;

	for(script = fh->main; script != NULL; script = script->next) {
		if (script->level == level) {
			status = script->ParseData(fh, data, size);

			if (status & FLASH_PARSE_START) {
				fh->msPerFrame = 1000/fh->main->frameRate;
				script->program->rewindMovie();
			}
			break;
		}
	}

	return status;
}

void
FlashGetInfo(FlashHandle flashHandle, struct FlashInfo *fi)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	fi->version = fh->main->m_fileVersion;
	fi->frameRate = fh->main->frameRate;
	fi->frameCount = fh->main->frameCount;
	fi->frameWidth = fh->main->frameRect.xmax - fh->main->frameRect.xmin;
	fi->frameHeight = fh->main->frameRect.ymax - fh->main->frameRect.ymin;
}

long FlashGraphicInit(FlashHandle flashHandle, FlashDisplay *fd)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	switch (fd->bpp) {
		case 4:
			fh->gd = new GraphicDevice32(fd);
			break;
		case 3:
			fh->gd = new GraphicDevice24(fd);
			break;
		case 2:
			fh->gd = new GraphicDevice16(fd);
			break;
		default:
			fprintf(stderr, "Unsupported depth\n");
	}

	fh->gd->setMovieDimension(fh->main->frameRect.xmax - fh->main->frameRect.xmin,
				  fh->main->frameRect.ymax - fh->main->frameRect.ymin);

	return 1;	// Ok
}

void
FlashSoundInit(FlashHandle flashHandle, char *device)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	fh->sm = new SoundMixer(device);
}

void
FlashZoom(FlashHandle flashHandle, int zoom)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	fh->gd->setMovieZoom(zoom);
}

void
FlashOffset(FlashHandle flashHandle, int x, int y)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	fh->gd->setMovieOffset(x,y);
}

long
FlashExec(FlashHandle flashHandle, long flag, 
          FlashEvent *fe, struct timeval *wakeDate)
{
	FlashMovie *fh;
	long wakeUp = 0;

	fh = (FlashMovie *)flashHandle;

	if (fh->main == NULL) return 0; // Not ready
	if (fh->main->program == NULL) return 0; // Not ready
	if (fh->main->program->nbFrames == 0) return 0; // Still not ready
	if (fh->gd == 0) return 0;

	switch (flag & FLASH_CMD_MASK) {
		case FLASH_STOP:
			fh->main->program->pauseMovie();
			wakeUp = 0;
			break;
		case FLASH_CONT:
			fh->main->program->continueMovie();
			wakeUp = FLASH_STATUS_WAKEUP;
			break;
		case FLASH_REWIND:
			fh->main->program->rewindMovie();
			wakeUp = 0;
			break;
		case FLASH_STEP:
			fh->main->program->nextStepMovie();
			wakeUp = 0;
			break;
	}

	if (flag & FLASH_WAKEUP) {
		// Compute next wakeup time
		gettimeofday(wakeDate,0);
		wakeDate->tv_usec += fh->msPerFrame*1000;
		if (wakeDate->tv_usec > 1000000) {
			wakeDate->tv_usec -= 1000000;
			wakeDate->tv_sec++;
		}
                
		// Play frame
                wakeUp = fh->processMovie(fh->gd, fh->sm);
	}

        if (checkFlashTimer(&fh->scheduledTime)) {
            if (fh->handleEvent(fh->gd, fh->sm, &fh->scheduledEvent)) {
                wakeUp = 1;
            }
            
            setFlashTimer(&fh->scheduledTime, -1);
        }

	if (flag & FLASH_EVENT) {
            wakeUp = fh->handleEvent(fh->gd, fh->sm, fe);
            if (wakeUp) {
                /* Wake up at once, except for mouse move (40 ms after) */
                gettimeofday(wakeDate,0);
                if (fe->type == FeMouseMove) {
                    wakeDate->tv_usec += 40*1000;
                    if (wakeDate->tv_usec > 1000000) {
			wakeDate->tv_usec -= 1000000;
			wakeDate->tv_sec++;
                    }
                }
            }
	}

	return wakeUp || (fh->scheduledTime.tv_sec != -1);
}

void FlashSetGetSwfMethod(FlashHandle flashHandle, void (*getSwf)(char *url, int level, void *clientData), void *clientData)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	fh->getSwf = getSwf;
	fh->getSwfClientData = clientData;
}


void
FlashSetCursorOnOffMethod(FlashHandle flashHandle, void (*cursorOnOff)(int , void *), void *clientData)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	fh->cursorOnOff = cursorOnOff;
	fh->cursorOnOffClientData = clientData;
}

void
FlashSetGetUrlMethod(FlashHandle flashHandle, void (*getUrl)(char *, char *, void *), void *clientData)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	fh->getUrl = getUrl;
	fh->getUrlClientData = clientData;
}

void
FlashClose(FlashHandle flashHandle)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	delete fh;
}

void
FlashSettings(FlashHandle flashHandle, long settings)
{
	FlashMovie *fh;

	fh = (FlashMovie *)flashHandle;

	fh->main->program->modifySettings( settings );
}

int shape_size,shape_nb,shaperecord_size,shaperecord_nb,style_size,style_nb;

void flash_dump(void)
{
    printf("flash: shape_size=%d (nb=%d)\n",shape_size,shape_nb);
    printf("flash: shaperecord_size=%d (nb=%d)\n",shaperecord_size,shaperecord_nb);
    printf("flash: style_size=%d (nb=%d)\n",style_size,style_nb);
}

}; /* end of extern C */

--- NEW FILE: mp3.h ---
#ifndef _MP3_H_
#define _MP3_H_

class Mp3 {

    	unsigned char  *src;
	int	        pos;
	int		len;
public:
	Mp3(unsigned char *buffer, int len, long flags);

	void Decompress(short * dst, long n); // return number of good samples
};

#endif /* _MP3_H_ */

--- NEW FILE: shape.h ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _SHAPE_H_
#define _SHAPE_H_

struct LineStyleDef {
    long		 width;
    Color		 color;
    FillStyleDef         fillstyle;
};

enum ShapeRecordType {
	shapeNonEdge,
	shapeCurve,
	shapeLine
};

enum ShapeFlags {
	flagsMoveTo	   = 0x01,
	flagsFill0	   = 0x02,
	flagsFill1	   = 0x04,
	flagsLine	   = 0x08,
	flagsNewStyles	   = 0x10,
	flagsEndShape 	   = 0x80
};

struct ShapeRecord {
	ShapeRecordType  type;

	// Non Edge
	ShapeFlags	 flags;
	long		 x,y;	// Moveto
	long		 fillStyle0;
	long		 fillStyle1;
	long		 lineStyle;
	FillStyleDef	*newFillStyles; // Array
	long		 nbNewFillStyles;
	LineStyleDef	*newLineStyles; // Array
	long		 nbNewLineStyles;

	// Curve Edge
	long		 ctrlX, ctrlY;
	long		 anchorX, anchorY;

	// Straight Line
	long		 dX,dY;

	struct ShapeRecord *next;

    ShapeRecord() {
        shaperecord_size += sizeof(ShapeRecord);
        shaperecord_nb++;
    }

};

enum ShapeAction {
	ShapeDraw,
	ShapeGetRegion
};

struct LineSegment {
    long x1,y1,x2,y2;
    char first;
    LineStyleDef *l;
    struct LineSegment *next;
};

struct Path {
    long lastX,lastY;
    int nb_edges;
    int nb_segments;
};

struct StyleList {
    FillStyleDef	*newFillStyles; // Array
    long		 nbNewFillStyles;
    LineStyleDef	*newLineStyles; // Array
    long		 nbNewLineStyles;
    
    StyleList *next;
};


/* fast bit parser */
struct BitParser {
    // Bit Handling
    S32 m_bitPos;
    U32 m_bitBuf;

    U8 *ptr;
};

class Shape;

/* state of the shape parser */
struct ShapeParser {
    Dict *dict;         /* XXX: should be put elsewhere */

    BitParser bit_parser;
    S32 m_nFillBits;
    S32 m_nLineBits;

    StyleList *style_list;
    Matrix *matrix;
    Path curPath;
    int reverse;

    /* line rasteriser */
    LineSegment *first_line,*last_line;
    GraphicDevice *gd;
    Cxform *cxform;
    Shape *shape;

    FillStyleDef *f0;
    FillStyleDef *f1;
    LineStyleDef *l;
};

class Shape : public Character {
 public:
	int		 defLevel; // 1,2 or 3
        

	Rect		 boundary;
	FillStyleDef	 defaultFillStyle;
	LineStyleDef	 defaultLineStyle;

	Matrix		 lastMat;
        /* parsing for the rendering stage (saves a lot of memory &
           may not reduce significantly the size). These variables
           should be in another structure (no state need to be
           maintained between two renderings) */
        int getAlpha, getStyles;
        unsigned char *file_ptr;
        Dict *dict;         /* XXX: should be put elsewhere */

protected:
	void	 drawLines(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, long, long);
	void	 buildSegmentList(Segment **segs, int height, long &n, Matrix *matrix, int update, int reverse);
	Segment *progressSegments(Segment *, long);
	Segment *newSegments(Segment *, Segment *);

public:
	Shape(long id = 0 , int level = 1);
	~Shape();

	void	 setBoundingBox(Rect rect);
	int	 execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform);
	void	 getRegion(GraphicDevice *gd, Matrix *matrix, 
                           void *id, ScanLineFunc scan_line_func);

	void	 getBoundingBox(Rect *bb, DisplayListEntry *);

#ifdef DUMP
	void	 dump(BitStream *bs);
	void	 dumpShapeRecords(BitStream *bs, int alpha);
	void	 dumpFillStyles(BitStream *bs, FillStyleDef *defs, long n, int alpha);
	void	 dumpLineStyles(BitStream *bs, LineStyleDef *defs, long n, int alpha);
	void	 checkBitmaps(BitStream *bs);
#endif
};

#endif /* _SHAPE_H_ */

--- NEW FILE: matrix.h ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _MATRIX_H_
#define _MATRIX_H_

struct Matrix {
	float a,b,c,d;
	long tx,ty;
public:
	Matrix operator*(Matrix);
	Matrix invert();
	Matrix();

#ifdef DUMP
	void dump(BitStream *bs);
#endif

	inline
	long Matrix::getX(long x, long y)
	{
		return (long) (x*a+y*b+tx);
	};

	inline
	long Matrix::getY(long x, long y)
	{
		return (long) (x*c+y*d+ty);
	};

};

#endif /* _MATRIX_H_ */

--- NEW FILE: font.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _SWFFONT_H_
#define _SWFFONT_H_

class SwfFont : public Character {
	Shape		*glyphs;	// Array
	long		 nbGlyphs;
	char		*name;
	FontFlags	 flags;
	long		*lookUpTable;	// Array

	// Font2
	long		 ascent;
	long		 descent;
	long		 leading;

public:
	SwfFont(long id);
	~SwfFont();

	void		 setFontShapeTable(Shape *shapes, long n);
	void		 setFontName(char *str);
	void		 setFontLookUpTable(long *lut);
	void		 setFontFlags(FontFlags f);
	long		 getGlyphCode(long index);
        long		 getNbGlyphs();
	Shape		*getGlyph(long index);

	char 		*getName();
	FontFlags	 getFlags();
	
#ifdef DUMP
	void		 dump(BitStream *bs);
	void		 dumpFontInfo(BitStream *bs);
#endif
};

#endif /* _SWFFONT_H_ */

--- NEW FILE: button.cc ---
/////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: button.cc,v 1.1 2006-10-03 11:26:08 dslinux_amadeus Exp $";
#endif

#define PRINT 0

// Contructor

Button::Button(long id, int level) : Character(ButtonType, id)
{
	defLevel = level;
	actionRecords = 0;
	buttonRecords = 0;
	conditionList = 0;
	reset();
	isMenu = 0;
	sound[0] = sound[1] = sound[2] = sound[3] = 0;
}

// Destructor

Button::~Button()
{
	if (actionRecords) {
		ActionRecord *ar,*del;
		for(ar = actionRecords; ar;) {
			del = ar;
			ar = ar->next;
			delete del;
		}
	}
	if (buttonRecords) {
		ButtonRecord *br,*del;
		for(br = buttonRecords; br;) {
			del = br;
			br = br->next;
			if (del->cxform)
				delete del->cxform;
			delete del;
		}
	}
	if (conditionList) {
		Condition *cond,*del;
		for(cond = conditionList; cond;) {
			ActionRecord *ar,*d;

			for(ar = cond->actions; ar;) {
				d = ar;
				ar = ar->next;
				delete d;
			}

			del = cond;
			cond = cond->next;
			delete del;
		}
	}
}

ButtonRecord *
Button::getButtonRecords()
{
	return buttonRecords;
}

ActionRecord *
Button::getActionRecords()
{
	return actionRecords;
}

Sound **
Button::getSounds()
{
	return sound;
}

Condition *
Button::getConditionList()
{
	return conditionList;
}

void
Button::setButtonSound(Sound *s, int state)
{
	if (state >=0 && state < 4) {
		sound[state] = s;
	}
}

void
Button::setButtonMenu(int menu)
{
	isMenu = menu;
}

void
Button::addButtonRecord( ButtonRecord *br )
{
#if 0
    /* SURTOUT PAS !!! */
    ButtonRecord **l;
    
    /* sort by layer */
    l=&buttonRecords;
    while (*l != NULL && (*l)->layer < br->layer) l = &(*l)->next;
    br->next = *l;
    *l = br;
#else
	br->next = 0;

	if (buttonRecords == 0) {
		buttonRecords = br;
	} else {
		ButtonRecord *current;

		for(current = buttonRecords; current->next; current = current->next);

		current->next = br;
	}
#endif
}

void
Button::addCondition( long transition )
{
	Condition *condition;

	condition = new Condition;
	if (condition == NULL) return;

	condition->transition = transition; 
	condition->next = conditionList;

	// Move current actionRecords to this condition
	condition->actions = actionRecords;
	actionRecords = 0;

	conditionList = condition;
}

void
Button::addActionRecord( ActionRecord *ar )
{
	ar->next = 0;

	if (actionRecords == 0) {
		actionRecords = ar;
	} else {
		ActionRecord *current;

		for(current = actionRecords; current->next; current = current->next);

		current->next = ar;
	}
}

void
Button::getRegion(GraphicDevice *gd, Matrix *matrix, void *id, ScanLineFunc scan_line_func)
{
	ButtonRecord *br;

	for (br = buttonRecords; br; br = br->next)
	{
		if ((br->state & stateHitTest) && br->character /* Temporaire */) {
			Matrix mat;

			mat = (*matrix) * br->buttonMatrix;
			br->character->getRegion(gd, &mat, id, scan_line_func);
		}
	}
}

int
Button::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, ButtonState renderState)
{
	ButtonRecord *br;
	int sprite = 0;
	Cxform *cxf = 0;

#if PRINT==2
	printf("Rendering Button %d  for State(s) ", getTagId());
#endif
	for (br = buttonRecords; br; br = br->next)
	{
            if ((br->state & renderState) && br->character != NULL) {
			Matrix mat;
			
#if PRINT==2
		printf("%d ", br->state);
#endif
			mat = (*matrix) * br->buttonMatrix;

                        if (cxform) {
				cxf = cxform;
			} else if (br->cxform) {
				cxf = br->cxform;
			} 

			if (br->character->execute(gd, &mat, cxf)) {
				sprite = 1;
			}
		}
	}
#if PRINT==2
	printf("\n");
#endif
	return sprite;
}

ActionRecord *
Button::getActionFromTransition(ButtonState cur, ButtonState old)
{
	Condition *cond;
	long mask;

	if (old == cur) return NULL;

        /* transitions */
        mask = 0;
        if (old == stateUp && cur == stateOver)
            mask |= 0x001;
        else if (old == stateOver && cur == stateUp)
            mask |= 0x002;
        else if (old == stateOver && cur == stateDown)
            mask |= 0x004;
        else if (old == stateDown && cur == stateOver)
            mask |= 0x008;

        if (!isMenu) {
            /* push button transitions (XXX: not quite correct) */
            if (old == stateDown && cur == stateUp)
                mask = 0x010;
            else if (old == stateUp && cur == stateDown)
                mask = 0x020;
            /* XXX: what is transition 0x040 ?? */
        } else {
            /* menu button transitions (XXX: not quite correct) */
            if (old == stateUp && cur == stateDown)
                mask = 0x080;
            else if (old == stateDown && cur == stateUp)
                mask = 0x100;
        }

	for (cond = conditionList; cond; cond = cond->next) {
		if (cond->transition & mask) {
			return cond->actions;
		}
	}
	return 0;
}

void
Button::getBoundingBox(Rect *bbox, DisplayListEntry *e)
{
	ButtonRecord *br;

	bbox->reset();
	for (br = buttonRecords; br; br = br->next)
	{
                if (br->state & e->renderState) {
			if (br->character) {
				Rect bb;
				
				bb.reset();
				br->character->getBoundingBox(&bb,e);
				transformBoundingBox(bbox, &br->buttonMatrix, &bb, 0);
			}
		}
	}
}

/* Get current render character, actually it should be a list of characters
   so a DisplayList after all */
Character *
Button::getRenderCharacter(ButtonState state)
{
	ButtonRecord *br;

	for (br = buttonRecords; br; br = br->next)
	{
                if (br->state & state) {
			return br->character;
		}
	}
	return 0;
}

void
Button::updateButtonState(DisplayListEntry *e)
{
	ButtonRecord *br;

	e->buttonCharacter = 0;
	for (br = buttonRecords; br; br = br->next)
	{
                if (br->state & e->renderState) {
			e->buttonCharacter = br->character;
			e->buttonMatrix = br->buttonMatrix;
			return;
		}
	}
}

--- NEW FILE: cxform.cc ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//  

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id";
#endif

long
Cxform::getRed(long v) {
	long val;

	val = (long)(ra*v+rb);
	if (val > 255) val = 255;
	else if (val < 0) val = 0;
	return val;
}

long
Cxform::getGreen(long v) {
	long val;

	val = (long)(ga*v+gb);
	if (val > 255) val = 255;
	else if (val < 0) val = 0;
	return val;
}

long
Cxform::getBlue(long v) {
	long val;

	val = (long)(ba*v+bb);
	if (val > 255) val = 255;
	else if (val < 0) val = 0;
	return val;
}

long
Cxform::getAlpha(long v) {
	long val;

	val = (long)(aa*v+ab);
	if (val > 255) val = 255;
	else if (val < 0) val = 0;
	return val;
}

Color
Cxform::getColor(Color color) {
	Color newColor;

	newColor.red = getRed(color.red);
	newColor.green = getGreen(color.green);
	newColor.blue = getBlue(color.blue);
	newColor.alpha = getAlpha(color.alpha);

	return newColor;
}

--- NEW FILE: graphic24.cc ---
////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

#include "graphic24.h"

extern unsigned char SQRT[];

#define FULL_AA

#define PRINT 0

typedef unsigned char TYPE;
#define BPP 3

GraphicDevice24::GraphicDevice24(FlashDisplay *fd) : GraphicDevice(fd)
{
}

long
GraphicDevice24::allocColor(Color color)
{
	return 0;
}

void
GraphicDevice24::clearCanvas()
{
    TYPE *point,*p;
    long                 h, w,n;

    if (!bgInitialized) return;

    point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin*BPP;
    w = clip_rect.xmax - clip_rect.xmin;
    h = clip_rect.ymax - clip_rect.ymin;

    while (h--) {
        p = point;
        n = w;
        while (n--) {
            *p++ = backgroundColor.blue;
            *p++ = backgroundColor.green;
            *p++ = backgroundColor.red;
        }

        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;
}

/* alpha = 0 : select c1, alpha = 255 select c2 */
static inline void mix_alpha(TYPE *c1, Color c2, int alpha)
{
	*c1 = (((c2.blue- (*c1))*alpha + (*c1) * 256) >> 8);
	c1++;
	*c1 = (((c2.green- (*c1))*alpha + (*c1) * 256) >> 8);
	c1++;
	*c1 = (((c2.red- (*c1))*alpha + (*c1) * 256) >> 8);
}

void
GraphicDevice24::fillLineAA(FillStyleDef *f, long y, long start, long end)
{
    register long   n;
    TYPE *line;
    TYPE *point;
    Color pixel;
    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;
    
    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*BPP];

        if (start == end) {
            mix_alpha(point, pixel, start_alpha + end_alpha - 255);
        } else {
            n = end-start;
            if (start_alpha < 255) {
                mix_alpha(point, pixel, start_alpha);
                point += BPP;
                n--;
            }
            while (n > 0) {
                *point++ = pixel.blue;
                *point++ = pixel.green;
                *point++ = pixel.red;
                n--;
            }
            if (end_alpha > 0) {
                mix_alpha(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*BPP];
        
        if (start == end) {
            mix_alpha(point, pixel, ((start_alpha + end_alpha - 255) * alpha) >> 8);
        } else {
            n = end-start;
            if (start_alpha < 255) {
                mix_alpha(point, pixel, (start_alpha * alpha) >> 8);
                point+=BPP;
                n--;
            }
            while (n > 0) {
                mix_alpha(point, pixel, alpha);
                point+=BPP;
                n--;
            }
            if (end_alpha > 0) {
                mix_alpha(point, pixel, (end_alpha * alpha) >> 8);
            }
        }
    }
}

void
GraphicDevice24::fillLine(FillStyleDef *f, long y, long start, long end)
{
	register long   n;
        TYPE *line,*point;
        Color pixel;
        unsigned int alpha;

	if (clip(y,start,end)) return;

        start >>= FRAC_BITS;
        end >>= FRAC_BITS;

	line = (TYPE *)(canvasBuffer + bpl*y);
	point = &line[start*BPP];			
	n = end-start;				
        alpha = f->color.alpha;
        pixel = f->color;
        if (alpha == ALPHA_OPAQUE) {
            while (n--) { 
		*point++ = pixel.blue;
		*point++ = pixel.green;
		*point++ = pixel.red;
            }
        } else {
            while (n--) { 
		mix_alpha(point, pixel, alpha);
		point+=BPP;			
            }
        }
}

void
GraphicDevice24::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;
    TYPE *p;
    Color *cmap;
    long pixbpl;
    Color 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 = (TYPE *) (canvasBuffer + bpl*y + start*BPP);
    
    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);
    
    pixels = b->pixels;
    pixbpl = b->bpl;
    cmap = f->cmap;

    if (b->alpha_buf == NULL) {
        while (n) {
            if (x1 >= 0 && y1 >= 0 && 
                (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
                
                pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]];
                *p++ = pixel.blue;
                *p++ = pixel.green;
                *p++ = pixel.red;
            } else {
                p+=BPP;
	    }
            x1 += dx;
            y1 += dy;
            n--;
        }
    } else if (f->alpha_table) {
        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);
                mix_alpha(p, cmap[pixels[offset]], alpha_table[b->alpha_buf[offset]]);
	    }
            p+=BPP;
            x1 += dx;
            y1 += dy;
            n--;
        }
    } else {
        while (n) {
            if (x1 >= 0 && y1 >= 0 && 
                (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
                
                offset = (y1 >> 16) * pixbpl + (x1 >> 16);
                mix_alpha(p, cmap[pixels[offset]], b->alpha_buf[offset]);
            }
            p+=BPP;
            x1 += dx;
            y1 += dy;
            n--;
        }
    }
}

void
GraphicDevice24::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;

        r = (long) (m->a * start + m->b * y + m->tx);
        dr = (long) (m->a);

        ramp = grad->ramp;

        line = (TYPE *)(canvasBuffer + bpl*y);
	point = &line[start*BPP];

        r2 = r + n * dr;
        if ( ((r | r2) & ~255) == 0 ) {
            if (!grad->has_alpha) {
#ifdef FULL_AA
		if (start_alpha < 255) {
                    v = r>>16;
                    mix_alpha(point, ramp[v], start_alpha);
                    point+=BPP;
                    r += dr;
		    n--;
		}
#endif /* FULL_AA */
                while (n>0) {
                    v = r>>16;
                    *point++ = ramp[v].blue;
                    *point++ = ramp[v].green;
                    *point++ = ramp[v].red;
                    r += dr;				
		    n--;
                }
#ifdef FULL_AA
		if (end_alpha > 0) {
                    v = r>>16;
                    mix_alpha(point, ramp[v], end_alpha);
		}
#endif /* FULL_AA */
            } else {
                while (n--) {
                    v = r>>16;
                    cp = &ramp[v];
                    mix_alpha(point, *cp, cp->alpha);
                    point+=BPP;
                    r += dr;
                }
            }
        } else {
            if (!grad->has_alpha) {
#ifdef FULL_AA
		if (start_alpha < 255) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    mix_alpha(point, ramp[v], start_alpha);
                    point+=BPP;
                    r += dr;
		    n--;
		}
#endif /* FULL_AA */
                while (n>0) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    *point++ = ramp[v].blue;
                    *point++ = ramp[v].green;
                    *point++ = ramp[v].red;
                    r += dr;				
		    n--;
                }
#ifdef FULL_AA
		if (end_alpha > 0) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    mix_alpha(point, ramp[v], end_alpha);
		}
#endif /* FULL_AA */
            } else {
                while (n--) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    cp = &ramp[v];
                    mix_alpha(point, *cp, cp->alpha);
                    point+=BPP;
                    r += dr;
                }
            }
        }
}

void
GraphicDevice24::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;
        
        X = (long) (m->a * start + m->b * y + m->tx);
        Y = (long) (m->c * start + m->d * y + m->ty);
        dx = (long) (m->a);
        dy = (long) (m->c);

        ramp = grad->ramp;
									
	line = (TYPE *)(canvasBuffer + bpl*y);
	point = &line[start*BPP];
			     
        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];	
			}
			mix_alpha(point, ramp[r], 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];	
			}
			mix_alpha(point, ramp[r], start_alpha);
			point+=BPP;
			X += dx;						
			Y += dy;						
			n--;
		    }
#endif /* FULL_AA */
		    while (n>0) {					
			dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
			if ((unsigned long)dist2 >= 65536) {
			    r = 255;					
			} else {						
			    r= SQRT[dist2];	
			}
			*point++ = ramp[r].blue;
			*point++ = ramp[r].green;
			*point++ = ramp[r].red;
			X += dx;						
			Y += dy;						
			n--;
		    }		
#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];	
			}
			mix_alpha(point, ramp[r], end_alpha);
		    }
		}
#endif /* FULL_AA */

        } 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];
		mix_alpha(point, *cp, cp->alpha);
		point+=BPP;
		X += dx;						
		Y += dy;						
            }		
        }
}

void
GraphicDevice24::drawLine(long x1, long y1, long x2, long y2, long width)
{
    int n,adr,dx,dy,sx;
    Color color;
    register int a;
    register TYPE *pp;
    int alpha;

    x1 = (x1) >> FRAC_BITS;
    y1 = (y1) >> FRAC_BITS;
    x2 = (x2) >> FRAC_BITS;
    y2 = (y2) >> FRAC_BITS;
    
    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 = (TYPE *)canvasBuffer + adr;
    
    dx = x2 - x1;
    dy = y2 - y1;

    color = foregroundColor;
    alpha = foregroundColor.alpha;

    if (alpha == ALPHA_OPAQUE) {

#define PUTPIXEL() 				\
  {						\
      *pp++=color.red;		                \
      *pp++=color.green;	                \
      *pp++=color.blue;		                \
  }

#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() 				\
  {						\
      mix_alpha(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*BPP); a-=dx; }\
		else { pp+=(inc_2*BPP); 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
    }
}

--- NEW FILE: matrix.cc ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//  

#include "matrix.h"

#ifdef RCSID
static char *rcsid = "$Id: matrix.cc,v 1.1 2006-10-03 11:26:09 dslinux_amadeus Exp $";
#endif

Matrix::Matrix()
{
	a = 1.0;
	d = 1.0;
	b = c = 0.0;
	tx = ty = 0;
}

Matrix Matrix::operator*(Matrix m)
{
	Matrix mat;

	mat.a = this->a * m.a + this->b * m.c;
	mat.b = this->a * m.b + this->b * m.d;
	mat.c = this->c * m.a + this->d * m.c;
	mat.d = this->c * m.b + this->d * m.d;

	mat.tx = this->getX(m.tx,m.ty);
	mat.ty = this->getY(m.tx,m.ty);

	return mat;
}

Matrix Matrix::invert()
{
	Matrix mat;
	float det;

	det = a*d-b*c;

	mat.a  = d/det;
	mat.b  = -b/det;
	mat.c  = -c/det;
	mat.d  = a/det;

	mat.tx = - (long)(mat.a * tx + mat.b * ty);
	mat.ty = - (long)(mat.c * tx + mat.d * ty);

	return mat;
}

--- NEW FILE: Makefile ---
CC=	gcc
CXX=	g++
OPTIMIZE=-g -O3

# Comment out the following line if you use egcs :
CXXFLAGS=$(OPTIMIZE) $(ALLCFLAGS) $(CXXFLAGS_$(CC)) -UNDEBUG
CXXFLAGS_gcc=  -Wall -fno-rtti -fno-exceptions

ifeq ($(RGB555),Y)
CXXFLAGS += -DRGB555=1
endif

CCC=	$(CXX)
CCFLAGS= $(CXXFLAGS)

INCLUDES= adpcm.h        cxform.h       graphic.h      script.h       sqrt.h\
	bitmap.h       displaylist.h  matrix.h       shape.h        swf.h\
	button.h       flash.h        program.h      sound.h        text.h\
	character.h    font.h         rect.h         sprite.h	movie.h\
	mp3.h

SWFOBJS=\
	flash.o \
	character.o \
	shape.o \
	button.o \
	program.o \
	bitmap.o \
	displaylist.o \
	font.o \
	graphic.o \
	text.o \
	matrix.o \
	script.o \
	sound.o \
	sprite.o \
	movie.o \
	cxform.o \
	adpcm.o \
	mp3.o \
	sqrt.o \
	graphic16.o \
	graphic24.o \
	graphic32.o

#	bitstream.o
#	dump.o

all: libflash.a

libflash.a: $(SWFOBJS) 
	ar rcs $@ $(SWFOBJS)

$(SWFOBJS): $(INCLUDES)

clean:
	rm -f $(SWFOBJS) *~ libflash.a

.PHONY: plugin jpeg all

--- NEW FILE: font.cc ---
/////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: font.cc,v 1.1 2006-10-03 11:26:09 dslinux_amadeus Exp $";
#endif

SwfFont::SwfFont(long id) : Character(FontType, id)
{
	glyphs = 0;
	nbGlyphs = 0;
        name = NULL;
	setFontName("Unknown");
	flags = (FontFlags)0;
	lookUpTable = 0;
}

SwfFont::~SwfFont()
{
	if (lookUpTable) {
		delete lookUpTable;
	}
        delete name;
        delete [] glyphs;
}

void
SwfFont::setFontFlags(FontFlags f)
{
	flags = f;
}

char *
SwfFont::getName()
{
	return name;
}

FontFlags
SwfFont::getFlags()
{
	return flags;
}

long
SwfFont::getNbGlyphs()
{
	return nbGlyphs;
}

Shape  *
SwfFont::getGlyph(long index)
{
	if (index >= nbGlyphs) return 0;
	return &glyphs[index];
}

long
SwfFont::getGlyphCode(long index)
{
	if (lookUpTable == 0 || index >= nbGlyphs) return 0;
	return lookUpTable[index];
}

void
SwfFont::setFontName(char *str)
{
    delete name;
    name = new char[strlen(str)+1];
    strcpy(name,str);
}

void
SwfFont::setFontLookUpTable(long *lut)
{
	lookUpTable = lut;
}

void
SwfFont::setFontShapeTable(Shape *shapes, long n)
{
	glyphs = shapes;
	nbGlyphs = n;
}

--- NEW FILE: sound.cc ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//

#include "swf.h"

#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#if	SUN_SOUND
#include <sys/audioio.h>
#endif
#if	OSS_SOUND
#ifdef __NetBSD__
#include <soundcard.h>
#else
#include <sys/soundcard.h>
#endif
#endif

#ifdef RCSID
static char *rcsid = "$Id: sound.cc,v 1.1 2006-10-03 11:26:10 dslinux_amadeus Exp $";
#endif

#define PRINT 0

/* There are some defined missing in NetBSD's audioio.h */
#if	SUN_SOUND
#ifndef	AUDIO_CHANNELS_STEREO
#define	AUDIO_CHANNELS_STEREO	2
#endif
#ifndef	AUDIO_PRECISION_16
#define	AUDIO_PRECISION_16	16
#endif
#endif

//////////// SOUND

Sound::Sound(long id) : Character(SoundType, id)
{
	samples = 0;
	stereo = 0;
	soundRate = 0;
	sampleSize = 1;
}

Sound::~Sound()
{
	if (samples) {
		delete samples;
	}
}

void
Sound::setSoundFlags(long f) {
	switch (GET_SOUND_RATE_CODE(f)) {
		case 0:
			soundRate = 5500;
			break;
		case 1:
			soundRate = 11000;
			break;
		case 2:
			soundRate = 22000;
			break;
		case 3:
			soundRate = 44000;
			break;
	}
	if (f & soundIs16bit) {
		sampleSize = 2;
	}
	if (f & soundIsStereo) {
		stereo = 1;
	}

#if PRINT
	printf("-----\nFlags = %2x\n", f);
	printf("Rate = %d kHz  ", soundRate);
	printf("SampleSize = %d byte(s) ", sampleSize);
	if (f & soundIsStereo) {
		printf("Stereo  ");
	} else {
		printf("Mono  ");
	}
	switch (f & soundFormatMaske) {
	case soundFormatADPCMCompressed:
		printf("ADPCM\n");
		break;
	case soundFormatMP3Compressed:
		printf("MP3\n");
		break;
	case soundFormatRaw:
		printf("Raw\n");
		break;
	default:
	    	printf("unknown sound format %x\n", f);
		break;
	}
#endif
}

char *
Sound::setNbSamples(long n) {
	long size;

	nbSamples = n;

	size = nbSamples * (stereo ? 2 : 1) * sampleSize;

	samples = new char[ size ];

	memset((char *)samples,0, size);

	return samples;
}

long
Sound::getRate() {
	return soundRate;
}

long
Sound::getChannel() {
	return stereo ? 2 : 1;
}

long
Sound::getNbSamples() {
	return nbSamples;
}

long
Sound::getSampleSize() {
	return sampleSize;
}

char *
Sound::getSamples() {
	return samples;
}

//////////// SOUND MIXER

long  SoundMixer::dsp = -1;	// Init of descriptor
long  SoundMixer::blockSize = 0;	// Driver sound buffer size
long  SoundMixer::nbInst = 0;	// Nb SoundMixer instances
long  SoundMixer::sampleSize = 0;
long  SoundMixer::stereo = 0;
long  SoundMixer::soundRate = 0;
char *SoundMixer::buffer = 0;

SoundMixer::SoundMixer(char *device)
{
#ifndef NOSOUND
	int status;

	list = 0;	// No sound to play

	if (nbInst++) {
		// Device is already open
		return;
	}

	dsp = open(device,O_WRONLY);
	if (dsp < 0) {
		perror("open dsp");
		return;
	}

#if	SUN_SOUND
	audio_info_t audio_info;

	// Init audio_info to "harmless" values
	AUDIO_INITINFO(&audio_info);

	// Set sound rate in Hertz, Stereo, 16-bit PCM
	audio_info.play.sample_rate = 11000;
	audio_info.play.channels  = AUDIO_CHANNELS_STEREO;
	audio_info.play.precision = AUDIO_PRECISION_16;
	audio_info.play.encoding  = AUDIO_ENCODING_LINEAR;

	// Configure the audio device
	status = ioctl(dsp, AUDIO_SETINFO, &audio_info);
	if (status < 0) perror("ioctl AUDIO_SETINFO");

	sampleSize = audio_info.play.precision / 8;
	stereo     = audio_info.play.channels >= AUDIO_CHANNELS_STEREO;
	soundRate  = audio_info.play.sample_rate;
	blockSize  = audio_info.play.buffer_size;

	if (blockSize < 1024)
	    blockSize = 32768;

#else	/* !SUN_SOUND */
#if	OSS_SOUND
	// Reset device
	status = ioctl(dsp, SNDCTL_DSP_RESET, 0);
	if (status < 0) perror("ioctl SNDCTL_DSP_RESET");

	// Set sample size
	long fmt = AFMT_S16_LE;
	sampleSize = 2;
	status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt);
	if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT");

	if (status) {
		fmt = AFMT_U8;
		sampleSize = 1;
		status = ioctl(dsp, SNDCTL_DSP_SETFMT, &fmt);
		if (status < 0) perror("ioctl SNDCTL_DSP_SETFMT");
	}

	// Set stereo channel
	stereo = 1;
	status = ioctl(dsp, SNDCTL_DSP_STEREO, &stereo);

	if (status) {
		stereo = 0;
	}

	// Set sound rate in Hertz
	soundRate = 11000;
	status = ioctl(dsp, SNDCTL_DSP_SPEED, &soundRate);
	if (status < 0) perror("ioctl SNDCTL_DSP_SPEED");

	// Get device buffer size
	status = ioctl(dsp, SNDCTL_DSP_GETBLKSIZE, &blockSize);
	if (status < 0) perror("ioctl SNDCTL_DSP_GETBLKSIZE");
	if (blockSize < 1024) {
		blockSize = 32768;
	}
#endif	/* OSS_SOUND */
#endif	/* SUN_SOUND */
	blockSize *= 2;

	buffer = (char *)malloc(blockSize);
	if (buffer == 0) {
		close(dsp);
		dsp = -1;
	}

#if PRINT
#if	OSS_SOUND
	int caps;

	ioctl(dsp,SNDCTL_DSP_GETCAPS, &caps);
	printf("Audio capabilities = %x\n", caps);
#endif
	printf("Sound Rate  = %d\n", soundRate);
	printf("Stereo      = %d\n", stereo);
	printf("Sample Size = %d\n", sampleSize);
	printf("Buffer Size = %d\n", blockSize);
#endif /* PRINT */

#endif	/* NOSOUND */
}

SoundMixer::~SoundMixer()
{
	if (--nbInst == 0) {
		if (dsp > 0) {
			close(dsp);
			free(buffer);
		}
	}
}

void
SoundMixer::stopSounds()
{
#ifndef NOSOUND
	SoundList *sl,*del;

	for(sl = list; sl; ) {
		del = sl;
		sl = sl->next;
		delete del;
	}
	list = 0;
#endif
}

void
SoundMixer::startSound(Sound *sound)
{
#ifndef NOSOUND
	SoundList *sl;

	if (sound) {
		// Add sound in list
		sl = new SoundList;
		sl->rate = sound->getRate();
		sl->stereo = (sound->getChannel() == 2);
		sl->sampleSize = sound->getSampleSize();
		sl->current = sound->getSamples();
		sl->remaining = sound->getSampleSize()*sound->getNbSamples()*sound->getChannel();
		sl->next = NULL;
		// Append new sound at end of list
		if (list != NULL) {
		    SoundList *last = list;
		    while (last->next != NULL)
			last = last->next;
		    last->next = sl;
		} else {
		    list = sl;
		}
	}
#endif
}

long
SoundMixer::playSounds()
{
#ifndef NOSOUND
	long		 nbBytes, n;
	SoundList	*sl;
	int		 status;

	// Init failed
	if (dsp < 0) return 0;

	// No sound to play
	if (list == 0) return 0;

#if	SUN_SOUND
	fd_set wrset;
	struct timeval timeout;

	FD_ZERO(&wrset);
	FD_SET(dsp, &wrset);
	timeout.tv_sec = 0;
	timeout.tv_usec = 0;
	status = select(dsp+1, NULL, &wrset, NULL, &timeout);

	// Cannot output sound data without blocking
	// But there are still sounds to play. We must wait.
	if (status != 1 || !FD_ISSET(dsp, &wrset)) return 1;
#endif
#if	OSS_SOUND
	audio_buf_info	 bufInfo;

	// Get free DMA buffer space
	status = ioctl(dsp, SNDCTL_DSP_GETOSPACE, &bufInfo);

	// Free space is not large enough to output data without blocking
	// But there are still sounds to play. We must wait.
	if (bufInfo.bytes < blockSize) return 1;
#endif

	nbBytes = 0;

	// Fill buffer with silence.
	memset((void*)buffer, 0, blockSize);

	sl = list;
	while (sl && nbBytes < blockSize) {

		// Ask sound to fill the buffer
		// according to device capabilities
		n = fillSoundBuffer(sl, buffer + nbBytes, blockSize - nbBytes);

		// Remember amount of data written
		nbBytes += n;

		// No more samples for this sound
		if (sl->remaining == 0) {
		        list = sl->next;
			delete sl;
			sl = list;
		}
	}

	if (nbBytes) {
		// At last ! Play It !
	    	if (write(dsp,buffer,nbBytes) != nbBytes)
			perror("write sound data");
#if	OSS_SOUND
		status = ioctl(dsp, SNDCTL_DSP_POST, 0);
#endif
	}

	return nbBytes;
#else
	return 0;
#endif
}

long
SoundMixer::fillSoundBuffer(SoundList *sl, char *buff, long buffSize)
{
	long sampleLeft, sampleRight;
	long skipOut, skipOutInit;
	long skipIn, skipInInit;
	long freqRatio;
	long totalOut = 0;

	sampleLeft = sampleRight = 0;
	skipOutInit = skipInInit = 0;

	freqRatio = sl->rate / soundRate;
	if (freqRatio) {
		skipOutInit = freqRatio - 1;
		skipInInit = 0;
	}

	freqRatio = soundRate / sl->rate;
	if (freqRatio) {
		skipInInit = freqRatio - 1;
		skipOutInit = 0;
	}

	skipOut = skipOutInit;
	skipIn = skipInInit;
	while (buffSize && sl->remaining) {
		if (skipIn-- == 0) {
			// Get sampleLeft
			if (sl->sampleSize == 2) {
				sampleLeft = (long)(*(short *)(sl->current));
				if (sampleSize == 1) {
					sampleLeft = (sampleLeft >> 8) &0xff;
				}
			} else {
				sampleLeft = (long)*(sl->current);
				if (sampleSize == 2) {
					sampleLeft <<= 8;
				}
			}
			sl->current += sl->sampleSize;
			sl->remaining -= sl->sampleSize;

			if (sl->stereo) {
				// Get sampleRight
				if (sl->sampleSize == 2) {
					sampleRight = (long)(*(short *)(sl->current));
					if (sampleSize == 1) {
						sampleRight = (sampleRight >> 8) &0xff;
					}
				} else {
					sampleRight = (long)*(sl->current);
					if (sampleSize == 2) {
						sampleRight <<= 8;
					}
				}
				sl->current += sl->sampleSize;
				sl->remaining -= sl->sampleSize;

			} else {
				sampleRight = sampleLeft;
			}
			
			skipIn = skipInInit;
		}

		if (skipOut-- == 0) {
			// Output
			if (stereo) {
				if (sampleSize == 2) {
					*((short *)buff) += sampleLeft/2;
					buffSize -= sampleSize;
					buff += sampleSize;
					*((short *)buff) += sampleRight/2;
					buffSize -= sampleSize;
					buff += sampleSize;
				} else {
					*((char *)buff) += sampleLeft/2;
					buffSize -= sampleSize;
					buff += sampleSize;
					*((char *)buff) += sampleRight/2;
					buffSize -= sampleSize;
					buff += sampleSize;
				}
				totalOut += 2*sampleSize;
			} else {
				if (sampleSize == 2) {
					*((short *)buff) += (sampleLeft+sampleRight)>>2;
					buffSize -= sampleSize;
					buff += sampleSize;
				} else {
					*((char *)buff) += (sampleLeft+sampleRight)>>2;
					buffSize -= sampleSize;
					buff += sampleSize;
				}
				totalOut += sampleSize;
			}

			skipOut = skipOutInit;
		}
	}

	return totalOut;
}

--- NEW FILE: graphic24.h ---
////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

class GraphicDevice24: public GraphicDevice {
private:
	long GraphicDevice24::allocColor(Color color);

public:
	GraphicDevice24(FlashDisplay *fd);

	void clearCanvas();
	void fillLineAA(FillStyleDef *f, long y, long start, long end);
	void fillLine(FillStyleDef *f, long y, long start, long end);
	void fillLineBitmap(FillStyleDef *f, long y, long start, long end);
	void fillLineLG(Gradient *grad, long y, long start, long end);
	void fillLineRG(Gradient *grad, long y, long start, long end);
	void drawLine(long x1, long y1, long x2, long y2, long width);
};

--- NEW FILE: mp3.cc ---

#include "swf.h"
#include <unistd.h>
#include <fcntl.h>

#ifdef RCSID
static char *rcsid = "$Id: mp3.cc,v 1.1 2006-10-03 11:26:09 dslinux_amadeus Exp $";
#endif


//
// MP3 tables
//

static int vertab[4]={2,3,1,0};
static int freqtab[4]={44100,48000,32000};
static int ratetab[2][3][16]=
{
  {
    {  0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448,  0},
    {  0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384,  0},
    {  0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,  0},
  },
  {
    {  0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,  0},
    {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,  0},
    {  0,  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,  0},
  },
};


//
// The Decompressor
//

// Constructor
Mp3::Mp3(unsigned char *buffer, int len, long flags)
{
    this->src = buffer;
    this->pos = 0;
    this->len = len;

    int fd = open("/tmp/data.mp3", O_WRONLY|O_CREAT|O_TRUNC, 0666);
    if (fd >= 0) {
	if (write(fd, buffer, len) != len)
	    perror("write mp3 data");
	close(fd);
    } else {
	perror("/tmp/data.mp3");
    }
}


void
Mp3::Decompress(short *dst, long n)
{
    int iFrameCount = 0;

    pos = 0;

    for (;;) {
	// Get the MP3 frame header
	U8  hdr[4];
	for (int i=0; i<4; i++)
	    hdr[i] = src[pos++];

	// Decode the MP3 frame header
	int ver     = vertab[((hdr[1] >> 3) & 3)];
	int layer   = 3 - ((hdr[1] >> 1) & 3);
	int pad     = (hdr[2] >>1 ) & 1;
	int stereo  = ((hdr[3] >> 6) & 3) != 3;
	int freq    = 0;
	int rate    = 0;

	if (hdr[0] != 0xFF || hdr[1] < 0xE0 || ver==3 || layer != 2) {
	    // bad MP3 header
	    printf("\t\tBAD MP3 FRAME HEADER\n");
	    break;
	} else {
	    freq = freqtab[(hdr[2] >>2 ) & 3] >> ver;
	    rate = ratetab[ver ? 1 : 0][layer][(hdr[2] >> 4) & 15] * 1000;

	    if (!freq || !rate) {
		// bad MP3 header
		printf("\t\tBAD MP3 FRAME HEADER\n");
		break;
	    }
	}

	// Get the size of a decoded MP3 frame
	int iDecodedFrameSize = (576 * (stereo + 1));
	if (!ver)
	    iDecodedFrameSize *= 2;

	// Get the size of this encoded MP3 frame
	int iEncodedFrameSize = ((ver ? 72 : 144) * rate) / freq + pad - 4;

	char* ppszMpegVer[4] = {"1","2","2.5","3?"};

	printf("Frame%d: MPEG%s Layer%d %dHz %s %dbps size:Encoded:%d Decoded:%d\n",
	       iFrameCount, ppszMpegVer[ver], layer+1,
	       freq, stereo ? "stereo" : "mono", rate,
	       iEncodedFrameSize, iDecodedFrameSize);

	// Decode the MP3 frame
	//DecodeMp3Frame(&m_fileBuf[m_filePos], iEncodedFrameSize, iDecodedFrameSize);

	// Move to the next frame
	iFrameCount++;
	if (pos + iEncodedFrameSize >= len)
	    break;
	pos += iEncodedFrameSize;
    }
}

--- NEW FILE: sprite.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _SPRITE_H_
#define _SPRITE_H_

class Sprite : public Character {
public:
	Program		*program;

	Sprite(FlashMovie *movie, long id, long frameCount);
	~Sprite();
	Program		*getProgram();
	int		 execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform);
	int		 hasEventHandler();
	void		 reset();
	ActionRecord	*eventHandler(GraphicDevice *, FlashEvent *);
        int              isSprite(void);
	void		 getBoundingBox(Rect *bb, DisplayListEntry *de);
};

#endif /* _SPRITE_H_ */

--- NEW FILE: bitmap.cc ---
/////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: bitmap.cc,v 1.1 2006-10-03 11:26:08 dslinux_amadeus Exp $";
#endif

static unsigned char *inputData;

// Class variables

int Bitmap::haveTables = 0;

struct jpeg_decompress_struct Bitmap::jpegObject;

struct jpeg_source_mgr Bitmap::jpegSourceManager;

MyErrorHandler Bitmap::jpegErrorMgr;

Bitmap::Bitmap(long id, int level) : Character(BitmapType, id )
{
    pixels = NULL;
    alpha_buf = NULL;
    colormap = NULL;
    nbColors = 0;
    defLevel = level;
}

Bitmap::~Bitmap()
{
	if (pixels) {
		delete[] pixels;
	}
        if (alpha_buf) {
            delete[] alpha_buf;
        }
	if (colormap)
	{
		delete colormap;
	}
	if (haveTables) {
		jpeg_destroy_decompress(&jpegObject);
		haveTables = 0;
	}
}

static void errorExit(j_common_ptr info)
{
	(*info->err->output_message) (info);
	longjmp(((MyErrorHandler *)info->err)->setjmp_buffer, 1);
}

// Methods for Source data manager
static void initSource(struct jpeg_decompress_struct *cInfo)
{
	cInfo->src->bytes_in_buffer = 0;
}

static boolean fillInputBuffer(struct jpeg_decompress_struct *cInfo)
{
	cInfo->src->next_input_byte = inputData;
	cInfo->src->bytes_in_buffer = 1;
	inputData++;

	return 1;
}

static void skipInputData(struct jpeg_decompress_struct *cInfo, long count)
{
	cInfo->src->bytes_in_buffer = 0;
	inputData += count;
}

static boolean resyncToRestart(struct jpeg_decompress_struct *cInfo, int desired)
{
	return jpeg_resync_to_restart(cInfo, desired);
}

static void termSource(struct jpeg_decompress_struct *cInfo)
{
}

long Bitmap::getWidth()
{
	return width;
}

long Bitmap::getHeight()
{
	return height;
}

Color *
Bitmap::getColormap(long *n) {
       if (n) *n = nbColors;
       return colormap;
}

unsigned char *
Bitmap::getPixels()
{
       return pixels;
}

// Read Tables and Compressed data to produce an image

static int
buildJpegAlpha(Bitmap *b, unsigned char *buffer)
{
    z_stream	stream;
    int		status;
    unsigned char  *data;

    data = new unsigned char[b->width*b->height];
    if (data == NULL) 
        return -1;

    stream.next_in = buffer;
    stream.avail_in = 1;
    stream.next_out = data;
    stream.avail_out = b->width*b->height;
    stream.zalloc = Z_NULL;
    stream.zfree = Z_NULL;
            
    status = inflateInit(&stream);

    while (1) {
        status = inflate(&stream, Z_SYNC_FLUSH) ;
        if (status == Z_STREAM_END) {
            break;
        }
        if (status != Z_OK) {
            printf("Zlib data error : %s\n", stream.msg);
	    delete data;
            return -1;
        }
        stream.avail_in = 1;
    }

    inflateEnd(&stream);
            
    b->alpha_buf = data;

    return 0;
}

int
Bitmap::buildFromJpegInterchangeData(unsigned char *stream, int read_alpha, long offset)
{
	struct jpeg_decompress_struct cInfo;
	struct jpeg_source_mgr mySrcMgr;
	MyErrorHandler errorMgr;
	JSAMPROW buffer[1];
	unsigned char *ptrPix;
	int stride;
	long n;

#if PRINT&1
        printf("flash: loading jpeg (interchange)\n");
#endif

	// Kludge to correct some corrupted files
	if (stream[1] == 0xd9 && stream[3] == 0xd8) {
		stream[3] = 0xd9;
		stream[1] = 0xd8;
	}

	// Setup error handler
	cInfo.err = jpeg_std_error(&errorMgr.pub);
	errorMgr.pub.error_exit = errorExit;

	if (setjmp(errorMgr.setjmp_buffer)) {
		// JPEG data Error
		jpeg_destroy_decompress(&cInfo);
		if (pixels) {
			delete[] pixels;
			pixels = NULL;
		}
		return -1;
	}

	// Set current stream pointer to stream
	inputData = stream;

	// Here it's Ok

	jpeg_create_decompress(&cInfo);

	// Setup source manager structure
	mySrcMgr.init_source = initSource;
	mySrcMgr.fill_input_buffer = fillInputBuffer;
	mySrcMgr.skip_input_data = skipInputData;
	mySrcMgr.resync_to_restart = resyncToRestart;
	mySrcMgr.term_source = termSource;

	// Set default source manager
	cInfo.src = &mySrcMgr;

	jpeg_read_header(&cInfo, FALSE);

	jpeg_read_header(&cInfo, TRUE);
	cInfo.quantize_colors = TRUE;	// Create colormapped image
	jpeg_start_decompress(&cInfo);

	// Set objet dimensions
	height = cInfo.output_height;
	width = cInfo.output_width;
        bpl = width;
	pixels = new unsigned char [height*width];
	if (pixels == NULL) {
		jpeg_finish_decompress(&cInfo);
		jpeg_destroy_decompress(&cInfo);
		return -1;
	}
	ptrPix = pixels;

	stride = cInfo.output_width * cInfo.output_components;

	buffer[0] = (JSAMPROW)malloc(stride);

	while (cInfo.output_scanline < cInfo.output_height) {

		jpeg_read_scanlines(&cInfo, buffer, 1);

		memcpy(ptrPix,buffer[0],stride);

		ptrPix+= stride;
	}

        free(buffer[0]);

	colormap = new Color[cInfo.actual_number_of_colors];
	if (colormap == NULL) {
		delete pixels;
		jpeg_finish_decompress(&cInfo);
		jpeg_destroy_decompress(&cInfo);
		return -1;
	}
	nbColors = cInfo.actual_number_of_colors;

	for(n=0; n < nbColors; n++)
	{
		colormap[n].red = cInfo.colormap[0][n];
		colormap[n].green = cInfo.colormap[1][n];
		colormap[n].blue = cInfo.colormap[2][n];
	}

	jpeg_finish_decompress(&cInfo);
	jpeg_destroy_decompress(&cInfo);

        if (read_alpha) {
            if (buildJpegAlpha(this,  stream + offset) < 0) {
	    	return -1;
	    }
        }
	return 0;
}

// Read JPEG image using pre-loaded Tables

int
Bitmap::buildFromJpegAbbreviatedData(unsigned char *stream)
{
	JSAMPROW buffer[1];
	unsigned char *ptrPix;
	int stride;
	long n;
	int status;

#if PRINT&1
        printf("flash: loading jpeg (abbreviated)\n");
#endif

	// Set current stream pointer to stream
	inputData = stream;

	// Error handler
	if (setjmp(jpegErrorMgr.setjmp_buffer)) {
		// JPEG data Error
		//jpeg_destroy_decompress(&jpegObject);
		if (pixels) {
			delete[] pixels;
			pixels = NULL;
		}
		return -1;
	}

	// Here it's ok

	jpeg_read_header(&jpegObject, TRUE);
	jpegObject.quantize_colors = TRUE;	// Create colormapped image
	jpeg_start_decompress(&jpegObject);

	// Set objet dimensions
	height = jpegObject.output_height;
	width = jpegObject.output_width;
        bpl = width;
	pixels = new unsigned char [height*width];
	if (pixels == NULL) {
		jpeg_finish_decompress(&jpegObject);
		return -1;
	}
	ptrPix = pixels;

	stride = jpegObject.output_width * jpegObject.output_components;

	buffer[0] = (JSAMPROW)malloc(stride);

	while (jpegObject.output_scanline < jpegObject.output_height) {

		status = jpeg_read_scanlines(&jpegObject, buffer, 1);

		memcpy(ptrPix,buffer[0],stride);

		ptrPix+= stride;
	}
        
        free(buffer[0]);

	colormap = new Color[jpegObject.actual_number_of_colors];
	if (colormap == NULL) {
		jpeg_finish_decompress(&jpegObject);
		delete pixels;
		return -1;
	}
	nbColors = jpegObject.actual_number_of_colors;

	for(n=0; n < nbColors; n++)
	{
		colormap[n].red = jpegObject.colormap[0][n];
		colormap[n].green = jpegObject.colormap[1][n];
		colormap[n].blue = jpegObject.colormap[2][n];
	}

	status = jpeg_finish_decompress(&jpegObject);

	return 0;
}

// Just init JPEG object and read JPEG Tables

int
Bitmap::readJpegTables(unsigned char *stream)
{
	if (haveTables) {
		//Error, it has already been initialized
		return -1;
	}

	// Setup error handler
	jpegObject.err = jpeg_std_error(&jpegErrorMgr.pub);
	jpegErrorMgr.pub.error_exit = errorExit;

	if (setjmp(jpegErrorMgr.setjmp_buffer)) {
		// JPEG data Error
		jpeg_destroy_decompress(&jpegObject);
		return -1;
	}

	// Set current stream pointer to stream
	inputData = stream;

	// Here it's Ok

	jpeg_create_decompress(&jpegObject);

	// Setup source manager structure
	jpegSourceManager.init_source = initSource;
	jpegSourceManager.fill_input_buffer = fillInputBuffer;
	jpegSourceManager.skip_input_data = skipInputData;
	jpegSourceManager.resync_to_restart = resyncToRestart;
	jpegSourceManager.term_source = termSource;

	// Set default source manager
	jpegObject.src = &jpegSourceManager;

	jpeg_read_header(&jpegObject, FALSE);

	haveTables = 1;

	return 0;
}

int
Bitmap::buildFromZlibData(unsigned char *buffer, int width, int height, int format, int tableSize, int tableHasAlpha)
{
	z_stream	stream;
	int		status;
	unsigned char  *data;
	int		elementSize;

#if PRINT&1
        printf("flash: loading with zlib\n");
#endif

	this->width = width;
	this->height = height;
        this->bpl = width;

	if (tableHasAlpha) {
		elementSize = 4;	// Cmap is RGBA
	} else {
		elementSize = 3;	// Cmap is RGB
	}

	stream.next_in = buffer;
	stream.avail_in = 1;
	stream.zalloc = Z_NULL;
	stream.zfree = Z_NULL;

	tableSize++;

	// Uncompress Color Table
	if (format == 3) {
		unsigned char *colorTable;
		long n;

		// Ajust width for 32 bit padding
		width = (width+3)/4*4;
		this->width = width;
		this->bpl = width;

		depth = 1;
		colorTable = new unsigned char[tableSize*elementSize];
		if (colorTable == NULL) {
			return -1;
		}

		stream.next_out = colorTable;
		stream.avail_out = tableSize*elementSize;

		inflateInit(&stream);

		while (1) {
			status = inflate(&stream, Z_SYNC_FLUSH);
			if (status == Z_STREAM_END) {
					break;
			}
			if (status != Z_OK) {
				printf("Zlib cmap error : %s\n", stream.msg);
				return -1;
			}
			stream.avail_in = 1;
			// Colormap if full
			if (stream.avail_out == 0) {
				break;
			}
		}

		nbColors = tableSize;

		colormap = new Color[nbColors];
		if (colormap == NULL) {
			delete colorTable;
			return -1;
		}

		for(n=0; n < nbColors; n++) {
			colormap[n].red = colorTable[n*elementSize+0];
			colormap[n].green = colorTable[n*elementSize+1];
			colormap[n].blue = colorTable[n*elementSize+2];
			if (tableHasAlpha) {
				colormap[n].alpha = colorTable[n*elementSize+3];
			}
		}

		delete colorTable;

	} else if (format == 4) {
		depth = 2;
		width = (width+1)/2*2;
		this->bpl = width;
	} else if (format == 5) {
		depth = 4;
	}

	data = new unsigned char[depth*width*height];
	if (data == NULL) {
		if (colormap) delete colormap;
		return -1;
	}

	stream.next_out = data;
	stream.avail_out = depth*width*height;

	if (format != 3) {
		status = inflateInit(&stream);
	}

	while (1) {
		status = inflate(&stream, Z_SYNC_FLUSH) ;
		if (status == Z_STREAM_END) {
				break;
		}
		if (status != Z_OK) {
			printf("Zlib data error : %s\n", stream.msg);
			delete data;
			return -1;
		}
		stream.avail_in = 1;
	}

	inflateEnd(&stream);

	pixels = new unsigned char [height*width];
	if (pixels == NULL) {
		if (colormap) delete colormap;
		delete data;
		return -1;
	}

	if (format != 3) {
		int n,c;
		unsigned char r,g,b,a;
		unsigned char *ptr;

                r = g = b = a = 0; /* to supress warnings */

		nbColors = 0;
		colormap = new Color[256];
		if (colormap == NULL) {
			delete data;
			delete pixels;
			return -1;
		}
                memset(colormap, 0, 256 * sizeof(Color));
		ptr = pixels;
		
		for(n=0; n < width*height*depth; n+=depth,ptr++) {
                    
			switch (format) {
				case 4:
					a = 1;
					r = (data[n] & 0x78)<<1;
					g = ((data[n] & 0x03)<<6) | (data[n+1] & 0xc0)>>2;
					b = (data[n+1] & 0x1e)<<3;
					break;
				case 5:
					a = data[n];
					// Reduce color dynamic range
					r = data[n+1]&0xe0;
					g = data[n+2]&0xe0;
					b = data[n+3]&0xe0;
					break;
			}
			for(c=0; c < nbColors; c++) {
				if (r == colormap[c].red
				&&  g == colormap[c].green
				&&  b == colormap[c].blue) {
					*ptr = c;
					break;
				}
			}
			if (c == nbColors) {
				if (nbColors == 256) continue;
				nbColors++;
				if (nbColors == 256) {
					//printf("Colormap entries exhausted. After %d scanned pixels\n", n/4);
				}
				colormap[c].alpha = a;
				colormap[c].red   = r;
				colormap[c].green = g;
				colormap[c].blue  = b;
				*ptr = c;
			}
		}
	} else {
		memcpy(pixels, data, width*height);
		if (tableHasAlpha) {
			int n;
			unsigned char *ptr, *alpha;

			alpha_buf = (unsigned char *)malloc(width*height);
			ptr = data;
			alpha = alpha_buf;
			for(n=0; n < width*height; n++, ptr++, alpha++) {
				*alpha = colormap[*ptr].alpha;
			}
		}
	}

	delete data;
	return 0;
}


--- NEW FILE: button.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _BUTTON_H_
#define _BUTTON_H_

struct ButtonRecord {
	ButtonState		 state;
	Character		*character;
	long			 layer;
	Matrix			 buttonMatrix;
	Cxform			*cxform;

	struct ButtonRecord	*next;
};

struct Condition {
	long			 transition;
	ActionRecord		*actions;

	Condition		*next;
};

class Button : public Character {
public:
	long			 defLevel;

	ButtonRecord		*buttonRecords;
	ActionRecord		*actionRecords;
	Condition		*conditionList;

	long			 isMenu;

	Sound			*sound[4];

	Button(long id, int level = 1);
	~Button();
	void		 addActionRecord( ActionRecord *ar );
        void		 addButtonRecord( ButtonRecord *br );
	void		 addCondition( long transition );
	int		 execute(GraphicDevice *gd, Matrix *matrix, 
                                 Cxform *cxform, ButtonState renderState);
	ActionRecord	*getActionFromTransition(ButtonState currentState, 
                                                 ButtonState old);
	void		 getRegion(GraphicDevice *gd, Matrix *matrix, 
                                   void *id, ScanLineFunc scan_line_func);
	ButtonRecord	*getButtonRecords();
	void		 setButtonSound(Sound *, int);
	void		 setButtonMenu(int);

	ActionRecord	*getActionRecords();
	Condition	*getConditionList();
	Sound	       **getSounds();

	void		 getBoundingBox(Rect *bb, DisplayListEntry *);

	void		 updateButtonState(DisplayListEntry *);
	Character	*getRenderCharacter(ButtonState state);

	// Builtin
	int	 isButton() {
		return 1;
	};

#ifdef DUMP
	void		 dump(BitStream *);
	void		 dumpButtonRecords(BitStream *, int putCxform = 0);
	void		 dumpButtonConditions(BitStream *);
#endif
};

#endif /* _BUTTON_H_ */

--- NEW FILE: displaylist.cc ---
////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//  

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: displaylist.cc,v 1.1 2006-10-03 11:26:08 dslinux_amadeus Exp $";
#endif

#define PRINT 0

void deleteButton(FlashMovie *movie, DisplayListEntry *e)
{
    /* save the focus */
    if (movie->mouse_active == 0 && e->renderState == stateOver) {
        movie->lost_over = (Button *)e->character;
        movie->cur_focus = NULL;
    }

    if (e == movie->cur_focus) {
        movie->cur_focus = NULL;
    }
}

void addButton(FlashMovie *movie, DisplayListEntry *e)
{
    if (movie->mouse_active == 0 && 
        movie->cur_focus == NULL &&
        movie->lost_over == (Button *)e->character) {
        /* restore the lost focus */
        e->renderState = stateOver;
        e->oldState = stateOver;
	((Button *)e->character)->updateButtonState(e);
        movie->lost_over = NULL;
        movie->cur_focus = e;
    }
}

DisplayList::DisplayList(FlashMovie *movie)
{
	list = NULL;
        this->movie = movie;
	bbox.reset();
	isSprite = 0;
}

DisplayList::~DisplayList()
{
	clearList();
}

void
DisplayList::clearList()
{
	DisplayListEntry *del, *e;

	for(e = list; e;)
	{
		updateBoundingBox(e);
                if (e->character->isButton()) {
                    deleteButton(movie,e);
                }
		del = e;
		e = e->next;
		delete del;
	}
	list = 0;
}

DisplayListEntry *
DisplayList::getList()
{
	return list;
}

static void bbox(Rect *rect, Matrix *m, long x1, long y1)
{
    long x,y;

    x = m->getX(x1,y1);
    y = m->getY(x1,y1);
    if (x < rect->xmin) rect->xmin = x;
    if (x > rect->xmax) rect->xmax = x;
    if (y < rect->ymin) rect->ymin = y;
    if (y > rect->ymax) rect->ymax = y;
}

// Update bb to include boundary, optional reset of bb
void transformBoundingBox(Rect *bb, Matrix *matrix, Rect *boundary, int reset)
{
    if (reset) {
        bb->reset();
    }
    
    if (boundary->xmin != LONG_MAX) {
        bbox(bb, matrix, boundary->xmin, boundary->ymin);
        bbox(bb, matrix, boundary->xmax, boundary->ymin);
        bbox(bb, matrix, boundary->xmin, boundary->ymax);
        bbox(bb, matrix, boundary->xmax, boundary->ymax);
    }
}

void
DisplayList::placeObject(GraphicDevice *gd,Character *character, long depth, Matrix *matrix, Cxform *cxform, char *name)
{
	DisplayListEntry *n,*e,*prev;

	n = new DisplayListEntry;
	if (n == NULL) return;

	n->depth = depth;
	n->matrix = matrix;
	n->cxform = cxform;
	n->character = character;
	n->instanceName = name;
	n->owner = this;

#if 0
        printf("Dl %lx: placeObject: depth=%d character=%d cxform=%p\n",
               this, n->depth,n->character ? n->character->getTagId() : 0, cxform);
#endif

	if (character == 0 || matrix == 0 || cxform == 0) {
		for (e = list; e; prev = e, e = e->next) {
			if (e->depth == n->depth) {
				if (character == 0) {
					n->character = e->character;
				}
				if (matrix == 0) {
					n->matrix = e->matrix;
				}
				if (cxform == 0) {
					n->cxform = e->cxform;
				}
				break;
			}
		}
	}

	if (n->character == 0) {
		// Not found !!!    Should not happen
            //		printf("PlaceObject cannot find character at depth %ld\n", n->depth);
		delete n;
		return;
	}

	prev = 0;
	for (e = list; e; prev = e, e = e->next)
	{
		if (e->depth == n->depth) {
                        if (e->character->isButton()) {
                            deleteButton(movie, e);
                        }

			// Do update, object has moved or been resized
		        updateBoundingBox(e);

			// Replace object
                        e->depth = n->depth;
                        e->matrix = n->matrix;
                        e->cxform = n->cxform;
                        e->character = n->character;
                        /* if it is a button, we must update its state */
                        if (e->character->isButton()) {
                            movie->buttons_updated = 1;
                            addButton(movie, e);
                        }

		        updateBoundingBox(e);

                        delete n;
                        return;
		}
		if (e->depth > n->depth) break;
	}
        /* new object */

        /* button instantiation */
        if (n->character->isButton()) {
            n->renderState = stateUp;
            n->oldState = stateUp;
	    ((Button *)n->character)->updateButtonState(n);
            addButton(movie,n);
        }

	updateBoundingBox(n);

	if (prev == 0) {
		// Object comes at first place
		n->next = list;
		list = n;
	} else {
		// Insert object
		n->next = prev->next;
		prev->next = n;
	}
}


Character *
DisplayList::removeObject(GraphicDevice *gd,Character *character, long depth)
{
    DisplayListEntry *e,*prev;
    
    // List should not be empty
    if (list == 0) return 0;
    
#if 0
    printf("removeObject: depth=%d character=%d\n",
           depth,character ? character->getTagId() : 0);
#endif
    
    prev = 0;
    for (e = list; e; prev = e, e = e->next) {
        if (e->depth == depth) {
            if (prev) {
                prev->next = e->next;
            } else {
                list = e->next;
            }
            if (character == 0) {
                character = e->character;
            }
            if (e->character->isButton()) {
                deleteButton(movie, e);
            }
            if (e->character->isSprite()) {
	    	((Sprite*)e->character)->reset();
	    }
                
	    updateBoundingBox(e);

            delete e;
            return character;
        }
    }
    return 0;	// Should not happen
}

void
DisplayList::updateBoundingBox(DisplayListEntry *e)
{
	Rect	 rect;

	//rect.reset();
	e->character->getBoundingBox(&rect,e);
	transformBoundingBox(&this->bbox, e->matrix, &rect, 0);
}

int
DisplayList::updateSprites()
{
    Sprite *sprite;
    DisplayListEntry *e;
    int refresh = 0;

    for (e = this->list; e != NULL; e = e->next) {
        if (e->character->isButton() && e->buttonCharacter) {
		if (e->buttonCharacter->isSprite()) {
			Matrix mat;

			sprite = (Sprite *)e->buttonCharacter;
			refresh |= sprite->program->dl->updateSprites();
			refresh |= sprite->program->nestedMovie(this->movie->gd,this->movie->sm, e->matrix, e->cxform);
			mat = (*e->matrix) * e->buttonMatrix;
			transformBoundingBox(&this->bbox, &mat,
					&(sprite->program->dl->bbox),
					0);
		}
	}
        if (e->character->isSprite()) {
		sprite = (Sprite *)e->character;
		refresh |= sprite->program->dl->updateSprites();
		refresh |= sprite->program->nestedMovie(this->movie->gd,this->movie->sm, e->matrix, e->cxform);
		transformBoundingBox(&this->bbox, e->matrix,
				&(sprite->program->dl->bbox),
				0);
        }
    }
    return refresh;
}

/* Function can return either 0,1 or 2
   0:  Nothing match, continue
   1:  Something matches, but continue searching
   2:  Something matches, but stop searching
*/

static int exploreButtons1(Program *prg, void *opaque, 
                           ExploreButtonFunc func)
{
    DisplayListEntry *e;
    int ret, ret2 = 0;

    for(e=prg->dl->list; e != NULL; e = e->next) {
	if (e->character == NULL) continue;
        if (e->character->isButton()) {
            ret = func(opaque,prg,e);
	    if (ret == 2) return ret;	// Func asks to return at once !!!
            if (ret) ret2 = 1;
        }
        if (e->character->isSprite()) {
            ret = exploreButtons1(((Sprite *)e->character)->program,
                                  opaque,func);
	    if (ret == 2) return ret;	// Func asks to return at once !!!
            if (ret) ret2 = 1;
        }
    }
    return ret2;
}

int exploreButtons(FlashMovie *movie, void *opaque, ExploreButtonFunc func)
{
    CInputScript *script;
    int ret;

    script = movie->main;
    while (script != NULL) {
	if (script->program) {
		ret = exploreButtons1(script->program, opaque, func);
		if (ret) return ret;
	}
        script = script->next;
    }
    return 0;
}

typedef struct {
    long x,y;
    int hit;
    DisplayListEntry *bhit;
} HitTable;

static void button_hit_func(void *id, long y, long start, long end)
{
    HitTable *h = (HitTable *) id;
    if ( y == h->y && (h->x >= start && h->x < end) )
        h->hit = 1;
}

typedef struct {
    FlashMovie *movie;
    DisplayListEntry *bhit;
} ButtonHit;

static int button_hit(void *opaque, Program *prg, DisplayListEntry *e)
{
    ButtonHit *h = (ButtonHit *) opaque;
    HitTable hit_table;
    FlashMovie *movie = h->movie;
    Rect bb,boundary;
    Matrix mat;
    ButtonState save;

    hit_table.x = movie->mouse_x;
    hit_table.y = movie->mouse_y / FRAC;
    hit_table.hit = 0;
    
    // Compute the bounding box in screen coordinates
    save = e->renderState;
    e->renderState = stateHitTest;
    e->character->getBoundingBox(&boundary,e);
    e->renderState = save;
    mat = (*movie->gd->adjust) * e->renderMatrix;
    transformBoundingBox(&bb, &mat, &boundary, 1);
    // Check if mouse is within bb
    if (movie->mouse_x < bb.xmin) return 0;
    if (movie->mouse_x > bb.xmax) return 0;
    if (movie->mouse_y < bb.ymin) return 0;
    if (movie->mouse_y > bb.ymax) return 0;

    e->character->getRegion(movie->gd, &e->renderMatrix, 
                            &hit_table, button_hit_func);
                
    if (hit_table.hit) {
        h->bhit = e;
        return 1;
    } else {
        return 0;
    }
}

static int button_reset(void *opaque, Program *prg, DisplayListEntry *e)
{
    if (e->renderState != stateUp) {
	    e->owner->updateBoundingBox(e);
	    e->oldState = e->renderState;
	    e->renderState = stateUp;
	    ((Button *)e->character)->updateButtonState(e);
	    e->owner->updateBoundingBox(e);
    }
    return 0;
}

/* update the button states according to the current mouse state & return the list of actions */
void
DisplayList::updateButtons(FlashMovie *movie)
{
    DisplayListEntry *bhit;
    ButtonHit h;

    if (movie->mouse_active) {

        h.bhit = NULL;
        h.movie = movie;

        exploreButtons(movie, &h, button_hit);

        bhit = h.bhit;

        /* set every button to not hit */
        exploreButtons(movie, NULL, button_reset);

        if (bhit) {
	    ButtonState state;

            if (movie->button_pressed) {
                state = stateDown;
            } else {
                state = stateOver;
            }
	    if (state != bhit->renderState) {
		    bhit->owner->updateBoundingBox(bhit);
		    bhit->renderState = state;
		    ((Button *)bhit->character)->updateButtonState(bhit);
		    bhit->owner->updateBoundingBox(bhit);
		    movie->cur_focus = bhit;
		    if (movie->cursorOnOff)
			    movie->cursorOnOff(1,movie->cursorOnOffClientData);
	    }
        } else {
	    if (movie->cursorOnOff)
		    movie->cursorOnOff(0,movie->cursorOnOffClientData);
	}
    }
}

typedef struct {
    ActionRecord *action;	// Action to do
    Program	 *prg;		// Context program
} ButtonAction;

static int button_action(void *opaque, Program *prg, DisplayListEntry *e)
{
    ButtonAction *h = (ButtonAction *)opaque;
    static ActionRecord actionRefresh;
    static ActionRecord soundFx;
    Button *b;
    ActionRecord **paction;
    int n;

    actionRefresh.action = ActionRefresh;
    actionRefresh.next = 0;
    
    soundFx.action = ActionPlaySound;
    soundFx.next = &actionRefresh;

    b = (Button *)e->character;

    if (e->oldState != e->renderState) {
        
        paction = &actionRefresh.next;
        
        if (b->conditionList) {
            *paction = b->getActionFromTransition(e->renderState, e->oldState);
        } else if (e->renderState == stateDown) {
            /* if the button is pressed and 
               no condition list is defined*/
            *paction = b->actionRecords;
        }
        
        switch(e->renderState) {
        case stateUp:
            n = 0;
            break;
        case stateOver:
            n = 1;
            break;
        default:
            /* case stateDown: */
            n = 2;
            break;
        }
        
        if (b->sound[n]) {
            soundFx.sound = b->sound[n];
            h->action = &soundFx;
        } else {
            h->action = &actionRefresh;
        }
        
        e->oldState = e->renderState;

        h->prg = prg;
        return 2;
    }
    h->action = 0;	// Nothing to do about this
    return 0;
}

int computeActions(FlashMovie *movie, Program **prg, ActionRecord **ar)
{
    ButtonAction h;

    h.action = NULL;
    exploreButtons(movie, &h, button_action);
    if (h.action) {
    	*prg = h.prg;
	*ar = h.action;
	return 1;
    }
    return 0;
}

#define FOCUS_ZOOM       1.5
/* in pixels */
#define FOCUS_SIZE_MIN   50
#define FOCUS_TRANSLATE  15

int
DisplayList::render(GraphicDevice *gd, Matrix *render_matrix, Cxform *cxform)
{
	DisplayListEntry *e,*cur_focus;
	int sprite = 0;
	long n = 0;
        Cxform cxf,*cxf1;
	Rect bb,boundary;

        cur_focus = NULL;

	/*
	if (isSprite == 0) {
		if (this->bbox.xmin == LONG_MAX) return 0;
		gd->updateClippingRegion(&this->bbox, render_matrix);
		gd->clearCanvas();
	}
	*/

	for (e = list; e; e = e->next)
	{
#if PRINT
		printf("Character %3d @ %3d\n", e->character ? e->character->getTagId() : 0, e->depth);
#endif
		if (e->character) {
			Matrix mat;

			if (render_matrix) {
				mat = *render_matrix;
			}

			if (e->matrix) {
				mat = mat * (*e->matrix);
			}

                        /* fast clipping */
			// If object boundaries are outside current clip region give up with rendering
                        e->character->getBoundingBox(&boundary,e);
                        if (boundary.xmin != LONG_MAX) {
                            Matrix tmat;

                            tmat = (*gd->adjust) * mat;
                            transformBoundingBox(&bb, &tmat, &boundary, 1);

                            bb.xmin = bb.xmin >> FRAC_BITS;
                            bb.ymin = bb.ymin >> FRAC_BITS;
                            bb.xmax = (bb.xmax + FRAC - 1) >> FRAC_BITS;
                            bb.ymax = (bb.ymax + FRAC - 1) >> FRAC_BITS;

                            if (bb.xmin >= gd->clip_rect.xmax ||
                                bb.xmax <= gd->clip_rect.xmin ||
                                bb.ymin >= gd->clip_rect.ymax ||
                                bb.ymax <= gd->clip_rect.ymin) {
                                continue;
                            }
                        }

                        if (cxform == NULL) {
                            cxf1 = e->cxform;
                        }
			else if (e->cxform == NULL) {
                            cxf1 = cxform;
                        }
			else {
                            cxf1 = &cxf;
                            cxf.ra = cxform->ra * e->cxform->ra;
                            cxf.ga = cxform->ga * e->cxform->ga;
                            cxf.ba = cxform->ba * e->cxform->ba;
                            cxf.aa = cxform->aa * e->cxform->aa;
                            
                            cxf.rb = (long)(cxform->ra * e->cxform->rb + cxform->rb);
                            cxf.gb = (long)(cxform->ga * e->cxform->gb + cxform->gb);
                            cxf.bb = (long)(cxform->ba * e->cxform->bb + cxform->bb);
                            cxf.ab = (long)(cxform->aa * e->cxform->ab + cxform->ab);
                        }

                        if (e->character->isButton()) {
                            Button *b = (Button *) e->character;

                            e->renderMatrix = mat;

                            if (e->renderState != stateUp && movie->mouse_active == 0) {
                                cur_focus = e;
				((Button *)e->character)->updateButtonState(e);
                            }

                            if (b->execute(gd, &mat, cxf1, e->renderState)) {
				sprite = 1;
                            }
                        } else {
                            if (e->character->execute(gd, &mat, cxf1)) {
				sprite = 1;
                            }
                        }

			n++;
		}
	}

#if 0
    {
	/* display the bounding box (debug) */
	Matrix tmat;
	long x1,x2,y1,y2;
	Color white;

	white.red = 255;
	white.green = white.blue = 0;
	gd->setForegroundColor(white);

	if (render_matrix) {
		tmat = (*gd->adjust) * (*render_matrix);
	} else {
		tmat = *gd->adjust;
	}
	x1 = bbox.xmin;
	y1 = bbox.ymin;
	x2 = bbox.xmax;
	y2 = bbox.ymax;
	gd->drawLine(tmat.getX(x1,y1),tmat.getY(x1,y1),tmat.getX(x2,y1),tmat.getY(x2,y1),10*FRAC);
	gd->drawLine(tmat.getX(x2,y1),tmat.getY(x2,y1),tmat.getX(x2,y2),tmat.getY(x2,y2),10*FRAC);
	gd->drawLine(tmat.getX(x2,y2),tmat.getY(x2,y2),tmat.getX(x1,y2),tmat.getY(x1,y2),10*FRAC);
	gd->drawLine(tmat.getX(x1,y2),tmat.getY(x1,y2),tmat.getX(x1,y1),tmat.getY(x1,y1),10*FRAC);
	bbox.print();
    }
#endif
        
	// Reset clipping zone
        bbox.reset();

	return sprite;
}

void
DisplayList::getBoundary(Rect *bb)
{
	DisplayListEntry *e;
	Rect boundary;

	bb->reset();
	for (e = list; e; e = e->next)
	{
		if (e->character) {
			e->character->getBoundingBox(&boundary,e);
			transformBoundingBox(bb, e->matrix, &boundary, 0);
		}
	}
}

extern "C" {

void dump_buttons(FlashHandle flashHandle)
{
#if 0
    Rect rect;
    DisplayListEntry *e;
    FlashMovie *movie;

    movie = (FlashMovie *)flashHandle;

    for (e = movie->first_button; e; e = e->next_button) {
        computeBBox(movie,&rect,e);
        printf("button: id=%d pos=%d %d %d %d\n",
               e->character->getTagId(),
               rect.xmin, rect.ymin, rect.xmax, rect.ymax);
    }
#endif
}

}

--- NEW FILE: graphic16.cc ---
////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

#include "graphic16.h"

extern unsigned char SQRT[];

#define FULL_AA
#define PRINT 0

typedef unsigned short TYPE;

#if RGB555
#define RED_MASK   0x7800
#define GREEN_MASK 0x03E0
#define BLUE_MASK  0x001F
#else
#define RED_MASK   0xF800
#define GREEN_MASK 0x07E0
#define BLUE_MASK  0x001F
#endif

GraphicDevice16::GraphicDevice16(FlashDisplay *fd) : GraphicDevice(fd)
{
}

long
GraphicDevice16::allocColor(Color color)
{
#if RGB555
	return (color.red >> 3)<<10 | (color.green>>3)<<5 | (color.blue>>3);
#else
	return (color.red >> 3)<<11 | (color.green>>2)<<5 | (color.blue>>3);
#endif
}

void
GraphicDevice16::clearCanvas()
{
    TYPE  pixel;
    TYPE *point,*p;
    long                 h, w,n;

    if (!bgInitialized) return;

    pixel = allocColor(backgroundColor);

    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;
        while (n--) {
            *p++ = pixel;
        }

        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;
}

/* alpha = 0 : select c1, alpha = 255 select c2 */
static inline unsigned long
mix_alpha(unsigned long c1, 
                                      unsigned long c2, int alpha)
{
	long r1,r2,r;
	long g1,g2,g;
	long b1,b2,b;

	r1 = c1 & RED_MASK;
	r2 = c2 & RED_MASK;
	r = (((r2-r1)*alpha + r1 * 256) >> 8) & RED_MASK;

	g1 = c1 & GREEN_MASK;
	g2 = c2 & GREEN_MASK;
	g = (((g2-g1)*alpha + g1 * 256) >> 8) & GREEN_MASK;

	b1 = c1 & BLUE_MASK;
	b2 = c2 & BLUE_MASK;
	b = (((b2-b1)*alpha + b1 * 256) >> 8) & BLUE_MASK;

	return (r|g|b);
}

void
GraphicDevice16::fillLineAA(FillStyleDef *f, long y, long start, long end)
{
    register long   n;
    TYPE *line;
    TYPE *point,pixel;
    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;
    
    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 = mix_alpha(*point, pixel, start_alpha + end_alpha - 255);
        } else {
            n = end-start;
            if (start_alpha < 255) {
                *point = mix_alpha(*point, pixel, start_alpha);
                point++;
                n--;
            }
            while (n > 0) {
                *point = pixel;
                point++;
                n--;
            }
            if (end_alpha > 0) {
                *point = mix_alpha(*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 = mix_alpha(*point, pixel, 
                               ((start_alpha + end_alpha - 255) * alpha) >> 8);
        } else {
            n = end-start;
            if (start_alpha < 255) {
                *point = mix_alpha(*point, pixel, (start_alpha * alpha) >> 8);
                point++;
                n--;
            }
            while (n > 0) {
                *point = mix_alpha(*point, pixel, alpha);
                point++;
                n--;
            }
            if (end_alpha > 0) {
                *point = mix_alpha(*point, pixel, (end_alpha * alpha) >> 8);
            }
        }
    }
}

void
GraphicDevice16::fillLine(FillStyleDef *f, long y, long start, long end)
{
	register long   n;
        TYPE *line,*point;
        TYPE pixel;
        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;
        alpha = f->color.alpha;
        if (alpha == ALPHA_OPAQUE) {
            while (n--) { 
		*point = pixel;
		point++;			
            }
        } else {
            while (n--) { 
		*point = mix_alpha(*point, pixel, alpha);
		point++;			
            }
        }
}

void
GraphicDevice16::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;
    TYPE *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 = (TYPE *) (this->canvasBuffer + this->bpl*y + start * 2);
    
    /* the coordinates in the image are normalized to 16 bits */
    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);
    
    pixels = b->pixels;
    pixbpl = b->bpl;
    cmap = f->cmap;

    if (b->alpha_buf == NULL) {
        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--;
        }
    } else if (f->alpha_table) {
        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_alpha(*p, pixel, alpha_table[b->alpha_buf[offset]]);
            }
            x1 += dx;
            y1 += dy;
            p++;
            n--;
        }
    } 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_alpha(*p, pixel, b->alpha_buf[offset]);
            }
            x1 += dx;
            y1 += dy;
            p++;
            n--;
        }
    }
}

void
GraphicDevice16::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;

        r = (long) (m->a * start + m->b * y + m->tx);
        dr = (long) (m->a);

        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>>16;
                    *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
                    point++;
                    r += dr;
		    n--;
		}
#endif /* FULL_AA */
                while (n>0) {
                    v = r>>16;
                    *point = (TYPE)ramp[v].pixel;	
                    point++;				
                    r += dr;				
		    n--;
                }
#ifdef FULL_AA
		if (end_alpha > 0) {
                    v = r>>16;
                    *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
		}
#endif /* FULL_AA */
            } else {
                while (n--) {
                    v = r>>16;
                    cp = &ramp[v];
                    *point = mix_alpha(*point, cp->pixel, cp->alpha);
                    point++;
                    r += dr;
                }
            }
        } else {
            if (!grad->has_alpha) {
#ifdef FULL_AA
		if (start_alpha < 255) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
                    point++;
                    r += dr;
		    n--;
		}
#endif /* FULL_AA */
                while (n>0) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    *point = (TYPE)ramp[v].pixel;	
                    point++;				
                    r += dr;				
		    n--;
                }
#ifdef FULL_AA
		if (end_alpha > 0) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
		}
#endif /* FULL_AA */
            } else {
                while (n--) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    cp = &ramp[v];
                    *point = mix_alpha(*point, cp->pixel, cp->alpha);
                    point++;
                    r += dr;
                }
            }
        }
}

void
GraphicDevice16::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;
        
        X = (long) (m->a * start + m->b * y + m->tx);
        Y = (long) (m->c * start + m->d * y + m->ty);
        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_alpha(*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_alpha(*point, (TYPE)ramp[r].pixel, start_alpha);
			point++;
			X += dx;						
			Y += dy;						
			n--;
		    }
#endif /* FULL_AA */
		    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--;
		    }		
#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_alpha(*point, (TYPE)ramp[r].pixel, end_alpha);
		    }
		}
#endif /* FULL_AA */

        } 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_alpha(*point, cp->pixel, cp->alpha);
		point++;
		X += dx;						
		Y += dy;						
            }		
        }
}

void
GraphicDevice16::drawLine(long x1, long y1, long x2, long y2, long width)
{
    int n,adr,dx,dy,sx,color;
    register int a;
    register TYPE *pp;
    int alpha;

    x1 = (x1) >> FRAC_BITS;
    y1 = (y1) >> FRAC_BITS;
    x2 = (x2) >> FRAC_BITS;
    y2 = (y2) >> FRAC_BITS;
    
    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 = (TYPE *)canvasBuffer + adr;
    
    dx = x2 - x1;
    dy = y2 - y1;

    color = allocColor(foregroundColor);
    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_alpha(*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
    }
}

--- NEW FILE: script.cc ---
#include "swf.h"

////////////////////////////////////////////////////////////
//  This file is derived from the 'buggy' SWF parser provided
//  by Macromedia.
//
//  Modifications : Olivier Debon  <odebon at club-internet.fr>
//  

#ifdef RCSID
static char *rcsid = "$Id: script.cc,v 1.1 2006-10-03 11:26:10 dslinux_amadeus Exp $";
#endif

#ifndef	NDEBUG
#define printf(fmt, args...)
#endif

//////////////////////////////////////////////////////////////////////
// Inline input script object methods.
[...1978 lines suppressed...]

	    frameRate = GetWord() >> 8;

	    frameCount = GetWord();

	    program = new Program(movie, frameCount);

	    if (program == NULL || program->totalFrames == 0) {
	    	return FLASH_PARSE_ERROR;
	    }

	    status |= FLASH_PARSE_START;
    }

    ParseTags(&status);

    return status;
}



--- NEW FILE: graphic.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _GRAPHIC_H_
#define _GRAPHIC_H_

#define ALPHA_OPAQUE 255

enum FillType {
	f_Solid          = 0x00,
	f_LinearGradient = 0x10,
	f_RadialGradient = 0x12,
	f_TiledBitmap    = 0x40,
	f_clippedBitmap  = 0x41,
	f_None		 = 0x80
};

struct Gradient {
    int		 nbGradients;
    unsigned char	 ratio[8];
    Color		 color[8];
    // For rendering
    Color		*ramp;
    Matrix		 imat;
    int has_alpha;
};


struct FillStyleDef {
    FillType	 type;	// See enum FillType
    
    // Solid
    Color		 color;
    
    // Gradient
    Gradient	 gradient;
    
    // Bitmap
    Bitmap		*bitmap;
    Matrix              bitmap_matrix;
    Color               *cmap;
    unsigned char *alpha_table;

    // Gradient or Bitmap
    Matrix		 matrix;

    FillStyleDef() {
        style_size += sizeof(FillStyleDef);
        style_nb++;
    }
};

struct Segment {
    long x1,x2;
    long		 ymax;
    FillStyleDef	*fs[2];	// 0 is left 1 is right
    int		 aa;
    long		 dX;
    long		 X;
    
    struct Segment *next;
    struct Segment *nextValid;
};

/* fractional bits (we don't use twips here... too expensive) */
#define FRAC_BITS    5
#define FRAC         (1 << FRAC_BITS)
#define NB_SEGMENT_MAX (2048*4)
#define SEGFRAC	     8

class GraphicDevice {
	int			 targetWidth;
	int 			 targetHeight;
	Rect			 viewPort;
	int			 movieWidth;
	int			 movieHeight;
	int			 zoom;
	unsigned long		 redMask;
	unsigned long		 greenMask;
	unsigned long		 blueMask;
	int			 clipping;

public:
	FlashDisplay		*flashDisplay;
	int			 bgInitialized;
	Color			 backgroundColor;
	Color			 foregroundColor;

public:
        void *scan_line_func_id;
        ScanLineFunc scan_line_func;
	Rect			 clip_rect;

private:
        Segment **segs;
        int ymin,ymax;
        int height;
        Segment *seg_pool;
        Segment *seg_pool_cur;

	Segment * allocSeg();
	Segment * progressSegments(Segment * curSegs, long y);
	Segment * newSegments(Segment *curSegs, Segment *newSegs);
	void      renderScanLine(long y, Segment *curSegs);
		
protected:
	long	 clip(long &y, long &start, long &end);

public:
	Matrix			*adjust;	// Matrix to fit window (shrink or expand)

	long			 showMore;	// Used for debugging

	// For Direct Graphics
	unsigned char 		*canvasBuffer;	// A pointer to canvas'memory
	long			 bpl;	// Bytes per line
	long			 bpp;	// Bytes per pixel
	long			 pad;	// Scanline pad in byte

	GraphicDevice(FlashDisplay *fd);
	virtual ~GraphicDevice();

	int	 setBackgroundColor(Color);
	void	 setForegroundColor(Color);
	Color	 getBackgroundColor();
	Color	 getForegroundColor();
	void	 setMovieDimension(long width, long height);
	void	 setMovieZoom(int zoom);
	void	 setMovieOffset(long x, long y);
	long	 getWidth();
	long	 getHeight();
	Color 	*getColormap(Color *old, long n, Cxform *cxform);

	void 	 drawBox(long x1, long y1, long x2, long y2);

        void     addSegment(long x1, long y1, long x2, long y2,
                            FillStyleDef *f0,
                            FillStyleDef *f1,
                            int aa);
        
        void     drawPolygon(void);

	void	 updateClippingRegion(Rect *);
	void	 setClipping(int);

	// Virtual functions
	virtual void	 clearCanvas();
	virtual long	 allocColor(Color color);
        virtual void     fillLineBitmap(FillStyleDef *f, long y, long start, long end);
	virtual void	 fillLineLG(Gradient *grad, long y, long start, long end);
	virtual void	 fillLineRG(Gradient *grad, long y, long start, long end);
        virtual void     fillLine(FillStyleDef *f, long y, long start, long end);
        virtual void     fillLineAA(FillStyleDef *f, long y, long start, long end);
        virtual void	 drawLine(long x1, long y1, long x2, long y2, long width);

};

#endif /* _GRAPHIC_H_ */

--- NEW FILE: sprite.cc ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//  

#include "swf.h"

#ifdef RCSID
static char *rcsid = "$Id: sprite.cc,v 1.1 2006-10-03 11:26:10 dslinux_amadeus Exp $";
#endif

Sprite::Sprite(FlashMovie *movie, long id, long frameCount) : Character(SpriteType, id)
{
	program = new Program(movie, frameCount);
	if (program == NULL) return;
	if (program->totalFrames == 0) {
		delete program;
		program = NULL;
		return;
	}
	program->dl->isSprite = 1;
}

Sprite::~Sprite()
{
	delete program;
}

void
Sprite::reset()
{
	program->rewindMovie();
}

int
Sprite::isSprite(void)
{
    return 1;
}

Program *
Sprite::getProgram()
{
	return program;
}

int
Sprite::execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform)
{
	return program->dl->render(gd,matrix,cxform);
}

ActionRecord *
Sprite::eventHandler(GraphicDevice *gd, FlashEvent *event)
{
#if 0
	DisplayList *dl;
	ActionRecord *actions;

	dl = program->getDisplayList();
	actions = dl->processEvent(gd, event);
	if (actions) {
		program->doAction(actions,0);
	}
	return actions;
#endif
	return NULL;
}

void
Sprite::getBoundingBox(Rect *bb, DisplayListEntry *e)
{
	program->dl->getBoundary(bb);
}

--- NEW FILE: displaylist.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _DISPLAYLIST_H_
#define _DISPLAYLIST_H_

class Character;
class Program;

struct DisplayList;

// Display List management
struct DisplayListEntry {
    Character		*character;
    long		 depth;
    Matrix		*matrix;
    Cxform		*cxform;
    char		*instanceName;
    
    /* button state */
    ButtonState		 renderState;
    ButtonState		 oldState;
    Character		*buttonCharacter;
    Matrix		 buttonMatrix;
    Matrix renderMatrix; /* last render matrix */

    DisplayListEntry	*next;

    DisplayList		*owner;	// Parent
};

struct DisplayList {
    DisplayListEntry	*list;
    FlashMovie          *movie;
    Rect		 bbox;		// Delta clipping region
    int			 isSprite;
public:
    DisplayList(FlashMovie *movie);
    ~DisplayList();
    DisplayListEntry	*getList();
    void		 clearList();
    void		 placeObject(GraphicDevice *gd,Character *character, long depth, Matrix *matrix = 0, Cxform *cxform = 0, char *name = 0);
    Character		*removeObject(GraphicDevice *gd, Character *character, long depth);

    int			 render(GraphicDevice *gd, Matrix *m = 0, Cxform *cxform = 0);
    void		 updateBoundingBox(DisplayListEntry *);
    void		 updateButtons (FlashMovie *);
    void 		 getBoundary(Rect *bb);	// Returns boundary of current displayed objects
    int			 updateSprites();	// Update sprites in the display list
};

typedef void (*DisplayListFunc)(DisplayListEntry *e, void *opaque);

void		 updateButtons(FlashMovie *m);
int		 computeActions(FlashMovie *m, Program **prog, ActionRecord **ar);
void		 renderFocus(FlashMovie *movie);

typedef int (*ExploreButtonFunc)(void *opaque, Program *prg, DisplayListEntry *e);
int		 exploreButtons(FlashMovie *movie, void *opaque, ExploreButtonFunc func);
void		 updateBoundingBox(DisplayListEntry *e);
void		 transformBoundingBox(Rect *bb, Matrix *matrix, Rect *boundary, int reset);
void		 updateButtonState(DisplayListEntry *e, ButtonState state);

#endif /* _DISPLAYLIST_H_ */

--- NEW FILE: sound.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _SOUND_H_
#define _SOUND_H_

#define GET_SOUND_RATE_CODE(f) (((f)&0x0c)>>2)

class Sound : public Character {
	long		 soundRate;	// In hz
	long		 stereo;	// True if stereo sound
	long		 sampleSize;	// 1 or 2 bytes

	char		*samples;		// Array of samples
	long		 nbSamples;

public:
	Sound(long id);
	~Sound();
	void    	 setSoundFlags(long f);
	char		*setNbSamples(long n);

	long		 getRate();
	long		 getChannel();
	long		 getNbSamples();
	long		 getSampleSize();
	char		*getSamples();
};

struct SoundList {
	long	 rate;
	long	 stereo;
	long	 sampleSize;
	long	 nbSamples;
	long	 remaining;
	char	*current;

	SoundList *next;
};

class SoundMixer {

	SoundList	*list;

// Class variables
static  long		 dsp;		// Descriptor for /dev/dsp
static  char *		 buffer;	// DMA buffer
static	long		 blockSize;
static	long		 nbInst;	// Number of instances

	// Sound Device Capabilities
static	long		 soundRate;	// In hz
static	long		 stereo;	// True if stereo sound
static	long		 sampleSize;	// 1 or 2 bytes

public:
	SoundMixer(char*);
	~SoundMixer();

	void		 startSound(Sound *sound);	// Register a sound to be played
	void		 stopSounds();		// Stop every current sounds in the instance

	long		 playSounds();		// Actually play sounds of all instances
	long		 fillSoundBuffer(SoundList *, char *buffer, long bufferSize); // Fill sound buffer
};

#endif /* _SOUND_H_ */

--- NEW FILE: cxform.h ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _CXFORM_H_
#define _CXFORM_H_

struct Color {
    unsigned char red,green,blue,alpha;
    long		 pixel;
};

struct Cxform
{
	float aa; long ab;	// a is multiply factor, b is addition factor
	float ra; long rb;
	float ga; long gb;
	float ba; long bb;

	long	getRed(long v);
	long	getGreen(long v);
	long	getBlue(long v);
	long	getAlpha(long v);
	Color	getColor(Color color);

#ifdef DUMP
	void dump(BitStream *bs, int alpha = 0);
#endif
};

#endif /* _CXFORM_H_ */

--- NEW FILE: graphic_generic.cc ---
////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
[...1241 lines suppressed...]
	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;
	}
}

--- NEW FILE: graphic32.cc ---
////////////////////////////////////////////////////////////
// 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 at club-internet.fr>
//  

#include "swf.h"

#include "graphic32.h"

extern unsigned char SQRT[];

#define FULL_AA

#define PRINT 0

typedef unsigned long TYPE;

GraphicDevice32::GraphicDevice32(FlashDisplay *fd) : GraphicDevice(fd)
{
}

long
GraphicDevice32::allocColor(Color color)
{
	return (color.red)<<16 | (color.green)<<8 | (color.blue);
}

void
GraphicDevice32::clearCanvas()
{
    TYPE  pixel;
    TYPE *point,*p;
    long                 h, w,n;

    if (!bgInitialized) return;

    pixel = allocColor(backgroundColor);

    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;
        while (n--) {
            *p++ = pixel;
        }

        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;
}

#define RED_MASK   0xFF0000
#define GREEN_MASK 0x00FF00
#define BLUE_MASK  0x0000FF

/* alpha = 0 : select c1, alpha = 255 select c2 */
static inline unsigned long
mix_alpha(unsigned long c1, unsigned long c2, int alpha)
{
	long r1,r2,r;
	long g1,g2,g;
	long b1,b2,b;

	r1 = c1 & RED_MASK;
	r2 = c2 & RED_MASK;
	r = (((r2-r1)*alpha + r1 * 256) >> 8) & RED_MASK;

	g1 = c1 & GREEN_MASK;
	g2 = c2 & GREEN_MASK;
	g = (((g2-g1)*alpha + g1 * 256) >> 8) & GREEN_MASK;

	b1 = c1 & BLUE_MASK;
	b2 = c2 & BLUE_MASK;
	b = (((b2-b1)*alpha + b1 * 256) >> 8) & BLUE_MASK;

	return (r|g|b);
}

void
GraphicDevice32::fillLineAA(FillStyleDef *f, long y, long start, long end)
{
    register long   n;
    TYPE *line;
    TYPE *point,pixel;
    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;
    
    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 = mix_alpha(*point, pixel, start_alpha + end_alpha - 255);
        } else {
            n = end-start;
            if (start_alpha < 255) {
                *point = mix_alpha(*point, pixel, start_alpha);
                point++;
                n--;
            }
            while (n > 0) {
                *point = pixel;
                point++;
                n--;
            }
            if (end_alpha > 0) {
                *point = mix_alpha(*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 = mix_alpha(*point, pixel, 
                               ((start_alpha + end_alpha - 255) * alpha) >> 8);
        } else {
            n = end-start;
            if (start_alpha < 255) {
                *point = mix_alpha(*point, pixel, (start_alpha * alpha) >> 8);
                point++;
                n--;
            }
            while (n > 0) {
                *point = mix_alpha(*point, pixel, alpha);
                point++;
                n--;
            }
            if (end_alpha > 0) {
                *point = mix_alpha(*point, pixel, (end_alpha * alpha) >> 8);
            }
        }
    }
}

void
GraphicDevice32::fillLine(FillStyleDef *f, long y, long start, long end)
{
	register long   n;
        TYPE *line,*point;
        TYPE pixel;
        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;
        alpha = f->color.alpha;
        if (alpha == ALPHA_OPAQUE) {
            while (n--) { 
		*point = pixel;
		point++;			
            }
        } else {
            while (n--) { 
		*point = mix_alpha(*point, pixel, alpha);
		point++;			
            }
        }
}

void
GraphicDevice32::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;
    TYPE *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 = (TYPE *) (this->canvasBuffer + this->bpl*y + start * sizeof(TYPE));
    
    /* the coordinates in the image are normalized to 16 bits */
    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);
    
    pixels = b->pixels;
    pixbpl = b->bpl;
    cmap = f->cmap;

    if (b->alpha_buf == NULL) {
        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--;
        }
    } else if (f->alpha_table) {
        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_alpha(*p, pixel, alpha_table[b->alpha_buf[offset]]);
            }
            x1 += dx;
            y1 += dy;
            p++;
            n--;
        }
    } 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_alpha(*p, pixel, b->alpha_buf[offset]);
            }
            x1 += dx;
            y1 += dy;
            p++;
            n--;
        }
    }
}

void
GraphicDevice32::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;

        r = (long) (m->a * start + m->b * y + m->tx);
        dr = (long) (m->a);

        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>>16;
                    *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
                    point++;
                    r += dr;
		    n--;
		}
#endif /* FULL_AA */
                while (n>0) {
                    v = r>>16;
                    *point = (TYPE)ramp[v].pixel;	
                    point++;				
                    r += dr;				
		    n--;
                }
#ifdef FULL_AA
		if (end_alpha > 0) {
                    v = r>>16;
                    *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
		}
#endif /* FULL_AA */
            } else {
                while (n--) {
                    v = r>>16;
                    cp = &ramp[v];
                    *point = mix_alpha(*point, cp->pixel, cp->alpha);
                    point++;
                    r += dr;
                }
            }
        } else {
            if (!grad->has_alpha) {
#ifdef FULL_AA
		if (start_alpha < 255) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
                    point++;
                    r += dr;
		    n--;
		}
#endif /* FULL_AA */
                while (n>0) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    *point = (TYPE)ramp[v].pixel;	
                    point++;				
                    r += dr;				
		    n--;
                }
#ifdef FULL_AA
		if (end_alpha > 0) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
		}
#endif /* FULL_AA */
            } else {
                while (n--) {
                    v = r>>16;
                    if (v < 0) v = 0;
                    else if (v > 255) v = 255;
                    cp = &ramp[v];
                    *point = mix_alpha(*point, cp->pixel, cp->alpha);
                    point++;
                    r += dr;
                }
            }
        }
}

void
GraphicDevice32::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;
        
        X = (long) (m->a * start + m->b * y + m->tx);
        Y = (long) (m->c * start + m->d * y + m->ty);
        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_alpha(*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_alpha(*point, (TYPE)ramp[r].pixel, start_alpha);
			point++;
			X += dx;						
			Y += dy;						
			n--;
		    }
#endif /* FULL_AA */
		    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--;
		    }		
#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_alpha(*point, (TYPE)ramp[r].pixel, end_alpha);
		    }
		}
#endif /* FULL_AA */

        } 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_alpha(*point, cp->pixel, cp->alpha);
		point++;
		X += dx;						
		Y += dy;						
            }		
        }
}

void
GraphicDevice32::drawLine(long x1, long y1, long x2, long y2, long width)
{
    int n,adr,dx,dy,sx,color;
    register int a;
    register TYPE *pp;
    int alpha;

    x1 = (x1) >> FRAC_BITS;
    y1 = (y1) >> FRAC_BITS;
    x2 = (x2) >> FRAC_BITS;
    y2 = (y2) >> FRAC_BITS;
    
    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 = (TYPE *)canvasBuffer + adr;
    
    dx = x2 - x1;
    dy = y2 - y1;

    color = allocColor(foregroundColor);
    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_alpha(*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
    }
}

--- NEW FILE: text.h ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _TEXT_H_
#define _TEXT_H_

struct Glyph {
	long	index;
	long	xAdvance;
	long	code;	// Ascii code
};

struct TextRecord {

	// Normal text record
	Glyph		*glyphs;
	long		 nbGlyphs;

	// Control text record
	TextFlags	 flags;
	SwfFont		*font;
	long		 fontHeight;
	Color		 color;
	long		 xOffset;
	long		 yOffset;

	TextRecord *next;

	TextRecord();
	~TextRecord();

	char		*getText();
};

class Text : public Character {

	Rect		 boundary;
	Matrix		 textMatrix;
	TextRecord	*textRecords;	// List

public:
	Text(long id);
	~Text();

	void		 setTextBoundary(Rect rect);
	void		 setTextMatrix(Matrix m);
	void		 addTextRecord(TextRecord *tr);
	int		 execute(GraphicDevice *gd, Matrix *matrix, Cxform *cxform);
	void		 getRegion(GraphicDevice *gd, Matrix *matrix, 
                                   void *id, ScanLineFunc scan_line_func);
	int		 doText(GraphicDevice *gd, Matrix *matrix, Cxform *cxform, ShapeAction action,
                                void *id, ScanLineFunc scan_line_func);
	void		 getBoundingBox(Rect *bb, DisplayListEntry *e);
	TextRecord 	*getTextRecords();

#ifdef DUMP
	void	 dump(BitStream *bs);
#endif
};

#endif /* _TEXT_H_ */

--- NEW FILE: program.cc ---
/////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//  

#include "swf.h"

#define NOTHING  0x0
#define WAKEUP   0x1
#define GOTO     0x2
#define REFRESH  0x4

#ifdef RCSID
static char *rcsid = "$Id: program.cc,v 1.1 2006-10-03 11:26:10 dslinux_amadeus Exp $";
#endif

#define PRINT 0

int debug = 0;

Program::Program(FlashMovie *movie, long n)
{
	long f;

        this->movie = movie;

	totalFrames = 0;

	dl = new DisplayList(movie);
	if (dl == NULL) return;
	frames = new Frame[n];
	if (frames == NULL) {
		delete dl;
		return;
	}

	nbFrames = 0;
	totalFrames = n;
	currentFrame = 0;
	loadingFrame = 0;
	movieWait = 1;
	nextFrame = currentFrame;
	for(f = 0; f < n; f++)
	{
		frames[f].controls = 0;
		frames[f].label = NULL;
	}

	movieStatus = MoviePlay;
	settings = 0;
}

Program::~Program()
{
    int i;
    Control *ctrl, *ctrl1;

    delete dl;

    if (frames != NULL) {
	    for(i=0;i<nbFrames;i++) {
		ctrl = frames[i].controls;
		if (frames[i].label) free(frames[i].label);
		while (ctrl != NULL) {
		    ctrl1 = ctrl->next;
		    ctrl->next = NULL;
		    delete ctrl;
		    ctrl = ctrl1;
		}
	    }

	    delete[] frames;
    }
}

void
Program::validateLoadingFrame()
{
	nbFrames = loadingFrame;
	loadingFrame++;
	movieWait = 0;
}

Frame	*
Program::getFrames()
{
	return frames;
}

long
Program::getNbFrames()
{
	return nbFrames;
}

DisplayList *
Program::getDisplayList()
{
	return dl;
}

long
Program::getCurrentFrame()
{
	return currentFrame;
}

void
Program::setCurrentFrame(long n)
{
	currentFrame = n;
	nextFrame = n;
	//refresh = 1;
}

void
Program::gotoFrame(GraphicDevice *gd, long frame)
{
	long f;

	//printf("GotoFrame %d  (Current = %d)\n", frame, currentFrame);
	dl->clearList();

	for(f=0; f <= frame; f++) {
		runFrame(gd, 0, f, 0);
	}
}

long
Program::runFrame(GraphicDevice *gd, SoundMixer *sm, long f, long action)
{
	Control		*ctrl;
	Character	*character;
	Matrix		*matrix;
	Cxform		*cxform;
	long		 status = NOTHING;
	long		 update = 0;
	char		*name;

#if PRINT&1
	if (action) printf("Prog %x (dl=%x): Frame N° %d/%d\n", this, this->dl, f, nbFrames-1);
#endif
        movie->buttons_updated = 0;

	for(ctrl = frames[f].controls; ctrl; ctrl = ctrl->next)
	{
		switch (ctrl->type)
		{
			case ctrlPlaceObject:
			case ctrlPlaceObject2:
				character = 0;
				matrix = 0;
				cxform = 0;
				name = "";
				if (ctrl->flags & placeHasCharacter) {
					character = ctrl->character;
				}
				if (ctrl->flags & placeHasMatrix) {
					matrix = &ctrl->matrix;
				}
				if (ctrl->flags & placeHasColorXform) {
					cxform = &ctrl->cxform;
				}
				if (ctrl->flags & placeHasName) {
					name = ctrl->name;
				}
				if (!ctrl->clipDepth) {	// Ignore
					dl->placeObject(gd,character, ctrl->depth, matrix, cxform, name);
					update = 1;
				}
				break;
			case ctrlRemoveObject:
				character = ctrl->character;

				if (!character) break;	// Should not happen

				dl->removeObject(gd, character, ctrl->depth);
				if (action) {
					character->reset();
					update = 1;
				}
				break;
			case ctrlRemoveObject2:
				character = dl->removeObject(gd,NULL, ctrl->depth);
				if (character && action) {
					character->reset();
					update = 1;
				}
				break;
		// Actions
			case ctrlDoAction:
				if (action) {
					status = doAction(gd, ctrl->actionRecords, sm);
				}
				break;
			case ctrlStartSound:
				if (action && sm) {
					sm->startSound( (Sound *)ctrl->character );
				}
				break;
			case ctrlStopSound:
				if (action && sm) {
					sm->stopSounds();
				}
				break;
			case ctrlBackgroundColor:
				if (action) {
					if (gd->setBackgroundColor(ctrl->color)) {
						dl->bbox.xmin = -32768;
						dl->bbox.ymin = -32768;
						dl->bbox.xmax =  32768;
						dl->bbox.ymax =  32768;
					}
				}
				break;
		}
	}
        if (movie->buttons_updated) {
            dl->updateButtons(movie);
        }

	if (status & GOTO) {
		if (nextFrame < nbFrames) {
			gotoFrame(gd,nextFrame);
			if (nextFrame != f)
			if (movieStatus == MoviePaused) runFrame(gd,sm,nextFrame);
			update = 1;
		}
	}

#if PRINT&1
	if (action) printf("Frame N° %d ready\n", f);
#endif
	return update;
}

long
Program::nestedMovie(GraphicDevice *gd, SoundMixer *sm, Matrix *mat, Cxform *cxform)
{
	if (movieStatus == MoviePlay) {
		// Movie Beeing Played
		advanceFrame();
		if (currentFrame == 0) {
			dl->clearList();
		}
		runFrame(gd, sm, currentFrame);
		if (nbFrames == 1) {
			pauseMovie();
		}
	}

	return (movieStatus == MoviePlay);
}

long
Program::processMovie(GraphicDevice *gd, SoundMixer *sm)
{
	int wakeUp = 0;

#if PRINT&1
	printf("Prog %x (dl=%x): Current = %d     Next = %d    Wait = %d  Status = %d\n", this, this->dl, currentFrame, nextFrame, movieWait, movieStatus);
#endif

	if (movieStatus == MoviePlay && movieWait == 0) {
		// Movie Beeing Played
		advanceFrame();
		if (currentFrame == 0) {
			dl->clearList();
		}
		wakeUp |= runFrame(gd, sm, currentFrame);
		wakeUp |= dl->updateSprites();
		if (nextFrame == nbFrames) {
			if (nbFrames != totalFrames) {
				movieWait = 1;
			} else if ((settings & PLAYER_LOOP) == 0) {
				pauseMovie();
			}
		}
	} else {
		wakeUp |= dl->updateSprites();
	}

	if (wakeUp) {
		render = 1;
	}

	return (wakeUp || movieStatus == MoviePlay);
}

/* timer (ms) -1 = delete timer */
void setFlashTimer(struct timeval *tv, int time_ms)
{
    if (time_ms == -1) {
        tv->tv_sec = -1;
    } else {
        gettimeofday(tv,0);
        
        tv->tv_usec += time_ms*1000;
        while (tv->tv_usec > 1000000) {
            tv->tv_usec -= 1000000;
            tv->tv_sec++;
        }
    }
}

int checkFlashTimer(struct timeval *tv)
{
    struct timeval now;

    if (tv->tv_sec == -1) return 0;

    gettimeofday(&now,0);
    return (now.tv_sec > tv->tv_sec ||
            (now.tv_sec == tv->tv_sec && now.tv_usec >= tv->tv_usec));
}

/* bbox */
typedef struct {
    long x1,y1,x2,y2;
} ButtonBoundingBox;


static void button_bbox_func(void *id, long y, long start, long end)
{
    ButtonBoundingBox *h = (ButtonBoundingBox *) id;

    if (y < h->y1) h->y1 = y;
    if (y > h->y2) h->y2 = y;
    if (start < h->x1) h->x1 = start;
    if (end > h->x2) h->x2 = end;
}

void computeBBox(FlashMovie *movie, Rect *rect, DisplayListEntry *e)
{
    ButtonBoundingBox bb;

    bb.x1 = LONG_MAX;
    bb.y1 = LONG_MAX;
    bb.x2 = LONG_MIN;
    bb.y2 = LONG_MIN;
    
    e->character->getRegion(movie->gd,&e->renderMatrix,&bb,button_bbox_func);
    
    rect->xmin = bb.x1 / FRAC;
    rect->xmax = bb.x2 / FRAC;
    rect->ymin = bb.y1;
    rect->ymax = bb.y2;
}

void transform_coords(long *x_ptr,long *y_ptr, long cx, long cy, long dx, long dy)
{
    long x,y,x1,y1;
    x = *x_ptr;
    y = *y_ptr;

    x -= cx;
    y -= cy;

    if (dx < 0) {
        /* left */
        x1 = - x;
        y1 = y;
    } else if (dy < 0) {
        /* up */
        y1 = x;
        x1 = -y;
    } else if (dy > 0) {
        /* down */
        y1 = x;
        x1 = y;
    } else {
        /* right */
        x1 = x;
        y1 = y;
    }
        
    *x_ptr = x1;
    *y_ptr = y1;
}

typedef struct {
    FlashMovie *movie;
    DisplayListEntry *emin,*cur_focus;
    long dmin;
    long w,cx,cy,dx,dy;
} ButtonFocus;

static int button_focus(void *opaque, Program *prg, DisplayListEntry *e)
{
    ButtonFocus *h=(ButtonFocus *)opaque;
    Rect rect;
    long d,x,y;

    if (e != h->cur_focus) {
        computeBBox(h->movie,&rect,e);
        x = (rect.xmin + rect.xmax) / 2;
        y = (rect.ymin + rect.ymax) / 2;
        
        /* transform the coords so that the angular sector is directed to the right */
        transform_coords(&x,&y,h->cx,h->cy,h->dx,h->dy);
        
        /* inside it ? */
        if ( x >= 0 && 
             (y - x - h->w) <= 0 && 
             (y + x + h->w) >= 0) {
            d = x*x + y*y;
            
            if (d < h->dmin) {
                h->dmin = d;
                h->emin = e;
            }
        }
    }
    return 0;
}

DisplayListEntry *moveFocus(FlashMovie *movie, long dx, long dy, 
                            DisplayListEntry *cur_focus)
{
    Rect cur_rect;
    ButtonFocus h;

    h.movie = movie;
    h.dx = dx;
    h.dy = dy;

    computeBBox(movie,&cur_rect,cur_focus);
    /* center */
    h.cx = (cur_rect.xmin + cur_rect.xmax) / 2;
    h.cy = (cur_rect.ymin + cur_rect.ymax) / 2;
    
    /* width/2 of the 45 degrees angular sector */
    if (dy != 0) {
        /* for vertical displacement, we have a larger width */
        h.w = (cur_rect.xmax - cur_rect.xmin) / 2;
    } else {
        /* zero width for horizontal displacement */
        h.w = 0;
    }

    /* now we select the nearest button in the angular sector */
    h.dmin = LONG_MAX;
    h.emin = NULL;
    h.cur_focus = cur_focus;

    exploreButtons(movie, &h, button_focus);
    
    return h.emin;
}

static int button_newfocus(void *opaque, Program *prg, DisplayListEntry *e)
{
    * (DisplayListEntry **)opaque = e;
    return 2;
}

static int button_nextfocus(void *opaque, Program *prg, DisplayListEntry *e)
{
    static int found = 0;
    DisplayListEntry **focus;

    focus = (DisplayListEntry **)opaque;
    if (found) {
    	*focus = e;
	found = 0;
	return 2;
    }
    if (e == *focus) {
    	found = 1;
    }
    return 0;
}


/* XXX: should not be here (one level upper) */
long
Program::handleEvent(GraphicDevice *gd, SoundMixer *sm, FlashEvent *fe)
{
    ActionRecord	*action;
    Program		*prog;
    long		 status = 0;
    DisplayListEntry *cur_focus, *new_focus;
    long dx,dy;
    int			 refresh;

    refresh = 0;

    switch(fe->type) {

    case FeKeyRelease:
        if (movie->mouse_active == 0) {
            
            if (movie->cur_focus) {
		movie->cur_focus->owner->updateBoundingBox(movie->cur_focus);
                movie->cur_focus->renderState = stateOver;
		movie->cur_focus->owner->updateBoundingBox(movie->cur_focus);
            }
        }
        break;

    case FeKeyPress:

        movie->mouse_active = 0;

        /* find the button which has the focus */
        cur_focus = movie->cur_focus;

        if (fe->key == FeKeyEnter) {
            /* selection */
            if (cur_focus) {
                /* select the button */
		cur_focus->owner->updateBoundingBox(cur_focus);
                cur_focus->renderState = stateDown;
	        ((Button *)cur_focus->character)->updateButtonState(cur_focus);
		cur_focus->owner->updateBoundingBox(cur_focus);

                movie->scheduledEvent.type = FeKeyRelease;
                movie->scheduledEvent.key = FeKeyEnter;

                setFlashTimer(&movie->scheduledTime, 250); /* 250 ms down */
            }
        } else {
            /* displacement */

            if (cur_focus == NULL) {
                /* no current focus : set one */
                exploreButtons(movie, &cur_focus, button_newfocus);
                if (cur_focus) {
                    cur_focus->renderState = stateOver;
		    ((Button *)cur_focus->character)->updateButtonState(cur_focus);
		    cur_focus->owner->updateBoundingBox(cur_focus);
                }
                movie->cur_focus = cur_focus;
            } else {
                /* move the focus (test) */
                switch(fe->key) {
                case FeKeyNext:
                    /* Next available */
		    cur_focus->owner->updateBoundingBox(cur_focus);
                    cur_focus->renderState = stateUp;
		    ((Button *)cur_focus->character)->updateButtonState(cur_focus);
		    cur_focus->owner->updateBoundingBox(cur_focus);
                    exploreButtons(movie, &cur_focus, button_nextfocus);
                    if (cur_focus) {
                        cur_focus->renderState = stateOver;
		        ((Button *)cur_focus->character)->updateButtonState(cur_focus);
		        cur_focus->owner->updateBoundingBox(cur_focus);
                    }
                    movie->cur_focus = cur_focus;
                    dx = 0;
                    dy = 0;
		    break;
                case FeKeyUp:
                    dx = 0;
                    dy = -1;
                    break;
                case FeKeyDown:
                    dx = 0;
                    dy = 1;
                    break;
                case FeKeyLeft:
                    dx = -1;
                    dy = 0;
                    break;
                case FeKeyRight:
                    dx = 1;
                    dy = 0;
                    break;
                default:
                    /* should not happen */
                    dx = 0;
                    dy = 0;
                    break;
                }

                if (dx != 0 || dy != 0) {

                    new_focus = moveFocus(movie, dx, dy, cur_focus);
                    if (new_focus) {
			cur_focus->owner->updateBoundingBox(cur_focus);
                        cur_focus->renderState = stateUp;
			((Button *)cur_focus->character)->updateButtonState(cur_focus);
			cur_focus->owner->updateBoundingBox(cur_focus);

		        if (computeActions(movie, &prog, &action)) {
			    status |= prog->doAction(gd, action, sm);
		        }
			    
                        new_focus->renderState = stateOver;
			((Button *)new_focus->character)->updateButtonState(new_focus);
                        movie->cur_focus = new_focus;
			new_focus->owner->updateBoundingBox(new_focus);
                    } else {
		    	return 0;
		    }
                }
            }
	    if (movie->cur_focus == NULL) return 0;
        }
        break;

    case FeMouseMove:
        movie->mouse_active = 1;
        movie->mouse_x = fe->x * FRAC;
        movie->mouse_y = fe->y * FRAC;
        dl->updateButtons(movie);
        break;

    case FeButtonPress:
        movie->mouse_active = 1;
        movie->button_pressed = 1;
        dl->updateButtons(movie);
        break;

    case FeButtonRelease:
        movie->mouse_active = 1;
        movie->button_pressed = 0;
        dl->updateButtons(movie);
        break;
        
    default:
        return 0;
    }

    if (computeActions(movie, &prog, &action)) {
        status |= prog->doAction(gd, action, sm);
    }

    if (status & REFRESH) {
        status |= WAKEUP;
        refresh = 1;
    }
    if (status & GOTO) {
        if (nextFrame < nbFrames) {
		gotoFrame(gd, nextFrame);
		if (movieStatus == MoviePaused) runFrame(gd,sm,nextFrame);
		refresh = 1;
	}
    }

    if (refresh) {
		dl->updateSprites();
		render = 1;
    }
    return (refresh || movieStatus == MoviePlay);
}

long
Program::doAction(GraphicDevice *gd, ActionRecord *action, SoundMixer *sm)
{
	long status = NOTHING;
        long f;
	char *target = "";
	long skip = 0;

	while(action)
	{
		if (skip) skip--;
		else
		switch (action->action)
		{
			case ActionPlaySound:
#if PRINT&2
				printf("Prog %x : PlaySound\n", this);
#endif
                                if (sm) {
                                    sm->startSound(action->sound);
                                }
				status |= WAKEUP;
				break;
			case ActionRefresh:
#if PRINT&2
				printf("Prog %x : Refresh\n", this);
#endif
				status |= REFRESH;
				break;
			case ActionGotoFrame:
#if PRINT&2
				printf("Prog %x : GotoFrame %d\n", this, action->frameIndex);
#endif
				if (target[0] == 0) {
					if (action->frameIndex < nbFrames) {
						currentFrame = action->frameIndex;
						pauseMovie();
						status |= WAKEUP|GOTO;
					}
				}
				break;
			case ActionGetURL:
#if PRINT&2
				printf("Prog %x : GetURL %s target = %s\n", this, action->url, action->target);
#endif
                                {
                                    int len,level;
                                    len = strlen(action->target);
                                    
                                    if (len > 6 && memcmp(action->target,"_level", 6) == 0) {
                                        level = atoi(action->target + 6);
                                        loadNewSwf(movie, action->url, level);
                                    } else {
                                        if (movie->getUrl) {
                                            movie->getUrl(action->url, action->target, movie->getUrlClientData);
                                        }
                                    }
                                }
				break;
			case ActionNextFrame:
				nextFrame = currentFrame+1;
				movieStatus = MoviePlay;
				status |= WAKEUP;
				break;
			case ActionPrevFrame:
				nextFrame = currentFrame-1;
				status |= WAKEUP|GOTO;
				break;
			case ActionPlay:
#if PRINT&2
				printf("Prog %x : Play\n", this);
#endif
				if (target[0] == 0) {
					movieStatus = MoviePlay;
					if ((status & GOTO) == 0) {
						if (currentFrame == nextFrame) advanceFrame();
					}
					status |= WAKEUP;
				}
				break;
			case ActionStop:
#if PRINT&2
				printf("Prog %x : Stop\n", this);
#endif
				if (target[0] == 0) {
					movieStatus = MoviePaused;
					nextFrame = currentFrame;
				}
				break;
			case ActionToggleQuality:
				break;
			case ActionStopSounds:
				if (sm) {
					sm->stopSounds();
				}
				break;
			case ActionWaitForFrame:
				if (action->frameIndex >= nbFrames) {
					skip = action->skipCount;
				}
				break;
			case ActionSetTarget:
#if PRINT&2
				printf("Prog %x : SetTarget '%s'\n", this, action->target);
#endif
				target = action->target;
				break;
			case ActionGoToLabel:
#if PRINT&2
				printf("Prog %x : GotoFrame '%s'\n", this, action->frameLabel);
#endif
                                f = searchFrame(gd, action->frameLabel, target);
                                if (f >= 0) {
				    currentFrame = f;
				    pauseMovie();
                                    status |= WAKEUP|GOTO;
                                } else {
                                    status |= REFRESH;
                                }
				break;
		}
		action = action->next;
	}
	return status;
}

void
Program::setCurrentFrameLabel(char *label)
{
    frames[loadingFrame].label = label;
}

void
Program::rewindMovie()
{
	currentFrame = 0;
	nextFrame = 0;
}

void
Program::pauseMovie()
{
	movieStatus = MoviePaused;
	nextFrame = currentFrame;
}

void
Program::continueMovie()
{
	movieStatus = MoviePlay;
}

void
Program::nextStepMovie()
{
	if (movieStatus == MoviePaused) {
		advanceFrame();
	}
}

void
Program::advanceFrame()
{
	currentFrame = nextFrame;
	nextFrame = currentFrame+1;
	if (currentFrame == nbFrames) {
		currentFrame = 0;
		nextFrame = 0;
		movieStatus = MoviePlay;
	}
}

void
Program::addControlInCurrentFrame(Control *ctrl)
{
	Control *c;

	ctrl->next = 0;
	if (frames[loadingFrame].controls == 0) {
		frames[loadingFrame].controls = ctrl;
	} else {
		for(c = frames[loadingFrame].controls; c->next; c = c->next);
		c->next = ctrl;
	}
}

void
Program::modifySettings(long flags)
{
	settings = flags;
}

long
Program::searchFrame(GraphicDevice *gd, char *label, char *target)
{
	long f;
        DisplayListEntry *e;
        Program *prg;

	// Current movie
	if (target[0] == 0) {
		for(f=0; f < nbFrames; f++)
		{
		    if (frames[f].label && !strcmp(label,frames[f].label)) {
			return f;
		    }
		}
	}

	// Kludge !!!
	for (e = dl->list; e; e = e->next) {
	    if (e->character->isSprite()) {
		prg = ((Sprite *)e->character)->program;
		f = prg->searchFrame(gd,label,"");
		if (f >= 0 && f < prg->nbFrames) {
		    prg->dl->updateBoundingBox(e);
		    prg->gotoFrame(gd, f);
		    prg->nextFrame = f;
		    prg->dl->updateBoundingBox(e);
		    return -1;
		}
	    }
	}

	return -1;
}

void loadNewSwf(FlashMovie *movie, char *url, int level)
{
    CInputScript *s,*prev,**l;

    if (movie->getSwf == NULL) return;

    for(s = movie->main, prev = 0; s != NULL; prev = s, s = s->next) {
    	if (s->level == level) {
		// Mark movie to be deleted
		s->level = -1;
		break;
	}
    }

    //printf("Unload movie @ %d\n", level);

    if (*url == 0) return;	// Just UnloadMovie

    s = new CInputScript(level);
    if (s == NULL) return;

    /* insert it in the right order */
    l = &movie->main;
    while (*l != NULL && (*l)->level < level) l = &(*l)->next;
    s->next = *l;
    *l = s;

    // Notify the external loader of a new movie to load
    movie->getSwf(url, level, movie->getSwfClientData);
}

--- NEW FILE: program.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _PROGRAM_H_
#define _PROGRAM_H_

enum ControlType {
	ctrlPlaceObject,
	ctrlPlaceObject2,
	ctrlRemoveObject,
	ctrlRemoveObject2,
	ctrlDoAction,
	ctrlStartSound,
	ctrlStopSound,
	ctrlBackgroundColor
};

enum PlaceFlags {
	placeIsMove		= 0x01,
	placeHasCharacter	= 0x02,
	placeHasMatrix		= 0x04,
	placeHasColorXform	= 0x08,
	placeHasRatio		= 0x10,
	placeHasName		= 0x20,
	placeHasClip		= 0x40
};

struct Control {
	ControlType	type;

	// Place, Remove, Sound
	Character	*character;
	long		 depth;

	// Place 1&2
	PlaceFlags	 flags;
	Matrix		 matrix;
	Cxform		 cxform;
	long		 ratio;
	long		 clipDepth;
	char		*name;

	// BackgroundColor
	Color		 color;

	// DoAction
	ActionRecord	*actionRecords;

	struct Control *next;


	// Methods

	void addActionRecord( ActionRecord   *ar)
	{
		ar->next = 0;

		if (actionRecords == 0) {
			actionRecords = ar;
		} else {
			ActionRecord *current;

			for(current = actionRecords; current->next; current = current->next);

			current->next = ar;
		}
	};

	Control()
	{
		actionRecords = 0;
		cxform.aa = 1.0; cxform.ab = 0;
		cxform.ra = 1.0; cxform.rb = 0;
		cxform.ga = 1.0; cxform.gb = 0;
		cxform.ba = 1.0; cxform.bb = 0;
		ratio = 0;
		clipDepth = 0;
		name = 0;
	};

	~Control()
	{
		ActionRecord	*ar,*del;
		for(ar = actionRecords; ar;)
		{
			del = ar;
			ar = ar->next;
			delete del;
		}
		if (name) {
			free(name);
		}
	};
};

struct Frame {
	char *label;
	Control *controls;	// Controls for this frame
};

enum MovieStatus {
	MoviePaused,
	MoviePlay
};

struct FlashMovie;

struct Program {
        DisplayList	*dl;

	Frame		*frames;	// Array
	long		 nbFrames;	// Number of valid frames
	long  		 currentFrame;
	long  		 loadingFrame;
	long  		 totalFrames;	// Total expected number of frames
	long  		 nextFrame;
	int		 movieWait;	// If true freeze movie until next loaded frame
	MovieStatus 	 movieStatus;
	Sound		*currentSound;
	long		 settings;
        FlashMovie      *movie;
	long		 render;	// True if needed to be rendered

	Program(FlashMovie *movie,long n);
	~Program();

	void	 rewindMovie();
	void	 pauseMovie();
	void	 continueMovie();
	void	 nextStepMovie();
	void	 gotoFrame(GraphicDevice *gd, long f);

	long	 processMovie(GraphicDevice *, SoundMixer *);
	long	 nestedMovie(GraphicDevice *, SoundMixer *, Matrix *, Cxform *);
	long	 runFrame(GraphicDevice *, SoundMixer *, long f, long action=1);
	long	 handleEvent(GraphicDevice *, SoundMixer *, FlashEvent *);
	long	 doAction(GraphicDevice *gd, ActionRecord *action, SoundMixer *);
	void	 setCurrentFrameLabel(char *label);
	void	 advanceFrame();
	void	 addControlInCurrentFrame(Control *ctrl);
	void	 setGetUrlMethod( void (*)(char *, char *, void *), void *);
	void	 modifySettings(long flags);
	long	 searchFrame(GraphicDevice *gd, char *, char *);
	void	 validateLoadingFrame();
	long	 getCurrentFrame();
	void	 setCurrentFrame(long);

	Frame	*getFrames();
	long	 getNbFrames();

	DisplayList *getDisplayList();

#ifdef DUMP
	void	 dump(BitStream *bs);
static  void	 dumpActions(BitStream *bs, ActionRecord *actions);
#endif
};

DisplayListEntry *findFocus(DisplayList *dl);
void setFlashTimer(struct timeval *tv, int time_ms);
int checkFlashTimer(struct timeval *tv);

void loadNewSwf(FlashMovie *movie, char *url, int level);

void computeBBox(FlashMovie *movie, Rect *rect, DisplayListEntry *e);

long processMovie(FlashMovie *movie);

#endif /* _PROGRAM_H_ */

--- NEW FILE: movie.cc ---
////////////////////////////////////////////////////////////
// Flash Plugin and Player
// Copyright (C) 1998,1999 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 at club-internet.fr>
//  
#include "movie.h"

FlashMovie::FlashMovie() 
{
	gd = NULL;
	sm = NULL;
	getSwf = NULL;
	getUrl = NULL;
	cursorOnOff = NULL;
	buttons_updated = 0;
	scheduledTime.tv_sec = -1;
	cur_focus = NULL;
	lost_over = NULL;
	msPerFrame = 0;

	/* mouse handling */
	mouse_active = 0;
	mouse_x = -1;
	mouse_y = -1;
	button_pressed = 0;
	refresh = 1;
}
    
FlashMovie::~FlashMovie() 
{
	CInputScript *n;

	while (main != NULL) {
		n = main->next;
		delete main;
		main = n;
	}

	if (gd) delete gd;
	if (sm) delete sm;
}

int
FlashMovie::processMovie(GraphicDevice *gd, SoundMixer *sm)
{
	CInputScript *script;
	int wakeUp = 0;

	if (sm && sm->playSounds()) {
		wakeUp = 1;
	}
	for (script = this->main; script != NULL; script = script->next) {
		if (script->program == NULL) continue;
		if (script->program->nbFrames == 0) continue;
		if (script->program->processMovie(gd,sm)) {
			wakeUp = 1;
		}
	}
	renderMovie();
	return wakeUp;
}

int
FlashMovie::handleEvent(GraphicDevice *gd, SoundMixer *sm, FlashEvent *event)
{
	int wakeUp = 0;

	if (sm && sm->playSounds()) {
		wakeUp = 1;
	}
	if (this->main == 0) return 0;
	if (this->main->program == 0) return 0;
	if (this->main->program->handleEvent(gd, sm, event)) {
		wakeUp = 1;
	}
	renderMovie();
	return wakeUp;
}

/* current focus bigger and translated if needed */
void
FlashMovie::renderFocus()
{
	Rect rect,boundary;
	Matrix mat;

	if (mouse_active || !cur_focus) return;

	/* rect is the bbox in screen coordinates */

        // Compute the bounding box in screen coordinates
        cur_focus->character->getBoundingBox(&boundary,cur_focus);
        mat = (*gd->adjust) * cur_focus->renderMatrix;
        transformBoundingBox(&rect, &mat, &boundary, 1);

	gd->drawBox(rect.xmin, rect.ymin, rect.xmax, rect.ymax);
}

void 
FlashMovie::renderMovie()
{
	CInputScript *script,*prev,*next;
	Rect clipping;
	Matrix identity;

	clipping.reset();

	// First pass to update the clipping region
	for (script = this->main; script != NULL; script = script->next) {
		if (script->level == -1) {
			clipping.xmin = -32768;
			clipping.ymin = -32768;
			clipping.xmax =  32767;
			clipping.ymax =  32767;
			continue;
		}
		if (script->program == NULL) continue;
		if (script->program->dl->bbox.xmin == LONG_MAX) continue;
		transformBoundingBox(&clipping, &identity, &script->program->dl->bbox, 0);
		script->program->render = 0;
	}

	if (clipping.xmin == LONG_MAX) return;

	// Update the clipping region
	gd->updateClippingRegion(&clipping);
	gd->clearCanvas();

	// Second pass to render the movie
	for (script = this->main; script != NULL; script = script->next) {
		if (script->level == -1) continue;
		if (script->program == NULL) continue;
		script->program->dl->render(gd);
	}
	renderFocus();

	// Final pass to delete some movies
	script = this->main;
	prev = 0;
	while (script != NULL) {
		if (script->level == -1) {
			next = script->next;
			if (prev == 0) {
				this->main = next;
			} else {
				prev->next = next;
			}
			delete script;
			script = next;
		} else {
			prev = script;
			script = script->next;
		}
	}
}

--- NEW FILE: bitmap.h ---
/////////////////////////////////////////////////////////////
// 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.
// 
///////////////////////////////////////////////////////////////
#ifndef _BITMAP_H_
#define _BITMAP_H_

struct MyErrorHandler {
	struct jpeg_error_mgr pub;
	jmp_buf setjmp_buffer;
};

class Bitmap : public Character {
 public:
	long		 width;
	long		 height;
        long             bpl;
	long		 depth;

	unsigned char 	*pixels;		// Array of Pixels
	Color		*colormap; 	// Array of color definitions
	long		 nbColors;

	unsigned char 	*alpha_buf;	// Array of alpha values (no alpha if NULL)

	int		 defLevel;

// Class Variables

	static int haveTables;
	static struct jpeg_decompress_struct jpegObject;
	static struct jpeg_source_mgr jpegSourceManager;
	static MyErrorHandler jpegErrorMgr;

public:
	Bitmap(long id, int level = 1);
	~Bitmap();

	// JPEG handling methods
	int	 buildFromJpegInterchangeData(unsigned char *stream, int alpha, long offset);	// Complete
	int	 buildFromJpegAbbreviatedData(unsigned char *stream);	// Abbreviated

		// Class Method
	static int readJpegTables(unsigned char *stream);	// Tables Only

	// ZLIB handling methods
	int	 buildFromZlibData(unsigned char *buffer,
					int width, int height,
					int format, int tableSize, int tableHasAlpha);

	long		 getWidth();
	long		 getHeight();
	Color   	*getColormap(long *n);
	unsigned char 	*getPixels();
};

#endif /* _BITMAP_H_ */




More information about the dslinux-commit mailing list