📄 graphic.cpp
字号:
////////////////////////////////////////////////////////////// Flash Plugin and Player// Copyright (C) 1998 Olivier Debon// // This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License// as published by the Free Software Foundation; either version 2// of the License, or (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.// ///////////////////////////////////////////////////////////////// Author : Olivier Debon <odebon@club-internet.fr>// #include "swf.h"#ifdef RCSIDstatic char *rcsid = "$Id: graphic.cc,v 1.1.1.1 2004/06/04 21:17:05 tgc Exp $";#endif#define PRINT 0// PublicGraphicDevice::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;}longGraphicDevice::getHeight(){ return targetHeight;}longGraphicDevice::getWidth(){ return targetWidth;}ColorGraphicDevice::getForegroundColor(){ return foregroundColor;}voidGraphicDevice::setForegroundColor(Color color){ foregroundColor = color;}ColorGraphicDevice::getBackgroundColor(){ return backgroundColor;}intGraphicDevice::setBackgroundColor(Color color){ if (bgInitialized == 0) { backgroundColor = color; clearCanvas(); bgInitialized = 1; return 1; } return 0;}voidGraphicDevice::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;}voidGraphicDevice::setMovieZoom(int z){ z *= FRAC; if (z <= 0 || z > 100) return; zoom = z; setMovieDimension(movieWidth,movieHeight);}voidGraphicDevice::setMovieOffset(long x, long y){ adjust->tx = -zoom*x; adjust->ty = -zoom*y;}longGraphicDevice::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;}voidGraphicDevice::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 */voidGraphicDevice::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 0static voidprintSeg(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); */}#endifinline voidGraphicDevice::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 */voidGraphicDevice::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;}voidGraphicDevice::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;}voidGraphicDevice::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; }}// VirtualvoidGraphicDevice::clearCanvas(){}longGraphicDevice::allocColor(Color color){ return 0;}voidGraphicDevice::fillLineBitmap(FillStyleDef *f, long y, long start, long end){}voidGraphicDevice::fillLineLG(Gradient *grad, long y, long start, long end){}voidGraphicDevice::fillLineRG(Gradient *grad, long y, long start, long end){}voidGraphicDevice::fillLine(FillStyleDef *f, long y, long start, long end){}voidGraphicDevice::fillLineAA(FillStyleDef *f, long y, long start, long end){}voidGraphicDevice::drawLine(long x1, long y1, long x2, long y2, long width){}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -