cmsInt.c revision 818534a1
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 = 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 = 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 = Xcalloc((unsigned)nScrn, sizeof(XcmsCCCRec)))) { 187 return(0); 188 } 189 dpy->cms.defaultCCCs = (XPointer)ccc; 190 dpy->free_funcs->defaultCCCs = _XcmsFreeDefaultCCCs; 191 192 for (i = 0; i < nScrn; i++, ccc++) { 193 ccc->dpy = dpy; 194 ccc->screenNumber = i; 195 ccc->visual = DefaultVisual(dpy, i); 196 /* 197 * Used calloc to allocate memory so: 198 * ccc->clientWhitePt->format == XcmsUndefinedFormat 199 * ccc->gamutCompProc == NULL 200 * ccc->whitePtAdjProc == NULL 201 * ccc->pPerScrnInfo = NULL 202 * 203 * Don't need to create XcmsPerScrnInfo and its functionSet and 204 * pScreenData components until the default CCC is accessed. 205 * Note that the XcmsDefaultCCC routine calls _XcmsInitScrnInto 206 * to do this. 207 */ 208 ccc->gamutCompProc = XCMSCOMPPROC; 209 } 210 211 return(1); 212} 213 214 215/* 216 * NAME 217 * _XcmsFreeDefaultCCCs - Free Default CCCs and its PerScrnInfo 218 * 219 * SYNOPSIS 220 */ 221static void 222_XcmsFreeDefaultCCCs( 223 Display *dpy) 224/* 225 * DESCRIPTION 226 * This routine frees the default XcmsCCC's associated with 227 * each screen and its associated substructures as neccessary. 228 * 229 * RETURNS 230 * void 231 * 232 * 233 */ 234{ 235 int nScrn = ScreenCount(dpy); 236 XcmsCCC ccc; 237 int i; 238 239 /* 240 * Free Screen data in each DefaultCCC 241 * Do not use XcmsFreeCCC here because it will not free 242 * DefaultCCC's. 243 */ 244 ccc = (XcmsCCC)dpy->cms.defaultCCCs; 245 for (i = nScrn; i--; ccc++) { 246 /* 247 * Check if XcmsPerScrnInfo exists. 248 * 249 * This is the only place where XcmsPerScrnInfo structures 250 * are freed since there is only one allocated per Screen. 251 * It just so happens that we place its reference in the 252 * default CCC. 253 */ 254 if (ccc->pPerScrnInfo) { 255 /* Check if SCCData exists */ 256 if (ccc->pPerScrnInfo->state != XcmsInitNone 257 && ccc->pPerScrnInfo->screenData) { 258 (*((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->screenFreeProc) 259 (ccc->pPerScrnInfo->screenData); 260 } 261 Xfree(ccc->pPerScrnInfo); 262 } 263 } 264 265 /* 266 * Free the array of XcmsCCC structures 267 */ 268 Xfree(dpy->cms.defaultCCCs); 269 dpy->cms.defaultCCCs = (XPointer)NULL; 270} 271 272 273 274/* 275 * NAME 276 * _XcmsInitScrnInfo 277 * 278 * SYNOPSIS 279 */ 280int 281_XcmsInitScrnInfo( 282 register Display *dpy, 283 int screenNumber) 284/* 285 * DESCRIPTION 286 * Given a display and screen number, this routine attempts 287 * to initialize the Xcms per Screen Info structure 288 * (XcmsPerScrnInfo). 289 * 290 * RETURNS 291 * Returns zero if initialization failed; non-zero otherwise. 292 */ 293{ 294 XcmsFunctionSet **papSCCFuncSet = _XcmsSCCFuncSets; 295 XcmsCCC defaultccc; 296 297 /* 298 * Check if the XcmsCCC's for each screen has been created. 299 * Really dont need to be created until some routine uses the Xcms 300 * API routines. 301 */ 302 if ((XcmsCCC)dpy->cms.defaultCCCs == NULL) { 303 if (!_XcmsInitDefaultCCCs(dpy)) { 304 return(0); 305 } 306 } 307 308 defaultccc = (XcmsCCC)dpy->cms.defaultCCCs + screenNumber; 309 310 /* 311 * For each SCCFuncSet, try its pInitScrnFunc. 312 * If the function succeeds, then we got it! 313 */ 314 315 if (!defaultccc->pPerScrnInfo) { 316 /* 317 * This is one of two places where XcmsPerScrnInfo structures 318 * are allocated. There is one allocated per Screen that is 319 * shared among visuals that do not have specific intensity 320 * tables. Other XcmsPerScrnInfo structures are created 321 * for the latter (see XcmsCreateCCC). The ones created 322 * here are referenced by the default CCC. 323 */ 324 if (!(defaultccc->pPerScrnInfo = 325 Xcalloc(1, sizeof(XcmsPerScrnInfo)))) { 326 return(0); 327 } 328 defaultccc->pPerScrnInfo->state = XcmsInitNone; 329 } 330 331 while (*papSCCFuncSet != NULL) { 332 if ((*(*papSCCFuncSet)->screenInitProc)(dpy, screenNumber, 333 defaultccc->pPerScrnInfo)) { 334 defaultccc->pPerScrnInfo->state = XcmsInitSuccess; 335 return(1); 336 } 337 papSCCFuncSet++; 338 } 339 340 /* 341 * Use Default SCCData 342 */ 343 return(_XcmsLRGB_InitScrnDefault(dpy, screenNumber, defaultccc->pPerScrnInfo)); 344} 345 346 347/* 348 * NAME 349 * _XcmsFreeIntensityMaps 350 * 351 * SYNOPSIS 352 */ 353void 354_XcmsFreeIntensityMaps( 355 Display *dpy) 356/* 357 * DESCRIPTION 358 * Frees all XcmsIntensityMap structures in the linked list 359 * and sets dpy->cms.perVisualIntensityMaps to NULL. 360 * 361 * RETURNS 362 * void 363 * 364 */ 365{ 366 XcmsIntensityMap *pNext, *pFree; 367 368 pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps; 369 while (pNext != NULL) { 370 pFree = pNext; 371 pNext = pNext->pNext; 372 (*pFree->pFreeScreenData)(pFree->screenData); 373 /* Now free the XcmsIntensityMap structure */ 374 Xfree(pFree); 375 } 376 dpy->cms.perVisualIntensityMaps = (XPointer)NULL; 377} 378 379 380/* 381 * NAME 382 * _XcmsGetIntensityMap 383 * 384 * SYNOPSIS 385 */ 386XcmsIntensityMap * 387_XcmsGetIntensityMap( 388 Display *dpy, 389 Visual *visual) 390/* 391 * DESCRIPTION 392 * Attempts to return a per-Visual intensity map. 393 * 394 * RETURNS 395 * Pointer to the XcmsIntensityMap structure if found; 396 * otherwise NULL 397 * 398 */ 399{ 400 VisualID targetID = visual->visualid; 401 XcmsIntensityMap *pNext; 402 403 pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps; 404 while (pNext != NULL) { 405 if (targetID == pNext->visualID) { 406 return(pNext); 407 } 408 pNext = pNext->pNext; 409 } 410 return((XcmsIntensityMap *)NULL); 411} 412