cmsInt.c revision 9c019ec5
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#include "reallocarray.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 = Xmallocarray(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 = Xmallocarray(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 = Xcalloc((unsigned)nScrn, 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 necessary. 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 don't 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 = 326 Xcalloc(1, 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