This is xttools.c in view mode; [Download] [Up]
/* xttools - Color conversion routines and other low-level X support Copyright (C) 1995 Free Software Foundation, Inc. Written by: Adam Fedor <fedor@boulder.colorado.edu> Date: Nov 1994 This file is part of the GNU Objective C User Interface Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <stdlib.h> #include <X11/Xatom.h> #include "xttools.h" #include "appkit/stdmacros.h" #define XW_STD_COLORMAP_STR "XWStdColormap" #define XW_GRAY_COLORMAP_STR "XWGrayColormap" #define XW_RGB_COLORMAP_STR "XWRGBColormap" /* static Atom XW_GRAY_COLORMAP = 0; static Atom XW_RGB_COLORMAP = 0; */ /* Right now we define the colormaps to be X default colormaps, since maybe the window manager might actually have one of these */ static Atom XW_GRAY_COLORMAP = XA_RGB_GRAY_MAP; static Atom XW_RGB_COLORMAP = XA_RGB_BEST_MAP; static Atom XW_STD_COLORMAP = 0; static void xtInitAtoms(XWContext context) { if (XW_GRAY_COLORMAP == 0) { XW_GRAY_COLORMAP = XInternAtom(context->display, XW_GRAY_COLORMAP_STR, 0); XW_RGB_COLORMAP = XInternAtom(context->display, XW_RGB_COLORMAP_STR, 0); } } /* Maintaining and using colormaps */ int xtSetGrayColormap(XWContext context, XStandardColormap *stdmap, unsigned long *cells, unsigned int colors) { int i; XColor color; for (i=0; i < colors; i++) { /* Careful to scale color from 0 to 65536 */ color.red = color.green = color.blue = i * 256 * (256.0 / colors); color.flags = DoRed | DoGreen | DoBlue; if (cells) color.pixel = cells[i]; else color.pixel = i; XStoreColor(context->display, stdmap->colormap, &color); } stdmap->red_max = colors - 1; stdmap->red_mult = 1; stdmap->green_max = 0; stdmap->green_mult = 0; stdmap->blue_max = 0; stdmap->blue_mult = 0; stdmap->base_pixel = 0; if (cells) stdmap->base_pixel = cells[0]; return 0; } /* Not implemented. FIXME */ int xtSetRGBColormap(XWContext context, XStandardColormap *stdmap, unsigned long *cells, unsigned int colors) { return 0; } /* Given a mask, find the minimum value where (number & mask) != 0 */ unsigned long mask_min(unsigned long mask) { unsigned long number = 1; if (mask == 0) return 0; while ((number & mask) == 0) number = (number << 1L); return number; } /* Gets and or creates a standard colormap for the visual type of the display. On some displays, there is no need for a color map, so we just store the characteristics of the display. On PseudoColor displays we try to allocate as many colors as possible in a shared colormap. If no colors are availible, use the default Black/White pixel. Use (or will use) the following hints: NSStdColormap - (best or gray) will look for the specified standard colomap and use it instead of creating a colormap. NSMaxColors - Will allocate less than the specified number of colors. NSPrivateColormap - Will allocate a private map if needed. */ XStandardColormap * xtDefaultColormap(XWContext context) { int i, map_count; unsigned int colors; unsigned long *cells; XStandardColormap *stdmap; int NSMaxColors, NSPrivateColormap; if (context->map) return context->map; /* Did the window manager already create a colormap for us? */ xtInitAtoms(context); if (XW_STD_COLORMAP == 0) { const char *NSStdColormap = getenv("COLORMAP"); if (NSStdColormap && NSStdColormap[0] == 'b') XW_STD_COLORMAP = XW_RGB_COLORMAP; else if (NSStdColormap && NSStdColormap[0] == 'g') XW_STD_COLORMAP = XW_GRAY_COLORMAP; else if (context->vinfo.class == DirectColor || context->vinfo.class == TrueColor) XW_STD_COLORMAP = XW_RGB_COLORMAP; else XW_STD_COLORMAP = XW_GRAY_COLORMAP; } i = XGetRGBColormaps(context->display, DefaultRootWindow(context->display), &stdmap, &map_count, XW_STD_COLORMAP); if (i) { context->map = stdmap; return stdmap; } /* Didn't find the standard map, create our own */ NX_MALLOC(stdmap, XStandardColormap, 1); /* Note: in many cases we just set stdmap->colormap to 0, since this is only needed to tell the Window which colormap to install, if colormap == 0, then we're using the DefaultColormap, and there is no need to install it. */ if (context->vinfo.class == DirectColor || context->vinfo.class == TrueColor) { stdmap->colormap = 0; stdmap->red_mult = mask_min(context->vinfo.red_mask); stdmap->red_max = context->vinfo.red_mask / stdmap->red_mult; stdmap->green_mult = mask_min(context->vinfo.green_mask); stdmap->green_max = context->vinfo.green_mask / stdmap->green_mult; stdmap->blue_mult = mask_min(context->vinfo.blue_mask); stdmap->blue_max = context->vinfo.blue_mask / stdmap->blue_mult; stdmap->base_pixel = 0; context->map = stdmap; return stdmap; } else if (context->vinfo.class == StaticGray) { stdmap->colormap = 0; stdmap->red_max = context->vinfo.colormap_size - 1; stdmap->red_mult = 1; stdmap->green_max = 0; stdmap->green_mult = 0; stdmap->blue_max = 0; stdmap->blue_mult = 0; stdmap->base_pixel = 0; context->map = stdmap; return stdmap; } /* How do you figure out the colormap structure for StaticColor? Punt */ /* FIXME */ if (context->vinfo.class == StaticColor) { fprintf(stderr, "Error (xttools): Can't determine colormap for StaticColor displays\n"); return NULL; } /* Only thing left is PseudoColor and GrayScale, which can be handled the same */ if (context->vinfo.class != PseudoColor && context->vinfo.class != GrayScale) { fprintf(stderr, "Error (xttools): Unknown visual class \n"); return NULL; } /* FIXME: Get these defaults */ NSMaxColors = context->vinfo.colormap_size - 8; NSPrivateColormap = 0; colors = NSMaxColors; stdmap->colormap = DefaultColormap(context->display, DefaultScreen(context->display)); i = 0; while (i == 0 && colors >= 4) { NX_MALLOC(cells, unsigned long, colors); i = XAllocColorCells(context->display, stdmap->colormap, TRUE, NULL, 0, cells, colors); if (i == 0) { NX_FREE(cells); cells = NULL; colors = colors - 4; } } if (i == 0) { NX_FREE(cells); cells = NULL; if (NSPrivateColormap) { fprintf(stderr, "Warning (xttools): No colors available, creating private map\n"); colors = NSMaxColors; stdmap->colormap = XCreateColormap(context->display, DefaultRootWindow(context->display), context->vinfo.visual, AllocAll); } else { fprintf(stderr, "Warning (xttools): No colors available, using standard BlackPixel/WhitePixel\n"); context->map = NULL; return NULL; } } else if (colors < 64) fprintf(stderr, "Warning: (xttools): Degraded colormap, only %d colors\n", colors); /* Now set up the cells */ if (XW_STD_COLORMAP == XW_RGB_COLORMAP) xtSetRGBColormap(context, stdmap, cells, colors); else xtSetGrayColormap(context, stdmap, cells, colors); /* Need to change the GC so that Background and Foreground pixels are properly set. This is down in xmView when creating the gstate. */ context->map = stdmap; return stdmap; } /* Internal conversion of colors to pixels values */ u_long xtGrayToPixel(XWContext context, float gray) { XStandardColormap *map; u_long color; map = context->map; if (map == NULL) { int screen = DefaultScreen(context->display); return (gray < 0.5) ? BlackPixel(context->display, screen) : WhitePixel(context->display, screen); } color = ((u_long)(0.5 + (gray * map->red_max)) * map->red_mult) + ((u_long)(0.5 + (gray*map->green_max)) * map->green_mult) + ((u_long)(0.5 + (gray*map->blue_max)) * map->blue_mult) + map->base_pixel; return color; } u_long xtRGBToPixel(XWContext context, float red, float green, float blue) { XStandardColormap *map; u_long color; map = context->map; if (map == NULL) { int gray = ((0.3*red) + (0.59*green) + (0.11*blue)); int screen = DefaultScreen(context->display); return (gray < 0.5) ? BlackPixel(context->display, screen) : WhitePixel(context->display, screen); } color = ((u_long)(0.5 + (red * map->red_max)) * map->red_mult) + ((u_long)(0.5 + (green * map->green_max)) * map->green_mult) + ((u_long)(0.5 + (blue * map->blue_max)) * map->blue_mult) + map->base_pixel; return color; } /* Not implemented. FIXME */ u_long xtHSBToPixel(XWContext context, float h, float s, float b) { return 0; } /* Not implemented. FIXME */ u_long xtCMYKToPixel(XWContext context, float c, float m, float y, float k) { return 0; } u_long xtColorToPixel(XWContext context, device_color_t color) { u_long pix; switch(color.space) { case gray_colorspace: pix = xtGrayToPixel(context, color.field[0]); break; case rgb_colorspace: pix = xtRGBToPixel(context, color.field[0], color.field[1], color.field[2]); break; case hsb_colorspace: pix = xtHSBToPixel(context, color.field[0], color.field[1], color.field[2]); break; case cmyk_colorspace: pix = xtCMYKToPixel(context, color.field[0], color.field[1], color.field[2], color.field[3]); break; default: break; } return pix; } device_color_t xtConvertToGray(device_color_t color) { device_color_t new; new.space = gray_colorspace; switch(color.space) { case gray_colorspace: new = color; break; case hsb_colorspace: case cmyk_colorspace: color = xtConvertToRGB(color); /* NO BREAK */ case rgb_colorspace: new.field[0] = ((0.3*color.field[0]) + (0.59*color.field[1]) + (0.11*color.field[2])); break; default: break; } return new; } device_color_t xtConvertToRGB(device_color_t color) { device_color_t new; new.space = rgb_colorspace; switch(color.space) { case gray_colorspace: new.field[0] = color.field[0]; new.field[1] = color.field[0]; new.field[2] = color.field[0]; break; case rgb_colorspace: new = color; break; case hsb_colorspace: case cmyk_colorspace: break; default: break; } return new; } device_color_t xtConvertToHSB(device_color_t color) { device_color_t new; new.space = hsb_colorspace; switch(color.space) { case gray_colorspace: break; case rgb_colorspace: break; case hsb_colorspace: new = color; break; case cmyk_colorspace: break; default: break; } return new; } device_color_t xtConvertToCMYK(device_color_t color) { device_color_t new; new.space = gray_colorspace; switch(color.space) { case gray_colorspace: break; case rgb_colorspace: break; case hsb_colorspace: break; case cmyk_colorspace: new = color; break; default: break; } return new; } /* Internal conversion of image data to pixel values These routines are here for consistency, but are really only used by xtNXBitmapImageRep. Look at that file for more information on how these routines are used. */ u_char * xtMapGrays(XWContext context, u_char **src, int colorspace, int bps, int spp, int ncolors, int planar, u_char *dest) { int i; XStandardColormap *map; u_int max; u_long color; u_char *gray; map = context->map; gray = src[0]; /* Ignore alpha */ if (map == NULL) return 0; max = (1 << bps); for (i=0; i < ncolors; i++) { /* Just skip the Alpha if there is one */ if (planar) color = (gray[i*bps/8] << ((i * bps) % 8)) % max; else color = (gray[i*spp*bps/8] << ((i * bps) % 8)) % max; color = ((color * map->red_max / max) * map->red_mult + (color * map->green_max / max) * map->green_mult + (color * map->blue_max / max) * map->blue_mult + map->base_pixel) & 0xFFFFFFFF; /* FIXME: Need to pack bits for displays with depth < 8 */ dest[i] = color; } return dest; } /* FIXME: Only handles RGB images (no CMYK) */ u_char * xtMapColors(XWContext context, u_char **src, int colorspace, int bps, int spp, int ncolors, int planar, u_char *dest) { int i; XStandardColormap *map; u_int max; u_long color; u_char *red, *green, *blue; u_char r, g, b; if (spp <= 2) return xtMapGrays(context, src, colorspace, bps, spp, ncolors, planar, dest); map = context->map; if (map == NULL) return 0; max = (1 << bps); red = src[0]; if (planar) { green = src[1]; blue = src[2]; } for (i=0; i < ncolors; i++) { u_int shift; shift = i * bps / 8; if (planar) { r = (red[shift] << ((i * bps) % 8)) % max; g = (green[shift] << ((i * bps) % 8)) % max; b = (blue[shift] << ((i * bps) % 8)) % max; /* Translate values for gray-scale display */ if ( map->green_max == 0 && map->blue_max == 0) r = (u_long)((0.3*r) + (0.59*g) + (0.11*b)); color = ((r * map->red_max / max) * map->red_mult + (g * map->green_max / max)*map->green_mult + (b * map->blue_max / max)*map->blue_mult + map->base_pixel) & 0xFFFFFFFF; } else { r = (red[i*spp*bps/8] << ((i * bps) % 8)) % max; g = (red[(i*spp+1)*bps/8] << (((i+1) * bps) % 8)) % max; b = (red[(i*spp+2)*bps/8] << (((i+2) * bps) % 8)) % max; /* Translate values for gray-scale display */ if ( map->green_max == 0 && map->blue_max == 0) r = (u_long)((0.3*r) + (0.59*g) + (0.11*b)); color = ((r * map->red_max / max) * map->red_mult + (g * map->green_max / max) * map->green_mult + (b * map->blue_max / max) * map->blue_mult + map->base_pixel) & 0xFFFFFFFF; } /* FIXME: Need to pack bits for displays with depth < 8 */ dest[i] = color; } return dest; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.