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.  TekColor is a
8 * trademark of Tektronix, Inc.  The term "TekHVC" designates a particular
9 * color space that is the subject of U.S. Patent No. 4,985,853 (equivalent
10 * foreign patents pending).  Permission is hereby granted to use, copy,
11 * modify, sell, and otherwise distribute this software and its
12 * documentation for any purpose and without fee, provided that:
13 *
14 * 1. This copyright, permission, and disclaimer notice is reproduced in
15 *    all copies of this software and any modification thereof and in
16 *    supporting documentation;
17 * 2. Any color-handling application which displays TekHVC color
18 *    cooordinates identifies these as TekHVC color coordinates in any
19 *    interface that displays these coordinates and in any associated
20 *    documentation;
21 * 3. The term "TekHVC" is always used, and is only used, in association
22 *    with the mathematical derivations of the TekHVC Color Space,
23 *    including those provided in this file and any equivalent pathways and
24 *    mathematical derivations, regardless of digital (e.g., floating point
25 *    or integer) representation.
26 *
27 * Tektronix makes no representation about the suitability of this software
28 * for any purpose.  It is provided "as is" and with all faults.
29 *
30 * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
31 * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
32 * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
33 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
34 * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
35 * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
36 * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
37 *
38 *	NAME
39 *		TekHVCMxVC.c
40 *
41 *	DESCRIPTION
42 *		Source for the XcmsTekHVCQueryMaxVC() gamut boundary
43 *		querying routine.
44 *
45 */
46
47#ifdef HAVE_CONFIG_H
48#include <config.h>
49#endif
50#include "Xlibint.h"
51#include "Xcmsint.h"
52#include "Cv.h"
53
54/*
55 *	DEFINES
56 */
57#define MIN(x,y) ((x) > (y) ? (y) : (x))
58#define MIN3(x,y,z) ((x) > (MIN((y), (z))) ? (MIN((y), (z))) : (x))
59#define MAX(x,y) ((x) > (y) ? (x) : (y))
60#define MAX3(x,y,z) ((x) > (MAX((y), (z))) ? (x) : (MAX((y), (z))))
61#define START_V	    40.0
62#define START_C	    120.0
63
64
65/************************************************************************
66 *									*
67 *			 API PRIVATE ROUTINES				*
68 *									*
69 ************************************************************************/
70
71/*
72 *	NAME
73 *		_XcmsTekHVCQueryMaxVCRGB - Compute maximum value/chroma.
74 *
75 *	SYNOPSIS
76 */
77Status
78_XcmsTekHVCQueryMaxVCRGB(
79    XcmsCCC	ccc,
80    XcmsFloat	hue,
81    XcmsColor   *pColor_return,
82    XcmsRGBi    *pRGB_return)
83
84/*
85 *	DESCRIPTION
86 *		Return the maximum chroma for a specified hue, and the
87 *		corresponding value.  This is computed by a binary search of
88 *		all possible chromas.  An assumption is made that there are
89 *		no local maxima.  Use the unrounded Max Chroma because
90 *		the difference check can be small.
91 *
92 *		NOTE:  No local CCC is used because this is a private
93 *		       routine and all routines that call it are expected
94 *		       to behave properly, i.e. send a local CCC with
95 *		       no white adjust function and no gamut compression
96 *		       function.
97 *
98 *		This routine only accepts hue as input and outputs
99 *		HVC's and RGBi's.
100 *
101 *	RETURNS
102 *		XcmsFailure - Failure
103 *		XCMS_SUCCUSS - Succeeded
104 *
105 */
106{
107    XcmsFloat nSmall, nLarge;
108    XcmsColor tmp;
109
110    tmp.format = XcmsTekHVCFormat;
111    tmp.spec.TekHVC.H = hue;
112    /*  Use some unreachable color on the given hue */
113    tmp.spec.TekHVC.V = START_V;
114    tmp.spec.TekHVC.C = START_C;
115
116
117    /*
118     * Convert from HVC to RGB
119     *
120     * Note that the CIEXYZ to RGBi conversion routine must stuff the
121     * out of bounds RGBi values in tmp when the ccc->gamutCompProc
122     * is NULL.
123     */
124    if ((_XcmsConvertColorsWithWhitePt(ccc, &tmp,
125	    &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsRGBiFormat, (Bool *) NULL)
126	    == XcmsFailure) && tmp.format != XcmsRGBiFormat) {
127	return (XcmsFailure);
128    }
129
130    /* Now pick the smallest RGB */
131    nSmall = MIN3(tmp.spec.RGBi.red,
132		  tmp.spec.RGBi.green,
133		  tmp.spec.RGBi.blue);
134    /* Make the smallest RGB equal to zero */
135    tmp.spec.RGBi.red   -= nSmall;
136    tmp.spec.RGBi.green -= nSmall;
137    tmp.spec.RGBi.blue  -= nSmall;
138
139    /* Now pick the largest RGB */
140    nLarge = MAX3(tmp.spec.RGBi.red,
141		  tmp.spec.RGBi.green,
142		  tmp.spec.RGBi.blue);
143    /* Scale the RGB values based on the largest one */
144    tmp.spec.RGBi.red   /= nLarge;
145    tmp.spec.RGBi.green /= nLarge;
146    tmp.spec.RGBi.blue  /= nLarge;
147    tmp.format = XcmsRGBiFormat;
148
149    /* If the calling routine wants RGB value give them the ones used. */
150    if (pRGB_return) {
151	pRGB_return->red   = tmp.spec.RGBi.red;
152	pRGB_return->green = tmp.spec.RGBi.green;
153	pRGB_return->blue  = tmp.spec.RGBi.blue;
154    }
155
156    /* Convert from RGBi to HVC */
157    if (_XcmsConvertColorsWithWhitePt(ccc, &tmp,
158	    &ccc->pPerScrnInfo->screenWhitePt, 1, XcmsTekHVCFormat, (Bool *) NULL)
159	    == XcmsFailure) {
160	return (XcmsFailure);
161    }
162
163    /* make sure to return the input hue */
164    tmp.spec.TekHVC.H = hue;
165    memcpy((char *)pColor_return, (char *)&tmp, sizeof(XcmsColor));
166    return (XcmsSuccess);
167}
168
169
170/************************************************************************
171 *									*
172 *			 PUBLIC ROUTINES				*
173 *									*
174 ************************************************************************/
175
176/*
177 *	NAME
178 *		XcmsTekHVCQueryMaxVC - Compute maximum value and chroma.
179 *
180 *	SYNOPSIS
181 */
182Status
183XcmsTekHVCQueryMaxVC (
184    XcmsCCC ccc,
185    XcmsFloat hue,
186    XcmsColor *pColor_return)
187
188/*
189 *	DESCRIPTION
190 *		Return the maximum chroma for the specified hue, and the
191 *		corresponding value.
192 *
193 *	ASSUMPTIONS
194 *		This routine assumes that the white point associated with
195 *		the color specification is the Screen White Point.  The
196 *		Screen White Point will also be associated with the
197 *		returned color specification.
198 *
199 *	RETURNS
200 *		XcmsFailure - Failure
201 *		XcmsSuccess - Succeeded
202 *
203 */
204{
205    XcmsCCCRec myCCC;
206
207    /*
208     * Check Arguments
209     */
210    if (ccc == NULL || pColor_return == NULL) {
211	return(XcmsFailure);
212    }
213
214    /*
215     * Insure TekHVC installed
216     */
217    if (XcmsAddColorSpace(&XcmsTekHVCColorSpace) == XcmsFailure) {
218	return(XcmsFailure);
219    }
220
221    /* Use my own CCC */
222    memcpy ((char *)&myCCC, (char *)ccc, sizeof(XcmsCCCRec));
223    myCCC.clientWhitePt.format = XcmsUndefinedFormat;
224    myCCC.gamutCompProc = (XcmsCompressionProc)NULL;
225
226    while (hue < 0.0) {
227	hue += 360.0;
228    }
229    while (hue >= 360.0) {
230	hue -= 360.0;
231    }
232
233    return(_XcmsTekHVCQueryMaxVCRGB (&myCCC, hue, pColor_return,
234	    (XcmsRGBi *)NULL));
235}
236