mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-13 14:47:21 -04:00
1830 lines
47 KiB
C
1830 lines
47 KiB
C
/* $Xorg: LRGB.c,v 1.3 2000/08/17 19:44:39 cpqbld Exp $ */
|
||
|
||
/*
|
||
* Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
|
||
* All Rights Reserved
|
||
*
|
||
* This file is a component of an X Window System-specific implementation
|
||
* of Xcms based on the TekColor Color Management System. Permission is
|
||
* hereby granted to use, copy, modify, sell, and otherwise distribute this
|
||
* software and its documentation for any purpose and without fee, provided
|
||
* that this copyright, permission, and disclaimer notice is reproduced in
|
||
* all copies of this software and in supporting documentation. TekColor
|
||
* is a trademark of Tektronix, Inc.
|
||
*
|
||
* Tektronix makes no representation about the suitability of this software
|
||
* for any purpose. It is provided "as is" and with all faults.
|
||
*
|
||
* TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
|
||
* INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||
* PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX 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 THE PERFORMANCE OF THIS SOFTWARE.
|
||
*
|
||
*
|
||
* NAME
|
||
* XcmsLRGB.c
|
||
*
|
||
* DESCRIPTION
|
||
* This file contains the conversion routines:
|
||
* 1. CIE XYZ to RGB intensity
|
||
* 2. RGB intensity to device RGB
|
||
* 3. device RGB to RGB intensity
|
||
* 4. RGB intensity to CIE XYZ
|
||
*
|
||
*/
|
||
/* $XFree86: xc/lib/X11/LRGB.c,v 3.7 2003/11/03 03:46:26 dawes Exp $ */
|
||
|
||
#include <stdio.h>
|
||
#include <X11/Xos.h>
|
||
#include <X11/Xatom.h>
|
||
#include "Xlibint.h"
|
||
#include "Xcmsint.h"
|
||
#include "Cv.h"
|
||
|
||
/*
|
||
* LOCAL DEFINES
|
||
* #define declarations local to this package.
|
||
*/
|
||
#define EPS 0.001
|
||
#ifndef MIN
|
||
#define MIN(x,y) ((x) > (y) ? (y) : (x))
|
||
#endif /* MIN */
|
||
#ifndef MAX
|
||
#define MAX(x,y) ((x) > (y) ? (x) : (y))
|
||
#endif /* MAX */
|
||
#ifndef MIN3
|
||
#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x))
|
||
#endif /* MIN3 */
|
||
#ifndef MAX3
|
||
#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z))))
|
||
#endif /* MAX3 */
|
||
|
||
/*
|
||
* LOCAL TYPEDEFS
|
||
* typedefs local to this package (for use with local vars).
|
||
*
|
||
*/
|
||
|
||
/*
|
||
* FORWARD DECLARATIONS
|
||
*/
|
||
static void LINEAR_RGB_FreeSCCData(XPointer pScreenDataTemp);
|
||
static int LINEAR_RGB_InitSCCData(Display *dpy,
|
||
int screenNumber, XcmsPerScrnInfo *pPerScrnInfo);
|
||
static int XcmsLRGB_RGB_ParseString(register char *spec, XcmsColor *pColor);
|
||
static int XcmsLRGB_RGBi_ParseString(register char *spec, XcmsColor *pColor);
|
||
static Status
|
||
_XcmsGetTableType0(
|
||
IntensityTbl *pTbl,
|
||
int format,
|
||
char **pChar,
|
||
unsigned long *pCount);
|
||
static Status
|
||
_XcmsGetTableType1(
|
||
IntensityTbl *pTbl,
|
||
int format,
|
||
char **pChar,
|
||
unsigned long *pCount);
|
||
|
||
/*
|
||
* LOCALS VARIABLES
|
||
* Variables local to this package.
|
||
* Usage example:
|
||
* static int ExampleLocalVar;
|
||
*/
|
||
|
||
static unsigned short const MASK[17] = {
|
||
0x0000, /* 0 bitsPerRGB */
|
||
0x8000, /* 1 bitsPerRGB */
|
||
0xc000, /* 2 bitsPerRGB */
|
||
0xe000, /* 3 bitsPerRGB */
|
||
0xf000, /* 4 bitsPerRGB */
|
||
0xf800, /* 5 bitsPerRGB */
|
||
0xfc00, /* 6 bitsPerRGB */
|
||
0xfe00, /* 7 bitsPerRGB */
|
||
0xff00, /* 8 bitsPerRGB */
|
||
0xff80, /* 9 bitsPerRGB */
|
||
0xffc0, /* 10 bitsPerRGB */
|
||
0xffe0, /* 11 bitsPerRGB */
|
||
0xfff0, /* 12 bitsPerRGB */
|
||
0xfff8, /* 13 bitsPerRGB */
|
||
0xfffc, /* 14 bitsPerRGB */
|
||
0xfffe, /* 15 bitsPerRGB */
|
||
0xffff /* 16 bitsPerRGB */
|
||
};
|
||
|
||
|
||
/*
|
||
* A NULL terminated array of function pointers that when applied
|
||
* in series will convert an XcmsColor structure from XcmsRGBFormat
|
||
* to XcmsCIEXYZFormat.
|
||
*/
|
||
static XcmsConversionProc Fl_RGB_to_CIEXYZ[] = {
|
||
(XcmsConversionProc)XcmsRGBToRGBi,
|
||
(XcmsConversionProc)XcmsRGBiToCIEXYZ,
|
||
NULL
|
||
};
|
||
|
||
/*
|
||
* A NULL terminated array of function pointers that when applied
|
||
* in series will convert an XcmsColor structure from XcmsCIEXYZFormat
|
||
* to XcmsRGBFormat.
|
||
*/
|
||
static XcmsConversionProc Fl_CIEXYZ_to_RGB[] = {
|
||
(XcmsConversionProc)XcmsCIEXYZToRGBi,
|
||
(XcmsConversionProc)XcmsRGBiToRGB,
|
||
NULL
|
||
};
|
||
|
||
/*
|
||
* A NULL terminated array of function pointers that when applied
|
||
* in series will convert an XcmsColor structure from XcmsRGBiFormat
|
||
* to XcmsCIEXYZFormat.
|
||
*/
|
||
static XcmsConversionProc Fl_RGBi_to_CIEXYZ[] = {
|
||
(XcmsConversionProc)XcmsRGBiToCIEXYZ,
|
||
NULL
|
||
};
|
||
|
||
/*
|
||
* A NULL terminated array of function pointers that when applied
|
||
* in series will convert an XcmsColor structure from XcmsCIEXYZFormat
|
||
* to XcmsRGBiFormat.
|
||
*/
|
||
static XcmsConversionProc Fl_CIEXYZ_to_RGBi[] = {
|
||
(XcmsConversionProc)XcmsCIEXYZToRGBi,
|
||
NULL
|
||
};
|
||
|
||
/*
|
||
* RGBi Color Spaces
|
||
*/
|
||
XcmsColorSpace XcmsRGBiColorSpace =
|
||
{
|
||
_XcmsRGBi_prefix, /* prefix */
|
||
XcmsRGBiFormat, /* id */
|
||
XcmsLRGB_RGBi_ParseString, /* parseString */
|
||
Fl_RGBi_to_CIEXYZ, /* to_CIEXYZ */
|
||
Fl_CIEXYZ_to_RGBi, /* from_CIEXYZ */
|
||
1
|
||
};
|
||
|
||
/*
|
||
* RGB Color Spaces
|
||
*/
|
||
XcmsColorSpace XcmsRGBColorSpace =
|
||
{
|
||
_XcmsRGB_prefix, /* prefix */
|
||
XcmsRGBFormat, /* id */
|
||
XcmsLRGB_RGB_ParseString, /* parseString */
|
||
Fl_RGB_to_CIEXYZ, /* to_CIEXYZ */
|
||
Fl_CIEXYZ_to_RGB, /* from_CIEXYZ */
|
||
1
|
||
};
|
||
|
||
/*
|
||
* Device-Independent Color Spaces known to the
|
||
* LINEAR_RGB Screen Color Characteristics Function Set.
|
||
*/
|
||
static XcmsColorSpace *DDColorSpaces[] = {
|
||
&XcmsRGBColorSpace,
|
||
&XcmsRGBiColorSpace,
|
||
NULL
|
||
};
|
||
|
||
|
||
/*
|
||
* GLOBALS
|
||
* Variables declared in this package that are allowed
|
||
* to be used globally.
|
||
*/
|
||
|
||
/*
|
||
* LINEAR_RGB Screen Color Characteristics Function Set.
|
||
*/
|
||
XcmsFunctionSet XcmsLinearRGBFunctionSet =
|
||
{
|
||
&DDColorSpaces[0], /* pDDColorSpaces */
|
||
LINEAR_RGB_InitSCCData, /* pInitScrnFunc */
|
||
LINEAR_RGB_FreeSCCData /* pFreeSCCData */
|
||
};
|
||
|
||
/*
|
||
* DESCRIPTION
|
||
* Contents of Default SCCData should be replaced if other
|
||
* data should be used as default.
|
||
*
|
||
*
|
||
*/
|
||
|
||
/*
|
||
* NAME Tektronix 19" (Sony) CRT
|
||
* PART_NUMBER 119-2451-00
|
||
* MODEL Tek4300, Tek4800
|
||
*/
|
||
|
||
static IntensityRec const Default_RGB_RedTuples[] = {
|
||
/* {unsigned short value, XcmsFloat intensity} */
|
||
{ 0x0000, 0.000000 },
|
||
{ 0x0909, 0.000000 },
|
||
{ 0x0a0a, 0.000936 },
|
||
{ 0x0f0f, 0.001481 },
|
||
{ 0x1414, 0.002329 },
|
||
{ 0x1919, 0.003529 },
|
||
{ 0x1e1e, 0.005127 },
|
||
{ 0x2323, 0.007169 },
|
||
{ 0x2828, 0.009699 },
|
||
{ 0x2d2d, 0.012759 },
|
||
{ 0x3232, 0.016392 },
|
||
{ 0x3737, 0.020637 },
|
||
{ 0x3c3c, 0.025533 },
|
||
{ 0x4141, 0.031119 },
|
||
{ 0x4646, 0.037431 },
|
||
{ 0x4b4b, 0.044504 },
|
||
{ 0x5050, 0.052373 },
|
||
{ 0x5555, 0.061069 },
|
||
{ 0x5a5a, 0.070624 },
|
||
{ 0x5f5f, 0.081070 },
|
||
{ 0x6464, 0.092433 },
|
||
{ 0x6969, 0.104744 },
|
||
{ 0x6e6e, 0.118026 },
|
||
{ 0x7373, 0.132307 },
|
||
{ 0x7878, 0.147610 },
|
||
{ 0x7d7d, 0.163958 },
|
||
{ 0x8282, 0.181371 },
|
||
{ 0x8787, 0.199871 },
|
||
{ 0x8c8c, 0.219475 },
|
||
{ 0x9191, 0.240202 },
|
||
{ 0x9696, 0.262069 },
|
||
{ 0x9b9b, 0.285089 },
|
||
{ 0xa0a0, 0.309278 },
|
||
{ 0xa5a5, 0.334647 },
|
||
{ 0xaaaa, 0.361208 },
|
||
{ 0xafaf, 0.388971 },
|
||
{ 0xb4b4, 0.417945 },
|
||
{ 0xb9b9, 0.448138 },
|
||
{ 0xbebe, 0.479555 },
|
||
{ 0xc3c3, 0.512202 },
|
||
{ 0xc8c8, 0.546082 },
|
||
{ 0xcdcd, 0.581199 },
|
||
{ 0xd2d2, 0.617552 },
|
||
{ 0xd7d7, 0.655144 },
|
||
{ 0xdcdc, 0.693971 },
|
||
{ 0xe1e1, 0.734031 },
|
||
{ 0xe6e6, 0.775322 },
|
||
{ 0xebeb, 0.817837 },
|
||
{ 0xf0f0, 0.861571 },
|
||
{ 0xf5f5, 0.906515 },
|
||
{ 0xfafa, 0.952662 },
|
||
{ 0xffff, 1.000000 }
|
||
};
|
||
|
||
static IntensityRec const Default_RGB_GreenTuples[] = {
|
||
/* {unsigned short value, XcmsFloat intensity} */
|
||
{ 0x0000, 0.000000 },
|
||
{ 0x1313, 0.000000 },
|
||
{ 0x1414, 0.000832 },
|
||
{ 0x1919, 0.001998 },
|
||
{ 0x1e1e, 0.003612 },
|
||
{ 0x2323, 0.005736 },
|
||
{ 0x2828, 0.008428 },
|
||
{ 0x2d2d, 0.011745 },
|
||
{ 0x3232, 0.015740 },
|
||
{ 0x3737, 0.020463 },
|
||
{ 0x3c3c, 0.025960 },
|
||
{ 0x4141, 0.032275 },
|
||
{ 0x4646, 0.039449 },
|
||
{ 0x4b4b, 0.047519 },
|
||
{ 0x5050, 0.056520 },
|
||
{ 0x5555, 0.066484 },
|
||
{ 0x5a5a, 0.077439 },
|
||
{ 0x5f5f, 0.089409 },
|
||
{ 0x6464, 0.102418 },
|
||
{ 0x6969, 0.116485 },
|
||
{ 0x6e6e, 0.131625 },
|
||
{ 0x7373, 0.147853 },
|
||
{ 0x7878, 0.165176 },
|
||
{ 0x7d7d, 0.183604 },
|
||
{ 0x8282, 0.203140 },
|
||
{ 0x8787, 0.223783 },
|
||
{ 0x8c8c, 0.245533 },
|
||
{ 0x9191, 0.268384 },
|
||
{ 0x9696, 0.292327 },
|
||
{ 0x9b9b, 0.317351 },
|
||
{ 0xa0a0, 0.343441 },
|
||
{ 0xa5a5, 0.370580 },
|
||
{ 0xaaaa, 0.398747 },
|
||
{ 0xafaf, 0.427919 },
|
||
{ 0xb4b4, 0.458068 },
|
||
{ 0xb9b9, 0.489165 },
|
||
{ 0xbebe, 0.521176 },
|
||
{ 0xc3c3, 0.554067 },
|
||
{ 0xc8c8, 0.587797 },
|
||
{ 0xcdcd, 0.622324 },
|
||
{ 0xd2d2, 0.657604 },
|
||
{ 0xd7d7, 0.693588 },
|
||
{ 0xdcdc, 0.730225 },
|
||
{ 0xe1e1, 0.767459 },
|
||
{ 0xe6e6, 0.805235 },
|
||
{ 0xebeb, 0.843491 },
|
||
{ 0xf0f0, 0.882164 },
|
||
{ 0xf5f5, 0.921187 },
|
||
{ 0xfafa, 0.960490 },
|
||
{ 0xffff, 1.000000 }
|
||
};
|
||
|
||
static IntensityRec const Default_RGB_BlueTuples[] = {
|
||
/* {unsigned short value, XcmsFloat intensity} */
|
||
{ 0x0000, 0.000000 },
|
||
{ 0x0e0e, 0.000000 },
|
||
{ 0x0f0f, 0.001341 },
|
||
{ 0x1414, 0.002080 },
|
||
{ 0x1919, 0.003188 },
|
||
{ 0x1e1e, 0.004729 },
|
||
{ 0x2323, 0.006766 },
|
||
{ 0x2828, 0.009357 },
|
||
{ 0x2d2d, 0.012559 },
|
||
{ 0x3232, 0.016424 },
|
||
{ 0x3737, 0.021004 },
|
||
{ 0x3c3c, 0.026344 },
|
||
{ 0x4141, 0.032489 },
|
||
{ 0x4646, 0.039481 },
|
||
{ 0x4b4b, 0.047357 },
|
||
{ 0x5050, 0.056154 },
|
||
{ 0x5555, 0.065903 },
|
||
{ 0x5a5a, 0.076634 },
|
||
{ 0x5f5f, 0.088373 },
|
||
{ 0x6464, 0.101145 },
|
||
{ 0x6969, 0.114968 },
|
||
{ 0x6e6e, 0.129862 },
|
||
{ 0x7373, 0.145841 },
|
||
{ 0x7878, 0.162915 },
|
||
{ 0x7d7d, 0.181095 },
|
||
{ 0x8282, 0.200386 },
|
||
{ 0x8787, 0.220791 },
|
||
{ 0x8c8c, 0.242309 },
|
||
{ 0x9191, 0.264937 },
|
||
{ 0x9696, 0.288670 },
|
||
{ 0x9b9b, 0.313499 },
|
||
{ 0xa0a0, 0.339410 },
|
||
{ 0xa5a5, 0.366390 },
|
||
{ 0xaaaa, 0.394421 },
|
||
{ 0xafaf, 0.423481 },
|
||
{ 0xb4b4, 0.453547 },
|
||
{ 0xb9b9, 0.484592 },
|
||
{ 0xbebe, 0.516587 },
|
||
{ 0xc3c3, 0.549498 },
|
||
{ 0xc8c8, 0.583291 },
|
||
{ 0xcdcd, 0.617925 },
|
||
{ 0xd2d2, 0.653361 },
|
||
{ 0xd7d7, 0.689553 },
|
||
{ 0xdcdc, 0.726454 },
|
||
{ 0xe1e1, 0.764013 },
|
||
{ 0xe6e6, 0.802178 },
|
||
{ 0xebeb, 0.840891 },
|
||
{ 0xf0f0, 0.880093 },
|
||
{ 0xf5f5, 0.919723 },
|
||
{ 0xfafa, 0.959715 },
|
||
{ 0xffff, 1.00000 }
|
||
};
|
||
|
||
static IntensityTbl Default_RGB_RedTbl = {
|
||
/* IntensityRec *pBase */
|
||
(IntensityRec *) Default_RGB_RedTuples,
|
||
/* unsigned int nEntries */
|
||
52
|
||
};
|
||
|
||
static IntensityTbl Default_RGB_GreenTbl = {
|
||
/* IntensityRec *pBase */
|
||
(IntensityRec *)Default_RGB_GreenTuples,
|
||
/* unsigned int nEntries */
|
||
50
|
||
};
|
||
|
||
static IntensityTbl Default_RGB_BlueTbl = {
|
||
/* IntensityRec *pBase */
|
||
(IntensityRec *)Default_RGB_BlueTuples,
|
||
/* unsigned int nEntries */
|
||
51
|
||
};
|
||
|
||
static LINEAR_RGB_SCCData Default_RGB_SCCData = {
|
||
/* XcmsFloat XYZtoRGBmatrix[3][3] */
|
||
{
|
||
{ 3.48340481253539000, -1.52176374927285200, -0.55923133354049780 },
|
||
{-1.07152751306193600, 1.96593795204372400, 0.03673691339553462 },
|
||
{ 0.06351179790497788, -0.20020501000496480, 0.81070942031648220 }
|
||
},
|
||
|
||
/* XcmsFloat RGBtoXYZmatrix[3][3] */
|
||
{
|
||
{ 0.38106149108714790, 0.32025712365352110, 0.24834578525933100 },
|
||
{ 0.20729745115140850, 0.68054638776373240, 0.11215616108485920 },
|
||
{ 0.02133944350088028, 0.14297193020246480, 1.24172892629665500 }
|
||
},
|
||
|
||
/* IntensityTbl *pRedTbl */
|
||
&Default_RGB_RedTbl,
|
||
|
||
/* IntensityTbl *pGreenTbl */
|
||
&Default_RGB_GreenTbl,
|
||
|
||
/* IntensityTbl *pBlueTbl */
|
||
&Default_RGB_BlueTbl
|
||
};
|
||
|
||
/************************************************************************
|
||
* *
|
||
* PRIVATE ROUTINES *
|
||
* *
|
||
************************************************************************/
|
||
|
||
/*
|
||
* NAME
|
||
* LINEAR_RGB_InitSCCData()
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static Status
|
||
LINEAR_RGB_InitSCCData(
|
||
Display *dpy,
|
||
int screenNumber,
|
||
XcmsPerScrnInfo *pPerScrnInfo)
|
||
/*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* XcmsFailure if failed.
|
||
* XcmsSuccess if succeeded.
|
||
*
|
||
*/
|
||
{
|
||
Atom CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True);
|
||
Atom MatrixAtom = XInternAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True);
|
||
int format_return, count, cType, nTables;
|
||
unsigned long nitems, nbytes_return;
|
||
char *property_return, *pChar;
|
||
XcmsFloat *pValue;
|
||
#ifdef ALLDEBUG
|
||
IntensityRec *pIRec;
|
||
#endif /* ALLDEBUG */
|
||
VisualID visualID;
|
||
|
||
LINEAR_RGB_SCCData *pScreenData, *pScreenDefaultData;
|
||
XcmsIntensityMap *pNewMap;
|
||
|
||
/*
|
||
* Allocate memory for pScreenData
|
||
*/
|
||
if (!(pScreenData = pScreenDefaultData = (LINEAR_RGB_SCCData *)
|
||
Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* 1. Get the XYZ->RGB and RGB->XYZ matrices
|
||
*/
|
||
|
||
if (MatrixAtom == None ||
|
||
!_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), MatrixAtom,
|
||
&format_return, &nitems, &nbytes_return, &property_return) ||
|
||
nitems != 18 || format_return != 32) {
|
||
/*
|
||
* As per the XDCCC, there must be 18 data items and each must be
|
||
* in 32 bits !
|
||
*/
|
||
goto FreeSCCData;
|
||
|
||
} else {
|
||
|
||
/*
|
||
* RGBtoXYZ and XYZtoRGB matrices
|
||
*/
|
||
pValue = (XcmsFloat *) pScreenData;
|
||
pChar = property_return;
|
||
for (count = 0; count < 18; count++) {
|
||
*pValue++ = (long)_XcmsGetElement(format_return, &pChar,
|
||
&nitems) / (XcmsFloat)XDCCC_NUMBER;
|
||
}
|
||
Xfree ((char *)property_return);
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X =
|
||
pScreenData->RGBtoXYZmatrix[0][0] +
|
||
pScreenData->RGBtoXYZmatrix[0][1] +
|
||
pScreenData->RGBtoXYZmatrix[0][2];
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y =
|
||
pScreenData->RGBtoXYZmatrix[1][0] +
|
||
pScreenData->RGBtoXYZmatrix[1][1] +
|
||
pScreenData->RGBtoXYZmatrix[1][2];
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z =
|
||
pScreenData->RGBtoXYZmatrix[2][0] +
|
||
pScreenData->RGBtoXYZmatrix[2][1] +
|
||
pScreenData->RGBtoXYZmatrix[2][2];
|
||
|
||
/*
|
||
* Compute the Screen White Point
|
||
*/
|
||
if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) )
|
||
|| (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) {
|
||
goto FreeSCCData;
|
||
} else {
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0;
|
||
}
|
||
pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat;
|
||
pPerScrnInfo->screenWhitePt.pixel = 0;
|
||
|
||
#ifdef PDEBUG
|
||
printf ("RGB to XYZ Matrix values:\n");
|
||
printf (" %f %f %f\n %f %f %f\n %f %f %f\n",
|
||
pScreenData->RGBtoXYZmatrix[0][0],
|
||
pScreenData->RGBtoXYZmatrix[0][1],
|
||
pScreenData->RGBtoXYZmatrix[0][2],
|
||
pScreenData->RGBtoXYZmatrix[1][0],
|
||
pScreenData->RGBtoXYZmatrix[1][1],
|
||
pScreenData->RGBtoXYZmatrix[1][2],
|
||
pScreenData->RGBtoXYZmatrix[2][0],
|
||
pScreenData->RGBtoXYZmatrix[2][1],
|
||
pScreenData->RGBtoXYZmatrix[2][2]);
|
||
printf ("XYZ to RGB Matrix values:\n");
|
||
printf (" %f %f %f\n %f %f %f\n %f %f %f\n",
|
||
pScreenData->XYZtoRGBmatrix[0][0],
|
||
pScreenData->XYZtoRGBmatrix[0][1],
|
||
pScreenData->XYZtoRGBmatrix[0][2],
|
||
pScreenData->XYZtoRGBmatrix[1][0],
|
||
pScreenData->XYZtoRGBmatrix[1][1],
|
||
pScreenData->XYZtoRGBmatrix[1][2],
|
||
pScreenData->XYZtoRGBmatrix[2][0],
|
||
pScreenData->XYZtoRGBmatrix[2][1],
|
||
pScreenData->XYZtoRGBmatrix[2][2]);
|
||
printf ("Screen White Pt value: %f %f %f\n",
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X,
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y,
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z);
|
||
#endif /* PDEBUG */
|
||
}
|
||
|
||
/*
|
||
* 2. Get the Intensity Profile
|
||
*/
|
||
if (CorrectAtom == None ||
|
||
!_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), CorrectAtom,
|
||
&format_return, &nitems, &nbytes_return, &property_return)) {
|
||
Xfree ((char *)property_return);
|
||
goto FreeSCCData;
|
||
}
|
||
|
||
pChar = property_return;
|
||
|
||
while (nitems) {
|
||
switch (format_return) {
|
||
case 8:
|
||
/*
|
||
* Must have at least:
|
||
* VisualID0
|
||
* VisualID1
|
||
* VisualID2
|
||
* VisualID3
|
||
* type
|
||
* count
|
||
* length
|
||
* intensity1
|
||
* intensity2
|
||
*/
|
||
if (nitems < 9) {
|
||
Xfree ((char *)property_return);
|
||
goto FreeSCCData;
|
||
}
|
||
count = 3;
|
||
break;
|
||
case 16:
|
||
/*
|
||
* Must have at least:
|
||
* VisualID0
|
||
* VisualID3
|
||
* type
|
||
* count
|
||
* length
|
||
* intensity1
|
||
* intensity2
|
||
*/
|
||
if (nitems < 7) {
|
||
Xfree ((char *)property_return);
|
||
goto FreeSCCData;
|
||
}
|
||
count = 1;
|
||
break;
|
||
case 32:
|
||
/*
|
||
* Must have at least:
|
||
* VisualID0
|
||
* type
|
||
* count
|
||
* length
|
||
* intensity1
|
||
* intensity2
|
||
*/
|
||
if (nitems < 6) {
|
||
Xfree ((char *)property_return);
|
||
goto FreeSCCData;
|
||
}
|
||
count = 0;
|
||
break;
|
||
default:
|
||
Xfree ((char *)property_return);
|
||
goto FreeSCCData;
|
||
}
|
||
|
||
/*
|
||
* Get VisualID
|
||
*/
|
||
visualID = _XcmsGetElement(format_return, &pChar, &nitems);
|
||
while (count--) {
|
||
visualID = visualID << format_return;
|
||
visualID |= _XcmsGetElement(format_return, &pChar, &nitems);
|
||
}
|
||
|
||
if (visualID == 0) {
|
||
/*
|
||
* This is a shared intensity table
|
||
*/
|
||
pScreenData = pScreenDefaultData;
|
||
} else {
|
||
/*
|
||
* This is a per-Visual intensity table
|
||
*/
|
||
if (!(pScreenData = (LINEAR_RGB_SCCData *)
|
||
Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
|
||
return(XcmsFailure);
|
||
}
|
||
/* copy matrices */
|
||
memcpy((char *)pScreenData, (char *)pScreenDefaultData,
|
||
18 * sizeof(XcmsFloat));
|
||
|
||
/* Create, initialize, and add map */
|
||
if (!(pNewMap = (XcmsIntensityMap *)
|
||
Xcalloc (1, sizeof(XcmsIntensityMap)))) {
|
||
Xfree((char *)pScreenData);
|
||
return(XcmsFailure);
|
||
}
|
||
pNewMap->visualID = visualID;
|
||
pNewMap->screenData = (XPointer)pScreenData;
|
||
pNewMap->pFreeScreenData = LINEAR_RGB_FreeSCCData;
|
||
pNewMap->pNext =
|
||
(XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps;
|
||
dpy->cms.perVisualIntensityMaps = (XPointer)pNewMap;
|
||
dpy->free_funcs->intensityMaps = _XcmsFreeIntensityMaps;
|
||
}
|
||
|
||
cType = _XcmsGetElement(format_return, &pChar, &nitems);
|
||
nTables = _XcmsGetElement(format_return, &pChar, &nitems);
|
||
|
||
if (cType == 0) {
|
||
|
||
/* Red Intensity Table */
|
||
if (!(pScreenData->pRedTbl = (IntensityTbl *)
|
||
Xcalloc (1, sizeof(IntensityTbl)))) {
|
||
goto FreeSCCData;
|
||
}
|
||
if (_XcmsGetTableType0(pScreenData->pRedTbl, format_return, &pChar,
|
||
&nitems) == XcmsFailure) {
|
||
goto FreeRedTbl;
|
||
}
|
||
|
||
if (nTables == 1) {
|
||
/* Green Intensity Table */
|
||
pScreenData->pGreenTbl = pScreenData->pRedTbl;
|
||
/* Blue Intensity Table */
|
||
pScreenData->pBlueTbl = pScreenData->pRedTbl;
|
||
} else {
|
||
/* Green Intensity Table */
|
||
if (!(pScreenData->pGreenTbl = (IntensityTbl *)
|
||
Xcalloc (1, sizeof(IntensityTbl)))) {
|
||
goto FreeRedTblElements;
|
||
}
|
||
if (_XcmsGetTableType0(pScreenData->pGreenTbl, format_return, &pChar,
|
||
&nitems) == XcmsFailure) {
|
||
goto FreeGreenTbl;
|
||
}
|
||
|
||
/* Blue Intensity Table */
|
||
if (!(pScreenData->pBlueTbl = (IntensityTbl *)
|
||
Xcalloc (1, sizeof(IntensityTbl)))) {
|
||
goto FreeGreenTblElements;
|
||
}
|
||
if (_XcmsGetTableType0(pScreenData->pBlueTbl, format_return, &pChar,
|
||
&nitems) == XcmsFailure) {
|
||
goto FreeBlueTbl;
|
||
}
|
||
}
|
||
} else if (cType == 1) {
|
||
/* Red Intensity Table */
|
||
if (!(pScreenData->pRedTbl = (IntensityTbl *)
|
||
Xcalloc (1, sizeof(IntensityTbl)))) {
|
||
goto FreeSCCData;
|
||
}
|
||
if (_XcmsGetTableType1(pScreenData->pRedTbl, format_return, &pChar,
|
||
&nitems) == XcmsFailure) {
|
||
goto FreeRedTbl;
|
||
}
|
||
|
||
if (nTables == 1) {
|
||
|
||
/* Green Intensity Table */
|
||
pScreenData->pGreenTbl = pScreenData->pRedTbl;
|
||
/* Blue Intensity Table */
|
||
pScreenData->pBlueTbl = pScreenData->pRedTbl;
|
||
|
||
} else {
|
||
|
||
/* Green Intensity Table */
|
||
if (!(pScreenData->pGreenTbl = (IntensityTbl *)
|
||
Xcalloc (1, sizeof(IntensityTbl)))) {
|
||
goto FreeRedTblElements;
|
||
}
|
||
if (_XcmsGetTableType1(pScreenData->pGreenTbl, format_return, &pChar,
|
||
&nitems) == XcmsFailure) {
|
||
goto FreeGreenTbl;
|
||
}
|
||
|
||
/* Blue Intensity Table */
|
||
if (!(pScreenData->pBlueTbl = (IntensityTbl *)
|
||
Xcalloc (1, sizeof(IntensityTbl)))) {
|
||
goto FreeBlueTblElements;
|
||
}
|
||
if (_XcmsGetTableType1(pScreenData->pBlueTbl, format_return, &pChar,
|
||
&nitems) == XcmsFailure) {
|
||
goto FreeBlueTbl;
|
||
}
|
||
}
|
||
} else {
|
||
Xfree ((char *)property_return);
|
||
goto FreeSCCData;
|
||
}
|
||
|
||
#ifdef ALLDEBUG
|
||
printf ("Intensity Table RED %d\n", pScreenData->pRedTbl->nEntries);
|
||
pIRec = (IntensityRec *) pScreenData->pRedTbl->pBase;
|
||
for (count = 0; count < pScreenData->pRedTbl->nEntries; count++, pIRec++) {
|
||
printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
|
||
}
|
||
if (pScreenData->pGreenTbl->pBase != pScreenData->pRedTbl->pBase) {
|
||
printf ("Intensity Table GREEN %d\n", pScreenData->pGreenTbl->nEntries);
|
||
pIRec = (IntensityRec *)pScreenData->pGreenTbl->pBase;
|
||
for (count = 0; count < pScreenData->pGreenTbl->nEntries; count++, pIRec++) {
|
||
printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
|
||
}
|
||
}
|
||
if (pScreenData->pBlueTbl->pBase != pScreenData->pRedTbl->pBase) {
|
||
printf ("Intensity Table BLUE %d\n", pScreenData->pBlueTbl->nEntries);
|
||
pIRec = (IntensityRec *) pScreenData->pBlueTbl->pBase;
|
||
for (count = 0; count < pScreenData->pBlueTbl->nEntries; count++, pIRec++) {
|
||
printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
|
||
}
|
||
}
|
||
#endif /* ALLDEBUG */
|
||
}
|
||
|
||
Xfree ((char *)property_return);
|
||
|
||
/* Free the old memory and use the new structure created. */
|
||
LINEAR_RGB_FreeSCCData(pPerScrnInfo->screenData);
|
||
|
||
pPerScrnInfo->functionSet = (XPointer) &XcmsLinearRGBFunctionSet;
|
||
|
||
pPerScrnInfo->screenData = (XPointer) pScreenData;
|
||
|
||
pPerScrnInfo->state = XcmsInitSuccess;
|
||
|
||
return(XcmsSuccess);
|
||
|
||
FreeBlueTblElements:
|
||
Xfree((char *)pScreenData->pBlueTbl->pBase);
|
||
|
||
FreeBlueTbl:
|
||
Xfree((char *)pScreenData->pBlueTbl);
|
||
|
||
FreeGreenTblElements:
|
||
Xfree((char *)pScreenData->pBlueTbl->pBase);
|
||
|
||
FreeGreenTbl:
|
||
Xfree((char *)pScreenData->pGreenTbl);
|
||
|
||
FreeRedTblElements:
|
||
Xfree((char *)pScreenData->pRedTbl->pBase);
|
||
|
||
FreeRedTbl:
|
||
Xfree((char *)pScreenData->pRedTbl);
|
||
|
||
FreeSCCData:
|
||
Xfree((char *)pScreenData);
|
||
pPerScrnInfo->state = XcmsInitNone;
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* LINEAR_RGB_FreeSCCData()
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static void
|
||
LINEAR_RGB_FreeSCCData(
|
||
XPointer pScreenDataTemp)
|
||
/*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* 0 if failed.
|
||
* 1 if succeeded with no modifications.
|
||
*
|
||
*/
|
||
{
|
||
LINEAR_RGB_SCCData *pScreenData = (LINEAR_RGB_SCCData *) pScreenDataTemp;
|
||
|
||
if (pScreenData && pScreenData != &Default_RGB_SCCData) {
|
||
if (pScreenData->pRedTbl) {
|
||
if (pScreenData->pGreenTbl) {
|
||
if (pScreenData->pRedTbl->pBase !=
|
||
pScreenData->pGreenTbl->pBase) {
|
||
if (pScreenData->pGreenTbl->pBase) {
|
||
Xfree ((char *)pScreenData->pGreenTbl->pBase);
|
||
}
|
||
}
|
||
if (pScreenData->pGreenTbl != pScreenData->pRedTbl) {
|
||
Xfree ((char *)pScreenData->pGreenTbl);
|
||
}
|
||
}
|
||
if (pScreenData->pBlueTbl) {
|
||
if (pScreenData->pRedTbl->pBase !=
|
||
pScreenData->pBlueTbl->pBase) {
|
||
if (pScreenData->pBlueTbl->pBase) {
|
||
Xfree ((char *)pScreenData->pBlueTbl->pBase);
|
||
}
|
||
}
|
||
if (pScreenData->pBlueTbl != pScreenData->pRedTbl) {
|
||
Xfree ((char *)pScreenData->pBlueTbl);
|
||
}
|
||
}
|
||
if (pScreenData->pRedTbl->pBase) {
|
||
Xfree ((char *)pScreenData->pRedTbl->pBase);
|
||
}
|
||
Xfree ((char *)pScreenData->pRedTbl);
|
||
}
|
||
Xfree ((char *)pScreenData);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/************************************************************************
|
||
* *
|
||
* API PRIVATE ROUTINES *
|
||
* *
|
||
************************************************************************/
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsGetTableType0
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static Status
|
||
_XcmsGetTableType0(
|
||
IntensityTbl *pTbl,
|
||
int format,
|
||
char **pChar,
|
||
unsigned long *pCount)
|
||
/*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* XcmsFailure if failed.
|
||
* XcmsSuccess if succeeded.
|
||
*
|
||
*/
|
||
{
|
||
unsigned int nElements;
|
||
IntensityRec *pIRec;
|
||
|
||
nElements = pTbl->nEntries =
|
||
_XcmsGetElement(format, pChar, pCount) + 1;
|
||
if (!(pIRec = pTbl->pBase = (IntensityRec *)
|
||
Xcalloc (nElements, sizeof(IntensityRec)))) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
switch (format) {
|
||
case 8:
|
||
for (; nElements--; pIRec++) {
|
||
/* 0xFFFF/0xFF = 0x101 */
|
||
pIRec->value = _XcmsGetElement (format, pChar, pCount) * 0x101;
|
||
pIRec->intensity =
|
||
_XcmsGetElement (format, pChar, pCount) / (XcmsFloat)255.0;
|
||
}
|
||
break;
|
||
case 16:
|
||
for (; nElements--; pIRec++) {
|
||
pIRec->value = _XcmsGetElement (format, pChar, pCount);
|
||
pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
|
||
/ (XcmsFloat)65535.0;
|
||
}
|
||
break;
|
||
case 32:
|
||
for (; nElements--; pIRec++) {
|
||
pIRec->value = _XcmsGetElement (format, pChar, pCount);
|
||
pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
|
||
/ (XcmsFloat)4294967295.0;
|
||
}
|
||
break;
|
||
default:
|
||
return(XcmsFailure);
|
||
}
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsGetTableType1
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static Status
|
||
_XcmsGetTableType1(
|
||
IntensityTbl *pTbl,
|
||
int format,
|
||
char **pChar,
|
||
unsigned long *pCount)
|
||
/*
|
||
* DESCRIPTION
|
||
*
|
||
* RETURNS
|
||
* XcmsFailure if failed.
|
||
* XcmsSuccess if succeeded.
|
||
*
|
||
*/
|
||
{
|
||
int count;
|
||
unsigned int max_index;
|
||
IntensityRec *pIRec;
|
||
|
||
max_index = _XcmsGetElement(format, pChar, pCount);
|
||
pTbl->nEntries = max_index + 1;
|
||
if (!(pIRec = pTbl->pBase = (IntensityRec *)
|
||
Xcalloc (max_index+1, sizeof(IntensityRec)))) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
switch (format) {
|
||
case 8:
|
||
for (count = 0; count < max_index+1; count++, pIRec++) {
|
||
pIRec->value = (count * 65535) / max_index;
|
||
pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
|
||
/ (XcmsFloat)255.0;
|
||
}
|
||
break;
|
||
case 16:
|
||
for (count = 0; count < max_index+1; count++, pIRec++) {
|
||
pIRec->value = (count * 65535) / max_index;
|
||
pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
|
||
/ (XcmsFloat)65535.0;
|
||
}
|
||
break;
|
||
case 32:
|
||
for (count = 0; count < max_index+1; count++, pIRec++) {
|
||
pIRec->value = (count * 65535) / max_index;
|
||
pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
|
||
/ (XcmsFloat)4294967295.0;
|
||
}
|
||
break;
|
||
default:
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* ValueCmp
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
_XcmsValueCmp(
|
||
IntensityRec *p1, IntensityRec *p2)
|
||
/*
|
||
* DESCRIPTION
|
||
* Compares the value component of two IntensityRec
|
||
* structures.
|
||
*
|
||
* RETURNS
|
||
* 0 if p1->value is equal to p2->value
|
||
* < 0 if p1->value is less than p2->value
|
||
* > 0 if p1->value is greater than p2->value
|
||
*
|
||
*/
|
||
{
|
||
return (p1->value - p2->value);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* IntensityCmp
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
_XcmsIntensityCmp(
|
||
IntensityRec *p1, IntensityRec *p2)
|
||
/*
|
||
* DESCRIPTION
|
||
* Compares the intensity component of two IntensityRec
|
||
* structures.
|
||
*
|
||
* RETURNS
|
||
* 0 if equal;
|
||
* < 0 if first precedes second
|
||
* > 0 if first succeeds second
|
||
*
|
||
*/
|
||
{
|
||
if (p1->intensity < p2->intensity) {
|
||
return (-1);
|
||
}
|
||
if (p1->intensity > p2->intensity) {
|
||
return (XcmsSuccess);
|
||
}
|
||
return (XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* NAME
|
||
* ValueInterpolation
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
/* ARGSUSED */
|
||
static int
|
||
_XcmsValueInterpolation(
|
||
IntensityRec *key, IntensityRec *lo, IntensityRec *hi, IntensityRec *answer,
|
||
int bitsPerRGB)
|
||
/*
|
||
* DESCRIPTION
|
||
* Based on a given value, performs a linear interpolation
|
||
* on the intensities between two IntensityRec structures.
|
||
* Note that the bitsPerRGB parameter is ignored.
|
||
*
|
||
* RETURNS
|
||
* Returns 0 if failed; otherwise non-zero.
|
||
*/
|
||
{
|
||
XcmsFloat ratio;
|
||
|
||
ratio = ((XcmsFloat)key->value - (XcmsFloat)lo->value) /
|
||
((XcmsFloat)hi->value - (XcmsFloat)lo->value);
|
||
answer->value = key->value;
|
||
answer->intensity = (hi->intensity - lo->intensity) * ratio;
|
||
answer->intensity += lo->intensity;
|
||
return (XcmsSuccess);
|
||
}
|
||
|
||
/*
|
||
* NAME
|
||
* IntensityInterpolation
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
_XcmsIntensityInterpolation(
|
||
IntensityRec *key, IntensityRec *lo, IntensityRec *hi, IntensityRec *answer,
|
||
int bitsPerRGB)
|
||
/*
|
||
* DESCRIPTION
|
||
* Based on a given intensity, performs a linear interpolation
|
||
* on the values between two IntensityRec structures.
|
||
* The bitsPerRGB parameter is necessary to perform rounding
|
||
* to the correct number of significant bits.
|
||
*
|
||
* RETURNS
|
||
* Returns 0 if failed; otherwise non-zero.
|
||
*/
|
||
{
|
||
XcmsFloat ratio;
|
||
long target, up, down;
|
||
int shift = 16 - bitsPerRGB;
|
||
int max_color = (1 << bitsPerRGB) - 1;
|
||
|
||
ratio = (key->intensity - lo->intensity) / (hi->intensity - lo->intensity);
|
||
answer->intensity = key->intensity;
|
||
target = hi->value - lo->value;
|
||
target *= ratio;
|
||
target += lo->value;
|
||
|
||
/*
|
||
* Ok now, lets find the closest in respects to bits per RGB
|
||
*/
|
||
up = ((target >> shift) * 0xFFFF) / max_color;
|
||
if (up < target) {
|
||
down = up;
|
||
up = (MIN((down >> shift) + 1, max_color) * 0xFFFF) / max_color;
|
||
} else {
|
||
down = (MAX((up >> shift) - 1, 0) * 0xFFFF) / max_color;
|
||
}
|
||
answer->value = ((up - target) < (target - down) ? up : down);
|
||
answer->value &= MASK[bitsPerRGB];
|
||
return (XcmsSuccess);
|
||
}
|
||
|
||
|
||
|
||
typedef int (*comparProcp)(
|
||
char *p1,
|
||
char *p2);
|
||
typedef int (*interpolProcp)(
|
||
char *key,
|
||
char *lo,
|
||
char *hi,
|
||
char *answer,
|
||
int bitsPerRGB);
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsTableSearch
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
_XcmsTableSearch(
|
||
char *key,
|
||
int bitsPerRGB,
|
||
char *base,
|
||
unsigned nel,
|
||
unsigned nKeyPtrSize,
|
||
int (*compar)(
|
||
char *p1,
|
||
char *p2),
|
||
int (*interpol)(
|
||
char *key,
|
||
char *lo,
|
||
char *hi,
|
||
char *answer,
|
||
int bitsPerRGB),
|
||
char *answer)
|
||
|
||
/*
|
||
* DESCRIPTION
|
||
* A binary search through the specificied table.
|
||
*
|
||
* RETURNS
|
||
* Returns 0 if failed; otherwise non-zero.
|
||
*
|
||
*/
|
||
{
|
||
char *hi, *lo, *mid, *last;
|
||
int result;
|
||
|
||
last = hi = base + ((nel - 1) * nKeyPtrSize);
|
||
mid = lo = base;
|
||
|
||
/* use only the significants bits, then scale into 16 bits */
|
||
((IntensityRec *)key)->value = ((unsigned long)
|
||
(((IntensityRec *)key)->value >> (16 - bitsPerRGB)) * 0xFFFF)
|
||
/ ((1 << bitsPerRGB) - 1);
|
||
|
||
/* Special case so that zero intensity always maps to zero value */
|
||
if ((*compar) (key,lo) <= 0) {
|
||
memcpy (answer, lo, nKeyPtrSize);
|
||
((IntensityRec *)answer)->value &= MASK[bitsPerRGB];
|
||
return XcmsSuccess;
|
||
}
|
||
while (mid != last) {
|
||
last = mid;
|
||
mid = lo + (((unsigned)(hi - lo) / nKeyPtrSize) / 2) * nKeyPtrSize;
|
||
result = (*compar) (key, mid);
|
||
if (result == 0) {
|
||
|
||
memcpy(answer, mid, nKeyPtrSize);
|
||
((IntensityRec *)answer)->value &= MASK[bitsPerRGB];
|
||
return (XcmsSuccess);
|
||
} else if (result < 0) {
|
||
hi = mid;
|
||
} else {
|
||
lo = mid;
|
||
}
|
||
}
|
||
|
||
/*
|
||
* If we got to here, we didn't find a solution, so we
|
||
* need to apply interpolation.
|
||
*/
|
||
return ((*interpol)(key, lo, hi, answer, bitsPerRGB));
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsMatVec - multiply a 3 x 3 by a 3 x 1 vector
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static void _XcmsMatVec(
|
||
XcmsFloat *pMat, XcmsFloat *pIn, XcmsFloat *pOut)
|
||
/*
|
||
* DESCRIPTION
|
||
* Multiply the passed vector by the passed matrix to return a
|
||
* vector. Matrix is 3x3, vectors are of length 3.
|
||
*
|
||
* RETURNS
|
||
* void
|
||
*/
|
||
{
|
||
int i, j;
|
||
|
||
for (i = 0; i < 3; i++) {
|
||
pOut[i] = 0.0;
|
||
for (j = 0; j < 3; j++)
|
||
pOut[i] += *(pMat+(i*3)+j) * pIn[j];
|
||
}
|
||
}
|
||
|
||
|
||
/************************************************************************
|
||
* *
|
||
* PUBLIC ROUTINES *
|
||
* *
|
||
************************************************************************/
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* XcmsLRGB_RGB_ParseString
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
XcmsLRGB_RGB_ParseString(
|
||
register char *spec,
|
||
XcmsColor *pColor)
|
||
/*
|
||
* DESCRIPTION
|
||
* This routines takes a string and attempts to convert
|
||
* it into a XcmsColor structure with XcmsRGBFormat.
|
||
*
|
||
* RETURNS
|
||
* 0 if failed, non-zero otherwise.
|
||
*/
|
||
{
|
||
register int n, i;
|
||
unsigned short r, g, b;
|
||
char c;
|
||
char *pchar;
|
||
unsigned short *pShort;
|
||
|
||
/*
|
||
* Check for old # format
|
||
*/
|
||
if (*spec == '#') {
|
||
/*
|
||
* Attempt to parse the value portion.
|
||
*/
|
||
spec++;
|
||
n = strlen(spec);
|
||
if (n != 3 && n != 6 && n != 9 && n != 12) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
n /= 3;
|
||
g = b = 0;
|
||
do {
|
||
r = g;
|
||
g = b;
|
||
b = 0;
|
||
for (i = n; --i >= 0; ) {
|
||
c = *spec++;
|
||
b <<= 4;
|
||
if (c >= '0' && c <= '9')
|
||
b |= c - '0';
|
||
/* assume string in lowercase
|
||
else if (c >= 'A' && c <= 'F')
|
||
b |= c - ('A' - 10);
|
||
*/
|
||
else if (c >= 'a' && c <= 'f')
|
||
b |= c - ('a' - 10);
|
||
else return (XcmsFailure);
|
||
}
|
||
} while (*spec != '\0');
|
||
|
||
/*
|
||
* Succeeded !
|
||
*/
|
||
n <<= 2;
|
||
n = 16 - n;
|
||
/* shift instead of scale, to match old broken semantics */
|
||
pColor->spec.RGB.red = r << n;
|
||
pColor->spec.RGB.green = g << n;
|
||
pColor->spec.RGB.blue = b << n;
|
||
} else {
|
||
if ((pchar = strchr(spec, ':')) == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
n = (int)(pchar - spec);
|
||
|
||
/*
|
||
* Check for proper prefix.
|
||
*/
|
||
if (strncmp(spec, _XcmsRGB_prefix, n) != 0) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* Attempt to parse the value portion.
|
||
*/
|
||
spec += (n + 1);
|
||
pShort = &pColor->spec.RGB.red;
|
||
for (i = 0; i < 3; i++, pShort++, spec++) {
|
||
n = 0;
|
||
*pShort = 0;
|
||
while (*spec != '/' && *spec != '\0') {
|
||
if (++n > 4) {
|
||
return(XcmsFailure);
|
||
}
|
||
c = *spec++;
|
||
*pShort <<= 4;
|
||
if (c >= '0' && c <= '9')
|
||
*pShort |= c - '0';
|
||
/* assume string in lowercase
|
||
else if (c >= 'A' && c <= 'F')
|
||
*pShort |= c - ('A' - 10);
|
||
*/
|
||
else if (c >= 'a' && c <= 'f')
|
||
*pShort |= c - ('a' - 10);
|
||
else return (XcmsFailure);
|
||
}
|
||
if (n == 0)
|
||
return (XcmsFailure);
|
||
if (n < 4) {
|
||
*pShort = ((unsigned long)*pShort * 0xFFFF) / ((1 << n*4) - 1);
|
||
}
|
||
}
|
||
}
|
||
pColor->format = XcmsRGBFormat;
|
||
pColor->pixel = 0;
|
||
return (XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* XcmsLRGB_RGBi_ParseString
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
static int
|
||
XcmsLRGB_RGBi_ParseString(
|
||
register char *spec,
|
||
XcmsColor *pColor)
|
||
/*
|
||
* DESCRIPTION
|
||
* This routines takes a string and attempts to convert
|
||
* it into a XcmsColor structure with XcmsRGBiFormat.
|
||
* The assumed RGBi string syntax is:
|
||
* RGBi:<r>/<g>/<b>
|
||
* Where r, g, and b are in string input format for floats
|
||
* consisting of:
|
||
* a. an optional sign
|
||
* b. a string of numbers possibly containing a decimal point,
|
||
* c. an optional exponent field containing an 'E' or 'e'
|
||
* followed by a possibly signed integer string.
|
||
*
|
||
* RETURNS
|
||
* 0 if failed, non-zero otherwise.
|
||
*/
|
||
{
|
||
int n;
|
||
char *pchar;
|
||
|
||
if ((pchar = strchr(spec, ':')) == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
n = (int)(pchar - spec);
|
||
|
||
/*
|
||
* Check for proper prefix.
|
||
*/
|
||
if (strncmp(spec, _XcmsRGBi_prefix, n) != 0) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* Attempt to parse the value portion.
|
||
*/
|
||
if (sscanf(spec + n + 1, "%lf/%lf/%lf",
|
||
&pColor->spec.RGBi.red,
|
||
&pColor->spec.RGBi.green,
|
||
&pColor->spec.RGBi.blue) != 3) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* Succeeded !
|
||
*/
|
||
pColor->format = XcmsRGBiFormat;
|
||
pColor->pixel = 0;
|
||
return (XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* XcmsCIEXYZToRGBi - convert CIE XYZ to RGB
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
/* ARGSUSED */
|
||
Status
|
||
XcmsCIEXYZToRGBi(ccc, pXcmsColors_in_out, nColors, pCompressed)
|
||
XcmsCCC ccc;
|
||
XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert */
|
||
unsigned int nColors; /* Number of colors */
|
||
Bool *pCompressed; /* pointer to an array of Bool */
|
||
/*
|
||
* DESCRIPTION
|
||
* Converts color specifications in an array of XcmsColor
|
||
* structures from RGB format to RGBi format.
|
||
*
|
||
* RETURNS
|
||
* XcmsFailure if failed,
|
||
* XcmsSuccess if succeeded without gamut compression.
|
||
* XcmsSuccessWithCompression if succeeded with gamut
|
||
* compression.
|
||
*/
|
||
{
|
||
LINEAR_RGB_SCCData *pScreenData;
|
||
XcmsFloat tmp[3];
|
||
int hasCompressed = 0;
|
||
unsigned int i;
|
||
XcmsColor *pColor = pXcmsColors_in_out;
|
||
|
||
if (ccc == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
|
||
|
||
/*
|
||
* XcmsColors should be White Point Adjusted, if necessary, by now!
|
||
*/
|
||
|
||
/*
|
||
* NEW!!! for extended gamut compression
|
||
*
|
||
* 1. Need to zero out pCompressed
|
||
*
|
||
* 2. Need to save initial address of pColor
|
||
*
|
||
* 3. Need to save initial address of pCompressed
|
||
*/
|
||
|
||
for (i = 0; i < nColors; i++) {
|
||
|
||
/* Make sure format is XcmsCIEXYZFormat */
|
||
if (pColor->format != XcmsCIEXYZFormat) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/* Multiply [A]-1 * [XYZ] to get RGB intensity */
|
||
_XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix,
|
||
(XcmsFloat *) &pColor->spec, tmp);
|
||
|
||
if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) ||
|
||
(MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) {
|
||
|
||
/*
|
||
* RGBi out of screen's gamut
|
||
*/
|
||
|
||
if (ccc->gamutCompProc == NULL) {
|
||
/*
|
||
* Aha!! Here's that little trick that will allow
|
||
* gamut compression routines to get the out of bound
|
||
* RGBi.
|
||
*/
|
||
memcpy((char *)&pColor->spec, (char *)tmp, sizeof(tmp));
|
||
pColor->format = XcmsRGBiFormat;
|
||
return(XcmsFailure);
|
||
} else if ((*ccc->gamutCompProc)(ccc, pXcmsColors_in_out, nColors,
|
||
i, pCompressed) == 0) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
/*
|
||
* The gamut compression function should return colors in CIEXYZ
|
||
* Also check again to if the new color is within gamut.
|
||
*/
|
||
if (pColor->format != XcmsCIEXYZFormat) {
|
||
return(XcmsFailure);
|
||
}
|
||
_XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix,
|
||
(XcmsFloat *) &pColor->spec, tmp);
|
||
if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) ||
|
||
(MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) {
|
||
return(XcmsFailure);
|
||
}
|
||
hasCompressed++;
|
||
}
|
||
memcpy((char *)&pColor->spec, (char *)tmp, sizeof(tmp));
|
||
/* These if statements are done to ensure the fudge factor is */
|
||
/* is taken into account. */
|
||
if (pColor->spec.RGBi.red < 0.0) {
|
||
pColor->spec.RGBi.red = 0.0;
|
||
} else if (pColor->spec.RGBi.red > 1.0) {
|
||
pColor->spec.RGBi.red = 1.0;
|
||
}
|
||
if (pColor->spec.RGBi.green < 0.0) {
|
||
pColor->spec.RGBi.green = 0.0;
|
||
} else if (pColor->spec.RGBi.green > 1.0) {
|
||
pColor->spec.RGBi.green = 1.0;
|
||
}
|
||
if (pColor->spec.RGBi.blue < 0.0) {
|
||
pColor->spec.RGBi.blue = 0.0;
|
||
} else if (pColor->spec.RGBi.blue > 1.0) {
|
||
pColor->spec.RGBi.blue = 1.0;
|
||
}
|
||
(pColor++)->format = XcmsRGBiFormat;
|
||
}
|
||
return (hasCompressed ? XcmsSuccessWithCompression : XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* LINEAR_RGBi_to_CIEXYZ - convert RGBi to CIEXYZ
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
/* ARGSUSED */
|
||
Status
|
||
XcmsRGBiToCIEXYZ(ccc, pXcmsColors_in_out, nColors, pCompressed)
|
||
XcmsCCC ccc;
|
||
XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert */
|
||
unsigned int nColors; /* Number of colors */
|
||
Bool *pCompressed; /* pointer to a bit array */
|
||
/*
|
||
* DESCRIPTION
|
||
* Converts color specifications in an array of XcmsColor
|
||
* structures from RGBi format to CIEXYZ format.
|
||
*
|
||
* RETURNS
|
||
* XcmsFailure if failed,
|
||
* XcmsSuccess if succeeded.
|
||
*/
|
||
{
|
||
LINEAR_RGB_SCCData *pScreenData;
|
||
XcmsFloat tmp[3];
|
||
|
||
/*
|
||
* pCompressed ignored in this function.
|
||
*/
|
||
|
||
if (ccc == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
|
||
|
||
/*
|
||
* XcmsColors should be White Point Adjusted, if necessary, by now!
|
||
*/
|
||
|
||
while (nColors--) {
|
||
|
||
/* Multiply [A]-1 * [XYZ] to get RGB intensity */
|
||
_XcmsMatVec((XcmsFloat *) pScreenData->RGBtoXYZmatrix,
|
||
(XcmsFloat *) &pXcmsColors_in_out->spec, tmp);
|
||
|
||
memcpy((char *)&pXcmsColors_in_out->spec, (char *)tmp, sizeof(tmp));
|
||
(pXcmsColors_in_out++)->format = XcmsCIEXYZFormat;
|
||
}
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* XcmsRGBiToRGB
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
/* ARGSUSED */
|
||
Status
|
||
XcmsRGBiToRGB(ccc, pXcmsColors_in_out, nColors, pCompressed)
|
||
XcmsCCC ccc;
|
||
XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert */
|
||
unsigned int nColors; /* Number of colors */
|
||
Bool *pCompressed; /* pointer to a bit array */
|
||
/*
|
||
* DESCRIPTION
|
||
* Converts color specifications in an array of XcmsColor
|
||
* structures from RGBi format to RGB format.
|
||
*
|
||
* RETURNS
|
||
* XcmsFailure if failed,
|
||
* XcmsSuccess if succeeded without gamut compression.
|
||
* XcmsSuccessWithCompression if succeeded with gamut
|
||
* compression.
|
||
*/
|
||
{
|
||
LINEAR_RGB_SCCData *pScreenData;
|
||
XcmsRGB tmpRGB;
|
||
IntensityRec keyIRec, answerIRec;
|
||
|
||
/*
|
||
* pCompressed ignored in this function.
|
||
*/
|
||
|
||
if (ccc == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
|
||
|
||
while (nColors--) {
|
||
|
||
/* Make sure format is XcmsRGBiFormat */
|
||
if (pXcmsColors_in_out->format != XcmsRGBiFormat) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.red;
|
||
if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
|
||
(char *)pScreenData->pRedTbl->pBase,
|
||
(unsigned)pScreenData->pRedTbl->nEntries,
|
||
(unsigned)sizeof(IntensityRec),
|
||
(comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) {
|
||
return(XcmsFailure);
|
||
}
|
||
tmpRGB.red = answerIRec.value;
|
||
|
||
keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.green;
|
||
if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
|
||
(char *)pScreenData->pGreenTbl->pBase,
|
||
(unsigned)pScreenData->pGreenTbl->nEntries,
|
||
(unsigned)sizeof(IntensityRec),
|
||
(comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) {
|
||
return(XcmsFailure);
|
||
}
|
||
tmpRGB.green = answerIRec.value;
|
||
|
||
keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.blue;
|
||
if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
|
||
(char *)pScreenData->pBlueTbl->pBase,
|
||
(unsigned)pScreenData->pBlueTbl->nEntries,
|
||
(unsigned)sizeof(IntensityRec),
|
||
(comparProcp)_XcmsIntensityCmp, (interpolProcp)_XcmsIntensityInterpolation, (char *)&answerIRec)) {
|
||
return(XcmsFailure);
|
||
}
|
||
tmpRGB.blue = answerIRec.value;
|
||
|
||
memcpy((char *)&pXcmsColors_in_out->spec, (char *)&tmpRGB, sizeof(XcmsRGB));
|
||
(pXcmsColors_in_out++)->format = XcmsRGBFormat;
|
||
}
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME
|
||
* XcmsRGBToRGBi
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
/* ARGSUSED */
|
||
Status
|
||
XcmsRGBToRGBi(
|
||
XcmsCCC ccc,
|
||
XcmsColor *pXcmsColors_in_out,/* pointer to XcmsColors to convert */
|
||
unsigned int nColors, /* Number of colors */
|
||
Bool *pCompressed) /* pointer to a bit array */
|
||
/*
|
||
* DESCRIPTION
|
||
* Converts color specifications in an array of XcmsColor
|
||
* structures from RGB format to RGBi format.
|
||
*
|
||
* RETURNS
|
||
* XcmsFailure if failed,
|
||
* XcmsSuccess if succeeded.
|
||
*/
|
||
{
|
||
LINEAR_RGB_SCCData *pScreenData;
|
||
XcmsRGBi tmpRGBi;
|
||
IntensityRec keyIRec, answerIRec;
|
||
|
||
/*
|
||
* pCompressed ignored in this function.
|
||
*/
|
||
|
||
if (ccc == NULL) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
|
||
|
||
while (nColors--) {
|
||
|
||
/* Make sure format is XcmsRGBFormat */
|
||
if (pXcmsColors_in_out->format != XcmsRGBFormat) {
|
||
return(XcmsFailure);
|
||
}
|
||
|
||
keyIRec.value = pXcmsColors_in_out->spec.RGB.red;
|
||
if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
|
||
(char *)pScreenData->pRedTbl->pBase,
|
||
(unsigned)pScreenData->pRedTbl->nEntries,
|
||
(unsigned)sizeof(IntensityRec),
|
||
(comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) {
|
||
return(XcmsFailure);
|
||
}
|
||
tmpRGBi.red = answerIRec.intensity;
|
||
|
||
keyIRec.value = pXcmsColors_in_out->spec.RGB.green;
|
||
if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
|
||
(char *)pScreenData->pGreenTbl->pBase,
|
||
(unsigned)pScreenData->pGreenTbl->nEntries,
|
||
(unsigned)sizeof(IntensityRec),
|
||
(comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) {
|
||
return(XcmsFailure);
|
||
}
|
||
tmpRGBi.green = answerIRec.intensity;
|
||
|
||
keyIRec.value = pXcmsColors_in_out->spec.RGB.blue;
|
||
if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
|
||
(char *)pScreenData->pBlueTbl->pBase,
|
||
(unsigned)pScreenData->pBlueTbl->nEntries,
|
||
(unsigned)sizeof(IntensityRec),
|
||
(comparProcp)_XcmsValueCmp, (interpolProcp)_XcmsValueInterpolation, (char *)&answerIRec)) {
|
||
return(XcmsFailure);
|
||
}
|
||
tmpRGBi.blue = answerIRec.intensity;
|
||
|
||
memcpy((char *)&pXcmsColors_in_out->spec, (char *)&tmpRGBi, sizeof(XcmsRGBi));
|
||
(pXcmsColors_in_out++)->format = XcmsRGBiFormat;
|
||
}
|
||
return(XcmsSuccess);
|
||
}
|
||
|
||
/*
|
||
* NAME
|
||
* _XcmsInitScrnDefaultInfo
|
||
*
|
||
* SYNOPSIS
|
||
*/
|
||
/* ARGSUSED */
|
||
int
|
||
_XcmsLRGB_InitScrnDefault(
|
||
Display *dpy,
|
||
int screenNumber,
|
||
XcmsPerScrnInfo *pPerScrnInfo)
|
||
/*
|
||
* DESCRIPTION
|
||
* Given a display and screen number, this routine attempts
|
||
* to initialize the Xcms per Screen Info structure
|
||
* (XcmsPerScrnInfo) with defaults.
|
||
*
|
||
* RETURNS
|
||
* Returns zero if initialization failed; non-zero otherwise.
|
||
*/
|
||
{
|
||
pPerScrnInfo->screenData = (XPointer)&Default_RGB_SCCData;
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X =
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[0][0] +
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[0][1] +
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[0][2];
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y =
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[1][0] +
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[1][1] +
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[1][2];
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z =
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[2][0] +
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[2][1] +
|
||
Default_RGB_SCCData.RGBtoXYZmatrix[2][2];
|
||
if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) )
|
||
|| (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) {
|
||
pPerScrnInfo->screenData = (XPointer)NULL;
|
||
pPerScrnInfo->state = XcmsInitNone;
|
||
return(0);
|
||
}
|
||
pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0;
|
||
pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat;
|
||
pPerScrnInfo->screenWhitePt.pixel = 0;
|
||
pPerScrnInfo->functionSet = (XPointer)&XcmsLinearRGBFunctionSet;
|
||
pPerScrnInfo->state = XcmsInitFailure; /* default initialization */
|
||
return(1);
|
||
}
|