From 5eea9c2eda761787b5b87d561db6e76761c05d51 Mon Sep 17 00:00:00 2001 From: "toshok%hungry.com" Date: Thu, 15 Apr 1999 08:04:37 +0000 Subject: [PATCH] region code for xlib gfx. git-svn-id: svn://10.0.0.236/trunk@27562 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/gfx/src/xlib/nsRegionXlib.cpp | 198 ++++++++++++++++++++++++-- mozilla/gfx/src/xlib/nsRegionXlib.h | 13 ++ mozilla/gfx/src/xlib/xregion.h | 177 +++++++++++++++++++++++ 3 files changed, 374 insertions(+), 14 deletions(-) create mode 100644 mozilla/gfx/src/xlib/xregion.h diff --git a/mozilla/gfx/src/xlib/nsRegionXlib.cpp b/mozilla/gfx/src/xlib/nsRegionXlib.cpp index e70526992bd..1b0ddbe5ca6 100644 --- a/mozilla/gfx/src/xlib/nsRegionXlib.cpp +++ b/mozilla/gfx/src/xlib/nsRegionXlib.cpp @@ -16,13 +16,26 @@ * Reserved. */ +#include "prmem.h" #include "nsRegionXlib.h" +#include "xregion.h" static NS_DEFINE_IID(kRegionIID, NS_IREGION_IID); nsRegionXlib::nsRegionXlib() { NS_INIT_REFCNT(); + + mRegion = nsnull; + mRegionType = eRegionComplexity_empty; +} + +nsRegionXlib::~nsRegionXlib() +{ + if (mRegion) + XDestroyRegion(mRegion); + + mRegion = NULL; } NS_IMPL_QUERY_INTERFACE(nsRegionXlib, kRegionIID) @@ -32,109 +45,266 @@ NS_IMPL_RELEASE(nsRegionXlib) nsresult nsRegionXlib::Init() { - return 0; + NS_ADDREF_THIS(); + + mRegion = XCreateRegion(); + mRegionType = eRegionComplexity_empty; + + return NS_OK; } void nsRegionXlib::SetTo(const nsIRegion &aRegion) { - return; + nsRegionXlib * pRegion = (nsRegionXlib *)&aRegion; + + SetRegionEmpty(); + + Region nRegion = XCreateRegion(); + XUnionRegion(mRegion, pRegion->mRegion, nRegion); + XDestroyRegion(mRegion); + mRegion = nRegion; } void nsRegionXlib::SetTo(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) { - return; + SetRegionEmpty(); + + XRectangle r; + + r.x = aX; + r.y = aY; + r.width = aWidth; + r.height = aHeight; + + Region nRegion = XCreateRegion(); + XUnionRectWithRegion(&r, mRegion, nRegion); + XDestroyRegion(mRegion); + mRegion = nRegion; } void nsRegionXlib::Intersect(const nsIRegion &aRegion) { - return; + nsRegionXlib * pRegion = (nsRegionXlib *)&aRegion; + + Region nRegion; + XIntersectRegion(mRegion, pRegion->mRegion, nRegion); + XDestroyRegion(mRegion); + mRegion = nRegion; } void nsRegionXlib::Intersect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) { - return; + Region tRegion = CreateRectRegion(aX, aY, aWidth, aHeight); + + Region nRegion; + + XIntersectRegion(mRegion, tRegion, nRegion); + XDestroyRegion(tRegion); + XDestroyRegion(mRegion); + mRegion = nRegion; } void nsRegionXlib::Union(const nsIRegion &aRegion) { - return; + nsRegionXlib * pRegion = (nsRegionXlib *)&aRegion; + + Region nRegion; + XUnionRegion(mRegion, pRegion->mRegion, nRegion); + XDestroyRegion(mRegion); + mRegion = nRegion; } void nsRegionXlib::Union(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) { - return; + Region tRegion = CreateRectRegion(aX, aY, aWidth, aHeight); + + Region nRegion; + XUnionRegion(mRegion, tRegion, nRegion); + XDestroyRegion(mRegion); + XDestroyRegion(tRegion); + mRegion = nRegion; } void nsRegionXlib::Subtract(const nsIRegion &aRegion) { - return; + nsRegionXlib * pRegion = (nsRegionXlib *)&aRegion; + + Region nRegion; + XSubtractRegion(mRegion, pRegion->mRegion, nRegion); + XDestroyRegion(mRegion); + mRegion = nRegion; } void nsRegionXlib::Subtract(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) { - return; + Region tRegion = CreateRectRegion(aX, aY, aWidth, aHeight); + + Region nRegion; + XSubtractRegion(mRegion, tRegion, nRegion); + XDestroyRegion(mRegion); + XDestroyRegion(tRegion); + mRegion = nRegion; } PRBool nsRegionXlib::IsEmpty(void) { - return PR_FALSE; + return XEmptyRegion(mRegion); } PRBool nsRegionXlib::IsEqual(const nsIRegion &aRegion) { - return PR_FALSE; + nsRegionXlib *pRegion = (nsRegionXlib *)&aRegion; + + return XEqualRegion(mRegion, pRegion->mRegion); } void nsRegionXlib::GetBoundingBox(PRInt32 *aX, PRInt32 *aY, PRInt32 *aWidth, PRInt32 *aHeight) { - return; + XRectangle r; + + XClipBox(mRegion, &r); + + *aX = r.x; + *aY = r.y; + *aWidth = r.width; + *aHeight = r.height; } void nsRegionXlib::Offset(PRInt32 aXOffset, PRInt32 aYOffset) { - return; + XOffsetRegion(mRegion, aXOffset, aYOffset); } PRBool nsRegionXlib::ContainsRect(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight) { - return PR_FALSE; + return XRectInRegion(mRegion, aX, aY, aWidth, aHeight); } NS_IMETHODIMP nsRegionXlib::GetRects(nsRegionRectSet **aRects) { + nsRegionRectSet *rects; + int nbox; + BOX *pbox; + nsRegionRect *rect; + + NS_ASSERTION(!(nsnull == aRects), "bad ptr"); + + //code lifted from old xfe. MMP + + pbox = mRegion->rects; + nbox = mRegion->numRects; + + rects = *aRects; + + if ((nsnull == rects) || (rects->mRectsLen < (PRUint32)nbox)) + { + void *buf = PR_Realloc(rects, sizeof(nsRegionRectSet) + (sizeof(nsRegionRect +) * (nbox - 1))); + + if (nsnull == buf) + { + if (nsnull != rects) + rects->mNumRects = 0; + + return NS_OK; + } + + rects = (nsRegionRectSet *)buf; + rects->mRectsLen = nbox; + } + + rects->mNumRects = nbox; + rects->mArea = 0; + rect = &rects->mRects[0]; + + while (nbox--) + { + rect->x = pbox->x1; + rect->width = (pbox->x2 - pbox->x1); + rect->y = pbox->y1; + rect->height = (pbox->y2 - pbox->y1); + + rects->mArea += rect->width * rect->height; + + pbox++; + rect++; + } + + *aRects = rects; + return NS_OK; } NS_IMETHODIMP nsRegionXlib::FreeRects(nsRegionRectSet *aRects) { + if (nsnull != aRects) + PR_Free((void *)aRects); + return NS_OK; } NS_IMETHODIMP nsRegionXlib::GetNativeRegion(void *&aRegion) const { + aRegion = (void *)mRegion; return NS_OK; } NS_IMETHODIMP nsRegionXlib::GetRegionComplexity(nsRegionComplexity &aComplexity) const { + // cast to avoid const-ness problems on some compilers + if (((nsRegionXlib*)this)->IsEmpty()) + aComplexity = eRegionComplexity_empty; + else + aComplexity = eRegionComplexity_rect; + return NS_OK; } + +void nsRegionXlib::SetRegionEmpty() +{ + if (!IsEmpty()) { + XDestroyRegion(mRegion); + mRegion = XCreateRegion(); + } +} + +Region +nsRegionXlib::CreateRectRegion(PRInt32 aX, + PRInt32 aY, + PRInt32 aWidth, + PRInt32 aHeight) +{ + Region tRegion = XCreateRegion(); + XRectangle r; + + r.x = aX; + r.y = aY; + r.width = aWidth; + r.height = aHeight; + + Region rRegion; + XUnionRectWithRegion(&r, tRegion, rRegion); + XDestroyRegion(tRegion); + + return (rRegion); +} + diff --git a/mozilla/gfx/src/xlib/nsRegionXlib.h b/mozilla/gfx/src/xlib/nsRegionXlib.h index 4bd17a16551..dbb1ff37a07 100644 --- a/mozilla/gfx/src/xlib/nsRegionXlib.h +++ b/mozilla/gfx/src/xlib/nsRegionXlib.h @@ -21,10 +21,15 @@ #include "nsIRegion.h" +#include +#include +#include + class nsRegionXlib : public nsIRegion { public: nsRegionXlib(); + virtual ~nsRegionXlib(); NS_DECL_ISUPPORTS @@ -48,6 +53,14 @@ class nsRegionXlib : public nsIRegion NS_IMETHOD GetNativeRegion(void *&aRegion) const; NS_IMETHOD GetRegionComplexity(nsRegionComplexity &aComplexity) const; +private: + Region mRegion; + nsRegionComplexity mRegionType; + + void SetRegionEmpty(); + Region CreateRectRegion(PRInt32 aX, PRInt32 aY, + PRInt32 aWidth, PRInt32 aHeight); + }; #endif diff --git a/mozilla/gfx/src/xlib/xregion.h b/mozilla/gfx/src/xlib/xregion.h new file mode 100644 index 00000000000..1d6207f9060 --- /dev/null +++ b/mozilla/gfx/src/xlib/xregion.h @@ -0,0 +1,177 @@ +/* $XConsortium: region.h,v 11.13 91/09/10 08:21:49 rws Exp $ */ +/************************************************************************ +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Digital or MIT not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +************************************************************************/ + +#ifndef _XREGION_H +#define _XREGION_H + +typedef struct { + short x1, x2, y1, y2; +} Box, BOX, BoxRec, *BoxPtr; + +typedef struct { + short x, y, width, height; +}RECTANGLE, RectangleRec, *RectanglePtr; + +#ifdef TRUE +#undef TRUE +#endif + +#define TRUE 1 +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef MAXSHORT +#define MAXSHORT 32767 +#endif +#ifndef MINSHORT +#define MINSHORT -MAXSHORT +#endif +#ifndef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + + +/* + * clip region + */ + +typedef struct _XRegion { + long size; + long numRects; + BOX *rects; + BOX extents; +} REGION; + +/* Xutil.h contains the declaration: + * typedef struct _XRegion *Region; + */ + +/* 1 if two BOXs overlap. + * 0 if two BOXs do not overlap. + * Remember, x2 and y2 are not in the region + */ +#define EXTENTCHECK(r1, r2) \ + ((r1)->x2 > (r2)->x1 && \ + (r1)->x1 < (r2)->x2 && \ + (r1)->y2 > (r2)->y1 && \ + (r1)->y1 < (r2)->y2) + +/* + * update region extents + */ +#define EXTENTS(r,idRect){\ + if((r)->x1 < (idRect)->extents.x1)\ + (idRect)->extents.x1 = (r)->x1;\ + if((r)->y1 < (idRect)->extents.y1)\ + (idRect)->extents.y1 = (r)->y1;\ + if((r)->x2 > (idRect)->extents.x2)\ + (idRect)->extents.x2 = (r)->x2;\ + if((r)->y2 > (idRect)->extents.y2)\ + (idRect)->extents.y2 = (r)->y2;\ + } + +/* + * Check to see if there is enough memory in the present region. + */ +#define MEMCHECK(reg, rect, firstrect){\ + if ((reg)->numRects >= ((reg)->size - 1)){\ + (firstrect) = (BOX *) Xrealloc \ + ((char *)(firstrect), (unsigned) (2 * (sizeof(BOX)) * ((reg)->size)));\ + if ((firstrect) == 0)\ + return(0);\ + (reg)->size *= 2;\ + (rect) = &(firstrect)[(reg)->numRects];\ + }\ + } + +/* this routine checks to see if the previous rectangle is the same + * or subsumes the new rectangle to add. + */ + +#define CHECK_PREVIOUS(Reg, R, Rx1, Ry1, Rx2, Ry2)\ + (!(((Reg)->numRects > 0)&&\ + ((R-1)->y1 == (Ry1)) &&\ + ((R-1)->y2 == (Ry2)) &&\ + ((R-1)->x1 <= (Rx1)) &&\ + ((R-1)->x2 >= (Rx2)))) + +/* add a rectangle to the given Region */ +#define ADDRECT(reg, r, rx1, ry1, rx2, ry2){\ + if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&\ + CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ + (r)->x1 = (rx1);\ + (r)->y1 = (ry1);\ + (r)->x2 = (rx2);\ + (r)->y2 = (ry2);\ + EXTENTS((r), (reg));\ + (reg)->numRects++;\ + (r)++;\ + }\ + } + + + +/* add a rectangle to the given Region */ +#define ADDRECTNOX(reg, r, rx1, ry1, rx2, ry2){\ + if ((rx1 < rx2) && (ry1 < ry2) &&\ + CHECK_PREVIOUS((reg), (r), (rx1), (ry1), (rx2), (ry2))){\ + (r)->x1 = (rx1);\ + (r)->y1 = (ry1);\ + (r)->x2 = (rx2);\ + (r)->y2 = (ry2);\ + (reg)->numRects++;\ + (r)++;\ + }\ + } + +#define EMPTY_REGION(pReg) pReg->numRects = 0 + +#define REGION_NOT_EMPTY(pReg) pReg->numRects + +#define INBOX(r, x, y) \ + ( ( ((r).x2 > x)) && \ + ( ((r).x1 <= x)) && \ + ( ((r).y2 > y)) && \ + ( ((r).y1 <= y)) ) + +/* + * number of points to buffer before sending them off + * to scanlines() : Must be an even number + */ +#define NUMPTSTOBUFFER 200 + +/* + * used to allocate buffers for points and link + * the buffers together + */ +typedef struct _POINTBLOCK { + XPoint pts[NUMPTSTOBUFFER]; + struct _POINTBLOCK *next; +} POINTBLOCK; + +#endif