339 lines
7.3 KiB
C
339 lines
7.3 KiB
C
/*
|
|
|
|
Copyright 1993 by Davor Matic
|
|
|
|
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. Davor Matic makes no representations about
|
|
the suitability of this software for any purpose. It is provided "as
|
|
is" without express or implied warranty.
|
|
|
|
*/
|
|
|
|
#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"
|
|
|
|
int xnestGCPrivateIndex;
|
|
|
|
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) /* this is handled in change clip */
|
|
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));
|
|
/*
|
|
* Need to change into region, so subsequent uses are with
|
|
* current pixmap contents.
|
|
*/
|
|
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:
|
|
|
|
/*
|
|
* other parts of server can only deal with CT_NONE,
|
|
* CT_PIXMAP and CT_REGION client clips.
|
|
*/
|
|
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;
|
|
}
|
|
}
|