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