home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / lib / X / XcmsLRGB.c.orig < prev    next >
Encoding:
Text File  |  1991-08-21  |  45.3 KB  |  1,811 lines

  1. /* $XConsortium: XcmsLRGB.c,v 1.20 91/08/20 13:51:23 keith Exp $" */
  2.  
  3. /*
  4.  * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
  5.  *     All Rights Reserved
  6.  * 
  7.  * This file is a component of an X Window System-specific implementation
  8.  * of Xcms based on the TekColor Color Management System.  Permission is
  9.  * hereby granted to use, copy, modify, sell, and otherwise distribute this
  10.  * software and its documentation for any purpose and without fee, provided
  11.  * that this copyright, permission, and disclaimer notice is reproduced in
  12.  * all copies of this software and in supporting documentation.  TekColor
  13.  * is a trademark of Tektronix, Inc.
  14.  * 
  15.  * Tektronix makes no representation about the suitability of this software
  16.  * for any purpose.  It is provided "as is" and with all faults.
  17.  * 
  18.  * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
  19.  * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  20.  * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
  21.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  22.  * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
  23.  * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  24.  * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
  25.  *
  26.  *
  27.  *    NAME
  28.  *        XcmsLRGB.c
  29.  *
  30.  *    DESCRIPTION
  31.  *        This file contains the conversion routines:
  32.  *            1. CIE XYZ to RGB intensity
  33.  *            2. RGB intensity to device RGB
  34.  *            3. device RGB to RGB intensity
  35.  *            4. RGB intensity to CIE XYZ
  36.  *
  37.  */
  38.  
  39. #include <stdio.h>
  40. #include <X11/Xos.h>
  41. #include <X11/Xatom.h>
  42. #include "Xlibint.h"
  43. #include "Xcmsint.h"
  44.  
  45. #if __STDC__
  46. #define Const const
  47. #else
  48. #define Const /**/
  49. #endif
  50.  
  51. /*
  52.  *      EXTERNS
  53.  *              External declarations required locally to this package
  54.  *              that are not already declared in any of the included header
  55.  *        files (external includes or internal includes).
  56.  */
  57. extern char XcmsRGB_prefix[];
  58. extern char XcmsRGBi_prefix[];
  59. extern unsigned long _XcmsGetElement();
  60. extern void _XcmsFreeIntensityMaps();
  61.  
  62.  
  63. /*
  64.  *      LOCAL DEFINES
  65.  *        #define declarations local to this package.
  66.  */
  67. #define EPS    0.001
  68. #ifndef MIN
  69. #define MIN(x,y) ((x) > (y) ? (y) : (x))
  70. #endif /* MIN */
  71. #ifndef MAX
  72. #define MAX(x,y) ((x) > (y) ? (x) : (y))
  73. #endif /* MAX */
  74. #ifndef MIN3
  75. #define MIN3(x,y,z) (MIN(x, MIN(y, z)))
  76. #endif /* MIN3 */
  77. #ifndef MAX3
  78. #define MAX3(x,y,z) (MAX(x, MAX(y, z)))
  79. #endif /* MAX3 */
  80.  
  81. /*
  82.  *      LOCAL TYPEDEFS
  83.  *              typedefs local to this package (for use with local vars).
  84.  *
  85.  */
  86.  
  87. /*
  88.  *      FORWARD DECLARATIONS
  89.  */
  90. static void LINEAR_RGB_FreeSCCData();
  91. static int LINEAR_RGB_InitSCCData();
  92. int XcmsLRGB_RGB_ParseString();
  93. int XcmsLRGB_RGBi_ParseString();
  94. Status _XcmsGetTableType0();
  95. Status _XcmsGetTableType1();
  96.  
  97. /*
  98.  *      LOCALS VARIABLES
  99.  *        Variables local to this package.
  100.  *            Usage example:
  101.  *                static int    ExampleLocalVar;
  102.  */
  103.  
  104. static unsigned short Const MASK[17] = {
  105.     0x0000,    /*  0 bitsPerRGB */
  106.     0x8000,    /*  1 bitsPerRGB */
  107.     0xc000,    /*  2 bitsPerRGB */
  108.     0xe000,    /*  3 bitsPerRGB */
  109.     0xf000,    /*  4 bitsPerRGB */
  110.     0xf800,    /*  5 bitsPerRGB */
  111.     0xfc00,    /*  6 bitsPerRGB */
  112.     0xfe00,    /*  7 bitsPerRGB */
  113.     0xff00,    /*  8 bitsPerRGB */
  114.     0xff80,    /*  9 bitsPerRGB */
  115.     0xffc0,    /* 10 bitsPerRGB */
  116.     0xffe0,    /* 11 bitsPerRGB */
  117.     0xfff0,    /* 12 bitsPerRGB */
  118.     0xfff8,    /* 13 bitsPerRGB */
  119.     0xfffc,    /* 14 bitsPerRGB */
  120.     0xfffe,    /* 15 bitsPerRGB */
  121.     0xffff    /* 16 bitsPerRGB */
  122. };
  123.  
  124.  
  125.     /*
  126.      * A NULL terminated array of function pointers that when applied
  127.      * in series will convert an XcmsColor structure from XcmsRGBFormat
  128.      * to XcmsCIEXYZFormat.
  129.      */
  130. static XcmsConversionProc Fl_RGB_to_CIEXYZ[] = {
  131.     XcmsRGBToRGBi,
  132.     XcmsRGBiToCIEXYZ,
  133.     NULL
  134. };
  135.  
  136.     /*
  137.      * A NULL terminated array of function pointers that when applied
  138.      * in series will convert an XcmsColor structure from XcmsCIEXYZFormat
  139.      * to XcmsRGBFormat.
  140.      */
  141. static XcmsConversionProc Fl_CIEXYZ_to_RGB[] = {
  142.     XcmsCIEXYZToRGBi,
  143.     XcmsRGBiToRGB,
  144.     NULL
  145. };
  146.  
  147.     /*
  148.      * A NULL terminated array of function pointers that when applied
  149.      * in series will convert an XcmsColor structure from XcmsRGBiFormat
  150.      * to XcmsCIEXYZFormat.
  151.      */
  152. static XcmsConversionProc Fl_RGBi_to_CIEXYZ[] = {
  153.     XcmsRGBiToCIEXYZ,
  154.     NULL
  155. };
  156.  
  157.     /*
  158.      * A NULL terminated array of function pointers that when applied
  159.      * in series will convert an XcmsColor structure from XcmsCIEXYZFormat
  160.      * to XcmsRGBiFormat.
  161.      */
  162. static XcmsConversionProc Fl_CIEXYZ_to_RGBi[] = {
  163.     XcmsCIEXYZToRGBi,
  164.     NULL
  165. };
  166.  
  167.     /*
  168.      * RGBi Color Spaces
  169.      */
  170. XcmsColorSpace    XcmsRGBiColorSpace =
  171.     {
  172.     XcmsRGBi_prefix,    /* prefix */
  173.     XcmsRGBiFormat,        /* id */
  174.     XcmsLRGB_RGBi_ParseString,    /* parseString */
  175.     Fl_RGBi_to_CIEXYZ,    /* to_CIEXYZ */
  176.     Fl_CIEXYZ_to_RGBi,    /* from_CIEXYZ */
  177.     1
  178.     };
  179.  
  180.     /*
  181.      * RGB Color Spaces
  182.      */
  183. XcmsColorSpace    XcmsRGBColorSpace =
  184.     {
  185.     XcmsRGB_prefix,        /* prefix */
  186.     XcmsRGBFormat,        /* id */
  187.     XcmsLRGB_RGB_ParseString,    /* parseString */
  188.     Fl_RGB_to_CIEXYZ,    /* to_CIEXYZ */
  189.     Fl_CIEXYZ_to_RGB,    /* from_CIEXYZ */
  190.     1
  191.     };
  192.  
  193.     /*
  194.      * Device-Independent Color Spaces known to the 
  195.      * LINEAR_RGB Screen Color Characteristics Function Set.
  196.      */
  197. static XcmsColorSpace    *DDColorSpaces[] = {
  198.     &XcmsRGBColorSpace,
  199.     &XcmsRGBiColorSpace,
  200.     NULL
  201. };
  202.  
  203.  
  204. /*
  205.  *      GLOBALS
  206.  *              Variables declared in this package that are allowed
  207.  *        to be used globally.
  208.  */
  209.  
  210.     /*
  211.      * LINEAR_RGB Screen Color Characteristics Function Set.
  212.      */
  213. XcmsFunctionSet    XcmsLinearRGBFunctionSet =
  214.     {
  215.     &DDColorSpaces[0],    /* pDDColorSpaces */
  216.     LINEAR_RGB_InitSCCData,    /* pInitScrnFunc */
  217.     LINEAR_RGB_FreeSCCData    /* pFreeSCCData */
  218.     };
  219.  
  220. /*
  221.  *    DESCRIPTION
  222.  *        Contents of Default SCCData should be replaced if other
  223.  *        data should be used as default.
  224.  *
  225.  *
  226.  */
  227.  
  228. /*
  229.  * NAME        Tektronix 19" (Sony) CRT
  230.  * PART_NUMBER        119-2451-00
  231.  * MODEL        Tek4300, Tek4800
  232.  */
  233.  
  234. static IntensityRec Const Default_RGB_RedTuples[] = {
  235.     /* {unsigned short value, XcmsFloat intensity} */
  236.             0x0000,    0.000000,
  237.             0x0909,    0.000000,
  238.             0x0a0a,    0.000936,
  239.             0x0f0f,    0.001481,
  240.             0x1414,    0.002329,
  241.             0x1919,    0.003529,
  242.             0x1e1e,    0.005127,
  243.             0x2323,    0.007169,
  244.             0x2828,    0.009699,
  245.             0x2d2d,    0.012759,
  246.             0x3232,    0.016392,
  247.             0x3737,    0.020637,
  248.             0x3c3c,    0.025533,
  249.             0x4141,    0.031119,
  250.             0x4646,    0.037431,
  251.             0x4b4b,    0.044504,
  252.             0x5050,    0.052373,
  253.             0x5555,    0.061069,
  254.             0x5a5a,    0.070624,
  255.             0x5f5f,    0.081070,
  256.             0x6464,    0.092433,
  257.             0x6969,    0.104744,
  258.             0x6e6e,    0.118026,
  259.             0x7373,    0.132307,
  260.             0x7878,    0.147610,
  261.             0x7d7d,    0.163958,
  262.             0x8282,    0.181371,
  263.             0x8787,    0.199871,
  264.             0x8c8c,    0.219475,
  265.             0x9191,    0.240202,
  266.             0x9696,    0.262069,
  267.             0x9b9b,    0.285089,
  268.             0xa0a0,    0.309278,
  269.             0xa5a5,    0.334647,
  270.             0xaaaa,    0.361208,
  271.             0xafaf,    0.388971,
  272.             0xb4b4,    0.417945,
  273.             0xb9b9,    0.448138,
  274.             0xbebe,    0.479555,
  275.             0xc3c3,    0.512202,
  276.             0xc8c8,    0.546082,
  277.             0xcdcd,    0.581199,
  278.             0xd2d2,    0.617552,
  279.             0xd7d7,    0.655144,
  280.             0xdcdc,    0.693971,
  281.             0xe1e1,    0.734031,
  282.             0xe6e6,    0.775322,
  283.             0xebeb,    0.817837,
  284.             0xf0f0,    0.861571,
  285.             0xf5f5,    0.906515,
  286.             0xfafa,    0.952662,
  287.             0xffff,    1.000000
  288. };
  289.  
  290. static IntensityRec Const Default_RGB_GreenTuples[] = {
  291.     /* {unsigned short value, XcmsFloat intensity} */
  292.             0x0000,    0.000000,
  293.             0x1313,    0.000000,
  294.             0x1414,    0.000832,
  295.             0x1919,    0.001998,
  296.             0x1e1e,    0.003612,
  297.             0x2323,    0.005736,
  298.             0x2828,    0.008428,
  299.             0x2d2d,    0.011745,
  300.             0x3232,    0.015740,
  301.             0x3737,    0.020463,
  302.             0x3c3c,    0.025960,
  303.             0x4141,    0.032275,
  304.             0x4646,    0.039449,
  305.             0x4b4b,    0.047519,
  306.             0x5050,    0.056520,
  307.             0x5555,    0.066484,
  308.             0x5a5a,    0.077439,
  309.             0x5f5f,    0.089409,
  310.             0x6464,    0.102418,
  311.             0x6969,    0.116485,
  312.             0x6e6e,    0.131625,
  313.             0x7373,    0.147853,
  314.             0x7878,    0.165176,
  315.             0x7d7d,    0.183604,
  316.             0x8282,    0.203140,
  317.             0x8787,    0.223783,
  318.             0x8c8c,    0.245533,
  319.             0x9191,    0.268384,
  320.             0x9696,    0.292327,
  321.             0x9b9b,    0.317351,
  322.             0xa0a0,    0.343441,
  323.             0xa5a5,    0.370580,
  324.             0xaaaa,    0.398747,
  325.             0xafaf,    0.427919,
  326.             0xb4b4,    0.458068,
  327.             0xb9b9,    0.489165,
  328.             0xbebe,    0.521176,
  329.             0xc3c3,    0.554067,
  330.             0xc8c8,    0.587797,
  331.             0xcdcd,    0.622324,
  332.             0xd2d2,    0.657604,
  333.             0xd7d7,    0.693588,
  334.             0xdcdc,    0.730225,
  335.             0xe1e1,    0.767459,
  336.             0xe6e6,    0.805235,
  337.             0xebeb,    0.843491,
  338.             0xf0f0,    0.882164,
  339.             0xf5f5,    0.921187,
  340.             0xfafa,    0.960490,
  341.             0xffff,    1.000000
  342. };
  343.  
  344. static IntensityRec Const Default_RGB_BlueTuples[] = {
  345.     /* {unsigned short value, XcmsFloat intensity} */
  346.             0x0000,    0.000000,
  347.             0x0e0e,    0.000000,
  348.             0x0f0f,    0.001341,
  349.             0x1414,    0.002080,
  350.             0x1919,    0.003188,
  351.             0x1e1e,    0.004729,
  352.             0x2323,    0.006766,
  353.             0x2828,    0.009357,
  354.             0x2d2d,    0.012559,
  355.             0x3232,    0.016424,
  356.             0x3737,    0.021004,
  357.             0x3c3c,    0.026344,
  358.             0x4141,    0.032489,
  359.             0x4646,    0.039481,
  360.             0x4b4b,    0.047357,
  361.             0x5050,    0.056154,
  362.             0x5555,    0.065903,
  363.             0x5a5a,    0.076634,
  364.             0x5f5f,    0.088373,
  365.             0x6464,    0.101145,
  366.             0x6969,    0.114968,
  367.             0x6e6e,    0.129862,
  368.             0x7373,    0.145841,
  369.             0x7878,    0.162915,
  370.             0x7d7d,    0.181095,
  371.             0x8282,    0.200386,
  372.             0x8787,    0.220791,
  373.             0x8c8c,    0.242309,
  374.             0x9191,    0.264937,
  375.             0x9696,    0.288670,
  376.             0x9b9b,    0.313499,
  377.             0xa0a0,    0.339410,
  378.             0xa5a5,    0.366390,
  379.             0xaaaa,    0.394421,
  380.             0xafaf,    0.423481,
  381.             0xb4b4,    0.453547,
  382.             0xb9b9,    0.484592,
  383.             0xbebe,    0.516587,
  384.             0xc3c3,    0.549498,
  385.             0xc8c8,    0.583291,
  386.             0xcdcd,    0.617925,
  387.             0xd2d2,    0.653361,
  388.             0xd7d7,    0.689553,
  389.             0xdcdc,    0.726454,
  390.             0xe1e1,    0.764013,
  391.             0xe6e6,    0.802178,
  392.             0xebeb,    0.840891,
  393.             0xf0f0,    0.880093,
  394.             0xf5f5,    0.919723,
  395.             0xfafa,    0.959715,
  396.             0xffff,    1.00000
  397. };
  398.  
  399. static IntensityTbl Default_RGB_RedTbl = {
  400.     /* IntensityRec *pBase */
  401.     (IntensityRec *) Default_RGB_RedTuples,
  402.     /* unsigned int nEntries */
  403.     52
  404. };
  405.  
  406. static IntensityTbl Default_RGB_GreenTbl = {
  407.     /* IntensityRec *pBase */
  408.     (IntensityRec *)Default_RGB_GreenTuples,
  409.     /* unsigned int nEntries */
  410.     50
  411. };
  412.  
  413. static IntensityTbl Default_RGB_BlueTbl = {
  414.     /* IntensityRec *pBase */
  415.     (IntensityRec *)Default_RGB_BlueTuples,
  416.     /* unsigned int nEntries */
  417.     51
  418. };
  419.  
  420. static LINEAR_RGB_SCCData Default_RGB_SCCData = {
  421.  
  422.     /* XcmsFloat XYZtoRGBmatrix[3][3] */
  423.        3.48340481253539000, -1.52176374927285200, -0.55923133354049780,
  424.       -1.07152751306193600,  1.96593795204372400,  0.03673691339553462,
  425.        0.06351179790497788, -0.20020501000496480,  0.81070942031648220,
  426.  
  427.     /* XcmsFloat RGBtoXYZmatrix[3][3] */
  428.        0.38106149108714790, 0.32025712365352110, 0.24834578525933100,
  429.        0.20729745115140850, 0.68054638776373240, 0.11215616108485920,
  430.        0.02133944350088028, 0.14297193020246480, 1.24172892629665500,
  431.  
  432.     /* IntensityTbl *pRedTbl */
  433.     &Default_RGB_RedTbl,
  434.  
  435.     /* IntensityTbl *pGreenTbl */
  436.     &Default_RGB_GreenTbl,
  437.  
  438.     /* IntensityTbl *pBlueTbl */
  439.     &Default_RGB_BlueTbl
  440. };
  441.  
  442. /************************************************************************
  443.  *                                    *
  444.  *            PRIVATE ROUTINES                *
  445.  *                                    *
  446.  ************************************************************************/
  447.  
  448. /*
  449.  *    NAME
  450.  *        LINEAR_RGB_InitSCCData()
  451.  *
  452.  *    SYNOPSIS
  453.  */
  454. static Status
  455. LINEAR_RGB_InitSCCData(dpy, screenNumber, pPerScrnInfo)
  456.     Display *dpy;
  457.     int screenNumber;
  458.     XcmsPerScrnInfo *pPerScrnInfo;
  459. /*
  460.  *    DESCRIPTION
  461.  *
  462.  *    RETURNS
  463.  *        XcmsFailure if failed.
  464.  *        XcmsSuccess if succeeded.
  465.  *
  466.  */
  467. {
  468.     Atom  CorrectAtom = XInternAtom (dpy, XDCCC_CORRECT_ATOM_NAME, True);
  469.     Atom  MatrixAtom  = XInternAtom (dpy, XDCCC_MATRIX_ATOM_NAME, True);
  470.     int      format_return, count, cType, nTables;
  471.     unsigned long nitems, nbytes_return;
  472.     char *property_return, *pChar;
  473.     XcmsFloat *pValue;
  474. #ifdef ALLDEBUG
  475.     IntensityRec *pIRec;
  476. #endif /* ALLDEBUG */
  477.     VisualID visualID;
  478.  
  479.     LINEAR_RGB_SCCData *pScreenData, *pScreenDefaultData;
  480.     XcmsIntensityMap *pNewMap;
  481.  
  482.     /*
  483.      * Allocate memory for pScreenData
  484.      */
  485.     if (!(pScreenData = pScreenDefaultData = (LINEAR_RGB_SCCData *) 
  486.               Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
  487.     return(XcmsFailure);
  488.     }
  489.  
  490.     /* 
  491.      *  1. Get the XYZ->RGB and RGB->XYZ matrices
  492.      */
  493.  
  494.     if (MatrixAtom == None ||
  495.     !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), MatrixAtom, 
  496.        &format_return, &nitems, &nbytes_return, &property_return) ||
  497.        nitems != 18 || format_return != 32) {
  498.     /*
  499.      * As per the XDCCC, there must be 18 data items and each must be
  500.      * in 32 bits !
  501.      */
  502.     goto FreeSCCData;
  503.  
  504.     } else {
  505.  
  506.     /*
  507.      * RGBtoXYZ and XYZtoRGB matrices
  508.      */
  509.     pValue = (XcmsFloat *) pScreenData;
  510.     pChar = property_return;
  511.     for (count = 0; count < 18; count++) {
  512.         *pValue++ = (long)_XcmsGetElement(format_return, &pChar,
  513.             &nitems) / (XcmsFloat)XDCCC_NUMBER;
  514.     }
  515.     XFree (property_return);
  516.     pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X =
  517.         pScreenData->RGBtoXYZmatrix[0][0] +
  518.         pScreenData->RGBtoXYZmatrix[0][1] +
  519.         pScreenData->RGBtoXYZmatrix[0][2];
  520.     pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y =
  521.         pScreenData->RGBtoXYZmatrix[1][0] +
  522.         pScreenData->RGBtoXYZmatrix[1][1] +
  523.         pScreenData->RGBtoXYZmatrix[1][2];
  524.     pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z =
  525.         pScreenData->RGBtoXYZmatrix[2][0] +
  526.         pScreenData->RGBtoXYZmatrix[2][1] +
  527.         pScreenData->RGBtoXYZmatrix[2][2];
  528.  
  529.     /*
  530.      * Compute the Screen White Point
  531.      */
  532.     if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) )
  533.         || (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) {
  534.         goto FreeSCCData;
  535.     } else {
  536.         pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0;
  537.     }
  538.     pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat;
  539.     pPerScrnInfo->screenWhitePt.pixel = 0;
  540.  
  541. #ifdef PDEBUG
  542.     printf ("RGB to XYZ Matrix values:\n");
  543.     printf ("       %f %f %f\n       %f %f %f\n       %f %f %f\n",
  544.         pScreenData->RGBtoXYZmatrix[0][0],
  545.         pScreenData->RGBtoXYZmatrix[0][1],
  546.         pScreenData->RGBtoXYZmatrix[0][2],
  547.         pScreenData->RGBtoXYZmatrix[1][0],
  548.         pScreenData->RGBtoXYZmatrix[1][1],
  549.         pScreenData->RGBtoXYZmatrix[1][2],
  550.         pScreenData->RGBtoXYZmatrix[2][0],
  551.         pScreenData->RGBtoXYZmatrix[2][1],
  552.         pScreenData->RGBtoXYZmatrix[2][2]);
  553.     printf ("XYZ to RGB Matrix values:\n");
  554.     printf ("       %f %f %f\n       %f %f %f\n       %f %f %f\n",
  555.         pScreenData->XYZtoRGBmatrix[0][0],
  556.         pScreenData->XYZtoRGBmatrix[0][1],
  557.         pScreenData->XYZtoRGBmatrix[0][2],
  558.         pScreenData->XYZtoRGBmatrix[1][0],
  559.         pScreenData->XYZtoRGBmatrix[1][1],
  560.         pScreenData->XYZtoRGBmatrix[1][2],
  561.         pScreenData->XYZtoRGBmatrix[2][0],
  562.         pScreenData->XYZtoRGBmatrix[2][1],
  563.         pScreenData->XYZtoRGBmatrix[2][2]);
  564.     printf ("Screen White Pt value: %f %f %f\n",
  565.         pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X,
  566.         pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y,
  567.         pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z);
  568. #endif /* PDEBUG */
  569.     }
  570.  
  571.     /*
  572.      *    2. Get the Intensity Profile
  573.      */
  574.     if (CorrectAtom == None ||
  575.     !_XcmsGetProperty (dpy, RootWindow(dpy, screenNumber), CorrectAtom,
  576.        &format_return, &nitems, &nbytes_return, &property_return)) {
  577.     XFree (property_return);
  578.     goto FreeSCCData;
  579.     }
  580.  
  581.     pChar = property_return;
  582.  
  583.     while (nitems) {
  584.     switch (format_return) {
  585.       case 8:
  586.         /*
  587.          * Must have at least:
  588.          *        VisualID0
  589.          *        VisualID1
  590.          *        VisualID2
  591.          *        VisualID3
  592.          *        type
  593.          *        count
  594.          *        length
  595.          *        intensity1
  596.          *        intensity2
  597.          */
  598.         if (nitems < 9) {
  599.         XFree (property_return);
  600.         goto FreeSCCData;
  601.         }
  602.         count = 3;
  603.         break;
  604.       case 16:
  605.         /*
  606.          * Must have at least:
  607.          *        VisualID0
  608.          *        VisualID3
  609.          *        type
  610.          *        count
  611.          *        length
  612.          *        intensity1
  613.          *        intensity2
  614.          */
  615.         if (nitems < 7) {
  616.         XFree (property_return);
  617.         goto FreeSCCData;
  618.         }
  619.         count = 1;
  620.         break;
  621.       case 32:
  622.         /*
  623.          * Must have at least:
  624.          *        VisualID0
  625.          *        type
  626.          *        count
  627.          *        length
  628.          *        intensity1
  629.          *        intensity2
  630.          */
  631.         if (nitems < 6) {
  632.         XFree (property_return);
  633.         goto FreeSCCData;
  634.         }
  635.         count = 0;
  636.         break;
  637.       default:
  638.         XFree (property_return);
  639.         goto FreeSCCData;
  640.         break;
  641.     }
  642.  
  643.     /*
  644.      * Get VisualID
  645.      */
  646.     visualID = _XcmsGetElement(format_return, &pChar, &nitems);
  647.     while (count--) {
  648.         visualID = visualID << format_return;
  649.         visualID |= _XcmsGetElement(format_return, &pChar, &nitems);
  650.     }
  651.  
  652.     if (visualID == 0) {
  653.         /*
  654.          * This is a shared intensity table
  655.          */
  656.         pScreenData = pScreenDefaultData;
  657.     } else {
  658.         /*
  659.          * This is a per-Visual intensity table
  660.          */
  661.         if (!(pScreenData = (LINEAR_RGB_SCCData *) 
  662.                   Xcalloc (1, sizeof(LINEAR_RGB_SCCData)))) {
  663.         return(XcmsFailure);
  664.         }
  665.         /* copy matrices */
  666.         bcopy((char *)pScreenDefaultData, (char *)pScreenData,
  667.             18 * sizeof(XcmsFloat));
  668.  
  669.         /* Create, initialize, and add map */
  670.         if (!(pNewMap = (XcmsIntensityMap *) 
  671.                   Xcalloc (1, sizeof(XcmsIntensityMap)))) {
  672.         Xfree(pScreenData);
  673.         return(XcmsFailure);
  674.         }
  675.         pNewMap->visualID = visualID;
  676.         pNewMap->screenData = (XPointer)pScreenData;
  677.         pNewMap->pFreeScreenData = LINEAR_RGB_FreeSCCData;
  678.         pNewMap->pNext =
  679.             (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps;
  680.         dpy->cms.perVisualIntensityMaps = (XPointer)pNewMap;
  681.         dpy->free_funcs->intensityMaps = _XcmsFreeIntensityMaps;
  682.     }
  683.  
  684.     cType = _XcmsGetElement(format_return, &pChar, &nitems);
  685.     nTables = _XcmsGetElement(format_return, &pChar, &nitems);
  686.  
  687.     if (cType == 0) {
  688.  
  689.         /* Red Intensity Table */
  690.         if (!(pScreenData->pRedTbl = (IntensityTbl *)
  691.             Xcalloc (1, sizeof(IntensityTbl)))) {
  692.         goto FreeSCCData;
  693.         }
  694.         if (_XcmsGetTableType0(pScreenData->pRedTbl, format_return, &pChar,
  695.             &nitems) == XcmsFailure) {
  696.         goto FreeRedTbl;
  697.         }
  698.  
  699.         if (nTables == 1) {
  700.         /* Green Intensity Table */
  701.         pScreenData->pGreenTbl = pScreenData->pRedTbl;
  702.         /* Blue Intensity Table */
  703.         pScreenData->pBlueTbl = pScreenData->pRedTbl;
  704.         } else {
  705.         /* Green Intensity Table */
  706.         if (!(pScreenData->pGreenTbl = (IntensityTbl *)
  707.             Xcalloc (1, sizeof(IntensityTbl)))) {
  708.             goto FreeRedTblElements;
  709.         }
  710.         if (_XcmsGetTableType0(pScreenData->pGreenTbl, format_return, &pChar,
  711.             &nitems) == XcmsFailure) {
  712.             goto FreeGreenTbl;
  713.         }
  714.  
  715.         /* Blue Intensity Table */
  716.         if (!(pScreenData->pBlueTbl = (IntensityTbl *)
  717.             Xcalloc (1, sizeof(IntensityTbl)))) {
  718.             goto FreeGreenTblElements;
  719.         }
  720.         if (_XcmsGetTableType0(pScreenData->pBlueTbl, format_return, &pChar,
  721.             &nitems) == XcmsFailure) {
  722.             goto FreeBlueTbl;
  723.         }
  724.         }        
  725.     } else if (cType == 1) {
  726.         /* Red Intensity Table */
  727.         if (!(pScreenData->pRedTbl = (IntensityTbl *)
  728.             Xcalloc (1, sizeof(IntensityTbl)))) {
  729.         goto FreeSCCData;
  730.         }
  731.         if (_XcmsGetTableType1(pScreenData->pRedTbl, format_return, &pChar,
  732.             &nitems) == XcmsFailure) {
  733.         goto FreeRedTbl;
  734.         }
  735.  
  736.         if (nTables == 1) {
  737.  
  738.         /* Green Intensity Table */
  739.         pScreenData->pGreenTbl = pScreenData->pRedTbl;
  740.         /* Blue Intensity Table */
  741.         pScreenData->pBlueTbl = pScreenData->pRedTbl;
  742.  
  743.         } else {
  744.  
  745.         /* Green Intensity Table */
  746.         if (!(pScreenData->pGreenTbl = (IntensityTbl *)
  747.             Xcalloc (1, sizeof(IntensityTbl)))) {
  748.             goto FreeRedTblElements;
  749.         }
  750.         if (_XcmsGetTableType1(pScreenData->pGreenTbl, format_return, &pChar,
  751.             &nitems) == XcmsFailure) {
  752.             goto FreeGreenTbl;
  753.         }
  754.  
  755.         /* Blue Intensity Table */
  756.         if (!(pScreenData->pBlueTbl = (IntensityTbl *)
  757.             Xcalloc (1, sizeof(IntensityTbl)))) {
  758.             goto FreeBlueTblElements;
  759.         }
  760.         if (_XcmsGetTableType1(pScreenData->pBlueTbl, format_return, &pChar,
  761.             &nitems) == XcmsFailure) {
  762.             goto FreeBlueTbl;
  763.         }
  764.         }
  765.     } else {
  766.         XFree (property_return);
  767.         goto FreeSCCData;
  768.     }
  769.  
  770. #ifdef ALLDEBUG
  771.     printf ("Intensity Table  RED    %d\n", pScreenData->pRedTbl->nEntries);
  772.     pIRec = (IntensityRec *) pScreenData->pRedTbl->pBase;
  773.     for (count = 0; count < pScreenData->pRedTbl->nEntries; count++, pIRec++) {
  774.         printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
  775.     }
  776.     if (pScreenData->pGreenTbl->pBase != pScreenData->pRedTbl->pBase) {
  777.         printf ("Intensity Table  GREEN  %d\n", pScreenData->pGreenTbl->nEntries);
  778.         pIRec = (IntensityRec *)pScreenData->pGreenTbl->pBase;
  779.         for (count = 0; count < pScreenData->pGreenTbl->nEntries; count++, pIRec++) {
  780.         printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
  781.         }
  782.     }
  783.     if (pScreenData->pBlueTbl->pBase != pScreenData->pRedTbl->pBase) {
  784.         printf ("Intensity Table  BLUE   %d\n", pScreenData->pBlueTbl->nEntries);
  785.         pIRec = (IntensityRec *) pScreenData->pBlueTbl->pBase;
  786.         for (count = 0; count < pScreenData->pBlueTbl->nEntries; count++, pIRec++) {
  787.         printf ("\t0x%4x\t%f\n", pIRec->value, pIRec->intensity);
  788.         }
  789.     }
  790. #endif /* ALLDEBUG */
  791.     }
  792.  
  793.     XFree (property_return);
  794.  
  795.     /* Free the old memory and use the new structure created. */
  796.     LINEAR_RGB_FreeSCCData((LINEAR_RGB_SCCData *) pPerScrnInfo->screenData);
  797.  
  798.     pPerScrnInfo->functionSet = (XPointer) &XcmsLinearRGBFunctionSet;
  799.  
  800.     pPerScrnInfo->screenData = (XPointer) pScreenData;
  801.  
  802.     pPerScrnInfo->state = XcmsInitSuccess;
  803.  
  804.     return(XcmsSuccess);
  805.  
  806. FreeBlueTblElements:
  807.     free(pScreenData->pBlueTbl->pBase);
  808.  
  809. FreeBlueTbl:
  810.     free(pScreenData->pBlueTbl);
  811.  
  812. FreeGreenTblElements:
  813.     free(pScreenData->pBlueTbl->pBase);
  814.  
  815. FreeGreenTbl:
  816.     free(pScreenData->pGreenTbl);
  817.  
  818. FreeRedTblElements:
  819.     free(pScreenData->pRedTbl->pBase);
  820.  
  821. FreeRedTbl:
  822.     free(pScreenData->pRedTbl);
  823.  
  824. FreeSCCData:
  825.     free(pScreenData);
  826.     pPerScrnInfo->state = XcmsInitNone;
  827.     return(XcmsFailure);
  828. }
  829.  
  830.  
  831. /*
  832.  *    NAME
  833.  *        LINEAR_RGB_FreeSCCData()
  834.  *
  835.  *    SYNOPSIS
  836.  */
  837. static void
  838. LINEAR_RGB_FreeSCCData(pScreenData)
  839.     LINEAR_RGB_SCCData *pScreenData;
  840. /*
  841.  *    DESCRIPTION
  842.  *
  843.  *    RETURNS
  844.  *        0 if failed.
  845.  *        1 if succeeded with no modifications.
  846.  *
  847.  */
  848. {
  849.     if (pScreenData) {
  850.     if (pScreenData->pRedTbl) {
  851.         if (pScreenData->pGreenTbl) {
  852.         if (pScreenData->pRedTbl->pBase != 
  853.             pScreenData->pGreenTbl->pBase) {
  854.             if (pScreenData->pGreenTbl->pBase) {
  855.             free (pScreenData->pGreenTbl->pBase);
  856.             }
  857.         }
  858.         if (pScreenData->pGreenTbl != pScreenData->pRedTbl) {
  859.             free (pScreenData->pGreenTbl);
  860.         }
  861.         }
  862.         if (pScreenData->pBlueTbl) {
  863.         if (pScreenData->pRedTbl->pBase != 
  864.             pScreenData->pBlueTbl->pBase) {
  865.             if (pScreenData->pBlueTbl->pBase) {
  866.             free (pScreenData->pBlueTbl->pBase);
  867.             }
  868.         }
  869.         if (pScreenData->pBlueTbl != pScreenData->pRedTbl) {
  870.             free (pScreenData->pBlueTbl);
  871.         }
  872.         }
  873.         if (pScreenData->pRedTbl->pBase) {
  874.         free (pScreenData->pRedTbl->pBase);
  875.         }
  876.         free (pScreenData->pRedTbl);
  877.     }
  878.     free (pScreenData);
  879.     }
  880. }
  881.  
  882.  
  883.  
  884. /************************************************************************
  885.  *                                    *
  886.  *            API PRIVATE ROUTINES                *
  887.  *                                    *
  888.  ************************************************************************/
  889.  
  890. /*
  891.  *    NAME
  892.  *        _XcmsGetTableType0
  893.  *
  894.  *    SYNOPSIS
  895.  */
  896. Status
  897. _XcmsGetTableType0(pTbl, format, pChar, pCount)
  898.     IntensityTbl *pTbl;
  899.     int      format;
  900.     char **pChar;
  901.     unsigned long *pCount;
  902. /*
  903.  *    DESCRIPTION
  904.  *
  905.  *    RETURNS
  906.  *        XcmsFailure if failed.
  907.  *        XcmsSuccess if succeeded.
  908.  *
  909.  */
  910. {
  911.     unsigned int nElements;
  912.     IntensityRec *pIRec;
  913.  
  914.     nElements = pTbl->nEntries =
  915.         _XcmsGetElement(format, pChar, pCount) + 1;
  916.     if (!(pIRec = pTbl->pBase = (IntensityRec *)
  917.       Xcalloc (nElements, sizeof(IntensityRec)))) {
  918.     return(XcmsFailure);
  919.     }
  920.  
  921.     switch (format) {
  922.       case 8: 
  923.     for (; nElements--; pIRec++) {
  924.         /* 0xFFFF/0xFF = 0x101 */
  925.         pIRec->value = _XcmsGetElement (format, pChar, pCount) * 0x101;
  926.         pIRec->intensity =
  927.             _XcmsGetElement (format, pChar, pCount) / (XcmsFloat)255.0;
  928.     }
  929.     break;
  930.       case 16: 
  931.     for (; nElements--; pIRec++) {
  932.         pIRec->value = _XcmsGetElement (format, pChar, pCount);
  933.         pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
  934.             / (XcmsFloat)65535.0;
  935.     }
  936.     break;
  937.       case 32: 
  938.     for (; nElements--; pIRec++) {
  939.         pIRec->value = _XcmsGetElement (format, pChar, pCount);
  940.         pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
  941.             / (XcmsFloat)4294967295.0;
  942.     }
  943.     break;
  944.       default:
  945.     return(XcmsFailure);
  946.     }
  947.     return(XcmsSuccess);
  948. }
  949.  
  950.  
  951. /*
  952.  *    NAME
  953.  *        _XcmsGetTableType1
  954.  *
  955.  *    SYNOPSIS
  956.  */
  957. Status
  958. _XcmsGetTableType1(pTbl, format, pChar, pCount)
  959.     IntensityTbl *pTbl;
  960.     int      format;
  961.     char **pChar;
  962.     unsigned long *pCount;
  963. /*
  964.  *    DESCRIPTION
  965.  *
  966.  *    RETURNS
  967.  *        XcmsFailure if failed.
  968.  *        XcmsSuccess if succeeded.
  969.  *
  970.  */
  971. {
  972.     int count;
  973.     unsigned int max_index;
  974.     IntensityRec *pIRec;
  975.  
  976.     max_index = _XcmsGetElement(format, pChar, pCount);
  977.     pTbl->nEntries = max_index + 1;
  978.     if (!(pIRec = pTbl->pBase = (IntensityRec *)
  979.       Xcalloc (max_index+1, sizeof(IntensityRec)))) {
  980.     return(XcmsFailure);
  981.     }
  982.  
  983.     switch (format) {
  984.       case 8: 
  985.     for (count = 0; count < max_index+1; count++, pIRec++) {
  986.         pIRec->value = (count * 65535) / max_index;
  987.         pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
  988.             / (XcmsFloat)255.0;
  989.     }
  990.     break;
  991.       case 16: 
  992.     for (count = 0; count < max_index+1; count++, pIRec++) {
  993.         pIRec->value = (count * 65535) / max_index;
  994.         pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
  995.             / (XcmsFloat)65535.0;
  996.     }
  997.     break;
  998.       case 32: 
  999.     for (count = 0; count < max_index+1; count++, pIRec++) {
  1000.         pIRec->value = (count * 65535) / max_index;
  1001.         pIRec->intensity = _XcmsGetElement (format, pChar, pCount)
  1002.             / (XcmsFloat)4294967295.0;
  1003.     }
  1004.     break;
  1005.       default:
  1006.     return(XcmsFailure);
  1007.     }
  1008.  
  1009.     return(XcmsSuccess);
  1010. }
  1011.  
  1012.  
  1013. /*
  1014.  *    NAME
  1015.  *        ValueCmp
  1016.  *
  1017.  *    SYNOPSIS
  1018.  */
  1019. int
  1020. _XcmsValueCmp (p1, p2)
  1021.     IntensityRec *p1, *p2;
  1022. /*
  1023.  *    DESCRIPTION
  1024.  *        Compares the value component of two IntensityRec
  1025.  *        structures.
  1026.  *
  1027.  *    RETURNS
  1028.  *        0 if p1->value is equal to p2->value
  1029.  *        < 0 if p1->value is less than p2->value
  1030.  *        > 0 if p1->value is greater than p2->value
  1031.  *
  1032.  */
  1033. {
  1034.     return (p1->value - p2->value);
  1035. }
  1036.  
  1037.  
  1038. /*
  1039.  *    NAME
  1040.  *        IntensityCmp
  1041.  *
  1042.  *    SYNOPSIS
  1043.  */
  1044. int
  1045. _XcmsIntensityCmp (p1, p2)
  1046.     IntensityRec *p1, *p2;
  1047. /*
  1048.  *    DESCRIPTION
  1049.  *        Compares the intensity component of two IntensityRec
  1050.  *        structures.
  1051.  *
  1052.  *    RETURNS
  1053.  *        0 if equal;
  1054.  *        < 0 if first precedes second
  1055.  *        > 0 if first succeeds second
  1056.  *
  1057.  */
  1058. {
  1059.     if (p1->intensity < p2->intensity) {
  1060.     return (-1);
  1061.     }
  1062.     if (p1->intensity > p2->intensity) {
  1063.     return (XcmsSuccess);
  1064.     }
  1065.     return (XcmsFailure);
  1066. }
  1067.  
  1068. /*
  1069.  *    NAME
  1070.  *        ValueInterpolation
  1071.  *
  1072.  *    SYNOPSIS
  1073.  */
  1074. /* ARGSUSED */
  1075. int
  1076. _XcmsValueInterpolation (key, lo, hi, answer, bitsPerRGB)
  1077.     IntensityRec *key, *lo, *hi, *answer;
  1078.     int bitsPerRGB;
  1079. /*
  1080.  *    DESCRIPTION
  1081.  *        Based on a given value, performs a linear interpolation
  1082.  *        on the intensities between two IntensityRec structures.
  1083.  *        Note that the bitsPerRGB parameter is ignored.
  1084.  *
  1085.  *    RETURNS
  1086.  *        Returns 0 if failed; otherwise non-zero.
  1087.  */
  1088. {
  1089.     XcmsFloat ratio;
  1090.  
  1091.     ratio = ((XcmsFloat)key->value - (XcmsFloat)lo->value) / 
  1092.     ((XcmsFloat)hi->value - (XcmsFloat)lo->value);
  1093.     answer->value = key->value;
  1094.     answer->intensity = (hi->intensity - lo->intensity) * ratio;
  1095.     answer->intensity += lo->intensity;
  1096.     return (XcmsSuccess);
  1097. }
  1098.  
  1099. /*
  1100.  *    NAME
  1101.  *        IntensityInterpolation
  1102.  *
  1103.  *    SYNOPSIS
  1104.  */
  1105. int
  1106. _XcmsIntensityInterpolation (key, lo, hi, answer, bitsPerRGB)
  1107.     IntensityRec *key, *lo, *hi, *answer;
  1108.     int bitsPerRGB;
  1109. /*
  1110.  *    DESCRIPTION
  1111.  *        Based on a given intensity, performs a linear interpolation
  1112.  *        on the values between two IntensityRec structures.
  1113.  *        The bitsPerRGB parameter is necessary to perform rounding
  1114.  *        to the correct number of significant bits.
  1115.  *
  1116.  *    RETURNS
  1117.  *        Returns 0 if failed; otherwise non-zero.
  1118.  */
  1119. {
  1120.     XcmsFloat ratio;
  1121.     long target, up, down;
  1122.     int shift = 16 - bitsPerRGB;
  1123.     int max_color = (1 << bitsPerRGB) - 1;
  1124.  
  1125.     ratio = (key->intensity - lo->intensity) / (hi->intensity - lo->intensity);
  1126.     answer->intensity = key->intensity;
  1127.     target = hi->value - lo->value;
  1128.     target *= ratio;
  1129.     target += lo->value;
  1130.  
  1131.     /*
  1132.      * Ok now, lets find the closest in respects to bits per RGB
  1133.      */
  1134.     up = ((target >> shift) * 0xFFFF) / max_color;
  1135.     if (up < target) {
  1136.     down = up;
  1137.     up = (MIN((down >> shift) + 1, max_color) * 0xFFFF) / max_color;
  1138.     } else {
  1139.     down = (MAX((up >> shift) - 1, 0) * 0xFFFF) / max_color;
  1140.     }
  1141.     answer->value = ((up - target) < (target - down) ? up : down);
  1142.     answer->value &= MASK[bitsPerRGB];
  1143.     return (XcmsSuccess);
  1144. }
  1145.  
  1146.  
  1147. /*
  1148.  *    NAME
  1149.  *        _XcmsTableSearch
  1150.  *
  1151.  *    SYNOPSIS
  1152.  */
  1153. int
  1154. _XcmsTableSearch (key, bitsPerRGB, base, nel, nKeyPtrSize, compar, interpol, answer)
  1155.     char *key;
  1156.     int bitsPerRGB;
  1157.     char *base;
  1158.     unsigned nel;
  1159.     unsigned nKeyPtrSize;
  1160.     int (*compar)();
  1161.     int (*interpol)();
  1162.     char *answer;
  1163.  
  1164. /*
  1165.  *    DESCRIPTION
  1166.  *        A binary search through the specificied table.
  1167.  *
  1168.  *    RETURNS
  1169.  *        Returns 0 if failed; otherwise non-zero.
  1170.  *
  1171.  */
  1172. {
  1173.     char *hi, *lo, *mid, *last;
  1174.     int result;
  1175.  
  1176.     last = hi = base + ((nel - 1) * nKeyPtrSize);
  1177.     mid = lo = base;
  1178.  
  1179.     /* use only the significants bits, then scale into 16 bits */
  1180.     ((IntensityRec *)key)->value = ((unsigned long)
  1181.         (((IntensityRec *)key)->value >> (16 - bitsPerRGB)) * 0xFFFF)
  1182.         / ((1 << bitsPerRGB) - 1);
  1183.  
  1184.     /* Special case so that zero intensity always maps to zero value */
  1185.     if ((*compar) (key,lo) == 0) {
  1186.     bcopy (lo, answer, nKeyPtrSize);
  1187.     ((IntensityRec *)answer)->value &= MASK[bitsPerRGB];
  1188.     return XcmsSuccess;
  1189.     }
  1190.     while (mid != last) {
  1191.     last = mid;
  1192.     mid = lo + (((unsigned)(hi - lo) / nKeyPtrSize) / 2) * nKeyPtrSize;
  1193.     result = (*compar) (key, mid);
  1194.     if (result == 0) {
  1195.  
  1196.         bcopy(mid, answer, nKeyPtrSize);
  1197.         ((IntensityRec *)answer)->value &= MASK[bitsPerRGB];
  1198.         return (XcmsSuccess);
  1199.     } else if (result < 0) {
  1200.         hi = mid;
  1201.     } else {
  1202.         lo = mid;
  1203.     }
  1204.     }
  1205.  
  1206.     /*
  1207.      * If we got to here, we didn't find a solution, so we
  1208.      * need to apply interpolation.
  1209.      */
  1210.     return ((*interpol)(key, lo, hi, answer, bitsPerRGB));
  1211. }
  1212.  
  1213.  
  1214. /*
  1215.  *      NAME
  1216.  *        _XcmsMatVec - multiply a 3 x 3 by a 3 x 1 vector
  1217.  *
  1218.  *    SYNOPSIS
  1219.  */
  1220. void _XcmsMatVec(pMat, pIn, pOut)
  1221.     XcmsFloat *pMat, *pIn, *pOut;
  1222. /*
  1223.  *      DESCRIPTION
  1224.  *        Multiply the passed vector by the passed matrix to return a 
  1225.  *        vector. Matrix is 3x3, vectors are of length 3.
  1226.  *
  1227.  *    RETURNS
  1228.  *        void
  1229.  */
  1230. {
  1231.     int i, j;
  1232.  
  1233.     for (i = 0; i < 3; i++) {
  1234.     pOut[i] = 0.0;
  1235.     for (j = 0; j < 3; j++)
  1236.         pOut[i] += *(pMat+(i*3)+j) * pIn[j];
  1237.     }
  1238. }
  1239.  
  1240.  
  1241. /************************************************************************
  1242.  *                                    *
  1243.  *             PUBLIC ROUTINES                *
  1244.  *                                    *
  1245.  ************************************************************************/
  1246.  
  1247.  
  1248. /*
  1249.  *    NAME
  1250.  *        XcmsLRGB_RGB_ParseString
  1251.  *
  1252.  *    SYNOPSIS
  1253.  */
  1254. int
  1255. XcmsLRGB_RGB_ParseString(spec, pColor)
  1256.     register char *spec;
  1257.     XcmsColor *pColor;
  1258. /*
  1259.  *    DESCRIPTION
  1260.  *        This routines takes a string and attempts to convert
  1261.  *        it into a XcmsColor structure with XcmsRGBFormat.
  1262.  *
  1263.  *    RETURNS
  1264.  *        0 if failed, non-zero otherwise.
  1265.  */
  1266. {
  1267.     register int n, i;
  1268.     unsigned short r, g, b;
  1269.     char c;
  1270.     char *pchar;
  1271.     unsigned short *pShort;
  1272.  
  1273.     /*
  1274.      * Check for old # format
  1275.      */
  1276.     if (*spec == '#') {
  1277.     /*
  1278.      * Attempt to parse the value portion.
  1279.      */
  1280.     spec++;
  1281.     n = strlen(spec);
  1282.     if (n != 3 && n != 6 && n != 9 && n != 12) {
  1283.         return(XcmsFailure);
  1284.     }
  1285.  
  1286.     n /= 3;
  1287.     g = b = 0;
  1288.     do {
  1289.         r = g;
  1290.         g = b;
  1291.         b = 0;
  1292.         for (i = n; --i >= 0; ) {
  1293.         c = *spec++;
  1294.         b <<= 4;
  1295.         if (c >= '0' && c <= '9')
  1296.             b |= c - '0';
  1297.         /* assume string in lowercase
  1298.         else if (c >= 'A' && c <= 'F')
  1299.             b |= c - ('A' - 10);
  1300.         */
  1301.         else if (c >= 'a' && c <= 'f')
  1302.             b |= c - ('a' - 10);
  1303.         else return (XcmsFailure);
  1304.         }
  1305.     } while (*spec != '\0');
  1306.  
  1307.     /*
  1308.      * Succeeded !
  1309.      */
  1310.     n <<= 2;
  1311.     n = 16 - n;
  1312.     /* shift instead of scale, to match old broken semantics */
  1313.     pColor->spec.RGB.red = r << n;
  1314.     pColor->spec.RGB.green = g << n;
  1315.     pColor->spec.RGB.blue =  b << n;
  1316.     } else {
  1317.     if ((pchar = strchr(spec, ':')) == NULL) {
  1318.         return(XcmsFailure);
  1319.     }
  1320.     n = (int)(pchar - spec);
  1321.  
  1322.     /*
  1323.      * Check for proper prefix.
  1324.      */
  1325.     if (strncmp(spec, XcmsRGB_prefix, n) != 0) {
  1326.         return(XcmsFailure);
  1327.     }
  1328.  
  1329.     /*
  1330.      * Attempt to parse the value portion.
  1331.      */
  1332.     spec += (n + 1);
  1333.     pShort = &pColor->spec.RGB.red;
  1334.     for (i = 0; i < 3; i++, pShort++, spec++) {
  1335.         n = 0;
  1336.         *pShort = 0;
  1337.         while (*spec != '/' && *spec != '\0') {
  1338.         if (++n > 4) {
  1339.             return(XcmsFailure);
  1340.         }
  1341.         c = *spec++;
  1342.         *pShort <<= 4;
  1343.         if (c >= '0' && c <= '9')
  1344.             *pShort |= c - '0';
  1345.         /* assume string in lowercase
  1346.         else if (c >= 'A' && c <= 'F')
  1347.             *pShort |= c - ('A' - 10);
  1348.         */
  1349.         else if (c >= 'a' && c <= 'f')
  1350.             *pShort |= c - ('a' - 10);
  1351.         else return (XcmsFailure);
  1352.         }
  1353.         if (n < 4) {
  1354.         *pShort = ((unsigned long)*pShort * 0xFFFF) / ((1 << n*4) - 1);
  1355.         }
  1356.     }
  1357.     }
  1358.     pColor->format = XcmsRGBFormat;
  1359.     pColor->pixel = 0;
  1360.     return (XcmsSuccess);
  1361. }
  1362.  
  1363.  
  1364. /*
  1365.  *    NAME
  1366.  *        XcmsLRGB_RGBi_ParseString
  1367.  *
  1368.  *    SYNOPSIS
  1369.  */
  1370. int
  1371. XcmsLRGB_RGBi_ParseString(spec, pColor)
  1372.     register char *spec;
  1373.     XcmsColor *pColor;
  1374. /*
  1375.  *    DESCRIPTION
  1376.  *        This routines takes a string and attempts to convert
  1377.  *        it into a XcmsColor structure with XcmsRGBiFormat.
  1378.  *        The assumed RGBi string syntax is:
  1379.  *            RGBi:<r>/<g>/<b>
  1380.  *        Where r, g, and b are in string input format for floats
  1381.  *        consisting of:
  1382.  *            a. an optional sign
  1383.  *            b. a string of numbers possibly containing a decimal point,
  1384.  *            c. an optional exponent field containing an 'E' or 'e'
  1385.  *            followed by a possibly signed integer string.
  1386.  *
  1387.  *    RETURNS
  1388.  *        0 if failed, non-zero otherwise.
  1389.  */
  1390. {
  1391.     int n;
  1392.     char *pchar;
  1393.  
  1394.     if ((pchar = strchr(spec, ':')) == NULL) {
  1395.     return(XcmsFailure);
  1396.     }
  1397.     n = (int)(pchar - spec);
  1398.  
  1399.     /*
  1400.      * Check for proper prefix.
  1401.      */
  1402.     if (strncmp(spec, XcmsRGBi_prefix, n) != 0) {
  1403.     return(XcmsFailure);
  1404.     }
  1405.  
  1406.     /*
  1407.      * Attempt to parse the value portion.
  1408.      */
  1409.     if (sscanf(spec + n + 1, "%lf/%lf/%lf",
  1410.         &pColor->spec.RGBi.red,
  1411.         &pColor->spec.RGBi.green,
  1412.         &pColor->spec.RGBi.blue) != 3) {
  1413.     return(XcmsFailure);
  1414.     }
  1415.  
  1416.     /*
  1417.      * Succeeded !
  1418.      */
  1419.     pColor->format = XcmsRGBiFormat;
  1420.     pColor->pixel = 0;
  1421.     return (XcmsSuccess);
  1422. }
  1423.  
  1424.  
  1425. /*
  1426.  *    NAME
  1427.  *        XcmsCIEXYZToRGBi - convert CIE XYZ to RGB
  1428.  *
  1429.  *    SYNOPSIS
  1430.  */
  1431. /* ARGSUSED */
  1432. Status 
  1433. XcmsCIEXYZToRGBi(ccc, pXcmsColors_in_out, nColors, pCompressed)
  1434.     XcmsCCC ccc;
  1435.     XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert     */
  1436.     unsigned int nColors;    /* Number of colors            */
  1437.     Bool *pCompressed;        /* pointer to an array of Bool        */
  1438. /*
  1439.  *    DESCRIPTION
  1440.  *        Converts color specifications in an array of XcmsColor
  1441.  *        structures from RGB format to RGBi format.
  1442.  *
  1443.  *    RETURNS
  1444.  *        XcmsFailure if failed,
  1445.  *        XcmsSuccess if succeeded without gamut compression.
  1446.  *        XcmsSuccessWithCompression if succeeded with gamut
  1447.  *            compression.
  1448.  */
  1449. {
  1450.     LINEAR_RGB_SCCData *pScreenData;
  1451.     XcmsFloat tmp[3];
  1452.     int hasCompressed = 0;
  1453.     unsigned int i;
  1454.     XcmsColor *pColor = pXcmsColors_in_out;
  1455.  
  1456.     if (ccc == NULL) {
  1457.     return(XcmsFailure);
  1458.     }
  1459.  
  1460.     pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
  1461.  
  1462.     /*
  1463.      * XcmsColors should be White Point Adjusted, if necessary, by now!
  1464.      */
  1465.  
  1466.     /*
  1467.      * NEW!!! for extended gamut compression
  1468.      *
  1469.      * 1. Need to zero out pCompressed
  1470.      *
  1471.      * 2. Need to save initial address of pColor
  1472.      *
  1473.      * 3. Need to save initial address of pCompressed
  1474.      */
  1475.  
  1476.     for (i = 0; i < nColors; i++) {
  1477.  
  1478.     /* Make sure format is XcmsCIEXYZFormat */
  1479.     if (pColor->format != XcmsCIEXYZFormat) {
  1480.         return(XcmsFailure);
  1481.     }
  1482.  
  1483.     /* Multiply [A]-1 * [XYZ] to get RGB intensity */
  1484.     _XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix,
  1485.         (XcmsFloat *) &pColor->spec, tmp);
  1486.  
  1487.     if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) ||
  1488.         (MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) {
  1489.  
  1490.         /*
  1491.          * RGBi out of screen's gamut
  1492.          */
  1493.  
  1494.         if (ccc->gamutCompProc == NULL) {
  1495.         /*
  1496.          * Aha!! Here's that little trick that will allow
  1497.          * gamut compression routines to get the out of bound
  1498.          * RGBi.  
  1499.          */
  1500.         bcopy((char *)tmp, (char *)&pColor->spec, sizeof(tmp));
  1501.         pColor->format = XcmsRGBiFormat;
  1502.         return(XcmsFailure);
  1503.         } else if ((*ccc->gamutCompProc)(ccc, pXcmsColors_in_out, nColors,
  1504.             i, pCompressed) == 0) {
  1505.         return(XcmsFailure);
  1506.         }
  1507.  
  1508.         /*
  1509.          * The gamut compression function should return colors in CIEXYZ
  1510.          *    Also check again to if the new color is within gamut.
  1511.          */
  1512.         if (pColor->format != XcmsCIEXYZFormat) {
  1513.         return(XcmsFailure);
  1514.         }
  1515.         _XcmsMatVec((XcmsFloat *) pScreenData->XYZtoRGBmatrix,
  1516.             (XcmsFloat *) &pColor->spec, tmp);
  1517.         if ((MIN3 (tmp[0], tmp[1], tmp[2]) < -EPS) ||
  1518.         (MAX3 (tmp[0], tmp[1], tmp[2]) > (1.0 + EPS))) {
  1519.         return(XcmsFailure);
  1520.         }
  1521.         hasCompressed++;
  1522.     }
  1523.     bcopy((char *)tmp, (char *)&pColor->spec, sizeof(tmp));
  1524.     /* These if statements are done to ensure the fudge factor is */
  1525.     /* is taken into account. */
  1526.     if (pColor->spec.RGBi.red < 0.0) {
  1527.         pColor->spec.RGBi.red = 0.0;
  1528.     } else if (pColor->spec.RGBi.red > 1.0) {
  1529.         pColor->spec.RGBi.red = 1.0;
  1530.     }
  1531.     if (pColor->spec.RGBi.green < 0.0) {
  1532.         pColor->spec.RGBi.green = 0.0;
  1533.     } else if (pColor->spec.RGBi.green > 1.0) {
  1534.         pColor->spec.RGBi.green = 1.0;
  1535.     }
  1536.     if (pColor->spec.RGBi.blue < 0.0) {
  1537.         pColor->spec.RGBi.blue = 0.0;
  1538.     } else if (pColor->spec.RGBi.blue > 1.0) {
  1539.         pColor->spec.RGBi.blue = 1.0;
  1540.     }
  1541.     (pColor++)->format = XcmsRGBiFormat;
  1542.     }
  1543.     return (hasCompressed ? XcmsSuccessWithCompression : XcmsSuccess);
  1544. }
  1545.  
  1546.  
  1547. /*
  1548.  *    NAME
  1549.  *        LINEAR_RGBi_to_CIEXYZ - convert RGBi to CIEXYZ
  1550.  *
  1551.  *    SYNOPSIS
  1552.  */
  1553. /* ARGSUSED */
  1554. Status 
  1555. XcmsRGBiToCIEXYZ(ccc, pXcmsColors_in_out, nColors, pCompressed)
  1556.     XcmsCCC ccc;
  1557.     XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert     */
  1558.     unsigned int nColors;    /* Number of colors            */
  1559.     Bool *pCompressed;        /* pointer to a bit array        */
  1560. /*
  1561.  *    DESCRIPTION
  1562.  *        Converts color specifications in an array of XcmsColor
  1563.  *        structures from RGBi format to CIEXYZ format.
  1564.  *
  1565.  *    RETURNS
  1566.  *        XcmsFailure if failed,
  1567.  *        XcmsSuccess if succeeded.
  1568.  */
  1569. {
  1570.     LINEAR_RGB_SCCData *pScreenData;
  1571.     XcmsFloat tmp[3];
  1572.  
  1573.     /*
  1574.      * pCompressed ignored in this function.
  1575.      */
  1576.  
  1577.     if (ccc == NULL) {
  1578.     return(XcmsFailure);
  1579.     }
  1580.  
  1581.     pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
  1582.  
  1583.     /*
  1584.      * XcmsColors should be White Point Adjusted, if necessary, by now!
  1585.      */
  1586.  
  1587.     while (nColors--) {
  1588.  
  1589.     /* Multiply [A]-1 * [XYZ] to get RGB intensity */
  1590.     _XcmsMatVec((XcmsFloat *) pScreenData->RGBtoXYZmatrix,
  1591.         (XcmsFloat *) &pXcmsColors_in_out->spec, tmp);
  1592.  
  1593.     bcopy((char *)tmp, (char *)&pXcmsColors_in_out->spec, sizeof(tmp));
  1594.     (pXcmsColors_in_out++)->format = XcmsCIEXYZFormat;
  1595.     }
  1596.     return(XcmsSuccess);
  1597. }
  1598.  
  1599.  
  1600. /*
  1601.  *    NAME
  1602.  *        XcmsRGBiToRGB
  1603.  *
  1604.  *    SYNOPSIS
  1605.  */
  1606. /* ARGSUSED */
  1607. Status 
  1608. XcmsRGBiToRGB(ccc, pXcmsColors_in_out, nColors, pCompressed)
  1609.     XcmsCCC ccc;
  1610.     XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert     */
  1611.     unsigned int nColors;    /* Number of colors            */
  1612.     Bool *pCompressed;        /* pointer to a bit array        */
  1613. /*
  1614.  *    DESCRIPTION
  1615.  *        Converts color specifications in an array of XcmsColor
  1616.  *        structures from RGBi format to RGB format.
  1617.  *
  1618.  *    RETURNS
  1619.  *        XcmsFailure if failed,
  1620.  *        XcmsSuccess if succeeded without gamut compression.
  1621.  *        XcmsSuccessWithCompression if succeeded with gamut
  1622.  *            compression.
  1623.  */
  1624. {
  1625.     LINEAR_RGB_SCCData *pScreenData;
  1626.     XcmsRGB tmpRGB;
  1627.     IntensityRec keyIRec, answerIRec;
  1628.  
  1629.     /*
  1630.      * pCompressed ignored in this function.
  1631.      */
  1632.  
  1633.     if (ccc == NULL) {
  1634.     return(XcmsFailure);
  1635.     }
  1636.  
  1637.     pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
  1638.  
  1639.     while (nColors--) {
  1640.  
  1641.     /* Make sure format is XcmsRGBiFormat */
  1642.     if (pXcmsColors_in_out->format != XcmsRGBiFormat) {
  1643.         return(XcmsFailure);
  1644.     }
  1645.  
  1646.     keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.red;
  1647.     if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
  1648.         (char *)pScreenData->pRedTbl->pBase,
  1649.         (unsigned)pScreenData->pRedTbl->nEntries,
  1650.         (unsigned)sizeof(IntensityRec),
  1651.         _XcmsIntensityCmp, _XcmsIntensityInterpolation, (char *)&answerIRec)) {
  1652.         return(XcmsFailure);
  1653.     }
  1654.     tmpRGB.red = answerIRec.value;
  1655.  
  1656.     keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.green;
  1657.     if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
  1658.         (char *)pScreenData->pGreenTbl->pBase,
  1659.         (unsigned)pScreenData->pGreenTbl->nEntries,
  1660.         (unsigned)sizeof(IntensityRec),
  1661.         _XcmsIntensityCmp, _XcmsIntensityInterpolation, (char *)&answerIRec)) {
  1662.         return(XcmsFailure);
  1663.     }
  1664.     tmpRGB.green = answerIRec.value;
  1665.  
  1666.     keyIRec.intensity = pXcmsColors_in_out->spec.RGBi.blue;
  1667.     if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
  1668.         (char *)pScreenData->pBlueTbl->pBase,
  1669.         (unsigned)pScreenData->pBlueTbl->nEntries,
  1670.         (unsigned)sizeof(IntensityRec),
  1671.         _XcmsIntensityCmp, _XcmsIntensityInterpolation, (char *)&answerIRec)) {
  1672.         return(XcmsFailure);
  1673.     }
  1674.     tmpRGB.blue = answerIRec.value;
  1675.  
  1676.     bcopy((char *)&tmpRGB, (char *)&pXcmsColors_in_out->spec, sizeof(XcmsRGB));
  1677.     (pXcmsColors_in_out++)->format = XcmsRGBFormat;
  1678.     }
  1679.     return(XcmsSuccess);
  1680. }
  1681.  
  1682.  
  1683. /*
  1684.  *    NAME
  1685.  *        XcmsRGBToRGBi
  1686.  *
  1687.  *    SYNOPSIS
  1688.  */
  1689. /* ARGSUSED */
  1690. Status 
  1691. XcmsRGBToRGBi(ccc, pXcmsColors_in_out, nColors, pCompressed)
  1692.     XcmsCCC ccc;
  1693.     XcmsColor *pXcmsColors_in_out;/* pointer to XcmsColors to convert     */
  1694.     unsigned int nColors;    /* Number of colors            */
  1695.     Bool *pCompressed;        /* pointer to a bit array        */
  1696. /*
  1697.  *    DESCRIPTION
  1698.  *        Converts color specifications in an array of XcmsColor
  1699.  *        structures from RGB format to RGBi format.
  1700.  *
  1701.  *    RETURNS
  1702.  *        XcmsFailure if failed,
  1703.  *        XcmsSuccess if succeeded.
  1704.  */
  1705. {
  1706.     LINEAR_RGB_SCCData *pScreenData;
  1707.     XcmsRGBi tmpRGBi;
  1708.     IntensityRec keyIRec, answerIRec;
  1709.  
  1710.     /*
  1711.      * pCompressed ignored in this function.
  1712.      */
  1713.  
  1714.     if (ccc == NULL) {
  1715.     return(XcmsFailure);
  1716.     }
  1717.  
  1718.     pScreenData = (LINEAR_RGB_SCCData *)ccc->pPerScrnInfo->screenData;
  1719.  
  1720.     while (nColors--) {
  1721.  
  1722.     /* Make sure format is XcmsRGBFormat */
  1723.     if (pXcmsColors_in_out->format != XcmsRGBFormat) {
  1724.         return(XcmsFailure);
  1725.     }
  1726.  
  1727.     keyIRec.value = pXcmsColors_in_out->spec.RGB.red;
  1728.     if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
  1729.         (char *)pScreenData->pRedTbl->pBase,
  1730.         (unsigned)pScreenData->pRedTbl->nEntries,
  1731.         (unsigned)sizeof(IntensityRec),
  1732.         _XcmsValueCmp, _XcmsValueInterpolation, (char *)&answerIRec)) {
  1733.         return(XcmsFailure);
  1734.     }
  1735.     tmpRGBi.red = answerIRec.intensity;
  1736.  
  1737.     keyIRec.value = pXcmsColors_in_out->spec.RGB.green;
  1738.     if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
  1739.         (char *)pScreenData->pGreenTbl->pBase,
  1740.         (unsigned)pScreenData->pGreenTbl->nEntries,
  1741.         (unsigned)sizeof(IntensityRec),
  1742.         _XcmsValueCmp, _XcmsValueInterpolation, (char *)&answerIRec)) {
  1743.         return(XcmsFailure);
  1744.     }
  1745.     tmpRGBi.green = answerIRec.intensity;
  1746.  
  1747.     keyIRec.value = pXcmsColors_in_out->spec.RGB.blue;
  1748.     if (!_XcmsTableSearch((char *)&keyIRec, ccc->visual->bits_per_rgb,
  1749.         (char *)pScreenData->pBlueTbl->pBase,
  1750.         (unsigned)pScreenData->pBlueTbl->nEntries,
  1751.         (unsigned)sizeof(IntensityRec),
  1752.         _XcmsValueCmp, _XcmsValueInterpolation, (char *)&answerIRec)) {
  1753.         return(XcmsFailure);
  1754.     }
  1755.     tmpRGBi.blue = answerIRec.intensity;
  1756.  
  1757.     bcopy((char *)&tmpRGBi, (char *)&pXcmsColors_in_out->spec, sizeof(XcmsRGBi));
  1758.     (pXcmsColors_in_out++)->format = XcmsRGBiFormat;
  1759.     }
  1760.     return(XcmsSuccess);
  1761. }
  1762.  
  1763. /*
  1764.  *    NAME
  1765.  *        _XcmsInitScrnDefaultInfo
  1766.  *
  1767.  *    SYNOPSIS
  1768.  */
  1769. /* ARGSUSED */
  1770. int
  1771. _XcmsLRGB_InitScrnDefault(dpy, screenNumber, pPerScrnInfo)
  1772.     Display *dpy;
  1773.     int screenNumber;
  1774.     XcmsPerScrnInfo *pPerScrnInfo;
  1775. /*
  1776.  *    DESCRIPTION
  1777.  *        Given a display and screen number, this routine attempts
  1778.  *        to initialize the TekCMS per Screen Info structure
  1779.  *        (XcmsPerScrnInfo) with defaults.
  1780.  *
  1781.  *    RETURNS
  1782.  *        Returns zero if initialization failed; non-zero otherwise.
  1783.  */
  1784. {
  1785.     pPerScrnInfo->screenData = (XPointer)&Default_RGB_SCCData;
  1786.     pPerScrnInfo->screenWhitePt.spec.CIEXYZ.X =
  1787.         Default_RGB_SCCData.RGBtoXYZmatrix[0][0] +
  1788.         Default_RGB_SCCData.RGBtoXYZmatrix[0][1] +
  1789.         Default_RGB_SCCData.RGBtoXYZmatrix[0][2];
  1790.     pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y =
  1791.         Default_RGB_SCCData.RGBtoXYZmatrix[1][0] +
  1792.         Default_RGB_SCCData.RGBtoXYZmatrix[1][1] +
  1793.         Default_RGB_SCCData.RGBtoXYZmatrix[1][2];
  1794.     pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Z =
  1795.         Default_RGB_SCCData.RGBtoXYZmatrix[2][0] +
  1796.         Default_RGB_SCCData.RGBtoXYZmatrix[2][1] +
  1797.         Default_RGB_SCCData.RGBtoXYZmatrix[2][2];
  1798.     if ((pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y < (1.0 - EPS) )
  1799.         || (pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y > (1.0 + EPS))) {
  1800.     pPerScrnInfo->screenData = (XPointer)NULL;
  1801.     pPerScrnInfo->state = XcmsInitNone;
  1802.     return(0);
  1803.     }
  1804.     pPerScrnInfo->screenWhitePt.spec.CIEXYZ.Y = 1.0;
  1805.     pPerScrnInfo->screenWhitePt.format = XcmsCIEXYZFormat;
  1806.     pPerScrnInfo->screenWhitePt.pixel = 0;
  1807.     pPerScrnInfo->functionSet = (XPointer)&XcmsLinearRGBFunctionSet;
  1808.     pPerScrnInfo->state = XcmsInitDefault;
  1809.     return(1);
  1810. }
  1811.