/* $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 #include #include #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:// * 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); }