< prev index next >

src/java.desktop/share/native/liblcms/cmstypes.c

Print this page




  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 //---------------------------------------------------------------------------------
  31 //
  32 //  Little Color Management System
  33 //  Copyright (c) 1998-2014 Marti Maria Saguer
  34 //
  35 // Permission is hereby granted, free of charge, to any person obtaining
  36 // a copy of this software and associated documentation files (the "Software"),
  37 // to deal in the Software without restriction, including without limitation
  38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39 // and/or sell copies of the Software, and to permit persons to whom the Software
  40 // is furnished to do so, subject to the following conditions:
  41 //
  42 // The above copyright notice and this permission notice shall be included in
  43 // all copies or substantial portions of the Software.
  44 //
  45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52 //
  53 //---------------------------------------------------------------------------------
  54 //
  55 
  56 #include "lcms2_internal.h"
  57 
  58 // Tag Serialization  -----------------------------------------------------------------------------
  59 // This file implements every single tag and tag type as described in the ICC spec. Some types
  60 // have been deprecated, like ncl and Data. There is no implementation for those types as there
  61 // are no profiles holding them. The programmer can also extend this list by defining his own types
  62 // by using the appropiate plug-in. There are three types of plug ins regarding that. First type
  63 // allows to define new tags using any existing type. Next plug-in type allows to define new types
  64 // and the third one is very specific: allows to extend the number of elements in the multiprocessing
  65 // elements special type.
  66 //--------------------------------------------------------------------------------------------------
  67 
  68 // Some broken types
  69 #define cmsCorbisBrokenXYZtype    ((cmsTagTypeSignature) 0x17A505B8)
  70 #define cmsMonacoBrokenCurveType  ((cmsTagTypeSignature) 0x9478ee00)
  71 
  72 // This is the linked list that keeps track of the defined types
  73 typedef struct _cmsTagTypeLinkedList_st {
  74 
  75     cmsTagTypeHandler Handler;
  76     struct _cmsTagTypeLinkedList_st* Next;
  77 
  78 } _cmsTagTypeLinkedList;
  79 
  80 // Some macros to define callbacks.
  81 #define READ_FN(x)  Type_##x##_Read
  82 #define WRITE_FN(x) Type_##x##_Write


 125     _cmsTagTypeLinkedList* pt;
 126 
 127     for (pt = PluginLinkedList;
 128          pt != NULL;
 129          pt = pt ->Next) {
 130 
 131             if (sig == pt -> Handler.Signature) return &pt ->Handler;
 132     }
 133 
 134     for (pt = DefaultLinkedList;
 135          pt != NULL;
 136          pt = pt ->Next) {
 137 
 138             if (sig == pt -> Handler.Signature) return &pt ->Handler;
 139     }
 140 
 141     return NULL;
 142 }
 143 
 144 
 145 // Auxiliar to convert UTF-32 to UTF-16 in some cases
 146 static
 147 cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* Array)
 148 {
 149     cmsUInt32Number i;
 150 
 151     _cmsAssert(io != NULL);
 152     _cmsAssert(!(Array == NULL && n > 0));
 153 
 154     for (i=0; i < n; i++) {
 155         if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Array[i])) return FALSE;
 156     }
 157 
 158     return TRUE;
 159 }
 160 
 161 // Auxiliar to read an array of wchar_t
 162 static
 163 cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array)
 164 {
 165     cmsUInt32Number i;
 166     cmsUInt16Number tmp;
 167 
 168     _cmsAssert(io != NULL);
 169 
 170     for (i=0; i < n; i++) {
 171 
 172         if (Array != NULL) {
 173 
 174             if (!_cmsReadUInt16Number(io, &tmp)) return FALSE;
 175             Array[i] = (wchar_t) tmp;
 176         }
 177         else {
 178             if (!_cmsReadUInt16Number(io, NULL)) return FALSE;
 179         }
 180 
 181     }
 182     return TRUE;
 183 }
 184 
 185 // To deal with position tables
 186 typedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self,
 187                                              cmsIOHANDLER* io,
 188                                              void* Cargo,
 189                                              cmsUInt32Number n,
 190                                              cmsUInt32Number SizeOfTag);
 191 
 192 // Helper function to deal with position tables as decribed in ICC spec 4.3
 193 // A table of n elements is readed, where first comes n records containing offsets and sizes and
 194 // then a block containing the data itself. This allows to reuse same data in more than one entry
 195 static
 196 cmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
 197                               cmsIOHANDLER* io,
 198                               cmsUInt32Number Count,
 199                               cmsUInt32Number BaseOffset,
 200                               void *Cargo,
 201                               PositionTableEntryFn ElementFn)
 202 {
 203     cmsUInt32Number i;
 204     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
 205 
 206     // Let's take the offsets to each element
 207     ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
 208     if (ElementOffsets == NULL) goto Error;
 209 
 210     ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
 211     if (ElementSizes == NULL) goto Error;
 212 


 963 
 964 Done:
 965 
 966     *nItems = 1;
 967     return mlu;
 968 
 969 Error:
 970     if (Text) _cmsFree(self ->ContextID, (void*) Text);
 971     if (mlu) cmsMLUfree(mlu);
 972     return NULL;
 973 }
 974 
 975 
 976 // This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
 977 static
 978 cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 979 {
 980     cmsMLU* mlu = (cmsMLU*) Ptr;
 981     char *Text = NULL;
 982     wchar_t *Wide = NULL;
 983     cmsUInt32Number len, len_aligned, len_filler_alignment;
 984     cmsBool  rc = FALSE;
 985     char Filler[68];
 986 
 987     // Used below for writting zeroes
 988     memset(Filler, 0, sizeof(Filler));
 989 
 990     // Get the len of string
 991     len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
 992 
 993     // From ICC3.4: It has been found that textDescriptionType can contain misaligned data
 994     //(see clause 4.1 for the definition of “aligned”). Because the Unicode language
 995     // code and Unicode count immediately follow the ASCII description, their
 996     // alignment is not correct if the ASCII count is not a multiple of four. The
 997     // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and
 998     // writing software must be written carefully in order to handle these alignment
 999     // problems.
1000 
1001     // Compute an aligned size
1002     len_aligned = _cmsALIGNLONG(len);
1003     len_filler_alignment = len_aligned - len;

1004 
1005     // Null strings
1006     if (len <= 0) {
1007 
1008         Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
1009         Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
1010     }
1011     else {
1012         // Create independent buffers
1013         Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));
1014         if (Text == NULL) goto Error;
1015 
1016         Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t));
1017         if (Wide == NULL) goto Error;
1018 
1019         // Get both representations.
1020         cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry,  Text, len * sizeof(char));
1021         cmsMLUgetWide(mlu,  cmsNoLanguage, cmsNoCountry,  Wide, len * sizeof(wchar_t));
1022     }
1023 






1024   // * cmsUInt32Number       count;          * Description length
1025   // * cmsInt8Number         desc[count]     * NULL terminated ascii string
1026   // * cmsUInt32Number       ucLangCode;     * UniCode language code
1027   // * cmsUInt32Number       ucCount;        * UniCode description length
1028   // * cmsInt16Number        ucDesc[ucCount];* The UniCode description
1029   // * cmsUInt16Number       scCode;         * ScriptCode code
1030   // * cmsUInt8Number        scCount;        * ScriptCode count
1031   // * cmsInt8Number         scDesc[67];     * ScriptCode Description
1032 
1033     if (!_cmsWriteUInt32Number(io, len_aligned)) goto Error;
1034     if (!io ->Write(io, len, Text)) goto Error;
1035     if (!io ->Write(io, len_filler_alignment, Filler)) goto Error;
1036 
1037     if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // ucLanguageCode
1038 
1039     // This part is tricky: we need an aligned tag size, and the ScriptCode part
1040     // takes 70 bytes, so we need 2 extra bytes to do the alignment
1041 
1042     if (!_cmsWriteUInt32Number(io, len_aligned+1)) goto Error;
1043 
1044     // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
1045     if (!_cmsWriteWCharArray(io, len, Wide)) goto Error;
1046     if (!_cmsWriteUInt16Array(io, len_filler_alignment+1, (cmsUInt16Number*) Filler)) goto Error;
1047 
1048     // ScriptCode Code & count (unused)
1049     if (!_cmsWriteUInt16Number(io, 0)) goto Error;
1050     if (!_cmsWriteUInt8Number(io, 0)) goto Error;
1051 
1052     if (!io ->Write(io, 67, Filler)) goto Error;
1053 




1054     rc = TRUE;
1055 
1056 Error:
1057     if (Text) _cmsFree(self ->ContextID, Text);
1058     if (Wide) _cmsFree(self ->ContextID, Wide);
1059 
1060     return rc;
1061 
1062     cmsUNUSED_PARAMETER(nItems);
1063 }
1064 
1065 
1066 static
1067 void* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1068 {
1069     return (void*) cmsMLUdup((cmsMLU*) Ptr);
1070 
1071     cmsUNUSED_PARAMETER(n);
1072     cmsUNUSED_PARAMETER(self);
1073 }


1481         // Now deal with Len and offset.
1482         if (!_cmsReadUInt32Number(io, &Len)) goto Error;
1483         if (!_cmsReadUInt32Number(io, &Offset)) goto Error;
1484 
1485         // Check for overflow
1486         if (Offset < (SizeOfHeader + 8)) goto Error;
1487 
1488         // True begin of the string
1489         BeginOfThisString = Offset - SizeOfHeader - 8;
1490 
1491         // Ajust to wchar_t elements
1492         mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1493         mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1494 
1495         // To guess maximum size, add offset + len
1496         EndOfThisString = BeginOfThisString + Len;
1497         if (EndOfThisString > LargestPosition)
1498             LargestPosition = EndOfThisString;
1499     }
1500 
1501     // Now read the remaining of tag and fill all strings. Substract the directory
1502     SizeOfTag   = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1503     if (SizeOfTag == 0)
1504     {
1505         Block = NULL;
1506         NumOfWchar = 0;
1507 
1508     }
1509     else
1510     {
1511         Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag);
1512         if (Block == NULL) goto Error;
1513         NumOfWchar = SizeOfTag / sizeof(wchar_t);
1514         if (!_cmsReadWCharArray(io, NumOfWchar, Block)) goto Error;
1515     }
1516 
1517     mlu ->MemPool  = Block;
1518     mlu ->PoolSize = SizeOfTag;
1519     mlu ->PoolUsed = SizeOfTag;
1520 
1521     *nItems = 1;
1522     return (void*) mlu;
1523 
1524 Error:
1525     if (mlu) cmsMLUfree(mlu);
1526     return NULL;
1527 }
1528 
1529 static
1530 cmsBool  Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1531 {
1532     cmsMLU* mlu =(cmsMLU*) Ptr;
1533     cmsUInt32Number HeaderSize;
1534     cmsUInt32Number  Len, Offset;
1535     int i;
1536 
1537     if (Ptr == NULL) {
1538 
1539           // Empty placeholder
1540           if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
1541           if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1542           return TRUE;
1543     }
1544 
1545     if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE;
1546     if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1547 
1548     HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase);
1549 
1550     for (i=0; i < mlu ->UsedEntries; i++) {
1551 
1552         Len    =  mlu ->Entries[i].Len;
1553         Offset =  mlu ->Entries[i].StrW;
1554 
1555         Len    = (Len * sizeof(cmsUInt16Number)) / sizeof(wchar_t);


3116     prefix[31] = suffix[31] = 0;
3117 
3118     v = cmsAllocNamedColorList(self ->ContextID, count, nDeviceCoords, prefix, suffix);
3119     if (v == NULL) {
3120         cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many named colors '%d'", count);
3121         return NULL;
3122     }
3123 
3124     if (nDeviceCoords > cmsMAXCHANNELS) {
3125         cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords);
3126         return 0;
3127     }
3128     for (i=0; i < count; i++) {
3129 
3130         cmsUInt16Number PCS[3];
3131         cmsUInt16Number Colorant[cmsMAXCHANNELS];
3132         char Root[33];
3133 
3134         memset(Colorant, 0, sizeof(Colorant));
3135         if (io -> Read(io, Root, 32, 1) != 1) return NULL;


3136         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
3137         if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
3138 
3139         if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error;
3140     }
3141 
3142     *nItems = 1;
3143     return (void*) v ;
3144 
3145 Error:
3146     cmsFreeNamedColorList(v);
3147     return NULL;
3148 
3149     cmsUNUSED_PARAMETER(SizeOfTag);
3150 }
3151 
3152 
3153 // Saves a named color list into a named color profile
3154 static
3155 cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3156 {
3157     cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
3158     char                prefix[32];     // Prefix for each color name
3159     char                suffix[32];     // Suffix for each color name
3160     int i, nColors;
3161 
3162     nColors = cmsNamedColorCount(NamedColorList);
3163 
3164     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
3165     if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
3166     if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE;
3167 
3168     strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
3169     strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
3170 
3171     suffix[31] = prefix[31] = 0;
3172 
3173     if (!io ->Write(io, 32, prefix)) return FALSE;
3174     if (!io ->Write(io, 32, suffix)) return FALSE;
3175 
3176     for (i=0; i < nColors; i++) {
3177 
3178        cmsUInt16Number PCS[3];
3179        cmsUInt16Number Colorant[cmsMAXCHANNELS];
3180        char Root[33];
3181 
3182         if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;

3183         if (!io ->Write(io, 32 , Root)) return FALSE;
3184         if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
3185         if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE;
3186     }
3187 
3188     return TRUE;
3189 
3190     cmsUNUSED_PARAMETER(nItems);
3191     cmsUNUSED_PARAMETER(self);
3192 }
3193 
3194 static
3195 void* Type_NamedColor_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3196 {
3197     cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
3198 
3199     return (void*) cmsDupNamedColorList(nc);
3200 
3201     cmsUNUSED_PARAMETER(n);
3202     cmsUNUSED_PARAMETER(self);


3613 
3614 // ********************************************************************************
3615 // Type cmsSigCrdInfoType
3616 // ********************************************************************************
3617 
3618 /*
3619 This type contains the PostScript product name to which this profile corresponds
3620 and the names of the companion CRDs. Recall that a single profile can generate
3621 multiple CRDs. It is implemented as a MLU being the language code "PS" and then
3622 country varies for each element:
3623 
3624                 nm: PostScript product name
3625                 #0: Rendering intent 0 CRD name
3626                 #1: Rendering intent 1 CRD name
3627                 #2: Rendering intent 2 CRD name
3628                 #3: Rendering intent 3 CRD name
3629 */
3630 
3631 
3632 
3633 // Auxiliar, read an string specified as count + string
3634 static
3635 cmsBool  ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section)
3636 {
3637     cmsUInt32Number Count;
3638     char* Text;
3639 
3640     if (*SizeOfTag < sizeof(cmsUInt32Number)) return FALSE;
3641 
3642     if (!_cmsReadUInt32Number(io, &Count)) return FALSE;
3643 
3644     if (Count > UINT_MAX - sizeof(cmsUInt32Number)) return FALSE;
3645     if (*SizeOfTag < Count + sizeof(cmsUInt32Number)) return FALSE;
3646 
3647     Text     = (char*) _cmsMalloc(self ->ContextID, Count+1);
3648     if (Text == NULL) return FALSE;
3649 
3650     if (io ->Read(io, Text, sizeof(cmsUInt8Number), Count) != Count) {
3651         _cmsFree(self ->ContextID, Text);
3652         return FALSE;
3653     }


3862 
3863 static
3864 cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3865 {
3866     cmsICCViewingConditions* sc = (cmsICCViewingConditions* ) Ptr;
3867 
3868     if (!_cmsWriteXYZNumber(io, &sc ->IlluminantXYZ)) return FALSE;
3869     if (!_cmsWriteXYZNumber(io, &sc ->SurroundXYZ)) return FALSE;
3870     if (!_cmsWriteUInt32Number(io, sc ->IlluminantType)) return FALSE;
3871 
3872     return TRUE;
3873 
3874     cmsUNUSED_PARAMETER(nItems);
3875     cmsUNUSED_PARAMETER(self);
3876 }
3877 
3878 
3879 static
3880 void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3881 {
3882    return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsScreening));
3883 
3884    cmsUNUSED_PARAMETER(n);
3885 }
3886 
3887 
3888 static
3889 void Type_ViewingConditions_Free(struct _cms_typehandler_struct* self, void* Ptr)
3890 {
3891    _cmsFree(self ->ContextID, Ptr);
3892 }
3893 
3894 
3895 // ********************************************************************************
3896 // Type cmsSigMultiProcessElementType
3897 // ********************************************************************************
3898 
3899 
3900 static
3901 void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3902 {


4316     for (i=0; i < clut ->nEntries; i++) {
4317 
4318         if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error;
4319     }
4320 
4321     *nItems = 1;
4322     return mpe;
4323 
4324 Error:
4325     *nItems = 0;
4326     if (mpe != NULL) cmsStageFree(mpe);
4327     return NULL;
4328 
4329     cmsUNUSED_PARAMETER(SizeOfTag);
4330 }
4331 
4332 // Write a CLUT in floating point
4333 static
4334 cmsBool  Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4335 {
4336     cmsUInt8Number Dimensions8[16];
4337     cmsUInt32Number i;
4338     cmsStage* mpe = (cmsStage*) Ptr;
4339     _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data;
4340 
4341     // Check for maximum number of channels
4342     if (mpe -> InputChannels > 15) return FALSE;
4343 
4344     // Only floats are supported in MPE
4345     if (clut ->HasFloatValues == FALSE) return FALSE;
4346 
4347     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4348     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
4349 
4350     memset(Dimensions8, 0, sizeof(Dimensions8));
4351 
4352     for (i=0; i < mpe ->InputChannels; i++)
4353         Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i];
4354 
4355     if (!io ->Write(io, 16, Dimensions8)) return FALSE;
4356 
4357     for (i=0; i < clut ->nEntries; i++) {
4358 
4359         if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE;
4360     }
4361 
4362     return TRUE;


5461 
5462     { cmsSigUcrBgTag,               { 1, 1, { cmsSigUcrBgType}, NULL},    &SupportedTags[47]},
5463     { cmsSigCrdInfoTag,             { 1, 1, { cmsSigCrdInfoType}, NULL},  &SupportedTags[48]},
5464 
5465     { cmsSigDToB0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[49]},
5466     { cmsSigDToB1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[50]},
5467     { cmsSigDToB2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[51]},
5468     { cmsSigDToB3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[52]},
5469     { cmsSigBToD0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[53]},
5470     { cmsSigBToD1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[54]},
5471     { cmsSigBToD2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[55]},
5472     { cmsSigBToD3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[56]},
5473 
5474     { cmsSigScreeningDescTag,       { 1, 1, { cmsSigTextDescriptionType },    NULL}, &SupportedTags[57]},
5475     { cmsSigViewingConditionsTag,   { 1, 1, { cmsSigViewingConditionsType },  NULL}, &SupportedTags[58]},
5476 
5477     { cmsSigScreeningTag,           { 1, 1, { cmsSigScreeningType},          NULL }, &SupportedTags[59]},
5478     { cmsSigVcgtTag,                { 1, 1, { cmsSigVcgtType},               NULL }, &SupportedTags[60]},
5479     { cmsSigMetaTag,                { 1, 1, { cmsSigDictType},               NULL }, &SupportedTags[61]},
5480     { cmsSigProfileSequenceIdTag,   { 1, 1, { cmsSigProfileSequenceIdType},  NULL },  &SupportedTags[62]},
5481     { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, NULL}

5482 
5483 
5484 };
5485 
5486 /*
5487     Not supported                 Why
5488     =======================       =========================================
5489     cmsSigOutputResponseTag   ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT!
5490     cmsSigNamedColorTag       ==> Deprecated
5491     cmsSigDataTag             ==> Ancient, unused
5492     cmsSigDeviceSettingsTag   ==> Deprecated, useless
5493 */
5494 
5495 
5496 _cmsTagPluginChunkType _cmsTagPluginChunk = { NULL };
5497 
5498 
5499 // Duplicates the zone of memory used by the plug-in in the new context
5500 static
5501 void DupTagList(struct _cmsContext_struct* ctx,




  13  * version 2 for more details (a copy is included in the LICENSE file that
  14  * accompanied this code).
  15  *
  16  * You should have received a copy of the GNU General Public License version
  17  * 2 along with this work; if not, write to the Free Software Foundation,
  18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  19  *
  20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  21  * or visit www.oracle.com if you need additional information or have any
  22  * questions.
  23  */
  24 
  25 // This file is available under and governed by the GNU General Public
  26 // License version 2 only, as published by the Free Software Foundation.
  27 // However, the following notice accompanied the original version of this
  28 // file:
  29 //
  30 //---------------------------------------------------------------------------------
  31 //
  32 //  Little Color Management System
  33 //  Copyright (c) 1998-2016 Marti Maria Saguer
  34 //
  35 // Permission is hereby granted, free of charge, to any person obtaining
  36 // a copy of this software and associated documentation files (the "Software"),
  37 // to deal in the Software without restriction, including without limitation
  38 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39 // and/or sell copies of the Software, and to permit persons to whom the Software
  40 // is furnished to do so, subject to the following conditions:
  41 //
  42 // The above copyright notice and this permission notice shall be included in
  43 // all copies or substantial portions of the Software.
  44 //
  45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  52 //
  53 //---------------------------------------------------------------------------------
  54 //
  55 
  56 #include "lcms2_internal.h"
  57 
  58 // Tag Serialization  -----------------------------------------------------------------------------
  59 // This file implements every single tag and tag type as described in the ICC spec. Some types
  60 // have been deprecated, like ncl and Data. There is no implementation for those types as there
  61 // are no profiles holding them. The programmer can also extend this list by defining his own types
  62 // by using the appropriate plug-in. There are three types of plug ins regarding that. First type
  63 // allows to define new tags using any existing type. Next plug-in type allows to define new types
  64 // and the third one is very specific: allows to extend the number of elements in the multiprocessing
  65 // elements special type.
  66 //--------------------------------------------------------------------------------------------------
  67 
  68 // Some broken types
  69 #define cmsCorbisBrokenXYZtype    ((cmsTagTypeSignature) 0x17A505B8)
  70 #define cmsMonacoBrokenCurveType  ((cmsTagTypeSignature) 0x9478ee00)
  71 
  72 // This is the linked list that keeps track of the defined types
  73 typedef struct _cmsTagTypeLinkedList_st {
  74 
  75     cmsTagTypeHandler Handler;
  76     struct _cmsTagTypeLinkedList_st* Next;
  77 
  78 } _cmsTagTypeLinkedList;
  79 
  80 // Some macros to define callbacks.
  81 #define READ_FN(x)  Type_##x##_Read
  82 #define WRITE_FN(x) Type_##x##_Write


 125     _cmsTagTypeLinkedList* pt;
 126 
 127     for (pt = PluginLinkedList;
 128          pt != NULL;
 129          pt = pt ->Next) {
 130 
 131             if (sig == pt -> Handler.Signature) return &pt ->Handler;
 132     }
 133 
 134     for (pt = DefaultLinkedList;
 135          pt != NULL;
 136          pt = pt ->Next) {
 137 
 138             if (sig == pt -> Handler.Signature) return &pt ->Handler;
 139     }
 140 
 141     return NULL;
 142 }
 143 
 144 
 145 // Auxiliary to convert UTF-32 to UTF-16 in some cases
 146 static
 147 cmsBool _cmsWriteWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, const wchar_t* Array)
 148 {
 149     cmsUInt32Number i;
 150 
 151     _cmsAssert(io != NULL);
 152     _cmsAssert(!(Array == NULL && n > 0));
 153 
 154     for (i=0; i < n; i++) {
 155         if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) Array[i])) return FALSE;
 156     }
 157 
 158     return TRUE;
 159 }
 160 
 161 // Auxiliary to read an array of wchar_t
 162 static
 163 cmsBool _cmsReadWCharArray(cmsIOHANDLER* io, cmsUInt32Number n, wchar_t* Array)
 164 {
 165     cmsUInt32Number i;
 166     cmsUInt16Number tmp;
 167 
 168     _cmsAssert(io != NULL);
 169 
 170     for (i=0; i < n; i++) {
 171 
 172         if (Array != NULL) {
 173 
 174             if (!_cmsReadUInt16Number(io, &tmp)) return FALSE;
 175             Array[i] = (wchar_t) tmp;
 176         }
 177         else {
 178             if (!_cmsReadUInt16Number(io, NULL)) return FALSE;
 179         }
 180 
 181     }
 182     return TRUE;
 183 }
 184 
 185 // To deal with position tables
 186 typedef cmsBool (* PositionTableEntryFn)(struct _cms_typehandler_struct* self,
 187                                              cmsIOHANDLER* io,
 188                                              void* Cargo,
 189                                              cmsUInt32Number n,
 190                                              cmsUInt32Number SizeOfTag);
 191 
 192 // Helper function to deal with position tables as described in ICC spec 4.3
 193 // A table of n elements is readed, where first comes n records containing offsets and sizes and
 194 // then a block containing the data itself. This allows to reuse same data in more than one entry
 195 static
 196 cmsBool ReadPositionTable(struct _cms_typehandler_struct* self,
 197                               cmsIOHANDLER* io,
 198                               cmsUInt32Number Count,
 199                               cmsUInt32Number BaseOffset,
 200                               void *Cargo,
 201                               PositionTableEntryFn ElementFn)
 202 {
 203     cmsUInt32Number i;
 204     cmsUInt32Number *ElementOffsets = NULL, *ElementSizes = NULL;
 205 
 206     // Let's take the offsets to each element
 207     ElementOffsets = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
 208     if (ElementOffsets == NULL) goto Error;
 209 
 210     ElementSizes = (cmsUInt32Number *) _cmsCalloc(io ->ContextID, Count, sizeof(cmsUInt32Number));
 211     if (ElementSizes == NULL) goto Error;
 212 


 963 
 964 Done:
 965 
 966     *nItems = 1;
 967     return mlu;
 968 
 969 Error:
 970     if (Text) _cmsFree(self ->ContextID, (void*) Text);
 971     if (mlu) cmsMLUfree(mlu);
 972     return NULL;
 973 }
 974 
 975 
 976 // This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
 977 static
 978 cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
 979 {
 980     cmsMLU* mlu = (cmsMLU*) Ptr;
 981     char *Text = NULL;
 982     wchar_t *Wide = NULL;
 983     cmsUInt32Number len, len_text, len_tag_requirement, len_aligned;
 984     cmsBool  rc = FALSE;
 985     char Filler[68];
 986 
 987     // Used below for writting zeroes
 988     memset(Filler, 0, sizeof(Filler));
 989 
 990     // Get the len of string
 991     len = cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry, NULL, 0);
 992 
 993     // Specification ICC.1:2001-04 (v2.4.0): It has been found that textDescriptionType can contain misaligned data
 994     //(see clause 4.1 for the definition of “aligned”). Because the Unicode language
 995     // code and Unicode count immediately follow the ASCII description, their
 996     // alignment is not correct if the ASCII count is not a multiple of four. The
 997     // ScriptCode code is misaligned when the ASCII count is odd. Profile reading and
 998     // writing software must be written carefully in order to handle these alignment
 999     // problems.
1000     //
1001     // The above last sentence suggest to handle alignment issues in the
1002     // parser. The provided example (Table 69 on Page 60) makes this clear.
1003     // The padding only in the ASCII count is not sufficient for a aligned tag
1004     // size, with the same text size in ASCII and Unicode.
1005 
1006     // Null strings
1007     if (len <= 0) {
1008 
1009         Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
1010         Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
1011     }
1012     else {
1013         // Create independent buffers
1014         Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));
1015         if (Text == NULL) goto Error;
1016 
1017         Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t));
1018         if (Wide == NULL) goto Error;
1019 
1020         // Get both representations.
1021         cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry,  Text, len * sizeof(char));
1022         cmsMLUgetWide(mlu,  cmsNoLanguage, cmsNoCountry,  Wide, len * sizeof(wchar_t));
1023     }
1024 
1025     // Tell the real text len including the null terminator and padding
1026     len_text = (cmsUInt32Number) strlen(Text) + 1;
1027     // Compute an total tag size requirement
1028     len_tag_requirement = (8+4+len_text+4+4+2*len_text+2+1+67);
1029     len_aligned = _cmsALIGNLONG(len_tag_requirement);
1030 
1031   // * cmsUInt32Number       count;          * Description length
1032   // * cmsInt8Number         desc[count]     * NULL terminated ascii string
1033   // * cmsUInt32Number       ucLangCode;     * UniCode language code
1034   // * cmsUInt32Number       ucCount;        * UniCode description length
1035   // * cmsInt16Number        ucDesc[ucCount];* The UniCode description
1036   // * cmsUInt16Number       scCode;         * ScriptCode code
1037   // * cmsUInt8Number        scCount;        * ScriptCode count
1038   // * cmsInt8Number         scDesc[67];     * ScriptCode Description
1039 
1040     if (!_cmsWriteUInt32Number(io, len_text)) goto Error;
1041     if (!io ->Write(io, len_text, Text)) goto Error;

1042 
1043     if (!_cmsWriteUInt32Number(io, 0)) goto Error;  // ucLanguageCode
1044 
1045     if (!_cmsWriteUInt32Number(io, len_text)) goto Error;




1046     // Note that in some compilers sizeof(cmsUInt16Number) != sizeof(wchar_t)
1047     if (!_cmsWriteWCharArray(io, len_text, Wide)) goto Error;

1048 
1049     // ScriptCode Code & count (unused)
1050     if (!_cmsWriteUInt16Number(io, 0)) goto Error;
1051     if (!_cmsWriteUInt8Number(io, 0)) goto Error;
1052 
1053     if (!io ->Write(io, 67, Filler)) goto Error;
1054 
1055     // possibly add pad at the end of tag
1056     if(len_aligned - len_tag_requirement > 0)
1057       if (!io ->Write(io, len_aligned - len_tag_requirement, Filler)) goto Error;
1058 
1059     rc = TRUE;
1060 
1061 Error:
1062     if (Text) _cmsFree(self ->ContextID, Text);
1063     if (Wide) _cmsFree(self ->ContextID, Wide);
1064 
1065     return rc;
1066 
1067     cmsUNUSED_PARAMETER(nItems);
1068 }
1069 
1070 
1071 static
1072 void* Type_Text_Description_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
1073 {
1074     return (void*) cmsMLUdup((cmsMLU*) Ptr);
1075 
1076     cmsUNUSED_PARAMETER(n);
1077     cmsUNUSED_PARAMETER(self);
1078 }


1486         // Now deal with Len and offset.
1487         if (!_cmsReadUInt32Number(io, &Len)) goto Error;
1488         if (!_cmsReadUInt32Number(io, &Offset)) goto Error;
1489 
1490         // Check for overflow
1491         if (Offset < (SizeOfHeader + 8)) goto Error;
1492 
1493         // True begin of the string
1494         BeginOfThisString = Offset - SizeOfHeader - 8;
1495 
1496         // Ajust to wchar_t elements
1497         mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1498         mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1499 
1500         // To guess maximum size, add offset + len
1501         EndOfThisString = BeginOfThisString + Len;
1502         if (EndOfThisString > LargestPosition)
1503             LargestPosition = EndOfThisString;
1504     }
1505 
1506     // Now read the remaining of tag and fill all strings. Subtract the directory
1507     SizeOfTag   = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1508     if (SizeOfTag == 0)
1509     {
1510         Block = NULL;
1511         NumOfWchar = 0;
1512 
1513     }
1514     else
1515     {
1516         Block = (wchar_t*) _cmsMalloc(self ->ContextID, SizeOfTag);
1517         if (Block == NULL) goto Error;
1518         NumOfWchar = SizeOfTag / sizeof(wchar_t);
1519         if (!_cmsReadWCharArray(io, NumOfWchar, Block)) goto Error;
1520     }
1521 
1522     mlu ->MemPool  = Block;
1523     mlu ->PoolSize = SizeOfTag;
1524     mlu ->PoolUsed = SizeOfTag;
1525 
1526     *nItems = 1;
1527     return (void*) mlu;
1528 
1529 Error:
1530     if (mlu) cmsMLUfree(mlu);
1531     return NULL;
1532 }
1533 
1534 static
1535 cmsBool  Type_MLU_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1536 {
1537     cmsMLU* mlu =(cmsMLU*) Ptr;
1538     cmsUInt32Number HeaderSize;
1539     cmsUInt32Number  Len, Offset;
1540     cmsUInt32Number i;
1541 
1542     if (Ptr == NULL) {
1543 
1544           // Empty placeholder
1545           if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
1546           if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1547           return TRUE;
1548     }
1549 
1550     if (!_cmsWriteUInt32Number(io, mlu ->UsedEntries)) return FALSE;
1551     if (!_cmsWriteUInt32Number(io, 12)) return FALSE;
1552 
1553     HeaderSize = 12 * mlu ->UsedEntries + sizeof(_cmsTagBase);
1554 
1555     for (i=0; i < mlu ->UsedEntries; i++) {
1556 
1557         Len    =  mlu ->Entries[i].Len;
1558         Offset =  mlu ->Entries[i].StrW;
1559 
1560         Len    = (Len * sizeof(cmsUInt16Number)) / sizeof(wchar_t);


3121     prefix[31] = suffix[31] = 0;
3122 
3123     v = cmsAllocNamedColorList(self ->ContextID, count, nDeviceCoords, prefix, suffix);
3124     if (v == NULL) {
3125         cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many named colors '%d'", count);
3126         return NULL;
3127     }
3128 
3129     if (nDeviceCoords > cmsMAXCHANNELS) {
3130         cmsSignalError(self->ContextID, cmsERROR_RANGE, "Too many device coordinates '%d'", nDeviceCoords);
3131         return 0;
3132     }
3133     for (i=0; i < count; i++) {
3134 
3135         cmsUInt16Number PCS[3];
3136         cmsUInt16Number Colorant[cmsMAXCHANNELS];
3137         char Root[33];
3138 
3139         memset(Colorant, 0, sizeof(Colorant));
3140         if (io -> Read(io, Root, 32, 1) != 1) return NULL;
3141         Root[32] = 0;  // To prevent exploits
3142 
3143         if (!_cmsReadUInt16Array(io, 3, PCS)) goto Error;
3144         if (!_cmsReadUInt16Array(io, nDeviceCoords, Colorant)) goto Error;
3145 
3146         if (!cmsAppendNamedColor(v, Root, PCS, Colorant)) goto Error;
3147     }
3148 
3149     *nItems = 1;
3150     return (void*) v ;
3151 
3152 Error:
3153     cmsFreeNamedColorList(v);
3154     return NULL;
3155 
3156     cmsUNUSED_PARAMETER(SizeOfTag);
3157 }
3158 
3159 
3160 // Saves a named color list into a named color profile
3161 static
3162 cmsBool Type_NamedColor_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3163 {
3164     cmsNAMEDCOLORLIST* NamedColorList = (cmsNAMEDCOLORLIST*) Ptr;
3165     char                prefix[33];     // Prefix for each color name
3166     char                suffix[33];     // Suffix for each color name
3167     int i, nColors;
3168 
3169     nColors = cmsNamedColorCount(NamedColorList);
3170 
3171     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
3172     if (!_cmsWriteUInt32Number(io, nColors)) return FALSE;
3173     if (!_cmsWriteUInt32Number(io, NamedColorList ->ColorantCount)) return FALSE;
3174 
3175     strncpy(prefix, (const char*) NamedColorList->Prefix, 32);
3176     strncpy(suffix, (const char*) NamedColorList->Suffix, 32);
3177 
3178     suffix[32] = prefix[32] = 0;
3179 
3180     if (!io ->Write(io, 32, prefix)) return FALSE;
3181     if (!io ->Write(io, 32, suffix)) return FALSE;
3182 
3183     for (i=0; i < nColors; i++) {
3184 
3185        cmsUInt16Number PCS[3];
3186        cmsUInt16Number Colorant[cmsMAXCHANNELS];
3187        char Root[33];
3188 
3189         if (!cmsNamedColorInfo(NamedColorList, i, Root, NULL, NULL, PCS, Colorant)) return 0;
3190         Root[32] = 0;
3191         if (!io ->Write(io, 32 , Root)) return FALSE;
3192         if (!_cmsWriteUInt16Array(io, 3, PCS)) return FALSE;
3193         if (!_cmsWriteUInt16Array(io, NamedColorList ->ColorantCount, Colorant)) return FALSE;
3194     }
3195 
3196     return TRUE;
3197 
3198     cmsUNUSED_PARAMETER(nItems);
3199     cmsUNUSED_PARAMETER(self);
3200 }
3201 
3202 static
3203 void* Type_NamedColor_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
3204 {
3205     cmsNAMEDCOLORLIST* nc = (cmsNAMEDCOLORLIST*) Ptr;
3206 
3207     return (void*) cmsDupNamedColorList(nc);
3208 
3209     cmsUNUSED_PARAMETER(n);
3210     cmsUNUSED_PARAMETER(self);


3621 
3622 // ********************************************************************************
3623 // Type cmsSigCrdInfoType
3624 // ********************************************************************************
3625 
3626 /*
3627 This type contains the PostScript product name to which this profile corresponds
3628 and the names of the companion CRDs. Recall that a single profile can generate
3629 multiple CRDs. It is implemented as a MLU being the language code "PS" and then
3630 country varies for each element:
3631 
3632                 nm: PostScript product name
3633                 #0: Rendering intent 0 CRD name
3634                 #1: Rendering intent 1 CRD name
3635                 #2: Rendering intent 2 CRD name
3636                 #3: Rendering intent 3 CRD name
3637 */
3638 
3639 
3640 
3641 // Auxiliary, read an string specified as count + string
3642 static
3643 cmsBool  ReadCountAndSting(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsMLU* mlu, cmsUInt32Number* SizeOfTag, const char* Section)
3644 {
3645     cmsUInt32Number Count;
3646     char* Text;
3647 
3648     if (*SizeOfTag < sizeof(cmsUInt32Number)) return FALSE;
3649 
3650     if (!_cmsReadUInt32Number(io, &Count)) return FALSE;
3651 
3652     if (Count > UINT_MAX - sizeof(cmsUInt32Number)) return FALSE;
3653     if (*SizeOfTag < Count + sizeof(cmsUInt32Number)) return FALSE;
3654 
3655     Text     = (char*) _cmsMalloc(self ->ContextID, Count+1);
3656     if (Text == NULL) return FALSE;
3657 
3658     if (io ->Read(io, Text, sizeof(cmsUInt8Number), Count) != Count) {
3659         _cmsFree(self ->ContextID, Text);
3660         return FALSE;
3661     }


3870 
3871 static
3872 cmsBool Type_ViewingConditions_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
3873 {
3874     cmsICCViewingConditions* sc = (cmsICCViewingConditions* ) Ptr;
3875 
3876     if (!_cmsWriteXYZNumber(io, &sc ->IlluminantXYZ)) return FALSE;
3877     if (!_cmsWriteXYZNumber(io, &sc ->SurroundXYZ)) return FALSE;
3878     if (!_cmsWriteUInt32Number(io, sc ->IlluminantType)) return FALSE;
3879 
3880     return TRUE;
3881 
3882     cmsUNUSED_PARAMETER(nItems);
3883     cmsUNUSED_PARAMETER(self);
3884 }
3885 
3886 
3887 static
3888 void* Type_ViewingConditions_Dup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3889 {
3890    return _cmsDupMem(self->ContextID, Ptr, sizeof(cmsICCViewingConditions));
3891 
3892    cmsUNUSED_PARAMETER(n);
3893 }
3894 
3895 
3896 static
3897 void Type_ViewingConditions_Free(struct _cms_typehandler_struct* self, void* Ptr)
3898 {
3899    _cmsFree(self ->ContextID, Ptr);
3900 }
3901 
3902 
3903 // ********************************************************************************
3904 // Type cmsSigMultiProcessElementType
3905 // ********************************************************************************
3906 
3907 
3908 static
3909 void* GenericMPEdup(struct _cms_typehandler_struct* self, const void *Ptr, cmsUInt32Number n)
3910 {


4324     for (i=0; i < clut ->nEntries; i++) {
4325 
4326         if (!_cmsReadFloat32Number(io, &clut ->Tab.TFloat[i])) goto Error;
4327     }
4328 
4329     *nItems = 1;
4330     return mpe;
4331 
4332 Error:
4333     *nItems = 0;
4334     if (mpe != NULL) cmsStageFree(mpe);
4335     return NULL;
4336 
4337     cmsUNUSED_PARAMETER(SizeOfTag);
4338 }
4339 
4340 // Write a CLUT in floating point
4341 static
4342 cmsBool  Type_MPEclut_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
4343 {
4344     cmsUInt8Number Dimensions8[16];  // 16 because the spec says 16 and not max number of channels
4345     cmsUInt32Number i;
4346     cmsStage* mpe = (cmsStage*) Ptr;
4347     _cmsStageCLutData* clut = (_cmsStageCLutData*) mpe ->Data;
4348 
4349     // Check for maximum number of channels supported by lcms
4350     if (mpe -> InputChannels > MAX_INPUT_DIMENSIONS) return FALSE;
4351 
4352     // Only floats are supported in MPE
4353     if (clut ->HasFloatValues == FALSE) return FALSE;
4354 
4355     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->InputChannels)) return FALSE;
4356     if (!_cmsWriteUInt16Number(io, (cmsUInt16Number) mpe ->OutputChannels)) return FALSE;
4357 
4358     memset(Dimensions8, 0, sizeof(Dimensions8));
4359 
4360     for (i=0; i < mpe ->InputChannels; i++)
4361         Dimensions8[i] = (cmsUInt8Number) clut ->Params ->nSamples[i];
4362 
4363     if (!io ->Write(io, 16, Dimensions8)) return FALSE;
4364 
4365     for (i=0; i < clut ->nEntries; i++) {
4366 
4367         if (!_cmsWriteFloat32Number(io, clut ->Tab.TFloat[i])) return FALSE;
4368     }
4369 
4370     return TRUE;


5469 
5470     { cmsSigUcrBgTag,               { 1, 1, { cmsSigUcrBgType}, NULL},    &SupportedTags[47]},
5471     { cmsSigCrdInfoTag,             { 1, 1, { cmsSigCrdInfoType}, NULL},  &SupportedTags[48]},
5472 
5473     { cmsSigDToB0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[49]},
5474     { cmsSigDToB1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[50]},
5475     { cmsSigDToB2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[51]},
5476     { cmsSigDToB3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[52]},
5477     { cmsSigBToD0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[53]},
5478     { cmsSigBToD1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[54]},
5479     { cmsSigBToD2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[55]},
5480     { cmsSigBToD3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[56]},
5481 
5482     { cmsSigScreeningDescTag,       { 1, 1, { cmsSigTextDescriptionType },    NULL}, &SupportedTags[57]},
5483     { cmsSigViewingConditionsTag,   { 1, 1, { cmsSigViewingConditionsType },  NULL}, &SupportedTags[58]},
5484 
5485     { cmsSigScreeningTag,           { 1, 1, { cmsSigScreeningType},          NULL }, &SupportedTags[59]},
5486     { cmsSigVcgtTag,                { 1, 1, { cmsSigVcgtType},               NULL }, &SupportedTags[60]},
5487     { cmsSigMetaTag,                { 1, 1, { cmsSigDictType},               NULL }, &SupportedTags[61]},
5488     { cmsSigProfileSequenceIdTag,   { 1, 1, { cmsSigProfileSequenceIdType},  NULL }, &SupportedTags[62]},
5489     { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]},
5490     { cmsSigArgyllArtsTag,          { 9, 1, { cmsSigS15Fixed16ArrayType},    NULL}, NULL}
5491 
5492 
5493 };
5494 
5495 /*
5496     Not supported                 Why
5497     =======================       =========================================
5498     cmsSigOutputResponseTag   ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT!
5499     cmsSigNamedColorTag       ==> Deprecated
5500     cmsSigDataTag             ==> Ancient, unused
5501     cmsSigDeviceSettingsTag   ==> Deprecated, useless
5502 */
5503 
5504 
5505 _cmsTagPluginChunkType _cmsTagPluginChunk = { NULL };
5506 
5507 
5508 // Duplicates the zone of memory used by the plug-in in the new context
5509 static
5510 void DupTagList(struct _cmsContext_struct* ctx,


< prev index next >