New upstream version 3.5.99.27

This commit is contained in:
geos_one
2025-08-08 20:00:36 +02:00
commit bc8d10cc33
4267 changed files with 1757978 additions and 0 deletions

View File

@@ -0,0 +1,194 @@
/**************************************************************************/
/* */
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
/* */
/* nx-X11, NX protocol compression and NX extensions to this software */
/* are copyright of the aforementioned persons and companies. */
/* */
/* Redistribution and use of the present software is allowed according */
/* to terms specified in the file LICENSE which comes in the source */
/* distribution. */
/* */
/* All rights reserved. */
/* */
/* NOTE: This software has received contributions from various other */
/* contributors, only the core maintainers and supporters are listed as */
/* copyright holders. Please contact us, if you feel you should be listed */
/* as copyright holder, as well. */
/* */
/**************************************************************************/
NULL =
#include <Server.tmpl>
#if ! HasCbrt
CBRT_SRC = cbrt.c
CBRT_OBJ = cbrt.o
#endif
#if HasFfs
FFS_DEFINES = -DHAS_FFS
#endif
MIINITEXTSRC = miinitext.c
MIINITEXTOBJ = miinitext.o
SRCS = $(CBRT_SRC) \
mivaltree.c \
mipolyseg.c \
mipolyrect.c \
mipoly.c \
mipolycon.c \
mipolygen.c \
mipolyutil.c \
mifillrct.c \
miwideline.c \
mispans.c \
miarc.c \
mizerarc.c \
mifillarc.c \
miwindow.c \
micursor.c \
mipolytext.c \
mibitblt.c \
mipolypnt.c \
mipushpxl.c \
miglblt.c \
mizerline.c \
mizerclip.c \
mifpolycon.c \
midash.c \
mibstore.c \
$(MIINITEXTSRC) \
mieq.c \
mipointer.c \
misprite.c \
midispcur.c \
miscrinit.c \
migc.c \
micmap.c \
mioverlay.c \
miexpose.c \
$(NULL)
OBJS = $(CBRT_OBJ) \
mivaltree.o \
mipolyseg.o \
mipolyrect.o \
mipoly.o \
mipolycon.o \
mipolygen.o \
mipolyutil.o \
mifillrct.o \
miwideline.o \
mispans.o \
miarc.o \
mizerarc.o \
mifillarc.o \
miwindow.o \
micursor.o \
mipolytext.o \
mibitblt.o \
mipolypnt.o \
mipushpxl.o \
miglblt.o \
mizerline.o \
mizerclip.o \
mifpolycon.o \
midash.o \
mibstore.o \
$(MIINITEXTOBJ) \
mieq.o \
mipointer.o \
misprite.o \
midispcur.o \
miscrinit.o \
migc.o \
micmap.o \
mioverlay.o \
miexpose.o \
$(NULL)
#if defined(XorgVersion)
/*
* Make sure XINPUT, XF86VidTune, etc aren't defined for the miinitext.o
* used by Xnest, Xvfb
*/
#if NXLibraries
NX_DEFINES = -DNXAGENT_SERVER \
$(NULL)
/*
* To build the NX agent we need the XINPUT symbol
* in order to build the XInputExtension, since we
* don't use the XF86 module loader.
*/
EXT_DEFINES = ExtensionDefines \
$(NULL)
#else
EXT_DEFINES = ExtensionDefines \
-UXINPUT \
$(NULL)
#endif
#endif
INCLUDES = -I. \
-I../include \
-I../render \
-I../xfixes \
-I../damageext \
-I../miext/damage \
-I$(XINCLUDESRC) \
-I$(EXTINCSRC) \
-I$(SERVERSRC)/Xext \
`pkg-config --cflags-only-I pixman-1` \
$(NULL)
LINTLIBS = \
../dix/llib-ldix.ln \
../os/llib-los.ln \
$(NULL)
DEFINES = $(FFS_DEFINES) $(NX_DEFINES)
NormalLibraryObjectRule()
NormalLibraryTarget(mi,$(OBJS))
LintLibraryTarget(mi,$(SRCS))
NormalLintTarget($(SRCS))
#ifndef Win32Architecture
NormalLibraryTarget(cbrt,cbrt.o)
#endif
SpecialCObjectRule(miinitext,$(ICONFIGFILES),$(EXT_DEFINES))
SpecialCObjectRule(miscrinit,$(ICONFIGFILES),$(EXT_DEFINES))
#ifdef ItsyCompilerBug
SpecialCObjectRule(mipolycon,$(_NOOP_),-O0)
#endif
#if defined(OpenBSDArchitecture) && defined(Sparc64Architecture)
SpecialCObjectRule(mizerclip,NullParameter,-O0)
#endif
AllTarget($(EXTRAMIINITEXTOBJ))
DependTarget()
InstallDriverSDKNonExecFile(mi.h,$(DRIVERSDKINCLUDEDIR))
InstallDriverSDKNonExecFile(mibstore.h,$(DRIVERSDKINCLUDEDIR))
InstallDriverSDKNonExecFile(micmap.h,$(DRIVERSDKINCLUDEDIR))
InstallDriverSDKNonExecFile(migc.h,$(DRIVERSDKINCLUDEDIR))
InstallDriverSDKNonExecFile(miline.h,$(DRIVERSDKINCLUDEDIR))
InstallDriverSDKNonExecFile(mipointer.h,$(DRIVERSDKINCLUDEDIR))
InstallDriverSDKNonExecFile(mipointrst.h,$(DRIVERSDKINCLUDEDIR))
InstallDriverSDKNonExecFile(mizerarc.h,$(DRIVERSDKINCLUDEDIR))
InstallDriverSDKNonExecFile(micoord.h,$(DRIVERSDKINCLUDEDIR))

View File

@@ -0,0 +1,46 @@
/*
Copyright 1990, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
/* simple cbrt, in case your math library doesn't have a good one */
/*
* Would normally include <math.h> for this, but for the sake of compiler
* warnings, we don't want to get duplicate declarations for cbrt().
*/
double pow(double, double);
double cbrt(double);
double
cbrt(double x)
{
if (x > 0.0)
return pow(x, 1.0/3.0);
else
return -pow(-x, 1.0/3.0);
}

View File

@@ -0,0 +1,629 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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 MI_H
#define MI_H
#include <nx-X11/X.h>
#include "region.h"
#include "validate.h"
#include "window.h"
#include "gc.h"
#include <X11/fonts/font.h>
#include "input.h"
#include "cursor.h"
#define MiBits CARD32
typedef struct _miDash *miDashPtr;
#define EVEN_DASH 0
#define ODD_DASH ~0
/* miarc.c */
extern void miPolyArc(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*narcs*/,
xArc * /*parcs*/
);
/* mibitblt.c */
extern RegionPtr miCopyArea(
DrawablePtr /*pSrcDrawable*/,
DrawablePtr /*pDstDrawable*/,
GCPtr /*pGC*/,
int /*xIn*/,
int /*yIn*/,
int /*widthSrc*/,
int /*heightSrc*/,
int /*xOut*/,
int /*yOut*/
);
extern void miOpqStipDrawable(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
RegionPtr /*prgnSrc*/,
MiBits * /*pbits*/,
int /*srcx*/,
int /*w*/,
int /*h*/,
int /*dstx*/,
int /*dsty*/
);
extern RegionPtr miCopyPlane(
DrawablePtr /*pSrcDrawable*/,
DrawablePtr /*pDstDrawable*/,
GCPtr /*pGC*/,
int /*srcx*/,
int /*srcy*/,
int /*width*/,
int /*height*/,
int /*dstx*/,
int /*dsty*/,
unsigned long /*bitPlane*/
);
extern void miGetImage(
DrawablePtr /*pDraw*/,
int /*sx*/,
int /*sy*/,
int /*w*/,
int /*h*/,
unsigned int /*format*/,
unsigned long /*planeMask*/,
char * /*pdstLine*/
);
extern void miPutImage(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*depth*/,
int /*x*/,
int /*y*/,
int /*w*/,
int /*h*/,
int /*leftPad*/,
int /*format*/,
char * /*pImage*/
);
/* micursor.c */
extern void miRecolorCursor(
ScreenPtr /*pScr*/,
CursorPtr /*pCurs*/,
Bool /*displayed*/
);
/* midash.c */
extern miDashPtr miDashLine(
int /*npt*/,
DDXPointPtr /*ppt*/,
unsigned int /*nDash*/,
unsigned char * /*pDash*/,
unsigned int /*offset*/,
int * /*pnseg*/
);
extern void miStepDash(
int /*dist*/,
int * /*pDashIndex*/,
unsigned char * /*pDash*/,
int /*numInDashList*/,
int * /*pDashOffset*/
);
/* mieq.c */
#ifndef INPUT_H
typedef struct _DeviceRec *DevicePtr;
#endif
extern Bool mieqInit(
DevicePtr /*pKbd*/,
DevicePtr /*pPtr*/
);
extern void mieqEnqueue(
xEventPtr /*e*/
);
extern void mieqSwitchScreen(
ScreenPtr /*pScreen*/,
Bool /*fromDIX*/
);
extern void mieqProcessInputEvents(
void
);
/* miexpose.c */
extern RegionPtr miHandleExposures(
DrawablePtr /*pSrcDrawable*/,
DrawablePtr /*pDstDrawable*/,
GCPtr /*pGC*/,
int /*srcx*/,
int /*srcy*/,
int /*width*/,
int /*height*/,
int /*dstx*/,
int /*dsty*/,
unsigned long /*plane*/
);
extern void miSendGraphicsExpose(
ClientPtr /*client*/,
RegionPtr /*pRgn*/,
XID /*drawable*/,
int /*major*/,
int /*minor*/
);
extern void miSendExposures(
WindowPtr /*pWin*/,
RegionPtr /*pRgn*/,
int /*dx*/,
int /*dy*/
);
extern void miWindowExposures(
WindowPtr /*pWin*/,
RegionPtr /*prgn*/,
RegionPtr /*other_exposed*/
);
extern void miPaintWindow(
WindowPtr /*pWin*/,
RegionPtr /*prgn*/,
int /*what*/
);
extern void miClearDrawable(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/
);
/* mifillrct.c */
extern void miPolyFillRect(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
int /*nrectFill*/,
xRectangle * /*prectInit*/
);
/* miglblt.c */
extern void miPolyGlyphBlt(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
int /*x*/,
int /*y*/,
unsigned int /*nglyph*/,
CharInfoPtr * /*ppci*/,
void * /*pglyphBase*/
);
extern void miImageGlyphBlt(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
int /*x*/,
int /*y*/,
unsigned int /*nglyph*/,
CharInfoPtr * /*ppci*/,
void * /*pglyphBase*/
);
/* mipoly.c */
extern void miFillPolygon(
DrawablePtr /*dst*/,
GCPtr /*pgc*/,
int /*shape*/,
int /*mode*/,
int /*count*/,
DDXPointPtr /*pPts*/
);
/* mipolycon.c */
extern Bool miFillConvexPoly(
DrawablePtr /*dst*/,
GCPtr /*pgc*/,
int /*count*/,
DDXPointPtr /*ptsIn*/
);
/* mipolygen.c */
extern Bool miFillGeneralPoly(
DrawablePtr /*dst*/,
GCPtr /*pgc*/,
int /*count*/,
DDXPointPtr /*ptsIn*/
);
/* mipolypnt.c */
extern void miPolyPoint(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
int /*mode*/,
int /*npt*/,
xPoint * /*pptInit*/
);
/* mipolyrect.c */
extern void miPolyRectangle(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*nrects*/,
xRectangle * /*pRects*/
);
/* mipolyseg.c */
extern void miPolySegment(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*nseg*/,
xSegment * /*pSegs*/
);
/* mipolytext.c */
extern int miPolyText(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*x*/,
int /*y*/,
int /*count*/,
char * /*chars*/,
FontEncoding /*fontEncoding*/
);
extern int miPolyText8(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*x*/,
int /*y*/,
int /*count*/,
char * /*chars*/
);
extern int miPolyText16(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*x*/,
int /*y*/,
int /*count*/,
unsigned short * /*chars*/
);
extern int miImageText(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*x*/,
int /*y*/,
int /*count*/,
char * /*chars*/,
FontEncoding /*fontEncoding*/
);
extern void miImageText8(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*x*/,
int /*y*/,
int /*count*/,
char * /*chars*/
);
extern void miImageText16(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*x*/,
int /*y*/,
int /*count*/,
unsigned short * /*chars*/
);
/* mipushpxl.c */
extern void miPushPixels(
GCPtr /*pGC*/,
PixmapPtr /*pBitMap*/,
DrawablePtr /*pDrawable*/,
int /*dx*/,
int /*dy*/,
int /*xOrg*/,
int /*yOrg*/
);
/* see also region.h */
extern Bool RegionRectAlloc(
RegionPtr /*pRgn*/,
int /*n*/
);
extern void RegionSetExtents(
RegionPtr /*pReg*/
);
extern int miFindMaxBand(
RegionPtr /*prgn*/
);
#ifdef DEBUG
extern Bool RegionIsValid(
RegionPtr /*prgn*/
);
#endif
extern Bool RegionBroken(RegionPtr pReg);
/* miscrinit.c */
extern Bool miModifyPixmapHeader(
PixmapPtr /*pPixmap*/,
int /*width*/,
int /*height*/,
int /*depth*/,
int /*bitsPerPixel*/,
int /*devKind*/,
void * /*pPixData*/
);
extern Bool miCloseScreen(
ScreenPtr /*pScreen*/
);
extern Bool miCreateScreenResources(
ScreenPtr /*pScreen*/
);
extern Bool miScreenDevPrivateInit(
ScreenPtr /*pScreen*/,
int /*width*/,
void * /*pbits*/
);
extern Bool miScreenInit(
ScreenPtr /*pScreen*/,
void * /*pbits*/,
int /*xsize*/,
int /*ysize*/,
int /*dpix*/,
int /*dpiy*/,
int /*width*/,
int /*rootDepth*/,
int /*numDepths*/,
DepthPtr /*depths*/,
VisualID /*rootVisual*/,
int /*numVisuals*/,
VisualPtr /*visuals*/
);
extern int miAllocateGCPrivateIndex(
void
);
extern PixmapPtr miGetScreenPixmap(
ScreenPtr pScreen
);
extern void miSetScreenPixmap(
PixmapPtr pPix
);
/* mivaltree.c */
extern int miShapedWindowIn(
ScreenPtr /*pScreen*/,
RegionPtr /*universe*/,
RegionPtr /*bounding*/,
BoxPtr /*rect*/,
int /*x*/,
int /*y*/
);
typedef void
(*SetRedirectBorderClipProcPtr) (WindowPtr pWindow, RegionPtr pRegion);
typedef RegionPtr
(*GetRedirectBorderClipProcPtr) (WindowPtr pWindow);
void
miRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip,
GetRedirectBorderClipProcPtr getBorderClip);
extern int miValidateTree(
WindowPtr /*pParent*/,
WindowPtr /*pChild*/,
VTKind /*kind*/
);
extern void miWideLine(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
int /*mode*/,
int /*npt*/,
DDXPointPtr /*pPts*/
);
extern void miWideDash(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
int /*mode*/,
int /*npt*/,
DDXPointPtr /*pPts*/
);
extern void miMiter(
void
);
extern void miNotMiter(
void
);
/* miwindow.c */
extern void miClearToBackground(
WindowPtr /*pWin*/,
int /*x*/,
int /*y*/,
int /*w*/,
int /*h*/,
Bool /*generateExposures*/
);
extern Bool miChangeSaveUnder(
WindowPtr /*pWin*/,
WindowPtr /*first*/
);
extern void miPostChangeSaveUnder(
WindowPtr /*pWin*/,
WindowPtr /*pFirst*/
);
extern void miMarkWindow(
WindowPtr /*pWin*/
);
extern Bool miMarkOverlappedWindows(
WindowPtr /*pWin*/,
WindowPtr /*pFirst*/,
WindowPtr * /*ppLayerWin*/
);
extern void miHandleValidateExposures(
WindowPtr /*pWin*/
);
extern void miMoveWindow(
WindowPtr /*pWin*/,
int /*x*/,
int /*y*/,
WindowPtr /*pNextSib*/,
VTKind /*kind*/
);
extern void miSlideAndSizeWindow(
WindowPtr /*pWin*/,
int /*x*/,
int /*y*/,
unsigned int /*w*/,
unsigned int /*h*/,
WindowPtr /*pSib*/
);
extern WindowPtr miGetLayerWindow(
WindowPtr /*pWin*/
);
extern void miSetShape(
WindowPtr /*pWin*/
);
extern void miChangeBorderWidth(
WindowPtr /*pWin*/,
unsigned int /*width*/
);
extern void miMarkUnrealizedWindow(
WindowPtr /*pChild*/,
WindowPtr /*pWin*/,
Bool /*fromConfigure*/
);
extern void miSegregateChildren(WindowPtr pWin, RegionPtr pReg, int depth);
/* mizerarc.c */
extern void miZeroPolyArc(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*narcs*/,
xArc * /*parcs*/
);
/* mizerline.c */
extern void miZeroLine(
DrawablePtr /*dst*/,
GCPtr /*pgc*/,
int /*mode*/,
int /*nptInit*/,
DDXPointRec * /*pptInit*/
);
extern void miZeroDashLine(
DrawablePtr /*dst*/,
GCPtr /*pgc*/,
int /*mode*/,
int /*nptInit*/,
DDXPointRec * /*pptInit*/
);
extern void miPolyFillArc(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
int /*narcs*/,
xArc * /*parcs*/
);
#endif /* MI_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,845 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
/* Author: Todd Newman (aided and abetted by Mr. Drewry) */
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xprotostr.h>
#include "misc.h"
#include "gcstruct.h"
#include "pixmapstr.h"
#include "windowstr.h"
#include "scrnintstr.h"
#include "mi.h"
#include "regionstr.h"
#include <nx-X11/Xmd.h>
#include "servermd.h"
#ifndef HAS_FFS
extern int ffs(int);
#endif
/* MICOPYAREA -- public entry for the CopyArea request
* For each rectangle in the source region
* get the pixels with GetSpans
* set them in the destination with SetSpans
* We let SetSpans worry about clipping to the destination.
*/
RegionPtr
miCopyArea(pSrcDrawable, pDstDrawable,
pGC, xIn, yIn, widthSrc, heightSrc, xOut, yOut)
register DrawablePtr pSrcDrawable;
register DrawablePtr pDstDrawable;
GCPtr pGC;
int xIn, yIn;
int widthSrc, heightSrc;
int xOut, yOut;
{
DDXPointPtr ppt, pptFirst;
unsigned int *pwidthFirst, *pwidth, *pbits;
BoxRec srcBox, *prect;
/* may be a new region, or just a copy */
RegionPtr prgnSrcClip;
/* non-0 if we've created a src clip */
RegionPtr prgnExposed;
int realSrcClip = 0;
int srcx, srcy, dstx, dsty, i, j, y, width, height,
xMin, xMax, yMin, yMax;
unsigned int *ordering;
int numRects;
BoxPtr boxes;
srcx = xIn + pSrcDrawable->x;
srcy = yIn + pSrcDrawable->y;
/* If the destination isn't realized, this is easy */
if (pDstDrawable->type == DRAWABLE_WINDOW &&
!((WindowPtr)pDstDrawable)->realized)
return (RegionPtr)NULL;
/* clip the source */
if (pSrcDrawable->type == DRAWABLE_PIXMAP)
{
BoxRec box;
box.x1 = pSrcDrawable->x;
box.y1 = pSrcDrawable->y;
box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
prgnSrcClip = RegionCreate(&box, 1);
realSrcClip = 1;
}
else
{
if (pGC->subWindowMode == IncludeInferiors) {
prgnSrcClip = NotClippedByChildren ((WindowPtr) pSrcDrawable);
realSrcClip = 1;
} else
prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
}
/* If the src drawable is a window, we need to translate the srcBox so
* that we can compare it with the window's clip region later on. */
srcBox.x1 = srcx;
srcBox.y1 = srcy;
srcBox.x2 = srcx + widthSrc;
srcBox.y2 = srcy + heightSrc;
dstx = xOut;
dsty = yOut;
if (pGC->miTranslate)
{
dstx += pDstDrawable->x;
dsty += pDstDrawable->y;
}
pptFirst = ppt = (DDXPointPtr)
malloc(heightSrc * sizeof(DDXPointRec));
pwidthFirst = pwidth = (unsigned int *)
malloc(heightSrc * sizeof(unsigned int));
numRects = RegionNumRects(prgnSrcClip);
boxes = RegionRects(prgnSrcClip);
ordering = (unsigned int *)
malloc(numRects * sizeof(unsigned int));
if(!pptFirst || !pwidthFirst || !ordering)
{
if (ordering)
free(ordering);
if (pwidthFirst)
free(pwidthFirst);
if (pptFirst)
free(pptFirst);
return (RegionPtr)NULL;
}
/* If not the same drawable then order of move doesn't matter.
Following assumes that boxes are sorted from top
to bottom and left to right.
*/
if ((pSrcDrawable != pDstDrawable) &&
((pGC->subWindowMode != IncludeInferiors) ||
(pSrcDrawable->type == DRAWABLE_PIXMAP) ||
(pDstDrawable->type == DRAWABLE_PIXMAP)))
for (i=0; i < numRects; i++)
ordering[i] = i;
else { /* within same drawable, must sequence moves carefully! */
if (dsty <= srcBox.y1) { /* Scroll up or stationary vertical.
Vertical order OK */
if (dstx <= srcBox.x1) /* Scroll left or stationary horizontal.
Horizontal order OK as well */
for (i=0; i < numRects; i++)
ordering[i] = i;
else { /* scroll right. must reverse horizontal banding of rects. */
for (i=0, j=1, xMax=0; i < numRects; j=i+1, xMax=i) {
/* find extent of current horizontal band */
y=boxes[i].y1; /* band has this y coordinate */
while ((j < numRects) && (boxes[j].y1 == y))
j++;
/* reverse the horizontal band in the output ordering */
for (j-- ; j >= xMax; j--, i++)
ordering[i] = j;
}
}
}
else { /* Scroll down. Must reverse vertical banding. */
if (dstx < srcBox.x1) { /* Scroll left. Horizontal order OK. */
for (i=numRects-1, j=i-1, yMin=i, yMax=0;
i >= 0;
j=i-1, yMin=i) {
/* find extent of current horizontal band */
y=boxes[i].y1; /* band has this y coordinate */
while ((j >= 0) && (boxes[j].y1 == y))
j--;
/* reverse the horizontal band in the output ordering */
for (j++ ; j <= yMin; j++, i--, yMax++)
ordering[yMax] = j;
}
}
else /* Scroll right or horizontal stationary.
Reverse horizontal order as well (if stationary, horizontal
order can be swapped without penalty and this is faster
to compute). */
for (i=0, j=numRects-1; i < numRects; i++, j--)
ordering[i] = j;
}
}
for(i = 0; i < numRects; i++)
{
prect = &boxes[ordering[i]];
xMin = max(prect->x1, srcBox.x1);
xMax = min(prect->x2, srcBox.x2);
yMin = max(prect->y1, srcBox.y1);
yMax = min(prect->y2, srcBox.y2);
/* is there anything visible here? */
if(xMax <= xMin || yMax <= yMin)
continue;
ppt = pptFirst;
pwidth = pwidthFirst;
y = yMin;
height = yMax - yMin;
width = xMax - xMin;
for(j = 0; j < height; j++)
{
/* We must untranslate before calling GetSpans */
ppt->x = xMin;
ppt++->y = y++;
*pwidth++ = width;
}
pbits = (unsigned int *)malloc(height * PixmapBytePad(width,
pSrcDrawable->depth));
if (pbits)
{
(*pSrcDrawable->pScreen->GetSpans)(pSrcDrawable, width, pptFirst,
(int *)pwidthFirst, height, (char *)pbits);
ppt = pptFirst;
pwidth = pwidthFirst;
xMin -= (srcx - dstx);
y = yMin - (srcy - dsty);
for(j = 0; j < height; j++)
{
ppt->x = xMin;
ppt++->y = y++;
*pwidth++ = width;
}
(*pGC->ops->SetSpans)(pDstDrawable, pGC, (char *)pbits, pptFirst,
(int *)pwidthFirst, height, TRUE);
free(pbits);
}
}
prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
widthSrc, heightSrc, xOut, yOut, (unsigned long)0);
if(realSrcClip)
RegionDestroy(prgnSrcClip);
free(ordering);
free(pwidthFirst);
free(pptFirst);
return prgnExposed;
}
/* MIGETPLANE -- gets a bitmap representing one plane of pDraw
* A helper used for CopyPlane and XY format GetImage
* No clever strategy here, we grab a scanline at a time, pull out the
* bits and then stuff them in a 1 bit deep map.
*/
/*
* This should be replaced with something more general. mi shouldn't have to
* care about such things as scanline padding et alia.
*/
static
MiBits *
miGetPlane(
DrawablePtr pDraw,
int planeNum, /* number of the bitPlane */
int sx,
int sy,
int w,
int h,
MiBits *result)
{
int i, j, k, width, bitsPerPixel, widthInBytes;
DDXPointRec pt = {0, 0};
MiBits pixel;
MiBits bit;
unsigned char *pCharsOut = NULL;
#if BITMAP_SCANLINE_UNIT == 8
#define OUT_TYPE unsigned char
#endif
#if BITMAP_SCANLINE_UNIT == 16
#define OUT_TYPE CARD16
#endif
#if BITMAP_SCANLINE_UNIT == 32
#define OUT_TYPE CARD32
#endif
#if BITMAP_SCANLINE_UNIT == 64
#define OUT_TYPE CARD64
#endif
OUT_TYPE *pOut;
int delta = 0;
sx += pDraw->x;
sy += pDraw->y;
widthInBytes = BitmapBytePad(w);
if(!result)
result = (MiBits *)malloc(h * widthInBytes);
if (!result)
return (MiBits *)NULL;
bitsPerPixel = pDraw->bitsPerPixel;
bzero((char *)result, h * widthInBytes);
pOut = (OUT_TYPE *) result;
if(bitsPerPixel == 1)
{
pCharsOut = (unsigned char *) result;
width = w;
}
else
{
delta = (widthInBytes / (BITMAP_SCANLINE_UNIT / 8)) -
(w / BITMAP_SCANLINE_UNIT);
width = 1;
#if IMAGE_BYTE_ORDER == MSBFirst
planeNum += (32 - bitsPerPixel);
#endif
}
pt.y = sy;
for (i = h; --i >= 0; pt.y++)
{
pt.x = sx;
if(bitsPerPixel == 1)
{
(*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1,
(char *)pCharsOut);
pCharsOut += widthInBytes;
}
else
{
k = 0;
for(j = w; --j >= 0; pt.x++)
{
/* Fetch the next pixel */
(*pDraw->pScreen->GetSpans)(pDraw, width, &pt, &width, 1,
(char *)&pixel);
/*
* Now get the bit and insert into a bitmap in XY format.
*/
bit = (pixel >> planeNum) & 1;
#ifndef XFree86Server
/* XXX assuming bit order == byte order */
#if BITMAP_BIT_ORDER == LSBFirst
bit <<= k;
#else
bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k);
#endif
#else
/* XXX assuming byte order == LSBFirst */
if (screenInfo.bitmapBitOrder == LSBFirst)
bit <<= k;
else
bit <<= ((screenInfo.bitmapScanlineUnit - 1) -
(k % screenInfo.bitmapScanlineUnit)) +
((k / screenInfo.bitmapScanlineUnit) *
screenInfo.bitmapScanlineUnit);
#endif
*pOut |= (OUT_TYPE) bit;
k++;
if (k == BITMAP_SCANLINE_UNIT)
{
pOut++;
k = 0;
}
}
pOut += delta;
}
}
return(result);
}
/* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw.
* Drawing through the clip mask we SetSpans() the bits into a
* bitmap and stipple those bits onto the destination drawable by doing a
* PolyFillRect over the whole drawable,
* then we invert the bitmap by copying it onto itself with an alu of
* GXinvert, invert the foreground/background colors of the gc, and draw
* the background bits.
* Note how the clipped out bits of the bitmap are always the background
* color so that the stipple never causes FillRect to draw them.
*/
void
miOpqStipDrawable(pDraw, pGC, prgnSrc, pbits, srcx, w, h, dstx, dsty)
DrawablePtr pDraw;
GCPtr pGC;
RegionPtr prgnSrc;
MiBits *pbits;
int srcx, w, h, dstx, dsty;
{
int oldfill, i;
unsigned long oldfg;
int *pwidth, *pwidthFirst;
ChangeGCVal gcv[6];
PixmapPtr pStipple, pPixmap;
DDXPointRec oldOrg;
GCPtr pGCT;
DDXPointPtr ppt, pptFirst;
xRectangle rect;
RegionPtr prgnSrcClip;
pPixmap = (*pDraw->pScreen->CreatePixmap)
(pDraw->pScreen, w + srcx, h, 1,
CREATE_PIXMAP_USAGE_SCRATCH);
if (!pPixmap)
return;
/* Put the image into a 1 bit deep pixmap */
pGCT = GetScratchGC(1, pDraw->pScreen);
if (!pGCT)
{
(*pDraw->pScreen->DestroyPixmap)(pPixmap);
return;
}
/* First set the whole pixmap to 0 */
gcv[0].val = 0;
dixChangeGC(NullClient, pGCT, GCBackground, NULL, gcv);
ValidateGC((DrawablePtr)pPixmap, pGCT);
miClearDrawable((DrawablePtr)pPixmap, pGCT);
ppt = pptFirst = (DDXPointPtr)malloc(h * sizeof(DDXPointRec));
pwidth = pwidthFirst = (int *)malloc(h * sizeof(int));
if(!pptFirst || !pwidthFirst)
{
if (pwidthFirst) free(pwidthFirst);
if (pptFirst) free(pptFirst);
FreeScratchGC(pGCT);
return;
}
/* we need a temporary region because ChangeClip must be assumed
to destroy what it's sent. note that this means we don't
have to free prgnSrcClip ourselves.
*/
prgnSrcClip = RegionCreate(NULL, 0);
RegionCopy(prgnSrcClip, prgnSrc);
RegionTranslate(prgnSrcClip, srcx, 0);
(*pGCT->funcs->ChangeClip)(pGCT, CT_REGION, prgnSrcClip, 0);
ValidateGC((DrawablePtr)pPixmap, pGCT);
/* Since we know pDraw is always a pixmap, we never need to think
* about translation here */
for(i = 0; i < h; i++)
{
ppt->x = 0;
ppt++->y = i;
*pwidth++ = w + srcx;
}
(*pGCT->ops->SetSpans)((DrawablePtr)pPixmap, pGCT, (char *)pbits,
pptFirst, pwidthFirst, h, TRUE);
free(pwidthFirst);
free(pptFirst);
/* Save current values from the client GC */
oldfill = pGC->fillStyle;
pStipple = pGC->stipple;
if(pStipple)
pStipple->refcnt++;
oldOrg = pGC->patOrg;
/* Set a new stipple in the drawable */
gcv[0].val = FillStippled;
gcv[1].ptr = pPixmap;
gcv[2].val = dstx - srcx;
gcv[3].val = dsty;
dixChangeGC(NullClient, pGC,
GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
NULL, gcv);
ValidateGC(pDraw, pGC);
/* Fill the drawable with the stipple. This will draw the
* foreground color whereever 1 bits are set, leaving everything
* with 0 bits untouched. Note that the part outside the clip
* region is all 0s. */
rect.x = dstx;
rect.y = dsty;
rect.width = w;
rect.height = h;
(*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
/* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only
* within the clipping region, the part outside is still all 0s */
gcv[0].val = GXinvert;
dixChangeGC(NullClient, pGCT, GCFunction, NULL, gcv);
ValidateGC((DrawablePtr)pPixmap, pGCT);
(*pGCT->ops->CopyArea)((DrawablePtr)pPixmap, (DrawablePtr)pPixmap,
pGCT, 0, 0, w + srcx, h, 0, 0);
/* Swap foreground and background colors on the GC for the drawable.
* Now when we fill the drawable, we will fill in the "Background"
* values */
oldfg = pGC->fgPixel;
gcv[0].val = pGC->bgPixel;
gcv[1].val = oldfg;
gcv[2].ptr = pPixmap;
dixChangeGC(NullClient, pGC, GCForeground | GCBackground | GCStipple,
NULL, gcv);
ValidateGC(pDraw, pGC);
/* PolyFillRect might have bashed the rectangle */
rect.x = dstx;
rect.y = dsty;
rect.width = w;
rect.height = h;
(*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
/* Now put things back */
if(pStipple)
pStipple->refcnt--;
gcv[0].val = oldfg;
gcv[1].val = pGC->fgPixel;
gcv[2].val = oldfill;
gcv[3].ptr = pStipple;
gcv[4].val = oldOrg.x;
gcv[5].val = oldOrg.y;
dixChangeGC(NullClient, pGC,
GCForeground | GCBackground | GCFillStyle | GCStipple |
GCTileStipXOrigin | GCTileStipYOrigin, NULL, gcv);
ValidateGC(pDraw, pGC);
/* put what we hope is a smaller clip region back in the scratch gc */
(*pGCT->funcs->ChangeClip)(pGCT, CT_NONE, NULL, 0);
FreeScratchGC(pGCT);
(*pDraw->pScreen->DestroyPixmap)(pPixmap);
}
/* MICOPYPLANE -- public entry for the CopyPlane request.
* strategy:
* First build up a bitmap out of the bits requested
* build a source clip
* Use the bitmap we've built up as a Stipple for the destination
*/
RegionPtr
miCopyPlane(pSrcDrawable, pDstDrawable,
pGC, srcx, srcy, width, height, dstx, dsty, bitPlane)
DrawablePtr pSrcDrawable;
DrawablePtr pDstDrawable;
GCPtr pGC;
int srcx, srcy;
int width, height;
int dstx, dsty;
unsigned long bitPlane;
{
MiBits *ptile;
BoxRec box;
RegionPtr prgnSrc, prgnExposed;
/* incorporate the source clip */
box.x1 = srcx + pSrcDrawable->x;
box.y1 = srcy + pSrcDrawable->y;
box.x2 = box.x1 + width;
box.y2 = box.y1 + height;
/* clip to visible drawable */
if (box.x1 < pSrcDrawable->x)
box.x1 = pSrcDrawable->x;
if (box.y1 < pSrcDrawable->y)
box.y1 = pSrcDrawable->y;
if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
if (box.x1 > box.x2)
box.x2 = box.x1;
if (box.y1 > box.y2)
box.y2 = box.y1;
prgnSrc = RegionCreate(&box, 1);
if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
/* clip to visible drawable */
if (pGC->subWindowMode == IncludeInferiors)
{
RegionPtr clipList = NotClippedByChildren ((WindowPtr) pSrcDrawable);
RegionIntersect(prgnSrc, prgnSrc, clipList);
RegionDestroy(clipList);
} else
RegionIntersect(prgnSrc, prgnSrc,
&((WindowPtr)pSrcDrawable)->clipList);
}
box = *RegionExtents(prgnSrc);
RegionTranslate(prgnSrc, -box.x1, -box.y1);
if ((box.x2 > box.x1) && (box.y2 > box.y1))
{
/* minimize the size of the data extracted */
/* note that we convert the plane mask bitPlane into a plane number */
box.x1 -= pSrcDrawable->x;
box.x2 -= pSrcDrawable->x;
box.y1 -= pSrcDrawable->y;
box.y2 -= pSrcDrawable->y;
ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1,
box.x1, box.y1,
box.x2 - box.x1, box.y2 - box.y1,
(MiBits *) NULL);
if (ptile)
{
miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0,
box.x2 - box.x1, box.y2 - box.y1,
dstx + box.x1 - srcx, dsty + box.y1 - srcy);
free(ptile);
}
}
prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
width, height, dstx, dsty, bitPlane);
RegionDestroy(prgnSrc);
return prgnExposed;
}
/* MIGETIMAGE -- public entry for the GetImage Request
* We're getting the image into a memory buffer. While we have to use GetSpans
* to read a line from the device (since we don't know what that looks like),
* we can just write into the destination buffer
*
* two different strategies are used, depending on whether we're getting the
* image in Z format or XY format
* Z format:
* Line at a time, GetSpans a line into the destination buffer, then if the
* planemask is not all ones, we do a SetSpans into a temporary buffer (to get
* bits turned off) and then another GetSpans to get stuff back (because
* pixmaps are opaque, and we are passed in the memory to write into). This is
* pretty ugly and slow but works. Life is hard.
* XY format:
* get the single plane specified in planemask
*/
void
miGetImage(pDraw, sx, sy, w, h, format, planeMask, pDst)
DrawablePtr pDraw;
int sx, sy, w, h;
unsigned int format;
unsigned long planeMask;
char * pDst;
{
unsigned char depth;
int i, linelength, width, srcx, srcy;
DDXPointRec pt = {0, 0};
XID gcv[2];
PixmapPtr pPixmap = (PixmapPtr)NULL;
GCPtr pGC = NULL;
depth = pDraw->depth;
if(format == ZPixmap)
{
if ( (((1<<depth)-1)&planeMask) != (1<<depth)-1 )
{
xPoint xpt;
pGC = GetScratchGC(depth, pDraw->pScreen);
if (!pGC)
return;
pPixmap = (*pDraw->pScreen->CreatePixmap)
(pDraw->pScreen, w, 1, depth,
CREATE_PIXMAP_USAGE_SCRATCH);
if (!pPixmap)
{
FreeScratchGC(pGC);
return;
}
/*
* Clear the pixmap before doing anything else
*/
ValidateGC((DrawablePtr)pPixmap, pGC);
xpt.x = xpt.y = 0;
width = w;
(*pGC->ops->FillSpans)((DrawablePtr)pPixmap, pGC, 1, &xpt, &width,
TRUE);
/* alu is already GXCopy */
gcv[0] = (XID)planeMask;
DoChangeGC(pGC, GCPlaneMask, gcv, 0);
ValidateGC((DrawablePtr)pPixmap, pGC);
}
linelength = PixmapBytePad(w, depth);
srcx = sx + pDraw->x;
srcy = sy + pDraw->y;
for(i = 0; i < h; i++)
{
pt.x = srcx;
pt.y = srcy + i;
width = w;
(*pDraw->pScreen->GetSpans)(pDraw, w, &pt, &width, 1, pDst);
if (pPixmap)
{
pt.x = 0;
pt.y = 0;
width = w;
(*pGC->ops->SetSpans)((DrawablePtr)pPixmap, pGC, pDst,
&pt, &width, 1, TRUE);
(*pDraw->pScreen->GetSpans)((DrawablePtr)pPixmap, w, &pt,
&width, 1, pDst);
}
pDst += linelength;
}
if (pPixmap)
{
(*pGC->pScreen->DestroyPixmap)(pPixmap);
FreeScratchGC(pGC);
}
}
else
{
(void) miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h,
(MiBits *)pDst);
}
}
/* MIPUTIMAGE -- public entry for the PutImage request
* Here we benefit from knowing the format of the bits pointed to by pImage,
* even if we don't know how pDraw represents them.
* Three different strategies are used depending on the format
* XYBitmap Format:
* we just use the Opaque Stipple helper function to cover the destination
* Note that this covers all the planes of the drawable with the
* foreground color (masked with the GC planemask) where there are 1 bits
* and the background color (masked with the GC planemask) where there are
* 0 bits
* XYPixmap format:
* what we're called with is a series of XYBitmaps, but we only want
* each XYPixmap to update 1 plane, instead of updating all of them.
* we set the foreground color to be all 1s and the background to all 0s
* then for each plane, we set the plane mask to only effect that one
* plane and recursive call ourself with the format set to XYBitmap
* (This clever idea courtesy of RGD.)
* ZPixmap format:
* This part is simple, just call SetSpans
*/
void
miPutImage(pDraw, pGC, depth, x, y, w, h, leftPad, format, pImage)
DrawablePtr pDraw;
GCPtr pGC;
int depth, x, y, w, h, leftPad;
int format;
char *pImage;
{
DDXPointPtr pptFirst, ppt;
int *pwidthFirst, *pwidth;
RegionPtr prgnSrc;
BoxRec box;
unsigned long oldFg, oldBg;
XID gcv[3];
unsigned long oldPlanemask;
unsigned long i;
long bytesPer;
if (!w || !h)
return;
switch(format)
{
case XYBitmap:
box.x1 = 0;
box.y1 = 0;
box.x2 = w;
box.y2 = h;
prgnSrc = RegionCreate(&box, 1);
miOpqStipDrawable(pDraw, pGC, prgnSrc, (MiBits *) pImage,
leftPad, w, h, x, y);
RegionDestroy(prgnSrc);
break;
case XYPixmap:
depth = pGC->depth;
oldPlanemask = pGC->planemask;
oldFg = pGC->fgPixel;
oldBg = pGC->bgPixel;
gcv[0] = (XID)~0;
gcv[1] = (XID)0;
DoChangeGC(pGC, GCForeground | GCBackground, gcv, 0);
bytesPer = (long)h * BitmapBytePad(w + leftPad);
for (i = 1 << (depth-1); i != 0; i >>= 1, pImage += bytesPer)
{
if (i & oldPlanemask)
{
gcv[0] = (XID)i;
DoChangeGC(pGC, GCPlaneMask, gcv, 0);
ValidateGC(pDraw, pGC);
(*pGC->ops->PutImage)(pDraw, pGC, 1, x, y, w, h, leftPad,
XYBitmap, (char *)pImage);
}
}
gcv[0] = (XID)oldPlanemask;
gcv[1] = (XID)oldFg;
gcv[2] = (XID)oldBg;
DoChangeGC(pGC, GCPlaneMask | GCForeground | GCBackground, gcv, 0);
ValidateGC(pDraw, pGC);
break;
case ZPixmap:
ppt = pptFirst = (DDXPointPtr)malloc(h * sizeof(DDXPointRec));
pwidth = pwidthFirst = (int *)malloc(h * sizeof(int));
if(!pptFirst || !pwidthFirst)
{
if (pwidthFirst)
free(pwidthFirst);
if (pptFirst)
free(pptFirst);
return;
}
if (pGC->miTranslate)
{
x += pDraw->x;
y += pDraw->y;
}
for(i = 0; i < h; i++)
{
ppt->x = x;
ppt->y = y + i;
ppt++;
*pwidth++ = w;
}
(*pGC->ops->SetSpans)(pDraw, pGC, (char *)pImage, pptFirst,
pwidthFirst, h, TRUE);
free(pwidthFirst);
free(pptFirst);
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,29 @@
/*-
* mibstore.h --
* Header file for users of the MI backing-store scheme.
*
* Copyright (c) 1987 by the Regents of the University of California
*
* 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. The University of California
* makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without
* express or implied warranty.
*
* "$Xorg: mibstore.h,v 1.3 2000/08/17 19:53:37 cpqbld Exp $
*/
#ifndef _MIBSTORE_H
#define _MIBSTORE_H
#include "screenint.h"
extern void miInitializeBackingStore(
ScreenPtr /*pScreen*/
);
#endif /* _MIBSTORE_H */

View File

@@ -0,0 +1,91 @@
/*
* mibstorest.h
*
* internal structure definitions for mi backing store
*/
/*
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "mibstore.h"
#include "regionstr.h"
/*
* One of these structures is allocated per GC used with a backing-store
* drawable.
*/
typedef struct {
GCPtr pBackingGC; /* Copy of the GC but with graphicsExposures
* set FALSE and the clientClip set to
* clip output to the valid regions of the
* backing pixmap. */
int guarantee; /* GuaranteeNothing, etc. */
unsigned long serialNumber; /* clientClip computed time */
unsigned long stateChanges; /* changes in parent gc since last copy */
GCOps *wrapOps; /* wrapped ops */
GCFuncs *wrapFuncs; /* wrapped funcs */
} miBSGCRec, *miBSGCPtr;
/*
* one of these structures is allocated per Window with backing store
*/
typedef struct {
PixmapPtr pBackingPixmap; /* Pixmap for saved areas */
short x; /* origin of pixmap relative to window */
short y;
RegionRec SavedRegion; /* Valid area in pBackingPixmap */
char viewable; /* Tracks pWin->viewable so SavedRegion may
* be initialized correctly when the window
* is first mapped */
char status; /* StatusNoPixmap, etc. */
char backgroundState; /* background type */
PixUnion background; /* background pattern */
} miBSWindowRec, *miBSWindowPtr;
#define StatusNoPixmap 1 /* pixmap has not been created */
#define StatusVirtual 2 /* pixmap is virtual, tiled with background */
#define StatusVDirty 3 /* pixmap is virtual, visiblt has contents */
#define StatusBadAlloc 4 /* pixmap create failed, do not try again */
#define StatusContents 5 /* pixmap is created, has valid contents */
typedef struct {
/*
* screen func wrappers
*/
CloseScreenProcPtr CloseScreen;
GetImageProcPtr GetImage;
GetSpansProcPtr GetSpans;
ChangeWindowAttributesProcPtr ChangeWindowAttributes;
CreateGCProcPtr CreateGC;
DestroyWindowProcPtr DestroyWindow;
} miBSScreenRec, *miBSScreenPtr;

View File

@@ -0,0 +1,698 @@
/* $XConsortium: cfbcmap.c,v 4.19 94/04/17 20:28:46 dpw Exp $ */
/************************************************************
Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
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 no-
tice appear in all copies and that both that copyright no-
tice and this permission notice appear in supporting docu-
mentation, and that the names of Sun or X Consortium
not be used in advertising or publicity pertaining to
distribution of the software without specific prior
written permission. Sun and X Consortium make no
representations about the suitability of this software for
any purpose. It is provided "as is" without any express or
implied warranty.
SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI-
ABLE 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.
********************************************************/
/*
* This is based on cfbcmap.c. The functions here are useful independently
* of cfb, which is the reason for including them here. How "mi" these
* are may be debatable.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xproto.h>
#include "scrnintstr.h"
#include "colormapst.h"
#include "resource.h"
#include "globals.h"
#include "micmap.h"
ColormapPtr miInstalledMaps[MAXSCREENS];
static Bool miDoInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
unsigned long sizes, int bitsPerRGB, int preferredVis);
miInitVisualsProcPtr miInitVisualsProc = miDoInitVisuals;
int
miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps)
{
if (miInstalledMaps[pScreen->myNum]) {
*pmaps = miInstalledMaps[pScreen->myNum]->mid;
return (1);
}
return 0;
}
void
miInstallColormap(ColormapPtr pmap)
{
int index = pmap->pScreen->myNum;
ColormapPtr oldpmap = miInstalledMaps[index];
if(pmap != oldpmap)
{
/* Uninstall pInstalledMap. No hardware changes required, just
* notify all interested parties. */
if(oldpmap != (ColormapPtr)None)
WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid);
/* Install pmap */
miInstalledMaps[index] = pmap;
WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid);
}
}
void
miUninstallColormap(ColormapPtr pmap)
{
int index = pmap->pScreen->myNum;
ColormapPtr curpmap = miInstalledMaps[index];
if(pmap == curpmap)
{
if (pmap->mid != pmap->pScreen->defColormap)
{
curpmap = (ColormapPtr) LookupIDByType(pmap->pScreen->defColormap,
RT_COLORMAP);
(*pmap->pScreen->InstallColormap)(curpmap);
}
}
}
void
miResolveColor(unsigned short *pred, unsigned short *pgreen,
unsigned short *pblue, VisualPtr pVisual)
{
int shift = 16 - pVisual->bitsPerRGBValue;
unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1;
if ((pVisual->class | DynamicClass) == GrayScale)
{
/* rescale to gray then rgb bits */
*pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100;
*pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim;
}
else
{
/* rescale to rgb bits */
*pred = ((*pred >> shift) * 65535) / lim;
*pgreen = ((*pgreen >> shift) * 65535) / lim;
*pblue = ((*pblue >> shift) * 65535) / lim;
}
}
Bool
miInitializeColormap(ColormapPtr pmap)
{
register unsigned i;
register VisualPtr pVisual;
unsigned lim, maxent, shift;
pVisual = pmap->pVisual;
lim = (1 << pVisual->bitsPerRGBValue) - 1;
shift = 16 - pVisual->bitsPerRGBValue;
maxent = pVisual->ColormapEntries - 1;
if (pVisual->class == TrueColor)
{
unsigned limr, limg, limb;
limr = pVisual->redMask >> pVisual->offsetRed;
limg = pVisual->greenMask >> pVisual->offsetGreen;
limb = pVisual->blueMask >> pVisual->offsetBlue;
for(i = 0; i <= maxent; i++)
{
/* rescale to [0..65535] then rgb bits */
pmap->red[i].co.local.red =
((((i * 65535) / limr) >> shift) * 65535) / lim;
pmap->green[i].co.local.green =
((((i * 65535) / limg) >> shift) * 65535) / lim;
pmap->blue[i].co.local.blue =
((((i * 65535) / limb) >> shift) * 65535) / lim;
}
}
else if (pVisual->class == StaticColor)
{
unsigned limr, limg, limb;
limr = pVisual->redMask >> pVisual->offsetRed;
limg = pVisual->greenMask >> pVisual->offsetGreen;
limb = pVisual->blueMask >> pVisual->offsetBlue;
for(i = 0; i <= maxent; i++)
{
/* rescale to [0..65535] then rgb bits */
pmap->red[i].co.local.red =
((((((i & pVisual->redMask) >> pVisual->offsetRed)
* 65535) / limr) >> shift) * 65535) / lim;
pmap->red[i].co.local.green =
((((((i & pVisual->greenMask) >> pVisual->offsetGreen)
* 65535) / limg) >> shift) * 65535) / lim;
pmap->red[i].co.local.blue =
((((((i & pVisual->blueMask) >> pVisual->offsetBlue)
* 65535) / limb) >> shift) * 65535) / lim;
}
}
else if (pVisual->class == StaticGray)
{
for(i = 0; i <= maxent; i++)
{
/* rescale to [0..65535] then rgb bits */
pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift)
* 65535) / lim;
pmap->red[i].co.local.green = pmap->red[i].co.local.red;
pmap->red[i].co.local.blue = pmap->red[i].co.local.red;
}
}
return TRUE;
}
/* When simulating DirectColor on PseudoColor hardware, multiple
entries of the colormap must be updated
*/
#define AddElement(mask) { \
pixel = red | green | blue; \
for (i = 0; i < nresult; i++) \
if (outdefs[i].pixel == pixel) \
break; \
if (i == nresult) \
{ \
nresult++; \
outdefs[i].pixel = pixel; \
outdefs[i].flags = 0; \
} \
outdefs[i].flags |= (mask); \
outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \
outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \
outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \
}
int
miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs,
xColorItem *outdefs)
{
register int red, green, blue;
int maxred, maxgreen, maxblue;
int stepred, stepgreen, stepblue;
VisualPtr pVisual;
register int pixel;
register int nresult;
register int i;
pVisual = pmap->pVisual;
stepred = 1 << pVisual->offsetRed;
stepgreen = 1 << pVisual->offsetGreen;
stepblue = 1 << pVisual->offsetBlue;
maxred = pVisual->redMask;
maxgreen = pVisual->greenMask;
maxblue = pVisual->blueMask;
nresult = 0;
for (;ndef--; indefs++)
{
if (indefs->flags & DoRed)
{
red = indefs->pixel & pVisual->redMask;
for (green = 0; green <= maxgreen; green += stepgreen)
{
for (blue = 0; blue <= maxblue; blue += stepblue)
{
AddElement (DoRed)
}
}
}
if (indefs->flags & DoGreen)
{
green = indefs->pixel & pVisual->greenMask;
for (red = 0; red <= maxred; red += stepred)
{
for (blue = 0; blue <= maxblue; blue += stepblue)
{
AddElement (DoGreen)
}
}
}
if (indefs->flags & DoBlue)
{
blue = indefs->pixel & pVisual->blueMask;
for (red = 0; red <= maxred; red += stepred)
{
for (green = 0; green <= maxgreen; green += stepgreen)
{
AddElement (DoBlue)
}
}
}
}
return nresult;
}
Bool
miCreateDefColormap(ScreenPtr pScreen)
{
/*
* In the following sources PC X server vendors may want to delete
* "_not_tog" from "#ifdef WIN32_not_tog"
*/
#ifdef WIN32_not_tog
/*
* these are the MS-Windows desktop colors, adjusted for X's 16-bit
* color specifications.
*/
static xColorItem citems[] = {
{ 0, 0, 0, 0, 0, 0 },
{ 1, 0x8000, 0, 0, 0, 0 },
{ 2, 0, 0x8000, 0, 0, 0 },
{ 3, 0x8000, 0x8000, 0, 0, 0 },
{ 4, 0, 0, 0x8000, 0, 0 },
{ 5, 0x8000, 0, 0x8000, 0, 0 },
{ 6, 0, 0x8000, 0x8000, 0, 0 },
{ 7, 0xc000, 0xc000, 0xc000, 0, 0 },
{ 8, 0xc000, 0xdc00, 0xc000, 0, 0 },
{ 9, 0xa600, 0xca00, 0xf000, 0, 0 },
{ 246, 0xff00, 0xfb00, 0xf000, 0, 0 },
{ 247, 0xa000, 0xa000, 0xa400, 0, 0 },
{ 248, 0x8000, 0x8000, 0x8000, 0, 0 },
{ 249, 0xff00, 0, 0, 0, 0 },
{ 250, 0, 0xff00, 0, 0, 0 },
{ 251, 0xff00, 0xff00, 0, 0, 0 },
{ 252, 0, 0, 0xff00, 0, 0 },
{ 253, 0xff00, 0, 0xff00, 0, 0 },
{ 254, 0, 0xff00, 0xff00, 0, 0 },
{ 255, 0xff00, 0xff00, 0xff00, 0, 0 }
};
#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0]
int i;
#else
unsigned short zero = 0, ones = 0xFFFF;
#endif
Pixel wp, bp;
VisualPtr pVisual;
ColormapPtr cmap;
int alloctype;
for (pVisual = pScreen->visuals;
pVisual->vid != pScreen->rootVisual;
pVisual++)
;
if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass))
alloctype = AllocNone;
else
alloctype = AllocAll;
if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap,
alloctype, 0) != Success)
return FALSE;
if (pScreen->rootDepth > 1) {
wp = pScreen->whitePixel;
bp = pScreen->blackPixel;
#ifdef WIN32_not_tog
for (i = 0; i < NUM_DESKTOP_COLORS; i++) {
if (AllocColor (cmap,
&citems[i].red, &citems[i].green, &citems[i].blue,
&citems[i].pixel, 0) != Success)
return FALSE;
}
#else
if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) !=
Success) ||
(AllocColor(cmap, &zero, &zero, &zero, &bp, 0) !=
Success))
return FALSE;
pScreen->whitePixel = wp;
pScreen->blackPixel = bp;
#endif
}
(*pScreen->InstallColormap)(cmap);
return TRUE;
}
/*
* Default true color bitmasks, should be overridden by
* driver
*/
#define _RZ(d) ((d + 2) / 3)
#define _RS(d) 0
#define _RM(d) ((1 << _RZ(d)) - 1)
#define _GZ(d) ((d - _RZ(d) + 1) / 2)
#define _GS(d) _RZ(d)
#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d))
#define _BZ(d) (d - _RZ(d) - _GZ(d))
#define _BS(d) (_RZ(d) + _GZ(d))
#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d))
#define _CE(d) (1 << _RZ(d))
typedef struct _miVisuals {
struct _miVisuals *next;
int depth;
int bitsPerRGB;
int visuals;
int count;
int preferredCVC;
Pixel redMask, greenMask, blueMask;
} miVisualsRec, *miVisualsPtr;
static int miVisualPriority[] = {
PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray
};
#define NUM_PRIORITY 6
static miVisualsPtr miVisuals;
void
miClearVisualTypes()
{
miVisualsPtr v;
while ((v = miVisuals)) {
miVisuals = v->next;
free(v);
}
}
Bool
miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
int preferredCVC,
Pixel redMask, Pixel greenMask, Pixel blueMask)
{
miVisualsPtr new, *prev, v;
int count;
new = (miVisualsPtr) malloc (sizeof *new);
if (!new)
return FALSE;
if (!redMask || !greenMask || !blueMask)
{
redMask = _RM(depth);
greenMask = _GM(depth);
blueMask = _BM(depth);
}
new->next = 0;
new->depth = depth;
new->visuals = visuals;
new->bitsPerRGB = bitsPerRGB;
new->preferredCVC = preferredCVC;
new->redMask = redMask;
new->greenMask = greenMask;
new->blueMask = blueMask;
count = (visuals >> 1) & 033333333333;
count = visuals - count - ((count >> 1) & 033333333333);
count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */
new->count = count;
for (prev = &miVisuals; (v = *prev); prev = &v->next);
*prev = new;
return TRUE;
}
Bool
miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC)
{
return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB,
preferredCVC, 0, 0, 0);
}
int
miGetDefaultVisualMask(int depth)
{
if (depth > MAX_PSEUDO_DEPTH)
return LARGE_VISUALS;
else if (depth >= MIN_TRUE_DEPTH)
return ALL_VISUALS;
else if (depth == 1)
return StaticGrayMask;
else
return SMALL_VISUALS;
}
static Bool
miVisualTypesSet (int depth)
{
miVisualsPtr visuals;
for (visuals = miVisuals; visuals; visuals = visuals->next)
if (visuals->depth == depth)
return TRUE;
return FALSE;
}
Bool
miSetPixmapDepths (void)
{
int d, f;
/* Add any unlisted depths from the pixmap formats */
for (f = 0; f < screenInfo.numPixmapFormats; f++)
{
d = screenInfo.formats[f].depth;
if (!miVisualTypesSet (d))
{
if (!miSetVisualTypes (d, 0, 0, -1))
return FALSE;
}
}
return TRUE;
}
Bool
miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
unsigned long sizes, int bitsPerRGB, int preferredVis)
{
if (miInitVisualsProc)
return miInitVisualsProc(visualp, depthp, nvisualp, ndepthp,
rootDepthp, defaultVisp, sizes, bitsPerRGB,
preferredVis);
else
return FALSE;
}
/*
* Distance to least significant one bit
*/
static int
maskShift (Pixel p)
{
int s;
if (!p) return 0;
s = 0;
while (!(p & 1))
{
s++;
p >>= 1;
}
return s;
}
/*
* Given a list of formats for a screen, create a list
* of visuals and depths for the screen which corespond to
* the set which can be used with this version of cfb.
*/
static Bool
miDoInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp,
int *ndepthp, int *rootDepthp, VisualID *defaultVisp,
unsigned long sizes, int bitsPerRGB, int preferredVis)
{
int i, j = 0, k;
VisualPtr visual;
DepthPtr depth;
VisualID *vid;
int d, b;
int f;
int ndepth, nvisual;
int nvtype;
int vtype;
miVisualsPtr visuals, nextVisuals;
int *preferredCVCs, *prefp;
int first_depth;
/* none specified, we'll guess from pixmap formats */
if (!miVisuals)
{
for (f = 0; f < screenInfo.numPixmapFormats; f++)
{
d = screenInfo.formats[f].depth;
b = screenInfo.formats[f].bitsPerPixel;
if (sizes & (1 << (b - 1)))
vtype = miGetDefaultVisualMask(d);
else
vtype = 0;
if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1))
return FALSE;
}
}
nvisual = 0;
ndepth = 0;
for (visuals = miVisuals; visuals; visuals = nextVisuals)
{
nextVisuals = visuals->next;
ndepth++;
nvisual += visuals->count;
}
depth = (DepthPtr) malloc (ndepth * sizeof (DepthRec));
visual = (VisualPtr) malloc (nvisual * sizeof (VisualRec));
preferredCVCs = (int *)malloc(ndepth * sizeof(int));
if (!depth || !visual || !preferredCVCs)
{
free (depth);
free (visual);
free (preferredCVCs);
return FALSE;
}
*depthp = depth;
*visualp = visual;
*ndepthp = ndepth;
*nvisualp = nvisual;
prefp = preferredCVCs;
for (visuals = miVisuals; visuals; visuals = nextVisuals)
{
nextVisuals = visuals->next;
d = visuals->depth;
vtype = visuals->visuals;
nvtype = visuals->count;
*prefp = visuals->preferredCVC;
prefp++;
vid = NULL;
if (nvtype)
{
vid = (VisualID *) malloc (nvtype * sizeof (VisualID));
if (!vid) {
free(preferredCVCs);
return FALSE;
}
}
depth->depth = d;
depth->numVids = nvtype;
depth->vids = vid;
depth++;
for (i = 0; i < NUM_PRIORITY; i++) {
if (! (vtype & (1 << miVisualPriority[i])))
continue;
visual->class = miVisualPriority[i];
visual->bitsPerRGBValue = visuals->bitsPerRGB;
visual->ColormapEntries = 1 << d;
visual->nplanes = d;
visual->vid = *vid = FakeClientID (0);
switch (visual->class) {
case PseudoColor:
case GrayScale:
case StaticGray:
visual->redMask = 0;
visual->greenMask = 0;
visual->blueMask = 0;
visual->offsetRed = 0;
visual->offsetGreen = 0;
visual->offsetBlue = 0;
break;
case DirectColor:
case TrueColor:
visual->ColormapEntries = _CE(d);
/* fall through */
case StaticColor:
visual->redMask = visuals->redMask;
visual->greenMask = visuals->greenMask;
visual->blueMask = visuals->blueMask;
visual->offsetRed = maskShift (visuals->redMask);
visual->offsetGreen = maskShift (visuals->greenMask);
visual->offsetBlue = maskShift (visuals->blueMask);
}
vid++;
visual++;
}
free (visuals);
}
miVisuals = NULL;
visual = *visualp;
depth = *depthp;
/*
* if we did not supplyied by a preferred visual class
* check if there is a preferred class in one of the depth
* structures - if there is, we want to start looking for the
* default visual/depth from that depth.
*/
first_depth = 0;
if (preferredVis < 0 && defaultColorVisualClass < 0 ) {
for (i = 0; i < ndepth; i++) {
if (preferredCVCs[i] >= 0) {
first_depth = i;
break;
}
}
}
for (i = first_depth; i < ndepth; i++)
{
int prefColorVisualClass = -1;
if (defaultColorVisualClass >= 0)
prefColorVisualClass = defaultColorVisualClass;
else if (preferredVis >= 0)
prefColorVisualClass = preferredVis;
else if (preferredCVCs[i] >= 0)
prefColorVisualClass = preferredCVCs[i];
if (*rootDepthp && *rootDepthp != depth[i].depth)
continue;
for (j = 0; j < depth[i].numVids; j++)
{
for (k = 0; k < nvisual; k++)
if (visual[k].vid == depth[i].vids[j])
break;
if (k == nvisual)
continue;
if (prefColorVisualClass < 0 ||
visual[k].class == prefColorVisualClass)
break;
}
if (j != depth[i].numVids)
break;
}
if (i == ndepth) {
i = 0;
j = 0;
}
*rootDepthp = depth[i].depth;
*defaultVisp = depth[i].vids[j];
free(preferredCVCs);
return TRUE;
}
void
miResetInitVisuals()
{
miInitVisualsProc = miDoInitVisuals;
}

View File

@@ -0,0 +1,64 @@
#include "colormapst.h"
#ifndef _MICMAP_H_
#define _MICMAP_H_
extern ColormapPtr miInstalledMaps[MAXSCREENS];
typedef Bool (* miInitVisualsProcPtr)(VisualPtr *, DepthPtr *, int *, int *,
int *, VisualID *, unsigned long, int,
int);
extern miInitVisualsProcPtr miInitVisualsProc;
int miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps);
void miInstallColormap(ColormapPtr pmap);
void miUninstallColormap(ColormapPtr pmap);
void miResolveColor(unsigned short *, unsigned short *, unsigned short *,
VisualPtr);
Bool miInitializeColormap(ColormapPtr);
int miExpandDirectColors(ColormapPtr, int, xColorItem *, xColorItem *);
Bool miCreateDefColormap(ScreenPtr);
void miClearVisualTypes(void);
Bool miSetVisualTypes(int, int, int, int);
Bool miSetPixmapDepths(void);
Bool miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB,
int preferredCVC,
Pixel redMask, Pixel greenMask, Pixel blueMask);
int miGetDefaultVisualMask(int);
Bool miInitVisuals(VisualPtr *, DepthPtr *, int *, int *, int *, VisualID *,
unsigned long, int, int);
void miResetInitVisuals(void);
void miHookInitVisuals(void (**old)(miInitVisualsProcPtr *),
void (*new)(miInitVisualsProcPtr *));
#define MAX_PSEUDO_DEPTH 10
#define MIN_TRUE_DEPTH 6
#define StaticGrayMask (1 << StaticGray)
#define GrayScaleMask (1 << GrayScale)
#define StaticColorMask (1 << StaticColor)
#define PseudoColorMask (1 << PseudoColor)
#define TrueColorMask (1 << TrueColor)
#define DirectColorMask (1 << DirectColor)
#define ALL_VISUALS (StaticGrayMask|\
GrayScaleMask|\
StaticColorMask|\
PseudoColorMask|\
TrueColorMask|\
DirectColorMask)
#define LARGE_VISUALS (TrueColorMask|\
DirectColorMask)
#define SMALL_VISUALS (StaticGrayMask|\
GrayScaleMask|\
StaticColorMask|\
PseudoColorMask)
#endif /* _MICMAP_H_ */

View File

@@ -0,0 +1,70 @@
/*
* Copyright (C) 2000 The XFree86 Project, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the XFree86 Project shall
* not be used in advertising or otherwise to promote the sale, use or other
* dealings in this Software without prior written authorization from the
* XFree86 Project.
*
*/
#ifndef _MICOORD_H_
#define _MICOORD_H_ 1
#include "servermd.h"
/* Macros which handle a coordinate in a single register */
/*
* Most compilers will convert divisions by 65536 into shifts, if signed
* shifts exist. If your machine does arithmetic shifts and your compiler
* can't get it right, add to this line.
*/
/*
* mips compiler - what a joke - it CSEs the 65536 constant into a reg
* forcing as to use div instead of shift. Let's be explicit.
*/
#if defined(mips) || \
defined(sparc) || defined(__sparc64__) || \
defined(__alpha) || defined(__alpha__) || \
defined(__i386__) || defined(i386) || \
defined(__ia64__) || defined(ia64) || \
defined(__s390x__) || defined(__s390__) || \
defined(__amd64__) || defined(amd64) || defined(__amd64)
#define GetHighWord(x) (((int) (x)) >> 16)
#else
#define GetHighWord(x) (((int) (x)) / 65536)
#endif
#if IMAGE_BYTE_ORDER == MSBFirst
#define intToCoord(i,x,y) (((x) = GetHighWord(i)), ((y) = (int) ((short) (i))))
#define coordToInt(x,y) (((x) << 16) | ((y) & 0xffff))
#define intToX(i) (GetHighWord(i))
#define intToY(i) ((int) ((short) i))
#else
#define intToCoord(i,x,y) (((x) = (int) ((short) (i))), ((y) = GetHighWord(i)))
#define coordToInt(x,y) (((y) << 16) | ((x) & 0xffff))
#define intToX(i) ((int) ((short) (i)))
#define intToY(i) (GetHighWord(i))
#endif
#endif /* _MICOORD_H_ */

View File

@@ -0,0 +1,71 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "scrnintstr.h"
#include "cursor.h"
#include "misc.h"
#include "mi.h"
void
miRecolorCursor( pScr, pCurs, displayed)
ScreenPtr pScr;
CursorPtr pCurs;
Bool displayed;
{
/*
* This is guaranteed to correct any color-dependent state which may have
* been bound up in private state created by RealizeCursor
*/
pScr->UnrealizeCursor(pScr, pCurs);
pScr->RealizeCursor(pScr, pCurs);
if (displayed)
pScr->DisplayCursor(pScr, pCurs);
}

View File

@@ -0,0 +1,313 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "regionstr.h"
#include "mistruct.h"
#include "mifpoly.h"
static miDashPtr CheckDashStorage(miDashPtr *ppseg, int nseg, int *pnsegMax);
/* return a list of DashRec. there will be an extra
entry at the end holding the last point of the polyline.
this means that the code that actually draws dashes can
get a pair of points for every dash. only the point in the last
dash record is useful; the other fields are not used.
nseg is the number of segments, not the number of points.
example:
dash1.start
dash2.start
dash3.start
last-point
defines a list of segments
(dash1.pt, dash2.pt)
(dash2.pt, dash3.pt)
(dash3.pt, last-point)
and nseg == 3.
NOTE:
EVEN_DASH == ~ODD_DASH
NOTE ALSO:
miDashLines may return 0 segments, going from pt[0] to pt[0] with one dash.
*/
miDashPtr
miDashLine(npt, ppt, nDash, pDash, offset, pnseg)
int npt;
DDXPointPtr ppt;
unsigned int nDash;
unsigned char *pDash;
unsigned int offset;
int *pnseg;
{
DDXPointRec pt1, pt2;
int lenCur; /* npt used from this dash */
int lenMax; /* npt in this dash */
int iDash = 0; /* index of current dash */
int which; /* EVEN_DASH or ODD_DASH */
miDashPtr pseg; /* list of dash segments */
miDashPtr psegBase; /* start of list */
int nseg = 0; /* number of dashes so far */
int nsegMax = 0; /* num segs we can fit in this list */
int x, y, len;
int adx, ady, signdx, signdy;
int du, dv, e1, e2, e, base_e = 0;
lenCur = offset;
which = EVEN_DASH;
while(lenCur >= pDash[iDash])
{
lenCur -= pDash[iDash];
iDash++;
if (iDash >= nDash)
iDash = 0;
which = ~which;
}
lenMax = pDash[iDash];
psegBase = (miDashPtr)NULL;
pt2 = ppt[0]; /* just in case there is only one point */
while(--npt)
{
if (PtEqual(ppt[0], ppt[1]))
{
ppt++;
continue; /* no duplicated points in polyline */
}
pt1 = *ppt++;
pt2 = *ppt;
adx = pt2.x - pt1.x;
ady = pt2.y - pt1.y;
signdx = sign(adx);
signdy = sign(ady);
adx = abs(adx);
ady = abs(ady);
if (adx > ady)
{
du = adx;
dv = ady;
len = adx;
}
else
{
du = ady;
dv = adx;
len = ady;
}
e1 = dv * 2;
e2 = e1 - 2*du;
e = e1 - du;
x = pt1.x;
y = pt1.y;
nseg++;
pseg = CheckDashStorage(&psegBase, nseg, &nsegMax);
if (!pseg)
return (miDashPtr)NULL;
pseg->pt = pt1;
pseg->e1 = e1;
pseg->e2 = e2;
base_e = pseg->e = e;
pseg->which = which;
pseg->newLine = 1;
while (len--)
{
if (adx > ady)
{
/* X_AXIS */
if (((signdx > 0) && (e < 0)) ||
((signdx <=0) && (e <=0))
)
{
e += e1;
}
else
{
y += signdy;
e += e2;
}
x += signdx;
}
else
{
/* Y_AXIS */
if (((signdx > 0) && (e < 0)) ||
((signdx <=0) && (e <=0))
)
{
e +=e1;
}
else
{
x += signdx;
e += e2;
}
y += signdy;
}
lenCur++;
if (lenCur >= lenMax && (len || npt <= 1))
{
nseg++;
pseg = CheckDashStorage(&psegBase, nseg, &nsegMax);
if (!pseg)
return (miDashPtr)NULL;
pseg->pt.x = x;
pseg->pt.y = y;
pseg->e1 = e1;
pseg->e2 = e2;
pseg->e = e;
which = ~which;
pseg->which = which;
pseg->newLine = 0;
/* move on to next dash */
iDash++;
if (iDash >= nDash)
iDash = 0;
lenMax = pDash[iDash];
lenCur = 0;
}
} /* while len-- */
} /* while --npt */
if (lenCur == 0 && nseg != 0)
{
nseg--;
which = ~which;
}
*pnseg = nseg;
pseg = CheckDashStorage(&psegBase, nseg+1, &nsegMax);
if (!pseg)
return (miDashPtr)NULL;
pseg->pt = pt2;
pseg->e = base_e;
pseg->which = which;
pseg->newLine = 0;
return psegBase;
}
#define NSEGDELTA 16
/* returns a pointer to the pseg[nseg-1], growing the storage as
necessary. this interface seems unnecessarily cumbersome.
*/
static
miDashPtr
CheckDashStorage(
miDashPtr *ppseg, /* base pointer */
int nseg, /* number of segment we want to write to */
int *pnsegMax) /* size (in segments) of list so far */
{
if (nseg > *pnsegMax)
{
miDashPtr newppseg;
*pnsegMax += NSEGDELTA;
newppseg = (miDashPtr)realloc(*ppseg,
(*pnsegMax)*sizeof(miDashRec));
if (!newppseg)
{
free(*ppseg);
return (miDashPtr)NULL;
}
*ppseg = newppseg;
}
return(*ppseg+(nseg-1));
}
void
miStepDash (dist, pDashIndex, pDash, numInDashList, pDashOffset)
int dist; /* distance to step */
int *pDashIndex; /* current dash */
unsigned char *pDash; /* dash list */
int numInDashList; /* total length of dash list */
int *pDashOffset; /* offset into current dash */
{
int dashIndex, dashOffset;
int totallen;
int i;
dashIndex = *pDashIndex;
dashOffset = *pDashOffset;
if (dist < pDash[dashIndex] - dashOffset)
{
*pDashOffset = dashOffset + dist;
return;
}
dist -= pDash[dashIndex] - dashOffset;
if (++dashIndex == numInDashList)
dashIndex = 0;
totallen = 0;
for (i = 0; i < numInDashList; i++)
totallen += pDash[i];
if (totallen <= dist)
dist = dist % totallen;
while (dist >= pDash[dashIndex])
{
dist -= pDash[dashIndex];
if (++dashIndex == numInDashList)
dashIndex = 0;
}
*pDashIndex = dashIndex;
*pDashOffset = dist;
}

View File

@@ -0,0 +1,813 @@
/*
* midispcur.c
*
* machine independent cursor display routines
*/
/*
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
# include <nx-X11/X.h>
# include "misc.h"
# include "input.h"
# include "cursorstr.h"
# include "windowstr.h"
# include "regionstr.h"
# include "dixstruct.h"
# include "scrnintstr.h"
# include "servermd.h"
# include "mipointer.h"
# include "misprite.h"
# include "gcstruct.h"
#ifdef ARGB_CURSOR
# include "picturestr.h"
#endif
/* per-screen private data */
static int miDCScreenIndex;
static unsigned long miDCGeneration = 0;
static Bool miDCCloseScreen(ScreenPtr pScreen);
typedef struct {
GCPtr pSourceGC, pMaskGC;
GCPtr pSaveGC, pRestoreGC;
GCPtr pMoveGC;
GCPtr pPixSourceGC, pPixMaskGC;
CloseScreenProcPtr CloseScreen;
PixmapPtr pSave, pTemp;
#ifdef ARGB_CURSOR
PicturePtr pRootPicture;
PicturePtr pTempPicture;
#endif
} miDCScreenRec, *miDCScreenPtr;
/* per-cursor per-screen private data */
typedef struct {
PixmapPtr sourceBits; /* source bits */
PixmapPtr maskBits; /* mask bits */
#ifdef ARGB_CURSOR
PicturePtr pPicture;
#endif
} miDCCursorRec, *miDCCursorPtr;
/*
* sprite/cursor method table
*/
static Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static Bool miDCPutUpCursor(ScreenPtr pScreen, CursorPtr pCursor,
int x, int y, unsigned long source,
unsigned long mask);
static Bool miDCSaveUnderCursor(ScreenPtr pScreen, int x, int y,
int w, int h);
static Bool miDCRestoreUnderCursor(ScreenPtr pScreen, int x, int y,
int w, int h);
static Bool miDCMoveCursor(ScreenPtr pScreen, CursorPtr pCursor,
int x, int y, int w, int h, int dx, int dy,
unsigned long source, unsigned long mask);
static Bool miDCChangeSave(ScreenPtr pScreen, int x, int y, int w, int h,
int dx, int dy);
static miSpriteCursorFuncRec miDCFuncs = {
miDCRealizeCursor,
miDCUnrealizeCursor,
miDCPutUpCursor,
miDCSaveUnderCursor,
miDCRestoreUnderCursor,
miDCMoveCursor,
miDCChangeSave,
};
Bool
miDCInitialize (pScreen, screenFuncs)
ScreenPtr pScreen;
miPointerScreenFuncPtr screenFuncs;
{
miDCScreenPtr pScreenPriv;
if (miDCGeneration != serverGeneration)
{
miDCScreenIndex = AllocateScreenPrivateIndex ();
if (miDCScreenIndex < 0)
return FALSE;
miDCGeneration = serverGeneration;
}
pScreenPriv = (miDCScreenPtr) malloc (sizeof (miDCScreenRec));
if (!pScreenPriv)
return FALSE;
/*
* initialize the entire private structure to zeros
*/
pScreenPriv->pSourceGC =
pScreenPriv->pMaskGC =
pScreenPriv->pSaveGC =
pScreenPriv->pRestoreGC =
pScreenPriv->pMoveGC =
pScreenPriv->pPixSourceGC =
pScreenPriv->pPixMaskGC = NULL;
#ifdef ARGB_CURSOR
pScreenPriv->pRootPicture = NULL;
pScreenPriv->pTempPicture = NULL;
#endif
pScreenPriv->pSave = pScreenPriv->pTemp = NULL;
pScreenPriv->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = miDCCloseScreen;
pScreen->devPrivates[miDCScreenIndex].ptr = (void *) pScreenPriv;
if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs))
{
free ((void *) pScreenPriv);
return FALSE;
}
return TRUE;
}
#define tossGC(gc) (gc ? FreeGC (gc, (GContext) 0) : 0)
#define tossPix(pix) (pix ? (*pScreen->DestroyPixmap) (pix) : TRUE)
#define tossPict(pict) (pict ? FreePicture (pict, 0) : 0)
static Bool
miDCCloseScreen (pScreen)
ScreenPtr pScreen;
{
miDCScreenPtr pScreenPriv;
pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
pScreen->CloseScreen = pScreenPriv->CloseScreen;
tossGC (pScreenPriv->pSourceGC);
tossGC (pScreenPriv->pMaskGC);
tossGC (pScreenPriv->pSaveGC);
tossGC (pScreenPriv->pRestoreGC);
tossGC (pScreenPriv->pMoveGC);
tossGC (pScreenPriv->pPixSourceGC);
tossGC (pScreenPriv->pPixMaskGC);
tossPix (pScreenPriv->pSave);
tossPix (pScreenPriv->pTemp);
#ifdef ARGB_CURSOR
tossPict (pScreenPriv->pRootPicture);
tossPict (pScreenPriv->pTempPicture);
#endif
free ((void *) pScreenPriv);
return (*pScreen->CloseScreen) (pScreen);
}
static Bool
miDCRealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
if (pCursor->bits->refcnt <= 1)
pCursor->bits->devPriv[pScreen->myNum] = (void *)NULL;
return TRUE;
}
#ifdef ARGB_CURSOR
#define EnsurePicture(picture,draw,win) (picture || miDCMakePicture(&picture,draw,win))
static VisualPtr
miDCGetWindowVisual (WindowPtr pWin)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
VisualID vid = wVisual (pWin);
int i;
for (i = 0; i < pScreen->numVisuals; i++)
if (pScreen->visuals[i].vid == vid)
return &pScreen->visuals[i];
return 0;
}
static PicturePtr
miDCMakePicture (PicturePtr *ppPicture, DrawablePtr pDraw, WindowPtr pWin)
{
ScreenPtr pScreen = pDraw->pScreen;
VisualPtr pVisual;
PictFormatPtr pFormat;
XID subwindow_mode = IncludeInferiors;
PicturePtr pPicture;
int error;
pVisual = miDCGetWindowVisual (pWin);
if (!pVisual)
return 0;
pFormat = PictureMatchVisual (pScreen, pDraw->depth, pVisual);
if (!pFormat)
return 0;
pPicture = CreatePicture (0, pDraw, pFormat,
CPSubwindowMode, &subwindow_mode,
serverClient, &error);
*ppPicture = pPicture;
return pPicture;
}
#endif
static miDCCursorPtr
miDCRealize (
ScreenPtr pScreen,
CursorPtr pCursor)
{
miDCCursorPtr pPriv;
GCPtr pGC;
XID gcvals[3];
pPriv = (miDCCursorPtr) malloc (sizeof (miDCCursorRec));
if (!pPriv)
return (miDCCursorPtr)NULL;
#ifdef ARGB_CURSOR
if (pCursor->bits->argb)
{
PixmapPtr pPixmap;
PictFormatPtr pFormat;
int error;
pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8);
if (!pFormat)
{
free ((void *) pPriv);
return (miDCCursorPtr)NULL;
}
pPriv->sourceBits = 0;
pPriv->maskBits = 0;
pPixmap = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width,
pCursor->bits->height, 32,
CREATE_PIXMAP_USAGE_SCRATCH);
if (!pPixmap)
{
free ((void *) pPriv);
return (miDCCursorPtr)NULL;
}
pGC = GetScratchGC (32, pScreen);
if (!pGC)
{
(*pScreen->DestroyPixmap) (pPixmap);
free ((void *) pPriv);
return (miDCCursorPtr)NULL;
}
ValidateGC (&pPixmap->drawable, pGC);
(*pGC->ops->PutImage) (&pPixmap->drawable, pGC, 32,
0, 0, pCursor->bits->width,
pCursor->bits->height,
0, ZPixmap, (char *) pCursor->bits->argb);
FreeScratchGC (pGC);
pPriv->pPicture = CreatePicture (0, &pPixmap->drawable,
pFormat, 0, 0, serverClient, &error);
(*pScreen->DestroyPixmap) (pPixmap);
if (!pPriv->pPicture)
{
free ((void *) pPriv);
return (miDCCursorPtr)NULL;
}
pCursor->bits->devPriv[pScreen->myNum] = (void *) pPriv;
return pPriv;
}
pPriv->pPicture = 0;
#endif
pPriv->sourceBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
if (!pPriv->sourceBits)
{
free ((void *) pPriv);
return (miDCCursorPtr)NULL;
}
pPriv->maskBits = (*pScreen->CreatePixmap) (pScreen, pCursor->bits->width, pCursor->bits->height, 1, 0);
if (!pPriv->maskBits)
{
(*pScreen->DestroyPixmap) (pPriv->sourceBits);
free ((void *) pPriv);
return (miDCCursorPtr)NULL;
}
pCursor->bits->devPriv[pScreen->myNum] = (void *) pPriv;
/* create the two sets of bits, clipping as appropriate */
pGC = GetScratchGC (1, pScreen);
if (!pGC)
{
(void) miDCUnrealizeCursor (pScreen, pCursor);
return (miDCCursorPtr)NULL;
}
ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
(*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
0, 0, pCursor->bits->width, pCursor->bits->height,
0, XYPixmap, (char *)pCursor->bits->source);
gcvals[0] = GXand;
ChangeGC (pGC, GCFunction, gcvals);
ValidateGC ((DrawablePtr)pPriv->sourceBits, pGC);
(*pGC->ops->PutImage) ((DrawablePtr)pPriv->sourceBits, pGC, 1,
0, 0, pCursor->bits->width, pCursor->bits->height,
0, XYPixmap, (char *)pCursor->bits->mask);
/* mask bits -- pCursor->mask & ~pCursor->source */
gcvals[0] = GXcopy;
ChangeGC (pGC, GCFunction, gcvals);
ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
(*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
0, 0, pCursor->bits->width, pCursor->bits->height,
0, XYPixmap, (char *)pCursor->bits->mask);
gcvals[0] = GXandInverted;
ChangeGC (pGC, GCFunction, gcvals);
ValidateGC ((DrawablePtr)pPriv->maskBits, pGC);
(*pGC->ops->PutImage) ((DrawablePtr)pPriv->maskBits, pGC, 1,
0, 0, pCursor->bits->width, pCursor->bits->height,
0, XYPixmap, (char *)pCursor->bits->source);
FreeScratchGC (pGC);
return pPriv;
}
static Bool
miDCUnrealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
miDCCursorPtr pPriv;
pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
if (pPriv && (pCursor->bits->refcnt <= 1))
{
if (pPriv->sourceBits)
(*pScreen->DestroyPixmap) (pPriv->sourceBits);
if (pPriv->maskBits)
(*pScreen->DestroyPixmap) (pPriv->maskBits);
#ifdef ARGB_CURSOR
if (pPriv->pPicture)
FreePicture (pPriv->pPicture, 0);
#endif
free ((void *) pPriv);
pCursor->bits->devPriv[pScreen->myNum] = (void *)NULL;
}
return TRUE;
}
static void
miDCPutBits (
DrawablePtr pDrawable,
miDCCursorPtr pPriv,
GCPtr sourceGC,
GCPtr maskGC,
int x_org,
int y_org,
unsigned w,
unsigned h,
unsigned long source,
unsigned long mask)
{
XID gcvals[1];
int x, y;
if (sourceGC->fgPixel != source)
{
gcvals[0] = source;
DoChangeGC (sourceGC, GCForeground, gcvals, 0);
}
if (sourceGC->serialNumber != pDrawable->serialNumber)
ValidateGC (pDrawable, sourceGC);
if(sourceGC->miTranslate)
{
x = pDrawable->x + x_org;
y = pDrawable->y + y_org;
}
else
{
x = x_org;
y = y_org;
}
(*sourceGC->ops->PushPixels) (sourceGC, pPriv->sourceBits, pDrawable, w, h, x, y);
if (maskGC->fgPixel != mask)
{
gcvals[0] = mask;
DoChangeGC (maskGC, GCForeground, gcvals, 0);
}
if (maskGC->serialNumber != pDrawable->serialNumber)
ValidateGC (pDrawable, maskGC);
if(maskGC->miTranslate)
{
x = pDrawable->x + x_org;
y = pDrawable->y + y_org;
}
else
{
x = x_org;
y = y_org;
}
(*maskGC->ops->PushPixels) (maskGC, pPriv->maskBits, pDrawable, w, h, x, y);
}
#define EnsureGC(gc,win) (gc || miDCMakeGC(&gc, win))
static GCPtr
miDCMakeGC(
GCPtr *ppGC,
WindowPtr pWin)
{
GCPtr pGC;
int status;
XID gcvals[2];
gcvals[0] = IncludeInferiors;
gcvals[1] = FALSE;
pGC = CreateGC((DrawablePtr)pWin,
GCSubwindowMode|GCGraphicsExposures, gcvals, &status);
if (pGC && pWin->drawable.pScreen->DrawGuarantee)
(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
*ppGC = pGC;
return pGC;
}
static Bool
miDCPutUpCursor (pScreen, pCursor, x, y, source, mask)
ScreenPtr pScreen;
CursorPtr pCursor;
int x, y;
unsigned long source, mask;
{
miDCScreenPtr pScreenPriv;
miDCCursorPtr pPriv;
WindowPtr pWin;
pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
if (!pPriv)
{
pPriv = miDCRealize(pScreen, pCursor);
if (!pPriv)
return FALSE;
}
pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
pWin = pScreen->root;
#ifdef ARGB_CURSOR
if (pPriv->pPicture)
{
if (!EnsurePicture(pScreenPriv->pRootPicture, &pWin->drawable, pWin))
return FALSE;
CompositePicture (PictOpOver,
pPriv->pPicture,
NULL,
pScreenPriv->pRootPicture,
0, 0, 0, 0,
x, y,
pCursor->bits->width,
pCursor->bits->height);
}
else
#endif
{
if (!EnsureGC(pScreenPriv->pSourceGC, pWin))
return FALSE;
if (!EnsureGC(pScreenPriv->pMaskGC, pWin))
{
FreeGC (pScreenPriv->pSourceGC, (GContext) 0);
pScreenPriv->pSourceGC = 0;
return FALSE;
}
miDCPutBits ((DrawablePtr)pWin, pPriv,
pScreenPriv->pSourceGC, pScreenPriv->pMaskGC,
x, y, pCursor->bits->width, pCursor->bits->height,
source, mask);
}
return TRUE;
}
static Bool
miDCSaveUnderCursor (pScreen, x, y, w, h)
ScreenPtr pScreen;
int x, y, w, h;
{
miDCScreenPtr pScreenPriv;
PixmapPtr pSave;
WindowPtr pWin;
GCPtr pGC;
pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
pSave = pScreenPriv->pSave;
pWin = pScreen->root;
if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h)
{
if (pSave)
(*pScreen->DestroyPixmap) (pSave);
pScreenPriv->pSave = pSave =
(*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0);
if (!pSave)
return FALSE;
}
if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
return FALSE;
pGC = pScreenPriv->pSaveGC;
if (pSave->drawable.serialNumber != pGC->serialNumber)
ValidateGC ((DrawablePtr) pSave, pGC);
(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
x, y, w, h, 0, 0);
return TRUE;
}
static Bool
miDCRestoreUnderCursor (pScreen, x, y, w, h)
ScreenPtr pScreen;
int x, y, w, h;
{
miDCScreenPtr pScreenPriv;
PixmapPtr pSave;
WindowPtr pWin;
GCPtr pGC;
pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
pSave = pScreenPriv->pSave;
pWin = pScreen->root;
if (!pSave)
return FALSE;
if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
return FALSE;
pGC = pScreenPriv->pRestoreGC;
if (pWin->drawable.serialNumber != pGC->serialNumber)
ValidateGC ((DrawablePtr) pWin, pGC);
(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
0, 0, w, h, x, y);
return TRUE;
}
static Bool
miDCChangeSave (pScreen, x, y, w, h, dx, dy)
ScreenPtr pScreen;
int x, y, w, h, dx, dy;
{
miDCScreenPtr pScreenPriv;
PixmapPtr pSave;
WindowPtr pWin;
GCPtr pGC;
int sourcex, sourcey, destx, desty, copyw, copyh;
pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
pSave = pScreenPriv->pSave;
pWin = pScreen->root;
/*
* restore the bits which are about to get trashed
*/
if (!pSave)
return FALSE;
if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
return FALSE;
pGC = pScreenPriv->pRestoreGC;
if (pWin->drawable.serialNumber != pGC->serialNumber)
ValidateGC ((DrawablePtr) pWin, pGC);
/*
* copy the old bits to the screen.
*/
if (dy > 0)
{
(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
0, h - dy, w, dy, x + dx, y + h);
}
else if (dy < 0)
{
(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
0, 0, w, -dy, x + dx, y + dy);
}
if (dy >= 0)
{
desty = y + dy;
sourcey = 0;
copyh = h - dy;
}
else
{
desty = y;
sourcey = - dy;
copyh = h + dy;
}
if (dx > 0)
{
(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
w - dx, sourcey, dx, copyh, x + w, desty);
}
else if (dx < 0)
{
(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC,
0, sourcey, -dx, copyh, x + dx, desty);
}
if (!EnsureGC(pScreenPriv->pSaveGC, pWin))
return FALSE;
pGC = pScreenPriv->pSaveGC;
if (pSave->drawable.serialNumber != pGC->serialNumber)
ValidateGC ((DrawablePtr) pSave, pGC);
/*
* move the bits that are still valid within the pixmap
*/
if (dx >= 0)
{
sourcex = 0;
destx = dx;
copyw = w - dx;
}
else
{
destx = 0;
sourcex = - dx;
copyw = w + dx;
}
if (dy >= 0)
{
sourcey = 0;
desty = dy;
copyh = h - dy;
}
else
{
desty = 0;
sourcey = -dy;
copyh = h + dy;
}
(*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pSave, pGC,
sourcex, sourcey, copyw, copyh, destx, desty);
/*
* copy the new bits from the screen into the remaining areas of the
* pixmap
*/
if (dy > 0)
{
(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
x, y, w, dy, 0, 0);
}
else if (dy < 0)
{
(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
x, y + h + dy, w, -dy, 0, h + dy);
}
if (dy >= 0)
{
desty = dy;
sourcey = y + dy;
copyh = h - dy;
}
else
{
desty = 0;
sourcey = y;
copyh = h + dy;
}
if (dx > 0)
{
(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
x, sourcey, dx, copyh, 0, desty);
}
else if (dx < 0)
{
(*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC,
x + w + dx, sourcey, -dx, copyh, w + dx, desty);
}
return TRUE;
}
static Bool
miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask)
ScreenPtr pScreen;
CursorPtr pCursor;
int x, y, w, h, dx, dy;
unsigned long source, mask;
{
miDCCursorPtr pPriv;
miDCScreenPtr pScreenPriv;
int status;
WindowPtr pWin;
GCPtr pGC;
XID gcval = FALSE;
PixmapPtr pTemp;
pPriv = (miDCCursorPtr) pCursor->bits->devPriv[pScreen->myNum];
if (!pPriv)
{
pPriv = miDCRealize(pScreen, pCursor);
if (!pPriv)
return FALSE;
}
pScreenPriv = (miDCScreenPtr) pScreen->devPrivates[miDCScreenIndex].ptr;
pWin = pScreen->root;
pTemp = pScreenPriv->pTemp;
if (!pTemp ||
pTemp->drawable.width != pScreenPriv->pSave->drawable.width ||
pTemp->drawable.height != pScreenPriv->pSave->drawable.height)
{
if (pTemp)
(*pScreen->DestroyPixmap) (pTemp);
#ifdef ARGB_CURSOR
if (pScreenPriv->pTempPicture)
{
FreePicture (pScreenPriv->pTempPicture, 0);
pScreenPriv->pTempPicture = 0;
}
#endif
pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap)
(pScreen, w, h, pScreenPriv->pSave->drawable.depth, 0);
if (!pTemp)
return FALSE;
}
if (!pScreenPriv->pMoveGC)
{
pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp,
GCGraphicsExposures, &gcval, &status);
if (!pScreenPriv->pMoveGC)
return FALSE;
}
/*
* copy the saved area to a temporary pixmap
*/
pGC = pScreenPriv->pMoveGC;
if (pGC->serialNumber != pTemp->drawable.serialNumber)
ValidateGC ((DrawablePtr) pTemp, pGC);
(*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave,
(DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0);
/*
* draw the cursor in the temporary pixmap
*/
#ifdef ARGB_CURSOR
if (pPriv->pPicture)
{
if (!EnsurePicture(pScreenPriv->pTempPicture, &pTemp->drawable, pWin))
return FALSE;
CompositePicture (PictOpOver,
pPriv->pPicture,
NULL,
pScreenPriv->pTempPicture,
0, 0, 0, 0,
dx, dy,
pCursor->bits->width,
pCursor->bits->height);
}
else
#endif
{
if (!pScreenPriv->pPixSourceGC)
{
pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp,
GCGraphicsExposures, &gcval, &status);
if (!pScreenPriv->pPixSourceGC)
return FALSE;
}
if (!pScreenPriv->pPixMaskGC)
{
pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp,
GCGraphicsExposures, &gcval, &status);
if (!pScreenPriv->pPixMaskGC)
return FALSE;
}
miDCPutBits ((DrawablePtr)pTemp, pPriv,
pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC,
dx, dy, pCursor->bits->width, pCursor->bits->height,
source, mask);
}
/*
* copy the temporary pixmap onto the screen
*/
if (!EnsureGC(pScreenPriv->pRestoreGC, pWin))
return FALSE;
pGC = pScreenPriv->pRestoreGC;
if (pWin->drawable.serialNumber != pGC->serialNumber)
ValidateGC ((DrawablePtr) pWin, pGC);
(*pGC->ops->CopyArea) ((DrawablePtr) pTemp, (DrawablePtr) pWin,
pGC,
0, 0, w, h, x, y);
return TRUE;
}

View File

@@ -0,0 +1,204 @@
/*
* $Xorg: mieq.c,v 1.4 2001/02/09 02:05:20 xorgcvs Exp $
*
Copyright 1990, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*
* Author: Keith Packard, MIT X Consortium
*/
/*
* mieq.c
*
* Machine independent event queue
*
*/
# include <nx-X11/X.h>
# include <nx-X11/Xmd.h>
# include <nx-X11/Xproto.h>
# include "misc.h"
# include "windowstr.h"
# include "pixmapstr.h"
# include "inputstr.h"
# include "mi.h"
# include "scrnintstr.h"
#ifdef DPMSExtension
# include "dpmsproc.h"
# define DPMS_SERVER
# include <nx-X11/extensions/dpms.h>
#endif
#define QUEUE_SIZE 256
typedef struct _Event {
xEvent event;
ScreenPtr pScreen;
} EventRec, *EventPtr;
typedef struct _EventQueue {
HWEventQueueType head, tail; /* long for SetInputCheck */
CARD32 lastEventTime; /* to avoid time running backwards */
Bool lastMotion;
EventRec events[QUEUE_SIZE]; /* static allocation for signals */
DevicePtr pKbd, pPtr; /* device pointer, to get funcs */
ScreenPtr pEnqueueScreen; /* screen events are being delivered to */
ScreenPtr pDequeueScreen; /* screen events are being dispatched to */
} EventQueueRec, *EventQueuePtr;
static EventQueueRec miEventQueue;
Bool
mieqInit (pKbd, pPtr)
DevicePtr pKbd, pPtr;
{
miEventQueue.head = miEventQueue.tail = 0;
miEventQueue.lastEventTime = GetTimeInMillis ();
miEventQueue.pKbd = pKbd;
miEventQueue.pPtr = pPtr;
miEventQueue.lastMotion = FALSE;
miEventQueue.pEnqueueScreen = screenInfo.screens[0];
miEventQueue.pDequeueScreen = miEventQueue.pEnqueueScreen;
SetInputCheck (&miEventQueue.head, &miEventQueue.tail);
return TRUE;
}
/*
* Must be reentrant with ProcessInputEvents. Assumption: mieqEnqueue
* will never be interrupted. If this is called from both signal
* handlers and regular code, make sure the signal is suspended when
* called from regular code.
*/
void
mieqEnqueue (e)
xEvent *e;
{
HWEventQueueType oldtail, newtail;
Bool isMotion;
oldtail = miEventQueue.tail;
isMotion = e->u.u.type == MotionNotify;
if (isMotion && miEventQueue.lastMotion && oldtail != miEventQueue.head)
{
if (oldtail == 0)
oldtail = QUEUE_SIZE;
oldtail = oldtail - 1;
}
else
{
newtail = oldtail + 1;
if (newtail == QUEUE_SIZE)
newtail = 0;
/* Toss events which come in late */
if (newtail == miEventQueue.head)
return;
miEventQueue.tail = newtail;
}
miEventQueue.lastMotion = isMotion;
miEventQueue.events[oldtail].event = *e;
/*
* Make sure that event times don't go backwards - this
* is "unnecessary", but very useful
*/
if (e->u.keyButtonPointer.time < miEventQueue.lastEventTime &&
miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000)
{
miEventQueue.events[oldtail].event.u.keyButtonPointer.time =
miEventQueue.lastEventTime;
}
miEventQueue.lastEventTime =
miEventQueue.events[oldtail].event.u.keyButtonPointer.time;
miEventQueue.events[oldtail].pScreen = miEventQueue.pEnqueueScreen;
}
void
mieqSwitchScreen (pScreen, fromDIX)
ScreenPtr pScreen;
Bool fromDIX;
{
miEventQueue.pEnqueueScreen = pScreen;
if (fromDIX)
miEventQueue.pDequeueScreen = pScreen;
}
/*
* Call this from ProcessInputEvents()
*/
void mieqProcessInputEvents ()
{
EventRec *e;
int x, y;
xEvent xe;
while (miEventQueue.head != miEventQueue.tail)
{
if (screenIsSaved == SCREEN_SAVER_ON)
SaveScreens (SCREEN_SAVER_OFF, ScreenSaverReset);
#ifdef DPMSExtension
else if (DPMSPowerLevel != DPMSModeOn)
SetScreenSaverTimer();
if (DPMSPowerLevel != DPMSModeOn)
DPMSSet(DPMSModeOn);
#endif
e = &miEventQueue.events[miEventQueue.head];
/*
* Assumption - screen switching can only occur on motion events
*/
if (e->pScreen != miEventQueue.pDequeueScreen)
{
miEventQueue.pDequeueScreen = e->pScreen;
x = e->event.u.keyButtonPointer.rootX;
y = e->event.u.keyButtonPointer.rootY;
if (miEventQueue.head == QUEUE_SIZE - 1)
miEventQueue.head = 0;
else
++miEventQueue.head;
NewCurrentScreen (miEventQueue.pDequeueScreen, x, y);
}
else
{
xe = e->event;
if (miEventQueue.head == QUEUE_SIZE - 1)
miEventQueue.head = 0;
else
++miEventQueue.head;
switch (xe.u.u.type)
{
case KeyPress:
case KeyRelease:
(*miEventQueue.pKbd->processInputProc)
(&xe, (DeviceIntPtr)miEventQueue.pKbd, 1);
break;
default:
(*miEventQueue.pPtr->processInputProc)
(&xe, (DeviceIntPtr)miEventQueue.pPtr, 1);
break;
}
}
}
}

View File

@@ -0,0 +1,905 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
/*****************************************************************
Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Digital Equipment Corporation
shall not be used in advertising or otherwise to promote the sale, use or other
dealings in this Software without prior written authorization from Digital
Equipment Corporation.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xproto.h>
#include <nx-X11/Xprotostr.h>
#include "misc.h"
#include "regionstr.h"
#include "scrnintstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmap.h"
#include "input.h"
#include "dixstruct.h"
#include "mi.h"
#include <nx-X11/Xmd.h>
#include "globals.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
/*
machine-independent graphics exposure code. any device that uses
the region package can call this.
*/
#ifndef RECTLIMIT
#define RECTLIMIT 25 /* pick a number, any number > 8 */
#endif
/* miHandleExposures
generate a region for exposures for areas that were copied from obscured or
non-existent areas to non-obscured areas of the destination. Paint the
background for the region, if the destination is a window.
NOTE:
this should generally be called, even if graphicsExposures is false,
because this is where bits get recovered from backing store.
NOTE:
added argument 'plane' is used to indicate how exposures from backing
store should be accomplished. If plane is 0 (i.e. no bit plane), CopyArea
should be used, else a CopyPlane of the indicated plane will be used. The
exposing is done by the backing store's GraphicsExpose function, of course.
*/
RegionPtr
miHandleExposures(pSrcDrawable, pDstDrawable,
pGC, srcx, srcy, width, height, dstx, dsty, plane)
register DrawablePtr pSrcDrawable;
register DrawablePtr pDstDrawable;
GCPtr pGC;
int srcx, srcy;
int width, height;
int dstx, dsty;
unsigned long plane;
{
register ScreenPtr pscr;
RegionPtr prgnSrcClip; /* drawable-relative source clip */
RegionRec rgnSrcRec;
RegionPtr prgnDstClip; /* drawable-relative dest clip */
RegionRec rgnDstRec;
BoxRec srcBox; /* unclipped source */
RegionRec rgnExposed; /* exposed region, calculated source-
relative, made dst relative to
intersect with visible parts of
dest and send events to client,
and then screen relative to paint
the window background
*/
WindowPtr pSrcWin;
BoxRec expBox = { 0, };
Bool extents;
/* This prevents warning about pscr not being used. */
pGC->pScreen = pscr = pGC->pScreen;
/* avoid work if we can */
if (!pGC->graphicsExposures &&
(pDstDrawable->type == DRAWABLE_PIXMAP) &&
((pSrcDrawable->type == DRAWABLE_PIXMAP) ||
(((WindowPtr)pSrcDrawable)->backStorage == NULL)))
return NULL;
srcBox.x1 = srcx;
srcBox.y1 = srcy;
srcBox.x2 = srcx+width;
srcBox.y2 = srcy+height;
if (pSrcDrawable->type != DRAWABLE_PIXMAP)
{
BoxRec TsrcBox;
TsrcBox.x1 = srcx + pSrcDrawable->x;
TsrcBox.y1 = srcy + pSrcDrawable->y;
TsrcBox.x2 = TsrcBox.x1 + width;
TsrcBox.y2 = TsrcBox.y1 + height;
pSrcWin = (WindowPtr) pSrcDrawable;
if (pGC->subWindowMode == IncludeInferiors)
{
prgnSrcClip = NotClippedByChildren (pSrcWin);
if ((RegionContainsRect(prgnSrcClip, &TsrcBox)) == rgnIN)
{
RegionDestroy(prgnSrcClip);
return NULL;
}
}
else
{
if ((RegionContainsRect(&pSrcWin->clipList, &TsrcBox)) == rgnIN)
return NULL;
prgnSrcClip = &rgnSrcRec;
RegionNull(prgnSrcClip);
RegionCopy(prgnSrcClip, &pSrcWin->clipList);
}
RegionTranslate(prgnSrcClip,
-pSrcDrawable->x, -pSrcDrawable->y);
}
else
{
BoxRec box;
if ((srcBox.x1 >= 0) && (srcBox.y1 >= 0) &&
(srcBox.x2 <= pSrcDrawable->width) &&
(srcBox.y2 <= pSrcDrawable->height))
return NULL;
box.x1 = 0;
box.y1 = 0;
box.x2 = pSrcDrawable->width;
box.y2 = pSrcDrawable->height;
prgnSrcClip = &rgnSrcRec;
RegionInit(prgnSrcClip, &box, 1);
pSrcWin = (WindowPtr)NULL;
}
if (pDstDrawable == pSrcDrawable)
{
prgnDstClip = prgnSrcClip;
}
else if (pDstDrawable->type != DRAWABLE_PIXMAP)
{
if (pGC->subWindowMode == IncludeInferiors)
{
prgnDstClip = NotClippedByChildren((WindowPtr)pDstDrawable);
}
else
{
prgnDstClip = &rgnDstRec;
RegionNull(prgnDstClip);
RegionCopy(prgnDstClip,
&((WindowPtr)pDstDrawable)->clipList);
}
RegionTranslate(prgnDstClip,
-pDstDrawable->x, -pDstDrawable->y);
}
else
{
BoxRec box;
box.x1 = 0;
box.y1 = 0;
box.x2 = pDstDrawable->width;
box.y2 = pDstDrawable->height;
prgnDstClip = &rgnDstRec;
RegionInit(prgnDstClip, &box, 1);
}
/* drawable-relative source region */
RegionInit(&rgnExposed, &srcBox, 1);
/* now get the hidden parts of the source box*/
RegionSubtract(&rgnExposed, &rgnExposed, prgnSrcClip);
if (pSrcWin && pSrcWin->backStorage)
{
/*
* Copy any areas from the source backing store. Modifies
* rgnExposed.
*/
(* pSrcWin->drawable.pScreen->ExposeCopy) ((WindowPtr)pSrcDrawable,
pDstDrawable,
pGC,
&rgnExposed,
srcx, srcy,
dstx, dsty,
plane);
}
/* move them over the destination */
RegionTranslate(&rgnExposed, dstx-srcx, dsty-srcy);
/* intersect with visible areas of dest */
RegionIntersect(&rgnExposed, &rgnExposed, prgnDstClip);
/*
* If we have LOTS of rectangles, we decide to take the extents
* and force an exposure on that. This should require much less
* work overall, on both client and server. This is cheating, but
* isn't prohibited by the protocol ("spontaneous combustion" :-)
* for windows.
*/
extents = pGC->graphicsExposures &&
(RegionNumRects(&rgnExposed) > RECTLIMIT) &&
(pDstDrawable->type != DRAWABLE_PIXMAP);
#ifdef SHAPE
if (pSrcWin)
{
RegionPtr region;
if (!(region = wClipShape (pSrcWin)))
region = wBoundingShape (pSrcWin);
/*
* If you try to CopyArea the extents of a shaped window, compacting the
* exposed region will undo all our work!
*/
if (extents && pSrcWin && region &&
(RegionContainsRect(region, &srcBox) != rgnIN))
extents = FALSE;
}
#endif
if (extents)
{
WindowPtr pWin = (WindowPtr)pDstDrawable;
expBox = *RegionExtents(&rgnExposed);
RegionReset(&rgnExposed, &expBox);
/* need to clear out new areas of backing store */
if (pWin->backStorage)
(void) (* pWin->drawable.pScreen->ClearBackingStore)(
pWin,
expBox.x1,
expBox.y1,
expBox.x2 - expBox.x1,
expBox.y2 - expBox.y1,
FALSE);
}
if ((pDstDrawable->type != DRAWABLE_PIXMAP) &&
(((WindowPtr)pDstDrawable)->backgroundState != None))
{
WindowPtr pWin = (WindowPtr)pDstDrawable;
/* make the exposed area screen-relative */
RegionTranslate(&rgnExposed,
pDstDrawable->x, pDstDrawable->y);
if (extents)
{
/* PaintWindowBackground doesn't clip, so we have to */
RegionIntersect(&rgnExposed, &rgnExposed, &pWin->clipList);
}
(*pWin->drawable.pScreen->PaintWindowBackground)(
(WindowPtr)pDstDrawable, &rgnExposed, PW_BACKGROUND);
if (extents)
{
RegionReset(&rgnExposed, &expBox);
}
else
RegionTranslate(&rgnExposed,
-pDstDrawable->x, -pDstDrawable->y);
}
if (prgnDstClip == &rgnDstRec)
{
RegionUninit(prgnDstClip);
}
else if (prgnDstClip != prgnSrcClip)
{
RegionDestroy(prgnDstClip);
}
if (prgnSrcClip == &rgnSrcRec)
{
RegionUninit(prgnSrcClip);
}
else
{
RegionDestroy(prgnSrcClip);
}
if (pGC->graphicsExposures)
{
/* don't look */
RegionPtr exposed = RegionCreate(NullBox, 0);
*exposed = rgnExposed;
return exposed;
}
else
{
RegionUninit(&rgnExposed);
return NULL;
}
}
/* send GraphicsExpose events, or a NoExpose event, based on the region */
void
miSendGraphicsExpose (client, pRgn, drawable, major, minor)
ClientPtr client;
RegionPtr pRgn;
XID drawable;
int major;
int minor;
{
if (pRgn && !RegionNil(pRgn))
{
xEvent *pEvent;
register xEvent *pe;
register BoxPtr pBox;
register int i;
int numRects;
numRects = RegionNumRects(pRgn);
pBox = RegionRects(pRgn);
if(!(pEvent = (xEvent *)calloc(numRects, sizeof(xEvent))))
return;
pe = pEvent;
for (i=1; i<=numRects; i++, pe++, pBox++)
{
pe->u.u.type = GraphicsExpose;
pe->u.graphicsExposure.drawable = drawable;
pe->u.graphicsExposure.x = pBox->x1;
pe->u.graphicsExposure.y = pBox->y1;
pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
pe->u.graphicsExposure.count = numRects - i;
pe->u.graphicsExposure.majorEvent = major;
pe->u.graphicsExposure.minorEvent = minor;
}
TryClientEvents(client, pEvent, numRects,
(Mask)0, NoEventMask, NullGrab);
free(pEvent);
}
else
{
xEvent event = {0};
event.u.u.type = NoExpose;
event.u.noExposure.drawable = drawable;
event.u.noExposure.majorEvent = major;
event.u.noExposure.minorEvent = minor;
TryClientEvents(client, &event, 1,
(Mask)0, NoEventMask, NullGrab);
}
}
void
miSendExposures(pWin, pRgn, dx, dy)
WindowPtr pWin;
RegionPtr pRgn;
register int dx, dy;
{
register BoxPtr pBox;
int numRects;
register xEvent *pEvent, *pe;
register int i;
pBox = RegionRects(pRgn);
numRects = RegionNumRects(pRgn);
if(!(pEvent = (xEvent *) calloc(numRects, sizeof(xEvent))))
return;
for (i=numRects, pe = pEvent; --i >= 0; pe++, pBox++)
{
pe->u.u.type = Expose;
pe->u.expose.window = pWin->drawable.id;
pe->u.expose.x = pBox->x1 - dx;
pe->u.expose.y = pBox->y1 - dy;
pe->u.expose.width = pBox->x2 - pBox->x1;
pe->u.expose.height = pBox->y2 - pBox->y1;
pe->u.expose.count = i;
}
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
int scrnum = pWin->drawable.pScreen->myNum;
int x = 0, y = 0;
XID realWin = 0;
if(!pWin->parent) {
x = panoramiXdataPtr[scrnum].x;
y = panoramiXdataPtr[scrnum].y;
pWin = screenInfo.screens[0]->root;
realWin = pWin->drawable.id;
} else if (scrnum) {
PanoramiXRes *win;
win = PanoramiXFindIDByScrnum(XRT_WINDOW,
pWin->drawable.id, scrnum);
if(!win) {
free(pEvent);
return;
}
realWin = win->info[0].id;
pWin = LookupIDByType(realWin, RT_WINDOW);
}
if(x || y || scrnum)
for (i = 0; i < numRects; i++) {
pEvent[i].u.expose.window = realWin;
pEvent[i].u.expose.x += x;
pEvent[i].u.expose.y += y;
}
}
#endif
DeliverEvents(pWin, pEvent, numRects, NullWindow);
free(pEvent);
}
void
miWindowExposures(pWin, prgn, other_exposed)
WindowPtr pWin;
register RegionPtr prgn, other_exposed;
{
RegionPtr exposures = prgn;
if (pWin->backStorage && prgn)
/*
* in some cases, backing store will cause a different
* region to be exposed than needs to be repainted
* (like when a window is mapped). RestoreAreas is
* allowed to return a region other than prgn,
* in which case this routine will free the resultant
* region. If exposures is null, then no events will
* be sent to the client; if prgn is empty
* no areas will be repainted.
*/
exposures = (*pWin->drawable.pScreen->RestoreAreas)(pWin, prgn);
if ((prgn && !RegionNil(prgn)) ||
(exposures && !RegionNil(exposures)) || other_exposed)
{
RegionRec expRec;
int clientInterested;
/*
* Restore from backing-store FIRST.
*/
clientInterested = (pWin->eventMask|wOtherEventMasks(pWin)) & ExposureMask;
if (other_exposed)
{
if (exposures)
{
RegionUnion(other_exposed,
exposures,
other_exposed);
if (exposures != prgn)
RegionDestroy(exposures);
}
exposures = other_exposed;
}
if (clientInterested && exposures && (RegionNumRects(exposures) > RECTLIMIT))
{
/*
* If we have LOTS of rectangles, we decide to take the extents
* and force an exposure on that. This should require much less
* work overall, on both client and server. This is cheating, but
* isn't prohibited by the protocol ("spontaneous combustion" :-).
*/
BoxRec box;
box = *RegionExtents(exposures);
if (exposures == prgn) {
exposures = &expRec;
RegionInit(exposures, &box, 1);
RegionReset(prgn, &box);
} else {
RegionReset(exposures, &box);
RegionUnion(prgn, prgn, exposures);
}
/* PaintWindowBackground doesn't clip, so we have to */
RegionIntersect(prgn, prgn, &pWin->clipList);
/* need to clear out new areas of backing store, too */
if (pWin->backStorage)
(void) (* pWin->drawable.pScreen->ClearBackingStore)(
pWin,
box.x1 - pWin->drawable.x,
box.y1 - pWin->drawable.y,
box.x2 - box.x1,
box.y2 - box.y1,
FALSE);
}
if (prgn && !RegionNil(prgn))
(*pWin->drawable.pScreen->PaintWindowBackground)(pWin, prgn, PW_BACKGROUND);
if (clientInterested && exposures && !RegionNil(exposures))
miSendExposures(pWin, exposures,
pWin->drawable.x, pWin->drawable.y);
if (exposures == &expRec)
{
RegionUninit(exposures);
}
else if (exposures && exposures != prgn && exposures != other_exposed)
RegionDestroy(exposures);
if (prgn)
RegionEmpty(prgn);
}
else if (exposures && exposures != prgn)
RegionDestroy(exposures);
}
/*
this code is highly unlikely. it is not haile selassie.
there is some hair here. we can't just use the window's
clip region as it is, because if we are painting the border,
the border is not in the client area and so we will be excluded
when we validate the GC, and if we are painting a parent-relative
background, the area we want to paint is in some other window.
since we trust the code calling us to tell us to paint only areas
that are really ours, we will temporarily give the window a
clipList the size of the whole screen and an origin at (0,0).
this more or less assumes that ddX code will do translation
based on the window's absolute position, and that ValidateGC will
look at clipList, and that no other fields from the
window will be used. it's not possible to just draw
in the root because it may be a different depth.
to get the tile to align correctly we set the GC's tile origin to
be the (x,y) of the window's upper left corner, after which we
get the right bits when drawing into the root.
because the clip_mask is being set to None, we may call DoChangeGC with
fPointer set true, thus we no longer need to install the background or
border tile in the resource table.
*/
static RESTYPE ResType = 0;
static int numGCs = 0;
static GCPtr screenContext[MAXSCREENS];
/*ARGSUSED*/
static int
tossGC (
void * value,
XID id)
{
GCPtr pGC = (GCPtr)value;
screenContext[pGC->pScreen->myNum] = (GCPtr)NULL;
FreeGC (pGC, id);
numGCs--;
if (!numGCs)
ResType = 0;
return 0;
}
void
miPaintWindow(pWin, prgn, what)
register WindowPtr pWin;
RegionPtr prgn;
int what;
{
int status;
Bool usingScratchGC = FALSE;
WindowPtr pRoot;
#define FUNCTION 0
#define FOREGROUND 1
#define TILE 2
#define FILLSTYLE 3
#define ABSX 4
#define ABSY 5
#define CLIPMASK 6
#define SUBWINDOW 7
#define COUNT_BITS 8
ChangeGCVal gcval[7];
ChangeGCVal newValues [COUNT_BITS] = {{ 0 }};
BITS32 gcmask, index, mask;
RegionRec prgnWin = {0};
DDXPointRec oldCorner = {0};
BoxRec box = {0};
WindowPtr pBgWin;
GCPtr pGC;
register int i;
register BoxPtr pbox;
register ScreenPtr pScreen = pWin->drawable.pScreen;
register xRectangle *prect;
int numRects;
gcmask = 0;
if (what == PW_BACKGROUND)
{
switch (pWin->backgroundState) {
case None:
return;
case ParentRelative:
(*pWin->parent->drawable.pScreen->PaintWindowBackground)(pWin->parent, prgn, what);
return;
case BackgroundPixel:
newValues[FOREGROUND].val = pWin->background.pixel;
newValues[FILLSTYLE].val = FillSolid;
gcmask |= GCForeground | GCFillStyle;
break;
case BackgroundPixmap:
newValues[TILE].ptr = (void *)pWin->background.pixmap;
newValues[FILLSTYLE].val = FillTiled;
gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
break;
}
}
else
{
if (pWin->borderIsPixel)
{
newValues[FOREGROUND].val = pWin->border.pixel;
newValues[FILLSTYLE].val = FillSolid;
gcmask |= GCForeground | GCFillStyle;
}
else
{
newValues[TILE].ptr = (void *)pWin->border.pixmap;
newValues[FILLSTYLE].val = FillTiled;
gcmask |= GCTile | GCFillStyle | GCTileStipXOrigin | GCTileStipYOrigin;
}
}
prect = (xRectangle *)calloc(RegionNumRects(prgn), sizeof(xRectangle));
if (!prect)
return;
newValues[FUNCTION].val = GXcopy;
gcmask |= GCFunction | GCClipMask;
i = pScreen->myNum;
pRoot = screenInfo.screens[i]->root;
pBgWin = pWin;
if (what == PW_BORDER)
{
while (pBgWin->backgroundState == ParentRelative)
pBgWin = pBgWin->parent;
}
if ((pWin->drawable.depth != pRoot->drawable.depth) ||
(pWin->drawable.bitsPerPixel != pRoot->drawable.bitsPerPixel))
{
usingScratchGC = TRUE;
pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
if (!pGC)
{
free(prect);
return;
}
/*
* mash the clip list so we can paint the border by
* mangling the window in place, pretending it
* spans the entire screen
*/
if (what == PW_BORDER)
{
prgnWin = pWin->clipList;
oldCorner.x = pWin->drawable.x;
oldCorner.y = pWin->drawable.y;
pWin->drawable.x = pWin->drawable.y = 0;
box.x1 = 0;
box.y1 = 0;
box.x2 = pScreen->width;
box.y2 = pScreen->height;
RegionInit(&pWin->clipList, &box, 1);
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
newValues[ABSX].val = pBgWin->drawable.x;
newValues[ABSY].val = pBgWin->drawable.y;
}
else
{
newValues[ABSX].val = 0;
newValues[ABSY].val = 0;
}
} else {
/*
* draw the background to the root window
*/
if (screenContext[i] == (GCPtr)NULL)
{
if (!ResType && !(ResType = CreateNewResourceType(tossGC)))
{
free(prect);
return;
}
screenContext[i] = CreateGC((DrawablePtr)pWin, (BITS32) 0,
(XID *)NULL, &status);
if (!screenContext[i])
{
free(prect);
return;
}
numGCs++;
if (!AddResource(FakeClientID(0), ResType,
(void *)screenContext[i]))
{
free(prect);
return;
}
}
pGC = screenContext[i];
newValues[SUBWINDOW].val = IncludeInferiors;
newValues[ABSX].val = pBgWin->drawable.x;
newValues[ABSY].val = pBgWin->drawable.y;
gcmask |= GCSubwindowMode;
pWin = pRoot;
}
if (pWin->backStorage)
(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeVisBack);
mask = gcmask;
gcmask = 0;
i = 0;
while (mask) {
index = lowbit (mask);
mask &= ~index;
switch (index) {
case GCFunction:
if (pGC->alu != newValues[FUNCTION].val) {
gcmask |= index;
gcval[i++].val = newValues[FUNCTION].val;
}
break;
case GCTileStipXOrigin:
if ( pGC->patOrg.x != newValues[ABSX].val) {
gcmask |= index;
gcval[i++].val = newValues[ABSX].val;
}
break;
case GCTileStipYOrigin:
if ( pGC->patOrg.y != newValues[ABSY].val) {
gcmask |= index;
gcval[i++].val = newValues[ABSY].val;
}
break;
case GCClipMask:
if ( pGC->clientClipType != CT_NONE) {
gcmask |= index;
gcval[i++].val = CT_NONE;
}
break;
case GCSubwindowMode:
if ( pGC->subWindowMode != newValues[SUBWINDOW].val) {
gcmask |= index;
gcval[i++].val = newValues[SUBWINDOW].val;
}
break;
case GCTile:
if (pGC->tileIsPixel || pGC->tile.pixmap != newValues[TILE].ptr)
{
gcmask |= index;
gcval[i++].ptr = newValues[TILE].ptr;
}
break;
case GCFillStyle:
if ( pGC->fillStyle != newValues[FILLSTYLE].val) {
gcmask |= index;
gcval[i++].val = newValues[FILLSTYLE].val;
}
break;
case GCForeground:
if ( pGC->fgPixel != newValues[FOREGROUND].val) {
gcmask |= index;
gcval[i++].val = newValues[FOREGROUND].val;
}
break;
}
}
if (gcmask)
dixChangeGC(NullClient, pGC, gcmask, NULL, gcval);
if (pWin->drawable.serialNumber != pGC->serialNumber)
ValidateGC((DrawablePtr)pWin, pGC);
numRects = RegionNumRects(prgn);
pbox = RegionRects(prgn);
for (i= numRects; --i >= 0; pbox++, prect++)
{
prect->x = pbox->x1 - pWin->drawable.x;
prect->y = pbox->y1 - pWin->drawable.y;
prect->width = pbox->x2 - pbox->x1;
prect->height = pbox->y2 - pbox->y1;
}
prect -= numRects;
(*pGC->ops->PolyFillRect)((DrawablePtr)pWin, pGC, numRects, prect);
free(prect);
if (pWin->backStorage)
(*pWin->drawable.pScreen->DrawGuarantee) (pWin, pGC, GuaranteeNothing);
if (usingScratchGC)
{
if (what == PW_BORDER)
{
RegionUninit(&pWin->clipList);
pWin->clipList = prgnWin;
pWin->drawable.x = oldCorner.x;
pWin->drawable.y = oldCorner.y;
pWin->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
FreeScratchGC(pGC);
}
}
/* MICLEARDRAWABLE -- sets the entire drawable to the background color of
* the GC. Useful when we have a scratch drawable and need to initialize
* it. */
void
miClearDrawable(pDraw, pGC)
DrawablePtr pDraw;
GCPtr pGC;
{
XID fg = pGC->fgPixel;
XID bg = pGC->bgPixel;
xRectangle rect = {0};
rect.x = 0;
rect.y = 0;
rect.width = pDraw->width;
rect.height = pDraw->height;
DoChangeGC(pGC, GCForeground, &bg, 0);
ValidateGC(pDraw, pGC);
(*pGC->ops->PolyFillRect)(pDraw, pGC, 1, &rect);
DoChangeGC(pGC, GCForeground, &fg, 0);
ValidateGC(pDraw, pGC);
}

View File

@@ -0,0 +1,815 @@
/************************************************************
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Author: Bob Scheifler, MIT X Consortium
********************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <math.h>
#include <nx-X11/X.h>
#include <nx-X11/Xprotostr.h>
#include "regionstr.h"
#include "gcstruct.h"
#include "pixmapstr.h"
#include "mifpoly.h"
#include "mi.h"
#include "mifillarc.h"
#define QUADRANT (90 * 64)
#define HALFCIRCLE (180 * 64)
#define QUADRANT3 (270 * 64)
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define Dsin(d) sin((double)d*(M_PI/11520.0))
#define Dcos(d) cos((double)d*(M_PI/11520.0))
void
miFillArcSetup(arc, info)
register xArc *arc;
register miFillArcRec *info;
{
info->y = arc->height >> 1;
info->dy = arc->height & 1;
info->yorg = arc->y + info->y;
info->dx = arc->width & 1;
info->xorg = arc->x + (arc->width >> 1) + info->dx;
info->dx = 1 - info->dx;
if (arc->width == arc->height)
{
/* (2x - 2xorg)^2 = d^2 - (2y - 2yorg)^2 */
/* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
info->ym = 8;
info->xm = 8;
info->yk = info->y << 3;
if (!info->dx)
{
info->xk = 0;
info->e = -1;
}
else
{
info->y++;
info->yk += 4;
info->xk = -4;
info->e = - (info->y << 3);
}
}
else
{
/* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
/* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
info->ym = (arc->width * arc->width) << 3;
info->xm = (arc->height * arc->height) << 3;
info->yk = info->y * info->ym;
if (!info->dy)
info->yk -= info->ym >> 1;
if (!info->dx)
{
info->xk = 0;
info->e = - (info->xm >> 3);
}
else
{
info->y++;
info->yk += info->ym;
info->xk = -(info->xm >> 1);
info->e = info->xk - info->yk;
}
}
}
void
miFillArcDSetup(arc, info)
register xArc *arc;
register miFillArcDRec *info;
{
/* h^2 * (2x - 2xorg)^2 = w^2 * h^2 - w^2 * (2y - 2yorg)^2 */
/* even: xorg = yorg = 0 odd: xorg = .5, yorg = -.5 */
info->y = arc->height >> 1;
info->dy = arc->height & 1;
info->yorg = arc->y + info->y;
info->dx = arc->width & 1;
info->xorg = arc->x + (arc->width >> 1) + info->dx;
info->dx = 1 - info->dx;
info->ym = ((double)arc->width) * (arc->width * 8);
info->xm = ((double)arc->height) * (arc->height * 8);
info->yk = info->y * info->ym;
if (!info->dy)
info->yk -= info->ym / 2.0;
if (!info->dx)
{
info->xk = 0;
info->e = - (info->xm / 8.0);
}
else
{
info->y++;
info->yk += info->ym;
info->xk = -info->xm / 2.0;
info->e = info->xk - info->yk;
}
}
static void
miGetArcEdge(
register xArc *arc,
register miSliceEdgePtr edge,
int k,
Bool top,
Bool left )
{
register int xady, y;
y = arc->height >> 1;
if (!(arc->width & 1))
y++;
if (!top)
{
y = -y;
if (arc->height & 1)
y--;
}
xady = k + y * edge->dx;
if (xady <= 0)
edge->x = - ((-xady) / edge->dy + 1);
else
edge->x = (xady - 1) / edge->dy;
edge->e = xady - edge->x * edge->dy;
if ((top && (edge->dx < 0)) || (!top && (edge->dx > 0)))
edge->e = edge->dy - edge->e + 1;
if (left)
edge->x++;
edge->x += arc->x + (arc->width >> 1);
if (edge->dx > 0)
{
edge->deltax = 1;
edge->stepx = edge->dx / edge->dy;
edge->dx = edge->dx % edge->dy;
}
else
{
edge->deltax = -1;
edge->stepx = - ((-edge->dx) / edge->dy);
edge->dx = (-edge->dx) % edge->dy;
}
if (!top)
{
edge->deltax = -edge->deltax;
edge->stepx = -edge->stepx;
}
}
void
miEllipseAngleToSlope (angle, width, height, dxp, dyp, d_dxp, d_dyp)
int angle;
int width;
int height;
int *dxp;
int *dyp;
double *d_dxp;
double *d_dyp;
{
int dx, dy;
double d_dx, d_dy, scale;
Bool negative_dx, negative_dy;
switch (angle) {
case 0:
*dxp = -1;
*dyp = 0;
if (d_dxp) {
*d_dxp = width / 2.0;
*d_dyp = 0;
}
break;
case QUADRANT:
*dxp = 0;
*dyp = 1;
if (d_dxp) {
*d_dxp = 0;
*d_dyp = - height / 2.0;
}
break;
case HALFCIRCLE:
*dxp = 1;
*dyp = 0;
if (d_dxp) {
*d_dxp = - width / 2.0;
*d_dyp = 0;
}
break;
case QUADRANT3:
*dxp = 0;
*dyp = -1;
if (d_dxp) {
*d_dxp = 0;
*d_dyp = height / 2.0;
}
break;
default:
d_dx = Dcos(angle) * width;
d_dy = Dsin(angle) * height;
if (d_dxp) {
*d_dxp = d_dx / 2.0;
*d_dyp = - d_dy / 2.0;
}
negative_dx = FALSE;
if (d_dx < 0.0)
{
d_dx = -d_dx;
negative_dx = TRUE;
}
negative_dy = FALSE;
if (d_dy < 0.0)
{
d_dy = -d_dy;
negative_dy = TRUE;
}
scale = d_dx;
if (d_dy > d_dx)
scale = d_dy;
dx = floor ((d_dx * 32768) / scale + 0.5);
if (negative_dx)
dx = -dx;
*dxp = dx;
dy = floor ((d_dy * 32768) / scale + 0.5);
if (negative_dy)
dy = -dy;
*dyp = dy;
break;
}
}
static void
miGetPieEdge(
register xArc *arc,
register int angle,
register miSliceEdgePtr edge,
Bool top,
Bool left )
{
register int k;
int dx, dy;
miEllipseAngleToSlope (angle, arc->width, arc->height, &dx, &dy, 0, 0);
if (dy == 0)
{
edge->x = left ? -65536 : 65536;
edge->stepx = 0;
edge->e = 0;
edge->dx = -1;
return;
}
if (dx == 0)
{
edge->x = arc->x + (arc->width >> 1);
if (left && (arc->width & 1))
edge->x++;
else if (!left && !(arc->width & 1))
edge->x--;
edge->stepx = 0;
edge->e = 0;
edge->dx = -1;
return;
}
if (dy < 0) {
dx = -dx;
dy = -dy;
}
k = (arc->height & 1) ? dx : 0;
if (arc->width & 1)
k += dy;
edge->dx = dx << 1;
edge->dy = dy << 1;
miGetArcEdge(arc, edge, k, top, left);
}
void
miFillArcSliceSetup(arc, slice, pGC)
register xArc *arc;
register miArcSliceRec *slice;
GCPtr pGC;
{
register int angle1, angle2;
angle1 = arc->angle1;
if (arc->angle2 < 0)
{
angle2 = angle1;
angle1 += arc->angle2;
}
else
angle2 = angle1 + arc->angle2;
while (angle1 < 0)
angle1 += FULLCIRCLE;
while (angle1 >= FULLCIRCLE)
angle1 -= FULLCIRCLE;
while (angle2 < 0)
angle2 += FULLCIRCLE;
while (angle2 >= FULLCIRCLE)
angle2 -= FULLCIRCLE;
slice->min_top_y = 0;
slice->max_top_y = arc->height >> 1;
slice->min_bot_y = 1 - (arc->height & 1);
slice->max_bot_y = slice->max_top_y - 1;
slice->flip_top = FALSE;
slice->flip_bot = FALSE;
if (pGC->arcMode == ArcPieSlice)
{
slice->edge1_top = (angle1 < HALFCIRCLE);
slice->edge2_top = (angle2 <= HALFCIRCLE);
if ((angle2 == 0) || (angle1 == HALFCIRCLE))
{
if (angle2 ? slice->edge2_top : slice->edge1_top)
slice->min_top_y = slice->min_bot_y;
else
slice->min_top_y = arc->height;
slice->min_bot_y = 0;
}
else if ((angle1 == 0) || (angle2 == HALFCIRCLE))
{
slice->min_top_y = slice->min_bot_y;
if (angle1 ? slice->edge1_top : slice->edge2_top)
slice->min_bot_y = arc->height;
else
slice->min_bot_y = 0;
}
else if (slice->edge1_top == slice->edge2_top)
{
if (angle2 < angle1)
{
slice->flip_top = slice->edge1_top;
slice->flip_bot = !slice->edge1_top;
}
else if (slice->edge1_top)
{
slice->min_top_y = 1;
slice->min_bot_y = arc->height;
}
else
{
slice->min_bot_y = 0;
slice->min_top_y = arc->height;
}
}
miGetPieEdge(arc, angle1, &slice->edge1,
slice->edge1_top, !slice->edge1_top);
miGetPieEdge(arc, angle2, &slice->edge2,
slice->edge2_top, slice->edge2_top);
}
else
{
double w2, h2, x1, y1, x2, y2, dx, dy, scale;
int signdx, signdy, y, k;
Bool isInt1 = TRUE, isInt2 = TRUE;
w2 = (double)arc->width / 2.0;
h2 = (double)arc->height / 2.0;
if ((angle1 == 0) || (angle1 == HALFCIRCLE))
{
x1 = angle1 ? -w2 : w2;
y1 = 0.0;
}
else if ((angle1 == QUADRANT) || (angle1 == QUADRANT3))
{
x1 = 0.0;
y1 = (angle1 == QUADRANT) ? h2 : -h2;
}
else
{
isInt1 = FALSE;
x1 = Dcos(angle1) * w2;
y1 = Dsin(angle1) * h2;
}
if ((angle2 == 0) || (angle2 == HALFCIRCLE))
{
x2 = angle2 ? -w2 : w2;
y2 = 0.0;
}
else if ((angle2 == QUADRANT) || (angle2 == QUADRANT3))
{
x2 = 0.0;
y2 = (angle2 == QUADRANT) ? h2 : -h2;
}
else
{
isInt2 = FALSE;
x2 = Dcos(angle2) * w2;
y2 = Dsin(angle2) * h2;
}
dx = x2 - x1;
dy = y2 - y1;
if (arc->height & 1)
{
y1 -= 0.5;
y2 -= 0.5;
}
if (arc->width & 1)
{
x1 += 0.5;
x2 += 0.5;
}
if (dy < 0.0)
{
dy = -dy;
signdy = -1;
}
else
signdy = 1;
if (dx < 0.0)
{
dx = -dx;
signdx = -1;
}
else
signdx = 1;
if (isInt1 && isInt2)
{
slice->edge1.dx = dx * 2;
slice->edge1.dy = dy * 2;
}
else
{
scale = (dx > dy) ? dx : dy;
slice->edge1.dx = floor((dx * 32768) / scale + .5);
slice->edge1.dy = floor((dy * 32768) / scale + .5);
}
if (!slice->edge1.dy)
{
if (signdx < 0)
{
y = floor(y1 + 1.0);
if (y >= 0)
{
slice->min_top_y = y;
slice->min_bot_y = arc->height;
}
else
{
slice->max_bot_y = -y - (arc->height & 1);
}
}
else
{
y = floor(y1);
if (y >= 0)
slice->max_top_y = y;
else
{
slice->min_top_y = arc->height;
slice->min_bot_y = -y - (arc->height & 1);
}
}
slice->edge1_top = TRUE;
slice->edge1.x = 65536;
slice->edge1.stepx = 0;
slice->edge1.e = 0;
slice->edge1.dx = -1;
slice->edge2 = slice->edge1;
slice->edge2_top = FALSE;
}
else if (!slice->edge1.dx)
{
if (signdy < 0)
x1 -= 1.0;
slice->edge1.x = ceil(x1);
slice->edge1_top = signdy < 0;
slice->edge1.x += arc->x + (arc->width >> 1);
slice->edge1.stepx = 0;
slice->edge1.e = 0;
slice->edge1.dx = -1;
slice->edge2_top = !slice->edge1_top;
slice->edge2 = slice->edge1;
}
else
{
if (signdx < 0)
slice->edge1.dx = -slice->edge1.dx;
if (signdy < 0)
slice->edge1.dx = -slice->edge1.dx;
k = ceil(((x1 + x2) * slice->edge1.dy - (y1 + y2) * slice->edge1.dx) / 2.0);
slice->edge2.dx = slice->edge1.dx;
slice->edge2.dy = slice->edge1.dy;
slice->edge1_top = signdy < 0;
slice->edge2_top = !slice->edge1_top;
miGetArcEdge(arc, &slice->edge1, k,
slice->edge1_top, !slice->edge1_top);
miGetArcEdge(arc, &slice->edge2, k,
slice->edge2_top, slice->edge2_top);
}
}
}
#define ADDSPANS() \
pts->x = xorg - x; \
pts->y = yorg - y; \
*wids = slw; \
pts++; \
wids++; \
if (miFillArcLower(slw)) \
{ \
pts->x = xorg - x; \
pts->y = yorg + y + dy; \
pts++; \
*wids++ = slw; \
}
static void
miFillEllipseI(
DrawablePtr pDraw,
GCPtr pGC,
xArc *arc )
{
register int x, y, e;
int yk, xk, ym, xm, dx, dy, xorg, yorg;
int slw;
miFillArcRec info;
DDXPointPtr points;
register DDXPointPtr pts;
int *widths;
register int *wids;
points = (DDXPointPtr)malloc(sizeof(DDXPointRec) * arc->height);
if (!points)
return;
widths = (int *)malloc(sizeof(int) * arc->height);
if (!widths)
{
free(points);
return;
}
miFillArcSetup(arc, &info);
MIFILLARCSETUP();
if (pGC->miTranslate)
{
xorg += pDraw->x;
yorg += pDraw->y;
}
pts = points;
wids = widths;
while (y > 0)
{
MIFILLARCSTEP(slw);
ADDSPANS();
}
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
free(widths);
free(points);
}
static void
miFillEllipseD(
DrawablePtr pDraw,
GCPtr pGC,
xArc *arc )
{
register int x, y;
int xorg, yorg, dx, dy, slw;
double e, yk, xk, ym, xm;
miFillArcDRec info;
DDXPointPtr points;
register DDXPointPtr pts;
int *widths;
register int *wids;
points = (DDXPointPtr)malloc(sizeof(DDXPointRec) * arc->height);
if (!points)
return;
widths = (int *)malloc(sizeof(int) * arc->height);
if (!widths)
{
free(points);
return;
}
miFillArcDSetup(arc, &info);
MIFILLARCSETUP();
if (pGC->miTranslate)
{
xorg += pDraw->x;
yorg += pDraw->y;
}
pts = points;
wids = widths;
while (y > 0)
{
MIFILLARCSTEP(slw);
ADDSPANS();
}
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
free(widths);
free(points);
}
#define ADDSPAN(l,r) \
if (r >= l) \
{ \
pts->x = l; \
pts->y = ya; \
pts++; \
*wids++ = r - l + 1; \
}
#define ADDSLICESPANS(flip) \
if (!flip) \
{ \
ADDSPAN(xl, xr); \
} \
else \
{ \
xc = xorg - x; \
ADDSPAN(xc, xr); \
xc += slw - 1; \
ADDSPAN(xl, xc); \
}
static void
miFillArcSliceI(
DrawablePtr pDraw,
GCPtr pGC,
xArc *arc )
{
int yk, xk, ym, xm, dx, dy, xorg, yorg, slw;
register int x, y, e;
miFillArcRec info;
miArcSliceRec slice;
int ya, xl, xr, xc;
DDXPointPtr points;
register DDXPointPtr pts;
int *widths;
register int *wids;
miFillArcSetup(arc, &info);
miFillArcSliceSetup(arc, &slice, pGC);
MIFILLARCSETUP();
slw = arc->height;
if (slice.flip_top || slice.flip_bot)
slw += (arc->height >> 1) + 1;
points = (DDXPointPtr)malloc(sizeof(DDXPointRec) * slw);
if (!points)
return;
widths = (int *)malloc(sizeof(int) * slw);
if (!widths)
{
free(points);
return;
}
if (pGC->miTranslate)
{
xorg += pDraw->x;
yorg += pDraw->y;
slice.edge1.x += pDraw->x;
slice.edge2.x += pDraw->x;
}
pts = points;
wids = widths;
while (y > 0)
{
MIFILLARCSTEP(slw);
MIARCSLICESTEP(slice.edge1);
MIARCSLICESTEP(slice.edge2);
if (miFillSliceUpper(slice))
{
ya = yorg - y;
MIARCSLICEUPPER(xl, xr, slice, slw);
ADDSLICESPANS(slice.flip_top);
}
if (miFillSliceLower(slice))
{
ya = yorg + y + dy;
MIARCSLICELOWER(xl, xr, slice, slw);
ADDSLICESPANS(slice.flip_bot);
}
}
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
free(widths);
free(points);
}
static void
miFillArcSliceD(
DrawablePtr pDraw,
GCPtr pGC,
xArc *arc )
{
register int x, y;
int dx, dy, xorg, yorg, slw;
double e, yk, xk, ym, xm;
miFillArcDRec info;
miArcSliceRec slice;
int ya, xl, xr, xc;
DDXPointPtr points;
register DDXPointPtr pts;
int *widths;
register int *wids;
miFillArcDSetup(arc, &info);
miFillArcSliceSetup(arc, &slice, pGC);
MIFILLARCSETUP();
slw = arc->height;
if (slice.flip_top || slice.flip_bot)
slw += (arc->height >> 1) + 1;
points = (DDXPointPtr)malloc(sizeof(DDXPointRec) * slw);
if (!points)
return;
widths = (int *)malloc(sizeof(int) * slw);
if (!widths)
{
free(points);
return;
}
if (pGC->miTranslate)
{
xorg += pDraw->x;
yorg += pDraw->y;
slice.edge1.x += pDraw->x;
slice.edge2.x += pDraw->x;
}
pts = points;
wids = widths;
while (y > 0)
{
MIFILLARCSTEP(slw);
MIARCSLICESTEP(slice.edge1);
MIARCSLICESTEP(slice.edge2);
if (miFillSliceUpper(slice))
{
ya = yorg - y;
MIARCSLICEUPPER(xl, xr, slice, slw);
ADDSLICESPANS(slice.flip_top);
}
if (miFillSliceLower(slice))
{
ya = yorg + y + dy;
MIARCSLICELOWER(xl, xr, slice, slw);
ADDSLICESPANS(slice.flip_bot);
}
}
(*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
free(widths);
free(points);
}
/* MIPOLYFILLARC -- The public entry for the PolyFillArc request.
* Since we don't have to worry about overlapping segments, we can just
* fill each arc as it comes.
*/
void
miPolyFillArc(pDraw, pGC, narcs, parcs)
DrawablePtr pDraw;
GCPtr pGC;
int narcs;
xArc *parcs;
{
register int i;
register xArc *arc;
for(i = narcs, arc = parcs; --i >= 0; arc++)
{
if (miFillArcEmpty(arc))
continue;;
if ((arc->angle2 >= FULLCIRCLE) || (arc->angle2 <= -FULLCIRCLE))
{
if (miCanFillArc(arc))
miFillEllipseI(pDraw, pGC, arc);
else
miFillEllipseD(pDraw, pGC, arc);
}
else
{
if (miCanFillArc(arc))
miFillArcSliceI(pDraw, pGC, arc);
else
miFillArcSliceD(pDraw, pGC, arc);
}
}
}

View File

@@ -0,0 +1,214 @@
/************************************************************
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
********************************************************/
#ifndef __MIFILLARC_H__
#define __MIFILLARC_H__
#define FULLCIRCLE (360 * 64)
typedef struct _miFillArc {
int xorg, yorg;
int y;
int dx, dy;
int e;
int ym, yk, xm, xk;
} miFillArcRec;
/* could use 64-bit integers */
typedef struct _miFillArcD {
int xorg, yorg;
int y;
int dx, dy;
double e;
double ym, yk, xm, xk;
} miFillArcDRec;
#define miFillArcEmpty(arc) (!(arc)->angle2 || \
!(arc)->width || !(arc)->height || \
(((arc)->width == 1) && ((arc)->height & 1)))
#define miCanFillArc(arc) (((arc)->width == (arc)->height) || \
(((arc)->width <= 800) && ((arc)->height <= 800)))
#define MIFILLARCSETUP() \
x = 0; \
y = info.y; \
e = info.e; \
xk = info.xk; \
xm = info.xm; \
yk = info.yk; \
ym = info.ym; \
dx = info.dx; \
dy = info.dy; \
xorg = info.xorg; \
yorg = info.yorg
#define MIFILLARCSTEP(slw) \
e += yk; \
while (e >= 0) \
{ \
x++; \
xk -= xm; \
e += xk; \
} \
y--; \
yk -= ym; \
slw = (x << 1) + dx; \
if ((e == xk) && (slw > 1)) \
slw--
#define MIFILLCIRCSTEP(slw) MIFILLARCSTEP(slw)
#define MIFILLELLSTEP(slw) MIFILLARCSTEP(slw)
#define miFillArcLower(slw) (((y + dy) != 0) && ((slw > 1) || (e != xk)))
typedef struct _miSliceEdge {
int x;
int stepx;
int deltax;
int e;
int dy;
int dx;
} miSliceEdgeRec, *miSliceEdgePtr;
typedef struct _miArcSlice {
miSliceEdgeRec edge1, edge2;
int min_top_y, max_top_y;
int min_bot_y, max_bot_y;
Bool edge1_top, edge2_top;
Bool flip_top, flip_bot;
} miArcSliceRec;
#define MIARCSLICESTEP(edge) \
edge.x -= edge.stepx; \
edge.e -= edge.dx; \
if (edge.e <= 0) \
{ \
edge.x -= edge.deltax; \
edge.e += edge.dy; \
}
#define miFillSliceUpper(slice) \
((y >= slice.min_top_y) && (y <= slice.max_top_y))
#define miFillSliceLower(slice) \
((y >= slice.min_bot_y) && (y <= slice.max_bot_y))
#define MIARCSLICEUPPER(xl,xr,slice,slw) \
xl = xorg - x; \
xr = xl + slw - 1; \
if (slice.edge1_top && (slice.edge1.x < xr)) \
xr = slice.edge1.x; \
if (slice.edge2_top && (slice.edge2.x > xl)) \
xl = slice.edge2.x;
#define MIARCSLICELOWER(xl,xr,slice,slw) \
xl = xorg - x; \
xr = xl + slw - 1; \
if (!slice.edge1_top && (slice.edge1.x > xl)) \
xl = slice.edge1.x; \
if (!slice.edge2_top && (slice.edge2.x < xr)) \
xr = slice.edge2.x;
#define MIWIDEARCSETUP(x,y,dy,slw,e,xk,xm,yk,ym) \
x = 0; \
y = slw >> 1; \
yk = y << 3; \
xm = 8; \
ym = 8; \
if (dy) \
{ \
xk = 0; \
if (slw & 1) \
e = -1; \
else \
e = -(y << 2) - 2; \
} \
else \
{ \
y++; \
yk += 4; \
xk = -4; \
if (slw & 1) \
e = -(y << 2) - 3; \
else \
e = - (y << 3); \
}
#define MIFILLINARCSTEP(slw) \
ine += inyk; \
while (ine >= 0) \
{ \
inx++; \
inxk -= inxm; \
ine += inxk; \
} \
iny--; \
inyk -= inym; \
slw = (inx << 1) + dx; \
if ((ine == inxk) && (slw > 1)) \
slw--
#define miFillInArcLower(slw) (((iny + dy) != 0) && \
((slw > 1) || (ine != inxk)))
extern int miFreeArcCache(
void * /*data*/,
XID /*id*/
);
extern struct finalSpan *realAllocSpan(
void
);
extern void miFillArcSetup(
xArc * /*arc*/,
miFillArcRec * /*info*/
);
extern void miFillArcDSetup(
xArc * /*arc*/,
miFillArcDRec * /*info*/
);
extern void miEllipseAngleToSlope(
int /*angle*/,
int /*width*/,
int /*height*/,
int * /*dxp*/,
int * /*dyp*/,
double * /*d_dxp*/,
double * /*d_dyp*/
);
extern void miFillArcSliceSetup(
xArc * /*arc*/,
miArcSliceRec * /*slice*/,
GCPtr /*pGC*/
);
#endif /* __MIFILLARC_H__ */

View File

@@ -0,0 +1,142 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xprotostr.h>
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmap.h"
#include "mi.h"
#include "misc.h"
/* mi rectangles
written by newman, with debts to all and sundry
*/
/* MIPOLYFILLRECT -- public entry for PolyFillRect request
* very straight forward: translate rectangles if necessary
* then call FillSpans to fill each rectangle. We let FillSpans worry about
* clipping to the destination
*/
void
miPolyFillRect(pDrawable, pGC, nrectFill, prectInit)
DrawablePtr pDrawable;
GCPtr pGC;
int nrectFill; /* number of rectangles to fill */
xRectangle *prectInit; /* Pointer to first rectangle to fill */
{
int i;
register int height;
register int width;
register xRectangle *prect;
int xorg;
register int yorg;
int maxheight;
DDXPointPtr pptFirst;
register DDXPointPtr ppt;
int *pwFirst;
register int *pw;
if (pGC->miTranslate)
{
xorg = pDrawable->x;
yorg = pDrawable->y;
prect = prectInit;
maxheight = 0;
for (i = 0; i<nrectFill; i++, prect++)
{
prect->x += xorg;
prect->y += yorg;
maxheight = max(maxheight, prect->height);
}
}
else
{
prect = prectInit;
maxheight = 0;
for (i = 0; i<nrectFill; i++, prect++)
maxheight = max(maxheight, prect->height);
}
pptFirst = (DDXPointPtr) malloc(maxheight * sizeof(DDXPointRec));
pwFirst = (int *) malloc(maxheight * sizeof(int));
if(!pptFirst || !pwFirst)
{
if (pwFirst) free(pwFirst);
if (pptFirst) free(pptFirst);
return;
}
prect = prectInit;
while(nrectFill--)
{
ppt = pptFirst;
pw = pwFirst;
height = prect->height;
width = prect->width;
xorg = prect->x;
yorg = prect->y;
while(height--)
{
*pw++ = width;
ppt->x = xorg;
ppt->y = yorg;
ppt++;
yorg++;
}
(* pGC->ops->FillSpans)(pDrawable, pGC,
prect->height, pptFirst, pwFirst,
1);
prect++;
}
free(pwFirst);
free(pptFirst);
}

View File

@@ -0,0 +1,109 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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 __MIFPOLY_H__
#define __MIFPOLY_H__
#define EPSILON 0.000001
#define ISEQUAL(a,b) (Fabs((a) - (b)) <= EPSILON)
#define UNEQUAL(a,b) (Fabs((a) - (b)) > EPSILON)
#define WITHINHALF(a, b) (((a) - (b) > 0.0) ? (a) - (b) < 0.5 : \
(b) - (a) <= 0.5)
#define ROUNDTOINT(x) ((int) (((x) > 0.0) ? ((x) + 0.5) : ((x) - 0.5)))
#define ISZERO(x) (Fabs((x)) <= EPSILON)
#define PTISEQUAL(a,b) (ISEQUAL(a.x,b.x) && ISEQUAL(a.y,b.y))
#define PTUNEQUAL(a,b) (UNEQUAL(a.x,b.x) || UNEQUAL(a.y,b.y))
#define PtEqual(a, b) (((a).x == (b).x) && ((a).y == (b).y))
#define NotEnd 0
#define FirstEnd 1
#define SecondEnd 2
#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - for 11o miter cutoff */
#define D2SECANT 5.21671526231167 /* 1/2*sin(11/2) - max extension per width */
#ifdef NOINLINEICEIL
#define ICEIL(x) ((int)ceil(x))
#else
#ifdef __GNUC__
static __inline int ICEIL(double x)
{
int _cTmp = x;
return ((x == _cTmp) || (x < 0.0)) ? _cTmp : _cTmp+1;
}
#else
#define ICEIL(x) ((((x) == (_cTmp = (x))) || ((x) < 0.0)) ? _cTmp : _cTmp+1)
#define ICEILTEMPDECL static int _cTmp;
#endif
#endif
/* Point with sub-pixel positioning. In this case we use doubles, but
* see mifpolycon.c for other suggestions
*/
typedef struct _SppPoint {
double x, y;
} SppPointRec, *SppPointPtr;
typedef struct _SppArc {
double x, y, width, height;
double angle1, angle2;
} SppArcRec, *SppArcPtr;
/* mifpolycon.c */
extern void miFillSppPoly(
DrawablePtr /*dst*/,
GCPtr /*pgc*/,
int /*count*/,
SppPointPtr /*ptsIn*/,
int /*xTrans*/,
int /*yTrans*/,
double /*xFtrans*/,
double /*yFtrans*/
);
#endif /* __MIFPOLY_H__ */

View File

@@ -0,0 +1,282 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <math.h>
#include <nx-X11/X.h>
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "mifpoly.h"
static int GetFPolyYBounds(register SppPointPtr pts, int n, double yFtrans,
int *by, int *ty);
#ifdef ICEILTEMPDECL
ICEILTEMPDECL
#endif
/*
* Written by Todd Newman; April. 1987.
*
* Fill a convex polygon. If the given polygon
* is not convex, then the result is undefined.
* The algorithm is to order the edges from smallest
* y to largest by partitioning the array into a left
* edge list and a right edge list. The algorithm used
* to traverse each edge is digital differencing analyzer
* line algorithm with y as the major axis. There's some funny linear
* interpolation involved because of the subpixel postioning.
*/
void
miFillSppPoly(dst, pgc, count, ptsIn, xTrans, yTrans, xFtrans, yFtrans)
DrawablePtr dst;
GCPtr pgc;
int count; /* number of points */
SppPointPtr ptsIn; /* the points */
int xTrans, yTrans; /* Translate each point by this */
double xFtrans, yFtrans; /* translate before conversion
by this amount. This provides
a mechanism to match rounding
errors with any shape that must
meet the polygon exactly.
*/
{
double xl = 0.0, xr = 0.0, /* x vals of left and right edges */
ml = 0.0, /* left edge slope */
mr = 0.0, /* right edge slope */
dy, /* delta y */
i; /* loop counter */
int y, /* current scanline */
j,
imin, /* index of vertex with smallest y */
ymin, /* y-extents of polygon */
ymax,
*width,
*FirstWidth, /* output buffer */
*Marked; /* set if this vertex has been used */
register int left, right, /* indices to first endpoints */
nextleft,
nextright; /* indices to second endpoints */
DDXPointPtr ptsOut,
FirstPoint; /* output buffer */
if (pgc->miTranslate)
{
xTrans += dst->x;
yTrans += dst->y;
}
imin = GetFPolyYBounds(ptsIn, count, yFtrans, &ymin, &ymax);
y = ymax - ymin + 1;
if ((count < 3) || (y <= 0))
return;
ptsOut = FirstPoint = (DDXPointPtr)malloc(sizeof(DDXPointRec) * y);
width = FirstWidth = (int *) malloc(sizeof(int) * y);
Marked = (int *) malloc(sizeof(int) * count);
if(!ptsOut || !width || !Marked)
{
if (Marked) free(Marked);
if (width) free(width);
if (ptsOut) free(ptsOut);
return;
}
for(j = 0; j < count; j++)
Marked[j] = 0;
nextleft = nextright = imin;
Marked[imin] = -1;
y = ICEIL(ptsIn[nextleft].y + yFtrans);
/*
* loop through all edges of the polygon
*/
do
{
/* add a left edge if we need to */
if ((y > (ptsIn[nextleft].y + yFtrans) ||
ISEQUAL(y, ptsIn[nextleft].y + yFtrans)) &&
Marked[nextleft] != 1)
{
Marked[nextleft]++;
left = nextleft++;
/* find the next edge, considering the end conditions */
if (nextleft >= count)
nextleft = 0;
/* now compute the starting point and slope */
dy = ptsIn[nextleft].y - ptsIn[left].y;
if (dy != 0.0)
{
ml = (ptsIn[nextleft].x - ptsIn[left].x) / dy;
dy = y - (ptsIn[left].y + yFtrans);
xl = (ptsIn[left].x + xFtrans) + ml * max(dy, 0);
}
}
/* add a right edge if we need to */
if ((y > ptsIn[nextright].y + yFtrans) ||
(ISEQUAL(y, ptsIn[nextright].y + yFtrans)
&& Marked[nextright] != 1))
{
Marked[nextright]++;
right = nextright--;
/* find the next edge, considering the end conditions */
if (nextright < 0)
nextright = count - 1;
/* now compute the starting point and slope */
dy = ptsIn[nextright].y - ptsIn[right].y;
if (dy != 0.0)
{
mr = (ptsIn[nextright].x - ptsIn[right].x) / dy;
dy = y - (ptsIn[right].y + yFtrans);
xr = (ptsIn[right].x + xFtrans) + mr * max(dy, 0);
}
}
/*
* generate scans to fill while we still have
* a right edge as well as a left edge.
*/
i = (min(ptsIn[nextleft].y, ptsIn[nextright].y) + yFtrans) - y;
if (i < EPSILON)
{
if(Marked[nextleft] && Marked[nextright])
{
/* Arrgh, we're trapped! (no more points)
* Out, we've got to get out of here before this decadence saps
* our will completely! */
break;
}
continue;
}
else
{
j = (int) i;
if(!j)
j++;
}
while (j > 0)
{
int cxl, cxr;
ptsOut->y = (y) + yTrans;
cxl = ICEIL(xl);
cxr = ICEIL(xr);
/* reverse the edges if necessary */
if (xl < xr)
{
*(width++) = cxr - cxl;
(ptsOut++)->x = cxl + xTrans;
}
else
{
*(width++) = cxl - cxr;
(ptsOut++)->x = cxr + xTrans;
}
y++;
/* increment down the edges */
xl += ml;
xr += mr;
j--;
}
} while (y <= ymax);
/* Finally, fill the spans we've collected */
(*pgc->ops->FillSpans)(dst, pgc,
ptsOut-FirstPoint, FirstPoint, FirstWidth, 1);
free(Marked);
free(FirstWidth);
free(FirstPoint);
}
/* Find the index of the point with the smallest y.also return the
* smallest and largest y */
static
int
GetFPolyYBounds(
register SppPointPtr pts,
int n,
double yFtrans,
int *by,
int *ty)
{
register SppPointPtr ptMin;
double ymin, ymax;
SppPointPtr ptsStart = pts;
ptMin = pts;
ymin = ymax = (pts++)->y;
while (--n > 0) {
if (pts->y < ymin)
{
ptMin = pts;
ymin = pts->y;
}
if(pts->y > ymax)
ymax = pts->y;
pts++;
}
*by = ICEIL(ymin + yFtrans);
*ty = ICEIL(ymax + yFtrans - 1);
return(ptMin-ptsStart);
}

View File

@@ -0,0 +1,298 @@
/*
Copyright 1993, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "regionstr.h"
#include "scrnintstr.h"
#include "gcstruct.h"
#include "pixmapstr.h"
#include "windowstr.h"
#include "migc.h"
/* ARGSUSED */
void
miChangeGC(pGC, mask)
GCPtr pGC;
unsigned long mask;
{
return;
}
void
miDestroyGC(pGC)
GCPtr pGC;
{
if (pGC->pRotatedPixmap)
(*pGC->pScreen->DestroyPixmap) (pGC->pRotatedPixmap);
if (pGC->freeCompClip)
RegionDestroy(pGC->pCompositeClip);
miDestroyGCOps(pGC->ops);
}
/*
* create a private op array for a gc
*/
GCOpsPtr
miCreateGCOps(prototype)
GCOpsPtr prototype;
{
GCOpsPtr ret;
ret = malloc(sizeof(GCOps));
if (!ret)
return NULL;
*ret = *prototype;
ret->devPrivate.val = 1;
return ret;
}
void
miDestroyGCOps(ops)
GCOpsPtr ops;
{
if (ops->devPrivate.val)
free(ops);
}
void
miDestroyClip(pGC)
GCPtr pGC;
{
if (pGC->clientClipType == CT_NONE)
return;
else if (pGC->clientClipType == CT_PIXMAP)
{
(*pGC->pScreen->DestroyPixmap) ((PixmapPtr) (pGC->clientClip));
}
else
{
/*
* we know we'll never have a list of rectangles, since ChangeClip
* immediately turns them into a region
*/
RegionDestroy(pGC->clientClip);
}
pGC->clientClip = NULL;
pGC->clientClipType = CT_NONE;
}
void
miChangeClip(pGC, type, pvalue, nrects)
GCPtr pGC;
int type;
void *pvalue;
int nrects;
{
(*pGC->funcs->DestroyClip) (pGC);
if (type == CT_PIXMAP)
{
/* convert the pixmap to a region */
pGC->clientClip = (void *) BitmapToRegion(pGC->pScreen,
(PixmapPtr) pvalue);
(*pGC->pScreen->DestroyPixmap) (pvalue);
}
else if (type == CT_REGION)
{
/* stuff the region in the GC */
pGC->clientClip = pvalue;
}
else if (type != CT_NONE)
{
pGC->clientClip = (void *) RegionFromRects(nrects,
(xRectangle *) pvalue,
type);
free(pvalue);
}
pGC->clientClipType = (type != CT_NONE && pGC->clientClip) ? CT_REGION : CT_NONE;
pGC->stateChanges |= GCClipMask;
}
void
miCopyClip(pgcDst, pgcSrc)
GCPtr pgcDst, pgcSrc;
{
RegionPtr prgnNew;
switch (pgcSrc->clientClipType)
{
case CT_PIXMAP:
((PixmapPtr) pgcSrc->clientClip)->refcnt++;
/* Fall through !! */
case CT_NONE:
(*pgcDst->funcs->ChangeClip) (pgcDst, (int) pgcSrc->clientClipType,
pgcSrc->clientClip, 0);
break;
case CT_REGION:
prgnNew = RegionCreate(NULL, 1);
RegionCopy(prgnNew,
(RegionPtr) (pgcSrc->clientClip));
(*pgcDst->funcs->ChangeClip) (pgcDst, CT_REGION, (void *) prgnNew, 0);
break;
}
}
/* ARGSUSED */
void
miCopyGC(pGCSrc, changes, pGCDst)
GCPtr pGCSrc;
unsigned long changes;
GCPtr pGCDst;
{
return;
}
void
miComputeCompositeClip(pGC, pDrawable)
GCPtr pGC;
DrawablePtr pDrawable;
{
ScreenPtr pScreen;
/* This prevents warnings about pScreen not being used. */
pGC->pScreen = pScreen = pGC->pScreen;
if (pDrawable->type == DRAWABLE_WINDOW)
{
WindowPtr pWin = (WindowPtr) pDrawable;
RegionPtr pregWin;
Bool freeTmpClip, freeCompClip;
if (pGC->subWindowMode == IncludeInferiors)
{
pregWin = NotClippedByChildren(pWin);
freeTmpClip = TRUE;
}
else
{
pregWin = &pWin->clipList;
freeTmpClip = FALSE;
}
freeCompClip = pGC->freeCompClip;
/*
* if there is no client clip, we can get by with just keeping the
* pointer we got, and remembering whether or not should destroy (or
* maybe re-use) it later. this way, we avoid unnecessary copying of
* regions. (this wins especially if many clients clip by children
* and have no client clip.)
*/
if (pGC->clientClipType == CT_NONE)
{
if (freeCompClip)
RegionDestroy(pGC->pCompositeClip);
pGC->pCompositeClip = pregWin;
pGC->freeCompClip = freeTmpClip;
}
else
{
/*
* we need one 'real' region to put into the composite clip. if
* pregWin the current composite clip are real, we can get rid of
* one. if pregWin is real and the current composite clip isn't,
* use pregWin for the composite clip. if the current composite
* clip is real and pregWin isn't, use the current composite
* clip. if neither is real, create a new region.
*/
RegionTranslate(pGC->clientClip,
pDrawable->x + pGC->clipOrg.x,
pDrawable->y + pGC->clipOrg.y);
if (freeCompClip)
{
RegionIntersect(pGC->pCompositeClip,
pregWin, pGC->clientClip);
if (freeTmpClip)
RegionDestroy(pregWin);
}
else if (freeTmpClip)
{
RegionIntersect(pregWin, pregWin, pGC->clientClip);
pGC->pCompositeClip = pregWin;
}
else
{
pGC->pCompositeClip = RegionCreate(NullBox, 0);
RegionIntersect(pGC->pCompositeClip,
pregWin, pGC->clientClip);
}
pGC->freeCompClip = TRUE;
RegionTranslate(pGC->clientClip,
-(pDrawable->x + pGC->clipOrg.x),
-(pDrawable->y + pGC->clipOrg.y));
}
} /* end of composite clip for a window */
else
{
BoxRec pixbounds;
/* XXX should we translate by drawable.x/y here ? */
/* If you want pixmaps in offscreen memory, yes */
pixbounds.x1 = pDrawable->x;
pixbounds.y1 = pDrawable->y;
pixbounds.x2 = pDrawable->x + pDrawable->width;
pixbounds.y2 = pDrawable->y + pDrawable->height;
if (pGC->freeCompClip)
{
RegionReset(pGC->pCompositeClip, &pixbounds);
}
else
{
pGC->freeCompClip = TRUE;
pGC->pCompositeClip = RegionCreate(&pixbounds, 1);
}
if (pGC->clientClipType == CT_REGION)
{
if(pDrawable->x || pDrawable->y) {
RegionTranslate(pGC->clientClip,
pDrawable->x + pGC->clipOrg.x,
pDrawable->y + pGC->clipOrg.y);
RegionIntersect(pGC->pCompositeClip,
pGC->pCompositeClip, pGC->clientClip);
RegionTranslate(pGC->clientClip,
-(pDrawable->x + pGC->clipOrg.x),
-(pDrawable->y + pGC->clipOrg.y));
} else {
RegionTranslate(pGC->pCompositeClip,
-pGC->clipOrg.x, -pGC->clipOrg.y);
RegionIntersect(pGC->pCompositeClip,
pGC->pCompositeClip, pGC->clientClip);
RegionTranslate(pGC->pCompositeClip,
pGC->clipOrg.x, pGC->clipOrg.y);
}
}
} /* end of composite clip for pixmap */
} /* end miComputeCompositeClip */

View File

@@ -0,0 +1,72 @@
/*
Copyright 1993, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
extern void miChangeGC(
GCPtr /*pGC*/,
unsigned long /*mask*/
);
extern void miDestroyGC(
GCPtr /*pGC*/
);
extern GCOpsPtr miCreateGCOps(
GCOpsPtr /*prototype*/
);
extern void miDestroyGCOps(
GCOpsPtr /*ops*/
);
extern void miDestroyClip(
GCPtr /*pGC*/
);
extern void miChangeClip(
GCPtr /*pGC*/,
int /*type*/,
void * /*pvalue*/,
int /*nrects*/
);
extern void miCopyClip(
GCPtr /*pgcDst*/,
GCPtr /*pgcSrc*/
);
extern void miCopyGC(
GCPtr /*pGCSrc*/,
unsigned long /*changes*/,
GCPtr /*pGCDst*/
);
extern void miComputeCompositeClip(
GCPtr /*pGC*/,
DrawablePtr /*pDrawable*/
);

View File

@@ -0,0 +1,264 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xmd.h>
#include <nx-X11/Xproto.h>
#include "misc.h"
#include <X11/fonts/fontstruct.h>
#ifdef HAS_XFONT2
# include <X11/fonts/libxfont2.h>
#else
# include <X11/fonts/fontutil.h>
#endif /* HAS_XFONT2 */
#include "dixfontstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "scrnintstr.h"
#include "pixmap.h"
#include "servermd.h"
#include "mi.h"
/*
machine-independent glyph blt.
assumes that glyph bits in snf are written in bytes,
have same bit order as the server's bitmap format,
and are byte padded. this corresponds to the snf distributed
with the sample server.
get a scratch GC.
in the scratch GC set alu = GXcopy, fg = 1, bg = 0
allocate a bitmap big enough to hold the largest glyph in the font
validate the scratch gc with the bitmap
for each glyph
carefully put the bits of the glyph in a buffer,
padded to the server pixmap scanline padding rules
fake a call to PutImage from the buffer into the bitmap
use the bitmap in a call to PushPixels
*/
void
miPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
DrawablePtr pDrawable;
GC *pGC;
int x, y;
unsigned int nglyph;
CharInfoPtr *ppci; /* array of character info */
void *pglyphBase; /* start of array of glyphs */
{
int width, height;
PixmapPtr pPixmap;
int nbyLine; /* bytes per line of padded pixmap */
FontPtr pfont;
GCPtr pGCtmp;
register int i;
register int j;
unsigned char *pbits; /* buffer for PutImage */
register unsigned char *pb; /* temp pointer into buffer */
register CharInfoPtr pci; /* currect char info */
register unsigned char *pglyph; /* pointer bits in glyph */
int gWidth, gHeight; /* width and height of glyph */
register int nbyGlyphWidth; /* bytes per scanline of glyph */
int nbyPadGlyph; /* server padded line of glyph */
XID gcvals[3];
if (pGC->miTranslate)
{
x += pDrawable->x;
y += pDrawable->y;
}
pfont = pGC->font;
width = FONTMAXBOUNDS(pfont,rightSideBearing) -
FONTMINBOUNDS(pfont,leftSideBearing);
height = FONTMAXBOUNDS(pfont,ascent) +
FONTMAXBOUNDS(pfont,descent);
pPixmap = (*pDrawable->pScreen->CreatePixmap)(pDrawable->pScreen,
width, height, 1,
CREATE_PIXMAP_USAGE_SCRATCH);
if (!pPixmap)
return;
pGCtmp = GetScratchGC(1, pDrawable->pScreen);
if (!pGCtmp)
{
(*pDrawable->pScreen->DestroyPixmap)(pPixmap);
return;
}
gcvals[0] = GXcopy;
gcvals[1] = 1;
gcvals[2] = 0;
DoChangeGC(pGCtmp, GCFunction|GCForeground|GCBackground, gcvals, 0);
nbyLine = BitmapBytePad(width);
pbits = (unsigned char *)malloc(height*nbyLine);
if (!pbits)
{
(*pDrawable->pScreen->DestroyPixmap)(pPixmap);
FreeScratchGC(pGCtmp);
return;
}
while(nglyph--)
{
pci = *ppci++;
pglyph = FONTGLYPHBITS(pglyphBase, pci);
gWidth = GLYPHWIDTHPIXELS(pci);
gHeight = GLYPHHEIGHTPIXELS(pci);
if (gWidth && gHeight)
{
nbyGlyphWidth = GLYPHWIDTHBYTESPADDED(pci);
nbyPadGlyph = BitmapBytePad(gWidth);
if (nbyGlyphWidth == nbyPadGlyph
#if GLYPHPADBYTES != 4
&& (((int) pglyph) & 3) == 0
#endif
)
{
pb = pglyph;
}
else
{
for (i=0, pb = pbits; i<gHeight; i++, pb = pbits+(i*nbyPadGlyph))
for (j = 0; j < nbyGlyphWidth; j++)
*pb++ = *pglyph++;
pb = pbits;
}
if ((pGCtmp->serialNumber) != (pPixmap->drawable.serialNumber))
ValidateGC((DrawablePtr)pPixmap, pGCtmp);
(*pGCtmp->ops->PutImage)((DrawablePtr)pPixmap, pGCtmp,
pPixmap->drawable.depth,
0, 0, gWidth, gHeight,
0, XYBitmap, (char *)pb);
if ((pGC->serialNumber) != (pDrawable->serialNumber))
ValidateGC(pDrawable, pGC);
(*pGC->ops->PushPixels)(pGC, pPixmap, pDrawable,
gWidth, gHeight,
x + pci->metrics.leftSideBearing,
y - pci->metrics.ascent);
}
x += pci->metrics.characterWidth;
}
(*pDrawable->pScreen->DestroyPixmap)(pPixmap);
free(pbits);
FreeScratchGC(pGCtmp);
}
void
miImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
DrawablePtr pDrawable;
GC *pGC;
int x, y;
unsigned int nglyph;
CharInfoPtr *ppci; /* array of character info */
void *pglyphBase; /* start of array of glyphs */
{
ExtentInfoRec info; /* used by xfont2_query_glyph_extents (libXfont2)
resp. QueryGlyphExtents() (libXfont1) */
XID gcvals[3];
int oldAlu, oldFS;
unsigned long oldFG;
xRectangle backrect;
#ifdef HAS_XFONT2
xfont2_query_glyph_extents(pGC->font, ppci, (unsigned long) nglyph, &info);
#else
QueryGlyphExtents(pGC->font, ppci, (unsigned long)nglyph, &info);
#endif /* HAS_XFONT2 */
if (info.overallWidth >= 0)
{
backrect.x = x;
backrect.width = info.overallWidth;
}
else
{
backrect.x = x + info.overallWidth;
backrect.width = -info.overallWidth;
}
backrect.y = y - FONTASCENT(pGC->font);
backrect.height = FONTASCENT(pGC->font) + FONTDESCENT(pGC->font);
oldAlu = pGC->alu;
oldFG = pGC->fgPixel;
oldFS = pGC->fillStyle;
/* fill in the background */
gcvals[0] = GXcopy;
gcvals[1] = pGC->bgPixel;
gcvals[2] = FillSolid;
DoChangeGC(pGC, GCFunction|GCForeground|GCFillStyle, gcvals, 0);
ValidateGC(pDrawable, pGC);
(*pGC->ops->PolyFillRect)(pDrawable, pGC, 1, &backrect);
/* put down the glyphs */
gcvals[0] = oldFG;
DoChangeGC(pGC, GCForeground, gcvals, 0);
ValidateGC(pDrawable, pGC);
(*pGC->ops->PolyGlyphBlt)(pDrawable, pGC, x, y, nglyph, ppci,
pglyphBase);
/* put all the toys away when done playing */
gcvals[0] = oldAlu;
gcvals[1] = oldFG;
gcvals[2] = oldFS;
DoChangeGC(pGC, GCFunction|GCForeground|GCFillStyle, gcvals, 0);
ValidateGC(pDrawable, pGC);
}

View File

@@ -0,0 +1,481 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#endif
#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#ifdef HAVE_XNEST_CONFIG_H
#include <xnest-config.h>
#undef DPMSExtension
#endif
#include "misc.h"
#include "extension.h"
#include "micmap.h"
extern Bool noTestExtensions;
#ifdef BIGREQS
extern Bool noBigReqExtension;
#endif
#ifdef COMPOSITE
extern Bool noCompositeExtension;
#endif
#ifdef DAMAGE
extern Bool noDamageExtension;
#endif
#ifdef DBE
extern Bool noDbeExtension;
#endif
#ifdef DPMSExtension
extern Bool noDPMSExtension;
#endif
#ifdef GLXEXT
extern Bool noGlxExtension;
#endif
#ifdef SCREENSAVER
extern Bool noScreenSaverExtension;
#endif
#ifdef MITSHM
extern Bool noMITShmExtension;
#endif
#ifdef RANDR
extern Bool noRRExtension;
#endif
#ifdef RENDER
extern Bool noRenderExtension;
#endif
#ifdef SHAPE
extern Bool noShapeExtension;
#endif
#ifdef XCSECURITY
extern Bool noSecurityExtension;
#endif
#ifdef XSYNC
extern Bool noSyncExtension;
#endif
#ifdef RES
extern Bool noResExtension;
#endif
#ifdef XCMISC
extern Bool noXCMiscExtension;
#endif
#ifdef XF86BIGFONT
extern Bool noXFree86BigfontExtension;
#endif
#ifdef XF86DRI
extern Bool noXFree86DRIExtension;
#endif
#ifdef XFIXES
extern Bool noXFixesExtension;
#endif
#ifdef XKB
/* |noXkbExtension| is defined in xc/programs/Xserver/xkb/xkbInit.c */
extern Bool noXkbExtension;
#endif
#ifdef PANORAMIX
extern Bool noPanoramiXExtension;
#endif
#ifdef XINPUT
extern Bool noXInputExtension;
#endif
#ifdef XIDLE
extern Bool noXIdleExtension;
#endif
#ifdef XV
extern Bool noXvExtension;
#endif
typedef void (*InitExtension)(void);
#ifdef MITSHM
#define _XSHM_SERVER_
#ifdef LEGACY_XEXT_PROTO
#include <X11/extensions/shmstr.h>
#else
#include <X11/extensions/shmproto.h>
#endif
#endif
#ifdef XTEST
#define _XTEST_SERVER_
#include <nx-X11/extensions/xtestconst.h>
#endif
#ifdef XKB
#include <nx-X11/extensions/XKB.h>
#endif
#ifdef XCSECURITY
#define _SECURITY_SERVER
#include <nx-X11/extensions/securstr.h>
#endif
#ifdef PANORAMIX
#include <nx-X11/extensions/panoramiXproto.h>
#endif
#ifdef XF86BIGFONT
#include <nx-X11/extensions/xf86bigfproto.h>
#endif
#ifdef RES
#include <nx-X11/extensions/XResproto.h>
#endif
/* FIXME: this whole block of externs should be from the appropriate headers */
#ifdef SHAPE
extern void ShapeExtensionInit(void);
#endif
#ifdef MITSHM
extern void ShmExtensionInit(void);
#endif
#ifdef PANORAMIX
extern void PanoramiXExtensionInit(void);
#endif
#ifdef XINPUT
extern void XInputExtensionInit(void);
#endif
#ifdef XTEST
extern void XTestExtensionInit(void);
#endif
#ifdef BIGREQS
extern void BigReqExtensionInit(void);
#endif
#ifdef XIDLE
extern void XIdleExtensionInit(void);
#endif
#ifdef SCREENSAVER
extern void ScreenSaverExtensionInit (void);
#endif
#ifdef XV
extern void XvExtensionInit(void);
extern void XvMCExtensionInit(void);
#endif
#ifdef XSYNC
extern void SyncExtensionInit(void);
#endif
#ifdef XKB
extern void XkbExtensionInit(void);
#endif
#ifdef XCMISC
extern void XCMiscExtensionInit(void);
#endif
#ifdef XRECORD
extern void RecordExtensionInit(void);
#endif
#ifdef DBE
extern void DbeExtensionInit(void);
#endif
#ifdef XCSECURITY
extern void SecurityExtensionInit(void);
#endif
#ifdef XF86BIGFONT
extern void XFree86BigfontExtensionInit(void);
#endif
#ifdef GLXEXT
/*
typedef struct __GLXprovider __GLXprovider;
extern __GLXprovider __glXMesaProvider;
extern void GlxPushProvider(__GLXprovider *impl);
*/
#ifndef __DARWIN__
extern void GlxExtensionInit(void);
#else
extern void DarwinGlxExtensionInit(void);
extern void DarwinGlxWrapInitVisuals(miInitVisualsProcPtr *);
#endif
#endif
#ifdef XF86DRI
extern void XFree86DRIExtensionInit(void);
#endif
#ifdef DPMSExtension
extern void DPMSExtensionInit(void);
#endif
#ifdef RENDER
extern void RenderExtensionInit(void);
#endif
#ifdef RANDR
extern void RRExtensionInit(void);
#endif
#ifdef RES
extern void ResExtensionInit(void);
#endif
#ifdef DMXEXT
extern void DMXExtensionInit(void);
#endif
#ifdef XFIXES
extern void XFixesExtensionInit(void);
#endif
#ifdef DAMAGE
extern void DamageExtensionInit(void);
#endif
#ifdef COMPOSITE
extern void CompositeExtensionInit(void);
#endif
/* The following is only a small first step towards run-time
* configurable extensions.
*/
typedef struct {
char *name;
Bool *disablePtr;
} ExtensionToggle;
static ExtensionToggle ExtensionToggleList[] =
{
/* sort order is extension name string as shown in xdpyinfo */
#ifdef BIGREQS
{ "BIG-REQUESTS", &noBigReqExtension },
#endif
#ifdef COMPOSITE
{ "Composite", &noCompositeExtension },
#endif
#ifdef DAMAGE
{ "DAMAGE", &noDamageExtension },
#endif
#ifdef DBE
{ "DOUBLE-BUFFER", &noDbeExtension },
#endif
#ifdef DPMSExtension
{ "DPMS", &noDPMSExtension },
#endif
#ifdef GLXEXT
{ "GLX", &noGlxExtension },
#endif
#ifdef SCREENSAVER
{ "MIT-SCREEN-SAVER", &noScreenSaverExtension },
#endif
#ifdef MITSHM
{ SHMNAME, &noMITShmExtension },
#endif
#ifdef RANDR
{ "RANDR", &noRRExtension },
#endif
#ifdef RENDER
{ "RENDER", &noRenderExtension },
#endif
#ifdef SHAPE
{ "SHAPE", &noShapeExtension },
#endif
#ifdef XCSECURITY
{ "SECURITY", &noSecurityExtension },
#endif
#ifdef XSYNC
{ "SYNC", &noSyncExtension },
#endif
#ifdef RES
{ "X-Resource", &noResExtension },
#endif
#ifdef XCMISC
{ "XC-MISC", &noXCMiscExtension },
#endif
#ifdef XF86BIGFONT
{ "XFree86-Bigfont", &noXFree86BigfontExtension },
#endif
#ifdef XF86DRI
{ "XFree86-DRI", &noXFree86DRIExtension },
#endif
#ifdef XFIXES
{ "XFIXES", &noXFixesExtension },
#endif
#ifdef PANORAMIX
{ "XINERAMA", &noPanoramiXExtension },
#endif
#ifdef XINPUT
{ "XInputExtension", &noXInputExtension },
#endif
#ifdef XKB
{ "XKEYBOARD", &noXkbExtension },
#endif
{ "XTEST", &noTestExtensions },
#ifdef XV
{ "XVideo", &noXvExtension },
#endif
{ NULL, NULL }
};
Bool EnableDisableExtension(char *name, Bool enable)
{
ExtensionToggle *ext = &ExtensionToggleList[0];
for (ext = &ExtensionToggleList[0]; ext->name != NULL; ext++) {
if (strcmp(name, ext->name) == 0) {
*ext->disablePtr = !enable;
return TRUE;
}
}
return FALSE;
}
void EnableDisableExtensionError(char *name, Bool enable)
{
ExtensionToggle *ext = &ExtensionToggleList[0];
ErrorF("Extension \"%s\" is not recognized\n", name);
ErrorF("Only the following extensions can be run-time %s:\n",
enable ? "enabled" : "disabled");
for (ext = &ExtensionToggleList[0]; ext->name != NULL; ext++)
ErrorF(" %s\n", ext->name);
}
/*ARGSUSED*/
void
InitExtensions(argc, argv)
int argc;
char *argv[];
{
#ifdef PANORAMIX
# if !defined(PRINT_ONLY_SERVER) && !defined(NO_PANORAMIX)
if (!noPanoramiXExtension) PanoramiXExtensionInit();
# endif
#endif
#ifdef SHAPE
if (!noShapeExtension) ShapeExtensionInit();
#endif
#ifdef MITSHM
if (!noMITShmExtension) ShmExtensionInit();
#endif
#if defined(XINPUT) && !defined(NO_HW_ONLY_EXTS)
if (!noXInputExtension) XInputExtensionInit();
#endif
#ifdef XTEST
if (!noTestExtensions) XTestExtensionInit();
#endif
#ifdef BIGREQS
if (!noBigReqExtension) BigReqExtensionInit();
#endif
#ifdef XIDLE
if (!noXIdleExtension) XIdleExtensionInit();
#endif
#if defined(SCREENSAVER) && !defined(PRINT_ONLY_SERVER)
if (!noScreenSaverExtension) ScreenSaverExtensionInit ();
#endif
#ifdef XV
if (!noXvExtension) {
XvExtensionInit();
XvMCExtensionInit();
}
#endif
#ifdef XSYNC
if (!noSyncExtension) SyncExtensionInit();
#endif
#if defined(XKB) && !defined(PRINT_ONLY_SERVER) && !defined(NO_HW_ONLY_EXTS)
if (!noXkbExtension) XkbExtensionInit();
#endif
#ifdef XCMISC
if (!noXCMiscExtension) XCMiscExtensionInit();
#endif
#ifdef XRECORD
if (!noTestExtensions) RecordExtensionInit();
#endif
#ifdef DBE
if (!noDbeExtension) DbeExtensionInit();
#endif
#ifdef XCSECURITY
if (!noSecurityExtension) SecurityExtensionInit();
#endif
#if defined(DPMSExtension) && !defined(NO_HW_ONLY_EXTS)
if (!noDPMSExtension) DPMSExtensionInit();
#endif
#ifdef XF86BIGFONT
if (!noXFree86BigfontExtension) XFree86BigfontExtensionInit();
#endif
#if !defined(PRINT_ONLY_SERVER) && !defined(NO_HW_ONLY_EXTS)
#ifdef XF86DRI
if (!noXFree86DRIExtension) XFree86DRIExtensionInit();
#endif
#endif
#ifdef GLXEXT
/*
GlxPushProvider(&__glXMesaProvider);
*/
#ifndef __DARWIN__
if (!noGlxExtension) GlxExtensionInit();
#else
if (!noGlxExtension) DarwinGlxExtensionInit();
#endif
#endif
#ifdef XFIXES
/* must be before Render to layer DisplayCursor correctly */
if (!noXFixesExtension) XFixesExtensionInit();
#endif
#ifdef RENDER
if (!noRenderExtension) RenderExtensionInit();
#endif
#ifdef RANDR
if (!noRRExtension) RRExtensionInit();
#endif
#ifdef RES
if (!noResExtension) ResExtensionInit();
#endif
#ifdef DMXEXT
DMXExtensionInit(); /* server-specific extension, cannot be disabled */
#endif
#ifdef COMPOSITE
if (!noCompositeExtension) CompositeExtensionInit();
#endif
#ifdef DAMAGE
if (!noDamageExtension) DamageExtensionInit();
#endif
}
void
InitVisualWrap()
{
miResetInitVisuals();
#ifdef GLXEXT
#ifdef __DARWIN__
DarwinGlxWrapInitVisuals(&miInitVisualsProc);
#endif
#endif
}

View File

@@ -0,0 +1,172 @@
/*
Copyright 1994, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
#ifndef MILINE_H
#include "screenint.h"
/*
* Public definitions used for configuring basic pixelization aspects
* of the sample implementation line-drawing routines provided in
* {mfb,mi,cfb*} at run-time.
*/
#define XDECREASING 4
#define YDECREASING 2
#define YMAJOR 1
#define OCTANT1 (1 << (YDECREASING))
#define OCTANT2 (1 << (YDECREASING|YMAJOR))
#define OCTANT3 (1 << (XDECREASING|YDECREASING|YMAJOR))
#define OCTANT4 (1 << (XDECREASING|YDECREASING))
#define OCTANT5 (1 << (XDECREASING))
#define OCTANT6 (1 << (XDECREASING|YMAJOR))
#define OCTANT7 (1 << (YMAJOR))
#define OCTANT8 (1 << (0))
#define XMAJOROCTANTS (OCTANT1 | OCTANT4 | OCTANT5 | OCTANT8)
#define DEFAULTZEROLINEBIAS (OCTANT2 | OCTANT3 | OCTANT4 | OCTANT5)
/*
* Devices can configure the rendering of routines in mi, mfb, and cfb*
* by specifying a thin line bias to be applied to a particular screen
* using the following function. The bias parameter is an OR'ing of
* the appropriate OCTANT constants defined above to indicate which
* octants to bias a line to prefer an axial step when the Bresenham
* error term is exactly zero. The octants are mapped as follows:
*
* \ | /
* \ 3 | 2 /
* \ | /
* 4 \ | / 1
* \|/
* -----------
* /|\
* 5 / | \ 8
* / | \
* / 6 | 7 \
* / | \
*
* For more information, see "Ambiguities in Incremental Line Rastering,"
* Jack E. Bresenham, IEEE CG&A, May 1987.
*/
extern void miSetZeroLineBias(
ScreenPtr /* pScreen */,
unsigned int /* bias */
);
/*
* Private definitions needed for drawing thin (zero width) lines
* Used by the mi, mfb, and all cfb* components.
*/
#define X_AXIS 0
#define Y_AXIS 1
#define OUT_LEFT 0x08
#define OUT_RIGHT 0x04
#define OUT_ABOVE 0x02
#define OUT_BELOW 0x01
#define OUTCODES(_result, _x, _y, _pbox) \
if ( (_x) < (_pbox)->x1) (_result) |= OUT_LEFT; \
else if ( (_x) >= (_pbox)->x2) (_result) |= OUT_RIGHT; \
if ( (_y) < (_pbox)->y1) (_result) |= OUT_ABOVE; \
else if ( (_y) >= (_pbox)->y2) (_result) |= OUT_BELOW;
#define MIOUTCODES(outcode, x, y, xmin, ymin, xmax, ymax) \
{\
if (x < xmin) outcode |= OUT_LEFT;\
if (x > xmax) outcode |= OUT_RIGHT;\
if (y < ymin) outcode |= OUT_ABOVE;\
if (y > ymax) outcode |= OUT_BELOW;\
}
#define SWAPINT(i, j) \
{ register int _t = i; i = j; j = _t; }
#define SWAPPT(i, j) \
{ DDXPointRec _t; _t = i; i = j; j = _t; }
#define SWAPINT_PAIR(x1, y1, x2, y2)\
{ int t = x1; x1 = x2; x2 = t;\
t = y1; y1 = y2; y2 = t;\
}
#define miGetZeroLineBias(_pScreen) \
((miZeroLineScreenIndex < 0) ? \
0 : ((_pScreen)->devPrivates[miZeroLineScreenIndex].uval))
#define CalcLineDeltas(_x1,_y1,_x2,_y2,_adx,_ady,_sx,_sy,_SX,_SY,_octant) \
(_octant) = 0; \
(_sx) = (_SX); \
if (((_adx) = (_x2) - (_x1)) < 0) { \
(_adx) = -(_adx); \
(_sx = -(_sx)); \
(_octant) |= XDECREASING; \
} \
(_sy) = (_SY); \
if (((_ady) = (_y2) - (_y1)) < 0) { \
(_ady) = -(_ady); \
(_sy = -(_sy)); \
(_octant) |= YDECREASING; \
}
#define SetYMajorOctant(_octant) ((_octant) |= YMAJOR)
#define FIXUP_ERROR(_e, _octant, _bias) \
(_e) -= (((_bias) >> (_octant)) & 1)
#define IsXMajorOctant(_octant) (!((_octant) & YMAJOR))
#define IsYMajorOctant(_octant) ((_octant) & YMAJOR)
#define IsXDecreasingOctant(_octant) ((_octant) & XDECREASING)
#define IsYDecreasingOctant(_octant) ((_octant) & YDECREASING)
extern int miZeroLineScreenIndex;
extern int miZeroClipLine(
int /*xmin*/,
int /*ymin*/,
int /*xmax*/,
int /*ymax*/,
int * /*new_x1*/,
int * /*new_y1*/,
int * /*new_x2*/,
int * /*new_y2*/,
unsigned int /*adx*/,
unsigned int /*ady*/,
int * /*pt1_clipped*/,
int * /*pt2_clipped*/,
int /*octant*/,
unsigned int /*bias*/,
int /*oc1*/,
int /*oc2*/
);
#endif /* MILINE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifndef __MIOVERLAY_H
#define __MIOVERLAY_H
typedef void (*miOverlayTransFunc)(ScreenPtr, int, BoxPtr);
typedef Bool (*miOverlayInOverlayFunc)(WindowPtr);
Bool
miInitOverlay(
ScreenPtr pScreen,
miOverlayInOverlayFunc inOverlay,
miOverlayTransFunc trans
);
Bool
miOverlayGetPrivateClips(
WindowPtr pWin,
RegionPtr *borderClip,
RegionPtr *clipList
);
Bool miOverlayCollectUnderlayRegions(WindowPtr, RegionPtr*);
void miOverlayComputeCompositeClip(GCPtr, WindowPtr);
Bool miOverlayCopyUnderlay(ScreenPtr);
void miOverlaySetTransFunction(ScreenPtr, miOverlayTransFunc);
void miOverlaySetRootClip(ScreenPtr, Bool);
#endif /* __MIOVERLAY_H */

View File

@@ -0,0 +1,545 @@
/*
* mipointer.c
*/
/*
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
# include <nx-X11/X.h>
# include <nx-X11/Xmd.h>
# include <nx-X11/Xproto.h>
# include "misc.h"
# include "windowstr.h"
# include "pixmapstr.h"
# include "mi.h"
# include "scrnintstr.h"
# include "mipointrst.h"
# include "cursorstr.h"
# include "dixstruct.h"
# include <nx-X11/extensions/XI.h>
int miPointerScreenIndex;
static unsigned long miPointerGeneration = 0;
#define GetScreenPrivate(s) ((miPointerScreenPtr) ((s)->devPrivates[miPointerScreenIndex].ptr))
#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s)
/*
* until more than one pointer device exists.
*/
static miPointerRec miPointer;
static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor);
static void miPointerConstrainCursor(ScreenPtr pScreen, BoxPtr pBox);
static void miPointerPointerNonInterestBox(ScreenPtr pScreen, BoxPtr pBox);
static void miPointerCursorLimits(ScreenPtr pScreen, CursorPtr pCursor,
BoxPtr pHotBox, BoxPtr pTopLeftBox);
static Bool miPointerSetCursorPosition(ScreenPtr pScreen, int x, int y,
Bool generateEvent);
static Bool miPointerCloseScreen(ScreenPtr pScreen);
static void miPointerMove(ScreenPtr pScreen, int x, int y, unsigned long time);
Bool
miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate)
ScreenPtr pScreen;
miPointerSpriteFuncPtr spriteFuncs;
miPointerScreenFuncPtr screenFuncs;
Bool waitForUpdate;
{
miPointerScreenPtr pScreenPriv;
if (miPointerGeneration != serverGeneration)
{
miPointerScreenIndex = AllocateScreenPrivateIndex();
if (miPointerScreenIndex < 0)
return FALSE;
miPointerGeneration = serverGeneration;
}
pScreenPriv = (miPointerScreenPtr) malloc (sizeof (miPointerScreenRec));
if (!pScreenPriv)
return FALSE;
pScreenPriv->spriteFuncs = spriteFuncs;
pScreenPriv->screenFuncs = screenFuncs;
/*
* check for uninitialized methods
*/
if (!screenFuncs->EnqueueEvent)
screenFuncs->EnqueueEvent = mieqEnqueue;
if (!screenFuncs->NewEventScreen)
screenFuncs->NewEventScreen = mieqSwitchScreen;
pScreenPriv->waitForUpdate = waitForUpdate;
pScreenPriv->showTransparent = FALSE;
pScreenPriv->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = miPointerCloseScreen;
pScreen->devPrivates[miPointerScreenIndex].ptr = (void *) pScreenPriv;
/*
* set up screen cursor method table
*/
pScreen->ConstrainCursor = miPointerConstrainCursor;
pScreen->CursorLimits = miPointerCursorLimits;
pScreen->DisplayCursor = miPointerDisplayCursor;
pScreen->RealizeCursor = miPointerRealizeCursor;
pScreen->UnrealizeCursor = miPointerUnrealizeCursor;
pScreen->SetCursorPosition = miPointerSetCursorPosition;
pScreen->RecolorCursor = miRecolorCursor;
pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox;
/*
* set up the pointer object
*/
miPointer.pScreen = NULL;
miPointer.pSpriteScreen = NULL;
miPointer.pCursor = NULL;
miPointer.pSpriteCursor = NULL;
miPointer.limits.x1 = 0;
miPointer.limits.x2 = 32767;
miPointer.limits.y1 = 0;
miPointer.limits.y2 = 32767;
miPointer.confined = FALSE;
miPointer.x = 0;
miPointer.y = 0;
miPointer.history_start = miPointer.history_end = 0;
return TRUE;
}
static Bool
miPointerCloseScreen (pScreen)
ScreenPtr pScreen;
{
SetupScreen(pScreen);
if (pScreen == miPointer.pScreen)
miPointer.pScreen = 0;
if (pScreen == miPointer.pSpriteScreen)
miPointer.pSpriteScreen = 0;
pScreen->CloseScreen = pScreenPriv->CloseScreen;
free ((void *) pScreenPriv);
return (*pScreen->CloseScreen) (pScreen);
}
/*
* DIX/DDX interface routines
*/
static Bool
miPointerRealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
SetupScreen(pScreen);
return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor);
}
static Bool
miPointerUnrealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
SetupScreen(pScreen);
return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor);
}
static Bool
miPointerDisplayCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
miPointer.pCursor = pCursor;
miPointer.pScreen = pScreen;
miPointerUpdate ();
return TRUE;
}
static void
miPointerConstrainCursor (pScreen, pBox)
ScreenPtr pScreen;
BoxPtr pBox;
{
miPointer.limits = *pBox;
miPointer.confined = PointerConfinedToScreen();
}
/*ARGSUSED*/
static void
miPointerPointerNonInterestBox (pScreen, pBox)
ScreenPtr pScreen;
BoxPtr pBox;
{
/* until DIX uses this, this will remain a stub */
}
/*ARGSUSED*/
static void
miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox)
ScreenPtr pScreen;
CursorPtr pCursor;
BoxPtr pHotBox;
BoxPtr pTopLeftBox;
{
*pTopLeftBox = *pHotBox;
}
static Bool GenerateEvent;
static Bool
miPointerSetCursorPosition(pScreen, x, y, generateEvent)
ScreenPtr pScreen;
int x, y;
Bool generateEvent;
{
SetupScreen (pScreen);
GenerateEvent = generateEvent;
if (pScreen->ConstrainCursorHarder)
pScreen->ConstrainCursorHarder(pScreen, Absolute, &x, &y);
/* device dependent - must pend signal and call miPointerWarpCursor */
(*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y);
if (!generateEvent)
miPointerUpdate();
return TRUE;
}
/* Once signals are ignored, the WarpCursor function can call this */
void
miPointerWarpCursor (pScreen, x, y)
ScreenPtr pScreen;
int x, y;
{
SetupScreen (pScreen);
if (miPointer.pScreen != pScreen)
(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE);
if (GenerateEvent)
{
miPointerMove (pScreen, x, y, GetTimeInMillis());
}
else
{
/* everything from miPointerMove except the event and history */
if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
{
miPointer.devx = x;
miPointer.devy = y;
if(!miPointer.pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
}
miPointer.x = x;
miPointer.y = y;
miPointer.pScreen = pScreen;
}
}
/*
* Pointer/CursorDisplay interface routines
*/
int
miPointerGetMotionBufferSize ()
{
return MOTION_SIZE;
}
int
miPointerGetMotionEvents (pPtr, coords, start, stop, pScreen)
DeviceIntPtr pPtr;
xTimecoord *coords;
unsigned long start, stop;
ScreenPtr pScreen;
{
int i;
int count = 0;
miHistoryPtr h;
for (i = miPointer.history_start; i != miPointer.history_end;)
{
h = &miPointer.history[i];
if (h->event.time >= stop)
break;
if (h->event.time >= start)
{
*coords++ = h->event;
count++;
}
if (++i == MOTION_SIZE) i = 0;
}
return count;
}
/*
* miPointerUpdate
*
* Syncronize the sprite with the cursor - called from ProcessInputEvents
*/
void
miPointerUpdate ()
{
ScreenPtr pScreen;
miPointerScreenPtr pScreenPriv;
CursorPtr pCursor;
int x, y, devx, devy;
pScreen = miPointer.pScreen;
x = miPointer.x;
y = miPointer.y;
devx = miPointer.devx;
devy = miPointer.devy;
if (!pScreen)
return;
pScreenPriv = GetScreenPrivate (pScreen);
/*
* if the cursor has switched screens, disable the sprite
* on the old screen
*/
if (pScreen != miPointer.pSpriteScreen)
{
if (miPointer.pSpriteScreen)
{
miPointerScreenPtr pOldPriv;
pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen);
if (miPointer.pCursor)
{
(*pOldPriv->spriteFuncs->SetCursor)
(miPointer.pSpriteScreen, NullCursor, 0, 0);
}
(*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE);
}
(*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE);
(*pScreenPriv->spriteFuncs->SetCursor)
(pScreen, miPointer.pCursor, x, y);
miPointer.devx = x;
miPointer.devy = y;
miPointer.pSpriteCursor = miPointer.pCursor;
miPointer.pSpriteScreen = pScreen;
}
/*
* if the cursor has changed, display the new one
*/
else if (miPointer.pCursor != miPointer.pSpriteCursor)
{
pCursor = miPointer.pCursor;
if (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)
pCursor = NullCursor;
(*pScreenPriv->spriteFuncs->SetCursor) (pScreen, pCursor, x, y);
miPointer.devx = x;
miPointer.devy = y;
miPointer.pSpriteCursor = miPointer.pCursor;
}
else if (x != devx || y != devy)
{
miPointer.devx = x;
miPointer.devy = y;
if(!miPointer.pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
}
}
/*
* miPointerDeltaCursor. The void * has moved dx,dy from it's previous
* position.
*/
void
miPointerDeltaCursor (dx, dy, time)
int dx, dy;
unsigned long time;
{
miPointerAbsoluteCursor (miPointer.x + dx, miPointer.y + dy, time);
}
void
miPointerSetNewScreen(int screen_no, int x, int y)
{
miPointerScreenPtr pScreenPriv;
ScreenPtr pScreen;
pScreen = screenInfo.screens[screen_no];
pScreenPriv = GetScreenPrivate (pScreen);
(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
NewCurrentScreen (pScreen, x, y);
miPointer.limits.x2 = pScreen->width;
miPointer.limits.y2 = pScreen->height;
}
ScreenPtr
miPointerCurrentScreen ()
{
return (miPointer.pScreen);
}
/*
* miPointerAbsoluteCursor. The void * has moved to x,y
*/
void
miPointerAbsoluteCursor (x, y, time)
int x, y;
unsigned long time;
{
miPointerScreenPtr pScreenPriv;
ScreenPtr pScreen;
ScreenPtr newScreen;
pScreen = miPointer.pScreen;
if (!pScreen)
return; /* called before ready */
if (x < 0 || x >= pScreen->width || y < 0 || y >= pScreen->height)
{
pScreenPriv = GetScreenPrivate (pScreen);
if (!miPointer.confined)
{
newScreen = pScreen;
(*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, &x, &y);
if (newScreen != pScreen)
{
pScreen = newScreen;
(*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE);
pScreenPriv = GetScreenPrivate (pScreen);
/* Smash the confine to the new screen */
miPointer.limits.x2 = pScreen->width;
miPointer.limits.y2 = pScreen->height;
}
}
}
/*
* constrain the hot-spot to the current
* limits
*/
if (x < miPointer.limits.x1)
x = miPointer.limits.x1;
if (x >= miPointer.limits.x2)
x = miPointer.limits.x2 - 1;
if (y < miPointer.limits.y1)
y = miPointer.limits.y1;
if (y >= miPointer.limits.y2)
y = miPointer.limits.y2 - 1;
if (miPointer.x == x && miPointer.y == y && miPointer.pScreen == pScreen)
return;
miPointerMove (pScreen, x, y, time);
}
void
miPointerPosition (x, y)
int *x, *y;
{
*x = miPointer.x;
*y = miPointer.y;
}
/*
* miPointerMove. The void * has moved to x,y on current screen
*/
static void
miPointerMove (pScreen, x, y, time)
ScreenPtr pScreen;
int x, y;
unsigned long time;
{
SetupScreen(pScreen);
xEvent xE;
miHistoryPtr history;
int prev, end, start;
if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen)
{
miPointer.devx = x;
miPointer.devy = y;
if(!miPointer.pCursor->bits->emptyMask)
(*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y);
}
miPointer.x = x;
miPointer.y = y;
miPointer.pScreen = pScreen;
xE.u.u.type = MotionNotify;
xE.u.keyButtonPointer.rootX = x;
xE.u.keyButtonPointer.rootY = y;
xE.u.keyButtonPointer.time = time;
(*pScreenPriv->screenFuncs->EnqueueEvent) (&xE);
end = miPointer.history_end;
start = miPointer.history_start;
prev = end - 1;
if (end == 0)
prev = MOTION_SIZE - 1;
history = &miPointer.history[prev];
if (end == start || history->event.time != time)
{
history = &miPointer.history[end];
if (++end == MOTION_SIZE)
end = 0;
if (end == start)
{
start = end + 1;
if (start == MOTION_SIZE)
start = 0;
miPointer.history_start = start;
}
miPointer.history_end = end;
}
history->event.x = x;
history->event.y = y;
history->event.time = time;
history->pScreen = pScreen;
}
void
_miRegisterPointerDevice (pScreen, pDevice)
ScreenPtr pScreen;
DeviceIntPtr pDevice;
{
miPointer.pPointer = (DevicePtr)pDevice;
}
/* obsolete: for binary compatibility */
#ifdef miRegisterPointerDevice
#undef miRegisterPointerDevice
void
miRegisterPointerDevice (pScreen, pDevice)
ScreenPtr pScreen;
DevicePtr pDevice;
{
miPointer.pPointer = pDevice;
}
#endif /* miRegisterPointerDevice */

View File

@@ -0,0 +1,160 @@
/*
* mipointer.h
*
*/
/*
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
#ifndef MIPOINTER_H
#define MIPOINTER_H
#include "cursor.h"
#include "input.h"
typedef struct _miPointerSpriteFuncRec {
Bool (*RealizeCursor)(
ScreenPtr /* pScr */,
CursorPtr /* pCurs */
);
Bool (*UnrealizeCursor)(
ScreenPtr /* pScr */,
CursorPtr /* pCurs */
);
void (*SetCursor)(
ScreenPtr /* pScr */,
CursorPtr /* pCurs */,
int /* x */,
int /* y */
);
void (*MoveCursor)(
ScreenPtr /* pScr */,
int /* x */,
int /* y */
);
} miPointerSpriteFuncRec, *miPointerSpriteFuncPtr;
typedef struct _miPointerScreenFuncRec {
Bool (*CursorOffScreen)(
ScreenPtr* /* ppScr */,
int* /* px */,
int* /* py */
);
void (*CrossScreen)(
ScreenPtr /* pScr */,
int /* entering */
);
void (*WarpCursor)(
ScreenPtr /* pScr */,
int /* x */,
int /* y */
);
void (*EnqueueEvent)(
xEventPtr /* event */
);
void (*NewEventScreen)(
ScreenPtr /* pScr */,
Bool /* fromDIX */
);
} miPointerScreenFuncRec, *miPointerScreenFuncPtr;
extern Bool miDCInitialize(
ScreenPtr /*pScreen*/,
miPointerScreenFuncPtr /*screenFuncs*/
);
extern Bool miPointerInitialize(
ScreenPtr /*pScreen*/,
miPointerSpriteFuncPtr /*spriteFuncs*/,
miPointerScreenFuncPtr /*screenFuncs*/,
Bool /*waitForUpdate*/
);
extern void miPointerWarpCursor(
ScreenPtr /*pScreen*/,
int /*x*/,
int /*y*/
);
extern int miPointerGetMotionBufferSize(
void
);
extern int miPointerGetMotionEvents(
DeviceIntPtr /*pPtr*/,
xTimecoord * /*coords*/,
unsigned long /*start*/,
unsigned long /*stop*/,
ScreenPtr /*pScreen*/
);
extern void miPointerUpdate(
void
);
extern void miPointerDeltaCursor(
int /*dx*/,
int /*dy*/,
unsigned long /*time*/
);
extern void miPointerAbsoluteCursor(
int /*x*/,
int /*y*/,
unsigned long /*time*/
);
extern void miPointerPosition(
int * /*x*/,
int * /*y*/
);
#undef miRegisterPointerDevice
extern void miRegisterPointerDevice(
ScreenPtr /*pScreen*/,
DevicePtr /*pDevice*/
);
extern void miPointerSetNewScreen(
int, /*screen_no*/
int, /*x*/
int /*y*/
);
extern ScreenPtr miPointerCurrentScreen(
void
);
#define miRegisterPointerDevice(pScreen,pDevice) \
_miRegisterPointerDevice(pScreen,pDevice)
extern void _miRegisterPointerDevice(
ScreenPtr /*pScreen*/,
DeviceIntPtr /*pDevice*/
);
extern int miPointerScreenIndex;
#endif /* MIPOINTER_H */

View File

@@ -0,0 +1,62 @@
/*
* mipointrst.h
*
*/
/*
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
#include "mipointer.h"
#include "scrnintstr.h"
#define MOTION_SIZE 256
typedef struct {
xTimecoord event;
ScreenPtr pScreen;
} miHistoryRec, *miHistoryPtr;
typedef struct {
ScreenPtr pScreen; /* current screen */
ScreenPtr pSpriteScreen;/* screen containing current sprite */
CursorPtr pCursor; /* current cursor */
CursorPtr pSpriteCursor;/* cursor on screen */
BoxRec limits; /* current constraints */
Bool confined; /* pointer can't change screens */
int x, y; /* hot spot location */
int devx, devy; /* sprite position */
DevicePtr pPointer; /* pointer device structure */
miHistoryRec history[MOTION_SIZE];
int history_start, history_end;
} miPointerRec, *miPointerPtr;
typedef struct {
miPointerSpriteFuncPtr spriteFuncs; /* sprite-specific methods */
miPointerScreenFuncPtr screenFuncs; /* screen-specific methods */
CloseScreenProcPtr CloseScreen;
Bool waitForUpdate; /* don't move cursor in SIGIO */
Bool showTransparent; /* show empty cursors */
} miPointerScreenRec, *miPointerScreenPtr;

View File

@@ -0,0 +1,127 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
/*
* mipoly.c
*
* Written by Brian Kelleher; June 1986
*
* Draw polygons. This routine translates the point by the
* origin if pGC->miTranslate is non-zero, and calls
* to the appropriate routine to actually scan convert the
* polygon.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "windowstr.h"
#include "gcstruct.h"
#include "pixmapstr.h"
#include "mi.h"
#include "regionstr.h"
void
miFillPolygon(dst, pgc, shape, mode, count, pPts)
DrawablePtr dst;
register GCPtr pgc;
int shape, mode;
register int count;
DDXPointPtr pPts;
{
int i;
register int xorg, yorg;
register DDXPointPtr ppt;
if (count == 0)
return;
ppt = pPts;
if (pgc->miTranslate)
{
xorg = dst->x;
yorg = dst->y;
if (mode == CoordModeOrigin)
{
for (i = 0; i<count; i++)
{
ppt->x += xorg;
ppt++->y += yorg;
}
}
else
{
ppt->x += xorg;
ppt++->y += yorg;
for (i = 1; i<count; i++)
{
ppt->x += (ppt-1)->x;
ppt->y += (ppt-1)->y;
ppt++;
}
}
}
else
{
if (mode == CoordModePrevious)
{
ppt++;
for (i = 1; i<count; i++)
{
ppt->x += (ppt-1)->x;
ppt->y += (ppt-1)->y;
ppt++;
}
}
}
if (shape == Convex)
miFillConvexPoly(dst, pgc, count, pPts);
else
miFillGeneralPoly(dst, pgc, count, pPts);
}

View File

@@ -0,0 +1,215 @@
/*
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
/*
* fill.h
*
* Created by Brian Kelleher; Oct 1985
*
* Include file for filled polygon routines.
*
* These are the data structures needed to scan
* convert regions. Two different scan conversion
* methods are available -- the even-odd method, and
* the winding number method.
* The even-odd rule states that a point is inside
* the polygon if a ray drawn from that point in any
* direction will pass through an odd number of
* path segments.
* By the winding number rule, a point is decided
* to be inside the polygon if a ray drawn from that
* point in any direction passes through a different
* number of clockwise and counter-clockwise path
* segments.
*
* These data structures are adapted somewhat from
* the algorithm in (Foley/Van Dam) for scan converting
* polygons.
* The basic algorithm is to start at the top (smallest y)
* of the polygon, stepping down to the bottom of
* the polygon by incrementing the y coordinate. We
* keep a list of edges which the current scanline crosses,
* sorted by x. This list is called the Active Edge Table (AET)
* As we change the y-coordinate, we update each entry in
* in the active edge table to reflect the edges new xcoord.
* This list must be sorted at each scanline in case
* two edges intersect.
* We also keep a data structure known as the Edge Table (ET),
* which keeps track of all the edges which the current
* scanline has not yet reached. The ET is basically a
* list of ScanLineList structures containing a list of
* edges which are entered at a given scanline. There is one
* ScanLineList per scanline at which an edge is entered.
* When we enter a new edge, we move it from the ET to the AET.
*
* From the AET, we can implement the even-odd rule as in
* (Foley/Van Dam).
* The winding number rule is a little trickier. We also
* keep the EdgeTableEntries in the AET linked by the
* nextWETE (winding EdgeTableEntry) link. This allows
* the edges to be linked just as before for updating
* purposes, but only uses the edges linked by the nextWETE
* link as edges representing spans of the polygon to
* drawn (as with the even-odd rule).
*/
/*
* for the winding number rule
*/
#define CLOCKWISE 1
#define COUNTERCLOCKWISE -1
typedef struct _EdgeTableEntry {
int ymax; /* ycoord at which we exit this edge. */
BRESINFO bres; /* Bresenham info to run the edge */
struct _EdgeTableEntry *next; /* next in the list */
struct _EdgeTableEntry *back; /* for insertion sort */
struct _EdgeTableEntry *nextWETE; /* for winding num rule */
int ClockWise; /* flag for winding number rule */
} EdgeTableEntry;
typedef struct _ScanLineList{
int scanline; /* the scanline represented */
EdgeTableEntry *edgelist; /* header node */
struct _ScanLineList *next; /* next in the list */
} ScanLineList;
typedef struct {
int ymax; /* ymax for the polygon */
int ymin; /* ymin for the polygon */
ScanLineList scanlines; /* header node */
} EdgeTable;
/*
* Here is a struct to help with storage allocation
* so we can allocate a big chunk at a time, and then take
* pieces from this heap when we need to.
*/
#define SLLSPERBLOCK 25
typedef struct _ScanLineListBlock {
ScanLineList SLLs[SLLSPERBLOCK];
struct _ScanLineListBlock *next;
} ScanLineListBlock;
/*
* number of points to buffer before sending them off
* to scanlines() : Must be an even number
*/
#define NUMPTSTOBUFFER 200
/*
*
* a few macros for the inner loops of the fill code where
* performance considerations don't allow a procedure call.
*
* Evaluate the given edge at the given scanline.
* If the edge has expired, then we leave it and fix up
* the active edge table; otherwise, we increment the
* x value to be ready for the next scanline.
* The winding number rule is in effect, so we must notify
* the caller when the edge has been removed so he
* can reorder the Winding Active Edge Table.
*/
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) { \
if (pAET->ymax == y) { /* leaving this edge */ \
pPrevAET->next = pAET->next; \
pAET = pPrevAET->next; \
fixWAET = 1; \
if (pAET) \
pAET->back = pPrevAET; \
} \
else { \
BRESINCRPGONSTRUCT(pAET->bres); \
pPrevAET = pAET; \
pAET = pAET->next; \
} \
}
/*
* Evaluate the given edge at the given scanline.
* If the edge has expired, then we leave it and fix up
* the active edge table; otherwise, we increment the
* x value to be ready for the next scanline.
* The even-odd rule is in effect.
*/
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y) { \
if (pAET->ymax == y) { /* leaving this edge */ \
pPrevAET->next = pAET->next; \
pAET = pPrevAET->next; \
if (pAET) \
pAET->back = pPrevAET; \
} \
else { \
BRESINCRPGONSTRUCT(pAET->bres); \
pPrevAET = pAET; \
pAET = pAET->next; \
} \
}
/* mipolyutil.c */
extern Bool miInsertEdgeInET(
EdgeTable * /*ET*/,
EdgeTableEntry * /*ETE*/,
int /*scanline*/,
ScanLineListBlock ** /*SLLBlock*/,
int * /*iSLLBlock*/
);
extern Bool miCreateETandAET(
int /*count*/,
DDXPointPtr /*pts*/,
EdgeTable * /*ET*/,
EdgeTableEntry * /*AET*/,
EdgeTableEntry * /*pETEs*/,
ScanLineListBlock * /*pSLLBlock*/
);
extern void miloadAET(
EdgeTableEntry * /*AET*/,
EdgeTableEntry * /*ETEs*/
);
extern void micomputeWAET(
EdgeTableEntry * /*AET*/
);
extern int miInsertionSort(
EdgeTableEntry * /*AET*/
);
extern void miFreeStorage(
ScanLineListBlock * /*pSLLBlock*/
);

View File

@@ -0,0 +1,246 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "gcstruct.h"
#include "pixmap.h"
#include "mi.h"
#include "miscanfill.h"
static int getPolyYBounds(DDXPointPtr pts, int n, int *by, int *ty);
/*
* convexpoly.c
*
* Written by Brian Kelleher; Dec. 1985.
*
* Fill a convex polygon. If the given polygon
* is not convex, then the result is undefined.
* The algorithm is to order the edges from smallest
* y to largest by partitioning the array into a left
* edge list and a right edge list. The algorithm used
* to traverse each edge is an extension of Bresenham's
* line algorithm with y as the major axis.
* For a derivation of the algorithm, see the author of
* this code.
*/
Bool
miFillConvexPoly(dst, pgc, count, ptsIn)
DrawablePtr dst;
GCPtr pgc;
int count; /* number of points */
DDXPointPtr ptsIn; /* the points */
{
register int xl = 0, xr = 0; /* x vals of left and right edges */
register int dl = 0, dr = 0; /* decision variables */
register 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 */
int y; /* current scanline */
int left, right; /* indices to first endpoints */
int i; /* loop counter */
int nextleft, nextright; /* indices to second endpoints */
DDXPointPtr ptsOut, FirstPoint; /* output buffer */
int *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. Also translate the points.
*/
imin = getPolyYBounds(ptsIn, count, &ymin, &ymax);
dy = ymax - ymin + 1;
if ((count < 3) || (dy < 0))
return(TRUE);
ptsOut = FirstPoint = (DDXPointPtr )malloc(sizeof(DDXPointRec)*dy);
width = FirstWidth = (int *)malloc(sizeof(int) * dy);
if(!FirstPoint || !FirstWidth)
{
if (FirstWidth) free(FirstWidth);
if (FirstPoint) free(FirstPoint);
return(FALSE);
}
nextleft = nextright = imin;
y = ptsIn[nextleft].y;
/*
* loop through all edges of the polygon
*/
do {
/*
* add a left edge if we need to
*/
if (ptsIn[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(ptsIn[nextleft].y-ptsIn[left].y,
ptsIn[left].x,ptsIn[nextleft].x,
xl, dl, ml, m1l, incr1l, incr2l);
}
/*
* add a right edge if we need to
*/
if (ptsIn[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(ptsIn[nextright].y-ptsIn[right].y,
ptsIn[right].x,ptsIn[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 = min(ptsIn[nextleft].y, ptsIn[nextright].y) - y;
/* in case we're called with non-convex polygon */
if(i < 0)
{
free(FirstWidth);
free(FirstPoint);
return(TRUE);
}
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 <remaining> spans
*/
(*pgc->ops->FillSpans)(dst, pgc,
ptsOut-FirstPoint,FirstPoint,FirstWidth,
1);
free(FirstWidth);
free(FirstPoint);
return(TRUE);
}
/*
* Find the index of the point with the smallest y.
*/
static int
getPolyYBounds(DDXPointPtr pts, int n, int *by, int *ty)
{
register DDXPointPtr ptMin;
int ymin, ymax;
DDXPointPtr ptsStart = pts;
ptMin = pts;
ymin = ymax = (pts++)->y;
while (--n > 0) {
if (pts->y < ymin)
{
ptMin = pts;
ymin = pts->y;
}
if(pts->y > ymax)
ymax = pts->y;
pts++;
}
*by = ymin;
*ty = ymax;
return(ptMin-ptsStart);
}

View File

@@ -0,0 +1,230 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "gcstruct.h"
#include "miscanfill.h"
#include "mipoly.h"
#include "pixmap.h"
#include "mi.h"
/*
*
* Written by Brian Kelleher; Oct. 1985
*
* Routine to fill a polygon. Two fill rules are
* supported: frWINDING and frEVENODD.
*
* See fillpoly.h for a complete description of the algorithm.
*/
Bool
miFillGeneralPoly(dst, pgc, count, ptsIn)
DrawablePtr dst;
GCPtr pgc;
int count; /* number of points */
DDXPointPtr ptsIn; /* the points */
{
register EdgeTableEntry *pAET; /* the Active Edge Table */
register int y; /* the current scanline */
register int nPts = 0; /* number of pts in buffer */
register EdgeTableEntry *pWETE; /* Winding Edge Table */
register ScanLineList *pSLL; /* Current ScanLineList */
register DDXPointPtr ptsOut; /* ptr to output buffers */
int *width;
DDXPointRec FirstPoint[NUMPTSTOBUFFER]; /* the output buffers */
int FirstWidth[NUMPTSTOBUFFER];
EdgeTableEntry *pPrevAET; /* previous AET entry */
EdgeTable ET; /* Edge Table header node */
EdgeTableEntry AET; /* Active ET header node */
EdgeTableEntry *pETEs; /* Edge Table Entries buff */
ScanLineListBlock SLLBlock; /* header for ScanLineList */
int fixWAET = 0;
if (count < 3)
return(TRUE);
if(!(pETEs = (EdgeTableEntry *)
malloc(sizeof(EdgeTableEntry) * count)))
return(FALSE);
ptsOut = FirstPoint;
width = FirstWidth;
if (!miCreateETandAET(count, ptsIn, &ET, &AET, pETEs, &SLLBlock))
{
free(pETEs);
return(FALSE);
}
pSLL = ET.scanlines.next;
if (pgc->fillRule == EvenOddRule)
{
/*
* 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 && y == pSLL->scanline)
{
miloadAET(&AET, pSLL->edgelist);
pSLL = pSLL->next;
}
pPrevAET = &AET;
pAET = AET.next;
/*
* for each active edge
*/
while (pAET)
{
ptsOut->x = pAET->bres.minor;
ptsOut++->y = y;
*width++ = pAET->next->bres.minor - pAET->bres.minor;
nPts++;
/*
* send out the buffer when its full
*/
if (nPts == NUMPTSTOBUFFER)
{
(*pgc->ops->FillSpans)(dst, pgc,
nPts, FirstPoint, FirstWidth,
1);
ptsOut = FirstPoint;
width = FirstWidth;
nPts = 0;
}
EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
EVALUATEEDGEEVENODD(pAET, pPrevAET, y);
}
miInsertionSort(&AET);
}
}
else /* default to WindingNumber */
{
/*
* 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 && y == pSLL->scanline)
{
miloadAET(&AET, pSLL->edgelist);
micomputeWAET(&AET);
pSLL = pSLL->next;
}
pPrevAET = &AET;
pAET = AET.next;
pWETE = pAET;
/*
* for each active edge
*/
while (pAET)
{
/*
* if the next edge in the active edge table is
* also the next edge in the winding active edge
* table.
*/
if (pWETE == pAET)
{
ptsOut->x = pAET->bres.minor;
ptsOut++->y = y;
*width++ = pAET->nextWETE->bres.minor - pAET->bres.minor;
nPts++;
/*
* send out the buffer
*/
if (nPts == NUMPTSTOBUFFER)
{
(*pgc->ops->FillSpans)(dst, pgc, nPts, FirstPoint,
FirstWidth, 1);
ptsOut = FirstPoint;
width = FirstWidth;
nPts = 0;
}
pWETE = pWETE->nextWETE;
while (pWETE != pAET)
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
pWETE = pWETE->nextWETE;
}
EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
}
/*
* reevaluate the Winding active edge table if we
* just had to resort it or if we just exited an edge.
*/
if (miInsertionSort(&AET) || fixWAET)
{
micomputeWAET(&AET);
fixWAET = 0;
}
}
}
/*
* Get any spans that we missed by buffering
*/
(*pgc->ops->FillSpans)(dst, pgc, nPts, FirstPoint, FirstWidth, 1);
free(pETEs);
miFreeStorage(SLLBlock.next);
return(TRUE);
}

View File

@@ -0,0 +1,123 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xprotostr.h>
#include "pixmapstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "mi.h"
void
miPolyPoint(pDrawable, pGC, mode, npt, pptInit)
DrawablePtr pDrawable;
GCPtr pGC;
int mode; /* Origin or Previous */
int npt;
xPoint *pptInit;
{
int xorg;
int yorg;
int nptTmp;
XID fsOld, fsNew;
int *pwidthInit, *pwidth;
int i;
register xPoint *ppt;
/* make pointlist origin relative */
if (mode == CoordModePrevious)
{
ppt = pptInit;
nptTmp = npt;
nptTmp--;
while(nptTmp--)
{
ppt++;
ppt->x += (ppt-1)->x;
ppt->y += (ppt-1)->y;
}
}
if(pGC->miTranslate)
{
ppt = pptInit;
nptTmp = npt;
xorg = pDrawable->x;
yorg = pDrawable->y;
while(nptTmp--)
{
ppt->x += xorg;
ppt++->y += yorg;
}
}
fsOld = pGC->fillStyle;
fsNew = FillSolid;
if(pGC->fillStyle != FillSolid)
{
DoChangeGC(pGC, GCFillStyle, &fsNew, 0);
ValidateGC(pDrawable, pGC);
}
if(!(pwidthInit = (int *)malloc(npt * sizeof(int))))
return;
pwidth = pwidthInit;
for(i = 0; i < npt; i++)
*pwidth++ = 1;
(*pGC->ops->FillSpans)(pDrawable, pGC, npt, pptInit, pwidthInit, FALSE);
if(fsOld != FillSolid)
{
DoChangeGC(pGC, GCFillStyle, &fsOld, 0);
ValidateGC(pDrawable, pGC);
}
free(pwidthInit);
}

View File

@@ -0,0 +1,191 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xprotostr.h>
#include "regionstr.h"
#include "gcstruct.h"
#include "pixmap.h"
#include "mi.h"
void
miPolyRectangle(pDraw, pGC, nrects, pRects)
DrawablePtr pDraw;
GCPtr pGC;
int nrects;
xRectangle *pRects;
{
int i;
xRectangle *pR = pRects;
DDXPointRec rect[5];
int bound_tmp;
#define MINBOUND(dst,eqn) bound_tmp = eqn; \
if (bound_tmp < -32768) \
bound_tmp = -32768; \
dst = bound_tmp;
#define MAXBOUND(dst,eqn) bound_tmp = eqn; \
if (bound_tmp > 32767) \
bound_tmp = 32767; \
dst = bound_tmp;
#define MAXUBOUND(dst,eqn) bound_tmp = eqn; \
if (bound_tmp > 65535) \
bound_tmp = 65535; \
dst = bound_tmp;
if (pGC->lineStyle == LineSolid && pGC->joinStyle == JoinMiter &&
pGC->lineWidth != 0)
{
xRectangle *tmp, *t;
int ntmp;
int offset1, offset2, offset3;
int x, y, width, height;
ntmp = (nrects << 2);
offset2 = pGC->lineWidth;
offset1 = offset2 >> 1;
offset3 = offset2 - offset1;
tmp = (xRectangle *) malloc(ntmp * sizeof (xRectangle));
if (!tmp)
return;
t = tmp;
for (i = 0; i < nrects; i++)
{
x = pR->x;
y = pR->y;
width = pR->width;
height = pR->height;
pR++;
if (width == 0 && height == 0)
{
rect[0].x = x;
rect[0].y = y;
rect[1].x = x;
rect[1].y = y;
(*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 2, rect);
}
else if (height < offset2 || width < offset1)
{
if (height == 0)
{
t->x = x;
t->width = width;
}
else
{
MINBOUND (t->x, x - offset1)
MAXUBOUND (t->width, width + offset2)
}
if (width == 0)
{
t->y = y;
t->height = height;
}
else
{
MINBOUND (t->y, y - offset1)
MAXUBOUND (t->height, height + offset2)
}
t++;
}
else
{
MINBOUND(t->x, x - offset1)
MINBOUND(t->y, y - offset1)
MAXUBOUND(t->width, width + offset2)
t->height = offset2;
t++;
MINBOUND(t->x, x - offset1)
MAXBOUND(t->y, y + offset3);
t->width = offset2;
t->height = height - offset2;
t++;
MAXBOUND(t->x, x + width - offset1);
MAXBOUND(t->y, y + offset3)
t->width = offset2;
t->height = height - offset2;
t++;
MINBOUND(t->x, x - offset1)
MAXBOUND(t->y, y + height - offset1)
MAXUBOUND(t->width, width + offset2)
t->height = offset2;
t++;
}
}
(*pGC->ops->PolyFillRect) (pDraw, pGC, t - tmp, tmp);
free ((void *) tmp);
}
else
{
for (i=0; i<nrects; i++)
{
rect[0].x = pR->x;
rect[0].y = pR->y;
MAXBOUND(rect[1].x, pR->x + (int) pR->width)
rect[1].y = rect[0].y;
rect[2].x = rect[1].x;
MAXBOUND(rect[2].y, pR->y + (int) pR->height);
rect[3].x = rect[0].x;
rect[3].y = rect[2].y;
rect[4].x = rect[0].x;
rect[4].y = rect[0].y;
(*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 5, rect);
pR++;
}
}
}

View File

@@ -0,0 +1,83 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xprotostr.h>
#include "regionstr.h"
#include "gcstruct.h"
#include "pixmap.h"
#include "mi.h"
/*****************************************************************
* miPolySegment
*
* For each segment, draws a line between (x1, y1) and (x2, y2). The
* lines are drawn in the order listed.
*
* Walks the segments, compressing them into format for PolyLines.
*
*****************************************************************/
void
miPolySegment(pDraw, pGC, nseg, pSegs)
DrawablePtr pDraw;
GCPtr pGC;
int nseg;
xSegment *pSegs;
{
int i;
for (i=0; i<nseg; i++)
{
(*pGC->ops->Polylines)(pDraw, pGC, CoordModeOrigin, 2,(DDXPointPtr)pSegs);
pSegs++;
}
}

View File

@@ -0,0 +1,200 @@
/*******************************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
************************************************************************/
/*
* mipolytext.c - text routines
*
* Author: haynes
* Digital Equipment Corporation
* Western Software Laboratory
* Date: Thu Feb 5 1987
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include <nx-X11/Xmd.h>
#include <nx-X11/Xproto.h>
#include "misc.h"
#include "gcstruct.h"
#include <X11/fonts/fontstruct.h>
#include "dixfontstr.h"
#include "mi.h"
int
miPolyText(pDraw, pGC, x, y, count, chars, fontEncoding)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
char *chars;
FontEncoding fontEncoding;
{
unsigned long n, i;
int w;
CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */
GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars,
fontEncoding, &n, charinfo);
w = 0;
for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
if (n != 0)
(*pGC->ops->PolyGlyphBlt)(
pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
return x+w;
}
int
miPolyText8(pDraw, pGC, x, y, count, chars)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
unsigned long n, i;
int w;
CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */
GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars,
Linear8Bit, &n, charinfo);
w = 0;
for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
if (n != 0)
(*pGC->ops->PolyGlyphBlt)(
pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
return x+w;
}
int
miPolyText16(pDraw, pGC, x, y, count, chars)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
unsigned short *chars;
{
unsigned long n, i;
int w;
CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */
GetGlyphs(pGC->font, (unsigned long)count, (unsigned char *)chars,
(FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
&n, charinfo);
w = 0;
for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
if (n != 0)
(*pGC->ops->PolyGlyphBlt)(
pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(pGC->font));
return x+w;
}
int
miImageText(pDraw, pGC, x, y, count, chars, fontEncoding)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
char *chars;
FontEncoding fontEncoding;
{
unsigned long n, i;
FontPtr font = pGC->font;
int w;
CharInfoPtr charinfo[255];
GetGlyphs(font, (unsigned long)count, (unsigned char *)chars,
fontEncoding, &n, charinfo);
w = 0;
for (i=0; i < n; i++) w += charinfo[i]->metrics.characterWidth;
if (n !=0 )
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(font));
return x+w;
}
void
miImageText8(pDraw, pGC, x, y, count, chars)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
char *chars;
{
unsigned long n;
FontPtr font = pGC->font;
CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */
GetGlyphs(font, (unsigned long)count, (unsigned char *)chars,
Linear8Bit, &n, charinfo);
if (n !=0 )
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(font));
}
void
miImageText16(pDraw, pGC, x, y, count, chars)
DrawablePtr pDraw;
GCPtr pGC;
int x, y;
int count;
unsigned short *chars;
{
unsigned long n;
FontPtr font = pGC->font;
CharInfoPtr charinfo[255]; /* encoding only has 1 byte for count */
GetGlyphs(font, (unsigned long)count, (unsigned char *)chars,
(FONTLASTROW(pGC->font) == 0) ? Linear16Bit : TwoD16Bit,
&n, charinfo);
if (n !=0 )
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, n, charinfo, FONTGLYPHS(font));
}

View File

@@ -0,0 +1,399 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "regionstr.h"
#include "gc.h"
#include "miscanfill.h"
#include "mipoly.h"
#include "misc.h" /* MAXINT */
/*
* fillUtils.c
*
* Written by Brian Kelleher; Oct. 1985
*
* This module contains all of the utility functions
* needed to scan convert a polygon.
*
*/
/*
* InsertEdgeInET
*
* Insert the given edge into the edge table.
* First we must find the correct bucket in the
* Edge table, then find the right slot in the
* bucket. Finally, we can insert it.
*
*/
Bool
miInsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
EdgeTable *ET;
EdgeTableEntry *ETE;
int scanline;
ScanLineListBlock **SLLBlock;
int *iSLLBlock;
{
register EdgeTableEntry *start, *prev;
register ScanLineList *pSLL, *pPrevSLL;
ScanLineListBlock *tmpSLLBlock;
/*
* find the right bucket to put the edge into
*/
pPrevSLL = &ET->scanlines;
pSLL = pPrevSLL->next;
while (pSLL && (pSLL->scanline < scanline))
{
pPrevSLL = pSLL;
pSLL = pSLL->next;
}
/*
* reassign pSLL (pointer to ScanLineList) if necessary
*/
if ((!pSLL) || (pSLL->scanline > scanline))
{
if (*iSLLBlock > SLLSPERBLOCK-1)
{
tmpSLLBlock =
(ScanLineListBlock *)malloc(sizeof(ScanLineListBlock));
if (!tmpSLLBlock)
return FALSE;
(*SLLBlock)->next = tmpSLLBlock;
tmpSLLBlock->next = (ScanLineListBlock *)NULL;
*SLLBlock = tmpSLLBlock;
*iSLLBlock = 0;
}
pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
pSLL->next = pPrevSLL->next;
pSLL->edgelist = (EdgeTableEntry *)NULL;
pPrevSLL->next = pSLL;
}
pSLL->scanline = scanline;
/*
* now insert the edge in the right bucket
*/
prev = (EdgeTableEntry *)NULL;
start = pSLL->edgelist;
while (start && (start->bres.minor < ETE->bres.minor))
{
prev = start;
start = start->next;
}
ETE->next = start;
if (prev)
prev->next = ETE;
else
pSLL->edgelist = ETE;
return TRUE;
}
/*
* CreateEdgeTable
*
* This routine creates the edge table for
* scan converting polygons.
* The Edge Table (ET) looks like:
*
* EdgeTable
* --------
* | ymax | ScanLineLists
* |scanline|-->------------>-------------->...
* -------- |scanline| |scanline|
* |edgelist| |edgelist|
* --------- ---------
* | |
* | |
* V V
* list of ETEs list of ETEs
*
* where ETE is an EdgeTableEntry data structure,
* and there is one ScanLineList per scanline at
* which an edge is initially entered.
*
*/
Bool
miCreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
register int count;
register DDXPointPtr pts;
EdgeTable *ET;
EdgeTableEntry *AET;
register EdgeTableEntry *pETEs;
ScanLineListBlock *pSLLBlock;
{
register DDXPointPtr top, bottom;
register DDXPointPtr PrevPt, CurrPt;
int iSLLBlock = 0;
int dy;
if (count < 2) return TRUE;
/*
* initialize the Active Edge Table
*/
AET->next = (EdgeTableEntry *)NULL;
AET->back = (EdgeTableEntry *)NULL;
AET->nextWETE = (EdgeTableEntry *)NULL;
AET->bres.minor = MININT;
/*
* initialize the Edge Table.
*/
ET->scanlines.next = (ScanLineList *)NULL;
ET->ymax = MININT;
ET->ymin = MAXINT;
pSLLBlock->next = (ScanLineListBlock *)NULL;
PrevPt = &pts[count-1];
/*
* for each vertex in the array of points.
* In this loop we are dealing with two vertices at
* a time -- these make up one edge of the polygon.
*/
while (count--)
{
CurrPt = pts++;
/*
* find out which point is above and which is below.
*/
if (PrevPt->y > CurrPt->y)
{
bottom = PrevPt, top = CurrPt;
pETEs->ClockWise = 0;
}
else
{
bottom = CurrPt, top = PrevPt;
pETEs->ClockWise = 1;
}
/*
* don't add horizontal edges to the Edge table.
*/
if (bottom->y != top->y)
{
pETEs->ymax = bottom->y-1; /* -1 so we don't get last scanline */
/*
* initialize integer edge algorithm
*/
dy = bottom->y - top->y;
BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock))
{
miFreeStorage(pSLLBlock->next);
return FALSE;
}
ET->ymax = max(ET->ymax, PrevPt->y);
ET->ymin = min(ET->ymin, PrevPt->y);
pETEs++;
}
PrevPt = CurrPt;
}
return TRUE;
}
/*
* loadAET
*
* This routine moves EdgeTableEntries from the
* EdgeTable into the Active Edge Table,
* leaving them sorted by smaller x coordinate.
*
*/
void
miloadAET(AET, ETEs)
register EdgeTableEntry *AET, *ETEs;
{
register EdgeTableEntry *pPrevAET;
register EdgeTableEntry *tmp;
pPrevAET = AET;
AET = AET->next;
while (ETEs)
{
while (AET && (AET->bres.minor < ETEs->bres.minor))
{
pPrevAET = AET;
AET = AET->next;
}
tmp = ETEs->next;
ETEs->next = AET;
if (AET)
AET->back = ETEs;
ETEs->back = pPrevAET;
pPrevAET->next = ETEs;
pPrevAET = ETEs;
ETEs = tmp;
}
}
/*
* computeWAET
*
* This routine links the AET by the
* nextWETE (winding EdgeTableEntry) link for
* use by the winding number rule. The final
* Active Edge Table (AET) might look something
* like:
*
* AET
* ---------- --------- ---------
* |ymax | |ymax | |ymax |
* | ... | |... | |... |
* |next |->|next |->|next |->...
* |nextWETE| |nextWETE| |nextWETE|
* --------- --------- ^--------
* | | |
* V-------------------> V---> ...
*
*/
void
micomputeWAET(AET)
register EdgeTableEntry *AET;
{
register EdgeTableEntry *pWETE;
register int inside = 1;
register int isInside = 0;
AET->nextWETE = (EdgeTableEntry *)NULL;
pWETE = AET;
AET = AET->next;
while (AET)
{
if (AET->ClockWise)
isInside++;
else
isInside--;
if ((!inside && !isInside) ||
( inside && isInside))
{
pWETE->nextWETE = AET;
pWETE = AET;
inside = !inside;
}
AET = AET->next;
}
pWETE->nextWETE = (EdgeTableEntry *)NULL;
}
/*
* InsertionSort
*
* Just a simple insertion sort using
* pointers and back pointers to sort the Active
* Edge Table.
*
*/
int
miInsertionSort(AET)
register EdgeTableEntry *AET;
{
register EdgeTableEntry *pETEchase;
register EdgeTableEntry *pETEinsert;
register EdgeTableEntry *pETEchaseBackTMP;
register int changed = 0;
AET = AET->next;
while (AET)
{
pETEinsert = AET;
pETEchase = AET;
while (pETEchase->back->bres.minor > AET->bres.minor)
pETEchase = pETEchase->back;
AET = AET->next;
if (pETEchase != pETEinsert)
{
pETEchaseBackTMP = pETEchase->back;
pETEinsert->back->next = AET;
if (AET)
AET->back = pETEinsert->back;
pETEinsert->next = pETEchase;
pETEchase->back->next = pETEinsert;
pETEchase->back = pETEinsert;
pETEinsert->back = pETEchaseBackTMP;
changed = 1;
}
}
return(changed);
}
/*
* Clean up our act.
*/
void
miFreeStorage(pSLLBlock)
register ScanLineListBlock *pSLLBlock;
{
register ScanLineListBlock *tmpSLLBlock;
while (pSLLBlock)
{
tmpSLLBlock = pSLLBlock->next;
free(pSLLBlock);
pSLLBlock = tmpSLLBlock;
}
}

View File

@@ -0,0 +1,274 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "gcstruct.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "regionstr.h"
#include "mi.h"
#include "servermd.h"
#define NPT 128
/* These were stolen from mfb. They don't really belong here. */
#define LONG2CHARSSAMEORDER(x) ((MiBits)(x))
#define LONG2CHARSDIFFORDER( x ) ( ( ( ( x ) & (MiBits)0x000000FF ) << 0x18 ) \
| ( ( ( x ) & (MiBits)0x0000FF00 ) << 0x08 ) \
| ( ( ( x ) & (MiBits)0x00FF0000 ) >> 0x08 ) \
| ( ( ( x ) & (MiBits)0xFF000000 ) >> 0x18 ) )
#define PGSZB 4
#define PPW (PGSZB<<3) /* assuming 8 bits per byte */
#define PGSZ PPW
#define PLST (PPW-1)
#define PIM PLST
#define PWSH 5
/* miPushPixels -- squeegees the fill style of pGC through pBitMap
* into pDrawable. pBitMap is a stencil (dx by dy of it is used, it may
* be bigger) which is placed on the drawable at xOrg, yOrg. Where a 1 bit
* is set in the bitmap, the fill style is put onto the drawable using
* the GC's logical function. The drawable is not changed where the bitmap
* has a zero bit or outside the area covered by the stencil.
WARNING:
this code works if the 1-bit deep pixmap format returned by GetSpans
is the same as the format defined by the mfb code (i.e. 32-bit padding
per scanline, scanline unit = 32 bits; later, this might mean
bitsizeof(int) padding and sacnline unit == bitsizeof(int).)
*/
/*
* in order to have both (MSB_FIRST and LSB_FIRST) versions of this
* in the server, we need to rename one of them
*/
void
miPushPixels(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg)
GCPtr pGC;
PixmapPtr pBitMap;
DrawablePtr pDrawable;
int dx, dy, xOrg, yOrg;
{
int h, dxDivPPW, ibEnd;
MiBits *pwLineStart;
register MiBits *pw, *pwEnd;
register MiBits msk;
register int ib, w;
register int ipt; /* index into above arrays */
Bool fInBox;
DDXPointRec pt[NPT], ptThisLine;
int width[NPT];
#ifdef XFree86Server
MiBits startmask;
if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
if (screenInfo.bitmapBitOrder == LSBFirst)
startmask = (MiBits)(-1) ^
LONG2CHARSSAMEORDER((MiBits)(-1) << 1);
else
startmask = (MiBits)(-1) ^
LONG2CHARSSAMEORDER((MiBits)(-1) >> 1);
else
if (screenInfo.bitmapBitOrder == LSBFirst)
startmask = (MiBits)(-1) ^
LONG2CHARSDIFFORDER((MiBits)(-1) << 1);
else
startmask = (MiBits)(-1) ^
LONG2CHARSDIFFORDER((MiBits)(-1) >> 1);
#endif
pwLineStart = (MiBits *)malloc(BitmapBytePad(dx));
if (!pwLineStart)
return;
ipt = 0;
dxDivPPW = dx/PPW;
for(h = 0, ptThisLine.x = 0, ptThisLine.y = 0;
h < dy;
h++, ptThisLine.y++)
{
(*pBitMap->drawable.pScreen->GetSpans)((DrawablePtr)pBitMap, dx,
&ptThisLine, &dx, 1, (char *)pwLineStart);
pw = pwLineStart;
/* Process all words which are fully in the pixmap */
fInBox = FALSE;
pwEnd = pwLineStart + dxDivPPW;
while(pw < pwEnd)
{
w = *pw;
#ifdef XFree86Server
msk = startmask;
#else
msk = (MiBits)(-1) ^ SCRRIGHT((MiBits)(-1), 1);
#endif
for(ib = 0; ib < PPW; ib++)
{
if(w & msk)
{
if(!fInBox)
{
pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg;
pt[ipt].y = h + yOrg;
/* start new box */
fInBox = TRUE;
}
}
else
{
if(fInBox)
{
width[ipt] = ((pw - pwLineStart) << PWSH) +
ib + xOrg - pt[ipt].x;
if (++ipt >= NPT)
{
(*pGC->ops->FillSpans)(pDrawable, pGC,
NPT, pt, width, TRUE);
ipt = 0;
}
/* end box */
fInBox = FALSE;
}
}
#ifdef XFree86Server
/* This is not quite right, but it'll do for now */
if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
if (screenInfo.bitmapBitOrder == LSBFirst)
msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1);
else
msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1);
else
if (screenInfo.bitmapBitOrder == LSBFirst)
msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1);
else
msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1);
#else
msk = SCRRIGHT(msk, 1);
#endif
}
pw++;
}
ibEnd = dx & PIM;
if(ibEnd)
{
/* Process final partial word on line */
w = *pw;
#ifdef XFree86Server
msk = startmask;
#else
msk = (MiBits)(-1) ^ SCRRIGHT((MiBits)(-1), 1);
#endif
for(ib = 0; ib < ibEnd; ib++)
{
if(w & msk)
{
if(!fInBox)
{
/* start new box */
pt[ipt].x = ((pw - pwLineStart) << PWSH) + ib + xOrg;
pt[ipt].y = h + yOrg;
fInBox = TRUE;
}
}
else
{
if(fInBox)
{
/* end box */
width[ipt] = ((pw - pwLineStart) << PWSH) +
ib + xOrg - pt[ipt].x;
if (++ipt >= NPT)
{
(*pGC->ops->FillSpans)(pDrawable,
pGC, NPT, pt, width, TRUE);
ipt = 0;
}
fInBox = FALSE;
}
}
#ifdef XFree86Server
/* This is not quite right, but it'll do for now */
if (screenInfo.bitmapBitOrder == IMAGE_BYTE_ORDER)
if (screenInfo.bitmapBitOrder == LSBFirst)
msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) << 1);
else
msk = LONG2CHARSSAMEORDER(LONG2CHARSSAMEORDER(msk) >> 1);
else
if (screenInfo.bitmapBitOrder == LSBFirst)
msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) << 1);
else
msk = LONG2CHARSDIFFORDER(LONG2CHARSDIFFORDER(msk) >> 1);
#else
msk = SCRRIGHT(msk, 1);
#endif
}
}
/* If scanline ended with last bit set, end the box */
if(fInBox)
{
width[ipt] = dx + xOrg - pt[ipt].x;
if (++ipt >= NPT)
{
(*pGC->ops->FillSpans)(pDrawable, pGC, NPT, pt, width, TRUE);
ipt = 0;
}
}
}
free(pwLineStart);
/* Flush any remaining spans */
if (ipt)
{
(*pGC->ops->FillSpans)(pDrawable, pGC, ipt, pt, width, TRUE);
}
}

View File

@@ -0,0 +1,147 @@
/*
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifndef SCANFILLINCLUDED
#define SCANFILLINCLUDED
/*
* scanfill.h
*
* Written by Brian Kelleher; Jan 1985
*
* This file contains a few macros to help track
* the edge of a filled object. The object is assumed
* to be filled in scanline order, and thus the
* algorithm used is an extension of Bresenham's line
* drawing algorithm which assumes that y is always the
* major axis.
* Since these pieces of code are the same for any filled shape,
* it is more convenient to gather the library in one
* place, but since these pieces of code are also in
* the inner loops of output primitives, procedure call
* overhead is out of the question.
* See the author for a derivation if needed.
*/
/*
* In scan converting polygons, we want to choose those pixels
* which are inside the polygon. Thus, we add .5 to the starting
* x coordinate for both left and right edges. Now we choose the
* first pixel which is inside the pgon for the left edge and the
* first pixel which is outside the pgon for the right edge.
* Draw the left pixel, but not the right.
*
* How to add .5 to the starting x coordinate:
* If the edge is moving to the right, then subtract dy from the
* error term from the general form of the algorithm.
* If the edge is moving to the left, then add dy to the error term.
*
* The reason for the difference between edges moving to the left
* and edges moving to the right is simple: If an edge is moving
* to the right, then we want the algorithm to flip immediately.
* If it is moving to the left, then we don't want it to flip until
* we traverse an entire pixel.
*/
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) { \
int dx; /* local storage */ \
\
/* \
* if the edge is horizontal, then it is ignored \
* and assumed not to be processed. Otherwise, do this stuff. \
*/ \
if ((dy) != 0) { \
xStart = (x1); \
dx = (x2) - xStart; \
if (dx < 0) { \
m = dx / (dy); \
m1 = m - 1; \
incr1 = -2 * dx + 2 * (dy) * m1; \
incr2 = -2 * dx + 2 * (dy) * m; \
d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
} else { \
m = dx / (dy); \
m1 = m + 1; \
incr1 = 2 * dx - 2 * (dy) * m1; \
incr2 = 2 * dx - 2 * (dy) * m; \
d = -2 * m * (dy) + 2 * dx; \
} \
} \
}
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2) { \
if (m1 > 0) { \
if (d > 0) { \
minval += m1; \
d += incr1; \
} \
else { \
minval += m; \
d += incr2; \
} \
} else {\
if (d >= 0) { \
minval += m1; \
d += incr1; \
} \
else { \
minval += m; \
d += incr2; \
} \
} \
}
/*
* This structure contains all of the information needed
* to run the bresenham algorithm.
* The variables may be hardcoded into the declarations
* instead of using this structure to make use of
* register declarations.
*/
typedef struct {
int minor; /* minor axis */
int d; /* decision variable */
int m, m1; /* slope and slope+1 */
int incr1, incr2; /* error increments */
} BRESINFO;
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
BRESINITPGON(dmaj, min1, min2, bres.minor, bres.d, \
bres.m, bres.m1, bres.incr1, bres.incr2)
#define BRESINCRPGONSTRUCT(bres) \
BRESINCRPGON(bres.d, bres.minor, bres.m, bres.m1, bres.incr1, bres.incr2)
#endif

View File

@@ -0,0 +1,342 @@
/*
Copyright 1990, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "servermd.h"
#include "misc.h"
#include "mi.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "dix.h"
#include "miline.h"
#ifdef MITSHM
#include "shmint.h"
#endif
/* We use this structure to propogate some information from miScreenInit to
* miCreateScreenResources. miScreenInit allocates the structure, fills it
* in, and puts it into pScreen->devPrivate. miCreateScreenResources
* extracts the info and frees the structure. We could've accomplished the
* same thing by adding fields to the screen structure, but they would have
* ended up being redundant, and would have exposed this mi implementation
* detail to the whole server.
*/
typedef struct
{
void * pbits; /* pointer to framebuffer */
int width; /* delta to add to a framebuffer addr to move one row down */
} miScreenInitParmsRec, *miScreenInitParmsPtr;
/* this plugs into pScreen->ModifyPixmapHeader */
Bool
miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind,
pPixData)
PixmapPtr pPixmap;
int width;
int height;
int depth;
int bitsPerPixel;
int devKind;
void *pPixData;
{
if (!pPixmap)
return FALSE;
/*
* If all arguments are specified, reinitialize everything (including
* validated state).
*/
if ((width > 0) && (height > 0) && (depth > 0) && (bitsPerPixel > 0) &&
(devKind > 0) && pPixData) {
pPixmap->drawable.depth = depth;
pPixmap->drawable.bitsPerPixel = bitsPerPixel;
pPixmap->drawable.id = 0;
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
pPixmap->drawable.x = 0;
pPixmap->drawable.y = 0;
pPixmap->drawable.width = width;
pPixmap->drawable.height = height;
pPixmap->devKind = devKind;
pPixmap->refcnt = 1;
pPixmap->devPrivate.ptr = pPixData;
} else {
/*
* Only modify specified fields, keeping all others intact.
*/
if (width > 0)
pPixmap->drawable.width = width;
if (height > 0)
pPixmap->drawable.height = height;
if (depth > 0)
pPixmap->drawable.depth = depth;
if (bitsPerPixel > 0)
pPixmap->drawable.bitsPerPixel = bitsPerPixel;
else if ((bitsPerPixel < 0) && (depth > 0))
pPixmap->drawable.bitsPerPixel = BitsPerPixel(depth);
/*
* CAVEAT: Non-SI DDXen may use devKind and devPrivate fields for
* other purposes.
*/
if (devKind > 0)
pPixmap->devKind = devKind;
else if ((devKind < 0) && ((width > 0) || (depth > 0)))
pPixmap->devKind = PixmapBytePad(pPixmap->drawable.width,
pPixmap->drawable.depth);
if (pPixData)
pPixmap->devPrivate.ptr = pPixData;
}
return TRUE;
}
/*ARGSUSED*/
Bool
miCloseScreen (pScreen)
ScreenPtr pScreen;
{
return ((*pScreen->DestroyPixmap)((PixmapPtr)pScreen->devPrivate));
}
/* With the introduction of pixmap privates, the "screen pixmap" can no
* longer be created in miScreenInit, since all the modules that could
* possibly ask for pixmap private space have not been initialized at
* that time. pScreen->CreateScreenResources is called after all
* possible private-requesting modules have been inited; we create the
* screen pixmap here.
*/
Bool
miCreateScreenResources(pScreen)
ScreenPtr pScreen;
{
miScreenInitParmsPtr pScrInitParms;
void * value;
pScrInitParms = (miScreenInitParmsPtr)pScreen->devPrivate;
/* if width is non-zero, pScreen->devPrivate will be a pixmap
* else it will just take the value pbits
*/
if (pScrInitParms->width)
{
PixmapPtr pPixmap;
/* create a pixmap with no data, then redirect it to point to
* the screen
*/
pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0);
if (!pPixmap)
return FALSE;
if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width,
pScreen->height, pScreen->rootDepth,
BitsPerPixel(pScreen->rootDepth),
PixmapBytePad(pScrInitParms->width, pScreen->rootDepth),
pScrInitParms->pbits))
return FALSE;
value = (void *)pPixmap;
}
else
{
value = pScrInitParms->pbits;
}
free(pScreen->devPrivate); /* freeing miScreenInitParmsRec */
pScreen->devPrivate = value; /* pPixmap or pbits */
return TRUE;
}
Bool
miScreenDevPrivateInit(pScreen, width, pbits)
register ScreenPtr pScreen;
int width;
void * pbits;
{
miScreenInitParmsPtr pScrInitParms;
/* Stash pbits and width in a short-lived miScreenInitParmsRec attached
* to the screen, until CreateScreenResources can put them in the
* screen pixmap.
*/
pScrInitParms = (miScreenInitParmsPtr)malloc(sizeof(miScreenInitParmsRec));
if (!pScrInitParms)
return FALSE;
pScrInitParms->pbits = pbits;
pScrInitParms->width = width;
pScreen->devPrivate = (void *)pScrInitParms;
return TRUE;
}
Bool
miScreenInit(pScreen, pbits, xsize, ysize, dpix, dpiy, width,
rootDepth, numDepths, depths, rootVisual, numVisuals, visuals)
register ScreenPtr pScreen;
void * pbits; /* pointer to screen bits */
int xsize, ysize; /* in pixels */
int dpix, dpiy; /* dots per inch */
int width; /* pixel width of frame buffer */
int rootDepth; /* depth of root window */
int numDepths; /* number of depths supported */
DepthRec *depths; /* supported depths */
VisualID rootVisual; /* root visual */
int numVisuals; /* number of visuals supported */
VisualRec *visuals; /* supported visuals */
{
pScreen->width = xsize;
pScreen->height = ysize;
pScreen->mmWidth = (xsize * 254 + dpix * 5) / (dpix * 10);
pScreen->mmHeight = (ysize * 254 + dpiy * 5) / (dpiy * 10);
pScreen->numDepths = numDepths;
pScreen->rootDepth = rootDepth;
pScreen->allowedDepths = depths;
pScreen->rootVisual = rootVisual;
/* defColormap */
pScreen->minInstalledCmaps = 1;
pScreen->maxInstalledCmaps = 1;
pScreen->backingStoreSupport = NotUseful;
pScreen->saveUnderSupport = NotUseful;
/* whitePixel, blackPixel */
pScreen->ModifyPixmapHeader = miModifyPixmapHeader;
pScreen->CreateScreenResources = miCreateScreenResources;
pScreen->GetScreenPixmap = miGetScreenPixmap;
pScreen->SetScreenPixmap = miSetScreenPixmap;
pScreen->numVisuals = numVisuals;
pScreen->visuals = visuals;
if (width)
{
#ifdef MITSHM
ShmRegisterFbFuncs(pScreen);
#endif
pScreen->CloseScreen = miCloseScreen;
}
/* else CloseScreen */
/* QueryBestSize, SaveScreen, GetImage, GetSpans */
pScreen->PointerNonInterestBox = (PointerNonInterestBoxProcPtr) 0;
pScreen->SourceValidate = (SourceValidateProcPtr) 0;
/* CreateWindow, DestroyWindow, PositionWindow, ChangeWindowAttributes */
/* RealizeWindow, UnrealizeWindow */
pScreen->ValidateTree = miValidateTree;
pScreen->PostValidateTree = (PostValidateTreeProcPtr) 0;
pScreen->WindowExposures = miWindowExposures;
/* PaintWindowBackground, PaintWindowBorder, CopyWindow */
pScreen->ClearToBackground = miClearToBackground;
pScreen->ClipNotify = (ClipNotifyProcPtr) 0;
pScreen->RestackWindow = (RestackWindowProcPtr) 0;
/* CreatePixmap, DestroyPixmap */
/* RealizeFont, UnrealizeFont */
/* CreateGC */
/* CreateColormap, DestroyColormap, InstallColormap, UninstallColormap */
/* ListInstalledColormaps, StoreColors, ResolveColor */
/* BitmapToRegion */
pScreen->SendGraphicsExpose = miSendGraphicsExpose;
pScreen->BlockHandler = (ScreenBlockHandlerProcPtr)NoopDDA;
pScreen->WakeupHandler = (ScreenWakeupHandlerProcPtr)NoopDDA;
pScreen->blockData = (void *)0;
pScreen->wakeupData = (void *)0;
pScreen->MarkWindow = miMarkWindow;
pScreen->MarkOverlappedWindows = miMarkOverlappedWindows;
pScreen->ChangeSaveUnder = miChangeSaveUnder;
pScreen->PostChangeSaveUnder = miPostChangeSaveUnder;
pScreen->MoveWindow = miMoveWindow;
pScreen->ResizeWindow = miSlideAndSizeWindow;
pScreen->GetLayerWindow = miGetLayerWindow;
pScreen->HandleExposures = miHandleValidateExposures;
pScreen->ReparentWindow = (ReparentWindowProcPtr) 0;
pScreen->ChangeBorderWidth = miChangeBorderWidth;
#ifdef SHAPE
pScreen->SetShape = miSetShape;
#endif
pScreen->MarkUnrealizedWindow = miMarkUnrealizedWindow;
pScreen->SaveDoomedAreas = 0;
pScreen->RestoreAreas = 0;
pScreen->ExposeCopy = 0;
pScreen->TranslateBackingStore = 0;
pScreen->ClearBackingStore = 0;
pScreen->DrawGuarantee = 0;
miSetZeroLineBias(pScreen, DEFAULTZEROLINEBIAS);
return miScreenDevPrivateInit(pScreen, width, pbits);
}
int
miAllocateGCPrivateIndex()
{
static int privateIndex = -1;
static unsigned long miGeneration = 0;
if (miGeneration != serverGeneration)
{
privateIndex = AllocateGCPrivateIndex();
miGeneration = serverGeneration;
}
return privateIndex;
}
int miZeroLineScreenIndex;
unsigned int miZeroLineGeneration = 0;
void
miSetZeroLineBias(pScreen, bias)
ScreenPtr pScreen;
unsigned int bias;
{
if (miZeroLineGeneration != serverGeneration)
{
miZeroLineScreenIndex = AllocateScreenPrivateIndex();
miZeroLineGeneration = serverGeneration;
}
if (miZeroLineScreenIndex >= 0)
pScreen->devPrivates[miZeroLineScreenIndex].uval = bias;
}
PixmapPtr
miGetScreenPixmap(pScreen)
ScreenPtr pScreen;
{
return (PixmapPtr)(pScreen->devPrivate);
}
void
miSetScreenPixmap(pPix)
PixmapPtr pPix;
{
if (pPix)
pPix->drawable.pScreen->devPrivate = (void *)pPix;
}

View File

@@ -0,0 +1,559 @@
/***********************************************************
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1989 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "misc.h"
#include "pixmapstr.h"
#include "gcstruct.h"
#include "mispans.h"
/*
These routines maintain lists of Spans, in order to implement the
``touch-each-pixel-once'' rules of wide lines and arcs.
Written by Joel McCormack, Summer 1989.
*/
void miInitSpanGroup(spanGroup)
SpanGroup *spanGroup;
{
spanGroup->size = 0;
spanGroup->count = 0;
spanGroup->group = NULL;
spanGroup->ymin = MAXSHORT;
spanGroup->ymax = MINSHORT;
} /* InitSpanGroup */
#define YMIN(spans) (spans->points[0].y)
#define YMAX(spans) (spans->points[spans->count-1].y)
void miSubtractSpans (spanGroup, sub)
SpanGroup *spanGroup;
Spans *sub;
{
int i, subCount, spansCount;
int ymin, ymax, xmin, xmax;
Spans *spans;
DDXPointPtr subPt, spansPt;
int *subWid, *spansWid;
int extra;
ymin = YMIN(sub);
ymax = YMAX(sub);
spans = spanGroup->group;
for (i = spanGroup->count; i; i--, spans++) {
if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) {
subCount = sub->count;
subPt = sub->points;
subWid = sub->widths;
spansCount = spans->count;
spansPt = spans->points;
spansWid = spans->widths;
extra = 0;
for (;;)
{
while (spansCount && spansPt->y < subPt->y)
{
spansPt++; spansWid++; spansCount--;
}
if (!spansCount)
break;
while (subCount && subPt->y < spansPt->y)
{
subPt++; subWid++; subCount--;
}
if (!subCount)
break;
if (subPt->y == spansPt->y)
{
xmin = subPt->x;
xmax = xmin + *subWid;
if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax)
{
;
}
else if (xmin <= spansPt->x)
{
if (xmax >= spansPt->x + *spansWid)
{
memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1));
memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1));
spansPt--;
spansWid--;
spans->count--;
extra++;
}
else
{
*spansWid = *spansWid - (xmax - spansPt->x);
spansPt->x = xmax;
}
}
else
{
if (xmax >= spansPt->x + *spansWid)
{
*spansWid = xmin - spansPt->x;
}
else
{
if (!extra) {
DDXPointPtr newPt;
int *newwid;
#define EXTRA 8
newPt = (DDXPointPtr) realloc (spans->points, (spans->count + EXTRA) * sizeof (DDXPointRec));
if (!newPt)
break;
spansPt = newPt + (spansPt - spans->points);
spans->points = newPt;
newwid = (int *) realloc (spans->widths, (spans->count + EXTRA) * sizeof (int));
if (!newwid)
break;
spansWid = newwid + (spansWid - spans->widths);
spans->widths = newwid;
extra = EXTRA;
}
memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount));
memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount));
spans->count++;
extra--;
*spansWid = xmin - spansPt->x;
spansWid++;
spansPt++;
*spansWid = *spansWid - (xmax - spansPt->x);
spansPt->x = xmax;
}
}
}
spansPt++; spansWid++; spansCount--;
}
}
}
}
void miAppendSpans(spanGroup, otherGroup, spans)
SpanGroup *spanGroup;
SpanGroup *otherGroup;
Spans *spans;
{
register int ymin, ymax;
register int spansCount;
spansCount = spans->count;
if (spansCount > 0) {
if (spanGroup->size == spanGroup->count) {
spanGroup->size = (spanGroup->size + 8) * 2;
spanGroup->group = (Spans *)
realloc(spanGroup->group, sizeof(Spans) * spanGroup->size);
}
spanGroup->group[spanGroup->count] = *spans;
(spanGroup->count)++;
ymin = spans->points[0].y;
if (ymin < spanGroup->ymin) spanGroup->ymin = ymin;
ymax = spans->points[spansCount - 1].y;
if (ymax > spanGroup->ymax) spanGroup->ymax = ymax;
if (otherGroup &&
otherGroup->ymin < ymax &&
ymin < otherGroup->ymax)
{
miSubtractSpans (otherGroup, spans);
}
}
else
{
free (spans->points);
free (spans->widths);
}
} /* AppendSpans */
void miFreeSpanGroup(spanGroup)
SpanGroup *spanGroup;
{
if (spanGroup->group != NULL) free(spanGroup->group);
}
static void QuickSortSpansX(
register DDXPointRec points[],
register int widths[],
register int numSpans )
{
register int x;
register int i, j, m;
register DDXPointPtr r;
/* Always called with numSpans > 1 */
/* Sorts only by x, as all y should be the same */
#define ExchangeSpans(a, b) \
{ \
DDXPointRec tpt; \
register int tw; \
\
tpt = points[a]; points[a] = points[b]; points[b] = tpt; \
tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \
}
do {
if (numSpans < 9) {
/* Do insertion sort */
register int xprev;
xprev = points[0].x;
i = 1;
do { /* while i != numSpans */
x = points[i].x;
if (xprev > x) {
/* points[i] is out of order. Move into proper location. */
DDXPointRec tpt;
int tw, k;
for (j = 0; x >= points[j].x; j++) {}
tpt = points[i];
tw = widths[i];
for (k = i; k != j; k--) {
points[k] = points[k-1];
widths[k] = widths[k-1];
}
points[j] = tpt;
widths[j] = tw;
x = points[i].x;
} /* if out of order */
xprev = x;
i++;
} while (i != numSpans);
return;
}
/* Choose partition element, stick in location 0 */
m = numSpans / 2;
if (points[m].x > points[0].x) ExchangeSpans(m, 0);
if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1);
if (points[m].x > points[0].x) ExchangeSpans(m, 0);
x = points[0].x;
/* Partition array */
i = 0;
j = numSpans;
do {
r = &(points[i]);
do {
r++;
i++;
} while (i != numSpans && r->x < x);
r = &(points[j]);
do {
r--;
j--;
} while (x < r->x);
if (i < j) ExchangeSpans(i, j);
} while (i < j);
/* Move partition element back to middle */
ExchangeSpans(0, j);
/* Recurse */
if (numSpans-j-1 > 1)
QuickSortSpansX(&points[j+1], &widths[j+1], numSpans-j-1);
numSpans = j;
} while (numSpans > 1);
} /* QuickSortSpans */
static int UniquifySpansX(
Spans *spans,
register DDXPointRec *newPoints,
register int *newWidths )
{
register int newx1, newx2, oldpt, i, y;
register DDXPointRec *oldPoints;
register int *oldWidths;
int *startNewWidths;
/* Always called with numSpans > 1 */
/* Uniquify the spans, and stash them into newPoints and newWidths. Return the
number of unique spans. */
startNewWidths = newWidths;
oldPoints = spans->points;
oldWidths = spans->widths;
y = oldPoints->y;
newx1 = oldPoints->x;
newx2 = newx1 + *oldWidths;
for (i = spans->count-1; i != 0; i--) {
oldPoints++;
oldWidths++;
oldpt = oldPoints->x;
if (oldpt > newx2) {
/* Write current span, start a new one */
newPoints->x = newx1;
newPoints->y = y;
*newWidths = newx2 - newx1;
newPoints++;
newWidths++;
newx1 = oldpt;
newx2 = oldpt + *oldWidths;
} else {
/* extend current span, if old extends beyond new */
oldpt = oldpt + *oldWidths;
if (oldpt > newx2) newx2 = oldpt;
}
} /* for */
/* Write final span */
newPoints->x = newx1;
*newWidths = newx2 - newx1;
newPoints->y = y;
return (newWidths - startNewWidths) + 1;
} /* UniquifySpansX */
void
miDisposeSpanGroup (spanGroup)
SpanGroup *spanGroup;
{
int i;
Spans *spans;
for (i = 0; i < spanGroup->count; i++)
{
spans = spanGroup->group + i;
free (spans->points);
free (spans->widths);
}
}
void miFillUniqueSpanGroup(pDraw, pGC, spanGroup)
DrawablePtr pDraw;
GCPtr pGC;
SpanGroup *spanGroup;
{
register int i;
register Spans *spans;
register Spans *yspans;
register int *ysizes;
register int ymin, ylength;
/* Outgoing spans for one big call to FillSpans */
register DDXPointPtr points;
register int *widths;
register int count;
if (spanGroup->count == 0) return;
if (spanGroup->count == 1) {
/* Already should be sorted, unique */
spans = spanGroup->group;
(*pGC->ops->FillSpans)
(pDraw, pGC, spans->count, spans->points, spans->widths, TRUE);
free(spans->points);
free(spans->widths);
}
else
{
/* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */
/* This seems to be the fastest thing to do. I've tried sorting on
both x and y at the same time rather than creating into all those
y buckets, but it was somewhat slower. */
ymin = spanGroup->ymin;
ylength = spanGroup->ymax - ymin + 1;
/* Allocate Spans for y buckets */
yspans = (Spans *) malloc(ylength * sizeof(Spans));
ysizes = (int *) malloc(ylength * sizeof (int));
if (!yspans || !ysizes)
{
if (yspans)
free (yspans);
if (ysizes)
free (ysizes);
miDisposeSpanGroup (spanGroup);
return;
}
for (i = 0; i != ylength; i++) {
ysizes[i] = 0;
yspans[i].count = 0;
yspans[i].points = NULL;
yspans[i].widths = NULL;
}
/* Go through every single span and put it into the correct bucket */
count = 0;
for (i = 0, spans = spanGroup->group;
i != spanGroup->count;
i++, spans++) {
int index;
int j;
for (j = 0, points = spans->points, widths = spans->widths;
j != spans->count;
j++, points++, widths++) {
index = points->y - ymin;
if (index >= 0 && index < ylength) {
Spans *newspans = &(yspans[index]);
if (newspans->count == ysizes[index]) {
DDXPointPtr newpoints;
int *newwidths;
ysizes[index] = (ysizes[index] + 8) * 2;
newpoints = (DDXPointPtr) realloc(
newspans->points,
ysizes[index] * sizeof(DDXPointRec));
newwidths = (int *) realloc(
newspans->widths,
ysizes[index] * sizeof(int));
if (!newpoints || !newwidths)
{
int k;
for (k = 0; k < ylength; k++)
{
free (yspans[k].points);
free (yspans[k].widths);
}
free (yspans);
free (ysizes);
miDisposeSpanGroup (spanGroup);
return;
}
newspans->points = newpoints;
newspans->widths = newwidths;
}
newspans->points[newspans->count] = *points;
newspans->widths[newspans->count] = *widths;
(newspans->count)++;
} /* if y value of span in range */
} /* for j through spans */
count += spans->count;
free(spans->points);
spans->points = NULL;
free(spans->widths);
spans->widths = NULL;
} /* for i thorough Spans */
/* Now sort by x and uniquify each bucket into the final array */
points = (DDXPointPtr) malloc(count * sizeof(DDXPointRec));
widths = (int *) malloc(count * sizeof(int));
if (!points || !widths)
{
for (i = 0; i < ylength; i++)
{
free (yspans[i].points);
free (yspans[i].widths);
}
free (yspans);
free (ysizes);
if (points)
free (points);
if (widths)
free (widths);
return;
}
count = 0;
for (i = 0; i != ylength; i++) {
int ycount = yspans[i].count;
if (ycount > 0) {
if (ycount > 1) {
QuickSortSpansX(yspans[i].points, yspans[i].widths, ycount);
count += UniquifySpansX
(&(yspans[i]), &(points[count]), &(widths[count]));
} else {
points[count] = yspans[i].points[0];
widths[count] = yspans[i].widths[0];
count++;
}
free(yspans[i].points);
free(yspans[i].widths);
}
}
(*pGC->ops->FillSpans) (pDraw, pGC, count, points, widths, TRUE);
free(points);
free(widths);
free(yspans);
free(ysizes);
}
spanGroup->count = 0;
spanGroup->ymin = MAXSHORT;
spanGroup->ymax = MINSHORT;
}
void miFillSpanGroup(pDraw, pGC, spanGroup)
DrawablePtr pDraw;
GCPtr pGC;
SpanGroup *spanGroup;
{
register int i;
register Spans *spans;
for (i = 0, spans = spanGroup->group; i != spanGroup->count; i++, spans++) {
(*pGC->ops->FillSpans)
(pDraw, pGC, spans->count, spans->points, spans->widths, TRUE);
free(spans->points);
free(spans->widths);
}
spanGroup->count = 0;
spanGroup->ymin = MAXSHORT;
spanGroup->ymax = MINSHORT;
} /* FillSpanGroup */

View File

@@ -0,0 +1,115 @@
/***********************************************************
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1989 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
typedef struct {
int count; /* number of spans */
DDXPointPtr points; /* pointer to list of start points */
int *widths; /* pointer to list of widths */
} Spans;
typedef struct {
int size; /* Total number of *Spans allocated */
int count; /* Number of *Spans actually in group */
Spans *group; /* List of Spans */
int ymin, ymax; /* Min, max y values encountered */
} SpanGroup;
/* Initialize SpanGroup. MUST BE DONE before use. */
extern void miInitSpanGroup(
SpanGroup * /*spanGroup*/
);
/* Add a Spans to a SpanGroup. The spans MUST BE in y-sorted order */
extern void miAppendSpans(
SpanGroup * /*spanGroup*/,
SpanGroup * /*otherGroup*/,
Spans * /*spans*/
);
/* Paint a span group, possibly with some overlap */
extern void miFillSpanGroup(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
SpanGroup * /*spanGroup*/
);
/* Paint a span group, insuring that each pixel is painted at most once */
extern void miFillUniqueSpanGroup(
DrawablePtr /*pDraw*/,
GCPtr /*pGC*/,
SpanGroup * /*spanGroup*/
);
/* Free up data in a span group. MUST BE DONE or you'll suffer memory leaks */
extern void miFreeSpanGroup(
SpanGroup * /*spanGroup*/
);
extern void miSubtractSpans(
SpanGroup * /*spanGroup*/,
Spans * /*sub*/
);
extern void miDisposeSpanGroup(
SpanGroup * /*spanGroup*/
);
extern int RegionClipSpans(
RegionPtr /*prgnDst*/,
DDXPointPtr /*ppt*/,
int * /*pwidth*/,
int /*nspans*/,
DDXPointPtr /*pptNew*/,
int * /*pwidthNew*/,
int /*fSorted*/
);
/* Rops which must use span groups */
#define miSpansCarefulRop(rop) (((rop) & 0xc) == 0x8 || ((rop) & 0x3) == 0x2)
#define miSpansEasyRop(rop) (!miSpansCarefulRop(rop))

View File

@@ -0,0 +1,828 @@
/*
* misprite.c
*
* machine independent software sprite routines
*/
/*
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
# include <nx-X11/X.h>
# include <nx-X11/Xproto.h>
# include "misc.h"
# include "pixmapstr.h"
# include "input.h"
# include "mi.h"
# include "cursorstr.h"
# include <X11/fonts/font.h>
# include "scrnintstr.h"
# include "colormapst.h"
# include "windowstr.h"
# include "gcstruct.h"
# include "mipointer.h"
# include "mispritest.h"
# include "dixfontstr.h"
# include <X11/fonts/fontstruct.h>
#ifdef RENDER
# include "mipict.h"
#endif
# include "damage.h"
#define SPRITE_DEBUG_ENABLE 0
#if SPRITE_DEBUG_ENABLE
#define SPRITE_DEBUG(x) ErrorF x
#else
#define SPRITE_DEBUG(x)
#endif
/*
* screen wrappers
*/
static int miSpriteScreenIndex;
static unsigned long miSpriteGeneration = 0;
static Bool miSpriteCloseScreen(ScreenPtr pScreen);
static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy,
int w, int h, unsigned int format,
unsigned long planemask, char *pdstLine);
static void miSpriteGetSpans(DrawablePtr pDrawable, int wMax,
DDXPointPtr ppt, int *pwidth, int nspans,
char *pdstStart);
static void miSpriteSourceValidate(DrawablePtr pDrawable, int x, int y,
int width, int height);
static void miSpriteCopyWindow (WindowPtr pWindow,
DDXPointRec ptOldOrg,
RegionPtr prgnSrc);
static void miSpriteBlockHandler(int i, void * blockData,
void * pTimeout,
void * pReadMask);
static void miSpriteInstallColormap(ColormapPtr pMap);
static void miSpriteStoreColors(ColormapPtr pMap, int ndef,
xColorItem *pdef);
static void miSpriteSaveDoomedAreas(WindowPtr pWin,
RegionPtr pObscured, int dx,
int dy);
static void miSpriteComputeSaved(ScreenPtr pScreen);
#define SCREEN_PROLOGUE(pScreen, field)\
((pScreen)->field = \
((miSpriteScreenPtr) (pScreen)->devPrivates[miSpriteScreenIndex].ptr)->field)
#define SCREEN_EPILOGUE(pScreen, field)\
((pScreen)->field = miSprite##field)
/*
* pointer-sprite method table
*/
static Bool miSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor);
static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor,
int x, int y);
static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y);
miPointerSpriteFuncRec miSpritePointerFuncs = {
miSpriteRealizeCursor,
miSpriteUnrealizeCursor,
miSpriteSetCursor,
miSpriteMoveCursor,
};
/*
* other misc functions
*/
static void miSpriteRemoveCursor(ScreenPtr pScreen);
static void miSpriteRestoreCursor(ScreenPtr pScreen);
static void
miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure)
{
ScreenPtr pScreen = closure;
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pScreenPriv->isUp &&
RegionContainsRect(pRegion, &pScreenPriv->saved) != rgnOUT)
{
SPRITE_DEBUG(("Damage remove\n"));
miSpriteRemoveCursor (pScreen);
}
}
/*
* miSpriteInitialize -- called from device-dependent screen
* initialization proc after all of the function pointers have
* been stored in the screen structure.
*/
Bool
miSpriteInitialize (pScreen, cursorFuncs, screenFuncs)
ScreenPtr pScreen;
miSpriteCursorFuncPtr cursorFuncs;
miPointerScreenFuncPtr screenFuncs;
{
miSpriteScreenPtr pScreenPriv;
VisualPtr pVisual;
if (!DamageSetup (pScreen))
return FALSE;
if (miSpriteGeneration != serverGeneration)
{
miSpriteScreenIndex = AllocateScreenPrivateIndex ();
if (miSpriteScreenIndex < 0)
return FALSE;
miSpriteGeneration = serverGeneration;
}
pScreenPriv = (miSpriteScreenPtr) malloc (sizeof (miSpriteScreenRec));
if (!pScreenPriv)
return FALSE;
pScreenPriv->pDamage = DamageCreate (miSpriteReportDamage,
(DamageDestroyFunc) 0,
DamageReportRawRegion,
TRUE,
pScreen,
(void *) pScreen);
if (!miPointerInitialize (pScreen, &miSpritePointerFuncs, screenFuncs,TRUE))
{
free ((void *) pScreenPriv);
return FALSE;
}
for (pVisual = pScreen->visuals;
pVisual->vid != pScreen->rootVisual;
pVisual++)
;
pScreenPriv->pVisual = pVisual;
pScreenPriv->CloseScreen = pScreen->CloseScreen;
pScreenPriv->GetImage = pScreen->GetImage;
pScreenPriv->GetSpans = pScreen->GetSpans;
pScreenPriv->SourceValidate = pScreen->SourceValidate;
pScreenPriv->CopyWindow = pScreen->CopyWindow;
pScreenPriv->SaveDoomedAreas = pScreen->SaveDoomedAreas;
pScreenPriv->InstallColormap = pScreen->InstallColormap;
pScreenPriv->StoreColors = pScreen->StoreColors;
pScreenPriv->BlockHandler = pScreen->BlockHandler;
pScreenPriv->pCursor = NULL;
pScreenPriv->x = 0;
pScreenPriv->y = 0;
pScreenPriv->isUp = FALSE;
pScreenPriv->shouldBeUp = FALSE;
pScreenPriv->pCacheWin = NullWindow;
pScreenPriv->isInCacheWin = FALSE;
pScreenPriv->checkPixels = TRUE;
pScreenPriv->pInstalledMap = NULL;
pScreenPriv->pColormap = NULL;
pScreenPriv->funcs = cursorFuncs;
pScreenPriv->colors[SOURCE_COLOR].red = 0;
pScreenPriv->colors[SOURCE_COLOR].green = 0;
pScreenPriv->colors[SOURCE_COLOR].blue = 0;
pScreenPriv->colors[MASK_COLOR].red = 0;
pScreenPriv->colors[MASK_COLOR].green = 0;
pScreenPriv->colors[MASK_COLOR].blue = 0;
pScreen->devPrivates[miSpriteScreenIndex].ptr = (void *) pScreenPriv;
pScreen->CloseScreen = miSpriteCloseScreen;
pScreen->GetImage = miSpriteGetImage;
pScreen->GetSpans = miSpriteGetSpans;
pScreen->SourceValidate = miSpriteSourceValidate;
pScreen->CopyWindow = miSpriteCopyWindow;
pScreen->SaveDoomedAreas = miSpriteSaveDoomedAreas;
pScreen->InstallColormap = miSpriteInstallColormap;
pScreen->StoreColors = miSpriteStoreColors;
pScreen->BlockHandler = miSpriteBlockHandler;
return TRUE;
}
/*
* Screen wrappers
*/
/*
* CloseScreen wrapper -- unwrap everything, free the private data
* and call the wrapped function
*/
static Bool
miSpriteCloseScreen (pScreen)
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pScreen->CloseScreen = pScreenPriv->CloseScreen;
pScreen->GetImage = pScreenPriv->GetImage;
pScreen->GetSpans = pScreenPriv->GetSpans;
pScreen->SourceValidate = pScreenPriv->SourceValidate;
pScreen->BlockHandler = pScreenPriv->BlockHandler;
pScreen->InstallColormap = pScreenPriv->InstallColormap;
pScreen->StoreColors = pScreenPriv->StoreColors;
pScreen->SaveDoomedAreas = pScreenPriv->SaveDoomedAreas;
miSpriteIsUpFALSE (pScreen, pScreenPriv);
DamageDestroy (pScreenPriv->pDamage);
free ((void *) pScreenPriv);
return (*pScreen->CloseScreen) (pScreen);
}
static void
miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine)
DrawablePtr pDrawable;
int sx, sy, w, h;
unsigned int format;
unsigned long planemask;
char *pdstLine;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, GetImage);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW &&
pScreenPriv->isUp &&
ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h))
{
SPRITE_DEBUG (("GetImage remove\n"));
miSpriteRemoveCursor (pScreen);
}
(*pScreen->GetImage) (pDrawable, sx, sy, w, h,
format, planemask, pdstLine);
SCREEN_EPILOGUE (pScreen, GetImage);
}
static void
miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart)
DrawablePtr pDrawable;
int wMax;
DDXPointPtr ppt;
int *pwidth;
int nspans;
char *pdstStart;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, GetSpans);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp)
{
register DDXPointPtr pts;
register int *widths;
register int nPts;
register int xorg,
yorg;
xorg = pDrawable->x;
yorg = pDrawable->y;
for (pts = ppt, widths = pwidth, nPts = nspans;
nPts--;
pts++, widths++)
{
if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg,
pts->x+xorg,*widths))
{
SPRITE_DEBUG (("GetSpans remove\n"));
miSpriteRemoveCursor (pScreen);
break;
}
}
}
(*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
SCREEN_EPILOGUE (pScreen, GetSpans);
}
static void
miSpriteSourceValidate (pDrawable, x, y, width, height)
DrawablePtr pDrawable;
int x, y, width, height;
{
ScreenPtr pScreen = pDrawable->pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, SourceValidate);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp &&
ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y,
x, y, width, height))
{
SPRITE_DEBUG (("SourceValidate remove\n"));
miSpriteRemoveCursor (pScreen);
}
if (pScreen->SourceValidate)
(*pScreen->SourceValidate) (pDrawable, x, y, width, height);
SCREEN_EPILOGUE (pScreen, SourceValidate);
}
static void
miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
ScreenPtr pScreen = pWindow->drawable.pScreen;
miSpriteScreenPtr pScreenPriv;
SCREEN_PROLOGUE (pScreen, CopyWindow);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
/*
* Damage will take care of destination check
*/
if (pScreenPriv->isUp &&
RegionContainsRect(prgnSrc, &pScreenPriv->saved) != rgnOUT)
{
SPRITE_DEBUG (("CopyWindow remove\n"));
miSpriteRemoveCursor (pScreen);
}
(*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc);
SCREEN_EPILOGUE (pScreen, CopyWindow);
}
static void
miSpriteBlockHandler (i, blockData, pTimeout, pReadmask)
int i;
void * blockData;
void * pTimeout;
void * pReadmask;
{
ScreenPtr pScreen = screenInfo.screens[i];
miSpriteScreenPtr pPriv;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, BlockHandler);
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
SCREEN_EPILOGUE(pScreen, BlockHandler);
if (!pPriv->isUp && pPriv->shouldBeUp)
{
SPRITE_DEBUG (("BlockHandler restore\n"));
miSpriteRestoreCursor (pScreen);
}
}
static void
miSpriteInstallColormap (pMap)
ColormapPtr pMap;
{
ScreenPtr pScreen = pMap->pScreen;
miSpriteScreenPtr pPriv;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, InstallColormap);
(*pScreen->InstallColormap) (pMap);
SCREEN_EPILOGUE(pScreen, InstallColormap);
pPriv->pInstalledMap = pMap;
if (pPriv->pColormap != pMap)
{
pPriv->checkPixels = TRUE;
if (pPriv->isUp)
miSpriteRemoveCursor (pScreen);
}
}
static void
miSpriteStoreColors (pMap, ndef, pdef)
ColormapPtr pMap;
int ndef;
xColorItem *pdef;
{
ScreenPtr pScreen = pMap->pScreen;
miSpriteScreenPtr pPriv;
int i;
int updated;
VisualPtr pVisual;
pPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
SCREEN_PROLOGUE(pScreen, StoreColors);
(*pScreen->StoreColors) (pMap, ndef, pdef);
SCREEN_EPILOGUE(pScreen, StoreColors);
if (pPriv->pColormap == pMap)
{
updated = 0;
pVisual = pMap->pVisual;
if (pVisual->class == DirectColor)
{
/* Direct color - match on any of the subfields */
#define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask)))
#define UpdateDAC(plane,dac,mask) {\
if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\
pPriv->colors[plane].dac = pdef[i].dac; \
updated = 1; \
} \
}
#define CheckDirect(plane) \
UpdateDAC(plane,red,redMask) \
UpdateDAC(plane,green,greenMask) \
UpdateDAC(plane,blue,blueMask)
for (i = 0; i < ndef; i++)
{
CheckDirect (SOURCE_COLOR)
CheckDirect (MASK_COLOR)
}
}
else
{
/* PseudoColor/GrayScale - match on exact pixel */
for (i = 0; i < ndef; i++)
{
if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel)
{
pPriv->colors[SOURCE_COLOR] = pdef[i];
if (++updated == 2)
break;
}
if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel)
{
pPriv->colors[MASK_COLOR] = pdef[i];
if (++updated == 2)
break;
}
}
}
if (updated)
{
pPriv->checkPixels = TRUE;
if (pPriv->isUp)
miSpriteRemoveCursor (pScreen);
}
}
}
static void
miSpriteFindColors (ScreenPtr pScreen)
{
miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr)
pScreen->devPrivates[miSpriteScreenIndex].ptr;
CursorPtr pCursor;
xColorItem *sourceColor, *maskColor;
pCursor = pScreenPriv->pCursor;
sourceColor = &pScreenPriv->colors[SOURCE_COLOR];
maskColor = &pScreenPriv->colors[MASK_COLOR];
if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap ||
!(pCursor->foreRed == sourceColor->red &&
pCursor->foreGreen == sourceColor->green &&
pCursor->foreBlue == sourceColor->blue &&
pCursor->backRed == maskColor->red &&
pCursor->backGreen == maskColor->green &&
pCursor->backBlue == maskColor->blue))
{
pScreenPriv->pColormap = pScreenPriv->pInstalledMap;
sourceColor->red = pCursor->foreRed;
sourceColor->green = pCursor->foreGreen;
sourceColor->blue = pCursor->foreBlue;
FakeAllocColor (pScreenPriv->pColormap, sourceColor);
maskColor->red = pCursor->backRed;
maskColor->green = pCursor->backGreen;
maskColor->blue = pCursor->backBlue;
FakeAllocColor (pScreenPriv->pColormap, maskColor);
/* "free" the pixels right away, don't let this confuse you */
FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel);
FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel);
}
pScreenPriv->checkPixels = FALSE;
}
/*
* BackingStore wrappers
*/
static void
miSpriteSaveDoomedAreas (pWin, pObscured, dx, dy)
WindowPtr pWin;
RegionPtr pObscured;
int dx, dy;
{
ScreenPtr pScreen;
miSpriteScreenPtr pScreenPriv;
BoxRec cursorBox;
pScreen = pWin->drawable.pScreen;
SCREEN_PROLOGUE (pScreen, SaveDoomedAreas);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pScreenPriv->isUp)
{
cursorBox = pScreenPriv->saved;
if (dx || dy)
{
cursorBox.x1 += dx;
cursorBox.y1 += dy;
cursorBox.x2 += dx;
cursorBox.y2 += dy;
}
if (RegionContainsRect(pObscured, &cursorBox) != rgnOUT)
miSpriteRemoveCursor (pScreen);
}
(*pScreen->SaveDoomedAreas) (pWin, pObscured, dx, dy);
SCREEN_EPILOGUE (pScreen, SaveDoomedAreas);
}
/*
* miPointer interface routines
*/
#define SPRITE_PAD 8
static Bool
miSpriteRealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (pCursor == pScreenPriv->pCursor)
pScreenPriv->checkPixels = TRUE;
return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor);
}
static Bool
miSpriteUnrealizeCursor (pScreen, pCursor)
ScreenPtr pScreen;
CursorPtr pCursor;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
return (*pScreenPriv->funcs->UnrealizeCursor) (pScreen, pCursor);
}
static void
miSpriteSetCursor (pScreen, pCursor, x, y)
ScreenPtr pScreen;
CursorPtr pCursor;
int x;
int y;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
if (!pCursor)
{
pScreenPriv->shouldBeUp = FALSE;
if (pScreenPriv->isUp)
miSpriteRemoveCursor (pScreen);
pScreenPriv->pCursor = 0;
return;
}
pScreenPriv->shouldBeUp = TRUE;
if (pScreenPriv->x == x &&
pScreenPriv->y == y &&
pScreenPriv->pCursor == pCursor &&
!pScreenPriv->checkPixels)
{
return;
}
pScreenPriv->x = x;
pScreenPriv->y = y;
pScreenPriv->pCacheWin = NullWindow;
if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor)
{
pScreenPriv->pCursor = pCursor;
miSpriteFindColors (pScreen);
}
if (pScreenPriv->isUp) {
int sx, sy;
/*
* check to see if the old saved region
* encloses the new sprite, in which case we use
* the flicker-free MoveCursor primitive.
*/
sx = pScreenPriv->x - (int)pCursor->bits->xhot;
sy = pScreenPriv->y - (int)pCursor->bits->yhot;
if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 &&
sx < pScreenPriv->saved.x2 &&
sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 &&
sy < pScreenPriv->saved.y2 &&
(int) pCursor->bits->width + (2 * SPRITE_PAD) ==
pScreenPriv->saved.x2 - pScreenPriv->saved.x1 &&
(int) pCursor->bits->height + (2 * SPRITE_PAD) ==
pScreenPriv->saved.y2 - pScreenPriv->saved.y1
)
{
DamageDrawInternal (pScreen, TRUE);
miSpriteIsUpFALSE (pScreen, pScreenPriv);
if (!(sx >= pScreenPriv->saved.x1 &&
sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 &&
sy >= pScreenPriv->saved.y1 &&
sy + (int)pCursor->bits->height < pScreenPriv->saved.y2))
{
int oldx1, oldy1, dx, dy;
oldx1 = pScreenPriv->saved.x1;
oldy1 = pScreenPriv->saved.y1;
dx = oldx1 - (sx - SPRITE_PAD);
dy = oldy1 - (sy - SPRITE_PAD);
pScreenPriv->saved.x1 -= dx;
pScreenPriv->saved.y1 -= dy;
pScreenPriv->saved.x2 -= dx;
pScreenPriv->saved.y2 -= dy;
(void) (*pScreenPriv->funcs->ChangeSave) (pScreen,
pScreenPriv->saved.x1,
pScreenPriv->saved.y1,
pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
dx, dy);
}
(void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor,
pScreenPriv->saved.x1,
pScreenPriv->saved.y1,
pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
pScreenPriv->saved.y2 - pScreenPriv->saved.y1,
sx - pScreenPriv->saved.x1,
sy - pScreenPriv->saved.y1,
pScreenPriv->colors[SOURCE_COLOR].pixel,
pScreenPriv->colors[MASK_COLOR].pixel);
miSpriteIsUpTRUE (pScreen, pScreenPriv);
DamageDrawInternal (pScreen, FALSE);
}
else
{
SPRITE_DEBUG (("SetCursor remove\n"));
miSpriteRemoveCursor (pScreen);
}
}
if (!pScreenPriv->isUp && pScreenPriv->pCursor)
{
SPRITE_DEBUG (("SetCursor restore\n"));
miSpriteRestoreCursor (pScreen);
}
}
static void
miSpriteMoveCursor (pScreen, x, y)
ScreenPtr pScreen;
int x, y;
{
miSpriteScreenPtr pScreenPriv;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y);
}
/*
* undraw/draw cursor
*/
static void
miSpriteRemoveCursor (pScreen)
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
DamageDrawInternal (pScreen, TRUE);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
miSpriteIsUpFALSE (pScreen, pScreenPriv);
pScreenPriv->pCacheWin = NullWindow;
if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen,
pScreenPriv->saved.x1,
pScreenPriv->saved.y1,
pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
{
miSpriteIsUpTRUE (pScreen, pScreenPriv);
}
DamageDrawInternal (pScreen, FALSE);
}
/*
* Called from the block handler, restores the cursor
* before waiting for something to do.
*/
static void
miSpriteRestoreCursor (pScreen)
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
int x, y;
CursorPtr pCursor;
DamageDrawInternal (pScreen, TRUE);
miSpriteComputeSaved (pScreen);
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pCursor = pScreenPriv->pCursor;
x = pScreenPriv->x - (int)pCursor->bits->xhot;
y = pScreenPriv->y - (int)pCursor->bits->yhot;
if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen,
pScreenPriv->saved.x1,
pScreenPriv->saved.y1,
pScreenPriv->saved.x2 - pScreenPriv->saved.x1,
pScreenPriv->saved.y2 - pScreenPriv->saved.y1))
{
if (pScreenPriv->checkPixels)
miSpriteFindColors (pScreen);
if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y,
pScreenPriv->colors[SOURCE_COLOR].pixel,
pScreenPriv->colors[MASK_COLOR].pixel))
{
miSpriteIsUpTRUE (pScreen, pScreenPriv);
}
}
DamageDrawInternal (pScreen, FALSE);
}
/*
* compute the desired area of the screen to save
*/
static void
miSpriteComputeSaved (pScreen)
ScreenPtr pScreen;
{
miSpriteScreenPtr pScreenPriv;
int x, y, w, h;
int wpad, hpad;
CursorPtr pCursor;
pScreenPriv = (miSpriteScreenPtr) pScreen->devPrivates[miSpriteScreenIndex].ptr;
pCursor = pScreenPriv->pCursor;
x = pScreenPriv->x - (int)pCursor->bits->xhot;
y = pScreenPriv->y - (int)pCursor->bits->yhot;
w = pCursor->bits->width;
h = pCursor->bits->height;
wpad = SPRITE_PAD;
hpad = SPRITE_PAD;
pScreenPriv->saved.x1 = x - wpad;
pScreenPriv->saved.y1 = y - hpad;
pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2;
pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2;
}

View File

@@ -0,0 +1,94 @@
/*
* misprite.h
*
* software-sprite/sprite drawing interface spec
*
* mi versions of these routines exist.
*/
/*
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
typedef struct {
Bool (*RealizeCursor)(
ScreenPtr /*pScreen*/,
CursorPtr /*pCursor*/
);
Bool (*UnrealizeCursor)(
ScreenPtr /*pScreen*/,
CursorPtr /*pCursor*/
);
Bool (*PutUpCursor)(
ScreenPtr /*pScreen*/,
CursorPtr /*pCursor*/,
int /*x*/,
int /*y*/,
unsigned long /*source*/,
unsigned long /*mask*/
);
Bool (*SaveUnderCursor)(
ScreenPtr /*pScreen*/,
int /*x*/,
int /*y*/,
int /*w*/,
int /*h*/
);
Bool (*RestoreUnderCursor)(
ScreenPtr /*pScreen*/,
int /*x*/,
int /*y*/,
int /*w*/,
int /*h*/
);
Bool (*MoveCursor)(
ScreenPtr /*pScreen*/,
CursorPtr /*pCursor*/,
int /*x*/,
int /*y*/,
int /*w*/,
int /*h*/,
int /*dx*/,
int /*dy*/,
unsigned long /*source*/,
unsigned long /*mask*/
);
Bool (*ChangeSave)(
ScreenPtr /*pScreen*/,
int /*x*/,
int /*y*/,
int /*w*/,
int /*h*/,
int /*dx*/,
int /*dy*/
);
} miSpriteCursorFuncRec, *miSpriteCursorFuncPtr;
extern Bool miSpriteInitialize(
ScreenPtr /*pScreen*/,
miSpriteCursorFuncPtr /*cursorFuncs*/,
miPointerScreenFuncPtr /*screenFuncs*/
);

View File

@@ -0,0 +1,132 @@
/*
* mispritest.h
*
* mi sprite structures
*/
/*
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifndef _MISPRITEST_H_
#define _MISPRITEST_H_
# include "misprite.h"
#ifdef RENDER
# include "picturestr.h"
#endif
# include "damage.h"
/*
* per screen information
*/
typedef struct {
/* screen procedures */
CloseScreenProcPtr CloseScreen;
GetImageProcPtr GetImage;
GetSpansProcPtr GetSpans;
SourceValidateProcPtr SourceValidate;
/* window procedures */
CopyWindowProcPtr CopyWindow;
/* backing store procedures */
SaveDoomedAreasProcPtr SaveDoomedAreas;
/* colormap procedures */
InstallColormapProcPtr InstallColormap;
StoreColorsProcPtr StoreColors;
/* os layer procedures */
ScreenBlockHandlerProcPtr BlockHandler;
CursorPtr pCursor;
int x; /* cursor hotspot */
int y;
BoxRec saved; /* saved area from the screen */
Bool isUp; /* cursor in frame buffer */
Bool shouldBeUp; /* cursor should be displayed */
WindowPtr pCacheWin; /* window the cursor last seen in */
Bool isInCacheWin;
Bool checkPixels; /* check colormap collision */
xColorItem colors[2];
ColormapPtr pInstalledMap;
ColormapPtr pColormap;
VisualPtr pVisual;
miSpriteCursorFuncPtr funcs;
DamagePtr pDamage; /* damage tracking structure */
} miSpriteScreenRec, *miSpriteScreenPtr;
#define SOURCE_COLOR 0
#define MASK_COLOR 1
#define miSpriteIsUpTRUE(pScreen, pScreenPriv) if (!pScreenPriv->isUp) { \
pScreenPriv->isUp = TRUE; \
DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
}
#define miSpriteIsUpFALSE(pScreen, pScreenPriv) if (pScreenPriv->isUp) { \
DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \
pScreenPriv->isUp = FALSE; \
}
/*
* Overlap BoxPtr and Box elements
*/
#define BOX_OVERLAP(pCbox,X1,Y1,X2,Y2) \
(((pCbox)->x1 <= (X2)) && ((X1) <= (pCbox)->x2) && \
((pCbox)->y1 <= (Y2)) && ((Y1) <= (pCbox)->y2))
/*
* Overlap BoxPtr, origins, and rectangle
*/
#define ORG_OVERLAP(pCbox,xorg,yorg,x,y,w,h) \
BOX_OVERLAP((pCbox),(x)+(xorg),(y)+(yorg),(x)+(xorg)+(w),(y)+(yorg)+(h))
/*
* Overlap BoxPtr, origins and RectPtr
*/
#define ORGRECT_OVERLAP(pCbox,xorg,yorg,pRect) \
ORG_OVERLAP((pCbox),(xorg),(yorg),(pRect)->x,(pRect)->y, \
(int)((pRect)->width), (int)((pRect)->height))
/*
* Overlap BoxPtr and horizontal span
*/
#define SPN_OVERLAP(pCbox,y,x,w) BOX_OVERLAP((pCbox),(x),(y),(x)+(w),(y))
#define LINE_SORT(x1,y1,x2,y2) \
{ int _t; \
if (x1 > x2) { _t = x1; x1 = x2; x2 = _t; } \
if (y1 > y2) { _t = y1; y1 = y2; y2 = _t; } }
#define LINE_OVERLAP(pCbox,x1,y1,x2,y2,lw2) \
BOX_OVERLAP((pCbox), (x1)-(lw2), (y1)-(lw2), (x2)+(lw2), (y2)+(lw2))
#endif /* _MISPRITEST_H_ */

View File

@@ -0,0 +1,63 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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 MISTRUCT_H
#define MISTRUCT_H
#include "mi.h"
#include "regionstr.h"
/* information about dashes */
typedef struct _miDash {
DDXPointRec pt;
int e1, e2; /* keep these, so we don't have to do it again */
int e; /* bresenham error term for this point on line */
int which;
int newLine;/* 0 if part of same original line as previous dash */
} miDashRec;
#endif /* MISTRUCT_H */

View File

@@ -0,0 +1,52 @@
/*
Copyright 1993, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#ifndef MIVALIDATE_H
#define MIVALIDATE_H
#include "regionstr.h"
typedef union _Validate {
struct BeforeValidate {
DDXPointRec oldAbsCorner; /* old window position */
RegionPtr borderVisible; /* visible region of border, */
/* non-null when size changes */
Bool resized; /* unclipped winSize has changed - */
/* don't call SaveDoomedAreas */
} before;
struct AfterValidate {
RegionRec exposed; /* exposed regions, absolute pos */
RegionRec borderExposed;
} after;
} ValidateRec;
#endif /* MIVALIDATE_H */

View File

@@ -0,0 +1,823 @@
/*
* mivaltree.c --
* Functions for recalculating window clip lists. Main function
* is miValidateTree.
*
Copyright 1987, 1988, 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
*
* Copyright 1987, 1988, 1989 by
* Digital Equipment Corporation, Maynard, 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 name of Digital 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.
*
******************************************************************/
/* The panoramix components contained the following notice */
/*****************************************************************
Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of Digital Equipment Corporation
shall not be used in advertising or otherwise to promote the sale, use or other
dealings in this Software without prior written authorization from Digital
Equipment Corporation.
******************************************************************/
/*
* Aug '86: Susan Angebranndt -- original code
* July '87: Adam de Boor -- substantially modified and commented
* Summer '89: Joel McCormack -- so fast you wouldn't believe it possible.
* In particular, much improved code for window mapping and
* circulating.
* Bob Scheifler -- avoid miComputeClips for unmapped windows,
* valdata changes
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "scrnintstr.h"
#include "validate.h"
#include "windowstr.h"
#include "mi.h"
#include "regionstr.h"
#include "mivalidate.h"
#include "globals.h"
#ifdef SHAPE
/*
* Compute the visibility of a shaped window
*/
int
miShapedWindowIn (pScreen, universe, bounding, rect, x, y)
ScreenPtr pScreen;
RegionPtr universe, bounding;
BoxPtr rect;
register int x, y;
{
BoxRec box;
register BoxPtr boundBox;
int nbox;
Bool someIn, someOut;
register int t, x1, y1, x2, y2;
nbox = RegionNumRects (bounding);
boundBox = RegionRects (bounding);
someIn = someOut = FALSE;
x1 = rect->x1;
y1 = rect->y1;
x2 = rect->x2;
y2 = rect->y2;
while (nbox--)
{
if ((t = boundBox->x1 + x) < x1)
t = x1;
box.x1 = t;
if ((t = boundBox->y1 + y) < y1)
t = y1;
box.y1 = t;
if ((t = boundBox->x2 + x) > x2)
t = x2;
box.x2 = t;
if ((t = boundBox->y2 + y) > y2)
t = y2;
box.y2 = t;
if (box.x1 > box.x2)
box.x2 = box.x1;
if (box.y1 > box.y2)
box.y2 = box.y1;
switch (RegionContainsRect(universe, &box))
{
case rgnIN:
if (someOut)
return rgnPART;
someIn = TRUE;
break;
case rgnOUT:
if (someIn)
return rgnPART;
someOut = TRUE;
break;
default:
return rgnPART;
}
boundBox++;
}
if (someIn)
return rgnIN;
return rgnOUT;
}
#endif
static GetRedirectBorderClipProcPtr miGetRedirectBorderClipProc;
static SetRedirectBorderClipProcPtr miSetRedirectBorderClipProc;
void
miRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip,
GetRedirectBorderClipProcPtr getBorderClip)
{
miSetRedirectBorderClipProc = setBorderClip;
miGetRedirectBorderClipProc = getBorderClip;
}
#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
HasBorder(w) && \
(w)->backgroundState == ParentRelative)
/*
*-----------------------------------------------------------------------
* miComputeClips --
* Recompute the clipList, borderClip, exposed and borderExposed
* regions for pParent and its children. Only viewable windows are
* taken into account.
*
* Results:
* None.
*
* Side Effects:
* clipList, borderClip, exposed and borderExposed are altered.
* A VisibilityNotify event may be generated on the parent window.
*
*-----------------------------------------------------------------------
*/
static void
miComputeClips (
register WindowPtr pParent,
register ScreenPtr pScreen,
register RegionPtr universe,
VTKind kind,
RegionPtr exposed ) /* for intermediate calculations */
{
int dx,
dy;
RegionRec childUniverse;
register WindowPtr pChild;
int oldVis, newVis;
BoxRec borderSize;
RegionRec childUnion;
Bool overlap;
RegionPtr borderVisible;
Bool resized;
/*
* Figure out the new visibility of this window.
* The extent of the universe should be the same as the extent of
* the borderSize region. If the window is unobscured, this rectangle
* will be completely inside the universe (the universe will cover it
* completely). If the window is completely obscured, none of the
* universe will cover the rectangle.
*/
borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent);
borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent);
dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent);
if (dx > 32767)
dx = 32767;
borderSize.x2 = dx;
dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent);
if (dy > 32767)
dy = 32767;
borderSize.y2 = dy;
#ifdef COMPOSITE
/*
* In redirected drawing case, reset universe to borderSize
*/
if (pParent->redirectDraw)
{
if (miSetRedirectBorderClipProc)
(*miSetRedirectBorderClipProc) (pParent, universe);
RegionCopy(universe, &pParent->borderSize);
}
#endif
oldVis = pParent->visibility;
switch (RegionContainsRect(universe, &borderSize))
{
case rgnIN:
newVis = VisibilityUnobscured;
break;
case rgnPART:
newVis = VisibilityPartiallyObscured;
#ifdef SHAPE
{
RegionPtr pBounding;
if ((pBounding = wBoundingShape (pParent)))
{
switch (miShapedWindowIn (pScreen, universe, pBounding,
&borderSize,
pParent->drawable.x,
pParent->drawable.y))
{
case rgnIN:
newVis = VisibilityUnobscured;
break;
case rgnOUT:
newVis = VisibilityFullyObscured;
break;
}
}
}
#endif
break;
default:
newVis = VisibilityFullyObscured;
break;
}
pParent->visibility = newVis;
if (oldVis != newVis &&
((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
SendVisibilityNotify(pParent);
dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
/*
* avoid computations when dealing with simple operations
*/
switch (kind) {
case VTMap:
case VTStack:
case VTUnmap:
break;
case VTMove:
if ((oldVis == newVis) &&
((oldVis == VisibilityFullyObscured) ||
(oldVis == VisibilityUnobscured)))
{
pChild = pParent;
while (1)
{
if (pChild->viewable)
{
if (pChild->visibility != VisibilityFullyObscured)
{
RegionTranslate(&pChild->borderClip,
dx, dy);
RegionTranslate(&pChild->clipList,
dx, dy);
pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER;
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pChild, dx, dy);
}
if (pChild->valdata)
{
RegionNull(
&pChild->valdata->after.borderExposed);
if (HasParentRelativeBorder(pChild))
{
RegionSubtract(
&pChild->valdata->after.borderExposed,
&pChild->borderClip,
&pChild->winSize);
}
RegionNull(&pChild->valdata->after.exposed);
}
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
}
while (!pChild->nextSib && (pChild != pParent))
pChild = pChild->parent;
if (pChild == pParent)
break;
pChild = pChild->nextSib;
}
return;
}
/* fall through */
default:
/*
* To calculate exposures correctly, we have to translate the old
* borderClip and clipList regions to the window's new location so there
* is a correspondence between pieces of the new and old clipping regions.
*/
if (dx || dy)
{
/*
* We translate the old clipList because that will be exposed or copied
* if gravity is right.
*/
RegionTranslate(&pParent->borderClip, dx, dy);
RegionTranslate(&pParent->clipList, dx, dy);
}
break;
case VTBroken:
RegionEmpty(&pParent->borderClip);
RegionEmpty(&pParent->clipList);
break;
}
borderVisible = pParent->valdata->before.borderVisible;
resized = pParent->valdata->before.resized;
RegionNull(&pParent->valdata->after.borderExposed);
RegionNull(&pParent->valdata->after.exposed);
/*
* Since the borderClip must not be clipped by the children, we do
* the border exposure first...
*
* 'universe' is the window's borderClip. To figure the exposures, remove
* the area that used to be exposed from the new.
* This leaves a region of pieces that weren't exposed before.
*/
if (HasBorder (pParent))
{
if (borderVisible)
{
/*
* when the border changes shape, the old visible portions
* of the border will be saved by DIX in borderVisible --
* use that region and destroy it
*/
RegionSubtract(exposed, universe, borderVisible);
RegionDestroy(borderVisible);
}
else
{
RegionSubtract(exposed, universe, &pParent->borderClip);
}
if (HasParentRelativeBorder(pParent) && (dx || dy))
RegionSubtract(&pParent->valdata->after.borderExposed,
universe,
&pParent->winSize);
else
RegionSubtract(&pParent->valdata->after.borderExposed,
exposed, &pParent->winSize);
RegionCopy(&pParent->borderClip, universe);
/*
* To get the right clipList for the parent, and to make doubly sure
* that no child overlaps the parent's border, we remove the parent's
* border from the universe before proceeding.
*/
RegionIntersect(universe, universe, &pParent->winSize);
}
else
RegionCopy(&pParent->borderClip, universe);
if ((pChild = pParent->firstChild) && pParent->mapped)
{
RegionNull(&childUniverse);
RegionNull(&childUnion);
if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
((pChild->drawable.y == pParent->lastChild->drawable.y) &&
(pChild->drawable.x < pParent->lastChild->drawable.x)))
{
for (; pChild; pChild = pChild->nextSib)
{
if (pChild->viewable)
RegionAppend(&childUnion, &pChild->borderSize);
}
}
else
{
for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib)
{
if (pChild->viewable)
RegionAppend(&childUnion, &pChild->borderSize);
}
}
RegionValidate(&childUnion, &overlap);
for (pChild = pParent->firstChild;
pChild;
pChild = pChild->nextSib)
{
if (pChild->viewable) {
/*
* If the child is viewable, we want to remove its extents
* from the current universe, but we only re-clip it if
* it's been marked.
*/
if (pChild->valdata) {
/*
* Figure out the new universe from the child's
* perspective and recurse.
*/
RegionIntersect(&childUniverse,
universe,
&pChild->borderSize);
miComputeClips (pChild, pScreen, &childUniverse, kind,
exposed);
}
/*
* Once the child has been processed, we remove its extents
* from the current universe, thus denying its space to any
* other sibling.
*/
if (overlap)
RegionSubtract(universe, universe,
&pChild->borderSize);
}
}
if (!overlap)
RegionSubtract(universe, universe, &childUnion);
RegionUninit(&childUnion);
RegionUninit(&childUniverse);
} /* if any children */
/*
* 'universe' now contains the new clipList for the parent window.
*
* To figure the exposure of the window we subtract the old clip from the
* new, just as for the border.
*/
if (oldVis == VisibilityFullyObscured ||
oldVis == VisibilityNotViewable)
{
RegionCopy(&pParent->valdata->after.exposed, universe);
}
else if (newVis != VisibilityFullyObscured &&
newVis != VisibilityNotViewable)
{
RegionSubtract(&pParent->valdata->after.exposed,
universe, &pParent->clipList);
}
/*
* One last thing: backing storage. We have to try to save what parts of
* the window are about to be obscured. We can just subtract the universe
* from the old clipList and get the areas that were in the old but aren't
* in the new and, hence, are about to be obscured.
*/
if (pParent->backStorage && !resized)
{
RegionSubtract(exposed, &pParent->clipList, universe);
(* pScreen->SaveDoomedAreas)(pParent, exposed, dx, dy);
}
/* HACK ALERT - copying contents of regions, instead of regions */
{
RegionRec tmp;
tmp = pParent->clipList;
pParent->clipList = *universe;
*universe = tmp;
}
#ifdef NOTDEF
RegionCopy(&pParent->clipList, universe);
#endif
pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pParent, dx, dy);
}
static void
miTreeObscured(
register WindowPtr pParent )
{
register WindowPtr pChild;
register int oldVis;
pChild = pParent;
while (1)
{
if (pChild->viewable)
{
oldVis = pChild->visibility;
if (oldVis != (pChild->visibility = VisibilityFullyObscured) &&
((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask))
SendVisibilityNotify(pChild);
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
}
while (!pChild->nextSib && (pChild != pParent))
pChild = pChild->parent;
if (pChild == pParent)
break;
pChild = pChild->nextSib;
}
}
/*
*-----------------------------------------------------------------------
* miValidateTree --
* Recomputes the clip list for pParent and all its inferiors.
*
* Results:
* Always returns 1.
*
* Side Effects:
* The clipList, borderClip, exposed, and borderExposed regions for
* each marked window are altered.
*
* Notes:
* This routine assumes that all affected windows have been marked
* (valdata created) and their winSize and borderSize regions
* adjusted to correspond to their new positions. The borderClip and
* clipList regions should not have been touched.
*
* The top-most level is treated differently from all lower levels
* because pParent is unchanged. For the top level, we merge the
* regions taken up by the marked children back into the clipList
* for pParent, thus forming a region from which the marked children
* can claim their areas. For lower levels, where the old clipList
* and borderClip are invalid, we can't do this and have to do the
* extra operations done in miComputeClips, but this is much faster
* e.g. when only one child has moved...
*
*-----------------------------------------------------------------------
*/
/*ARGSUSED*/
int
miValidateTree (pParent, pChild, kind)
WindowPtr pParent; /* Parent to validate */
WindowPtr pChild; /* First child of pParent that was
* affected */
VTKind kind; /* What kind of configuration caused call */
{
RegionRec totalClip; /* Total clipping region available to
* the marked children. pParent's clipList
* merged with the borderClips of all
* the marked children. */
RegionRec childClip; /* The new borderClip for the current
* child */
RegionRec childUnion; /* the space covered by borderSize for
* all marked children */
RegionRec exposed; /* For intermediate calculations */
register ScreenPtr pScreen;
register WindowPtr pWin;
Bool overlap;
int viewvals;
Bool forward;
pScreen = pParent->drawable.pScreen;
if (pChild == NullWindow)
pChild = pParent->firstChild;
RegionNull(&childClip);
RegionNull(&exposed);
/*
* compute the area of the parent window occupied
* by the marked children + the parent itself. This
* is the area which can be divied up among the marked
* children in their new configuration.
*/
RegionNull(&totalClip);
viewvals = 0;
if (RegionBroken(&pParent->clipList) &&
!RegionBroken(&pParent->borderClip))
{
kind = VTBroken;
/*
* When rebuilding clip lists after out of memory,
* assume everything is busted.
*/
forward = TRUE;
RegionCopy(&totalClip, &pParent->borderClip);
RegionIntersect(&totalClip, &totalClip, &pParent->winSize);
for (pWin = pParent->firstChild; pWin != pChild; pWin = pWin->nextSib)
{
if (pWin->viewable)
RegionSubtract(&totalClip, &totalClip, &pWin->borderSize);
}
for (pWin = pChild; pWin; pWin = pWin->nextSib)
if (pWin->valdata && pWin->viewable)
viewvals++;
RegionEmpty(&pParent->clipList);
}
else
{
if ((pChild->drawable.y < pParent->lastChild->drawable.y) ||
((pChild->drawable.y == pParent->lastChild->drawable.y) &&
(pChild->drawable.x < pParent->lastChild->drawable.x)))
{
forward = TRUE;
for (pWin = pChild; pWin; pWin = pWin->nextSib)
{
if (pWin->valdata)
{
RegionPtr pBorderClip = &pWin->borderClip;
#ifdef COMPOSITE
if (pWin->redirectDraw && miGetRedirectBorderClipProc)
pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
#endif
RegionAppend(&totalClip, pBorderClip );
if (pWin->viewable)
viewvals++;
}
}
}
else
{
forward = FALSE;
pWin = pParent->lastChild;
while (1)
{
if (pWin->valdata)
{
RegionPtr pBorderClip = &pWin->borderClip;
#ifdef COMPOSITE
if (pWin->redirectDraw && miGetRedirectBorderClipProc)
pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
#endif
RegionAppend(&totalClip, pBorderClip );
if (pWin->viewable)
viewvals++;
}
if (pWin == pChild)
break;
pWin = pWin->prevSib;
}
}
RegionValidate(&totalClip, &overlap);
}
/*
* Now go through the children of the root and figure their new
* borderClips from the totalClip, passing that off to miComputeClips
* to handle recursively. Once that's done, we remove the child
* from the totalClip to clip any siblings below it.
*/
overlap = TRUE;
if (kind != VTStack)
{
RegionUnion(&totalClip, &totalClip, &pParent->clipList);
if (viewvals > 1)
{
/*
* precompute childUnion to discover whether any of them
* overlap. This seems redundant, but performance studies
* have demonstrated that the cost of this loop is
* lower than the cost of multiple Subtracts in the
* loop below.
*/
RegionNull(&childUnion);
if (forward)
{
for (pWin = pChild; pWin; pWin = pWin->nextSib)
if (pWin->valdata && pWin->viewable)
RegionAppend(&childUnion,
&pWin->borderSize);
}
else
{
pWin = pParent->lastChild;
while (1)
{
if (pWin->valdata && pWin->viewable)
RegionAppend(&childUnion,
&pWin->borderSize);
if (pWin == pChild)
break;
pWin = pWin->prevSib;
}
}
RegionValidate(&childUnion, &overlap);
if (overlap)
RegionUninit(&childUnion);
}
}
for (pWin = pChild;
pWin != NullWindow;
pWin = pWin->nextSib)
{
if (pWin->viewable) {
if (pWin->valdata) {
RegionIntersect(&childClip,
&totalClip,
&pWin->borderSize);
miComputeClips (pWin, pScreen, &childClip, kind, &exposed);
if (overlap)
{
RegionSubtract(&totalClip,
&totalClip,
&pWin->borderSize);
}
} else if (pWin->visibility == VisibilityNotViewable) {
miTreeObscured(pWin);
}
} else {
if (pWin->valdata) {
RegionEmpty(&pWin->clipList);
if (pScreen->ClipNotify)
(* pScreen->ClipNotify) (pWin, 0, 0);
RegionEmpty(&pWin->borderClip);
pWin->valdata = (ValidatePtr)NULL;
}
}
}
RegionUninit(&childClip);
if (!overlap)
{
RegionSubtract(&totalClip, &totalClip, &childUnion);
RegionUninit(&childUnion);
}
RegionNull(&pParent->valdata->after.exposed);
RegionNull(&pParent->valdata->after.borderExposed);
/*
* each case below is responsible for updating the
* clipList and serial number for the parent window
*/
switch (kind) {
case VTStack:
break;
default:
/*
* totalClip contains the new clipList for the parent. Figure out
* exposures and obscures as per miComputeClips and reset the parent's
* clipList.
*/
RegionSubtract(&pParent->valdata->after.exposed,
&totalClip, &pParent->clipList);
/* fall through */
case VTMap:
if (pParent->backStorage) {
RegionSubtract(&exposed, &pParent->clipList, &totalClip);
(* pScreen->SaveDoomedAreas)(pParent, &exposed, 0, 0);
}
RegionCopy(&pParent->clipList, &totalClip);
pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER;
break;
}
RegionUninit(&totalClip);
RegionUninit(&exposed);
if (pScreen->ClipNotify)
(*pScreen->ClipNotify) (pParent, 0, 0);
return (1);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,222 @@
/*
Copyright 1988, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall
not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization
from The Open Group.
*/
/* Author: Keith Packard, MIT X Consortium */
#include "mispans.h"
#include "mifpoly.h" /* for ICEIL */
/*
* interface data to span-merging polygon filler
*/
typedef struct _SpanData {
SpanGroup fgGroup, bgGroup;
} SpanDataRec, *SpanDataPtr;
#define AppendSpanGroup(pGC, pixel, spanPtr, spanData) { \
SpanGroup *group, *othergroup = NULL; \
if (pixel == pGC->fgPixel) \
{ \
group = &spanData->fgGroup; \
if (pGC->lineStyle == LineDoubleDash) \
othergroup = &spanData->bgGroup; \
} \
else \
{ \
group = &spanData->bgGroup; \
othergroup = &spanData->fgGroup; \
} \
miAppendSpans (group, othergroup, spanPtr); \
}
/*
* Polygon edge description for integer wide-line routines
*/
typedef struct _PolyEdge {
int height; /* number of scanlines to process */
int x; /* starting x coordinate */
int stepx; /* fixed integral dx */
int signdx; /* variable dx sign */
int e; /* initial error term */
int dy;
int dx;
} PolyEdgeRec, *PolyEdgePtr;
#define SQSECANT 108.856472512142 /* 1/sin^2(11/2) - miter limit constant */
/*
* types for general polygon routines
*/
typedef struct _PolyVertex {
double x, y;
} PolyVertexRec, *PolyVertexPtr;
typedef struct _PolySlope {
int dx, dy;
double k; /* x0 * dy - y0 * dx */
} PolySlopeRec, *PolySlopePtr;
/*
* Line face description for caps/joins
*/
typedef struct _LineFace {
double xa, ya;
int dx, dy;
int x, y;
double k;
} LineFaceRec, *LineFacePtr;
/*
* macros for polygon fillers
*/
#define MIPOLYRELOADLEFT if (!left_height && left_count) { \
left_height = left->height; \
left_x = left->x; \
left_stepx = left->stepx; \
left_signdx = left->signdx; \
left_e = left->e; \
left_dy = left->dy; \
left_dx = left->dx; \
--left_count; \
++left; \
}
#define MIPOLYRELOADRIGHT if (!right_height && right_count) { \
right_height = right->height; \
right_x = right->x; \
right_stepx = right->stepx; \
right_signdx = right->signdx; \
right_e = right->e; \
right_dy = right->dy; \
right_dx = right->dx; \
--right_count; \
++right; \
}
#define MIPOLYSTEPLEFT left_x += left_stepx; \
left_e += left_dx; \
if (left_e > 0) \
{ \
left_x += left_signdx; \
left_e -= left_dy; \
}
#define MIPOLYSTEPRIGHT right_x += right_stepx; \
right_e += right_dx; \
if (right_e > 0) \
{ \
right_x += right_signdx; \
right_e -= right_dy; \
}
#define MILINESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \
oldPixel = pGC->fgPixel; \
if (pixel != oldPixel) { \
DoChangeGC (pGC, GCForeground, (XID *) &pixel, FALSE); \
ValidateGC (pDrawable, pGC); \
} \
}
#define MILINERESETPIXEL(pDrawable, pGC, pixel, oldPixel) { \
if (pixel != oldPixel) { \
DoChangeGC (pGC, GCForeground, (XID *) &oldPixel, FALSE); \
ValidateGC (pDrawable, pGC); \
} \
}
extern void miFillPolyHelper(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
unsigned long /*pixel*/,
SpanDataPtr /*spanData*/,
int /*y*/,
int /*overall_height*/,
PolyEdgePtr /*left*/,
PolyEdgePtr /*right*/,
int /*left_count*/,
int /*right_count*/
);
extern int miRoundJoinFace(
LineFacePtr /*face*/,
PolyEdgePtr /*edge*/,
Bool * /*leftEdge*/
);
extern void miRoundJoinClip(
LineFacePtr /*pLeft*/,
LineFacePtr /*pRight*/,
PolyEdgePtr /*edge1*/,
PolyEdgePtr /*edge2*/,
int * /*y1*/,
int * /*y2*/,
Bool * /*left1*/,
Bool * /*left2*/
);
extern int miRoundCapClip(
LineFacePtr /*face*/,
Bool /*isInt*/,
PolyEdgePtr /*edge*/,
Bool * /*leftEdge*/
);
extern void miLineProjectingCap(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
unsigned long /*pixel*/,
SpanDataPtr /*spanData*/,
LineFacePtr /*face*/,
Bool /*isLeft*/,
double /*xorg*/,
double /*yorg*/,
Bool /*isInt*/
);
extern SpanDataPtr miSetupSpanData(
GCPtr /*pGC*/,
SpanDataPtr /*spanData*/,
int /*npt*/
);
extern void miCleanupSpanData(
DrawablePtr /*pDrawable*/,
GCPtr /*pGC*/,
SpanDataPtr /*spanData*/
);
extern int miPolyBuildEdge(double x0, double y0, double k, int dx, int dy,
int xi, int yi, int left, PolyEdgePtr edge);
extern int miPolyBuildPoly(PolyVertexPtr vertices, PolySlopePtr slopes,
int count, int xi, int yi, PolyEdgePtr left,
PolyEdgePtr right, int *pnleft, int *pnright,
int *h);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,853 @@
/************************************************************
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Author: Bob Scheifler, MIT X Consortium
********************************************************/
/* Derived from:
* "Algorithm for drawing ellipses or hyperbolae with a digital plotter"
* by M. L. V. Pitteway
* The Computer Journal, November 1967, Volume 10, Number 3, pp. 282-289
*/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <math.h>
#include <nx-X11/X.h>
#include <nx-X11/Xprotostr.h>
#include "regionstr.h"
#include "gcstruct.h"
#include "pixmapstr.h"
#include "mi.h"
#include "mizerarc.h"
#define FULLCIRCLE (360 * 64)
#define OCTANT (45 * 64)
#define QUADRANT (90 * 64)
#define HALFCIRCLE (180 * 64)
#define QUADRANT3 (270 * 64)
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#define Dsin(d) ((d) == 0 ? 0.0 : ((d) == QUADRANT ? 1.0 : \
((d) == HALFCIRCLE ? 0.0 : \
((d) == QUADRANT3 ? -1.0 : sin((double)d*(M_PI/11520.0))))))
#define Dcos(d) ((d) == 0 ? 1.0 : ((d) == QUADRANT ? 0.0 : \
((d) == HALFCIRCLE ? -1.0 : \
((d) == QUADRANT3 ? 0.0 : cos((double)d*(M_PI/11520.0))))))
#define EPSILON45 64
typedef struct {
int skipStart;
int haveStart;
DDXPointRec startPt;
int haveLast;
int skipLast;
DDXPointRec endPt;
int dashIndex;
int dashOffset;
int dashIndexInit;
int dashOffsetInit;
} DashInfo;
static miZeroArcPtRec oob = {65536, 65536, 0};
/*
* (x - l)^2 / (W/2)^2 + (y + H/2)^2 / (H/2)^2 = 1
*
* where l is either 0 or .5
*
* alpha = 4(W^2)
* beta = 4(H^2)
* gamma = 0
* u = 2(W^2)H
* v = 4(H^2)l
* k = -4(H^2)(l^2)
*
*/
Bool
miZeroArcSetup(arc, info, ok360)
register xArc *arc;
register miZeroArcRec *info;
Bool ok360;
{
int l;
int angle1, angle2;
int startseg, endseg;
int startAngle, endAngle;
int i, overlap;
miZeroArcPtRec start, end;
l = arc->width & 1;
if (arc->width == arc->height)
{
info->alpha = 4;
info->beta = 4;
info->k1 = -8;
info->k3 = -16;
info->b = 12;
info->a = (arc->width << 2) - 12;
info->d = 17 - (arc->width << 1);
if (l)
{
info->b -= 4;
info->a += 4;
info->d -= 7;
}
}
else if (!arc->width || !arc->height)
{
info->alpha = 0;
info->beta = 0;
info->k1 = 0;
info->k3 = 0;
info->a = -(int)arc->height;
info->b = 0;
info->d = -1;
}
else
{
/* initial conditions */
info->alpha = (arc->width * arc->width) << 2;
info->beta = (arc->height * arc->height) << 2;
info->k1 = info->beta << 1;
info->k3 = info->k1 + (info->alpha << 1);
info->b = l ? 0 : -info->beta;
info->a = info->alpha * arc->height;
info->d = info->b - (info->a >> 1) - (info->alpha >> 2);
if (l)
info->d -= info->beta >> 2;
info->a -= info->b;
/* take first step, d < 0 always */
info->b -= info->k1;
info->a += info->k1;
info->d += info->b;
/* octant change, b < 0 always */
info->k1 = -info->k1;
info->k3 = -info->k3;
info->b = -info->b;
info->d = info->b - info->a - info->d;
info->a = info->a - (info->b << 1);
}
info->dx = 1;
info->dy = 0;
info->w = (arc->width + 1) >> 1;
info->h = arc->height >> 1;
info->xorg = arc->x + (arc->width >> 1);
info->yorg = arc->y;
info->xorgo = info->xorg + l;
info->yorgo = info->yorg + arc->height;
if (!arc->width)
{
if (!arc->height)
{
info->x = 0;
info->y = 0;
info->initialMask = 0;
info->startAngle = 0;
info->endAngle = 0;
info->start = oob;
info->end = oob;
return FALSE;
}
info->x = 0;
info->y = 1;
}
else
{
info->x = 1;
info->y = 0;
}
angle1 = arc->angle1;
angle2 = arc->angle2;
if ((angle1 == 0) && (angle2 >= FULLCIRCLE))
{
startAngle = 0;
endAngle = 0;
}
else
{
if (angle2 > FULLCIRCLE)
angle2 = FULLCIRCLE;
else if (angle2 < -FULLCIRCLE)
angle2 = -FULLCIRCLE;
if (angle2 < 0)
{
startAngle = angle1 + angle2;
endAngle = angle1;
}
else
{
startAngle = angle1;
endAngle = angle1 + angle2;
}
if (startAngle < 0)
startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
if (startAngle >= FULLCIRCLE)
startAngle = startAngle % FULLCIRCLE;
if (endAngle < 0)
endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
if (endAngle >= FULLCIRCLE)
endAngle = endAngle % FULLCIRCLE;
}
info->startAngle = startAngle;
info->endAngle = endAngle;
if (ok360 && (startAngle == endAngle) && arc->angle2 &&
arc->width && arc->height)
{
info->initialMask = 0xf;
info->start = oob;
info->end = oob;
return TRUE;
}
startseg = startAngle / OCTANT;
if (!arc->height || (((startseg + 1) & 2) && arc->width))
{
start.x = Dcos(startAngle) * ((arc->width + 1) / 2.0);
if (start.x < 0)
start.x = -start.x;
start.y = -1;
}
else
{
start.y = Dsin(startAngle) * (arc->height / 2.0);
if (start.y < 0)
start.y = -start.y;
start.y = info->h - start.y;
start.x = 65536;
}
endseg = endAngle / OCTANT;
if (!arc->height || (((endseg + 1) & 2) && arc->width))
{
end.x = Dcos(endAngle) * ((arc->width + 1) / 2.0);
if (end.x < 0)
end.x = -end.x;
end.y = -1;
}
else
{
end.y = Dsin(endAngle) * (arc->height / 2.0);
if (end.y < 0)
end.y = -end.y;
end.y = info->h - end.y;
end.x = 65536;
}
info->firstx = start.x;
info->firsty = start.y;
info->initialMask = 0;
overlap = arc->angle2 && (endAngle <= startAngle);
for (i = 0; i < 4; i++)
{
if (overlap ?
((i * QUADRANT <= endAngle) || ((i + 1) * QUADRANT > startAngle)) :
((i * QUADRANT <= endAngle) && ((i + 1) * QUADRANT > startAngle)))
info->initialMask |= (1 << i);
}
start.mask = info->initialMask;
end.mask = info->initialMask;
startseg >>= 1;
endseg >>= 1;
overlap = overlap && (endseg == startseg);
if (start.x != end.x || start.y != end.y || !overlap)
{
if (startseg & 1)
{
if (!overlap)
info->initialMask &= ~(1 << startseg);
if (start.x > end.x || start.y > end.y)
end.mask &= ~(1 << startseg);
}
else
{
start.mask &= ~(1 << startseg);
if (((start.x < end.x || start.y < end.y) ||
(start.x == end.x && start.y == end.y && (endseg & 1))) &&
!overlap)
end.mask &= ~(1 << startseg);
}
if (endseg & 1)
{
end.mask &= ~(1 << endseg);
if (((start.x > end.x || start.y > end.y) ||
(start.x == end.x && start.y == end.y && !(startseg & 1))) &&
!overlap)
start.mask &= ~(1 << endseg);
}
else
{
if (!overlap)
info->initialMask &= ~(1 << endseg);
if (start.x < end.x || start.y < end.y)
start.mask &= ~(1 << endseg);
}
}
/* take care of case when start and stop are both near 45 */
/* handle here rather than adding extra code to pixelization loops */
if (startAngle &&
((start.y < 0 && end.y >= 0) || (start.y >= 0 && end.y < 0)))
{
i = (startAngle + OCTANT) % OCTANT;
if (i < EPSILON45 || i > OCTANT - EPSILON45)
{
i = (endAngle + OCTANT) % OCTANT;
if (i < EPSILON45 || i > OCTANT - EPSILON45)
{
if (start.y < 0)
{
i = Dsin(startAngle) * (arc->height / 2.0);
if (i < 0)
i = -i;
if (info->h - i == end.y)
start.mask = end.mask;
}
else
{
i = Dsin(endAngle) * (arc->height / 2.0);
if (i < 0)
i = -i;
if (info->h - i == start.y)
end.mask = start.mask;
}
}
}
}
if (startseg & 1)
{
info->start = start;
info->end = oob;
}
else
{
info->end = start;
info->start = oob;
}
if (endseg & 1)
{
info->altend = end;
if (info->altend.x < info->end.x || info->altend.y < info->end.y)
{
miZeroArcPtRec tmp;
tmp = info->altend;
info->altend = info->end;
info->end = tmp;
}
info->altstart = oob;
}
else
{
info->altstart = end;
if (info->altstart.x < info->start.x ||
info->altstart.y < info->start.y)
{
miZeroArcPtRec tmp;
tmp = info->altstart;
info->altstart = info->start;
info->start = tmp;
}
info->altend = oob;
}
if (!info->start.x || !info->start.y)
{
info->initialMask = info->start.mask;
info->start = info->altstart;
}
if (!arc->width && (arc->height == 1))
{
/* kludge! */
info->initialMask |= info->end.mask;
info->initialMask |= info->initialMask << 1;
info->end.x = 0;
info->end.mask = 0;
}
return FALSE;
}
#define Pixelate(xval,yval) \
{ \
pts->x = xval; \
pts->y = yval; \
pts++; \
}
#define DoPix(idx,xval,yval) if (mask & (1 << idx)) Pixelate(xval, yval);
DDXPointPtr
miZeroArcPts(arc, pts)
xArc *arc;
register DDXPointPtr pts;
{
miZeroArcRec info;
register int x, y, a, b, d, mask;
register int k1, k3, dx, dy;
Bool do360;
do360 = miZeroArcSetup(arc, &info, TRUE);
MIARCSETUP();
mask = info.initialMask;
if (!(arc->width & 1))
{
DoPix(1, info.xorgo, info.yorg);
DoPix(3, info.xorgo, info.yorgo);
}
if (!info.end.x || !info.end.y)
{
mask = info.end.mask;
info.end = info.altend;
}
if (do360 && (arc->width == arc->height) && !(arc->width & 1))
{
int yorgh = info.yorg + info.h;
int xorghp = info.xorg + info.h;
int xorghn = info.xorg - info.h;
while (1)
{
Pixelate(info.xorg + x, info.yorg + y);
Pixelate(info.xorg - x, info.yorg + y);
Pixelate(info.xorg - x, info.yorgo - y);
Pixelate(info.xorg + x, info.yorgo - y);
if (a < 0)
break;
Pixelate(xorghp - y, yorgh - x);
Pixelate(xorghn + y, yorgh - x);
Pixelate(xorghn + y, yorgh + x);
Pixelate(xorghp - y, yorgh + x);
MIARCCIRCLESTEP(;);
}
if (x > 1 && pts[-1].x == pts[-5].x && pts[-1].y == pts[-5].y)
pts -= 4;
x = info.w;
y = info.h;
}
else if (do360)
{
while (y < info.h || x < info.w)
{
MIARCOCTANTSHIFT(;);
Pixelate(info.xorg + x, info.yorg + y);
Pixelate(info.xorgo - x, info.yorg + y);
Pixelate(info.xorgo - x, info.yorgo - y);
Pixelate(info.xorg + x, info.yorgo - y);
MIARCSTEP(;,;);
}
}
else
{
while (y < info.h || x < info.w)
{
MIARCOCTANTSHIFT(;);
if ((x == info.start.x) || (y == info.start.y))
{
mask = info.start.mask;
info.start = info.altstart;
}
DoPix(0, info.xorg + x, info.yorg + y);
DoPix(1, info.xorgo - x, info.yorg + y);
DoPix(2, info.xorgo - x, info.yorgo - y);
DoPix(3, info.xorg + x, info.yorgo - y);
if ((x == info.end.x) || (y == info.end.y))
{
mask = info.end.mask;
info.end = info.altend;
}
MIARCSTEP(;,;);
}
}
if ((x == info.start.x) || (y == info.start.y))
mask = info.start.mask;
DoPix(0, info.xorg + x, info.yorg + y);
DoPix(2, info.xorgo - x, info.yorgo - y);
if (arc->height & 1)
{
DoPix(1, info.xorgo - x, info.yorg + y);
DoPix(3, info.xorg + x, info.yorgo - y);
}
return pts;
}
#undef DoPix
#define DoPix(idx,xval,yval) \
if (mask & (1 << idx)) \
{ \
arcPts[idx]->x = xval; \
arcPts[idx]->y = yval; \
arcPts[idx]++; \
}
static void
miZeroArcDashPts(
GCPtr pGC,
xArc *arc,
DashInfo *dinfo,
register DDXPointPtr points,
int maxPts,
register DDXPointPtr *evenPts,
register DDXPointPtr *oddPts )
{
miZeroArcRec info;
register int x, y, a, b, d, mask;
register int k1, k3, dx, dy;
int dashRemaining;
DDXPointPtr arcPts[4];
DDXPointPtr startPts[5], endPts[5];
int deltas[5];
DDXPointPtr startPt, pt, lastPt, pts;
int i, j, delta, ptsdelta, seg, startseg;
for (i = 0; i < 4; i++)
arcPts[i] = points + (i * maxPts);
(void)miZeroArcSetup(arc, &info, FALSE);
MIARCSETUP();
mask = info.initialMask;
startseg = info.startAngle / QUADRANT;
startPt = arcPts[startseg];
if (!(arc->width & 1))
{
DoPix(1, info.xorgo, info.yorg);
DoPix(3, info.xorgo, info.yorgo);
}
if (!info.end.x || !info.end.y)
{
mask = info.end.mask;
info.end = info.altend;
}
while (y < info.h || x < info.w)
{
MIARCOCTANTSHIFT(;);
if ((x == info.firstx) || (y == info.firsty))
startPt = arcPts[startseg];
if ((x == info.start.x) || (y == info.start.y))
{
mask = info.start.mask;
info.start = info.altstart;
}
DoPix(0, info.xorg + x, info.yorg + y);
DoPix(1, info.xorgo - x, info.yorg + y);
DoPix(2, info.xorgo - x, info.yorgo - y);
DoPix(3, info.xorg + x, info.yorgo - y);
if ((x == info.end.x) || (y == info.end.y))
{
mask = info.end.mask;
info.end = info.altend;
}
MIARCSTEP(;,;);
}
if ((x == info.firstx) || (y == info.firsty))
startPt = arcPts[startseg];
if ((x == info.start.x) || (y == info.start.y))
mask = info.start.mask;
DoPix(0, info.xorg + x, info.yorg + y);
DoPix(2, info.xorgo - x, info.yorgo - y);
if (arc->height & 1)
{
DoPix(1, info.xorgo - x, info.yorg + y);
DoPix(3, info.xorg + x, info.yorgo - y);
}
for (i = 0; i < 4; i++)
{
seg = (startseg + i) & 3;
pt = points + (seg * maxPts);
if (seg & 1)
{
startPts[i] = pt;
endPts[i] = arcPts[seg];
deltas[i] = 1;
}
else
{
startPts[i] = arcPts[seg] - 1;
endPts[i] = pt - 1;
deltas[i] = -1;
}
}
startPts[4] = startPts[0];
endPts[4] = startPt;
startPts[0] = startPt;
if (startseg & 1)
{
if (startPts[4] != endPts[4])
endPts[4]--;
deltas[4] = 1;
}
else
{
if (startPts[0] > startPts[4])
startPts[0]--;
if (startPts[4] < endPts[4])
endPts[4]--;
deltas[4] = -1;
}
if (arc->angle2 < 0)
{
DDXPointPtr tmps, tmpe;
int tmpd;
tmpd = deltas[0];
tmps = startPts[0] - tmpd;
tmpe = endPts[0] - tmpd;
startPts[0] = endPts[4] - deltas[4];
endPts[0] = startPts[4] - deltas[4];
deltas[0] = -deltas[4];
startPts[4] = tmpe;
endPts[4] = tmps;
deltas[4] = -tmpd;
tmpd = deltas[1];
tmps = startPts[1] - tmpd;
tmpe = endPts[1] - tmpd;
startPts[1] = endPts[3] - deltas[3];
endPts[1] = startPts[3] - deltas[3];
deltas[1] = -deltas[3];
startPts[3] = tmpe;
endPts[3] = tmps;
deltas[3] = -tmpd;
tmps = startPts[2] - deltas[2];
startPts[2] = endPts[2] - deltas[2];
endPts[2] = tmps;
deltas[2] = -deltas[2];
}
for (i = 0; i < 5 && startPts[i] == endPts[i]; i++)
;
if (i == 5)
return;
pt = startPts[i];
for (j = 4; startPts[j] == endPts[j]; j--)
;
lastPt = endPts[j] - deltas[j];
if (dinfo->haveLast &&
(pt->x == dinfo->endPt.x) && (pt->y == dinfo->endPt.y))
{
startPts[i] += deltas[i];
}
else
{
dinfo->dashIndex = dinfo->dashIndexInit;
dinfo->dashOffset = dinfo->dashOffsetInit;
}
if (!dinfo->skipStart && (info.startAngle != info.endAngle))
{
dinfo->startPt = *pt;
dinfo->haveStart = TRUE;
}
else if (!dinfo->skipLast && dinfo->haveStart &&
(lastPt->x == dinfo->startPt.x) &&
(lastPt->y == dinfo->startPt.y) &&
(lastPt != startPts[i]))
endPts[j] = lastPt;
if (info.startAngle != info.endAngle)
{
dinfo->haveLast = TRUE;
dinfo->endPt = *lastPt;
}
dashRemaining = pGC->dash[dinfo->dashIndex] - dinfo->dashOffset;
for (i = 0; i < 5; i++)
{
pt = startPts[i];
lastPt = endPts[i];
delta = deltas[i];
while (pt != lastPt)
{
if (dinfo->dashIndex & 1)
{
pts = *oddPts;
ptsdelta = -1;
}
else
{
pts = *evenPts;
ptsdelta = 1;
}
while ((pt != lastPt) && --dashRemaining >= 0)
{
*pts = *pt;
pts += ptsdelta;
pt += delta;
}
if (dinfo->dashIndex & 1)
*oddPts = pts;
else
*evenPts = pts;
if (dashRemaining <= 0)
{
if (++(dinfo->dashIndex) == pGC->numInDashList)
dinfo->dashIndex = 0;
dashRemaining = pGC->dash[dinfo->dashIndex];
}
}
}
dinfo->dashOffset = pGC->dash[dinfo->dashIndex] - dashRemaining;
}
void
miZeroPolyArc(pDraw, pGC, narcs, parcs)
DrawablePtr pDraw;
GCPtr pGC;
int narcs;
xArc *parcs;
{
int maxPts = 0;
register int n, maxw = 0;
register xArc *arc;
register int i;
DDXPointPtr points, pts, oddPts = NULL;
register DDXPointPtr pt;
int numPts;
Bool dospans;
int *widths = NULL;
XID fgPixel = pGC->fgPixel;
DashInfo dinfo;
for (arc = parcs, i = narcs; --i >= 0; arc++)
{
if (!miCanZeroArc(arc))
miPolyArc(pDraw, pGC, 1, arc);
else
{
if (arc->width > arc->height)
n = arc->width + (arc->height >> 1);
else
n = arc->height + (arc->width >> 1);
if (n > maxPts)
maxPts = n;
}
}
if (!maxPts)
return;
numPts = maxPts << 2;
dospans = (pGC->fillStyle != FillSolid);
if (dospans)
{
widths = (int *)malloc(sizeof(int) * numPts);
if (!widths)
return;
maxw = 0;
}
if (pGC->lineStyle != LineSolid)
{
numPts <<= 1;
dinfo.haveStart = FALSE;
dinfo.skipStart = FALSE;
dinfo.haveLast = FALSE;
dinfo.dashIndexInit = 0;
dinfo.dashOffsetInit = 0;
miStepDash((int)pGC->dashOffset, &dinfo.dashIndexInit,
(unsigned char *) pGC->dash, (int)pGC->numInDashList,
&dinfo.dashOffsetInit);
}
points = (DDXPointPtr)malloc(sizeof(DDXPointRec) * numPts);
if (!points)
{
if (dospans)
{
free(widths);
}
return;
}
for (arc = parcs, i = narcs; --i >= 0; arc++)
{
if (miCanZeroArc(arc))
{
if (pGC->lineStyle == LineSolid)
pts = miZeroArcPts(arc, points);
else
{
pts = points;
oddPts = &points[(numPts >> 1) - 1];
dinfo.skipLast = i;
miZeroArcDashPts(pGC, arc, &dinfo,
oddPts + 1, maxPts, &pts, &oddPts);
dinfo.skipStart = TRUE;
}
n = pts - points;
if (!dospans)
(*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, points);
else
{
if (n > maxw)
{
while (maxw < n)
widths[maxw++] = 1;
}
if (pGC->miTranslate)
{
for (pt = points; pt != pts; pt++)
{
pt->x += pDraw->x;
pt->y += pDraw->y;
}
}
(*pGC->ops->FillSpans)(pDraw, pGC, n, points, widths, FALSE);
}
if (pGC->lineStyle != LineDoubleDash)
continue;
if ((pGC->fillStyle == FillSolid) ||
(pGC->fillStyle == FillStippled))
{
DoChangeGC(pGC, GCForeground, (XID *)&pGC->bgPixel, 0);
ValidateGC(pDraw, pGC);
}
pts = &points[numPts >> 1];
oddPts++;
n = pts - oddPts;
if (!dospans)
(*pGC->ops->PolyPoint)(pDraw, pGC, CoordModeOrigin, n, oddPts);
else
{
if (n > maxw)
{
while (maxw < n)
widths[maxw++] = 1;
}
if (pGC->miTranslate)
{
for (pt = oddPts; pt != pts; pt++)
{
pt->x += pDraw->x;
pt->y += pDraw->y;
}
}
(*pGC->ops->FillSpans)(pDraw, pGC, n, oddPts, widths, FALSE);
}
if ((pGC->fillStyle == FillSolid) ||
(pGC->fillStyle == FillStippled))
{
DoChangeGC(pGC, GCForeground, &fgPixel, 0);
ValidateGC(pDraw, pGC);
}
}
}
free(points);
if (dospans)
{
free(widths);
}
}

View File

@@ -0,0 +1,132 @@
/************************************************************
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
********************************************************/
typedef struct {
int x;
int y;
int mask;
} miZeroArcPtRec;
typedef struct {
int x, y, k1, k3, a, b, d, dx, dy;
int alpha, beta;
int xorg, yorg;
int xorgo, yorgo;
int w, h;
int initialMask;
miZeroArcPtRec start, altstart, end, altend;
int firstx, firsty;
int startAngle, endAngle;
} miZeroArcRec;
#define miCanZeroArc(arc) (((arc)->width == (arc)->height) || \
(((arc)->width <= 800) && ((arc)->height <= 800)))
#define MIARCSETUP() \
x = info.x; \
y = info.y; \
k1 = info.k1; \
k3 = info.k3; \
a = info.a; \
b = info.b; \
d = info.d; \
dx = info.dx; \
dy = info.dy
#define MIARCOCTANTSHIFT(clause) \
if (a < 0) \
{ \
if (y == info.h) \
{ \
d = -1; \
a = b = k1 = 0; \
} \
else \
{ \
dx = (k1 << 1) - k3; \
k1 = dx - k1; \
k3 = -k3; \
b = b + a - (k1 >> 1); \
d = b + ((-a) >> 1) - d + (k3 >> 3); \
if (dx < 0) \
a = -((-dx) >> 1) - a; \
else \
a = (dx >> 1) - a; \
dx = 0; \
dy = 1; \
clause \
} \
}
#define MIARCSTEP(move1,move2) \
b -= k1; \
if (d < 0) \
{ \
x += dx; \
y += dy; \
a += k1; \
d += b; \
move1 \
} \
else \
{ \
x++; \
y++; \
a += k3; \
d -= a; \
move2 \
}
#define MIARCCIRCLESTEP(clause) \
b -= k1; \
x++; \
if (d < 0) \
{ \
a += k1; \
d += b; \
} \
else \
{ \
y++; \
a += k3; \
d -= a; \
clause \
}
/* mizerarc.c */
extern Bool miZeroArcSetup(
xArc * /*arc*/,
miZeroArcRec * /*info*/,
Bool /*ok360*/
);
extern DDXPointPtr miZeroArcPts(
xArc * /*arc*/,
DDXPointPtr /*pts*/
);

View File

@@ -0,0 +1,635 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "misc.h"
#include "scrnintstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmap.h"
#include "mi.h"
#include "miline.h"
/*
The bresenham error equation used in the mi/mfb/cfb line routines is:
e = error
dx = difference in raw X coordinates
dy = difference in raw Y coordinates
M = # of steps in X direction
N = # of steps in Y direction
B = 0 to prefer diagonal steps in a given octant,
1 to prefer axial steps in a given octant
For X major lines:
e = 2Mdy - 2Ndx - dx - B
-2dx <= e < 0
For Y major lines:
e = 2Ndx - 2Mdy - dy - B
-2dy <= e < 0
At the start of the line, we have taken 0 X steps and 0 Y steps,
so M = 0 and N = 0:
X major e = 2Mdy - 2Ndx - dx - B
= -dx - B
Y major e = 2Ndx - 2Mdy - dy - B
= -dy - B
At the end of the line, we have taken dx X steps and dy Y steps,
so M = dx and N = dy:
X major e = 2Mdy - 2Ndx - dx - B
= 2dxdy - 2dydx - dx - B
= -dx - B
Y major e = 2Ndx - 2Mdy - dy - B
= 2dydx - 2dxdy - dy - B
= -dy - B
Thus, the error term is the same at the start and end of the line.
Let us consider clipping an X coordinate. There are 4 cases which
represent the two independent cases of clipping the start vs. the
end of the line and an X major vs. a Y major line. In any of these
cases, we know the number of X steps (M) and we wish to find the
number of Y steps (N). Thus, we will solve our error term equation.
If we are clipping the start of the line, we will find the smallest
N that satisfies our error term inequality. If we are clipping the
end of the line, we will find the largest number of Y steps that
satisfies the inequality. In that case, since we are representing
the Y steps as (dy - N), we will actually want to solve for the
smallest N in that equation.
Case 1: X major, starting X coordinate moved by M steps
-2dx <= 2Mdy - 2Ndx - dx - B < 0
2Ndx <= 2Mdy - dx - B + 2dx 2Ndx > 2Mdy - dx - B
2Ndx <= 2Mdy + dx - B N > (2Mdy - dx - B) / 2dx
N <= (2Mdy + dx - B) / 2dx
Since we are trying to find the smallest N that satisfies these
equations, we should use the > inequality to find the smallest:
N = floor((2Mdy - dx - B) / 2dx) + 1
= floor((2Mdy - dx - B + 2dx) / 2dx)
= floor((2Mdy + dx - B) / 2dx)
Case 1b: X major, ending X coordinate moved to M steps
Same derivations as Case 1, but we want the largest N that satisfies
the equations, so we use the <= inequality:
N = floor((2Mdy + dx - B) / 2dx)
Case 2: X major, ending X coordinate moved by M steps
-2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0
-2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0
-2dx <= 2Ndx - 2Mdy - dx - B < 0
2Ndx >= 2Mdy + dx + B - 2dx 2Ndx < 2Mdy + dx + B
2Ndx >= 2Mdy - dx + B N < (2Mdy + dx + B) / 2dx
N >= (2Mdy - dx + B) / 2dx
Since we are trying to find the highest number of Y steps that
satisfies these equations, we need to find the smallest N, so
we should use the >= inequality to find the smallest:
N = ceiling((2Mdy - dx + B) / 2dx)
= floor((2Mdy - dx + B + 2dx - 1) / 2dx)
= floor((2Mdy + dx + B - 1) / 2dx)
Case 2b: X major, starting X coordinate moved to M steps from end
Same derivations as Case 2, but we want the smallest number of Y
steps, so we want the highest N, so we use the < inequality:
N = ceiling((2Mdy + dx + B) / 2dx) - 1
= floor((2Mdy + dx + B + 2dx - 1) / 2dx) - 1
= floor((2Mdy + dx + B + 2dx - 1 - 2dx) / 2dx)
= floor((2Mdy + dx + B - 1) / 2dx)
Case 3: Y major, starting X coordinate moved by M steps
-2dy <= 2Ndx - 2Mdy - dy - B < 0
2Ndx >= 2Mdy + dy + B - 2dy 2Ndx < 2Mdy + dy + B
2Ndx >= 2Mdy - dy + B N < (2Mdy + dy + B) / 2dx
N >= (2Mdy - dy + B) / 2dx
Since we are trying to find the smallest N that satisfies these
equations, we should use the >= inequality to find the smallest:
N = ceiling((2Mdy - dy + B) / 2dx)
= floor((2Mdy - dy + B + 2dx - 1) / 2dx)
= floor((2Mdy - dy + B - 1) / 2dx) + 1
Case 3b: Y major, ending X coordinate moved to M steps
Same derivations as Case 3, but we want the largest N that satisfies
the equations, so we use the < inequality:
N = ceiling((2Mdy + dy + B) / 2dx) - 1
= floor((2Mdy + dy + B + 2dx - 1) / 2dx) - 1
= floor((2Mdy + dy + B + 2dx - 1 - 2dx) / 2dx)
= floor((2Mdy + dy + B - 1) / 2dx)
Case 4: Y major, ending X coordinate moved by M steps
-2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0
-2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0
-2dy <= 2Mdy - 2Ndx - dy - B < 0
2Ndx <= 2Mdy - dy - B + 2dy 2Ndx > 2Mdy - dy - B
2Ndx <= 2Mdy + dy - B N > (2Mdy - dy - B) / 2dx
N <= (2Mdy + dy - B) / 2dx
Since we are trying to find the highest number of Y steps that
satisfies these equations, we need to find the smallest N, so
we should use the > inequality to find the smallest:
N = floor((2Mdy - dy - B) / 2dx) + 1
Case 4b: Y major, starting X coordinate moved to M steps from end
Same analysis as Case 4, but we want the smallest number of Y steps
which means the largest N, so we use the <= inequality:
N = floor((2Mdy + dy - B) / 2dx)
Now let's try the Y coordinates, we have the same 4 cases.
Case 5: X major, starting Y coordinate moved by N steps
-2dx <= 2Mdy - 2Ndx - dx - B < 0
2Mdy >= 2Ndx + dx + B - 2dx 2Mdy < 2Ndx + dx + B
2Mdy >= 2Ndx - dx + B M < (2Ndx + dx + B) / 2dy
M >= (2Ndx - dx + B) / 2dy
Since we are trying to find the smallest M, we use the >= inequality:
M = ceiling((2Ndx - dx + B) / 2dy)
= floor((2Ndx - dx + B + 2dy - 1) / 2dy)
= floor((2Ndx - dx + B - 1) / 2dy) + 1
Case 5b: X major, ending Y coordinate moved to N steps
Same derivations as Case 5, but we want the largest M that satisfies
the equations, so we use the < inequality:
M = ceiling((2Ndx + dx + B) / 2dy) - 1
= floor((2Ndx + dx + B + 2dy - 1) / 2dy) - 1
= floor((2Ndx + dx + B + 2dy - 1 - 2dy) / 2dy)
= floor((2Ndx + dx + B - 1) / 2dy)
Case 6: X major, ending Y coordinate moved by N steps
-2dx <= 2(dx - M)dy - 2(dy - N)dx - dx - B < 0
-2dx <= 2dxdy - 2Mdy - 2dxdy + 2Ndx - dx - B < 0
-2dx <= 2Ndx - 2Mdy - dx - B < 0
2Mdy <= 2Ndx - dx - B + 2dx 2Mdy > 2Ndx - dx - B
2Mdy <= 2Ndx + dx - B M > (2Ndx - dx - B) / 2dy
M <= (2Ndx + dx - B) / 2dy
Largest # of X steps means smallest M, so use the > inequality:
M = floor((2Ndx - dx - B) / 2dy) + 1
Case 6b: X major, starting Y coordinate moved to N steps from end
Same derivations as Case 6, but we want the smallest # of X steps
which means the largest M, so use the <= inequality:
M = floor((2Ndx + dx - B) / 2dy)
Case 7: Y major, starting Y coordinate moved by N steps
-2dy <= 2Ndx - 2Mdy - dy - B < 0
2Mdy <= 2Ndx - dy - B + 2dy 2Mdy > 2Ndx - dy - B
2Mdy <= 2Ndx + dy - B M > (2Ndx - dy - B) / 2dy
M <= (2Ndx + dy - B) / 2dy
To find the smallest M, use the > inequality:
M = floor((2Ndx - dy - B) / 2dy) + 1
= floor((2Ndx - dy - B + 2dy) / 2dy)
= floor((2Ndx + dy - B) / 2dy)
Case 7b: Y major, ending Y coordinate moved to N steps
Same derivations as Case 7, but we want the largest M that satisfies
the equations, so use the <= inequality:
M = floor((2Ndx + dy - B) / 2dy)
Case 8: Y major, ending Y coordinate moved by N steps
-2dy <= 2(dy - N)dx - 2(dx - M)dy - dy - B < 0
-2dy <= 2dxdy - 2Ndx - 2dxdy + 2Mdy - dy - B < 0
-2dy <= 2Mdy - 2Ndx - dy - B < 0
2Mdy >= 2Ndx + dy + B - 2dy 2Mdy < 2Ndx + dy + B
2Mdy >= 2Ndx - dy + B M < (2Ndx + dy + B) / 2dy
M >= (2Ndx - dy + B) / 2dy
To find the highest X steps, find the smallest M, use the >= inequality:
M = ceiling((2Ndx - dy + B) / 2dy)
= floor((2Ndx - dy + B + 2dy - 1) / 2dy)
= floor((2Ndx + dy + B - 1) / 2dy)
Case 8b: Y major, starting Y coordinate moved to N steps from the end
Same derivations as Case 8, but we want to find the smallest # of X
steps which means the largest M, so we use the < inequality:
M = ceiling((2Ndx + dy + B) / 2dy) - 1
= floor((2Ndx + dy + B + 2dy - 1) / 2dy) - 1
= floor((2Ndx + dy + B + 2dy - 1 - 2dy) / 2dy)
= floor((2Ndx + dy + B - 1) / 2dy)
So, our equations are:
1: X major move x1 to x1+M floor((2Mdy + dx - B) / 2dx)
1b: X major move x2 to x1+M floor((2Mdy + dx - B) / 2dx)
2: X major move x2 to x2-M floor((2Mdy + dx + B - 1) / 2dx)
2b: X major move x1 to x2-M floor((2Mdy + dx + B - 1) / 2dx)
3: Y major move x1 to x1+M floor((2Mdy - dy + B - 1) / 2dx) + 1
3b: Y major move x2 to x1+M floor((2Mdy + dy + B - 1) / 2dx)
4: Y major move x2 to x2-M floor((2Mdy - dy - B) / 2dx) + 1
4b: Y major move x1 to x2-M floor((2Mdy + dy - B) / 2dx)
5: X major move y1 to y1+N floor((2Ndx - dx + B - 1) / 2dy) + 1
5b: X major move y2 to y1+N floor((2Ndx + dx + B - 1) / 2dy)
6: X major move y2 to y2-N floor((2Ndx - dx - B) / 2dy) + 1
6b: X major move y1 to y2-N floor((2Ndx + dx - B) / 2dy)
7: Y major move y1 to y1+N floor((2Ndx + dy - B) / 2dy)
7b: Y major move y2 to y1+N floor((2Ndx + dy - B) / 2dy)
8: Y major move y2 to y2-N floor((2Ndx + dy + B - 1) / 2dy)
8b: Y major move y1 to y2-N floor((2Ndx + dy + B - 1) / 2dy)
We have the following constraints on all of the above terms:
0 < M,N <= 2^15 2^15 can be imposed by miZeroClipLine
0 <= dx/dy <= 2^16 - 1
0 <= B <= 1
The floor in all of the above equations can be accomplished with a
simple C divide operation provided that both numerator and denominator
are positive.
Since dx,dy >= 0 and since moving an X coordinate implies that dx != 0
and moving a Y coordinate implies dy != 0, we know that the denominators
are all > 0.
For all lines, (-B) and (B-1) are both either 0 or -1, depending on the
bias. Thus, we have to show that the 2MNdxy +/- dxy terms are all >= 1
or > 0 to prove that the numerators are positive (or zero).
For X Major lines we know that dx > 0 and since 2Mdy is >= 0 due to the
constraints, the first four equations all have numerators >= 0.
For the second four equations, M > 0, so 2Mdy >= 2dy so (2Mdy - dy) >= dy
So (2Mdy - dy) > 0, since they are Y major lines. Also, (2Mdy + dy) >= 3dy
or (2Mdy + dy) > 0. So all of their numerators are >= 0.
For the third set of four equations, N > 0, so 2Ndx >= 2dx so (2Ndx - dx)
>= dx > 0. Similarly (2Ndx + dx) >= 3dx > 0. So all numerators >= 0.
For the fourth set of equations, dy > 0 and 2Ndx >= 0, so all numerators
are > 0.
To consider overflow, consider the case of 2 * M,N * dx,dy + dx,dy. This
is bounded <= 2 * 2^15 * (2^16 - 1) + (2^16 - 1)
<= 2^16 * (2^16 - 1) + (2^16 - 1)
<= 2^32 - 2^16 + 2^16 - 1
<= 2^32 - 1
Since the (-B) and (B-1) terms are all 0 or -1, the maximum value of
the numerator is therefore (2^32 - 1), which does not overflow an unsigned
32 bit variable.
*/
/* Bit codes for the terms of the 16 clipping equations defined below. */
#define T_2NDX (1 << 0)
#define T_2MDY (0) /* implicit term */
#define T_DXNOTY (1 << 1)
#define T_DYNOTX (0) /* implicit term */
#define T_SUBDXORY (1 << 2)
#define T_ADDDX (T_DXNOTY) /* composite term */
#define T_SUBDX (T_DXNOTY | T_SUBDXORY) /* composite term */
#define T_ADDDY (T_DYNOTX) /* composite term */
#define T_SUBDY (T_DYNOTX | T_SUBDXORY) /* composite term */
#define T_BIASSUBONE (1 << 3)
#define T_SUBBIAS (0) /* implicit term */
#define T_DIV2DX (1 << 4)
#define T_DIV2DY (0) /* implicit term */
#define T_ADDONE (1 << 5)
/* Bit masks defining the 16 equations used in miZeroClipLine. */
#define EQN1 (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX)
#define EQN1B (T_2MDY | T_ADDDX | T_SUBBIAS | T_DIV2DX)
#define EQN2 (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX)
#define EQN2B (T_2MDY | T_ADDDX | T_BIASSUBONE | T_DIV2DX)
#define EQN3 (T_2MDY | T_SUBDY | T_BIASSUBONE | T_DIV2DX | T_ADDONE)
#define EQN3B (T_2MDY | T_ADDDY | T_BIASSUBONE | T_DIV2DX)
#define EQN4 (T_2MDY | T_SUBDY | T_SUBBIAS | T_DIV2DX | T_ADDONE)
#define EQN4B (T_2MDY | T_ADDDY | T_SUBBIAS | T_DIV2DX)
#define EQN5 (T_2NDX | T_SUBDX | T_BIASSUBONE | T_DIV2DY | T_ADDONE)
#define EQN5B (T_2NDX | T_ADDDX | T_BIASSUBONE | T_DIV2DY)
#define EQN6 (T_2NDX | T_SUBDX | T_SUBBIAS | T_DIV2DY | T_ADDONE)
#define EQN6B (T_2NDX | T_ADDDX | T_SUBBIAS | T_DIV2DY)
#define EQN7 (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY)
#define EQN7B (T_2NDX | T_ADDDY | T_SUBBIAS | T_DIV2DY)
#define EQN8 (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY)
#define EQN8B (T_2NDX | T_ADDDY | T_BIASSUBONE | T_DIV2DY)
/* miZeroClipLine
*
* returns: 1 for partially clipped line
* -1 for completely clipped line
*
*/
int
miZeroClipLine(xmin, ymin, xmax, ymax,
new_x1, new_y1, new_x2, new_y2,
adx, ady,
pt1_clipped, pt2_clipped, octant, bias, oc1, oc2)
int xmin, ymin, xmax, ymax;
int *new_x1, *new_y1, *new_x2, *new_y2;
int *pt1_clipped, *pt2_clipped;
unsigned int adx, ady;
int octant;
unsigned int bias;
int oc1, oc2;
{
int swapped = 0;
int clipDone = 0;
CARD32 utmp = 0;
int clip1, clip2;
int x1, y1, x2, y2;
int x1_orig, y1_orig, x2_orig, y2_orig;
int xmajor;
int negslope = 0, anchorval = 0;
unsigned int eqn = 0;
x1 = x1_orig = *new_x1;
y1 = y1_orig = *new_y1;
x2 = x2_orig = *new_x2;
y2 = y2_orig = *new_y2;
clip1 = 0;
clip2 = 0;
xmajor = IsXMajorOctant(octant);
bias = ((bias >> octant) & 1);
while (1)
{
if ((oc1 & oc2) != 0) /* trivial reject */
{
clipDone = -1;
clip1 = oc1;
clip2 = oc2;
break;
}
else if ((oc1 | oc2) == 0) /* trivial accept */
{
clipDone = 1;
if (swapped)
{
SWAPINT_PAIR(x1, y1, x2, y2);
SWAPINT(clip1, clip2);
}
break;
}
else /* have to clip */
{
/* only clip one point at a time */
if (oc1 == 0)
{
SWAPINT_PAIR(x1, y1, x2, y2);
SWAPINT_PAIR(x1_orig, y1_orig, x2_orig, y2_orig);
SWAPINT(oc1, oc2);
SWAPINT(clip1, clip2);
swapped = !swapped;
}
clip1 |= oc1;
if (oc1 & OUT_LEFT)
{
negslope = IsYDecreasingOctant(octant);
utmp = xmin - x1_orig;
if (utmp <= 32767) /* clip based on near endpt */
{
if (xmajor)
eqn = (swapped) ? EQN2 : EQN1;
else
eqn = (swapped) ? EQN4 : EQN3;
anchorval = y1_orig;
}
else /* clip based on far endpt */
{
utmp = x2_orig - xmin;
if (xmajor)
eqn = (swapped) ? EQN1B : EQN2B;
else
eqn = (swapped) ? EQN3B : EQN4B;
anchorval = y2_orig;
negslope = !negslope;
}
x1 = xmin;
}
else if (oc1 & OUT_ABOVE)
{
negslope = IsXDecreasingOctant(octant);
utmp = ymin - y1_orig;
if (utmp <= 32767) /* clip based on near endpt */
{
if (xmajor)
eqn = (swapped) ? EQN6 : EQN5;
else
eqn = (swapped) ? EQN8 : EQN7;
anchorval = x1_orig;
}
else /* clip based on far endpt */
{
utmp = y2_orig - ymin;
if (xmajor)
eqn = (swapped) ? EQN5B : EQN6B;
else
eqn = (swapped) ? EQN7B : EQN8B;
anchorval = x2_orig;
negslope = !negslope;
}
y1 = ymin;
}
else if (oc1 & OUT_RIGHT)
{
negslope = IsYDecreasingOctant(octant);
utmp = x1_orig - xmax;
if (utmp <= 32767) /* clip based on near endpt */
{
if (xmajor)
eqn = (swapped) ? EQN2 : EQN1;
else
eqn = (swapped) ? EQN4 : EQN3;
anchorval = y1_orig;
}
else /* clip based on far endpt */
{
/*
* Technically since the equations can handle
* utmp == 32768, this overflow code isn't
* needed since X11 protocol can't generate
* a line which goes more than 32768 pixels
* to the right of a clip rectangle.
*/
utmp = xmax - x2_orig;
if (xmajor)
eqn = (swapped) ? EQN1B : EQN2B;
else
eqn = (swapped) ? EQN3B : EQN4B;
anchorval = y2_orig;
negslope = !negslope;
}
x1 = xmax;
}
else if (oc1 & OUT_BELOW)
{
negslope = IsXDecreasingOctant(octant);
utmp = y1_orig - ymax;
if (utmp <= 32767) /* clip based on near endpt */
{
if (xmajor)
eqn = (swapped) ? EQN6 : EQN5;
else
eqn = (swapped) ? EQN8 : EQN7;
anchorval = x1_orig;
}
else /* clip based on far endpt */
{
/*
* Technically since the equations can handle
* utmp == 32768, this overflow code isn't
* needed since X11 protocol can't generate
* a line which goes more than 32768 pixels
* below the bottom of a clip rectangle.
*/
utmp = ymax - y2_orig;
if (xmajor)
eqn = (swapped) ? EQN5B : EQN6B;
else
eqn = (swapped) ? EQN7B : EQN8B;
anchorval = x2_orig;
negslope = !negslope;
}
y1 = ymax;
}
if (swapped)
negslope = !negslope;
utmp <<= 1; /* utmp = 2N or 2M */
if (eqn & T_2NDX)
utmp = (utmp * adx);
else /* (eqn & T_2MDY) */
utmp = (utmp * ady);
if (eqn & T_DXNOTY)
if (eqn & T_SUBDXORY)
utmp -= adx;
else
utmp += adx;
else /* (eqn & T_DYNOTX) */
if (eqn & T_SUBDXORY)
utmp -= ady;
else
utmp += ady;
if (eqn & T_BIASSUBONE)
utmp += bias - 1;
else /* (eqn & T_SUBBIAS) */
utmp -= bias;
if (eqn & T_DIV2DX)
utmp /= (adx << 1);
else /* (eqn & T_DIV2DY) */
utmp /= (ady << 1);
if (eqn & T_ADDONE)
utmp++;
if (negslope)
utmp = -utmp;
if (eqn & T_2NDX) /* We are calculating X steps */
x1 = anchorval + utmp;
else /* else, Y steps */
y1 = anchorval + utmp;
oc1 = 0;
MIOUTCODES(oc1, x1, y1, xmin, ymin, xmax, ymax);
}
}
*new_x1 = x1;
*new_y1 = y1;
*new_x2 = x2;
*new_y2 = y2;
*pt1_clipped = clip1;
*pt2_clipped = clip2;
return clipDone;
}

View File

@@ -0,0 +1,383 @@
/***********************************************************
Copyright 1987, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
documentation for any purpose is hereby granted without fee, provided that
the above copyright notice appear in all copies and that both that
copyright notice and this permission notice appear in supporting
documentation.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of The Open Group shall not be
used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization from The Open Group.
Copyright 1987 by Digital Equipment Corporation, Maynard, 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 name of Digital 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.
******************************************************************/
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <nx-X11/X.h>
#include "misc.h"
#include "scrnintstr.h"
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmap.h"
#include "mi.h"
#include "miline.h"
/* Draw lineSolid, fillStyle-independent zero width lines.
*
* Must keep X and Y coordinates in "ints" at least until after they're
* translated and clipped to accomodate CoordModePrevious lines with very
* large coordinates.
*
* Draws the same pixels regardless of sign(dx) or sign(dy).
*
* Ken Whaley
*
*/
/* largest positive value that can fit into a component of a point.
* Assumes that the point structure is {type x, y;} where type is
* a signed type.
*/
#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1)
#define MI_OUTPUT_POINT(xx, yy)\
{\
if ( !new_span && yy == current_y)\
{\
if (xx < spans->x)\
spans->x = xx;\
++*widths;\
}\
else\
{\
++Nspans;\
++spans;\
++widths;\
spans->x = xx;\
spans->y = yy;\
*widths = 1;\
current_y = yy;\
new_span = FALSE;\
}\
}
void
miZeroLine(pDraw, pGC, mode, npt, pptInit)
DrawablePtr pDraw;
GCPtr pGC;
int mode; /* Origin or Previous */
int npt; /* number of points */
DDXPointPtr pptInit;
{
int Nspans, current_y = 0;
DDXPointPtr ppt;
DDXPointPtr pspanInit, spans;
int *pwidthInit, *widths, list_len;
int xleft, ytop, xright, ybottom;
int new_x1, new_y1, new_x2, new_y2;
int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart;
int oc1, oc2;
int result;
int pt1_clipped, pt2_clipped = 0;
Bool new_span;
int signdx, signdy;
int clipdx, clipdy;
int width, height;
int adx, ady;
int octant;
unsigned int bias = miGetZeroLineBias(pDraw->pScreen);
int e, e1, e2, e3; /* Bresenham error terms */
int length; /* length of lines == # of pixels on major axis */
xleft = pDraw->x;
ytop = pDraw->y;
xright = pDraw->x + pDraw->width - 1;
ybottom = pDraw->y + pDraw->height - 1;
if (!pGC->miTranslate)
{
/* do everything in drawable-relative coordinates */
xleft = 0;
ytop = 0;
xright -= pDraw->x;
ybottom -= pDraw->y;
}
/* it doesn't matter whether we're in drawable or screen coordinates,
* FillSpans simply cannot take starting coordinates outside of the
* range of a DDXPointRec component.
*/
if (xright > MAX_COORDINATE)
xright = MAX_COORDINATE;
if (ybottom > MAX_COORDINATE)
ybottom = MAX_COORDINATE;
/* since we're clipping to the drawable's boundaries & coordinate
* space boundaries, we're guaranteed that the larger of width/height
* is the longest span we'll need to output
*/
width = xright - xleft + 1;
height = ybottom - ytop + 1;
list_len = (height >= width) ? height : width;
pspanInit = (DDXPointPtr)malloc(list_len * sizeof(DDXPointRec));
pwidthInit = (int *)malloc(list_len * sizeof(int));
if (!pspanInit || !pwidthInit)
{
free(pspanInit);
free(pwidthInit);
return;
}
Nspans = 0;
new_span = TRUE;
spans = pspanInit - 1;
widths = pwidthInit - 1;
ppt = pptInit;
xstart = ppt->x;
ystart = ppt->y;
if (pGC->miTranslate)
{
xstart += pDraw->x;
ystart += pDraw->y;
}
/* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify
* iteration logic
*/
x2 = xstart;
y2 = ystart;
oc2 = 0;
MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
while (--npt > 0)
{
if (Nspans > 0)
(*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
pwidthInit, FALSE);
Nspans = 0;
new_span = TRUE;
spans = pspanInit - 1;
widths = pwidthInit - 1;
x1 = x2;
y1 = y2;
oc1 = oc2;
++ppt;
x2 = ppt->x;
y2 = ppt->y;
if (pGC->miTranslate && (mode != CoordModePrevious))
{
x2 += pDraw->x;
y2 += pDraw->y;
}
else if (mode == CoordModePrevious)
{
x2 += x1;
y2 += y1;
}
oc2 = 0;
MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom);
CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant);
if (adx > ady)
{
e1 = ady << 1;
e2 = e1 - (adx << 1);
e = e1 - adx;
length = adx; /* don't draw endpoint in main loop */
FIXUP_ERROR(e, octant, bias);
new_x1 = x1;
new_y1 = y1;
new_x2 = x2;
new_y2 = y2;
pt1_clipped = 0;
pt2_clipped = 0;
if ((oc1 | oc2) != 0)
{
result = miZeroClipLine(xleft, ytop, xright, ybottom,
&new_x1, &new_y1, &new_x2, &new_y2,
adx, ady,
&pt1_clipped, &pt2_clipped,
octant, bias, oc1, oc2);
if (result == -1)
continue;
length = abs(new_x2 - new_x1);
/* if we've clipped the endpoint, always draw the full length
* of the segment, because then the capstyle doesn't matter
*/
if (pt2_clipped)
length++;
if (pt1_clipped)
{
/* must calculate new error terms */
clipdx = abs(new_x1 - x1);
clipdy = abs(new_y1 - y1);
e += (clipdy * e2) + ((clipdx - clipdy) * e1);
}
}
/* draw the segment */
x = new_x1;
y = new_y1;
e3 = e2 - e1;
e = e - e1;
while (length--)
{
MI_OUTPUT_POINT(x, y);
e += e1;
if (e >= 0)
{
y += signdy;
e += e3;
}
x += signdx;
}
}
else /* Y major line */
{
e1 = adx << 1;
e2 = e1 - (ady << 1);
e = e1 - ady;
length = ady; /* don't draw endpoint in main loop */
SetYMajorOctant(octant);
FIXUP_ERROR(e, octant, bias);
new_x1 = x1;
new_y1 = y1;
new_x2 = x2;
new_y2 = y2;
pt1_clipped = 0;
pt2_clipped = 0;
if ((oc1 | oc2) != 0)
{
result = miZeroClipLine(xleft, ytop, xright, ybottom,
&new_x1, &new_y1, &new_x2, &new_y2,
adx, ady,
&pt1_clipped, &pt2_clipped,
octant, bias, oc1, oc2);
if (result == -1)
continue;
length = abs(new_y2 - new_y1);
/* if we've clipped the endpoint, always draw the full length
* of the segment, because then the capstyle doesn't matter
*/
if (pt2_clipped)
length++;
if (pt1_clipped)
{
/* must calculate new error terms */
clipdx = abs(new_x1 - x1);
clipdy = abs(new_y1 - y1);
e += (clipdx * e2) + ((clipdy - clipdx) * e1);
}
}
/* draw the segment */
x = new_x1;
y = new_y1;
e3 = e2 - e1;
e = e - e1;
while (length--)
{
MI_OUTPUT_POINT(x, y);
e += e1;
if (e >= 0)
{
x += signdx;
e += e3;
}
y += signdy;
}
}
}
/* only do the capnotlast check on the last segment
* and only if the endpoint wasn't clipped. And then, if the last
* point is the same as the first point, do not draw it, unless the
* line is degenerate
*/
if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) &&
(((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1)))
{
MI_OUTPUT_POINT(x, y);
}
if (Nspans > 0)
(*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit,
pwidthInit, FALSE);
free(pwidthInit);
free(pspanInit);
}
void
miZeroDashLine(dst, pgc, mode, nptInit, pptInit)
DrawablePtr dst;
GCPtr pgc;
int mode;
int nptInit; /* number of points in polyline */
DDXPointRec *pptInit; /* points in the polyline */
{
/* XXX kludge until real zero-width dash code is written */
pgc->lineWidth = 1;
miWideDash (dst, pgc, mode, nptInit, pptInit);
pgc->lineWidth = 0;
}