diff options
Diffstat (limited to 'mi/miregion.c')
-rw-r--r-- | mi/miregion.c | 323 |
1 files changed, 227 insertions, 96 deletions
diff --git a/mi/miregion.c b/mi/miregion.c index f9c25b09d..9a40e7757 100644 --- a/mi/miregion.c +++ b/mi/miregion.c @@ -1,3 +1,4 @@ +/* $XFree86: xc/programs/Xserver/mi/miregion.c,v 1.8 2001/12/14 20:00:26 dawes Exp $ */ /*********************************************************** Copyright 1987, 1988, 1989, 1998 The Open Group @@ -47,11 +48,34 @@ SOFTWARE. ******************************************************************/ /* $Xorg: miregion.c,v 1.4 2001/02/09 02:05:21 xorgcvs Exp $ */ -#include <stdio.h> +/* The panoramix components contained the following notice */ +/**************************************************************** +* * +* Copyright (c) Digital Equipment Corporation, 1991, 1997 * +* * +* All Rights Reserved. Unpublished rights reserved under * +* the copyright laws of the United States. * +* * +* The software contained on this media is proprietary to * +* and embodies the confidential technology of Digital * +* Equipment Corporation. Possession, use, duplication or * +* dissemination of the software and media is authorized only * +* pursuant to a valid written license from Digital Equipment * +* Corporation. * +* * +* RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure * +* by the U.S. Government is subject to restrictions as set * +* forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, * +* or in FAR 52.227-19, as applicable. * +* * +*****************************************************************/ + #include "miscstruct.h" #include "regionstr.h" #include "Xprotostr.h" #include "gc.h" +#include "mi.h" +#include "mispans.h" #if defined (__GNUC__) && !defined (NO_INLINES) #define INLINE __inline @@ -59,12 +83,7 @@ SOFTWARE. #define INLINE #endif -/* - * hack until callers of these functions can deal with out-of-memory - */ - -extern Bool Must_have_memory; - +#undef assert #ifdef DEBUG #define assert(expr) {if (!(expr)) \ FatalError("Assertion failed file %s, line %d: expr\n", \ @@ -146,9 +165,13 @@ extern Bool Must_have_memory; #define xallocData(n) (RegDataPtr)xalloc(REGION_SZOF(n)) #define xfreeData(reg) if ((reg)->data && (reg)->data->size) xfree((reg)->data) +#define RECTALLOC_BAIL(pReg,n,bail) \ +if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ + if (!miRectAlloc(pReg, n)) { goto bail; } + #define RECTALLOC(pReg,n) \ if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ - miRectAlloc(pReg, n) + if (!miRectAlloc(pReg, n)) { return FALSE; } #define ADDRECT(pNextRect,nx1,ny1,nx2,ny2) \ { \ @@ -163,7 +186,8 @@ if (!(pReg)->data || (((pReg)->data->numRects + (n)) > (pReg)->data->size)) \ { \ if (!(pReg)->data || ((pReg)->data->numRects == (pReg)->data->size))\ { \ - miRectAlloc(pReg, 1); \ + if (!miRectAlloc(pReg, 1)) \ + return FALSE; \ pNextRect = REGION_TOP(pReg); \ } \ ADDRECT(pNextRect,nx1,ny1,nx2,ny2); \ @@ -188,6 +212,9 @@ if (((numRects) < ((reg)->data->size >> 1)) && ((reg)->data->size > 50)) \ BoxRec miEmptyBox = {0, 0, 0, 0}; RegDataRec miEmptyData = {0, 0}; +RegDataRec miBrokenData = {0, 0}; +RegionRec miBrokenRegion = { { 0, 0, 0, 0 }, &miBrokenData }; + #ifdef DEBUG int miPrintRegion(rgn) @@ -298,9 +325,9 @@ miRegionCreate(rect, size) { register RegionPtr pReg; - Must_have_memory = TRUE; /* XXX */ pReg = (RegionPtr)xalloc(sizeof(RegionRec)); - Must_have_memory = FALSE; /* XXX */ + if (!pReg) + return &miBrokenRegion; if (rect) { pReg->extents = *rect; @@ -355,7 +382,8 @@ miRegionDestroy(pReg) { good(pReg); xfreeData(pReg); - xfree(pReg); + if (pReg != &miBrokenRegion) + xfree(pReg); } void @@ -367,21 +395,36 @@ miRegionUninit(pReg) } Bool -miRectAlloc(pRgn, n) - register RegionPtr pRgn; - int n; +miRegionBreak (pReg) + RegionPtr pReg; { - Must_have_memory = TRUE; /* XXX */ + xfreeData (pReg); + pReg->extents = miEmptyBox; + pReg->data = &miBrokenData; + return FALSE; +} + +Bool +miRectAlloc( + register RegionPtr pRgn, + int n) +{ + RegDataPtr data; + if (!pRgn->data) { n++; pRgn->data = xallocData(n); + if (!pRgn->data) + return miRegionBreak (pRgn); pRgn->data->numRects = 1; *REGION_BOXPTR(pRgn) = pRgn->extents; } else if (!pRgn->data->size) { pRgn->data = xallocData(n); + if (!pRgn->data) + return miRegionBreak (pRgn); pRgn->data->numRects = 0; } else @@ -393,9 +436,11 @@ miRectAlloc(pRgn, n) n = 250; } n += pRgn->data->numRects; - pRgn->data = (RegDataPtr)xrealloc(pRgn->data, REGION_SZOF(n)); + data = (RegDataPtr)xrealloc(pRgn->data, REGION_SZOF(n)); + if (!data) + return miRegionBreak (pRgn); + pRgn->data = data; } - Must_have_memory = FALSE; /* XXX */ pRgn->data->size = n; return TRUE; } @@ -419,9 +464,9 @@ miRegionCopy(dst, src) if (!dst->data || (dst->data->size < src->data->numRects)) { xfreeData(dst); - Must_have_memory = TRUE; /* XXX */ dst->data = xallocData(src->data->numRects); - Must_have_memory = FALSE; /* XXX */ + if (!dst->data) + return miRegionBreak (dst); dst->data->size = src->data->numRects; } dst->data->numRects = src->data->numRects; @@ -454,10 +499,10 @@ miRegionCopy(dst, src) *----------------------------------------------------------------------- */ INLINE static int -miCoalesce (pReg, prevStart, curStart) - register RegionPtr pReg; /* Region to coalesce */ - int prevStart; /* Index of start of previous band */ - int curStart; /* Index of start of current band */ +miCoalesce ( + register RegionPtr pReg, /* Region to coalesce */ + int prevStart, /* Index of start of previous band */ + int curStart) /* Index of start of current band */ { register BoxPtr pPrevBox; /* Current box in previous band */ register BoxPtr pCurBox; /* Current box in current band */ @@ -538,12 +583,12 @@ miCoalesce (pReg, prevStart, curStart) */ INLINE static Bool -miAppendNonO (pReg, r, rEnd, y1, y2) - register RegionPtr pReg; - register BoxPtr r; - BoxPtr rEnd; - register int y1; - register int y2; +miAppendNonO ( + register RegionPtr pReg, + register BoxPtr r, + BoxPtr rEnd, + register int y1, + register int y2) { register BoxPtr pNextRect; register int newRects; @@ -578,7 +623,7 @@ miAppendNonO (pReg, r, rEnd, y1, y2) #define AppendRegions(newReg, r, rEnd) \ { \ int newRects; \ - if (newRects = rEnd - r) { \ + if ((newRects = rEnd - r)) { \ RECTALLOC(newReg, newRects); \ memmove((char *)REGION_TOP(newReg),(char *)r, \ newRects * sizeof(BoxRec)); \ @@ -614,18 +659,29 @@ miAppendNonO (pReg, r, rEnd, y1, y2) * *----------------------------------------------------------------------- */ + +typedef Bool (*OverlapProcPtr)( + RegionPtr pReg, + BoxPtr r1, + BoxPtr r1End, + BoxPtr r2, + BoxPtr r2End, + short y1, + short y2, + Bool *pOverlap); + static Bool -miRegionOp(newReg, reg1, reg2, overlapFunc, appendNon1, appendNon2, pOverlap) - RegionPtr newReg; /* Place to store result */ - RegionPtr reg1; /* First region in operation */ - RegionPtr reg2; /* 2d region in operation */ - Bool (*overlapFunc)(); /* Function to call for over- +miRegionOp( + RegionPtr newReg, /* Place to store result */ + RegionPtr reg1, /* First region in operation */ + RegionPtr reg2, /* 2d region in operation */ + OverlapProcPtr overlapFunc, /* Function to call for over- * lapping bands */ - Bool appendNon1; /* Append non-overlapping bands */ + Bool appendNon1, /* Append non-overlapping bands */ /* in region 1 ? */ - Bool appendNon2; /* Append non-overlapping bands */ + Bool appendNon2, /* Append non-overlapping bands */ /* in region 2 ? */ - Bool *pOverlap; + Bool *pOverlap) { register BoxPtr r1; /* Pointer into first region */ register BoxPtr r2; /* Pointer into 2d region */ @@ -648,6 +704,12 @@ miRegionOp(newReg, reg1, reg2, overlapFunc, appendNon1, appendNon2, pOverlap) int numRects; /* + * Break any region computed from a broken region + */ + if (REGION_NAR (reg1) || REGION_NAR(reg2)) + return miRegionBreak (newReg); + + /* * Initialization: * set r1, r2, r1End and r2End appropriately, save the rectangles * of the destination region until the end in case it's one of @@ -680,7 +742,8 @@ miRegionOp(newReg, reg1, reg2, overlapFunc, appendNon1, appendNon2, pOverlap) else if (newReg->data->size) newReg->data->numRects = 0; if (newSize > newReg->data->size) - miRectAlloc(newReg, newSize); + if (!miRectAlloc(newReg, newSize)) + return FALSE; /* * Initialize ybot. @@ -902,15 +965,15 @@ miSetExtents (pReg) */ /*ARGSUSED*/ static Bool -miIntersectO (pReg, r1, r1End, r2, r2End, y1, y2, pOverlap) - register RegionPtr pReg; - register BoxPtr r1; - BoxPtr r1End; - register BoxPtr r2; - BoxPtr r2End; - short y1; - short y2; - Bool *pOverlap; +miIntersectO ( + register RegionPtr pReg, + register BoxPtr r1, + BoxPtr r1End, + register BoxPtr r2, + BoxPtr r2End, + short y1, + short y2, + Bool *pOverlap) { register int x1; register int x2; @@ -966,7 +1029,13 @@ miIntersect(newReg, reg1, reg2) xfreeData(newReg); newReg->extents.x2 = newReg->extents.x1; newReg->extents.y2 = newReg->extents.y1; - newReg->data = &miEmptyData; + if (REGION_NAR(reg1) || REGION_NAR(reg2)) + { + newReg->data = &miBrokenData; + return FALSE; + } + else + newReg->data = &miEmptyData; } else if (!reg1->data && !reg2->data) { @@ -1039,15 +1108,15 @@ miIntersect(newReg, reg1, reg2) *----------------------------------------------------------------------- */ static Bool -miUnionO (pReg, r1, r1End, r2, r2End, y1, y2, pOverlap) - register RegionPtr pReg; - register BoxPtr r1; - BoxPtr r1End; - register BoxPtr r2; - BoxPtr r2End; - short y1; - short y2; - Bool *pOverlap; +miUnionO ( + register RegionPtr pReg, + register BoxPtr r1, + BoxPtr r1End, + register BoxPtr r2, + BoxPtr r2End, + short y1, + short y2, + Bool *pOverlap) { register BoxPtr pNextRect; register int x1; /* left and right side of current union */ @@ -1125,6 +1194,8 @@ miUnion(newReg, reg1, reg2) */ if (REGION_NIL(reg1)) { + if (REGION_NAR(reg1)) + return miRegionBreak (newReg); if (newReg != reg2) return miRegionCopy(newReg, reg2); return TRUE; @@ -1135,6 +1206,8 @@ miUnion(newReg, reg1, reg2) */ if (REGION_NIL(reg2)) { + if (REGION_NAR(reg2)) + return miRegionBreak (newReg); if (newReg != reg1) return miRegionCopy(newReg, reg1); return TRUE; @@ -1202,6 +1275,9 @@ miRegionAppend(dstrgn, rgn) BoxPtr new, old; Bool prepend; + if (REGION_NAR(rgn)) + return miRegionBreak (dstrgn); + if (!rgn->data && (dstrgn->data == &miEmptyData)) { dstrgn->extents = rgn->extents; @@ -1286,9 +1362,9 @@ miRegionAppend(dstrgn, rgn) } static void -QuickSortRects(rects, numRects) - register BoxRec rects[]; - register int numRects; +QuickSortRects( + register BoxRec rects[], + register int numRects) { register int y1; register int x1; @@ -1399,6 +1475,7 @@ miRegionValidate(badreg, pOverlap) register BoxPtr box; /* Current box in rects */ register BoxPtr riBox; /* Last box in ri[j].reg */ register RegionPtr hreg; /* ri[j_half].reg */ + Bool ret = TRUE; *pOverlap = FALSE; if (!badreg->data) @@ -1409,6 +1486,8 @@ miRegionValidate(badreg, pOverlap) numRects = badreg->data->numRects; if (!numRects) { + if (REGION_NAR(badreg)) + return FALSE; good(badreg); return TRUE; } @@ -1434,9 +1513,9 @@ miRegionValidate(badreg, pOverlap) /* Set up the first region to be the first rectangle in badreg */ /* Note that step 2 code will never overflow the ri[0].reg rects array */ - Must_have_memory = TRUE; /* XXX */ ri = (RegionInfo *) xalloc(4 * sizeof(RegionInfo)); - Must_have_memory = FALSE; /* XXX */ + if (!ri) + return miRegionBreak (badreg); sizeRI = 4; numRI = 1; ri[0].prevBand = 0; @@ -1472,7 +1551,7 @@ miRegionValidate(badreg, pOverlap) } else { - RECTALLOC(reg, 1); + RECTALLOC_BAIL(reg, 1, bail); *REGION_TOP(reg) = *box; reg->data->numRects++; } @@ -1485,7 +1564,7 @@ miRegionValidate(badreg, pOverlap) if (reg->extents.x1 > box->x1) reg->extents.x1 = box->x1; Coalesce(reg, rit->prevBand, rit->curBand); rit->curBand = reg->data->numRects; - RECTALLOC(reg, 1); + RECTALLOC_BAIL(reg, 1, bail); *REGION_TOP(reg) = *box; reg->data->numRects++; goto NextRect; @@ -1498,9 +1577,10 @@ miRegionValidate(badreg, pOverlap) { /* Oops, allocate space for new region information */ sizeRI <<= 1; - Must_have_memory = TRUE; /* XXX */ - ri = (RegionInfo *) xrealloc(ri, sizeRI * sizeof(RegionInfo)); - Must_have_memory = FALSE; /* XXX */ + rit = (RegionInfo *) xrealloc(ri, sizeRI * sizeof(RegionInfo)); + if (!rit) + goto bail; + ri = rit; rit = &ri[numRI]; } numRI++; @@ -1508,7 +1588,8 @@ miRegionValidate(badreg, pOverlap) rit->curBand = 0; rit->reg.extents = *box; rit->reg.data = (RegDataPtr)NULL; - miRectAlloc(&rit->reg, (i+numRI) / numRI); /* MUST force allocation */ + if (!miRectAlloc(&rit->reg, (i+numRI) / numRI)) /* MUST force allocation */ + goto bail; NextRect: ; } /* for i */ @@ -1537,7 +1618,8 @@ NextRect: ; { reg = &ri[j].reg; hreg = &ri[j+half].reg; - miRegionOp(reg, reg, hreg, miUnionO, TRUE, TRUE, pOverlap); + if (!miRegionOp(reg, reg, hreg, miUnionO, TRUE, TRUE, pOverlap)) + ret = FALSE; if (hreg->extents.x1 < reg->extents.x1) reg->extents.x1 = hreg->extents.x1; if (hreg->extents.y1 < reg->extents.y1) @@ -1553,7 +1635,12 @@ NextRect: ; *badreg = ri[0].reg; xfree(ri); good(badreg); - return TRUE; + return ret; +bail: + for (i = 0; i < numRI; i++) + xfreeData(&ri[i].reg); + xfree (ri); + return miRegionBreak (badreg); } RegionPtr @@ -1569,6 +1656,8 @@ miRectsToRegion(nrects, prect, ctype) int x1, y1, x2, y2; pRgn = miRegionCreate(NullBox, 0); + if (REGION_NAR (pRgn)) + return pRgn; if (!nrects) return pRgn; if (nrects == 1) @@ -1589,10 +1678,13 @@ miRectsToRegion(nrects, prect, ctype) } return pRgn; } - Must_have_memory = TRUE; /* XXX */ pData = xallocData(nrects); + if (!pData) + { + miRegionBreak (pRgn); + return pRgn; + } pBox = (BoxPtr) (pData + 1); - Must_have_memory = FALSE; /* XXX */ for (i = nrects; --i >= 0; prect++) { x1 = prect->x; @@ -1653,15 +1745,15 @@ miRectsToRegion(nrects, prect, ctype) */ /*ARGSUSED*/ static Bool -miSubtractO (pReg, r1, r1End, r2, r2End, y1, y2, pOverlap) - register RegionPtr pReg; - register BoxPtr r1; - BoxPtr r1End; - register BoxPtr r2; - BoxPtr r2End; - register int y1; - int y2; - Bool *pOverlap; +miSubtractO ( + register RegionPtr pReg, + register BoxPtr r1, + BoxPtr r1End, + register BoxPtr r2, + BoxPtr r2End, + register short y1, + short y2, + Bool *pOverlap) { register BoxPtr pNextRect; register int x1; @@ -1791,6 +1883,8 @@ miSubtract(regD, regM, regS) if (REGION_NIL(regM) || REGION_NIL(regS) || !EXTENTCHECK(®M->extents, ®S->extents)) { + if (REGION_NAR (regS)) + return miRegionBreak (regD); return miRegionCopy(regD, regM); } else if (regM == regS) @@ -1854,6 +1948,8 @@ miInverse(newReg, reg1, invRect) /* check for trivial rejects */ if (REGION_NIL(reg1) || !EXTENTCHECK(invRect, ®1->extents)) { + if (REGION_NAR(reg1)) + return miRegionBreak (newReg); newReg->extents = *invRect; xfreeData(newReg); newReg->data = (RegDataPtr)NULL; @@ -2078,6 +2174,35 @@ miTranslateRegion(pReg, x, y) } } +Bool +miRegionDataCopy( + register RegionPtr dst, + register RegionPtr src) +{ + good(dst); + good(src); + if (dst->data) + return TRUE; + if (dst == src) + return TRUE; + if (!src->data || !src->data->size) + { + xfreeData(dst); + dst->data = (RegDataPtr)NULL; + return TRUE; + } + if (!dst->data || (dst->data->size < src->data->numRects)) + { + xfreeData(dst); + dst->data = xallocData(src->data->numRects); + if (!dst->data) + return miRegionBreak (dst); + } + dst->data->size = src->data->size; + dst->data->numRects = src->data->numRects; + return TRUE; +} + void miRegionReset(pReg, pBox) RegionPtr pReg; @@ -2133,6 +2258,12 @@ miRegionNotEmpty(pReg) return(!REGION_NIL(pReg)); } +Bool +miRegionBroken(RegionPtr pReg) +{ + good(pReg); + return (REGION_NAR(pReg)); +} void miRegionEmpty(pReg) @@ -2167,10 +2298,10 @@ miRegionExtents(pReg) so forget it. */ -static void QuickSortSpans(spans, widths, numSpans) - register DDXPointRec spans[]; - register int widths[]; - register int numSpans; +static void QuickSortSpans( + register DDXPointRec spans[], + register int widths[], + register int numSpans) { register int y; register int i, j, m; @@ -2272,14 +2403,14 @@ static void QuickSortSpans(spans, widths, numSpans) */ int -miClipSpans(prgnDst, ppt, pwidth, nspans, pptNew, pwidthNew, fSorted) - RegionPtr prgnDst; - register DDXPointPtr ppt; - register int *pwidth; - int nspans; - register DDXPointPtr pptNew; - int *pwidthNew; - int fSorted; +miClipSpans( + RegionPtr prgnDst, + register DDXPointPtr ppt, + register int *pwidth, + int nspans, + register DDXPointPtr pptNew, + int *pwidthNew, + int fSorted) { register DDXPointPtr pptLast; int *pwidthNewStart; /* the vengeance of Xerox! */ @@ -2325,7 +2456,7 @@ miClipSpans(prgnDst, ppt, pwidth, nspans, pptNew, pwidthNew, fSorted) } /* end for */ } - else if (numRects = prgnDst->data->numRects) + else if ((numRects = prgnDst->data->numRects)) { /* Have to clip against many boxes */ BoxPtr pboxBandStart, pboxBandEnd; |