From eaedc21febeadad4cf0e370f5d97e7bdb4470870 Mon Sep 17 00:00:00 2001 From: marha Date: Tue, 5 Apr 2011 09:51:44 +0000 Subject: xserver xkeyboard-config libxcb xkbcomp mesa git update 5 Apr 2011 --- xorg-server/mi/micmap.c | 1338 +++++++++++++++++++++--------------------- xorg-server/mi/midispcur.c | 10 +- xorg-server/mi/mipointer.c | 1395 ++++++++++++++++++++++---------------------- xorg-server/mi/mispans.c | 1052 ++++++++++++++++----------------- xorg-server/mi/mizerline.c | 760 ++++++++++++------------ 5 files changed, 2276 insertions(+), 2279 deletions(-) (limited to 'xorg-server/mi') diff --git a/xorg-server/mi/micmap.c b/xorg-server/mi/micmap.c index 87d4248d0..7448ef8fd 100644 --- a/xorg-server/mi/micmap.c +++ b/xorg-server/mi/micmap.c @@ -1,668 +1,670 @@ -/* - * Copyright (c) 1987, Oracle and/or its affiliates. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -/* - * This is based on cfbcmap.c. The functions here are useful independently - * of cfb, which is the reason for including them here. How "mi" these - * are may be debatable. - */ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "scrnintstr.h" -#include "colormapst.h" -#include "resource.h" -#include "globals.h" -#include "micmap.h" - -DevPrivateKeyRec micmapScrPrivateKeyRec; - -int -miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) -{ - if (GetInstalledmiColormap(pScreen)) { - *pmaps = GetInstalledmiColormap(pScreen)->mid; - return 1; - } - return 0; -} - -void -miInstallColormap(ColormapPtr pmap) -{ - ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen); - - if(pmap != oldpmap) - { - /* Uninstall pInstalledMap. No hardware changes required, just - * notify all interested parties. */ - if(oldpmap != (ColormapPtr)None) - WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); - /* Install pmap */ - SetInstalledmiColormap(pmap->pScreen, pmap); - WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); - - } -} - -void -miUninstallColormap(ColormapPtr pmap) -{ - ColormapPtr curpmap = GetInstalledmiColormap(pmap->pScreen); - - if(pmap == curpmap) - { - if (pmap->mid != pmap->pScreen->defColormap) - { - dixLookupResourceByType((pointer *)&curpmap, - pmap->pScreen->defColormap, - RT_COLORMAP, serverClient, - DixUseAccess); - (*pmap->pScreen->InstallColormap)(curpmap); - } - } -} - -void -miResolveColor(unsigned short *pred, unsigned short *pgreen, - unsigned short *pblue, VisualPtr pVisual) -{ - int shift = 16 - pVisual->bitsPerRGBValue; - unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1; - - if ((pVisual->class | DynamicClass) == GrayScale) - { - /* rescale to gray then rgb bits */ - *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100; - *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim; - } - else - { - /* rescale to rgb bits */ - *pred = ((*pred >> shift) * 65535) / lim; - *pgreen = ((*pgreen >> shift) * 65535) / lim; - *pblue = ((*pblue >> shift) * 65535) / lim; - } -} - -Bool -miInitializeColormap(ColormapPtr pmap) -{ - unsigned i; - VisualPtr pVisual; - unsigned lim, maxent, shift; - - pVisual = pmap->pVisual; - lim = (1 << pVisual->bitsPerRGBValue) - 1; - shift = 16 - pVisual->bitsPerRGBValue; - maxent = pVisual->ColormapEntries - 1; - if (pVisual->class == TrueColor) - { - unsigned limr, limg, limb; - - limr = pVisual->redMask >> pVisual->offsetRed; - limg = pVisual->greenMask >> pVisual->offsetGreen; - limb = pVisual->blueMask >> pVisual->offsetBlue; - for(i = 0; i <= maxent; i++) - { - /* rescale to [0..65535] then rgb bits */ - pmap->red[i].co.local.red = - ((((i * 65535) / limr) >> shift) * 65535) / lim; - pmap->green[i].co.local.green = - ((((i * 65535) / limg) >> shift) * 65535) / lim; - pmap->blue[i].co.local.blue = - ((((i * 65535) / limb) >> shift) * 65535) / lim; - } - } - else if (pVisual->class == StaticColor) - { - unsigned limr, limg, limb; - - limr = pVisual->redMask >> pVisual->offsetRed; - limg = pVisual->greenMask >> pVisual->offsetGreen; - limb = pVisual->blueMask >> pVisual->offsetBlue; - for(i = 0; i <= maxent; i++) - { - /* rescale to [0..65535] then rgb bits */ - pmap->red[i].co.local.red = - ((((((i & pVisual->redMask) >> pVisual->offsetRed) - * 65535) / limr) >> shift) * 65535) / lim; - pmap->red[i].co.local.green = - ((((((i & pVisual->greenMask) >> pVisual->offsetGreen) - * 65535) / limg) >> shift) * 65535) / lim; - pmap->red[i].co.local.blue = - ((((((i & pVisual->blueMask) >> pVisual->offsetBlue) - * 65535) / limb) >> shift) * 65535) / lim; - } - } - else if (pVisual->class == StaticGray) - { - for(i = 0; i <= maxent; i++) - { - /* rescale to [0..65535] then rgb bits */ - pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift) - * 65535) / lim; - pmap->red[i].co.local.green = pmap->red[i].co.local.red; - pmap->red[i].co.local.blue = pmap->red[i].co.local.red; - } - } - return TRUE; -} - -/* When simulating DirectColor on PseudoColor hardware, multiple - entries of the colormap must be updated - */ - -#define AddElement(mask) { \ - pixel = red | green | blue; \ - for (i = 0; i < nresult; i++) \ - if (outdefs[i].pixel == pixel) \ - break; \ - if (i == nresult) \ - { \ - nresult++; \ - outdefs[i].pixel = pixel; \ - outdefs[i].flags = 0; \ - } \ - outdefs[i].flags |= (mask); \ - outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \ - outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \ - outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \ -} - -int -miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs, - xColorItem *outdefs) -{ - int red, green, blue; - int maxred, maxgreen, maxblue; - int stepred, stepgreen, stepblue; - VisualPtr pVisual; - int pixel; - int nresult; - int i; - - pVisual = pmap->pVisual; - - stepred = 1 << pVisual->offsetRed; - stepgreen = 1 << pVisual->offsetGreen; - stepblue = 1 << pVisual->offsetBlue; - maxred = pVisual->redMask; - maxgreen = pVisual->greenMask; - maxblue = pVisual->blueMask; - nresult = 0; - for (;ndef--; indefs++) - { - if (indefs->flags & DoRed) - { - red = indefs->pixel & pVisual->redMask; - for (green = 0; green <= maxgreen; green += stepgreen) - { - for (blue = 0; blue <= maxblue; blue += stepblue) - { - AddElement (DoRed) - } - } - } - if (indefs->flags & DoGreen) - { - green = indefs->pixel & pVisual->greenMask; - for (red = 0; red <= maxred; red += stepred) - { - for (blue = 0; blue <= maxblue; blue += stepblue) - { - AddElement (DoGreen) - } - } - } - if (indefs->flags & DoBlue) - { - blue = indefs->pixel & pVisual->blueMask; - for (red = 0; red <= maxred; red += stepred) - { - for (green = 0; green <= maxgreen; green += stepgreen) - { - AddElement (DoBlue) - } - } - } - } - return nresult; -} - -Bool -miCreateDefColormap(ScreenPtr pScreen) -{ -/* - * In the following sources PC X server vendors may want to delete - * "_not_tog" from "#ifdef WIN32_not_tog" - */ -#ifdef WIN32_not_tog - /* - * these are the MS-Windows desktop colors, adjusted for X's 16-bit - * color specifications. - */ - static xColorItem citems[] = { - { 0, 0, 0, 0, 0, 0 }, - { 1, 0x8000, 0, 0, 0, 0 }, - { 2, 0, 0x8000, 0, 0, 0 }, - { 3, 0x8000, 0x8000, 0, 0, 0 }, - { 4, 0, 0, 0x8000, 0, 0 }, - { 5, 0x8000, 0, 0x8000, 0, 0 }, - { 6, 0, 0x8000, 0x8000, 0, 0 }, - { 7, 0xc000, 0xc000, 0xc000, 0, 0 }, - { 8, 0xc000, 0xdc00, 0xc000, 0, 0 }, - { 9, 0xa600, 0xca00, 0xf000, 0, 0 }, - { 246, 0xff00, 0xfb00, 0xf000, 0, 0 }, - { 247, 0xa000, 0xa000, 0xa400, 0, 0 }, - { 248, 0x8000, 0x8000, 0x8000, 0, 0 }, - { 249, 0xff00, 0, 0, 0, 0 }, - { 250, 0, 0xff00, 0, 0, 0 }, - { 251, 0xff00, 0xff00, 0, 0, 0 }, - { 252, 0, 0, 0xff00, 0, 0 }, - { 253, 0xff00, 0, 0xff00, 0, 0 }, - { 254, 0, 0xff00, 0xff00, 0, 0 }, - { 255, 0xff00, 0xff00, 0xff00, 0, 0 } - }; -#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0] - int i; -#else - unsigned short zero = 0, ones = 0xFFFF; -#endif - Pixel wp, bp; - VisualPtr pVisual; - ColormapPtr cmap; - int alloctype; - - if (!dixRegisterPrivateKey(&micmapScrPrivateKeyRec, PRIVATE_SCREEN, 0)) - return FALSE; - - for (pVisual = pScreen->visuals; - pVisual->vid != pScreen->rootVisual; - pVisual++) - ; - - if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass)) - alloctype = AllocNone; - else - alloctype = AllocAll; - - if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap, - alloctype, 0) != Success) - return FALSE; - - if (pScreen->rootDepth > 1) { - wp = pScreen->whitePixel; - bp = pScreen->blackPixel; -#ifdef WIN32_not_tog - for (i = 0; i < NUM_DESKTOP_COLORS; i++) { - if (AllocColor (cmap, - &citems[i].red, &citems[i].green, &citems[i].blue, - &citems[i].pixel, 0) != Success) - return FALSE; - } -#else - if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) != - Success) || - (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != - Success)) - return FALSE; - pScreen->whitePixel = wp; - pScreen->blackPixel = bp; -#endif - } - - (*pScreen->InstallColormap)(cmap); - return TRUE; -} - -/* - * Default true color bitmasks, should be overridden by - * driver - */ - -#define _RZ(d) ((d + 2) / 3) -#define _RS(d) 0 -#define _RM(d) ((1 << _RZ(d)) - 1) -#define _GZ(d) ((d - _RZ(d) + 1) / 2) -#define _GS(d) _RZ(d) -#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d)) -#define _BZ(d) (d - _RZ(d) - _GZ(d)) -#define _BS(d) (_RZ(d) + _GZ(d)) -#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d)) -#define _CE(d) (1 << _RZ(d)) - -typedef struct _miVisuals { - struct _miVisuals *next; - int depth; - int bitsPerRGB; - int visuals; - int count; - int preferredCVC; - Pixel redMask, greenMask, blueMask; -} miVisualsRec, *miVisualsPtr; - -static int miVisualPriority[] = { - PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray -}; - -#define NUM_PRIORITY 6 - -static miVisualsPtr miVisuals; - -void -miClearVisualTypes(void) -{ - miVisualsPtr v; - - while ((v = miVisuals)) { - miVisuals = v->next; - free(v); - } -} - - -Bool -miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB, - int preferredCVC, - Pixel redMask, Pixel greenMask, Pixel blueMask) -{ - miVisualsPtr new, *prev, v; - int count; - - new = malloc(sizeof *new); - if (!new) - return FALSE; - if (!redMask || !greenMask || !blueMask) - { - redMask = _RM(depth); - greenMask = _GM(depth); - blueMask = _BM(depth); - } - new->next = 0; - new->depth = depth; - new->visuals = visuals; - new->bitsPerRGB = bitsPerRGB; - new->preferredCVC = preferredCVC; - new->redMask = redMask; - new->greenMask = greenMask; - new->blueMask = blueMask; - count = (visuals >> 1) & 033333333333; - count = visuals - count - ((count >> 1) & 033333333333); - count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */ - new->count = count; - for (prev = &miVisuals; (v = *prev); prev = &v->next); - *prev = new; - return TRUE; -} - -Bool -miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC) -{ - return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB, - preferredCVC, 0, 0, 0); -} - -int -miGetDefaultVisualMask(int depth) -{ - if (depth > MAX_PSEUDO_DEPTH) - return LARGE_VISUALS; - else if (depth >= MIN_TRUE_DEPTH) - return ALL_VISUALS; - else if (depth == 1) - return StaticGrayMask; - else - return SMALL_VISUALS; -} - -static Bool -miVisualTypesSet (int depth) -{ - miVisualsPtr visuals; - - for (visuals = miVisuals; visuals; visuals = visuals->next) - if (visuals->depth == depth) - return TRUE; - return FALSE; -} - -Bool -miSetPixmapDepths (void) -{ - int d, f; - - /* Add any unlisted depths from the pixmap formats */ - for (f = 0; f < screenInfo.numPixmapFormats; f++) - { - d = screenInfo.formats[f].depth; - if (!miVisualTypesSet (d)) - { - if (!miSetVisualTypes (d, 0, 0, -1)) - return FALSE; - } - } - return TRUE; -} - -/* - * Distance to least significant one bit - */ -static int -maskShift (Pixel p) -{ - int s; - - if (!p) return 0; - s = 0; - while (!(p & 1)) - { - s++; - p >>= 1; - } - return s; -} - -/* - * Given a list of formats for a screen, create a list - * of visuals and depths for the screen which corespond to - * the set which can be used with this version of cfb. - */ - -Bool -miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp, - int *ndepthp, int *rootDepthp, VisualID *defaultVisp, - unsigned long sizes, int bitsPerRGB, int preferredVis) - -{ - int i, j = 0, k; - VisualPtr visual; - DepthPtr depth; - VisualID *vid; - int d, b; - int f; - int ndepth, nvisual; - int nvtype; - int vtype; - miVisualsPtr visuals, nextVisuals; - int *preferredCVCs, *prefp; - int first_depth; - - /* none specified, we'll guess from pixmap formats */ - if (!miVisuals) - { - for (f = 0; f < screenInfo.numPixmapFormats; f++) - { - d = screenInfo.formats[f].depth; - b = screenInfo.formats[f].bitsPerPixel; - if (sizes & (1 << (b - 1))) - vtype = miGetDefaultVisualMask(d); - else - vtype = 0; - if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1)) - return FALSE; - } - } - nvisual = 0; - ndepth = 0; - for (visuals = miVisuals; visuals; visuals = nextVisuals) - { - nextVisuals = visuals->next; - ndepth++; - nvisual += visuals->count; - } - depth = malloc(ndepth * sizeof (DepthRec)); - visual = malloc(nvisual * sizeof (VisualRec)); - preferredCVCs = malloc(ndepth * sizeof(int)); - if (!depth || !visual || !preferredCVCs) - { - free(depth); - free(visual); - free(preferredCVCs); - return FALSE; - } - *depthp = depth; - *visualp = visual; - *ndepthp = ndepth; - *nvisualp = nvisual; - prefp = preferredCVCs; - for (visuals = miVisuals; visuals; visuals = nextVisuals) - { - nextVisuals = visuals->next; - d = visuals->depth; - vtype = visuals->visuals; - nvtype = visuals->count; - *prefp = visuals->preferredCVC; - prefp++; - vid = NULL; - if (nvtype) - { - vid = malloc(nvtype * sizeof (VisualID)); - if (!vid) { - free(preferredCVCs); - return FALSE; - } - } - depth->depth = d; - depth->numVids = nvtype; - depth->vids = vid; - depth++; - for (i = 0; i < NUM_PRIORITY; i++) { - if (! (vtype & (1 << miVisualPriority[i]))) - continue; - visual->class = miVisualPriority[i]; - visual->bitsPerRGBValue = visuals->bitsPerRGB; - visual->ColormapEntries = 1 << d; - visual->nplanes = d; - visual->vid = *vid = FakeClientID (0); - switch (visual->class) { - case PseudoColor: - case GrayScale: - case StaticGray: - visual->redMask = 0; - visual->greenMask = 0; - visual->blueMask = 0; - visual->offsetRed = 0; - visual->offsetGreen = 0; - visual->offsetBlue = 0; - break; - case DirectColor: - case TrueColor: - visual->ColormapEntries = _CE(d); - /* fall through */ - case StaticColor: - visual->redMask = visuals->redMask; - visual->greenMask = visuals->greenMask; - visual->blueMask = visuals->blueMask; - visual->offsetRed = maskShift (visuals->redMask); - visual->offsetGreen = maskShift (visuals->greenMask); - visual->offsetBlue = maskShift (visuals->blueMask); - } - vid++; - visual++; - } - free(visuals); - } - miVisuals = NULL; - visual = *visualp; - depth = *depthp; - - /* - * if we did not supplyied by a preferred visual class - * check if there is a preferred class in one of the depth - * structures - if there is, we want to start looking for the - * default visual/depth from that depth. - */ - first_depth = 0; - if (preferredVis < 0 && defaultColorVisualClass < 0 ) { - for (i = 0; i < ndepth; i++) { - if (preferredCVCs[i] >= 0) { - first_depth = i; - break; - } - } - } - - for (i = first_depth; i < ndepth; i++) - { - int prefColorVisualClass = -1; - - if (defaultColorVisualClass >= 0) - prefColorVisualClass = defaultColorVisualClass; - else if (preferredVis >= 0) - prefColorVisualClass = preferredVis; - else if (preferredCVCs[i] >= 0) - prefColorVisualClass = preferredCVCs[i]; - - if (*rootDepthp && *rootDepthp != depth[i].depth) - continue; - - for (j = 0; j < depth[i].numVids; j++) - { - for (k = 0; k < nvisual; k++) - if (visual[k].vid == depth[i].vids[j]) - break; - if (k == nvisual) - continue; - if (prefColorVisualClass < 0 || - visual[k].class == prefColorVisualClass) - break; - } - if (j != depth[i].numVids) - break; - } - if (i == ndepth) { - i = 0; - j = 0; - } - *rootDepthp = depth[i].depth; - *defaultVisp = depth[i].vids[j]; - free(preferredCVCs); - - return TRUE; -} +/* + * Copyright (c) 1987, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* + * This is based on cfbcmap.c. The functions here are useful independently + * of cfb, which is the reason for including them here. How "mi" these + * are may be debatable. + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "scrnintstr.h" +#include "colormapst.h" +#include "resource.h" +#include "globals.h" +#include "micmap.h" + +DevPrivateKeyRec micmapScrPrivateKeyRec; + +int +miListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps) +{ + if (GetInstalledmiColormap(pScreen)) { + *pmaps = GetInstalledmiColormap(pScreen)->mid; + return 1; + } + return 0; +} + +void +miInstallColormap(ColormapPtr pmap) +{ + ColormapPtr oldpmap = GetInstalledmiColormap(pmap->pScreen); + + if(pmap != oldpmap) + { + /* Uninstall pInstalledMap. No hardware changes required, just + * notify all interested parties. */ + if(oldpmap != (ColormapPtr)None) + WalkTree(pmap->pScreen, TellLostMap, (char *)&oldpmap->mid); + /* Install pmap */ + SetInstalledmiColormap(pmap->pScreen, pmap); + WalkTree(pmap->pScreen, TellGainedMap, (char *)&pmap->mid); + + } +} + +void +miUninstallColormap(ColormapPtr pmap) +{ + ColormapPtr curpmap = GetInstalledmiColormap(pmap->pScreen); + + if(pmap == curpmap) + { + if (pmap->mid != pmap->pScreen->defColormap) + { + dixLookupResourceByType((pointer *)&curpmap, + pmap->pScreen->defColormap, + RT_COLORMAP, serverClient, + DixUseAccess); + (*pmap->pScreen->InstallColormap)(curpmap); + } + } +} + +void +miResolveColor(unsigned short *pred, unsigned short *pgreen, + unsigned short *pblue, VisualPtr pVisual) +{ + int shift = 16 - pVisual->bitsPerRGBValue; + unsigned lim = (1 << pVisual->bitsPerRGBValue) - 1; + + if ((pVisual->class | DynamicClass) == GrayScale) + { + /* rescale to gray then rgb bits */ + *pred = (30L * *pred + 59L * *pgreen + 11L * *pblue) / 100; + *pblue = *pgreen = *pred = ((*pred >> shift) * 65535) / lim; + } + else + { + /* rescale to rgb bits */ + *pred = ((*pred >> shift) * 65535) / lim; + *pgreen = ((*pgreen >> shift) * 65535) / lim; + *pblue = ((*pblue >> shift) * 65535) / lim; + } +} + +Bool +miInitializeColormap(ColormapPtr pmap) +{ + unsigned i; + VisualPtr pVisual; + unsigned lim, maxent, shift; + + pVisual = pmap->pVisual; + lim = (1 << pVisual->bitsPerRGBValue) - 1; + shift = 16 - pVisual->bitsPerRGBValue; + maxent = pVisual->ColormapEntries - 1; + if (pVisual->class == TrueColor) + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + for(i = 0; i <= maxent; i++) + { + /* rescale to [0..65535] then rgb bits */ + pmap->red[i].co.local.red = + ((((i * 65535) / limr) >> shift) * 65535) / lim; + pmap->green[i].co.local.green = + ((((i * 65535) / limg) >> shift) * 65535) / lim; + pmap->blue[i].co.local.blue = + ((((i * 65535) / limb) >> shift) * 65535) / lim; + } + } + else if (pVisual->class == StaticColor) + { + unsigned limr, limg, limb; + + limr = pVisual->redMask >> pVisual->offsetRed; + limg = pVisual->greenMask >> pVisual->offsetGreen; + limb = pVisual->blueMask >> pVisual->offsetBlue; + for(i = 0; i <= maxent; i++) + { + /* rescale to [0..65535] then rgb bits */ + pmap->red[i].co.local.red = + ((((((i & pVisual->redMask) >> pVisual->offsetRed) + * 65535) / limr) >> shift) * 65535) / lim; + pmap->red[i].co.local.green = + ((((((i & pVisual->greenMask) >> pVisual->offsetGreen) + * 65535) / limg) >> shift) * 65535) / lim; + pmap->red[i].co.local.blue = + ((((((i & pVisual->blueMask) >> pVisual->offsetBlue) + * 65535) / limb) >> shift) * 65535) / lim; + } + } + else if (pVisual->class == StaticGray) + { + for(i = 0; i <= maxent; i++) + { + /* rescale to [0..65535] then rgb bits */ + pmap->red[i].co.local.red = ((((i * 65535) / maxent) >> shift) + * 65535) / lim; + pmap->red[i].co.local.green = pmap->red[i].co.local.red; + pmap->red[i].co.local.blue = pmap->red[i].co.local.red; + } + } + return TRUE; +} + +/* When simulating DirectColor on PseudoColor hardware, multiple + entries of the colormap must be updated + */ + +#define AddElement(mask) { \ + pixel = red | green | blue; \ + for (i = 0; i < nresult; i++) \ + if (outdefs[i].pixel == pixel) \ + break; \ + if (i == nresult) \ + { \ + nresult++; \ + outdefs[i].pixel = pixel; \ + outdefs[i].flags = 0; \ + } \ + outdefs[i].flags |= (mask); \ + outdefs[i].red = pmap->red[red >> pVisual->offsetRed].co.local.red; \ + outdefs[i].green = pmap->green[green >> pVisual->offsetGreen].co.local.green; \ + outdefs[i].blue = pmap->blue[blue >> pVisual->offsetBlue].co.local.blue; \ +} + +int +miExpandDirectColors(ColormapPtr pmap, int ndef, xColorItem *indefs, + xColorItem *outdefs) +{ + int red, green, blue; + int maxred, maxgreen, maxblue; + int stepred, stepgreen, stepblue; + VisualPtr pVisual; + int pixel; + int nresult; + int i; + + pVisual = pmap->pVisual; + + stepred = 1 << pVisual->offsetRed; + stepgreen = 1 << pVisual->offsetGreen; + stepblue = 1 << pVisual->offsetBlue; + maxred = pVisual->redMask; + maxgreen = pVisual->greenMask; + maxblue = pVisual->blueMask; + nresult = 0; + for (;ndef--; indefs++) + { + if (indefs->flags & DoRed) + { + red = indefs->pixel & pVisual->redMask; + for (green = 0; green <= maxgreen; green += stepgreen) + { + for (blue = 0; blue <= maxblue; blue += stepblue) + { + AddElement (DoRed) + } + } + } + if (indefs->flags & DoGreen) + { + green = indefs->pixel & pVisual->greenMask; + for (red = 0; red <= maxred; red += stepred) + { + for (blue = 0; blue <= maxblue; blue += stepblue) + { + AddElement (DoGreen) + } + } + } + if (indefs->flags & DoBlue) + { + blue = indefs->pixel & pVisual->blueMask; + for (red = 0; red <= maxred; red += stepred) + { + for (green = 0; green <= maxgreen; green += stepgreen) + { + AddElement (DoBlue) + } + } + } + } + return nresult; +} + +Bool +miCreateDefColormap(ScreenPtr pScreen) +{ +/* + * In the following sources PC X server vendors may want to delete + * "_not_tog" from "#ifdef WIN32_not_tog" + */ +#ifdef WIN32_not_tog + /* + * these are the MS-Windows desktop colors, adjusted for X's 16-bit + * color specifications. + */ + static xColorItem citems[] = { + { 0, 0, 0, 0, 0, 0 }, + { 1, 0x8000, 0, 0, 0, 0 }, + { 2, 0, 0x8000, 0, 0, 0 }, + { 3, 0x8000, 0x8000, 0, 0, 0 }, + { 4, 0, 0, 0x8000, 0, 0 }, + { 5, 0x8000, 0, 0x8000, 0, 0 }, + { 6, 0, 0x8000, 0x8000, 0, 0 }, + { 7, 0xc000, 0xc000, 0xc000, 0, 0 }, + { 8, 0xc000, 0xdc00, 0xc000, 0, 0 }, + { 9, 0xa600, 0xca00, 0xf000, 0, 0 }, + { 246, 0xff00, 0xfb00, 0xf000, 0, 0 }, + { 247, 0xa000, 0xa000, 0xa400, 0, 0 }, + { 248, 0x8000, 0x8000, 0x8000, 0, 0 }, + { 249, 0xff00, 0, 0, 0, 0 }, + { 250, 0, 0xff00, 0, 0, 0 }, + { 251, 0xff00, 0xff00, 0, 0, 0 }, + { 252, 0, 0, 0xff00, 0, 0 }, + { 253, 0xff00, 0, 0xff00, 0, 0 }, + { 254, 0, 0xff00, 0xff00, 0, 0 }, + { 255, 0xff00, 0xff00, 0xff00, 0, 0 } + }; +#define NUM_DESKTOP_COLORS sizeof citems / sizeof citems[0] + int i; +#else + unsigned short zero = 0, ones = 0xFFFF; +#endif + Pixel wp, bp; + VisualPtr pVisual; + ColormapPtr cmap; + int alloctype; + + if (!dixRegisterPrivateKey(&micmapScrPrivateKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + for (pVisual = pScreen->visuals; + pVisual->vid != pScreen->rootVisual; + pVisual++) + ; + + if (pScreen->rootDepth == 1 || (pVisual->class & DynamicClass)) + alloctype = AllocNone; + else + alloctype = AllocAll; + + if (CreateColormap(pScreen->defColormap, pScreen, pVisual, &cmap, + alloctype, 0) != Success) + return FALSE; + + if (pScreen->rootDepth > 1) { + wp = pScreen->whitePixel; + bp = pScreen->blackPixel; +#ifdef WIN32_not_tog + for (i = 0; i < NUM_DESKTOP_COLORS; i++) { + if (AllocColor (cmap, + &citems[i].red, &citems[i].green, &citems[i].blue, + &citems[i].pixel, 0) != Success) + return FALSE; + } +#else + if ((AllocColor(cmap, &ones, &ones, &ones, &wp, 0) != + Success) || + (AllocColor(cmap, &zero, &zero, &zero, &bp, 0) != + Success)) + return FALSE; + pScreen->whitePixel = wp; + pScreen->blackPixel = bp; +#endif + } + + (*pScreen->InstallColormap)(cmap); + return TRUE; +} + +/* + * Default true color bitmasks, should be overridden by + * driver + */ + +#define _RZ(d) ((d + 2) / 3) +#define _RS(d) 0 +#define _RM(d) ((1 << _RZ(d)) - 1) +#define _GZ(d) ((d - _RZ(d) + 1) / 2) +#define _GS(d) _RZ(d) +#define _GM(d) (((1 << _GZ(d)) - 1) << _GS(d)) +#define _BZ(d) (d - _RZ(d) - _GZ(d)) +#define _BS(d) (_RZ(d) + _GZ(d)) +#define _BM(d) (((1 << _BZ(d)) - 1) << _BS(d)) +#define _CE(d) (1 << _RZ(d)) + +typedef struct _miVisuals { + struct _miVisuals *next; + int depth; + int bitsPerRGB; + int visuals; + int count; + int preferredCVC; + Pixel redMask, greenMask, blueMask; +} miVisualsRec, *miVisualsPtr; + +static int miVisualPriority[] = { + PseudoColor, GrayScale, StaticColor, TrueColor, DirectColor, StaticGray +}; + +#define NUM_PRIORITY 6 + +static miVisualsPtr miVisuals; + +void +miClearVisualTypes(void) +{ + miVisualsPtr v; + + while ((v = miVisuals)) { + miVisuals = v->next; + free(v); + } +} + + +Bool +miSetVisualTypesAndMasks(int depth, int visuals, int bitsPerRGB, + int preferredCVC, + Pixel redMask, Pixel greenMask, Pixel blueMask) +{ + miVisualsPtr new, *prev, v; + int count; + + new = malloc(sizeof *new); + if (!new) + return FALSE; + if (!redMask || !greenMask || !blueMask) + { + redMask = _RM(depth); + greenMask = _GM(depth); + blueMask = _BM(depth); + } + new->next = 0; + new->depth = depth; + new->visuals = visuals; + new->bitsPerRGB = bitsPerRGB; + new->preferredCVC = preferredCVC; + new->redMask = redMask; + new->greenMask = greenMask; + new->blueMask = blueMask; + count = (visuals >> 1) & 033333333333; + count = visuals - count - ((count >> 1) & 033333333333); + count = (((count + (count >> 3)) & 030707070707) % 077); /* HAKMEM 169 */ + new->count = count; + for (prev = &miVisuals; (v = *prev); prev = &v->next); + *prev = new; + return TRUE; +} + +Bool +miSetVisualTypes(int depth, int visuals, int bitsPerRGB, int preferredCVC) +{ + return miSetVisualTypesAndMasks (depth, visuals, bitsPerRGB, + preferredCVC, 0, 0, 0); +} + +int +miGetDefaultVisualMask(int depth) +{ + if (depth > MAX_PSEUDO_DEPTH) + return LARGE_VISUALS; + else if (depth >= MIN_TRUE_DEPTH) + return ALL_VISUALS; + else if (depth == 1) + return StaticGrayMask; + else + return SMALL_VISUALS; +} + +static Bool +miVisualTypesSet (int depth) +{ + miVisualsPtr visuals; + + for (visuals = miVisuals; visuals; visuals = visuals->next) + if (visuals->depth == depth) + return TRUE; + return FALSE; +} + +Bool +miSetPixmapDepths (void) +{ + int d, f; + + /* Add any unlisted depths from the pixmap formats */ + for (f = 0; f < screenInfo.numPixmapFormats; f++) + { + d = screenInfo.formats[f].depth; + if (!miVisualTypesSet (d)) + { + if (!miSetVisualTypes (d, 0, 0, -1)) + return FALSE; + } + } + return TRUE; +} + +/* + * Distance to least significant one bit + */ +static int +maskShift (Pixel p) +{ + int s; + + if (!p) return 0; + s = 0; + while (!(p & 1)) + { + s++; + p >>= 1; + } + return s; +} + +/* + * Given a list of formats for a screen, create a list + * of visuals and depths for the screen which corespond to + * the set which can be used with this version of cfb. + */ + +Bool +miInitVisuals(VisualPtr *visualp, DepthPtr *depthp, int *nvisualp, + int *ndepthp, int *rootDepthp, VisualID *defaultVisp, + unsigned long sizes, int bitsPerRGB, int preferredVis) + +{ + int i, j = 0, k; + VisualPtr visual; + DepthPtr depth; + VisualID *vid; + int d, b; + int f; + int ndepth, nvisual; + int nvtype; + int vtype; + miVisualsPtr visuals, nextVisuals; + int *preferredCVCs, *prefp; + int first_depth; + + /* none specified, we'll guess from pixmap formats */ + if (!miVisuals) + { + for (f = 0; f < screenInfo.numPixmapFormats; f++) + { + d = screenInfo.formats[f].depth; + b = screenInfo.formats[f].bitsPerPixel; + if (sizes & (1 << (b - 1))) + vtype = miGetDefaultVisualMask(d); + else + vtype = 0; + if (!miSetVisualTypes (d, vtype, bitsPerRGB, -1)) + return FALSE; + } + } + nvisual = 0; + ndepth = 0; + for (visuals = miVisuals; visuals; visuals = nextVisuals) + { + nextVisuals = visuals->next; + ndepth++; + nvisual += visuals->count; + } + depth = malloc(ndepth * sizeof (DepthRec)); + visual = malloc(nvisual * sizeof (VisualRec)); + preferredCVCs = malloc(ndepth * sizeof(int)); + if (!depth || !visual || !preferredCVCs) + { + free(depth); + free(visual); + free(preferredCVCs); + return FALSE; + } + *depthp = depth; + *visualp = visual; + *ndepthp = ndepth; + *nvisualp = nvisual; + prefp = preferredCVCs; + for (visuals = miVisuals; visuals; visuals = nextVisuals) + { + nextVisuals = visuals->next; + d = visuals->depth; + vtype = visuals->visuals; + nvtype = visuals->count; + *prefp = visuals->preferredCVC; + prefp++; + vid = NULL; + if (nvtype) + { + vid = malloc(nvtype * sizeof (VisualID)); + if (!vid) { + free(depth); + free(visual); + free(preferredCVCs); + return FALSE; + } + } + depth->depth = d; + depth->numVids = nvtype; + depth->vids = vid; + depth++; + for (i = 0; i < NUM_PRIORITY; i++) { + if (! (vtype & (1 << miVisualPriority[i]))) + continue; + visual->class = miVisualPriority[i]; + visual->bitsPerRGBValue = visuals->bitsPerRGB; + visual->ColormapEntries = 1 << d; + visual->nplanes = d; + visual->vid = *vid = FakeClientID (0); + switch (visual->class) { + case PseudoColor: + case GrayScale: + case StaticGray: + visual->redMask = 0; + visual->greenMask = 0; + visual->blueMask = 0; + visual->offsetRed = 0; + visual->offsetGreen = 0; + visual->offsetBlue = 0; + break; + case DirectColor: + case TrueColor: + visual->ColormapEntries = _CE(d); + /* fall through */ + case StaticColor: + visual->redMask = visuals->redMask; + visual->greenMask = visuals->greenMask; + visual->blueMask = visuals->blueMask; + visual->offsetRed = maskShift (visuals->redMask); + visual->offsetGreen = maskShift (visuals->greenMask); + visual->offsetBlue = maskShift (visuals->blueMask); + } + vid++; + visual++; + } + free(visuals); + } + miVisuals = NULL; + visual = *visualp; + depth = *depthp; + + /* + * if we did not supplyied by a preferred visual class + * check if there is a preferred class in one of the depth + * structures - if there is, we want to start looking for the + * default visual/depth from that depth. + */ + first_depth = 0; + if (preferredVis < 0 && defaultColorVisualClass < 0 ) { + for (i = 0; i < ndepth; i++) { + if (preferredCVCs[i] >= 0) { + first_depth = i; + break; + } + } + } + + for (i = first_depth; i < ndepth; i++) + { + int prefColorVisualClass = -1; + + if (defaultColorVisualClass >= 0) + prefColorVisualClass = defaultColorVisualClass; + else if (preferredVis >= 0) + prefColorVisualClass = preferredVis; + else if (preferredCVCs[i] >= 0) + prefColorVisualClass = preferredCVCs[i]; + + if (*rootDepthp && *rootDepthp != depth[i].depth) + continue; + + for (j = 0; j < depth[i].numVids; j++) + { + for (k = 0; k < nvisual; k++) + if (visual[k].vid == depth[i].vids[j]) + break; + if (k == nvisual) + continue; + if (prefColorVisualClass < 0 || + visual[k].class == prefColorVisualClass) + break; + } + if (j != depth[i].numVids) + break; + } + if (i == ndepth) { + i = 0; + j = 0; + } + *rootDepthp = depth[i].depth; + *defaultVisp = depth[i].vids[j]; + free(preferredCVCs); + + return TRUE; +} diff --git a/xorg-server/mi/midispcur.c b/xorg-server/mi/midispcur.c index 9b3e87a57..32c5c9df6 100644 --- a/xorg-server/mi/midispcur.c +++ b/xorg-server/mi/midispcur.c @@ -397,7 +397,6 @@ Bool miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y, unsigned long source, unsigned long mask) { - miDCScreenPtr pScreenPriv; miDCCursorPtr pPriv; miDCBufferPtr pBuffer; WindowPtr pWin; @@ -410,8 +409,7 @@ miDCPutUpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, if (!pPriv) return FALSE; } - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); + pWin = pScreen->root; pBuffer = miGetDCDevice(pDev, pScreen); @@ -444,14 +442,11 @@ Bool miDCSaveUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, int w, int h) { - miDCScreenPtr pScreenPriv; miDCBufferPtr pBuffer; PixmapPtr pSave; WindowPtr pWin; GCPtr pGC; - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); pBuffer = miGetDCDevice(pDev, pScreen); pSave = pBuffer->pSave; @@ -478,14 +473,11 @@ Bool miDCRestoreUnderCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, int w, int h) { - miDCScreenPtr pScreenPriv; miDCBufferPtr pBuffer; PixmapPtr pSave; WindowPtr pWin; GCPtr pGC; - pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - miDCScreenKey); pBuffer = miGetDCDevice(pDev, pScreen); pSave = pBuffer->pSave; diff --git a/xorg-server/mi/mipointer.c b/xorg-server/mi/mipointer.c index e8ed106ea..db243810c 100644 --- a/xorg-server/mi/mipointer.c +++ b/xorg-server/mi/mipointer.c @@ -1,698 +1,697 @@ -/* - -Copyright 1989, 1998 The Open Group - -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. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. -*/ - -/** - * @file - * This file contains functions to move the pointer on the screen and/or - * restrict its movement. These functions are divided into two sets: - * Screen-specific functions that are used as function pointers from other - * parts of the server (and end up heavily wrapped by e.g. animcur and - * xfixes): - * miPointerConstrainCursor - * miPointerCursorLimits - * miPointerDisplayCursor - * miPointerRealizeCursor - * miPointerUnrealizeCursor - * miPointerSetCursorPosition - * miRecolorCursor - * miPointerDeviceInitialize - * miPointerDeviceCleanup - * If wrapped, these are the last element in the wrapping chain. They may - * call into sprite-specific code through further function pointers though. - * - * The second type of functions are those that are directly called by the - * DIX, DDX and some drivers. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -# include -# include -# include -# include "misc.h" -# include "windowstr.h" -# include "pixmapstr.h" -# include "mi.h" -# include "scrnintstr.h" -# include "mipointrst.h" -# include "cursorstr.h" -# include "dixstruct.h" -# include "inputstr.h" -# include "inpututils.h" - -DevPrivateKeyRec miPointerScreenKeyRec; - -#define GetScreenPrivate(s) ((miPointerScreenPtr) \ - dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) -#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) - -DevPrivateKeyRec miPointerPrivKeyRec; - -#define MIPOINTER(dev) \ - (IsFloating(dev) ? \ - (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ - (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) - -static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor); -static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, - BoxPtr pBox); -static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, - CursorPtr pCursor, BoxPtr pHotBox, - BoxPtr pTopLeftBox); -static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, - Bool generateEvent); -static Bool miPointerCloseScreen(int index, ScreenPtr pScreen); -static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y); -static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); -static void miPointerDeviceCleanup(DeviceIntPtr pDev, - ScreenPtr pScreen); -static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); - -static EventList* events; /* for WarpPointer MotionNotifies */ - -Bool -miPointerInitialize (ScreenPtr pScreen, - miPointerSpriteFuncPtr spriteFuncs, - miPointerScreenFuncPtr screenFuncs, - Bool waitForUpdate) -{ - miPointerScreenPtr pScreenPriv; - - if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) - return FALSE; - - if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) - return FALSE; - - pScreenPriv = malloc(sizeof (miPointerScreenRec)); - if (!pScreenPriv) - return FALSE; - pScreenPriv->spriteFuncs = spriteFuncs; - pScreenPriv->screenFuncs = screenFuncs; - /* - * check for uninitialized methods - */ - if (!screenFuncs->EnqueueEvent) - screenFuncs->EnqueueEvent = mieqEnqueue; - if (!screenFuncs->NewEventScreen) - screenFuncs->NewEventScreen = mieqSwitchScreen; - pScreenPriv->waitForUpdate = waitForUpdate; - pScreenPriv->showTransparent = FALSE; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = miPointerCloseScreen; - dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); - /* - * set up screen cursor method table - */ - pScreen->ConstrainCursor = miPointerConstrainCursor; - pScreen->CursorLimits = miPointerCursorLimits; - pScreen->DisplayCursor = miPointerDisplayCursor; - pScreen->RealizeCursor = miPointerRealizeCursor; - pScreen->UnrealizeCursor = miPointerUnrealizeCursor; - pScreen->SetCursorPosition = miPointerSetCursorPosition; - pScreen->RecolorCursor = miRecolorCursor; - pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; - pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; - - events = NULL; - return TRUE; -} - -/** - * Destroy screen-specific information. - * - * @param index Screen index of the screen in screenInfo.screens[] - * @param pScreen The actual screen pointer - */ -static Bool -miPointerCloseScreen (int index, ScreenPtr pScreen) -{ - SetupScreen(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - free((pointer) pScreenPriv); - FreeEventList(events, GetMaximumEventsNum()); - events = NULL; - return (*pScreen->CloseScreen) (index, pScreen); -} - -/* - * DIX/DDX interface routines - */ - -static Bool -miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - SetupScreen(pScreen); - return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); -} - -static Bool -miPointerUnrealizeCursor (DeviceIntPtr pDev, - ScreenPtr pScreen, - CursorPtr pCursor) -{ - SetupScreen(pScreen); - return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); -} - -static Bool -miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) -{ - miPointerPtr pPointer; - - /* return for keyboards */ - if (!IsPointerDevice(pDev)) - return FALSE; - - pPointer = MIPOINTER(pDev); - - pPointer->pCursor = pCursor; - pPointer->pScreen = pScreen; - miPointerUpdateSprite(pDev); - return TRUE; -} - -/** - * Set up the constraints for the given device. This function does not - * actually constrain the cursor but merely copies the given box to the - * internal constraint storage. - * - * @param pDev The device to constrain to the box - * @param pBox The rectangle to constrain the cursor to - * @param pScreen Used for copying screen confinement - */ -static void -miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) -{ - miPointerPtr pPointer; - - pPointer = MIPOINTER(pDev); - - pPointer->limits = *pBox; - pPointer->confined = PointerConfinedToScreen(pDev); -} - -/** - * Should calculate the box for the given cursor, based on screen and the - * confinement given. But we assume that whatever box is passed in is valid - * anyway. - * - * @param pDev The device to calculate the cursor limits for - * @param pScreen The screen the confinement happens on - * @param pCursor The screen the confinement happens on - * @param pHotBox The confinement box for the cursor - * @param[out] pTopLeftBox The new confinement box, always *pHotBox. - */ -static void -miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, - BoxPtr pHotBox, BoxPtr pTopLeftBox) -{ - *pTopLeftBox = *pHotBox; -} - -/** - * Set the device's cursor position to the x/y position on the given screen. - * Generates and event if required. - * - * This function is called from: - * - sprite init code to place onto initial position - * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…) - * - during the cursor update path in CheckMotion - * - in the Xinerama part of NewCurrentScreen - * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so - * it's set back to the original pos) - * - * @param pDev The device to move - * @param pScreen The screen the device is on - * @param x The x coordinate in per-screen coordinates - * @param y The y coordinate in per-screen coordinates - * @param generateEvent True if the pointer movement should generate an - * event. - * - * @return TRUE in all cases - */ -static Bool -miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y, Bool generateEvent) -{ - SetupScreen (pScreen); - miPointerPtr pPointer = MIPOINTER(pDev); - - pPointer->generateEvent = generateEvent; - - if (pScreen->ConstrainCursorHarder) - pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y); - - /* device dependent - must pend signal and call miPointerWarpCursor */ - (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); - if (!generateEvent) - miPointerUpdateSprite(pDev); - return TRUE; -} - -/** - * Set up sprite information for the device. - * This function will be called once for each device after it is initialized - * in the DIX. - * - * @param pDev The newly created device - * @param pScreen The initial sprite scree. - */ -static Bool -miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - miPointerPtr pPointer; - SetupScreen (pScreen); - - pPointer = malloc(sizeof(miPointerRec)); - if (!pPointer) - return FALSE; - - pPointer->pScreen = NULL; - pPointer->pSpriteScreen = NULL; - pPointer->pCursor = NULL; - pPointer->pSpriteCursor = NULL; - pPointer->limits.x1 = 0; - pPointer->limits.x2 = 32767; - pPointer->limits.y1 = 0; - pPointer->limits.y2 = 32767; - pPointer->confined = FALSE; - pPointer->x = 0; - pPointer->y = 0; - pPointer->generateEvent = FALSE; - - if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) - { - free(pPointer); - return FALSE; - } - - dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); - return TRUE; -} - -/** - * Clean up after device. - * This function will be called once before the device is freed in the DIX - * - * @param pDev The device to be removed from the server - * @param pScreen Current screen of the device - */ -static void -miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) -{ - SetupScreen(pScreen); - - if (!IsMaster(pDev) && !IsFloating(pDev)) - return; - - (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); - free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); - dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); -} - - -/** - * Warp the pointer to the given position on the given screen. May generate - * an event, depending on whether we're coming from miPointerSetPosition. - * - * Once signals are ignored, the WarpCursor function can call this - * - * @param pDev The device to warp - * @param pScreen Screen to warp on - * @param x The x coordinate in per-screen coordinates - * @param y The y coordinate in per-screen coordinates - */ - -void -miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - miPointerPtr pPointer; - BOOL changedScreen = FALSE; - - SetupScreen (pScreen); - pPointer = MIPOINTER(pDev); - - if (pPointer->pScreen != pScreen) - { - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); - changedScreen = TRUE; - } - - if (pPointer->generateEvent) - miPointerMove (pDev, pScreen, x, y); - else - miPointerMoveNoEvent(pDev, pScreen, x, y); - - /* Don't call USFS if we use Xinerama, otherwise the root window is - * updated to the second screen, and we never receive any events. - * (FDO bug #18668) */ - if (changedScreen -#ifdef PANORAMIX - && noPanoramiXExtension -#endif - ) - UpdateSpriteForScreen (pDev, pScreen) ; -} - -/** - * Syncronize the sprite with the cursor. - * - * @param pDev The device to sync - */ -void -miPointerUpdateSprite (DeviceIntPtr pDev) -{ - ScreenPtr pScreen; - miPointerScreenPtr pScreenPriv; - CursorPtr pCursor; - int x, y, devx, devy; - miPointerPtr pPointer; - - if (!pDev || !pDev->coreEvents) - return; - - pPointer = MIPOINTER(pDev); - - if (!pPointer) - return; - - pScreen = pPointer->pScreen; - if (!pScreen) - return; - - x = pPointer->x; - y = pPointer->y; - devx = pPointer->devx; - devy = pPointer->devy; - - pScreenPriv = GetScreenPrivate (pScreen); - /* - * if the cursor has switched screens, disable the sprite - * on the old screen - */ - if (pScreen != pPointer->pSpriteScreen) - { - if (pPointer->pSpriteScreen) - { - miPointerScreenPtr pOldPriv; - - pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); - if (pPointer->pCursor) - { - (*pOldPriv->spriteFuncs->SetCursor) - (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); - } - (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); - } - (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); - (*pScreenPriv->spriteFuncs->SetCursor) - (pDev, pScreen, pPointer->pCursor, x, y); - pPointer->devx = x; - pPointer->devy = y; - pPointer->pSpriteCursor = pPointer->pCursor; - pPointer->pSpriteScreen = pScreen; - } - /* - * if the cursor has changed, display the new one - */ - else if (pPointer->pCursor != pPointer->pSpriteCursor) - { - pCursor = pPointer->pCursor; - if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) - pCursor = NullCursor; - (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); - - pPointer->devx = x; - pPointer->devy = y; - pPointer->pSpriteCursor = pPointer->pCursor; - } - else if (x != devx || y != devy) - { - pPointer->devx = x; - pPointer->devy = y; - if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); - } -} - -/** - * Set the device to the coordinates on the given screen. - * - * @param pDev The device to move - * @param screen_no Index of the screen to move to - * @param x The x coordinate in per-screen coordinates - * @param y The y coordinate in per-screen coordinates - */ -void -miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) -{ - miPointerScreenPtr pScreenPriv; - ScreenPtr pScreen; - miPointerPtr pPointer; - - pPointer = MIPOINTER(pDev); - - pScreen = screenInfo.screens[screen_no]; - pScreenPriv = GetScreenPrivate (pScreen); - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); - NewCurrentScreen (pDev, pScreen, x, y); - - pPointer->limits.x2 = pScreen->width; - pPointer->limits.y2 = pScreen->height; -} - -/** - * @return The current screen of the VCP - */ -ScreenPtr -miPointerCurrentScreen (void) -{ - return miPointerGetScreen(inputInfo.pointer); -} - -/** - * @return The current screen of the given device or NULL. - */ -ScreenPtr -miPointerGetScreen(DeviceIntPtr pDev) -{ - miPointerPtr pPointer = MIPOINTER(pDev); - return (pPointer) ? pPointer->pScreen : NULL; -} - -/* Controls whether the cursor image should be updated immediately when - moved (FALSE) or if something else will be responsible for updating - it later (TRUE). Returns current setting. - Caller is responsible for calling OsBlockSignal first. -*/ -Bool -miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) -{ - SetupScreen(pScreen); - Bool prevWait = pScreenPriv->waitForUpdate; - - pScreenPriv->waitForUpdate = wait; - return prevWait; -} - - -/* Move the pointer on the current screen, and update the sprite. */ -static void -miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, - int x, int y) -{ - miPointerPtr pPointer; - SetupScreen(pScreen); - - pPointer = MIPOINTER(pDev); - - /* Hack: We mustn't call into ->MoveCursor for anything but the - * VCP, as this may cause a non-HW rendered cursor to be rendered during - * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT. - */ - if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer - && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) - { - pPointer->devx = x; - pPointer->devy = y; - if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); - } - - pPointer->x = x; - pPointer->y = y; - pPointer->pScreen = pScreen; -} - -/** - * Set the devices' cursor position to the given x/y position. - * - * This function is called during the pointer update path in - * GetPointerEvents and friends (and the same in the xwin DDX). - * - * The coordinates provided are always absolute. The parameter mode whether - * it was relative or absolute movement that landed us at those coordinates. - * - * @param pDev The device to move - * @param mode Movement mode (Absolute or Relative) - * @param[in,out] x The x coordiante in screen coordinates (in regards to total - * desktop size) - * @param[in,out] y The y coordiante in screen coordinates (in regards to total - * desktop size) - */ -void -miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y) -{ - miPointerScreenPtr pScreenPriv; - ScreenPtr pScreen; - ScreenPtr newScreen; - - miPointerPtr pPointer; - - if (!pDev || !pDev->coreEvents) - return; - - pPointer = MIPOINTER(pDev); - pScreen = pPointer->pScreen; - if (!pScreen) - return; /* called before ready */ - - if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) - { - pScreenPriv = GetScreenPrivate (pScreen); - if (!pPointer->confined) - { - newScreen = pScreen; - (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); - if (newScreen != pScreen) - { - pScreen = newScreen; - (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, - FALSE); - pScreenPriv = GetScreenPrivate (pScreen); - /* Smash the confine to the new screen */ - pPointer->limits.x2 = pScreen->width; - pPointer->limits.y2 = pScreen->height; - } - } - } - /* Constrain the sprite to the current limits. */ - if (*x < pPointer->limits.x1) - *x = pPointer->limits.x1; - if (*x >= pPointer->limits.x2) - *x = pPointer->limits.x2 - 1; - if (*y < pPointer->limits.y1) - *y = pPointer->limits.y1; - if (*y >= pPointer->limits.y2) - *y = pPointer->limits.y2 - 1; - - if (pScreen->ConstrainCursorHarder) - pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y); - - if (pPointer->x == *x && pPointer->y == *y && - pPointer->pScreen == pScreen) - return; - - miPointerMoveNoEvent(pDev, pScreen, *x, *y); -} - -/** - * Get the current position of the device in desktop coordinates. - * - * @param x Return value for the current x coordinate in desktop coordiates. - * @param y Return value for the current y coordinate in desktop coordiates. - */ -void -miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) -{ - *x = MIPOINTER(pDev)->x; - *y = MIPOINTER(pDev)->y; -} - -#ifdef XQUARTZ -#include -void darwinEvents_lock(void); -void darwinEvents_unlock(void); -#endif - -/** - * Move the device's pointer to the x/y coordinates on the given screen. - * This function generates and enqueues pointer events. - * - * @param pDev The device to move - * @param pScreen The screen the device is on - * @param x The x coordinate in per-screen coordinates - * @param y The y coordinate in per-screen coordinates - */ -void -miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) -{ - int i, nevents; - int valuators[2]; - ValuatorMask mask; - - miPointerMoveNoEvent(pDev, pScreen, x, y); - - /* generate motion notify */ - valuators[0] = x; - valuators[1] = y; - - if (!events) - { - events = InitEventList(GetMaximumEventsNum()); - - if (!events) - { - FatalError("Could not allocate event store.\n"); - return; - } - } - - valuator_mask_set_range(&mask, 0, 2, valuators); - nevents = GetPointerEvents(events, pDev, MotionNotify, 0, - POINTER_SCREEN | POINTER_ABSOLUTE, &mask); - - OsBlockSignals(); -#ifdef XQUARTZ - darwinEvents_lock(); -#endif - for (i = 0; i < nevents; i++) - mieqEnqueue(pDev, (InternalEvent*)events[i].event); -#ifdef XQUARTZ - darwinEvents_unlock(); -#endif - OsReleaseSignals(); -} +/* + +Copyright 1989, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. +*/ + +/** + * @file + * This file contains functions to move the pointer on the screen and/or + * restrict its movement. These functions are divided into two sets: + * Screen-specific functions that are used as function pointers from other + * parts of the server (and end up heavily wrapped by e.g. animcur and + * xfixes): + * miPointerConstrainCursor + * miPointerCursorLimits + * miPointerDisplayCursor + * miPointerRealizeCursor + * miPointerUnrealizeCursor + * miPointerSetCursorPosition + * miRecolorCursor + * miPointerDeviceInitialize + * miPointerDeviceCleanup + * If wrapped, these are the last element in the wrapping chain. They may + * call into sprite-specific code through further function pointers though. + * + * The second type of functions are those that are directly called by the + * DIX, DDX and some drivers. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +# include +# include +# include +# include "misc.h" +# include "windowstr.h" +# include "pixmapstr.h" +# include "mi.h" +# include "scrnintstr.h" +# include "mipointrst.h" +# include "cursorstr.h" +# include "dixstruct.h" +# include "inputstr.h" +# include "inpututils.h" + +DevPrivateKeyRec miPointerScreenKeyRec; + +#define GetScreenPrivate(s) ((miPointerScreenPtr) \ + dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) +#define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) + +DevPrivateKeyRec miPointerPrivKeyRec; + +#define MIPOINTER(dev) \ + (IsFloating(dev) ? \ + (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ + (miPointerPtr)dixLookupPrivate(&(GetMaster(dev, MASTER_POINTER))->devPrivates, miPointerPrivKey)) + +static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + BoxPtr pBox); +static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, BoxPtr pHotBox, + BoxPtr pTopLeftBox); +static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, + Bool generateEvent); +static Bool miPointerCloseScreen(int index, ScreenPtr pScreen); +static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); +static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); +static void miPointerDeviceCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); + +static EventList* events; /* for WarpPointer MotionNotifies */ + +Bool +miPointerInitialize (ScreenPtr pScreen, + miPointerSpriteFuncPtr spriteFuncs, + miPointerScreenFuncPtr screenFuncs, + Bool waitForUpdate) +{ + miPointerScreenPtr pScreenPriv; + + if (!dixRegisterPrivateKey(&miPointerScreenKeyRec, PRIVATE_SCREEN, 0)) + return FALSE; + + if (!dixRegisterPrivateKey(&miPointerPrivKeyRec, PRIVATE_DEVICE, 0)) + return FALSE; + + pScreenPriv = malloc(sizeof (miPointerScreenRec)); + if (!pScreenPriv) + return FALSE; + pScreenPriv->spriteFuncs = spriteFuncs; + pScreenPriv->screenFuncs = screenFuncs; + /* + * check for uninitialized methods + */ + if (!screenFuncs->EnqueueEvent) + screenFuncs->EnqueueEvent = mieqEnqueue; + if (!screenFuncs->NewEventScreen) + screenFuncs->NewEventScreen = mieqSwitchScreen; + pScreenPriv->waitForUpdate = waitForUpdate; + pScreenPriv->showTransparent = FALSE; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = miPointerCloseScreen; + dixSetPrivate(&pScreen->devPrivates, miPointerScreenKey, pScreenPriv); + /* + * set up screen cursor method table + */ + pScreen->ConstrainCursor = miPointerConstrainCursor; + pScreen->CursorLimits = miPointerCursorLimits; + pScreen->DisplayCursor = miPointerDisplayCursor; + pScreen->RealizeCursor = miPointerRealizeCursor; + pScreen->UnrealizeCursor = miPointerUnrealizeCursor; + pScreen->SetCursorPosition = miPointerSetCursorPosition; + pScreen->RecolorCursor = miRecolorCursor; + pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; + pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; + + events = NULL; + return TRUE; +} + +/** + * Destroy screen-specific information. + * + * @param index Screen index of the screen in screenInfo.screens[] + * @param pScreen The actual screen pointer + */ +static Bool +miPointerCloseScreen (int index, ScreenPtr pScreen) +{ + SetupScreen(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + free((pointer) pScreenPriv); + FreeEventList(events, GetMaximumEventsNum()); + events = NULL; + return (*pScreen->CloseScreen) (index, pScreen); +} + +/* + * DIX/DDX interface routines + */ + +static Bool +miPointerRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + SetupScreen(pScreen); + return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); +} + +static Bool +miPointerUnrealizeCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + SetupScreen(pScreen); + return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); +} + +static Bool +miPointerDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) +{ + miPointerPtr pPointer; + + /* return for keyboards */ + if (!IsPointerDevice(pDev)) + return FALSE; + + pPointer = MIPOINTER(pDev); + + pPointer->pCursor = pCursor; + pPointer->pScreen = pScreen; + miPointerUpdateSprite(pDev); + return TRUE; +} + +/** + * Set up the constraints for the given device. This function does not + * actually constrain the cursor but merely copies the given box to the + * internal constraint storage. + * + * @param pDev The device to constrain to the box + * @param pBox The rectangle to constrain the cursor to + * @param pScreen Used for copying screen confinement + */ +static void +miPointerConstrainCursor (DeviceIntPtr pDev, ScreenPtr pScreen, BoxPtr pBox) +{ + miPointerPtr pPointer; + + pPointer = MIPOINTER(pDev); + + pPointer->limits = *pBox; + pPointer->confined = PointerConfinedToScreen(pDev); +} + +/** + * Should calculate the box for the given cursor, based on screen and the + * confinement given. But we assume that whatever box is passed in is valid + * anyway. + * + * @param pDev The device to calculate the cursor limits for + * @param pScreen The screen the confinement happens on + * @param pCursor The screen the confinement happens on + * @param pHotBox The confinement box for the cursor + * @param[out] pTopLeftBox The new confinement box, always *pHotBox. + */ +static void +miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, + BoxPtr pHotBox, BoxPtr pTopLeftBox) +{ + *pTopLeftBox = *pHotBox; +} + +/** + * Set the device's cursor position to the x/y position on the given screen. + * Generates and event if required. + * + * This function is called from: + * - sprite init code to place onto initial position + * - the various WarpPointer implementations (core, XI, Xinerama, dmx,…) + * - during the cursor update path in CheckMotion + * - in the Xinerama part of NewCurrentScreen + * - when a RandR/RandR1.2 mode was applied (it may have moved the pointer, so + * it's set back to the original pos) + * + * @param pDev The device to move + * @param pScreen The screen the device is on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + * @param generateEvent True if the pointer movement should generate an + * event. + * + * @return TRUE in all cases + */ +static Bool +miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, Bool generateEvent) +{ + SetupScreen (pScreen); + miPointerPtr pPointer = MIPOINTER(pDev); + + pPointer->generateEvent = generateEvent; + + if (pScreen->ConstrainCursorHarder) + pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y); + + /* device dependent - must pend signal and call miPointerWarpCursor */ + (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); + if (!generateEvent) + miPointerUpdateSprite(pDev); + return TRUE; +} + +/** + * Set up sprite information for the device. + * This function will be called once for each device after it is initialized + * in the DIX. + * + * @param pDev The newly created device + * @param pScreen The initial sprite scree. + */ +static Bool +miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + miPointerPtr pPointer; + SetupScreen (pScreen); + + pPointer = malloc(sizeof(miPointerRec)); + if (!pPointer) + return FALSE; + + pPointer->pScreen = NULL; + pPointer->pSpriteScreen = NULL; + pPointer->pCursor = NULL; + pPointer->pSpriteCursor = NULL; + pPointer->limits.x1 = 0; + pPointer->limits.x2 = 32767; + pPointer->limits.y1 = 0; + pPointer->limits.y2 = 32767; + pPointer->confined = FALSE; + pPointer->x = 0; + pPointer->y = 0; + pPointer->generateEvent = FALSE; + + if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) + { + free(pPointer); + return FALSE; + } + + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); + return TRUE; +} + +/** + * Clean up after device. + * This function will be called once before the device is freed in the DIX + * + * @param pDev The device to be removed from the server + * @param pScreen Current screen of the device + */ +static void +miPointerDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + SetupScreen(pScreen); + + if (!IsMaster(pDev) && !IsFloating(pDev)) + return; + + (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); + free(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); +} + + +/** + * Warp the pointer to the given position on the given screen. May generate + * an event, depending on whether we're coming from miPointerSetPosition. + * + * Once signals are ignored, the WarpCursor function can call this + * + * @param pDev The device to warp + * @param pScreen Screen to warp on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ + +void +miPointerWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + miPointerPtr pPointer; + BOOL changedScreen = FALSE; + + SetupScreen (pScreen); + pPointer = MIPOINTER(pDev); + + if (pPointer->pScreen != pScreen) + { + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); + changedScreen = TRUE; + } + + if (pPointer->generateEvent) + miPointerMove (pDev, pScreen, x, y); + else + miPointerMoveNoEvent(pDev, pScreen, x, y); + + /* Don't call USFS if we use Xinerama, otherwise the root window is + * updated to the second screen, and we never receive any events. + * (FDO bug #18668) */ + if (changedScreen +#ifdef PANORAMIX + && noPanoramiXExtension +#endif + ) + UpdateSpriteForScreen (pDev, pScreen) ; +} + +/** + * Syncronize the sprite with the cursor. + * + * @param pDev The device to sync + */ +void +miPointerUpdateSprite (DeviceIntPtr pDev) +{ + ScreenPtr pScreen; + miPointerScreenPtr pScreenPriv; + CursorPtr pCursor; + int x, y, devx, devy; + miPointerPtr pPointer; + + if (!pDev || !pDev->coreEvents) + return; + + pPointer = MIPOINTER(pDev); + + if (!pPointer) + return; + + pScreen = pPointer->pScreen; + if (!pScreen) + return; + + x = pPointer->x; + y = pPointer->y; + devx = pPointer->devx; + devy = pPointer->devy; + + pScreenPriv = GetScreenPrivate (pScreen); + /* + * if the cursor has switched screens, disable the sprite + * on the old screen + */ + if (pScreen != pPointer->pSpriteScreen) + { + if (pPointer->pSpriteScreen) + { + miPointerScreenPtr pOldPriv; + + pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); + if (pPointer->pCursor) + { + (*pOldPriv->spriteFuncs->SetCursor) + (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); + } + (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); + } + (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); + (*pScreenPriv->spriteFuncs->SetCursor) + (pDev, pScreen, pPointer->pCursor, x, y); + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + pPointer->pSpriteScreen = pScreen; + } + /* + * if the cursor has changed, display the new one + */ + else if (pPointer->pCursor != pPointer->pSpriteCursor) + { + pCursor = pPointer->pCursor; + if (!pCursor || (pCursor->bits->emptyMask && !pScreenPriv->showTransparent)) + pCursor = NullCursor; + (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); + + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + } + else if (x != devx || y != devy) + { + pPointer->devx = x; + pPointer->devy = y; + if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); + } +} + +/** + * Set the device to the coordinates on the given screen. + * + * @param pDev The device to move + * @param screen_no Index of the screen to move to + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ +void +miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + miPointerPtr pPointer; + + pPointer = MIPOINTER(pDev); + + pScreen = screenInfo.screens[screen_no]; + pScreenPriv = GetScreenPrivate (pScreen); + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); + NewCurrentScreen (pDev, pScreen, x, y); + + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; +} + +/** + * @return The current screen of the VCP + */ +ScreenPtr +miPointerCurrentScreen (void) +{ + return miPointerGetScreen(inputInfo.pointer); +} + +/** + * @return The current screen of the given device or NULL. + */ +ScreenPtr +miPointerGetScreen(DeviceIntPtr pDev) +{ + miPointerPtr pPointer = MIPOINTER(pDev); + return (pPointer) ? pPointer->pScreen : NULL; +} + +/* Controls whether the cursor image should be updated immediately when + moved (FALSE) or if something else will be responsible for updating + it later (TRUE). Returns current setting. + Caller is responsible for calling OsBlockSignal first. +*/ +Bool +miPointerSetWaitForUpdate(ScreenPtr pScreen, Bool wait) +{ + SetupScreen(pScreen); + Bool prevWait = pScreenPriv->waitForUpdate; + + pScreenPriv->waitForUpdate = wait; + return prevWait; +} + + +/* Move the pointer on the current screen, and update the sprite. */ +static void +miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y) +{ + miPointerPtr pPointer; + SetupScreen(pScreen); + + pPointer = MIPOINTER(pDev); + + /* Hack: We mustn't call into ->MoveCursor for anything but the + * VCP, as this may cause a non-HW rendered cursor to be rendered during + * SIGIO. This again leads to allocs during SIGIO which leads to SIGABRT. + */ + if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer + && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) + { + pPointer->devx = x; + pPointer->devy = y; + if(pPointer->pCursor && !pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); + } + + pPointer->x = x; + pPointer->y = y; + pPointer->pScreen = pScreen; +} + +/** + * Set the devices' cursor position to the given x/y position. + * + * This function is called during the pointer update path in + * GetPointerEvents and friends (and the same in the xwin DDX). + * + * The coordinates provided are always absolute. The parameter mode whether + * it was relative or absolute movement that landed us at those coordinates. + * + * @param pDev The device to move + * @param mode Movement mode (Absolute or Relative) + * @param[in,out] x The x coordiante in screen coordinates (in regards to total + * desktop size) + * @param[in,out] y The y coordiante in screen coordinates (in regards to total + * desktop size) + */ +void +miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y) +{ + miPointerScreenPtr pScreenPriv; + ScreenPtr pScreen; + ScreenPtr newScreen; + + miPointerPtr pPointer; + + if (!pDev || !pDev->coreEvents) + return; + + pPointer = MIPOINTER(pDev); + pScreen = pPointer->pScreen; + if (!pScreen) + return; /* called before ready */ + + if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) + { + pScreenPriv = GetScreenPrivate (pScreen); + if (!pPointer->confined) + { + newScreen = pScreen; + (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); + if (newScreen != pScreen) + { + pScreen = newScreen; + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, + FALSE); + /* Smash the confine to the new screen */ + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; + } + } + } + /* Constrain the sprite to the current limits. */ + if (*x < pPointer->limits.x1) + *x = pPointer->limits.x1; + if (*x >= pPointer->limits.x2) + *x = pPointer->limits.x2 - 1; + if (*y < pPointer->limits.y1) + *y = pPointer->limits.y1; + if (*y >= pPointer->limits.y2) + *y = pPointer->limits.y2 - 1; + + if (pScreen->ConstrainCursorHarder) + pScreen->ConstrainCursorHarder(pDev, pScreen, mode, x, y); + + if (pPointer->x == *x && pPointer->y == *y && + pPointer->pScreen == pScreen) + return; + + miPointerMoveNoEvent(pDev, pScreen, *x, *y); +} + +/** + * Get the current position of the device in desktop coordinates. + * + * @param x Return value for the current x coordinate in desktop coordiates. + * @param y Return value for the current y coordinate in desktop coordiates. + */ +void +miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) +{ + *x = MIPOINTER(pDev)->x; + *y = MIPOINTER(pDev)->y; +} + +#ifdef XQUARTZ +#include +void darwinEvents_lock(void); +void darwinEvents_unlock(void); +#endif + +/** + * Move the device's pointer to the x/y coordinates on the given screen. + * This function generates and enqueues pointer events. + * + * @param pDev The device to move + * @param pScreen The screen the device is on + * @param x The x coordinate in per-screen coordinates + * @param y The y coordinate in per-screen coordinates + */ +void +miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + int i, nevents; + int valuators[2]; + ValuatorMask mask; + + miPointerMoveNoEvent(pDev, pScreen, x, y); + + /* generate motion notify */ + valuators[0] = x; + valuators[1] = y; + + if (!events) + { + events = InitEventList(GetMaximumEventsNum()); + + if (!events) + { + FatalError("Could not allocate event store.\n"); + return; + } + } + + valuator_mask_set_range(&mask, 0, 2, valuators); + nevents = GetPointerEvents(events, pDev, MotionNotify, 0, + POINTER_SCREEN | POINTER_ABSOLUTE, &mask); + + OsBlockSignals(); +#ifdef XQUARTZ + darwinEvents_lock(); +#endif + for (i = 0; i < nevents; i++) + mieqEnqueue(pDev, (InternalEvent*)events[i].event); +#ifdef XQUARTZ + darwinEvents_unlock(); +#endif + OsReleaseSignals(); +} diff --git a/xorg-server/mi/mispans.c b/xorg-server/mi/mispans.c index 4202c9bb9..21ba4da4f 100644 --- a/xorg-server/mi/mispans.c +++ b/xorg-server/mi/mispans.c @@ -1,525 +1,527 @@ -/*********************************************************** - -Copyright 1989, 1998 The Open Group - -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. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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. - -******************************************************************/ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "misc.h" -#include "pixmapstr.h" -#include "gcstruct.h" -#include "mispans.h" - -/* - -These routines maintain lists of Spans, in order to implement the -``touch-each-pixel-once'' rules of wide lines and arcs. - -Written by Joel McCormack, Summer 1989. - -*/ - - -void miInitSpanGroup(SpanGroup *spanGroup) -{ - spanGroup->size = 0; - spanGroup->count = 0; - spanGroup->group = NULL; - spanGroup->ymin = MAXSHORT; - spanGroup->ymax = MINSHORT; -} /* InitSpanGroup */ - -#define YMIN(spans) (spans->points[0].y) -#define YMAX(spans) (spans->points[spans->count-1].y) - -static void miSubtractSpans (SpanGroup *spanGroup, Spans *sub) -{ - int i, subCount, spansCount; - int ymin, ymax, xmin, xmax; - Spans *spans; - DDXPointPtr subPt, spansPt; - int *subWid, *spansWid; - int extra; - - ymin = YMIN(sub); - ymax = YMAX(sub); - spans = spanGroup->group; - for (i = spanGroup->count; i; i--, spans++) { - if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) { - subCount = sub->count; - subPt = sub->points; - subWid = sub->widths; - spansCount = spans->count; - spansPt = spans->points; - spansWid = spans->widths; - extra = 0; - for (;;) - { - while (spansCount && spansPt->y < subPt->y) - { - spansPt++; spansWid++; spansCount--; - } - if (!spansCount) - break; - while (subCount && subPt->y < spansPt->y) - { - subPt++; subWid++; subCount--; - } - if (!subCount) - break; - if (subPt->y == spansPt->y) - { - xmin = subPt->x; - xmax = xmin + *subWid; - if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax) - { - ; - } - else if (xmin <= spansPt->x) - { - if (xmax >= spansPt->x + *spansWid) - { - memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1)); - memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1)); - spansPt--; - spansWid--; - spans->count--; - extra++; - } - else - { - *spansWid = *spansWid - (xmax - spansPt->x); - spansPt->x = xmax; - } - } - else - { - if (xmax >= spansPt->x + *spansWid) - { - *spansWid = xmin - spansPt->x; - } - else - { - if (!extra) { - DDXPointPtr newPt; - int *newwid; - -#define EXTRA 8 - newPt = (DDXPointPtr) realloc(spans->points, (spans->count + EXTRA) * sizeof (DDXPointRec)); - if (!newPt) - break; - spansPt = newPt + (spansPt - spans->points); - spans->points = newPt; - newwid = (int *) realloc(spans->widths, (spans->count + EXTRA) * sizeof (int)); - if (!newwid) - break; - spansWid = newwid + (spansWid - spans->widths); - spans->widths = newwid; - extra = EXTRA; - } - memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount)); - memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount)); - spans->count++; - extra--; - *spansWid = xmin - spansPt->x; - spansWid++; - spansPt++; - *spansWid = *spansWid - (xmax - spansPt->x); - spansPt->x = xmax; - } - } - } - spansPt++; spansWid++; spansCount--; - } - } - } -} - -void miAppendSpans(SpanGroup *spanGroup, SpanGroup *otherGroup, Spans *spans) -{ - int ymin, ymax; - int spansCount; - - spansCount = spans->count; - if (spansCount > 0) { - if (spanGroup->size == spanGroup->count) { - spanGroup->size = (spanGroup->size + 8) * 2; - spanGroup->group = (Spans *) - realloc(spanGroup->group, sizeof(Spans) * spanGroup->size); - } - - spanGroup->group[spanGroup->count] = *spans; - (spanGroup->count)++; - ymin = spans->points[0].y; - if (ymin < spanGroup->ymin) spanGroup->ymin = ymin; - ymax = spans->points[spansCount - 1].y; - if (ymax > spanGroup->ymax) spanGroup->ymax = ymax; - if (otherGroup && - otherGroup->ymin < ymax && - ymin < otherGroup->ymax) - { - miSubtractSpans (otherGroup, spans); - } - } - else - { - free(spans->points); - free(spans->widths); - } -} /* AppendSpans */ - -void miFreeSpanGroup(SpanGroup *spanGroup) -{ - free(spanGroup->group); -} - -static void QuickSortSpansX( - DDXPointRec points[], - int widths[], - int numSpans ) -{ - int x; - int i, j, m; - DDXPointPtr r; - -/* Always called with numSpans > 1 */ -/* Sorts only by x, as all y should be the same */ - -#define ExchangeSpans(a, b) \ -{ \ - DDXPointRec tpt; \ - int tw; \ - \ - tpt = points[a]; points[a] = points[b]; points[b] = tpt; \ - tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ -} - - do { - if (numSpans < 9) { - /* Do insertion sort */ - int xprev; - - xprev = points[0].x; - i = 1; - do { /* while i != numSpans */ - x = points[i].x; - if (xprev > x) { - /* points[i] is out of order. Move into proper location. */ - DDXPointRec tpt; - int tw, k; - - for (j = 0; x >= points[j].x; j++) {} - tpt = points[i]; - tw = widths[i]; - for (k = i; k != j; k--) { - points[k] = points[k-1]; - widths[k] = widths[k-1]; - } - points[j] = tpt; - widths[j] = tw; - x = points[i].x; - } /* if out of order */ - xprev = x; - i++; - } while (i != numSpans); - return; - } - - /* Choose partition element, stick in location 0 */ - m = numSpans / 2; - if (points[m].x > points[0].x) ExchangeSpans(m, 0); - if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1); - if (points[m].x > points[0].x) ExchangeSpans(m, 0); - x = points[0].x; - - /* Partition array */ - i = 0; - j = numSpans; - do { - r = &(points[i]); - do { - r++; - i++; - } while (i != numSpans && r->x < x); - r = &(points[j]); - do { - r--; - j--; - } while (x < r->x); - if (i < j) ExchangeSpans(i, j); - } while (i < j); - - /* Move partition element back to middle */ - ExchangeSpans(0, j); - - /* Recurse */ - if (numSpans-j-1 > 1) - QuickSortSpansX(&points[j+1], &widths[j+1], numSpans-j-1); - numSpans = j; - } while (numSpans > 1); -} /* QuickSortSpans */ - - -static int UniquifySpansX( - Spans *spans, - DDXPointRec *newPoints, - int *newWidths ) -{ - int newx1, newx2, oldpt, i, y; - DDXPointRec *oldPoints; - int *oldWidths; - int *startNewWidths; - -/* Always called with numSpans > 1 */ -/* Uniquify the spans, and stash them into newPoints and newWidths. Return the - number of unique spans. */ - - - startNewWidths = newWidths; - - oldPoints = spans->points; - oldWidths = spans->widths; - - y = oldPoints->y; - newx1 = oldPoints->x; - newx2 = newx1 + *oldWidths; - - for (i = spans->count-1; i != 0; i--) { - oldPoints++; - oldWidths++; - oldpt = oldPoints->x; - if (oldpt > newx2) { - /* Write current span, start a new one */ - newPoints->x = newx1; - newPoints->y = y; - *newWidths = newx2 - newx1; - newPoints++; - newWidths++; - newx1 = oldpt; - newx2 = oldpt + *oldWidths; - } else { - /* extend current span, if old extends beyond new */ - oldpt = oldpt + *oldWidths; - if (oldpt > newx2) newx2 = oldpt; - } - } /* for */ - - /* Write final span */ - newPoints->x = newx1; - *newWidths = newx2 - newx1; - newPoints->y = y; - - return (newWidths - startNewWidths) + 1; -} /* UniquifySpansX */ - -static void -miDisposeSpanGroup (SpanGroup *spanGroup) -{ - int i; - Spans *spans; - - for (i = 0; i < spanGroup->count; i++) - { - spans = spanGroup->group + i; - free(spans->points); - free(spans->widths); - } -} - -void miFillUniqueSpanGroup(DrawablePtr pDraw, GCPtr pGC, SpanGroup *spanGroup) -{ - int i; - Spans *spans; - Spans *yspans; - int *ysizes; - int ymin, ylength; - - /* Outgoing spans for one big call to FillSpans */ - DDXPointPtr points; - int *widths; - int count; - - if (spanGroup->count == 0) return; - - if (spanGroup->count == 1) { - /* Already should be sorted, unique */ - spans = spanGroup->group; - (*pGC->ops->FillSpans) - (pDraw, pGC, spans->count, spans->points, spans->widths, TRUE); - free(spans->points); - free(spans->widths); - } - else - { - /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */ - /* This seems to be the fastest thing to do. I've tried sorting on - both x and y at the same time rather than creating into all those - y buckets, but it was somewhat slower. */ - - ymin = spanGroup->ymin; - ylength = spanGroup->ymax - ymin + 1; - - /* Allocate Spans for y buckets */ - yspans = malloc(ylength * sizeof(Spans)); - ysizes = malloc(ylength * sizeof (int)); - - if (!yspans || !ysizes) - { - free(yspans); - free(ysizes); - miDisposeSpanGroup (spanGroup); - return; - } - - for (i = 0; i != ylength; i++) { - ysizes[i] = 0; - yspans[i].count = 0; - yspans[i].points = NULL; - yspans[i].widths = NULL; - } - - /* Go through every single span and put it into the correct bucket */ - count = 0; - for (i = 0, spans = spanGroup->group; - i != spanGroup->count; - i++, spans++) { - int index; - int j; - - for (j = 0, points = spans->points, widths = spans->widths; - j != spans->count; - j++, points++, widths++) { - index = points->y - ymin; - if (index >= 0 && index < ylength) { - Spans *newspans = &(yspans[index]); - if (newspans->count == ysizes[index]) { - DDXPointPtr newpoints; - int *newwidths; - ysizes[index] = (ysizes[index] + 8) * 2; - newpoints = (DDXPointPtr) realloc( - newspans->points, - ysizes[index] * sizeof(DDXPointRec)); - newwidths = (int *) realloc( - newspans->widths, - ysizes[index] * sizeof(int)); - if (!newpoints || !newwidths) - { - int i; - - for (i = 0; i < ylength; i++) - { - free(yspans[i].points); - free(yspans[i].widths); - } - free(yspans); - free(ysizes); - miDisposeSpanGroup (spanGroup); - return; - } - newspans->points = newpoints; - newspans->widths = newwidths; - } - newspans->points[newspans->count] = *points; - newspans->widths[newspans->count] = *widths; - (newspans->count)++; - } /* if y value of span in range */ - } /* for j through spans */ - count += spans->count; - free(spans->points); - spans->points = NULL; - free(spans->widths); - spans->widths = NULL; - } /* for i thorough Spans */ - - /* Now sort by x and uniquify each bucket into the final array */ - points = malloc(count * sizeof(DDXPointRec)); - widths = malloc(count * sizeof(int)); - if (!points || !widths) - { - int i; - - for (i = 0; i < ylength; i++) - { - free(yspans[i].points); - free(yspans[i].widths); - } - free(yspans); - free(ysizes); - free(points); - free(widths); - return; - } - count = 0; - for (i = 0; i != ylength; i++) { - int ycount = yspans[i].count; - if (ycount > 0) { - if (ycount > 1) { - QuickSortSpansX(yspans[i].points, yspans[i].widths, ycount); - count += UniquifySpansX - (&(yspans[i]), &(points[count]), &(widths[count])); - } else { - points[count] = yspans[i].points[0]; - widths[count] = yspans[i].widths[0]; - count++; - } - free(yspans[i].points); - free(yspans[i].widths); - } - } - - (*pGC->ops->FillSpans) (pDraw, pGC, count, points, widths, TRUE); - free(points); - free(widths); - free(yspans); - free(ysizes); /* use (DE)xalloc for these? */ - } - - spanGroup->count = 0; - spanGroup->ymin = MAXSHORT; - spanGroup->ymax = MINSHORT; -} +/*********************************************************** + +Copyright 1989, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "misc.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "mispans.h" + +/* + +These routines maintain lists of Spans, in order to implement the +``touch-each-pixel-once'' rules of wide lines and arcs. + +Written by Joel McCormack, Summer 1989. + +*/ + + +void miInitSpanGroup(SpanGroup *spanGroup) +{ + spanGroup->size = 0; + spanGroup->count = 0; + spanGroup->group = NULL; + spanGroup->ymin = MAXSHORT; + spanGroup->ymax = MINSHORT; +} /* InitSpanGroup */ + +#define YMIN(spans) (spans->points[0].y) +#define YMAX(spans) (spans->points[spans->count-1].y) + +static void miSubtractSpans (SpanGroup *spanGroup, Spans *sub) +{ + int i, subCount, spansCount; + int ymin, ymax, xmin, xmax; + Spans *spans; + DDXPointPtr subPt, spansPt; + int *subWid, *spansWid; + int extra; + + ymin = YMIN(sub); + ymax = YMAX(sub); + spans = spanGroup->group; + for (i = spanGroup->count; i; i--, spans++) { + if (YMIN(spans) <= ymax && ymin <= YMAX(spans)) { + subCount = sub->count; + subPt = sub->points; + subWid = sub->widths; + spansCount = spans->count; + spansPt = spans->points; + spansWid = spans->widths; + extra = 0; + for (;;) + { + while (spansCount && spansPt->y < subPt->y) + { + spansPt++; spansWid++; spansCount--; + } + if (!spansCount) + break; + while (subCount && subPt->y < spansPt->y) + { + subPt++; subWid++; subCount--; + } + if (!subCount) + break; + if (subPt->y == spansPt->y) + { + xmin = subPt->x; + xmax = xmin + *subWid; + if (xmin >= spansPt->x + *spansWid || spansPt->x >= xmax) + { + ; + } + else if (xmin <= spansPt->x) + { + if (xmax >= spansPt->x + *spansWid) + { + memmove (spansPt, spansPt + 1, sizeof *spansPt * (spansCount - 1)); + memmove (spansWid, spansWid + 1, sizeof *spansWid * (spansCount - 1)); + spansPt--; + spansWid--; + spans->count--; + extra++; + } + else + { + *spansWid = *spansWid - (xmax - spansPt->x); + spansPt->x = xmax; + } + } + else + { + if (xmax >= spansPt->x + *spansWid) + { + *spansWid = xmin - spansPt->x; + } + else + { + if (!extra) { + DDXPointPtr newPt; + int *newwid; + +#define EXTRA 8 + newPt = (DDXPointPtr) realloc(spans->points, (spans->count + EXTRA) * sizeof (DDXPointRec)); + if (!newPt) + break; + spansPt = newPt + (spansPt - spans->points); + spans->points = newPt; + newwid = (int *) realloc(spans->widths, (spans->count + EXTRA) * sizeof (int)); + if (!newwid) + break; + spansWid = newwid + (spansWid - spans->widths); + spans->widths = newwid; + extra = EXTRA; + } + memmove (spansPt + 1, spansPt, sizeof *spansPt * (spansCount)); + memmove (spansWid + 1, spansWid, sizeof *spansWid * (spansCount)); + spans->count++; + extra--; + *spansWid = xmin - spansPt->x; + spansWid++; + spansPt++; + *spansWid = *spansWid - (xmax - spansPt->x); + spansPt->x = xmax; + } + } + } + spansPt++; spansWid++; spansCount--; + } + } + } +} + +void miAppendSpans(SpanGroup *spanGroup, SpanGroup *otherGroup, Spans *spans) +{ + int ymin, ymax; + int spansCount; + + spansCount = spans->count; + if (spansCount > 0) { + if (spanGroup->size == spanGroup->count) { + spanGroup->size = (spanGroup->size + 8) * 2; + spanGroup->group = (Spans *) + realloc(spanGroup->group, sizeof(Spans) * spanGroup->size); + } + + spanGroup->group[spanGroup->count] = *spans; + (spanGroup->count)++; + ymin = spans->points[0].y; + if (ymin < spanGroup->ymin) spanGroup->ymin = ymin; + ymax = spans->points[spansCount - 1].y; + if (ymax > spanGroup->ymax) spanGroup->ymax = ymax; + if (otherGroup && + otherGroup->ymin < ymax && + ymin < otherGroup->ymax) + { + miSubtractSpans (otherGroup, spans); + } + } + else + { + free(spans->points); + free(spans->widths); + } +} /* AppendSpans */ + +void miFreeSpanGroup(SpanGroup *spanGroup) +{ + free(spanGroup->group); +} + +static void QuickSortSpansX( + DDXPointRec points[], + int widths[], + int numSpans ) +{ + int x; + int i, j, m; + DDXPointPtr r; + +/* Always called with numSpans > 1 */ +/* Sorts only by x, as all y should be the same */ + +#define ExchangeSpans(a, b) \ +{ \ + DDXPointRec tpt; \ + int tw; \ + \ + tpt = points[a]; points[a] = points[b]; points[b] = tpt; \ + tw = widths[a]; widths[a] = widths[b]; widths[b] = tw; \ +} + + do { + if (numSpans < 9) { + /* Do insertion sort */ + int xprev; + + xprev = points[0].x; + i = 1; + do { /* while i != numSpans */ + x = points[i].x; + if (xprev > x) { + /* points[i] is out of order. Move into proper location. */ + DDXPointRec tpt; + int tw, k; + + for (j = 0; x >= points[j].x; j++) {} + tpt = points[i]; + tw = widths[i]; + for (k = i; k != j; k--) { + points[k] = points[k-1]; + widths[k] = widths[k-1]; + } + points[j] = tpt; + widths[j] = tw; + x = points[i].x; + } /* if out of order */ + xprev = x; + i++; + } while (i != numSpans); + return; + } + + /* Choose partition element, stick in location 0 */ + m = numSpans / 2; + if (points[m].x > points[0].x) ExchangeSpans(m, 0); + if (points[m].x > points[numSpans-1].x) ExchangeSpans(m, numSpans-1); + if (points[m].x > points[0].x) ExchangeSpans(m, 0); + x = points[0].x; + + /* Partition array */ + i = 0; + j = numSpans; + do { + r = &(points[i]); + do { + r++; + i++; + } while (i != numSpans && r->x < x); + r = &(points[j]); + do { + r--; + j--; + } while (x < r->x); + if (i < j) ExchangeSpans(i, j); + } while (i < j); + + /* Move partition element back to middle */ + ExchangeSpans(0, j); + + /* Recurse */ + if (numSpans-j-1 > 1) + QuickSortSpansX(&points[j+1], &widths[j+1], numSpans-j-1); + numSpans = j; + } while (numSpans > 1); +} /* QuickSortSpans */ + + +static int UniquifySpansX( + Spans *spans, + DDXPointRec *newPoints, + int *newWidths ) +{ + int newx1, newx2, oldpt, i, y; + DDXPointRec *oldPoints; + int *oldWidths; + int *startNewWidths; + +/* Always called with numSpans > 1 */ +/* Uniquify the spans, and stash them into newPoints and newWidths. Return the + number of unique spans. */ + + + startNewWidths = newWidths; + + oldPoints = spans->points; + oldWidths = spans->widths; + + y = oldPoints->y; + newx1 = oldPoints->x; + newx2 = newx1 + *oldWidths; + + for (i = spans->count-1; i != 0; i--) { + oldPoints++; + oldWidths++; + oldpt = oldPoints->x; + if (oldpt > newx2) { + /* Write current span, start a new one */ + newPoints->x = newx1; + newPoints->y = y; + *newWidths = newx2 - newx1; + newPoints++; + newWidths++; + newx1 = oldpt; + newx2 = oldpt + *oldWidths; + } else { + /* extend current span, if old extends beyond new */ + oldpt = oldpt + *oldWidths; + if (oldpt > newx2) newx2 = oldpt; + } + } /* for */ + + /* Write final span */ + newPoints->x = newx1; + *newWidths = newx2 - newx1; + newPoints->y = y; + + return (newWidths - startNewWidths) + 1; +} /* UniquifySpansX */ + +static void +miDisposeSpanGroup (SpanGroup *spanGroup) +{ + int i; + Spans *spans; + + for (i = 0; i < spanGroup->count; i++) + { + spans = spanGroup->group + i; + free(spans->points); + free(spans->widths); + } +} + +void miFillUniqueSpanGroup(DrawablePtr pDraw, GCPtr pGC, SpanGroup *spanGroup) +{ + int i; + Spans *spans; + Spans *yspans; + int *ysizes; + int ymin, ylength; + + /* Outgoing spans for one big call to FillSpans */ + DDXPointPtr points; + int *widths; + int count; + + if (spanGroup->count == 0) return; + + if (spanGroup->count == 1) { + /* Already should be sorted, unique */ + spans = spanGroup->group; + (*pGC->ops->FillSpans) + (pDraw, pGC, spans->count, spans->points, spans->widths, TRUE); + free(spans->points); + free(spans->widths); + } + else + { + /* Yuck. Gross. Radix sort into y buckets, then sort x and uniquify */ + /* This seems to be the fastest thing to do. I've tried sorting on + both x and y at the same time rather than creating into all those + y buckets, but it was somewhat slower. */ + + ymin = spanGroup->ymin; + ylength = spanGroup->ymax - ymin + 1; + + /* Allocate Spans for y buckets */ + yspans = malloc(ylength * sizeof(Spans)); + ysizes = malloc(ylength * sizeof (int)); + + if (!yspans || !ysizes) + { + free(yspans); + free(ysizes); + miDisposeSpanGroup (spanGroup); + return; + } + + for (i = 0; i != ylength; i++) { + ysizes[i] = 0; + yspans[i].count = 0; + yspans[i].points = NULL; + yspans[i].widths = NULL; + } + + /* Go through every single span and put it into the correct bucket */ + count = 0; + for (i = 0, spans = spanGroup->group; + i != spanGroup->count; + i++, spans++) { + int index; + int j; + + for (j = 0, points = spans->points, widths = spans->widths; + j != spans->count; + j++, points++, widths++) { + index = points->y - ymin; + if (index >= 0 && index < ylength) { + Spans *newspans = &(yspans[index]); + if (newspans->count == ysizes[index]) { + DDXPointPtr newpoints; + int *newwidths; + ysizes[index] = (ysizes[index] + 8) * 2; + newpoints = (DDXPointPtr) realloc( + newspans->points, + ysizes[index] * sizeof(DDXPointRec)); + newwidths = (int *) realloc( + newspans->widths, + ysizes[index] * sizeof(int)); + if (!newpoints || !newwidths) + { + int i; + + for (i = 0; i < ylength; i++) + { + free(yspans[i].points); + free(yspans[i].widths); + } + free(yspans); + free(ysizes); + free(newpoints); + free(newwidths); + miDisposeSpanGroup (spanGroup); + return; + } + newspans->points = newpoints; + newspans->widths = newwidths; + } + newspans->points[newspans->count] = *points; + newspans->widths[newspans->count] = *widths; + (newspans->count)++; + } /* if y value of span in range */ + } /* for j through spans */ + count += spans->count; + free(spans->points); + spans->points = NULL; + free(spans->widths); + spans->widths = NULL; + } /* for i thorough Spans */ + + /* Now sort by x and uniquify each bucket into the final array */ + points = malloc(count * sizeof(DDXPointRec)); + widths = malloc(count * sizeof(int)); + if (!points || !widths) + { + int i; + + for (i = 0; i < ylength; i++) + { + free(yspans[i].points); + free(yspans[i].widths); + } + free(yspans); + free(ysizes); + free(points); + free(widths); + return; + } + count = 0; + for (i = 0; i != ylength; i++) { + int ycount = yspans[i].count; + if (ycount > 0) { + if (ycount > 1) { + QuickSortSpansX(yspans[i].points, yspans[i].widths, ycount); + count += UniquifySpansX + (&(yspans[i]), &(points[count]), &(widths[count])); + } else { + points[count] = yspans[i].points[0]; + widths[count] = yspans[i].widths[0]; + count++; + } + free(yspans[i].points); + free(yspans[i].widths); + } + } + + (*pGC->ops->FillSpans) (pDraw, pGC, count, points, widths, TRUE); + free(points); + free(widths); + free(yspans); + free(ysizes); /* use (DE)xalloc for these? */ + } + + spanGroup->count = 0; + spanGroup->ymin = MAXSHORT; + spanGroup->ymax = MINSHORT; +} diff --git a/xorg-server/mi/mizerline.c b/xorg-server/mi/mizerline.c index d37e1cc96..7077b5198 100644 --- a/xorg-server/mi/mizerline.c +++ b/xorg-server/mi/mizerline.c @@ -1,379 +1,381 @@ -/*********************************************************** - -Copyright 1987, 1998 The Open Group - -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. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -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 Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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. - -******************************************************************/ -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include "misc.h" -#include "scrnintstr.h" -#include "gcstruct.h" -#include "windowstr.h" -#include "pixmap.h" -#include "mi.h" -#include "miline.h" - -/* Draw lineSolid, fillStyle-independent zero width lines. - * - * Must keep X and Y coordinates in "ints" at least until after they're - * translated and clipped to accomodate CoordModePrevious lines with very - * large coordinates. - * - * Draws the same pixels regardless of sign(dx) or sign(dy). - * - * Ken Whaley - * - */ - -/* largest positive value that can fit into a component of a point. - * Assumes that the point structure is {type x, y;} where type is - * a signed type. - */ -#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1) - -#define MI_OUTPUT_POINT(xx, yy)\ -{\ - if ( !new_span && yy == current_y)\ - {\ - if (xx < spans->x)\ - spans->x = xx;\ - ++*widths;\ - }\ - else\ - {\ - ++Nspans;\ - ++spans;\ - ++widths;\ - spans->x = xx;\ - spans->y = yy;\ - *widths = 1;\ - current_y = yy;\ - new_span = FALSE;\ - }\ -} - -void -miZeroLine( - DrawablePtr pDraw, - GCPtr pGC, - int mode, /* Origin or Previous */ - int npt, /* number of points */ - DDXPointPtr pptInit) -{ - int Nspans, current_y = 0; - DDXPointPtr ppt; - DDXPointPtr pspanInit, spans; - int *pwidthInit, *widths, list_len; - int xleft, ytop, xright, ybottom; - int new_x1, new_y1, new_x2, new_y2; - int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart; - int oc1, oc2; - int result; - int pt1_clipped, pt2_clipped = 0; - Bool new_span; - int signdx, signdy; - int clipdx, clipdy; - int width, height; - int adx, ady; - int octant; - unsigned int bias = miGetZeroLineBias(pDraw->pScreen); - int e, e1, e2, e3; /* Bresenham error terms */ - int length; /* length of lines == # of pixels on major axis */ - - xleft = pDraw->x; - ytop = pDraw->y; - xright = pDraw->x + pDraw->width - 1; - ybottom = pDraw->y + pDraw->height - 1; - - if (!pGC->miTranslate) - { - /* do everything in drawable-relative coordinates */ - xleft = 0; - ytop = 0; - xright -= pDraw->x; - ybottom -= pDraw->y; - } - - /* it doesn't matter whether we're in drawable or screen coordinates, - * FillSpans simply cannot take starting coordinates outside of the - * range of a DDXPointRec component. - */ - if (xright > MAX_COORDINATE) - xright = MAX_COORDINATE; - if (ybottom > MAX_COORDINATE) - ybottom = MAX_COORDINATE; - - /* since we're clipping to the drawable's boundaries & coordinate - * space boundaries, we're guaranteed that the larger of width/height - * is the longest span we'll need to output - */ - width = xright - xleft + 1; - height = ybottom - ytop + 1; - list_len = (height >= width) ? height : width; - pspanInit = malloc(list_len * sizeof(DDXPointRec)); - pwidthInit = malloc(list_len * sizeof(int)); - if (!pspanInit || !pwidthInit) - return; - - Nspans = 0; - new_span = TRUE; - spans = pspanInit - 1; - widths = pwidthInit - 1; - ppt = pptInit; - - xstart = ppt->x; - ystart = ppt->y; - if (pGC->miTranslate) - { - xstart += pDraw->x; - ystart += pDraw->y; - } - - /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify - * iteration logic - */ - x2 = xstart; - y2 = ystart; - oc2 = 0; - MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); - - while (--npt > 0) - { - if (Nspans > 0) - (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, - pwidthInit, FALSE); - Nspans = 0; - new_span = TRUE; - spans = pspanInit - 1; - widths = pwidthInit - 1; - - x1 = x2; - y1 = y2; - oc1 = oc2; - ++ppt; - - x2 = ppt->x; - y2 = ppt->y; - if (pGC->miTranslate && (mode != CoordModePrevious)) - { - x2 += pDraw->x; - y2 += pDraw->y; - } - else if (mode == CoordModePrevious) - { - x2 += x1; - y2 += y1; - } - - oc2 = 0; - MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); - - CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); - - if (adx > ady) - { - e1 = ady << 1; - e2 = e1 - (adx << 1); - e = e1 - adx; - length = adx; /* don't draw endpoint in main loop */ - - FIXUP_ERROR(e, octant, bias); - - new_x1 = x1; - new_y1 = y1; - new_x2 = x2; - new_y2 = y2; - pt1_clipped = 0; - pt2_clipped = 0; - - if ((oc1 | oc2) != 0) - { - result = miZeroClipLine(xleft, ytop, xright, ybottom, - &new_x1, &new_y1, &new_x2, &new_y2, - adx, ady, - &pt1_clipped, &pt2_clipped, - octant, bias, oc1, oc2); - if (result == -1) - continue; - - length = abs(new_x2 - new_x1); - - /* if we've clipped the endpoint, always draw the full length - * of the segment, because then the capstyle doesn't matter - */ - if (pt2_clipped) - length++; - - if (pt1_clipped) - { - /* must calculate new error terms */ - clipdx = abs(new_x1 - x1); - clipdy = abs(new_y1 - y1); - e += (clipdy * e2) + ((clipdx - clipdy) * e1); - } - } - - /* draw the segment */ - - x = new_x1; - y = new_y1; - - e3 = e2 - e1; - e = e - e1; - - while (length--) - { - MI_OUTPUT_POINT(x, y); - e += e1; - if (e >= 0) - { - y += signdy; - e += e3; - } - x += signdx; - } - } - else /* Y major line */ - { - e1 = adx << 1; - e2 = e1 - (ady << 1); - e = e1 - ady; - length = ady; /* don't draw endpoint in main loop */ - - SetYMajorOctant(octant); - FIXUP_ERROR(e, octant, bias); - - new_x1 = x1; - new_y1 = y1; - new_x2 = x2; - new_y2 = y2; - pt1_clipped = 0; - pt2_clipped = 0; - - if ((oc1 | oc2) != 0) - { - result = miZeroClipLine(xleft, ytop, xright, ybottom, - &new_x1, &new_y1, &new_x2, &new_y2, - adx, ady, - &pt1_clipped, &pt2_clipped, - octant, bias, oc1, oc2); - if (result == -1) - continue; - - length = abs(new_y2 - new_y1); - - /* if we've clipped the endpoint, always draw the full length - * of the segment, because then the capstyle doesn't matter - */ - if (pt2_clipped) - length++; - - if (pt1_clipped) - { - /* must calculate new error terms */ - clipdx = abs(new_x1 - x1); - clipdy = abs(new_y1 - y1); - e += (clipdx * e2) + ((clipdy - clipdx) * e1); - } - } - - /* draw the segment */ - - x = new_x1; - y = new_y1; - - e3 = e2 - e1; - e = e - e1; - - while (length--) - { - MI_OUTPUT_POINT(x, y); - e += e1; - if (e >= 0) - { - x += signdx; - e += e3; - } - y += signdy; - } - } - } - - /* only do the capnotlast check on the last segment - * and only if the endpoint wasn't clipped. And then, if the last - * point is the same as the first point, do not draw it, unless the - * line is degenerate - */ - if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) && - (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1))) - { - MI_OUTPUT_POINT(x, y); - } - - if (Nspans > 0) - (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, - pwidthInit, FALSE); - - free(pwidthInit); - free(pspanInit); -} - -void -miZeroDashLine( - DrawablePtr dst, - GCPtr pgc, - int mode, - int nptInit, /* number of points in polyline */ - DDXPointRec *pptInit /* points in the polyline */ - ) -{ - /* XXX kludge until real zero-width dash code is written */ - pgc->lineWidth = 1; - miWideDash (dst, pgc, mode, nptInit, pptInit); - pgc->lineWidth = 0; -} +/*********************************************************** + +Copyright 1987, 1998 The Open Group + +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. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +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 Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL 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. + +******************************************************************/ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include "misc.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "windowstr.h" +#include "pixmap.h" +#include "mi.h" +#include "miline.h" + +/* Draw lineSolid, fillStyle-independent zero width lines. + * + * Must keep X and Y coordinates in "ints" at least until after they're + * translated and clipped to accomodate CoordModePrevious lines with very + * large coordinates. + * + * Draws the same pixels regardless of sign(dx) or sign(dy). + * + * Ken Whaley + * + */ + +/* largest positive value that can fit into a component of a point. + * Assumes that the point structure is {type x, y;} where type is + * a signed type. + */ +#define MAX_COORDINATE ((1 << (((sizeof(DDXPointRec) >> 1) << 3) - 1)) - 1) + +#define MI_OUTPUT_POINT(xx, yy)\ +{\ + if ( !new_span && yy == current_y)\ + {\ + if (xx < spans->x)\ + spans->x = xx;\ + ++*widths;\ + }\ + else\ + {\ + ++Nspans;\ + ++spans;\ + ++widths;\ + spans->x = xx;\ + spans->y = yy;\ + *widths = 1;\ + current_y = yy;\ + new_span = FALSE;\ + }\ +} + +void +miZeroLine( + DrawablePtr pDraw, + GCPtr pGC, + int mode, /* Origin or Previous */ + int npt, /* number of points */ + DDXPointPtr pptInit) +{ + int Nspans, current_y = 0; + DDXPointPtr ppt; + DDXPointPtr pspanInit, spans; + int *pwidthInit, *widths, list_len; + int xleft, ytop, xright, ybottom; + int new_x1, new_y1, new_x2, new_y2; + int x = 0, y = 0, x1, y1, x2, y2, xstart, ystart; + int oc1, oc2; + int result; + int pt1_clipped, pt2_clipped = 0; + Bool new_span; + int signdx, signdy; + int clipdx, clipdy; + int width, height; + int adx, ady; + int octant; + unsigned int bias = miGetZeroLineBias(pDraw->pScreen); + int e, e1, e2, e3; /* Bresenham error terms */ + int length; /* length of lines == # of pixels on major axis */ + + xleft = pDraw->x; + ytop = pDraw->y; + xright = pDraw->x + pDraw->width - 1; + ybottom = pDraw->y + pDraw->height - 1; + + if (!pGC->miTranslate) + { + /* do everything in drawable-relative coordinates */ + xleft = 0; + ytop = 0; + xright -= pDraw->x; + ybottom -= pDraw->y; + } + + /* it doesn't matter whether we're in drawable or screen coordinates, + * FillSpans simply cannot take starting coordinates outside of the + * range of a DDXPointRec component. + */ + if (xright > MAX_COORDINATE) + xright = MAX_COORDINATE; + if (ybottom > MAX_COORDINATE) + ybottom = MAX_COORDINATE; + + /* since we're clipping to the drawable's boundaries & coordinate + * space boundaries, we're guaranteed that the larger of width/height + * is the longest span we'll need to output + */ + width = xright - xleft + 1; + height = ybottom - ytop + 1; + list_len = (height >= width) ? height : width; + pspanInit = malloc(list_len * sizeof(DDXPointRec)); + pwidthInit = malloc(list_len * sizeof(int)); + if (!pspanInit || !pwidthInit) { + free(pspanInit); + free(pwidthInit); + return; + } + Nspans = 0; + new_span = TRUE; + spans = pspanInit - 1; + widths = pwidthInit - 1; + ppt = pptInit; + + xstart = ppt->x; + ystart = ppt->y; + if (pGC->miTranslate) + { + xstart += pDraw->x; + ystart += pDraw->y; + } + + /* x2, y2, oc2 copied to x1, y1, oc1 at top of loop to simplify + * iteration logic + */ + x2 = xstart; + y2 = ystart; + oc2 = 0; + MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); + + while (--npt > 0) + { + if (Nspans > 0) + (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, + pwidthInit, FALSE); + Nspans = 0; + new_span = TRUE; + spans = pspanInit - 1; + widths = pwidthInit - 1; + + x1 = x2; + y1 = y2; + oc1 = oc2; + ++ppt; + + x2 = ppt->x; + y2 = ppt->y; + if (pGC->miTranslate && (mode != CoordModePrevious)) + { + x2 += pDraw->x; + y2 += pDraw->y; + } + else if (mode == CoordModePrevious) + { + x2 += x1; + y2 += y1; + } + + oc2 = 0; + MIOUTCODES(oc2, x2, y2, xleft, ytop, xright, ybottom); + + CalcLineDeltas(x1, y1, x2, y2, adx, ady, signdx, signdy, 1, 1, octant); + + if (adx > ady) + { + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + length = adx; /* don't draw endpoint in main loop */ + + FIXUP_ERROR(e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if ((oc1 | oc2) != 0) + { + result = miZeroClipLine(xleft, ytop, xright, ybottom, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, + octant, bias, oc1, oc2); + if (result == -1) + continue; + + length = abs(new_x2 - new_x1); + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + */ + if (pt2_clipped) + length++; + + if (pt1_clipped) + { + /* must calculate new error terms */ + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + e += (clipdy * e2) + ((clipdx - clipdy) * e1); + } + } + + /* draw the segment */ + + x = new_x1; + y = new_y1; + + e3 = e2 - e1; + e = e - e1; + + while (length--) + { + MI_OUTPUT_POINT(x, y); + e += e1; + if (e >= 0) + { + y += signdy; + e += e3; + } + x += signdx; + } + } + else /* Y major line */ + { + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + length = ady; /* don't draw endpoint in main loop */ + + SetYMajorOctant(octant); + FIXUP_ERROR(e, octant, bias); + + new_x1 = x1; + new_y1 = y1; + new_x2 = x2; + new_y2 = y2; + pt1_clipped = 0; + pt2_clipped = 0; + + if ((oc1 | oc2) != 0) + { + result = miZeroClipLine(xleft, ytop, xright, ybottom, + &new_x1, &new_y1, &new_x2, &new_y2, + adx, ady, + &pt1_clipped, &pt2_clipped, + octant, bias, oc1, oc2); + if (result == -1) + continue; + + length = abs(new_y2 - new_y1); + + /* if we've clipped the endpoint, always draw the full length + * of the segment, because then the capstyle doesn't matter + */ + if (pt2_clipped) + length++; + + if (pt1_clipped) + { + /* must calculate new error terms */ + clipdx = abs(new_x1 - x1); + clipdy = abs(new_y1 - y1); + e += (clipdx * e2) + ((clipdy - clipdx) * e1); + } + } + + /* draw the segment */ + + x = new_x1; + y = new_y1; + + e3 = e2 - e1; + e = e - e1; + + while (length--) + { + MI_OUTPUT_POINT(x, y); + e += e1; + if (e >= 0) + { + x += signdx; + e += e3; + } + y += signdy; + } + } + } + + /* only do the capnotlast check on the last segment + * and only if the endpoint wasn't clipped. And then, if the last + * point is the same as the first point, do not draw it, unless the + * line is degenerate + */ + if ( (! pt2_clipped) && (pGC->capStyle != CapNotLast) && + (((xstart != x2) || (ystart != y2)) || (ppt == pptInit + 1))) + { + MI_OUTPUT_POINT(x, y); + } + + if (Nspans > 0) + (*pGC->ops->FillSpans)(pDraw, pGC, Nspans, pspanInit, + pwidthInit, FALSE); + + free(pwidthInit); + free(pspanInit); +} + +void +miZeroDashLine( + DrawablePtr dst, + GCPtr pgc, + int mode, + int nptInit, /* number of points in polyline */ + DDXPointRec *pptInit /* points in the polyline */ + ) +{ + /* XXX kludge until real zero-width dash code is written */ + pgc->lineWidth = 1; + miWideDash (dst, pgc, mode, nptInit, pptInit); + pgc->lineWidth = 0; +} -- cgit v1.2.3