1121 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1121 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			C
		
	
	
	
/***********************************************************
 | 
						|
 | 
						|
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 <stdlib.h>
 | 
						|
 | 
						|
#include <X11/X.h>
 | 
						|
#include <X11/Xmd.h>
 | 
						|
#include <X11/Xproto.h>
 | 
						|
#include "mfb.h"
 | 
						|
#include "dixfontstr.h"
 | 
						|
#include <X11/fonts/fontstruct.h>
 | 
						|
#include "gcstruct.h"
 | 
						|
#include "windowstr.h"
 | 
						|
#include "pixmapstr.h"
 | 
						|
#include "scrnintstr.h"
 | 
						|
#include "region.h"
 | 
						|
 | 
						|
#include "mistruct.h"
 | 
						|
#include "migc.h"
 | 
						|
 | 
						|
#include "maskbits.h"
 | 
						|
 | 
						|
static GCFuncs	mfbFuncs = {
 | 
						|
	mfbValidateGC,
 | 
						|
	miChangeGC,
 | 
						|
	miCopyGC,
 | 
						|
	miDestroyGC,
 | 
						|
	miChangeClip,
 | 
						|
	miDestroyClip,
 | 
						|
	miCopyClip
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
static GCOps	whiteTECopyOps = {
 | 
						|
	mfbWhiteSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	mfbZeroPolyArcSS,
 | 
						|
	mfbFillPolyWhite,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	mfbTEGlyphBltWhite,
 | 
						|
	mfbPolyGlyphBltWhite,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	blackTECopyOps = {
 | 
						|
	mfbBlackSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	mfbZeroPolyArcSS,
 | 
						|
	mfbFillPolyBlack,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	mfbTEGlyphBltBlack,
 | 
						|
	mfbPolyGlyphBltBlack,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	whiteTEInvertOps = {
 | 
						|
	mfbInvertSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	miCopyArea,
 | 
						|
	miCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	miZeroPolyArc,
 | 
						|
	mfbFillPolyInvert,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	mfbTEGlyphBltWhite,
 | 
						|
	mfbPolyGlyphBltInvert,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	blackTEInvertOps = {
 | 
						|
	mfbInvertSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	miZeroPolyArc,
 | 
						|
	mfbFillPolyInvert,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	mfbTEGlyphBltBlack,
 | 
						|
	mfbPolyGlyphBltInvert,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	whiteCopyOps = {
 | 
						|
	mfbWhiteSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	mfbZeroPolyArcSS,
 | 
						|
	mfbFillPolyWhite,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	mfbImageGlyphBltWhite,
 | 
						|
	mfbPolyGlyphBltWhite,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	blackCopyOps = {
 | 
						|
	mfbBlackSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	mfbZeroPolyArcSS,
 | 
						|
	mfbFillPolyBlack,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	mfbImageGlyphBltBlack,
 | 
						|
	mfbPolyGlyphBltBlack,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	whiteInvertOps = {
 | 
						|
	mfbInvertSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	miZeroPolyArc,
 | 
						|
	mfbFillPolyInvert,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	mfbImageGlyphBltWhite,
 | 
						|
	mfbPolyGlyphBltInvert,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	blackInvertOps = {
 | 
						|
	mfbInvertSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	miZeroPolyArc,
 | 
						|
	mfbFillPolyInvert,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	mfbImageGlyphBltBlack,
 | 
						|
	mfbPolyGlyphBltInvert,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	whiteWhiteCopyOps = {
 | 
						|
	mfbWhiteSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	mfbZeroPolyArcSS,
 | 
						|
	mfbFillPolyWhite,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	miImageGlyphBlt,
 | 
						|
	mfbPolyGlyphBltWhite,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	blackBlackCopyOps = {
 | 
						|
	mfbBlackSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	mfbZeroPolyArcSS,
 | 
						|
	mfbFillPolyBlack,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	miImageGlyphBlt,
 | 
						|
	mfbPolyGlyphBltBlack,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
static GCOps	fgEqBgInvertOps = {
 | 
						|
	mfbInvertSolidFS,
 | 
						|
	mfbSetSpans,
 | 
						|
	mfbPutImage,
 | 
						|
	mfbCopyArea,
 | 
						|
	mfbCopyPlane,
 | 
						|
	mfbPolyPoint,
 | 
						|
	mfbLineSS,
 | 
						|
	mfbSegmentSS,
 | 
						|
	miPolyRectangle,
 | 
						|
	miZeroPolyArc,
 | 
						|
	mfbFillPolyInvert,
 | 
						|
	mfbPolyFillRect,
 | 
						|
	mfbPolyFillArcSolid,
 | 
						|
	miPolyText8,
 | 
						|
	miPolyText16,
 | 
						|
	miImageText8,
 | 
						|
	miImageText16,
 | 
						|
	miImageGlyphBlt,
 | 
						|
	mfbPolyGlyphBltInvert,
 | 
						|
	mfbSolidPP
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
struct commonOps {
 | 
						|
    int		    fg, bg;
 | 
						|
    int		    rrop;
 | 
						|
    int		    terminalFont;
 | 
						|
    GCOps	    *ops;
 | 
						|
    void	    (*fillArea)(
 | 
						|
	DrawablePtr /*pDraw*/,
 | 
						|
    	int /*nbox*/,
 | 
						|
    	BoxPtr /*pbox*/,
 | 
						|
    	int /*alu*/,
 | 
						|
    	PixmapPtr /*nop*/);
 | 
						|
};
 | 
						|
 | 
						|
static struct commonOps mfbCommonOps[] = {
 | 
						|
    { 1, 0, RROP_WHITE, 1, &whiteTECopyOps, mfbSolidWhiteArea },
 | 
						|
    { 0, 1, RROP_BLACK, 1, &blackTECopyOps, mfbSolidBlackArea },
 | 
						|
    { 1, 0, RROP_INVERT, 1, &whiteTEInvertOps, mfbSolidInvertArea },
 | 
						|
    { 0, 1, RROP_INVERT, 1, &blackTEInvertOps, mfbSolidInvertArea },
 | 
						|
    { 1, 0, RROP_WHITE, 0, &whiteCopyOps, mfbSolidWhiteArea },
 | 
						|
    { 0, 1, RROP_BLACK, 0, &blackCopyOps, mfbSolidBlackArea },
 | 
						|
    { 1, 0, RROP_INVERT, 0, &whiteInvertOps, mfbSolidInvertArea },
 | 
						|
    { 0, 1, RROP_INVERT, 0, &blackInvertOps, mfbSolidInvertArea },
 | 
						|
    { 1, 1, RROP_WHITE, 0, &whiteWhiteCopyOps, mfbSolidWhiteArea },
 | 
						|
    { 0, 0, RROP_BLACK, 0, &blackBlackCopyOps, mfbSolidBlackArea },
 | 
						|
    { 1, 1, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea },
 | 
						|
    { 0, 0, RROP_INVERT, 0, &fgEqBgInvertOps, mfbSolidInvertArea },
 | 
						|
};
 | 
						|
 | 
						|
#define numberCommonOps	(sizeof (mfbCommonOps) / sizeof (mfbCommonOps[0]))
 | 
						|
 | 
						|
static GCOps *
 | 
						|
matchCommon (
 | 
						|
    GCPtr   pGC)
 | 
						|
{
 | 
						|
    int	i;
 | 
						|
    struct commonOps	*cop;
 | 
						|
    mfbPrivGC		*priv;
 | 
						|
 | 
						|
    if (pGC->lineWidth != 0)
 | 
						|
	return 0;
 | 
						|
    if (pGC->lineStyle != LineSolid)
 | 
						|
	return 0;
 | 
						|
    if (pGC->fillStyle != FillSolid)
 | 
						|
	return 0;
 | 
						|
    if (!pGC->font ||
 | 
						|
        FONTMAXBOUNDS(pGC->font,rightSideBearing) -
 | 
						|
	FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
 | 
						|
	FONTMINBOUNDS(pGC->font,characterWidth) < 0)
 | 
						|
	return 0;
 | 
						|
    priv = (mfbPrivGC *)dixLookupPrivate(&pGC->devPrivates,
 | 
						|
					 mfbGetGCPrivateKey());
 | 
						|
    for (i = 0; i < numberCommonOps; i++) {
 | 
						|
	cop = &mfbCommonOps[i];
 | 
						|
	if ((pGC->fgPixel & 1) != cop->fg)
 | 
						|
	    continue;
 | 
						|
	if ((pGC->bgPixel & 1) != cop->bg)
 | 
						|
	    continue;
 | 
						|
	if (priv->rop != cop->rrop)
 | 
						|
	    continue;
 | 
						|
	if (cop->terminalFont && !TERMINALFONT(pGC->font))
 | 
						|
	    continue;
 | 
						|
	priv->FillArea = cop->fillArea;
 | 
						|
	return cop->ops;
 | 
						|
    }
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
Bool
 | 
						|
mfbCreateGC(pGC)
 | 
						|
    register GCPtr pGC;
 | 
						|
{
 | 
						|
    mfbPrivGC 	*pPriv;
 | 
						|
 | 
						|
    pGC->clientClip = NULL;
 | 
						|
    pGC->clientClipType = CT_NONE;
 | 
						|
    
 | 
						|
    /* some of the output primitives aren't really necessary, since
 | 
						|
       they will be filled in ValidateGC because of dix/CreateGC()
 | 
						|
       setting all the change bits.  Others are necessary because although
 | 
						|
       they depend on being a monochrome frame buffer, they don't change 
 | 
						|
    */
 | 
						|
 | 
						|
    pGC->ops = &whiteCopyOps;
 | 
						|
    pGC->funcs = &mfbFuncs;
 | 
						|
 | 
						|
    /* mfb wants to translate before scan convesion */
 | 
						|
    pGC->miTranslate = 1;
 | 
						|
 | 
						|
    pPriv = (mfbPrivGC *)dixLookupPrivate(&pGC->devPrivates,
 | 
						|
					  mfbGetGCPrivateKey());
 | 
						|
    pPriv->rop = mfbReduceRop(pGC->alu, pGC->fgPixel);
 | 
						|
    pGC->fExpose = TRUE;
 | 
						|
    pGC->pRotatedPixmap = NullPixmap;
 | 
						|
    pGC->freeCompClip = FALSE;
 | 
						|
    pPriv->FillArea = mfbSolidInvertArea;
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/* some noop functions */
 | 
						|
static void
 | 
						|
mfbPolyGlyphBltNoop(
 | 
						|
    DrawablePtr pDrawable,
 | 
						|
    GCPtr pGC,
 | 
						|
    int x,
 | 
						|
    int y,
 | 
						|
    unsigned int nglyph,
 | 
						|
    CharInfoPtr * ppci,
 | 
						|
    pointer pglyphBase)
 | 
						|
{
 | 
						|
    /* this is a no-op function */
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
mfbNoopFS(
 | 
						|
    DrawablePtr pDrawable,
 | 
						|
    GCPtr pGC,
 | 
						|
    int nInit,
 | 
						|
    DDXPointPtr pptInit,
 | 
						|
    int * pwidthInit,
 | 
						|
    int fSorted)
 | 
						|
{
 | 
						|
    /* this is a no-op function */
 | 
						|
}
 | 
						|
 | 
						|
static void
 | 
						|
mfbFillPolyNoop(
 | 
						|
    DrawablePtr pDrawable,
 | 
						|
    GCPtr pGC,
 | 
						|
    int shape,
 | 
						|
    int mode,
 | 
						|
    int count,
 | 
						|
    DDXPointPtr ptsIn)
 | 
						|
{
 | 
						|
    /* this is a no-op function */
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Clipping conventions
 | 
						|
	if the drawable is a window
 | 
						|
	    CT_REGION ==> pCompositeClip really is the composite
 | 
						|
	    CT_other ==> pCompositeClip is the window clip region
 | 
						|
	if the drawable is a pixmap
 | 
						|
	    CT_REGION ==> pCompositeClip is the translated client region
 | 
						|
		clipped to the pixmap boundary
 | 
						|
	    CT_other ==> pCompositeClip is the pixmap bounding box
 | 
						|
*/
 | 
						|
 | 
						|
/*ARGSUSED*/
 | 
						|
void
 | 
						|
mfbValidateGC(pGC, changes, pDrawable)
 | 
						|
    register GCPtr 	pGC;
 | 
						|
    unsigned long	changes;
 | 
						|
    DrawablePtr 	pDrawable;
 | 
						|
{
 | 
						|
    register mfbPrivGCPtr	devPriv;
 | 
						|
    int mask;			/* stateChanges */
 | 
						|
    int index;			/* used for stepping through bitfields */
 | 
						|
    int	xrot, yrot;		/* rotations for tile and stipple pattern */
 | 
						|
    int rrop;			/* reduced rasterop */
 | 
						|
				/* flags for changing the proc vector 
 | 
						|
				   and updating things in devPriv
 | 
						|
				*/
 | 
						|
    int new_rotate, new_rrop,  new_line, new_text, new_fill;
 | 
						|
    DDXPointRec	oldOrg;		/* origin of thing GC was last used with */
 | 
						|
 | 
						|
    oldOrg = pGC->lastWinOrg;
 | 
						|
 | 
						|
    pGC->lastWinOrg.x = pDrawable->x;
 | 
						|
    pGC->lastWinOrg.y = pDrawable->y;
 | 
						|
 | 
						|
    /* we need to re-rotate the tile if the previous window/pixmap
 | 
						|
       origin (oldOrg) differs from the new window/pixmap origin
 | 
						|
       (pGC->lastWinOrg)
 | 
						|
    */
 | 
						|
    new_rotate = (oldOrg.x != pGC->lastWinOrg.x) ||
 | 
						|
		 (oldOrg.y != pGC->lastWinOrg.y);
 | 
						|
 | 
						|
    devPriv = (mfbPrivGCPtr)dixLookupPrivate(&pGC->devPrivates,
 | 
						|
					     mfbGetGCPrivateKey());
 | 
						|
    /*
 | 
						|
	if the client clip is different or moved OR
 | 
						|
	the subwindowMode has changed OR
 | 
						|
	the window's clip has changed since the last validation
 | 
						|
	we need to recompute the composite clip
 | 
						|
    */
 | 
						|
    if ((changes & (GCClipXOrigin|GCClipYOrigin|GCClipMask|GCSubwindowMode)) ||
 | 
						|
	(pDrawable->serialNumber != (pGC->serialNumber & DRAWABLE_SERIAL_BITS))
 | 
						|
       )
 | 
						|
    {
 | 
						|
	miComputeCompositeClip(pGC, pDrawable);
 | 
						|
    }
 | 
						|
 | 
						|
    new_rrop = FALSE;
 | 
						|
    new_line = FALSE;
 | 
						|
    new_text = FALSE;
 | 
						|
    new_fill = FALSE;
 | 
						|
 | 
						|
    mask = changes;
 | 
						|
    while (mask)
 | 
						|
    {
 | 
						|
	index = lowbit (mask);
 | 
						|
	mask &= ~index;
 | 
						|
 | 
						|
	/* this switch acculmulates a list of which procedures
 | 
						|
	   might have to change due to changes in the GC.  in
 | 
						|
	   some cases (e.g. changing one 16 bit tile for another)
 | 
						|
	   we might not really need a change, but the code is
 | 
						|
	   being paranoid.
 | 
						|
	   this sort of batching wins if, for example, the alu
 | 
						|
	   and the font have been changed, or any other pair
 | 
						|
	   of items that both change the same thing.
 | 
						|
	*/
 | 
						|
	switch (index)
 | 
						|
	{
 | 
						|
	  case GCFunction:
 | 
						|
	  case GCForeground:
 | 
						|
	    new_rrop = TRUE;
 | 
						|
	    break;
 | 
						|
	  case GCPlaneMask:
 | 
						|
	    break;
 | 
						|
	  case GCBackground:
 | 
						|
	    new_rrop = TRUE;	/* for opaque stipples */
 | 
						|
	    break;
 | 
						|
	  case GCLineStyle:
 | 
						|
	  case GCLineWidth:
 | 
						|
	  case GCJoinStyle:
 | 
						|
	    new_line = TRUE;
 | 
						|
	    break;
 | 
						|
	  case GCCapStyle:
 | 
						|
	    break;
 | 
						|
	  case GCFillStyle:
 | 
						|
	    new_fill = TRUE;
 | 
						|
	    break;
 | 
						|
	  case GCFillRule:
 | 
						|
	    break;
 | 
						|
	  case GCTile:
 | 
						|
	    if(pGC->tileIsPixel)
 | 
						|
		break;
 | 
						|
	    new_rotate = TRUE;
 | 
						|
	    new_fill = TRUE;
 | 
						|
	    break;
 | 
						|
 | 
						|
	  case GCStipple:
 | 
						|
	    if(pGC->stipple == (PixmapPtr)NULL)
 | 
						|
		break;
 | 
						|
	    new_rotate = TRUE;
 | 
						|
	    new_fill = TRUE;
 | 
						|
	    break;
 | 
						|
 | 
						|
	  case GCTileStipXOrigin:
 | 
						|
	    new_rotate = TRUE;
 | 
						|
	    break;
 | 
						|
 | 
						|
	  case GCTileStipYOrigin:
 | 
						|
	    new_rotate = TRUE;
 | 
						|
	    break;
 | 
						|
 | 
						|
	  case GCFont:
 | 
						|
	    new_text = TRUE;
 | 
						|
	    break;
 | 
						|
	  case GCSubwindowMode:
 | 
						|
	    break;
 | 
						|
	  case GCGraphicsExposures:
 | 
						|
	    break;
 | 
						|
	  case GCClipXOrigin:
 | 
						|
	    break;
 | 
						|
	  case GCClipYOrigin:
 | 
						|
	    break;
 | 
						|
	  case GCClipMask:
 | 
						|
	    break;
 | 
						|
	  case GCDashOffset:
 | 
						|
	    break;
 | 
						|
	  case GCDashList:
 | 
						|
	    break;
 | 
						|
	  case GCArcMode:
 | 
						|
	    break;
 | 
						|
	  default:
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /* deal with the changes we've collected .
 | 
						|
       new_rrop must be done first because subsequent things
 | 
						|
       depend on it.
 | 
						|
    */
 | 
						|
 | 
						|
    if(new_rotate || new_fill)
 | 
						|
    {
 | 
						|
	Bool new_pix = FALSE;
 | 
						|
 | 
						|
	/* figure out how much to rotate */
 | 
						|
	xrot = pGC->patOrg.x;
 | 
						|
	yrot = pGC->patOrg.y;
 | 
						|
	xrot += pDrawable->x;
 | 
						|
	yrot += pDrawable->y;
 | 
						|
 | 
						|
	switch (pGC->fillStyle)
 | 
						|
	{
 | 
						|
	case FillTiled:
 | 
						|
	    /* copy current tile and stipple */
 | 
						|
	    if (!pGC->tileIsPixel && (pGC->tile.pixmap->drawable.width <= PPW) &&
 | 
						|
		!(pGC->tile.pixmap->drawable.width & (pGC->tile.pixmap->drawable.width - 1)))
 | 
						|
	    {
 | 
						|
		mfbCopyRotatePixmap(pGC->tile.pixmap,
 | 
						|
				    &pGC->pRotatedPixmap, xrot, yrot);
 | 
						|
		new_pix = TRUE;
 | 
						|
	    }
 | 
						|
	    break;
 | 
						|
	case FillStippled:
 | 
						|
	case FillOpaqueStippled:
 | 
						|
	    if (pGC->stipple && (pGC->stipple->drawable.width <= PPW) &&
 | 
						|
	    	!(pGC->stipple->drawable.width & (pGC->stipple->drawable.width - 1)))
 | 
						|
	    {
 | 
						|
		mfbCopyRotatePixmap(pGC->stipple,
 | 
						|
				    &pGC->pRotatedPixmap, xrot, yrot);
 | 
						|
		new_pix = TRUE;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	/* destroy any previously rotated tile or stipple */
 | 
						|
	if (!new_pix && pGC->pRotatedPixmap)
 | 
						|
	{
 | 
						|
	    (*pDrawable->pScreen->DestroyPixmap)(pGC->pRotatedPixmap);
 | 
						|
	    pGC->pRotatedPixmap = (PixmapPtr)NULL;
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    /*
 | 
						|
     * duck out here when the GC is unchanged
 | 
						|
     */
 | 
						|
 | 
						|
    if (!changes)
 | 
						|
	return;
 | 
						|
 | 
						|
    if (new_rrop || new_fill)
 | 
						|
    {
 | 
						|
	rrop = mfbReduceRop(pGC->alu, pGC->fgPixel);
 | 
						|
	devPriv->rop = rrop;
 | 
						|
	new_fill = TRUE;
 | 
						|
	/* FillArea raster op is GC's for tile filling,
 | 
						|
	   and the reduced rop for solid and stipple
 | 
						|
	*/
 | 
						|
	if (pGC->fillStyle == FillTiled)
 | 
						|
	    devPriv->ropFillArea = pGC->alu;
 | 
						|
	else
 | 
						|
	    devPriv->ropFillArea = rrop;
 | 
						|
 | 
						|
	/* opaque stipples:
 | 
						|
	   fg	bg	ropOpStip	fill style
 | 
						|
	   1	0	alu		tile
 | 
						|
	   0	1	inverseAlu	tile
 | 
						|
	   1	1	rrop(fg, alu)	solid
 | 
						|
	   0	0	rrop(fg, alu)	solid
 | 
						|
	Note that rrop(fg, alu) == mfbPrivGC.rop, so we don't really need to
 | 
						|
	compute it.
 | 
						|
	*/
 | 
						|
        if (pGC->fillStyle == FillOpaqueStippled)
 | 
						|
        {
 | 
						|
	    if ((pGC->fgPixel & 1) != (pGC->bgPixel & 1))
 | 
						|
	    {
 | 
						|
	        if (pGC->fgPixel & 1)
 | 
						|
		    devPriv->ropOpStip = pGC->alu;
 | 
						|
	        else
 | 
						|
		    devPriv->ropOpStip = InverseAlu[pGC->alu];
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	        devPriv->ropOpStip = rrop;
 | 
						|
	    devPriv->ropFillArea = devPriv->ropOpStip;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
	rrop = devPriv->rop;
 | 
						|
 | 
						|
    if (new_line || new_fill || new_text)
 | 
						|
    {
 | 
						|
	GCOps	*newops;
 | 
						|
 | 
						|
	if ((newops = matchCommon (pGC)))
 | 
						|
 	{
 | 
						|
	    if (pGC->ops->devPrivate.val)
 | 
						|
		miDestroyGCOps (pGC->ops);
 | 
						|
	    pGC->ops = newops;
 | 
						|
	    new_line = new_fill = new_text = 0;
 | 
						|
	}
 | 
						|
 	else
 | 
						|
 	{
 | 
						|
	    if (!pGC->ops->devPrivate.val)
 | 
						|
 	    {
 | 
						|
		pGC->ops = miCreateGCOps (pGC->ops);
 | 
						|
		pGC->ops->devPrivate.val = 1;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (new_line || new_fill)
 | 
						|
    {
 | 
						|
	if (pGC->lineWidth == 0)
 | 
						|
	{
 | 
						|
	    if ((pGC->lineStyle == LineSolid) && (pGC->fillStyle == FillSolid)
 | 
						|
		&& ((rrop == RROP_WHITE) || (rrop == RROP_BLACK)))
 | 
						|
		pGC->ops->PolyArc = mfbZeroPolyArcSS;
 | 
						|
	    else
 | 
						|
		pGC->ops->PolyArc = miZeroPolyArc;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	    pGC->ops->PolyArc = miPolyArc;
 | 
						|
	if (pGC->lineStyle == LineSolid)
 | 
						|
	{
 | 
						|
	    if(pGC->lineWidth == 0)
 | 
						|
	    {
 | 
						|
	        if (pGC->fillStyle == FillSolid)
 | 
						|
		{
 | 
						|
		    pGC->ops->PolySegment = mfbSegmentSS;
 | 
						|
		    pGC->ops->Polylines = mfbLineSS;
 | 
						|
	        }
 | 
						|
 		else
 | 
						|
		{
 | 
						|
		    pGC->ops->PolySegment = miPolySegment;
 | 
						|
		    pGC->ops->Polylines = miZeroLine;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		pGC->ops->PolySegment = miPolySegment;
 | 
						|
		pGC->ops->Polylines = miWideLine;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    if(pGC->lineWidth == 0 && pGC->fillStyle == FillSolid)
 | 
						|
	    {
 | 
						|
	        pGC->ops->Polylines = mfbLineSD;
 | 
						|
		pGC->ops->PolySegment = mfbSegmentSD;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
	        pGC->ops->Polylines = miWideDash;
 | 
						|
		pGC->ops->PolySegment = miPolySegment;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (new_text || new_fill)
 | 
						|
    {
 | 
						|
	if ((pGC->font) &&
 | 
						|
	    (FONTMAXBOUNDS(pGC->font,rightSideBearing) -
 | 
						|
	     FONTMINBOUNDS(pGC->font,leftSideBearing) > 32 ||
 | 
						|
	     FONTMINBOUNDS(pGC->font,characterWidth) < 0))
 | 
						|
	{
 | 
						|
	    pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
 | 
						|
	    pGC->ops->ImageGlyphBlt = miImageGlyphBlt;
 | 
						|
	}
 | 
						|
	else
 | 
						|
	{
 | 
						|
	    /* special case ImageGlyphBlt for terminal emulator fonts */
 | 
						|
 | 
						|
 | 
						|
	    if ((pGC->font) &&
 | 
						|
		TERMINALFONT(pGC->font) &&
 | 
						|
		((pGC->fgPixel & 1) != (pGC->bgPixel & 1)))
 | 
						|
	    {
 | 
						|
		/* pcc bug makes this not compile...
 | 
						|
		pGC->ops->ImageGlyphBlt = (pGC->fgPixel & 1) ? mfbTEGlyphBltWhite :
 | 
						|
						      mfbTEGlyphBltBlack;
 | 
						|
		*/
 | 
						|
		if (pGC->fgPixel & 1)
 | 
						|
		    pGC->ops->ImageGlyphBlt = mfbTEGlyphBltWhite;
 | 
						|
		else
 | 
						|
		    pGC->ops->ImageGlyphBlt = mfbTEGlyphBltBlack;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
 | 
						|
 | 
						|
	    {
 | 
						|
	        if (pGC->fgPixel & 1)
 | 
						|
		    pGC->ops->ImageGlyphBlt = mfbImageGlyphBltWhite;
 | 
						|
	        else
 | 
						|
		    pGC->ops->ImageGlyphBlt = mfbImageGlyphBltBlack;
 | 
						|
	    }
 | 
						|
 | 
						|
	    /* now do PolyGlyphBlt */
 | 
						|
	    if (pGC->fillStyle == FillSolid ||
 | 
						|
		(pGC->fillStyle == FillOpaqueStippled &&
 | 
						|
		 (pGC->fgPixel & 1) == (pGC->bgPixel & 1)
 | 
						|
		)
 | 
						|
	       )
 | 
						|
	    {
 | 
						|
		if (rrop == RROP_WHITE)
 | 
						|
		    pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltWhite;
 | 
						|
		else if (rrop == RROP_BLACK)
 | 
						|
		    pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltBlack;
 | 
						|
		else if (rrop == RROP_INVERT)
 | 
						|
		    pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltInvert;
 | 
						|
		else
 | 
						|
		    pGC->ops->PolyGlyphBlt = mfbPolyGlyphBltNoop;
 | 
						|
	    }
 | 
						|
	    else
 | 
						|
	    {
 | 
						|
		pGC->ops->PolyGlyphBlt = miPolyGlyphBlt;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
    }
 | 
						|
 | 
						|
    if (new_fill)
 | 
						|
 | 
						|
 | 
						|
    {
 | 
						|
	/* install a suitable fillspans and pushpixels */
 | 
						|
	pGC->ops->PushPixels = mfbPushPixels;
 | 
						|
	pGC->ops->FillPolygon = miFillPolygon;
 | 
						|
	if ((pGC->fillStyle == FillSolid) ||
 | 
						|
	    ((pGC->fillStyle == FillOpaqueStippled) &&
 | 
						|
	     ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))))
 | 
						|
	{
 | 
						|
	    pGC->ops->PushPixels = mfbSolidPP;
 | 
						|
	    switch(devPriv->rop)
 | 
						|
	    {
 | 
						|
	      case RROP_WHITE:
 | 
						|
		pGC->ops->FillSpans = mfbWhiteSolidFS;
 | 
						|
		pGC->ops->FillPolygon = mfbFillPolyWhite;
 | 
						|
		break;
 | 
						|
	      case RROP_BLACK:
 | 
						|
		pGC->ops->FillSpans = mfbBlackSolidFS;
 | 
						|
		pGC->ops->FillPolygon = mfbFillPolyBlack;
 | 
						|
		break;
 | 
						|
	      case RROP_INVERT:
 | 
						|
		pGC->ops->FillSpans = mfbInvertSolidFS;
 | 
						|
		pGC->ops->FillPolygon = mfbFillPolyInvert;
 | 
						|
		break;
 | 
						|
	      case RROP_NOP:
 | 
						|
		pGC->ops->FillSpans = mfbNoopFS;
 | 
						|
		pGC->ops->FillPolygon = mfbFillPolyNoop;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	/* beyond this point, opaqueStippled ==> fg != bg */
 | 
						|
	else if (((pGC->fillStyle == FillTiled) ||
 | 
						|
		  (pGC->fillStyle == FillOpaqueStippled)) &&
 | 
						|
		 !pGC->pRotatedPixmap)
 | 
						|
	{
 | 
						|
	    pGC->ops->FillSpans = mfbUnnaturalTileFS;
 | 
						|
	}
 | 
						|
	else if ((pGC->fillStyle == FillStippled) && !pGC->pRotatedPixmap)
 | 
						|
	{
 | 
						|
	    pGC->ops->FillSpans = mfbUnnaturalStippleFS;
 | 
						|
	}
 | 
						|
	else if (pGC->fillStyle == FillStippled)
 | 
						|
	{
 | 
						|
	    switch(devPriv->rop)
 | 
						|
	    {
 | 
						|
	      case RROP_WHITE:
 | 
						|
		pGC->ops->FillSpans = mfbWhiteStippleFS;
 | 
						|
		break;
 | 
						|
	      case RROP_BLACK:
 | 
						|
		pGC->ops->FillSpans = mfbBlackStippleFS;
 | 
						|
		break;
 | 
						|
	      case RROP_INVERT:
 | 
						|
		pGC->ops->FillSpans = mfbInvertStippleFS;
 | 
						|
		break;
 | 
						|
	      case RROP_NOP:
 | 
						|
		pGC->ops->FillSpans = mfbNoopFS;
 | 
						|
		break;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
	else /* overload tiles to do parti-colored opaque stipples */
 | 
						|
	{
 | 
						|
	    pGC->ops->FillSpans = mfbTileFS;
 | 
						|
	}
 | 
						|
	if (pGC->fillStyle == FillSolid)
 | 
						|
	    pGC->ops->PolyFillArc = mfbPolyFillArcSolid;
 | 
						|
	else
 | 
						|
	    pGC->ops->PolyFillArc = miPolyFillArc;
 | 
						|
	/* the rectangle code doesn't deal with opaque stipples that
 | 
						|
	   are two colors -- we can fool it for fg==bg, though
 | 
						|
	 */
 | 
						|
	if ((((pGC->fillStyle == FillTiled) ||
 | 
						|
	      (pGC->fillStyle == FillStippled)) &&
 | 
						|
	     !pGC->pRotatedPixmap) ||
 | 
						|
	    ((pGC->fillStyle == FillOpaqueStippled) &&
 | 
						|
	     ((pGC->fgPixel & 1) != (pGC->bgPixel & 1)))
 | 
						|
	   )
 | 
						|
	{
 | 
						|
	    pGC->ops->PolyFillRect = miPolyFillRect;
 | 
						|
	}
 | 
						|
	else /* deal with solids and natural stipples and tiles */
 | 
						|
	{
 | 
						|
	    pGC->ops->PolyFillRect = mfbPolyFillRect;
 | 
						|
 | 
						|
	    if ((pGC->fillStyle == FillSolid) ||
 | 
						|
		((pGC->fillStyle == FillOpaqueStippled) &&
 | 
						|
		 ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))))
 | 
						|
	    {
 | 
						|
		switch(devPriv->rop)
 | 
						|
		{
 | 
						|
		  case RROP_WHITE:
 | 
						|
		    devPriv->FillArea = mfbSolidWhiteArea;
 | 
						|
		    break;
 | 
						|
		  case RROP_BLACK:
 | 
						|
		    devPriv->FillArea = mfbSolidBlackArea;
 | 
						|
		    break;
 | 
						|
		  case RROP_INVERT:
 | 
						|
		    devPriv->FillArea = mfbSolidInvertArea;
 | 
						|
		    break;
 | 
						|
		  case RROP_NOP:
 | 
						|
		    devPriv->FillArea = (mfbFillAreaProcPtr)NoopDDA;
 | 
						|
		    break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else if (pGC->fillStyle == FillStippled)
 | 
						|
	    {
 | 
						|
		switch(devPriv->rop)
 | 
						|
		{
 | 
						|
		  case RROP_WHITE:
 | 
						|
		    devPriv->FillArea = mfbStippleWhiteArea;
 | 
						|
		    break;
 | 
						|
		  case RROP_BLACK:
 | 
						|
		    devPriv->FillArea = mfbStippleBlackArea;
 | 
						|
		    break;
 | 
						|
		  case RROP_INVERT:
 | 
						|
		    devPriv->FillArea = mfbStippleInvertArea;
 | 
						|
		    break;
 | 
						|
		  case RROP_NOP:
 | 
						|
		    devPriv->FillArea = (mfbFillAreaProcPtr)NoopDDA;
 | 
						|
		    break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	    else /* deal with tiles */
 | 
						|
	    {
 | 
						|
		switch (pGC->alu)
 | 
						|
		{
 | 
						|
		  case GXcopy:
 | 
						|
		    devPriv->FillArea = mfbTileAreaPPWCopy;
 | 
						|
		    break;
 | 
						|
		  default:
 | 
						|
		    devPriv->FillArea = mfbTileAreaPPWGeneral;
 | 
						|
		    break;
 | 
						|
		}
 | 
						|
	    }
 | 
						|
	} /* end of natural rectangles */
 | 
						|
    } /* end of new_fill */
 | 
						|
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/* table to map alu(src, dst) to alu(~src, dst) */
 | 
						|
int InverseAlu[16] = {
 | 
						|
	GXclear,
 | 
						|
	GXandInverted,
 | 
						|
	GXnor,
 | 
						|
	GXcopyInverted,
 | 
						|
	GXand,
 | 
						|
	GXnoop,
 | 
						|
	GXequiv,
 | 
						|
	GXorInverted,
 | 
						|
	GXandReverse,
 | 
						|
	GXxor,
 | 
						|
	GXinvert,
 | 
						|
	GXnand,
 | 
						|
	GXcopy,
 | 
						|
	GXor,
 | 
						|
	GXorReverse,
 | 
						|
	GXset
 | 
						|
};
 | 
						|
 | 
						|
int mfbGetInverseAlu(i)
 | 
						|
    int i;
 | 
						|
{
 | 
						|
    return InverseAlu[i];
 | 
						|
}
 | 
						|
 | 
						|
int
 | 
						|
mfbReduceRop(alu, src)
 | 
						|
    register int alu;
 | 
						|
    register Pixel src;
 | 
						|
{
 | 
						|
    int rop = 0;
 | 
						|
    if ((src & 1) == 0)	/* src is black */
 | 
						|
    {
 | 
						|
	switch(alu)
 | 
						|
	{
 | 
						|
	  case GXclear:
 | 
						|
	    rop = RROP_BLACK;
 | 
						|
	    break;
 | 
						|
	  case GXand:
 | 
						|
	    rop = RROP_BLACK;
 | 
						|
	    break;
 | 
						|
	  case GXandReverse:
 | 
						|
	    rop = RROP_BLACK;
 | 
						|
	    break;
 | 
						|
	  case GXcopy:
 | 
						|
	    rop = RROP_BLACK;
 | 
						|
	    break;
 | 
						|
	  case GXandInverted:
 | 
						|
	    rop = RROP_NOP;
 | 
						|
	    break;
 | 
						|
	  case GXnoop:
 | 
						|
	    rop = RROP_NOP;
 | 
						|
	    break;
 | 
						|
	  case GXxor:
 | 
						|
	    rop = RROP_NOP;
 | 
						|
	    break;
 | 
						|
	  case GXor:
 | 
						|
	    rop = RROP_NOP;
 | 
						|
	    break;
 | 
						|
	  case GXnor:
 | 
						|
	    rop = RROP_INVERT;
 | 
						|
	    break;
 | 
						|
	  case GXequiv:
 | 
						|
	    rop = RROP_INVERT;
 | 
						|
	    break;
 | 
						|
	  case GXinvert:
 | 
						|
	    rop = RROP_INVERT;
 | 
						|
	    break;
 | 
						|
	  case GXorReverse:
 | 
						|
	    rop = RROP_INVERT;
 | 
						|
	    break;
 | 
						|
	  case GXcopyInverted:
 | 
						|
	    rop = RROP_WHITE;
 | 
						|
	    break;
 | 
						|
	  case GXorInverted:
 | 
						|
	    rop = RROP_WHITE;
 | 
						|
	    break;
 | 
						|
	  case GXnand:
 | 
						|
	    rop = RROP_WHITE;
 | 
						|
	    break;
 | 
						|
	  case GXset:
 | 
						|
	    rop = RROP_WHITE;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    else /* src is white */
 | 
						|
    {
 | 
						|
	switch(alu)
 | 
						|
	{
 | 
						|
	  case GXclear:
 | 
						|
	    rop = RROP_BLACK;
 | 
						|
	    break;
 | 
						|
	  case GXand:
 | 
						|
	    rop = RROP_NOP;
 | 
						|
	    break;
 | 
						|
	  case GXandReverse:
 | 
						|
	    rop = RROP_INVERT;
 | 
						|
	    break;
 | 
						|
	  case GXcopy:
 | 
						|
	    rop = RROP_WHITE;
 | 
						|
	    break;
 | 
						|
	  case GXandInverted:
 | 
						|
	    rop = RROP_BLACK;
 | 
						|
	    break;
 | 
						|
	  case GXnoop:
 | 
						|
	    rop = RROP_NOP;
 | 
						|
	    break;
 | 
						|
	  case GXxor:
 | 
						|
	    rop = RROP_INVERT;
 | 
						|
	    break;
 | 
						|
	  case GXor:
 | 
						|
	    rop = RROP_WHITE;
 | 
						|
	    break;
 | 
						|
	  case GXnor:
 | 
						|
	    rop = RROP_BLACK;
 | 
						|
	    break;
 | 
						|
	  case GXequiv:
 | 
						|
	    rop = RROP_NOP;
 | 
						|
	    break;
 | 
						|
	  case GXinvert:
 | 
						|
	    rop = RROP_INVERT;
 | 
						|
	    break;
 | 
						|
	  case GXorReverse:
 | 
						|
	    rop = RROP_WHITE;
 | 
						|
	    break;
 | 
						|
	  case GXcopyInverted:
 | 
						|
	    rop = RROP_BLACK;
 | 
						|
	    break;
 | 
						|
	  case GXorInverted:
 | 
						|
	    rop = RROP_NOP;
 | 
						|
	    break;
 | 
						|
	  case GXnand:
 | 
						|
	    rop = RROP_INVERT;
 | 
						|
	    break;
 | 
						|
	  case GXset:
 | 
						|
	    rop = RROP_WHITE;
 | 
						|
	    break;
 | 
						|
	}
 | 
						|
    }
 | 
						|
    return rop;
 | 
						|
}
 |