xref: /aosp_15_r20/external/pdfium/third_party/lcms/src/cmssm.c (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker //---------------------------------------------------------------------------------
2*3ac0a46fSAndroid Build Coastguard Worker //
3*3ac0a46fSAndroid Build Coastguard Worker //  Little Color Management System
4*3ac0a46fSAndroid Build Coastguard Worker //  Copyright (c) 1998-2023 Marti Maria Saguer
5*3ac0a46fSAndroid Build Coastguard Worker //
6*3ac0a46fSAndroid Build Coastguard Worker // Permission is hereby granted, free of charge, to any person obtaining
7*3ac0a46fSAndroid Build Coastguard Worker // a copy of this software and associated documentation files (the "Software"),
8*3ac0a46fSAndroid Build Coastguard Worker // to deal in the Software without restriction, including without limitation
9*3ac0a46fSAndroid Build Coastguard Worker // the rights to use, copy, modify, merge, publish, distribute, sublicense,
10*3ac0a46fSAndroid Build Coastguard Worker // and/or sell copies of the Software, and to permit persons to whom the Software
11*3ac0a46fSAndroid Build Coastguard Worker // is furnished to do so, subject to the following conditions:
12*3ac0a46fSAndroid Build Coastguard Worker //
13*3ac0a46fSAndroid Build Coastguard Worker // The above copyright notice and this permission notice shall be included in
14*3ac0a46fSAndroid Build Coastguard Worker // all copies or substantial portions of the Software.
15*3ac0a46fSAndroid Build Coastguard Worker //
16*3ac0a46fSAndroid Build Coastguard Worker // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17*3ac0a46fSAndroid Build Coastguard Worker // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18*3ac0a46fSAndroid Build Coastguard Worker // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19*3ac0a46fSAndroid Build Coastguard Worker // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20*3ac0a46fSAndroid Build Coastguard Worker // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21*3ac0a46fSAndroid Build Coastguard Worker // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22*3ac0a46fSAndroid Build Coastguard Worker // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23*3ac0a46fSAndroid Build Coastguard Worker //
24*3ac0a46fSAndroid Build Coastguard Worker //---------------------------------------------------------------------------------
25*3ac0a46fSAndroid Build Coastguard Worker //
26*3ac0a46fSAndroid Build Coastguard Worker 
27*3ac0a46fSAndroid Build Coastguard Worker #include "lcms2_internal.h"
28*3ac0a46fSAndroid Build Coastguard Worker 
29*3ac0a46fSAndroid Build Coastguard Worker 
30*3ac0a46fSAndroid Build Coastguard Worker // ------------------------------------------------------------------------
31*3ac0a46fSAndroid Build Coastguard Worker 
32*3ac0a46fSAndroid Build Coastguard Worker // Gamut boundary description by using Jan Morovic's Segment maxima method
33*3ac0a46fSAndroid Build Coastguard Worker // Many thanks to Jan for allowing me to use his algorithm.
34*3ac0a46fSAndroid Build Coastguard Worker 
35*3ac0a46fSAndroid Build Coastguard Worker // r = C*
36*3ac0a46fSAndroid Build Coastguard Worker // alpha = Hab
37*3ac0a46fSAndroid Build Coastguard Worker // theta = L*
38*3ac0a46fSAndroid Build Coastguard Worker 
39*3ac0a46fSAndroid Build Coastguard Worker #define SECTORS 16      // number of divisions in alpha and theta
40*3ac0a46fSAndroid Build Coastguard Worker 
41*3ac0a46fSAndroid Build Coastguard Worker // Spherical coordinates
42*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
43*3ac0a46fSAndroid Build Coastguard Worker 
44*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number r;
45*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number alpha;
46*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number theta;
47*3ac0a46fSAndroid Build Coastguard Worker 
48*3ac0a46fSAndroid Build Coastguard Worker } cmsSpherical;
49*3ac0a46fSAndroid Build Coastguard Worker 
50*3ac0a46fSAndroid Build Coastguard Worker typedef  enum {
51*3ac0a46fSAndroid Build Coastguard Worker         GP_EMPTY,
52*3ac0a46fSAndroid Build Coastguard Worker         GP_SPECIFIED,
53*3ac0a46fSAndroid Build Coastguard Worker         GP_MODELED
54*3ac0a46fSAndroid Build Coastguard Worker 
55*3ac0a46fSAndroid Build Coastguard Worker     } GDBPointType;
56*3ac0a46fSAndroid Build Coastguard Worker 
57*3ac0a46fSAndroid Build Coastguard Worker 
58*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
59*3ac0a46fSAndroid Build Coastguard Worker 
60*3ac0a46fSAndroid Build Coastguard Worker     GDBPointType Type;
61*3ac0a46fSAndroid Build Coastguard Worker     cmsSpherical p;         // Keep also alpha & theta of maximum
62*3ac0a46fSAndroid Build Coastguard Worker 
63*3ac0a46fSAndroid Build Coastguard Worker } cmsGDBPoint;
64*3ac0a46fSAndroid Build Coastguard Worker 
65*3ac0a46fSAndroid Build Coastguard Worker 
66*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
67*3ac0a46fSAndroid Build Coastguard Worker 
68*3ac0a46fSAndroid Build Coastguard Worker     cmsContext ContextID;
69*3ac0a46fSAndroid Build Coastguard Worker     cmsGDBPoint Gamut[SECTORS][SECTORS];
70*3ac0a46fSAndroid Build Coastguard Worker 
71*3ac0a46fSAndroid Build Coastguard Worker } cmsGDB;
72*3ac0a46fSAndroid Build Coastguard Worker 
73*3ac0a46fSAndroid Build Coastguard Worker 
74*3ac0a46fSAndroid Build Coastguard Worker // A line using the parametric form
75*3ac0a46fSAndroid Build Coastguard Worker // P = a + t*u
76*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
77*3ac0a46fSAndroid Build Coastguard Worker 
78*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 a;
79*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 u;
80*3ac0a46fSAndroid Build Coastguard Worker 
81*3ac0a46fSAndroid Build Coastguard Worker } cmsLine;
82*3ac0a46fSAndroid Build Coastguard Worker 
83*3ac0a46fSAndroid Build Coastguard Worker 
84*3ac0a46fSAndroid Build Coastguard Worker // A plane using the parametric form
85*3ac0a46fSAndroid Build Coastguard Worker // Q = b + r*v + s*w
86*3ac0a46fSAndroid Build Coastguard Worker typedef struct {
87*3ac0a46fSAndroid Build Coastguard Worker 
88*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 b;
89*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 v;
90*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 w;
91*3ac0a46fSAndroid Build Coastguard Worker 
92*3ac0a46fSAndroid Build Coastguard Worker } cmsPlane;
93*3ac0a46fSAndroid Build Coastguard Worker 
94*3ac0a46fSAndroid Build Coastguard Worker 
95*3ac0a46fSAndroid Build Coastguard Worker 
96*3ac0a46fSAndroid Build Coastguard Worker // --------------------------------------------------------------------------------------------
97*3ac0a46fSAndroid Build Coastguard Worker 
98*3ac0a46fSAndroid Build Coastguard Worker // ATAN2() which always returns degree positive numbers
99*3ac0a46fSAndroid Build Coastguard Worker 
100*3ac0a46fSAndroid Build Coastguard Worker static
_cmsAtan2(cmsFloat64Number y,cmsFloat64Number x)101*3ac0a46fSAndroid Build Coastguard Worker cmsFloat64Number _cmsAtan2(cmsFloat64Number y, cmsFloat64Number x)
102*3ac0a46fSAndroid Build Coastguard Worker {
103*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number a;
104*3ac0a46fSAndroid Build Coastguard Worker 
105*3ac0a46fSAndroid Build Coastguard Worker     // Deal with undefined case
106*3ac0a46fSAndroid Build Coastguard Worker     if (x == 0.0 && y == 0.0) return 0;
107*3ac0a46fSAndroid Build Coastguard Worker 
108*3ac0a46fSAndroid Build Coastguard Worker     a = (atan2(y, x) * 180.0) / M_PI;
109*3ac0a46fSAndroid Build Coastguard Worker 
110*3ac0a46fSAndroid Build Coastguard Worker     while (a < 0) {
111*3ac0a46fSAndroid Build Coastguard Worker         a += 360;
112*3ac0a46fSAndroid Build Coastguard Worker     }
113*3ac0a46fSAndroid Build Coastguard Worker 
114*3ac0a46fSAndroid Build Coastguard Worker     return a;
115*3ac0a46fSAndroid Build Coastguard Worker }
116*3ac0a46fSAndroid Build Coastguard Worker 
117*3ac0a46fSAndroid Build Coastguard Worker // Convert to spherical coordinates
118*3ac0a46fSAndroid Build Coastguard Worker static
ToSpherical(cmsSpherical * sp,const cmsVEC3 * v)119*3ac0a46fSAndroid Build Coastguard Worker void ToSpherical(cmsSpherical* sp, const cmsVEC3* v)
120*3ac0a46fSAndroid Build Coastguard Worker {
121*3ac0a46fSAndroid Build Coastguard Worker 
122*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number L, a, b;
123*3ac0a46fSAndroid Build Coastguard Worker 
124*3ac0a46fSAndroid Build Coastguard Worker     L = v ->n[VX];
125*3ac0a46fSAndroid Build Coastguard Worker     a = v ->n[VY];
126*3ac0a46fSAndroid Build Coastguard Worker     b = v ->n[VZ];
127*3ac0a46fSAndroid Build Coastguard Worker 
128*3ac0a46fSAndroid Build Coastguard Worker     sp ->r = sqrt( L*L + a*a + b*b );
129*3ac0a46fSAndroid Build Coastguard Worker 
130*3ac0a46fSAndroid Build Coastguard Worker    if (sp ->r == 0) {
131*3ac0a46fSAndroid Build Coastguard Worker         sp ->alpha = sp ->theta = 0;
132*3ac0a46fSAndroid Build Coastguard Worker         return;
133*3ac0a46fSAndroid Build Coastguard Worker     }
134*3ac0a46fSAndroid Build Coastguard Worker 
135*3ac0a46fSAndroid Build Coastguard Worker     sp ->alpha = _cmsAtan2(a, b);
136*3ac0a46fSAndroid Build Coastguard Worker     sp ->theta = _cmsAtan2(sqrt(a*a + b*b), L);
137*3ac0a46fSAndroid Build Coastguard Worker }
138*3ac0a46fSAndroid Build Coastguard Worker 
139*3ac0a46fSAndroid Build Coastguard Worker 
140*3ac0a46fSAndroid Build Coastguard Worker // Convert to cartesian from spherical
141*3ac0a46fSAndroid Build Coastguard Worker static
ToCartesian(cmsVEC3 * v,const cmsSpherical * sp)142*3ac0a46fSAndroid Build Coastguard Worker void ToCartesian(cmsVEC3* v, const cmsSpherical* sp)
143*3ac0a46fSAndroid Build Coastguard Worker {
144*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number sin_alpha;
145*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number cos_alpha;
146*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number sin_theta;
147*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number cos_theta;
148*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number L, a, b;
149*3ac0a46fSAndroid Build Coastguard Worker 
150*3ac0a46fSAndroid Build Coastguard Worker     sin_alpha = sin((M_PI * sp ->alpha) / 180.0);
151*3ac0a46fSAndroid Build Coastguard Worker     cos_alpha = cos((M_PI * sp ->alpha) / 180.0);
152*3ac0a46fSAndroid Build Coastguard Worker     sin_theta = sin((M_PI * sp ->theta) / 180.0);
153*3ac0a46fSAndroid Build Coastguard Worker     cos_theta = cos((M_PI * sp ->theta) / 180.0);
154*3ac0a46fSAndroid Build Coastguard Worker 
155*3ac0a46fSAndroid Build Coastguard Worker     a = sp ->r * sin_theta * sin_alpha;
156*3ac0a46fSAndroid Build Coastguard Worker     b = sp ->r * sin_theta * cos_alpha;
157*3ac0a46fSAndroid Build Coastguard Worker     L = sp ->r * cos_theta;
158*3ac0a46fSAndroid Build Coastguard Worker 
159*3ac0a46fSAndroid Build Coastguard Worker     v ->n[VX] = L;
160*3ac0a46fSAndroid Build Coastguard Worker     v ->n[VY] = a;
161*3ac0a46fSAndroid Build Coastguard Worker     v ->n[VZ] = b;
162*3ac0a46fSAndroid Build Coastguard Worker }
163*3ac0a46fSAndroid Build Coastguard Worker 
164*3ac0a46fSAndroid Build Coastguard Worker 
165*3ac0a46fSAndroid Build Coastguard Worker // Quantize sector of a spherical coordinate. Saturate 360, 180 to last sector
166*3ac0a46fSAndroid Build Coastguard Worker // The limits are the centers of each sector, so
167*3ac0a46fSAndroid Build Coastguard Worker static
QuantizeToSector(const cmsSpherical * sp,int * alpha,int * theta)168*3ac0a46fSAndroid Build Coastguard Worker void QuantizeToSector(const cmsSpherical* sp, int* alpha, int* theta)
169*3ac0a46fSAndroid Build Coastguard Worker {
170*3ac0a46fSAndroid Build Coastguard Worker     *alpha = (int) floor(((sp->alpha * (SECTORS)) / 360.0) );
171*3ac0a46fSAndroid Build Coastguard Worker     *theta = (int) floor(((sp->theta * (SECTORS)) / 180.0) );
172*3ac0a46fSAndroid Build Coastguard Worker 
173*3ac0a46fSAndroid Build Coastguard Worker     if (*alpha >= SECTORS)
174*3ac0a46fSAndroid Build Coastguard Worker         *alpha = SECTORS-1;
175*3ac0a46fSAndroid Build Coastguard Worker     if (*theta >= SECTORS)
176*3ac0a46fSAndroid Build Coastguard Worker         *theta = SECTORS-1;
177*3ac0a46fSAndroid Build Coastguard Worker }
178*3ac0a46fSAndroid Build Coastguard Worker 
179*3ac0a46fSAndroid Build Coastguard Worker 
180*3ac0a46fSAndroid Build Coastguard Worker // Line determined by 2 points
181*3ac0a46fSAndroid Build Coastguard Worker static
LineOf2Points(cmsLine * line,cmsVEC3 * a,cmsVEC3 * b)182*3ac0a46fSAndroid Build Coastguard Worker void LineOf2Points(cmsLine* line, cmsVEC3* a, cmsVEC3* b)
183*3ac0a46fSAndroid Build Coastguard Worker {
184*3ac0a46fSAndroid Build Coastguard Worker 
185*3ac0a46fSAndroid Build Coastguard Worker     _cmsVEC3init(&line ->a, a ->n[VX], a ->n[VY], a ->n[VZ]);
186*3ac0a46fSAndroid Build Coastguard Worker     _cmsVEC3init(&line ->u, b ->n[VX] - a ->n[VX],
187*3ac0a46fSAndroid Build Coastguard Worker                             b ->n[VY] - a ->n[VY],
188*3ac0a46fSAndroid Build Coastguard Worker                             b ->n[VZ] - a ->n[VZ]);
189*3ac0a46fSAndroid Build Coastguard Worker }
190*3ac0a46fSAndroid Build Coastguard Worker 
191*3ac0a46fSAndroid Build Coastguard Worker 
192*3ac0a46fSAndroid Build Coastguard Worker // Evaluate parametric line
193*3ac0a46fSAndroid Build Coastguard Worker static
GetPointOfLine(cmsVEC3 * p,const cmsLine * line,cmsFloat64Number t)194*3ac0a46fSAndroid Build Coastguard Worker void GetPointOfLine(cmsVEC3* p, const cmsLine* line, cmsFloat64Number t)
195*3ac0a46fSAndroid Build Coastguard Worker {
196*3ac0a46fSAndroid Build Coastguard Worker     p ->n[VX] = line ->a.n[VX] + t * line->u.n[VX];
197*3ac0a46fSAndroid Build Coastguard Worker     p ->n[VY] = line ->a.n[VY] + t * line->u.n[VY];
198*3ac0a46fSAndroid Build Coastguard Worker     p ->n[VZ] = line ->a.n[VZ] + t * line->u.n[VZ];
199*3ac0a46fSAndroid Build Coastguard Worker }
200*3ac0a46fSAndroid Build Coastguard Worker 
201*3ac0a46fSAndroid Build Coastguard Worker 
202*3ac0a46fSAndroid Build Coastguard Worker 
203*3ac0a46fSAndroid Build Coastguard Worker /*
204*3ac0a46fSAndroid Build Coastguard Worker     Closest point in sector line1 to sector line2 (both are defined as 0 <=t <= 1)
205*3ac0a46fSAndroid Build Coastguard Worker     http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
206*3ac0a46fSAndroid Build Coastguard Worker 
207*3ac0a46fSAndroid Build Coastguard Worker     Copyright 2001, softSurfer (www.softsurfer.com)
208*3ac0a46fSAndroid Build Coastguard Worker     This code may be freely used and modified for any purpose
209*3ac0a46fSAndroid Build Coastguard Worker     providing that this copyright notice is included with it.
210*3ac0a46fSAndroid Build Coastguard Worker     SoftSurfer makes no warranty for this code, and cannot be held
211*3ac0a46fSAndroid Build Coastguard Worker     liable for any real or imagined damage resulting from its use.
212*3ac0a46fSAndroid Build Coastguard Worker     Users of this code must verify correctness for their application.
213*3ac0a46fSAndroid Build Coastguard Worker 
214*3ac0a46fSAndroid Build Coastguard Worker */
215*3ac0a46fSAndroid Build Coastguard Worker 
216*3ac0a46fSAndroid Build Coastguard Worker static
ClosestLineToLine(cmsVEC3 * r,const cmsLine * line1,const cmsLine * line2)217*3ac0a46fSAndroid Build Coastguard Worker cmsBool ClosestLineToLine(cmsVEC3* r, const cmsLine* line1, const cmsLine* line2)
218*3ac0a46fSAndroid Build Coastguard Worker {
219*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number a, b, c, d, e, D;
220*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number sc, sN, sD;
221*3ac0a46fSAndroid Build Coastguard Worker     //cmsFloat64Number tc; // left for future use
222*3ac0a46fSAndroid Build Coastguard Worker     cmsFloat64Number tN, tD;
223*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 w0;
224*3ac0a46fSAndroid Build Coastguard Worker 
225*3ac0a46fSAndroid Build Coastguard Worker     _cmsVEC3minus(&w0, &line1 ->a, &line2 ->a);
226*3ac0a46fSAndroid Build Coastguard Worker 
227*3ac0a46fSAndroid Build Coastguard Worker     a  = _cmsVEC3dot(&line1 ->u, &line1 ->u);
228*3ac0a46fSAndroid Build Coastguard Worker     b  = _cmsVEC3dot(&line1 ->u, &line2 ->u);
229*3ac0a46fSAndroid Build Coastguard Worker     c  = _cmsVEC3dot(&line2 ->u, &line2 ->u);
230*3ac0a46fSAndroid Build Coastguard Worker     d  = _cmsVEC3dot(&line1 ->u, &w0);
231*3ac0a46fSAndroid Build Coastguard Worker     e  = _cmsVEC3dot(&line2 ->u, &w0);
232*3ac0a46fSAndroid Build Coastguard Worker 
233*3ac0a46fSAndroid Build Coastguard Worker     D  = a*c - b * b;      // Denominator
234*3ac0a46fSAndroid Build Coastguard Worker     sD = tD = D;           // default sD = D >= 0
235*3ac0a46fSAndroid Build Coastguard Worker 
236*3ac0a46fSAndroid Build Coastguard Worker     if (D <  MATRIX_DET_TOLERANCE) {   // the lines are almost parallel
237*3ac0a46fSAndroid Build Coastguard Worker 
238*3ac0a46fSAndroid Build Coastguard Worker         sN = 0.0;        // force using point P0 on segment S1
239*3ac0a46fSAndroid Build Coastguard Worker         sD = 1.0;        // to prevent possible division by 0.0 later
240*3ac0a46fSAndroid Build Coastguard Worker         tN = e;
241*3ac0a46fSAndroid Build Coastguard Worker         tD = c;
242*3ac0a46fSAndroid Build Coastguard Worker     }
243*3ac0a46fSAndroid Build Coastguard Worker     else {                // get the closest points on the infinite lines
244*3ac0a46fSAndroid Build Coastguard Worker 
245*3ac0a46fSAndroid Build Coastguard Worker         sN = (b*e - c*d);
246*3ac0a46fSAndroid Build Coastguard Worker         tN = (a*e - b*d);
247*3ac0a46fSAndroid Build Coastguard Worker 
248*3ac0a46fSAndroid Build Coastguard Worker         if (sN < 0.0) {       // sc < 0 => the s=0 edge is visible
249*3ac0a46fSAndroid Build Coastguard Worker 
250*3ac0a46fSAndroid Build Coastguard Worker             sN = 0.0;
251*3ac0a46fSAndroid Build Coastguard Worker             tN = e;
252*3ac0a46fSAndroid Build Coastguard Worker             tD = c;
253*3ac0a46fSAndroid Build Coastguard Worker         }
254*3ac0a46fSAndroid Build Coastguard Worker         else if (sN > sD) {   // sc > 1 => the s=1 edge is visible
255*3ac0a46fSAndroid Build Coastguard Worker             sN = sD;
256*3ac0a46fSAndroid Build Coastguard Worker             tN = e + b;
257*3ac0a46fSAndroid Build Coastguard Worker             tD = c;
258*3ac0a46fSAndroid Build Coastguard Worker         }
259*3ac0a46fSAndroid Build Coastguard Worker     }
260*3ac0a46fSAndroid Build Coastguard Worker 
261*3ac0a46fSAndroid Build Coastguard Worker     if (tN < 0.0) {           // tc < 0 => the t=0 edge is visible
262*3ac0a46fSAndroid Build Coastguard Worker 
263*3ac0a46fSAndroid Build Coastguard Worker         tN = 0.0;
264*3ac0a46fSAndroid Build Coastguard Worker         // recompute sc for this edge
265*3ac0a46fSAndroid Build Coastguard Worker         if (-d < 0.0)
266*3ac0a46fSAndroid Build Coastguard Worker             sN = 0.0;
267*3ac0a46fSAndroid Build Coastguard Worker         else if (-d > a)
268*3ac0a46fSAndroid Build Coastguard Worker             sN = sD;
269*3ac0a46fSAndroid Build Coastguard Worker         else {
270*3ac0a46fSAndroid Build Coastguard Worker             sN = -d;
271*3ac0a46fSAndroid Build Coastguard Worker             sD = a;
272*3ac0a46fSAndroid Build Coastguard Worker         }
273*3ac0a46fSAndroid Build Coastguard Worker     }
274*3ac0a46fSAndroid Build Coastguard Worker     else if (tN > tD) {      // tc > 1 => the t=1 edge is visible
275*3ac0a46fSAndroid Build Coastguard Worker 
276*3ac0a46fSAndroid Build Coastguard Worker         tN = tD;
277*3ac0a46fSAndroid Build Coastguard Worker 
278*3ac0a46fSAndroid Build Coastguard Worker         // recompute sc for this edge
279*3ac0a46fSAndroid Build Coastguard Worker         if ((-d + b) < 0.0)
280*3ac0a46fSAndroid Build Coastguard Worker             sN = 0;
281*3ac0a46fSAndroid Build Coastguard Worker         else if ((-d + b) > a)
282*3ac0a46fSAndroid Build Coastguard Worker             sN = sD;
283*3ac0a46fSAndroid Build Coastguard Worker         else {
284*3ac0a46fSAndroid Build Coastguard Worker             sN = (-d + b);
285*3ac0a46fSAndroid Build Coastguard Worker             sD = a;
286*3ac0a46fSAndroid Build Coastguard Worker         }
287*3ac0a46fSAndroid Build Coastguard Worker     }
288*3ac0a46fSAndroid Build Coastguard Worker     // finally do the division to get sc and tc
289*3ac0a46fSAndroid Build Coastguard Worker     sc = (fabs(sN) < MATRIX_DET_TOLERANCE ? 0.0 : sN / sD);
290*3ac0a46fSAndroid Build Coastguard Worker     //tc = (fabs(tN) < MATRIX_DET_TOLERANCE ? 0.0 : tN / tD); // left for future use.
291*3ac0a46fSAndroid Build Coastguard Worker 
292*3ac0a46fSAndroid Build Coastguard Worker     GetPointOfLine(r, line1, sc);
293*3ac0a46fSAndroid Build Coastguard Worker     return TRUE;
294*3ac0a46fSAndroid Build Coastguard Worker }
295*3ac0a46fSAndroid Build Coastguard Worker 
296*3ac0a46fSAndroid Build Coastguard Worker 
297*3ac0a46fSAndroid Build Coastguard Worker 
298*3ac0a46fSAndroid Build Coastguard Worker // ------------------------------------------------------------------ Wrapper
299*3ac0a46fSAndroid Build Coastguard Worker 
300*3ac0a46fSAndroid Build Coastguard Worker 
301*3ac0a46fSAndroid Build Coastguard Worker // Allocate & free structure
cmsGBDAlloc(cmsContext ContextID)302*3ac0a46fSAndroid Build Coastguard Worker cmsHANDLE  CMSEXPORT cmsGBDAlloc(cmsContext ContextID)
303*3ac0a46fSAndroid Build Coastguard Worker {
304*3ac0a46fSAndroid Build Coastguard Worker     cmsGDB* gbd = (cmsGDB*) _cmsMallocZero(ContextID, sizeof(cmsGDB));
305*3ac0a46fSAndroid Build Coastguard Worker     if (gbd == NULL) return NULL;
306*3ac0a46fSAndroid Build Coastguard Worker 
307*3ac0a46fSAndroid Build Coastguard Worker     gbd -> ContextID = ContextID;
308*3ac0a46fSAndroid Build Coastguard Worker 
309*3ac0a46fSAndroid Build Coastguard Worker     return (cmsHANDLE) gbd;
310*3ac0a46fSAndroid Build Coastguard Worker }
311*3ac0a46fSAndroid Build Coastguard Worker 
312*3ac0a46fSAndroid Build Coastguard Worker 
cmsGBDFree(cmsHANDLE hGBD)313*3ac0a46fSAndroid Build Coastguard Worker void CMSEXPORT cmsGBDFree(cmsHANDLE hGBD)
314*3ac0a46fSAndroid Build Coastguard Worker {
315*3ac0a46fSAndroid Build Coastguard Worker     cmsGDB* gbd = (cmsGDB*) hGBD;
316*3ac0a46fSAndroid Build Coastguard Worker     if (hGBD != NULL)
317*3ac0a46fSAndroid Build Coastguard Worker         _cmsFree(gbd->ContextID, (void*) gbd);
318*3ac0a46fSAndroid Build Coastguard Worker }
319*3ac0a46fSAndroid Build Coastguard Worker 
320*3ac0a46fSAndroid Build Coastguard Worker 
321*3ac0a46fSAndroid Build Coastguard Worker // Auxiliary to retrieve a pointer to the segmentr containing the Lab value
322*3ac0a46fSAndroid Build Coastguard Worker static
GetPoint(cmsGDB * gbd,const cmsCIELab * Lab,cmsSpherical * sp)323*3ac0a46fSAndroid Build Coastguard Worker cmsGDBPoint* GetPoint(cmsGDB* gbd, const cmsCIELab* Lab, cmsSpherical* sp)
324*3ac0a46fSAndroid Build Coastguard Worker {
325*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 v;
326*3ac0a46fSAndroid Build Coastguard Worker     int alpha, theta;
327*3ac0a46fSAndroid Build Coastguard Worker 
328*3ac0a46fSAndroid Build Coastguard Worker     // Housekeeping
329*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(gbd != NULL);
330*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(Lab != NULL);
331*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(sp != NULL);
332*3ac0a46fSAndroid Build Coastguard Worker 
333*3ac0a46fSAndroid Build Coastguard Worker     // Center L* by subtracting half of its domain, that's 50
334*3ac0a46fSAndroid Build Coastguard Worker     _cmsVEC3init(&v, Lab ->L - 50.0, Lab ->a, Lab ->b);
335*3ac0a46fSAndroid Build Coastguard Worker 
336*3ac0a46fSAndroid Build Coastguard Worker     // Convert to spherical coordinates
337*3ac0a46fSAndroid Build Coastguard Worker     ToSpherical(sp, &v);
338*3ac0a46fSAndroid Build Coastguard Worker 
339*3ac0a46fSAndroid Build Coastguard Worker     if (sp ->r < 0 || sp ->alpha < 0 || sp->theta < 0) {
340*3ac0a46fSAndroid Build Coastguard Worker          cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, "spherical value out of range");
341*3ac0a46fSAndroid Build Coastguard Worker          return NULL;
342*3ac0a46fSAndroid Build Coastguard Worker     }
343*3ac0a46fSAndroid Build Coastguard Worker 
344*3ac0a46fSAndroid Build Coastguard Worker     // On which sector it falls?
345*3ac0a46fSAndroid Build Coastguard Worker     QuantizeToSector(sp, &alpha, &theta);
346*3ac0a46fSAndroid Build Coastguard Worker 
347*3ac0a46fSAndroid Build Coastguard Worker     if (alpha < 0 || theta < 0 || alpha >= SECTORS || theta >= SECTORS) {
348*3ac0a46fSAndroid Build Coastguard Worker          cmsSignalError(gbd ->ContextID, cmsERROR_RANGE, " quadrant out of range");
349*3ac0a46fSAndroid Build Coastguard Worker          return NULL;
350*3ac0a46fSAndroid Build Coastguard Worker     }
351*3ac0a46fSAndroid Build Coastguard Worker 
352*3ac0a46fSAndroid Build Coastguard Worker     // Get pointer to the sector
353*3ac0a46fSAndroid Build Coastguard Worker     return &gbd ->Gamut[theta][alpha];
354*3ac0a46fSAndroid Build Coastguard Worker }
355*3ac0a46fSAndroid Build Coastguard Worker 
356*3ac0a46fSAndroid Build Coastguard Worker // Add a point to gamut descriptor. Point to add is in Lab color space.
357*3ac0a46fSAndroid Build Coastguard Worker // GBD is centered on a=b=0 and L*=50
cmsGDBAddPoint(cmsHANDLE hGBD,const cmsCIELab * Lab)358*3ac0a46fSAndroid Build Coastguard Worker cmsBool CMSEXPORT cmsGDBAddPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
359*3ac0a46fSAndroid Build Coastguard Worker {
360*3ac0a46fSAndroid Build Coastguard Worker     cmsGDB* gbd = (cmsGDB*) hGBD;
361*3ac0a46fSAndroid Build Coastguard Worker     cmsGDBPoint* ptr;
362*3ac0a46fSAndroid Build Coastguard Worker     cmsSpherical sp;
363*3ac0a46fSAndroid Build Coastguard Worker 
364*3ac0a46fSAndroid Build Coastguard Worker 
365*3ac0a46fSAndroid Build Coastguard Worker     // Get pointer to the sector
366*3ac0a46fSAndroid Build Coastguard Worker     ptr = GetPoint(gbd, Lab, &sp);
367*3ac0a46fSAndroid Build Coastguard Worker     if (ptr == NULL) return FALSE;
368*3ac0a46fSAndroid Build Coastguard Worker 
369*3ac0a46fSAndroid Build Coastguard Worker     // If no samples at this sector, add it
370*3ac0a46fSAndroid Build Coastguard Worker     if (ptr ->Type == GP_EMPTY) {
371*3ac0a46fSAndroid Build Coastguard Worker 
372*3ac0a46fSAndroid Build Coastguard Worker         ptr -> Type = GP_SPECIFIED;
373*3ac0a46fSAndroid Build Coastguard Worker         ptr -> p    = sp;
374*3ac0a46fSAndroid Build Coastguard Worker     }
375*3ac0a46fSAndroid Build Coastguard Worker     else {
376*3ac0a46fSAndroid Build Coastguard Worker 
377*3ac0a46fSAndroid Build Coastguard Worker 
378*3ac0a46fSAndroid Build Coastguard Worker         // Substitute only if radius is greater
379*3ac0a46fSAndroid Build Coastguard Worker         if (sp.r > ptr -> p.r) {
380*3ac0a46fSAndroid Build Coastguard Worker 
381*3ac0a46fSAndroid Build Coastguard Worker                 ptr -> Type = GP_SPECIFIED;
382*3ac0a46fSAndroid Build Coastguard Worker                 ptr -> p    = sp;
383*3ac0a46fSAndroid Build Coastguard Worker         }
384*3ac0a46fSAndroid Build Coastguard Worker     }
385*3ac0a46fSAndroid Build Coastguard Worker 
386*3ac0a46fSAndroid Build Coastguard Worker     return TRUE;
387*3ac0a46fSAndroid Build Coastguard Worker }
388*3ac0a46fSAndroid Build Coastguard Worker 
389*3ac0a46fSAndroid Build Coastguard Worker // Check if a given point falls inside gamut
cmsGDBCheckPoint(cmsHANDLE hGBD,const cmsCIELab * Lab)390*3ac0a46fSAndroid Build Coastguard Worker cmsBool CMSEXPORT cmsGDBCheckPoint(cmsHANDLE hGBD, const cmsCIELab* Lab)
391*3ac0a46fSAndroid Build Coastguard Worker {
392*3ac0a46fSAndroid Build Coastguard Worker     cmsGDB* gbd = (cmsGDB*) hGBD;
393*3ac0a46fSAndroid Build Coastguard Worker     cmsGDBPoint* ptr;
394*3ac0a46fSAndroid Build Coastguard Worker     cmsSpherical sp;
395*3ac0a46fSAndroid Build Coastguard Worker 
396*3ac0a46fSAndroid Build Coastguard Worker     // Get pointer to the sector
397*3ac0a46fSAndroid Build Coastguard Worker     ptr = GetPoint(gbd, Lab, &sp);
398*3ac0a46fSAndroid Build Coastguard Worker     if (ptr == NULL) return FALSE;
399*3ac0a46fSAndroid Build Coastguard Worker 
400*3ac0a46fSAndroid Build Coastguard Worker     // If no samples at this sector, return no data
401*3ac0a46fSAndroid Build Coastguard Worker     if (ptr ->Type == GP_EMPTY) return FALSE;
402*3ac0a46fSAndroid Build Coastguard Worker 
403*3ac0a46fSAndroid Build Coastguard Worker     // In gamut only if radius is greater
404*3ac0a46fSAndroid Build Coastguard Worker 
405*3ac0a46fSAndroid Build Coastguard Worker     return (sp.r <= ptr -> p.r);
406*3ac0a46fSAndroid Build Coastguard Worker }
407*3ac0a46fSAndroid Build Coastguard Worker 
408*3ac0a46fSAndroid Build Coastguard Worker // -----------------------------------------------------------------------------------------------------------------------
409*3ac0a46fSAndroid Build Coastguard Worker 
410*3ac0a46fSAndroid Build Coastguard Worker // Find near sectors. The list of sectors found is returned on Close[].
411*3ac0a46fSAndroid Build Coastguard Worker // The function returns the number of sectors as well.
412*3ac0a46fSAndroid Build Coastguard Worker 
413*3ac0a46fSAndroid Build Coastguard Worker // 24   9  10  11  12
414*3ac0a46fSAndroid Build Coastguard Worker // 23   8   1   2  13
415*3ac0a46fSAndroid Build Coastguard Worker // 22   7   *   3  14
416*3ac0a46fSAndroid Build Coastguard Worker // 21   6   5   4  15
417*3ac0a46fSAndroid Build Coastguard Worker // 20  19  18  17  16
418*3ac0a46fSAndroid Build Coastguard Worker //
419*3ac0a46fSAndroid Build Coastguard Worker // Those are the relative movements
420*3ac0a46fSAndroid Build Coastguard Worker // {-2,-2}, {-1, -2}, {0, -2}, {+1, -2}, {+2,  -2},
421*3ac0a46fSAndroid Build Coastguard Worker // {-2,-1}, {-1, -1}, {0, -1}, {+1, -1}, {+2,  -1},
422*3ac0a46fSAndroid Build Coastguard Worker // {-2, 0}, {-1,  0}, {0,  0}, {+1,  0}, {+2,   0},
423*3ac0a46fSAndroid Build Coastguard Worker // {-2,+1}, {-1, +1}, {0, +1}, {+1,  +1}, {+2,  +1},
424*3ac0a46fSAndroid Build Coastguard Worker // {-2,+2}, {-1, +2}, {0, +2}, {+1,  +2}, {+2,  +2}};
425*3ac0a46fSAndroid Build Coastguard Worker 
426*3ac0a46fSAndroid Build Coastguard Worker 
427*3ac0a46fSAndroid Build Coastguard Worker static
428*3ac0a46fSAndroid Build Coastguard Worker const struct _spiral {
429*3ac0a46fSAndroid Build Coastguard Worker 
430*3ac0a46fSAndroid Build Coastguard Worker     int AdvX, AdvY;
431*3ac0a46fSAndroid Build Coastguard Worker 
432*3ac0a46fSAndroid Build Coastguard Worker     } Spiral[] = { {0,  -1}, {+1, -1}, {+1,  0}, {+1, +1}, {0,  +1}, {-1, +1},
433*3ac0a46fSAndroid Build Coastguard Worker                    {-1,  0}, {-1, -1}, {-1, -2}, {0,  -2}, {+1, -2}, {+2, -2},
434*3ac0a46fSAndroid Build Coastguard Worker                    {+2, -1}, {+2,  0}, {+2, +1}, {+2, +2}, {+1, +2}, {0,  +2},
435*3ac0a46fSAndroid Build Coastguard Worker                    {-1, +2}, {-2, +2}, {-2, +1}, {-2, 0},  {-2, -1}, {-2, -2} };
436*3ac0a46fSAndroid Build Coastguard Worker 
437*3ac0a46fSAndroid Build Coastguard Worker #define NSTEPS (sizeof(Spiral) / sizeof(struct _spiral))
438*3ac0a46fSAndroid Build Coastguard Worker 
439*3ac0a46fSAndroid Build Coastguard Worker static
FindNearSectors(cmsGDB * gbd,int alpha,int theta,cmsGDBPoint * Close[])440*3ac0a46fSAndroid Build Coastguard Worker int FindNearSectors(cmsGDB* gbd, int alpha, int theta, cmsGDBPoint* Close[])
441*3ac0a46fSAndroid Build Coastguard Worker {
442*3ac0a46fSAndroid Build Coastguard Worker     int nSectors = 0;
443*3ac0a46fSAndroid Build Coastguard Worker     int a, t;
444*3ac0a46fSAndroid Build Coastguard Worker     cmsUInt32Number i;
445*3ac0a46fSAndroid Build Coastguard Worker     cmsGDBPoint* pt;
446*3ac0a46fSAndroid Build Coastguard Worker 
447*3ac0a46fSAndroid Build Coastguard Worker     for (i=0; i < NSTEPS; i++) {
448*3ac0a46fSAndroid Build Coastguard Worker 
449*3ac0a46fSAndroid Build Coastguard Worker         a = alpha + Spiral[i].AdvX;
450*3ac0a46fSAndroid Build Coastguard Worker         t = theta + Spiral[i].AdvY;
451*3ac0a46fSAndroid Build Coastguard Worker 
452*3ac0a46fSAndroid Build Coastguard Worker         // Cycle at the end
453*3ac0a46fSAndroid Build Coastguard Worker         a %= SECTORS;
454*3ac0a46fSAndroid Build Coastguard Worker         t %= SECTORS;
455*3ac0a46fSAndroid Build Coastguard Worker 
456*3ac0a46fSAndroid Build Coastguard Worker         // Cycle at the begin
457*3ac0a46fSAndroid Build Coastguard Worker         if (a < 0) a = SECTORS + a;
458*3ac0a46fSAndroid Build Coastguard Worker         if (t < 0) t = SECTORS + t;
459*3ac0a46fSAndroid Build Coastguard Worker 
460*3ac0a46fSAndroid Build Coastguard Worker         pt = &gbd ->Gamut[t][a];
461*3ac0a46fSAndroid Build Coastguard Worker 
462*3ac0a46fSAndroid Build Coastguard Worker         if (pt -> Type != GP_EMPTY) {
463*3ac0a46fSAndroid Build Coastguard Worker 
464*3ac0a46fSAndroid Build Coastguard Worker             Close[nSectors++] = pt;
465*3ac0a46fSAndroid Build Coastguard Worker         }
466*3ac0a46fSAndroid Build Coastguard Worker     }
467*3ac0a46fSAndroid Build Coastguard Worker 
468*3ac0a46fSAndroid Build Coastguard Worker     return nSectors;
469*3ac0a46fSAndroid Build Coastguard Worker }
470*3ac0a46fSAndroid Build Coastguard Worker 
471*3ac0a46fSAndroid Build Coastguard Worker 
472*3ac0a46fSAndroid Build Coastguard Worker // Interpolate a missing sector. Method identifies whatever this is top, bottom or mid
473*3ac0a46fSAndroid Build Coastguard Worker static
InterpolateMissingSector(cmsGDB * gbd,int alpha,int theta)474*3ac0a46fSAndroid Build Coastguard Worker cmsBool InterpolateMissingSector(cmsGDB* gbd, int alpha, int theta)
475*3ac0a46fSAndroid Build Coastguard Worker {
476*3ac0a46fSAndroid Build Coastguard Worker     cmsSpherical sp;
477*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 Lab;
478*3ac0a46fSAndroid Build Coastguard Worker     cmsVEC3 Centre;
479*3ac0a46fSAndroid Build Coastguard Worker     cmsLine ray;
480*3ac0a46fSAndroid Build Coastguard Worker     int nCloseSectors;
481*3ac0a46fSAndroid Build Coastguard Worker     cmsGDBPoint* Close[NSTEPS + 1];
482*3ac0a46fSAndroid Build Coastguard Worker     cmsSpherical closel, templ;
483*3ac0a46fSAndroid Build Coastguard Worker     cmsLine edge;
484*3ac0a46fSAndroid Build Coastguard Worker     int k, m;
485*3ac0a46fSAndroid Build Coastguard Worker 
486*3ac0a46fSAndroid Build Coastguard Worker     // Is that point already specified?
487*3ac0a46fSAndroid Build Coastguard Worker     if (gbd ->Gamut[theta][alpha].Type != GP_EMPTY) return TRUE;
488*3ac0a46fSAndroid Build Coastguard Worker 
489*3ac0a46fSAndroid Build Coastguard Worker     // Fill close points
490*3ac0a46fSAndroid Build Coastguard Worker     nCloseSectors = FindNearSectors(gbd, alpha, theta, Close);
491*3ac0a46fSAndroid Build Coastguard Worker 
492*3ac0a46fSAndroid Build Coastguard Worker 
493*3ac0a46fSAndroid Build Coastguard Worker     // Find a central point on the sector
494*3ac0a46fSAndroid Build Coastguard Worker     sp.alpha = (cmsFloat64Number) ((alpha + 0.5) * 360.0) / (SECTORS);
495*3ac0a46fSAndroid Build Coastguard Worker     sp.theta = (cmsFloat64Number) ((theta + 0.5) * 180.0) / (SECTORS);
496*3ac0a46fSAndroid Build Coastguard Worker     sp.r     = 50.0;
497*3ac0a46fSAndroid Build Coastguard Worker 
498*3ac0a46fSAndroid Build Coastguard Worker     // Convert to Cartesian
499*3ac0a46fSAndroid Build Coastguard Worker     ToCartesian(&Lab, &sp);
500*3ac0a46fSAndroid Build Coastguard Worker 
501*3ac0a46fSAndroid Build Coastguard Worker     // Create a ray line from centre to this point
502*3ac0a46fSAndroid Build Coastguard Worker     _cmsVEC3init(&Centre, 50.0, 0, 0);
503*3ac0a46fSAndroid Build Coastguard Worker     LineOf2Points(&ray, &Lab, &Centre);
504*3ac0a46fSAndroid Build Coastguard Worker 
505*3ac0a46fSAndroid Build Coastguard Worker     // For all close sectors
506*3ac0a46fSAndroid Build Coastguard Worker     closel.r = 0.0;
507*3ac0a46fSAndroid Build Coastguard Worker     closel.alpha = 0;
508*3ac0a46fSAndroid Build Coastguard Worker     closel.theta = 0;
509*3ac0a46fSAndroid Build Coastguard Worker 
510*3ac0a46fSAndroid Build Coastguard Worker     for (k=0; k < nCloseSectors; k++) {
511*3ac0a46fSAndroid Build Coastguard Worker 
512*3ac0a46fSAndroid Build Coastguard Worker         for(m = k+1; m < nCloseSectors; m++) {
513*3ac0a46fSAndroid Build Coastguard Worker 
514*3ac0a46fSAndroid Build Coastguard Worker             cmsVEC3 temp, a1, a2;
515*3ac0a46fSAndroid Build Coastguard Worker 
516*3ac0a46fSAndroid Build Coastguard Worker             // A line from sector to sector
517*3ac0a46fSAndroid Build Coastguard Worker             ToCartesian(&a1, &Close[k]->p);
518*3ac0a46fSAndroid Build Coastguard Worker             ToCartesian(&a2, &Close[m]->p);
519*3ac0a46fSAndroid Build Coastguard Worker 
520*3ac0a46fSAndroid Build Coastguard Worker             LineOf2Points(&edge, &a1, &a2);
521*3ac0a46fSAndroid Build Coastguard Worker 
522*3ac0a46fSAndroid Build Coastguard Worker             // Find a line
523*3ac0a46fSAndroid Build Coastguard Worker             ClosestLineToLine(&temp, &ray, &edge);
524*3ac0a46fSAndroid Build Coastguard Worker 
525*3ac0a46fSAndroid Build Coastguard Worker             // Convert to spherical
526*3ac0a46fSAndroid Build Coastguard Worker             ToSpherical(&templ, &temp);
527*3ac0a46fSAndroid Build Coastguard Worker 
528*3ac0a46fSAndroid Build Coastguard Worker 
529*3ac0a46fSAndroid Build Coastguard Worker             if ( templ.r > closel.r &&
530*3ac0a46fSAndroid Build Coastguard Worker                  templ.theta >= (theta*180.0/SECTORS) &&
531*3ac0a46fSAndroid Build Coastguard Worker                  templ.theta <= ((theta+1)*180.0/SECTORS) &&
532*3ac0a46fSAndroid Build Coastguard Worker                  templ.alpha >= (alpha*360.0/SECTORS) &&
533*3ac0a46fSAndroid Build Coastguard Worker                  templ.alpha <= ((alpha+1)*360.0/SECTORS)) {
534*3ac0a46fSAndroid Build Coastguard Worker 
535*3ac0a46fSAndroid Build Coastguard Worker                 closel = templ;
536*3ac0a46fSAndroid Build Coastguard Worker             }
537*3ac0a46fSAndroid Build Coastguard Worker         }
538*3ac0a46fSAndroid Build Coastguard Worker     }
539*3ac0a46fSAndroid Build Coastguard Worker 
540*3ac0a46fSAndroid Build Coastguard Worker     gbd ->Gamut[theta][alpha].p = closel;
541*3ac0a46fSAndroid Build Coastguard Worker     gbd ->Gamut[theta][alpha].Type = GP_MODELED;
542*3ac0a46fSAndroid Build Coastguard Worker 
543*3ac0a46fSAndroid Build Coastguard Worker     return TRUE;
544*3ac0a46fSAndroid Build Coastguard Worker 
545*3ac0a46fSAndroid Build Coastguard Worker }
546*3ac0a46fSAndroid Build Coastguard Worker 
547*3ac0a46fSAndroid Build Coastguard Worker 
548*3ac0a46fSAndroid Build Coastguard Worker // Interpolate missing parts. The algorithm fist computes slices at
549*3ac0a46fSAndroid Build Coastguard Worker // theta=0 and theta=Max.
cmsGDBCompute(cmsHANDLE hGBD,cmsUInt32Number dwFlags)550*3ac0a46fSAndroid Build Coastguard Worker cmsBool CMSEXPORT cmsGDBCompute(cmsHANDLE hGBD, cmsUInt32Number dwFlags)
551*3ac0a46fSAndroid Build Coastguard Worker {
552*3ac0a46fSAndroid Build Coastguard Worker     int alpha, theta;
553*3ac0a46fSAndroid Build Coastguard Worker     cmsGDB* gbd = (cmsGDB*) hGBD;
554*3ac0a46fSAndroid Build Coastguard Worker 
555*3ac0a46fSAndroid Build Coastguard Worker     _cmsAssert(hGBD != NULL);
556*3ac0a46fSAndroid Build Coastguard Worker 
557*3ac0a46fSAndroid Build Coastguard Worker     // Interpolate black
558*3ac0a46fSAndroid Build Coastguard Worker     for (alpha = 0; alpha < SECTORS; alpha++) {
559*3ac0a46fSAndroid Build Coastguard Worker 
560*3ac0a46fSAndroid Build Coastguard Worker         if (!InterpolateMissingSector(gbd, alpha, 0)) return FALSE;
561*3ac0a46fSAndroid Build Coastguard Worker     }
562*3ac0a46fSAndroid Build Coastguard Worker 
563*3ac0a46fSAndroid Build Coastguard Worker     // Interpolate white
564*3ac0a46fSAndroid Build Coastguard Worker     for (alpha = 0; alpha < SECTORS; alpha++) {
565*3ac0a46fSAndroid Build Coastguard Worker 
566*3ac0a46fSAndroid Build Coastguard Worker         if (!InterpolateMissingSector(gbd, alpha, SECTORS-1)) return FALSE;
567*3ac0a46fSAndroid Build Coastguard Worker     }
568*3ac0a46fSAndroid Build Coastguard Worker 
569*3ac0a46fSAndroid Build Coastguard Worker 
570*3ac0a46fSAndroid Build Coastguard Worker     // Interpolate Mid
571*3ac0a46fSAndroid Build Coastguard Worker     for (theta = 1; theta < SECTORS; theta++) {
572*3ac0a46fSAndroid Build Coastguard Worker         for (alpha = 0; alpha < SECTORS; alpha++) {
573*3ac0a46fSAndroid Build Coastguard Worker 
574*3ac0a46fSAndroid Build Coastguard Worker             if (!InterpolateMissingSector(gbd, alpha, theta)) return FALSE;
575*3ac0a46fSAndroid Build Coastguard Worker         }
576*3ac0a46fSAndroid Build Coastguard Worker     }
577*3ac0a46fSAndroid Build Coastguard Worker 
578*3ac0a46fSAndroid Build Coastguard Worker     // Done
579*3ac0a46fSAndroid Build Coastguard Worker     return TRUE;
580*3ac0a46fSAndroid Build Coastguard Worker 
581*3ac0a46fSAndroid Build Coastguard Worker     cmsUNUSED_PARAMETER(dwFlags);
582*3ac0a46fSAndroid Build Coastguard Worker }
583*3ac0a46fSAndroid Build Coastguard Worker 
584*3ac0a46fSAndroid Build Coastguard Worker 
585*3ac0a46fSAndroid Build Coastguard Worker 
586*3ac0a46fSAndroid Build Coastguard Worker 
587*3ac0a46fSAndroid Build Coastguard Worker // --------------------------------------------------------------------------------------------------------
588*3ac0a46fSAndroid Build Coastguard Worker 
589*3ac0a46fSAndroid Build Coastguard Worker // Great for debug, but not suitable for real use
590*3ac0a46fSAndroid Build Coastguard Worker 
591*3ac0a46fSAndroid Build Coastguard Worker #if 0
592*3ac0a46fSAndroid Build Coastguard Worker cmsBool cmsGBDdumpVRML(cmsHANDLE hGBD, const char* fname)
593*3ac0a46fSAndroid Build Coastguard Worker {
594*3ac0a46fSAndroid Build Coastguard Worker     FILE* fp;
595*3ac0a46fSAndroid Build Coastguard Worker     int   i, j;
596*3ac0a46fSAndroid Build Coastguard Worker     cmsGDB* gbd = (cmsGDB*) hGBD;
597*3ac0a46fSAndroid Build Coastguard Worker     cmsGDBPoint* pt;
598*3ac0a46fSAndroid Build Coastguard Worker 
599*3ac0a46fSAndroid Build Coastguard Worker     fp = fopen (fname, "wt");
600*3ac0a46fSAndroid Build Coastguard Worker     if (fp == NULL)
601*3ac0a46fSAndroid Build Coastguard Worker         return FALSE;
602*3ac0a46fSAndroid Build Coastguard Worker 
603*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "#VRML V2.0 utf8\n");
604*3ac0a46fSAndroid Build Coastguard Worker 
605*3ac0a46fSAndroid Build Coastguard Worker     // set the viewing orientation and distance
606*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "DEF CamTest Group {\n");
607*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\tchildren [\n");
608*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\tDEF Cameras Group {\n");
609*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\tchildren [\n");
610*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\tDEF DefaultView Viewpoint {\n");
611*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tposition 0 0 340\n");
612*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\torientation 0 0 1 0\n");
613*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tdescription \"default view\"\n");
614*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t}\n");
615*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t]\n");
616*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t},\n");
617*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t]\n");
618*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "}\n");
619*3ac0a46fSAndroid Build Coastguard Worker 
620*3ac0a46fSAndroid Build Coastguard Worker     // Output the background stuff
621*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "Background {\n");
622*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\tskyColor [\n");
623*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t.5 .5 .5\n");
624*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t]\n");
625*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "}\n");
626*3ac0a46fSAndroid Build Coastguard Worker 
627*3ac0a46fSAndroid Build Coastguard Worker     // Output the shape stuff
628*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "Transform {\n");
629*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\tscale .3 .3 .3\n");
630*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\tchildren [\n");
631*3ac0a46fSAndroid Build Coastguard Worker 
632*3ac0a46fSAndroid Build Coastguard Worker     // Draw the axes as a shape:
633*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\tShape {\n");
634*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\tappearance Appearance {\n");
635*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\tmaterial Material {\n");
636*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tdiffuseColor 0 0.8 0\n");
637*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\temissiveColor 1.0 1.0 1.0\n");
638*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tshininess 0.8\n");
639*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t}\n");
640*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t}\n");
641*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\tgeometry IndexedLineSet {\n");
642*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\tcoord Coordinate {\n");
643*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tpoint [\n");
644*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\t0.0 0.0 0.0,\n");
645*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\t%f 0.0 0.0,\n",  255.0);
646*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\t0.0 %f 0.0,\n",  255.0);
647*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\t0.0 0.0 %f]\n",  255.0);
648*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t}\n");
649*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\tcoordIndex [\n");
650*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\t0, 1, -1\n");
651*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\t0, 2, -1\n");
652*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\t0, 3, -1]\n");
653*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t}\n");
654*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t}\n");
655*3ac0a46fSAndroid Build Coastguard Worker 
656*3ac0a46fSAndroid Build Coastguard Worker 
657*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\tShape {\n");
658*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\tappearance Appearance {\n");
659*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\tmaterial Material {\n");
660*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tdiffuseColor 0 0.8 0\n");
661*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\temissiveColor 1 1 1\n");
662*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tshininess 0.8\n");
663*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t}\n");
664*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t}\n");
665*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\tgeometry PointSet {\n");
666*3ac0a46fSAndroid Build Coastguard Worker 
667*3ac0a46fSAndroid Build Coastguard Worker     // fill in the points here
668*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\tcoord Coordinate {\n");
669*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tpoint [\n");
670*3ac0a46fSAndroid Build Coastguard Worker 
671*3ac0a46fSAndroid Build Coastguard Worker     // We need to transverse all gamut hull.
672*3ac0a46fSAndroid Build Coastguard Worker     for (i=0; i < SECTORS; i++)
673*3ac0a46fSAndroid Build Coastguard Worker         for (j=0; j < SECTORS; j++) {
674*3ac0a46fSAndroid Build Coastguard Worker 
675*3ac0a46fSAndroid Build Coastguard Worker             cmsVEC3 v;
676*3ac0a46fSAndroid Build Coastguard Worker 
677*3ac0a46fSAndroid Build Coastguard Worker             pt = &gbd ->Gamut[i][j];
678*3ac0a46fSAndroid Build Coastguard Worker             ToCartesian(&v, &pt ->p);
679*3ac0a46fSAndroid Build Coastguard Worker 
680*3ac0a46fSAndroid Build Coastguard Worker             fprintf (fp, "\t\t\t\t\t%g %g %g", v.n[0]+50, v.n[1], v.n[2]);
681*3ac0a46fSAndroid Build Coastguard Worker 
682*3ac0a46fSAndroid Build Coastguard Worker             if ((j == SECTORS - 1) && (i == SECTORS - 1))
683*3ac0a46fSAndroid Build Coastguard Worker                 fprintf (fp, "]\n");
684*3ac0a46fSAndroid Build Coastguard Worker             else
685*3ac0a46fSAndroid Build Coastguard Worker                 fprintf (fp, ",\n");
686*3ac0a46fSAndroid Build Coastguard Worker 
687*3ac0a46fSAndroid Build Coastguard Worker         }
688*3ac0a46fSAndroid Build Coastguard Worker 
689*3ac0a46fSAndroid Build Coastguard Worker         fprintf (fp, "\t\t\t\t}\n");
690*3ac0a46fSAndroid Build Coastguard Worker 
691*3ac0a46fSAndroid Build Coastguard Worker 
692*3ac0a46fSAndroid Build Coastguard Worker 
693*3ac0a46fSAndroid Build Coastguard Worker     // fill in the face colors
694*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\tcolor Color {\n");
695*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t\t\tcolor [\n");
696*3ac0a46fSAndroid Build Coastguard Worker 
697*3ac0a46fSAndroid Build Coastguard Worker     for (i=0; i < SECTORS; i++)
698*3ac0a46fSAndroid Build Coastguard Worker         for (j=0; j < SECTORS; j++) {
699*3ac0a46fSAndroid Build Coastguard Worker 
700*3ac0a46fSAndroid Build Coastguard Worker            cmsVEC3 v;
701*3ac0a46fSAndroid Build Coastguard Worker 
702*3ac0a46fSAndroid Build Coastguard Worker             pt = &gbd ->Gamut[i][j];
703*3ac0a46fSAndroid Build Coastguard Worker 
704*3ac0a46fSAndroid Build Coastguard Worker 
705*3ac0a46fSAndroid Build Coastguard Worker             ToCartesian(&v, &pt ->p);
706*3ac0a46fSAndroid Build Coastguard Worker 
707*3ac0a46fSAndroid Build Coastguard Worker 
708*3ac0a46fSAndroid Build Coastguard Worker         if (pt ->Type == GP_EMPTY)
709*3ac0a46fSAndroid Build Coastguard Worker             fprintf (fp, "\t\t\t\t\t%g %g %g", 0.0, 0.0, 0.0);
710*3ac0a46fSAndroid Build Coastguard Worker         else
711*3ac0a46fSAndroid Build Coastguard Worker             if (pt ->Type == GP_MODELED)
712*3ac0a46fSAndroid Build Coastguard Worker                 fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, .5, .5);
713*3ac0a46fSAndroid Build Coastguard Worker             else {
714*3ac0a46fSAndroid Build Coastguard Worker                 fprintf (fp, "\t\t\t\t\t%g %g %g", 1.0, 1.0, 1.0);
715*3ac0a46fSAndroid Build Coastguard Worker 
716*3ac0a46fSAndroid Build Coastguard Worker             }
717*3ac0a46fSAndroid Build Coastguard Worker 
718*3ac0a46fSAndroid Build Coastguard Worker         if ((j == SECTORS - 1) && (i == SECTORS - 1))
719*3ac0a46fSAndroid Build Coastguard Worker                 fprintf (fp, "]\n");
720*3ac0a46fSAndroid Build Coastguard Worker             else
721*3ac0a46fSAndroid Build Coastguard Worker                 fprintf (fp, ",\n");
722*3ac0a46fSAndroid Build Coastguard Worker     }
723*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t}\n");
724*3ac0a46fSAndroid Build Coastguard Worker 
725*3ac0a46fSAndroid Build Coastguard Worker 
726*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t\t}\n");
727*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t\t}\n");
728*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "\t]\n");
729*3ac0a46fSAndroid Build Coastguard Worker     fprintf (fp, "}\n");
730*3ac0a46fSAndroid Build Coastguard Worker 
731*3ac0a46fSAndroid Build Coastguard Worker     fclose (fp);
732*3ac0a46fSAndroid Build Coastguard Worker 
733*3ac0a46fSAndroid Build Coastguard Worker     return TRUE;
734*3ac0a46fSAndroid Build Coastguard Worker }
735*3ac0a46fSAndroid Build Coastguard Worker #endif
736*3ac0a46fSAndroid Build Coastguard Worker 
737