GC.c revision 35c4bbdf
105b261ecSmrg/*
205b261ecSmrg
305b261ecSmrgCopyright 1993 by Davor Matic
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software
605b261ecSmrgand its documentation for any purpose is hereby granted without fee,
705b261ecSmrgprovided that the above copyright notice appear in all copies and that
805b261ecSmrgboth that copyright notice and this permission notice appear in
905b261ecSmrgsupporting documentation.  Davor Matic makes no representations about
1005b261ecSmrgthe suitability of this software for any purpose.  It is provided "as
1105b261ecSmrgis" without express or implied warranty.
1205b261ecSmrg
1305b261ecSmrg*/
1405b261ecSmrg
1505b261ecSmrg#ifdef HAVE_XNEST_CONFIG_H
1605b261ecSmrg#include <xnest-config.h>
1705b261ecSmrg#endif
1805b261ecSmrg
1905b261ecSmrg#include <X11/X.h>
2005b261ecSmrg#include <X11/Xproto.h>
2105b261ecSmrg#include "gcstruct.h"
2205b261ecSmrg#include "windowstr.h"
2305b261ecSmrg#include "pixmapstr.h"
2405b261ecSmrg#include "scrnintstr.h"
2505b261ecSmrg#include <X11/fonts/fontstruct.h>
2605b261ecSmrg#include "mistruct.h"
2705b261ecSmrg#include "region.h"
2805b261ecSmrg
2905b261ecSmrg#include "Xnest.h"
3005b261ecSmrg
3105b261ecSmrg#include "Display.h"
3235c4bbdfSmrg#include "XNGC.h"
3305b261ecSmrg#include "GCOps.h"
3405b261ecSmrg#include "Drawable.h"
3505b261ecSmrg#include "XNFont.h"
3605b261ecSmrg#include "Color.h"
3705b261ecSmrg
386747b715SmrgDevPrivateKeyRec xnestGCPrivateKeyRec;
3905b261ecSmrg
4005b261ecSmrgstatic GCFuncs xnestFuncs = {
4135c4bbdfSmrg    xnestValidateGC,
4235c4bbdfSmrg    xnestChangeGC,
4335c4bbdfSmrg    xnestCopyGC,
4435c4bbdfSmrg    xnestDestroyGC,
4535c4bbdfSmrg    xnestChangeClip,
4635c4bbdfSmrg    xnestDestroyClip,
4735c4bbdfSmrg    xnestCopyClip,
4805b261ecSmrg};
4905b261ecSmrg
5005b261ecSmrgstatic GCOps xnestOps = {
5135c4bbdfSmrg    xnestFillSpans,
5235c4bbdfSmrg    xnestSetSpans,
5335c4bbdfSmrg    xnestPutImage,
5435c4bbdfSmrg    xnestCopyArea,
5535c4bbdfSmrg    xnestCopyPlane,
5635c4bbdfSmrg    xnestPolyPoint,
5735c4bbdfSmrg    xnestPolylines,
5835c4bbdfSmrg    xnestPolySegment,
5935c4bbdfSmrg    xnestPolyRectangle,
6035c4bbdfSmrg    xnestPolyArc,
6135c4bbdfSmrg    xnestFillPolygon,
6235c4bbdfSmrg    xnestPolyFillRect,
6335c4bbdfSmrg    xnestPolyFillArc,
6435c4bbdfSmrg    xnestPolyText8,
6535c4bbdfSmrg    xnestPolyText16,
6635c4bbdfSmrg    xnestImageText8,
6735c4bbdfSmrg    xnestImageText16,
6835c4bbdfSmrg    xnestImageGlyphBlt,
6935c4bbdfSmrg    xnestPolyGlyphBlt,
7035c4bbdfSmrg    xnestPushPixels
7105b261ecSmrg};
7205b261ecSmrg
7305b261ecSmrgBool
7405b261ecSmrgxnestCreateGC(GCPtr pGC)
7505b261ecSmrg{
7635c4bbdfSmrg    pGC->funcs = &xnestFuncs;
7735c4bbdfSmrg    pGC->ops = &xnestOps;
7835c4bbdfSmrg
7935c4bbdfSmrg    pGC->miTranslate = 1;
8035c4bbdfSmrg
8135c4bbdfSmrg    xnestGCPriv(pGC)->gc = XCreateGC(xnestDisplay,
8235c4bbdfSmrg                                     xnestDefaultDrawables[pGC->depth],
8335c4bbdfSmrg                                     0L, NULL);
8435c4bbdfSmrg
8535c4bbdfSmrg    return True;
8605b261ecSmrg}
8705b261ecSmrg
8805b261ecSmrgvoid
8905b261ecSmrgxnestValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
9005b261ecSmrg{
9105b261ecSmrg}
9205b261ecSmrg
9305b261ecSmrgvoid
9405b261ecSmrgxnestChangeGC(GCPtr pGC, unsigned long mask)
9505b261ecSmrg{
9635c4bbdfSmrg    XGCValues values;
9735c4bbdfSmrg
9835c4bbdfSmrg    if (mask & GCFunction)
9935c4bbdfSmrg        values.function = pGC->alu;
10035c4bbdfSmrg
10135c4bbdfSmrg    if (mask & GCPlaneMask)
10235c4bbdfSmrg        values.plane_mask = pGC->planemask;
10335c4bbdfSmrg
10435c4bbdfSmrg    if (mask & GCForeground)
10535c4bbdfSmrg        values.foreground = xnestPixel(pGC->fgPixel);
10635c4bbdfSmrg
10735c4bbdfSmrg    if (mask & GCBackground)
10835c4bbdfSmrg        values.background = xnestPixel(pGC->bgPixel);
10935c4bbdfSmrg
11035c4bbdfSmrg    if (mask & GCLineWidth)
11135c4bbdfSmrg        values.line_width = pGC->lineWidth;
11235c4bbdfSmrg
11335c4bbdfSmrg    if (mask & GCLineStyle)
11435c4bbdfSmrg        values.line_style = pGC->lineStyle;
11535c4bbdfSmrg
11635c4bbdfSmrg    if (mask & GCCapStyle)
11735c4bbdfSmrg        values.cap_style = pGC->capStyle;
11835c4bbdfSmrg
11935c4bbdfSmrg    if (mask & GCJoinStyle)
12035c4bbdfSmrg        values.join_style = pGC->joinStyle;
12135c4bbdfSmrg
12235c4bbdfSmrg    if (mask & GCFillStyle)
12335c4bbdfSmrg        values.fill_style = pGC->fillStyle;
12435c4bbdfSmrg
12535c4bbdfSmrg    if (mask & GCFillRule)
12635c4bbdfSmrg        values.fill_rule = pGC->fillRule;
12735c4bbdfSmrg
12835c4bbdfSmrg    if (mask & GCTile) {
12935c4bbdfSmrg        if (pGC->tileIsPixel)
13035c4bbdfSmrg            mask &= ~GCTile;
13135c4bbdfSmrg        else
13235c4bbdfSmrg            values.tile = xnestPixmap(pGC->tile.pixmap);
13335c4bbdfSmrg    }
13435c4bbdfSmrg
13535c4bbdfSmrg    if (mask & GCStipple)
13635c4bbdfSmrg        values.stipple = xnestPixmap(pGC->stipple);
13735c4bbdfSmrg
13835c4bbdfSmrg    if (mask & GCTileStipXOrigin)
13935c4bbdfSmrg        values.ts_x_origin = pGC->patOrg.x;
14035c4bbdfSmrg
14135c4bbdfSmrg    if (mask & GCTileStipYOrigin)
14235c4bbdfSmrg        values.ts_y_origin = pGC->patOrg.y;
14335c4bbdfSmrg
14435c4bbdfSmrg    if (mask & GCFont)
14535c4bbdfSmrg        values.font = xnestFont(pGC->font);
14635c4bbdfSmrg
14735c4bbdfSmrg    if (mask & GCSubwindowMode)
14835c4bbdfSmrg        values.subwindow_mode = pGC->subWindowMode;
14935c4bbdfSmrg
15035c4bbdfSmrg    if (mask & GCGraphicsExposures)
15135c4bbdfSmrg        values.graphics_exposures = pGC->graphicsExposures;
15235c4bbdfSmrg
15335c4bbdfSmrg    if (mask & GCClipXOrigin)
15435c4bbdfSmrg        values.clip_x_origin = pGC->clipOrg.x;
15535c4bbdfSmrg
15635c4bbdfSmrg    if (mask & GCClipYOrigin)
15735c4bbdfSmrg        values.clip_y_origin = pGC->clipOrg.y;
15835c4bbdfSmrg
15935c4bbdfSmrg    if (mask & GCClipMask)      /* this is handled in change clip */
16035c4bbdfSmrg        mask &= ~GCClipMask;
16135c4bbdfSmrg
16235c4bbdfSmrg    if (mask & GCDashOffset)
16335c4bbdfSmrg        values.dash_offset = pGC->dashOffset;
16435c4bbdfSmrg
16535c4bbdfSmrg    if (mask & GCDashList) {
16635c4bbdfSmrg        mask &= ~GCDashList;
16735c4bbdfSmrg        XSetDashes(xnestDisplay, xnestGC(pGC),
16835c4bbdfSmrg                   pGC->dashOffset, (char *) pGC->dash, pGC->numInDashList);
16935c4bbdfSmrg    }
17035c4bbdfSmrg
17135c4bbdfSmrg    if (mask & GCArcMode)
17235c4bbdfSmrg        values.arc_mode = pGC->arcMode;
17335c4bbdfSmrg
17435c4bbdfSmrg    if (mask)
17535c4bbdfSmrg        XChangeGC(xnestDisplay, xnestGC(pGC), mask, &values);
17605b261ecSmrg}
17705b261ecSmrg
17805b261ecSmrgvoid
17905b261ecSmrgxnestCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
18005b261ecSmrg{
18135c4bbdfSmrg    XCopyGC(xnestDisplay, xnestGC(pGCSrc), mask, xnestGC(pGCDst));
18205b261ecSmrg}
18305b261ecSmrg
18405b261ecSmrgvoid
18505b261ecSmrgxnestDestroyGC(GCPtr pGC)
18605b261ecSmrg{
18735c4bbdfSmrg    XFreeGC(xnestDisplay, xnestGC(pGC));
18805b261ecSmrg}
18905b261ecSmrg
19005b261ecSmrgvoid
19135c4bbdfSmrgxnestChangeClip(GCPtr pGC, int type, void *pValue, int nRects)
19205b261ecSmrg{
19335c4bbdfSmrg    int i;
19435c4bbdfSmrg    BoxPtr pBox;
19535c4bbdfSmrg    XRectangle *pRects;
19605b261ecSmrg
19735c4bbdfSmrg    xnestDestroyClip(pGC);
19805b261ecSmrg
19935c4bbdfSmrg    switch (type) {
20005b261ecSmrg    case CT_NONE:
20135c4bbdfSmrg        XSetClipMask(xnestDisplay, xnestGC(pGC), None);
20235c4bbdfSmrg        pValue = NULL;
20335c4bbdfSmrg        break;
20435c4bbdfSmrg
20505b261ecSmrg    case CT_REGION:
20635c4bbdfSmrg        nRects = RegionNumRects((RegionPtr) pValue);
20735c4bbdfSmrg        pRects = xallocarray(nRects, sizeof(*pRects));
20835c4bbdfSmrg        pBox = RegionRects((RegionPtr) pValue);
20935c4bbdfSmrg        for (i = nRects; i-- > 0;) {
21035c4bbdfSmrg            pRects[i].x = pBox[i].x1;
21135c4bbdfSmrg            pRects[i].y = pBox[i].y1;
21235c4bbdfSmrg            pRects[i].width = pBox[i].x2 - pBox[i].x1;
21335c4bbdfSmrg            pRects[i].height = pBox[i].y2 - pBox[i].y1;
21435c4bbdfSmrg        }
21535c4bbdfSmrg        XSetClipRectangles(xnestDisplay, xnestGC(pGC), 0, 0,
21635c4bbdfSmrg                           pRects, nRects, Unsorted);
21735c4bbdfSmrg        free((char *) pRects);
21835c4bbdfSmrg        break;
21905b261ecSmrg
22005b261ecSmrg    case CT_PIXMAP:
22135c4bbdfSmrg        XSetClipMask(xnestDisplay, xnestGC(pGC),
22235c4bbdfSmrg                     xnestPixmap((PixmapPtr) pValue));
22335c4bbdfSmrg        /*
22435c4bbdfSmrg         * Need to change into region, so subsequent uses are with
22535c4bbdfSmrg         * current pixmap contents.
22635c4bbdfSmrg         */
22735c4bbdfSmrg        pGC->clientClip = (*pGC->pScreen->BitmapToRegion) ((PixmapPtr) pValue);
22835c4bbdfSmrg        (*pGC->pScreen->DestroyPixmap) ((PixmapPtr) pValue);
22935c4bbdfSmrg        pValue = pGC->clientClip;
23035c4bbdfSmrg        break;
23105b261ecSmrg
23205b261ecSmrg    case CT_UNSORTED:
23335c4bbdfSmrg        XSetClipRectangles(xnestDisplay, xnestGC(pGC),
23435c4bbdfSmrg                           pGC->clipOrg.x, pGC->clipOrg.y,
23535c4bbdfSmrg                           (XRectangle *) pValue, nRects, Unsorted);
23635c4bbdfSmrg        break;
23705b261ecSmrg
23805b261ecSmrg    case CT_YSORTED:
23935c4bbdfSmrg        XSetClipRectangles(xnestDisplay, xnestGC(pGC),
24035c4bbdfSmrg                           pGC->clipOrg.x, pGC->clipOrg.y,
24135c4bbdfSmrg                           (XRectangle *) pValue, nRects, YSorted);
24235c4bbdfSmrg        break;
24305b261ecSmrg
24405b261ecSmrg    case CT_YXSORTED:
24535c4bbdfSmrg        XSetClipRectangles(xnestDisplay, xnestGC(pGC),
24635c4bbdfSmrg                           pGC->clipOrg.x, pGC->clipOrg.y,
24735c4bbdfSmrg                           (XRectangle *) pValue, nRects, YXSorted);
24835c4bbdfSmrg        break;
24905b261ecSmrg
25005b261ecSmrg    case CT_YXBANDED:
25135c4bbdfSmrg        XSetClipRectangles(xnestDisplay, xnestGC(pGC),
25235c4bbdfSmrg                           pGC->clipOrg.x, pGC->clipOrg.y,
25335c4bbdfSmrg                           (XRectangle *) pValue, nRects, YXBanded);
25435c4bbdfSmrg        break;
25505b261ecSmrg    }
25605b261ecSmrg
25735c4bbdfSmrg    switch (type) {
25805b261ecSmrg    default:
25935c4bbdfSmrg        break;
26005b261ecSmrg
26105b261ecSmrg    case CT_UNSORTED:
26205b261ecSmrg    case CT_YSORTED:
26305b261ecSmrg    case CT_YXSORTED:
26405b261ecSmrg    case CT_YXBANDED:
26535c4bbdfSmrg        /* server clip representation is a region */
26635c4bbdfSmrg        pGC->clientClip = RegionFromRects(nRects, (xRectangle *) pValue, type);
26735c4bbdfSmrg        free(pValue);
26835c4bbdfSmrg        pValue = pGC->clientClip;
26935c4bbdfSmrg        break;
27005b261ecSmrg    }
27105b261ecSmrg
27235c4bbdfSmrg    pGC->clientClip = pValue;
27305b261ecSmrg}
27405b261ecSmrg
27505b261ecSmrgvoid
27605b261ecSmrgxnestDestroyClip(GCPtr pGC)
27705b261ecSmrg{
27835c4bbdfSmrg    if (pGC->clientClip) {
27935c4bbdfSmrg        RegionDestroy(pGC->clientClip);
28035c4bbdfSmrg        XSetClipMask(xnestDisplay, xnestGC(pGC), None);
28135c4bbdfSmrg        pGC->clientClip = NULL;
28205b261ecSmrg    }
28305b261ecSmrg}
28405b261ecSmrg
28505b261ecSmrgvoid
28605b261ecSmrgxnestCopyClip(GCPtr pGCDst, GCPtr pGCSrc)
28705b261ecSmrg{
28835c4bbdfSmrg    if (pGCSrc->clientClip) {
28935c4bbdfSmrg        RegionPtr pRgn = RegionCreate(NULL, 1);
29035c4bbdfSmrg        RegionCopy(pRgn, pGCSrc->clientClip);
29135c4bbdfSmrg        xnestChangeClip(pGCDst, CT_REGION, pRgn, 0);
29235c4bbdfSmrg    } else {
29335c4bbdfSmrg        xnestDestroyClip(pGCDst);
29405b261ecSmrg    }
29505b261ecSmrg}
296