123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- /*
- *
- * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #ifndef _MIINDEX_H_
- #define _MIINDEX_H_
- #include "scrnintstr.h"
- #include "gcstruct.h"
- #include "pixmapstr.h"
- #include "windowstr.h"
- #include "mi.h"
- #include "picturestr.h"
- #include "mipict.h"
- #include "colormapst.h"
- #define NUM_CUBE_LEVELS 4
- #define NUM_GRAY_LEVELS 13
- static Bool
- miBuildRenderColormap(ColormapPtr pColormap, Pixel * pixels, int *nump)
- {
- int r, g, b;
- unsigned short red, green, blue;
- Pixel pixel;
- Bool used[MI_MAX_INDEXED];
- int needed;
- int policy;
- int cube, gray;
- int i, n;
- if (pColormap->mid != pColormap->pScreen->defColormap) {
- policy = PictureCmapPolicyAll;
- }
- else {
- int avail = pColormap->pVisual->ColormapEntries;
- policy = PictureCmapPolicy;
- if (policy == PictureCmapPolicyDefault) {
- if (avail >= 256 &&
- (pColormap->pVisual->class | DynamicClass) == PseudoColor)
- policy = PictureCmapPolicyColor;
- else if (avail >= 64)
- policy = PictureCmapPolicyGray;
- else
- policy = PictureCmapPolicyMono;
- }
- }
- /*
- * Make sure enough cells are free for the chosen policy
- */
- for (;;) {
- switch (policy) {
- case PictureCmapPolicyAll:
- needed = 0;
- break;
- case PictureCmapPolicyColor:
- needed = 71;
- break;
- case PictureCmapPolicyGray:
- needed = 11;
- break;
- case PictureCmapPolicyMono:
- default:
- needed = 0;
- break;
- }
- if (needed <= pColormap->freeRed)
- break;
- policy--;
- }
- /*
- * Compute size of cube and gray ramps
- */
- cube = gray = 0;
- switch (policy) {
- case PictureCmapPolicyAll:
- /*
- * Allocate as big a cube as possible
- */
- if ((pColormap->pVisual->class | DynamicClass) == PseudoColor) {
- for (cube = 1;
- cube * cube * cube < pColormap->pVisual->ColormapEntries;
- cube++);
- cube--;
- if (cube == 1)
- cube = 0;
- }
- else
- cube = 0;
- /*
- * Figure out how many gray levels to use so that they
- * line up neatly with the cube
- */
- if (cube) {
- needed = pColormap->pVisual->ColormapEntries - (cube * cube * cube);
- /* levels to fill in with */
- gray = needed / (cube - 1);
- /* total levels */
- gray = (gray + 1) * (cube - 1) + 1;
- }
- else
- gray = pColormap->pVisual->ColormapEntries;
- break;
- case PictureCmapPolicyColor:
- cube = NUM_CUBE_LEVELS;
- /* fall through ... */
- case PictureCmapPolicyGray:
- gray = NUM_GRAY_LEVELS;
- break;
- case PictureCmapPolicyMono:
- default:
- gray = 2;
- break;
- }
- memset(used, '\0', pColormap->pVisual->ColormapEntries * sizeof(Bool));
- for (r = 0; r < cube; r++)
- for (g = 0; g < cube; g++)
- for (b = 0; b < cube; b++) {
- pixel = 0;
- red = (r * 65535 + (cube - 1) / 2) / (cube - 1);
- green = (g * 65535 + (cube - 1) / 2) / (cube - 1);
- blue = (b * 65535 + (cube - 1) / 2) / (cube - 1);
- if (AllocColor(pColormap, &red, &green,
- &blue, &pixel, 0) != Success)
- return FALSE;
- used[pixel] = TRUE;
- }
- for (g = 0; g < gray; g++) {
- pixel = 0;
- red = green = blue = (g * 65535 + (gray - 1) / 2) / (gray - 1);
- if (AllocColor(pColormap, &red, &green, &blue, &pixel, 0) != Success)
- return FALSE;
- used[pixel] = TRUE;
- }
- n = 0;
- for (i = 0; i < pColormap->pVisual->ColormapEntries; i++)
- if (used[i])
- pixels[n++] = i;
- *nump = n;
- return TRUE;
- }
- /* 0 <= red, green, blue < 32 */
- static Pixel
- FindBestColor(miIndexedPtr pIndexed, Pixel * pixels, int num,
- int red, int green, int blue)
- {
- Pixel best = pixels[0];
- int bestDist = 1 << 30;
- int dist;
- int dr, dg, db;
- while (num--) {
- Pixel pixel = *pixels++;
- CARD32 v = pIndexed->rgba[pixel];
- dr = ((v >> 19) & 0x1f);
- dg = ((v >> 11) & 0x1f);
- db = ((v >> 3) & 0x1f);
- dr = dr - red;
- dg = dg - green;
- db = db - blue;
- dist = dr * dr + dg * dg + db * db;
- if (dist < bestDist) {
- bestDist = dist;
- best = pixel;
- }
- }
- return best;
- }
- /* 0 <= gray < 32768 */
- static Pixel
- FindBestGray(miIndexedPtr pIndexed, Pixel * pixels, int num, int gray)
- {
- Pixel best = pixels[0];
- int bestDist = 1 << 30;
- int dist;
- int dr;
- int r;
- while (num--) {
- Pixel pixel = *pixels++;
- CARD32 v = pIndexed->rgba[pixel];
- r = v & 0xff;
- r = r | (r << 8);
- dr = gray - (r >> 1);
- dist = dr * dr;
- if (dist < bestDist) {
- bestDist = dist;
- best = pixel;
- }
- }
- return best;
- }
- Bool
- miInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
- {
- ColormapPtr pColormap = pFormat->index.pColormap;
- VisualPtr pVisual = pColormap->pVisual;
- miIndexedPtr pIndexed;
- Pixel pixels[MI_MAX_INDEXED];
- xrgb rgb[MI_MAX_INDEXED];
- int num = 0;
- int i;
- Pixel p, r, g, b;
- if (pVisual->ColormapEntries > MI_MAX_INDEXED)
- return FALSE;
- if (pVisual->class & DynamicClass) {
- if (!miBuildRenderColormap(pColormap, pixels, &num))
- return FALSE;
- }
- else {
- num = pVisual->ColormapEntries;
- for (p = 0; p < num; p++)
- pixels[p] = p;
- }
- pIndexed = malloc(sizeof(miIndexedRec));
- if (!pIndexed)
- return FALSE;
- pFormat->index.nvalues = num;
- pFormat->index.pValues = malloc(num * sizeof(xIndexValue));
- if (!pFormat->index.pValues || !num) {
- free(pIndexed);
- return FALSE;
- }
- /*
- * Build mapping from pixel value to ARGB
- */
- QueryColors(pColormap, num, pixels, rgb);
- for (i = 0; i < num; i++) {
- p = pixels[i];
- pFormat->index.pValues[i].pixel = p;
- pFormat->index.pValues[i].red = rgb[i].red;
- pFormat->index.pValues[i].green = rgb[i].green;
- pFormat->index.pValues[i].blue = rgb[i].blue;
- pFormat->index.pValues[i].alpha = 0xffff;
- pIndexed->rgba[p] = (0xff000000 |
- ((rgb[i].red & 0xff00) << 8) |
- ((rgb[i].green & 0xff00)) |
- ((rgb[i].blue & 0xff00) >> 8));
- }
- /*
- * Build mapping from RGB to pixel value. This could probably be
- * done a bit quicker...
- */
- switch (pVisual->class | DynamicClass) {
- case GrayScale:
- pIndexed->color = FALSE;
- for (r = 0; r < 32768; r++)
- pIndexed->ent[r] = FindBestGray(pIndexed, pixels, num, r);
- break;
- case PseudoColor:
- pIndexed->color = TRUE;
- p = 0;
- for (r = 0; r < 32; r++)
- for (g = 0; g < 32; g++)
- for (b = 0; b < 32; b++) {
- pIndexed->ent[p] = FindBestColor(pIndexed, pixels, num,
- r, g, b);
- p++;
- }
- break;
- }
- pFormat->index.devPrivate = pIndexed;
- return TRUE;
- }
- void
- miCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
- {
- if (pFormat->index.devPrivate) {
- free(pFormat->index.devPrivate);
- pFormat->index.devPrivate = 0;
- }
- if (pFormat->index.pValues) {
- free(pFormat->index.pValues);
- pFormat->index.pValues = 0;
- }
- }
- void
- miUpdateIndexed(ScreenPtr pScreen,
- PictFormatPtr pFormat, int ndef, xColorItem * pdef)
- {
- miIndexedPtr pIndexed = pFormat->index.devPrivate;
- if (pIndexed) {
- while (ndef--) {
- pIndexed->rgba[pdef->pixel] = (0xff000000 |
- ((pdef->red & 0xff00) << 8) |
- ((pdef->green & 0xff00)) |
- ((pdef->blue & 0xff00) >> 8));
- pdef++;
- }
- }
- }
- #endif /* _MIINDEX_H_ */
|