Пример #1
0
BOOL WINAPI
UnionRect( LPRECT dest, const RECT *src1, const RECT *src2 )
{
    if (IsRectEmpty(src1))
    {
	if (IsRectEmpty(src2))
	{
	    SetRectEmpty( dest );
	    return FALSE;
	}
	else *dest = *src2;
    }
    else
    {
	if (IsRectEmpty(src2)) *dest = *src1;
	else
	{
	    dest->left   = MWMIN( src1->left, src2->left );
	    dest->right  = MWMAX( src1->right, src2->right );
	    dest->top    = MWMIN( src1->top, src2->top );
	    dest->bottom = MWMAX( src1->bottom, src2->bottom );	    
	}
    }
    return TRUE;
}
Пример #2
0
/*
 * Rectangle-related functions
 *
 * Copyright 1993, 1996 Alexandre Julliard
 *
 */
BOOL WINAPI
IntersectRect( LPRECT dest, const RECT *src1, const RECT *src2 )
{
    if (IsRectEmpty(src1) || IsRectEmpty(src2) ||
	(src1->left >= src2->right) || (src2->left >= src1->right) ||
	(src1->top >= src2->bottom) || (src2->top >= src1->bottom))
    {
	SetRectEmpty( dest );
	return FALSE;
    }
    dest->left   = MWMAX( src1->left, src2->left );
    dest->right  = MWMIN( src1->right, src2->right );
    dest->top    = MWMAX( src1->top, src2->top );
    dest->bottom = MWMIN( src1->bottom, src2->bottom );
    return TRUE;
}
Пример #3
0
/*
 * Draw a window's background pixmap.
 *
 * The flags mean:
 *   GR_BACKGROUND_TILE- tile the pixmap across the window (default).
 *   GR_BACKGROUND_TOPLEFT- draw the pixmap at (0,0) relative to the window.
 *   GR_BACKGROUND_CENTER- draw the pixmap in the middle of the window.
 *   GR_BACKGROUND_STRETCH- stretch the pixmap within the window.
 *   GR_BACKGROUND_TRANS- if the pixmap is smaller than the window and not
 *     using tile mode, there will be gaps around the pixmap. This flag causes
 *     to not fill in the spaces with the background colour.
 */
void
GsDrawBackgroundPixmap(GR_WINDOW *wp, GR_PIXMAP *pm, GR_COORD x,
	GR_COORD y, GR_SIZE width, GR_SIZE height)
{
	GR_SIZE destwidth, destheight, fillwidth, fillheight, pmwidth, pmheight;
	GR_COORD fromx, fromy, destx, desty, pixmapx = 0, pixmapy = 0;

	if(wp->bgpixmapflags & GR_BACKGROUND_STRETCH) {
		/* must use whole window coords or stretch will have incorrect ratios*/
		GdStretchBlit(wp->psd, wp->x, wp->y, wp->x + wp->width, wp->y + wp->height,
			pm->psd, 0, 0, pm->width - 1, pm->height - 1, MWROP_SRC_OVER);
		return;
	}

	if(wp->bgpixmapflags == GR_BACKGROUND_TILE) {
		GsTileBackgroundPixmap(wp, pm, x, y, width, height);
		return;
	}

	if(wp->bgpixmapflags & GR_BACKGROUND_CENTER) {
		if (pm->width < wp->width) pixmapx = (wp->width - pm->width) / 2;
		if (pm->height < wp->height) pixmapy = (wp->height - pm->height) / 2;
	}

	/* topleft & center calcs*/
	pmwidth = MWMIN(pm->width, wp->width);
	pmheight = MWMIN(pm->height, wp->height);

	if(x > pixmapx) {
		destx = x;
		fromx = x - pixmapx;
		destwidth = pixmapx + pmwidth - x;
	} else {
		destx = pixmapx;
		fromx = 0;
		destwidth = x + width - pixmapx;
	}

	if(y > pixmapy) {
		desty = y;
		fromy = y - pixmapy;
		destheight = pixmapy + pmheight - desty;
	} else {
		desty = pixmapy;
		fromy = 0;
		destheight = y + height - pixmapy;
	}

	if(destwidth > 0 && destheight > 0) {
		destwidth = MWMIN(width, destwidth);
		destheight = MWMIN(height, destheight);

		GdBlit(wp->psd, wp->x + destx, wp->y + desty, destwidth, destheight,
			pm->psd, fromx, fromy, MWROP_SRC_OVER);
	}

	if(wp->bgpixmapflags & GR_BACKGROUND_TRANS)
		return;

	/* Fill in the gaps around the pixmap */
	if(x < pixmapx) {
		fillwidth = pixmapx - x;
		if(fillwidth > width) fillwidth = width;
		fillheight = height;

		GdFillRect(wp->psd, wp->x + x, wp->y + y, fillwidth, fillheight);
	}
	if(x + width > pixmapx + pmwidth) {
		fillwidth = (x + width) - (pixmapx + pmwidth);
		if(fillwidth > width) fillwidth = width;
		fillheight = height;

		if(x < pixmapx + pmwidth)
			destx = pixmapx + pmwidth + wp->x;
		else destx = x + wp->x;

		GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight);
	}
	if(y < pixmapy) {
		fillheight = pixmapy - y;
		if(fillheight > height) fillheight = height;

		if(x < pixmapx)
			destx = pixmapx + wp->x;
		else destx = x + wp->x;
		if(x + width > pixmapx + pmwidth)
			fillwidth = pixmapx + pmwidth - destx;
		else fillwidth = x + width - destx;

		if(fillwidth > 0 && fillheight > 0)
			GdFillRect(wp->psd, destx, wp->y + y, fillwidth, fillheight);
	}
	if(y + height > pixmapy + pmheight) {
		fillheight = (y + height) - (pixmapy + pmheight);
		if(fillheight > height) fillheight = height;

		if(x < pixmapx)
			destx = pixmapx + wp->x;
		else destx = x + wp->x;
		if(y < pixmapy + pmheight)
			desty = pixmapy + pmheight + wp->y;
		else desty = y + wp->y;
	
		if(x + width > pixmapx + pmwidth)
			fillwidth = pixmapx + pmwidth - destx;
		else fillwidth = x + width - destx;
		if(fillwidth > 0 && fillheight > 0)
			GdFillRect(wp->psd, destx, desty, fillwidth, fillheight);
	}
}
Пример #4
0
void
GdFillPoly(PSD psd, int count, MWPOINT *pointtable)
{
    MWCOORD xl = 0, xr = 0;     /* x vals of left and right edges */
    int dl = 0, dr = 0;         /* decision variables             */
    int ml = 0, m1l = 0;        /* left edge slope and slope+1    */
    int mr = 0, m1r = 0;        /* right edge slope and slope+1   */
    int incr1l = 0, incr2l = 0; /* left edge error increments     */
    int incr1r = 0, incr2r = 0; /* right edge error increments    */
    int dy;                     /* delta y                        */
    MWCOORD y;                  /* current scanline               */
    int left, right;            /* indices to first endpoints     */
    int i;                      /* loop counter                   */
    int nextleft, nextright;    /* indices to second endpoints    */
    MWPOINT *ptsOut, *FirstPoint;/* output buffer                 */
    MWCOORD *width, *FirstWidth;/* output buffer                  */
    int imin;                   /* index of smallest vertex (in y)*/
    int ymin;                   /* y-extents of polygon           */
    int ymax;

    /*
     *  find leftx, bottomy, rightx, topy, and the index
     *  of bottomy.
     */

    imin = getPolyYBounds(pointtable, count, &ymin, &ymax);

    if (gr_fillmode != MWFILL_SOLID) {
      int xmin, xmax;
      getPolyXBounds(pointtable, count, &xmin, &xmax);
      set_ts_origin(xmin, ymin);
    }

    dy = ymax - ymin + 1;
    if ((count < 3) || (dy < 0))
	return;
    ptsOut = FirstPoint = (MWPOINT *)ALLOCA(sizeof(MWPOINT) * dy);
    width = FirstWidth = (MWCOORD *)ALLOCA(sizeof(MWCOORD) * dy);
    if(!FirstPoint || !FirstWidth)
    {
	if (FirstWidth) FREEA(FirstWidth);
	if (FirstPoint) FREEA(FirstPoint);
	return;
    }

    nextleft = nextright = imin;
    y = pointtable[nextleft].y;

    /*
     *  loop through all edges of the polygon
     */
    do {
        /*
         *  add a left edge if we need to
         */
        if (pointtable[nextleft].y == y) {
            left = nextleft;

            /*
             *  find the next edge, considering the end
             *  conditions of the array.
             */
            nextleft++;
            if (nextleft >= count)
                nextleft = 0;

            /*
             *  now compute all of the random information
             *  needed to run the iterative algorithm.
             */
            BRESINITPGON(pointtable[nextleft].y-pointtable[left].y,
                         pointtable[left].x,pointtable[nextleft].x,
                         xl, dl, ml, m1l, incr1l, incr2l);
        }

        /*
         *  add a right edge if we need to
         */
        if (pointtable[nextright].y == y) {
            right = nextright;

            /*
             *  find the next edge, considering the end
             *  conditions of the array.
             */
            nextright--;
            if (nextright < 0)
                nextright = count-1;

            /*
             *  now compute all of the random information
             *  needed to run the iterative algorithm.
             */
            BRESINITPGON(pointtable[nextright].y-pointtable[right].y,
                         pointtable[right].x,pointtable[nextright].x,
                         xr, dr, mr, m1r, incr1r, incr2r);
        }

        /*
         *  generate scans to fill while we still have
         *  a right edge as well as a left edge.
         */
        i = MWMIN(pointtable[nextleft].y, pointtable[nextright].y) - y;
	/* in case we're called with non-convex polygon */
	if(i < 0)
        {
	    FREEA(FirstWidth);
	    FREEA(FirstPoint);
	    return;
	}
        while (i-- > 0) 
        {
            ptsOut->y = y;

            /*
             *  reverse the edges if necessary
             */
            if (xl < xr) 
            {
                *(width++) = xr - xl;
                (ptsOut++)->x = xl;
            }
            else 
            {
                *(width++) = xl - xr;
                (ptsOut++)->x = xr;
            }
            y++;

            /* increment down the edges */
            BRESINCRPGON(dl, xl, ml, m1l, incr1l, incr2l);
            BRESINCRPGON(dr, xr, mr, m1r, incr1r, incr2r);
        }
    }  while (y != ymax);

    /*
     * Finally, fill the spans
     */
    i = ptsOut-FirstPoint;
    ptsOut = FirstPoint;
    width = FirstWidth;
    while (--i >= 0) {
	/* calc x extent from width*/
	int e = *width++ - 1;
	if (e >= 0) {
	  if (gr_fillmode != MWFILL_SOLID) 
	    ts_drawrow(psd, ptsOut->x, ptsOut->x + e, ptsOut->y);
	   else
	     drawrow(psd, ptsOut->x, ptsOut->x + e, ptsOut->y);
	}
	++ptsOut;
    }

    FREEA(FirstWidth);
    FREEA(FirstPoint);
    GdFixCursor(psd);
}
Пример #5
0
/*
 *           GdAllocPolyPolygonRegion
 */
MWCLIPREGION *
GdAllocPolyPolygonRegion(MWPOINT *points, int *count, int nbpolygons, int mode)
{
    MWCLIPREGION *rgn;
    EdgeTableEntry *pAET;   /* Active Edge Table       */
    int y;                  /* current scanline        */
    int iPts = 0;           /* number of pts in buffer */
    EdgeTableEntry *pWETE;  /* Winding Edge Table Entry*/
    ScanLineList *pSLL;     /* current scanLineList    */
    MWPOINT *pts;           /* output buffer           */
    EdgeTableEntry *pPrevAET;        /* ptr to previous AET     */
    EdgeTable ET;                    /* header node for ET      */
    EdgeTableEntry AET;              /* header node for AET     */
    EdgeTableEntry *pETEs;           /* EdgeTableEntries pool   */
    ScanLineListBlock SLLBlock;      /* header for scanlinelist */
    int fixWAET = FALSE;
    POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers    */
    POINTBLOCK *tmpPtBlock;
    int numFullPtBlocks = 0;
    int poly, total;

    if(!(rgn = GdAllocRegion()))
        return NULL;

    /* special case a rectangle */

    if (((nbpolygons == 1) && ((*count == 4) ||
       ((*count == 5) && (points[4].x == points[0].x)
        && (points[4].y == points[0].y)))) &&
        (((points[0].y == points[1].y) &&
          (points[1].x == points[2].x) &&
          (points[2].y == points[3].y) &&
          (points[3].x == points[0].x)) ||
         ((points[0].x == points[1].x) &&
          (points[1].y == points[2].y) &&
          (points[2].x == points[3].x) &&
          (points[3].y == points[0].y))))
    {
        GdSetRectRegion( rgn,
	    MWMIN(points[0].x, points[2].x), MWMIN(points[0].y, points[2].y),
	    MWMAX(points[0].x, points[2].x), MWMAX(points[0].y, points[2].y) );
        return rgn;
    }

    for(poly = total = 0; poly < nbpolygons; poly++)
        total += count[poly];
    if (! (pETEs = malloc( sizeof(EdgeTableEntry) * total )))
    {
        GdDestroyRegion( rgn );
        return 0;
    }
    pts = FirstPtBlock.pts;
    REGION_CreateETandAET(count, nbpolygons, points, &ET, &AET,
        pETEs, &SLLBlock);
    pSLL = ET.scanlines.next;
    curPtBlock = &FirstPtBlock;

    if (mode != MWPOLY_WINDING) {
        /*
         *  for each scanline
         */
        for (y = ET.ymin; y < ET.ymax; y++) {
            /*
             *  Add a new edge to the active edge table when we
             *  get to the next edge.
             */
            if (pSLL != NULL && y == pSLL->scanline) {
                REGION_loadAET(&AET, pSLL->edgelist);
                pSLL = pSLL->next;
            }
            pPrevAET = &AET;
            pAET = AET.next;

            /*
             *  for each active edge
             */
            while (pAET) {
                pts->x = pAET->bres.minor_axis,  pts->y = y;
                pts++, iPts++;

                /*
                 *  send out the buffer
                 */
                if (iPts == NUMPTSTOBUFFER) {
                    tmpPtBlock = malloc( sizeof(POINTBLOCK));
                    if(!tmpPtBlock) {
                        return 0;
                    }
                    curPtBlock->next = tmpPtBlock;
                    curPtBlock = tmpPtBlock;
                    pts = curPtBlock->pts;
                    numFullPtBlocks++;
                    iPts = 0;
                }
                EVALUATEEDGEEVENODD(pAET, pPrevAET, y);

            }
            REGION_InsertionSort(&AET);
        }
    }
    else {
        /*
         *  for each scanline
         */
        for (y = ET.ymin; y < ET.ymax; y++) {
            /*
             *  Add a new edge to the active edge table when we
             *  get to the next edge.
             */
            if (pSLL != NULL && y == pSLL->scanline) {
                REGION_loadAET(&AET, pSLL->edgelist);
                REGION_computeWAET(&AET);
                pSLL = pSLL->next;
            }
            pPrevAET = &AET;
            pAET = AET.next;
            pWETE = pAET;

            /*
             *  for each active edge
             */
            while (pAET) {
                /*
                 *  add to the buffer only those edges that
                 *  are in the Winding active edge table.
                 */
                if (pWETE == pAET) {
                    pts->x = pAET->bres.minor_axis,  pts->y = y;
                    pts++, iPts++;

                    /*
                     *  send out the buffer
                     */
                    if (iPts == NUMPTSTOBUFFER) {
                        tmpPtBlock = malloc( sizeof(POINTBLOCK) );
                        if(!tmpPtBlock) {
                            return 0;
                        }
                        curPtBlock->next = tmpPtBlock;
                        curPtBlock = tmpPtBlock;
                        pts = curPtBlock->pts;
                        numFullPtBlocks++;    iPts = 0;
                    }
                    pWETE = pWETE->nextWETE;
                }
                EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
            }

            /*
             *  recompute the winding active edge table if
             *  we just resorted or have exited an edge.
             */
            if (REGION_InsertionSort(&AET) || fixWAET) {
                REGION_computeWAET(&AET);
                fixWAET = FALSE;
            }
        }
    }
    REGION_FreeStorage(SLLBlock.next);
    REGION_PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, rgn);
    for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
        tmpPtBlock = curPtBlock->next;
        free( curPtBlock );
        curPtBlock = tmpPtBlock;
    }
    free( pETEs );
    return rgn;
}