⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 graphic.cpp

📁 Evc编的一个在wince5.0上运行的flash播放器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  }

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

/************************************************************************/

/* polygon rasteriser */

static inline Segment *allocSeg(GraphicDevice *gd)
{
    Segment *seg;

    if ( (gd->seg_pool_cur - gd->seg_pool) >= NB_SEGMENT_MAX )
        return NULL;
    seg = gd->seg_pool_cur++;

    return seg;
}

/* add a segment to the current path */
/* XXX: handle reverse here ? */
/* XXX: should not malloc here */
/* XXX: handle y1 == y2 case (different for fill / line) */
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 0
    if ( ((y1 + (FRAC-1)) & ~(FRAC-1)) == ((y2 + (FRAC-1)) & ~(FRAC-1)) ) {
        return;
    }
#else
    if ( y1 == y2 ) {
        return;
    }
#endif

    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 (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(this);
    if (seg == NULL) {
        //        printf("addSegment: too many segments\n");.
        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;
        }
    }
}

static Segment *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;
#if 0
            if (prev && prev->X > seg->X) {
                s = &curSegs;
                while ((*s)->X < seg->X) s=&(*s)->nextValid;
                prev->nextValid = seg->nextValid;
                seg->nextValid = *s;
                *s = seg;
                seg = prev->nextValid;
            } else 
#endif
                {
                prev = seg;
                seg = seg->nextValid;
            }
        }
    }
    return curSegs;
}

static Segment *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

static void
renderScanLine(GraphicDevice *gd, long y, Segment *curSegs)
{
    Segment *seg;
    long width;
    int fi = 1;
    FillStyleDef *f;

    width = gd->getWidth() * 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;
#if 0
        if (seg->X > seg->nextValid->X) {
            printf("error %d %d\n",seg->X,seg->nextValid->X);
        }
#endif
        f = seg->fs[fi];
        if (f) {
            switch (f->type) {
                case f_Solid:
                    if (seg->aa) {
                        gd->fillLineAA(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
                    } else  {
                        gd->fillLine(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
                    }
                    break;
                case f_TiledBitmap:
                case f_clippedBitmap:
                    gd->fillLineBitmap(f, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
                    break;
                case f_LinearGradient:
                    gd->fillLineLG(&f->gradient, y, seg->X>>SEGFRAC, seg->nextValid->X>>SEGFRAC);
                    break;
                case f_RadialGradient:
                    gd->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(this, y, curSegs);
        } else {
            for(seg = curSegs; seg && seg->nextValid; seg = seg->nextValid) {
                if (seg->nextValid->X >= seg->X) {
                    this->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;

#if PRINT&1
	clip_rect.print();
#endif

	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) {
		//printf("Clipping Off\n");
		// Reset region
		clip_rect.xmin = viewPort.xmin;
		clip_rect.xmax = viewPort.xmax;
		clip_rect.ymin = viewPort.ymin;
		clip_rect.ymax = viewPort.ymax;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -