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