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