/* * REGION_FrameRgn * Create a region that is a frame around another region. * Expand all rectangles by +/- x and y, then subtract original region. */ BOOL REGION_FrameRgn( HRGN hDest, HRGN hSrc, INT x, INT y ) { BOOL bRet; MWRGNOBJ *srcObj = (MWRGNOBJ*) GDI_GetObjPtr( hSrc, OBJ_REGION ); if (srcObj->rgn->numRects != 0) { MWRGNOBJ* destObj = (MWRGNOBJ*) GDI_GetObjPtr( hDest, OBJ_REGION ); RECT *pRect, *pEndRect; RECT tempRect; EMPTY_REGION( destObj->rgn ); pEndRect = srcObj->rgn->rects + srcObj->rgn->numRects; for(pRect = srcObj->rgn->rects; pRect < pEndRect; pRect++) { tempRect.left = pRect->left - x; tempRect.top = pRect->top - y; tempRect.right = pRect->right + x; tempRect.bottom = pRect->bottom + y; GdUnionRectWithRegion( &tempRect, destObj->rgn ); } GdSubtractRegion( destObj->rgn, destObj->rgn, srcObj->rgn ); bRet = TRUE; } else bRet = FALSE; return bRet; }
HRGN WINAPI ExtCreateRegion(const XFORM* lpXform, DWORD dwCount, const RGNDATA* rgndata) { HRGN hrgn = CreateRectRgn(0, 0, 0, 0); MWRGNOBJ *obj = (MWRGNOBJ *) GDI_GetObjPtr( hrgn, OBJ_REGION ); RECT *pCurRect, *pEndRect; /*TRACE(region, " %p %ld %p. Returning %04x\n", lpXform, dwCount, rgndata, hrgn);*/ if(!hrgn) { WARN(region, "Can't create a region!\n"); return 0; } if(lpXform) WARN(region, "Xform not implemented - ignoring\n"); if(rgndata->rdh.iType != RDH_RECTANGLES) { WARN(region, "Type not RDH_RECTANGLES\n"); DeleteObject( hrgn ); return 0; } pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount; for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++) GdUnionRectWithRegion( pCurRect, obj->rgn ); return hrgn; }
/* * REGION_UnionRectWithRgn * Adds a rectangle to a HRGN * A helper used by scroll.c */ BOOL REGION_UnionRectWithRgn( HRGN hrgn, const RECT *lpRect ) { MWRGNOBJ *obj = (MWRGNOBJ *)hrgn; if(!obj) return FALSE; GdUnionRectWithRegion( lpRect, obj->rgn ); return TRUE; }
/* update framebuffer*/ static void fb_update(PSD psd, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height) { MWRECT rc; if (!width) width = psd->xres; if (!height) height = psd->yres; /* add update rect to update region*/ rc.left = x; rc.right = x + width; rc.top = y; rc.bottom = y + height; GdUnionRectWithRegion(&rc, fb_updateregion); }
/* * Combine the passed rectangle with the update region for the given window. * Coordinates are passed relative to window. * If bUnion is TRUE, union the rectangle, otherwise subtract it. */ void MwUnionUpdateRegion(HWND wp, MWCOORD x, MWCOORD y, MWCOORD width, MWCOORD height, BOOL bUnion) { #if UPDATEREGIONS MWRECT rc; if (wp->unmapcount) return; /* convert window relative coords to screen coords*/ rc.left = x + wp->winrect.left; rc.top = y + wp->winrect.top; rc.right = rc.left + width; rc.bottom = rc.top + height; if(bUnion) GdUnionRectWithRegion(&rc, wp->update); else GdSubtractRectFromRegion(&rc, wp->update); #endif }
HRGN WINAPI CreateRoundRectRgn( INT left, INT top, INT right, INT bottom, INT ellipse_width, INT ellipse_height ) { MWRGNOBJ * obj; HRGN hrgn; int asq, bsq, d, xd, yd; RECT rect; /* Check if we can do a normal rectangle instead */ if (ellipse_width == 0 || ellipse_height == 0) return CreateRectRgn( left, top, right, bottom ); /* Make the dimensions sensible */ if (left > right) { INT tmp = left; left = right; right = tmp; } if (top > bottom) { INT tmp = top; top = bottom; bottom = tmp; } ellipse_width = MWABS(ellipse_width); ellipse_height = MWABS(ellipse_height); /* Create region */ if (!(hrgn = REGION_CreateRegion())) return 0; obj = (MWRGNOBJ *)hrgn; /*TRACE(region,"(%d,%d-%d,%d %dx%d): ret=%04x\n", left, top, right, bottom, ellipse_width, ellipse_height, hrgn);*/ /* Check parameters */ if (ellipse_width > right-left) ellipse_width = right-left; if (ellipse_height > bottom-top) ellipse_height = bottom-top; /* Ellipse algorithm, based on an article by K. Porter */ /* in DDJ Graphics Programming Column, 8/89 */ asq = ellipse_width * ellipse_width / 4; /* a^2 */ bsq = ellipse_height * ellipse_height / 4; /* b^2 */ if (asq == 0) asq = 1; if (bsq == 0) bsq = 1; d = bsq - asq * ellipse_height / 2 + asq / 4; /* b^2 - a^2b + a^2/4 */ xd = 0; yd = asq * ellipse_height; /* 2a^2b */ rect.left = left + ellipse_width / 2; rect.right = right - ellipse_width / 2; /* Loop to draw first half of quadrant */ while (xd < yd) { if (d > 0) /* if nearest pixel is toward the center */ { /* move toward center */ rect.top = top++; rect.bottom = rect.top + 1; GdUnionRectWithRegion( &rect, obj->rgn ); rect.top = --bottom; rect.bottom = rect.top + 1; GdUnionRectWithRegion( &rect, obj->rgn ); yd -= 2*asq; d -= yd; } rect.left--; /* next horiz point */ rect.right++; xd += 2*bsq; d += bsq + xd; } /* Loop to draw second half of quadrant */ d += (3 * (asq-bsq) / 2 - (xd+yd)) / 2; while (yd >= 0) { /* next vertical point */ rect.top = top++; rect.bottom = rect.top + 1; GdUnionRectWithRegion( &rect, obj->rgn ); rect.top = --bottom; rect.bottom = rect.top + 1; GdUnionRectWithRegion( &rect, obj->rgn ); if (d < 0) /* if nearest pixel is outside ellipse */ { rect.left--; /* move away from center */ rect.right++; xd += 2*bsq; d += xd; } yd -= 2*asq; d += asq - yd; } /* Add the inside rectangle */ if (top <= bottom) { rect.top = top; rect.bottom = bottom; GdUnionRectWithRegion( &rect, obj->rgn ); } obj->rgn->type = SIMPLEREGION; /* FIXME? */ return hrgn; }
/** * Set a clip region for future drawing actions. * Each pixel will be drawn only if lies in one or more of the contained * clip rectangles. All clip rectangles are modified * if necessary to lie within the device area. Call only after device * has been initialized. * * @param psd Drawing surface. * @param reg New clipping region. */ void GdSetClipRegion(PSD psd, MWCLIPREGION *reg) { if(clipregion) GdDestroyRegion(clipregion); if(!reg) reg = GdAllocRegion(); clipregion = reg; #if 0 MWRECT rc; /* Copy the clip table to our own static array, modifying each * rectangle as necesary to fit within the device area. If the clip * rectangle lies entirely outside of the device area, then skip it. */ while (count-- > 0) { MWCLIPRECT cr; MWCLIPRECT *rp = &cr; *rp = *table++; if (rp->x < 0) { rp->width += rp->x; rp->x = 0; } if (rp->y < 0) { rp->height += rp->y; rp->y = 0; } if ((rp->x >= psd->xvirtres) || (rp->width <= 0) || (rp->y >= psd->yvirtres) || (rp->height <= 0)) continue; if (rp->x + rp->width > psd->xvirtres) rp->width = psd->xvirtres - rp->x; if (rp->y + rp->height > psd->yvirtres) rp->height = psd->yvirtres - rp->y; rc.left = rp->x; rc.top = rp->y; rc.right = rp->x+rp->width; rc.bottom = rp->y+rp->height; GdUnionRectWithRegion(&rc, clipregion); } #endif /* If there were no surviving clip rectangles, then set the clip * cache to prevent all drawing. */ if (clipregion->numRects == 0) { clipminx = MIN_MWCOORD; clipminy = MIN_MWCOORD; clipmaxx = MAX_MWCOORD; clipmaxy = MAX_MWCOORD; clipresult = FALSE; return; } /* There was at least one valid clip rectangle. Default the clip * cache to be the first clip rectangle. */ clipminx = clipregion->rects[0].left; clipminy = clipregion->rects[0].top; clipmaxx = clipregion->rects[0].right - 1; clipmaxy = clipregion->rects[0].bottom - 1; clipresult = TRUE; }