1540 lines
35 KiB
C
1540 lines
35 KiB
C
/*
|
|
* $XFree86: xc/programs/Xserver/miext/shadow/shadow.c,v 1.14tsi Exp $
|
|
*
|
|
* Copyright © 2000 Keith Packard
|
|
*
|
|
* 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, and that the name of Keith Packard not be used in
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
* specific, written prior permission. Keith Packard makes no
|
|
* representations about the suitability of this software for any purpose. It
|
|
* is provided "as is" without express or implied warranty.
|
|
*
|
|
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
|
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
|
|
#include "X.h"
|
|
#include "scrnintstr.h"
|
|
#include "windowstr.h"
|
|
#include "font.h"
|
|
#include "dixfontstr.h"
|
|
#include "fontstruct.h"
|
|
#include "mi.h"
|
|
#include "regionstr.h"
|
|
#include "globals.h"
|
|
#include "gcstruct.h"
|
|
#include "shadow.h"
|
|
|
|
typedef struct _shadowGCPriv {
|
|
GCOps *ops;
|
|
GCFuncs *funcs;
|
|
} shadowGCPrivRec, *shadowGCPrivPtr;
|
|
|
|
int shadowScrPrivateIndex;
|
|
int shadowGCPrivateIndex;
|
|
int shadowGeneration;
|
|
|
|
#define shadowGetGCPriv(pGC) \
|
|
((shadowGCPrivPtr) (pGC)->devPrivates[shadowGCPrivateIndex].ptr)
|
|
#define shadowGCPriv(pGC) \
|
|
shadowGCPrivPtr pGCPriv = shadowGetGCPriv(pGC)
|
|
|
|
#define wrap(priv, real, mem, func) {\
|
|
priv->mem = real->mem; \
|
|
real->mem = func; \
|
|
}
|
|
|
|
#define unwrap(priv, real, mem) {\
|
|
real->mem = priv->mem; \
|
|
}
|
|
|
|
static void
|
|
shadowRedisplay (ScreenPtr pScreen)
|
|
{
|
|
shadowScrPriv(pScreen);
|
|
shadowBufPtr pBuf;
|
|
|
|
for (pBuf = pScrPriv->pBuf; pBuf; pBuf = pBuf->pNext)
|
|
{
|
|
if (REGION_NOTEMPTY (pScreen, &pBuf->damage))
|
|
{
|
|
REGION_INTERSECT (pScreen, &pBuf->damage, &pBuf->damage,
|
|
&WindowTable[pScreen->myNum]->borderClip);
|
|
(*pBuf->update) (pScreen, pBuf);
|
|
REGION_EMPTY (pScreen, &pBuf->damage);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
shadowBlockHandler (pointer data,
|
|
OSTimePtr pTimeout,
|
|
pointer pRead)
|
|
{
|
|
ScreenPtr pScreen = (ScreenPtr) data;
|
|
|
|
shadowRedisplay (pScreen);
|
|
}
|
|
|
|
static void
|
|
shadowWakeupHandler (pointer data, int i, pointer LastSelectMask)
|
|
{
|
|
}
|
|
|
|
static void
|
|
shadowDamageRegion (WindowPtr pWindow, RegionPtr pRegion)
|
|
{
|
|
shadowBufPtr pBuf = shadowFindBuf (pWindow);
|
|
|
|
if (!pBuf)
|
|
abort ();
|
|
|
|
REGION_INTERSECT(pWindow->drawable.pScreen, pRegion, pRegion,
|
|
&pWindow->borderClip);
|
|
REGION_UNION(pWindow->drawable.pScreen, &pBuf->damage, &pBuf->damage,
|
|
pRegion);
|
|
#ifdef ALWAYS_DISPLAY
|
|
shadowRedisplay (pWindow->drawable.pScreen);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
shadowDamageBox (WindowPtr pWindow, BoxPtr pBox)
|
|
{
|
|
RegionRec region;
|
|
|
|
REGION_INIT (pWindow->drawable.pScreen, ®ion, pBox, 1);
|
|
shadowDamageRegion (pWindow, ®ion);
|
|
}
|
|
|
|
static void
|
|
shadowDamageRect (WindowPtr pWindow, int x, int y, int w, int h)
|
|
{
|
|
BoxRec box;
|
|
|
|
x += pWindow->drawable.x;
|
|
y += pWindow->drawable.y;
|
|
box.x1 = x;
|
|
box.x2 = x + w;
|
|
box.y1 = y;
|
|
box.y2 = y + h;
|
|
shadowDamageBox (pWindow, &box);
|
|
}
|
|
|
|
static void shadowValidateGC(GCPtr, unsigned long, DrawablePtr);
|
|
static void shadowChangeGC(GCPtr, unsigned long);
|
|
static void shadowCopyGC(GCPtr, unsigned long, GCPtr);
|
|
static void shadowDestroyGC(GCPtr);
|
|
static void shadowChangeClip(GCPtr, int, pointer, int);
|
|
static void shadowDestroyClip(GCPtr);
|
|
static void shadowCopyClip(GCPtr, GCPtr);
|
|
|
|
GCFuncs shadowGCFuncs = {
|
|
shadowValidateGC, shadowChangeGC, shadowCopyGC, shadowDestroyGC,
|
|
shadowChangeClip, shadowDestroyClip, shadowCopyClip
|
|
};
|
|
|
|
extern GCOps shadowGCOps;
|
|
|
|
static Bool
|
|
shadowCreateGC(GCPtr pGC)
|
|
{
|
|
ScreenPtr pScreen = pGC->pScreen;
|
|
shadowScrPriv(pScreen);
|
|
shadowGCPriv(pGC);
|
|
Bool ret;
|
|
|
|
unwrap (pScrPriv, pScreen, CreateGC);
|
|
if((ret = (*pScreen->CreateGC) (pGC))) {
|
|
pGCPriv->ops = NULL;
|
|
pGCPriv->funcs = pGC->funcs;
|
|
pGC->funcs = &shadowGCFuncs;
|
|
}
|
|
wrap (pScrPriv, pScreen, CreateGC, shadowCreateGC);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void
|
|
shadowWrapGC (GCPtr pGC)
|
|
{
|
|
shadowGCPriv(pGC);
|
|
|
|
pGCPriv->ops = NULL;
|
|
pGCPriv->funcs = pGC->funcs;
|
|
pGC->funcs = &shadowGCFuncs;
|
|
}
|
|
|
|
void
|
|
shadowUnwrapGC (GCPtr pGC)
|
|
{
|
|
shadowGCPriv(pGC);
|
|
|
|
pGC->funcs = pGCPriv->funcs;
|
|
if (pGCPriv->ops)
|
|
pGC->ops = pGCPriv->ops;
|
|
}
|
|
|
|
#define SHADOW_GC_OP_PROLOGUE(pGC, pDraw) \
|
|
shadowGCPriv(pGC); \
|
|
GCFuncs *oldFuncs = pGC->funcs; \
|
|
unwrap(pGCPriv, pGC, funcs); \
|
|
unwrap(pGCPriv, pGC, ops); \
|
|
|
|
#define SHADOW_GC_OP_EPILOGUE(pGC, pDraw) \
|
|
wrap(pGCPriv, pGC, funcs, oldFuncs); \
|
|
wrap(pGCPriv, pGC, ops, &shadowGCOps)
|
|
|
|
#define SHADOW_GC_FUNC_PROLOGUE(pGC) \
|
|
shadowGCPriv(pGC); \
|
|
unwrap(pGCPriv, pGC, funcs); \
|
|
if (pGCPriv->ops) unwrap(pGCPriv, pGC, ops)
|
|
|
|
#define SHADOW_GC_FUNC_EPILOGUE(pGC) \
|
|
wrap(pGCPriv, pGC, funcs, &shadowGCFuncs); \
|
|
if (pGCPriv->ops) wrap(pGCPriv, pGC, ops, &shadowGCOps)
|
|
|
|
static void
|
|
shadowValidateGC(
|
|
GCPtr pGC,
|
|
unsigned long changes,
|
|
DrawablePtr pDraw
|
|
){
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
|
|
if(pDraw->type == DRAWABLE_WINDOW)
|
|
pGCPriv->ops = pGC->ops; /* just so it's not NULL */
|
|
else
|
|
pGCPriv->ops = NULL;
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
shadowDestroyGC(GCPtr pGC)
|
|
{
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(*pGC->funcs->DestroyGC)(pGC);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
shadowChangeGC (
|
|
GCPtr pGC,
|
|
unsigned long mask
|
|
){
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(*pGC->funcs->ChangeGC) (pGC, mask);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
shadowCopyGC (
|
|
GCPtr pGCSrc,
|
|
unsigned long mask,
|
|
GCPtr pGCDst
|
|
){
|
|
SHADOW_GC_FUNC_PROLOGUE (pGCDst);
|
|
(*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGCDst);
|
|
}
|
|
|
|
static void
|
|
shadowChangeClip (
|
|
GCPtr pGC,
|
|
int type,
|
|
pointer pvalue,
|
|
int nrects
|
|
){
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
static void
|
|
shadowCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
|
|
{
|
|
SHADOW_GC_FUNC_PROLOGUE (pgcDst);
|
|
(* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
|
|
SHADOW_GC_FUNC_EPILOGUE (pgcDst);
|
|
}
|
|
|
|
static void
|
|
shadowDestroyClip(GCPtr pGC)
|
|
{
|
|
SHADOW_GC_FUNC_PROLOGUE (pGC);
|
|
(* pGC->funcs->DestroyClip)(pGC);
|
|
SHADOW_GC_FUNC_EPILOGUE (pGC);
|
|
}
|
|
|
|
#define IS_VISIBLE(pWin) 1
|
|
|
|
|
|
#define TRIM_BOX(box, pGC) { \
|
|
BoxPtr extents = &pGC->pCompositeClip->extents;\
|
|
if(box.x1 < extents->x1) box.x1 = extents->x1; \
|
|
if(box.x2 > extents->x2) box.x2 = extents->x2; \
|
|
if(box.y1 < extents->y1) box.y1 = extents->y1; \
|
|
if(box.y2 > extents->y2) box.y2 = extents->y2; \
|
|
}
|
|
|
|
#define TRANSLATE_BOX(box, pDraw) { \
|
|
box.x1 += pDraw->x; \
|
|
box.x2 += pDraw->x; \
|
|
box.y1 += pDraw->y; \
|
|
box.y2 += pDraw->y; \
|
|
}
|
|
|
|
#define TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC) { \
|
|
TRANSLATE_BOX(box, pDraw); \
|
|
TRIM_BOX(box, pGC); \
|
|
}
|
|
|
|
#define BOX_NOT_EMPTY(box) \
|
|
(((box.x2 - box.x1) > 0) && ((box.y2 - box.y1) > 0))
|
|
|
|
#ifdef RENDER
|
|
static void
|
|
shadowComposite (CARD8 op,
|
|
PicturePtr pSrc,
|
|
PicturePtr pMask,
|
|
PicturePtr pDst,
|
|
INT16 xSrc,
|
|
INT16 ySrc,
|
|
INT16 xMask,
|
|
INT16 yMask,
|
|
INT16 xDst,
|
|
INT16 yDst,
|
|
CARD16 width,
|
|
CARD16 height)
|
|
{
|
|
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
|
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
|
shadowScrPriv(pScreen);
|
|
|
|
unwrap (pScrPriv, ps, Composite);
|
|
(*ps->Composite) (op,
|
|
pSrc,
|
|
pMask,
|
|
pDst,
|
|
xSrc,
|
|
ySrc,
|
|
xMask,
|
|
yMask,
|
|
xDst,
|
|
yDst,
|
|
width,
|
|
height);
|
|
wrap (pScrPriv, ps, Composite, shadowComposite);
|
|
if (pDst->pDrawable->type == DRAWABLE_WINDOW)
|
|
shadowDamageRect ((WindowPtr) pDst->pDrawable, xDst, yDst,
|
|
width, height);
|
|
}
|
|
|
|
static void
|
|
shadowGlyphs (CARD8 op,
|
|
PicturePtr pSrc,
|
|
PicturePtr pDst,
|
|
PictFormatPtr maskFormat,
|
|
INT16 xSrc,
|
|
INT16 ySrc,
|
|
int nlist,
|
|
GlyphListPtr list,
|
|
GlyphPtr *glyphs)
|
|
{
|
|
ScreenPtr pScreen = pDst->pDrawable->pScreen;
|
|
PictureScreenPtr ps = GetPictureScreen(pScreen);
|
|
shadowScrPriv(pScreen);
|
|
int x, y;
|
|
int n;
|
|
GlyphPtr glyph;
|
|
|
|
unwrap (pScrPriv, ps, Glyphs);
|
|
(*ps->Glyphs) (op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
|
|
wrap (pScrPriv, ps, Glyphs, shadowGlyphs);
|
|
if (pDst->pDrawable->type == DRAWABLE_WINDOW)
|
|
{
|
|
x = xSrc;
|
|
y = ySrc;
|
|
while (nlist--)
|
|
{
|
|
x += list->xOff;
|
|
y += list->yOff;
|
|
n = list->len;
|
|
while (n--)
|
|
{
|
|
glyph = *glyphs++;
|
|
shadowDamageRect ((WindowPtr) pDst->pDrawable,
|
|
x - glyph->info.x,
|
|
y - glyph->info.y,
|
|
glyph->info.width,
|
|
glyph->info.height);
|
|
x += glyph->info.xOff;
|
|
y += glyph->info.yOff;
|
|
}
|
|
list++;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/**********************************************************/
|
|
|
|
|
|
static void
|
|
shadowFillSpans(
|
|
DrawablePtr pDraw,
|
|
GC *pGC,
|
|
int nInit,
|
|
DDXPointPtr pptInit,
|
|
int *pwidthInit,
|
|
int fSorted
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && nInit) {
|
|
DDXPointPtr ppt = pptInit;
|
|
int *pwidth = pwidthInit;
|
|
int i = nInit;
|
|
BoxRec box;
|
|
|
|
box.x1 = ppt->x;
|
|
box.x2 = box.x1 + *pwidth;
|
|
box.y2 = box.y1 = ppt->y;
|
|
|
|
while(--i) {
|
|
ppt++;
|
|
pwidth++;
|
|
if(box.x1 > ppt->x) box.x1 = ppt->x;
|
|
if(box.x2 < (ppt->x + *pwidth))
|
|
box.x2 = ppt->x + *pwidth;
|
|
if(box.y1 > ppt->y) box.y1 = ppt->y;
|
|
else if(box.y2 < ppt->y) box.y2 = ppt->y;
|
|
}
|
|
|
|
box.y2++;
|
|
|
|
(*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
|
|
|
|
if(!pGC->miTranslate) {
|
|
TRANSLATE_BOX(box, pDraw);
|
|
}
|
|
TRIM_BOX(box, pGC);
|
|
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
} else
|
|
(*pGC->ops->FillSpans)(pDraw, pGC, nInit, pptInit, pwidthInit, fSorted);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
}
|
|
|
|
static void
|
|
shadowSetSpans(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
char *pcharsrc,
|
|
DDXPointPtr pptInit,
|
|
int *pwidthInit,
|
|
int nspans,
|
|
int fSorted
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && nspans) {
|
|
DDXPointPtr ppt = pptInit;
|
|
int *pwidth = pwidthInit;
|
|
int i = nspans;
|
|
BoxRec box;
|
|
|
|
box.x1 = ppt->x;
|
|
box.x2 = box.x1 + *pwidth;
|
|
box.y2 = box.y1 = ppt->y;
|
|
|
|
while(--i) {
|
|
ppt++;
|
|
pwidth++;
|
|
if(box.x1 > ppt->x) box.x1 = ppt->x;
|
|
if(box.x2 < (ppt->x + *pwidth))
|
|
box.x2 = ppt->x + *pwidth;
|
|
if(box.y1 > ppt->y) box.y1 = ppt->y;
|
|
else if(box.y2 < ppt->y) box.y2 = ppt->y;
|
|
}
|
|
|
|
box.y2++;
|
|
|
|
(*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
|
|
pwidthInit, nspans, fSorted);
|
|
|
|
if(!pGC->miTranslate) {
|
|
TRANSLATE_BOX(box, pDraw);
|
|
}
|
|
TRIM_BOX(box, pGC);
|
|
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
} else
|
|
(*pGC->ops->SetSpans)(pDraw, pGC, pcharsrc, pptInit,
|
|
pwidthInit, nspans, fSorted);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
}
|
|
|
|
static void
|
|
shadowPutImage(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int depth,
|
|
int x, int y, int w, int h,
|
|
int leftPad,
|
|
int format,
|
|
char *pImage
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->PutImage)(pDraw, pGC, depth, x, y, w, h,
|
|
leftPad, format, pImage);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw)) {
|
|
BoxRec box;
|
|
|
|
box.x1 = x + pDraw->x;
|
|
box.x2 = box.x1 + w;
|
|
box.y1 = y + pDraw->y;
|
|
box.y2 = box.y1 + h;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
static RegionPtr
|
|
shadowCopyArea(
|
|
DrawablePtr pSrc,
|
|
DrawablePtr pDst,
|
|
GC *pGC,
|
|
int srcx, int srcy,
|
|
int width, int height,
|
|
int dstx, int dsty
|
|
){
|
|
RegionPtr ret;
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDst);
|
|
ret = (*pGC->ops->CopyArea)(pSrc, pDst,
|
|
pGC, srcx, srcy, width, height, dstx, dsty);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDst);
|
|
|
|
if(IS_VISIBLE(pDst)) {
|
|
BoxRec box;
|
|
|
|
box.x1 = dstx + pDst->x;
|
|
box.x2 = box.x1 + width;
|
|
box.y1 = dsty + pDst->y;
|
|
box.y2 = box.y1 + height;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDst, &box);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static RegionPtr
|
|
shadowCopyPlane(
|
|
DrawablePtr pSrc,
|
|
DrawablePtr pDst,
|
|
GCPtr pGC,
|
|
int srcx, int srcy,
|
|
int width, int height,
|
|
int dstx, int dsty,
|
|
unsigned long bitPlane
|
|
){
|
|
RegionPtr ret;
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDst);
|
|
ret = (*pGC->ops->CopyPlane)(pSrc, pDst,
|
|
pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDst);
|
|
|
|
if(IS_VISIBLE(pDst)) {
|
|
BoxRec box;
|
|
|
|
box.x1 = dstx + pDst->x;
|
|
box.x2 = box.x1 + width;
|
|
box.y1 = dsty + pDst->y;
|
|
box.y2 = box.y1 + height;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDst, &box);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void
|
|
shadowPolyPoint(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int mode,
|
|
int npt,
|
|
xPoint *pptInit
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->PolyPoint)(pDraw, pGC, mode, npt, pptInit);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && npt) {
|
|
BoxRec box;
|
|
|
|
box.x2 = box.x1 = pptInit->x;
|
|
box.y2 = box.y1 = pptInit->y;
|
|
|
|
/* this could be slow if the points were spread out */
|
|
|
|
while(--npt) {
|
|
pptInit++;
|
|
if(box.x1 > pptInit->x) box.x1 = pptInit->x;
|
|
else if(box.x2 < pptInit->x) box.x2 = pptInit->x;
|
|
if(box.y1 > pptInit->y) box.y1 = pptInit->y;
|
|
else if(box.y2 < pptInit->y) box.y2 = pptInit->y;
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
static void
|
|
shadowPolylines(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int mode,
|
|
int npt,
|
|
DDXPointPtr pptInit
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->Polylines)(pDraw, pGC, mode, npt, pptInit);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
|
|
if(IS_VISIBLE(pDraw) && npt) {
|
|
BoxRec box;
|
|
int extra = pGC->lineWidth >> 1;
|
|
|
|
box.x2 = box.x1 = pptInit->x;
|
|
box.y2 = box.y1 = pptInit->y;
|
|
|
|
if(npt > 1) {
|
|
if(pGC->joinStyle == JoinMiter)
|
|
extra = 6 * pGC->lineWidth;
|
|
else if(pGC->capStyle == CapProjecting)
|
|
extra = pGC->lineWidth;
|
|
}
|
|
|
|
if(mode == CoordModePrevious) {
|
|
int x = box.x1;
|
|
int y = box.y1;
|
|
while(--npt) {
|
|
pptInit++;
|
|
x += pptInit->x;
|
|
y += pptInit->y;
|
|
if(box.x1 > x) box.x1 = x;
|
|
else if(box.x2 < x) box.x2 = x;
|
|
if(box.y1 > y) box.y1 = y;
|
|
else if(box.y2 < y) box.y2 = y;
|
|
}
|
|
} else {
|
|
while(--npt) {
|
|
pptInit++;
|
|
if(box.x1 > pptInit->x) box.x1 = pptInit->x;
|
|
else if(box.x2 < pptInit->x) box.x2 = pptInit->x;
|
|
if(box.y1 > pptInit->y) box.y1 = pptInit->y;
|
|
else if(box.y2 < pptInit->y) box.y2 = pptInit->y;
|
|
}
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
if(extra) {
|
|
box.x1 -= extra;
|
|
box.x2 += extra;
|
|
box.y1 -= extra;
|
|
box.y2 += extra;
|
|
}
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
static void
|
|
shadowPolySegment(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int nseg,
|
|
xSegment *pSeg
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->PolySegment)(pDraw, pGC, nseg, pSeg);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && nseg) {
|
|
BoxRec box;
|
|
int extra = pGC->lineWidth;
|
|
|
|
if(pGC->capStyle != CapProjecting)
|
|
extra >>= 1;
|
|
|
|
if(pSeg->x2 > pSeg->x1) {
|
|
box.x1 = pSeg->x1;
|
|
box.x2 = pSeg->x2;
|
|
} else {
|
|
box.x2 = pSeg->x1;
|
|
box.x1 = pSeg->x2;
|
|
}
|
|
|
|
if(pSeg->y2 > pSeg->y1) {
|
|
box.y1 = pSeg->y1;
|
|
box.y2 = pSeg->y2;
|
|
} else {
|
|
box.y2 = pSeg->y1;
|
|
box.y1 = pSeg->y2;
|
|
}
|
|
|
|
while(--nseg) {
|
|
pSeg++;
|
|
if(pSeg->x2 > pSeg->x1) {
|
|
if(pSeg->x1 < box.x1) box.x1 = pSeg->x1;
|
|
if(pSeg->x2 > box.x2) box.x2 = pSeg->x2;
|
|
} else {
|
|
if(pSeg->x2 < box.x1) box.x1 = pSeg->x2;
|
|
if(pSeg->x1 > box.x2) box.x2 = pSeg->x1;
|
|
}
|
|
if(pSeg->y2 > pSeg->y1) {
|
|
if(pSeg->y1 < box.y1) box.y1 = pSeg->y1;
|
|
if(pSeg->y2 > box.y2) box.y2 = pSeg->y2;
|
|
} else {
|
|
if(pSeg->y2 < box.y1) box.y1 = pSeg->y2;
|
|
if(pSeg->y1 > box.y2) box.y2 = pSeg->y1;
|
|
}
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
if(extra) {
|
|
box.x1 -= extra;
|
|
box.x2 += extra;
|
|
box.y1 -= extra;
|
|
box.y2 += extra;
|
|
}
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
static void
|
|
shadowPolyRectangle(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int nRects,
|
|
xRectangle *pRects
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->PolyRectangle)(pDraw, pGC, nRects, pRects);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && nRects)
|
|
{
|
|
BoxRec box;
|
|
int offset1, offset2, offset3;
|
|
|
|
offset2 = pGC->lineWidth;
|
|
if(!offset2) offset2 = 1;
|
|
offset1 = offset2 >> 1;
|
|
offset3 = offset2 - offset1;
|
|
|
|
while(nRects--)
|
|
{
|
|
box.x1 = pRects->x - offset1;
|
|
box.y1 = pRects->y - offset1;
|
|
box.x2 = box.x1 + pRects->width + offset2;
|
|
box.y2 = box.y1 + offset2;
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
|
|
box.x1 = pRects->x - offset1;
|
|
box.y1 = pRects->y + offset3;
|
|
box.x2 = box.x1 + offset2;
|
|
box.y2 = box.y1 + pRects->height - offset2;
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
|
|
box.x1 = pRects->x + pRects->width - offset1;
|
|
box.y1 = pRects->y + offset3;
|
|
box.x2 = box.x1 + offset2;
|
|
box.y2 = box.y1 + pRects->height - offset2;
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
|
|
box.x1 = pRects->x - offset1;
|
|
box.y1 = pRects->y + pRects->height - offset1;
|
|
box.x2 = box.x1 + pRects->width + offset2;
|
|
box.y2 = box.y1 + offset2;
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
|
|
pRects++;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
shadowPolyArc(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int narcs,
|
|
xArc *parcs
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->PolyArc)(pDraw, pGC, narcs, parcs);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && narcs) {
|
|
int extra = pGC->lineWidth >> 1;
|
|
BoxRec box;
|
|
|
|
box.x1 = parcs->x;
|
|
box.x2 = box.x1 + parcs->width;
|
|
box.y1 = parcs->y;
|
|
box.y2 = box.y1 + parcs->height;
|
|
|
|
/* should I break these up instead ? */
|
|
|
|
while(--narcs) {
|
|
parcs++;
|
|
if(box.x1 > parcs->x) box.x1 = parcs->x;
|
|
if(box.x2 < (parcs->x + parcs->width))
|
|
box.x2 = parcs->x + parcs->width;
|
|
if(box.y1 > parcs->y) box.y1 = parcs->y;
|
|
if(box.y2 < (parcs->y + parcs->height))
|
|
box.y2 = parcs->y + parcs->height;
|
|
}
|
|
|
|
if(extra) {
|
|
box.x1 -= extra;
|
|
box.x2 += extra;
|
|
box.y1 -= extra;
|
|
box.y2 += extra;
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
static void
|
|
shadowFillPolygon(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int shape,
|
|
int mode,
|
|
int count,
|
|
DDXPointPtr pptInit
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && (count > 2)) {
|
|
DDXPointPtr ppt = pptInit;
|
|
int i = count;
|
|
BoxRec box;
|
|
|
|
box.x2 = box.x1 = ppt->x;
|
|
box.y2 = box.y1 = ppt->y;
|
|
|
|
if(mode != CoordModeOrigin) {
|
|
int x = box.x1;
|
|
int y = box.y1;
|
|
while(--i) {
|
|
ppt++;
|
|
x += ppt->x;
|
|
y += ppt->y;
|
|
if(box.x1 > x) box.x1 = x;
|
|
else if(box.x2 < x) box.x2 = x;
|
|
if(box.y1 > y) box.y1 = y;
|
|
else if(box.y2 < y) box.y2 = y;
|
|
}
|
|
} else {
|
|
while(--i) {
|
|
ppt++;
|
|
if(box.x1 > ppt->x) box.x1 = ppt->x;
|
|
else if(box.x2 < ppt->x) box.x2 = ppt->x;
|
|
if(box.y1 > ppt->y) box.y1 = ppt->y;
|
|
else if(box.y2 < ppt->y) box.y2 = ppt->y;
|
|
}
|
|
}
|
|
|
|
box.x2++;
|
|
box.y2++;
|
|
|
|
(*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
} else
|
|
(*pGC->ops->FillPolygon)(pDraw, pGC, shape, mode, count, pptInit);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
}
|
|
|
|
|
|
static void
|
|
shadowPolyFillRect(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int nRectsInit,
|
|
xRectangle *pRectsInit
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && nRectsInit) {
|
|
BoxRec box;
|
|
xRectangle *pRects = pRectsInit;
|
|
int nRects = nRectsInit;
|
|
|
|
box.x1 = pRects->x;
|
|
box.x2 = box.x1 + pRects->width;
|
|
box.y1 = pRects->y;
|
|
box.y2 = box.y1 + pRects->height;
|
|
|
|
while(--nRects) {
|
|
pRects++;
|
|
if(box.x1 > pRects->x) box.x1 = pRects->x;
|
|
if(box.x2 < (pRects->x + pRects->width))
|
|
box.x2 = pRects->x + pRects->width;
|
|
if(box.y1 > pRects->y) box.y1 = pRects->y;
|
|
if(box.y2 < (pRects->y + pRects->height))
|
|
box.y2 = pRects->y + pRects->height;
|
|
}
|
|
|
|
/* cfb messes with the pRectsInit so we have to do our
|
|
calculations first */
|
|
|
|
(*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
} else
|
|
(*pGC->ops->PolyFillRect)(pDraw, pGC, nRectsInit, pRectsInit);
|
|
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
}
|
|
|
|
|
|
static void
|
|
shadowPolyFillArc(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int narcs,
|
|
xArc *parcs
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->PolyFillArc)(pDraw, pGC, narcs, parcs);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && narcs) {
|
|
BoxRec box;
|
|
|
|
box.x1 = parcs->x;
|
|
box.x2 = box.x1 + parcs->width;
|
|
box.y1 = parcs->y;
|
|
box.y2 = box.y1 + parcs->height;
|
|
|
|
/* should I break these up instead ? */
|
|
|
|
while(--narcs) {
|
|
parcs++;
|
|
if(box.x1 > parcs->x) box.x1 = parcs->x;
|
|
if(box.x2 < (parcs->x + parcs->width))
|
|
box.x2 = parcs->x + parcs->width;
|
|
if(box.y1 > parcs->y) box.y1 = parcs->y;
|
|
if(box.y2 < (parcs->y + parcs->height))
|
|
box.y2 = parcs->y + parcs->height;
|
|
}
|
|
|
|
TRIM_AND_TRANSLATE_BOX(box, pDraw, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
|
|
}
|
|
|
|
static int
|
|
shadowPolyText8(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
char *chars
|
|
){
|
|
int width;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
width = (*pGC->ops->PolyText8)(pDraw, pGC, x, y, count, chars);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
width -= x;
|
|
|
|
if(IS_VISIBLE(pDraw) && (width > 0)) {
|
|
BoxRec box;
|
|
|
|
/* ugh */
|
|
box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
|
|
box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
|
|
|
|
if(count > 1) {
|
|
if(width > 0) box.x2 += width;
|
|
else box.x1 += width;
|
|
}
|
|
|
|
box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
|
|
box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
|
|
return (width + x);
|
|
}
|
|
|
|
static int
|
|
shadowPolyText16(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
unsigned short *chars
|
|
){
|
|
int width;
|
|
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
width = (*pGC->ops->PolyText16)(pDraw, pGC, x, y, count, chars);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
width -= x;
|
|
|
|
if(IS_VISIBLE(pDraw) && (width > 0)) {
|
|
BoxRec box;
|
|
|
|
/* ugh */
|
|
box.x1 = pDraw->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
|
|
box.x2 = pDraw->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
|
|
|
|
if(count > 1) {
|
|
if(width > 0) box.x2 += width;
|
|
else box.x1 += width;
|
|
}
|
|
|
|
box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
|
|
box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
|
|
return (width + x);
|
|
}
|
|
|
|
static void
|
|
shadowImageText8(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
char *chars
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->ImageText8)(pDraw, pGC, x, y, count, chars);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && count) {
|
|
int top, bot, Min, Max;
|
|
BoxRec box;
|
|
|
|
top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
|
|
bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
|
|
|
|
Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
|
|
if(Min > 0) Min = 0;
|
|
Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
|
|
if(Max < 0) Max = 0;
|
|
|
|
/* ugh */
|
|
box.x1 = pDraw->x + x + Min +
|
|
FONTMINBOUNDS(pGC->font, leftSideBearing);
|
|
box.x2 = pDraw->x + x + Max +
|
|
FONTMAXBOUNDS(pGC->font, rightSideBearing);
|
|
|
|
box.y1 = pDraw->y + y - top;
|
|
box.y2 = pDraw->y + y + bot;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
static void
|
|
shadowImageText16(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x,
|
|
int y,
|
|
int count,
|
|
unsigned short *chars
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->ImageText16)(pDraw, pGC, x, y, count, chars);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && count) {
|
|
int top, bot, Min, Max;
|
|
BoxRec box;
|
|
|
|
top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
|
|
bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
|
|
|
|
Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
|
|
if(Min > 0) Min = 0;
|
|
Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
|
|
if(Max < 0) Max = 0;
|
|
|
|
/* ugh */
|
|
box.x1 = pDraw->x + x + Min +
|
|
FONTMINBOUNDS(pGC->font, leftSideBearing);
|
|
box.x2 = pDraw->x + x + Max +
|
|
FONTMAXBOUNDS(pGC->font, rightSideBearing);
|
|
|
|
box.y1 = pDraw->y + y - top;
|
|
box.y2 = pDraw->y + y + bot;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
shadowImageGlyphBlt(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x, int y,
|
|
unsigned int nglyph,
|
|
CharInfoPtr *ppci,
|
|
pointer pglyphBase
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->ImageGlyphBlt)(pDraw, pGC, x, y, nglyph,
|
|
ppci, pglyphBase);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && nglyph) {
|
|
int top, bot, width = 0;
|
|
BoxRec box;
|
|
|
|
top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
|
|
bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
|
|
|
|
box.x1 = ppci[0]->metrics.leftSideBearing;
|
|
if(box.x1 > 0) box.x1 = 0;
|
|
box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
|
|
ppci[nglyph - 1]->metrics.characterWidth;
|
|
if(box.x2 < 0) box.x2 = 0;
|
|
|
|
box.x2 += pDraw->x + x;
|
|
box.x1 += pDraw->x + x;
|
|
|
|
while(nglyph--) {
|
|
width += (*ppci)->metrics.characterWidth;
|
|
ppci++;
|
|
}
|
|
|
|
if(width > 0)
|
|
box.x2 += width;
|
|
else
|
|
box.x1 += width;
|
|
|
|
box.y1 = pDraw->y + y - top;
|
|
box.y2 = pDraw->y + y + bot;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
static void
|
|
shadowPolyGlyphBlt(
|
|
DrawablePtr pDraw,
|
|
GCPtr pGC,
|
|
int x, int y,
|
|
unsigned int nglyph,
|
|
CharInfoPtr *ppci,
|
|
pointer pglyphBase
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->PolyGlyphBlt)(pDraw, pGC, x, y, nglyph,
|
|
ppci, pglyphBase);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw) && nglyph) {
|
|
BoxRec box;
|
|
|
|
/* ugh */
|
|
box.x1 = pDraw->x + x + ppci[0]->metrics.leftSideBearing;
|
|
box.x2 = pDraw->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
|
|
|
|
if(nglyph > 1) {
|
|
int width = 0;
|
|
|
|
while(--nglyph) {
|
|
width += (*ppci)->metrics.characterWidth;
|
|
ppci++;
|
|
}
|
|
|
|
if(width > 0) box.x2 += width;
|
|
else box.x1 += width;
|
|
}
|
|
|
|
box.y1 = pDraw->y + y - FONTMAXBOUNDS(pGC->font, ascent);
|
|
box.y2 = pDraw->y + y + FONTMAXBOUNDS(pGC->font, descent);
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
static void
|
|
shadowPushPixels(
|
|
GCPtr pGC,
|
|
PixmapPtr pBitMap,
|
|
DrawablePtr pDraw,
|
|
int dx, int dy, int xOrg, int yOrg
|
|
){
|
|
SHADOW_GC_OP_PROLOGUE(pGC, pDraw);
|
|
(*pGC->ops->PushPixels)(pGC, pBitMap, pDraw, dx, dy, xOrg, yOrg);
|
|
SHADOW_GC_OP_EPILOGUE(pGC, pDraw);
|
|
|
|
if(IS_VISIBLE(pDraw)) {
|
|
BoxRec box;
|
|
|
|
box.x1 = xOrg;
|
|
box.y1 = yOrg;
|
|
|
|
if(!pGC->miTranslate) {
|
|
box.x1 += pDraw->x;
|
|
box.y1 += pDraw->y;
|
|
}
|
|
|
|
box.x2 = box.x1 + dx;
|
|
box.y2 = box.y1 + dy;
|
|
|
|
TRIM_BOX(box, pGC);
|
|
if(BOX_NOT_EMPTY(box))
|
|
shadowDamageBox ((WindowPtr) pDraw, &box);
|
|
}
|
|
}
|
|
|
|
|
|
static void
|
|
shadowPaintWindow(
|
|
WindowPtr pWindow,
|
|
RegionPtr prgn,
|
|
int what
|
|
){
|
|
ScreenPtr pScreen = pWindow->drawable.pScreen;
|
|
shadowScrPriv(pScreen);
|
|
|
|
if(what == PW_BACKGROUND) {
|
|
unwrap (pScrPriv, pScreen, PaintWindowBackground);
|
|
(*pScreen->PaintWindowBackground) (pWindow, prgn, what);
|
|
wrap (pScrPriv, pScreen, PaintWindowBackground, shadowPaintWindow);
|
|
} else {
|
|
unwrap (pScrPriv, pScreen, PaintWindowBorder);
|
|
(*pScreen->PaintWindowBorder) (pWindow, prgn, what);
|
|
wrap (pScrPriv, pScreen, PaintWindowBorder, shadowPaintWindow);
|
|
}
|
|
shadowDamageRegion (pWindow, prgn);
|
|
}
|
|
|
|
|
|
static void
|
|
shadowCopyWindow(
|
|
WindowPtr pWindow,
|
|
DDXPointRec ptOldOrg,
|
|
RegionPtr prgn
|
|
){
|
|
ScreenPtr pScreen = pWindow->drawable.pScreen;
|
|
shadowScrPriv(pScreen);
|
|
|
|
unwrap (pScrPriv, pScreen, CopyWindow);
|
|
(*pScreen->CopyWindow) (pWindow, ptOldOrg, prgn);
|
|
wrap (pScrPriv, pScreen, CopyWindow, shadowCopyWindow);
|
|
shadowDamageRegion (pWindow, prgn);
|
|
}
|
|
|
|
GCOps shadowGCOps = {
|
|
shadowFillSpans, shadowSetSpans,
|
|
shadowPutImage, shadowCopyArea,
|
|
shadowCopyPlane, shadowPolyPoint,
|
|
shadowPolylines, shadowPolySegment,
|
|
shadowPolyRectangle, shadowPolyArc,
|
|
shadowFillPolygon, shadowPolyFillRect,
|
|
shadowPolyFillArc, shadowPolyText8,
|
|
shadowPolyText16, shadowImageText8,
|
|
shadowImageText16, shadowImageGlyphBlt,
|
|
shadowPolyGlyphBlt, shadowPushPixels,
|
|
#ifdef NEED_LINEHELPER
|
|
NULL,
|
|
#endif
|
|
{NULL} /* devPrivate */
|
|
};
|
|
|
|
static void
|
|
shadowGetImage (DrawablePtr pDrawable,
|
|
int sx,
|
|
int sy,
|
|
int w,
|
|
int h,
|
|
unsigned int format,
|
|
unsigned long planeMask,
|
|
char * pdstLine)
|
|
{
|
|
ScreenPtr pScreen = pDrawable->pScreen;
|
|
shadowScrPriv(pScreen);
|
|
|
|
/* Many apps use GetImage to sync with the visable frame buffer */
|
|
if (pDrawable->type == DRAWABLE_WINDOW)
|
|
shadowRedisplay (pScreen);
|
|
unwrap (pScrPriv, pScreen, GetImage);
|
|
(*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planeMask, pdstLine);
|
|
wrap (pScrPriv, pScreen, GetImage, shadowGetImage);
|
|
}
|
|
|
|
static void
|
|
shadowRestoreAreas (PixmapPtr pPixmap,
|
|
RegionPtr prgn,
|
|
int xorg,
|
|
int yorg,
|
|
WindowPtr pWin)
|
|
{
|
|
ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
shadowScrPriv(pScreen);
|
|
|
|
unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
|
|
(*pScreen->BackingStoreFuncs.RestoreAreas) (pPixmap, prgn,
|
|
xorg, yorg, pWin);
|
|
wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
|
|
shadowRestoreAreas);
|
|
shadowDamageRegion (pWin, prgn);
|
|
}
|
|
|
|
static Bool
|
|
shadowCloseScreen (int i, ScreenPtr pScreen)
|
|
{
|
|
shadowScrPriv(pScreen);
|
|
|
|
unwrap (pScrPriv, pScreen, CreateGC);
|
|
unwrap (pScrPriv, pScreen, PaintWindowBackground);
|
|
unwrap (pScrPriv, pScreen, PaintWindowBorder);
|
|
unwrap (pScrPriv, pScreen, CopyWindow);
|
|
unwrap (pScrPriv, pScreen, CloseScreen);
|
|
unwrap (pScrPriv, pScreen, GetImage);
|
|
unwrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas);
|
|
xfree (pScrPriv);
|
|
return (*pScreen->CloseScreen) (i, pScreen);
|
|
}
|
|
|
|
Bool
|
|
shadowSetup (ScreenPtr pScreen)
|
|
{
|
|
shadowScrPrivPtr pScrPriv;
|
|
#ifdef RENDER
|
|
PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
|
|
#endif
|
|
|
|
if (shadowGeneration != serverGeneration)
|
|
{
|
|
shadowScrPrivateIndex = AllocateScreenPrivateIndex ();
|
|
if (shadowScrPrivateIndex == -1)
|
|
return FALSE;
|
|
shadowGCPrivateIndex = AllocateGCPrivateIndex ();
|
|
if (shadowGCPrivateIndex == -1)
|
|
return FALSE;
|
|
shadowGeneration = serverGeneration;
|
|
}
|
|
if (!AllocateGCPrivate (pScreen, shadowGCPrivateIndex, sizeof (shadowGCPrivRec)))
|
|
return FALSE;
|
|
pScrPriv = (shadowScrPrivPtr) xalloc (sizeof (shadowScrPrivRec));
|
|
if (!pScrPriv)
|
|
return FALSE;
|
|
|
|
if (!RegisterBlockAndWakeupHandlers (shadowBlockHandler,
|
|
shadowWakeupHandler,
|
|
(pointer) pScreen))
|
|
return FALSE;
|
|
|
|
wrap (pScrPriv, pScreen, CreateGC, shadowCreateGC);
|
|
wrap (pScrPriv, pScreen, PaintWindowBackground, shadowPaintWindow);
|
|
wrap (pScrPriv, pScreen, PaintWindowBorder, shadowPaintWindow);
|
|
wrap (pScrPriv, pScreen, CopyWindow, shadowCopyWindow);
|
|
wrap (pScrPriv, pScreen, CloseScreen, shadowCloseScreen);
|
|
wrap (pScrPriv, pScreen, GetImage, shadowGetImage);
|
|
wrap (pScrPriv, pScreen, BackingStoreFuncs.RestoreAreas,
|
|
shadowRestoreAreas);
|
|
#ifdef RENDER
|
|
if (ps) {
|
|
wrap (pScrPriv, ps, Glyphs, shadowGlyphs);
|
|
wrap (pScrPriv, ps, Composite, shadowComposite);
|
|
}
|
|
#endif
|
|
pScrPriv->pBuf = 0;
|
|
|
|
pScreen->devPrivates[shadowScrPrivateIndex].ptr = (pointer) pScrPriv;
|
|
return TRUE;
|
|
}
|
|
|
|
Bool
|
|
shadowAdd (ScreenPtr pScreen,
|
|
PixmapPtr pPixmap,
|
|
ShadowUpdateProc update,
|
|
ShadowWindowProc window,
|
|
int randr,
|
|
void *closure)
|
|
{
|
|
shadowScrPriv(pScreen);
|
|
shadowBufPtr pBuf;
|
|
|
|
pBuf = (shadowBufPtr) xalloc (sizeof (shadowBufRec));
|
|
if (!pBuf)
|
|
return FALSE;
|
|
/*
|
|
* Map simple rotation values to bitmasks; fortunately,
|
|
* these are all unique
|
|
*/
|
|
switch (randr) {
|
|
case 0:
|
|
randr = SHADOW_ROTATE_0;
|
|
break;
|
|
case 90:
|
|
randr = SHADOW_ROTATE_90;
|
|
break;
|
|
case 180:
|
|
randr = SHADOW_ROTATE_180;
|
|
break;
|
|
case 270:
|
|
randr = SHADOW_ROTATE_270;
|
|
break;
|
|
}
|
|
pBuf->pPixmap = pPixmap;
|
|
pBuf->update = update;
|
|
pBuf->window = window;
|
|
REGION_NULL(pScreen, &pBuf->damage);
|
|
pBuf->pNext = pScrPriv->pBuf;
|
|
pBuf->randr = randr;
|
|
pBuf->closure = 0;
|
|
pScrPriv->pBuf = pBuf;
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
shadowRemove (ScreenPtr pScreen, PixmapPtr pPixmap)
|
|
{
|
|
shadowScrPriv(pScreen);
|
|
shadowBufPtr pBuf, *pPrev;
|
|
|
|
for (pPrev = &pScrPriv->pBuf; (pBuf = *pPrev); pPrev = &pBuf->pNext)
|
|
if (pBuf->pPixmap == pPixmap)
|
|
{
|
|
REGION_UNINIT (pScreen, &pBuf->damage);
|
|
*pPrev = pBuf->pNext;
|
|
xfree (pBuf);
|
|
break;
|
|
}
|
|
}
|
|
|
|
shadowBufPtr
|
|
shadowFindBuf (WindowPtr pWindow)
|
|
{
|
|
ScreenPtr pScreen = pWindow->drawable.pScreen;
|
|
shadowScrPriv(pScreen);
|
|
shadowBufPtr pBuf, *pPrev;
|
|
PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWindow);
|
|
|
|
for (pPrev = &pScrPriv->pBuf; (pBuf = *pPrev); pPrev = &pBuf->pNext)
|
|
{
|
|
if (!pBuf->pPixmap)
|
|
pBuf->pPixmap = (*pScreen->GetScreenPixmap) (pScreen);
|
|
if (pBuf->pPixmap == pPixmap)
|
|
{
|
|
/*
|
|
* Reorder so this one is first next time
|
|
*/
|
|
if (pPrev != &pScrPriv->pBuf)
|
|
{
|
|
*pPrev = pBuf->pNext;
|
|
pBuf->pNext = pScrPriv->pBuf;
|
|
pScrPriv->pBuf = pBuf;
|
|
}
|
|
return pBuf;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Bool
|
|
shadowInit (ScreenPtr pScreen, ShadowUpdateProc update, ShadowWindowProc window)
|
|
{
|
|
if (!shadowSetup (pScreen))
|
|
return FALSE;
|
|
|
|
if (!shadowAdd (pScreen, 0, update, window, SHADOW_ROTATE_0, 0))
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|