cmsInt.c revision 61b2299d
1/* $Xorg: cmsInt.c,v 1.4 2000/08/17 19:45:09 cpqbld 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 * XcmsInt.c - Xcms API utility routines 29 * 30 * DESCRIPTION 31 * Xcms Application Program Interface (API) utility 32 * routines for hanging information directly onto 33 * the Display structure. 34 * 35 * 36 */ 37/* $XFree86: xc/lib/X11/cmsInt.c,v 1.4 2003/04/13 19:22:20 dawes Exp $ */ 38 39/* #define NEED_EVENTS */ 40#ifdef HAVE_CONFIG_H 41#include <config.h> 42#endif 43#include <stdio.h> 44#include "Xlibint.h" 45#include "Xcmsint.h" 46#include "Cv.h" 47 48#ifndef XCMSCOMPPROC 49# define XCMSCOMPPROC XcmsTekHVCClipC 50#endif 51 52/* forward/static */ 53static void _XcmsFreeDefaultCCCs(Display *dpy); 54 55 56/************************************************************************ 57 * * 58 * API PRIVATE ROUTINES * 59 * * 60 ************************************************************************/ 61 62/* 63 * NAME 64 * _XcmsCopyPointerArray 65 * 66 * SYNOPSIS 67 */ 68XPointer * 69_XcmsCopyPointerArray( 70 XPointer *pap) 71/* 72 * DESCRIPTION 73 * Copies an array of NULL terminated pointers. 74 * 75 * RETURNS 76 * Returns NULL if failed; otherwise the address to 77 * the copy. 78 * 79 */ 80{ 81 XPointer *newArray; 82 char **tmp; 83 int n; 84 85 for (tmp = pap, n = 0; *tmp != NULL; tmp++, n++); 86 n++; /* add 1 to include the NULL pointer */ 87 88 if ((newArray = (XPointer *)Xmalloc(n * sizeof(XPointer)))) { 89 memcpy((char *)newArray, (char *)pap, 90 (unsigned)(n * sizeof(XPointer))); 91 } 92 return((XPointer *)newArray); 93} 94 95/* 96 * NAME 97 * _XcmsFreePointerArray 98 * 99 * SYNOPSIS 100 */ 101void 102_XcmsFreePointerArray( 103 XPointer *pap) 104/* 105 * DESCRIPTION 106 * Frees an array of NULL terminated pointers. 107 * 108 * RETURNS 109 * void 110 * 111 */ 112{ 113 Xfree(pap); 114} 115 116/* 117 * NAME 118 * _XcmsPushPointerArray 119 * 120 * SYNOPSIS 121 */ 122XPointer * 123_XcmsPushPointerArray( 124 XPointer *pap, 125 XPointer p, 126 XPointer *papNoFree) 127/* 128 * DESCRIPTION 129 * Places the specified pointer at the head of an array of NULL 130 * terminated pointers. 131 * 132 * RETURNS 133 * Returns NULL if failed; otherwise the address to 134 * the head of the array. 135 * 136 */ 137{ 138 XPointer *newArray; 139 char **tmp; 140 int n; 141 142 for (tmp = pap, n = 0; *tmp != NULL; tmp++, n++); 143 144 /* add 2: 1 for the new pointer and another for the NULL pointer */ 145 n += 2; 146 147 if ((newArray = (XPointer *)Xmalloc(n * sizeof(XPointer)))) { 148 memcpy((char *)(newArray+1),(char *)pap, 149 (unsigned)((n-1) * sizeof(XPointer))); 150 *newArray = p; 151 } 152 if (pap != papNoFree) { 153 _XcmsFreePointerArray(pap); 154 } 155 return((XPointer *)newArray); 156} 157 158/* 159 * NAME 160 * _XcmsInitDefaultCCCs 161 * 162 * SYNOPSIS 163 */ 164int 165_XcmsInitDefaultCCCs( 166 Display *dpy) 167/* 168 * DESCRIPTION 169 * Initializes the Xcms per Display Info structure 170 * (XcmsPerDpyInfo). 171 * 172 * RETURNS 173 * Returns 0 if failed; otherwise non-zero. 174 * 175 */ 176{ 177 int nScrn = ScreenCount(dpy); 178 int i; 179 XcmsCCC ccc; 180 181 if (nScrn <= 0) { 182 return(0); 183 } 184 185 /* 186 * Create an array of XcmsCCC structures, one for each screen. 187 * They serve as the screen's default CCC. 188 */ 189 if (!(ccc = (XcmsCCC) 190 Xcalloc((unsigned)nScrn, (unsigned) sizeof(XcmsCCCRec)))) { 191 return(0); 192 } 193 dpy->cms.defaultCCCs = (XPointer)ccc; 194 dpy->free_funcs->defaultCCCs = _XcmsFreeDefaultCCCs; 195 196 for (i = 0; i < nScrn; i++, ccc++) { 197 ccc->dpy = dpy; 198 ccc->screenNumber = i; 199 ccc->visual = DefaultVisual(dpy, i); 200 /* 201 * Used calloc to allocate memory so: 202 * ccc->clientWhitePt->format == XcmsUndefinedFormat 203 * ccc->gamutCompProc == NULL 204 * ccc->whitePtAdjProc == NULL 205 * ccc->pPerScrnInfo = NULL 206 * 207 * Don't need to create XcmsPerScrnInfo and its functionSet and 208 * pScreenData components until the default CCC is accessed. 209 * Note that the XcmsDefaultCCC routine calls _XcmsInitScrnInto 210 * to do this. 211 */ 212 ccc->gamutCompProc = XCMSCOMPPROC; 213 } 214 215 return(1); 216} 217 218 219/* 220 * NAME 221 * _XcmsFreeDefaultCCCs - Free Default CCCs and its PerScrnInfo 222 * 223 * SYNOPSIS 224 */ 225static void 226_XcmsFreeDefaultCCCs( 227 Display *dpy) 228/* 229 * DESCRIPTION 230 * This routine frees the default XcmsCCC's associated with 231 * each screen and its associated substructures as neccessary. 232 * 233 * RETURNS 234 * void 235 * 236 * 237 */ 238{ 239 int nScrn = ScreenCount(dpy); 240 XcmsCCC ccc; 241 int i; 242 243 /* 244 * Free Screen data in each DefaultCCC 245 * Do not use XcmsFreeCCC here because it will not free 246 * DefaultCCC's. 247 */ 248 ccc = (XcmsCCC)dpy->cms.defaultCCCs; 249 for (i = nScrn; i--; ccc++) { 250 /* 251 * Check if XcmsPerScrnInfo exists. 252 * 253 * This is the only place where XcmsPerScrnInfo structures 254 * are freed since there is only one allocated per Screen. 255 * It just so happens that we place its reference in the 256 * default CCC. 257 */ 258 if (ccc->pPerScrnInfo) { 259 /* Check if SCCData exists */ 260 if (ccc->pPerScrnInfo->state != XcmsInitNone 261 && ccc->pPerScrnInfo->screenData) { 262 (*((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->screenFreeProc) 263 (ccc->pPerScrnInfo->screenData); 264 } 265 Xfree(ccc->pPerScrnInfo); 266 } 267 } 268 269 /* 270 * Free the array of XcmsCCC structures 271 */ 272 Xfree(dpy->cms.defaultCCCs); 273 dpy->cms.defaultCCCs = (XPointer)NULL; 274} 275 276 277 278/* 279 * NAME 280 * _XcmsInitScrnInfo 281 * 282 * SYNOPSIS 283 */ 284int 285_XcmsInitScrnInfo( 286 register Display *dpy, 287 int screenNumber) 288/* 289 * DESCRIPTION 290 * Given a display and screen number, this routine attempts 291 * to initialize the Xcms per Screen Info structure 292 * (XcmsPerScrnInfo). 293 * 294 * RETURNS 295 * Returns zero if initialization failed; non-zero otherwise. 296 */ 297{ 298 XcmsFunctionSet **papSCCFuncSet = _XcmsSCCFuncSets; 299 XcmsCCC defaultccc; 300 301 /* 302 * Check if the XcmsCCC's for each screen has been created. 303 * Really dont need to be created until some routine uses the Xcms 304 * API routines. 305 */ 306 if ((XcmsCCC)dpy->cms.defaultCCCs == NULL) { 307 if (!_XcmsInitDefaultCCCs(dpy)) { 308 return(0); 309 } 310 } 311 312 defaultccc = (XcmsCCC)dpy->cms.defaultCCCs + screenNumber; 313 314 /* 315 * For each SCCFuncSet, try its pInitScrnFunc. 316 * If the function succeeds, then we got it! 317 */ 318 319 if (!defaultccc->pPerScrnInfo) { 320 /* 321 * This is one of two places where XcmsPerScrnInfo structures 322 * are allocated. There is one allocated per Screen that is 323 * shared among visuals that do not have specific intensity 324 * tables. Other XcmsPerScrnInfo structures are created 325 * for the latter (see XcmsCreateCCC). The ones created 326 * here are referenced by the default CCC. 327 */ 328 if (!(defaultccc->pPerScrnInfo = (XcmsPerScrnInfo *) 329 Xcalloc(1, (unsigned) sizeof(XcmsPerScrnInfo)))) { 330 return(0); 331 } 332 defaultccc->pPerScrnInfo->state = XcmsInitNone; 333 } 334 335 while (*papSCCFuncSet != NULL) { 336 if ((*(*papSCCFuncSet)->screenInitProc)(dpy, screenNumber, 337 defaultccc->pPerScrnInfo)) { 338 defaultccc->pPerScrnInfo->state = XcmsInitSuccess; 339 return(1); 340 } 341 papSCCFuncSet++; 342 } 343 344 /* 345 * Use Default SCCData 346 */ 347 return(_XcmsLRGB_InitScrnDefault(dpy, screenNumber, defaultccc->pPerScrnInfo)); 348} 349 350 351/* 352 * NAME 353 * _XcmsFreeIntensityMaps 354 * 355 * SYNOPSIS 356 */ 357void 358_XcmsFreeIntensityMaps( 359 Display *dpy) 360/* 361 * DESCRIPTION 362 * Frees all XcmsIntensityMap structures in the linked list 363 * and sets dpy->cms.perVisualIntensityMaps to NULL. 364 * 365 * RETURNS 366 * void 367 * 368 */ 369{ 370 XcmsIntensityMap *pNext, *pFree; 371 372 pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps; 373 while (pNext != NULL) { 374 pFree = pNext; 375 pNext = pNext->pNext; 376 (*pFree->pFreeScreenData)(pFree->screenData); 377 /* Now free the XcmsIntensityMap structure */ 378 Xfree(pFree); 379 } 380 dpy->cms.perVisualIntensityMaps = (XPointer)NULL; 381} 382 383 384/* 385 * NAME 386 * _XcmsGetIntensityMap 387 * 388 * SYNOPSIS 389 */ 390XcmsIntensityMap * 391_XcmsGetIntensityMap( 392 Display *dpy, 393 Visual *visual) 394/* 395 * DESCRIPTION 396 * Attempts to return a per-Visual intensity map. 397 * 398 * RETURNS 399 * Pointer to the XcmsIntensityMap structure if found; 400 * otherwise NULL 401 * 402 */ 403{ 404 VisualID targetID = visual->visualid; 405 XcmsIntensityMap *pNext; 406 407 pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps; 408 while (pNext != NULL) { 409 if (targetID == pNext->visualID) { 410 return(pNext); 411 } 412 pNext = pNext->pNext; 413 } 414 return((XcmsIntensityMap *)NULL); 415} 416