#ifdef HAVE_XNEST_CONFIG_H
#include <xnest-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include "gcstruct.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "scrnintstr.h"
#include <X11/fonts/fontstruct.h>
#include "mistruct.h"
#include "region.h"
#include "Xnest.h"
#include "Display.h"
#include "XNGC.h"
#include "GCOps.h"
#include "Drawable.h"
#include "XNFont.h"
#include "Color.h"
static int xnestGCPrivateKeyIndex;
DevPrivateKey xnestGCPrivateKey = &xnestGCPrivateKeyIndex;
static GCFuncs xnestFuncs = {
xnestValidateGC,
xnestChangeGC,
xnestCopyGC,
xnestDestroyGC,
xnestChangeClip,
xnestDestroyClip,
xnestCopyClip,
};
static GCOps xnestOps = {
xnestFillSpans,
xnestSetSpans,
xnestPutImage,
xnestCopyArea,
xnestCopyPlane,
xnestPolyPoint,
xnestPolylines,
xnestPolySegment,
xnestPolyRectangle,
xnestPolyArc,
xnestFillPolygon,
xnestPolyFillRect,
xnestPolyFillArc,
xnestPolyText8,
xnestPolyText16,
xnestImageText8,
xnestImageText16,
xnestImageGlyphBlt,
xnestPolyGlyphBlt,
xnestPushPixels
};
Bool
xnestCreateGC(GCPtr pGC)
{
pGC->clientClipType = CT_NONE;
pGC->clientClip = NULL;
pGC->funcs = &xnestFuncs;
pGC->ops = &xnestOps;
pGC->miTranslate = 1;
xnestGCPriv(pGC)->gc = XCreateGC(xnestDisplay,
xnestDefaultDrawables[pGC->depth],
0L, NULL);
xnestGCPriv(pGC)->nClipRects = 0;
return True;
}
void
xnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
{
pGC->lastWinOrg.x = pDrawable->x;
pGC->lastWinOrg.y = pDrawable->y;
}
void
xnestChangeGC(GCPtr pGC, unsigned long mask)
{
XGCValues values;
if (mask & GCFunction)
values.function = pGC->alu;
if (mask & GCPlaneMask)
values.plane_mask = pGC->planemask;
if (mask & GCForeground)
values.foreground = xnestPixel(pGC->fgPixel);
if (mask & GCBackground)
values.background = xnestPixel(pGC->bgPixel);
if (mask & GCLineWidth)
values.line_width = pGC->lineWidth;
if (mask & GCLineStyle)
values.line_style = pGC->lineStyle;
if (mask & GCCapStyle)
values.cap_style = pGC->capStyle;
if (mask & GCJoinStyle)
values.join_style = pGC->joinStyle;
if (mask & GCFillStyle)
values.fill_style = pGC->fillStyle;
if (mask & GCFillRule)
values.fill_rule = pGC->fillRule;
if (mask & GCTile) {
if (pGC->tileIsPixel)
mask &= ~GCTile;
else
values.tile = xnestPixmap(pGC->tile.pixmap);
}
if (mask & GCStipple)
values.stipple = xnestPixmap(pGC->stipple);
if (mask & GCTileStipXOrigin)
values.ts_x_origin = pGC->patOrg.x;
if (mask & GCTileStipYOrigin)
values.ts_y_origin = pGC->patOrg.y;
if (mask & GCFont)
values.font = xnestFont(pGC->font);
if (mask & GCSubwindowMode)
values.subwindow_mode = pGC->subWindowMode;
if (mask & GCGraphicsExposures)
values.graphics_exposures = pGC->graphicsExposures;
if (mask & GCClipXOrigin)
values.clip_x_origin = pGC->clipOrg.x;
if (mask & GCClipYOrigin)
values.clip_y_origin = pGC->clipOrg.y;
if (mask & GCClipMask)
mask &= ~GCClipMask;
if (mask & GCDashOffset)
values.dash_offset = pGC->dashOffset;
if (mask & GCDashList) {
mask &= ~GCDashList;
XSetDashes(xnestDisplay, xnestGC(pGC),
pGC->dashOffset, (char *)pGC->dash, pGC->numInDashList);
}
if (mask & GCArcMode)
values.arc_mode = pGC->arcMode;
if (mask)
XChangeGC(xnestDisplay, xnestGC(pGC), mask, &values);
}
void
xnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
{
XCopyGC(xnestDisplay, xnestGC(pGCSrc), mask, xnestGC(pGCDst));
}
void
xnestDestroyGC(GCPtr pGC)
{
XFreeGC(xnestDisplay, xnestGC(pGC));
}
void
xnestChangeClip(GCPtr pGC, int type, pointer pValue, int nRects)
{
int i, size;
BoxPtr pBox;
XRectangle *pRects;
xnestDestroyClipHelper(pGC);
switch(type)
{
case CT_NONE:
XSetClipMask(xnestDisplay, xnestGC(pGC), None);
break;
case CT_REGION:
nRects = REGION_NUM_RECTS((RegionPtr)pValue);
size = nRects * sizeof(*pRects);
pRects = (XRectangle *) xalloc(size);
pBox = REGION_RECTS((RegionPtr)pValue);
for (i = nRects; i-- > 0; ) {
pRects[i].x = pBox[i].x1;
pRects[i].y = pBox[i].y1;
pRects[i].width = pBox[i].x2 - pBox[i].x1;
pRects[i].height = pBox[i].y2 - pBox[i].y1;
}
XSetClipRectangles(xnestDisplay, xnestGC(pGC), 0, 0,
pRects, nRects, Unsorted);
xfree((char *) pRects);
break;
case CT_PIXMAP:
XSetClipMask(xnestDisplay, xnestGC(pGC),
xnestPixmap((PixmapPtr)pValue));
pGC->clientClip = (pointer) (*pGC->pScreen->BitmapToRegion)((PixmapPtr)pValue);
(*pGC->pScreen->DestroyPixmap)((PixmapPtr)pValue);
pValue = pGC->clientClip;
type = CT_REGION;
break;
case CT_UNSORTED:
XSetClipRectangles(xnestDisplay, xnestGC(pGC),
pGC->clipOrg.x, pGC->clipOrg.y,
(XRectangle *)pValue, nRects, Unsorted);
break;
case CT_YSORTED:
XSetClipRectangles(xnestDisplay, xnestGC(pGC),
pGC->clipOrg.x, pGC->clipOrg.y,
(XRectangle *)pValue, nRects, YSorted);
break;
case CT_YXSORTED:
XSetClipRectangles(xnestDisplay, xnestGC(pGC),
pGC->clipOrg.x, pGC->clipOrg.y,
(XRectangle *)pValue, nRects, YXSorted);
break;
case CT_YXBANDED:
XSetClipRectangles(xnestDisplay, xnestGC(pGC),
pGC->clipOrg.x, pGC->clipOrg.y,
(XRectangle *)pValue, nRects, YXBanded);
break;
}
switch(type)
{
default:
break;
case CT_UNSORTED:
case CT_YSORTED:
case CT_YXSORTED:
case CT_YXBANDED:
pGC->clientClip = (pointer) RECTS_TO_REGION(pGC->pScreen, nRects,
(xRectangle *)pValue, type);
xfree(pValue);
pValue = pGC->clientClip;
type = CT_REGION;
break;
}
pGC->clientClipType = type;
pGC->clientClip = pValue;
xnestGCPriv(pGC)->nClipRects = nRects;
}
void
xnestDestroyClip(GCPtr pGC)
{
xnestDestroyClipHelper(pGC);
XSetClipMask(xnestDisplay, xnestGC(pGC), None);
pGC->clientClipType = CT_NONE;
pGC->clientClip = NULL;
xnestGCPriv(pGC)->nClipRects = 0;
}
void
xnestDestroyClipHelper(GCPtr pGC)
{
switch (pGC->clientClipType)
{
default:
case CT_NONE:
break;
case CT_REGION:
REGION_DESTROY(pGC->pScreen, pGC->clientClip);
break;
}
}
void
xnestCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
{
RegionPtr pRgn;
switch (pGCSrc->clientClipType)
{
default:
case CT_NONE:
xnestDestroyClip(pGCDst);
break;
case CT_REGION:
pRgn = REGION_CREATE(pGCDst->pScreen, NULL, 1);
REGION_COPY(pGCDst->pScreen, pRgn, pGCSrc->clientClip);
xnestChangeClip(pGCDst, CT_REGION, pRgn, 0);
break;
}
}