+++ /dev/null
-/*
- * draw.c - drawing routines for the RFB X server. This is a set of
- * wrappers around the standard MI/MFB/CFB drawing routines which work out
- * to a fair approximation the region of the screen being modified by the
- * drawing. If the RFB client is ready then the modified region of the screen
- * is sent to the client, otherwise the modified region will simply grow with
- * each drawing request until the client is ready.
- */
-
-/*
- * Copyright (C) 2002-2003 RealVNC Ltd.
- * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-/*
-
-Copyright (c) 1989 X Consortium
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from the X Consortium.
-*/
-
-#include <stdio.h>
-#include "scrnintstr.h"
-#include "gcstruct.h"
-#include "windowstr.h"
-#include "regionstr.h"
-#include "dixfontstr.h"
-#include "rfb.h"
-#include "mfb.h"
-
-extern WindowPtr *WindowTable; /* Why isn't this in a header file? */
-
-int rfbDeferUpdateTime = 40; /* ms */
-
-/* MAX_RECTS_PER_OP is the maximum number of rectangles we generate from
- operations like Polylines and PolySegment. If the operation is more complex
- than this, we simply use the bounding box. Ideally it would be a
- command-line option, but that would involve an extra malloc each time, so we
- fix it here. */
-#define MAX_RECTS_PER_OP 5
-
-
-/****************************************************************************/
-/*
- * Macro definitions
- */
-/****************************************************************************/
-
-/* SLIGHTLY DIRTY HACK - use Composite Clip region calculated by mfb */
-
-#define WINDOW_CLIP_REGION(_w, _gc) \
- (((mfbPrivGCPtr)((_gc)->devPrivates[mfbGCPrivateIndex].ptr))->pCompositeClip)
-
-#define TRC(x) if (rfbTrace) rfbLog x
-
-/* ADD_TO_MODIFIED_REGION adds the given region to the modified region for each
- client */
-
-#define ADD_TO_MODIFIED_REGION(pScreen,reg) \
- { \
- rfbClientPtr cl; \
- for (cl = rfbClientHead; cl; cl = cl->next) { \
- if (REGION_NUM_RECTS(&cl->modifiedRegion) > rfbMaxRects) { \
- BoxRec boundingBox = *(REGION_EXTENTS((pScreen), \
- &cl->modifiedRegion)); \
- REGION_RESET((pScreen), &cl->modifiedRegion, &boundingBox); \
- } \
- \
- REGION_UNION((pScreen),&cl->modifiedRegion,&cl->modifiedRegion,reg);\
- } \
- }
-
-/* SCHEDULE_FB_UPDATE is used at the end of each drawing routine to schedule an
- update to be sent to each client if there is one pending and the client is
- ready for it. */
-
-#define SCHEDULE_FB_UPDATE(pScreen,prfb) \
- if (!prfb->dontSendFramebufferUpdate) { \
- rfbClientPtr cl, nextCl; \
- for (cl = rfbClientHead; cl; cl = nextCl) { \
- nextCl = cl->next; \
- if (!cl->deferredUpdateScheduled && FB_UPDATE_PENDING(cl) && \
- REGION_NOTEMPTY(pScreen,&cl->requestedRegion)) \
- { \
- rfbScheduleDeferredUpdate(cl); \
- } \
- } \
- }
-
-/* function prototypes */
-
-static void rfbCopyRegion(ScreenPtr pScreen, rfbClientPtr cl,
- RegionPtr src, RegionPtr dst, int dx, int dy);
-
-/* GC funcs */
-
-static void rfbValidateGC(GCPtr, unsigned long /*changes*/, DrawablePtr);
-static void rfbChangeGC(GCPtr, unsigned long /*mask*/);
-static void rfbCopyGC(GCPtr /*src*/, unsigned long /*mask*/, GCPtr /*dst*/);
-static void rfbDestroyGC(GCPtr);
-static void rfbChangeClip(GCPtr, int /*type*/, pointer /*pValue*/,
- int /*nrects*/);
-static void rfbDestroyClip(GCPtr);
-static void rfbCopyClip(GCPtr /*dst*/, GCPtr /*src*/);
-
-/* GC ops */
-
-static void rfbFillSpans();
-static void rfbSetSpans();
-static void rfbPutImage();
-static RegionPtr rfbCopyArea();
-static RegionPtr rfbCopyPlane();
-static void rfbPolyPoint();
-static void rfbPolylines();
-static void rfbPolySegment();
-static void rfbPolyRectangle();
-static void rfbPolyArc();
-static void rfbFillPolygon();
-static void rfbPolyFillRect();
-static void rfbPolyFillArc();
-static int rfbPolyText8();
-static int rfbPolyText16();
-static void rfbImageText8();
-static void rfbImageText16();
-static void rfbImageGlyphBlt();
-static void rfbPolyGlyphBlt();
-static void rfbPushPixels();
-
-
-static GCFuncs rfbGCFuncs = {
- rfbValidateGC,
- rfbChangeGC,
- rfbCopyGC,
- rfbDestroyGC,
- rfbChangeClip,
- rfbDestroyClip,
- rfbCopyClip,
-};
-
-
-static GCOps rfbGCOps = {
- rfbFillSpans, rfbSetSpans, rfbPutImage,
- rfbCopyArea, rfbCopyPlane, rfbPolyPoint,
- rfbPolylines, rfbPolySegment, rfbPolyRectangle,
- rfbPolyArc, rfbFillPolygon, rfbPolyFillRect,
- rfbPolyFillArc, rfbPolyText8, rfbPolyText16,
- rfbImageText8, rfbImageText16, rfbImageGlyphBlt,
- rfbPolyGlyphBlt, rfbPushPixels
-};
-
-
-
-/****************************************************************************/
-/*
- * Screen functions wrapper stuff
- */
-/****************************************************************************/
-
-#define SCREEN_PROLOGUE(scrn, field) \
- ScreenPtr pScreen = scrn; \
- rfbScreenInfoPtr prfb = &rfbScreen; \
- pScreen->field = prfb->field;
-
-#define SCREEN_EPILOGUE(field, wrapper) \
- pScreen->field = wrapper;
-
-
-/*
- * CloseScreen wrapper -- unwrap everything, free the private data
- * and call the wrapped CloseScreen function.
- */
-
-Bool
-rfbCloseScreen (i, pScreen)
- int i;
- ScreenPtr pScreen;
-{
- rfbScreenInfoPtr prfb = &rfbScreen;
-
- pScreen->CloseScreen = prfb->CloseScreen;
- pScreen->CreateGC = prfb->CreateGC;
- pScreen->PaintWindowBackground = prfb->PaintWindowBackground;
- pScreen->PaintWindowBorder = prfb->PaintWindowBorder;
- pScreen->CopyWindow = prfb->CopyWindow;
- pScreen->ClearToBackground = prfb->ClearToBackground;
- pScreen->RestoreAreas = prfb->RestoreAreas;
-
- TRC(("Unwrapped screen functions\n"));
-
- return (*pScreen->CloseScreen) (i, pScreen);
-}
-
-/*
- * CreateGC - wrap the GC funcs (the GC ops will be wrapped when the GC
- * func "ValidateGC" is called).
- */
-
-Bool
-rfbCreateGC (pGC)
- GCPtr pGC;
-{
- Bool ret;
- rfbGCPtr pGCPriv;
-
- SCREEN_PROLOGUE(pGC->pScreen,CreateGC);
-
- pGCPriv = (rfbGCPtr)pGC->devPrivates[rfbGCIndex].ptr;
-
- ret = (*pScreen->CreateGC) (pGC);
-
- TRC(("rfbCreateGC called\n"));
-
- pGCPriv->wrapOps = NULL;
- pGCPriv->wrapFuncs = pGC->funcs;
- pGC->funcs = &rfbGCFuncs;
-
- SCREEN_EPILOGUE(CreateGC,rfbCreateGC);
-
- return ret;
-}
-
-/*
- * PaintWindowBackground - the region being modified is just the given region.
- */
-
-void
-rfbPaintWindowBackground (pWin, pRegion, what)
- WindowPtr pWin;
- RegionPtr pRegion;
- int what;
-{
- SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBackground);
-
- TRC(("rfbPaintWindowBackground called\n"));
-
- ADD_TO_MODIFIED_REGION(pScreen,pRegion);
-
- (*pScreen->PaintWindowBackground) (pWin, pRegion, what);
-
- SCHEDULE_FB_UPDATE(pScreen, prfb);
-
- SCREEN_EPILOGUE(PaintWindowBackground,rfbPaintWindowBackground);
-}
-
-/*
- * PaintWindowBorder - the region being modified is just the given region.
- */
-
-void
-rfbPaintWindowBorder (pWin, pRegion, what)
- WindowPtr pWin;
- RegionPtr pRegion;
- int what;
-{
- SCREEN_PROLOGUE(pWin->drawable.pScreen,PaintWindowBorder);
-
- TRC(("rfbPaintWindowBorder called\n"));
-
- ADD_TO_MODIFIED_REGION(pScreen,pRegion);
-
- (*pScreen->PaintWindowBorder) (pWin, pRegion, what);
-
- SCHEDULE_FB_UPDATE(pScreen, prfb);
-
- SCREEN_EPILOGUE(PaintWindowBorder,rfbPaintWindowBorder);
-}
-
-/*
- * CopyWindow - the region being modified is the translation of the old
- * region, clipped to the border clip region of the window. Note that any
- * parts of the window which have become newly-visible will not be affected by
- * this call - a separate PaintWindowBackground/Border will be called to do
- * that. If the client will accept CopyRect messages then use rfbCopyRegion to
- * optimise the pending screen changes into a single "copy region" plus the
- * ordinary modified region.
- */
-
-void
-rfbCopyWindow (pWin, ptOldOrg, pOldRegion)
- WindowPtr pWin;
- DDXPointRec ptOldOrg;
- RegionPtr pOldRegion;
-{
- rfbClientPtr cl;
- RegionRec srcRegion, dstRegion;
- SCREEN_PROLOGUE(pWin->drawable.pScreen,CopyWindow);
-
- TRC(("rfbCopyWindow called\n"));
-
- REGION_INIT(pScreen,&dstRegion,NullBox,0);
- REGION_COPY(pScreen,&dstRegion,pOldRegion);
- REGION_TRANSLATE(pWin->drawable.pScreen, &dstRegion,
- pWin->drawable.x - ptOldOrg.x,
- pWin->drawable.y - ptOldOrg.y);
- REGION_INTERSECT(pWin->drawable.pScreen, &dstRegion, &dstRegion,
- &pWin->borderClip);
-
- for (cl = rfbClientHead; cl; cl = cl->next) {
- if (cl->useCopyRect) {
- REGION_INIT(pScreen,&srcRegion,NullBox,0);
- REGION_COPY(pScreen,&srcRegion,pOldRegion);
-
- rfbCopyRegion(pScreen, cl, &srcRegion, &dstRegion,
- pWin->drawable.x - ptOldOrg.x,
- pWin->drawable.y - ptOldOrg.y);
-
- REGION_UNINIT(pSrc->pScreen, &srcRegion);
-
- } else {
-
- REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
- &dstRegion);
- }
- }
-
- REGION_UNINIT(pSrc->pScreen, &dstRegion);
-
- (*pScreen->CopyWindow) (pWin, ptOldOrg, pOldRegion);
-
- SCHEDULE_FB_UPDATE(pScreen, prfb);
-
- SCREEN_EPILOGUE(CopyWindow,rfbCopyWindow);
-}
-
-/*
- * ClearToBackground - when generateExposures is false, the region being
- * modified is the given rectangle (clipped to the "window clip region").
- */
-
-void
-rfbClearToBackground (pWin, x, y, w, h, generateExposures)
- WindowPtr pWin;
- int x,y,w,h;
- Bool generateExposures;
-{
- RegionRec tmpRegion;
- BoxRec box;
- SCREEN_PROLOGUE(pWin->drawable.pScreen,ClearToBackground);
-
- TRC(("rfbClearToBackground called\n"));
-
- if (!generateExposures) {
- box.x1 = x + pWin->drawable.x;
- box.y1 = y + pWin->drawable.y;
- box.x2 = w ? (box.x1 + w) : (pWin->drawable.x + pWin->drawable.width);
- box.y2 = h ? (box.y1 + h) : (pWin->drawable.y + pWin->drawable.height);
-
- SAFE_REGION_INIT(pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pScreen, &tmpRegion, &tmpRegion, &pWin->clipList);
-
- ADD_TO_MODIFIED_REGION(pScreen, &tmpRegion);
-
- REGION_UNINIT(pScreen, &tmpRegion);
- }
-
- (*pScreen->ClearToBackground) (pWin, x, y, w, h, generateExposures);
-
- if (!generateExposures) {
- SCHEDULE_FB_UPDATE(pScreen, prfb);
- }
-
- SCREEN_EPILOGUE(ClearToBackground,rfbClearToBackground);
-}
-
-/*
- * RestoreAreas - just be safe here - the region being modified is the whole
- * exposed region.
- */
-
-RegionPtr
-rfbRestoreAreas (pWin, prgnExposed)
- WindowPtr pWin;
- RegionPtr prgnExposed;
-{
- RegionPtr result;
- SCREEN_PROLOGUE(pWin->drawable.pScreen,RestoreAreas);
-
- TRC(("rfbRestoreAreas called\n"));
-
- ADD_TO_MODIFIED_REGION(pScreen, prgnExposed);
-
- result = (*pScreen->RestoreAreas) (pWin, prgnExposed);
-
- SCHEDULE_FB_UPDATE(pScreen, prfb);
-
- SCREEN_EPILOGUE(RestoreAreas,rfbRestoreAreas);
-
- return result;
-}
-
-
-
-/****************************************************************************/
-/*
- * GC funcs wrapper stuff
- *
- * We only really want to wrap the GC ops, but to do this we need to wrap
- * ValidateGC and so all the other GC funcs must be wrapped as well.
- */
-/****************************************************************************/
-
-#define GC_FUNC_PROLOGUE(pGC) \
- rfbGCPtr pGCPriv = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \
- (pGC)->funcs = pGCPriv->wrapFuncs; \
- if (pGCPriv->wrapOps) \
- (pGC)->ops = pGCPriv->wrapOps;
-
-#define GC_FUNC_EPILOGUE(pGC) \
- pGCPriv->wrapFuncs = (pGC)->funcs; \
- (pGC)->funcs = &rfbGCFuncs; \
- if (pGCPriv->wrapOps) { \
- pGCPriv->wrapOps = (pGC)->ops; \
- (pGC)->ops = &rfbGCOps; \
- }
-
-
-/*
- * ValidateGC - call the wrapped ValidateGC, then wrap the resulting GC ops if
- * the drawing will be to a viewable window.
- */
-
-static void
-rfbValidateGC (pGC, changes, pDrawable)
- GCPtr pGC;
- unsigned long changes;
- DrawablePtr pDrawable;
-{
- GC_FUNC_PROLOGUE(pGC);
-
- TRC(("rfbValidateGC called\n"));
-
- (*pGC->funcs->ValidateGC) (pGC, changes, pDrawable);
-
- pGCPriv->wrapOps = NULL;
- if (pDrawable->type == DRAWABLE_WINDOW && ((WindowPtr)pDrawable)->viewable)
- {
- WindowPtr pWin = (WindowPtr) pDrawable;
- RegionPtr pRegion = &pWin->clipList;
-
- if (pGC->subWindowMode == IncludeInferiors)
- pRegion = &pWin->borderClip;
- if (REGION_NOTEMPTY(pDrawable->pScreen, pRegion)) {
- pGCPriv->wrapOps = pGC->ops;
- TRC(("rfbValidateGC: wrapped GC ops\n"));
- }
- }
-
- GC_FUNC_EPILOGUE(pGC);
-}
-
-/*
- * All other GC funcs simply unwrap the GC funcs and ops, call the wrapped
- * function and then rewrap the funcs and ops.
- */
-
-static void
-rfbChangeGC (pGC, mask)
- GCPtr pGC;
- unsigned long mask;
-{
- GC_FUNC_PROLOGUE(pGC);
- (*pGC->funcs->ChangeGC) (pGC, mask);
- GC_FUNC_EPILOGUE(pGC);
-}
-
-static void
-rfbCopyGC (pGCSrc, mask, pGCDst)
- GCPtr pGCSrc, pGCDst;
- unsigned long mask;
-{
- GC_FUNC_PROLOGUE(pGCDst);
- (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
- GC_FUNC_EPILOGUE(pGCDst);
-}
-
-static void
-rfbDestroyGC (pGC)
- GCPtr pGC;
-{
- GC_FUNC_PROLOGUE(pGC);
- (*pGC->funcs->DestroyGC) (pGC);
- GC_FUNC_EPILOGUE(pGC);
-}
-
-static void
-rfbChangeClip (pGC, type, pvalue, nrects)
- GCPtr pGC;
- int type;
- pointer pvalue;
- int nrects;
-{
- GC_FUNC_PROLOGUE(pGC);
- (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
- GC_FUNC_EPILOGUE(pGC);
-}
-
-static void
-rfbDestroyClip(pGC)
- GCPtr pGC;
-{
- GC_FUNC_PROLOGUE(pGC);
- (* pGC->funcs->DestroyClip)(pGC);
- GC_FUNC_EPILOGUE(pGC);
-}
-
-static void
-rfbCopyClip(pgcDst, pgcSrc)
- GCPtr pgcDst, pgcSrc;
-{
- GC_FUNC_PROLOGUE(pgcDst);
- (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
- GC_FUNC_EPILOGUE(pgcDst);
-}
-
-
-/****************************************************************************/
-/*
- * GC ops wrapper stuff
- *
- * Note that these routines will only have been wrapped for drawing to
- * viewable windows so we don't need to check each time that the drawable
- * is a viewable window.
- */
-/****************************************************************************/
-
-#define GC_OP_PROLOGUE(pDrawable,pGC) \
- rfbScreenInfoPtr prfb = &rfbScreen; \
- rfbGCPtr pGCPrivate = (rfbGCPtr) (pGC)->devPrivates[rfbGCIndex].ptr; \
- GCFuncs *oldFuncs = pGC->funcs; \
- (pGC)->funcs = pGCPrivate->wrapFuncs; \
- (pGC)->ops = pGCPrivate->wrapOps;
-
-#define GC_OP_EPILOGUE(pGC) \
- pGCPrivate->wrapOps = (pGC)->ops; \
- (pGC)->funcs = oldFuncs; \
- (pGC)->ops = &rfbGCOps;
-
-
-/*
- * FillSpans - being very safe - the region being modified is the border clip
- * region of the window.
- */
-
-static void
-rfbFillSpans(pDrawable, pGC, nInit, pptInit, pwidthInit, fSorted)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int nInit; /* number of spans to fill */
- DDXPointPtr pptInit; /* pointer to list of start points */
- int *pwidthInit; /* pointer to list of n widths */
- int fSorted;
-{
- GC_OP_PROLOGUE(pDrawable,pGC);
-
- TRC(("rfbFillSpans called\n"));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen,
- &((WindowPtr)pDrawable)->borderClip);
-
- (*pGC->ops->FillSpans) (pDrawable, pGC, nInit, pptInit,pwidthInit,fSorted);
-
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * SetSpans - being very safe - the region being modified is the border clip
- * region of the window.
- */
-
-static void
-rfbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted)
- DrawablePtr pDrawable;
- GCPtr pGC;
- char *psrc;
- register DDXPointPtr ppt;
- int *pwidth;
- int nspans;
- int fSorted;
-{
- GC_OP_PROLOGUE(pDrawable,pGC);
-
- TRC(("rfbSetSpans called\n"));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen,
- &((WindowPtr)pDrawable)->borderClip);
-
- (*pGC->ops->SetSpans) (pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
-
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PutImage - the region being modified is the rectangle of the
- * PutImage (clipped to the window clip region).
- */
-
-static void
-rfbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format, pBits)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int depth;
- int x;
- int y;
- int w;
- int h;
- int leftPad;
- int format;
- char *pBits;
-{
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPutImage called\n"));
-
- box.x1 = x + pDrawable->x;
- box.y1 = y + pDrawable->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDrawable,pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
-
- (*pGC->ops->PutImage) (pDrawable, pGC, depth, x, y, w, h,
- leftPad, format, pBits);
-
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * CopyArea - the region being modified is the destination rectangle (clipped
- * to the window clip region).
- * If the client will accept CopyRect messages then use rfbCopyRegion
- * to optimise the pending screen changes into a single "copy region" plus
- * the ordinary modified region.
- */
-
-static RegionPtr
-rfbCopyArea (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty)
- DrawablePtr pSrc;
- DrawablePtr pDst;
- GCPtr pGC;
- int srcx;
- int srcy;
- int w;
- int h;
- int dstx;
- int dsty;
-{
- rfbClientPtr cl;
- RegionPtr rgn;
- RegionRec srcRegion, dstRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDst, pGC);
-
- TRC(("rfbCopyArea called\n"));
-
- box.x1 = dstx + pDst->x;
- box.y1 = dsty + pDst->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- SAFE_REGION_INIT(pDst->pScreen, &dstRegion, &box, 0);
- REGION_INTERSECT(pDst->pScreen, &dstRegion, &dstRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDst,pGC));
-
- if ((pSrc->type == DRAWABLE_WINDOW) && (pSrc->pScreen == pDst->pScreen)) {
- box.x1 = srcx + pSrc->x;
- box.y1 = srcy + pSrc->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- for (cl = rfbClientHead; cl; cl = cl->next) {
- if (cl->useCopyRect) {
- SAFE_REGION_INIT(pSrc->pScreen, &srcRegion, &box, 0);
- REGION_INTERSECT(pSrc->pScreen, &srcRegion, &srcRegion,
- &((WindowPtr)pSrc)->clipList);
-
- rfbCopyRegion(pSrc->pScreen, cl, &srcRegion, &dstRegion,
- dstx + pDst->x - srcx - pSrc->x,
- dsty + pDst->y - srcy - pSrc->y);
-
- REGION_UNINIT(pSrc->pScreen, &srcRegion);
-
- } else {
-
- REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
- &dstRegion);
- }
- }
-
- } else {
-
- ADD_TO_MODIFIED_REGION(pDst->pScreen, &dstRegion);
- }
-
- REGION_UNINIT(pDst->pScreen, &dstRegion);
-
- rgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, srcx, srcy, w, h,
- dstx, dsty);
-
- SCHEDULE_FB_UPDATE(pDst->pScreen, prfb);
-
- GC_OP_EPILOGUE(pGC);
-
- return rgn;
-}
-
-
-/*
- * CopyPlane - the region being modified is the destination rectangle (clipped
- * to the window clip region).
- */
-
-static RegionPtr
-rfbCopyPlane (pSrc, pDst, pGC, srcx, srcy, w, h, dstx, dsty, plane)
- DrawablePtr pSrc;
- DrawablePtr pDst;
- register GCPtr pGC;
- int srcx,
- srcy;
- int w,
- h;
- int dstx,
- dsty;
- unsigned long plane;
-{
- RegionPtr rgn;
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDst, pGC);
-
- TRC(("rfbCopyPlane called\n"));
-
- box.x1 = dstx + pDst->x;
- box.y1 = dsty + pDst->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- SAFE_REGION_INIT(pDst->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDst->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDst,pGC));
-
- ADD_TO_MODIFIED_REGION(pDst->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDst->pScreen, &tmpRegion);
-
- rgn = (*pGC->ops->CopyPlane) (pSrc, pDst, pGC, srcx, srcy, w, h,
- dstx, dsty, plane);
-
- SCHEDULE_FB_UPDATE(pDst->pScreen, prfb);
-
- GC_OP_EPILOGUE(pGC);
-
- return rgn;
-}
-
-/*
- * PolyPoint - find the smallest rectangle which encloses the points drawn
- * (and clip).
- */
-
-static void
-rfbPolyPoint (pDrawable, pGC, mode, npt, pts)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int mode; /* Origin or Previous */
- int npt;
- xPoint *pts;
-{
- int i;
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolyPoint called: %d points\n",npt));
-
- if (npt) {
- int minX = pts[0].x, maxX = pts[0].x;
- int minY = pts[0].y, maxY = pts[0].y;
-
- if (mode == CoordModePrevious)
- {
- int x = pts[0].x, y = pts[0].y;
-
- for (i = 1; i < npt; i++) {
- x += pts[i].x;
- y += pts[i].y;
- if (x < minX) minX = x;
- if (x > maxX) maxX = x;
- if (y < minY) minY = y;
- if (y > maxY) maxY = y;
- }
- }
- else
- {
- for (i = 1; i < npt; i++) {
- if (pts[i].x < minX) minX = pts[i].x;
- if (pts[i].x > maxX) maxX = pts[i].x;
- if (pts[i].y < minY) minY = pts[i].y;
- if (pts[i].y > maxY) maxY = pts[i].y;
- }
- }
-
- box.x1 = minX + pDrawable->x;
- box.y1 = minY + pDrawable->y;
- box.x2 = maxX + 1 + pDrawable->x;
- box.y2 = maxY + 1 + pDrawable->y;
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
- }
-
- (*pGC->ops->PolyPoint) (pDrawable, pGC, mode, npt, pts);
-
- if (npt) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PolyLines - take the union of bounding boxes around each line (and clip).
- */
-
-static void
-rfbPolylines (pDrawable, pGC, mode, npt, ppts)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int mode;
- int npt;
- DDXPointPtr ppts;
-{
- RegionPtr tmpRegion;
- xRectangle regRects[MAX_RECTS_PER_OP];
- int i, extra, nregRects, lw;
- int prevX, prevY, curX, curY;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolylines called: %d points\n",npt));
-
- if (npt) {
- lw = pGC->lineWidth;
- if (lw == 0)
- lw = 1;
-
- if (npt == 1)
- {
- nregRects = 1;
- regRects[0].x = ppts[0].x - lw + pDrawable->x; /* being safe */
- regRects[0].y = ppts[0].y - lw + pDrawable->y;
- regRects[0].width = 2*lw;
- regRects[0].height = 2*lw;
- }
- else
- {
- nregRects = npt - 1;
-
- /*
- * mitered joins can project quite a way from
- * the line end; the 11 degree miter limit limits
- * this extension to lw / (2 * tan(11/2)), rounded up
- * and converted to int yields 6 * lw
- */
-
- if (pGC->joinStyle == JoinMiter) {
- extra = 6 * lw;
- } else {
- extra = lw / 2;
- }
-
- prevX = ppts[0].x + pDrawable->x;
- prevY = ppts[0].y + pDrawable->y;
- minX = maxX = prevX;
- minY = maxY = prevY;
-
- for (i = 0; i < nregRects; i++) {
- if (mode == CoordModeOrigin) {
- curX = pDrawable->x + ppts[i+1].x;
- curY = pDrawable->y + ppts[i+1].y;
- } else {
- curX = prevX + ppts[i+1].x;
- curY = prevY + ppts[i+1].y;
- }
-
- if (prevX > curX) {
- rectX1 = curX - extra;
- rectX2 = prevX + extra + 1;
- } else {
- rectX1 = prevX - extra;
- rectX2 = curX + extra + 1;
- }
-
- if (prevY > curY) {
- rectY1 = curY - extra;
- rectY2 = prevY + extra + 1;
- } else {
- rectY1 = prevY - extra;
- rectY2 = curY + extra + 1;
- }
-
- if (nregRects <= MAX_RECTS_PER_OP) {
- regRects[i].x = rectX1;
- regRects[i].y = rectY1;
- regRects[i].width = rectX2 - rectX1;
- regRects[i].height = rectY2 - rectY1;
- } else {
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
-
- prevX = curX;
- prevY = curY;
- }
-
- if (nregRects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nregRects = 1;
- }
- }
-
- tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nregRects, regRects,
- CT_NONE);
- REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDrawable,pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
-
- REGION_DESTROY(pDrawable->pScreen, tmpRegion);
- }
-
- (*pGC->ops->Polylines) (pDrawable, pGC, mode, npt, ppts);
-
- if (npt) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PolySegment - take the union of bounding boxes around each segment (and
- * clip).
- */
-
-static void
-rfbPolySegment(pDrawable, pGC, nseg, segs)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int nseg;
- xSegment *segs;
-{
- RegionPtr tmpRegion;
- xRectangle regRects[MAX_RECTS_PER_OP];
- int i, extra, lw, nregRects;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
-
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolySegment called: %d segments\n",nseg));
-
- if (nseg) {
- nregRects = nseg;
- lw = pGC->lineWidth;
- extra = lw / 2;
-
- minX = maxX = segs[0].x1;
- minY = maxY = segs[0].y1;
-
- for (i = 0; i < nseg; i++)
- {
- if (segs[i].x1 > segs[i].x2) {
- rectX1 = pDrawable->x + segs[i].x2 - extra;
- rectX2 = pDrawable->x + segs[i].x1 + extra + 1;
- } else {
- rectX1 = pDrawable->x + segs[i].x1 - extra;
- rectX2 = pDrawable->x + segs[i].x2 + extra + 1;
- }
-
- if (segs[i].y1 > segs[i].y2) {
- rectY1 = pDrawable->y + segs[i].y2 - extra;
- rectY2 = pDrawable->y + segs[i].y1 + extra + 1;
- } else {
- rectY1 = pDrawable->y + segs[i].y1 - extra;
- rectY2 = pDrawable->y + segs[i].y2 + extra + 1;
- }
-
- if (nseg <= MAX_RECTS_PER_OP) {
- regRects[i].x = rectX1;
- regRects[i].y = rectY1;
- regRects[i].width = rectX2 - rectX1;
- regRects[i].height = rectY2 - rectY1;
- } else {
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nseg > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nregRects = 1;
- }
-
- tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nregRects, regRects,
- CT_NONE);
- REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDrawable,pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
-
- REGION_DESTROY(pDrawable->pScreen, tmpRegion);
- }
-
- (*pGC->ops->PolySegment) (pDrawable, pGC, nseg, segs);
-
- if (nseg) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PolyRectangle (rectangle outlines) - take the union of bounding boxes
- * around each line (and clip).
- */
-
-static void
-rfbPolyRectangle(pDrawable, pGC, nrects, rects)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int nrects;
- xRectangle *rects;
-{
- int i, extra, lw, nregRects;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
- RegionPtr tmpRegion;
- xRectangle regRects[MAX_RECTS_PER_OP*4];
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolyRectangle called: %d rects\n",nrects));
-
- if (nrects) {
- nregRects = nrects * 4;
- lw = pGC->lineWidth;
- extra = lw / 2;
-
- minX = maxX = rects[0].x;
- minY = maxY = rects[0].y;
-
- for (i = 0; i < nrects; i++)
- {
- if (nrects <= MAX_RECTS_PER_OP) {
- regRects[i*4].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4].width = rects[i].width + 1 + 2 * extra;
- regRects[i*4].height = 1 + 2 * extra;
-
- regRects[i*4+1].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4+1].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4+1].width = 1 + 2 * extra;
- regRects[i*4+1].height = rects[i].height + 1 + 2 * extra;
-
- regRects[i*4+2].x
- = rects[i].x + rects[i].width - extra + pDrawable->x;
- regRects[i*4+2].y = rects[i].y - extra + pDrawable->y;
- regRects[i*4+2].width = 1 + 2 * extra;
- regRects[i*4+2].height = rects[i].height + 1 + 2 * extra;
-
- regRects[i*4+3].x = rects[i].x - extra + pDrawable->x;
- regRects[i*4+3].y
- = rects[i].y + rects[i].height - extra + pDrawable->y;
- regRects[i*4+3].width = rects[i].width + 1 + 2 * extra;
- regRects[i*4+3].height = 1 + 2 * extra;
- } else {
- rectX1 = pDrawable->x + rects[i].x - extra;
- rectY1 = pDrawable->y + rects[i].y - extra;
- rectX2 = pDrawable->x + rects[i].x + rects[i].width + extra+1;
- rectY2 = pDrawable->y + rects[i].y + rects[i].height + extra+1;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nrects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nregRects = 1;
- }
-
- tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nregRects,
- regRects, CT_NONE);
- REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDrawable,pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
-
- REGION_DESTROY(pDrawable->pScreen, tmpRegion);
- }
-
- (*pGC->ops->PolyRectangle) (pDrawable, pGC, nrects, rects);
-
- if (nrects) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PolyArc - take the union of bounding boxes around each arc (and clip).
- * Bounding boxes assume each is a full circle / ellipse.
- */
-
-static void
-rfbPolyArc(pDrawable, pGC, narcs, arcs)
- DrawablePtr pDrawable;
- register GCPtr pGC;
- int narcs;
- xArc *arcs;
-{
- int i, extra, lw, nregRects;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
- RegionPtr tmpRegion;
- xRectangle regRects[MAX_RECTS_PER_OP];
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolyArc called: %d arcs\n",narcs));
-
- if (narcs) {
- nregRects = narcs;
- lw = pGC->lineWidth;
- if (lw == 0)
- lw = 1;
- extra = lw / 2;
-
- minX = maxX = arcs[0].x;
- minY = maxY = arcs[0].y;
-
- for (i = 0; i < narcs; i++)
- {
- if (narcs <= MAX_RECTS_PER_OP) {
- regRects[i].x = arcs[i].x - extra + pDrawable->x;
- regRects[i].y = arcs[i].y - extra + pDrawable->y;
- regRects[i].width = arcs[i].width + lw;
- regRects[i].height = arcs[i].height + lw;
- } else {
- rectX1 = pDrawable->x + arcs[i].x - extra;
- rectY1 = pDrawable->y + arcs[i].y - extra;
- rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
- rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (narcs > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nregRects = 1;
- }
-
- tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nregRects, regRects,
- CT_NONE);
- REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDrawable,pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
-
- REGION_DESTROY(pDrawable->pScreen, tmpRegion);
- }
-
- (*pGC->ops->PolyArc) (pDrawable, pGC, narcs, arcs);
-
- if (narcs) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * FillPolygon - take bounding box around polygon (and clip).
- */
-
-static void
-rfbFillPolygon(pDrawable, pGC, shape, mode, count, pts)
- register DrawablePtr pDrawable;
- register GCPtr pGC;
- int shape, mode;
- int count;
- DDXPointPtr pts;
-{
- int i;
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbFillPolygon called\n"));
-
- if (count) {
- int minX = pts[0].x, maxX = pts[0].x;
- int minY = pts[0].y, maxY = pts[0].y;
-
- if (mode == CoordModePrevious)
- {
- int x = pts[0].x, y = pts[0].y;
-
- for (i = 1; i < count; i++) {
- x += pts[i].x;
- y += pts[i].y;
- if (x < minX) minX = x;
- if (x > maxX) maxX = x;
- if (y < minY) minY = y;
- if (y > maxY) maxY = y;
- }
- }
- else
- {
- for (i = 1; i < count; i++) {
- if (pts[i].x < minX) minX = pts[i].x;
- if (pts[i].x > maxX) maxX = pts[i].x;
- if (pts[i].y < minY) minY = pts[i].y;
- if (pts[i].y > maxY) maxY = pts[i].y;
- }
- }
-
- box.x1 = minX + pDrawable->x;
- box.y1 = minY + pDrawable->y;
- box.x2 = maxX + 1 + pDrawable->x;
- box.y2 = maxY + 1 + pDrawable->y;
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
- }
-
- (*pGC->ops->FillPolygon) (pDrawable, pGC, shape, mode, count, pts);
-
- if (count) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PolyFillRect - take the union of the given rectangles (and clip).
- */
-
-static void
-rfbPolyFillRect(pDrawable, pGC, nrects, rects)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int nrects;
- xRectangle *rects;
-{
- RegionPtr tmpRegion;
- xRectangle regRects[MAX_RECTS_PER_OP];
- int i, nregRects;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolyFillRect called: %d rects\n",nrects));
-
- if (nrects) {
- nregRects = nrects;
-
- minX = maxX = rects[0].x;
- minY = maxY = rects[0].y;
-
- for (i = 0; i < nrects; i++) {
- if (nrects <= MAX_RECTS_PER_OP) {
- regRects[i].x = rects[i].x + pDrawable->x;
- regRects[i].y = rects[i].y + pDrawable->y;
- regRects[i].width = rects[i].width;
- regRects[i].height = rects[i].height;
- } else {
- rectX1 = pDrawable->x + rects[i].x;
- rectY1 = pDrawable->y + rects[i].y;
- rectX2 = pDrawable->x + rects[i].x + rects[i].width;
- rectY2 = pDrawable->y + rects[i].y + rects[i].height;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (nrects > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nregRects = 1;
- }
-
- tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nregRects, regRects,
- CT_NONE);
- REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDrawable,pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
-
- REGION_DESTROY(pDrawable->pScreen, tmpRegion);
- }
-
- (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, rects);
-
- if (nrects) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PolyFillArc - take the union of bounding boxes around each arc (and clip).
- * Bounding boxes assume each is a full circle / ellipse.
- */
-
-static void
-rfbPolyFillArc(pDrawable, pGC, narcs, arcs)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int narcs;
- xArc *arcs;
-{
- int i, extra, lw, nregRects;
- int rectX1, rectY1, rectX2, rectY2;
- int minX, minY, maxX, maxY;
- RegionPtr tmpRegion;
- xRectangle regRects[MAX_RECTS_PER_OP];
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolyFillArc called: %d arcs\n",narcs));
-
- if (narcs) {
- nregRects = narcs;
- lw = pGC->lineWidth;
- if (lw == 0)
- lw = 1;
- extra = lw / 2;
-
- minX = maxX = arcs[0].x;
- minY = maxY = arcs[0].y;
-
- for (i = 0; i < narcs; i++)
- {
- if (narcs <= MAX_RECTS_PER_OP) {
- regRects[i].x = arcs[i].x - extra + pDrawable->x;
- regRects[i].y = arcs[i].y - extra + pDrawable->y;
- regRects[i].width = arcs[i].width + lw;
- regRects[i].height = arcs[i].height + lw;
- } else {
- rectX1 = pDrawable->x + arcs[i].x - extra;
- rectY1 = pDrawable->y + arcs[i].y - extra;
- rectX2 = pDrawable->x + arcs[i].x + arcs[i].width + lw;
- rectY2 = pDrawable->y + arcs[i].y + arcs[i].height + lw;
- if (rectX1 < minX) minX = rectX1;
- if (rectY1 < minY) minY = rectY1;
- if (rectX2 > maxX) maxX = rectX2;
- if (rectY2 > maxY) maxY = rectY2;
- }
- }
-
- if (narcs > MAX_RECTS_PER_OP) {
- regRects[0].x = minX;
- regRects[0].y = minY;
- regRects[0].width = maxX - minX;
- regRects[0].height = maxY - minY;
- nregRects = 1;
- }
-
- tmpRegion = RECTS_TO_REGION(pDrawable->pScreen, nregRects, regRects,
- CT_NONE);
- REGION_INTERSECT(pDrawable->pScreen, tmpRegion, tmpRegion,
- WINDOW_CLIP_REGION((WindowPtr)pDrawable,pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, tmpRegion);
-
- REGION_DESTROY(pDrawable->pScreen, tmpRegion);
- }
-
- (*pGC->ops->PolyFillArc) (pDrawable, pGC, narcs, arcs);
-
- if (narcs) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * Get a rough bounding box around n characters of the given font.
- */
-
-static void GetTextBoundingBox(pDrawable, font, x, y, n, pbox)
- DrawablePtr pDrawable;
- FontPtr font;
- int x, y, n;
- BoxPtr pbox;
-{
- int maxAscent, maxDescent, maxCharWidth;
-
- if (FONTASCENT(font) > FONTMAXBOUNDS(font,ascent))
- maxAscent = FONTASCENT(font);
- else
- maxAscent = FONTMAXBOUNDS(font,ascent);
-
- if (FONTDESCENT(font) > FONTMAXBOUNDS(font,descent))
- maxDescent = FONTDESCENT(font);
- else
- maxDescent = FONTMAXBOUNDS(font,descent);
-
- if (FONTMAXBOUNDS(font,rightSideBearing) > FONTMAXBOUNDS(font,characterWidth))
- maxCharWidth = FONTMAXBOUNDS(font,rightSideBearing);
- else
- maxCharWidth = FONTMAXBOUNDS(font,characterWidth);
-
- pbox->x1 = pDrawable->x + x;
- pbox->y1 = pDrawable->y + y - maxAscent;
- pbox->x2 = pbox->x1 + maxCharWidth * n;
- pbox->y2 = pbox->y1 + maxAscent + maxDescent;
-
- if (FONTMINBOUNDS(font,leftSideBearing) < 0) {
- pbox->x1 += FONTMINBOUNDS(font,leftSideBearing);
- }
-}
-
-
-/*
- * PolyText8 - use rough bounding box.
- */
-
-static int
-rfbPolyText8(pDrawable, pGC, x, y, count, chars)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int x, y;
- int count;
- char *chars;
-{
- int ret;
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolyText8 called '%.*s'\n",count,chars));
-
- if (count) {
- GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
- }
-
- ret = (*pGC->ops->PolyText8) (pDrawable, pGC, x, y, count, chars);
-
- if (count) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
- return ret;
-}
-
-/*
- * PolyText16 - use rough bounding box.
- */
-
-static int
-rfbPolyText16(pDrawable, pGC, x, y, count, chars)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int x, y;
- int count;
- unsigned short *chars;
-{
- int ret;
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolyText16 called\n"));
-
- if (count) {
- GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
- }
-
- ret = (*pGC->ops->PolyText16) (pDrawable, pGC, x, y, count, chars);
-
- if (count) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
- return ret;
-}
-
-/*
- * ImageText8 - use rough bounding box.
- */
-
-static void
-rfbImageText8(pDrawable, pGC, x, y, count, chars)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int x, y;
- int count;
- char *chars;
-{
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbImageText8 called '%.*s'\n",count,chars));
-
- if (count) {
- GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
- }
-
- (*pGC->ops->ImageText8) (pDrawable, pGC, x, y, count, chars);
-
- if (count) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * ImageText16 - use rough bounding box.
- */
-
-static void
-rfbImageText16(pDrawable, pGC, x, y, count, chars)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int x, y;
- int count;
- unsigned short *chars;
-{
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbImageText16 called\n"));
-
- if (count) {
- GetTextBoundingBox(pDrawable, pGC->font, x, y, count, &box);
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
- }
-
- (*pGC->ops->ImageText16) (pDrawable, pGC, x, y, count, chars);
-
- if (count) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * ImageGlyphBlt - use rough bounding box.
- */
-
-static void
-rfbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int x, y;
- unsigned int nglyph;
- CharInfoPtr *ppci; /* array of character info */
- pointer pglyphBase; /* start of array of glyphs */
-{
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbImageGlyphBlt called\n"));
-
- if (nglyph) {
- GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box);
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
- }
-
- (*pGC->ops->ImageGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci,pglyphBase);
-
- if (nglyph) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PolyGlyphBlt - use rough bounding box.
- */
-
-static void
-rfbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase)
- DrawablePtr pDrawable;
- GCPtr pGC;
- int x, y;
- unsigned int nglyph;
- CharInfoPtr *ppci; /* array of character info */
- pointer pglyphBase; /* start of array of glyphs */
-{
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPolyGlyphBlt called\n"));
-
- if (nglyph) {
- GetTextBoundingBox(pDrawable, pGC->font, x, y, nglyph, &box);
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
- }
-
- (*pGC->ops->PolyGlyphBlt) (pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
-
- if (nglyph) {
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
- }
-
- GC_OP_EPILOGUE(pGC);
-}
-
-/*
- * PushPixels - be fairly safe - region modified is intersection of the given
- * rectangle with the window clip region.
- */
-
-static void
-rfbPushPixels(pGC, pBitMap, pDrawable, w, h, x, y)
- GCPtr pGC;
- PixmapPtr pBitMap;
- DrawablePtr pDrawable;
- int w, h, x, y;
-{
- RegionRec tmpRegion;
- BoxRec box;
- GC_OP_PROLOGUE(pDrawable, pGC);
-
- TRC(("rfbPushPixels called\n"));
-
- box.x1 = x + pDrawable->x;
- box.y1 = y + pDrawable->y;
- box.x2 = box.x1 + w;
- box.y2 = box.y1 + h;
-
- SAFE_REGION_INIT(pDrawable->pScreen, &tmpRegion, &box, 0);
-
- REGION_INTERSECT(pDrawable->pScreen, &tmpRegion, &tmpRegion,
- WINDOW_CLIP_REGION(((WindowPtr)pDrawable),pGC));
-
- ADD_TO_MODIFIED_REGION(pDrawable->pScreen, &tmpRegion);
-
- REGION_UNINIT(pDrawable->pScreen, &tmpRegion);
-
- (*pGC->ops->PushPixels) (pGC, pBitMap, pDrawable, w, h, x, y);
-
- SCHEDULE_FB_UPDATE(pDrawable->pScreen, prfb);
-
- GC_OP_EPILOGUE(pGC);
-}
-
-
-
-/****************************************************************************/
-/*
- * Other functions
- */
-/****************************************************************************/
-
-/*
- * rfbCopyRegion. Args are src and dst regions plus a translation (dx,dy).
- * Takes these args together with the existing modified region and possibly an
- * existing copy region and translation. Produces a combined modified region
- * plus copy region and translation. Note that the copy region is the
- * destination of the copy.
- *
- * First we trim parts of src which are invalid (ie in the modified region).
- * Then we see if there is any overlap between the src and the existing copy
- * region. If not then the two copies cannot be combined, so we choose
- * whichever is bigger to form the basis of a new copy, while the other copy is
- * just done the hard way by being added to the modified region. So if the
- * existing copy is bigger then we simply add the destination of the new copy
- * to the modified region and we're done. If the new copy is bigger, we add
- * the old copy region to the modified region and behave as though there is no
- * existing copy region.
- *
- * At this stage we now know that either the two copies can be combined, or
- * that there is no existing copy. We temporarily add both the existing copy
- * region and dst to the modified region (this is the entire area of the screen
- * affected in any way). Finally we calculate the new copy region, and remove
- * it from the modified region.
- *
- * Note:
- * 1. The src region is modified by this routine.
- * 2. When the copy region is empty, copyDX and copyDY MUST be set to zero.
- */
-
-static void
-rfbCopyRegion(pScreen, cl, src, dst, dx, dy)
- ScreenPtr pScreen;
- rfbClientPtr cl;
- RegionPtr src;
- RegionPtr dst;
- int dx, dy;
-{
- RegionRec tmp;
-
- /* src = src - modifiedRegion */
-
- REGION_SUBTRACT(pScreen, src, src, &cl->modifiedRegion);
-
- if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) {
-
- REGION_INIT(pScreen, &tmp, NullBox, 0);
- REGION_INTERSECT(pScreen, &tmp, src, &cl->copyRegion);
-
- if (REGION_NOTEMPTY(pScreen, &tmp)) {
-
- /* if src and copyRegion overlap:
- src = src intersect copyRegion */
-
- REGION_COPY(pScreen, src, &tmp);
-
- } else {
-
- /* if no overlap, find bigger region */
-
- int newArea = (((REGION_EXTENTS(pScreen,src))->x2
- - (REGION_EXTENTS(pScreen,src))->x1)
- * ((REGION_EXTENTS(pScreen,src))->y2
- - (REGION_EXTENTS(pScreen,src))->y1));
-
- int oldArea = (((REGION_EXTENTS(pScreen,&cl->copyRegion))->x2
- - (REGION_EXTENTS(pScreen,&cl->copyRegion))->x1)
- * ((REGION_EXTENTS(pScreen,&cl->copyRegion))->y2
- - (REGION_EXTENTS(pScreen,&cl->copyRegion))->y1));
-
- if (oldArea > newArea) {
-
- /* existing copy is bigger:
- modifiedRegion = modifiedRegion union dst
- copyRegion = copyRegion - dst
- return */
-
- REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
- dst);
- REGION_SUBTRACT(pScreen, &cl->copyRegion, &cl->copyRegion,
- dst);
- if (!REGION_NOTEMPTY(pScreen, &cl->copyRegion)) {
- cl->copyDX = 0;
- cl->copyDY = 0;
- }
- return;
- }
-
- /* new copy is bigger:
- modifiedRegion = modifiedRegion union copyRegion
- copyRegion = empty */
-
- REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
- &cl->copyRegion);
- REGION_EMPTY(pScreen, &cl->copyRegion);
- cl->copyDX = cl->copyDY = 0;
- }
- }
-
-
- /* modifiedRegion = modifiedRegion union dst union copyRegion */
-
- REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion, dst);
- REGION_UNION(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
- &cl->copyRegion);
-
- /* copyRegion = T(src) intersect dst */
-
- REGION_TRANSLATE(pScreen, src, dx, dy);
- REGION_INTERSECT(pScreen, &cl->copyRegion, src, dst);
-
- /* modifiedRegion = modifiedRegion - copyRegion */
-
- REGION_SUBTRACT(pScreen, &cl->modifiedRegion, &cl->modifiedRegion,
- &cl->copyRegion);
-
- /* combine new translation T with existing translation */
-
- if (REGION_NOTEMPTY(pScreen, &cl->copyRegion)) {
- cl->copyDX += dx;
- cl->copyDY += dy;
- } else {
- cl->copyDX = 0;
- cl->copyDY = 0;
- }
-}
-
-
-/*
- * rfbDeferredUpdateCallback() is called when a client's deferredUpdateTimer
- * goes off.
- */
-
-static CARD32
-rfbDeferredUpdateCallback(OsTimerPtr timer, CARD32 now, pointer arg)
-{
- rfbClientPtr cl = (rfbClientPtr)arg;
-
- rfbSendFramebufferUpdate(cl);
-
- cl->deferredUpdateScheduled = FALSE;
- return 0;
-}
-
-
-/*
- * rfbScheduleDeferredUpdate() is called from the SCHEDULE_FB_UPDATE macro
- * to schedule an update.
- */
-
-void
-rfbScheduleDeferredUpdate(rfbClientPtr cl)
-{
- if (rfbDeferUpdateTime != 0) {
- cl->deferredUpdateTimer = TimerSet(cl->deferredUpdateTimer, 0,
- rfbDeferUpdateTime,
- rfbDeferredUpdateCallback, cl);
- cl->deferredUpdateScheduled = TRUE;
- } else {
- rfbSendFramebufferUpdate(cl);
- }
-}
-
-
-/*
- * PrintRegion is useful for debugging.
- */
-
-#if 0
-static void
-PrintRegion(pScreen,reg)
- ScreenPtr pScreen;
- RegionPtr reg;
-{
- int nrects = REGION_NUM_RECTS(reg);
- int i;
-
- rfbLog("Region num rects %d extents %d,%d %d,%d\n",nrects,
- (REGION_EXTENTS(pScreen,reg))->x1,
- (REGION_EXTENTS(pScreen,reg))->y1,
- (REGION_EXTENTS(pScreen,reg))->x2,
- (REGION_EXTENTS(pScreen,reg))->y2);
-
- for (i = 0; i < nrects; i++) {
- rfbLog(" rect %d,%d %dx%d\n",
- REGION_RECTS(reg)[i].x1,
- REGION_RECTS(reg)[i].y1,
- REGION_RECTS(reg)[i].x2-REGION_RECTS(reg)[i].x1,
- REGION_RECTS(reg)[i].y2-REGION_RECTS(reg)[i].y1);
- }
-}
-#endif