wine/objects/color.c
Alexandre Julliard ff8331ea68 Release 950918
Sun Sep 17 16:47:49 1995  Alexandre Julliard  <julliard@sunsite.unc.edu>

	* [configure.in] [*/Makefile.in] [Make.rules.in]
	Cleaned up makefiles, added configuration option for Winelib,
	grouped common make rules in Make.rules.in.

	* [Configure]
	Renamed to 'Configure.old'; please use 'configure' instead.

	* [controls/menu.c]
	Fixed DestroyMenu() to avoid deleting the same menu twice.
	More fixes to WM_MENUSELECT, and added WM_INITMENU.

	* [if1632/relay.c]
	Fixed wrong register values displayed by RELAY_DebugCall32().

	* [memory/local.c]
	Fixed LocalLock() and LocalUnlock() to increment/decrement the
	lock count for moveable blocks.

	* [misc/commdlg.c] [misc/shell.c] [rc/winerc.c]
	Modified the generated C file so that the resource information
	(size, etc.) is also exported.
	Modified common dialogs to use the new informations.

	* [misc/main.c] [ANNOUNCE]
	Update the list of contributors. Please let me know if I forgot
	someone.

	* [rc/sysres.rc] [rc/sysres_En.rc]
	Moved English resources to sysres_En.rc.
	Changed ids from numeric to symbolic for dialogs.

	* [windows/dialog.c]
	Modified template parsing to be able to pass segmented pointers to
	CreateWindow().

	* [windows/win.c]
	CreateWindow() now takes segmented pointers for class and window
	names.
	Maxmimize or minimize the window upon creation if the WS_MAXIMIZE
	or WS_MINIMIZE bits are set.

Thu Sep 14 17:19:57 1995  Paul Wilhelm  <paul@paul.accessone.com>

	* [controls/scroll.c]
	Fixed scroll-bar bugs for non-client windows.

Thu Sep 14 14:04:14 MET DST 1995 Jochen Hoenicke <Jochen.Hoenicke@arbi.Informatik.Uni-Oldenburg.de>

	* [include/cursor.h] [windows/cursor.c]
	Cursor is not mirrored any more and the hotspot is set right.

Wed Sep 13 14:22:31 1995  Marcus Meissner  <msmeissn@faui01.informatik.uni-erlangen.de>

	* [ole.h]
	Misc small fixes.

Mon Sep  4 00:01:23 1995  Jon Tombs <jon@gte.esi.us.es>

	* [rc/sysres_Es.rc]
	First attempt at Spanish [Es] language support.

Sun Sep  3 13:22:33 1995     Martin von Loewis <loewis@informatik.hu-berlin.de>

	* [include/alias.h][windows/alias.c][include/relay32.h]
	New files

	* [controls/widgets.c]
	WIDGETS_Init: register alias window procedures

	* [if1632/callback.c]
	CallWndProc: Call alias functions if necessary

	* [if1632/gdi32.spec]
	GetStockObject, TextOutA: new relays

	* [misc/user32.c][if1632/user32.spec][misc/Makefile.in][misc/Imakefile]
	user32.c: new file
	BeginPaint,CreateWindowExA,DefWindowProcA,DispatchMessage,EndPaint,
	GetMessageA,RegisterClassA,ShowWindow,UpdateWindow: new relays

	* [if1632/winprocs32.spec][loader/pe_image.c][loader/module.c]
	PE_Win32CallToStart: new function
	MODULE_CreateInstance: removed static attribute
	LoadModule: Try loading PE image on error 21
	PE_LoadModule: new function
	PE_LoadImage: initialize pe_data with 0
	
	* [include/dlls.h][include/peexe.h]
	moved pe_data and w_files to peexe.h
	
	* [misc/shell.c]
	ShellAbout: Register AboutWndProc aliases

	* [miscemu/int21.c]
	handle 0x440A and 0xDC

	* [miscemu/int2f.c]
	handle 0x84

	* [objects/dib.c]
	CreateDIBitmap: complain if BITMAPINFOHEADER is of wrong size

	* [tools/build.c]
	include windows.h and relay32.h into generated Win32 relays,
	don't declare the implementation as int (*)();
	limit in WIN32_builtin was off by one

	* [windows/caret.c]
	CARET_Initialize: new function, call on strategic places

	* [windows/messagebox.c]
	MessageBox: register message box proc aliases

	* [if1632/advapi32.spec][if1632/comdlg32.spec]
	New files

	* [if1632/Makefile.in][if1632/Imakefile][if1632/relay32.c]
	added new spec files
	RELAY32_GetBuiltinDLL: perform lookup case insensitive
	RELAY32_GetEntryPoint: start name search at 0

	* [if1632/user.spec][if1632/kernel.spec][if1632/gdi.spec]
	Added stubs for new Win95 API

Sat Sep 2 1995  Martin Roy

	* [misc/commdlg.c]
	In WM_INITDIALOG, current filter must reflect lpofn->nFilterIndex.
  	When process IDOK button in FILEDLG_WMCommand(),
 	lpofn->nFilterIndex should be updated to current selection.

Thu Aug 31 15:00:00 1995 Ram'on Garc'ia <ramon@ie3.clubs.etsit.upm.es>

	* [loader/module.c] [loader/ne_image.c]
	Added support of self-loading modules.
1995-09-18 11:19:54 +00:00

458 lines
13 KiB
C

/*
* Color functions
*
* Copyright 1993 Alexandre Julliard
*
static char Copyright[] = "Copyright Alexandre Julliard, 1993";
*/
#include <stdlib.h>
#include <X11/Xlib.h>
#include <stdio.h>
#include "windows.h"
#include "options.h"
#include "gdi.h"
#include "color.h"
#include "palette.h"
Colormap COLOR_WinColormap = 0;
int COLOR_FixedMap = 0;
int COLOR_Redshift = 0;
int COLOR_Redmax = 0;
int COLOR_Greenshift = 0;
int COLOR_Greenmax = 0;
int COLOR_Blueshift = 0;
int COLOR_Bluemax = 0;
int COLOR_Graymax = 0;
/* System palette static colors */
#define NB_RESERVED_COLORS 20
/* The first and last eight colors are EGA colors */
static PALETTEENTRY COLOR_sysPaletteEntries[NB_RESERVED_COLORS] =
{
/* red green blue flags */
{ 0x00, 0x00, 0x00, 0 },
{ 0x80, 0x00, 0x00, 0 },
{ 0x00, 0x80, 0x00, 0 },
{ 0x80, 0x80, 0x00, 0 },
{ 0x00, 0x00, 0x80, 0 },
{ 0x80, 0x00, 0x80, 0 },
{ 0x00, 0x80, 0x80, 0 },
{ 0xc0, 0xc0, 0xc0, 0 },
{ 0xc0, 0xdc, 0xc0, 0 },
{ 0xa6, 0xca, 0xf0, 0 },
{ 0xff, 0xfb, 0xf0, 0 },
{ 0xa0, 0xa0, 0xa4, 0 },
{ 0x80, 0x80, 0x80, 0 },
{ 0xff, 0x00, 0x00, 0 },
{ 0x00, 0xff, 0x00, 0 },
{ 0xff, 0xff, 0x00, 0 },
{ 0x00, 0x00, 0xff, 0 },
{ 0xff, 0x00, 0xff, 0 },
{ 0x00, 0xff, 0xff, 0 },
{ 0xff, 0xff, 0xff, 0 }
};
static HANDLE hSysColorTranslation = 0;
static HANDLE hRevSysColorTranslation = 0;
/* Map an EGA index (0..15) to a pixel value. Used for dithering. */
int COLOR_mapEGAPixel[16];
int* COLOR_PaletteToPixel = NULL;
int* COLOR_PixelToPalette = NULL;
int COLOR_ColormapSize = 0;
/***********************************************************************
* COLOR_BuildMap
*
* Fill the private colormap.
*/
static BOOL COLOR_BuildMap( Colormap map, int depth, int size )
{
XColor color;
int r, g, b, red_incr, green_incr, blue_incr;
int index = 0;
/* Fill the whole map with a range of colors */
blue_incr = 0x10000 >> (depth / 3);
red_incr = 0x10000 >> ((depth + 1) / 3);
green_incr = 0x10000 >> ((depth + 2) / 3);
for (r = red_incr - 1; r < 0x10000; r += red_incr)
for (g = green_incr - 1; g < 0x10000; g += green_incr)
for (b = blue_incr - 1; b < 0x10000; b += blue_incr)
{
if (index >= size) break;
color.pixel = index++;
color.red = r;
color.green = g;
color.blue = b;
XStoreColor( display, map, &color );
}
return TRUE;
}
/***********************************************************************
* COLOR_InitPalette
*
* Create the system palette.
*/
static HPALETTE COLOR_InitPalette(void)
{
int i, size, pixel;
XColor color;
HPALETTE hpalette;
LOGPALETTE * palPtr;
WORD *colorTranslation, *revTranslation;
size = DefaultVisual( display, DefaultScreen(display) )->map_entries;
COLOR_ColormapSize = size;
if (screenDepth <= 8)
{
if (!(hSysColorTranslation = GDI_HEAP_ALLOC(sizeof(WORD)*NB_RESERVED_COLORS )))
return FALSE;
if (!(hRevSysColorTranslation = GDI_HEAP_ALLOC( sizeof(WORD)*size )))
return FALSE;
colorTranslation = (WORD *) GDI_HEAP_LIN_ADDR( hSysColorTranslation );
revTranslation = (WORD *) GDI_HEAP_LIN_ADDR( hRevSysColorTranslation );
}
else colorTranslation = revTranslation = NULL;
if ((COLOR_WinColormap == DefaultColormapOfScreen(screen)) && (screenDepth <= 8))
{
COLOR_PaletteToPixel = (int *)malloc( sizeof(int) * size );
COLOR_PixelToPalette = (int *)malloc( sizeof(int) * size );
for (i = 0; i < size; i++) /* Set the default mapping */
COLOR_PaletteToPixel[i] = COLOR_PixelToPalette[i] = i;
}
for (i = 0; i < NB_RESERVED_COLORS; i++)
{
color.red = COLOR_sysPaletteEntries[i].peRed * 65535 / 255;
color.green = COLOR_sysPaletteEntries[i].peGreen * 65535 / 255;
color.blue = COLOR_sysPaletteEntries[i].peBlue * 65535 / 255;
color.flags = DoRed | DoGreen | DoBlue;
if (i < NB_RESERVED_COLORS/2)
{
/* Bottom half of the colormap */
pixel = i;
if (pixel >= size/2) continue;
}
else
{
/* Top half of the colormap */
pixel = size - NB_RESERVED_COLORS + i;
if (pixel < size/2) continue;
}
if (COLOR_WinColormap != DefaultColormapOfScreen(screen))
{
color.pixel = pixel;
XStoreColor( display, COLOR_WinColormap, &color );
}
else
{
if (!XAllocColor( display, COLOR_WinColormap, &color ))
{
fprintf(stderr, "Warning: Not enough free colors. Try using the -privatemap option.\n" );
color.pixel = color.red = color.green = color.blue = 0;
}
else if (COLOR_PaletteToPixel)
{
COLOR_PaletteToPixel[pixel] = color.pixel;
COLOR_PixelToPalette[color.pixel] = pixel;
}
}
if (colorTranslation) colorTranslation[i] = color.pixel;
if (revTranslation) revTranslation[color.pixel] = i;
/* Set EGA mapping if color in the first or last eight */
if (i < 8)
COLOR_mapEGAPixel[i] = color.pixel;
else if (i >= NB_RESERVED_COLORS-8)
COLOR_mapEGAPixel[i - (NB_RESERVED_COLORS-16)] = color.pixel;
}
palPtr = malloc( sizeof(LOGPALETTE) + (NB_RESERVED_COLORS-1)*sizeof(PALETTEENTRY) );
if (!palPtr) return FALSE;
palPtr->palVersion = 0x300;
palPtr->palNumEntries = NB_RESERVED_COLORS;
memcpy( palPtr->palPalEntry, COLOR_sysPaletteEntries,
sizeof(COLOR_sysPaletteEntries) );
hpalette = CreatePalette( palPtr );
free( palPtr );
return hpalette;
}
void
COLOR_Computeshifts(unsigned long maskbits, int *shift, int *max)
{
int i;
if(maskbits==0) {
*shift=0;
*max=0;
return;
}
for(i=0;!(maskbits&1);i++)
maskbits >>= 1;
*shift = i;
*max = maskbits;
}
/***********************************************************************
* COLOR_Init
*
* Initialize color map and system palette.
*/
HPALETTE COLOR_Init(void)
{
Visual * visual = DefaultVisual( display, DefaultScreen(display) );
switch(visual->class)
{
case GrayScale:
case PseudoColor:
case DirectColor:
COLOR_FixedMap = 0;
if (Options.usePrivateMap)
{
COLOR_WinColormap = XCreateColormap( display, rootWindow,
visual, AllocAll );
if (COLOR_WinColormap)
{
COLOR_BuildMap( COLOR_WinColormap, screenDepth,
visual->map_entries );
if (rootWindow != DefaultRootWindow(display))
{
XSetWindowAttributes win_attr;
win_attr.colormap = COLOR_WinColormap;
XChangeWindowAttributes( display, rootWindow,
CWColormap, &win_attr );
}
break;
}
}
COLOR_WinColormap = DefaultColormapOfScreen( screen );
break;
/* Fall through */
case StaticGray:
COLOR_WinColormap = DefaultColormapOfScreen( screen );
COLOR_FixedMap = 1;
COLOR_Graymax = (1<<screenDepth)-1;
break;
case StaticColor:
case TrueColor:
COLOR_WinColormap = DefaultColormapOfScreen( screen );
COLOR_FixedMap = 1;
COLOR_Computeshifts(visual->red_mask, &COLOR_Redshift, &COLOR_Redmax);
COLOR_Computeshifts(visual->green_mask, &COLOR_Greenshift, &COLOR_Greenmax);
COLOR_Computeshifts(visual->blue_mask, &COLOR_Blueshift, &COLOR_Bluemax);
break;
}
return COLOR_InitPalette();
}
/***********************************************************************
* COLOR_IsSolid
*
* Check whether 'color' can be represented with a solid color.
*/
BOOL COLOR_IsSolid( COLORREF color )
{
int i;
PALETTEENTRY *pEntry = COLOR_sysPaletteEntries;
if (color & 0xff000000) return TRUE;
if (!color || (color == 0xffffff)) return TRUE;
for (i = NB_RESERVED_COLORS; i > 0; i--, pEntry++)
{
if ((GetRValue(color) == pEntry->peRed) &&
(GetGValue(color) == pEntry->peGreen) &&
(GetBValue(color) == pEntry->peBlue)) return TRUE;
}
return FALSE;
}
/***********************************************************************
* COLOR_ToPhysical
*
* Return the physical color closest to 'color'.
*
* ESW: This still needs a lot of work; in particular, what happens when
* we have really large (> 8 bit) DirectColor boards?
* But it should work better in 16 and 24 bit modes now.
* (At least it pays attention to the X server's description
* in TrueColor mode, instead of blindly passing through the
* color spec and swapping red to blue or losing blue and part of the
* green entirely, depending on what mode one is in!)
*
*/
int COLOR_ToPhysical( DC *dc, COLORREF color )
{
WORD index = 0;
WORD *mapping;
/* if (screenDepth > 8) return color; */
if (dc && (dc->w.bitsPerPixel == 1) && ((color >> 24) == 0))
{
/* monochrome */
if (((color >> 16) & 0xff) +
((color >> 8) & 0xff) + (color & 0xff) > 255*3/2)
return 1; /* white */
else return 0; /* black */
}
if(COLOR_FixedMap) {
/* there is no colormap possible; we are going to have to compute
the pixel value from the visual information stored earlier */
unsigned long which = color >> 24;
unsigned long red, green, blue;
unsigned idx;
PALETTEOBJ * palPtr;
switch(which) {
case 0: /* RGB */
case 2: /* PALETTERGB -- needs some work, but why bother; we've got a REALLY LARGE number of colors...? */
default:
red = GetRValue(color);
green = GetGValue(color);
blue = GetBValue(color);
break;
case 1: /* PALETTEIDX -- hmm, get the real color from the stock palette */
palPtr = (PALETTEOBJ *) GDI_GetObjPtr( STOCK_DEFAULT_PALETTE, PALETTE_MAGIC);
idx = color & 0xffff;
if(idx >= palPtr->logpalette.palNumEntries) {
/* out of bounds */
red = green = blue = 0;
}
else {
red = palPtr->logpalette.palPalEntry[idx].peRed;
green = palPtr->logpalette.palPalEntry[idx].peGreen;
blue = palPtr->logpalette.palPalEntry[idx].peBlue;
}
}
if(COLOR_Graymax) {
/* grayscale only; return scaled value */
return ( (red * 30 + green * 69 + blue * 11) * COLOR_Graymax) / 25500;
}
else {
/* scale each individually and construct the TrueColor pixel value */
if(COLOR_Redmax != 255)
red = (red * COLOR_Redmax) / 255;
if(COLOR_Greenmax != 255)
green = (green * COLOR_Greenmax) / 255;
if(COLOR_Bluemax != 255)
blue = (blue * COLOR_Bluemax) / 255;
return (red << COLOR_Redshift) | (green << COLOR_Greenshift) | (blue << COLOR_Blueshift);
}
}
else switch(color >> 24)
{
case 0: /* RGB */
index = GetNearestPaletteIndex( STOCK_DEFAULT_PALETTE, color );
break;
case 1: /* PALETTEINDEX */
index = color & 0xffff;
break;
case 2: /* PALETTERGB */
if (dc) index = GetNearestPaletteIndex( dc->w.hPalette, color );
else index = 0;
break;
}
if (dc&&dc->u.x.pal.mappingSize)
{
if (index >= dc->u.x.pal.mappingSize) return 0;
mapping = (WORD *) GDI_HEAP_LIN_ADDR( dc->u.x.pal.hMapping );
}
else
{
if (index >= NB_RESERVED_COLORS) return 0;
mapping = (WORD *) GDI_HEAP_LIN_ADDR( hSysColorTranslation );
}
if (mapping) return mapping[index];
else return index; /* Identity mapping */
}
/***********************************************************************
* COLOR_SetMapping
*
* Set the color-mapping table in a DC.
*/
void COLOR_SetMapping( DC *dc, HANDLE map, HANDLE revMap, WORD size )
{
WORD *pmap, *pnewmap;
WORD i;
if (dc->u.x.pal.hMapping && (dc->u.x.pal.hMapping != hSysColorTranslation))
GDI_HEAP_FREE( dc->u.x.pal.hMapping );
if (dc->u.x.pal.hRevMapping &&
(dc->u.x.pal.hRevMapping != hRevSysColorTranslation))
GDI_HEAP_FREE( dc->u.x.pal.hRevMapping );
if (map && (map != hSysColorTranslation))
{
/* Copy mapping table */
dc->u.x.pal.hMapping = GDI_HEAP_ALLOC( sizeof(WORD) * size );
pmap = (WORD *) GDI_HEAP_LIN_ADDR( map );
pnewmap = (WORD *) GDI_HEAP_LIN_ADDR( dc->u.x.pal.hMapping );
memcpy( pnewmap, pmap, sizeof(WORD)*size );
/* Build reverse table */
dc->u.x.pal.hRevMapping = GDI_HEAP_ALLOC(sizeof(WORD)*COLOR_ColormapSize);
pmap = (WORD *) GDI_HEAP_LIN_ADDR( dc->u.x.pal.hRevMapping );
for (i = 0; i < size; i++) pmap[pnewmap[i]] = i;
}
else
{
dc->u.x.pal.hMapping = map;
dc->u.x.pal.hRevMapping = map ? hRevSysColorTranslation : 0;
}
dc->u.x.pal.mappingSize = size;
}
/***********************************************************************
* GetNearestColor (GDI.154)
*/
COLORREF GetNearestColor( HDC hdc, COLORREF color )
{
WORD index;
DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
if (!dc) return 0;
if (screenDepth > 8) return color; /* FIXME */
index = (WORD)(COLOR_ToPhysical( dc, color & 0xffffff ) & 0xffff);
return PALETTEINDEX( index );
}
/***********************************************************************
* RealizeDefaultPalette (GDI.365)
*/
WORD RealizeDefaultPalette( HDC hdc )
{
DC *dc;
if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
dc->w.hPalette = STOCK_DEFAULT_PALETTE;
COLOR_SetMapping( dc, hSysColorTranslation,
hRevSysColorTranslation, NB_RESERVED_COLORS );
return NB_RESERVED_COLORS;
}