cmsInt.c revision 61b2299d
1/* $Xorg: cmsInt.c,v 1.4 2000/08/17 19:45:09 cpqbld Exp $ */
2
3/*
4 * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
5 * 	All Rights Reserved
6 *
7 * This file is a component of an X Window System-specific implementation
8 * of Xcms based on the TekColor Color Management System.  Permission is
9 * hereby granted to use, copy, modify, sell, and otherwise distribute this
10 * software and its documentation for any purpose and without fee, provided
11 * that this copyright, permission, and disclaimer notice is reproduced in
12 * all copies of this software and in supporting documentation.  TekColor
13 * is a trademark of Tektronix, Inc.
14 *
15 * Tektronix makes no representation about the suitability of this software
16 * for any purpose.  It is provided "as is" and with all faults.
17 *
18 * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
19 * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
21 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22 * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
23 * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
24 * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
25 *
26 *
27 *	NAME
28 *		XcmsInt.c - Xcms API utility routines
29 *
30 *	DESCRIPTION
31 *		Xcms Application Program Interface (API) utility
32 *		routines for hanging information directly onto
33 *		the Display structure.
34 *
35 *
36 */
37/* $XFree86: xc/lib/X11/cmsInt.c,v 1.4 2003/04/13 19:22:20 dawes Exp $ */
38
39/* #define NEED_EVENTS */
40#ifdef HAVE_CONFIG_H
41#include <config.h>
42#endif
43#include <stdio.h>
44#include "Xlibint.h"
45#include "Xcmsint.h"
46#include "Cv.h"
47
48#ifndef XCMSCOMPPROC
49#  define XCMSCOMPPROC	XcmsTekHVCClipC
50#endif
51
52/* forward/static */
53static void _XcmsFreeDefaultCCCs(Display *dpy);
54
55
56/************************************************************************
57 *									*
58 *			   API PRIVATE ROUTINES				*
59 *									*
60 ************************************************************************/
61
62/*
63 *	NAME
64 *		_XcmsCopyPointerArray
65 *
66 *	SYNOPSIS
67 */
68XPointer *
69_XcmsCopyPointerArray(
70    XPointer *pap)
71/*
72 *	DESCRIPTION
73 *		Copies an array of NULL terminated pointers.
74 *
75 *	RETURNS
76 *		Returns NULL if failed; otherwise the address to
77 *		the copy.
78 *
79 */
80{
81    XPointer *newArray;
82    char **tmp;
83    int n;
84
85    for (tmp = pap, n = 0; *tmp != NULL; tmp++, n++);
86    n++; /* add 1 to include the NULL pointer */
87
88    if ((newArray = (XPointer *)Xmalloc(n * sizeof(XPointer)))) {
89	memcpy((char *)newArray, (char *)pap,
90	       (unsigned)(n * sizeof(XPointer)));
91    }
92    return((XPointer *)newArray);
93}
94
95/*
96 *	NAME
97 *		_XcmsFreePointerArray
98 *
99 *	SYNOPSIS
100 */
101void
102_XcmsFreePointerArray(
103    XPointer *pap)
104/*
105 *	DESCRIPTION
106 *		Frees an array of NULL terminated pointers.
107 *
108 *	RETURNS
109 *		void
110 *
111 */
112{
113    Xfree(pap);
114}
115
116/*
117 *	NAME
118 *		_XcmsPushPointerArray
119 *
120 *	SYNOPSIS
121 */
122XPointer *
123_XcmsPushPointerArray(
124    XPointer *pap,
125    XPointer p,
126    XPointer *papNoFree)
127/*
128 *	DESCRIPTION
129 *		Places the specified pointer at the head of an array of NULL
130 *		terminated pointers.
131 *
132 *	RETURNS
133 *		Returns NULL if failed; otherwise the address to
134 *		the head of the array.
135 *
136 */
137{
138    XPointer *newArray;
139    char **tmp;
140    int n;
141
142    for (tmp = pap, n = 0; *tmp != NULL; tmp++, n++);
143
144    /* add 2: 1 for the new pointer and another for the NULL pointer */
145    n += 2;
146
147    if ((newArray = (XPointer *)Xmalloc(n * sizeof(XPointer)))) {
148	memcpy((char *)(newArray+1),(char *)pap,
149	       (unsigned)((n-1) * sizeof(XPointer)));
150	*newArray = p;
151    }
152    if (pap != papNoFree) {
153        _XcmsFreePointerArray(pap);
154    }
155    return((XPointer *)newArray);
156}
157
158/*
159 *	NAME
160 *		_XcmsInitDefaultCCCs
161 *
162 *	SYNOPSIS
163 */
164int
165_XcmsInitDefaultCCCs(
166    Display *dpy)
167/*
168 *	DESCRIPTION
169 *		Initializes the Xcms per Display Info structure
170 *		(XcmsPerDpyInfo).
171 *
172 *	RETURNS
173 *		Returns 0 if failed; otherwise non-zero.
174 *
175 */
176{
177    int nScrn = ScreenCount(dpy);
178    int i;
179    XcmsCCC ccc;
180
181    if (nScrn <= 0) {
182	return(0);
183    }
184
185    /*
186     * Create an array of XcmsCCC structures, one for each screen.
187     * They serve as the screen's default CCC.
188     */
189    if (!(ccc = (XcmsCCC)
190	    Xcalloc((unsigned)nScrn, (unsigned) sizeof(XcmsCCCRec)))) {
191	return(0);
192    }
193    dpy->cms.defaultCCCs = (XPointer)ccc;
194    dpy->free_funcs->defaultCCCs = _XcmsFreeDefaultCCCs;
195
196    for (i = 0; i < nScrn; i++, ccc++) {
197	ccc->dpy = dpy;
198	ccc->screenNumber = i;
199	ccc->visual = DefaultVisual(dpy, i);
200	/*
201	 * Used calloc to allocate memory so:
202	 *	ccc->clientWhitePt->format == XcmsUndefinedFormat
203	 *	ccc->gamutCompProc == NULL
204	 *	ccc->whitePtAdjProc == NULL
205	 *	ccc->pPerScrnInfo = NULL
206	 *
207	 * Don't need to create XcmsPerScrnInfo and its functionSet and
208	 * pScreenData components until the default CCC is accessed.
209	 * Note that the XcmsDefaultCCC routine calls _XcmsInitScrnInto
210	 * to do this.
211	 */
212	ccc->gamutCompProc = XCMSCOMPPROC;
213    }
214
215    return(1);
216}
217
218
219/*
220 *	NAME
221 *		_XcmsFreeDefaultCCCs - Free Default CCCs and its PerScrnInfo
222 *
223 *	SYNOPSIS
224 */
225static void
226_XcmsFreeDefaultCCCs(
227    Display *dpy)
228/*
229 *	DESCRIPTION
230 *		This routine frees the default XcmsCCC's associated with
231 *		each screen and its associated substructures as neccessary.
232 *
233 *	RETURNS
234 *		void
235 *
236 *
237 */
238{
239    int nScrn = ScreenCount(dpy);
240    XcmsCCC ccc;
241    int i;
242
243    /*
244     * Free Screen data in each DefaultCCC
245     *		Do not use XcmsFreeCCC here because it will not free
246     *		DefaultCCC's.
247     */
248    ccc = (XcmsCCC)dpy->cms.defaultCCCs;
249    for (i = nScrn; i--; ccc++) {
250	/*
251	 * Check if XcmsPerScrnInfo exists.
252	 *
253	 * This is the only place where XcmsPerScrnInfo structures
254	 * are freed since there is only one allocated per Screen.
255	 * It just so happens that we place its reference in the
256	 * default CCC.
257	 */
258	if (ccc->pPerScrnInfo) {
259	    /* Check if SCCData exists */
260	    if (ccc->pPerScrnInfo->state != XcmsInitNone
261		    && ccc->pPerScrnInfo->screenData) {
262		(*((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->screenFreeProc)
263			(ccc->pPerScrnInfo->screenData);
264	    }
265	    Xfree(ccc->pPerScrnInfo);
266	}
267    }
268
269    /*
270     * Free the array of XcmsCCC structures
271     */
272    Xfree(dpy->cms.defaultCCCs);
273    dpy->cms.defaultCCCs = (XPointer)NULL;
274}
275
276
277
278/*
279 *	NAME
280 *		_XcmsInitScrnInfo
281 *
282 *	SYNOPSIS
283 */
284int
285_XcmsInitScrnInfo(
286    register Display *dpy,
287    int screenNumber)
288/*
289 *	DESCRIPTION
290 *		Given a display and screen number, this routine attempts
291 *		to initialize the Xcms per Screen Info structure
292 *		(XcmsPerScrnInfo).
293 *
294 *	RETURNS
295 *		Returns zero if initialization failed; non-zero otherwise.
296 */
297{
298    XcmsFunctionSet **papSCCFuncSet = _XcmsSCCFuncSets;
299    XcmsCCC defaultccc;
300
301    /*
302     * Check if the XcmsCCC's for each screen has been created.
303     * Really dont need to be created until some routine uses the Xcms
304     * API routines.
305     */
306    if ((XcmsCCC)dpy->cms.defaultCCCs == NULL) {
307	if (!_XcmsInitDefaultCCCs(dpy)) {
308	    return(0);
309	}
310    }
311
312    defaultccc = (XcmsCCC)dpy->cms.defaultCCCs + screenNumber;
313
314    /*
315     * For each SCCFuncSet, try its pInitScrnFunc.
316     *	If the function succeeds, then we got it!
317     */
318
319    if (!defaultccc->pPerScrnInfo) {
320	/*
321	 * This is one of two places where XcmsPerScrnInfo structures
322	 * are allocated.  There is one allocated per Screen that is
323	 * shared among visuals that do not have specific intensity
324	 * tables.  Other XcmsPerScrnInfo structures are created
325	 * for the latter (see XcmsCreateCCC).  The ones created
326	 * here are referenced by the default CCC.
327	 */
328	if (!(defaultccc->pPerScrnInfo = (XcmsPerScrnInfo *)
329		Xcalloc(1, (unsigned) sizeof(XcmsPerScrnInfo)))) {
330	    return(0);
331	}
332	defaultccc->pPerScrnInfo->state = XcmsInitNone;
333    }
334
335    while (*papSCCFuncSet != NULL) {
336	if ((*(*papSCCFuncSet)->screenInitProc)(dpy, screenNumber,
337		defaultccc->pPerScrnInfo)) {
338	    defaultccc->pPerScrnInfo->state = XcmsInitSuccess;
339	    return(1);
340	}
341	papSCCFuncSet++;
342    }
343
344    /*
345     * Use Default SCCData
346     */
347    return(_XcmsLRGB_InitScrnDefault(dpy, screenNumber, defaultccc->pPerScrnInfo));
348}
349
350
351/*
352 *	NAME
353 *		_XcmsFreeIntensityMaps
354 *
355 *	SYNOPSIS
356 */
357void
358_XcmsFreeIntensityMaps(
359    Display *dpy)
360/*
361 *	DESCRIPTION
362 *		Frees all XcmsIntensityMap structures in the linked list
363 *		and sets dpy->cms.perVisualIntensityMaps to NULL.
364 *
365 *	RETURNS
366 *		void
367 *
368 */
369{
370    XcmsIntensityMap *pNext, *pFree;
371
372    pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps;
373    while (pNext != NULL) {
374	pFree = pNext;
375	pNext = pNext->pNext;
376	(*pFree->pFreeScreenData)(pFree->screenData);
377	/* Now free the XcmsIntensityMap structure */
378	Xfree(pFree);
379    }
380    dpy->cms.perVisualIntensityMaps = (XPointer)NULL;
381}
382
383
384/*
385 *	NAME
386 *		_XcmsGetIntensityMap
387 *
388 *	SYNOPSIS
389 */
390XcmsIntensityMap *
391_XcmsGetIntensityMap(
392    Display *dpy,
393    Visual *visual)
394/*
395 *	DESCRIPTION
396 *		Attempts to return a per-Visual intensity map.
397 *
398 *	RETURNS
399 *		Pointer to the XcmsIntensityMap structure if found;
400 *		otherwise NULL
401 *
402 */
403{
404    VisualID targetID = visual->visualid;
405    XcmsIntensityMap *pNext;
406
407    pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps;
408    while (pNext != NULL) {
409	if (targetID == pNext->visualID) {
410	    return(pNext);
411	}
412	pNext = pNext->pNext;
413    }
414    return((XcmsIntensityMap *)NULL);
415}
416