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 */
51 static void _XcmsFreeDefaultCCCs(Display *dpy);
52
53
54 /************************************************************************
55 * *
56 * API PRIVATE ROUTINES *
57 * *
58 ************************************************************************/
59
60 /*
61 * NAME
62 * _XcmsCopyPointerArray
63 *
64 * SYNOPSIS
65 */
66 XPointer *
_XcmsCopyPointerArray(XPointer * pap)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 */
99 void
_XcmsFreePointerArray(XPointer * pap)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 */
120 XPointer *
_XcmsPushPointerArray(XPointer * pap,XPointer p,XPointer * papNoFree)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 */
162 int
_XcmsInitDefaultCCCs(Display * dpy)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 */
222 static void
_XcmsFreeDefaultCCCs(Display * dpy)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 */
281 int
_XcmsInitScrnInfo(register Display * dpy,int screenNumber)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 */
354 void
_XcmsFreeIntensityMaps(Display * dpy)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 */
387 XcmsIntensityMap *
_XcmsGetIntensityMap(Display * dpy,Visual * visual)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