Logo Search packages:      
Sourcecode: xorg-server version File versions  Download package

fbpseudocolor.c

#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

#include <X11/X.h>
#include <X11/Xproto.h>
#include "scrnintstr.h"
#include "colormapst.h"
#include "glyphstr.h"
#include "resource.h"
#include <X11/fonts/font.h>
#include "dixfontstr.h"
#include <X11/fonts/fontstruct.h>
#include "micmap.h"
#include "fb.h"
#include "fbpseudocolor.h"

static Bool xxCreateGC(GCPtr pGC);
static void xxValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw);
static void xxDestroyGC(GCPtr pGC);
static void xxChangeGC (GCPtr pGC, unsigned long   mask);
static void xxCopyGC (GCPtr pGCSrc, unsigned long   mask, GCPtr pGCDst);
static void xxChangeClip (GCPtr pGC, int type, pointer pvalue, int nrects);

static void xxCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
static void xxDestroyClip(GCPtr pGC);
static void xxFillSpans(DrawablePtr pDraw, GC *pGC, int nInit,
                  DDXPointPtr pptInit, int *pwidthInit, int fSorted);
static void xxSetSpans(DrawablePtr pDraw, GCPtr pGC, char *pcharsrc,
                   DDXPointPtr pptInit, int     *pwidthInit, int nspans,
                   int fSorted);
static void xxPutImage(DrawablePtr pDraw, GCPtr pGC, int depth, int x, int y,
                   int w, int h,int leftPad, int format, char *pImage);
static RegionPtr xxCopyPlane(DrawablePtr pSrc,
                       DrawablePtr pDst, GCPtr pGC,int srcx, int srcy,
                       int width, int height, int     dstx, int dsty,
                       unsigned long bitPlane);
static void xxPolyPoint(DrawablePtr pDraw, GCPtr pGC, int mode, int npt,
                  xPoint *pptInit);
static void xxPolylines(DrawablePtr pDraw, GCPtr pGC, int mode,
                  int npt, DDXPointPtr pptInit);
static void xxPolySegment(DrawablePtr pDraw, GCPtr pGC, int nseg,
                    xSegment *pSeg);
static void xxPolyRectangle(DrawablePtr  pDraw, GCPtr pGC, int nRects,
                      xRectangle  *pRects);
static void xxPolyArc( DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs);
static void xxFillPolygon(DrawablePtr pDraw, GCPtr pGC, int shape,
                    int mode, int count, DDXPointPtr pptInit);
static void xxPolyFillRect(DrawablePtr pDraw, GCPtr pGC, int nRectsInit, 
                     xRectangle *pRectsInit);
static RegionPtr xxCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GC *pGC,
                      int srcx, int srcy, int width, int height,
                      int dstx, int dsty);
static void xxPolyFillArc(DrawablePtr pDraw, GCPtr pGC, int narcs,
                    xArc *parcs);
static int xxPolyText8(DrawablePtr pDraw, GCPtr pGC, int x, int   y, int count,
                   char *chars);
static int xxPolyText16(DrawablePtr pDraw, GCPtr pGC, int x, int y,
                  int count, unsigned short *chars);
static void xxImageText8(DrawablePtr pDraw, GCPtr pGC, int x, 
                   int y, int count, char *chars);
static void xxImageText16(DrawablePtr pDraw, GCPtr pGC, int x, int y,
                    int count, unsigned short *chars);
static void xxImageGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int x, int y,
                      unsigned int nglyph, CharInfoPtr *ppci,
                      pointer pglyphBase);
static void xxPolyGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int x, int y,
                     unsigned int nglyph, CharInfoPtr *ppci,
                     pointer pglyphBase);
static void xxPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDraw,
                   int  dx, int dy, int xOrg, int yOrg);
static void
xxComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
           INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
           INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
static void
xxGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
        PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
        GlyphListPtr list, GlyphPtr *glyphs);


typedef struct _xxCmapPrivRec {
    CARD32* cmap;
    ColormapPtr pmap;
    Bool dirty;
    struct _xxCmapPrivRec *next;
} xxCmapPrivRec, *xxCmapPrivPtr;


typedef struct {
    CloseScreenProcPtr        CloseScreen;
    CreateScreenResourcesProcPtr CreateScreenResources;
    CreateWindowProcPtr       CreateWindow;
    CopyWindowProcPtr         CopyWindow;
    PaintWindowProcPtr        PaintWindowBackground;
    PaintWindowProcPtr        PaintWindowBorder;
    WindowExposuresProcPtr    WindowExposures;
    CreateGCProcPtr           CreateGC;
    CreateColormapProcPtr     CreateColormap;
    DestroyColormapProcPtr    DestroyColormap;
    InstallColormapProcPtr    InstallColormap;
    UninstallColormapProcPtr  UninstallColormap;
    ListInstalledColormapsProcPtr ListInstalledColormaps;
    StoreColorsProcPtr        StoreColors;
#ifdef RENDER
    CompositeProcPtr          Composite;
    GlyphsProcPtr       Glyphs;
#endif    
    PixmapPtr                 pPixmap;
    char *              addr;
    pointer             pBits;
    RegionRec                 region;
    VisualPtr                 bVisual;
    RegionRec                 bRegion;
    int                       myDepth;
    int                       depth;
    ColormapPtr               baseCmap;
    ColormapPtr*        InstalledCmaps;
    xxCmapPrivPtr       Cmaps;
    int                       numInstalledColormaps;
    int                       colormapDirty;
    xxSyncFunc                sync;
} xxScrPrivRec, *xxScrPrivPtr;

#define xxGetScrPriv(s) ((xxScrPrivPtr) \
                         (xxScrPrivateIndex != -1) \
                          ? (s)->devPrivates[xxScrPrivateIndex].ptr\
                        : NULL)
#define xxScrPriv(s)     xxScrPrivPtr pScrPriv = xxGetScrPriv(s)

#define xxGetCmapPriv(s) ((xxCmapPrivPtr) \
                          (s)->devPrivates[xxColormapPrivateIndex].ptr)
#define xxCmapPriv(s)    xxCmapPrivPtr pCmapPriv = xxGetCmapPriv(s);

typedef struct _xxGCPriv {
    GCOps   *ops;
    GCFuncs *funcs;
} xxGCPrivRec, *xxGCPrivPtr;

#define xxGetGCPriv(pGC) ((xxGCPrivPtr) \
                              (pGC)->devPrivates[xxGCPrivateIndex].ptr)
#define xxGCPriv(pGC)   xxGCPrivPtr  pGCPriv = xxGetGCPriv(pGC)

int xxScrPrivateIndex = -1;
int xxGCPrivateIndex;
int xxColormapPrivateIndex = -1;
int xxGeneration;


#define wrap(priv,real,mem,func) {\
    priv->mem = real->mem; \
    real->mem = func; \
}

#define unwrap(priv,real,mem) {\
    real->mem = priv->mem; \
}

#define MARK_DIRTY (1 << 31)

#define MAX_NUM_XX_INSTALLED_CMAPS 255
/* #define DEBUG  */
#ifdef DEBUG
# define DBG ErrorF
# define DBG_ARGS(x) ErrorF x
# define PRINT_RECTS(rec) {\
       int i;\
       BoxPtr box;\
       ErrorF("RECTS: %i\n",REGION_NUM_RECTS(&rec));\
       if (REGION_NUM_RECTS(&rec) > 1)  { \
          for (i = 0; i < REGION_NUM_RECTS(&rec); i++ ) {\
             box = REGION_BOX(&rec,i);\
           ErrorF("x1: %hi x2: %hi y1: %hi y2: %hi\n", \
             box->x1,box->x2,box->y1,box->y2);\
          }\
       } else { \
             box = &(rec.extents); \
           ErrorF("x1: %hi x2: %hi y1: %hi y2: %hi\n", \
             box->x1,box->x2,box->y1,box->y2);\
       } \
}
#else
# define DBG(x)
# define DBG_ARGS(x)
# define PRINT_RECTS(rec)
#endif

#if 0
static void xxCopyPseudocolorRegion(ScreenPtr pScreen, RegionPtr pReg,
                            xxCmapPrivPtr pCmapPriv);
static void xxUpdateFb(ScreenPtr pScreen);


static void
xxUpdateWindowImmediately(WindowPtr pWin)
{
    xxScrPriv(pWin->drawable.pScreen);
    xxCmapPrivPtr pCmapPriv;
    ColormapPtr pmap;
          
    pmap = (ColormapPtr)LookupIDByType(wColormap(pWin),RT_COLORMAP);
    
    if (pmap && (pCmapPriv = xxGetCmapPriv(pmap)) != (pointer)-1) {
      xxCopyPseudocolorRegion(pWin->drawable.pScreen,
                        &pScrPriv->region, pCmapPriv);
    }
}
#else
# define xxUpdateWindowImmediately(x)
#endif

static ColormapPtr
xxGetBaseColormap(ScreenPtr pScreen)
{
    xxScrPriv(pScreen);
    DepthPtr pDepth = pScreen->allowedDepths;
    int i,j,k;
    ColormapPtr pDefMap
      =  (ColormapPtr) LookupIDByType(pScreen->defColormap,RT_COLORMAP);
    ColormapPtr cmap = NULL;
    VisualPtr pVisual = NULL;
      
    for (i = 0; i < pScreen->numDepths; i++, pDepth++)
      if (pDepth->depth == pScrPriv->depth) {
          for (j = 0; j < pDepth->numVids; j++) {
            if (pDefMap->pVisual->vid == pDepth->vids[j]
                && pDefMap->pVisual->class == TrueColor) {
                cmap = pDefMap;
                break;
            }
            if (!pVisual) {
                for (k = 0; k < pScreen->numVisuals; k++) {
                  if (pScreen->visuals[k].class == TrueColor
                      && pScreen->visuals[k].vid
                      == pDepth->vids[j]) {
                      pVisual = &pScreen->visuals[k];
                      break;
                  }
                }
            }
          }
          if (cmap)
            break;
      }
          
    if (!cmap) {
      CreateColormap(FakeClientID(0),pScreen,pVisual,&cmap,AllocNone,0);
    }
    
    return cmap;
}

static Bool
xxCreateScreenResources(ScreenPtr pScreen)
{
    PixmapPtr           pPix;
    xxScrPriv(pScreen);
    Bool          ret;
    PixmapPtr           pPixmap;
    BoxRec        box;
    int                 depth = pScrPriv->myDepth;
    pointer       pBits;
    
    unwrap (pScrPriv,pScreen, CreateScreenResources);
    ret = pScreen->CreateScreenResources(pScreen);
    wrap(pScrPriv,pScreen,CreateScreenResources,xxCreateScreenResources);

    if (!ret) return FALSE;
    
    pScrPriv->pBits = NULL;
    if (pScrPriv->addr)
      pBits = pScrPriv->addr;
    else
      pBits = xalloc(pScreen->width * pScreen->height
                   * (BitsPerPixel(depth) >> 3));
    if (!pBits) return FALSE;
    
    pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth);
    if (!pPixmap) {
      xfree(pBits);
      return FALSE;
    }
    if (!(*pScreen->ModifyPixmapHeader)(pPixmap, pScreen->width,
                              pScreen->height, depth,
                              BitsPerPixel(depth),
                              PixmapBytePad(pScreen->width, depth),
                              pBits)) {
      xfree(pBits);
      return FALSE;
    }
    if (pScreen->rootDepth == pScrPriv->myDepth) {
      pPix = (PixmapPtr)pScreen->devPrivate;    
      if (!(*pScreen->ModifyPixmapHeader)(pPix, 0,0, pScrPriv->depth,
                                  BitsPerPixel(pScrPriv->depth),
                                  PixmapBytePad(pScreen->width,
                                            pScrPriv->depth),
                                  0)) {
          xfree(pBits);
          return FALSE;
      }
    }

    pScrPriv->baseCmap = xxGetBaseColormap(pScreen);
    
    pScrPriv->pBits = pBits;
    pScrPriv->pPixmap = pPixmap;
    box.x1 = 0;
    box.y1 = 0;
    box.x2 = pScreen->width;
    box.y2 = pScreen->height;
    REGION_NULL(pScreen, &pScrPriv->region);
    REGION_INIT(pScreen, &pScrPriv->bRegion, &box, 0);
    
    return TRUE;
}

static Bool
xxCloseScreen (int iScreen, ScreenPtr pScreen)
{
    xxScrPriv(pScreen);
    Bool          ret;

    (*pScreen->DestroyPixmap)(pScrPriv->pPixmap);
    /* We don't need to free the baseColormap as FreeClientResourcess
       will have taken care of it. */
    REGION_UNINIT (pScreen, &pScrPriv->region);
    
    unwrap (pScrPriv,pScreen, CloseScreen);
    ret = pScreen->CloseScreen(iScreen,pScreen);

    xfree(pScrPriv->pBits);
    xfree(pScrPriv->InstalledCmaps);
    xfree(pScrPriv);
    
    return TRUE;
}

static Bool
xxMyVisual(ScreenPtr pScreen, VisualID vid)
{
    xxScrPriv(pScreen);
    DepthPtr pDepth = pScreen->allowedDepths;
    int i,j;
    
    for (i = 0; i < pScreen->numDepths; i++, pDepth++)
      if (pDepth->depth == pScrPriv->myDepth) {
          for (j = 0; j < pDepth->numVids; j++) {
            if (vid == pDepth->vids[j]) {
                return TRUE;
            }
          }
      }
    return FALSE;
}

static Bool
xxInitColormapDummy(ColormapPtr pmap, int index)
{
    return TRUE;
}

static Bool
xxInitColormapPrivate(ColormapPtr pmap)
{
    xxScrPriv(pmap->pScreen);
    xxCmapPrivPtr pCmapPriv;
    pointer       cmap;

    pmap->devPrivates[xxColormapPrivateIndex].ptr = (pointer) -1;
    
    if (xxMyVisual(pmap->pScreen,pmap->pVisual->vid)) {
      DBG("CreateColormap\n");
      pCmapPriv = (xxCmapPrivPtr) xalloc (sizeof (xxCmapPrivRec));
      if (!pCmapPriv)
          return FALSE;
      pmap->devPrivates[xxColormapPrivateIndex].ptr = (pointer) pCmapPriv;
      cmap = xalloc(sizeof (CARD32) * (1 << pScrPriv->myDepth));
      if (!cmap)
      return FALSE;

      memset(cmap,0,sizeof (CARD32) * (1 << pScrPriv->myDepth));
      
      pCmapPriv->cmap = cmap;
      pCmapPriv->dirty = FALSE;
      pCmapPriv->pmap = pmap;
      pCmapPriv->next = pScrPriv->Cmaps;
      pScrPriv->Cmaps = pCmapPriv;
    }
    return TRUE;
}


static Bool
xxCreateColormap(ColormapPtr pmap)
{
    xxScrPriv(pmap->pScreen);
    Bool          ret;
    
    if (!xxInitColormapPrivate(pmap)) return FALSE;
    
    unwrap(pScrPriv,pmap->pScreen, CreateColormap);
    ret = pmap->pScreen->CreateColormap(pmap);
    wrap(pScrPriv,pmap->pScreen,CreateColormap,xxCreateColormap);
    
    return ret;
}

static int
xxCmapInstalled(ColormapPtr pmap)
{
    xxScrPriv(pmap->pScreen);
    int i;
    
    for (i = 0; i < pScrPriv->numInstalledColormaps; i++)
      if (pScrPriv->InstalledCmaps[i] == pmap)
          break;
      if (i == pScrPriv->numInstalledColormaps) /* not installed */
          return -1;
      return i;
}

static void
xxInstalledCmapDelete(ScreenPtr pScreen, int num)
{
    xxScrPriv(pScreen);
    int i;

    pScrPriv->numInstalledColormaps--;
    
    for (i = num; i < pScrPriv->numInstalledColormaps; i++)
      pScrPriv->InstalledCmaps[i] = pScrPriv->InstalledCmaps[i+1];
}

static void
xxDestroyColormap(ColormapPtr pmap)
{
    xxScrPriv(pmap->pScreen);
    xxCmapPriv(pmap);

    if (pCmapPriv != (pointer) -1) {
      xxCmapPrivPtr tmpCmapPriv = pScrPriv->Cmaps;
      xxCmapPrivPtr *prevCmapPriv = &pScrPriv->Cmaps;
      int n;
      
      DBG("DestroyColormap\n");

      if ((n = xxCmapInstalled(pmap)) != -1)
          xxInstalledCmapDelete(pmap->pScreen,n);

      while (tmpCmapPriv) {
          if (tmpCmapPriv->pmap == pmap) {
            *prevCmapPriv = tmpCmapPriv->next;
            break;
          }
          prevCmapPriv = &tmpCmapPriv->next;
          tmpCmapPriv = tmpCmapPriv->next;
      }
      
      xfree(pCmapPriv->cmap);
      xfree(pCmapPriv);
    }

    unwrap(pScrPriv,pmap->pScreen, DestroyColormap);
    pmap->pScreen->DestroyColormap(pmap);
    wrap(pScrPriv,pmap->pScreen,DestroyColormap,xxDestroyColormap);
}

#define Shift(v,d)  ((d) < 0 ? ((v) >> (-d)) : ((v) << (d)))

static int
xxComputeCmapShift (unsigned long mask)
{
    int     shift;
    unsigned long   bit;
    
    shift = 16;
    bit = 0x80000000;
    while (!(mask & bit))
    {
      shift--;
      bit >>= 1;
    }
    return shift;
}

static void
xxStoreColors(ColormapPtr pmap, int nColors, xColorItem *pColors)
{
    xxScrPriv(pmap->pScreen);
    xxCmapPriv(pmap);

    if (pCmapPriv != (pointer) -1) {

      xColorItem  *expanddefs;
      int         i;
      VisualPtr   bVisual;
      int         rs, gs, bs;

      if (nColors == 0) return;

      DBG("StoreColors\n");
      
      expanddefs = ALLOCATE_LOCAL(sizeof(xColorItem)
                            * (1 <<  pScrPriv->myDepth));
      if (!expanddefs) return;
      
      bVisual = pScrPriv->bVisual;

      DBG("StoreColors\n");

      rs = xxComputeCmapShift(bVisual->redMask);
      gs = xxComputeCmapShift(bVisual->greenMask);
      bs = xxComputeCmapShift(bVisual->blueMask);
      
      if ((pmap->pVisual->class | DynamicClass) == DirectColor) {
          nColors = miExpandDirectColors(pmap, nColors, pColors, expanddefs);
          pColors = expanddefs;
      }

      for (i = 0; i < nColors; i++) {
          DBG_ARGS(("index: %i r 0x%x g 0x%x b 0x%x\n", pColors->pixel,
               pColors->red, pColors->green, pColors->blue));
          pCmapPriv->cmap[pColors->pixel] = MARK_DIRTY
            | (Shift(pColors->red, rs) & bVisual->redMask)
            | (Shift(pColors->green, gs) & bVisual->greenMask)
            | (Shift(pColors->blue, bs)  & bVisual->blueMask);
          pColors++;
      }

      DEALLOCATE_LOCAL(expanddefs);

      pCmapPriv->dirty = TRUE;
      pScrPriv->colormapDirty = TRUE;
      
      return;
    }
    
    unwrap(pScrPriv,pmap->pScreen, StoreColors);
    pmap->pScreen->StoreColors(pmap,nColors,pColors);
    wrap(pScrPriv,pmap->pScreen,StoreColors,xxStoreColors);
}

static void
xxInstallColormap(ColormapPtr pmap)
{
    int i;
    xxScrPriv(pmap->pScreen);
    xxCmapPriv(pmap);
    
    if (pCmapPriv != (pointer) -1) {
      Pixel       *pixels;
      xrgb        *colors;
      int         i;
      VisualPtr   pVisual;
      xColorItem  *defs;

      DBG("InstallColormap\n");

      if (xxCmapInstalled(pmap) != -1)
          return;

      if (!pScrPriv->numInstalledColormaps) {
          unwrap(pScrPriv,pmap->pScreen, InstallColormap);
          pmap->pScreen->InstallColormap(pScrPriv->baseCmap);
          wrap(pScrPriv,pmap->pScreen,InstallColormap,xxInstallColormap);
      }
          
      pixels = ALLOCATE_LOCAL(sizeof(Pixel) * (1 <<  pScrPriv->myDepth));
      colors = ALLOCATE_LOCAL(sizeof(xrgb) * (1 <<  pScrPriv->myDepth));
      defs = ALLOCATE_LOCAL(sizeof(xColorItem) * (1 << pScrPriv->myDepth));
      
      if (!pixels || !colors)
          return;

      /* if we have more than max installed delete the oldest */
      if (pScrPriv->numInstalledColormaps == MAX_NUM_XX_INSTALLED_CMAPS)
          xxInstalledCmapDelete(pmap->pScreen,0);
      
      pScrPriv->InstalledCmaps[pScrPriv->numInstalledColormaps] = pmap;
      pScrPriv->numInstalledColormaps++;
      
      pVisual = pScrPriv->bVisual;
      
      for (i = 0; i < (1 <<  pScrPriv->myDepth); i++)
          pixels[i] = i;
      
      QueryColors (pmap, (1 << pScrPriv->myDepth), pixels, colors);

      for (i = 0; i < (1 <<  pScrPriv->myDepth); i++) {
          defs[i].pixel = pixels[i];
            defs[i].red = colors[i].red;
            defs[i].green = colors[i].green;
            defs[i].blue = colors[i].blue;
            defs[i].flags =  DoRed|DoGreen|DoBlue;
        }
      xxStoreColors(pmap,(1 <<  pScrPriv->myDepth),defs);

      DEALLOCATE_LOCAL(pixels);
      DEALLOCATE_LOCAL(colors);
      DEALLOCATE_LOCAL(defs);

      return;
    } 

    for (i = pScrPriv->numInstalledColormaps; i ; i--)
      WalkTree(pmap->pScreen, TellLostMap,
             (char *)&pScrPriv->InstalledCmaps[i-1]->mid);
    
    pScrPriv->numInstalledColormaps = 0;
     
    unwrap(pScrPriv,pmap->pScreen, InstallColormap);
    pmap->pScreen->InstallColormap(pmap);
    wrap(pScrPriv,pmap->pScreen,InstallColormap,xxInstallColormap);
}

static void
xxUninstallColormap(ColormapPtr pmap)
{
    xxScrPriv(pmap->pScreen);
    xxCmapPriv(pmap);

    if (pCmapPriv != (pointer) -1) {
      int num;
      
      if ((num = xxCmapInstalled(pmap)) == -1)
          return;
      
      DBG("UninstallColormap\n");
      xxInstalledCmapDelete(pmap->pScreen,num);

      return;
    } 
    
    unwrap(pScrPriv,pmap->pScreen, UninstallColormap);
    pmap->pScreen->UninstallColormap(pmap);
    wrap(pScrPriv,pmap->pScreen,UninstallColormap,xxUninstallColormap);
      
}

static int
xxListInstalledColormaps(ScreenPtr pScreen, Colormap *pCmapIds)
{
    int                 n,i;
    xxScrPriv(pScreen);

    unwrap(pScrPriv,pScreen, ListInstalledColormaps);
    n = pScreen->ListInstalledColormaps(pScreen, pCmapIds);
    wrap (pScrPriv,pScreen,ListInstalledColormaps,xxListInstalledColormaps);

    pCmapIds += n;

    for (i = 0; i < pScrPriv->numInstalledColormaps; i++) {
      *pCmapIds++ = pScrPriv->InstalledCmaps[i]->mid;
      n++;
    }

    return n;
}

static Bool
xxCreateWindow(WindowPtr pWin)
{
    xxScrPriv(pWin->drawable.pScreen);
    
    if (pWin->drawable.class != InputOutput
      || pScrPriv->myDepth != pWin->drawable.depth) {
      Bool ret;
      DBG("CreateWindow NoPseudo\n");
      unwrap (pScrPriv, pWin->drawable.pScreen, CreateWindow);
      ret = pWin->drawable.pScreen->CreateWindow(pWin);
      wrap(pScrPriv, pWin->drawable.pScreen, CreateWindow, xxCreateWindow);

      return ret;
    }
    
    DBG("CreateWindow\n");

    pWin->devPrivates[fbWinPrivateIndex].ptr = (pointer) pScrPriv->pPixmap;
    PRINT_RECTS(pScrPriv->region);
      if (!pWin->parent) {
      REGION_EMPTY (pWin->drawable.pScreen, &pScrPriv->region);
    }
    PRINT_RECTS(pScrPriv->region);
    
    return TRUE;
}

static void
xxWalkChildren(WindowPtr pWin, RegionPtr pReg, PixmapPtr pPixmap)
{
    
    WindowPtr           pCurWin = pWin;
    
    do {
      if (fbGetWindowPixmap(pCurWin) == pPixmap) {
          DBG("WalkWindow Add\n");
          REGION_UNION(pWin->drawable.pScreen,pReg,pReg,
                   &pCurWin->borderClip);
      } else {
          DBG("WalkWindow Sub\n");
          REGION_SUBTRACT(pWin->drawable.pScreen,pReg,pReg,
                      &pCurWin->borderClip);
      }
      if (pCurWin->lastChild)
          xxWalkChildren(pCurWin->lastChild,pReg, pPixmap);
    } while ((pCurWin = pCurWin->prevSib));
}

static void
xxPickMyWindows(WindowPtr pWin, RegionPtr pRgn)
{
    ScreenPtr           pScreen = pWin->drawable.pScreen;
    xxScrPriv(pScreen);

    if (fbGetWindowPixmap(pWin) == pScrPriv->pPixmap) {
      REGION_UNION(pWin->drawable.pScreen,pRgn,pRgn,&pWin->borderClip);
    }
    if (pWin->lastChild)
      xxWalkChildren(pWin->lastChild,pRgn,pScrPriv->pPixmap);
}

static void
xxCopyWindow(WindowPtr  pWin,
           DDXPointRec  ptOldOrg,
           RegionPtr    prgnSrc)
{
    ScreenPtr           pScreen = pWin->drawable.pScreen;
    xxScrPriv(pScreen);
    RegionRec           rgn;
    RegionRec           rgn_new;
    int                 dx, dy;
    PixmapPtr pPixmap = fbGetWindowPixmap(pWin);

    DBG("xxCopyWindow\n");

    dx = ptOldOrg.x - pWin->drawable.x;
    dy = ptOldOrg.y - pWin->drawable.y;

    REGION_NULL(pScreen, &rgn_new);
    REGION_UNION(pScreen, &rgn_new,&rgn_new,prgnSrc);
    REGION_TRANSLATE(pScreen,&rgn_new,-dx,-dy);

    REGION_NULL(pScreen, &rgn);
    xxPickMyWindows(pWin,&rgn);

    unwrap (pScrPriv, pScreen, CopyWindow);
    pWin->devPrivates[fbWinPrivateIndex].ptr = fbGetScreenPixmap(pScreen);
    pScreen->CopyWindow(pWin, ptOldOrg, prgnSrc);
    pWin->devPrivates[fbWinPrivateIndex].ptr = pPixmap;
    wrap(pScrPriv, pScreen, CopyWindow, xxCopyWindow);

    REGION_INTERSECT(pScreen,&rgn,&rgn,&rgn_new);
    if (REGION_NOTEMPTY (pScreen,&rgn)) {
      fbCopyRegion(&pScrPriv->pPixmap->drawable,&pScrPriv->pPixmap->drawable,
                 0,&rgn,dx,dy,fbCopyWindowProc,0,(void*)0);
      REGION_TRANSLATE(pScreen,&rgn,dx,dy);
      REGION_INTERSECT(pScreen,&rgn_new,&pScrPriv->region,&rgn);
      REGION_SUBTRACT(pScreen,&pScrPriv->region,&pScrPriv->region,&rgn);
      REGION_TRANSLATE(pScreen,&rgn_new,-dx,-dy);
      REGION_UNION(pScreen,&pScrPriv->region,&pScrPriv->region,&rgn_new);
    }
#if 1
    REGION_UNINIT(pScreen,&rgn_new);
    REGION_UNINIT(pScreen,&rgn);
#endif
}

static void
xxWindowExposures (WindowPtr  pWin,
                    RegionPtr prgn,
                    RegionPtr other_exposed)
{
    xxScrPriv(pWin->drawable.pScreen);

    if (fbGetWindowPixmap(pWin) == pScrPriv->pPixmap) {
      DBG("WindowExposures\n");
      PRINT_RECTS(pScrPriv->region);
      REGION_UNION(pWin->drawable.pScreen,&pScrPriv->region,
                 &pScrPriv->region,
                 prgn);
      PRINT_RECTS(pScrPriv->region);
    } else {
      DBG("WindowExposures NonPseudo\n");
      PRINT_RECTS(pScrPriv->region);
      REGION_SUBTRACT(pWin->drawable.pScreen,&pScrPriv->region,
                 &pScrPriv->region,
                 prgn);
      PRINT_RECTS(pScrPriv->region);
    }
    unwrap (pScrPriv, pWin->drawable.pScreen, WindowExposures);
    pWin->drawable.pScreen->WindowExposures(pWin, prgn, other_exposed);
    wrap(pScrPriv, pWin->drawable.pScreen, WindowExposures, xxWindowExposures);
}

static void
xxPaintWindow(WindowPtr pWin, RegionPtr pRegion, int what)
{
    xxScrPriv(pWin->drawable.pScreen);
    RegionRec           rgni;

    DBG("xxPaintWindow\n");

    REGION_NULL (pWin->drawable.pScreen, &rgni);
#if 0
    REGION_UNION (pWin->drawable.pScreen, &rgni, &rgni, &pWin->borderClip);
    REGION_INTERSECT(pWin->drawable.pScreen, &rgni, &rgni, pRegion);
#else
    REGION_UNION (pWin->drawable.pScreen, &rgni, &rgni, pRegion);
#endif
    switch (what) {
    case PW_BORDER:
      REGION_SUBTRACT (pWin->drawable.pScreen, &rgni, &rgni, &pWin->winSize);
      if (fbGetWindowPixmap(pWin) == pScrPriv->pPixmap) {
          DBG("PaintWindowBorder\n");
          REGION_UNION (pWin->drawable.pScreen, &pScrPriv->region,
                    &pScrPriv->region, &rgni);
      } else {
          DBG("PaintWindowBorder NoOverlay\n");
          REGION_SUBTRACT (pWin->drawable.pScreen, &pScrPriv->region,
                       &pScrPriv->region, &rgni);     
      }
      unwrap (pScrPriv, pWin->drawable.pScreen, PaintWindowBorder);
      pWin->drawable.pScreen->PaintWindowBorder (pWin, pRegion, what);
      wrap(pScrPriv, pWin->drawable.pScreen, PaintWindowBorder,
           xxPaintWindow);    
      break;
    case PW_BACKGROUND:
      switch (pWin->backgroundState) {
      case None:
          break;
      default:
          REGION_INTERSECT (pWin->drawable.pScreen, &rgni,
                        &rgni,&pWin->winSize);
          if (fbGetWindowPixmap(pWin) == pScrPriv->pPixmap) {
            DBG("PaintWindowBackground\n");
            REGION_UNION (pWin->drawable.pScreen, &pScrPriv->region,
                        &pScrPriv->region, &rgni);
          } else {
            DBG("PaintWindowBackground NoOverlay\n");
            REGION_SUBTRACT (pWin->drawable.pScreen, &pScrPriv->region,
                         &pScrPriv->region, &rgni);   
          }
          break;
      }
      
      unwrap (pScrPriv, pWin->drawable.pScreen, PaintWindowBackground);
      pWin->drawable.pScreen->PaintWindowBackground (pWin, pRegion, what);
      wrap(pScrPriv, pWin->drawable.pScreen, PaintWindowBackground,
           xxPaintWindow);
      break;
    }
    PRINT_RECTS(rgni);
    PRINT_RECTS(pScrPriv->region);
#if 1
    REGION_UNINIT(pWin->drawable.pScreen,&rgni);
#endif
}

static void
xxCopyPseudocolorRegion(ScreenPtr pScreen, RegionPtr pReg,
                  xxCmapPrivPtr pCmapPriv)
{
    xxScrPriv(pScreen);
    CARD32        mask = (1 << pScrPriv->myDepth) - 1;
    int                 num = REGION_NUM_RECTS(pReg);
    BoxPtr        pbox = REGION_RECTS(pReg);
    int                 width, height;
    CARD8         *src;
    CARD16        *dst, *dst_base;
    int                 dst_stride;
    register CARD32     *cmap = pCmapPriv->cmap;
    register CARD8      *s;
    register CARD16     *d;
    int w;

    dst_base = (CARD16*) ((PixmapPtr)pScreen->devPrivate)->devPrivate.ptr;
    dst_stride = (int)((PixmapPtr)pScreen->devPrivate)->devKind
      / sizeof (CARD16);

    while (num--) {
      height = pbox->y2 - pbox->y1;
      width = pbox->x2 - pbox->x1;
      
      src = (unsigned char *) pScrPriv->pBits
          + (pbox->y1 * pScreen->width) + pbox->x1;
      dst = dst_base + (pbox->y1 * dst_stride) + pbox->x1;
      while (height--) {
          w = width;
          s = src;
          d = dst;

          while(w--) {
            *(d++) = (CARD16)*(cmap + ((*(s++)) & mask));
          }
          src += pScreen->width;
          dst += dst_stride;
      }
      pbox++;
    }
}

static void
xxUpdateCmapPseudocolorRegion(ScreenPtr pScreen, RegionPtr pReg,
                  xxCmapPrivPtr pCmapPriv)
{
    xxScrPriv(pScreen);
    CARD32        mask = (1 << pScrPriv->myDepth) - 1;
    int                 num = REGION_NUM_RECTS(pReg);
    BoxPtr        pbox = REGION_RECTS(pReg);
    int                 width, height;
    CARD8         *src;
    CARD16        *dst, *dst_base;
    int                 dst_stride;
    register CARD32     val;
    register CARD32     *cmap = pCmapPriv->cmap;
    register CARD8      *s;
    register CARD16     *d;
    int w;

    dst_base = (CARD16*) ((PixmapPtr)pScreen->devPrivate)->devPrivate.ptr;
    dst_stride = (int)((PixmapPtr)pScreen->devPrivate)->devKind
      / sizeof (CARD16);

    while (num--) {

      height = pbox->y2 - pbox->y1;
      width = pbox->x2 - pbox->x1;
      
      src = (unsigned char *) pScrPriv->pBits
          + (pbox->y1 * pScreen->width) + pbox->x1;
      dst = dst_base + (pbox->y1 * dst_stride) + pbox->x1;
      while (height--) {
          w = width;
          s = src;
          d = dst;
          while(w--) {
            val = *(cmap + ((*(s++)) & mask));
                  if (val & MARK_DIRTY) {
                *d = (CARD16) val;
            }
            d++;
          }
          src += pScreen->width;
          dst += dst_stride;
      }
      pbox++;
    }
}

static void
xxGetWindowRegion(WindowPtr pWin,RegionPtr winreg)
{
    REGION_NULL(pWin->drawable.pScreen,winreg);
    /* get visible part of the border ...Argh */
    REGION_SUBTRACT(pWin->drawable.pScreen,winreg,&pWin->borderSize,
                &pWin->winSize);
    REGION_INTERSECT(pWin->drawable.pScreen,winreg,winreg,
                 &pWin->borderClip);
    /* add window interior excluding children */
    REGION_UNION(pWin->drawable.pScreen,winreg,winreg,
             &pWin->clipList);
}

static int
xxUpdateRegion(WindowPtr pWin, pointer unused)
{
    ScreenPtr pScreen = pWin->drawable.pScreen;
    xxScrPriv(pScreen);
    ColormapPtr pmap = (pointer) -1;
    RegionRec           winreg, rgni;
    
    if (pScrPriv->myDepth == pWin->drawable.depth) {
      xxCmapPrivPtr pCmapPriv = (pointer)-1;
      xxGetWindowRegion(pWin,&winreg);

      if (pScrPriv->colormapDirty) {

          pmap = (ColormapPtr)LookupIDByType(wColormap(pWin),RT_COLORMAP);
          if (!pmap)
            goto CONTINUE; /* return ? */

          pCmapPriv = xxGetCmapPriv(pmap);
          if (pCmapPriv == (pointer) -1)
            return WT_WALKCHILDREN;
          if (!pCmapPriv->dirty)
            goto CONTINUE;

          REGION_NULL (pScreen, &rgni);
          /* This will be taken care of when damaged regions are updated */
          REGION_SUBTRACT(pScreen, &rgni, &winreg, &pScrPriv->region);
          if (REGION_NOTEMPTY (pScreen,&rgni))
            xxUpdateCmapPseudocolorRegion(pScreen,&rgni, pCmapPriv);
      }
    CONTINUE:

      REGION_NULL (pScreen, &rgni);
      REGION_INTERSECT (pScreen, &rgni, &winreg, &pScrPriv->region);
      
      if (REGION_NOTEMPTY (pScreen,&rgni)) {
          if (pmap == (pointer) -1) {
            pmap =
                (ColormapPtr)LookupIDByType(wColormap(pWin),RT_COLORMAP);
            if (!pmap) /* return ? */
                pmap = (ColormapPtr)LookupIDByType(pScreen->defColormap,
                                           RT_COLORMAP);
            pCmapPriv = xxGetCmapPriv(pmap);
          }
          
          if (pCmapPriv != (pointer)-1)
            xxCopyPseudocolorRegion(pScreen,&rgni, pCmapPriv);
          REGION_SUBTRACT(pScreen, &pScrPriv->region, &pScrPriv->region,
                      &rgni);
      }
#if 1
      REGION_UNINIT(pScreen,&rgni);
      REGION_UNINIT(pScreen,&winreg);
#endif
    }
    return WT_WALKCHILDREN;
}


static void
xxUpdateFb(ScreenPtr pScreen)
{
    xxScrPriv(pScreen);

    DBG("Update FB\n");
    PRINT_RECTS(pScrPriv->region);

    if (pScrPriv->sync)
      pScrPriv->sync(pScreen); /*@!@*/
    
    WalkTree(pScreen,xxUpdateRegion,NULL);
#if 0
    if (REGION_NOTEMPTY (pScreen,&pScrPriv->region)) {
      ColormapPtr pmap = (pointer) -1;
      xxCmapPrivPtr pCmapPriv;
      
      pmap = (ColormapPtr)LookupIDByType(pScreen->defColormap,
                                 RT_COLORMAP);
      pCmapPriv = xxGetCmapPriv(pmap);
      if (pCmapPriv != (pointer)-1)
          xxCopyPseudocolorRegion(pScreen,&pScrPriv->region, pCmapPriv);
      REGION_SUBTRACT(pScreen, &pScrPriv->region, &pScrPriv->region,
                  &pScrPriv->region);
    }
#endif
    if (pScrPriv->colormapDirty) {
      xxCmapPrivPtr pCmap = pScrPriv->Cmaps;

      while (pCmap) {
          int j;

          if (pCmap->dirty) {
            for (j = 0; j < (1 <<  pScrPriv->myDepth); j++) 
                pCmap->cmap[j] &= ~MARK_DIRTY;
            pCmap->dirty = FALSE;
          }
          pCmap = pCmap->next;
      }
      pScrPriv->colormapDirty = FALSE;
    }
}

static void
xxBlockHandler (pointer data,
            OSTimePtr pTimeout,
            pointer pRead)
{
    ScreenPtr     pScreen = (ScreenPtr) data;
    xxScrPriv(pScreen);

    if (REGION_NOTEMPTY (pScreen,&pScrPriv->region) || pScrPriv->colormapDirty)
      xxUpdateFb (pScreen);
}

static void
xxWakeupHandler (pointer data, int i, pointer LastSelectMask)
{
}

Bool
xxSetup(ScreenPtr pScreen, int myDepth, int baseDepth, char* addr, xxSyncFunc sync)
{
    xxScrPrivPtr  pScrPriv;
    DepthPtr            pDepths;
    ColormapPtr         pDefMap;
    int i,j,k;
    
#ifdef RENDER
    PictureScreenPtr    ps = GetPictureScreenIfSet(pScreen);
#endif

    if (xxGeneration != serverGeneration) {
      xxScrPrivateIndex = AllocateScreenPrivateIndex ();
      if (xxScrPrivateIndex == -1)
          return FALSE;
      xxColormapPrivateIndex
          = AllocateColormapPrivateIndex (xxInitColormapDummy);
      if (xxColormapPrivateIndex == -1)
          return FALSE;
      xxGCPrivateIndex = AllocateGCPrivateIndex ();
      if (xxGCPrivateIndex == -1)
          return FALSE;
      xxGeneration = serverGeneration;
    }

    if (!AllocateGCPrivate (pScreen, xxGCPrivateIndex, sizeof (xxGCPrivRec)))
      return FALSE;

    pScrPriv = (xxScrPrivPtr) xalloc (sizeof (xxScrPrivRec));
    if (!pScrPriv)
      return FALSE;
    
    if (baseDepth)
      pScrPriv->depth = baseDepth;
    else {
      pDepths = pScreen->allowedDepths;
        for (i = 0; i < pScreen->numDepths; i++, pDepths++)
          if (pDepths->depth != myDepth)
            pScrPriv->depth = pDepths->depth;
    }
    if (!pScrPriv->depth)
      return FALSE;
    
    pDepths = pScreen->allowedDepths;
    for (i = 0; i < pScreen->numDepths; i++, pDepths++)
      if (pDepths->depth == pScrPriv->depth) {
          for (j = 0; i < pDepths->numVids; j++) {
            for (k = 0; k < pScreen->numVisuals; k++) {
                if (pScreen->visuals[k].vid
                  == pDepths[i].vids[j]
                  && pScreen->visuals[k].class == TrueColor) {
                  pScrPriv->bVisual =  &pScreen->visuals[k];
                  goto DONE;
                }
            }
          }
      }
    
 DONE:
    if (!pScrPriv->bVisual)
      return FALSE;

    pScrPriv->myDepth = myDepth;
    pScrPriv->numInstalledColormaps = 0;
    pScrPriv->colormapDirty = FALSE;
    pScrPriv->Cmaps = NULL;
    pScrPriv->sync = sync;
    
    pScreen->maxInstalledCmaps += MAX_NUM_XX_INSTALLED_CMAPS;
    pScrPriv->InstalledCmaps = xcalloc(MAX_NUM_XX_INSTALLED_CMAPS,
                               sizeof(ColormapPtr));
    if (!pScrPriv->InstalledCmaps)
      return FALSE;

    
    if (!RegisterBlockAndWakeupHandlers (xxBlockHandler,
                               xxWakeupHandler,
                               (pointer) pScreen))
      return FALSE;

    wrap (pScrPriv, pScreen, CloseScreen, xxCloseScreen);
    wrap (pScrPriv, pScreen, CreateScreenResources, xxCreateScreenResources);
    wrap (pScrPriv, pScreen, CreateWindow, xxCreateWindow);
    wrap (pScrPriv, pScreen, CopyWindow, xxCopyWindow);
    wrap (pScrPriv, pScreen, PaintWindowBorder, xxPaintWindow);
    wrap (pScrPriv, pScreen, PaintWindowBackground, xxPaintWindow);
#if 0 /* can we leave this out even with backing store enabled ? */
    wrap (pScrPriv, pScreen, WindowExposures, xxWindowExposures);
#endif
    wrap (pScrPriv, pScreen, CreateGC, xxCreateGC);
    wrap (pScrPriv, pScreen, CreateColormap, xxCreateColormap);
    wrap (pScrPriv, pScreen, DestroyColormap, xxDestroyColormap);
    wrap (pScrPriv, pScreen, InstallColormap, xxInstallColormap);
    wrap (pScrPriv, pScreen, UninstallColormap, xxUninstallColormap);
    wrap (pScrPriv, pScreen, ListInstalledColormaps, xxListInstalledColormaps);
    wrap (pScrPriv, pScreen, StoreColors, xxStoreColors);
#ifdef RENDER
    if (ps) {
      wrap (pScrPriv, ps, Glyphs, xxGlyphs);
      wrap (pScrPriv, ps, Composite, xxComposite);
    }
#endif
    pScrPriv->addr = addr;
    pScreen->devPrivates[xxScrPrivateIndex].ptr = (pointer) pScrPriv;

    pDefMap = (ColormapPtr) LookupIDByType(pScreen->defColormap, RT_COLORMAP);
    if (!xxInitColormapPrivate(pDefMap))
      return FALSE;
    
    return TRUE;
}

GCFuncs xxGCFuncs = {
    xxValidateGC, xxChangeGC, xxCopyGC, xxDestroyGC,
    xxChangeClip, xxDestroyClip, xxCopyClip
};

GCOps xxGCOps = {
    xxFillSpans, xxSetSpans, 
    xxPutImage, xxCopyArea, 
    xxCopyPlane, xxPolyPoint, 
    xxPolylines, xxPolySegment, 
    xxPolyRectangle, xxPolyArc, 
    xxFillPolygon, xxPolyFillRect, 
    xxPolyFillArc, xxPolyText8, 
    xxPolyText16, xxImageText8, 
    xxImageText16, xxImageGlyphBlt, 
    xxPolyGlyphBlt, xxPushPixels,
#ifdef NEED_LINEHELPER
    NULL,
#endif
    {NULL}        /* devPrivate */
};

#define IS_VISIBLE(pDraw) (pDraw->type == DRAWABLE_WINDOW \
         && (fbGetWindowPixmap((WindowPtr) pDraw) == pScrPriv->pPixmap))

#define TRANSLATE_BOX(box, pDraw) { \
    box.x1 += pDraw->x; \
    box.x2 += pDraw->x; \
    box.y1 += pDraw->y; \
    box.y2 += pDraw->y; \
    }

#define TRIM_BOX(box, pGC) { \
    BoxPtr extents = &pGC->pCompositeClip->extents;\
    if(box.x1 < extents->x1) box.x1 = extents->x1; \
    if(box.x2 > extents->x2) box.x2 = extents->x2; \
    if(box.y1 < extents->y1) box.y1 = extents->y1; \
    if(box.y2 > extents->y2) box.y2 = extents->y2; \
    }

#define BOX_NOT_EMPTY(box) \
    (((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))


#define _ADD_BOX(box,pGC) {\
    if (BOX_NOT_EMPTY(box)) { \
       RegionRec region; \
       ScreenPtr pScreen = pGC->pScreen;\
       REGION_INIT (pScreen, &region, &box, 1); \
       REGION_INTERSECT(pScreen,&region,&region,\
                                 (pGC)->pCompositeClip);\
       if (REGION_NOTEMPTY(pScreen,&region)) { \
           xxScrPriv(pScreen);\
         PRINT_RECTS(pScrPriv->region);\
           REGION_UNION(pScreen,&pScrPriv->region,&pScrPriv->region,&region);\
         PRINT_RECTS(pScrPriv->region);\
           REGION_UNINIT(pScreen,&region);\
       }\
   }\
}

#define TRANSLATE_AND_ADD_BOX(box,pGC) {\
         TRANSLATE_BOX(box,pDraw); \
         TRIM_BOX(box,pGC); \
         _ADD_BOX(box,pGC); \
}

#define ADD_BOX(box,pGC) { \
        TRIM_BOX(box,pGC); \
        _ADD_BOX(box,pGC); \
}

#define XX_GC_FUNC_PROLOGUE(pGC) \
    xxGCPriv(pGC); \
    unwrap(pGCPriv, pGC, funcs); \
    if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)

#define XX_GC_FUNC_EPILOGUE(pGC) \
    wrap(pGCPriv, pGC, funcs, &xxGCFuncs);  \
    if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &xxGCOps)

static Bool
xxCreateGC(GCPtr pGC)
{
    ScreenPtr           pScreen = pGC->pScreen;
    xxScrPriv(pScreen);
    xxGCPriv(pGC);
    Bool ret;

    unwrap (pScrPriv, pScreen, CreateGC);
    if((ret = (*pScreen->CreateGC) (pGC))) {
      pGCPriv->ops = NULL;
      pGCPriv->funcs = pGC->funcs;
      pGC->funcs = &xxGCFuncs;
    }
    wrap (pScrPriv, pScreen, CreateGC, xxCreateGC);

    return ret;
}

static void
xxValidateGC(
   GCPtr         pGC,
   unsigned long changes,
   DrawablePtr   pDraw 
){
    XX_GC_FUNC_PROLOGUE (pGC);
    (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
    if(pDraw->type == DRAWABLE_WINDOW)
      pGCPriv->ops = pGC->ops;  /* just so it's not NULL */
    else 
      pGCPriv->ops = NULL;
    XX_GC_FUNC_EPILOGUE (pGC);
}

static void
xxDestroyGC(GCPtr pGC)
{
    XX_GC_FUNC_PROLOGUE (pGC);
    (*pGC->funcs->DestroyGC)(pGC);
    XX_GC_FUNC_EPILOGUE (pGC);
}

static void
xxChangeGC (
    GCPtr       pGC,
    unsigned long   mask
){
    XX_GC_FUNC_PROLOGUE (pGC);
    (*pGC->funcs->ChangeGC) (pGC, mask);
    XX_GC_FUNC_EPILOGUE (pGC);
}

static void
xxCopyGC (
    GCPtr       pGCSrc, 
    unsigned long   mask,
    GCPtr       pGCDst
){
    XX_GC_FUNC_PROLOGUE (pGCDst);
    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
    XX_GC_FUNC_EPILOGUE (pGCDst);
}

static void
xxChangeClip (
    GCPtr   pGC,
    int           type,
    pointer pvalue,
    int           nrects 
){
    XX_GC_FUNC_PROLOGUE (pGC);
    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
    XX_GC_FUNC_EPILOGUE (pGC);
}

static void
xxCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
{
    XX_GC_FUNC_PROLOGUE (pgcDst);
    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
    XX_GC_FUNC_EPILOGUE (pgcDst);
}

static void
xxDestroyClip(GCPtr pGC)
{
    XX_GC_FUNC_PROLOGUE (pGC);
    (* pGC->funcs->DestroyClip)(pGC);
    XX_GC_FUNC_EPILOGUE (pGC);
}

#define XX_GC_OP_PROLOGUE(pGC,pDraw) \
    xxScrPriv(pDraw->pScreen); \
    xxGCPriv(pGC);  \
    GCFuncs *oldFuncs = pGC->funcs; \
    unwrap(pGCPriv, pGC, funcs);  \
    unwrap(pGCPriv, pGC, ops); \
      
#define XX_GC_OP_EPILOGUE(pGC,pDraw) \
    wrap(pGCPriv, pGC, funcs, oldFuncs); \
    wrap(pGCPriv, pGC, ops, &xxGCOps)

static void
xxFillSpans(
    DrawablePtr pDraw,
    GC            *pGC,
    int           nInit,      
    DDXPointPtr pptInit,      
    int     *pwidthInit,            
    int     fSorted 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);    

    if(IS_VISIBLE(pDraw) && nInit) {
      DDXPointPtr ppt = pptInit;
      int *pwidth = pwidthInit;
      int i = nInit;
      BoxRec box;

      DBG("FillSpans\n");
      box.x1 = ppt->x;
      box.x2 = box.x1 + *pwidth;
      box.y2 = box.y1 = ppt->y;

      while(--i) {
         ppt++;
         pwidthInit++;
         if(box.x1 > ppt->x) box.x1 = ppt->x;
         if(box.x2 < (ppt->x + *pwidth)) 
            box.x2 = ppt->x + *pwidth;
         if(box.y1 > ppt->y) box.y1 = ppt->y;
         else if(box.y2 < ppt->y) box.y2 = ppt->y;
      }

      box.y2++;

      (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);

      
      TRANSLATE_AND_ADD_BOX(box, pGC);
    } else
      (*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);

    XX_GC_OP_EPILOGUE(pGC, pDraw);
}

static void
xxSetSpans(
    DrawablePtr         pDraw,
    GCPtr         pGC,
    char          *pcharsrc,
    DDXPointPtr   pptInit,
    int                 *pwidthInit,
    int                 nspans,
    int                 fSorted 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && nspans) {
      DDXPointPtr ppt = pptInit;
      int *pwidth = pwidthInit;
      int i = nspans;
      BoxRec box;

      DBG("SetSpans\n");
      box.x1 = ppt->x;
      box.x2 = box.x1 + *pwidth;
      box.y2 = box.y1 = ppt->y;

      while(--i) {
         ppt++;
         pwidth++;
         if(box.x1 > ppt->x) box.x1 = ppt->x;
         if(box.x2 < (ppt->x + *pwidth)) 
            box.x2 = ppt->x + *pwidth;
         if(box.y1 > ppt->y) box.y1 = ppt->y;
         else if(box.y2 < ppt->y) box.y2 = ppt->y;
      }

      box.y2++;

      (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, 
                        pwidthInit, nspans, fSorted);

      TRANSLATE_AND_ADD_BOX(box, pGC);
    } else
      (*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit, 
                        pwidthInit, nspans, fSorted);

    XX_GC_OP_EPILOGUE(pGC, pDraw);
}

static void
xxPutImage(
    DrawablePtr pDraw,
    GCPtr   pGC,
    int           depth, 
    int x, int y, int w, int h,
    int           leftPad,
    int           format,
    char    *pImage 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h, 
            leftPad, format, pImage);
    XX_GC_OP_EPILOGUE(pGC, pDraw);
    if(IS_VISIBLE(pDraw)) {
      BoxRec box;

      DBG("PutImage\n");
      box.x1 = x + pDraw->x;
      box.x2 = box.x1 + w;
      box.y1 = y + pDraw->y;
      box.y2 = box.y1 + h;

      ADD_BOX(box, pGC);
    }
}

static RegionPtr
xxCopyArea(
    DrawablePtr pSrc,
    DrawablePtr pDst,
    GC *pGC,
    int srcx, int srcy,
    int width, int height,
    int dstx, int dsty 
){
    RegionPtr ret;
    XX_GC_OP_PROLOGUE(pGC, pDst);
    DBG("xxCopyArea\n");
    ret = (*pGC->ops->CopyArea)(pSrc, pDst,
            pGC, srcx, srcy, width, height, dstx, dsty);
    XX_GC_OP_EPILOGUE(pGC, pDst);

    if(IS_VISIBLE(pDst)) {
      BoxRec box;

      DBG("CopyArea\n");
      box.x1 = dstx + pDst->x;
      box.x2 = box.x1 + width;
      box.y1 = dsty + pDst->y;
      box.y2 = box.y1 + height;

      ADD_BOX(box, pGC);
    }

    return ret;
}

static RegionPtr
xxCopyPlane(
    DrawablePtr   pSrc,
    DrawablePtr   pDst,
    GCPtr pGC,
    int     srcx, int srcy,
    int     width, int height,
    int     dstx, int dsty,
    unsigned long bitPlane 
){
    RegionPtr ret;
    XX_GC_OP_PROLOGUE(pGC, pDst);
    ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
             pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
    XX_GC_OP_EPILOGUE(pGC, pDst);

    if(IS_VISIBLE(pDst)) {
      BoxRec box;

      DBG("CopyPlane\n");
      box.x1 = dstx + pDst->x;
      box.x2 = box.x1 + width;
      box.y1 = dsty + pDst->y;
      box.y2 = box.y1 + height;

      ADD_BOX(box, pGC);
    }

    return ret;
}

static void
xxPolyPoint(
    DrawablePtr pDraw,
    GCPtr pGC,
    int mode,
    int npt,
    xPoint *pptInit 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && npt) {
      BoxRec box;

      DBG("PolyPoint\n");
      box.x2 = box.x1 = pptInit->x;
      box.y2 = box.y1 = pptInit->y;

      /* this could be slow if the points were spread out */

      while(--npt) {
         pptInit++;
         if(box.x1 > pptInit->x) box.x1 = pptInit->x;
         else if(box.x2 < pptInit->x) box.x2 = pptInit->x;
         if(box.y1 > pptInit->y) box.y1 = pptInit->y;
         else if(box.y2 < pptInit->y) box.y2 = pptInit->y;
      }

      box.x2++;
      box.y2++;

      TRANSLATE_AND_ADD_BOX(box, pGC);
    }
}

static void
xxPolylines(
    DrawablePtr pDraw,
    GCPtr   pGC,
    int           mode,       
    int           npt,        
    DDXPointPtr pptInit 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
    XX_GC_OP_EPILOGUE(pGC, pDraw);


    if(IS_VISIBLE(pDraw) && npt) {
      BoxRec box;
      int extra = pGC->lineWidth >> 1;

      DBG("PolyLine\n");
      box.x2 = box.x1 = pptInit->x;
      box.y2 = box.y1 = pptInit->y;

      if(npt > 1) {
         if(pGC->joinStyle == JoinMiter)
            extra = 6 * pGC->lineWidth;
         else if(pGC->capStyle == CapProjecting)
            extra = pGC->lineWidth;
        }

      if(mode == CoordModePrevious) {
         int x = box.x1;
         int y = box.y1;
         while(--npt) {
            pptInit++;
            x += pptInit->x;
            y += pptInit->y;
            if(box.x1 > x) box.x1 = x;
            else if(box.x2 < x) box.x2 = x;
            if(box.y1 > y) box.y1 = y;
            else if(box.y2 < y) box.y2 = y;
          }
      } else {
         while(--npt) {
            pptInit++;
            if(box.x1 > pptInit->x) box.x1 = pptInit->x;
            else if(box.x2 < pptInit->x) box.x2 = pptInit->x;
            if(box.y1 > pptInit->y) box.y1 = pptInit->y;
            else if(box.y2 < pptInit->y) box.y2 = pptInit->y;
          }
      }

      box.x2++;
      box.y2++;

      if(extra) {
         box.x1 -= extra;
         box.x2 += extra;
         box.y1 -= extra;
         box.y2 += extra;
        }

      TRANSLATE_AND_ADD_BOX(box, pGC);
    }
}

static void 
xxPolySegment(
    DrawablePtr   pDraw,
    GCPtr   pGC,
    int           nseg,
    xSegment      *pSeg
    ){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && nseg) {
      BoxRec box;
      int extra = pGC->lineWidth;

      DBG("PolySegment\n");
        if(pGC->capStyle != CapProjecting)      
         extra >>= 1;

      if(pSeg->x2 > pSeg->x1) {
          box.x1 = pSeg->x1;
          box.x2 = pSeg->x2;
      } else {
          box.x2 = pSeg->x1;
          box.x1 = pSeg->x2;
      }

      if(pSeg->y2 > pSeg->y1) {
          box.y1 = pSeg->y1;
          box.y2 = pSeg->y2;
      } else {
          box.y2 = pSeg->y1;
          box.y1 = pSeg->y2;
      }

      while(--nseg) {
          pSeg++;
          if(pSeg->x2 > pSeg->x1) {
            if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
            if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
          } else {
            if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
            if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
          }
          if(pSeg->y2 > pSeg->y1) {
            if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
            if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
          } else {
            if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
            if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
          }
      }

      box.x2++;
      box.y2++;

      if(extra) {
         box.x1 -= extra;
         box.x2 += extra;
         box.y1 -= extra;
         box.y2 += extra;
        }
      
      TRANSLATE_AND_ADD_BOX(box, pGC);
    }
}

static void
xxPolyRectangle(
    DrawablePtr  pDraw,
    GCPtr        pGC,
    int              nRects,
    xRectangle  *pRects 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->PolyRectangle)(pDraw, pGC, nRects, pRects);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && nRects) 
    {
      BoxRec box;
      int offset1, offset2, offset3;

      DBG("PolyRectangle\n");
      offset2 = pGC->lineWidth;
      if(!offset2) offset2 = 1;
      offset1 = offset2 >> 1;
      offset3 = offset2 - offset1;

      while(nRects--) 
      {
          box.x1 = pRects->x - offset1;
          box.y1 = pRects->y - offset1;
          box.x2 = box.x1 + pRects->width + offset2;
          box.y2 = box.y1 + offset2;            
          TRANSLATE_AND_ADD_BOX(box, pGC);
          box.x1 = pRects->x - offset1;
          box.y1 = pRects->y + offset3;
          box.x2 = box.x1 + offset2;
          box.y2 = box.y1 + pRects->height - offset2;       
          TRANSLATE_AND_ADD_BOX(box, pGC);
          box.x1 = pRects->x + pRects->width - offset1;
          box.y1 = pRects->y + offset3;
          box.x2 = box.x1 + offset2;
          box.y2 = box.y1 + pRects->height - offset2;       
          TRANSLATE_AND_ADD_BOX(box, pGC);
          box.x1 = pRects->x - offset1;
          box.y1 = pRects->y + pRects->height - offset1;
          box.x2 = box.x1 + pRects->width + offset2;
          box.y2 = box.y1 + offset2;            
          TRANSLATE_AND_ADD_BOX(box, pGC);

          pRects++;
      }
    }
}

static void
xxPolyArc(
    DrawablePtr   pDraw,
    GCPtr   pGC,
    int           narcs,
    xArc    *parcs 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && narcs) {
      int extra = pGC->lineWidth >> 1;
      BoxRec box;

      DBG("PolyArc\n");
      box.x1 = parcs->x;
      box.x2 = box.x1 + parcs->width;
      box.y1 = parcs->y;
      box.y2 = box.y1 + parcs->height;

      /* should I break these up instead ? */

      while(--narcs) {
         parcs++;
         if(box.x1 > parcs->x) box.x1 = parcs->x;
         if(box.x2 < (parcs->x + parcs->width))
            box.x2 = parcs->x + parcs->width;
         if(box.y1 > parcs->y) box.y1 = parcs->y;
         if(box.y2 < (parcs->y + parcs->height))
            box.y2 = parcs->y + parcs->height;
        }

      if(extra) {
         box.x1 -= extra;
         box.x2 += extra;
         box.y1 -= extra;
         box.y2 += extra;
        }

      box.x2++;
      box.y2++;

      TRANSLATE_AND_ADD_BOX(box, pGC);
    }
}

static void
xxFillPolygon(
    DrawablePtr   pDraw,
    GCPtr   pGC,
    int           shape,
    int           mode,
    int           count,
    DDXPointPtr   pptInit 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && (count > 2)) {
      DDXPointPtr ppt = pptInit;
      int i = count;
      BoxRec box;

      DBG("FillPolygon\n");
      box.x2 = box.x1 = ppt->x;
      box.y2 = box.y1 = ppt->y;

      if(mode != CoordModeOrigin) {
         int x = box.x1;
         int y = box.y1;
         while(--i) {
            ppt++;
            x += ppt->x;
            y += ppt->y;
            if(box.x1 > x) box.x1 = x;
            else if(box.x2 < x) box.x2 = x;
            if(box.y1 > y) box.y1 = y;
            else if(box.y2 < y) box.y2 = y;
          }
      } else {
         while(--i) {
            ppt++;
            if(box.x1 > ppt->x) box.x1 = ppt->x;
            else if(box.x2 < ppt->x) box.x2 = ppt->x;
            if(box.y1 > ppt->y) box.y1 = ppt->y;
            else if(box.y2 < ppt->y) box.y2 = ppt->y;
          }
      }

      box.x2++;
      box.y2++;

      (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);

      TRANSLATE_AND_ADD_BOX(box, pGC);
    } else
      (*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);

    XX_GC_OP_EPILOGUE(pGC, pDraw);
}

static void 
xxPolyFillRect(
    DrawablePtr   pDraw,
    GCPtr   pGC,
    int           nRectsInit, 
    xRectangle    *pRectsInit 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && nRectsInit) {
      BoxRec box;
      xRectangle *pRects = pRectsInit;
      int nRects = nRectsInit;

      DBG("PolyFillRect\n");
      box.x1 = pRects->x;
      box.x2 = box.x1 + pRects->width;
      box.y1 = pRects->y;
      box.y2 = box.y1 + pRects->height;

      while(--nRects) {
          pRects++;
          if(box.x1 > pRects->x) box.x1 = pRects->x;
          if(box.x2 < (pRects->x + pRects->width))
            box.x2 = pRects->x + pRects->width;
          if(box.y1 > pRects->y) box.y1 = pRects->y;
          if(box.y2 < (pRects->y + pRects->height))
            box.y2 = pRects->y + pRects->height;
      }

      /* cfb messes with the pRectsInit so we have to do our
         calculations first */

      (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);

      TRANSLATE_AND_ADD_BOX(box, pGC);
    } else
      (*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);

    XX_GC_OP_EPILOGUE(pGC, pDraw);
}

static void
xxPolyFillArc(
    DrawablePtr   pDraw,
    GCPtr   pGC,
    int           narcs,
    xArc    *parcs 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && narcs) {
      BoxRec box;

      DBG("PolyFillArc\n");
      box.x1 = parcs->x;
      box.x2 = box.x1 + parcs->width;
      box.y1 = parcs->y;
      box.y2 = box.y1 + parcs->height;

      /* should I break these up instead ? */

      while(--narcs) {
         parcs++;
         if(box.x1 > parcs->x) box.x1 = parcs->x;
         if(box.x2 < (parcs->x + parcs->width))
            box.x2 = parcs->x + parcs->width;
         if(box.y1 > parcs->y) box.y1 = parcs->y;
         if(box.y2 < (parcs->y + parcs->height))
            box.y2 = parcs->y + parcs->height;
        }

      TRANSLATE_AND_ADD_BOX(box, pGC);
    }
}

static int
xxPolyText8(
    DrawablePtr pDraw,
    GCPtr   pGC,
    int           x, 
    int     y,
    int     count,
    char    *chars 
){
    int width;

    XX_GC_OP_PROLOGUE(pGC, pDraw);
    width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    width -= x;

    if(IS_VISIBLE(pDraw) && (width > 0)) {
      BoxRec box;

      DBG("PolyText8\n");
      /* ugh */
      box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
      box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);

      if(count > 1) {
         if(width > 0) box.x2 += width;
         else box.x1 += width;
      }

      box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
      box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);

      ADD_BOX(box,  pGC);
    }

    return (width + x);
}

static int
xxPolyText16(
    DrawablePtr pDraw,
    GCPtr   pGC,
    int           x,
    int           y,
    int     count,
    unsigned short *chars 
){
    int width;

    XX_GC_OP_PROLOGUE(pGC, pDraw);
    width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    width -= x;

    if(IS_VISIBLE(pDraw) && (width > 0)) {
      BoxRec box;

      DBG("PolyText16\n");
      /* ugh */
      box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
      box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);

      if(count > 1) {
         if(width > 0) box.x2 += width;
         else box.x1 += width;
      }

      box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
      box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);

      ADD_BOX(box, pGC);
    }

    return (width + x);
}

static void
xxImageText8(
    DrawablePtr pDraw,
    GCPtr   pGC,
    int           x, 
    int           y,
    int     count,
    char    *chars 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && count) {
      int top, bot, Min, Max;
      BoxRec box;

      DBG("ImageText8\n");
      top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
      bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));

      Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
      if(Min > 0) Min = 0;
      Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);     
      if(Max < 0) Max = 0;

      /* ugh */
      box.x1 = pDraw->x + x + Min +
            FONTMINBOUNDS(pGC->font, leftSideBearing);
      box.x2 = pDraw->x + x + Max + 
            FONTMAXBOUNDS(pGC->font, rightSideBearing);

      box.y1 = pDraw->y + y - top;
      box.y2 = pDraw->y + y + bot;

      ADD_BOX(box, pGC);
    }
}

static void
xxImageText16(
    DrawablePtr pDraw,
    GCPtr   pGC,
    int           x,
    int           y,
    int     count,
    unsigned short *chars 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && count) {
      int top, bot, Min, Max;
      BoxRec box;

      DBG("ImageText16\n");
      top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
      bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));

      Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
      if(Min > 0) Min = 0;
      Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);     
      if(Max < 0) Max = 0;

      /* ugh */
      box.x1 = pDraw->x + x + Min +
            FONTMINBOUNDS(pGC->font, leftSideBearing);
      box.x2 = pDraw->x + x + Max + 
            FONTMAXBOUNDS(pGC->font, rightSideBearing);

      box.y1 = pDraw->y + y - top;
      box.y2 = pDraw->y + y + bot;

      ADD_BOX(box, pGC);
    }
}

static void
xxImageGlyphBlt(
    DrawablePtr pDraw,
    GCPtr pGC,
    int x, int y,
    unsigned int nglyph,
    CharInfoPtr *ppci,
    pointer pglyphBase 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyph, 
                              ppci, pglyphBase);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && nglyph) {
      int top, bot, width = 0;
      BoxRec box;

      DBG("ImageGlyphBlt\n");
      top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
      bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));

      box.x1 = ppci[0]->metrics.leftSideBearing;
      if(box.x1 > 0) box.x1 = 0;
      box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - 
            ppci[nglyph - 1]->metrics.characterWidth;
      if(box.x2 < 0) box.x2 = 0;

      box.x2 += pDraw->x + x;
      box.x1 += pDraw->x + x;
         
      while(nglyph--) {
          width += (*ppci)->metrics.characterWidth;
          ppci++;
      }

      if(width > 0) 
         box.x2 += width;
      else 
         box.x1 += width;

      box.y1 = pDraw->y + y - top;
      box.y2 = pDraw->y + y + bot;

      ADD_BOX(box, pGC);
    }
}

static void
xxPolyGlyphBlt(
    DrawablePtr pDraw,
    GCPtr pGC,
    int x, int y,
    unsigned int nglyph,
    CharInfoPtr *ppci,
    pointer pglyphBase 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyph, 
                        ppci, pglyphBase);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw) && nglyph) {
      BoxRec box;

      DBG("PolyGlyphBlt\n");
      /* ugh */
      box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing;
      box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;

      if(nglyph > 1) {
          int width = 0;

          while(--nglyph) { 
            width += (*ppci)->metrics.characterWidth;
            ppci++;
          }
      
          if(width > 0) box.x2 += width;
          else box.x1 += width;
      }

      box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
      box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);

      ADD_BOX(box, pGC);
    }
}

static void
xxPushPixels(
    GCPtr   pGC,
    PixmapPtr     pBitMap,
    DrawablePtr pDraw,
    int     dx, int dy, int xOrg, int yOrg 
){
    XX_GC_OP_PROLOGUE(pGC, pDraw);
    (*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
    XX_GC_OP_EPILOGUE(pGC, pDraw);

    if(IS_VISIBLE(pDraw)) {
      BoxRec box;

      DBG("PushPixels\n");
      box.x1 = xOrg + pDraw->x;
      box.x2 = box.x1 + dx;
      box.y1 = yOrg + pDraw->y;
      box.y2 = box.y1 + dy;

      ADD_BOX(box, pGC);
    }
}


#ifdef RENDER
#define RENDER_MAKE_BOX(pDrawable,X,Y,W,H) { \
    box.x1 = X + pDrawable->x; \
    box.x2 = X + pDrawable->x + W; \
    box.y1 = Y + pDrawable->y; \
    box.y2 = Y + pDrawable->y + H; \
}

#define RENDER_ADD_BOX(pScreen,box) {\
    if (BOX_NOT_EMPTY(box)) { \
       RegionRec region; \
       xxScrPriv(pScreen);\
       ScreenPtr pScreen = pScreen;\
       REGION_INIT (pScreen, &region, &box, 1); \
       PRINT_RECTS(pScrPriv->region);\
       REGION_UNION(pScreen,&pScrPriv->region,&pScrPriv->region,&region);\
       PRINT_RECTS(pScrPriv->region);\
       REGION_UNINIT(pScreen,&region);\
   }\
}

static void
xxComposite (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
           INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask,
    INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
{
    ScreenPtr           pScreen = pDst->pDrawable->pScreen;
    PictureScreenPtr    ps = GetPictureScreen(pScreen);
    xxScrPriv(pScreen);
    BoxRec        box;

    unwrap (pScrPriv, ps, Composite);
    (*ps->Composite) (op, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask,
                  xDst, yDst, width, height);
    wrap (pScrPriv, ps, Composite, xxComposite);
    if (pDst->pDrawable->type == DRAWABLE_WINDOW) {
      RENDER_MAKE_BOX(pDst->pDrawable, xDst, yDst, width, height);
      RENDER_ADD_BOX(pScreen,box);
    }
}


static void
xxGlyphs (CARD8 op, PicturePtr pSrc, PicturePtr pDst,
        PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, int nlist,
        GlyphListPtr list, GlyphPtr *glyphs)
{
    ScreenPtr           pScreen = pDst->pDrawable->pScreen;
    PictureScreenPtr    ps = GetPictureScreen(pScreen);
    xxScrPriv(pScreen);
    int                 x, y;
    int                 n;
    GlyphPtr            glyph;
    BoxRec        box;

    unwrap (pScrPriv, ps, Glyphs);
    (*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc,
               nlist, list, glyphs);
    wrap (pScrPriv, ps, Glyphs, xxGlyphs);
    if (pDst->pDrawable->type == DRAWABLE_WINDOW)
    {
      x = xSrc;
      y = ySrc;
      while (nlist--)
      {
          x += list->xOff;
          y += list->yOff;
          n = list->len;
          while (n--)
          {
            glyph = *glyphs++;
            RENDER_MAKE_BOX(pDst->pDrawable,
                        x - glyph->info.x, y - glyph->info.y,
                        glyph->info.width, glyph->info.height);
            RENDER_ADD_BOX(pScreen,box);
            x += glyph->info.xOff;
            y += glyph->info.yOff;
          }
          list++;
      }
    }
}
#endif

void
xxPrintVisuals(void)
{
    int k,i,j;
    DepthPtr pDepth;
    VisualPtr pVisual;

    for (k = 0; k < screenInfo.numScreens; k++) {
      ScreenPtr pScreen = screenInfo.screens[k];
      
      pDepth = pScreen->allowedDepths;
      for (i = 0; i < pScreen->numDepths; i++, pDepth++)
          for (j = 0; j < pDepth->numVids; j++) {
            ErrorF("depth: %i vid: 0x%lx\n",
                   pDepth->depth, pDepth->vids[j]);
          }
      
      pVisual = pScreen->visuals;
      for (i = 0; i < pScreen->numVisuals; i++, pVisual++)
          ErrorF("vid: 0x%x rm: 0x%lx gm: 0x%lx bm: 0x%lx\n",
               (unsigned int)pVisual->vid,
               pVisual->redMask,
               pVisual->greenMask,
               pVisual->blueMask);
    }
}



Generated by  Doxygen 1.6.0   Back to index