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