1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//---------------------------------------------------------------------------------
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//  Little Color Management System
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//  Copyright (c) 1998-2014 Marti Maria Saguer
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Permission is hereby granted, free of charge, to any person obtaining
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a copy of this software and associated documentation files (the "Software"),
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// to deal in the Software without restriction, including without limitation
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the rights to use, copy, modify, merge, publish, distribute, sublicense,
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// and/or sell copies of the Software, and to permit persons to whom the Software
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is furnished to do so, subject to the following conditions:
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The above copyright notice and this permission notice shall be included in
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// all copies or substantial portions of the Software.
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//---------------------------------------------------------------------------------
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "lcms2_internal.h"
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Tag Serialization  -----------------------------------------------------------------------------
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This file implements every single tag and tag type as described in the ICC spec. Some types
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// have been deprecated, like ncl and Data. There is no implementation for those types as there
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// are no profiles holding them. The programmer can also extend this list by defining his own types
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// by using the appropiate plug-in. There are three types of plug ins regarding that. First type
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// allows to define new tags using any existing type. Next plug-in type allows to define new types
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// and the third one is very specific: allows to extend the number of elements in the multiprocessing
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// elements special type.
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//--------------------------------------------------------------------------------------------------
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Some broken types
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define cmsCorbisBrokenXYZtype    ((cmsTagTypeSignature) 0x17A505B8)
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define cmsMonacoBrokenCurveType  ((cmsTagTypeSignature) 0x9478ee00)
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is the linked list that keeps track of the defined types
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct _cmsTagTypeLinkedList_st {
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsTagTypeHandler Handler;
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    struct _cmsTagTypeLinkedList_st* Next;
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} _cmsTagTypeLinkedList;
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Some macros to define callbacks.
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define READ_FN(x)  Type_##x##_Read
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define WRITE_FN(x) Type_##x##_Write
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FREE_FN(x)  Type_##x##_Free
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define DUP_FN(x)   Type_##x##_Dup
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Helper macro to define a handler. Callbacks do have a fixed naming convention.
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TYPE_HANDLER(t, x)  { (t), READ_FN(x), WRITE_FN(x), DUP_FN(x), FREE_FN(x), NULL, 0 }
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Helper macro to define a MPE handler. Callbacks do have a fixed naming convention
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define TYPE_MPE_HANDLER(t, x)  { (t), READ_FN(x), WRITE_FN(x), GenericMPEdup, GenericMPEfree, NULL, 0 }
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Register a new type handler. This routine is shared between normal types and MPE. LinkedList points to the optional list head
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool RegisterTypesPlugin(cmsContext id, cmsPluginBase* Data, _cmsMemoryClient pos)
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPluginTagType* Plugin = (cmsPluginTagType*) Data;
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(id, pos);
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagTypeLinkedList *pt;
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Calling the function with NULL as plug-in would unregister the plug in.
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Data == NULL) {
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // There is no need to set free the memory, as pool is destroyed as a whole.
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ctx ->TagTypes = NULL;
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Registering happens in plug-in memory pool.
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pt == NULL) return FALSE;
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pt ->Handler   = Plugin ->Handler;
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pt ->Next      = ctx ->TagTypes;
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ctx ->TagTypes = pt;
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additons
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// made by plug-ins and then the built-in defaults.
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList)
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagTypeLinkedList* pt;
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (pt = PluginLinkedList;
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         pt != NULL;
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         pt = pt ->Next) {
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (sig == pt -> Handler.Signature) return &pt ->Handler;
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (pt = DefaultLinkedList;
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         pt != NULL;
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         pt = pt ->Next) {
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (sig == pt -> Handler.Signature) return &pt ->Handler;
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Auxiliar to convert UTF-32 to UTF-16 in some cases
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* Array)
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(io != NULL);
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(!(Array == NULL && n > 0));
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < n; i++) {
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Array[i])) return FALSE;
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Auxiliar to read an array of wchar_t
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array)
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number tmp;
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(io != NULL);
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < n; i++) {
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Array != NULL) {
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsReadUInt16Number(io, &tmp)) return FALSE;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Array[i] = (wchar_t) tmp;
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsReadUInt16Number(io, NULL)) return FALSE;
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// To deal with position tables
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self,
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsIOHANDLER* io,
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             void* Cargo,
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsUInt32Number n,
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsUInt32Number SizeOfTag);
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Helper function to deal with position tables as decribed in ICC spec 4.3
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// A table of n elements is readed, where first comes n records containing offsets and sizes and
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// then a block containing the data itself. This allows to reuse same data in more than one entry
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              cmsIOHANDLER* io,
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              cmsUInt32Number Count,
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              cmsUInt32Number BaseOffset,
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              void *Cargo,
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                              PositionTableEntryFn ElementFn)
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Let's take the offsets to each element
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets == NULL) goto Error;
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes == NULL) goto Error;
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, &ElementOffsets[i])) goto Error;
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, &ElementSizes[i])) goto Error;
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ElementOffsets[i] += BaseOffset;
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Seek to each element and read it
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!io -> Seek(io, ElementOffsets[i])) goto Error;
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // This is the reader callback
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!ElementFn(self, io, Cargo, i, ElementSizes[i])) goto Error;
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Success
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Same as anterior, but for write position tables
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WritePositionTable(struct _cms_typehandler_struct* self,
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               cmsIOHANDLER* io,
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               cmsUInt32Number SizeOfTag,
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               cmsUInt32Number Count,
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               cmsUInt32Number BaseOffset,
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               void *Cargo,
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               PositionTableEntryFn ElementFn)
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number DirectoryPos, CurrentPos, Before;
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     // Create table
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets == NULL) goto Error;
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes == NULL) goto Error;
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Keep starting position of curve offsets
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    DirectoryPos = io ->Tell(io);
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write a fake directory to be filled latter on
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // Offset
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // size
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write each element. Keep track of the size as well.
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Before = io ->Tell(io);
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ElementOffsets[i] = Before - BaseOffset;
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Callback to write...
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!ElementFn(self, io, Cargo, i, SizeOfTag)) goto Error;
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Now the size
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ElementSizes[i] = io ->Tell(io) - Before;
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the directory
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CurrentPos = io ->Tell(io);
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, DirectoryPos)) goto Error;
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i <  Count; i++) {
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error;
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error;
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, CurrentPos)) goto Error;
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets != NULL) _cmsFree(io ->ContextID, ElementOffsets);
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes != NULL) _cmsFree(io ->ContextID, ElementSizes);
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type XYZ. Only one value is allowed
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//The XYZType contains an array of three encoded values for the XYZ tristimulus
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//values. Tristimulus values must be non-negative. The signed encoding allows for
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//implementation optimizations by minimizing the number of fixed formats.
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_XYZ_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsCIEXYZ* xyz;
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    xyz = (cmsCIEXYZ*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIEXYZ));
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (xyz == NULL) return NULL;
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadXYZNumber(io, xyz)) {
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, xyz);
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) xyz;
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_XYZ_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsWriteXYZNumber(io, (cmsCIEXYZ*) Ptr);
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_XYZ_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIEXYZ));
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_XYZ_Free(struct _cms_typehandler_struct* self, void *Ptr)
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeSignature DecideXYZtype(cmsFloat64Number ICCVersion, const void *Data)
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsSigXYZType;
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(ICCVersion);
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(Data);
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type chromaticity. Only one value is allowed
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The chromaticity tag type provides basic chromaticity data and type of
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// phosphors or colorants of a monitor to applications and utilities.
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Chromaticity_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsCIExyYTRIPLE* chrm;
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number nChans, Table;
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    chrm =  (cmsCIExyYTRIPLE*) _cmsMallocZero(self ->ContextID, sizeof(cmsCIExyYTRIPLE));
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (chrm == NULL) return NULL;
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &nChans)) goto Error;
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Let's recover from a bug introduced in early versions of lcms1
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nChans == 0 && SizeOfTag == 32) {
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Number(io, NULL)) goto Error;
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Number(io, &nChans)) goto Error;
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nChans != 3) goto Error;
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &Table)) goto Error;
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &chrm ->Red.x)) goto Error;
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &chrm ->Red.y)) goto Error;
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    chrm ->Red.Y = 1.0;
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &chrm ->Green.x)) goto Error;
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &chrm ->Green.y)) goto Error;
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    chrm ->Green.Y = 1.0;
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.x)) goto Error;
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &chrm ->Blue.y)) goto Error;
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    chrm ->Blue.Y = 1.0;
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) chrm;
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, (void*) chrm);
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  SaveOneChromaticity(cmsFloat64Number x, cmsFloat64Number y, cmsIOHANDLER* io)
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(x))) return FALSE;
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, _cmsDoubleTo15Fixed16(y))) return FALSE;
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_Chromaticity_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsCIExyYTRIPLE* chrm = (cmsCIExyYTRIPLE*) Ptr;
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, 3)) return FALSE;        // nChannels
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;        // Table
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!SaveOneChromaticity(chrm -> Red.x,   chrm -> Red.y, io)) return FALSE;
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!SaveOneChromaticity(chrm -> Green.x, chrm -> Green.y, io)) return FALSE;
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!SaveOneChromaticity(chrm -> Blue.x,  chrm -> Blue.y, io)) return FALSE;
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Chromaticity_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsCIExyYTRIPLE));
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Chromaticity_Free(struct _cms_typehandler_struct* self, void* Ptr)
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigColorantOrderType
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is an optional tag which specifies the laydown order in which colorants will
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// be printed on an n-colorant device. The laydown order may be the same as the
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// channel generation order listed in the colorantTableTag or the channel order of a
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// colour space such as CMYK, in which case this tag is not needed. When this is not
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the case (for example, ink-towers sometimes use the order KCMY), this tag may be
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// used to specify the laydown order of the colorants.
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_ColorantOrderType_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* ColorantOrder;
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Count;
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Count > cmsMAXCHANNELS) return NULL;
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ColorantOrder = (cmsUInt8Number*) _cmsCalloc(self ->ContextID, cmsMAXCHANNELS, sizeof(cmsUInt8Number));
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ColorantOrder == NULL) return NULL;
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // We use FF as end marker
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(ColorantOrder, 0xFF, cmsMAXCHANNELS * sizeof(cmsUInt8Number));
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io ->Read(io, ColorantOrder, sizeof(cmsUInt8Number), Count) != Count) {
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, (void*) ColorantOrder);
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) ColorantOrder;
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_ColorantOrderType_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number*  ColorantOrder = (cmsUInt8Number*) Ptr;
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, sz, Count;
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get the length
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (Count=i=0; i < cmsMAXCHANNELS; i++) {
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (ColorantOrder[i] != 0xFF) Count++;
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, Count)) return FALSE;
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    sz = Count * sizeof(cmsUInt8Number);
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io -> Write(io, sz, ColorantOrder)) return FALSE;
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_ColorantOrderType_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, Ptr, cmsMAXCHANNELS * sizeof(cmsUInt8Number));
503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_ColorantOrderType_Free(struct _cms_typehandler_struct* self, void* Ptr)
510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigS15Fixed16ArrayType
516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This type represents an array of generic 4-byte/32-bit fixed point quantity.
518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The number of values is determined from the size of the tag.
519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_S15Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number*  array_double;
524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, n;
525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    n = SizeOfTag / sizeof(cmsUInt32Number);
528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number));
529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (array_double == NULL) return NULL;
530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < n; i++) {
532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsRead15Fixed16Number(io, &array_double[i])) {
534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            _cmsFree(self ->ContextID, array_double);
536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return NULL;
537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = n;
541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) array_double;
542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
545ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_S15Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number* Value = (cmsFloat64Number*) Ptr;
548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nItems; i++) {
551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, Value[i])) return FALSE;
553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_S15Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number));
564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_S15Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr)
569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigU16Fixed16ArrayType
575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This type represents an array of generic 4-byte/32-bit quantity.
577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The number of values is determined from the size of the tag.
578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_U16Fixed16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number*  array_double;
584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number v;
585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, n;
586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    n = SizeOfTag / sizeof(cmsUInt32Number);
589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    array_double = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, n, sizeof(cmsFloat64Number));
590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (array_double == NULL) return NULL;
591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < n; i++) {
593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, &v)) {
595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            _cmsFree(self ->ContextID, (void*) array_double);
596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return NULL;
597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Convert to cmsFloat64Number
600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        array_double[i] =  (cmsFloat64Number) (v / 65536.0);
601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = n;
604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) array_double;
605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
608ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_U16Fixed16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number* Value = (cmsFloat64Number*) Ptr;
611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nItems; i++) {
614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsUInt32Number v = (cmsUInt32Number) floor(Value[i]*65536.0 + 0.5);
616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, v)) return FALSE;
618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_U16Fixed16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsFloat64Number));
630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_U16Fixed16_Free(struct _cms_typehandler_struct* self, void* Ptr)
634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigSignatureType
640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The signatureType contains a four-byte sequence, Sequences of less than four
643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// characters are padded at the end with spaces, 20h.
644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Typically this type is used for registered tags that can be displayed on many
645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// development systems as a sequence of four characters.
646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Signature_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSignature* SigPtr = (cmsSignature*) _cmsMalloc(self ->ContextID, sizeof(cmsSignature));
651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SigPtr == NULL) return NULL;
652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (!_cmsReadUInt32Number(io, SigPtr)) return NULL;
654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *nItems = 1;
655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     return SigPtr;
657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     cmsUNUSED_PARAMETER(SizeOfTag);
659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
662ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_Signature_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSignature* SigPtr = (cmsSignature*) Ptr;
665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsWriteUInt32Number(io, *SigPtr);
667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Signature_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, Ptr, n * sizeof(cmsSignature));
676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Signature_Free(struct _cms_typehandler_struct* self, void* Ptr)
680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigTextType
687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The textType is a simple text structure that contains a 7-bit ASCII text string.
690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The length of the string is obtained by subtracting 8 from the element size portion
691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// of the tag itself. This string must be terminated with a 00h byte.
692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Text_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char* Text = NULL;
697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu = NULL;
698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Create a container
700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mlu = cmsMLUalloc(self ->ContextID, 1);
701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mlu == NULL) return NULL;
702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // We need to store the "\0" at the end, so +1
706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag == UINT_MAX) goto Error;
707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Text == NULL) goto Error;
710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io -> Read(io, Text, sizeof(char), SizeOfTag) != SizeOfTag) goto Error;
712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Make sure text is properly ended
714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text[SizeOfTag] = 0;
715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Keep the result
718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error;
719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Text);
721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) mlu;
722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
723ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mlu != NULL)
725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsMLUfree(mlu);
726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Text != NULL)
727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, Text);
728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The conversion implies to choose a language. So, we choose the actual language.
733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
734ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_Text_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu = (cmsMLU*) Ptr;
737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number size;
738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsBool  rc;
739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char* Text;
740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get the size of the string. Note there is an extra "\0" at the end
742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    size = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (size == 0) return FALSE;       // Cannot be zero!
744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Create memory
746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text = (char*) _cmsMalloc(self ->ContextID, size);
747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Text == NULL) return FALSE;
748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text, size);
750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write it, including separator
752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rc = io ->Write(io, size, Text);
753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Text);
755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return rc;
756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Text_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsMLUdup((cmsMLU*) Ptr);
764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Text_Free(struct _cms_typehandler_struct* self, void* Ptr)
772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu = (cmsMLU*) Ptr;
774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLUfree(mlu);
775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
781ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeSignature DecideTextType(cmsFloat64Number ICCVersion, const void *Data)
782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ICCVersion >= 4.0)
784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return cmsSigMultiLocalizedUnicodeType;
785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsSigTextType;
787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(Data);
789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigDataType
794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// General purpose data type
797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Data_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsICCData* BinData;
801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number LenOfData;
802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    LenOfData = SizeOfTag - sizeof(cmsUInt32Number);
808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (LenOfData > INT_MAX) return NULL;
809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BinData = (cmsICCData*) _cmsMalloc(self ->ContextID, sizeof(cmsICCData) + LenOfData - 1);
811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (BinData == NULL) return NULL;
812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BinData ->len = LenOfData;
814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &BinData->flag)) {
815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, BinData);
816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io -> Read(io, BinData ->data, sizeof(cmsUInt8Number), LenOfData) != LenOfData) {
820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, BinData);
822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) BinData;
828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
832ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_Data_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsICCData* BinData = (cmsICCData*) Ptr;
835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   if (!_cmsWriteUInt32Number(io, BinData ->flag)) return FALSE;
837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   return io ->Write(io, BinData ->len, BinData ->data);
839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsUNUSED_PARAMETER(nItems);
841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsUNUSED_PARAMETER(self);
842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Data_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsICCData* BinData = (cmsICCData*) Ptr;
849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCData) + BinData ->len - 1);
851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Data_Free(struct _cms_typehandler_struct* self, void* Ptr)
857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigTextDescriptionType
863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char* Text = NULL;
869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu = NULL;
870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number  AsciiCount;
871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number  i, UnicodeCode, UnicodeCount;
872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number  ScriptCodeCode, Dummy;
873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number   ScriptCodeCount;
874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    //  One dword should be there
878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read len of ASCII
881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL;
882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= sizeof(cmsUInt32Number);
883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check for size
885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < AsciiCount) return NULL;
886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // All seems Ok, allocate the container
888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mlu = cmsMLUalloc(self ->ContextID, 1);
889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mlu == NULL) return NULL;
890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // As many memory as size of tag
892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text = (char*) _cmsMalloc(self ->ContextID, AsciiCount + 1);
893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Text == NULL) goto Error;
894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read it
896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io ->Read(io, Text, sizeof(char), AsciiCount) != AsciiCount) goto Error;
897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= AsciiCount;
898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Make sure there is a terminator
900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text[AsciiCount] = 0;
901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Set the MLU entry. From here we can be tolerant to wrong types
903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error;
904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, (void*) Text);
905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text = NULL;
906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Skip Unicode code
908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < 2* sizeof(cmsUInt32Number)) goto Done;
909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &UnicodeCode)) goto Done;
910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= 2* sizeof(cmsUInt32Number);
912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < UnicodeCount; i++) {
916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!io ->Read(io, &Dummy, sizeof(cmsUInt16Number), 1)) goto Done;
917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= UnicodeCount*sizeof(cmsUInt16Number);
919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Skip ScriptCode code if present. Some buggy profiles does have less
921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // data that stricttly required. We need to skip it as this type may come
922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // embedded in other types.
923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag >= sizeof(cmsUInt16Number) + sizeof(cmsUInt8Number) + 67) {
925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Number(io, &ScriptCodeCode)) goto Done;
927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt8Number(io,  &ScriptCodeCount)) goto Done;
928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Skip rest of tag
930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i=0; i < 67; i++) {
931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!io ->Read(io, &Dummy, sizeof(cmsUInt8Number), 1)) goto Error;
932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
935ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovDone:
936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return mlu;
939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
940ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Text) _cmsFree(self ->ContextID, (void*) Text);
942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mlu) cmsMLUfree(mlu);
943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
949ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu = (cmsMLU*) Ptr;
952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char *Text = NULL;
953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    wchar_t *Wide = NULL;
954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number len, len_aligned, len_filler_alignment;
955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsBool  rc = FALSE;
956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char Filler[68];
957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Used below for writting zeroes
959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(Filler, 0, sizeof(Filler));
960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get the len of string
962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // From ICC3.4: It has been found that textDescriptionType can contain misaligned data
965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    //(see clause 4.1 for the definition of �aligned?. Because the Unicode language
966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // code and Unicode count immediately follow the ASCII description, their
967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // alignment is not correct if the ASCII count is not a multiple of four. The
968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and
969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // writing software must be written carefully in order to handle these alignment
970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // problems.
971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Compute an aligned size
973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    len_aligned = _cmsALIGNLONG(len);
974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    len_filler_alignment = len_aligned - len;
975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Null strings
977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (len <= 0) {
978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Create independent buffers
984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));
985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Text == NULL) goto Error;
986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t));
988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Wide == NULL) goto Error;
989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Get both representations.
991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry,  Text, len * sizeof(char));
992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsMLUgetWide(mlu,  cmsNoLanguage, cmsNoCountry,  Wide, len * sizeof(wchar_t));
993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  // * cmsUInt32Number       count;          * Description length
996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  // * cmsInt8Number         desc[count]     * NULL terminated ascii string
997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  // * cmsUInt32Number       ucLangCode;     * UniCode language code
998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  // * cmsUInt32Number       ucCount;        * UniCode description length
999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  // * cmsInt16Number        ucDesc[ucCount];* The UniCode description
1000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  // * cmsUInt16Number       scCode;         * ScriptCode code
1001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  // * cmsUInt8Number        scCount;        * ScriptCode count
1002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  // * cmsInt8Number         scDesc[67];     * ScriptCode Description
1003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, len_aligned)) goto Error;
1005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, len, Text)) goto Error;
1006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, len_filler_alignment, Filler)) goto Error;
1007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // ucLanguageCode
1009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // This part is tricky: we need an aligned tag size, and the ScriptCode part
1011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // takes 70 bytes, so we need 2 extra bytes to do the alignment
1012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error;
1014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
1016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteWCharArray(io, len, Wide)) goto Error;
1017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error;
1018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // ScriptCode Code & count (unused)
1020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, 0)) goto Error;
1021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, 0)) goto Error;
1022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, 67, Filler)) goto Error;
1024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rc = TRUE;
1026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1027ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
1028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Text) _cmsFree(self ->ContextID, Text);
1029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Wide) _cmsFree(self ->ContextID, Wide);
1030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return rc;
1032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
1034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsMLUdup((cmsMLU*) Ptr);
1041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
1043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Text_Description_Free(struct _cms_typehandler_struct* self, void* Ptr)
1048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu = (cmsMLU*) Ptr;
1050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLUfree(mlu);
1052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
1053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1059ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeSignature DecideTextDescType(cmsFloat64Number ICCVersion, const void *Data)
1060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ICCVersion >= 4.0)
1062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return cmsSigMultiLocalizedUnicodeType;
1063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsSigTextDescriptionType;
1065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(Data);
1067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigCurveType
1072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Curve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Count;
1078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* NewGamma;
1079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
1081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
1082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch (Count) {
1084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 0:   // Linear.
1086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               {
1087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   cmsFloat64Number SingleGamma = 1.0;
1088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   NewGamma = cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
1090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   if (!NewGamma) return NULL;
1091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   *nItems = 1;
1092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   return NewGamma;
1093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               }
1094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 1:  // Specified as the exponent of gamma function
1096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               {
1097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   cmsUInt16Number SingleGammaFixed;
1098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   cmsFloat64Number SingleGamma;
1099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   if (!_cmsReadUInt16Number(io, &SingleGammaFixed)) return NULL;
1101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   SingleGamma = _cms8Fixed8toDouble(SingleGammaFixed);
1102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   *nItems = 1;
1104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   return cmsBuildParametricToneCurve(self ->ContextID, 1, &SingleGamma);
1105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               }
1106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           default:  // Curve
1108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (Count > 0x7FFF)
1110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   return NULL; // This is to prevent bad guys for doing bad things
1111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               NewGamma = cmsBuildTabulatedToneCurve16(self ->ContextID, Count, NULL);
1113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (!NewGamma) return NULL;
1114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (!_cmsReadUInt16Array(io, Count, NewGamma -> Table16)) return NULL;
1116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               *nItems = 1;
1118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               return NewGamma;
1119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
1122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1126ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_Curve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* Curve = (cmsToneCurve*) Ptr;
1129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Curve ->nSegments == 1 && Curve ->Segments[0].Type == 1) {
1131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // Single gamma, preserve number
1133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cmsUInt16Number SingleGammaFixed = _cmsDoubleTo8Fixed8(Curve ->Segments[0].Params[0]);
1134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt32Number(io, 1)) return FALSE;
1136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, SingleGammaFixed)) return FALSE;
1137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return TRUE;
1138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, Curve ->nEntries)) return FALSE;
1142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsWriteUInt16Array(io, Curve ->nEntries, Curve ->Table16);
1143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
1145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Curve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr);
1153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
1155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Curve_Free(struct _cms_typehandler_struct* self, void* Ptr)
1160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* gamma = (cmsToneCurve*) Ptr;
1162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeToneCurve(gamma);
1164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
1165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigParametricCurveType
1172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Decide which curve type to use on writting
1176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1177ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeSignature DecideCurveType(cmsFloat64Number ICCVersion, const void *Data)
1178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* Curve = (cmsToneCurve*) Data;
1180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ICCVersion < 4.0) return cmsSigCurveType;
1182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Curve ->nSegments != 1) return cmsSigCurveType;          // Only 1-segment curves can be saved as parametric
1183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Curve ->Segments[0].Type < 0) return cmsSigCurveType;    // Only non-inverted curves
1184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Curve ->Segments[0].Type > 5) return cmsSigCurveType;    // Only ICC parametric curves
1185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return cmsSigParametricCurveType;
1187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_ParametricCurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    static const int ParamsByType[] = { 1, 3, 4, 5, 7 };
1193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number Params[10];
1194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number Type;
1195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i, n;
1196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* NewGamma;
1197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &Type)) return NULL;
1199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, NULL)) return NULL;   // Reserved
1200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Type > 4) {
1202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown parametric curve type '%d'", Type);
1204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(Params, 0, sizeof(Params));
1208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    n = ParamsByType[Type];
1209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < n; i++) {
1211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsRead15Fixed16Number(io, &Params[i])) return NULL;
1213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewGamma = cmsBuildParametricToneCurve(self ->ContextID, Type+1, Params);
1216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
1218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NewGamma;
1219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
1221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1225ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_ParametricCurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* Curve = (cmsToneCurve*) Ptr;
1228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i, nParams, typen;
1229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    static const int ParamsByType[] = { 0, 1, 3, 4, 5, 7 };
1230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    typen = Curve -> Segments[0].Type;
1232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Curve ->nSegments > 1 || typen < 1) {
1234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Multisegment or Inverted parametric curves cannot be written");
1236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (typen > 5) {
1240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported parametric curve");
1241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nParams = ParamsByType[typen];
1245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) (Curve ->Segments[0].Type - 1))) return FALSE;
1247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;        // Reserved
1248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nParams; i++) {
1250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, Curve -> Segments[0].Params[i])) return FALSE;
1252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
1257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_ParametricCurve_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsDupToneCurve((cmsToneCurve*) Ptr);
1263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
1265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_ParametricCurve_Free(struct _cms_typehandler_struct* self, void* Ptr)
1270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* gamma = (cmsToneCurve*) Ptr;
1272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeToneCurve(gamma);
1274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
1275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigDateTimeType
1282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// A 12-byte value representation of the time and date, where the byte usage is assigned
1285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// as specified in table 1. The actual values are encoded as 16-bit unsigned integers
1286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// (uInt16Number - see 5.1.6).
1287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
1288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// All the dateTimeNumber values in a profile shall be in Coordinated Universal Time
1289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// (UTC, also known as GMT or ZULU Time). Profile writers are required to convert local
1290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// time to UTC when setting these values. Programmes that display these values may show
1291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the dateTimeNumber as UTC, show the equivalent local time (at current locale), or
1292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// display both UTC and local versions of the dateTimeNumber.
1293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_DateTime_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsDateTimeNumber timestamp;
1298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    struct tm * NewDateTime;
1299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
1301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewDateTime = (struct tm*) _cmsMalloc(self ->ContextID, sizeof(struct tm));
1302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewDateTime == NULL) return NULL;
1303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io->Read(io, &timestamp, sizeof(cmsDateTimeNumber), 1) != 1) return NULL;
1305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     _cmsDecodeDateTimeNumber(&timestamp, NewDateTime);
1307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     *nItems = 1;
1309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     return NewDateTime;
1310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     cmsUNUSED_PARAMETER(SizeOfTag);
1312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1316ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_DateTime_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    struct tm * DateTime = (struct tm*) Ptr;
1319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsDateTimeNumber timestamp;
1320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsEncodeDateTimeNumber(&timestamp, DateTime);
1322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, sizeof(cmsDateTimeNumber), &timestamp)) return FALSE;
1323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
1327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_DateTime_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, Ptr, sizeof(struct tm));
1334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
1336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_DateTime_Free(struct _cms_typehandler_struct* self, void* Ptr)
1340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
1342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type icMeasurementType
1348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
1351ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovThe measurementType information refers only to the internal profile data and is
1352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovmeant to provide profile makers an alternative to the default measurement
1353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovspecifications.
1354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
1355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Measurement_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsICCMeasurementConditions mc;
1360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(&mc, 0, sizeof(mc));
1363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &mc.Observer)) return NULL;
1365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadXYZNumber(io,    &mc.Backing)) return NULL;
1366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &mc.Geometry)) return NULL;
1367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &mc.Flare)) return NULL;
1368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &mc.IlluminantType)) return NULL;
1369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
1371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return _cmsDupMem(self ->ContextID, &mc, sizeof(cmsICCMeasurementConditions));
1372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
1374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1378ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_Measurement_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsICCMeasurementConditions* mc =(cmsICCMeasurementConditions*) Ptr;
1381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, mc->Observer)) return FALSE;
1383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteXYZNumber(io,    &mc->Backing)) return FALSE;
1384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, mc->Geometry)) return FALSE;
1385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, mc->Flare)) return FALSE;
1386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, mc->IlluminantType)) return FALSE;
1387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
1391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Measurement_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCMeasurementConditions));
1398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     cmsUNUSED_PARAMETER(n);
1400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Measurement_Free(struct _cms_typehandler_struct* self, void* Ptr)
1404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsFree(self ->ContextID, Ptr);
1406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigMultiLocalizedUnicodeType
1411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
1413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//   Do NOT trust SizeOfTag as there is an issue on the definition of profileSequenceDescTag. See the TechNote from
1414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//   Max Derhak and Rohit Patil about this: basically the size of the string table should be guessed and cannot be
1415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//   taken from the size of tag if this tag is embedded as part of bigger structures (profileSequenceDescTag, for instance)
1416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
1417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_MLU_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu;
1422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Count, RecLen, NumOfWchar;
1423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number SizeOfHeader;
1424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number  Len, Offset;
1425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number  i;
1426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    wchar_t*         Block;
1427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number  BeginOfThisString, EndOfThisString, LargestPosition;
1428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
1430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
1431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &RecLen)) return NULL;
1432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (RecLen != 12) {
1434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "multiLocalizedUnicodeType of len != 12 is not supported.");
1436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
1437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mlu = cmsMLUalloc(self ->ContextID, Count);
1440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mlu == NULL) return NULL;
1441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mlu ->UsedEntries = Count;
1443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfHeader = 12 * Count + sizeof(_cmsTagBase);
1445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    LargestPosition = 0;
1446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
1448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Language)) goto Error;
1450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Number(io, &mlu ->Entries[i].Country))  goto Error;
1451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Now deal with Len and offset.
1453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, &Len)) goto Error;
1454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, &Offset)) goto Error;
1455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Check for overflow
1457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Offset < (SizeOfHeader + 8)) goto Error;
1458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // True begin of the string
1460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        BeginOfThisString = Offset - SizeOfHeader - 8;
1461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Ajust to wchar_t elements
1463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // To guess maximum size, add offset + len
1467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        EndOfThisString = BeginOfThisString + Len;
1468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (EndOfThisString > LargestPosition)
1469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            LargestPosition = EndOfThisString;
1470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Now read the remaining of tag and fill all strings. Substract the directory
1473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag   = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag == 0)
1475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
1476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Block = NULL;
1477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        NumOfWchar = 0;
1478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
1481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
1482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag);
1483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Block == NULL) goto Error;
1484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        NumOfWchar = SizeOfTag / sizeof(wchar_t);
1485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadWCharArray(io, NumOfWchar, Block)) goto Error;
1486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mlu ->MemPool  = Block;
1489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mlu ->PoolSize = SizeOfTag;
1490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mlu ->PoolUsed = SizeOfTag;
1491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
1493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) mlu;
1494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1495ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
1496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mlu) cmsMLUfree(mlu);
1497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
1498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1501ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu =(cmsMLU*) Ptr;
1504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number HeaderSize;
1505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number  Len, Offset;
1506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i;
1507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Ptr == NULL) {
1509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          // Empty placeholder
1511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
1512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return TRUE;
1514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE;
1517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase);
1520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < mlu ->UsedEntries; i++) {
1522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Len    =  mlu ->Entries[i].Len;
1524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Offset =  mlu ->Entries[i].StrW;
1525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Len    = (Len * sizeof(cmsUInt16Number)) / sizeof(wchar_t);
1527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Offset = (Offset * sizeof(cmsUInt16Number)) / sizeof(wchar_t) + HeaderSize + 8;
1528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Language)) return FALSE;
1530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, mlu ->Entries[i].Country))  return FALSE;
1531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, Len)) return FALSE;
1532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, Offset)) return FALSE;
1533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteWCharArray(io, mlu ->PoolUsed / sizeof(wchar_t), (wchar_t*)  mlu ->MemPool)) return FALSE;
1536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
1540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_MLU_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsMLUdup((cmsMLU*) Ptr);
1548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
1550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_MLU_Free(struct _cms_typehandler_struct* self, void* Ptr)
1555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLUfree((cmsMLU*) Ptr);
1557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
1558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigLut8Type
1565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Decide which LUT type to use on writting
1568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1569ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeSignature DecideLUTtypeA2B(cmsFloat64Number ICCVersion, const void *Data)
1570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* Lut = (cmsPipeline*) Data;
1572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ICCVersion < 4.0) {
1574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Lut ->SaveAs8Bits) return cmsSigLut8Type;
1575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return cmsSigLut16Type;
1576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
1578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         return cmsSigLutAtoBType;
1579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1583ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeSignature DecideLUTtypeB2A(cmsFloat64Number ICCVersion, const void *Data)
1584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* Lut = (cmsPipeline*) Data;
1586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ICCVersion < 4.0) {
1588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Lut ->SaveAs8Bits) return cmsSigLut8Type;
1589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return cmsSigLut16Type;
1590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
1592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         return cmsSigLutBtoAType;
1593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
1597ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovThis structure represents a colour transform using tables of 8-bit precision.
1598ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovThis type contains four processing elements: a 3 by 3 matrix (which shall be
1599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovthe identity matrix unless the input colour space is XYZ), a set of one dimensional
1600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovinput tables, a multidimensional lookup table, and a set of one dimensional output
1601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtables. Data is processed using these elements via the following sequence:
1602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov(matrix) -> (1d input tables)  -> (multidimensional lookup table - CLUT) -> (1d output tables)
1603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1604ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovByte Position   Field Length (bytes)  Content Encoded as...
1605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov8                  1          Number of Input Channels (i)    uInt8Number
1606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov9                  1          Number of Output Channels (o)   uInt8Number
1607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov10                 1          Number of CLUT grid points (identical for each side) (g) uInt8Number
1608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov11                 1          Reserved for padding (fill with 00h)
1609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov12..15             4          Encoded e00 parameter   s15Fixed16Number
1611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
1612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Read 8 bit tables as gamma functions
1615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1616ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Read8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels)
1617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* Temp = NULL;
1619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i, j;
1620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* Tables[cmsMAXCHANNELS];
1621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nChannels > cmsMAXCHANNELS) return FALSE;
1623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nChannels <= 0) return FALSE;
1624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(Tables, 0, sizeof(Tables));
1626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Temp = (cmsUInt8Number*) _cmsMalloc(ContextID, 256);
1628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Temp == NULL) return FALSE;
1629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nChannels; i++) {
1631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, 256, NULL);
1632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Tables[i] == NULL) goto Error;
1633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nChannels; i++) {
1636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (io ->Read(io, Temp, 256, 1) != 1) goto Error;
1638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (j=0; j < 256; j++)
1640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Tables[i]->Table16[j] = (cmsUInt16Number) FROM_8_TO_16(Temp[j]);
1641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(ContextID, Temp);
1644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Temp = NULL;
1645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
1647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Error;
1648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nChannels; i++)
1650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFreeToneCurve(Tables[i]);
1651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1654ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
1655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nChannels; i++) {
1656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Tables[i]) cmsFreeToneCurve(Tables[i]);
1657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Temp) _cmsFree(ContextID, Temp);
1660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
1661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1665ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Write8bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsUInt32Number n, _cmsStageToneCurvesData* Tables)
1666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int j;
1668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
1669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number val;
1670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < n; i++) {
1672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Tables) {
1674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // Usual case of identity curves
1676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if ((Tables ->TheCurves[i]->nEntries == 2) &&
1677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                (Tables->TheCurves[i]->Table16[0] == 0) &&
1678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                (Tables->TheCurves[i]->Table16[1] == 65535)) {
1679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    for (j=0; j < 256; j++) {
1681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) j)) return FALSE;
1682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
1683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            else
1685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (Tables ->TheCurves[i]->nEntries != 256) {
1686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsSignalError(ContextID, cmsERROR_RANGE, "LUT8 needs 256 entries on prelinearization");
1687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    return FALSE;
1688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
1689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                else
1690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    for (j=0; j < 256; j++) {
1691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if (Tables != NULL)
1693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            val = (cmsUInt8Number) FROM_16_TO_8(Tables->TheCurves[i]->Table16[j]);
1694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        else
1695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            val = (cmsUInt8Number) j;
1696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        if (!_cmsWriteUInt8Number(io, val)) return FALSE;
1698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
1699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Check overflow
1706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1707ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number uipow(cmsUInt32Number n, cmsUInt32Number a, cmsUInt32Number b)
1708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number rv = 1, rc;
1710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (a == 0) return 0;
1712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (n == 0) return 0;
1713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (; b > 0; b--) {
1715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        rv *= a;
1717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Check for overflow
1719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (rv > UINT_MAX / a) return (cmsUInt32Number) -1;
1720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    rc = rv * n;
1724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (rv != rc / n) return (cmsUInt32Number) -1;
1726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return rc;
1727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// That will create a MPE LUT with Matrix, pre tables, CLUT and post tables.
1731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// 8 bit lut may be scaled easely to v4 PCS, but we need also to properly adjust
1732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// PCS on BToAxx tags and AtoB if abstract. We need to fix input direction.
1733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_LUT8_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
1736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
1738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number* Temp = NULL;
1739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* NewLUT = NULL;
1740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nTabSize, i;
1741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number Matrix[3*3];
1742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
1744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &InputChannels)) goto Error;
1746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &OutputChannels)) goto Error;
1747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &CLUTpoints)) goto Error;
1748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (CLUTpoints == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least
1750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Padding
1752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, NULL)) goto Error;
1753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Do some checking
1755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (InputChannels > cmsMAXCHANNELS)  goto Error;
1756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (OutputChannels > cmsMAXCHANNELS) goto Error;
1757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   // Allocates an empty Pipeline
1759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels);
1760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewLUT == NULL) goto Error;
1761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read the Matrix
1763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[0])) goto Error;
1764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[1])) goto Error;
1765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[2])) goto Error;
1766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[3])) goto Error;
1767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[4])) goto Error;
1768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[5])) goto Error;
1769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[6])) goto Error;
1770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[7])) goto Error;
1771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[8])) goto Error;
1772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Only operates if not identity...
1775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
1776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_BEGIN, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
1778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
1779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get input tables
1782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!Read8bitTables(self ->ContextID, io,  NewLUT, InputChannels)) goto Error;
1783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get 3D CLUT. Check the overflow....
1785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
1786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nTabSize == (cmsUInt32Number) -1) goto Error;
1787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nTabSize > 0) {
1788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsUInt16Number *PtrW, *T;
1790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        PtrW = T  = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
1792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (T  == NULL) goto Error;
1793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Temp = (cmsUInt8Number*) _cmsMalloc(self ->ContextID, nTabSize);
1795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Temp == NULL) {
1796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            _cmsFree(self ->ContextID, T);
1797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
1798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (io ->Read(io, Temp, nTabSize, 1) != 1) {
1801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            _cmsFree(self ->ContextID, T);
1802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            _cmsFree(self ->ContextID, Temp);
1803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
1804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i = 0; i < nTabSize; i++) {
1807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            *PtrW++ = FROM_8_TO_16(Temp[i]);
1809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, Temp);
1811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Temp = NULL;
1812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T)))
1814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
1815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, T);
1816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get output tables
1820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;
1821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
1823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NewLUT;
1824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1825ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
1826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
1827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
1828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
1830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
1833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1834ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number j, nTabSize;
1837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number  val;
1838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
1839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* mpe;
1840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
1841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageMatrixData* MatMPE = NULL;
1842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageCLutData* clut = NULL;
1843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int clutPoints;
1844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Disassemble the LUT into components.
1846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mpe = NewLUT -> Elements;
1847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe ->Type == cmsSigMatrixElemType) {
1848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        MatMPE = (_cmsStageMatrixData*) mpe ->Data;
1850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = mpe -> Next;
1851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
1854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
1855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = mpe -> Next;
1856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
1859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        clut  = (_cmsStageCLutData*) mpe -> Data;
1860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = mpe ->Next;
1861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
1864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
1865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = mpe -> Next;
1866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // That should be all
1869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL) {
1870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT8");
1871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
1872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (clut == NULL)
1876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        clutPoints = 0;
1877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
1878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        clutPoints    = clut->Params->nSamples[0];
1879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->InputChannels)) return FALSE;
1881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) NewLUT ->OutputChannels)) return FALSE;
1882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
1883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
1884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (MatMPE != NULL) {
1887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE;
1889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE;
1890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE;
1891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE;
1892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE;
1893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE;
1894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE;
1895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE;
1896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE;
1897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
1900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
1909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
1910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // The prelinearization table
1913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!Write8bitTables(self ->ContextID, io, NewLUT ->InputChannels, PreMPE)) return FALSE;
1914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nTabSize = uipow(NewLUT->OutputChannels, clutPoints, NewLUT ->InputChannels);
1916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nTabSize == (cmsUInt32Number) -1) return FALSE;
1917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nTabSize > 0) {
1918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // The 3D CLUT.
1920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (clut != NULL) {
1921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (j=0; j < nTabSize; j++) {
1923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                val = (cmsUInt8Number) FROM_16_TO_8(clut ->Tab.T[j]);
1925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsWriteUInt8Number(io, val)) return FALSE;
1926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
1927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
1928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // The postlinearization table
1931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!Write8bitTables(self ->ContextID, io, NewLUT ->OutputChannels, PostMPE)) return FALSE;
1932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
1936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_LUT8_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
1943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
1945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_LUT8_Free(struct _cms_typehandler_struct* self, void* Ptr)
1950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipelineFree((cmsPipeline*) Ptr);
1952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
1953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
1955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
1956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigLut16Type
1959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
1960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Read 16 bit tables as gamma functions
1962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
1963ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Read16bitTables(cmsContext ContextID, cmsIOHANDLER* io, cmsPipeline* lut, int nChannels, int nEntries)
1964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
1965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i;
1966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* Tables[cmsMAXCHANNELS];
1967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Maybe an empty table? (this is a lcms extension)
1969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nEntries <= 0) return TRUE;
1970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check for malicious profiles
1972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nEntries < 2) return FALSE;
1973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nChannels > cmsMAXCHANNELS) return FALSE;
1974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Init table to zero
1976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(Tables, 0, sizeof(Tables));
1977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nChannels; i++) {
1979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Tables[i] = cmsBuildTabulatedToneCurve16(ContextID, nEntries, NULL);
1981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Tables[i] == NULL) goto Error;
1982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Array(io, nEntries, Tables[i]->Table16)) goto Error;
1984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
1985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Add the table (which may certainly be an identity, but this is up to the optimizer, not the reading code)
1988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!cmsPipelineInsertStage(lut, cmsAT_END, cmsStageAllocToneCurves(ContextID, nChannels, Tables)))
1989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Error;
1990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nChannels; i++)
1992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFreeToneCurve(Tables[i]);
1993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
1995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
1996ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
1997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nChannels; i++) {
1998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Tables[i]) cmsFreeToneCurve(Tables[i]);
1999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
2002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2005ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Write16bitTables(cmsContext ContextID, cmsIOHANDLER* io, _cmsStageToneCurvesData* Tables)
2006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int j;
2008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
2009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number val;
2010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int nEntries;
2011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsAssert(Tables != NULL);
2013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nEntries = Tables->TheCurves[0]->nEntries;
2015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Tables ->nCurves; i++) {
2017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (j=0; j < nEntries; j++) {
2019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            val = Tables->TheCurves[i]->Table16[j];
2021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, val)) return FALSE;
2022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
2025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(ContextID);
2027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_LUT16_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number InputChannels, OutputChannels, CLUTpoints;
2033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* NewLUT = NULL;
2034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nTabSize;
2035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number Matrix[3*3];
2036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number InputEntries, OutputEntries;
2037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
2039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &InputChannels)) return NULL;
2041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &OutputChannels)) return NULL;
2042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &CLUTpoints)) return NULL;   // 255 maximum
2043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Padding
2045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
2046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Do some checking
2048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (InputChannels > cmsMAXCHANNELS)  goto Error;
2049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (OutputChannels > cmsMAXCHANNELS) goto Error;
2050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Allocates an empty LUT
2052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChannels, OutputChannels);
2053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewLUT == NULL) goto Error;
2054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read the Matrix
2056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[0])) goto Error;
2057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[1])) goto Error;
2058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[2])) goto Error;
2059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[3])) goto Error;
2060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[4])) goto Error;
2061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[5])) goto Error;
2062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[6])) goto Error;
2063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[7])) goto Error;
2064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io,  &Matrix[8])) goto Error;
2065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Only operates on 3 channels
2068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ((InputChannels == 3) && !_cmsMAT3isIdentity((cmsMAT3*) Matrix)) {
2069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocMatrix(self ->ContextID, 3, 3, Matrix, NULL)))
2071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &InputEntries)) goto Error;
2075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &OutputEntries)) goto Error;
2076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (InputEntries > 0x7FFF || OutputEntries > 0x7FFF) goto Error;
2078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CLUTpoints == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least
2079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get input tables
2081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!Read16bitTables(self ->ContextID, io,  NewLUT, InputChannels, InputEntries)) goto Error;
2082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get 3D CLUT
2084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nTabSize = uipow(OutputChannels, CLUTpoints, InputChannels);
2085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nTabSize == (cmsUInt32Number) -1) goto Error;
2086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nTabSize > 0) {
2087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsUInt16Number *T;
2089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        T  = (cmsUInt16Number*) _cmsCalloc(self ->ContextID, nTabSize, sizeof(cmsUInt16Number));
2091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (T  == NULL) goto Error;
2092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Array(io, nTabSize, T)) {
2094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            _cmsFree(self ->ContextID, T);
2095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, cmsStageAllocCLut16bit(self ->ContextID, CLUTpoints, InputChannels, OutputChannels, T))) {
2099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            _cmsFree(self ->ContextID, T);
2100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, T);
2103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get output tables
2107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!Read16bitTables(self ->ContextID, io,  NewLUT, OutputChannels, OutputEntries)) goto Error;
2108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
2110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NewLUT;
2111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2112ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
2113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewLUT != NULL) cmsPipelineFree(NewLUT);
2114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
2115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
2117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// We only allow some specific MPE structures: Matrix plus prelin, plus clut, plus post-lin.
2120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Some empty defaults are created for missing parts
2121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2123ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_LUT16_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nTabSize;
2126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
2127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* mpe;
2128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
2129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageMatrixData* MatMPE = NULL;
2130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageCLutData* clut = NULL;
2131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i, InputChannels, OutputChannels, clutPoints;
2132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Disassemble the LUT into components.
2134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mpe = NewLUT -> Elements;
2135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL && mpe ->Type == cmsSigMatrixElemType) {
2136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        MatMPE = (_cmsStageMatrixData*) mpe ->Data;
2138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = mpe -> Next;
2139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
2143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
2144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = mpe -> Next;
2145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
2148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        clut  = (_cmsStageCLutData*) mpe -> Data;
2149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = mpe ->Next;
2150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
2153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
2154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = mpe -> Next;
2155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // That should be all
2158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL) {
2159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(mpe->ContextID, cmsERROR_UNKNOWN_EXTENSION, "LUT is not suitable to be saved as LUT16");
2160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
2161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    InputChannels  = cmsPipelineInputChannels(NewLUT);
2164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    OutputChannels = cmsPipelineOutputChannels(NewLUT);
2165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (clut == NULL)
2167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        clutPoints = 0;
2168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
2169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        clutPoints    = clut->Params->nSamples[0];
2170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) InputChannels)) return FALSE;
2172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) OutputChannels)) return FALSE;
2173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) clutPoints)) return FALSE;
2174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, 0)) return FALSE; // Padding
2175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (MatMPE != NULL) {
2178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[0])) return FALSE;
2180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[1])) return FALSE;
2181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[2])) return FALSE;
2182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[3])) return FALSE;
2183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[4])) return FALSE;
2184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[5])) return FALSE;
2185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[6])) return FALSE;
2186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[7])) return FALSE;
2187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, MatMPE -> Double[8])) return FALSE;
2188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
2190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 1)) return FALSE;
2200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (PreMPE != NULL) {
2204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PreMPE ->TheCurves[0]->nEntries)) return FALSE;
2205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
2206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
2207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (PostMPE != NULL) {
2210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) PostMPE ->TheCurves[0]->nEntries)) return FALSE;
2211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    } else {
2212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
2213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // The prelinearization table
2217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (PreMPE != NULL) {
2219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!Write16bitTables(self ->ContextID, io, PreMPE)) return FALSE;
2220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
2222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i=0; i < InputChannels; i++) {
2223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
2225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
2226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nTabSize = uipow(OutputChannels, clutPoints, InputChannels);
2230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nTabSize == (cmsUInt32Number) -1) return FALSE;
2231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nTabSize > 0) {
2232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // The 3D CLUT.
2233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (clut != NULL) {
2234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Array(io, nTabSize, clut->Tab.T)) return FALSE;
2235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // The postlinearization table
2239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (PostMPE != NULL) {
2240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!Write16bitTables(self ->ContextID, io, PostMPE)) return FALSE;
2241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
2243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i=0; i < OutputChannels; i++) {
2244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
2246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, 0xffff)) return FALSE;
2247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
2251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
2253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_LUT16_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
2261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
2262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_LUT16_Free(struct _cms_typehandler_struct* self, void* Ptr)
2266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipelineFree((cmsPipeline*) Ptr);
2268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
2269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
2271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
2275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigLutAToBType
2276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
2277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// V4 stuff. Read matrix for LutAtoB and LutBtoA
2280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2282ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsStage* ReadMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset)
2283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number dMat[3*3];
2285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number dOff[3];
2286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* Mat;
2287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Go to address
2289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io -> Seek(io, Offset)) return NULL;
2290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read the Matrix
2292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[0])) return NULL;
2293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[1])) return NULL;
2294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[2])) return NULL;
2295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[3])) return NULL;
2296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[4])) return NULL;
2297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[5])) return NULL;
2298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[6])) return NULL;
2299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[7])) return NULL;
2300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dMat[8])) return NULL;
2301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dOff[0])) return NULL;
2303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dOff[1])) return NULL;
2304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsRead15Fixed16Number(io, &dOff[2])) return NULL;
2305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Mat = cmsStageAllocMatrix(self ->ContextID, 3, 3, dMat, dOff);
2307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     return Mat;
2309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//  V4 stuff. Read CLUT part for LutAtoB and LutBtoA
2315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2317ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsStage* ReadCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, int InputChannels, int OutputChannels)
2318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number  gridPoints8[cmsMAXCHANNELS]; // Number of grid points in each dimension.
2320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number GridPoints[cmsMAXCHANNELS], i;
2321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number  Precision;
2322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* CLUT;
2323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageCLutData* Data;
2324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io -> Seek(io, Offset)) return NULL;
2326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io -> Read(io, gridPoints8, cmsMAXCHANNELS, 1) != 1) return NULL;
2327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < cmsMAXCHANNELS; i++) {
2330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (gridPoints8[i] == 1) return NULL; // Impossible value, 0 for no CLUT and then 2 at least
2332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        GridPoints[i] = gridPoints8[i];
2333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &Precision)) return NULL;
2336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
2338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
2339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, NULL)) return NULL;
2340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CLUT = cmsStageAllocCLut16bitGranular(self ->ContextID, GridPoints, InputChannels, OutputChannels, NULL);
2342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CLUT == NULL) return NULL;
2343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Data = (_cmsStageCLutData*) CLUT ->Data;
2345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Precision can be 1 or 2 bytes
2347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Precision == 1) {
2348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsUInt8Number  v;
2350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i=0; i < Data ->nEntries; i++) {
2352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (io ->Read(io, &v, sizeof(cmsUInt8Number), 1) != 1) return NULL;
2354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Data ->Tab.T[i] = FROM_8_TO_16(v);
2355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
2359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Precision == 2) {
2360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsReadUInt16Array(io, Data->nEntries, Data ->Tab.T)) {
2362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmsStageFree(CLUT);
2363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return NULL;
2364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
2365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
2367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cmsStageFree(CLUT);
2368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision);
2369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return NULL;
2370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return CLUT;
2373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2376ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsToneCurve* ReadEmbeddedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
2377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsTagTypeSignature  BaseType;
2379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nItems;
2380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseType = _cmsReadTypeBase(io);
2382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch (BaseType) {
2383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cmsSigCurveType:
2385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return (cmsToneCurve*) Type_Curve_Read(self, io, &nItems, 0);
2386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cmsSigParametricCurveType:
2388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return (cmsToneCurve*) Type_ParametricCurve_Read(self, io, &nItems, 0);
2389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            default:
2391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                {
2392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    char String[5];
2393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    _cmsTagSignature2String(String, (cmsTagSignature) BaseType);
2395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve type '%s'", String);
2396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
2397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return NULL;
2398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Read a set of curves from specific offset
2403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2404ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsStage* ReadSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number Offset, cmsUInt32Number nCurves)
2405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* Curves[cmsMAXCHANNELS];
2407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
2408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* Lin = NULL;
2409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nCurves > cmsMAXCHANNELS) return FALSE;
2411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io -> Seek(io, Offset)) return FALSE;
2413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nCurves; i++)
2415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Curves[i] = NULL;
2416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nCurves; i++) {
2418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Curves[i] = ReadEmbeddedCurve(self, io);
2420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Curves[i] == NULL) goto Error;
2421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadAlignment(io)) goto Error;
2422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Lin = cmsStageAllocToneCurves(self ->ContextID, nCurves, Curves);
2426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2427ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
2428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nCurves; i++)
2429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFreeToneCurve(Curves[i]);
2430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return Lin;
2432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LutAtoB type
2436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This structure represents a colour transform. The type contains up to five processing
2438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// elements which are stored in the AtoBTag tag in the following order: a set of one
2439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// dimensional curves, a 3 by 3 matrix with offset terms, a set of one dimensional curves,
2440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// a multidimensional lookup table, and a set of one dimensional output curves.
2441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Data are processed using these elements via the following sequence:
2442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
2443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//("A" curves) -> (multidimensional lookup table - CLUT) -> ("M" curves) -> (matrix) -> ("B" curves).
2444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
2445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
2446ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIt is possible to use any or all of these processing elements. At least one processing element
2447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovmust be included.Only the following combinations are allowed:
2448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2449ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovB
2450ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovM - Matrix - B
2451ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovA - CLUT - B
2452ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovA - CLUT - M - Matrix - B
2453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
2455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_LUTA2B_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      BaseOffset;
2460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number       inputChan;      // Number of input channels
2461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number       outputChan;     // Number of output channels
2462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetB;        // Offset to first "B" curve
2463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetMat;      // Offset to matrix
2464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetM;        // Offset to first "M" curve
2465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetC;        // Offset to CLUT
2466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetA;        // Offset to first "A" curve
2467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* NewLUT = NULL;
2468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
2471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &inputChan)) return NULL;
2473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &outputChan)) return NULL;
2474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, NULL)) return NULL;
2476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetB)) return NULL;
2478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL;
2479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetM)) return NULL;
2480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetC)) return NULL;
2481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetA)) return NULL;
2482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   // Allocates an empty LUT
2484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan);
2485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewLUT == NULL) return NULL;
2486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetA!= 0) {
2488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, inputChan)))
2489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetC != 0) {
2493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
2494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetM != 0) {
2498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, outputChan)))
2499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetMat != 0) {
2503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
2504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetB != 0) {
2508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, outputChan)))
2509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
2513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NewLUT;
2514ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
2515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipelineFree(NewLUT);
2516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
2517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
2519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Write a set of curves
2522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2523ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  WriteMatrix(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsStage* mpe)
2524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageMatrixData* m = (_cmsStageMatrixData*) mpe -> Data;
2526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the Matrix
2528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[0])) return FALSE;
2529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[1])) return FALSE;
2530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[2])) return FALSE;
2531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[3])) return FALSE;
2532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[4])) return FALSE;
2533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[5])) return FALSE;
2534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[6])) return FALSE;
2535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[7])) return FALSE;
2536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Double[8])) return FALSE;
2537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (m ->Offset != NULL) {
2539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Offset[0])) return FALSE;
2541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Offset[1])) return FALSE;
2542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWrite15Fixed16Number(io, m -> Offset[2])) return FALSE;
2543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
2545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, 0)) return FALSE;
2548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
2553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
2555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Write a set of curves
2559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2560ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
2561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, n;
2563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsTagTypeSignature CurrentType;
2564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve** Curves;
2565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    n      = cmsStageOutputChannels(mpe);
2568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Curves = _cmsStageGetPtrToCurveSet(mpe);
2569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < n; i++) {
2571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // If this is a table-based curve, use curve type even on V4
2573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        CurrentType = Type;
2574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if ((Curves[i] ->nSegments == 0)||
2576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            ((Curves[i]->nSegments == 2) && (Curves[i] ->Segments[1].Type == 0)) )
2577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CurrentType = cmsSigCurveType;
2578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else
2579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Curves[i] ->Segments[0].Type < 0)
2580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            CurrentType = cmsSigCurveType;
2581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteTypeBase(io, CurrentType)) return FALSE;
2583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        switch (CurrentType) {
2585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cmsSigCurveType:
2587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!Type_Curve_Write(self, io, Curves[i], 1)) return FALSE;
2588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
2589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cmsSigParametricCurveType:
2591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!Type_ParametricCurve_Write(self, io, Curves[i], 1)) return FALSE;
2592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
2593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            default:
2595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                {
2596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    char String[5];
2597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    _cmsTagSignature2String(String, (cmsTagSignature) Type);
2599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve type '%s'", String);
2600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
2601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return FALSE;
2602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteAlignment(io)) return FALSE;
2605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
2609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2613ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteCLUT(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt8Number  Precision, cmsStage* mpe)
2614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number  gridPoints[cmsMAXCHANNELS]; // Number of grid points in each dimension.
2616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
2617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageCLutData* CLUT = ( _cmsStageCLutData*) mpe -> Data;
2618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CLUT ->HasFloatValues) {
2620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         cmsSignalError(self ->ContextID, cmsERROR_NOT_SUITABLE, "Cannot save floating point data, CLUT are 8 or 16 bit only");
2621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         return FALSE;
2622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(gridPoints, 0, sizeof(gridPoints));
2625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < (cmsUInt32Number) CLUT ->Params ->nInputs; i++)
2626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        gridPoints[i] = (cmsUInt8Number) CLUT ->Params ->nSamples[i];
2627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io -> Write(io, cmsMAXCHANNELS*sizeof(cmsUInt8Number), gridPoints)) return FALSE;
2629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) Precision)) return FALSE;
2631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;
2632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;
2633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, 0)) return FALSE;
2634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Precision can be 1 or 2 bytes
2636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Precision == 1) {
2637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i=0; i < CLUT->nEntries; i++) {
2639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt8Number(io, FROM_16_TO_8(CLUT->Tab.T[i]))) return FALSE;
2641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
2644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Precision == 2) {
2645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Array(io, CLUT->nEntries, CLUT ->Tab.T)) return FALSE;
2647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
2649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown precision of '%d'", Precision);
2650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
2651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
2652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteAlignment(io)) return FALSE;
2654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
2656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2662ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_LUTA2B_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* Lut = (cmsPipeline*) Ptr;
2665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int inputChan, outputChan;
2666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage *A = NULL, *B = NULL, *M = NULL;
2667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage * Matrix = NULL;
2668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage * CLUT = NULL;
2669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0;
2670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos;
2671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get the base for all offsets
2673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
2674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Lut ->Elements != NULL)
2676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B))
2677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &M, &Matrix, &B))
2678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &A, &CLUT, &B))
2679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType,
2680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        cmsSigMatrixElemType, cmsSigCurveSetElemType, &A, &CLUT, &M, &Matrix, &B)) {
2681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutAToB");
2683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                            return FALSE;
2684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    }
2685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get input, output channels
2687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    inputChan  = cmsPipelineInputChannels(Lut);
2688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    outputChan = cmsPipelineOutputChannels(Lut);
2689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write channel count
2691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE;
2692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE;
2693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
2694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Keep directory to be filled latter
2696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    DirectoryPos = io ->Tell(io);
2697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the directory
2699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (A != NULL) {
2706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetA = io ->Tell(io) - BaseOffset;
2708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE;
2709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CLUT != NULL) {
2712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetC = io ->Tell(io) - BaseOffset;
2713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE;
2714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (M != NULL) {
2717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetM = io ->Tell(io) - BaseOffset;
2719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE;
2720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Matrix != NULL) {
2723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetMat = io ->Tell(io) - BaseOffset;
2724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteMatrix(self, io, Matrix)) return FALSE;
2725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (B != NULL) {
2728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetB = io ->Tell(io) - BaseOffset;
2730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
2731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CurrentPos = io ->Tell(io);
2734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, DirectoryPos)) return FALSE;
2736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
2738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
2739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
2740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
2741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;
2742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, CurrentPos)) return FALSE;
2744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
2746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
2748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_LUTA2B_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
2757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
2758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_LUTA2B_Free(struct _cms_typehandler_struct* self, void* Ptr)
2762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipelineFree((cmsPipeline*) Ptr);
2764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
2765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
2767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LutBToA type
2771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_LUTB2A_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number       inputChan;      // Number of input channels
2776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number       outputChan;     // Number of output channels
2777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      BaseOffset;     // Actual position in file
2778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetB;        // Offset to first "B" curve
2779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetMat;      // Offset to matrix
2780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetM;        // Offset to first "M" curve
2781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetC;        // Offset to CLUT
2782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      offsetA;        // Offset to first "A" curve
2783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* NewLUT = NULL;
2784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
2787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &inputChan)) return NULL;
2789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt8Number(io, &outputChan)) return NULL;
2790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Padding
2792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, NULL)) return NULL;
2793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetB)) return NULL;
2795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetMat)) return NULL;
2796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetM)) return NULL;
2797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetC)) return NULL;
2798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &offsetA)) return NULL;
2799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Allocates an empty LUT
2801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewLUT = cmsPipelineAlloc(self ->ContextID, inputChan, outputChan);
2802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewLUT == NULL) return NULL;
2803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetB != 0) {
2805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetB, inputChan)))
2806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetMat != 0) {
2810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadMatrix(self, io, BaseOffset + offsetMat)))
2811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetM != 0) {
2815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetM, inputChan)))
2816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetC != 0) {
2820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadCLUT(self, io, BaseOffset + offsetC, inputChan, outputChan)))
2821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (offsetA!= 0) {
2825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, ReadSetOfCurves(self, io, BaseOffset + offsetA, outputChan)))
2826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            goto Error;
2827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
2830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NewLUT;
2831ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
2832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipelineFree(NewLUT);
2833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
2834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
2836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
2840ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovB
2841ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovB - Matrix - M
2842ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovB - CLUT - A
2843ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovB - Matrix - M - CLUT - A
2844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
2845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2847ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_LUTB2A_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
2848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* Lut = (cmsPipeline*) Ptr;
2850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int inputChan, outputChan;
2851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage *A = NULL, *B = NULL, *M = NULL;
2852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage *Matrix = NULL;
2853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage *CLUT = NULL;
2854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number offsetB = 0, offsetMat = 0, offsetM = 0, offsetC = 0, offsetA = 0;
2855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number BaseOffset, DirectoryPos, CurrentPos;
2856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
2859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!cmsPipelineCheckAndRetreiveStages(Lut, 1, cmsSigCurveSetElemType, &B))
2861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType, &B, &Matrix, &M))
2862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!cmsPipelineCheckAndRetreiveStages(Lut, 3, cmsSigCurveSetElemType, cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &CLUT, &A))
2863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!cmsPipelineCheckAndRetreiveStages(Lut, 5, cmsSigCurveSetElemType, cmsSigMatrixElemType, cmsSigCurveSetElemType,
2864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsSigCLutElemType, cmsSigCurveSetElemType, &B, &Matrix, &M, &CLUT, &A)) {
2865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        cmsSignalError(self->ContextID, cmsERROR_NOT_SUITABLE, "LUT is not suitable to be saved as LutBToA");
2866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        return FALSE;
2867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
2868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    inputChan  = cmsPipelineInputChannels(Lut);
2870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    outputChan = cmsPipelineOutputChannels(Lut);
2871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) inputChan)) return FALSE;
2873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt8Number(io, (cmsUInt8Number) outputChan)) return FALSE;
2874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, 0)) return FALSE;
2875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    DirectoryPos = io ->Tell(io);
2877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
2883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (A != NULL) {
2885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetA = io ->Tell(io) - BaseOffset;
2887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, A)) return FALSE;
2888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (CLUT != NULL) {
2891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetC = io ->Tell(io) - BaseOffset;
2892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteCLUT(self, io, Lut ->SaveAs8Bits ? 1 : 2, CLUT)) return FALSE;
2893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (M != NULL) {
2896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetM = io ->Tell(io) - BaseOffset;
2898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, M)) return FALSE;
2899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Matrix != NULL) {
2902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetMat = io ->Tell(io) - BaseOffset;
2903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteMatrix(self, io, Matrix)) return FALSE;
2904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (B != NULL) {
2907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        offsetB = io ->Tell(io) - BaseOffset;
2909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteSetOfCurves(self, io, cmsSigParametricCurveType, B)) return FALSE;
2910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CurrentPos = io ->Tell(io);
2913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, DirectoryPos)) return FALSE;
2915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetB)) return FALSE;
2917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetMat)) return FALSE;
2918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetM)) return FALSE;
2919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetC)) return FALSE;
2920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, offsetA)) return FALSE;
2921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, CurrentPos)) return FALSE;
2923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
2925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
2927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_LUTB2A_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
2933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
2935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
2937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
2938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_LUTB2A_Free(struct _cms_typehandler_struct* self, void* Ptr)
2942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipelineFree((cmsPipeline*) Ptr);
2944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
2945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
2947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
2948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
2952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigColorantTableType
2953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
2954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
2955ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovThe purpose of this tag is to identify the colorants used in the profile by a
2956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovunique name and set of XYZ or L*a*b* values to give the colorant an unambiguous
2957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvalue. The first colorant listed is the colorant of the first device channel of
2958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganova lut tag. The second colorant listed is the colorant of the second device channel
2959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovof a lut tag, and so on.
2960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
2961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
2963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_ColorantTable_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
2964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
2965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, Count;
2966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsNAMEDCOLORLIST* List;
2967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char Name[34];
2968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number PCS[3];
2969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
2972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Count > cmsMAXCHANNELS) {
2974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many colorants '%d'", Count);
2975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
2976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    List = cmsAllocNamedColorList(self ->ContextID, Count, 0, "", "");
2979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
2980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (io ->Read(io, Name, 32, 1) != 1) goto Error;
2982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Name[33] = 0;
2983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
2985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsAppendNamedColor(List, Name, PCS, NULL)) goto Error;
2987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
2989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
2991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return List;
2992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2993ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
2994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
2995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeNamedColorList(List);
2996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
2997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
2998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
2999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Saves a colorant table. It is using the named color structure for simplicity sake
3004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3005ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_ColorantTable_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
3008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i, nColors;
3009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nColors = cmsNamedColorCount(NamedColorList);
3011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
3013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nColors; i++) {
3015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        char root[33];
3017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsUInt16Number PCS[3];
3018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsNamedColorInfo(NamedColorList, i, root, NULL, NULL, PCS, NULL)) return 0;
3020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        root[32] = 0;
3021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!io ->Write(io, 32, root)) return FALSE;
3023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
3024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
3029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_ColorantTable_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
3037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsDupNamedColorList(nc);
3038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
3040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_ColorantTable_Free(struct _cms_typehandler_struct* self, void* Ptr)
3046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);
3048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
3049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigNamedColor2Type
3056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
3058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//The namedColor2Type is a count value and array of structures that provide color
3059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//coordinates for 7-bit ASCII color names. For each named color, a PCS and optional
3060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//device representation of the color are given. Both representations are 16-bit values.
3061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//The device representation corresponds to the header�s �color space of data?field.
3062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//This representation should be consistent with the �number of device components?//field in the namedColor2Type. If this field is 0, device coordinates are not provided.
3063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//The PCS representation corresponds to the header�s PCS field. The PCS representation
3064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//is always provided. Color names are fixed-length, 32-byte fields including null
3065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//termination. In order to maintain maximum portability, it is strongly recommended
3066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//that special characters of the 7-bit ASCII set not be used.
3067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_NamedColor_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      vendorFlag;     // Bottom 16 bits for ICC use
3073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      count;          // Count of named colors
3074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number      nDeviceCoords;  // Num of device coordinates
3075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char                 prefix[32];     // Prefix for each color name
3076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char                 suffix[32];     // Suffix for each color name
3077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsNAMEDCOLORLIST*  v;
3078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
3079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
3082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &vendorFlag)) return NULL;
3083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &count)) return NULL;
3084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &nDeviceCoords)) return NULL;
3085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io -> Read(io, prefix, 32, 1) != 1) return NULL;
3087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io -> Read(io, suffix, 32, 1) != 1) return NULL;
3088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    prefix[31] = suffix[31] = 0;
3090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v = cmsAllocNamedColorList(self ->ContextID, count, nDeviceCoords, prefix, suffix);
3092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (v == NULL) {
3093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many named colors '%d'", count);
3094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
3095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (nDeviceCoords > cmsMAXCHANNELS) {
3098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords);
3099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return 0;
3100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < count; i++) {
3102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsUInt16Number PCS[3];
3104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsUInt16Number Colorant[cmsMAXCHANNELS];
3105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        char Root[33];
3106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        memset(Colorant, 0, sizeof(Colorant));
3108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (io -> Read(io, Root, 32, 1) != 1) return NULL;
3109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
3110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
3111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error;
3113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
3116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) v ;
3117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3118ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
3119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeNamedColorList(v);
3120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
3121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
3123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Saves a named color list into a named color profile
3127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3128ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
3131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char                prefix[32];     // Prefix for each color name
3132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char                suffix[32];     // Suffix for each color name
3133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int i, nColors;
3134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nColors = cmsNamedColorCount(NamedColorList);
3136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
3138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
3139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE;
3140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
3142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
3143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    suffix[31] = prefix[31] = 0;
3145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, 32, prefix)) return FALSE;
3147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, 32, suffix)) return FALSE;
3148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nColors; i++) {
3150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt16Number PCS[3];
3152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt16Number Colorant[cmsMAXCHANNELS];
3153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       char Root[33];
3154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;
3156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!io ->Write(io, 32 , Root)) return FALSE;
3157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
3158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE;
3159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
3164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_NamedColor_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
3171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsDupNamedColorList(nc);
3173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
3175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_NamedColor_Free(struct _cms_typehandler_struct* self, void* Ptr)
3181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeNamedColorList((cmsNAMEDCOLORLIST*) Ptr);
3183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
3184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigProfileSequenceDescType
3191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This type is an array of structures, each of which contains information from the
3194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// header fields and tags from the original profiles which were combined to create
3195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// the final profile. The order of the structures is the order in which the profiles
3196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// were combined and includes a structure for the final profile. This provides a
3197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// description of the profile sequence from source to destination,
3198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// typically used with the DeviceLink profile.
3199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3201ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadEmbeddedText(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU** mlu, cmsUInt32Number SizeOfTag)
3202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsTagTypeSignature  BaseType;
3204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nItems;
3205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseType = _cmsReadTypeBase(io);
3207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch (BaseType) {
3209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       case cmsSigTextType:
3211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (*mlu) cmsMLUfree(*mlu);
3212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           *mlu = (cmsMLU*)Type_Text_Read(self, io, &nItems, SizeOfTag);
3213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           return (*mlu != NULL);
3214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       case cmsSigTextDescriptionType:
3216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (*mlu) cmsMLUfree(*mlu);
3217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           *mlu =  (cmsMLU*) Type_Text_Description_Read(self, io, &nItems, SizeOfTag);
3218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           return (*mlu != NULL);
3219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           /*
3221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           TBD: Size is needed for MLU, and we have no idea on which is the available size
3222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           */
3223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       case cmsSigMultiLocalizedUnicodeType:
3225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (*mlu) cmsMLUfree(*mlu);
3226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           *mlu =  (cmsMLU*) Type_MLU_Read(self, io, &nItems, SizeOfTag);
3227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           return (*mlu != NULL);
3228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       default: return FALSE;
3230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_ProfileSequenceDesc_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSEQ* OutSeq;
3238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, Count;
3239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
3241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
3243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
3245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= sizeof(cmsUInt32Number);
3246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count);
3249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (OutSeq == NULL) return NULL;
3250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    OutSeq ->n = Count;
3252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get structures as well
3254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
3256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsPSEQDESC* sec = &OutSeq -> seq[i];
3258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, &sec ->deviceMfg)) goto Error;
3260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error;
3261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        SizeOfTag -= sizeof(cmsUInt32Number);
3262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, &sec ->deviceModel)) goto Error;
3264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error;
3265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        SizeOfTag -= sizeof(cmsUInt32Number);
3266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt64Number(io, &sec ->attributes)) goto Error;
3268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (SizeOfTag < sizeof(cmsUInt64Number)) goto Error;
3269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        SizeOfTag -= sizeof(cmsUInt64Number);
3270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, (cmsUInt32Number *)&sec ->technology)) goto Error;
3272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (SizeOfTag < sizeof(cmsUInt32Number)) goto Error;
3273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        SizeOfTag -= sizeof(cmsUInt32Number);
3274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!ReadEmbeddedText(self, io, &sec ->Manufacturer, SizeOfTag)) goto Error;
3276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!ReadEmbeddedText(self, io, &sec ->Model, SizeOfTag)) goto Error;
3277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
3280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return OutSeq;
3281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3282ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
3283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeProfileSequenceDescription(OutSeq);
3284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
3285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Aux--Embed a text description type. It can be of type text description or multilocalized unicode
3289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// and it depends of the version number passed on cmsTagDescriptor structure instead of stack
3290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3291ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  SaveDescription(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* Text)
3292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (self ->ICCVersion < 0x4000000) {
3294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteTypeBase(io, cmsSigTextDescriptionType)) return FALSE;
3296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return Type_Text_Description_Write(self, io, Text, 1);
3297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
3299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteTypeBase(io, cmsSigMultiLocalizedUnicodeType)) return FALSE;
3300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return Type_MLU_Write(self, io, Text, 1);
3301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3306ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_ProfileSequenceDesc_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSEQ* Seq = (cmsSEQ*) Ptr;
3309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
3310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, Seq->n)) return FALSE;
3312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Seq ->n; i++) {
3314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsPSEQDESC* sec = &Seq -> seq[i];
3316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, sec ->deviceMfg)) return FALSE;
3318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, sec ->deviceModel)) return FALSE;
3319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt64Number(io, &sec ->attributes)) return FALSE;
3320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, sec ->technology)) return FALSE;
3321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!SaveDescription(self, io, sec ->Manufacturer)) return FALSE;
3323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!SaveDescription(self, io, sec ->Model)) return FALSE;
3324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     return TRUE;
3327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     cmsUNUSED_PARAMETER(nItems);
3329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_ProfileSequenceDesc_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr);
3336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
3338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_ProfileSequenceDesc_Free(struct _cms_typehandler_struct* self, void* Ptr)
3343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr);
3345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
3346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigProfileSequenceIdType
3353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
3355ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovIn certain workflows using ICC Device Link Profiles, it is necessary to identify the
3356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovoriginal profiles that were combined to create the Device Link Profile.
3357ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovThis type is an array of structures, each of which contains information for
3358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovidentification of a profile used in a sequence
3359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
3360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3363ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadSeqID(struct _cms_typehandler_struct* self,
3364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsIOHANDLER* io,
3365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             void* Cargo,
3366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsUInt32Number n,
3367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsUInt32Number SizeOfTag)
3368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSEQ* OutSeq = (cmsSEQ*) Cargo;
3370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPSEQDESC* seq = &OutSeq ->seq[n];
3371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io -> Read(io, seq ->ProfileID.ID8, 16, 1) != 1) return FALSE;
3373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadEmbeddedText(self, io, &seq ->Description, SizeOfTag)) return FALSE;
3374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_ProfileSequenceId_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSEQ* OutSeq;
3384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Count;
3385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number BaseOffset;
3386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
3388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get actual position as a basis for element offsets
3390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
3391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get table count
3393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
3394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= sizeof(cmsUInt32Number);
3395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Allocate an empty structure
3397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    OutSeq = cmsAllocProfileSequenceDescription(self ->ContextID, Count);
3398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (OutSeq == NULL) return NULL;
3399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read the position table
3402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadPositionTable(self, io, Count, BaseOffset, OutSeq, ReadSeqID)) {
3403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFreeProfileSequenceDescription(OutSeq);
3405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
3406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Success
3409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
3410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return OutSeq;
3411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3416ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteSeqID(struct _cms_typehandler_struct* self,
3417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsIOHANDLER* io,
3418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             void* Cargo,
3419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsUInt32Number n,
3420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                             cmsUInt32Number SizeOfTag)
3421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSEQ* Seq = (cmsSEQ*) Cargo;
3423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, 16, Seq ->seq[n].ProfileID.ID8)) return FALSE;
3425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Store here the MLU
3427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!SaveDescription(self, io, Seq ->seq[n].Description)) return FALSE;
3428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
3432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3435ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_ProfileSequenceId_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSEQ* Seq = (cmsSEQ*) Ptr;
3438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number BaseOffset;
3439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Keep the base offset
3441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
3442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // This is the table count
3444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, Seq ->n)) return FALSE;
3445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // This is the position table and content
3447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WritePositionTable(self, io, 0, Seq ->n, BaseOffset, Seq, WriteSeqID)) return FALSE;
3448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
3452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_ProfileSequenceId_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsDupProfileSequenceDescription((cmsSEQ*) Ptr);
3458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
3460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_ProfileSequenceId_Free(struct _cms_typehandler_struct* self, void* Ptr)
3465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeProfileSequenceDescription((cmsSEQ*) Ptr);
3467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
3468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigUcrBgType
3475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
3477ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovThis type contains curves representing the under color removal and black
3478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovgeneration and a text string which is a general description of the method used
3479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovfor the ucr/bg.
3480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
3481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_UcrBg_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUcrBg* n = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
3486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number CountUcr, CountBg;
3487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char* ASCIIString;
3488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
3490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (n == NULL) return NULL;
3491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // First curve is Under color removal
3493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &CountUcr)) return NULL;
3494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
3495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= sizeof(cmsUInt32Number);
3496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    n ->Ucr = cmsBuildTabulatedToneCurve16(self ->ContextID, CountUcr, NULL);
3498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (n ->Ucr == NULL) return NULL;
3499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Array(io, CountUcr, n ->Ucr->Table16)) return NULL;
3501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
3502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= CountUcr * sizeof(cmsUInt16Number);
3503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Second curve is Black generation
3505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &CountBg)) return NULL;
3506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
3507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= sizeof(cmsUInt32Number);
3508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    n ->Bg = cmsBuildTabulatedToneCurve16(self ->ContextID, CountBg, NULL);
3510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (n ->Bg == NULL) return NULL;
3511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Array(io, CountBg, n ->Bg->Table16)) return NULL;
3512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag < CountBg * sizeof(cmsUInt16Number)) return NULL;
3513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= CountBg * sizeof(cmsUInt16Number);
3514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (SizeOfTag == UINT_MAX) return NULL;
3515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Now comes the text. The length is specified by the tag size
3517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    n ->Desc = cmsMLUalloc(self ->ContextID, 1);
3518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (n ->Desc == NULL) return NULL;
3519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ASCIIString = (char*) _cmsMalloc(self ->ContextID, SizeOfTag + 1);
3521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io ->Read(io, ASCIIString, sizeof(char), SizeOfTag) != SizeOfTag) return NULL;
3522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ASCIIString[SizeOfTag] = 0;
3523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLUsetASCII(n ->Desc, cmsNoLanguage, cmsNoCountry, ASCIIString);
3524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, ASCIIString);
3525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
3527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) n;
3528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3531ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_UcrBg_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUcrBg* Value = (cmsUcrBg*) Ptr;
3534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number TextSize;
3535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char* Text;
3536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // First curve is Under color removal
3538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, Value ->Ucr ->nEntries)) return FALSE;
3539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Array(io, Value ->Ucr ->nEntries, Value ->Ucr ->Table16)) return FALSE;
3540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Then black generation
3542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, Value ->Bg ->nEntries)) return FALSE;
3543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Array(io, Value ->Bg ->nEntries, Value ->Bg ->Table16)) return FALSE;
3544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Now comes the text. The length is specified by the tag size
3546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TextSize = cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, NULL, 0);
3547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text     = (char*) _cmsMalloc(self ->ContextID, TextSize);
3548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (cmsMLUgetASCII(Value ->Desc, cmsNoLanguage, cmsNoCountry, Text, TextSize) != TextSize) return FALSE;
3549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, TextSize, Text)) return FALSE;
3551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Text);
3552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
3556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_UcrBg_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUcrBg* Src = (cmsUcrBg*) Ptr;
3562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUcrBg* NewUcrBg = (cmsUcrBg*) _cmsMallocZero(self ->ContextID, sizeof(cmsUcrBg));
3563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewUcrBg == NULL) return NULL;
3565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewUcrBg ->Bg   = cmsDupToneCurve(Src ->Bg);
3567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewUcrBg ->Ucr  = cmsDupToneCurve(Src ->Ucr);
3568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewUcrBg ->Desc = cmsMLUdup(Src ->Desc);
3569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) NewUcrBg;
3571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
3573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_UcrBg_Free(struct _cms_typehandler_struct* self, void *Ptr)
3577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsUcrBg* Src = (cmsUcrBg*) Ptr;
3579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   if (Src ->Ucr) cmsFreeToneCurve(Src ->Ucr);
3581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   if (Src ->Bg)  cmsFreeToneCurve(Src ->Bg);
3582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   if (Src ->Desc) cmsMLUfree(Src ->Desc);
3583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsFree(self ->ContextID, Ptr);
3585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigCrdInfoType
3589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
3592ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovThis type contains the PostScript product name to which this profile corresponds
3593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovand the names of the companion CRDs. Recall that a single profile can generate
3594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovmultiple CRDs. It is implemented as a MLU being the language code "PS" and then
3595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovcountry varies for each element:
3596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                nm: PostScript product name
3598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                #0: Rendering intent 0 CRD name
3599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                #1: Rendering intent 1 CRD name
3600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                #2: Rendering intent 2 CRD name
3601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                #3: Rendering intent 3 CRD name
3602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
3603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Auxiliar, read an string specified as count + string
3607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3608ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section)
3609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Count;
3611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    char* Text;
3612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (*SizeOfTag < sizeof(cmsUInt32Number)) return FALSE;
3614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Count)) return FALSE;
3616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Count > UINT_MAX - sizeof(cmsUInt32Number)) return FALSE;
3618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (*SizeOfTag < Count + sizeof(cmsUInt32Number)) return FALSE;
3619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text     = (char*) _cmsMalloc(self ->ContextID, Count+1);
3621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Text == NULL) return FALSE;
3622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io ->Read(io, Text, sizeof(cmsUInt8Number), Count) != Count) {
3624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, Text);
3625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
3626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text[Count] = 0;
3629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLUsetASCII(mlu, "PS", Section, Text);
3631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Text);
3632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *SizeOfTag -= (Count + sizeof(cmsUInt32Number));
3634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3638ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  WriteCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, const char* Section)
3639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov cmsUInt32Number TextSize;
3641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov char* Text;
3642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TextSize = cmsMLUgetASCII(mlu, "PS", Section, NULL, 0);
3644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Text     = (char*) _cmsMalloc(self ->ContextID, TextSize);
3645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, TextSize)) return FALSE;
3647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (cmsMLUgetASCII(mlu, "PS", Section, Text, TextSize) == 0) return FALSE;
3649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, TextSize, Text)) return FALSE;
3651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Text);
3652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_CrdInfo_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu = cmsMLUalloc(self ->ContextID, 5);
3660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
3662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "nm")) goto Error;
3663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#0")) goto Error;
3664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#1")) goto Error;
3665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#2")) goto Error;
3666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadCountAndSting(self, io, mlu, &SizeOfTag, "#3")) goto Error;
3667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
3669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) mlu;
3670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3671ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
3672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLUfree(mlu);
3673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
3674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3678ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_CrdInfo_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLU* mlu = (cmsMLU*) Ptr;
3682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WriteCountAndSting(self, io, mlu, "nm")) goto Error;
3684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WriteCountAndSting(self, io, mlu, "#0")) goto Error;
3685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WriteCountAndSting(self, io, mlu, "#1")) goto Error;
3686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WriteCountAndSting(self, io, mlu, "#2")) goto Error;
3687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WriteCountAndSting(self, io, mlu, "#3")) goto Error;
3688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3691ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
3692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
3693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
3695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3697ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_CrdInfo_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsMLUdup((cmsMLU*) Ptr);
3702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
3704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_CrdInfo_Free(struct _cms_typehandler_struct* self, void *Ptr)
3709ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsMLUfree((cmsMLU*) Ptr);
3711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
3712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigScreeningType
3718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
3720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//The screeningType describes various screening parameters including screen
3721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//frequency, screening angle, and spot shape.
3722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Screening_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsScreening* sc = NULL;
3727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
3728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    sc = (cmsScreening*) _cmsMallocZero(self ->ContextID, sizeof(cmsScreening));
3730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (sc == NULL) return NULL;
3731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
3733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &sc ->Flag)) goto Error;
3735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &sc ->nChannels)) goto Error;
3736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (sc ->nChannels > cmsMAXCHANNELS - 1)
3738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        sc ->nChannels = cmsMAXCHANNELS - 1;
3739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < sc ->nChannels; i++) {
3741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].Frequency)) goto Error;
3743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsRead15Fixed16Number(io, &sc ->Channels[i].ScreenAngle)) goto Error;
3744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadUInt32Number(io, &sc ->Channels[i].SpotShape)) goto Error;
3745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
3749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) sc;
3751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3752ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
3753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (sc != NULL)
3754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, sc);
3755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
3757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
3759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3763ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_Screening_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsScreening* sc = (cmsScreening* ) Ptr;
3766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
3767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, sc ->Flag)) return FALSE;
3769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, sc ->nChannels)) return FALSE;
3770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < sc ->nChannels; i++) {
3772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].Frequency)) return FALSE;
3774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWrite15Fixed16Number(io, sc ->Channels[i].ScreenAngle)) return FALSE;
3775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, sc ->Channels[i].SpotShape)) return FALSE;
3776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
3777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
3781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Screening_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsUNUSED_PARAMETER(n);
3791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Screening_Free(struct _cms_typehandler_struct* self, void* Ptr)
3796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsFree(self ->ContextID, Ptr);
3798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigViewingConditionsType
3802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
3804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//This type represents a set of viewing condition parameters including:
3805ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//CIE �absolute?illuminant white point tristimulus values and CIE �absolute?//surround tristimulus values.
3806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_ViewingConditions_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
3809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsICCViewingConditions* vc = NULL;
3811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vc = (cmsICCViewingConditions*) _cmsMallocZero(self ->ContextID, sizeof(cmsICCViewingConditions));
3813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (vc == NULL) return NULL;
3814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
3816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadXYZNumber(io, &vc ->IlluminantXYZ)) goto Error;
3818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadXYZNumber(io, &vc ->SurroundXYZ)) goto Error;
3819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &vc ->IlluminantType)) goto Error;
3820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
3822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) vc;
3824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3825ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
3826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (vc != NULL)
3827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, vc);
3828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
3830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
3832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3836ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsICCViewingConditions* sc = (cmsICCViewingConditions* ) Ptr;
3839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteXYZNumber(io, &sc ->IlluminantXYZ)) return FALSE;
3841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteXYZNumber(io, &sc ->SurroundXYZ)) return FALSE;
3842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, sc ->IlluminantType)) return FALSE;
3843ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
3845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
3847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsUNUSED_PARAMETER(n);
3857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3861ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_ViewingConditions_Free(struct _cms_typehandler_struct* self, void* Ptr)
3862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsFree(self ->ContextID, Ptr);
3864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3868ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigMultiProcessElementType
3869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
3870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsStageDup((cmsStage*) Ptr);
3876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
3878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3881ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid GenericMPEfree(struct _cms_typehandler_struct* self, void *Ptr)
3883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStageFree((cmsStage*) Ptr);
3885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
3886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
3888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
3889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Each curve is stored in one or more curve segments, with break-points specified between curve segments.
3891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The first curve segment always starts at �Infinity, and the last curve segment always ends at +Infinity. The
3892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// first and last curve segments shall be specified in terms of a formula, whereas the other segments shall be
3893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// specified either in terms of a formula, or by a sampled curve.
3894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Read an embedded segmented curve
3897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
3898ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsToneCurve* ReadSegmentedCurve(struct _cms_typehandler_struct* self, cmsIOHANDLER* io)
3899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
3900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsCurveSegSignature ElementSig;
3901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, j;
3902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number nSegments;
3903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsCurveSegment*  Segments;
3904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve* Curve;
3905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat32Number PrevBreak = -1E22F;    // - infinite
3906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Take signature and channels for each element.
3908ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return NULL;
3909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     // That should be a segmented curve
3911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (ElementSig != cmsSigSegmentedCurve) return NULL;
3912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (!_cmsReadUInt32Number(io, NULL)) return NULL;
3914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (!_cmsReadUInt16Number(io, &nSegments)) return NULL;
3915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (!_cmsReadUInt16Number(io, NULL)) return NULL;
3916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3917ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (nSegments < 1) return NULL;
3918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     Segments = (cmsCurveSegment*) _cmsCalloc(self ->ContextID, nSegments, sizeof(cmsCurveSegment));
3919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (Segments == NULL) return NULL;
3920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     // Read breakpoints
3922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     for (i=0; i < (cmsUInt32Number) nSegments - 1; i++) {
3923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         Segments[i].x0 = PrevBreak;
3925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         if (!_cmsReadFloat32Number(io, &Segments[i].x1)) goto Error;
3926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         PrevBreak = Segments[i].x1;
3927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     }
3928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     Segments[nSegments-1].x0 = PrevBreak;
3930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     Segments[nSegments-1].x1 = 1E22F;     // A big cmsFloat32Number number
3931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     // Read segments
3933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     for (i=0; i < nSegments; i++) {
3934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) goto Error;
3936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          if (!_cmsReadUInt32Number(io, NULL)) goto Error;
3937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           switch (ElementSig) {
3939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cmsSigFormulaCurveSeg: {
3941ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmsUInt16Number Type;
3943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmsUInt32Number ParamsByType[] = {4, 5, 5 };
3944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsReadUInt16Number(io, &Type)) goto Error;
3946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsReadUInt16Number(io, NULL)) goto Error;
3947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Segments[i].Type = Type + 6;
3949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (Type > 2) goto Error;
3950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (j=0; j < ParamsByType[Type]; j++) {
3952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsFloat32Number f;
3954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (!_cmsReadFloat32Number(io, &f)) goto Error;
3955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    Segments[i].Params[j] = f;
3956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
3957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
3958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
3959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            case cmsSigSampledCurveSeg: {
3962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmsUInt32Number Count;
3963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsReadUInt32Number(io, &Count)) return NULL;
3965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Segments[i].nGridPoints = Count;
3967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                Segments[i].SampledPoints = (cmsFloat32Number*) _cmsCalloc(self ->ContextID, Count, sizeof(cmsFloat32Number));
3968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (Segments[i].SampledPoints == NULL) goto Error;
3969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                for (j=0; j < Count; j++) {
3971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    if (!_cmsReadFloat32Number(io, &Segments[i].SampledPoints[j])) goto Error;
3972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
3973ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
3974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                break;
3975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            default:
3977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                {
3978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                char String[5];
3979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
3981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown curve element type '%s' found.", String);
3982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                }
3983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                return NULL;
3984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3985ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         }
3986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     }
3987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     Curve = cmsBuildSegmentedToneCurve(self ->ContextID, nSegments, Segments);
3989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     for (i=0; i < nSegments; i++) {
3991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         if (Segments[i].SampledPoints) _cmsFree(self ->ContextID, Segments[i].SampledPoints);
3992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     }
3993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     _cmsFree(self ->ContextID, Segments);
3994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     return Curve;
3995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
3996ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
3997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (Segments) _cmsFree(self ->ContextID, Segments);
3998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     return NULL;
3999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4003ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadMPECurve(struct _cms_typehandler_struct* self,
4004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     cmsIOHANDLER* io,
4005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     void* Cargo,
4006ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     cmsUInt32Number n,
4007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     cmsUInt32Number SizeOfTag)
4008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      cmsToneCurve** GammaTables = ( cmsToneCurve**) Cargo;
4010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      GammaTables[n] = ReadSegmentedCurve(self, io);
4012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return (GammaTables[n] != NULL);
4013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      cmsUNUSED_PARAMETER(SizeOfTag);
4015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_MPEcurve_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* mpe = NULL;
4021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number InputChans, OutputChans;
4022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, BaseOffset;
4023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve** GammaTables;
4024ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
4026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get actual position as a basis for element offsets
4028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (InputChans != OutputChans) return NULL;
4034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    GammaTables = (cmsToneCurve**) _cmsCalloc(self ->ContextID, InputChans, sizeof(cmsToneCurve*));
4036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (GammaTables == NULL) return NULL;
4037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ReadPositionTable(self, io, InputChans, BaseOffset, GammaTables, ReadMPECurve)) {
4039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = cmsStageAllocToneCurves(self ->ContextID, InputChans, GammaTables);
4041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
4043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        mpe = NULL;
4044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < InputChans; i++) {
4047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (GammaTables[i]) cmsFreeToneCurve(GammaTables[i]);
4048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, GammaTables);
4051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = (mpe != NULL) ? 1 : 0;
4052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return mpe;
4053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
4055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Write a single segmented curve. NO CHECK IS PERFORMED ON VALIDITY
4059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4060ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteSegmentedCurve(cmsIOHANDLER* io, cmsToneCurve* g)
4061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, j;
4063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsCurveSegment* Segments = g ->Segments;
4064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nSegments = g ->nSegments;
4065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, cmsSigSegmentedCurve)) goto Error;
4067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, 0)) goto Error;
4068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) nSegments)) goto Error;
4069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, 0)) goto Error;
4070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the break-points
4072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nSegments - 1; i++) {
4073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteFloat32Number(io, Segments[i].x1)) goto Error;
4074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the segments
4077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < g ->nSegments; i++) {
4078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsCurveSegment* ActualSeg = Segments + i;
4080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (ActualSeg -> Type == 0) {
4082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // This is a sampled curve
4084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigSampledCurveSeg)) goto Error;
4085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt32Number(io, 0)) goto Error;
4086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt32Number(io, ActualSeg -> nGridPoints)) goto Error;
4087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (j=0; j < g ->Segments[i].nGridPoints; j++) {
4089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsWriteFloat32Number(io, ActualSeg -> SampledPoints[j])) goto Error;
4090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
4091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
4094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            int Type;
4095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cmsUInt32Number ParamsByType[] = { 4, 5, 5 };
4096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // This is a formula-based
4098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt32Number(io, (cmsUInt32Number) cmsSigFormulaCurveSeg)) goto Error;
4099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt32Number(io, 0)) goto Error;
4100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // We only allow 1, 2 and 3 as types
4102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            Type = ActualSeg ->Type - 6;
4103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (Type > 2 || Type < 0) goto Error;
4104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Type)) goto Error;
4106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt16Number(io, 0)) goto Error;
4107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (j=0; j < ParamsByType[Type]; j++) {
4109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) ActualSeg ->Params[j])) goto Error;
4110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
4111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // It seems there is no need to align. Code is here, and for safety commented out
4114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // if (!_cmsWriteAlignment(io)) goto Error;
4115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4119ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
4120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
4121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4125ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteMPECurve(struct _cms_typehandler_struct* self,
4126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      cmsIOHANDLER* io,
4127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      void* Cargo,
4128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      cmsUInt32Number n,
4129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      cmsUInt32Number SizeOfTag)
4130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageToneCurvesData* Curves  = (_cmsStageToneCurvesData*) Cargo;
4132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return WriteSegmentedCurve(io, Curves ->TheCurves[n]);
4134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
4136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
4137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Write a curve, checking first for validity
4140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4141ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_MPEcurve_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number BaseOffset;
4144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* mpe = (cmsStage*) Ptr;
4145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageToneCurvesData* Curves = (_cmsStageToneCurvesData*) mpe ->Data;
4146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the header. Since those are curves, input and output channels are same
4150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WritePositionTable(self, io, 0,
4154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                mpe ->InputChannels, BaseOffset, Curves, WriteMPECurve)) return FALSE;
4155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
4160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// The matrix is organized as an array of PxQ+Q elements, where P is the number of input channels to the
4165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// matrix, and Q is the number of output channels. The matrix elements are each float32Numbers. The array
4166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// is organized as follows:
4167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// array = [e11, e12, ? e1P, e21, e22, ? e2P, ? eQ1, eQ2, ? eQP, e1, e2, ? eQ]
4168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_MPEmatrix_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* mpe;
4173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number   InputChans, OutputChans;
4174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number   nElems, i;
4175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number* Matrix;
4176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFloat64Number* Offsets;
4177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nElems = InputChans * OutputChans;
4183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Input and output chans may be ANY (up to 0xffff)
4185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Matrix = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, nElems, sizeof(cmsFloat64Number));
4186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Matrix == NULL) return NULL;
4187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Offsets = (cmsFloat64Number*) _cmsCalloc(self ->ContextID, OutputChans, sizeof(cmsFloat64Number));
4189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Offsets == NULL) {
4190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(self ->ContextID, Matrix);
4192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
4193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nElems; i++) {
4196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFloat32Number v;
4198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadFloat32Number(io, &v)) return NULL;
4200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Matrix[i] = v;
4201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < OutputChans; i++) {
4205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsFloat32Number v;
4207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadFloat32Number(io, &v)) return NULL;
4209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Offsets[i] = v;
4210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mpe = cmsStageAllocMatrix(self ->ContextID, OutputChans, InputChans, Matrix, Offsets);
4214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Matrix);
4215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Offsets);
4216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
4218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return mpe;
4220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
4222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4225ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_MPEmatrix_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, nElems;
4228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* mpe = (cmsStage*) Ptr;
4229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageMatrixData* Matrix = (_cmsStageMatrixData*) mpe ->Data;
4230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
4233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nElems = mpe ->InputChannels * mpe ->OutputChannels;
4235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nElems; i++) {
4237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Double[i])) return FALSE;
4238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < mpe ->OutputChannels; i++) {
4242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Matrix ->Offset == NULL) {
4244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (!_cmsWriteFloat32Number(io, 0)) return FALSE;
4246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
4248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               if (!_cmsWriteFloat32Number(io, (cmsFloat32Number) Matrix->Offset[i])) return FALSE;
4249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
4255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
4256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* mpe = NULL;
4264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number InputChans, OutputChans;
4265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number Dimensions8[16];
4266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS];
4267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageCLutData* clut;
4268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (InputChans == 0) goto Error;
4273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (OutputChans == 0) goto Error;
4274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
4276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        goto Error;
4277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number
4279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? MAX_INPUT_DIMENSIONS : InputChans;
4280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < nMaxGrids; i++) GridPoints[i] = (cmsUInt32Number) Dimensions8[i];
4281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Allocate the true CLUT
4283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
4284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe == NULL) goto Error;
4285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read the data
4287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    clut = (_cmsStageCLutData*) mpe ->Data;
4288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < clut ->nEntries; i++) {
4289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error;
4291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
4294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return mpe;
4295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4296ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
4297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
4298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe != NULL) cmsStageFree(mpe);
4299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
4300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
4302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Write a CLUT in floating point
4305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4306ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt8Number Dimensions8[16];
4309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
4310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* mpe = (cmsStage*) Ptr;
4311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data;
4312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check for maximum number of channels
4314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (mpe -> InputChannels > 15) return FALSE;
4315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Only floats are supported in MPE
4317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (clut ->HasFloatValues == FALSE) return FALSE;
4318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
4321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(Dimensions8, 0, sizeof(Dimensions8));
4323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < mpe ->InputChannels; i++)
4325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i];
4326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Write(io, 16, Dimensions8)) return FALSE;
4328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < clut ->nEntries; i++) {
4330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE;
4332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
4337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
4338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is the list of built-in MPE types
4343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic _cmsTagTypeLinkedList SupportedMPEtypes[] = {
4344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{{ (cmsTagTypeSignature) cmsSigBAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[1] },   // Ignore those elements for now
4346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{{ (cmsTagTypeSignature) cmsSigEAcsElemType, NULL, NULL, NULL, NULL, NULL, 0 }, &SupportedMPEtypes[2] },   // (That's what the spec says)
4347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCurveSetElemType,     MPEcurve),      &SupportedMPEtypes[3] },
4349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigMatrixElemType,       MPEmatrix),     &SupportedMPEtypes[4] },
4350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_MPE_HANDLER((cmsTagTypeSignature) cmsSigCLutElemType,         MPEclut),        NULL },
4351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
4352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsTagTypePluginChunkType _cmsMPETypePluginChunk = { NULL };
4354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4356ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadMPEElem(struct _cms_typehandler_struct* self,
4357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsIOHANDLER* io,
4358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    void* Cargo,
4359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsUInt32Number n,
4360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    cmsUInt32Number SizeOfTag)
4361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStageSignature ElementSig;
4363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsTagTypeHandler* TypeHandler;
4364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nItems;
4365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline *NewLUT = (cmsPipeline *) Cargo;
4366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagTypePluginChunkType* MPETypePluginChunk  = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);
4367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Take signature and channels for each element.
4370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, (cmsUInt32Number*) &ElementSig)) return FALSE;
4371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // The reserved placeholder
4373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, NULL)) return FALSE;
4374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read diverse MPE types
4376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk ->TagTypes, SupportedMPEtypes);
4377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (TypeHandler == NULL)  {
4378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        char String[5];
4380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
4382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // An unknown element was found.
4384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsSignalError(self ->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown MPE type '%s' found.", String);
4385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
4386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // If no read method, just ignore the element (valid for cmsSigBAcsElemType and cmsSigEAcsElemType)
4389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read the MPE. No size is given
4390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (TypeHandler ->ReadPtr != NULL) {
4391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // This is a real element which should be read and processed
4393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!cmsPipelineInsertStage(NewLUT, cmsAT_END, (cmsStage*) TypeHandler ->ReadPtr(self, io, &nItems, SizeOfTag)))
4394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            return FALSE;
4395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
4400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
4401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is the main dispatcher for MPE
4405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_MPE_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt16Number InputChans, OutputChans;
4409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number ElementCount;
4410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline *NewLUT = NULL;
4411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number BaseOffset;
4412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get actual position as a basis for element offsets
4414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read channels and element count
4417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Allocates an empty LUT
4421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewLUT = cmsPipelineAlloc(self ->ContextID, InputChans, OutputChans);
4422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewLUT == NULL) return NULL;
4423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &ElementCount)) return NULL;
4425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadPositionTable(self, io, ElementCount, BaseOffset, NewLUT, ReadMPEElem)) {
4427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (NewLUT != NULL) cmsPipelineFree(NewLUT);
4428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *nItems = 0;
4429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return NULL;
4430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Success
4433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 1;
4434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NewLUT;
4435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(SizeOfTag);
4437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This one is a liitle bit more complex, so we don't use position tables this time.
4442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4443ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_MPE_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, BaseOffset, DirectoryPos, CurrentPos;
4446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    int inputChan, outputChan;
4447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number ElemCount;
4448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL, Before;
4449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStageSignature ElementSig;
4450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipeline* Lut = (cmsPipeline*) Ptr;
4451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsStage* Elem = Lut ->Elements;
4452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsTagTypeHandler* TypeHandler;
4453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagTypePluginChunkType* MPETypePluginChunk  = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(self->ContextID, MPEPlugin);
4454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
4456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    inputChan  = cmsPipelineInputChannels(Lut);
4458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    outputChan = cmsPipelineOutputChannels(Lut);
4459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ElemCount  = cmsPipelineStageCount(Lut);
4460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ElementOffsets = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
4462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets == NULL) goto Error;
4463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ElementSizes = (cmsUInt32Number *) _cmsCalloc(self ->ContextID, ElemCount, sizeof(cmsUInt32Number));
4465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes == NULL) goto Error;
4466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the head
4468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) inputChan)) goto Error;
4469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) outputChan)) goto Error;
4470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, (cmsUInt16Number) ElemCount)) goto Error;
4471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    DirectoryPos = io ->Tell(io);
4473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write a fake directory to be filled latter on
4475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < ElemCount; i++) {
4476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // Offset
4477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // size
4478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write each single tag. Keep track of the size as well.
4481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < ElemCount; i++) {
4482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ElementOffsets[i] = io ->Tell(io) - BaseOffset;
4484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ElementSig = Elem ->Type;
4486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        TypeHandler = GetHandler((cmsTagTypeSignature) ElementSig, MPETypePluginChunk->TagTypes, SupportedMPEtypes);
4488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (TypeHandler == NULL)  {
4489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                char String[5];
4491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                _cmsTagSignature2String(String, (cmsTagSignature) ElementSig);
4493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 // An unknow element was found.
4495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Found unknown MPE type '%s'", String);
4496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 goto Error;
4497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, ElementSig)) goto Error;
4500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, 0)) goto Error;
4501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Before = io ->Tell(io);
4502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!TypeHandler ->WritePtr(self, io, Elem, 1)) goto Error;
4503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteAlignment(io)) goto Error;
4504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ElementSizes[i] = io ->Tell(io) - Before;
4506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Elem = Elem ->Next;
4508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the directory
4511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CurrentPos = io ->Tell(io);
4512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, DirectoryPos)) goto Error;
4514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < ElemCount; i++) {
4516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, ElementOffsets[i])) goto Error;
4517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, ElementSizes[i])) goto Error;
4518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4519ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, CurrentPos)) goto Error;
4521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
4523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
4524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4526ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
4527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementOffsets != NULL) _cmsFree(self ->ContextID, ElementOffsets);
4528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (ElementSizes != NULL) _cmsFree(self ->ContextID, ElementSizes);
4529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
4530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
4532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_MPE_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
4537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) cmsPipelineDup((cmsPipeline*) Ptr);
4539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
4541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
4542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4544ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_MPE_Free(struct _cms_typehandler_struct* self, void *Ptr)
4546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPipelineFree((cmsPipeline*) Ptr);
4548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return;
4549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
4551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
4555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigVcgtType
4556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
4557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define cmsVideoCardGammaTableType    0
4560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define cmsVideoCardGammaFormulaType  1
4561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Used internally
4563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct {
4564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    double Gamma;
4565ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    double Min;
4566ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    double Max;
4567ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} _cmsVCGTGAMMA;
4568ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4569ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4570ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4571ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_vcgt_Read(struct _cms_typehandler_struct* self,
4572ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     cmsIOHANDLER* io,
4573ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     cmsUInt32Number* nItems,
4574ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                     cmsUInt32Number SizeOfTag)
4575ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4576ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number TagType, n, i;
4577ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve** Curves;
4578ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4579ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
4580ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4581ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read tag type
4582ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &TagType)) return NULL;
4583ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4584ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Allocate space for the array
4585ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Curves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*));
4586ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Curves == NULL) return NULL;
4587ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4588ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // There are two possible flavors
4589ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    switch (TagType) {
4590ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4591ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Gamma is stored as a table
4592ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    case cmsVideoCardGammaTableType:
4593ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
4594ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       cmsUInt16Number nChannels, nElems, nBytes;
4595ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4596ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       // Check channel count, which should be 3 (we don't support monochrome this time)
4597ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       if (!_cmsReadUInt16Number(io, &nChannels)) goto Error;
4598ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4599ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       if (nChannels != 3) {
4600ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported number of channels for VCGT '%d'", nChannels);
4601ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           goto Error;
4602ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
4603ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4604ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       // Get Table element count and bytes per element
4605ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       if (!_cmsReadUInt16Number(io, &nElems)) goto Error;
4606ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       if (!_cmsReadUInt16Number(io, &nBytes)) goto Error;
4607ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4608ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       // Adobe's quirk fixup. Fixing broken profiles...
4609ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       if (nElems == 256 && nBytes == 1 && SizeOfTag == 1576)
4610ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           nBytes = 2;
4611ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4612ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4613ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       // Populate tone curves
4614ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (n=0; n < 3; n++) {
4615ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4616ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Curves[n] = cmsBuildTabulatedToneCurve16(self ->ContextID, nElems, NULL);
4617ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (Curves[n] == NULL) goto Error;
4618ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4619ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           // On depending on byte depth
4620ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           switch (nBytes) {
4621ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4622ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           // One byte, 0..255
4623ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 1:
4624ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               for (i=0; i < nElems; i++) {
4625ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4626ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                   cmsUInt8Number v;
4627ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4628ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      if (!_cmsReadUInt8Number(io, &v)) goto Error;
4629ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      Curves[n] ->Table16[i] = FROM_8_TO_16(v);
4630ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               }
4631ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               break;
4632ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4633ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           // One word 0..65535
4634ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           case 2:
4635ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              if (!_cmsReadUInt16Array(io, nElems, Curves[n]->Table16)) goto Error;
4636ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              break;
4637ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4638ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          // Unsupported
4639ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           default:
4640ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported bit depth for VCGT '%d'", nBytes * 8);
4641ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov              goto Error;
4642ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           }
4643ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       } // For all 3 channels
4644ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4645ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    break;
4646ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4647ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   // In this case, gamma is stored as a formula
4648ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   case cmsVideoCardGammaFormulaType:
4649ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   {
4650ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       _cmsVCGTGAMMA Colorant[3];
4651ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4652ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Populate tone curves
4653ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       for (n=0; n < 3; n++) {
4654ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4655ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           double Params[10];
4656ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4657ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Gamma)) goto Error;
4658ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Min)) goto Error;
4659ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (!_cmsRead15Fixed16Number(io, &Colorant[n].Max)) goto Error;
4660ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4661ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // Parametric curve type 5 is:
4662ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // Y = (aX + b)^Gamma + e | X >= d
4663ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // Y = cX + f             | X < d
4664ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4665ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // vcgt formula is:
4666ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // Y = (Max ?Min) * (X ^ Gamma) + Min
4667ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4668ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // So, the translation is
4669ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // a = (Max ?Min) ^ ( 1 / Gamma)
4670ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // e = Min
4671ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // b=c=d=f=0
4672ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4673ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Params[0] = Colorant[n].Gamma;
4674ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Params[1] = pow((Colorant[n].Max - Colorant[n].Min), (1.0 / Colorant[n].Gamma));
4675ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Params[2] = 0;
4676ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Params[3] = 0;
4677ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Params[4] = 0;
4678ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Params[5] = Colorant[n].Min;
4679ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Params[6] = 0;
4680ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4681ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Curves[n] = cmsBuildParametricToneCurve(self ->ContextID, 5, Params);
4682ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (Curves[n] == NULL) goto Error;
4683ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       }
4684ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   }
4685ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   break;
4686ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4687ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   // Unsupported
4688ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   default:
4689ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unsupported tag type for VCGT '%d'", TagType);
4690ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      goto Error;
4691ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   }
4692ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4693ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *nItems = 1;
4694ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   return (void*) Curves;
4695ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4696ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Regret,  free all resources
4697ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
4698ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4699ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeToneCurveTriple(Curves);
4700ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Curves);
4701ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
4702ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4703ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     cmsUNUSED_PARAMETER(SizeOfTag);
4704ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4705ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4706ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4707ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// We don't support all flavors, only 16bits tables and formula
4708ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4709ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_vcgt_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4710ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4711ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve** Curves =  (cmsToneCurve**) Ptr;
4712ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, j;
4713ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4714ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (cmsGetToneCurveParametricType(Curves[0]) == 5 &&
4715ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsGetToneCurveParametricType(Curves[1]) == 5 &&
4716ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        cmsGetToneCurveParametricType(Curves[2]) == 5) {
4717ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4718ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaFormulaType)) return FALSE;
4719ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4720ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            // Save parameters
4721ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (i=0; i < 3; i++) {
4722ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4723ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                _cmsVCGTGAMMA v;
4724ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4725ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                v.Gamma = Curves[i] ->Segments[0].Params[0];
4726ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                v.Min   = Curves[i] ->Segments[0].Params[5];
4727ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                v.Max   = pow(Curves[i] ->Segments[0].Params[1], v.Gamma) + v.Min;
4728ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4729ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsWrite15Fixed16Number(io, v.Gamma)) return FALSE;
4730ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsWrite15Fixed16Number(io, v.Min)) return FALSE;
4731ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsWrite15Fixed16Number(io, v.Max)) return FALSE;
4732ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
4733ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4734ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4735ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
4736ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4737ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Always store as a table of 256 words
4738ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt32Number(io, cmsVideoCardGammaTableType)) return FALSE;
4739ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, 3)) return FALSE;
4740ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, 256)) return FALSE;
4741ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!_cmsWriteUInt16Number(io, 2)) return FALSE;
4742ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4743ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        for (i=0; i < 3; i++) {
4744ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            for (j=0; j < 256; j++) {
4745ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4746ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmsFloat32Number v = cmsEvalToneCurveFloat(Curves[i], (cmsFloat32Number) (j / 255.0));
4747ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                cmsUInt16Number  n = _cmsQuickSaturateWord(v * 65535.0);
4748ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4749ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (!_cmsWriteUInt16Number(io, n)) return FALSE;
4750ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            }
4751ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4752ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4753ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4754ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4755ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4756ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
4757ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
4758ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4759ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4760ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4761ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_vcgt_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
4762ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4763ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve** OldCurves =  (cmsToneCurve**) Ptr;
4764ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsToneCurve** NewCurves;
4765ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4766ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewCurves = ( cmsToneCurve**) _cmsCalloc(self ->ContextID, 3, sizeof(cmsToneCurve*));
4767ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (NewCurves == NULL) return NULL;
4768ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4769ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewCurves[0] = cmsDupToneCurve(OldCurves[0]);
4770ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewCurves[1] = cmsDupToneCurve(OldCurves[1]);
4771ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    NewCurves[2] = cmsDupToneCurve(OldCurves[2]);
4772ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4773ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*) NewCurves;
4774ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4775ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
4776ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4777ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4778ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4779ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4780ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_vcgt_Free(struct _cms_typehandler_struct* self, void* Ptr)
4781ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4782ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsFreeToneCurveTriple((cmsToneCurve**) Ptr);
4783ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsFree(self ->ContextID, Ptr);
4784ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4785ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4786ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4787ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
4788ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type cmsSigDictType
4789ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
4790ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4791ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Single column of the table can point to wchar or MLUC elements. Holds arrays of data
4792ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct {
4793ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsContext ContextID;
4794ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number *Offsets;
4795ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number *Sizes;
4796ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} _cmsDICelem;
4797ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4798ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct {
4799ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsDICelem Name, Value, DisplayName, DisplayValue;
4800ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4801ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} _cmsDICarray;
4802ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4803ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Allocate an empty array element
4804ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4805ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool AllocElem(cmsContext ContextID, _cmsDICelem* e,  cmsUInt32Number Count)
4806ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4807ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    e->Offsets = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number));
4808ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (e->Offsets == NULL) return FALSE;
4809ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4810ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    e->Sizes = (cmsUInt32Number *) _cmsCalloc(ContextID, Count, sizeof(cmsUInt32Number));
4811ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (e->Sizes == NULL) {
4812ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4813ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        _cmsFree(ContextID, e -> Offsets);
4814ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return FALSE;
4815ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4816ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4817ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    e ->ContextID = ContextID;
4818ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4819ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4820ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4821ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Free an array element
4822ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4823ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid FreeElem(_cmsDICelem* e)
4824ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4825ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (e ->Offsets != NULL)  _cmsFree(e -> ContextID, e -> Offsets);
4826ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (e ->Sizes   != NULL)  _cmsFree(e -> ContextID, e -> Sizes);
4827ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    e->Offsets = e ->Sizes = NULL;
4828ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4829ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4830ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Get rid of whole array
4831ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4832ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid FreeArray( _cmsDICarray* a)
4833ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4834ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (a ->Name.Offsets != NULL) FreeElem(&a->Name);
4835ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (a ->Value.Offsets != NULL) FreeElem(&a ->Value);
4836ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (a ->DisplayName.Offsets != NULL) FreeElem(&a->DisplayName);
4837ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (a ->DisplayValue.Offsets != NULL) FreeElem(&a ->DisplayValue);
4838ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4839ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4840ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4841ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Allocate whole array
4842ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4843ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool AllocArray(cmsContext ContextID, _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length)
4844ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4845ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Empty values
4846ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    memset(a, 0, sizeof(_cmsDICarray));
4847ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4848ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // On depending on record size, create column arrays
4849ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!AllocElem(ContextID, &a ->Name, Count)) goto Error;
4850ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!AllocElem(ContextID, &a ->Value, Count)) goto Error;
4851ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4852ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Length > 16) {
4853ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!AllocElem(ContextID, &a -> DisplayName, Count)) goto Error;
4854ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4855ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4856ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Length > 24) {
4857ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!AllocElem(ContextID, &a ->DisplayValue, Count)) goto Error;
4858ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4859ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4860ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4861ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
4862ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FreeArray(a);
4863ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
4864ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4865ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4866ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Read one element
4867ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4868ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadOneElem(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, cmsUInt32Number BaseOffset)
4869ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4870ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &e->Offsets[i])) return FALSE;
4871ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &e ->Sizes[i])) return FALSE;
4872ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4873ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // An offset of zero has special meaning and shal be preserved
4874ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (e ->Offsets[i] > 0)
4875ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        e ->Offsets[i] += BaseOffset;
4876ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4877ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4878ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4879ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4880ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4881ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadOffsetArray(cmsIOHANDLER* io,  _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length, cmsUInt32Number BaseOffset)
4882ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4883ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
4884ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4885ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read column arrays
4886ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
4887ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4888ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!ReadOneElem(io, &a -> Name, i, BaseOffset)) return FALSE;
4889ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!ReadOneElem(io, &a -> Value, i, BaseOffset)) return FALSE;
4890ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4891ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Length > 16) {
4892ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4893ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!ReadOneElem(io, &a ->DisplayName, i, BaseOffset)) return FALSE;
4894ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4895ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4896ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4897ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Length > 24) {
4898ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4899ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!ReadOneElem(io, & a -> DisplayValue, i, BaseOffset)) return FALSE;
4900ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4901ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4902ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4903ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4904ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4905ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4906ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Write one element
4907ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4908ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteOneElem(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i)
4909ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4910ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, e->Offsets[i])) return FALSE;
4911ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, e ->Sizes[i])) return FALSE;
4912ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4913ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4914ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4915ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4916ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4917ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteOffsetArray(cmsIOHANDLER* io,  _cmsDICarray* a, cmsUInt32Number Count, cmsUInt32Number Length)
4918ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4919ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i;
4920ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4921ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
4922ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4923ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteOneElem(io, &a -> Name, i)) return FALSE;
4924ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteOneElem(io, &a -> Value, i))  return FALSE;
4925ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4926ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Length > 16) {
4927ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4928ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!WriteOneElem(io, &a -> DisplayName, i))  return FALSE;
4929ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4930ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4931ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Length > 24) {
4932ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4933ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!WriteOneElem(io, &a -> DisplayValue, i))  return FALSE;
4934ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
4935ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4936ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4937ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
4938ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4939ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4940ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4941ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadOneWChar(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, wchar_t ** wcstr)
4942ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4943ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4944ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nChars;
4945ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4946ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      // Special case for undefined strings (see ICC Votable
4947ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      // Proposal Submission, Dictionary Type and Metadata TAG Definition)
4948ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (e -> Offsets[i] == 0) {
4949ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4950ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          *wcstr = NULL;
4951ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return TRUE;
4952ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
4953ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4954ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
4955ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4956ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      nChars = e ->Sizes[i] / sizeof(cmsUInt16Number);
4957ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4958ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4959ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      *wcstr = (wchar_t*) _cmsMallocZero(e ->ContextID, (nChars + 1) * sizeof(wchar_t));
4960ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (*wcstr == NULL) return FALSE;
4961ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4962ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if (!_cmsReadWCharArray(io, nChars, *wcstr)) {
4963ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          _cmsFree(e ->ContextID, *wcstr);
4964ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov          return FALSE;
4965ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
4966ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4967ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      // End of string marker
4968ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      (*wcstr)[nChars] = 0;
4969ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return TRUE;
4970ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4971ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4972ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4973ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsUInt32Number mywcslen(const wchar_t *s)
4974ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4975ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const wchar_t *p;
4976ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4977ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p = s;
4978ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while (*p)
4979ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        p++;
4980ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4981ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (cmsUInt32Number)(p - s);
4982ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
4983ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4984ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
4985ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteOneWChar(cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, const wchar_t * wcstr, cmsUInt32Number BaseOffset)
4986ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
4987ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Before = io ->Tell(io);
4988ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number n;
4989ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4990ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    e ->Offsets[i] = Before - BaseOffset;
4991ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4992ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (wcstr == NULL) {
4993ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        e ->Sizes[i] = 0;
4994ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        e ->Offsets[i] = 0;
4995ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
4996ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
4997ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
4998ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    n = mywcslen(wcstr);
4999ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteWCharArray(io,  n, wcstr)) return FALSE;
5000ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5001ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    e ->Sizes[i] = io ->Tell(io) - Before;
5002ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
5003ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5004ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5005ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
5006ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool ReadOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, cmsMLU** mlu)
5007ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5008ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number nItems = 0;
5009ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5010ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // A way to get null MLUCs
5011ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (e -> Offsets[i] == 0 || e ->Sizes[i] == 0) {
5012ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5013ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        *mlu = NULL;
5014ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
5015ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5016ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5017ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
5018ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5019ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, e ->Sizes[i]);
5020ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return *mlu != NULL;
5021ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5022ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5023ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
5024ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, const cmsMLU* mlu, cmsUInt32Number BaseOffset)
5025ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5026ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number Before;
5027ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5028ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     // Special case for undefined strings (see ICC Votable
5029ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     // Proposal Submission, Dictionary Type and Metadata TAG Definition)
5030ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     if (mlu == NULL) {
5031ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        e ->Sizes[i] = 0;
5032ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        e ->Offsets[i] = 0;
5033ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
5034ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5035ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5036ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Before = io ->Tell(io);
5037ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    e ->Offsets[i] = Before - BaseOffset;
5038ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5039ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!Type_MLU_Write(self, io, (void*) mlu, 1)) return FALSE;
5040ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5041ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    e ->Sizes[i] = io ->Tell(io) - Before;
5042ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
5043ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5044ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5045ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5046ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
5047ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
5048ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5049ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsHANDLE hDict;
5050ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsUInt32Number i, Count, Length;
5051ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsUInt32Number BaseOffset;
5052ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsDICarray a;
5053ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   wchar_t *NameWCS = NULL, *ValueWCS = NULL;
5054ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsMLU *DisplayNameMLU = NULL, *DisplayValueMLU=NULL;
5055ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsBool rc;
5056ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5057ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *nItems = 0;
5058ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5059ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get actual position as a basis for element offsets
5060ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
5061ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5062ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get name-value record count
5063ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Count)) return NULL;
5064ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= sizeof(cmsUInt32Number);
5065ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5066ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Get rec length
5067ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsReadUInt32Number(io, &Length)) return NULL;
5068ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    SizeOfTag -= sizeof(cmsUInt32Number);
5069ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5070ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Check for valid lengths
5071ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Length != 16 && Length != 24 && Length != 32) {
5072ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "Unknown record length in dictionary '%d'", Length);
5073ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov         return NULL;
5074ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5075ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5076ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Creates an empty dictionary
5077ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hDict = cmsDictAlloc(self -> ContextID);
5078ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (hDict == NULL) return NULL;
5079ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5080ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // On depending on record size, create column arrays
5081ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!AllocArray(self -> ContextID, &a, Count, Length)) goto Error;
5082ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5083ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Read column arrays
5084ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!ReadOffsetArray(io, &a, Count, Length, BaseOffset)) goto Error;
5085ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5086ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Seek to each element and read it
5087ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
5088ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5089ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!ReadOneWChar(io, &a.Name, i, &NameWCS)) goto Error;
5090ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!ReadOneWChar(io, &a.Value, i, &ValueWCS)) goto Error;
5091ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5092ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Length > 16) {
5093ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!ReadOneMLUC(self, io, &a.DisplayName, i, &DisplayNameMLU)) goto Error;
5094ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
5095ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5096ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (Length > 24) {
5097ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!ReadOneMLUC(self, io, &a.DisplayValue, i, &DisplayValueMLU)) goto Error;
5098ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
5099ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (NameWCS == NULL || ValueWCS == NULL) {
5101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cmsSignalError(self->ContextID, cmsERROR_CORRUPTION_DETECTED, "Bad dictionary Name/Value");
5103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            rc = FALSE;
5104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
5105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        else {
5106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            rc = cmsDictAddEntry(hDict, NameWCS, ValueWCS, DisplayNameMLU, DisplayValueMLU);
5108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
5109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (NameWCS != NULL) _cmsFree(self ->ContextID, NameWCS);
5111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (ValueWCS != NULL) _cmsFree(self ->ContextID, ValueWCS);
5112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (DisplayNameMLU != NULL) cmsMLUfree(DisplayNameMLU);
5113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (DisplayValueMLU != NULL) cmsMLUfree(DisplayValueMLU);
5114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!rc) goto Error;
5116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   FreeArray(&a);
5119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   *nItems = 1;
5120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   return (void*) hDict;
5121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5122ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
5123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   FreeArray(&a);
5124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   cmsDictFree(hDict);
5125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   return NULL;
5126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
5130ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool Type_Dictionary_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
5131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsHANDLE hDict = (cmsHANDLE) Ptr;
5133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const cmsDICTentry* p;
5134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsBool AnyName, AnyValue;
5135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number i, Count, Length;
5136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUInt32Number DirectoryPos, CurrentPos, BaseOffset;
5137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsDICarray a;
5138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (hDict == NULL) return FALSE;
5140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    BaseOffset = io ->Tell(io) - sizeof(_cmsTagBase);
5142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Let's inspect the dictionary
5144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Count = 0; AnyName = FALSE; AnyValue = FALSE;
5145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (p = cmsDictGetEntryList(hDict); p != NULL; p = cmsDictNextEntry(p)) {
5146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p ->DisplayName != NULL) AnyName = TRUE;
5148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p ->DisplayValue != NULL) AnyValue = TRUE;
5149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        Count++;
5150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Length = 16;
5153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (AnyName)  Length += 8;
5154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (AnyValue) Length += 8;
5155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, Count)) return FALSE;
5157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!_cmsWriteUInt32Number(io, Length)) return FALSE;
5158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Keep starting position of offsets table
5160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    DirectoryPos = io ->Tell(io);
5161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Allocate offsets array
5163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!AllocArray(self ->ContextID, &a, Count, Length)) goto Error;
5164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write a fake directory to be filled latter on
5166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WriteOffsetArray(io, &a, Count, Length)) goto Error;
5167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write each element. Keep track of the size as well.
5169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    p = cmsDictGetEntryList(hDict);
5170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (i=0; i < Count; i++) {
5171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteOneWChar(io, &a.Name, i,  p ->Name, BaseOffset)) goto Error;
5173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (!WriteOneWChar(io, &a.Value, i, p ->Value, BaseOffset)) goto Error;
5174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p ->DisplayName != NULL) {
5176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!WriteOneMLUC(self, io, &a.DisplayName, i, p ->DisplayName, BaseOffset)) goto Error;
5177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
5178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        if (p ->DisplayValue != NULL) {
5180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            if (!WriteOneMLUC(self, io, &a.DisplayValue, i, p ->DisplayValue, BaseOffset)) goto Error;
5181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        }
5182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       p = cmsDictNextEntry(p);
5184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Write the directory
5187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    CurrentPos = io ->Tell(io);
5188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, DirectoryPos)) goto Error;
5189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!WriteOffsetArray(io, &a, Count, Length)) goto Error;
5191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (!io ->Seek(io, CurrentPos)) goto Error;
5193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FreeArray(&a);
5195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
5196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5197ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovError:
5198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FreeArray(&a);
5199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FALSE;
5200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(nItems);
5202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
5206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid* Type_Dictionary_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
5207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (void*)  cmsDictDup((cmsHANDLE) Ptr);
5209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(n);
5211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
5212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
5216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid Type_Dictionary_Free(struct _cms_typehandler_struct* self, void* Ptr)
5217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsDictFree((cmsHANDLE) Ptr);
5219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsUNUSED_PARAMETER(self);
5220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
5224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Type support main routines
5225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
5226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is the list of built-in types
5229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic _cmsTagTypeLinkedList SupportedTagTypes[] = {
5230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigChromaticityType,          Chromaticity),        &SupportedTagTypes[1] },
5232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigColorantOrderType,         ColorantOrderType),   &SupportedTagTypes[2] },
5233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigS15Fixed16ArrayType,       S15Fixed16),          &SupportedTagTypes[3] },
5234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigU16Fixed16ArrayType,       U16Fixed16),          &SupportedTagTypes[4] },
5235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigTextType,                  Text),                &SupportedTagTypes[5] },
5236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigTextDescriptionType,       Text_Description),    &SupportedTagTypes[6] },
5237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigCurveType,                 Curve),               &SupportedTagTypes[7] },
5238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigParametricCurveType,       ParametricCurve),     &SupportedTagTypes[8] },
5239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigDateTimeType,              DateTime),            &SupportedTagTypes[9] },
5240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigLut8Type,                  LUT8),                &SupportedTagTypes[10] },
5241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigLut16Type,                 LUT16),               &SupportedTagTypes[11] },
5242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigColorantTableType,         ColorantTable),       &SupportedTagTypes[12] },
5243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigNamedColor2Type,           NamedColor),          &SupportedTagTypes[13] },
5244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU),                 &SupportedTagTypes[14] },
5245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigProfileSequenceDescType,   ProfileSequenceDesc), &SupportedTagTypes[15] },
5246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigSignatureType,             Signature),           &SupportedTagTypes[16] },
5247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigMeasurementType,           Measurement),         &SupportedTagTypes[17] },
5248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigDataType,                  Data),                &SupportedTagTypes[18] },
5249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigLutAtoBType,               LUTA2B),              &SupportedTagTypes[19] },
5250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigLutBtoAType,               LUTB2A),              &SupportedTagTypes[20] },
5251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigUcrBgType,                 UcrBg),               &SupportedTagTypes[21] },
5252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigCrdInfoType,               CrdInfo),             &SupportedTagTypes[22] },
5253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigMultiProcessElementType,   MPE),                 &SupportedTagTypes[23] },
5254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigScreeningType,             Screening),           &SupportedTagTypes[24] },
5255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigViewingConditionsType,     ViewingConditions),   &SupportedTagTypes[25] },
5256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigXYZType,                   XYZ),                 &SupportedTagTypes[26] },
5257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsCorbisBrokenXYZtype,          XYZ),                 &SupportedTagTypes[27] },
5258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsMonacoBrokenCurveType,        Curve),               &SupportedTagTypes[28] },
5259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigProfileSequenceIdType,     ProfileSequenceId),   &SupportedTagTypes[29] },
5260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigDictType,                  Dictionary),          &SupportedTagTypes[30] },
5261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{TYPE_HANDLER(cmsSigVcgtType,                  vcgt),                NULL }
5262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
5263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsTagTypePluginChunkType _cmsTagTypePluginChunk = { NULL };
5266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Duplicates the zone of memory used by the plug-in in the new context
5270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
5271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid DupTagTypeList(struct _cmsContext_struct* ctx,
5272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    const struct _cmsContext_struct* src,
5273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    int loc)
5274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTagTypePluginChunkType newHead = { NULL };
5276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTagTypeLinkedList*  entry;
5277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTagTypeLinkedList*  Anterior = NULL;
5278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc];
5279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   // Walk the list copying all nodes
5281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   for (entry = head->TagTypes;
5282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       entry != NULL;
5283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       entry = entry ->Next) {
5284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           _cmsTagTypeLinkedList *newEntry = ( _cmsTagTypeLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagTypeLinkedList));
5286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (newEntry == NULL)
5288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               return;
5289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           // We want to keep the linked list order, so this is a little bit tricky
5291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           newEntry -> Next = NULL;
5292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (Anterior)
5293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               Anterior -> Next = newEntry;
5294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Anterior = newEntry;
5296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (newHead.TagTypes == NULL)
5298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               newHead.TagTypes = newEntry;
5299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   }
5300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   ctx ->chunks[loc] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagTypePluginChunkType));
5302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocTagTypePluginChunk(struct _cmsContext_struct* ctx,
5306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                 const struct _cmsContext_struct* src)
5307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src != NULL) {
5309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Duplicate the LIST
5311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        DupTagTypeList(ctx, src, TagTypePlugin);
5312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
5314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL };
5315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ctx ->chunks[TagTypePlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType));
5316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocMPETypePluginChunk(struct _cmsContext_struct* ctx,
5320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                               const struct _cmsContext_struct* src)
5321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src != NULL) {
5323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        // Duplicate the LIST
5325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        DupTagTypeList(ctx, src, MPEPlugin);
5326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
5328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        static _cmsTagTypePluginChunkType TagTypePluginChunk = { NULL };
5329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ctx ->chunks[MPEPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagTypePluginChunk, sizeof(_cmsTagTypePluginChunkType));
5330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Both kind of plug-ins share same structure
5336ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  _cmsRegisterTagTypePlugin(cmsContext id, cmsPluginBase* Data)
5337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return RegisterTypesPlugin(id, Data, TagTypePlugin);
5339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5341ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  _cmsRegisterMultiProcessElementPlugin(cmsContext id, cmsPluginBase* Data)
5342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return RegisterTypesPlugin(id, Data,MPEPlugin);
5344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Wrapper for tag types
5348ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagTypeHandler* _cmsGetTagTypeHandler(cmsContext ContextID, cmsTagTypeSignature sig)
5349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagTypePluginChunkType* ctx = ( _cmsTagTypePluginChunkType*) _cmsContextGetClientChunk(ContextID, TagTypePlugin);
5351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return GetHandler(sig, ctx->TagTypes, SupportedTagTypes);
5353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
5356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Tag support main routines
5357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// ********************************************************************************
5358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovtypedef struct _cmsTagLinkedList_st {
5360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cmsTagSignature Signature;
5362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            cmsTagDescriptor Descriptor;
5363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            struct _cmsTagLinkedList_st* Next;
5364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov} _cmsTagLinkedList;
5366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// This is the list of built-in tags
5368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic _cmsTagLinkedList SupportedTags[] = {
5369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigAToB0Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[1]},
5371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigAToB1Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[2]},
5372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigAToB2Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutAtoBType, cmsSigLut8Type}, DecideLUTtypeA2B}, &SupportedTags[3]},
5373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBToA0Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[4]},
5374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBToA1Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[5]},
5375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBToA2Tag,               { 1, 3,  { cmsSigLut16Type,  cmsSigLutBtoAType, cmsSigLut8Type}, DecideLUTtypeB2A}, &SupportedTags[6]},
5376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    // Allow corbis  and its broken XYZ type
5378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigRedColorantTag,         { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[7]},
5379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigGreenColorantTag,       { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[8]},
5380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBlueColorantTag,        { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, DecideXYZtype}, &SupportedTags[9]},
5381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigRedTRCTag,              { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[10]},
5383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigGreenTRCTag,            { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[11]},
5384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBlueTRCTag,             { 1, 3, { cmsSigCurveType, cmsSigParametricCurveType, cmsMonacoBrokenCurveType }, DecideCurveType}, &SupportedTags[12]},
5385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigCalibrationDateTimeTag, { 1, 1, { cmsSigDateTimeType }, NULL}, &SupportedTags[13]},
5387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigCharTargetTag,          { 1, 1, { cmsSigTextType },     NULL}, &SupportedTags[14]},
5388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigChromaticAdaptationTag, { 9, 1, { cmsSigS15Fixed16ArrayType }, NULL}, &SupportedTags[15]},
5390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigChromaticityTag,        { 1, 1, { cmsSigChromaticityType    }, NULL}, &SupportedTags[16]},
5391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigColorantOrderTag,       { 1, 1, { cmsSigColorantOrderType   }, NULL}, &SupportedTags[17]},
5392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigColorantTableTag,       { 1, 1, { cmsSigColorantTableType   }, NULL}, &SupportedTags[18]},
5393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigColorantTableOutTag,    { 1, 1, { cmsSigColorantTableType   }, NULL}, &SupportedTags[19]},
5394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigCopyrightTag,           { 1, 3, { cmsSigTextType,  cmsSigMultiLocalizedUnicodeType, cmsSigTextDescriptionType}, DecideTextType}, &SupportedTags[20]},
5396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigDateTimeTag,            { 1, 1, { cmsSigDateTimeType }, NULL}, &SupportedTags[21]},
5397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigDeviceMfgDescTag,       { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[22]},
5399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigDeviceModelDescTag,     { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[23]},
5400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigGamutTag,               { 1, 3, { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[24]},
5402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigGrayTRCTag,             { 1, 2, { cmsSigCurveType, cmsSigParametricCurveType }, DecideCurveType}, &SupportedTags[25]},
5404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigLuminanceTag,           { 1, 1, { cmsSigXYZType }, NULL}, &SupportedTags[26]},
5405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigMediaBlackPointTag,     { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, NULL}, &SupportedTags[27]},
5407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigMediaWhitePointTag,     { 1, 2, { cmsSigXYZType, cmsCorbisBrokenXYZtype }, NULL}, &SupportedTags[28]},
5408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigNamedColor2Tag,         { 1, 1, { cmsSigNamedColor2Type }, NULL}, &SupportedTags[29]},
5410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPreview0Tag,            { 1, 3,  { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[30]},
5412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPreview1Tag,            { 1, 3,  { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[31]},
5413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPreview2Tag,            { 1, 3,  { cmsSigLut16Type, cmsSigLutBtoAType, cmsSigLut8Type }, DecideLUTtypeB2A}, &SupportedTags[32]},
5414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigProfileDescriptionTag,  { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[33]},
5416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigProfileSequenceDescTag, { 1, 1, { cmsSigProfileSequenceDescType }, NULL}, &SupportedTags[34]},
5417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigTechnologyTag,          { 1, 1, { cmsSigSignatureType }, NULL},  &SupportedTags[35]},
5418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigColorimetricIntentImageStateTag,   { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[36]},
5420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPerceptualRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[37]},
5421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigSaturationRenderingIntentGamutTag, { 1, 1, { cmsSigSignatureType }, NULL}, &SupportedTags[38]},
5422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigMeasurementTag,         { 1, 1, { cmsSigMeasurementType }, NULL}, &SupportedTags[39]},
5424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPs2CRD0Tag,             { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[40]},
5426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPs2CRD1Tag,             { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[41]},
5427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPs2CRD2Tag,             { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[42]},
5428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPs2CRD3Tag,             { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[43]},
5429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPs2CSATag,              { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[44]},
5430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigPs2RenderingIntentTag,  { 1, 1, { cmsSigDataType }, NULL}, &SupportedTags[45]},
5431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigViewingCondDescTag,     { 1, 3, { cmsSigTextDescriptionType, cmsSigMultiLocalizedUnicodeType, cmsSigTextType}, DecideTextDescType}, &SupportedTags[46]},
5433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigUcrBgTag,               { 1, 1, { cmsSigUcrBgType}, NULL},    &SupportedTags[47]},
5435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigCrdInfoTag,             { 1, 1, { cmsSigCrdInfoType}, NULL},  &SupportedTags[48]},
5436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigDToB0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[49]},
5438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigDToB1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[50]},
5439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigDToB2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[51]},
5440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigDToB3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[52]},
5441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBToD0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[53]},
5442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBToD1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[54]},
5443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBToD2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[55]},
5444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigBToD3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[56]},
5445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigScreeningDescTag,       { 1, 1, { cmsSigTextDescriptionType },    NULL}, &SupportedTags[57]},
5447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigViewingConditionsTag,   { 1, 1, { cmsSigViewingConditionsType },  NULL}, &SupportedTags[58]},
5448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigScreeningTag,           { 1, 1, { cmsSigScreeningType},          NULL }, &SupportedTags[59]},
5450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigVcgtTag,                { 1, 1, { cmsSigVcgtType},               NULL }, &SupportedTags[60]},
5451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigMetaTag,                { 1, 1, { cmsSigDictType},               NULL }, &SupportedTags[61]},
5452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigProfileSequenceIdTag,   { 1, 1, { cmsSigProfileSequenceIdType},  NULL },  &SupportedTags[62]},
5453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL}
5454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
5457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*
5459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    Not supported                 Why
5460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    =======================       =========================================
5461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSigOutputResponseTag   ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT!
5462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSigNamedColorTag       ==> Deprecated
5463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSigDataTag             ==> Ancient, unused
5464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsSigDeviceSettingsTag   ==> Deprecated, useless
5465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov*/
5466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov_cmsTagPluginChunkType _cmsTagPluginChunk = { NULL };
5469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Duplicates the zone of memory used by the plug-in in the new context
5472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovstatic
5473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid DupTagList(struct _cmsContext_struct* ctx,
5474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    const struct _cmsContext_struct* src)
5475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTagPluginChunkType newHead = { NULL };
5477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTagLinkedList*  entry;
5478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTagLinkedList*  Anterior = NULL;
5479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   _cmsTagPluginChunkType* head = (_cmsTagPluginChunkType*) src->chunks[TagPlugin];
5480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   // Walk the list copying all nodes
5482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   for (entry = head->Tag;
5483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       entry != NULL;
5484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov       entry = entry ->Next) {
5485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           _cmsTagLinkedList *newEntry = ( _cmsTagLinkedList *) _cmsSubAllocDup(ctx ->MemPool, entry, sizeof(_cmsTagLinkedList));
5487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (newEntry == NULL)
5489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               return;
5490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           // We want to keep the linked list order, so this is a little bit tricky
5492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           newEntry -> Next = NULL;
5493ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (Anterior)
5494ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               Anterior -> Next = newEntry;
5495ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5496ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           Anterior = newEntry;
5497ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5498ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov           if (newHead.Tag == NULL)
5499ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov               newHead.Tag = newEntry;
5500ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   }
5501ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5502ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov   ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx->MemPool, &newHead, sizeof(_cmsTagPluginChunkType));
5503ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5504ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5505ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvoid _cmsAllocTagPluginChunk(struct _cmsContext_struct* ctx,
5506ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                                 const struct _cmsContext_struct* src)
5507ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5508ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (src != NULL) {
5509ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5510ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        DupTagList(ctx, src);
5511ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5512ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else {
5513ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        static _cmsTagPluginChunkType TagPluginChunk = { NULL };
5514ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        ctx ->chunks[TagPlugin] = _cmsSubAllocDup(ctx ->MemPool, &TagPluginChunk, sizeof(_cmsTagPluginChunkType));
5515ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5516ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5517ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5518ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5519ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsBool  _cmsRegisterTagPlugin(cmsContext id, cmsPluginBase* Data)
5520ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5521ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    cmsPluginTag* Plugin = (cmsPluginTag*) Data;
5522ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagLinkedList *pt;
5523ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(id, TagPlugin);
5524ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5525ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (Data == NULL) {
5526ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5527ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        TagPluginChunk->Tag = NULL;
5528ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        return TRUE;
5529ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5530ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5531ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pt = (_cmsTagLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagLinkedList));
5532ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if (pt == NULL) return FALSE;
5533ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5534ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pt ->Signature  = Plugin ->Signature;
5535ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pt ->Descriptor = Plugin ->Descriptor;
5536ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    pt ->Next       = TagPluginChunk ->Tag;
5537ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5538ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    TagPluginChunk ->Tag = pt;
5539ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5540ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return TRUE;
5541ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5542ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5543ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Return a descriptor for a given tag or NULL
5544ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovcmsTagDescriptor* _cmsGetTagDescriptor(cmsContext ContextID, cmsTagSignature sig)
5545ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov{
5546ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagLinkedList* pt;
5547ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    _cmsTagPluginChunkType* TagPluginChunk = ( _cmsTagPluginChunkType*) _cmsContextGetClientChunk(ContextID, TagPlugin);
5548ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5549ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (pt = TagPluginChunk->Tag;
5550ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             pt != NULL;
5551ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov             pt = pt ->Next) {
5552ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5553ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (sig == pt -> Signature) return &pt ->Descriptor;
5554ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5555ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5556ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for (pt = SupportedTags;
5557ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pt != NULL;
5558ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            pt = pt ->Next) {
5559ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5560ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                if (sig == pt -> Signature) return &pt ->Descriptor;
5561ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
5562ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
5563ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return NULL;
5564ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
5565