diff options
Diffstat (limited to 'krdc/vnc/colour.c')
-rw-r--r-- | krdc/vnc/colour.c | 415 |
1 files changed, 0 insertions, 415 deletions
diff --git a/krdc/vnc/colour.c b/krdc/vnc/colour.c deleted file mode 100644 index 06af4fd3..00000000 --- a/krdc/vnc/colour.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. - * - * This is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this software; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - */ - -/* - * colour.c - functions to deal with colour - i.e. RFB pixel formats, X visuals - * and colormaps. Thanks to Grant McDorman for some of the ideas used here. - */ - -#include "vncviewer.h" -#include <limits.h> - - -#define INVALID_PIXEL 0xffffffff -#define MAX_CMAP_SIZE 256 -#define BGR233_SIZE 256 -unsigned long BGR233ToPixel[BGR233_SIZE]; - -Colormap cmap; -Visual *vis; -unsigned int visdepth, visbpp; -Bool allocColorFailed = False; - -static int nBGR233ColoursAllocated; - -static int GetBPPForDepth(int depth); -static void SetupBGR233Map(void); -static void AllocateExactBGR233Colours(void); -static Bool AllocateBGR233Colour(int r, int g, int b); - - -/* - * SetVisualAndCmap() deals with the wonderful world of X "visuals" (which are - * equivalent to the RFB protocol's "pixel format"). Having decided on the - * best visual, it also creates a colormap if necessary, sets the appropriate - * resources on the toplevel widget, and sets up the myFormat structure to - * describe the pixel format in terms that the RFB server will be able to - * understand. - * - * The algorithm for deciding which visual to use is as follows: - * - * If forceOwnCmap is true then we try to use a PseudoColor visual - we first - * see if there's one of the same depth as the RFB server, followed by an 8-bit - * deep one. - * - * If forceTrueColour is true then we try to use a TrueColor visual - if - * requestedDepth is set then it must be of that depth, otherwise any depth - * will be used. - * - * Otherwise, we use the X server's default visual and colormap. If this is - * TrueColor then we just ask the RFB server for this format. If the default - * isn't TrueColor, or if useBGR233 is true, then we ask the RFB server for - * BGR233 pixel format and use a lookup table to translate to the nearest - * colours provided by the X server. - */ - -void -SetVisualAndCmap() -{ - /* just use default visual and colormap */ - - vis = DefaultVisual(dpy,DefaultScreen(dpy)); - visdepth = DefaultDepth(dpy,DefaultScreen(dpy)); - visbpp = GetBPPForDepth(visdepth); - cmap = DefaultColormap(dpy,DefaultScreen(dpy)); - - if (!appData.useBGR233 && (vis->class == TrueColor)) { - - myFormat.bitsPerPixel = visbpp; - myFormat.depth = visdepth; - myFormat.trueColour = 1; - myFormat.bigEndian = (ImageByteOrder(dpy) == MSBFirst); - myFormat.redShift = ffs(vis->red_mask) - 1; - myFormat.greenShift = ffs(vis->green_mask) - 1; - myFormat.blueShift = ffs(vis->blue_mask) - 1; - myFormat.redMax = vis->red_mask >> myFormat.redShift; - myFormat.greenMax = vis->green_mask >> myFormat.greenShift; - myFormat.blueMax = vis->blue_mask >> myFormat.blueShift; - - fprintf(stderr, - "Using default colormap which is TrueColor. Pixel format:\n"); - PrintPixelFormat(&myFormat); - return; - } - - appData.useBGR233 = True; - - myFormat.bitsPerPixel = 8; - myFormat.depth = 8; - myFormat.trueColour = 1; - myFormat.bigEndian = 0; - myFormat.redMax = 7; - myFormat.greenMax = 7; - myFormat.blueMax = 3; - myFormat.redShift = 0; - myFormat.greenShift = 3; - myFormat.blueShift = 6; - - fprintf(stderr, - "Using default colormap and translating from BGR233. Pixel format:\n"); - PrintPixelFormat(&myFormat); - - SetupBGR233Map(); -} - - -/* - * GetBPPForDepth looks through the "pixmap formats" to find the bits-per-pixel - * for the given depth. - */ - -static int -GetBPPForDepth(int depth) -{ - XPixmapFormatValues *format; - int nformats; - int i; - int bpp; - - format = XListPixmapFormats(dpy, &nformats); - - for (i = 0; i < nformats; i++) { - if (format[i].depth == depth) - break; - } - - if (i == nformats) { - fprintf(stderr,"no pixmap format for depth %d???\n", depth); - exit(1); - } - - bpp = format[i].bits_per_pixel; - - XFree(format); - - if (bpp != 1 && bpp != 8 && bpp != 16 && bpp != 32) { - fprintf(stderr,"Can't cope with %d bits-per-pixel. Sorry.\n", bpp); - exit(1); - } - - return bpp; -} - - - -/* - * SetupBGR233Map() sets up the BGR233ToPixel array. - * - * It calls AllocateExactBGR233Colours to allocate some exact BGR233 colours - * (limited by space in the colormap and/or by the value of the nColours - * resource). If the number allocated is less than BGR233_SIZE then it fills - * the rest in using the "nearest" colours available. How this is done depends - * on the value of the useSharedColours resource. If it's false, we use only - * colours from the exact BGR233 colours we've just allocated. If it's true, - * then we also use other clients' "shared" colours available in the colormap. - */ - -static void -SetupBGR233Map(void) -{ - int r, g, b; - long i; - unsigned long nearestPixel = 0; - int cmapSize; - XColor cmapEntry[MAX_CMAP_SIZE]; - Bool exactBGR233[MAX_CMAP_SIZE]; - Bool shared[MAX_CMAP_SIZE]; - Bool usedAsNearest[MAX_CMAP_SIZE]; - int nSharedUsed = 0; - - if (visdepth > 8) { - appData.nColours = 256; /* ignore nColours setting for > 8-bit deep */ - } - - for (i = 0; i < BGR233_SIZE; i++) { - BGR233ToPixel[i] = INVALID_PIXEL; - } - - AllocateExactBGR233Colours(); - - fprintf(stderr,"Got %d exact BGR233 colours out of %d\n", - nBGR233ColoursAllocated, appData.nColours); - - if (nBGR233ColoursAllocated < BGR233_SIZE) { - - if (visdepth > 8) { /* shouldn't get here */ - fprintf(stderr,"Error: couldn't allocate BGR233 colours even though " - "depth is %d\n", visdepth); - exit(1); - } - - cmapSize = (1 << visdepth); - - for (i = 0; i < cmapSize; i++) { - cmapEntry[i].pixel = i; - exactBGR233[i] = False; - shared[i] = False; - usedAsNearest[i] = False; - } - - XQueryColors(dpy, cmap, cmapEntry, cmapSize); - - /* mark all our exact BGR233 pixels */ - - for (i = 0; i < BGR233_SIZE; i++) { - if (BGR233ToPixel[i] != INVALID_PIXEL) - exactBGR233[BGR233ToPixel[i]] = True; - } - - if (appData.useSharedColours) { - - /* Try to find existing shared colours. This is harder than it sounds - because XQueryColors doesn't tell us whether colours are shared, - private or unallocated. What we do is go through the colormap and for - each pixel try to allocate exactly its RGB values. If this returns a - different pixel then it's definitely either a private or unallocated - pixel, so no use to us. If it returns us the same pixel again, then - it's likely that it's a shared colour - however, it is possible that - it was actually an unallocated pixel, which we've now allocated. We - minimise this possibility by going through the pixels in reverse order - - this helps becuse the X server allocates new pixels from the lowest - number up, so it should only be a problem for the lowest unallocated - pixel. Got that? */ - - for (i = cmapSize-1; i >= 0; i--) { - if (!exactBGR233[i] && - XAllocColor(dpy, cmap, &cmapEntry[i])) { - - if (cmapEntry[i].pixel == (unsigned long) i) { - - shared[i] = True; /* probably shared */ - - } else { - - /* "i" is either unallocated or private. We have now unnecessarily - allocated cmapEntry[i].pixel. Free it. */ - - XFreeColors(dpy, cmap, &cmapEntry[i].pixel, 1, 0); - } - } - } - } - - /* Now fill in the nearest colours */ - - for (r = 0; r < 8; r++) { - for (g = 0; g < 8; g++) { - for (b = 0; b < 4; b++) { - if (BGR233ToPixel[(b<<6) | (g<<3) | r] == INVALID_PIXEL) { - - unsigned long minDistance = ULONG_MAX; - - for (i = 0; i < cmapSize; i++) { - if (exactBGR233[i] || shared[i]) { - unsigned long distance - = (abs(cmapEntry[i].red - r * 65535 / 7) - + abs(cmapEntry[i].green - g * 65535 / 7) - + abs(cmapEntry[i].blue - b * 65535 / 3)); - - if (distance < minDistance) { - minDistance = distance; - nearestPixel = i; - } - } - } - - BGR233ToPixel[(b<<6) | (g<<3) | r] = nearestPixel; - if (shared[nearestPixel] && !usedAsNearest[nearestPixel]) - nSharedUsed++; - usedAsNearest[nearestPixel] = True; - } - } - } - } - - /* Tidy up shared colours which we allocated but aren't going to use */ - - for (i = 0; i < cmapSize; i++) { - if (shared[i] && !usedAsNearest[i]) { - XFreeColors(dpy, cmap, (unsigned long *)&i, 1, 0); - } - } - - fprintf(stderr,"Using %d existing shared colours\n", nSharedUsed); - } -} - - -/* - * AllocateExactBGR233Colours() attempts to allocate each of the colours in the - * BGR233 colour cube, stopping when an allocation fails. The order it does - * this in is such that we should get a fairly well spread subset of the cube, - * however many allocations are made. There's probably a neater algorithm for - * doing this, but it's not obvious to me anyway. The way this algorithm works - * is: - * - * At each stage, we introduce a new value for one of the primaries, and - * allocate all the colours with the new value of that primary and all previous - * values of the other two primaries. We start with r=0 as the "new" value - * for r, and g=0, b=0 as the "previous" values of g and b. So we get: - * - * New primary value Previous values of other primaries Colours allocated - * ----------------- ---------------------------------- ----------------- - * r=0 g=0 b=0 r0 g0 b0 - * g=7 r=0 b=0 r0 g7 b0 - * b=3 r=0 g=0,7 r0 g0 b3 - * r0 g7 b3 - * r=7 g=0,7 b=0,3 r7 g0 b0 - * r7 g0 b3 - * r7 g7 b0 - * r7 g7 b3 - * g=3 r=0,7 b=0,3 r0 g3 b0 - * r0 g3 b3 - * r7 g3 b0 - * r7 g3 b3 - * ....etc. - * */ - -static void -AllocateExactBGR233Colours(void) -{ - int rv[] = {0,7,3,5,1,6,2,4}; - int gv[] = {0,7,3,5,1,6,2,4}; - int bv[] = {0,3,1,2}; - int rn = 0; - int gn = 1; - int bn = 1; - int ri, gi, bi; - - nBGR233ColoursAllocated = 0; - - while (1) { - if (rn == 8) - break; - - ri = rn; - for (gi = 0; gi < gn; gi++) { - for (bi = 0; bi < bn; bi++) { - if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) - return; - } - } - rn++; - - if (gn == 8) - break; - - gi = gn; - for (ri = 0; ri < rn; ri++) { - for (bi = 0; bi < bn; bi++) { - if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) - return; - } - } - gn++; - - if (bn < 4) { - - bi = bn; - for (ri = 0; ri < rn; ri++) { - for (gi = 0; gi < gn; gi++) { - if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi])) - return; - } - } - bn++; - } - } -} - - -/* - * AllocateBGR233Colour() attempts to allocate the given BGR233 colour as a - * shared colormap entry, storing its pixel value in the BGR233ToPixel array. - * r is from 0 to 7, g from 0 to 7 and b from 0 to 3. It fails either when the - * allocation fails or when we would exceed the number of colours specified in - * the nColours resource. - */ - -static Bool -AllocateBGR233Colour(int r, int g, int b) -{ - XColor c; - - if (nBGR233ColoursAllocated >= appData.nColours) - return False; - - c.red = r * 65535 / 7; - c.green = g * 65535 / 7; - c.blue = b * 65535 / 3; - - if (!XAllocColor(dpy, cmap, &c)) - return False; - - BGR233ToPixel[(b<<6) | (g<<3) | r] = c.pixel; - - nBGR233ColoursAllocated++; - - return True; -} |