00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020
00021
00022
00023 #include "swf.h"
00024
00025 #ifdef RCSID
00026 static char *rcsid = "$Id: graphic.cc,v 1.1.1.1 2002/01/25 22:14:58 kergoth Exp $";
00027 #endif
00028
00029 #define PRINT 0
00030
00031
00032
00033 GraphicDevice::GraphicDevice(FlashDisplay *fd)
00034 {
00035 flashDisplay = fd;
00036
00037 bgInitialized = 0;
00038
00039
00040 flashDisplay->flash_refresh = 0;
00041
00042
00043 redMask = 0xF800;
00044 greenMask = 0x07E0;
00045 blueMask = 0x001F;
00046
00047
00048 targetWidth = fd->width;
00049 targetHeight = fd->height;
00050 bpl = fd->bpl;
00051
00052 #if PRINT
00053 printf("Target Width = %d\n", targetWidth);
00054 printf("Target Height = %d\n", targetHeight);
00055 #endif
00056
00057 zoom = FRAC;
00058 movieWidth = targetWidth;
00059 movieHeight = targetHeight;
00060
00061 viewPort.xmin = 0;
00062 viewPort.xmax = targetWidth-1;
00063 viewPort.ymin = 0;
00064 viewPort.ymax = targetHeight-1;
00065
00066 canvasBuffer = (unsigned char *) fd->pixels;
00067
00068 adjust = new Matrix;
00069 foregroundColor.red = 0;
00070 foregroundColor.green = 0;
00071 foregroundColor.blue = 0;
00072 foregroundColor.alpha = ALPHA_OPAQUE;
00073
00074 backgroundColor.red = 0;
00075 backgroundColor.green = 0;
00076 backgroundColor.blue = 0;
00077 backgroundColor.alpha = ALPHA_OPAQUE;
00078
00079 showMore = 0;
00080
00081 setClipping(0);
00082 setClipping(1);
00083
00084
00085
00086 height = targetHeight;
00087 segs = (Segment **)malloc(height * sizeof(Segment *));
00088 memset(segs, 0, height * sizeof(Segment *));
00089 ymin = height;
00090 ymax = -1;
00091
00092 seg_pool = (Segment *)malloc(NB_SEGMENT_MAX * sizeof(Segment));
00093 seg_pool_cur = seg_pool;
00094 }
00095
00096 GraphicDevice::~GraphicDevice()
00097 {
00098 free(segs);
00099 free(seg_pool);
00100
00101 if (adjust) {
00102 delete adjust;
00103 }
00104 }
00105
00106 Color *
00107 GraphicDevice::getColormap(Color *old, long n, Cxform *cxform)
00108 {
00109 Color *newCmp;
00110
00111 newCmp = new Color[n];
00112 if (newCmp == NULL) return NULL;
00113
00114 if (cxform) {
00115 for(long i = 0; i < n; i++)
00116 {
00117 newCmp[i] = cxform->getColor(old[i]);
00118 newCmp[i].pixel = allocColor(newCmp[i]);
00119 }
00120 } else {
00121 for(long i = 0; i < n; i++)
00122 {
00123 newCmp[i] = old[i];
00124 newCmp[i].pixel = allocColor(old[i]);
00125 }
00126 }
00127
00128 return newCmp;
00129 }
00130
00131 long
00132 GraphicDevice::getHeight()
00133 {
00134 return targetHeight;
00135 }
00136
00137 long
00138 GraphicDevice::getWidth()
00139 {
00140 return targetWidth;
00141 }
00142
00143 Color
00144 GraphicDevice::getForegroundColor()
00145 {
00146 return foregroundColor;
00147 }
00148
00149 void
00150 GraphicDevice::setForegroundColor(Color color)
00151 {
00152 foregroundColor = color;
00153 }
00154
00155 Color
00156 GraphicDevice::getBackgroundColor()
00157 {
00158 return backgroundColor;
00159 }
00160
00161 int
00162 GraphicDevice::setBackgroundColor(Color color)
00163 {
00164 if (bgInitialized == 0) {
00165 backgroundColor = color;
00166 clearCanvas();
00167 bgInitialized = 1;
00168 return 1;
00169 }
00170 return 0;
00171 }
00172
00173 void
00174 GraphicDevice::setMovieDimension(long width, long height)
00175 {
00176 float xAdjust, yAdjust;
00177
00178 movieWidth = width;
00179 movieHeight = height;
00180
00181 xAdjust = (float)targetWidth*zoom/(float)width;
00182 yAdjust = (float)targetHeight*zoom/(float)height;
00183
00184 if (xAdjust < yAdjust) {
00185 adjust->a = xAdjust;
00186 adjust->d = xAdjust;
00187 adjust->ty = ((targetHeight*zoom) - (long)(height * xAdjust))/2;
00188 viewPort.ymin = adjust->ty/zoom;
00189 viewPort.ymax = targetHeight-viewPort.ymin-1;
00190 } else {
00191 adjust->a = yAdjust;
00192 adjust->d = yAdjust;
00193 adjust->tx = ((targetWidth*zoom) - (long)(width * yAdjust))/2;
00194 viewPort.xmin = adjust->tx/zoom;
00195 viewPort.xmax = targetWidth-viewPort.xmin-1;
00196 }
00197
00198 if (viewPort.xmin < 0) viewPort.xmin = 0;
00199 if (viewPort.ymin < 0) viewPort.ymin = 0;
00200 if (viewPort.xmax >= targetWidth) viewPort.xmax = targetWidth-1;
00201 if (viewPort.ymax >= targetHeight) viewPort.ymax = targetHeight-1;
00202 }
00203
00204 void
00205 GraphicDevice::setMovieZoom(int z)
00206 {
00207 z *= FRAC;
00208 if (z <= 0 || z > 100) return;
00209 zoom = z;
00210 setMovieDimension(movieWidth,movieHeight);
00211 }
00212
00213 void
00214 GraphicDevice::setMovieOffset(long x, long y)
00215 {
00216 adjust->tx = -zoom*x;
00217 adjust->ty = -zoom*y;
00218 }
00219
00220 long
00221 GraphicDevice::clip(long &y, long &start, long &end)
00222 {
00223 long xmin,xend;
00224
00225 if (y < clip_rect.ymin ||
00226 y >= clip_rect.ymax) return 1;
00227 if (end <= start)
00228 return 1;
00229 xmin = clip_rect.xmin * FRAC;
00230 xend = clip_rect.xmax * FRAC;
00231
00232 if (end <= xmin || start >= xend) return 1;
00233
00234 if (start < xmin) start = xmin;
00235 if (end > xend) end = xend;
00236
00237 return 0;
00238 }
00239
00240 void
00241 GraphicDevice::drawBox(long x1, long y1, long x2, long y2)
00242 {
00243 int i;
00244
00245 for(i=0;i<FRAC*2;i++) {
00246 drawLine(x1+i, y1+i, x2-i, y1+i, 0);
00247 drawLine(x1+i, y2-i, x2-i, y2-i, 0);
00248
00249 drawLine(x1+i, y1+i+1, x1+i, y2-i-1, 0);
00250 drawLine(x2-i, y1+i+1, x2-i, y2-i-1, 0);
00251 }
00252 }
00253
00254
00255
00256 inline Segment *
00257 GraphicDevice::allocSeg()
00258 {
00259 Segment *seg;
00260
00261 if ( (seg_pool_cur - seg_pool) >= NB_SEGMENT_MAX )
00262 return NULL;
00263 seg = seg_pool_cur++;
00264
00265 return seg;
00266 }
00267
00268
00269 void
00270 GraphicDevice::addSegment(long x1, long y1, long x2, long y2,
00271 FillStyleDef *f0,
00272 FillStyleDef *f1,
00273 int aa)
00274 {
00275 Segment *seg,**segs;
00276 long dX, X, Y, ymin, ymax, tmp;
00277 FillStyleDef *ff;
00278
00279 if ( y1 == y2 ) {
00280 return;
00281 }
00282
00283 if (y1 < y2) {
00284 ymin = y1;
00285 ymax = y2;
00286 ff = f0;
00287 f0 = f1;
00288 f1 = ff;
00289 } else {
00290 ymin = y2;
00291 ymax = y1;
00292 tmp = x1;
00293 x1 = x2;
00294 x2 = tmp;
00295 }
00296
00297 if (ymax>>FRAC_BITS < clip_rect.ymin) {
00298 return;
00299 }
00300 if (ymin>>FRAC_BITS > clip_rect.ymax) {
00301 return;
00302 }
00303
00304 X = x1 << SEGFRAC;
00305 dX = ((x2 - x1)<<SEGFRAC)/(ymax-ymin);
00306
00307 if (ymin < 0) {
00308 X += dX * (-ymin);
00309 ymin = 0;
00310 }
00311
00312 Y = (ymin + (FRAC-1)) & ~(FRAC-1);
00313 if (Y > ymax) {
00314
00315 return;
00316 }
00317 X += dX * (Y-ymin);
00318
00319 Y >>= FRAC_BITS;
00320 if (Y >= clip_rect.ymax) {
00321 return;
00322 }
00323
00324 seg = allocSeg();
00325 if (seg == NULL) {
00326 return;
00327 }
00328
00329 seg->next = 0;
00330 seg->nextValid = 0;
00331 seg->aa = aa;
00332 seg->ymax = ymax;
00333 seg->x1 = x1;
00334 seg->x2 = x2;
00335 seg->X = X;
00336 seg->dX = dX;
00337 seg->fs[0] = f0;
00338 seg->fs[1] = f1;
00339
00340 if (Y < this->ymin) this->ymin = Y;
00341 ymax = (seg->ymax + FRAC - 1) >> FRAC_BITS;
00342 if (ymax >= this->height) ymax = this->height-1;
00343 if (ymax > this->ymax) this->ymax = ymax;
00344
00345 segs = this->segs;
00346
00347 if (segs[Y] == 0) {
00348 segs[Y] = seg;
00349 } else {
00350 Segment *s,*prev;
00351
00352 prev = 0;
00353 for(s = segs[Y]; s; prev = s, s = s->next) {
00354 if (s->X > seg->X) {
00355 if (prev) {
00356 prev->next = seg;
00357 seg->next = s;
00358 } else {
00359 seg->next = segs[Y];
00360 segs[Y] = seg;
00361 }
00362 break;
00363 }
00364 }
00365 if (s == 0) {
00366 prev->next = seg;
00367 seg->next = s;
00368 }
00369 }
00370 }
00371
00372 inline Segment *
00373 GraphicDevice::progressSegments(Segment * curSegs, long y)
00374 {
00375 Segment *seg,*prev;
00376
00377
00378 seg = curSegs;
00379 prev = 0;
00380 while(seg)
00381 {
00382 if ((y*FRAC) > seg->ymax) {
00383
00384 if (prev) {
00385 prev->nextValid = seg->nextValid;
00386 } else {
00387 curSegs = seg->nextValid;
00388 }
00389 seg = seg->nextValid;
00390 } else {
00391 seg->X += seg->dX * FRAC;
00392 prev = seg;
00393 seg = seg->nextValid;
00394 }
00395 }
00396 return curSegs;
00397 }
00398
00399 inline Segment *
00400 GraphicDevice::newSegments(Segment *curSegs, Segment *newSegs)
00401 {
00402 Segment *s,*seg,*prev;
00403
00404 s = curSegs;
00405 prev = 0;
00406
00407
00408 for (seg = newSegs; seg; seg=seg->next)
00409 {
00410
00411 if (curSegs == 0) {
00412 curSegs = seg;
00413 seg->nextValid = 0;
00414 } else {
00415 for(; s; prev = s, s = s->nextValid)
00416 {
00417 if ( s->X > seg->X ||
00418 ( (s->X == seg->X) &&
00419 ( (seg->x1 == s->x1 && seg->dX < s->dX) ||
00420 (seg->x2 == s->x2 && seg->dX > s->dX)
00421 ))) {
00422
00423 if (prev) {
00424 seg->nextValid = s;
00425 prev->nextValid = seg;
00426 } else {
00427 seg->nextValid = curSegs;
00428 curSegs = seg;
00429 }
00430 break;
00431 }
00432 }
00433
00434 if (s == 0) {
00435 prev->nextValid = seg;
00436 seg->nextValid = 0;
00437 }
00438 }
00439
00440 s = seg;
00441 }
00442
00443 return curSegs;
00444 }
00445
00446 #if 0
00447 static void
00448 printSeg(Segment *seg)
00449 {
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462 }
00463 #endif
00464
00465 inline void
00466 GraphicDevice::renderScanLine(long y, Segment *curSegs)
00467 {
00468 Segment *seg;
00469 long width;
00470 int fi = 1;
00471 FillStyleDef *f;
00472
00473 width = targetWidth * FRAC;
00474
00475 if (curSegs && curSegs->fs[0] && curSegs->fs[1] == 0) {
00476 fi = 0;
00477 }
00478 for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid)
00479 {
00480 if (seg->nextValid->X <0) continue;
00481 if ((seg->X>>SEGFRAC) > width) break;
00482 f = seg->fs[fi];
00483 if (f) {
00484 switch (f->type) {
00485 case f_Solid:
00486 if (seg->aa) {
00487 fillLineAA(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
00488 } else {
00489 fillLine(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
00490 }
00491 break;
00492 case f_TiledBitmap:
00493 case f_clippedBitmap:
00494 fillLineBitmap(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
00495 break;
00496 case f_LinearGradient:
00497 fillLineLG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
00498 break;
00499 case f_RadialGradient:
00500 fillLineRG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
00501 break;
00502 case f_None:
00503 break;
00504 }
00505 }
00506 }
00507 }
00508
00509
00510 void
00511 GraphicDevice::drawPolygon(void)
00512 {
00513 long y;
00514 Segment *curSegs,*seg;
00515
00516
00517 if (this->ymax == -1)
00518 return;
00519
00520
00521 curSegs = 0;
00522 for(y=this->ymin; y <= this->ymax; y++) {
00523
00524
00525 curSegs = progressSegments(curSegs, y);
00526
00527
00528 curSegs = newSegments(curSegs, this->segs[y]);
00529
00530
00531 if (this->scan_line_func == NULL) {
00532 renderScanLine(y, curSegs);
00533 } else {
00534 for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid) {
00535 if (seg->nextValid->X >= seg->X) {
00536 scan_line_func(this->scan_line_func_id, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
00537 }
00538 }
00539 }
00540 }
00541
00542
00543 memset(this->segs + this->ymin, 0,
00544 (this->ymax - this->ymin + 1) * sizeof(Segment *));
00545
00546 this->ymax = -1;
00547 this->ymin = this->height;
00548
00549 this->seg_pool_cur = this->seg_pool;
00550 }
00551
00552 void
00553 GraphicDevice::updateClippingRegion(Rect *rect)
00554 {
00555 if (!clipping) return;
00556
00557 transformBoundingBox(&clip_rect, adjust, rect, 1);
00558 clip_rect.xmin >>= FRAC_BITS;
00559 clip_rect.xmax >>= FRAC_BITS;
00560 clip_rect.ymin >>= FRAC_BITS;
00561 clip_rect.ymax >>= FRAC_BITS;
00562
00563 clip_rect.xmin-=2;
00564 clip_rect.ymin-=2;
00565 clip_rect.xmax+=2;
00566 clip_rect.ymax+=2;
00567
00568 if (clip_rect.xmin < viewPort.xmin) clip_rect.xmin = viewPort.xmin;
00569 if (clip_rect.xmax < viewPort.xmin) clip_rect.xmax = viewPort.xmin;
00570 if (clip_rect.ymin < viewPort.ymin) clip_rect.ymin = viewPort.ymin;
00571 if (clip_rect.ymax < viewPort.ymin) clip_rect.ymax = viewPort.ymin;
00572
00573 if (clip_rect.xmax > viewPort.xmax) clip_rect.xmax = viewPort.xmax;
00574 if (clip_rect.ymax > viewPort.ymax) clip_rect.ymax = viewPort.ymax;
00575 if (clip_rect.xmin > viewPort.xmax) clip_rect.xmin = viewPort.xmax;
00576 if (clip_rect.ymin > viewPort.ymax) clip_rect.ymin = viewPort.ymax;
00577 }
00578
00579 void
00580 GraphicDevice::setClipping(int value)
00581 {
00582 clipping = value;
00583 if (clipping == 0) {
00584
00585 clip_rect.xmin = viewPort.xmin;
00586 clip_rect.xmax = viewPort.xmax;
00587 clip_rect.ymin = viewPort.ymin;
00588 clip_rect.ymax = viewPort.ymax;
00589 }
00590 }
00591
00592
00593 void
00594 GraphicDevice::clearCanvas()
00595 {
00596 }
00597
00598 long
00599 GraphicDevice::allocColor(Color color)
00600 {
00601 return 0;
00602 }
00603
00604 void
00605 GraphicDevice::fillLineBitmap(FillStyleDef *f, long y, long start, long end)
00606 {
00607 }
00608
00609 void
00610 GraphicDevice::fillLineLG(Gradient *grad, long y, long start, long end)
00611 {
00612 }
00613
00614 void
00615 GraphicDevice::fillLineRG(Gradient *grad, long y, long start, long end)
00616 {
00617 }
00618
00619 void
00620 GraphicDevice::fillLine(FillStyleDef *f, long y, long start, long end)
00621 {
00622 }
00623
00624 void
00625 GraphicDevice::fillLineAA(FillStyleDef *f, long y, long start, long end)
00626 {
00627 }
00628
00629 void
00630 GraphicDevice::drawLine(long x1, long y1, long x2, long y2, long width)
00631 {
00632 }