#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include "Xlibint.h"
#include "Xcmsint.h"
#include "Cv.h"
#define EPS 0.001
#ifndef MIN
#define MIN(x,y) ((x) > (y) ? (y) : (x))
#endif
#ifndef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#endif
#ifndef MIN3
#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x))
#endif
#ifndef MAX3
#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z))))
#endif
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);
static unsigned short const MASK[17] = {
0x0000,
0x8000,
0xc000,
0xe000,
0xf000,
0xf800,
0xfc00,
0xfe00,
0xff00,
0xff80,
0xffc0,
0xffe0,
0xfff0,
0xfff8,
0xfffc,
0xfffe,
0xffff
};
static XcmsConversionProc Fl_RGB_to_CIEXYZ[] = {
(XcmsConversionProc)XcmsRGBToRGBi,
(XcmsConversionProc)XcmsRGBiToCIEXYZ,
NULL
};
static XcmsConversionProc Fl_CIEXYZ_to_RGB[] = {
(XcmsConversionProc)XcmsCIEXYZToRGBi,
(XcmsConversionProc)XcmsRGBiToRGB,
NULL
};
static XcmsConversionProc Fl_RGBi_to_CIEXYZ[] = {
(XcmsConversionProc)XcmsRGBiToCIEXYZ,
NULL
};
static XcmsConversionProc Fl_CIEXYZ_to_RGBi[] = {
(XcmsConversionProc)XcmsCIEXYZToRGBi,
NULL
};
XcmsColorSpace XcmsRGBiColorSpace =
{
_XcmsRGBi_prefix,
XcmsRGBiFormat,
XcmsLRGB_RGBi_ParseString,
Fl_RGBi_to_CIEXYZ,
Fl_CIEXYZ_to_RGBi,
1
};
XcmsColorSpace XcmsRGBColorSpace =
{
_XcmsRGB_prefix,
XcmsRGBFormat,
XcmsLRGB_RGB_ParseString,
Fl_RGB_to_CIEXYZ,
Fl_CIEXYZ_to_RGB,
1
};
static XcmsColorSpace *DDColorSpaces[] = {
&XcmsRGBColorSpace,
&XcmsRGBiColorSpace,
NULL
};
XcmsFunctionSet XcmsLinearRGBFunctionSet =
{
&DDColorSpaces[0],
LINEAR_RGB_InitSCCData,
LINEAR_RGB_FreeSCCData
};
static IntensityRec const Default_RGB_RedTuples[] = {
{ 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[] = {
{ 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[] = {
{ 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 *) Default_RGB_RedTuples,
52
};
static IntensityTbl Default_RGB_GreenTbl = {
(IntensityRec *)Default_RGB_GreenTuples,
50
};
static IntensityTbl Default_RGB_BlueTbl = {
(IntensityRec *)Default_RGB_BlueTuples,
51
};
static LINEAR_RGB_SCCData Default_RGB_SCCData = {
{
{ 3.48340481253539000, -1.52176374927285200, -0.55923133354049780 },
{-1.07152751306193600, 1.96593795204372400, 0.03673691339553462 },
{ 0.06351179790497788, -0.20020501000496480, 0.81070942031648220 }
},
{
{ 0.38106149108714790, 0.32025712365352110, 0.24834578525933100 },
{ 0.20729745115140850, 0.68054638776373240, 0.11215616108485920 },
{ 0.02133944350088028, 0.14297193020246480, 1.24172892629665500 }
},
&Default_RGB_RedTbl,
&Default_RGB_GreenTbl,
&Default_RGB_BlueTbl
};
static Status
LINEAR_RGB_InitSCCData(
Display *dpy,
int screenNumber,
XcmsPerScrnInfo *pPerScrnInfo)
{
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
VisualID visualID;
LINEAR_RGB_SCCData *pScreenData, *pScreenDefaultData;
XcmsIntensityMap *pNewMap;
if (!(pScreenData = pScreenDefaultData = (LINEAR_RGB_SCCData *)
Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
return(XcmsFailure);
}
if (MatrixAtom == None ||
!_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), MatrixAtom,
&format_return, &nitems, &nbytes_return, &property_return) ||
nitems != 18 || format_return != 32) {
goto FreeSCCData;
} else {
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];
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
}
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:
if (nitems < 9) {
Xfree ((char *)property_return);
goto FreeSCCData;
}
count = 3;
break;
case 16:
if (nitems < 7) {
Xfree ((char *)property_return);
goto FreeSCCData;
}
count = 1;
break;
case 32:
if (nitems < 6) {
Xfree ((char *)property_return);
goto FreeSCCData;
}
count = 0;
break;
default:
Xfree ((char *)property_return);
goto FreeSCCData;
}
visualID = _XcmsGetElement(format_return, &pChar, &nitems);
while (count--) {
visualID = visualID << format_return;
visualID |= _XcmsGetElement(format_return, &pChar, &nitems);
}
if (visualID == 0) {
pScreenData = pScreenDefaultData;
} else {
if (!(pScreenData = (LINEAR_RGB_SCCData *)
Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
return(XcmsFailure);
}
memcpy((char *)pScreenData, (char *)pScreenDefaultData,
18 * sizeof(XcmsFloat));
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) {
if (!(pScreenData->pRedTbl = (IntensityTbl *)
Xcalloc (1, sizeof(IntensityTbl)))) {
goto FreeSCCData;
}
if (_XcmsGetTableType0(pScreenData->pRedTbl, format_return, &pChar,
&nitems) == XcmsFailure) {
goto FreeRedTbl;
}
if (nTables == 1) {
pScreenData->pGreenTbl = pScreenData->pRedTbl;
pScreenData->pBlueTbl = pScreenData->pRedTbl;
} else {
if (!(pScreenData->pGreenTbl = (IntensityTbl *)
Xcalloc (1, sizeof(IntensityTbl)))) {
goto FreeRedTblElements;
}
if (_XcmsGetTableType0(pScreenData->pGreenTbl, format_return, &pChar,
&nitems) == XcmsFailure) {
goto FreeGreenTbl;
}
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) {
if (!(pScreenData->pRedTbl = (IntensityTbl *)
Xcalloc (1, sizeof(IntensityTbl)))) {
goto FreeSCCData;
}
if (_XcmsGetTableType1(pScreenData->pRedTbl, format_return, &pChar,
&nitems) == XcmsFailure) {
goto FreeRedTbl;
}
if (nTables == 1) {
pScreenData->pGreenTbl = pScreenData->pRedTbl;
pScreenData->pBlueTbl = pScreenData->pRedTbl;
} else {
if (!(pScreenData->pGreenTbl = (IntensityTbl *)
Xcalloc (1, sizeof(IntensityTbl)))) {
goto FreeRedTblElements;
}
if (_XcmsGetTableType1(pScreenData->pGreenTbl, format_return, &pChar,
&nitems) == XcmsFailure) {
goto FreeGreenTbl;
}
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
}
Xfree ((char *)property_return);
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);
}
static void
LINEAR_RGB_FreeSCCData(
XPointer pScreenDataTemp)
{
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);
}
}
static Status
_XcmsGetTableType0(
IntensityTbl *pTbl,
int format,
char **pChar,
unsigned long *pCount)
{
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++) {
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);
}
static Status
_XcmsGetTableType1(
IntensityTbl *pTbl,
int format,
char **pChar,
unsigned long *pCount)
{
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);
}
static int
_XcmsValueCmp(
IntensityRec *p1, IntensityRec *p2)
{
return (p1->value - p2->value);
}
static int
_XcmsIntensityCmp(
IntensityRec *p1, IntensityRec *p2)
{
if (p1->intensity < p2->intensity) {
return (-1);
}
if (p1->intensity > p2->intensity) {
return (XcmsSuccess);
}
return (XcmsFailure);
}
static int
_XcmsValueInterpolation(
IntensityRec *key, IntensityRec *lo, IntensityRec *hi, IntensityRec *answer,
int bitsPerRGB)
{
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);
}
static int
_XcmsIntensityInterpolation(
IntensityRec *key, IntensityRec *lo, IntensityRec *hi, IntensityRec *answer,
int bitsPerRGB)
{
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;
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);
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)
{
char *hi, *lo, *mid, *last;
int result;
last = hi = base + ((nel - 1) * nKeyPtrSize);
mid = lo = base;
((IntensityRec *)key)->value = ((unsigned long)
(((IntensityRec *)key)->value >> (16 - bitsPerRGB)) * 0xFFFF)
/ ((1 << bitsPerRGB) - 1);
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;
}
}
return ((*interpol)(key, lo, hi, answer, bitsPerRGB));
}
static void _XcmsMatVec(
XcmsFloat *pMat, XcmsFloat *pIn, XcmsFloat *pOut)
{
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];
}
}
static int
XcmsLRGB_RGB_ParseString(
register char *spec,
XcmsColor *pColor)
{
register int n, i;
unsigned short r, g, b;
char c;
char *pchar;
unsigned short *pShort;
if (*spec == '#') {
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';
else if (c >= 'a' && c <= 'f')
b |= c - ('a' - 10);
else return (XcmsFailure);
}
} while (*spec != '\0');
n <<= 2;
n = 16 - n;
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);
if (strncmp(spec, _XcmsRGB_prefix, n) != 0) {
return(XcmsFailure);
}
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';
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);
}
static int
XcmsLRGB_RGBi_ParseString(
register char *spec,
XcmsColor *pColor)
{
int n;
char *pchar;
if ((pchar = strchr(spec, ':')) == NULL) {
return(XcmsFailure);
}
n = (int)(pchar - spec);
if (strncmp(spec, _XcmsRGBi_prefix, n) != 0) {
return(XcmsFailure);
}
if (sscanf(spec + n + 1, "%lf/%lf/%lf",
&pColor->spec.RGBi.red,
&pColor->spec.RGBi.green,
&pColor->spec.RGBi.blue) != 3) {
char *s;
int f;
if ((s = strdup(spec))) {
for (f = 0; s[f]; ++f)
if (s[f] == '.')
s[f] = ',';
else if (s[f] == ',')
s[f] = '.';
if (sscanf(s + n + 1, "%lf/%lf/%lf",
&pColor->spec.RGBi.red,
&pColor->spec.RGBi.green,
&pColor->spec.RGBi.blue) != 3) {
free(s);
return(XcmsFailure);
}
free(s);
} else
return(XcmsFailure);
}
pColor->format = XcmsRGBiFormat;
pColor->pixel = 0;
return (XcmsSuccess);
}
Status
XcmsCIEXYZToRGBi(
XcmsCCC ccc,
XcmsColor *pXcmsColors_in_out,
unsigned int nColors,
Bool *pCompressed)
{
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;
for (i = 0; i < nColors; i++) {
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))) {
if (ccc->gamutCompProc == NULL) {
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);
}
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));
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);
}
Status
XcmsRGBiToCIEXYZ(
XcmsCCC ccc,
XcmsColor *pXcmsColors_in_out,
unsigned int nColors,
Bool *pCompressed)
{
LINEAR_RGB_SCCData *pScreenData;
XcmsFloat tmp[3];
if (ccc == NULL) {
return(XcmsFailure);
}
pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
while (nColors--) {
_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);
}
Status
XcmsRGBiToRGB(
XcmsCCC ccc,
XcmsColor *pXcmsColors_in_out,
unsigned int nColors,
Bool *pCompressed)
{
LINEAR_RGB_SCCData *pScreenData;
XcmsRGB tmpRGB;
IntensityRec keyIRec, answerIRec;
if (ccc == NULL) {
return(XcmsFailure);
}
pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
while (nColors--) {
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);
}
Status
XcmsRGBToRGBi(
XcmsCCC ccc,
XcmsColor *pXcmsColors_in_out,
unsigned int nColors,
Bool *pCompressed)
{
LINEAR_RGB_SCCData *pScreenData;
XcmsRGBi tmpRGBi;
IntensityRec keyIRec, answerIRec;
if (ccc == NULL) {
return(XcmsFailure);
}
pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
while (nColors--) {
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);
}
int
_XcmsLRGB_InitScrnDefault(
Display *dpy,
int screenNumber,
XcmsPerScrnInfo *pPerScrnInfo)
{
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;
return(1);
}