123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556 |
- /***********************************************************
- 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 <dix-config.h>
- #endif
- #include <X11/X.h>
- #include <X11/Xproto.h>
- #include <stdio.h>
- #include <string.h>
- #include <strings.h>
- #include "misc.h"
- #include "dix.h"
- #include "colormapst.h"
- #include "os.h"
- #include "scrnintstr.h"
- #include "resource.h"
- #include "windowstr.h"
- extern XID clientErrorValue;
- extern int colormapPrivateCount;
- static Pixel FindBestPixel(EntryPtr /*pentFirst */ ,
- int /*size */ ,
- xrgb * /*prgb */ ,
- int /*channel */
- );
- static int AllComp(EntryPtr /*pent */ ,
- xrgb * /*prgb */
- );
- static int RedComp(EntryPtr /*pent */ ,
- xrgb * /*prgb */
- );
- static int GreenComp(EntryPtr /*pent */ ,
- xrgb * /*prgb */
- );
- static int BlueComp(EntryPtr /*pent */ ,
- xrgb * /*prgb */
- );
- static void FreePixels(register ColormapPtr /*pmap */ ,
- register int /*client */
- );
- static void CopyFree(int /*channel */ ,
- int /*client */ ,
- ColormapPtr /*pmapSrc */ ,
- ColormapPtr /*pmapDst */
- );
- static void FreeCell(ColormapPtr /*pmap */ ,
- Pixel /*i */ ,
- int /*channel */
- );
- static void UpdateColors(ColormapPtr /*pmap */
- );
- static int AllocDirect(int /*client */ ,
- ColormapPtr /*pmap */ ,
- int /*c */ ,
- int /*r */ ,
- int /*g */ ,
- int /*b */ ,
- Bool /*contig */ ,
- Pixel * /*pixels */ ,
- Pixel * /*prmask */ ,
- Pixel * /*pgmask */ ,
- Pixel * /*pbmask */
- );
- static int AllocPseudo(int /*client */ ,
- ColormapPtr /*pmap */ ,
- int /*c */ ,
- int /*r */ ,
- Bool /*contig */ ,
- Pixel * /*pixels */ ,
- Pixel * /*pmask */ ,
- Pixel ** /*pppixFirst */
- );
- static Bool AllocCP(ColormapPtr /*pmap */ ,
- EntryPtr /*pentFirst */ ,
- int /*count */ ,
- int /*planes */ ,
- Bool /*contig */ ,
- Pixel * /*pixels */ ,
- Pixel * /*pMask */
- );
- static Bool AllocShared(ColormapPtr /*pmap */ ,
- Pixel * /*ppix */ ,
- int /*c */ ,
- int /*r */ ,
- int /*g */ ,
- int /*b */ ,
- Pixel /*rmask */ ,
- Pixel /*gmask */ ,
- Pixel /*bmask */ ,
- Pixel * /*ppixFirst */
- );
- static int FreeCo(ColormapPtr /*pmap */ ,
- int /*client */ ,
- int /*color */ ,
- int /*npixIn */ ,
- Pixel * /*ppixIn */ ,
- Pixel /*mask */
- );
- static int TellNoMap(WindowPtr /*pwin */ ,
- Colormap * /*pmid */
- );
- static void FindColorInRootCmap(ColormapPtr /* pmap */ ,
- EntryPtr /* pentFirst */ ,
- int /* size */ ,
- xrgb * /* prgb */ ,
- Pixel * /* pPixel */ ,
- int /* channel */ ,
- ColorCompareProcPtr /* comp */
- );
- #define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
- #define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
- #define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
- #define ALPHAMASK(vis) 0
- #define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis))
- /* GetNextBitsOrBreak(bits, mask, base) --
- * (Suggestion: First read the macro, then read this explanation.
- *
- * Either generate the next value to OR in to a pixel or break out of this
- * while loop
- *
- * This macro is used when we're trying to generate all 2^n combinations of
- * bits in mask. What we're doing here is counting in binary, except that
- * the bits we use to count may not be contiguous. This macro will be
- * called 2^n times, returning a different value in bits each time. Then
- * it will cause us to break out of a surrounding loop. (It will always be
- * called from within a while loop.)
- * On call: mask is the value we want to find all the combinations for
- * base has 1 bit set where the least significant bit of mask is set
- *
- * For example,if mask is 01010, base should be 0010 and we count like this:
- * 00010 (see this isn't so hard),
- * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so
- * we add that to bits getting (0100 + 0100) =
- * 01000 for our next value.
- * then we add 0010 to get
- * 01010 and we're done (easy as 1, 2, 3)
- */
- #define GetNextBitsOrBreak(bits, mask, base) \
- if((bits) == (mask)) \
- break; \
- (bits) += (base); \
- while((bits) & ~(mask)) \
- (bits) += ((bits) & ~(mask));
- /* ID of server as client */
- #define SERVER_ID 0
- typedef struct _colorResource {
- Colormap mid;
- int client;
- } colorResource;
- /* Invariants:
- * refcnt == 0 means entry is empty
- * refcnt > 0 means entry is useable by many clients, so it can't be changed
- * refcnt == AllocPrivate means entry owned by one client only
- * fShared should only be set if refcnt == AllocPrivate, and only in red map
- */
- /**
- * Create and initialize the color map
- *
- * \param mid resource to use for this colormap
- * \param alloc 1 iff all entries are allocated writable
- */
- _X_EXPORT int
- CreateColormap(Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
- ColormapPtr *ppcmap, int alloc, int client)
- {
- int class, size;
- unsigned long sizebytes;
- ColormapPtr pmap;
- EntryPtr pent;
- int i;
- Pixel *ppix, **pptr;
- class = pVisual->class;
- if (!(class & DynamicClass) && (alloc != AllocNone) &&
- (client != SERVER_ID))
- return (BadMatch);
- size = pVisual->ColormapEntries;
- sizebytes = (size * sizeof(Entry)) +
- (MAXCLIENTS * sizeof(Pixel *)) + (MAXCLIENTS * sizeof(int));
- if ((class | DynamicClass) == DirectColor)
- sizebytes *= 3;
- sizebytes += sizeof(ColormapRec);
- pmap = malloc(sizebytes);
- if (!pmap)
- return (BadAlloc);
- #if defined(_XSERVER64)
- pmap->pad0 = 0;
- pmap->pad1 = 0;
- #if (X_BYTE_ORDER == X_LITTLE_ENDIAN)
- pmap->pad2 = 0;
- #endif
- #endif
- pmap->red = (EntryPtr) ((char *) pmap + sizeof(ColormapRec));
- sizebytes = size * sizeof(Entry);
- pmap->clientPixelsRed = (Pixel **) ((char *) pmap->red + sizebytes);
- pmap->numPixelsRed = (int *) ((char *) pmap->clientPixelsRed +
- (MAXCLIENTS * sizeof(Pixel *)));
- pmap->mid = mid;
- pmap->flags = 0; /* start out with all flags clear */
- if (mid == pScreen->defColormap)
- pmap->flags |= IsDefault;
- pmap->pScreen = pScreen;
- pmap->pVisual = pVisual;
- pmap->class = class;
- if ((class | DynamicClass) == DirectColor)
- size = NUMRED(pVisual);
- pmap->freeRed = size;
- bzero((char *) pmap->red, (int) sizebytes);
- bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int));
- for (pptr = &pmap->clientPixelsRed[MAXCLIENTS];
- --pptr >= pmap->clientPixelsRed;)
- *pptr = (Pixel *) NULL;
- if (alloc == AllocAll) {
- if (class & DynamicClass)
- pmap->flags |= AllAllocated;
- for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeRed = 0;
- ppix = malloc(size * sizeof(Pixel));
- if (!ppix) {
- free(pmap);
- return (BadAlloc);
- }
- pmap->clientPixelsRed[client] = ppix;
- for (i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsRed[client] = size;
- }
- if ((class | DynamicClass) == DirectColor) {
- pmap->freeGreen = NUMGREEN(pVisual);
- pmap->green = (EntryPtr) ((char *) pmap->numPixelsRed +
- (MAXCLIENTS * sizeof(int)));
- pmap->clientPixelsGreen = (Pixel **) ((char *) pmap->green + sizebytes);
- pmap->numPixelsGreen = (int *) ((char *) pmap->clientPixelsGreen +
- (MAXCLIENTS * sizeof(Pixel *)));
- pmap->freeBlue = NUMBLUE(pVisual);
- pmap->blue = (EntryPtr) ((char *) pmap->numPixelsGreen +
- (MAXCLIENTS * sizeof(int)));
- pmap->clientPixelsBlue = (Pixel **) ((char *) pmap->blue + sizebytes);
- pmap->numPixelsBlue = (int *) ((char *) pmap->clientPixelsBlue +
- (MAXCLIENTS * sizeof(Pixel *)));
- bzero((char *) pmap->green, (int) sizebytes);
- bzero((char *) pmap->blue, (int) sizebytes);
- memmove((char *) pmap->clientPixelsGreen,
- (char *) pmap->clientPixelsRed, MAXCLIENTS * sizeof(Pixel *));
- memmove((char *) pmap->clientPixelsBlue,
- (char *) pmap->clientPixelsRed, MAXCLIENTS * sizeof(Pixel *));
- bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int));
- bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int));
- /* If every cell is allocated, mark its refcnt */
- if (alloc == AllocAll) {
- size = pmap->freeGreen;
- for (pent = &pmap->green[size - 1]; pent >= pmap->green; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeGreen = 0;
- ppix = malloc(size * sizeof(Pixel));
- if (!ppix) {
- free(pmap->clientPixelsRed[client]);
- free(pmap);
- return (BadAlloc);
- }
- pmap->clientPixelsGreen[client] = ppix;
- for (i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsGreen[client] = size;
- size = pmap->freeBlue;
- for (pent = &pmap->blue[size - 1]; pent >= pmap->blue; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeBlue = 0;
- ppix = malloc(size * sizeof(Pixel));
- if (!ppix) {
- free(pmap->clientPixelsGreen[client]);
- free(pmap->clientPixelsRed[client]);
- free(pmap);
- return (BadAlloc);
- }
- pmap->clientPixelsBlue[client] = ppix;
- for (i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsBlue[client] = size;
- }
- }
- if (!AddResource(mid, RT_COLORMAP, (pointer) pmap))
- return (BadAlloc);
- /* If the device wants a chance to initialize the colormap in any way,
- * this is it. In specific, if this is a Static colormap, this is the
- * time to fill in the colormap's values */
- pmap->flags |= BeingCreated;
- /*
- * Allocate the array of devPrivate's for this colormap.
- */
- if (colormapPrivateCount == 0)
- pmap->devPrivates = NULL;
- else {
- pmap->devPrivates =
- calloc(sizeof(DevUnion), colormapPrivateCount);
- if (!pmap->devPrivates) {
- FreeResource(mid, RT_NONE);
- return BadAlloc;
- }
- }
- if (!(*pScreen->CreateColormap) (pmap)) {
- FreeResource(mid, RT_NONE);
- return BadAlloc;
- }
- pmap->flags &= ~BeingCreated;
- *ppcmap = pmap;
- return (Success);
- }
- /**
- *
- * \param value must conform to DeleteType
- */
- int
- FreeColormap(pointer value, XID mid)
- {
- int i;
- EntryPtr pent;
- ColormapPtr pmap = (ColormapPtr) value;
- if (CLIENT_ID(mid) != SERVER_ID) {
- (*pmap->pScreen->UninstallColormap) (pmap);
- WalkTree(pmap->pScreen, (VisitWindowProcPtr) TellNoMap, (pointer) &mid);
- }
- /* This is the device's chance to undo anything it needs to, especially
- * to free any storage it allocated */
- (*pmap->pScreen->DestroyColormap) (pmap);
- if (pmap->clientPixelsRed) {
- for (i = 0; i < MAXCLIENTS; i++)
- free(pmap->clientPixelsRed[i]);
- }
- if ((pmap->class == PseudoColor) || (pmap->class == GrayScale)) {
- for (pent = &pmap->red[pmap->pVisual->ColormapEntries - 1];
- pent >= pmap->red; pent--) {
- if (pent->fShared) {
- if (--pent->co.shco.red->refcnt == 0)
- free(pent->co.shco.red);
- if (--pent->co.shco.green->refcnt == 0)
- free(pent->co.shco.green);
- if (--pent->co.shco.blue->refcnt == 0)
- free(pent->co.shco.blue);
- }
- }
- }
- if ((pmap->class | DynamicClass) == DirectColor) {
- for (i = 0; i < MAXCLIENTS; i++) {
- free(pmap->clientPixelsGreen[i]);
- free(pmap->clientPixelsBlue[i]);
- }
- }
- if (pmap->devPrivates)
- free(pmap->devPrivates);
- free(pmap);
- return (Success);
- }
- /* Tell window that pmid has disappeared */
- static int
- TellNoMap(WindowPtr pwin, Colormap * pmid)
- {
- xEvent xE;
- if (wColormap(pwin) == *pmid) {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = None;
- xE.u.colormap.new = TRUE;
- xE.u.colormap.state = ColormapUninstalled;
- DeliverEvents(pwin, &xE, 1, (WindowPtr) NULL);
- if (pwin->optional) {
- pwin->optional->colormap = None;
- CheckWindowOptionalNeed(pwin);
- }
- }
- return (WT_WALKCHILDREN);
- }
- /* Tell window that pmid got uninstalled */
- _X_EXPORT int
- TellLostMap(WindowPtr pwin, pointer value)
- {
- Colormap *pmid = (Colormap *) value;
- xEvent xE;
- if (wColormap(pwin) == *pmid) {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = *pmid;
- xE.u.colormap.new = FALSE;
- xE.u.colormap.state = ColormapUninstalled;
- DeliverEvents(pwin, &xE, 1, (WindowPtr) NULL);
- }
- return (WT_WALKCHILDREN);
- }
- /* Tell window that pmid got installed */
- _X_EXPORT int
- TellGainedMap(WindowPtr pwin, pointer value)
- {
- Colormap *pmid = (Colormap *) value;
- xEvent xE;
- if (wColormap(pwin) == *pmid) {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = *pmid;
- xE.u.colormap.new = FALSE;
- xE.u.colormap.state = ColormapInstalled;
- DeliverEvents(pwin, &xE, 1, (WindowPtr) NULL);
- }
- return (WT_WALKCHILDREN);
- }
- int
- CopyColormapAndFree(Colormap mid, ColormapPtr pSrc, int client)
- {
- ColormapPtr pmap = (ColormapPtr) NULL;
- int result, alloc, size;
- Colormap midSrc;
- ScreenPtr pScreen;
- VisualPtr pVisual;
- pScreen = pSrc->pScreen;
- pVisual = pSrc->pVisual;
- midSrc = pSrc->mid;
- alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ?
- AllocAll : AllocNone;
- size = pVisual->ColormapEntries;
- /* If the create returns non-0, it failed */
- result = CreateColormap(mid, pScreen, pVisual, &pmap, alloc, client);
- if (result != Success)
- return (result);
- if (alloc == AllocAll) {
- memmove((char *) pmap->red, (char *) pSrc->red, size * sizeof(Entry));
- if ((pmap->class | DynamicClass) == DirectColor) {
- memmove((char *) pmap->green, (char *) pSrc->green,
- size * sizeof(Entry));
- memmove((char *) pmap->blue, (char *) pSrc->blue,
- size * sizeof(Entry));
- }
- pSrc->flags &= ~AllAllocated;
- FreePixels(pSrc, client);
- UpdateColors(pmap);
- return (Success);
- }
- CopyFree(REDMAP, client, pSrc, pmap);
- if ((pmap->class | DynamicClass) == DirectColor) {
- CopyFree(GREENMAP, client, pSrc, pmap);
- CopyFree(BLUEMAP, client, pSrc, pmap);
- }
- if (pmap->class & DynamicClass)
- UpdateColors(pmap);
- /* XXX should worry about removing any RT_CMAPENTRY resource */
- return (Success);
- }
- /* Helper routine for freeing large numbers of cells from a map */
- static void
- CopyFree(int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst)
- {
- int z, npix;
- EntryPtr pentSrcFirst, pentDstFirst;
- EntryPtr pentSrc, pentDst;
- Pixel *ppix;
- int nalloc;
- switch (channel) {
- default: /* so compiler can see that everything gets initialized */
- case REDMAP:
- ppix = (pmapSrc->clientPixelsRed)[client];
- npix = (pmapSrc->numPixelsRed)[client];
- pentSrcFirst = pmapSrc->red;
- pentDstFirst = pmapDst->red;
- break;
- case GREENMAP:
- ppix = (pmapSrc->clientPixelsGreen)[client];
- npix = (pmapSrc->numPixelsGreen)[client];
- pentSrcFirst = pmapSrc->green;
- pentDstFirst = pmapDst->green;
- break;
- case BLUEMAP:
- ppix = (pmapSrc->clientPixelsBlue)[client];
- npix = (pmapSrc->numPixelsBlue)[client];
- pentSrcFirst = pmapSrc->blue;
- pentDstFirst = pmapDst->blue;
- break;
- }
- nalloc = 0;
- if (pmapSrc->class & DynamicClass) {
- for (z = npix; --z >= 0; ppix++) {
- /* Copy entries */
- pentSrc = pentSrcFirst + *ppix;
- pentDst = pentDstFirst + *ppix;
- if (pentDst->refcnt > 0) {
- pentDst->refcnt++;
- }
- else {
- *pentDst = *pentSrc;
- nalloc++;
- if (pentSrc->refcnt > 0)
- pentDst->refcnt = 1;
- else
- pentSrc->fShared = FALSE;
- }
- FreeCell(pmapSrc, *ppix, channel);
- }
- }
- /* Note that FreeCell has already fixed pmapSrc->free{Color} */
- switch (channel) {
- case REDMAP:
- pmapDst->freeRed -= nalloc;
- (pmapDst->clientPixelsRed)[client] = (pmapSrc->clientPixelsRed)[client];
- (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL;
- (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client];
- (pmapSrc->numPixelsRed)[client] = 0;
- break;
- case GREENMAP:
- pmapDst->freeGreen -= nalloc;
- (pmapDst->clientPixelsGreen)[client] =
- (pmapSrc->clientPixelsGreen)[client];
- (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL;
- (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client];
- (pmapSrc->numPixelsGreen)[client] = 0;
- break;
- case BLUEMAP:
- pmapDst->freeBlue -= nalloc;
- pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client];
- pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL;
- pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client];
- pmapSrc->numPixelsBlue[client] = 0;
- break;
- }
- }
- /* Free the ith entry in a color map. Must handle freeing of
- * colors allocated through AllocColorPlanes */
- static void
- FreeCell(ColormapPtr pmap, Pixel i, int channel)
- {
- EntryPtr pent;
- int *pCount;
- switch (channel) {
- default: /* so compiler can see that everything gets initialized */
- case PSEUDOMAP:
- case REDMAP:
- pent = (EntryPtr) & pmap->red[i];
- pCount = &pmap->freeRed;
- break;
- case GREENMAP:
- pent = (EntryPtr) & pmap->green[i];
- pCount = &pmap->freeGreen;
- break;
- case BLUEMAP:
- pent = (EntryPtr) & pmap->blue[i];
- pCount = &pmap->freeBlue;
- break;
- }
- /* If it's not privately allocated and it's not time to free it, just
- * decrement the count */
- if (pent->refcnt > 1)
- pent->refcnt--;
- else {
- /* If the color type is shared, find the sharedcolor. If decremented
- * refcnt is 0, free the shared cell. */
- if (pent->fShared) {
- if (--pent->co.shco.red->refcnt == 0)
- free(pent->co.shco.red);
- if (--pent->co.shco.green->refcnt == 0)
- free(pent->co.shco.green);
- if (--pent->co.shco.blue->refcnt == 0)
- free(pent->co.shco.blue);
- pent->fShared = FALSE;
- }
- pent->refcnt = 0;
- *pCount += 1;
- }
- }
- static void
- UpdateColors(ColormapPtr pmap)
- {
- xColorItem *defs;
- xColorItem *pdef;
- EntryPtr pent;
- VisualPtr pVisual;
- int i, n, size;
- pVisual = pmap->pVisual;
- size = pVisual->ColormapEntries;
- defs = (xColorItem *) ALLOCATE_LOCAL(size * sizeof(xColorItem));
- if (!defs)
- return;
- n = 0;
- pdef = defs;
- if (pmap->class == DirectColor) {
- for (i = 0; i < size; i++) {
- if (!pmap->red[i].refcnt &&
- !pmap->green[i].refcnt && !pmap->blue[i].refcnt)
- continue;
- pdef->pixel = ((Pixel) i << pVisual->offsetRed) |
- ((Pixel) i << pVisual->offsetGreen) |
- ((Pixel) i << pVisual->offsetBlue);
- pdef->red = pmap->red[i].co.local.red;
- pdef->green = pmap->green[i].co.local.green;
- pdef->blue = pmap->blue[i].co.local.blue;
- pdef->flags = DoRed | DoGreen | DoBlue;
- pdef++;
- n++;
- }
- }
- else {
- for (i = 0, pent = pmap->red; i < size; i++, pent++) {
- if (!pent->refcnt)
- continue;
- pdef->pixel = i;
- if (pent->fShared) {
- pdef->red = pent->co.shco.red->color;
- pdef->green = pent->co.shco.green->color;
- pdef->blue = pent->co.shco.blue->color;
- }
- else {
- pdef->red = pent->co.local.red;
- pdef->green = pent->co.local.green;
- pdef->blue = pent->co.local.blue;
- }
- pdef->flags = DoRed | DoGreen | DoBlue;
- pdef++;
- n++;
- }
- }
- if (n)
- (*pmap->pScreen->StoreColors) (pmap, n, defs);
- DEALLOCATE_LOCAL(defs);
- }
- /* Get a read-only color from a ColorMap (probably slow for large maps)
- * Returns by changing the value in pred, pgreen, pblue and pPix
- */
- _X_EXPORT int
- AllocColor(ColormapPtr pmap,
- unsigned short *pred, unsigned short *pgreen, unsigned short *pblue,
- Pixel * pPix, int client)
- {
- Pixel pixR, pixG, pixB;
- int entries;
- xrgb rgb;
- int class;
- VisualPtr pVisual;
- int npix;
- Pixel *ppix;
- pVisual = pmap->pVisual;
- (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual);
- rgb.red = *pred;
- rgb.green = *pgreen;
- rgb.blue = *pblue;
- class = pmap->class;
- entries = pVisual->ColormapEntries;
- /* If the colormap is being created, then we want to be able to change
- * the colormap, even if it's a static type. Otherwise, we'd never be
- * able to initialize static colormaps
- */
- if (pmap->flags & BeingCreated)
- class |= DynamicClass;
- /* If this is one of the static storage classes, and we're not initializing
- * it, the best we can do is to find the closest color entry to the
- * requested one and return that.
- */
- switch (class) {
- case StaticColor:
- case StaticGray:
- /* Look up all three components in the same pmap */
- *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
- *pred = pmap->red[pixR].co.local.red;
- *pgreen = pmap->red[pixR].co.local.green;
- *pblue = pmap->red[pixR].co.local.blue;
- npix = pmap->numPixelsRed[client];
- ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixR;
- pmap->clientPixelsRed[client] = ppix;
- pmap->numPixelsRed[client]++;
- break;
- case TrueColor:
- /* Look up each component in its own map, then OR them together */
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
- *pPix = (pixR << pVisual->offsetRed) |
- (pixG << pVisual->offsetGreen) |
- (pixB << pVisual->offsetBlue) | ALPHAMASK(pVisual);
- *pred = pmap->red[pixR].co.local.red;
- *pgreen = pmap->green[pixG].co.local.green;
- *pblue = pmap->blue[pixB].co.local.blue;
- npix = pmap->numPixelsRed[client];
- ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixR;
- pmap->clientPixelsRed[client] = ppix;
- npix = pmap->numPixelsGreen[client];
- ppix = (Pixel *) realloc(pmap->clientPixelsGreen[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixG;
- pmap->clientPixelsGreen[client] = ppix;
- npix = pmap->numPixelsBlue[client];
- ppix = (Pixel *) realloc(pmap->clientPixelsBlue[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixB;
- pmap->clientPixelsBlue[client] = ppix;
- pmap->numPixelsRed[client]++;
- pmap->numPixelsGreen[client]++;
- pmap->numPixelsBlue[client]++;
- break;
- case GrayScale:
- case PseudoColor:
- if (pmap->mid != pmap->pScreen->defColormap &&
- pmap->pVisual->vid == pmap->pScreen->rootVisual) {
- ColormapPtr prootmap = (ColormapPtr)
- SecurityLookupIDByType(clients[client],
- pmap->pScreen->defColormap,
- RT_COLORMAP, SecurityReadAccess);
- if (pmap->class == prootmap->class)
- FindColorInRootCmap(prootmap, prootmap->red, entries, &rgb,
- pPix, PSEUDOMAP, AllComp);
- }
- if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
- client, AllComp) != Success)
- return (BadAlloc);
- break;
- case DirectColor:
- if (pmap->mid != pmap->pScreen->defColormap &&
- pmap->pVisual->vid == pmap->pScreen->rootVisual) {
- ColormapPtr prootmap = (ColormapPtr)
- SecurityLookupIDByType(clients[client],
- pmap->pScreen->defColormap,
- RT_COLORMAP, SecurityReadAccess);
- if (pmap->class == prootmap->class) {
- pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
- FindColorInRootCmap(prootmap, prootmap->red, entries, &rgb,
- &pixR, REDMAP, RedComp);
- pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
- FindColorInRootCmap(prootmap, prootmap->green, entries, &rgb,
- &pixG, GREENMAP, GreenComp);
- pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
- FindColorInRootCmap(prootmap, prootmap->blue, entries, &rgb,
- &pixB, BLUEMAP, BlueComp);
- *pPix = pixR | pixG | pixB;
- }
- }
- pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
- if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
- client, RedComp) != Success)
- return (BadAlloc);
- pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
- if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
- GREENMAP, client, GreenComp) != Success) {
- (void) FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel) 0);
- return (BadAlloc);
- }
- pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
- if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
- client, BlueComp) != Success) {
- (void) FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel) 0);
- (void) FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel) 0);
- return (BadAlloc);
- }
- *pPix = pixR | pixG | pixB | ALPHAMASK(pVisual);
- break;
- }
- /* if this is the client's first pixel in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((pmap->numPixelsRed[client] == 1) &&
- (CLIENT_ID(pmap->mid) != client) && !(pmap->flags & BeingCreated)) {
- colorResource *pcr;
- pcr = malloc(sizeof(colorResource));
- if (!pcr) {
- (void) FreeColors(pmap, client, 1, pPix, (Pixel) 0);
- return (BadAlloc);
- }
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer) pcr))
- return (BadAlloc);
- }
- return (Success);
- }
- /*
- * FakeAllocColor -- fake an AllocColor request by
- * returning a free pixel if availible, otherwise returning
- * the closest matching pixel. This is used by the mi
- * software sprite code to recolor cursors. A nice side-effect
- * is that this routine will never return failure.
- */
- _X_EXPORT void
- FakeAllocColor(register ColormapPtr pmap, register xColorItem * item)
- {
- Pixel pixR, pixG, pixB;
- Pixel temp;
- int entries;
- xrgb rgb;
- int class;
- VisualPtr pVisual;
- pVisual = pmap->pVisual;
- rgb.red = item->red;
- rgb.green = item->green;
- rgb.blue = item->blue;
- (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual);
- class = pmap->class;
- entries = pVisual->ColormapEntries;
- switch (class) {
- case GrayScale:
- case PseudoColor:
- item->pixel = 0;
- if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP,
- -1, AllComp) == Success) {
- item->pixel = temp;
- break;
- }
- /* fall through ... */
- case StaticColor:
- case StaticGray:
- item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
- break;
- case DirectColor:
- /* Look up each component in its own map, then OR them together */
- pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed;
- pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
- -1, RedComp) != Success)
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP)
- << pVisual->offsetRed;
- if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
- GREENMAP, -1, GreenComp) != Success)
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb,
- GREENMAP) << pVisual->offsetGreen;
- if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
- -1, BlueComp) != Success)
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP)
- << pVisual->offsetBlue;
- item->pixel = pixR | pixG | pixB;
- break;
- case TrueColor:
- /* Look up each component in its own map, then OR them together */
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
- item->pixel = (pixR << pVisual->offsetRed) |
- (pixG << pVisual->offsetGreen) | (pixB << pVisual->offsetBlue);
- break;
- }
- }
- /* free a pixel value obtained from FakeAllocColor */
- _X_EXPORT void
- FakeFreeColor(register ColormapPtr pmap, Pixel pixel)
- {
- VisualPtr pVisual;
- Pixel pixR, pixG, pixB;
- switch (pmap->class) {
- case GrayScale:
- case PseudoColor:
- if (pmap->red[pixel].refcnt == AllocTemporary)
- pmap->red[pixel].refcnt = 0;
- break;
- case DirectColor:
- pVisual = pmap->pVisual;
- pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed;
- pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (pmap->red[pixR].refcnt == AllocTemporary)
- pmap->red[pixR].refcnt = 0;
- if (pmap->green[pixG].refcnt == AllocTemporary)
- pmap->green[pixG].refcnt = 0;
- if (pmap->blue[pixB].refcnt == AllocTemporary)
- pmap->blue[pixB].refcnt = 0;
- break;
- }
- }
- typedef unsigned short BigNumUpper;
- typedef unsigned long BigNumLower;
- #define BIGNUMLOWERBITS 24
- #define BIGNUMUPPERBITS 16
- #define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
- #define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
- #define UPPERPART(i) ((i) >> BIGNUMLOWERBITS)
- #define LOWERPART(i) ((i) & (BIGNUMLOWER - 1))
- typedef struct _bignum {
- BigNumUpper upper;
- BigNumLower lower;
- } BigNumRec, *BigNumPtr;
- #define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\
- ((x)->upper == (y)->upper && (x)->lower > (y)->lower))
- #define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \
- ((r)->lower = LOWERPART(u)))
- #define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \
- ((r)->lower = BIGNUMLOWER-1))
- static void
- BigNumAdd(BigNumPtr x, BigNumPtr y, BigNumPtr r)
- {
- BigNumLower lower, carry = 0;
- lower = x->lower + y->lower;
- if (lower >= BIGNUMLOWER) {
- lower -= BIGNUMLOWER;
- carry = 1;
- }
- r->lower = lower;
- r->upper = x->upper + y->upper + carry;
- }
- static Pixel
- FindBestPixel(EntryPtr pentFirst, int size, xrgb * prgb, int channel)
- {
- EntryPtr pent;
- Pixel pixel, final;
- long dr, dg, db;
- unsigned long sq;
- BigNumRec minval, sum, temp;
- final = 0;
- MaxBigNum(&minval);
- /* look for the minimal difference */
- for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++) {
- dr = dg = db = 0;
- switch (channel) {
- case PSEUDOMAP:
- dg = (long) pent->co.local.green - prgb->green;
- db = (long) pent->co.local.blue - prgb->blue;
- case REDMAP:
- dr = (long) pent->co.local.red - prgb->red;
- break;
- case GREENMAP:
- dg = (long) pent->co.local.green - prgb->green;
- break;
- case BLUEMAP:
- db = (long) pent->co.local.blue - prgb->blue;
- break;
- }
- sq = dr * dr;
- UnsignedToBigNum(sq, &sum);
- sq = dg * dg;
- UnsignedToBigNum(sq, &temp);
- BigNumAdd(&sum, &temp, &sum);
- sq = db * db;
- UnsignedToBigNum(sq, &temp);
- BigNumAdd(&sum, &temp, &sum);
- if (BigNumGreater(&minval, &sum)) {
- final = pixel;
- minval = sum;
- }
- }
- return (final);
- }
- static void
- FindColorInRootCmap(ColormapPtr pmap, EntryPtr pentFirst, int size,
- xrgb * prgb, Pixel * pPixel, int channel,
- ColorCompareProcPtr comp)
- {
- EntryPtr pent;
- Pixel pixel;
- int count;
- if ((pixel = *pPixel) >= size)
- pixel = 0;
- for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++) {
- if (pent->refcnt > 0 && (*comp) (pent, prgb)) {
- switch (channel) {
- case REDMAP:
- pixel <<= pmap->pVisual->offsetRed;
- break;
- case GREENMAP:
- pixel <<= pmap->pVisual->offsetGreen;
- break;
- case BLUEMAP:
- pixel <<= pmap->pVisual->offsetBlue;
- break;
- default: /* PSEUDOMAP */
- break;
- }
- *pPixel = pixel;
- }
- }
- }
- /* Tries to find a color in pmap that exactly matches the one requested in prgb
- * if it can't it allocates one.
- * Starts looking at pentFirst + *pPixel, so if you want a specific pixel,
- * load *pPixel with that value, otherwise set it to 0
- */
- int
- FindColor(ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb * prgb,
- Pixel * pPixel, int channel, int client, ColorCompareProcPtr comp)
- {
- EntryPtr pent;
- Bool foundFree;
- Pixel pixel, Free = 0;
- int npix, count, *nump = NULL;
- Pixel **pixp = NULL, *ppix;
- xColorItem def;
- foundFree = FALSE;
- if ((pixel = *pPixel) >= size)
- pixel = 0;
- /* see if there is a match, and also look for a free entry */
- for (pent = pentFirst + pixel, count = size; --count >= 0;) {
- if (pent->refcnt > 0) {
- if ((*comp) (pent, prgb)) {
- if (client >= 0)
- pent->refcnt++;
- *pPixel = pixel;
- switch (channel) {
- case REDMAP:
- *pPixel <<= pmap->pVisual->offsetRed;
- case PSEUDOMAP:
- break;
- case GREENMAP:
- *pPixel <<= pmap->pVisual->offsetGreen;
- break;
- case BLUEMAP:
- *pPixel <<= pmap->pVisual->offsetBlue;
- break;
- }
- goto gotit;
- }
- }
- else if (!foundFree && pent->refcnt == 0) {
- Free = pixel;
- foundFree = TRUE;
- /* If we're initializing the colormap, then we are looking for
- * the first free cell we can find, not to minimize the number
- * of entries we use. So don't look any further. */
- if (pmap->flags & BeingCreated)
- break;
- }
- pixel++;
- if (pixel >= size) {
- pent = pentFirst;
- pixel = 0;
- }
- else
- pent++;
- }
- /* If we got here, we didn't find a match. If we also didn't find
- * a free entry, we're out of luck. Otherwise, we'll usurp a free
- * entry and fill it in */
- if (!foundFree)
- return (BadAlloc);
- pent = pentFirst + Free;
- pent->fShared = FALSE;
- pent->refcnt = (client >= 0) ? 1 : AllocTemporary;
- switch (channel) {
- case PSEUDOMAP:
- pent->co.local.red = prgb->red;
- pent->co.local.green = prgb->green;
- pent->co.local.blue = prgb->blue;
- def.red = prgb->red;
- def.green = prgb->green;
- def.blue = prgb->blue;
- def.flags = (DoRed | DoGreen | DoBlue);
- if (client >= 0)
- pmap->freeRed--;
- def.pixel = Free;
- break;
- case REDMAP:
- pent->co.local.red = prgb->red;
- def.red = prgb->red;
- def.green = pmap->green[0].co.local.green;
- def.blue = pmap->blue[0].co.local.blue;
- def.flags = DoRed;
- if (client >= 0)
- pmap->freeRed--;
- def.pixel = Free << pmap->pVisual->offsetRed;
- break;
- case GREENMAP:
- pent->co.local.green = prgb->green;
- def.red = pmap->red[0].co.local.red;
- def.green = prgb->green;
- def.blue = pmap->blue[0].co.local.blue;
- def.flags = DoGreen;
- if (client >= 0)
- pmap->freeGreen--;
- def.pixel = Free << pmap->pVisual->offsetGreen;
- break;
- case BLUEMAP:
- pent->co.local.blue = prgb->blue;
- def.red = pmap->red[0].co.local.red;
- def.green = pmap->green[0].co.local.green;
- def.blue = prgb->blue;
- def.flags = DoBlue;
- if (client >= 0)
- pmap->freeBlue--;
- def.pixel = Free << pmap->pVisual->offsetBlue;
- break;
- }
- (*pmap->pScreen->StoreColors) (pmap, 1, &def);
- pixel = Free;
- *pPixel = def.pixel;
- gotit:
- if (pmap->flags & BeingCreated || client == -1)
- return (Success);
- /* Now remember the pixel, for freeing later */
- switch (channel) {
- case PSEUDOMAP:
- case REDMAP:
- nump = pmap->numPixelsRed;
- pixp = pmap->clientPixelsRed;
- break;
- case GREENMAP:
- nump = pmap->numPixelsGreen;
- pixp = pmap->clientPixelsGreen;
- break;
- case BLUEMAP:
- nump = pmap->numPixelsBlue;
- pixp = pmap->clientPixelsBlue;
- break;
- }
- npix = nump[client];
- ppix = (Pixel *) realloc(pixp[client], (npix + 1) * sizeof(Pixel));
- if (!ppix) {
- pent->refcnt--;
- if (!pent->fShared)
- switch (channel) {
- case PSEUDOMAP:
- case REDMAP:
- pmap->freeRed++;
- break;
- case GREENMAP:
- pmap->freeGreen++;
- break;
- case BLUEMAP:
- pmap->freeBlue++;
- break;
- }
- return (BadAlloc);
- }
- ppix[npix] = pixel;
- pixp[client] = ppix;
- nump[client]++;
- return (Success);
- }
- /* Comparison functions -- passed to FindColor to determine if an
- * entry is already the color we're looking for or not */
- static int
- AllComp(EntryPtr pent, xrgb * prgb)
- {
- if ((pent->co.local.red == prgb->red) &&
- (pent->co.local.green == prgb->green) &&
- (pent->co.local.blue == prgb->blue))
- return (1);
- return (0);
- }
- static int
- RedComp(EntryPtr pent, xrgb * prgb)
- {
- if (pent->co.local.red == prgb->red)
- return (1);
- return (0);
- }
- static int
- GreenComp(EntryPtr pent, xrgb * prgb)
- {
- if (pent->co.local.green == prgb->green)
- return (1);
- return (0);
- }
- static int
- BlueComp(EntryPtr pent, xrgb * prgb)
- {
- if (pent->co.local.blue == prgb->blue)
- return (1);
- return (0);
- }
- /* Read the color value of a cell */
- _X_EXPORT int
- QueryColors(ColormapPtr pmap, int count, Pixel * ppixIn, xrgb * prgbList)
- {
- Pixel *ppix, pixel;
- xrgb *prgb;
- VisualPtr pVisual;
- EntryPtr pent;
- Pixel i;
- int errVal = Success;
- pVisual = pmap->pVisual;
- if ((pmap->class | DynamicClass) == DirectColor) {
- int numred, numgreen, numblue;
- Pixel rgbbad;
- numred = NUMRED(pVisual);
- numgreen = NUMGREEN(pVisual);
- numblue = NUMBLUE(pVisual);
- rgbbad = ~RGBMASK(pVisual);
- for (ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) {
- pixel = *ppix;
- if (pixel & rgbbad) {
- clientErrorValue = pixel;
- errVal = BadValue;
- continue;
- }
- i = (pixel & pVisual->redMask) >> pVisual->offsetRed;
- if (i >= numred) {
- clientErrorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->red = pmap->red[i].co.local.red;
- i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- if (i >= numgreen) {
- clientErrorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->green = pmap->green[i].co.local.green;
- i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (i >= numblue) {
- clientErrorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->blue = pmap->blue[i].co.local.blue;
- }
- }
- else {
- for (ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++) {
- pixel = *ppix;
- if (pixel >= pVisual->ColormapEntries) {
- clientErrorValue = pixel;
- errVal = BadValue;
- }
- else {
- pent = (EntryPtr) & pmap->red[pixel];
- if (pent->fShared) {
- prgb->red = pent->co.shco.red->color;
- prgb->green = pent->co.shco.green->color;
- prgb->blue = pent->co.shco.blue->color;
- }
- else {
- prgb->red = pent->co.local.red;
- prgb->green = pent->co.local.green;
- prgb->blue = pent->co.local.blue;
- }
- }
- }
- }
- return (errVal);
- }
- static void
- FreePixels(register ColormapPtr pmap, register int client)
- {
- Pixel *ppix, *ppixStart;
- int class, n;
- class = pmap->class;
- ppixStart = pmap->clientPixelsRed[client];
- if (class & DynamicClass) {
- n = pmap->numPixelsRed[client];
- for (ppix = ppixStart; --n >= 0;) {
- FreeCell(pmap, *ppix, REDMAP);
- ppix++;
- }
- }
- free(ppixStart);
- pmap->clientPixelsRed[client] = (Pixel *) NULL;
- pmap->numPixelsRed[client] = 0;
- if ((class | DynamicClass) == DirectColor) {
- ppixStart = pmap->clientPixelsGreen[client];
- if (class & DynamicClass)
- for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;)
- FreeCell(pmap, *ppix++, GREENMAP);
- free(ppixStart);
- pmap->clientPixelsGreen[client] = (Pixel *) NULL;
- pmap->numPixelsGreen[client] = 0;
- ppixStart = pmap->clientPixelsBlue[client];
- if (class & DynamicClass)
- for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0;)
- FreeCell(pmap, *ppix++, BLUEMAP);
- free(ppixStart);
- pmap->clientPixelsBlue[client] = (Pixel *) NULL;
- pmap->numPixelsBlue[client] = 0;
- }
- }
- /**
- * Frees all of a client's colors and cells.
- *
- * \param value must conform to DeleteType
- * \unused fakeid
- */
- int
- FreeClientPixels(pointer value, XID fakeid)
- {
- ColormapPtr pmap;
- colorResource *pcr = (colorResource *) value;
- pmap = (ColormapPtr) LookupIDByType(pcr->mid, RT_COLORMAP);
- if (pmap)
- FreePixels(pmap, pcr->client);
- free(pcr);
- return Success;
- }
- int
- AllocColorCells(int client, ColormapPtr pmap, int colors, int planes,
- Bool contig, Pixel * ppix, Pixel * masks)
- {
- Pixel rmask, gmask, bmask, *ppixFirst, r, g, b;
- int n, class;
- int ok;
- int oldcount;
- colorResource *pcr = (colorResource *) NULL;
- class = pmap->class;
- if (!(class & DynamicClass))
- return (BadAlloc); /* Shouldn't try on this type */
- oldcount = pmap->numPixelsRed[client];
- if (pmap->class == DirectColor)
- oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
- if (!oldcount && (CLIENT_ID(pmap->mid) != client)) {
- pcr = malloc(sizeof(colorResource));
- if (!pcr)
- return (BadAlloc);
- }
- if (pmap->class == DirectColor) {
- ok = AllocDirect(client, pmap, colors, planes, planes, planes,
- contig, ppix, &rmask, &gmask, &bmask);
- if (ok == Success) {
- for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b) {
- while (!(rmask & r))
- r += r;
- while (!(gmask & g))
- g += g;
- while (!(bmask & b))
- b += b;
- *masks++ = r | g | b;
- }
- }
- }
- else {
- ok = AllocPseudo(client, pmap, colors, planes, contig, ppix, &rmask,
- &ppixFirst);
- if (ok == Success) {
- for (r = 1, n = planes; --n >= 0; r += r) {
- while (!(rmask & r))
- r += r;
- *masks++ = r;
- }
- }
- }
- /* if this is the client's first pixels in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((ok == Success) && pcr) {
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer) pcr))
- ok = BadAlloc;
- }
- else if (pcr)
- free(pcr);
- return (ok);
- }
- int
- AllocColorPlanes(int client, ColormapPtr pmap, int colors,
- int r, int g, int b, Bool contig, Pixel * pixels,
- Pixel * prmask, Pixel * pgmask, Pixel * pbmask)
- {
- int ok;
- Pixel mask, *ppixFirst;
- Pixel shift;
- int i;
- int class;
- int oldcount;
- colorResource *pcr = (colorResource *) NULL;
- class = pmap->class;
- if (!(class & DynamicClass))
- return (BadAlloc); /* Shouldn't try on this type */
- oldcount = pmap->numPixelsRed[client];
- if (class == DirectColor)
- oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
- if (!oldcount && (CLIENT_ID(pmap->mid) != client)) {
- pcr = malloc(sizeof(colorResource));
- if (!pcr)
- return (BadAlloc);
- }
- if (class == DirectColor) {
- ok = AllocDirect(client, pmap, colors, r, g, b, contig, pixels,
- prmask, pgmask, pbmask);
- }
- else {
- /* Allocate the proper pixels */
- /* XXX This is sort of bad, because of contig is set, we force all
- * r + g + b bits to be contiguous. Should only force contiguity
- * per mask
- */
- ok = AllocPseudo(client, pmap, colors, r + g + b, contig, pixels,
- &mask, &ppixFirst);
- if (ok == Success) {
- /* now split that mask into three */
- *prmask = *pgmask = *pbmask = 0;
- shift = 1;
- for (i = r; --i >= 0; shift += shift) {
- while (!(mask & shift))
- shift += shift;
- *prmask |= shift;
- }
- for (i = g; --i >= 0; shift += shift) {
- while (!(mask & shift))
- shift += shift;
- *pgmask |= shift;
- }
- for (i = b; --i >= 0; shift += shift) {
- while (!(mask & shift))
- shift += shift;
- *pbmask |= shift;
- }
- /* set up the shared color cells */
- if (!AllocShared(pmap, pixels, colors, r, g, b,
- *prmask, *pgmask, *pbmask, ppixFirst)) {
- (void) FreeColors(pmap, client, colors, pixels, mask);
- ok = BadAlloc;
- }
- }
- }
- /* if this is the client's first pixels in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((ok == Success) && pcr) {
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer) pcr))
- ok = BadAlloc;
- }
- else if (pcr)
- free(pcr);
- return (ok);
- }
- static int
- AllocDirect(int client, ColormapPtr pmap, int c, int r, int g, int b,
- Bool contig, Pixel * pixels, Pixel * prmask, Pixel * pgmask,
- Pixel * pbmask)
- {
- Pixel *ppixRed, *ppixGreen, *ppixBlue;
- Pixel *ppix, *pDst, *p;
- int npix, npixR, npixG, npixB;
- Bool okR, okG, okB;
- Pixel *rpix = 0, *gpix = 0, *bpix = 0;
- npixR = c << r;
- npixG = c << g;
- npixB = c << b;
- if ((r >= 32) || (g >= 32) || (b >= 32) ||
- (npixR > pmap->freeRed) || (npixR < c) ||
- (npixG > pmap->freeGreen) || (npixG < c) ||
- (npixB > pmap->freeBlue) || (npixB < c))
- return BadAlloc;
- /* start out with empty pixels */
- for (p = pixels; p < pixels + c; p++)
- *p = 0;
- ppixRed = (Pixel *) ALLOCATE_LOCAL(npixR * sizeof(Pixel));
- ppixGreen = (Pixel *) ALLOCATE_LOCAL(npixG * sizeof(Pixel));
- ppixBlue = (Pixel *) ALLOCATE_LOCAL(npixB * sizeof(Pixel));
- if (!ppixRed || !ppixGreen || !ppixBlue) {
- if (ppixBlue)
- DEALLOCATE_LOCAL(ppixBlue);
- if (ppixGreen)
- DEALLOCATE_LOCAL(ppixGreen);
- if (ppixRed)
- DEALLOCATE_LOCAL(ppixRed);
- return (BadAlloc);
- }
- okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask);
- okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask);
- okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask);
- if (okR && okG && okB) {
- rpix = (Pixel *) realloc(pmap->clientPixelsRed[client],
- (pmap->numPixelsRed[client] + (c << r)) *
- sizeof(Pixel));
- if (rpix)
- pmap->clientPixelsRed[client] = rpix;
- gpix = (Pixel *) realloc(pmap->clientPixelsGreen[client],
- (pmap->numPixelsGreen[client] + (c << g)) *
- sizeof(Pixel));
- if (gpix)
- pmap->clientPixelsGreen[client] = gpix;
- bpix = (Pixel *) realloc(pmap->clientPixelsBlue[client],
- (pmap->numPixelsBlue[client] + (c << b)) *
- sizeof(Pixel));
- if (bpix)
- pmap->clientPixelsBlue[client] = bpix;
- }
- if (!okR || !okG || !okB || !rpix || !gpix || !bpix) {
- if (okR)
- for (ppix = ppixRed, npix = npixR; --npix >= 0; ppix++)
- pmap->red[*ppix].refcnt = 0;
- if (okG)
- for (ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++)
- pmap->green[*ppix].refcnt = 0;
- if (okB)
- for (ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++)
- pmap->blue[*ppix].refcnt = 0;
- DEALLOCATE_LOCAL(ppixBlue);
- DEALLOCATE_LOCAL(ppixGreen);
- DEALLOCATE_LOCAL(ppixRed);
- return (BadAlloc);
- }
- *prmask <<= pmap->pVisual->offsetRed;
- *pgmask <<= pmap->pVisual->offsetGreen;
- *pbmask <<= pmap->pVisual->offsetBlue;
- ppix = rpix + pmap->numPixelsRed[client];
- for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++) {
- *ppix++ = *p;
- if (p < ppixRed + c)
- *pDst++ |= *p << pmap->pVisual->offsetRed;
- }
- pmap->numPixelsRed[client] += npixR;
- pmap->freeRed -= npixR;
- ppix = gpix + pmap->numPixelsGreen[client];
- for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++) {
- *ppix++ = *p;
- if (p < ppixGreen + c)
- *pDst++ |= *p << pmap->pVisual->offsetGreen;
- }
- pmap->numPixelsGreen[client] += npixG;
- pmap->freeGreen -= npixG;
- ppix = bpix + pmap->numPixelsBlue[client];
- for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++) {
- *ppix++ = *p;
- if (p < ppixBlue + c)
- *pDst++ |= *p << pmap->pVisual->offsetBlue;
- }
- pmap->numPixelsBlue[client] += npixB;
- pmap->freeBlue -= npixB;
- for (pDst = pixels; pDst < pixels + c; pDst++)
- *pDst |= ALPHAMASK(pmap->pVisual);
- DEALLOCATE_LOCAL(ppixBlue);
- DEALLOCATE_LOCAL(ppixGreen);
- DEALLOCATE_LOCAL(ppixRed);
- return (Success);
- }
- static int
- AllocPseudo(int client, ColormapPtr pmap, int c, int r, Bool contig,
- Pixel * pixels, Pixel * pmask, Pixel ** pppixFirst)
- {
- Pixel *ppix, *p, *pDst, *ppixTemp;
- int npix;
- Bool ok;
- npix = c << r;
- if ((r >= 32) || (npix > pmap->freeRed) || (npix < c))
- return (BadAlloc);
- if (!(ppixTemp = (Pixel *) ALLOCATE_LOCAL(npix * sizeof(Pixel))))
- return (BadAlloc);
- ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask);
- if (ok) {
- /* all the allocated pixels are added to the client pixel list,
- * but only the unique ones are returned to the client */
- ppix = (Pixel *) realloc(pmap->clientPixelsRed[client],
- (pmap->numPixelsRed[client] +
- npix) * sizeof(Pixel));
- if (!ppix) {
- for (p = ppixTemp; p < ppixTemp + npix; p++)
- pmap->red[*p].refcnt = 0;
- return (BadAlloc);
- }
- pmap->clientPixelsRed[client] = ppix;
- ppix += pmap->numPixelsRed[client];
- *pppixFirst = ppix;
- pDst = pixels;
- for (p = ppixTemp; p < ppixTemp + npix; p++) {
- *ppix++ = *p;
- if (p < ppixTemp + c)
- *pDst++ = *p;
- }
- pmap->numPixelsRed[client] += npix;
- pmap->freeRed -= npix;
- }
- DEALLOCATE_LOCAL(ppixTemp);
- return (ok ? Success : BadAlloc);
- }
- /* Allocates count << planes pixels from colormap pmap for client. If
- * contig, then the plane mask is made of consecutive bits. Returns
- * all count << pixels in the array pixels. The first count of those
- * pixels are the unique pixels. *pMask has the mask to Or with the
- * unique pixels to get the rest of them.
- *
- * Returns True iff all pixels could be allocated
- * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE
- * (see AllocShared for why we care)
- */
- static Bool
- AllocCP(ColormapPtr pmap, EntryPtr pentFirst, int count, int planes,
- Bool contig, Pixel * pixels, Pixel * pMask)
- {
- EntryPtr ent;
- Pixel pixel, base, entries, maxp, save;
- int dplanes, found;
- Pixel *ppix;
- Pixel mask;
- Pixel finalmask;
- dplanes = pmap->pVisual->nplanes;
- /* Easy case. Allocate pixels only */
- if (planes == 0) {
- /* allocate writable entries */
- ppix = pixels;
- ent = pentFirst;
- pixel = 0;
- while (--count >= 0) {
- /* Just find count unallocated cells */
- while (ent->refcnt) {
- ent++;
- pixel++;
- }
- ent->refcnt = AllocPrivate;
- *ppix++ = pixel;
- ent->fShared = FALSE;
- }
- *pMask = 0;
- return (TRUE);
- }
- else if (planes > dplanes) {
- return (FALSE);
- }
- /* General case count pixels * 2 ^ planes cells to be allocated */
- /* make room for new pixels */
- ent = pentFirst;
- /* first try for contiguous planes, since it's fastest */
- for (mask = (((Pixel) 1) << planes) - 1, base = 1, dplanes -= (planes - 1);
- --dplanes >= 0; mask += mask, base += base) {
- ppix = pixels;
- found = 0;
- pixel = 0;
- entries = pmap->pVisual->ColormapEntries - mask;
- while (pixel < entries) {
- save = pixel;
- maxp = pixel + mask + base;
- /* check if all are free */
- while (pixel != maxp && ent[pixel].refcnt == 0)
- pixel += base;
- if (pixel == maxp) {
- /* this one works */
- *ppix++ = save;
- found++;
- if (found == count) {
- /* found enough, allocate them all */
- while (--count >= 0) {
- pixel = pixels[count];
- maxp = pixel + mask;
- while (1) {
- ent[pixel].refcnt = AllocPrivate;
- ent[pixel].fShared = FALSE;
- if (pixel == maxp)
- break;
- pixel += base;
- *ppix++ = pixel;
- }
- }
- *pMask = mask;
- return (TRUE);
- }
- }
- pixel = save + 1;
- if (pixel & mask)
- pixel += mask;
- }
- }
- dplanes = pmap->pVisual->nplanes;
- if (contig || planes == 1 || dplanes < 3)
- return (FALSE);
- /* this will be very slow for large maps, need a better algorithm */
- /*
- we can generate the smallest and largest numbers that fits in dplanes
- bits and contain exactly planes bits set as follows. First, we need to
- check that it is possible to generate such a mask at all.
- (Non-contiguous masks need one more bit than contiguous masks). Then
- the smallest such mask consists of the rightmost planes-1 bits set, then
- a zero, then a one in position planes + 1. The formula is
- (3 << (planes-1)) -1
- The largest such masks consists of the leftmost planes-1 bits set, then
- a zero, then a one bit in position dplanes-planes-1. If dplanes is
- smaller than 32 (the number of bits in a word) then the formula is:
- (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1)
- If dplanes = 32, then we can't calculate (1<<dplanes) and we have
- to use:
- ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1))
- << Thank you, Loretta>>>
- */
- finalmask =
- (((((Pixel) 1) << (planes - 1)) - 1) << (dplanes - planes + 1)) +
- (((Pixel) 1) << (dplanes - planes - 1));
- for (mask = (((Pixel) 3) << (planes - 1)) - 1; mask <= finalmask; mask++) {
- /* next 3 magic statements count number of ones (HAKMEM #169) */
- pixel = (mask >> 1) & 033333333333;
- pixel = mask - pixel - ((pixel >> 1) & 033333333333);
- if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes)
- continue;
- ppix = pixels;
- found = 0;
- entries = pmap->pVisual->ColormapEntries - mask;
- base = lowbit(mask);
- for (pixel = 0; pixel < entries; pixel++) {
- if (pixel & mask)
- continue;
- maxp = 0;
- /* check if all are free */
- while (ent[pixel + maxp].refcnt == 0) {
- GetNextBitsOrBreak(maxp, mask, base);
- }
- if ((maxp < mask) || (ent[pixel + mask].refcnt != 0))
- continue;
- /* this one works */
- *ppix++ = pixel;
- found++;
- if (found < count)
- continue;
- /* found enough, allocate them all */
- while (--count >= 0) {
- pixel = (pixels)[count];
- maxp = 0;
- while (1) {
- ent[pixel + maxp].refcnt = AllocPrivate;
- ent[pixel + maxp].fShared = FALSE;
- GetNextBitsOrBreak(maxp, mask, base);
- *ppix++ = pixel + maxp;
- }
- }
- *pMask = mask;
- return (TRUE);
- }
- }
- return (FALSE);
- }
- /**
- *
- * \param ppixFirst First of the client's new pixels
- */
- static Bool
- AllocShared(ColormapPtr pmap, Pixel * ppix, int c, int r, int g, int b,
- Pixel rmask, Pixel gmask, Pixel bmask, Pixel * ppixFirst)
- {
- Pixel *pptr, *cptr;
- int npix, z, npixClientNew, npixShared;
- Pixel basemask, base, bits, common;
- SHAREDCOLOR *pshared, **ppshared, **psharedList;
- npixClientNew = c << (r + g + b);
- npixShared = (c << r) + (c << g) + (c << b);
- psharedList = (SHAREDCOLOR **) ALLOCATE_LOCAL(npixShared *
- sizeof(SHAREDCOLOR *));
- if (!psharedList)
- return FALSE;
- ppshared = psharedList;
- for (z = npixShared; --z >= 0;) {
- if (!(ppshared[z] = malloc(sizeof(SHAREDCOLOR)))) {
- for (z++; z < npixShared; z++)
- free(ppshared[z]);
- return FALSE;
- }
- }
- for (pptr = ppix, npix = c; --npix >= 0; pptr++) {
- basemask = ~(gmask | bmask);
- common = *pptr & basemask;
- if (rmask) {
- bits = 0;
- base = lowbit(rmask);
- while (1) {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
- if ((*cptr & basemask) == (common | bits)) {
- pmap->red[*cptr].fShared = TRUE;
- pmap->red[*cptr].co.shco.red = pshared;
- }
- }
- GetNextBitsOrBreak(bits, rmask, base);
- }
- }
- else {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
- if ((*cptr & basemask) == common) {
- pmap->red[*cptr].fShared = TRUE;
- pmap->red[*cptr].co.shco.red = pshared;
- }
- }
- }
- basemask = ~(rmask | bmask);
- common = *pptr & basemask;
- if (gmask) {
- bits = 0;
- base = lowbit(gmask);
- while (1) {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (r + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
- if ((*cptr & basemask) == (common | bits)) {
- pmap->red[*cptr].co.shco.green = pshared;
- }
- }
- GetNextBitsOrBreak(bits, gmask, base);
- }
- }
- else {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
- if ((*cptr & basemask) == common) {
- pmap->red[*cptr].co.shco.green = pshared;
- }
- }
- }
- basemask = ~(rmask | gmask);
- common = *pptr & basemask;
- if (bmask) {
- bits = 0;
- base = lowbit(bmask);
- while (1) {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (r + g);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
- if ((*cptr & basemask) == (common | bits)) {
- pmap->red[*cptr].co.shco.blue = pshared;
- }
- }
- GetNextBitsOrBreak(bits, bmask, base);
- }
- }
- else {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++) {
- if ((*cptr & basemask) == common) {
- pmap->red[*cptr].co.shco.blue = pshared;
- }
- }
- }
- }
- DEALLOCATE_LOCAL(psharedList);
- return TRUE;
- }
- /** FreeColors
- * Free colors and/or cells (probably slow for large numbers)
- */
- _X_EXPORT int
- FreeColors(ColormapPtr pmap, int client, int count, Pixel * pixels, Pixel mask)
- {
- int rval, result, class;
- Pixel rmask;
- class = pmap->class;
- if (pmap->flags & AllAllocated)
- return (BadAccess);
- if ((class | DynamicClass) == DirectColor) {
- rmask = mask & RGBMASK(pmap->pVisual);
- result = FreeCo(pmap, client, REDMAP, count, pixels,
- mask & pmap->pVisual->redMask);
- /* If any of the three calls fails, we must report that, if more
- * than one fails, it's ok that we report the last one */
- rval = FreeCo(pmap, client, GREENMAP, count, pixels,
- mask & pmap->pVisual->greenMask);
- if (rval != Success)
- result = rval;
- rval = FreeCo(pmap, client, BLUEMAP, count, pixels,
- mask & pmap->pVisual->blueMask);
- if (rval != Success)
- result = rval;
- }
- else {
- rmask = mask & ((((Pixel) 1) << pmap->pVisual->nplanes) - 1);
- result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask);
- }
- if ((mask != rmask) && count) {
- clientErrorValue = *pixels | mask;
- result = BadValue;
- }
- /* XXX should worry about removing any RT_CMAPENTRY resource */
- return (result);
- }
- /**
- * Helper for FreeColors -- frees all combinations of *newpixels and mask bits
- * which the client has allocated in channel colormap cells of pmap.
- * doesn't change newpixels if it doesn't need to
- *
- * \param pmap which colormap head
- * \param color which sub-map, eg, RED, BLUE, PSEUDO
- * \param npixIn number of pixels passed in
- * \param ppixIn number of base pixels
- * \param mask mask client gave us
- */
- static int
- FreeCo(ColormapPtr pmap, int client, int color, int npixIn, Pixel * ppixIn,
- Pixel mask)
- {
- Pixel *ppixClient, pixTest;
- int npixClient, npixNew, npix;
- Pixel bits, base, cmask, rgbbad;
- Pixel *pptr, *cptr;
- int n, zapped;
- int errVal = Success;
- int offset, numents;
- if (npixIn == 0)
- return (errVal);
- bits = 0;
- zapped = 0;
- base = lowbit(mask);
- switch (color) {
- case REDMAP:
- cmask = pmap->pVisual->redMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetRed;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsRed[client];
- npixClient = pmap->numPixelsRed[client];
- break;
- case GREENMAP:
- cmask = pmap->pVisual->greenMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetGreen;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsGreen[client];
- npixClient = pmap->numPixelsGreen[client];
- break;
- case BLUEMAP:
- cmask = pmap->pVisual->blueMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetBlue;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsBlue[client];
- npixClient = pmap->numPixelsBlue[client];
- break;
- default: /* so compiler can see that everything gets initialized */
- case PSEUDOMAP:
- cmask = ~((Pixel) 0);
- rgbbad = 0;
- offset = 0;
- numents = pmap->pVisual->ColormapEntries;
- ppixClient = pmap->clientPixelsRed[client];
- npixClient = pmap->numPixelsRed[client];
- break;
- }
- /* zap all pixels which match */
- while (1) {
- /* go through pixel list */
- for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++) {
- pixTest = ((*pptr | bits) & cmask) >> offset;
- if ((pixTest >= numents) || (*pptr & rgbbad)) {
- clientErrorValue = *pptr | bits;
- errVal = BadValue;
- continue;
- }
- /* find match in client list */
- for (cptr = ppixClient, npix = npixClient;
- --npix >= 0 && *cptr != pixTest; cptr++);
- if (npix >= 0) {
- if (pmap->class & DynamicClass) {
- FreeCell(pmap, pixTest, color);
- }
- *cptr = ~((Pixel) 0);
- zapped++;
- }
- else
- errVal = BadAccess;
- }
- /* generate next bits value */
- GetNextBitsOrBreak(bits, mask, base);
- }
- /* delete freed pixels from client pixel list */
- if (zapped) {
- npixNew = npixClient - zapped;
- if (npixNew) {
- /* Since the list can only get smaller, we can do a copy in
- * place and then realloc to a smaller size */
- pptr = cptr = ppixClient;
- /* If we have all the new pixels, we don't have to examine the
- * rest of the old ones */
- for (npix = 0; npix < npixNew; cptr++) {
- if (*cptr != ~((Pixel) 0)) {
- *pptr++ = *cptr;
- npix++;
- }
- }
- pptr = (Pixel *) realloc(ppixClient, npixNew * sizeof(Pixel));
- if (pptr)
- ppixClient = pptr;
- npixClient = npixNew;
- }
- else {
- npixClient = 0;
- free(ppixClient);
- ppixClient = (Pixel *) NULL;
- }
- switch (color) {
- case PSEUDOMAP:
- case REDMAP:
- pmap->clientPixelsRed[client] = ppixClient;
- pmap->numPixelsRed[client] = npixClient;
- break;
- case GREENMAP:
- pmap->clientPixelsGreen[client] = ppixClient;
- pmap->numPixelsGreen[client] = npixClient;
- break;
- case BLUEMAP:
- pmap->clientPixelsBlue[client] = ppixClient;
- pmap->numPixelsBlue[client] = npixClient;
- break;
- }
- }
- return (errVal);
- }
- /* Redefine color values */
- _X_EXPORT int
- StoreColors(ColormapPtr pmap, int count, xColorItem * defs)
- {
- Pixel pix;
- xColorItem *pdef;
- EntryPtr pent, pentT, pentLast;
- VisualPtr pVisual;
- SHAREDCOLOR *pred, *pgreen, *pblue;
- int n, ChgRed, ChgGreen, ChgBlue, idef;
- int class, errVal = Success;
- int ok;
- class = pmap->class;
- if (!(class & DynamicClass) && !(pmap->flags & BeingCreated)) {
- return (BadAccess);
- }
- pVisual = pmap->pVisual;
- idef = 0;
- if ((class | DynamicClass) == DirectColor) {
- int numred, numgreen, numblue;
- Pixel rgbbad;
- numred = NUMRED(pVisual);
- numgreen = NUMGREEN(pVisual);
- numblue = NUMBLUE(pVisual);
- rgbbad = ~RGBMASK(pVisual);
- for (pdef = defs, n = 0; n < count; pdef++, n++) {
- ok = TRUE;
- (*pmap->pScreen->ResolveColor)
- (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
- if (pdef->pixel & rgbbad) {
- errVal = BadValue;
- clientErrorValue = pdef->pixel;
- continue;
- }
- pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed;
- if (pix >= numred) {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->red[pix].refcnt != AllocPrivate) {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoRed) {
- pmap->red[pix].co.local.red = pdef->red;
- }
- else {
- pdef->red = pmap->red[pix].co.local.red;
- }
- pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- if (pix >= numgreen) {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->green[pix].refcnt != AllocPrivate) {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoGreen) {
- pmap->green[pix].co.local.green = pdef->green;
- }
- else {
- pdef->green = pmap->green[pix].co.local.green;
- }
- pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (pix >= numblue) {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->blue[pix].refcnt != AllocPrivate) {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoBlue) {
- pmap->blue[pix].co.local.blue = pdef->blue;
- }
- else {
- pdef->blue = pmap->blue[pix].co.local.blue;
- }
- /* If this is an o.k. entry, then it gets added to the list
- * to be sent to the hardware. If not, skip it. Once we've
- * skipped one, we have to copy all the others.
- */
- if (ok) {
- if (idef != n)
- defs[idef] = defs[n];
- idef++;
- }
- else
- clientErrorValue = pdef->pixel;
- }
- }
- else {
- for (pdef = defs, n = 0; n < count; pdef++, n++) {
- ok = TRUE;
- if (pdef->pixel >= pVisual->ColormapEntries) {
- clientErrorValue = pdef->pixel;
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->red[pdef->pixel].refcnt != AllocPrivate) {
- errVal = BadAccess;
- ok = FALSE;
- }
- /* If this is an o.k. entry, then it gets added to the list
- * to be sent to the hardware. If not, skip it. Once we've
- * skipped one, we have to copy all the others.
- */
- if (ok) {
- if (idef != n)
- defs[idef] = defs[n];
- idef++;
- }
- else
- continue;
- (*pmap->pScreen->ResolveColor)
- (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
- pent = &pmap->red[pdef->pixel];
- if (pdef->flags & DoRed) {
- if (pent->fShared) {
- pent->co.shco.red->color = pdef->red;
- if (pent->co.shco.red->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.red = pdef->red;
- }
- else {
- if (pent->fShared)
- pdef->red = pent->co.shco.red->color;
- else
- pdef->red = pent->co.local.red;
- }
- if (pdef->flags & DoGreen) {
- if (pent->fShared) {
- pent->co.shco.green->color = pdef->green;
- if (pent->co.shco.green->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.green = pdef->green;
- }
- else {
- if (pent->fShared)
- pdef->green = pent->co.shco.green->color;
- else
- pdef->green = pent->co.local.green;
- }
- if (pdef->flags & DoBlue) {
- if (pent->fShared) {
- pent->co.shco.blue->color = pdef->blue;
- if (pent->co.shco.blue->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.blue = pdef->blue;
- }
- else {
- if (pent->fShared)
- pdef->blue = pent->co.shco.blue->color;
- else
- pdef->blue = pent->co.local.blue;
- }
- if (!ok) {
- /* have to run through the colormap and change anybody who
- * shares this value */
- pred = pent->co.shco.red;
- pgreen = pent->co.shco.green;
- pblue = pent->co.shco.blue;
- ChgRed = pdef->flags & DoRed;
- ChgGreen = pdef->flags & DoGreen;
- ChgBlue = pdef->flags & DoBlue;
- pentLast = pmap->red + pVisual->ColormapEntries;
- for (pentT = pmap->red; pentT < pentLast; pentT++) {
- if (pentT->fShared && (pentT != pent)) {
- xColorItem defChg;
- /* There are, alas, devices in this world too dumb
- * to read their own hardware colormaps. Sick, but
- * true. So we're going to be really nice and load
- * the xColorItem with the proper value for all the
- * fields. We will only set the flags for those
- * fields that actually change. Smart devices can
- * arrange to change only those fields. Dumb devices
- * can rest assured that we have provided for them,
- * and can change all three fields */
- defChg.flags = 0;
- if (ChgRed && pentT->co.shco.red == pred) {
- defChg.flags |= DoRed;
- }
- if (ChgGreen && pentT->co.shco.green == pgreen) {
- defChg.flags |= DoGreen;
- }
- if (ChgBlue && pentT->co.shco.blue == pblue) {
- defChg.flags |= DoBlue;
- }
- if (defChg.flags != 0) {
- defChg.pixel = pentT - pmap->red;
- defChg.red = pentT->co.shco.red->color;
- defChg.green = pentT->co.shco.green->color;
- defChg.blue = pentT->co.shco.blue->color;
- (*pmap->pScreen->StoreColors) (pmap, 1, &defChg);
- }
- }
- }
- }
- }
- }
- /* Note that we use idef, the count of acceptable entries, and not
- * count, the count of proposed entries */
- if (idef != 0)
- (*pmap->pScreen->StoreColors) (pmap, idef, defs);
- return (errVal);
- }
- int
- IsMapInstalled(Colormap map, WindowPtr pWin)
- {
- Colormap *pmaps;
- int imap, nummaps, found;
- pmaps =
- (Colormap *) ALLOCATE_LOCAL(pWin->drawable.pScreen->maxInstalledCmaps *
- sizeof(Colormap));
- if (!pmaps)
- return (FALSE);
- nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
- (pWin->drawable.pScreen, pmaps);
- found = FALSE;
- for (imap = 0; imap < nummaps; imap++) {
- if (pmaps[imap] == map) {
- found = TRUE;
- break;
- }
- }
- DEALLOCATE_LOCAL(pmaps);
- return (found);
- }
|