2040 lines
60 KiB
C
2040 lines
60 KiB
C
/**************************************************************************/
|
|
/* */
|
|
/* Copyright (c) 2001, 2011 NoMachine (http://www.nomachine.com) */
|
|
/* Copyright (c) 2008-2017 Oleksandr Shneyder <o.shneyder@phoca-gmbh.de> */
|
|
/* Copyright (c) 2011-2022 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>*/
|
|
/* Copyright (c) 2014-2019 Mihai Moldovan <ionic@ionic.de> */
|
|
/* Copyright (c) 2014-2022 Ulrich Sibiller <uli42@gmx.de> */
|
|
/* Copyright (c) 2015-2016 Qindel Group (http://www.qindel.com) */
|
|
/* */
|
|
/* NXAGENT, NX protocol compression and NX extensions to this software */
|
|
/* are copyright of the aforementioned persons and companies. */
|
|
/* */
|
|
/* Redistribution and use of the present software is allowed according */
|
|
/* to terms specified in the file LICENSE which comes in the source */
|
|
/* distribution. */
|
|
/* */
|
|
/* All rights reserved. */
|
|
/* */
|
|
/* NOTE: This software has received contributions from various other */
|
|
/* contributors, only the core maintainers and supporters are listed as */
|
|
/* copyright holders. Please contact us, if you feel you should be listed */
|
|
/* as copyright holder, as well. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
/*
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
#include "scrnintstr.h"
|
|
#include "resource.h"
|
|
#include "dixstruct.h"
|
|
#include "../../fb/fb.h"
|
|
|
|
#include "Agent.h"
|
|
#include "Composite.h"
|
|
#include "Display.h"
|
|
#include "Visual.h"
|
|
#include "Drawable.h"
|
|
#include "Pixmaps.h"
|
|
#include "GCs.h"
|
|
#include "Image.h"
|
|
#include "Font.h"
|
|
#include "Events.h"
|
|
#include "Client.h"
|
|
#include "Trap.h"
|
|
#include "Args.h"
|
|
#include "Screen.h"
|
|
#include "Utils.h"
|
|
|
|
#include "compext/Compext.h"
|
|
|
|
/*
|
|
* Set here the required log level.
|
|
*/
|
|
|
|
#define PANIC
|
|
#define WARNING
|
|
#undef TEST
|
|
#undef DEBUG
|
|
#undef DUMP
|
|
|
|
/*
|
|
* Temporarily set/reset the trap.
|
|
*/
|
|
|
|
static int nxagentSaveGCTrap;
|
|
|
|
#define SET_GC_TRAP() \
|
|
{ \
|
|
nxagentSaveGCTrap = nxagentGCTrap;\
|
|
\
|
|
nxagentGCTrap = True; \
|
|
}
|
|
|
|
#define RESET_GC_TRAP() \
|
|
{ \
|
|
nxagentGCTrap = nxagentSaveGCTrap; \
|
|
}
|
|
|
|
/*
|
|
* This is currently unused.
|
|
*/
|
|
|
|
RegionPtr nxagentBitBlitHelper(GC *pGC);
|
|
|
|
/*
|
|
* The NX agent implementation of the X server's graphics functions.
|
|
*/
|
|
|
|
void nxagentFillSpans(DrawablePtr pDrawable, GCPtr pGC, int nSpans,
|
|
xPoint *pPoints, int *pWidths, int fSorted)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to FillSpans on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
fbFillSpans(nxagentVirtualDrawable(pDrawable), pGC, nSpans, pPoints, pWidths, fSorted);
|
|
}
|
|
else
|
|
{
|
|
fbFillSpans(pDrawable, pGC, nSpans, pPoints, pWidths, fSorted);
|
|
}
|
|
}
|
|
|
|
void nxagentSetSpans(DrawablePtr pDrawable, GCPtr pGC, char *pSrc,
|
|
xPoint *pPoints, int *pWidths, int nSpans, int fSorted)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to SetSpans on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
fbSetSpans(nxagentVirtualDrawable(pDrawable), pGC, pSrc, pPoints, pWidths, nSpans, fSorted);
|
|
}
|
|
else
|
|
{
|
|
fbSetSpans(pDrawable, pGC, pSrc, pPoints, pWidths, nSpans, fSorted);
|
|
}
|
|
}
|
|
|
|
void nxagentGetSpans(DrawablePtr pDrawable, int maxWidth, xPoint *pPoints,
|
|
int *pWidths, int nSpans, char *pBuffer)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: going to GetSpans on FB pixmap [%p].\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
fbGetSpans(nxagentVirtualDrawable(pDrawable), maxWidth, pPoints, pWidths, nSpans, pBuffer);
|
|
}
|
|
else
|
|
{
|
|
fbGetSpans(pDrawable, maxWidth, pPoints, pWidths, nSpans, pBuffer);
|
|
}
|
|
}
|
|
|
|
void nxagentQueryBestSize(int class, unsigned short *pwidth,
|
|
unsigned short *pheight, ScreenPtr pScreen)
|
|
{
|
|
unsigned width, test;
|
|
|
|
switch(class)
|
|
{
|
|
case CursorShape:
|
|
if (*pwidth > pScreen->width)
|
|
*pwidth = pScreen->width;
|
|
if (*pheight > pScreen->height)
|
|
*pheight = pScreen->height;
|
|
break;
|
|
case TileShape:
|
|
case StippleShape:
|
|
width = *pwidth;
|
|
if (!width) break;
|
|
/* Return the closest power of two not less than what they gave me */
|
|
test = 0x80000000;
|
|
/* Find the highest 1 bit in the width given */
|
|
while(!(test & width))
|
|
test >>= 1;
|
|
/* If their number is greater than that, bump up to the next
|
|
* power of two */
|
|
if((test - 1) & width)
|
|
test <<= 1;
|
|
*pwidth = test;
|
|
/* We don't care what height they use */
|
|
break;
|
|
}
|
|
}
|
|
|
|
RegionPtr nxagentBitBlitHelper(GC *pGC)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentBitBlitHelper: Called for GC at [%p].\n", (void *) pGC);
|
|
#endif
|
|
|
|
/*
|
|
* Force NullRegion. We consider enough the graphics expose events
|
|
* generated internally by the nxagent server.
|
|
*/
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentBitBlitHelper: WARNING! Skipping check on exposures events.\n");
|
|
#endif
|
|
|
|
return NullRegion;
|
|
}
|
|
|
|
/*
|
|
* The deferring of X_RenderCompositeTrapezoids caused an ugly effect
|
|
* on pulldown menu: as the background may be not synchronized, the
|
|
* text floats in an invisible window. To avoid such effects, we use a
|
|
* system to guess if the destination target of a copy area is a
|
|
* popup, by assuming that those kind of windows use the override
|
|
* redirect property.
|
|
*/
|
|
|
|
Bool nxagentWindowIsPopup(DrawablePtr pDrawable)
|
|
{
|
|
if (pDrawable -> type != DRAWABLE_WINDOW)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
Bool windowIsPopup = False;
|
|
|
|
if (((WindowPtr) pDrawable) -> overrideRedirect == 1)
|
|
{
|
|
windowIsPopup = True;
|
|
}
|
|
else
|
|
{
|
|
WindowPtr parent = ((WindowPtr) pDrawable) -> parent;
|
|
|
|
/*
|
|
* Go up on the tree until a parent exists or 4 windows has been
|
|
* checked. This seems a good limit to up children's popup.
|
|
*/
|
|
|
|
int level = 0;
|
|
|
|
while (parent != NULL && ++level <= 4)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentWindowIsPopup: Window [%p] has parent [%p] in tree with OverrideRedirect [%d] "
|
|
" Level [%d].\n", (void *) pDrawable, (void *) parent, parent -> overrideRedirect, level);
|
|
#endif
|
|
|
|
if (parent -> overrideRedirect == 1)
|
|
{
|
|
windowIsPopup = True;
|
|
break;
|
|
}
|
|
|
|
parent = parent -> parent;
|
|
}
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentWindowIsPopup: Window [%p] %s to be a popup.\n", (void *) pDrawable,
|
|
windowIsPopup ? "seems" : "does not seem");
|
|
#endif
|
|
|
|
return windowIsPopup;
|
|
}
|
|
|
|
/*
|
|
* This function returns True if the XCopyArea request must be skipped.
|
|
*/
|
|
|
|
Bool nxagentDeferCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
|
|
GCPtr pGC, int srcx, int srcy, int width,
|
|
int height, int dstx, int dsty)
|
|
{
|
|
/*
|
|
* If the destination drawable is a popup window, we try to
|
|
* synchronize the source drawable to show a nice menu. Anyway if
|
|
* this synchronization breaks, the copy area is handled in the
|
|
* normal way.
|
|
*/
|
|
|
|
/*
|
|
FIXME: The popup could be synchronized with one single put image,
|
|
clipped to the corrupted region. As an intermediate step, the
|
|
pixmap to synchronize could be copied on a cleared scratch
|
|
pixmap, in order to have a solid color in the clipped regions.
|
|
*/
|
|
|
|
if (nxagentOption(DeferLevel) >= 2 &&
|
|
pSrcDrawable -> type == DRAWABLE_PIXMAP &&
|
|
nxagentPixmapContainTrapezoids((PixmapPtr) pSrcDrawable) == 1 &&
|
|
nxagentWindowIsPopup(pDstDrawable))
|
|
{
|
|
RegionPtr pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height);
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentDeferCopyArea: Copying to a popup menu. Source region [%d,%d,%d,%d].\n",
|
|
pSrcRegion -> extents.x1, pSrcRegion -> extents.y1,
|
|
pSrcRegion -> extents.x2, pSrcRegion -> extents.y2);
|
|
#endif
|
|
|
|
RegionRec corruptedRegion;
|
|
RegionInit(&corruptedRegion, NullBox, 1);
|
|
|
|
RegionIntersect(&corruptedRegion,
|
|
pSrcRegion, nxagentCorruptedRegion(pSrcDrawable));
|
|
|
|
if (!RegionNil(&corruptedRegion))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentDeferCopyArea: Forcing the synchronization of source drawable at [%p].\n",
|
|
(void *) pSrcDrawable);
|
|
#endif
|
|
|
|
nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion, EVENT_BREAK, NULL);
|
|
}
|
|
|
|
RegionUninit(&corruptedRegion);
|
|
|
|
nxagentFreeRegion(pSrcRegion);
|
|
|
|
if (nxagentDrawableStatus(pSrcDrawable) == Synchronized)
|
|
{
|
|
return False;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* We are going to decide if the source drawable must be
|
|
* synchronized before using it, or if the copy will be clipped to
|
|
* the synchronized source region.
|
|
*/
|
|
|
|
if ((pDstDrawable -> type == DRAWABLE_PIXMAP &&
|
|
nxagentOption(DeferLevel) > 0) || nxagentOption(DeferLevel) >= 3)
|
|
{
|
|
RegionPtr pClipRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy,
|
|
width, height);
|
|
|
|
/*
|
|
* We called this variable pCorruptedRegion because in the worst
|
|
* case the corrupted region will be equal to the destination
|
|
* region. The GC's clip mask is used to narrow the destination.
|
|
*/
|
|
|
|
RegionPtr pCorruptedRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty,
|
|
width, height);
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentDeferCopyArea: Copy area source region is [%d,%d,%d,%d].\n",
|
|
pClipRegion -> extents.x1, pClipRegion -> extents.y1,
|
|
pClipRegion -> extents.x2, pClipRegion -> extents.y2);
|
|
#endif
|
|
|
|
RegionSubtract(pClipRegion, pClipRegion, nxagentCorruptedRegion(pSrcDrawable));
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentDeferCopyArea: Usable copy area source region is [%d,%d,%d,%d].\n",
|
|
pClipRegion -> extents.x1, pClipRegion -> extents.y1,
|
|
pClipRegion -> extents.x2, pClipRegion -> extents.y2);
|
|
#endif
|
|
|
|
if (pGC -> clientClip == NULL || pGC -> clientClipType != CT_REGION)
|
|
{
|
|
#ifdef WARNING
|
|
|
|
if (pGC -> clientClipType != CT_NONE)
|
|
{
|
|
fprintf(stderr, "nxagentDeferCopyArea: WARNING! pGC [%p] has a clip type [%d].\n",
|
|
(void *) pGC, pGC -> clientClipType);
|
|
}
|
|
|
|
#endif
|
|
|
|
RegionTranslate(pClipRegion, dstx - srcx, dsty - srcy);
|
|
}
|
|
else
|
|
{
|
|
RegionRec tmpRegion;
|
|
RegionInit(&tmpRegion, NullBox, 1);
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentDeferCopyArea: Going to modify the original GC [%p] with clip mask "
|
|
"[%d,%d,%d,%d] and origin [%d,%d].\n",
|
|
(void *) pGC,
|
|
((RegionPtr) pGC -> clientClip) -> extents.x1, ((RegionPtr) pGC -> clientClip) -> extents.y1,
|
|
((RegionPtr) pGC -> clientClip) -> extents.x2, ((RegionPtr) pGC -> clientClip) -> extents.y2,
|
|
pGC -> clipOrg.x, pGC -> clipOrg.y);
|
|
#endif
|
|
|
|
RegionCopy(&tmpRegion, (RegionPtr) pGC -> clientClip);
|
|
|
|
if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0)
|
|
{
|
|
RegionTranslate(&tmpRegion, pGC -> clipOrg.x, pGC -> clipOrg.y);
|
|
}
|
|
|
|
RegionTranslate(pClipRegion, dstx - srcx, dsty - srcy);
|
|
|
|
RegionIntersect(pClipRegion, &tmpRegion, pClipRegion);
|
|
|
|
RegionUninit(&tmpRegion);
|
|
}
|
|
|
|
/*
|
|
* The corrupted region on the destination drawable is composed by
|
|
* the areas of the destination that we are not going to copy.
|
|
*/
|
|
|
|
RegionSubtract(pCorruptedRegion, pCorruptedRegion, pClipRegion);
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentDeferCopyArea: Recomputed clip region is [%d,%d,%d,%d][%d].\n",
|
|
pClipRegion -> extents.x1, pClipRegion -> extents.y1,
|
|
pClipRegion -> extents.x2, pClipRegion -> extents.y2,
|
|
RegionNumRects(pClipRegion));
|
|
|
|
fprintf(stderr, "nxagentDeferCopyArea: Inherited corrupted region is [%d,%d,%d,%d][%d].\n",
|
|
pCorruptedRegion -> extents.x1, pCorruptedRegion -> extents.y1,
|
|
pCorruptedRegion -> extents.x2, pCorruptedRegion -> extents.y2,
|
|
RegionNumRects(pCorruptedRegion));
|
|
#endif
|
|
|
|
/*
|
|
* The destination drawable inherits both the synchronized and the
|
|
* corrupted region.
|
|
*/
|
|
|
|
if (!RegionNil(pClipRegion))
|
|
{
|
|
nxagentUnmarkCorruptedRegion(pDstDrawable, pClipRegion);
|
|
}
|
|
|
|
if (!RegionNil(pCorruptedRegion))
|
|
{
|
|
nxagentMarkCorruptedRegion(pDstDrawable, pCorruptedRegion);
|
|
}
|
|
|
|
if (!RegionNil(pClipRegion))
|
|
{
|
|
Bool pClipRegionFree = True;
|
|
|
|
/*
|
|
* As we want to copy only the synchronized areas of the source
|
|
* drawable, we create a new GC copying the original one and
|
|
* setting a new clip mask.
|
|
*/
|
|
|
|
GCPtr targetGC = GetScratchGC(pDstDrawable -> depth, pDstDrawable -> pScreen);
|
|
|
|
ValidateGC(pDstDrawable, targetGC);
|
|
|
|
CopyGC(pGC, targetGC, GCFunction | GCPlaneMask | GCSubwindowMode |
|
|
GCClipXOrigin | GCClipYOrigin | GCClipMask | GCForeground |
|
|
GCBackground | GCGraphicsExposures);
|
|
|
|
if (RegionNumRects(pClipRegion) == 1)
|
|
{
|
|
/*
|
|
* If the region to copy is formed by one rectangle, we change
|
|
* only the copy coordinates.
|
|
*/
|
|
|
|
srcx = srcx + pClipRegion -> extents.x1 - dstx;
|
|
srcy = srcy + pClipRegion -> extents.y1 - dsty;
|
|
|
|
dstx = pClipRegion -> extents.x1;
|
|
dsty = pClipRegion -> extents.y1;
|
|
|
|
width = pClipRegion -> extents.x2 - pClipRegion -> extents.x1;
|
|
height = pClipRegion -> extents.y2 - pClipRegion -> extents.y1;
|
|
}
|
|
else
|
|
{
|
|
CARD32 targetAttributes[2];
|
|
|
|
/*
|
|
* Setting the clip mask origin. This operation must precede
|
|
* the clip change, because the origin information is used in
|
|
* the XSetClipRectangles().
|
|
*/
|
|
|
|
targetAttributes[0] = 0;
|
|
targetAttributes[1] = 0;
|
|
|
|
ChangeGC(targetGC, GCClipXOrigin | GCClipYOrigin, targetAttributes);
|
|
|
|
/*
|
|
* Setting the new clip mask.
|
|
*/
|
|
|
|
nxagentChangeClip(targetGC, CT_REGION, pClipRegion, 0);
|
|
|
|
/*
|
|
* Next call to nxagentChangeClip() will destroy pClipRegion,
|
|
* so it has not to be freed.
|
|
*/
|
|
|
|
pClipRegionFree = False;
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentDeferCopyArea: Going to execute a copy area with clip mask "
|
|
"[%d,%d,%d,%d] and origin [%d,%d].\n", ((RegionPtr) targetGC -> clientClip) -> extents.x1,
|
|
((RegionPtr) targetGC -> clientClip) -> extents.y1,
|
|
((RegionPtr) targetGC -> clientClip) -> extents.x2,
|
|
((RegionPtr) targetGC -> clientClip) -> extents.y2,
|
|
targetGC -> clipOrg.x, targetGC -> clipOrg.y);
|
|
#endif
|
|
}
|
|
|
|
XCopyArea(nxagentDisplay, nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable),
|
|
nxagentGC(targetGC), srcx, srcy, width, height, dstx, dsty);
|
|
|
|
nxagentChangeClip(targetGC, CT_NONE, NullRegion, 0);
|
|
|
|
if (pClipRegionFree)
|
|
{
|
|
nxagentFreeRegion(pClipRegion);
|
|
}
|
|
|
|
FreeScratchGC(targetGC);
|
|
}
|
|
else
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentDeferCopyArea: The clipped region is NIL. CopyArea skipped.\n");
|
|
#endif
|
|
|
|
/*
|
|
* The pClipRegion is destroyed calling nxagentChangeClip(), so
|
|
* we deallocate it explicitly only if we don't change the clip.
|
|
*/
|
|
|
|
nxagentFreeRegion(pClipRegion);
|
|
}
|
|
|
|
nxagentFreeRegion(pCorruptedRegion);
|
|
|
|
return True;
|
|
}
|
|
else
|
|
{
|
|
RegionPtr pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height);
|
|
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentDeferCopyArea: Source region [%d,%d,%d,%d].\n",
|
|
pSrcRegion -> extents.x1, pSrcRegion -> extents.y1,
|
|
pSrcRegion -> extents.x2, pSrcRegion -> extents.y2);
|
|
#endif
|
|
|
|
RegionRec corruptedRegion;
|
|
RegionInit(&corruptedRegion, NullBox, 1);
|
|
|
|
RegionIntersect(&corruptedRegion,
|
|
pSrcRegion, nxagentCorruptedRegion(pSrcDrawable));
|
|
|
|
if (!RegionNil(&corruptedRegion))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentDeferCopyArea: Forcing the synchronization of source drawable at [%p].\n",
|
|
(void *) pSrcDrawable);
|
|
#endif
|
|
|
|
nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion /*pSrcRegion*/, NEVER_BREAK, NULL);
|
|
}
|
|
|
|
RegionUninit(&corruptedRegion);
|
|
|
|
nxagentFreeRegion(pSrcRegion);
|
|
}
|
|
|
|
return False;
|
|
}
|
|
|
|
RegionPtr nxagentCopyArea(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
|
|
GCPtr pGC, int srcx, int srcy, int width,
|
|
int height, int dstx, int dsty)
|
|
{
|
|
Bool skip = False;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Image src [%s:%p], dst [%s:%p] (%d,%d) -> (%d,%d) size (%d,%d)\n",
|
|
(pSrcDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable,
|
|
(pDstDrawable -> type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW",
|
|
(void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height);
|
|
#endif
|
|
|
|
/*
|
|
* Here, before using fbDoCopy() called by fbCopyArea(), it should be
|
|
* provided that the cast in fbDoCopy() from int to short int would
|
|
* not cut off significative bits.
|
|
*/
|
|
|
|
if (dstx + pDstDrawable->x + width > 32767)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCopyArea: x2 exceeding short int.\n");
|
|
#endif
|
|
|
|
width = 32767 - dstx - pDstDrawable->x;
|
|
|
|
if (width <= 0)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Returning null on x2 check.\n");
|
|
#endif
|
|
|
|
return NullRegion;
|
|
}
|
|
}
|
|
|
|
if (dstx + pDstDrawable->x < -32768)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCopyArea: x1 exceeding short int.\n");
|
|
#endif
|
|
|
|
width += pDstDrawable->x + dstx + 32768;
|
|
srcx -= pDstDrawable->x + dstx + 32768;
|
|
dstx = -32768 - pDstDrawable->x;
|
|
|
|
if (width <= 0)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Returning null on x1 check.\n");
|
|
#endif
|
|
|
|
return NullRegion;
|
|
}
|
|
}
|
|
|
|
if (dsty + pDstDrawable->y + height > 32767)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCopyArea: y2 exceeding short int.\n");
|
|
#endif
|
|
|
|
height = 32767 - dsty - pDstDrawable->y;
|
|
|
|
if (height <= 0)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Returning null on y2 check.\n");
|
|
#endif
|
|
|
|
return NullRegion;
|
|
}
|
|
}
|
|
|
|
if (dsty + pDstDrawable->y < -32768)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCopyArea: y1 exceeding short int.\n");
|
|
#endif
|
|
|
|
height += 32768 + pDstDrawable->y + dsty;
|
|
srcy -= 32768 + pDstDrawable->y + dsty;
|
|
dsty = -32768 - pDstDrawable->y;
|
|
|
|
if (height <= 0)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Returning null on y1 check.\n");
|
|
#endif
|
|
|
|
return NullRegion;
|
|
}
|
|
}
|
|
|
|
|
|
if (nxagentGCTrap || nxagentShmTrap)
|
|
{
|
|
if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
|
|
pDstDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable),
|
|
nxagentVirtualDrawable(pDstDrawable),
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
}
|
|
else if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
}
|
|
else if (pDstDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
return fbCopyArea(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable),
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
}
|
|
else
|
|
{
|
|
return fbCopyArea(pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
}
|
|
|
|
return NullRegion;
|
|
}
|
|
|
|
/*
|
|
* Try to detect if the copy area is to a window that is unmapped or
|
|
* fully covered. Similarly to the check in Image.c, this is of
|
|
* little use.
|
|
*/
|
|
|
|
if (!nxagentOption(IgnoreVisibility) && pDstDrawable -> type == DRAWABLE_WINDOW &&
|
|
(!nxagentWindowIsVisible((WindowPtr) pDstDrawable) ||
|
|
(!nxagentDefaultWindowIsVisible() && !nxagentCompositeEnable)))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Prevented operation on fully obscured window at [%p].\n",
|
|
(void *) pDstDrawable);
|
|
#endif
|
|
|
|
return NullRegion;
|
|
}
|
|
|
|
/*
|
|
* If the pixmap is on shared memory, we can't know if the pixmap
|
|
* content is changed and so have to translate the operation in a
|
|
* put image operation. This can seriously affect the performance.
|
|
*/
|
|
|
|
if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
|
|
nxagentIsShmPixmap((PixmapPtr) pSrcDrawable))
|
|
{
|
|
char *data;
|
|
|
|
int depth = pSrcDrawable -> depth;
|
|
|
|
unsigned int format = (depth == 1) ? XYPixmap : ZPixmap;
|
|
|
|
int length = nxagentImageLength(width, height, format, 0, depth);
|
|
|
|
if ((data = malloc(length)) == NULL)
|
|
{
|
|
#ifdef WARNING
|
|
fprintf(stderr, "nxagentCopyArea: WARNING! Failed to allocate memory for the operation.\n");
|
|
#endif
|
|
|
|
return NullRegion;
|
|
}
|
|
|
|
unsigned long planeMask = 0xffffffff;
|
|
fbGetImage(nxagentVirtualDrawable(pSrcDrawable), srcx, srcy, width, height, format, planeMask, data);
|
|
|
|
/*
|
|
* If the source is a shared memory pixmap, put the image directly
|
|
* to the destination.
|
|
*/
|
|
|
|
nxagentPutImage(pDstDrawable, pGC, depth, dstx, dsty,
|
|
width, height, 0, format, data);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr,"nxagentCopyArea: Realize Pixmap %p virtual %p x %d y %d w %d h %d\n",
|
|
(void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pSrcDrawable),
|
|
srcx, srcy, width, height);
|
|
#endif
|
|
|
|
SAFE_free(data);
|
|
|
|
/*
|
|
* If the source is a shared memory pixmap, the content of the
|
|
* framebuffer has been placed directly on the destination so we
|
|
* can skip the copy area operation.
|
|
*/
|
|
|
|
skip = True;
|
|
}
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Image src [%s:%p], dst [%s:%p] sx %d sy %d dx %d dy %d size w %d h %d\n",
|
|
((pSrcDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable,
|
|
((pDstDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW",
|
|
(void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height);
|
|
#endif
|
|
|
|
if (!skip && nxagentDrawableStatus(pSrcDrawable) == NotSynchronized)
|
|
{
|
|
skip = nxagentDeferCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
|
|
width, height, dstx, dsty);
|
|
}
|
|
#ifdef TEST
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentCopyArea: Source drawable at [%p] already synchronized.\n",
|
|
(void *) pSrcDrawable);
|
|
}
|
|
#endif
|
|
|
|
if (!skip)
|
|
{
|
|
XCopyArea(nxagentDisplay, nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable),
|
|
nxagentGC(pGC), srcx, srcy, width, height, dstx, dsty);
|
|
|
|
/*
|
|
* The copy area restored the synchronization status of
|
|
* destination drawable.
|
|
*/
|
|
|
|
if (nxagentDrawableStatus(pDstDrawable) == NotSynchronized)
|
|
{
|
|
RegionPtr pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height);
|
|
|
|
nxagentUnmarkCorruptedRegion(pDstDrawable, pDstRegion);
|
|
|
|
nxagentFreeRegion(pDstRegion);
|
|
}
|
|
}
|
|
|
|
if (nxagentDrawableContainGlyphs(pSrcDrawable) == 1)
|
|
{
|
|
nxagentSetDrawableContainGlyphs(pDstDrawable, 1);
|
|
}
|
|
|
|
if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
nxagentIncreasePixmapUsageCounter((PixmapPtr) pSrcDrawable);
|
|
}
|
|
|
|
if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
|
|
pDstDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Going to copy area from virtual pixmap [%p] to [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pSrcDrawable),
|
|
(void *) nxagentVirtualDrawable(pDstDrawable));
|
|
#endif
|
|
|
|
return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable),
|
|
nxagentVirtualDrawable(pDstDrawable),
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
}
|
|
else if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Going to copy area from virtual pixmap [%p] to window [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pSrcDrawable),
|
|
(void *) pDstDrawable);
|
|
#endif
|
|
|
|
return fbCopyArea(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
}
|
|
else if (pDstDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
/*
|
|
* If we are here the source drawable must be a window.
|
|
*/
|
|
|
|
if (((WindowPtr) pSrcDrawable) -> viewable)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Going to copy area from window [%p] to virtual pixmap [%p]\n",
|
|
(void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pDstDrawable));
|
|
#endif
|
|
|
|
return fbCopyArea(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable),
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* If we are here the source drawable must be a window.
|
|
*/
|
|
|
|
if (((WindowPtr) pSrcDrawable) -> viewable)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyArea: Going to copy area from window [%p] to window [%p]\n",
|
|
(void *) pSrcDrawable, (void *) pDstDrawable);
|
|
#endif
|
|
|
|
return fbCopyArea(pSrcDrawable, pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
}
|
|
}
|
|
|
|
return miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
|
|
srcx, srcy, width, height, dstx, dsty, 0);
|
|
}
|
|
|
|
RegionPtr nxagentCopyPlane(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
|
|
GCPtr pGC, int srcx, int srcy, int width, int height,
|
|
int dstx, int dsty, unsigned long plane)
|
|
{
|
|
Bool skip = False;
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyPlane: Image src [%s:%p], dst [%s:%p] (%d,%d) -> (%d,%d) size (%d,%d)\n",
|
|
((pSrcDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW", (void *) pSrcDrawable,
|
|
((pDstDrawable)->type == DRAWABLE_PIXMAP) ? "PIXMAP" : "WINDOW",
|
|
(void *) pDstDrawable, srcx, srcy, dstx, dsty, width, height);
|
|
#endif
|
|
|
|
if (nxagentGCTrap || nxagentShmTrap)
|
|
{
|
|
if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
|
|
pDstDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable),
|
|
nxagentVirtualDrawable(pDstDrawable),
|
|
pGC, srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
else if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable,
|
|
pGC, srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
else if (pDstDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
return fbCopyPlane(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable),
|
|
pGC, srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
else
|
|
{
|
|
return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC, srcx, srcy, width, height,
|
|
dstx, dsty, plane);
|
|
}
|
|
|
|
return NullRegion;
|
|
}
|
|
|
|
/*
|
|
* If the pixmap is on shared memory, we can't know if the pixmap
|
|
* content is changed and so have to translate the operation in a
|
|
* put image operation. This can seriously affect the performance.
|
|
*/
|
|
|
|
if (pSrcDrawable -> type == DRAWABLE_PIXMAP &&
|
|
nxagentIsShmPixmap((PixmapPtr) pSrcDrawable))
|
|
{
|
|
char *data;
|
|
|
|
int depth = pSrcDrawable -> depth;
|
|
|
|
unsigned int format = (depth == 1) ? XYPixmap : ZPixmap;
|
|
|
|
int length = nxagentImageLength(width, height, format, 0, depth);
|
|
|
|
if ((data = malloc(length)) == NULL)
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf(stderr, "nxagentCopyPlane: WARNING! Failed to allocate memory for the operation.\n");
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned long planeMask = 0xffffffff;
|
|
fbGetImage(nxagentVirtualDrawable(pSrcDrawable), srcx, srcy, width, height, format, planeMask, data);
|
|
|
|
/*
|
|
* If the source is a shared memory pixmap, put the image directly
|
|
* to the destination.
|
|
*/
|
|
|
|
nxagentPutImage(pDstDrawable, pGC, depth, dstx, dsty,
|
|
width, height, 0, format, data);
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr,"nxagentCopyPlane: Synchronize Pixmap %p virtual %p x %d y %d w %d h %d \n",
|
|
(void *) pSrcDrawable, (void *) nxagentVirtualDrawable(pSrcDrawable),
|
|
srcx, srcy, width, height);
|
|
#endif
|
|
|
|
SAFE_free(data);
|
|
|
|
/*
|
|
* If the source is a shared memory pixmap, the content of the
|
|
* framebuffer has been placed directly on the destination so we
|
|
* can skip the copy plane operation.
|
|
*/
|
|
|
|
skip = True;
|
|
}
|
|
|
|
if (!skip && nxagentDrawableStatus(pSrcDrawable) == NotSynchronized)
|
|
{
|
|
if (pDstDrawable -> type == DRAWABLE_PIXMAP &&
|
|
nxagentOption(DeferLevel) > 0)
|
|
{
|
|
RegionPtr pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height);
|
|
|
|
nxagentMarkCorruptedRegion(pDstDrawable, pDstRegion);
|
|
|
|
nxagentFreeRegion(pDstRegion);
|
|
|
|
skip = True;
|
|
}
|
|
else
|
|
{
|
|
RegionPtr pSrcRegion = nxagentCreateRegion(pSrcDrawable, NULL, srcx, srcy, width, height);
|
|
|
|
RegionRec corruptedRegion;
|
|
|
|
RegionInit(&corruptedRegion, NullBox, 1);
|
|
|
|
RegionIntersect(&corruptedRegion,
|
|
pSrcRegion, nxagentCorruptedRegion(pSrcDrawable));
|
|
|
|
if (!RegionNil(&corruptedRegion))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyPlane: Forcing the synchronization of source drawable at [%p].\n",
|
|
(void *) pSrcDrawable);
|
|
#endif
|
|
|
|
nxagentSynchronizeRegion(pSrcDrawable, &corruptedRegion /*pSrcRegion*/, NEVER_BREAK, NULL);
|
|
|
|
RegionPtr pDstRegion = nxagentCreateRegion(pDstDrawable, pGC, dstx, dsty, width, height);
|
|
|
|
nxagentUnmarkCorruptedRegion(pDstDrawable, pDstRegion);
|
|
|
|
nxagentFreeRegion(pDstRegion);
|
|
}
|
|
|
|
RegionUninit(&corruptedRegion);
|
|
|
|
nxagentFreeRegion(pSrcRegion);
|
|
}
|
|
}
|
|
#ifdef TEST
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentCopyPlane: Source drawable at [%p] already synchronized.\n",
|
|
(void *) pSrcDrawable);
|
|
}
|
|
#endif
|
|
|
|
if (!skip)
|
|
{
|
|
XCopyPlane(nxagentDisplay,
|
|
nxagentDrawable(pSrcDrawable), nxagentDrawable(pDstDrawable),
|
|
nxagentGC(pGC), srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
|
|
if ((pSrcDrawable)->type == DRAWABLE_PIXMAP &&
|
|
(pDstDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentCopyPlane: going to copy plane from FB pixmap [%p] to [%p].\n",
|
|
(void *) nxagentVirtualDrawable(pSrcDrawable),
|
|
(void *) nxagentVirtualDrawable(pDstDrawable));
|
|
#endif
|
|
|
|
return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable),
|
|
nxagentVirtualDrawable(pDstDrawable),
|
|
pGC, srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
else if (pSrcDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
return fbCopyPlane(nxagentVirtualDrawable(pSrcDrawable), pDstDrawable, pGC,
|
|
srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
else if (pDstDrawable -> type == DRAWABLE_PIXMAP)
|
|
{
|
|
return fbCopyPlane(pSrcDrawable, nxagentVirtualDrawable(pDstDrawable), pGC,
|
|
srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
else
|
|
{
|
|
return fbCopyPlane(pSrcDrawable, pDstDrawable, pGC,
|
|
srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
|
|
return miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
|
|
srcx, srcy, width, height, dstx, dsty, plane);
|
|
}
|
|
|
|
void nxagentPolyPoint(DrawablePtr pDrawable, GCPtr pGC, int mode,
|
|
int nPoints, xPoint *pPoints)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentPolyPoint: Drawable at [%p] GC at [%p] Points [%d].\n",
|
|
(void *) pDrawable, (void *) pGC, nPoints);
|
|
#endif
|
|
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
fbPolyPoint(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints);
|
|
}
|
|
else
|
|
{
|
|
fbPolyPoint(pDrawable, pGC, mode, nPoints, pPoints);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly point on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly point enters with virtual pixmap [%p] parent is [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawPoints(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), (XPoint *) pPoints, nPoints, mode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawPoints(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XPoint *) pPoints, nPoints, mode);
|
|
}
|
|
|
|
fbPolyPoint(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XDrawPoints(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XPoint *) pPoints, nPoints, mode);
|
|
|
|
fbPolyPoint(pDrawable, pGC, mode, nPoints, pPoints);
|
|
}
|
|
}
|
|
|
|
void nxagentPolyLines(DrawablePtr pDrawable, GCPtr pGC, int mode,
|
|
int nPoints, xPoint *pPoints)
|
|
{
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
fbPolyLine(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints);
|
|
}
|
|
else
|
|
{
|
|
fbPolyLine(pDrawable, pGC, mode, nPoints, pPoints);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly line on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly lines enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawLines(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), (XPoint *) pPoints, nPoints, mode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawLines(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XPoint *) pPoints, nPoints, mode);
|
|
}
|
|
|
|
fbPolyLine(nxagentVirtualDrawable(pDrawable), pGC, mode, nPoints, pPoints);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XDrawLines(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XPoint *) pPoints, nPoints, mode);
|
|
|
|
fbPolyLine(pDrawable, pGC, mode, nPoints, pPoints);
|
|
}
|
|
}
|
|
|
|
void nxagentPolySegment(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nSegments, xSegment *pSegments)
|
|
{
|
|
#ifdef TEST
|
|
|
|
if (nSegments == 1)
|
|
{
|
|
fprintf(stderr, "nxagentPolySegment: Drawable at [%p] GC at [%p] Segment [%d,%d,%d,%d].\n",
|
|
(void *) pDrawable, (void *) pGC,
|
|
pSegments -> x1, pSegments -> y1, pSegments -> x2, pSegments -> y2);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentPolySegment: Drawable at [%p] GC at [%p] Segments [%d].\n",
|
|
(void *) pDrawable, (void *) pGC, nSegments);
|
|
}
|
|
|
|
#endif
|
|
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments);
|
|
}
|
|
else
|
|
{
|
|
fbPolySegment(pDrawable, pGC, nSegments, pSegments);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly segment on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly segment enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawSegments(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), (XSegment *) pSegments, nSegments);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XSegment *) pSegments, nSegments);
|
|
}
|
|
|
|
SET_GC_TRAP();
|
|
fbPolySegment(nxagentVirtualDrawable(pDrawable), pGC, nSegments, pSegments);
|
|
RESET_GC_TRAP();
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XDrawSegments(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XSegment *) pSegments, nSegments);
|
|
|
|
SET_GC_TRAP();
|
|
fbPolySegment(pDrawable, pGC, nSegments, pSegments);
|
|
RESET_GC_TRAP();
|
|
}
|
|
}
|
|
|
|
void nxagentPolyRectangle(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nRectangles, xRectangle *pRectangles)
|
|
{
|
|
#ifdef TEST
|
|
|
|
if (nRectangles == 1)
|
|
{
|
|
fprintf(stderr, "nxagentPolyRectangle: Drawable at [%p] GC at [%p] Rectangle [%d,%d][%d,%d].\n",
|
|
(void *) pDrawable, (void *) pGC,
|
|
pRectangles -> x, pRectangles -> y, pRectangles -> width, pRectangles -> height);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentPolyRectangle: Drawable at [%p] GC at [%p] Rectangles [%d].\n",
|
|
(void *) pDrawable, (void *) pGC, nRectangles);
|
|
}
|
|
|
|
#endif
|
|
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
miPolyRectangle(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles);
|
|
}
|
|
else
|
|
{
|
|
miPolyRectangle(pDrawable, pGC, nRectangles, pRectangles);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly rectangle on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly rectangle enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawRectangles(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), (XRectangle *) pRectangles, nRectangles);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XRectangle *) pRectangles, nRectangles);
|
|
}
|
|
|
|
SET_GC_TRAP();
|
|
|
|
miPolyRectangle(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles);
|
|
|
|
RESET_GC_TRAP();
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XDrawRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XRectangle *) pRectangles, nRectangles);
|
|
|
|
SET_GC_TRAP();
|
|
|
|
miPolyRectangle(pDrawable, pGC, nRectangles, pRectangles);
|
|
|
|
RESET_GC_TRAP();
|
|
}
|
|
}
|
|
|
|
void nxagentPolyArc(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nArcs, xArc *pArcs)
|
|
{
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
fbPolyArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs);
|
|
}
|
|
else
|
|
{
|
|
fbPolyArc(pDrawable, pGC, nArcs, pArcs);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly arc on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly arc enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawArcs(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), (XArc *) pArcs, nArcs);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XArc *) pArcs, nArcs);
|
|
}
|
|
|
|
fbPolyArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XDrawArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XArc *) pArcs, nArcs);
|
|
|
|
fbPolyArc(pDrawable, pGC, nArcs, pArcs);
|
|
}
|
|
}
|
|
|
|
void nxagentFillPolygon(DrawablePtr pDrawable, GCPtr pGC, int shape,
|
|
int mode, int nPoints, xPoint *pPoints)
|
|
{
|
|
xPoint *newPoints = NULL;
|
|
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
miFillPolygon(nxagentVirtualDrawable(pDrawable), pGC, shape, mode, nPoints, pPoints);
|
|
}
|
|
else
|
|
{
|
|
miFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* The coordinate-mode must be CoordModePrevious to make better use
|
|
* of differential encoding of X_FillPoly request by the side of
|
|
* proxy.
|
|
*/
|
|
|
|
if (mode == CoordModeOrigin)
|
|
{
|
|
mode = CoordModePrevious;
|
|
|
|
newPoints = malloc(nPoints * sizeof(xPoint));
|
|
|
|
/*
|
|
* The first point is always relative to the drawable's origin.
|
|
*/
|
|
|
|
newPoints[0].x = pPoints[0].x;
|
|
newPoints[0].y = pPoints[0].y;
|
|
|
|
/*
|
|
* If coordinate-mode is CoordModePrevious, the points following
|
|
* the first are relative to the previous point.
|
|
*/
|
|
|
|
for (int i = 1; i < nPoints; i++)
|
|
{
|
|
newPoints[i].x = pPoints[i].x - pPoints[i-1].x;
|
|
newPoints[i].y = pPoints[i].y - pPoints[i-1].y;
|
|
}
|
|
|
|
pPoints = newPoints;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to fill polygon on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: fill polygon enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XFillPolygon(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), (XPoint *) pPoints, nPoints, shape, mode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XFillPolygon(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XPoint *) pPoints, nPoints, shape, mode);
|
|
}
|
|
|
|
SET_GC_TRAP();
|
|
|
|
miFillPolygon(nxagentVirtualDrawable(pDrawable), pGC, shape, mode, nPoints, pPoints);
|
|
|
|
RESET_GC_TRAP();
|
|
}
|
|
else
|
|
{
|
|
XFillPolygon(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XPoint *) pPoints, nPoints, shape, mode);
|
|
|
|
SET_GC_TRAP();
|
|
|
|
miFillPolygon(pDrawable, pGC, shape, mode, nPoints, pPoints);
|
|
|
|
RESET_GC_TRAP();
|
|
}
|
|
|
|
SAFE_free(newPoints);
|
|
}
|
|
|
|
void nxagentPolyFillRect(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nRectangles, xRectangle *pRectangles)
|
|
{
|
|
#ifdef TEST
|
|
|
|
if (nRectangles == 1)
|
|
{
|
|
fprintf(stderr, "nxagentPolyFillRect: Drawable at [%p] GC at [%p] FillStyle [%d] Rectangle [%d,%d][%d,%d].\n",
|
|
(void *) pDrawable, (void *) pGC, pGC -> fillStyle,
|
|
pRectangles -> x, pRectangles -> y, pRectangles -> width, pRectangles -> height);
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "nxagentPolyFillRect: Drawable at [%p] GC at [%p] FillStyle [%d] Rectangles [%d].\n",
|
|
(void *) pDrawable, (void *) pGC, pGC -> fillStyle, nRectangles);
|
|
}
|
|
|
|
#endif
|
|
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
fbPolyFillRect(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles);
|
|
}
|
|
else
|
|
{
|
|
fbPolyFillRect(pDrawable, pGC, nRectangles, pRectangles);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* The PolyFillRect acts in two ways: if the GC has a corrupted
|
|
* tile, the operation propagates the corrupted region on the
|
|
* destination. In other cases, because the PolyFillRect will cover
|
|
* the destination, any corrupted region intersecting the target
|
|
* will be cleared.
|
|
*/
|
|
|
|
Bool inheritCorruptedRegion = False;
|
|
|
|
if (pGC -> fillStyle == FillTiled &&
|
|
pGC -> tileIsPixel == 0 && pGC -> tile.pixmap != NULL)
|
|
{
|
|
nxagentIncreasePixmapUsageCounter(pGC -> tile.pixmap);
|
|
|
|
if (nxagentDrawableStatus((DrawablePtr) pGC -> tile.pixmap) == NotSynchronized)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentPolyFillRect: GC at [%p] uses corrupted tile pixmap at [%p]. Going to "
|
|
"corrupt the destination [%s][%p].\n", (void *) pGC, (void *) pGC -> tile.pixmap,
|
|
(pDrawable -> type == DRAWABLE_PIXMAP ? "pixmap" : "window"), (void *) pDrawable);
|
|
|
|
#endif
|
|
|
|
inheritCorruptedRegion = True;
|
|
}
|
|
}
|
|
|
|
if (inheritCorruptedRegion || nxagentDrawableStatus(pDrawable) == NotSynchronized)
|
|
{
|
|
RegionPtr rectRegion = RegionFromRects(nRectangles, pRectangles, CT_REGION);
|
|
|
|
if (pGC -> clientClip != NULL)
|
|
{
|
|
RegionRec tmpRegion;
|
|
|
|
RegionInit(&tmpRegion, NullBox, 1);
|
|
|
|
RegionCopy(&tmpRegion, ((RegionPtr) pGC -> clientClip));
|
|
|
|
if (pGC -> clipOrg.x != 0 || pGC -> clipOrg.y != 0)
|
|
{
|
|
RegionTranslate(&tmpRegion, pGC -> clipOrg.x, pGC -> clipOrg.y);
|
|
}
|
|
|
|
RegionIntersect(rectRegion, rectRegion, &tmpRegion);
|
|
|
|
RegionUninit(&tmpRegion);
|
|
}
|
|
|
|
if (inheritCorruptedRegion)
|
|
{
|
|
/*
|
|
* The fill style should affect the corrupted region
|
|
* propagation: if the tile is not completely corrupted the
|
|
* region should be 'tiled' over the destination.
|
|
*/
|
|
|
|
nxagentMarkCorruptedRegion(pDrawable, rectRegion);
|
|
}
|
|
else
|
|
{
|
|
if (pGC -> fillStyle != FillStippled && pGC -> fillStyle != FillOpaqueStippled)
|
|
{
|
|
nxagentUnmarkCorruptedRegion(pDrawable, rectRegion);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* The stipple mask computation could cause an high
|
|
* fragmentation of the destination region. An analysis should
|
|
* be done to examine the better solution (e.g.rdesktop uses
|
|
* stipples to draw texts).
|
|
*/
|
|
|
|
#ifdef TEST
|
|
fprintf(stderr, "nxagentPolyFillRect: Synchronizing the region [%d,%d,%d,%d] before using "
|
|
"the stipple at [%p].\n", rectRegion -> extents.x1, rectRegion -> extents.y1,
|
|
rectRegion -> extents.x2, rectRegion -> extents.y2, (void *) pGC -> stipple);
|
|
#endif
|
|
|
|
nxagentSynchronizeRegion(pDrawable, rectRegion, NEVER_BREAK, NULL);
|
|
}
|
|
}
|
|
|
|
RegionDestroy(rectRegion);
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly fill rect on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly fill rect enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XFillRectangles(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), (XRectangle *) pRectangles, nRectangles);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XRectangle *) pRectangles, nRectangles);
|
|
}
|
|
|
|
fbPolyFillRect(nxagentVirtualDrawable(pDrawable), pGC, nRectangles, pRectangles);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XFillRectangles(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XRectangle *) pRectangles, nRectangles);
|
|
|
|
fbPolyFillRect(pDrawable, pGC, nRectangles, pRectangles);
|
|
}
|
|
}
|
|
|
|
void nxagentPolyFillArc(DrawablePtr pDrawable, GCPtr pGC,
|
|
int nArcs, xArc *pArcs)
|
|
{
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
miPolyFillArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs);
|
|
}
|
|
else
|
|
{
|
|
miPolyFillArc(pDrawable, pGC, nArcs, pArcs);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly fillarc on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly fill arc enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XFillArcs(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), (XArc *) pArcs, nArcs);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XFillArcs(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
(XArc *) pArcs, nArcs);
|
|
}
|
|
|
|
SET_GC_TRAP();
|
|
|
|
miPolyFillArc(nxagentVirtualDrawable(pDrawable), pGC, nArcs, pArcs);
|
|
|
|
RESET_GC_TRAP();
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XFillArcs(nxagentDisplay, nxagentDrawable(pDrawable),
|
|
nxagentGC(pGC), (XArc *) pArcs, nArcs);
|
|
|
|
SET_GC_TRAP();
|
|
|
|
miPolyFillArc(pDrawable, pGC, nArcs, pArcs);
|
|
|
|
RESET_GC_TRAP();
|
|
}
|
|
}
|
|
|
|
int nxagentPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x,
|
|
int y, int count, char *string)
|
|
{
|
|
/*
|
|
* While the session is suspended the font structure is NULL.
|
|
*/
|
|
|
|
if (nxagentFontStruct(pGC -> font) == NULL)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
int width = XTextWidth(nxagentFontStruct(pGC->font), string, count);
|
|
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
miPolyText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
|
|
}
|
|
else
|
|
{
|
|
miPolyText8(pDrawable, pGC, x, y, count, string);
|
|
}
|
|
|
|
return width + x;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly text8 on FB pixmap [%p] with string [%s].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string);
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly text8 enters with virtual pixmap [%p] parent is [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawString(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), x, y, string, count);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawString(nxagentDisplay, nxagentDrawable(pDrawable),
|
|
nxagentGC(pGC), x, y, string, count);
|
|
}
|
|
|
|
miPolyText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
|
|
|
|
return width + x;
|
|
}
|
|
else
|
|
{
|
|
XDrawString(nxagentDisplay, nxagentDrawable(pDrawable), nxagentGC(pGC),
|
|
x, y, string, count);
|
|
|
|
miPolyText8(pDrawable, pGC, x, y, count, string);
|
|
}
|
|
|
|
return width + x;
|
|
}
|
|
|
|
int nxagentPolyText16(DrawablePtr pDrawable, GCPtr pGC, int x,
|
|
int y, int count, unsigned short *string)
|
|
{
|
|
/*
|
|
* While the session is suspended the font structure is NULL.
|
|
*/
|
|
|
|
if (nxagentFontStruct(pGC -> font) == NULL)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
int width = XTextWidth16(nxagentFontStruct(pGC->font), (XChar2b *)string, count);
|
|
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
miPolyText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
|
|
}
|
|
else
|
|
{
|
|
miPolyText16(pDrawable, pGC, x, y, count, string);
|
|
}
|
|
|
|
return width + x;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to poly text16 on FB pixmap %p] with string [%s]\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string);
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly text16 enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawString16(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), x, y, (XChar2b *)string, count);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawString16(nxagentDisplay, nxagentDrawable(pDrawable),
|
|
nxagentGC(pGC), x, y, (XChar2b *)string, count);
|
|
}
|
|
|
|
miPolyText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
|
|
|
|
return width + x;
|
|
}
|
|
else
|
|
{
|
|
XDrawString16(nxagentDisplay, nxagentDrawable(pDrawable),
|
|
nxagentGC(pGC), x, y, (XChar2b *)string, count);
|
|
|
|
miPolyText16(pDrawable, pGC, x, y, count, string);
|
|
}
|
|
|
|
return width + x;
|
|
}
|
|
|
|
void nxagentImageText8(DrawablePtr pDrawable, GCPtr pGC, int x,
|
|
int y, int count, char *string)
|
|
{
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
miImageText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
|
|
}
|
|
else
|
|
{
|
|
miImageText8(pDrawable, pGC, x, y, count, string);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to image text8 on FB pixmap [%p] with string [%s].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), string);
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly image text8 enters with virtual pixmap [%p] parent is [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawImageString(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), x, y, string, count);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawImageString(nxagentDisplay, nxagentDrawable(pDrawable),
|
|
nxagentGC(pGC), x, y, string, count);
|
|
}
|
|
|
|
miImageText8(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XDrawImageString(nxagentDisplay, nxagentDrawable(pDrawable),
|
|
nxagentGC(pGC), x, y, string, count);
|
|
|
|
miImageText8(pDrawable, pGC, x, y, count, string);
|
|
}
|
|
}
|
|
|
|
void nxagentImageText16(DrawablePtr pDrawable, GCPtr pGC, int x,
|
|
int y, int count, unsigned short *string)
|
|
{
|
|
if (nxagentGCTrap)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
miImageText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
|
|
}
|
|
else
|
|
{
|
|
miImageText16(pDrawable, pGC, x, y, count, string);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to image text16 on FB pixmap [%p] with string [%s].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable), (char *) string);
|
|
#endif
|
|
|
|
if (nxagentPixmapIsVirtual((PixmapPtr) pDrawable))
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: poly image text16 enters with virtual pixmap = [%p] parent is = [%p]\n",
|
|
(void *) nxagentVirtualDrawable(pDrawable),
|
|
(void *) nxagentRealPixmap((PixmapPtr) pDrawable));
|
|
#endif
|
|
|
|
if (nxagentRealPixmap((PixmapPtr) pDrawable))
|
|
{
|
|
XDrawImageString16(nxagentDisplay, nxagentDrawable((DrawablePtr) nxagentRealPixmap((PixmapPtr) pDrawable)),
|
|
nxagentGC(pGC), x, y, (XChar2b *)string, count);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XDrawImageString16(nxagentDisplay, nxagentDrawable(pDrawable),
|
|
nxagentGC(pGC), x, y, (XChar2b *)string, count);
|
|
}
|
|
|
|
miImageText16(nxagentVirtualDrawable(pDrawable), pGC, x, y, count, string);
|
|
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
XDrawImageString16(nxagentDisplay, nxagentDrawable(pDrawable),
|
|
nxagentGC(pGC), x, y, (XChar2b *)string, count);
|
|
|
|
miImageText16(pDrawable, pGC, x, y, count, string);
|
|
}
|
|
}
|
|
|
|
void nxagentImageGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
|
|
unsigned int nGlyphs, CharInfoPtr *pCharInfo,
|
|
void * pGlyphBase)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to imageGlyphBlt on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
fbImageGlyphBlt(nxagentVirtualDrawable(pDrawable), pGC, x, y, nGlyphs, pCharInfo, pGlyphBase);
|
|
}
|
|
else
|
|
{
|
|
fbImageGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase);
|
|
}
|
|
}
|
|
|
|
void nxagentPolyGlyphBlt(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
|
|
unsigned int nGlyphs, CharInfoPtr *pCharInfo,
|
|
void * pGlyphBase)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to PolyGlyphBlt on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
fbPolyGlyphBlt(nxagentVirtualDrawable(pDrawable), pGC, x, y, nGlyphs, pCharInfo, pGlyphBase);
|
|
}
|
|
else
|
|
{
|
|
fbPolyGlyphBlt(pDrawable, pGC, x, y, nGlyphs, pCharInfo, pGlyphBase);
|
|
}
|
|
}
|
|
|
|
void nxagentPushPixels(GCPtr pGC, PixmapPtr pBitmap, DrawablePtr pDrawable,
|
|
int width, int height, int x, int y)
|
|
{
|
|
if ((pDrawable)->type == DRAWABLE_PIXMAP)
|
|
{
|
|
#ifdef TEST
|
|
fprintf(stderr, "GCOps: GC [%p] going to PushPixels on FB pixmap [%p].\n",
|
|
(void *) pGC, (void *) nxagentVirtualDrawable(pDrawable));
|
|
#endif
|
|
|
|
fbPushPixels(pGC, nxagentVirtualPixmap(pBitmap),
|
|
(DrawablePtr) nxagentVirtualDrawable(pDrawable),
|
|
width, height, x, y);
|
|
}
|
|
else
|
|
{
|
|
fbPushPixels(pGC, nxagentVirtualPixmap(pBitmap),
|
|
(DrawablePtr) pDrawable, width, height, x, y);
|
|
}
|
|
}
|