コード例 #1
0
ファイル: rootlessGC.c プロジェクト: sheldonrobinson/VcXsrv
/* changed area is *dest* rect */
static RegionPtr
RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
                  GCPtr pGC, int srcx, int srcy,
                  int w, int h, int dstx, int dsty, unsigned long plane)
{
    RegionPtr result;
    BoxRec box;

    GCOP_UNWRAP(pGC);

    RL_DEBUG_MSG("copy plane start ");

    if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) {
        RootlessStartDrawing((WindowPtr) pSrc);
    }
    RootlessStartDrawing((WindowPtr) dst);
    result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h,
                                 dstx, dsty, plane);

    box.x1 = dstx + dst->x;
    box.x2 = box.x1 + w;
    box.y1 = dsty + dst->y;
    box.y2 = box.y1 + h;

    TRIM_BOX(box, pGC);
    if (BOX_NOT_EMPTY(box))
        RootlessDamageBox((WindowPtr) dst, &box);

    GCOP_WRAP(pGC);
    RL_DEBUG_MSG("copy plane end\n");
    return result;
}
コード例 #2
0
ファイル: rootlessGC.c プロジェクト: sheldonrobinson/VcXsrv
static void
RootlessPutImage(DrawablePtr dst, GCPtr pGC,
                 int depth, int x, int y, int w, int h,
                 int leftPad, int format, char *pBits)
{
    BoxRec box;

    GCOP_UNWRAP(pGC);
    RL_DEBUG_MSG("put image start ");

    RootlessStartDrawing((WindowPtr) dst);
    pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits);

    box.x1 = x + dst->x;
    box.x2 = box.x1 + w;
    box.y1 = y + dst->y;
    box.y2 = box.y1 + h;

    TRIM_BOX(box, pGC);
    if (BOX_NOT_EMPTY(box))
        RootlessDamageBox((WindowPtr) dst, &box);

    GCOP_WRAP(pGC);
    RL_DEBUG_MSG("put image end\n");
}
コード例 #3
0
ファイル: rootlessGC.c プロジェクト: sheldonrobinson/VcXsrv
static void
RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
                  DDXPointPtr pptInit, int *pwidthInit, int sorted)
{
    GC_SAVE(pGC);
    GCOP_UNWRAP(pGC);
    RL_DEBUG_MSG("fill spans start ");

    if (nInit <= 0) {
        pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
    }
    else {
        DDXPointPtr ppt = pptInit;
        int *pwidth = pwidthInit;
        int i = nInit;
        BoxRec box;

        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++;

        RootlessStartDrawing((WindowPtr) dst);

        if (canAccelFill(dst, pGC)) {
            GC_UNSET_PM(pGC, dst);
        }

        pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);

        TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
        if (BOX_NOT_EMPTY(box))
            RootlessDamageBox((WindowPtr) dst, &box);
    }

    GC_RESTORE(pGC, dst);
    GCOP_WRAP(pGC);
    RL_DEBUG_MSG("fill spans end\n");
}
コード例 #4
0
ファイル: rootlessGC.c プロジェクト: sheldonrobinson/VcXsrv
/* changed area is *dest* rect */
static RegionPtr
RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
                 int srcx, int srcy, int w, int h, int dstx, int dsty)
{
    RegionPtr result;
    BoxRec box;

    GC_SAVE(pGC);
    GCOP_UNWRAP(pGC);

    RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst);

    if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) {
        /* If both source and dest are windows, and we're doing
           a simple copy operation, we can remove the alpha-protecting
           planemask (since source has opaque alpha as well) */

        if (canAccelBlit(pSrc, pGC)) {
            GC_UNSET_PM(pGC, dst);
        }

        RootlessStartDrawing((WindowPtr) pSrc);
    }
    RootlessStartDrawing((WindowPtr) dst);
    result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty);

    box.x1 = dstx + dst->x;
    box.x2 = box.x1 + w;
    box.y1 = dsty + dst->y;
    box.y2 = box.y1 + h;

    TRIM_BOX(box, pGC);
    if (BOX_NOT_EMPTY(box))
        RootlessDamageBox((WindowPtr) dst, &box);

    GC_RESTORE(pGC, dst);
    GCOP_WRAP(pGC);
    RL_DEBUG_MSG("copy area end\n");
    return result;
}
コード例 #5
0
ファイル: rootlessScreen.c プロジェクト: aosm/X11server
static void
RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h,
                 unsigned int format, unsigned long planeMask, char *pdstLine)
{
    ScreenPtr pScreen = pDrawable->pScreen;
    SCREEN_UNWRAP(pScreen, GetImage);

    if (pDrawable->type == DRAWABLE_WINDOW) {
        int x0, y0, x1, y1;
        RootlessWindowRec *winRec;

        // Many apps use GetImage to sync with the visible frame buffer
        // FIXME: entire screen or just window or all screens?
        RootlessRedisplayScreen(pScreen);

        // RedisplayScreen stops drawing, so we need to start it again
        RootlessStartDrawing((WindowPtr)pDrawable);

        /* Check that we have some place to read from. */
        winRec = WINREC(TopLevelParent((WindowPtr) pDrawable));
        if (winRec == NULL)
            goto out;

        /* Clip to top-level window bounds. */
        /* FIXME: fbGetImage uses the width parameter to calculate the
           stride of the destination pixmap. If w is clipped, the data
           returned will be garbage, although we will not crash. */

        x0 = pDrawable->x + sx;
        y0 = pDrawable->y + sy;
        x1 = x0 + w;
        y1 = y0 + h;

        x0 = max (x0, winRec->x);
        y0 = max (y0, winRec->y);
        x1 = min (x1, winRec->x + winRec->width);
        y1 = min (y1, winRec->y + winRec->height);

        sx = x0 - pDrawable->x;
        sy = y0 - pDrawable->y;
        w = x1 - x0;
        h = y1 - y0;

        if (w <= 0 || h <= 0)
            goto out;
    }

    pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine);

out:
    SCREEN_WRAP(pScreen, GetImage);
}
コード例 #6
0
ファイル: rootlessScreen.c プロジェクト: aosm/X11server
static void
RootlessComposite(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);
    WindowPtr srcWin, dstWin, maskWin = NULL;

    if (pMask) {                        // pMask can be NULL
        maskWin = (pMask->pDrawable && pMask->pDrawable->type == DRAWABLE_WINDOW) ?
                  (WindowPtr)pMask->pDrawable : NULL;
    }
    srcWin  = (pSrc->pDrawable && pSrc->pDrawable->type  == DRAWABLE_WINDOW) ?
              (WindowPtr)pSrc->pDrawable  :  NULL;
    dstWin  = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
              (WindowPtr)pDst->pDrawable  :  NULL;

    // SCREEN_UNWRAP(ps, Composite);
    ps->Composite = SCREENREC(pScreen)->Composite;

    if (srcWin  && IsFramedWindow(srcWin))
        RootlessStartDrawing(srcWin);
    if (maskWin && IsFramedWindow(maskWin))
        RootlessStartDrawing(maskWin);
    if (dstWin  && IsFramedWindow(dstWin))
        RootlessStartDrawing(dstWin);

    ps->Composite(op, pSrc, pMask, pDst,
                  xSrc, ySrc, xMask, yMask,
                  xDst, yDst, width, height);

    if (dstWin  && IsFramedWindow(dstWin)) {
        RootlessDamageRect(dstWin, xDst, yDst, width, height);
    }

    ps->Composite = RootlessComposite;
    // SCREEN_WRAP(ps, Composite);
}
コード例 #7
0
ファイル: rootlessScreen.c プロジェクト: aosm/X11server
/*
 * RootlessSourceValidate
 *  CopyArea and CopyPlane use a GC tied to the destination drawable.
 *  StartDrawing/StopDrawing wrappers won't be called if source is
 *  a visible window but the destination isn't. So, we call StartDrawing
 *  here and leave StopDrawing for the block handler.
 */
static void
RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h,
                       unsigned int subWindowMode)
{
    SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate);
    if (pDrawable->type == DRAWABLE_WINDOW) {
        WindowPtr pWin = (WindowPtr)pDrawable;
        RootlessStartDrawing(pWin);
    }
    if (pDrawable->pScreen->SourceValidate) {
        pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, subWindowMode);
    }
    SCREEN_WRAP(pDrawable->pScreen, SourceValidate);
}
コード例 #8
0
ファイル: rootlessGC.c プロジェクト: sheldonrobinson/VcXsrv
static void
RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
                 DDXPointPtr pptInit, int *pwidthInit, int nspans, int sorted)
{
    GCOP_UNWRAP(pGC);
    RL_DEBUG_MSG("set spans start ");

    if (nspans <= 0) {
        pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted);
    }
    else {
        DDXPointPtr ppt = pptInit;
        int *pwidth = pwidthInit;
        int i = nspans;
        BoxRec box;

        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++;

        RootlessStartDrawing((WindowPtr) dst);
        pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted);

        TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
        if (BOX_NOT_EMPTY(box))
            RootlessDamageBox((WindowPtr) dst, &box);
    }
    GCOP_WRAP(pGC);
    RL_DEBUG_MSG("set spans end\n");
}
コード例 #9
0
ファイル: rootlessScreen.c プロジェクト: aosm/X11server
static void
RootlessGlyphs(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);
    int x, y;
    int n;
    GlyphPtr glyph;
    WindowPtr srcWin, dstWin;

    srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ?
             (WindowPtr)pSrc->pDrawable  :  NULL;
    dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ?
             (WindowPtr)pDst->pDrawable  :  NULL;

    if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin);
    if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin);

    //SCREEN_UNWRAP(ps, Glyphs);
    ps->Glyphs = SCREENREC(pScreen)->Glyphs;
    ps->Glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
    ps->Glyphs = RootlessGlyphs;
    //SCREEN_WRAP(ps, Glyphs);

    if (dstWin && IsFramedWindow(dstWin)) {
        x = xSrc;
        y = ySrc;

        while (nlist--) {
            x += list->xOff;
            y += list->yOff;
            n = list->len;

            /* Calling DamageRect for the bounding box of each glyph is
               inefficient. So compute the union of all glyphs in a list
               and damage that. */

            if (n > 0) {
                BoxRec box;

                glyph = *glyphs++;

                box.x1 = x - glyph->info.x;
                box.y1 = y - glyph->info.y;
                box.x2 = box.x1 + glyph->info.width;
                box.y2 = box.y1 + glyph->info.height;

                x += glyph->info.xOff;
                y += glyph->info.yOff;

                while (--n > 0) {
                    short x1, y1, x2, y2;

                    glyph = *glyphs++;

                    x1 = x - glyph->info.x;
                    y1 = y - glyph->info.y;
                    x2 = x1 + glyph->info.width;
                    y2 = y1 + glyph->info.height;

                    box.x1 = max (box.x1, x1);
                    box.y1 = max (box.y1, y1);
                    box.x2 = max (box.x2, x2);
                    box.y2 = max (box.y2, y2);

                    x += glyph->info.xOff;
                    y += glyph->info.yOff;
                }

                RootlessDamageBox(dstWin, &box);
            }
            list++;
        }
    }
}
コード例 #10
0
ファイル: rootlessGC.c プロジェクト: sheldonrobinson/VcXsrv
/* changed area is box around each line */
static void
RootlessPolylines(DrawablePtr dst, GCPtr pGC,
                  int mode, int npt, DDXPointPtr pptInit)
{
    GCOP_UNWRAP(pGC);
    RL_DEBUG_MSG("poly lines start ");

    RootlessStartDrawing((WindowPtr) dst);
    pGC->ops->Polylines(dst, pGC, mode, npt, pptInit);

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

        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;
        }

        TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
        if (BOX_NOT_EMPTY(box))
            RootlessDamageBox((WindowPtr) dst, &box);
    }
コード例 #11
0
ファイル: rootlessGC.c プロジェクト: sheldonrobinson/VcXsrv
/* changed area is box around all points */
static void
RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
                  int mode, int npt, DDXPointPtr pptInit)
{
    GCOP_UNWRAP(pGC);
    RL_DEBUG_MSG("polypoint start ");

    RootlessStartDrawing((WindowPtr) dst);
    pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit);

    if (npt > 0) {
#if ROOTLESS_CHANGED_AREA==0
        // box per point
        BoxRec box;

        while (npt) {
            box.x1 = pptInit->x;
            box.y1 = pptInit->y;
            box.x2 = box.x1 + 1;
            box.y2 = box.y1 + 1;

            TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
            if (BOX_NOT_EMPTY(box))
                RootlessDamageBox((WindowPtr) dst, &box);

            npt--;
            pptInit++;
        }

#elif ROOTLESS_CHANGED_AREA==1
        // one big box
        BoxRec box;

        box.x2 = box.x1 = pptInit->x;
        box.y2 = box.y1 = pptInit->y;
        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++;

        TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
        if (BOX_NOT_EMPTY(box))
            RootlessDamageBox((WindowPtr) dst, &box);

#elif ROOTLESS_CHANGED_AREA==2
        // clever(?) method: accumulate point in 20-pixel radius
        BoxRec box;
        int firstx, firsty;

        box.x2 = box.x1 = firstx = pptInit->x;
        box.y2 = box.y1 = firsty = pptInit->y;
        while (--npt) {
            pptInit++;
            if (abs(pptInit->x - firstx) > 20 || abs(pptInit->y - firsty) > 20) {
                box.x2++;
                box.y2++;
                TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
                if (BOX_NOT_EMPTY(box))
                    RootlessDamageBox((WindowPtr) dst, &box);
                box.x2 = box.x1 = firstx = pptInit->x;
                box.y2 = box.y1 = firsty = pptInit->y;
            }
            else {
                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++;
        TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
        if (BOX_NOT_EMPTY(box))
            RootlessDamageBox((WindowPtr) dst, &box);
#endif                          /* ROOTLESS_CHANGED_AREA */
    }

    GCOP_WRAP(pGC);
    RL_DEBUG_MSG("polypoint end\n");
}
コード例 #12
0
ファイル: miexpose.c プロジェクト: MrKepzie/xserver
void
miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
{
    ScreenPtr pScreen = pWin->drawable.pScreen;
    ChangeGCVal gcval[6];
    BITS32 gcmask;
    GCPtr pGC;
    int i;
    BoxPtr pbox;
    xRectangle *prect;
    int numRects;

    /*
     * Distance from screen to destination drawable, use this
     * to adjust rendering coordinates which come in in screen space
     */
    int draw_x_off, draw_y_off;

    /*
     * Tile offset for drawing; these need to align the tile
     * to the appropriate window origin
     */
    int tile_x_off, tile_y_off;
    PixUnion fill;
    Bool solid = TRUE;
    DrawablePtr drawable = &pWin->drawable;

#ifdef ROOTLESS
    if (!drawable || drawable->type == UNDRAWABLE_WINDOW)
        return;

    if (IsFramedWindow(pWin)) {
        RootlessStartDrawing(pWin);
        RootlessDamageRegion(pWin, prgn);

        if (pWin->backgroundState == ParentRelative) {
            if ((what == PW_BACKGROUND) ||
                (what == PW_BORDER && !pWin->borderIsPixel))
                RootlessSetPixmapOfAncestors(pWin);
        }
    }
#endif

    if (what == PW_BACKGROUND) {
        while (pWin->backgroundState == ParentRelative)
            pWin = pWin->parent;

        draw_x_off = drawable->x;
        draw_y_off = drawable->y;

        tile_x_off = pWin->drawable.x - draw_x_off;
        tile_y_off = pWin->drawable.y - draw_y_off;
        fill = pWin->background;
#ifdef COMPOSITE
        if (pWin->inhibitBGPaint)
            return;
#endif
        switch (pWin->backgroundState) {
        case None:
            return;
        case BackgroundPixmap:
            solid = FALSE;
            break;
        }
    }
    else {
        PixmapPtr pixmap;

        tile_x_off = drawable->x;
        tile_y_off = drawable->y;

        /* servers without pixmaps draw their own borders */
        if (!pScreen->GetWindowPixmap)
            return;
        pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
        drawable = &pixmap->drawable;
#ifdef COMPOSITE
        draw_x_off = pixmap->screen_x;
        draw_y_off = pixmap->screen_y;
        tile_x_off -= draw_x_off;
        tile_y_off -= draw_y_off;
#else
        draw_x_off = 0;
        draw_y_off = 0;
#endif
        fill = pWin->border;
        solid = pWin->borderIsPixel;
    }

    gcval[0].val = GXcopy;
    gcmask = GCFunction;

#ifdef ROOTLESS_SAFEALPHA
/* Bit mask for alpha channel with a particular number of bits per
 * pixel. Note that we only care for 32bpp data. Mac OS X uses planar
 * alpha for 16bpp.
 */
#define RootlessAlphaMask(bpp) ((bpp) == 32 ? 0xFF000000 : 0)
#endif

    if (solid) {
#ifdef ROOTLESS_SAFEALPHA
        gcval[1].val =
            fill.pixel | RootlessAlphaMask(pWin->drawable.bitsPerPixel);
#else
        gcval[1].val = fill.pixel;
#endif
        gcval[2].val = FillSolid;
        gcmask |= GCForeground | GCFillStyle;
    }
    else {
        int c = 1;

#ifdef ROOTLESS_SAFEALPHA
        gcval[c++].val =
            ((CARD32) -1) & ~RootlessAlphaMask(pWin->drawable.bitsPerPixel);
        gcmask |= GCPlaneMask;
#endif
        gcval[c++].val = FillTiled;
        gcval[c++].ptr = (void *) fill.pixmap;
        gcval[c++].val = tile_x_off;
        gcval[c++].val = tile_y_off;
        gcmask |= GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
    }

    prect = malloc(RegionNumRects(prgn) * sizeof(xRectangle));
    if (!prect)
        return;

    pGC = GetScratchGC(drawable->depth, drawable->pScreen);
    if (!pGC) {
        free(prect);
        return;
    }

    ChangeGC(NullClient, pGC, gcmask, gcval);
    ValidateGC(drawable, pGC);

    numRects = RegionNumRects(prgn);
    pbox = RegionRects(prgn);
    for (i = numRects; --i >= 0; pbox++, prect++) {
        prect->x = pbox->x1 - draw_x_off;
        prect->y = pbox->y1 - draw_y_off;
        prect->width = pbox->x2 - pbox->x1;
        prect->height = pbox->y2 - pbox->y1;
    }
    prect -= numRects;
    (*pGC->ops->PolyFillRect) (drawable, pGC, numRects, prect);
    free(prect);

    FreeScratchGC(pGC);
}