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