cmsInt.c revision b4ee4795
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/* #define NEED_EVENTS */
38#ifdef HAVE_CONFIG_H
39#include <config.h>
40#endif
41#include <stdio.h>
42#include "Xlibint.h"
43#include "Xcmsint.h"
44#include "Cv.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 = (XPointer *)Xmalloc(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 = (XPointer *)Xmalloc(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 = (XcmsCCC)
188	    Xcalloc((unsigned)nScrn, (unsigned) sizeof(XcmsCCCRec)))) {
189	return(0);
190    }
191    dpy->cms.defaultCCCs = (XPointer)ccc;
192    dpy->free_funcs->defaultCCCs = _XcmsFreeDefaultCCCs;
193
194    for (i = 0; i < nScrn; i++, ccc++) {
195	ccc->dpy = dpy;
196	ccc->screenNumber = i;
197	ccc->visual = DefaultVisual(dpy, i);
198	/*
199	 * Used calloc to allocate memory so:
200	 *	ccc->clientWhitePt->format == XcmsUndefinedFormat
201	 *	ccc->gamutCompProc == NULL
202	 *	ccc->whitePtAdjProc == NULL
203	 *	ccc->pPerScrnInfo = NULL
204	 *
205	 * Don't need to create XcmsPerScrnInfo and its functionSet and
206	 * pScreenData components until the default CCC is accessed.
207	 * Note that the XcmsDefaultCCC routine calls _XcmsInitScrnInto
208	 * to do this.
209	 */
210	ccc->gamutCompProc = XCMSCOMPPROC;
211    }
212
213    return(1);
214}
215
216
217/*
218 *	NAME
219 *		_XcmsFreeDefaultCCCs - Free Default CCCs and its PerScrnInfo
220 *
221 *	SYNOPSIS
222 */
223static void
224_XcmsFreeDefaultCCCs(
225    Display *dpy)
226/*
227 *	DESCRIPTION
228 *		This routine frees the default XcmsCCC's associated with
229 *		each screen and its associated substructures as neccessary.
230 *
231 *	RETURNS
232 *		void
233 *
234 *
235 */
236{
237    int nScrn = ScreenCount(dpy);
238    XcmsCCC ccc;
239    int i;
240
241    /*
242     * Free Screen data in each DefaultCCC
243     *		Do not use XcmsFreeCCC here because it will not free
244     *		DefaultCCC's.
245     */
246    ccc = (XcmsCCC)dpy->cms.defaultCCCs;
247    for (i = nScrn; i--; ccc++) {
248	/*
249	 * Check if XcmsPerScrnInfo exists.
250	 *
251	 * This is the only place where XcmsPerScrnInfo structures
252	 * are freed since there is only one allocated per Screen.
253	 * It just so happens that we place its reference in the
254	 * default CCC.
255	 */
256	if (ccc->pPerScrnInfo) {
257	    /* Check if SCCData exists */
258	    if (ccc->pPerScrnInfo->state != XcmsInitNone
259		    && ccc->pPerScrnInfo->screenData) {
260		(*((XcmsFunctionSet *)ccc->pPerScrnInfo->functionSet)->screenFreeProc)
261			(ccc->pPerScrnInfo->screenData);
262	    }
263	    Xfree(ccc->pPerScrnInfo);
264	}
265    }
266
267    /*
268     * Free the array of XcmsCCC structures
269     */
270    Xfree(dpy->cms.defaultCCCs);
271    dpy->cms.defaultCCCs = (XPointer)NULL;
272}
273
274
275
276/*
277 *	NAME
278 *		_XcmsInitScrnInfo
279 *
280 *	SYNOPSIS
281 */
282int
283_XcmsInitScrnInfo(
284    register Display *dpy,
285    int screenNumber)
286/*
287 *	DESCRIPTION
288 *		Given a display and screen number, this routine attempts
289 *		to initialize the Xcms per Screen Info structure
290 *		(XcmsPerScrnInfo).
291 *
292 *	RETURNS
293 *		Returns zero if initialization failed; non-zero otherwise.
294 */
295{
296    XcmsFunctionSet **papSCCFuncSet = _XcmsSCCFuncSets;
297    XcmsCCC defaultccc;
298
299    /*
300     * Check if the XcmsCCC's for each screen has been created.
301     * Really dont need to be created until some routine uses the Xcms
302     * API routines.
303     */
304    if ((XcmsCCC)dpy->cms.defaultCCCs == NULL) {
305	if (!_XcmsInitDefaultCCCs(dpy)) {
306	    return(0);
307	}
308    }
309
310    defaultccc = (XcmsCCC)dpy->cms.defaultCCCs + screenNumber;
311
312    /*
313     * For each SCCFuncSet, try its pInitScrnFunc.
314     *	If the function succeeds, then we got it!
315     */
316
317    if (!defaultccc->pPerScrnInfo) {
318	/*
319	 * This is one of two places where XcmsPerScrnInfo structures
320	 * are allocated.  There is one allocated per Screen that is
321	 * shared among visuals that do not have specific intensity
322	 * tables.  Other XcmsPerScrnInfo structures are created
323	 * for the latter (see XcmsCreateCCC).  The ones created
324	 * here are referenced by the default CCC.
325	 */
326	if (!(defaultccc->pPerScrnInfo = (XcmsPerScrnInfo *)
327		Xcalloc(1, (unsigned) sizeof(XcmsPerScrnInfo)))) {
328	    return(0);
329	}
330	defaultccc->pPerScrnInfo->state = XcmsInitNone;
331    }
332
333    while (*papSCCFuncSet != NULL) {
334	if ((*(*papSCCFuncSet)->screenInitProc)(dpy, screenNumber,
335		defaultccc->pPerScrnInfo)) {
336	    defaultccc->pPerScrnInfo->state = XcmsInitSuccess;
337	    return(1);
338	}
339	papSCCFuncSet++;
340    }
341
342    /*
343     * Use Default SCCData
344     */
345    return(_XcmsLRGB_InitScrnDefault(dpy, screenNumber, defaultccc->pPerScrnInfo));
346}
347
348
349/*
350 *	NAME
351 *		_XcmsFreeIntensityMaps
352 *
353 *	SYNOPSIS
354 */
355void
356_XcmsFreeIntensityMaps(
357    Display *dpy)
358/*
359 *	DESCRIPTION
360 *		Frees all XcmsIntensityMap structures in the linked list
361 *		and sets dpy->cms.perVisualIntensityMaps to NULL.
362 *
363 *	RETURNS
364 *		void
365 *
366 */
367{
368    XcmsIntensityMap *pNext, *pFree;
369
370    pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps;
371    while (pNext != NULL) {
372	pFree = pNext;
373	pNext = pNext->pNext;
374	(*pFree->pFreeScreenData)(pFree->screenData);
375	/* Now free the XcmsIntensityMap structure */
376	Xfree(pFree);
377    }
378    dpy->cms.perVisualIntensityMaps = (XPointer)NULL;
379}
380
381
382/*
383 *	NAME
384 *		_XcmsGetIntensityMap
385 *
386 *	SYNOPSIS
387 */
388XcmsIntensityMap *
389_XcmsGetIntensityMap(
390    Display *dpy,
391    Visual *visual)
392/*
393 *	DESCRIPTION
394 *		Attempts to return a per-Visual intensity map.
395 *
396 *	RETURNS
397 *		Pointer to the XcmsIntensityMap structure if found;
398 *		otherwise NULL
399 *
400 */
401{
402    VisualID targetID = visual->visualid;
403    XcmsIntensityMap *pNext;
404
405    pNext = (XcmsIntensityMap *)dpy->cms.perVisualIntensityMaps;
406    while (pNext != NULL) {
407	if (targetID == pNext->visualID) {
408	    return(pNext);
409	}
410	pNext = pNext->pNext;
411    }
412    return((XcmsIntensityMap *)NULL);
413}
414