< prev index next >

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

Print this page

 105     // Calling the function with NULL as plug-in would unregister the plug in.
 106     if (Data == NULL) {
 107 
 108         // There is no need to set free the memory, as pool is destroyed as a whole.
 109         ctx ->TagTypes = NULL;
 110         return TRUE;
 111     }
 112 
 113     // Registering happens in plug-in memory pool.
 114     pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
 115     if (pt == NULL) return FALSE;
 116 
 117     pt ->Handler   = Plugin ->Handler;
 118     pt ->Next      = ctx ->TagTypes;
 119 
 120     ctx ->TagTypes = pt;
 121 
 122     return TRUE;
 123 }
 124 
 125 // Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additons
 126 // made by plug-ins and then the built-in defaults.
 127 static
 128 cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList)
 129 {
 130     _cmsTagTypeLinkedList* pt;
 131 
 132     for (pt = PluginLinkedList;
 133          pt != NULL;
 134          pt = pt ->Next) {
 135 
 136             if (sig == pt -> Handler.Signature) return &pt ->Handler;
 137     }
 138 
 139     for (pt = DefaultLinkedList;
 140          pt != NULL;
 141          pt = pt ->Next) {
 142 
 143             if (sig == pt -> Handler.Signature) return &pt ->Handler;
 144     }
 145 

 937 
 938     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCData) + BinData ->len - 1);
 939 
 940     cmsUNUSED_PARAMETER(n);
 941 }
 942 
 943 static
 944 void Type_Data_Free(struct _cms_typehandler_struct* self, void* Ptr)
 945 {
 946     _cmsFree(self ->ContextID, Ptr);
 947 }
 948 
 949 // ********************************************************************************
 950 // Type cmsSigTextDescriptionType
 951 // ********************************************************************************
 952 
 953 static
 954 void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 955 {
 956     char* Text = NULL;

 957     cmsMLU* mlu = NULL;
 958     cmsUInt32Number  AsciiCount;
 959     cmsUInt32Number  i, UnicodeCode, UnicodeCount;
 960     cmsUInt16Number  ScriptCodeCode, Dummy;
 961     cmsUInt8Number   ScriptCodeCount;
 962 
 963     *nItems = 0;
 964 
 965     //  One dword should be there
 966     if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
 967 
 968     // Read len of ASCII
 969     if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL;
 970     SizeOfTag -= sizeof(cmsUInt32Number);
 971 
 972     // Check for size
 973     if (SizeOfTag < AsciiCount) return NULL;
 974 
 975     // All seems Ok, allocate the container
 976     mlu = cmsMLUalloc(self ->ContextID, 1);
 977     if (mlu == NULL) return NULL;
 978 
 979     // As many memory as size of tag
 980     Text = (char*) _cmsMalloc(self ->ContextID, AsciiCount + 1);
 981     if (Text == NULL) goto Error;
 982 
 983     // Read it
 984     if (io ->Read(io, Text, sizeof(char), AsciiCount) != AsciiCount) goto Error;
 985     SizeOfTag -= AsciiCount;
 986 
 987     // Make sure there is a terminator
 988     Text[AsciiCount] = 0;
 989 
 990     // Set the MLU entry. From here we can be tolerant to wrong types
 991     if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error;
 992     _cmsFree(self ->ContextID, (void*) Text);
 993     Text = NULL;
 994 
 995     // Skip Unicode code
 996     if (SizeOfTag < 2* sizeof(cmsUInt32Number)) goto Done;
 997     if (!_cmsReadUInt32Number(io, &UnicodeCode)) goto Done;
 998     if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
 999     SizeOfTag -= 2* sizeof(cmsUInt32Number);
1000 
1001     if (SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;










1002 
1003     for (i=0; i < UnicodeCount; i++) {
1004         if (!io ->Read(io, &Dummy, sizeof(cmsUInt16Number), 1)) goto Done;

1005     }




1006     SizeOfTag -= UnicodeCount*sizeof(cmsUInt16Number);
1007 
1008     // Skip ScriptCode code if present. Some buggy profiles does have less
1009     // data that stricttly required. We need to skip it as this type may come
1010     // embedded in other types.
1011 
1012     if (SizeOfTag >= sizeof(cmsUInt16Number) + sizeof(cmsUInt8Number) + 67) {
1013 
1014         if (!_cmsReadUInt16Number(io, &ScriptCodeCode)) goto Done;
1015         if (!_cmsReadUInt8Number(io,  &ScriptCodeCount)) goto Done;
1016 
1017         // Skip rest of tag
1018         for (i=0; i < 67; i++) {
1019             if (!io ->Read(io, &Dummy, sizeof(cmsUInt8Number), 1)) goto Error;
1020         }
1021     }
1022 
1023 Done:
1024 
1025     *nItems = 1;
1026     return mlu;
1027 
1028 Error:

1029     if (Text) _cmsFree(self ->ContextID, (void*) Text);
1030     if (mlu) cmsMLUfree(mlu);
1031     return NULL;
1032 }
1033 
1034 
1035 // This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
1036 static
1037 cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1038 {
1039     cmsMLU* mlu = (cmsMLU*) Ptr;
1040     char *Text = NULL;
1041     wchar_t *Wide = NULL;
1042     cmsUInt32Number len, len_text, len_tag_requirement, len_aligned;
1043     cmsBool  rc = FALSE;
1044     char Filler[68];
1045 
1046     // Used below for writing zeroes
1047     memset(Filler, 0, sizeof(Filler));
1048 

1061     // parser. The provided example (Table 69 on Page 60) makes this clear.
1062     // The padding only in the ASCII count is not sufficient for a aligned tag
1063     // size, with the same text size in ASCII and Unicode.
1064 
1065     // Null strings
1066     if (len <= 0) {
1067 
1068         Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
1069         Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
1070     }
1071     else {
1072         // Create independent buffers
1073         Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));
1074         if (Text == NULL) goto Error;
1075 
1076         Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t));
1077         if (Wide == NULL) goto Error;
1078 
1079         // Get both representations.
1080         cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry,  Text, len * sizeof(char));
1081         cmsMLUgetWide(mlu,  cmsNoLanguage, cmsNoCountry,  Wide, len * sizeof(wchar_t));
1082     }
1083 
1084     // Tell the real text len including the null terminator and padding
1085     len_text = (cmsUInt32Number) strlen(Text) + 1;
1086     // Compute an total tag size requirement
1087     len_tag_requirement = (8+4+len_text+4+4+2*len_text+2+1+67);
1088     len_aligned = _cmsALIGNLONG(len_tag_requirement);
1089 
1090   // * cmsUInt32Number       count;          * Description length
1091   // * cmsInt8Number         desc[count]     * NULL terminated ascii string
1092   // * cmsUInt32Number       ucLangCode;     * UniCode language code
1093   // * cmsUInt32Number       ucCount;        * UniCode description length
1094   // * cmsInt16Number        ucDesc[ucCount];* The UniCode description
1095   // * cmsUInt16Number       scCode;         * ScriptCode code
1096   // * cmsUInt8Number        scCount;        * ScriptCode count
1097   // * cmsInt8Number         scDesc[67];     * ScriptCode Description
1098 
1099     if (!_cmsWriteUInt32Number(io, len_text)) goto Error;
1100     if (!io ->Write(io, len_text, Text)) goto Error;
1101 

1560         if (((Offset + Len) < Len) || ((Offset + Len) > SizeOfTag + 8)) goto Error;
1561 
1562         // True begin of the string
1563         BeginOfThisString = Offset - SizeOfHeader - 8;
1564 
1565         // Adjust to wchar_t elements
1566         mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1567         mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1568 
1569         // To guess maximum size, add offset + len
1570         EndOfThisString = BeginOfThisString + Len;
1571         if (EndOfThisString > LargestPosition)
1572             LargestPosition = EndOfThisString;
1573     }
1574 
1575     // Now read the remaining of tag and fill all strings. Subtract the directory
1576     SizeOfTag   = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1577     if (SizeOfTag == 0)
1578     {
1579         Block = NULL;
1580         NumOfWchar = 0;
1581 
1582     }
1583     else
1584     {
1585         // Make sure this is an even utf16 size.
1586         if (SizeOfTag & 1) goto Error;
1587 
1588         Block = (wchar_t*) _cmsCalloc(self ->ContextID, 1, SizeOfTag);
1589         if (Block == NULL) goto Error;
1590 
1591         NumOfWchar = SizeOfTag / sizeof(wchar_t);
1592         if (!_cmsReadWCharArray(io, NumOfWchar, Block)) {
1593             _cmsFree(self->ContextID, Block);
1594             goto Error;
1595         }
1596     }
1597 
1598     mlu ->MemPool  = Block;
1599     mlu ->PoolSize = SizeOfTag;
1600     mlu ->PoolUsed = SizeOfTag;
1601 

1923         }
1924         _cmsFree(self ->ContextID, T);
1925     }
1926 
1927 
1928     // Get output tables
1929     if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;
1930 
1931     *nItems = 1;
1932     return NewLUT;
1933 
1934 Error:
1935     if (NewLUT != NULL) cmsPipelineFree(NewLUT);
1936     return NULL;
1937 
1938     cmsUNUSED_PARAMETER(SizeOfTag);
1939 }
1940 
1941 // We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
1942 static
1943 cmsBool  Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1944 {
1945     cmsUInt32Number j, nTabSize, i;
1946     cmsUInt8Number  val;
1947     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
1948     cmsStage* mpe;
1949     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
1950     _cmsStageMatrixData* MatMPE = NULL;
1951     _cmsStageCLutData* clut = NULL;
1952     cmsUInt32Number clutPoints;
1953 
1954     // Disassemble the LUT into components.
1955     mpe = NewLUT -> Elements;






1956     if (mpe ->Type == cmsSigMatrixElemType) {
1957 
1958         if (mpe->InputChannels != 3 || mpe->OutputChannels != 3) return FALSE;
1959         MatMPE = (_cmsStageMatrixData*) mpe ->Data;
1960         mpe = mpe -> Next;
1961     }
1962 
1963     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
1964         PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
1965         mpe = mpe -> Next;
1966     }
1967 
1968     if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
1969         clut  = (_cmsStageCLutData*) mpe -> Data;
1970         mpe = mpe ->Next;
1971     }
1972 
1973     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
1974         PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
1975         mpe = mpe -> Next;

2677 }
2678 
2679 
2680 // Write a set of curves
2681 static
2682 cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
2683 {
2684     cmsUInt32Number i, n;
2685     cmsTagTypeSignature CurrentType;
2686     cmsToneCurve** Curves;
2687 
2688 
2689     n      = cmsStageOutputChannels(mpe);
2690     Curves = _cmsStageGetPtrToCurveSet(mpe);
2691 
2692     for (i=0; i < n; i++) {
2693 
2694         // If this is a table-based curve, use curve type even on V4
2695         CurrentType = Type;
2696 
2697         if ((Curves[i] ->nSegments == 0)||
2698             ((Curves[i]->nSegments == 2) && (Curves[i] ->Segments[1].Type == 0)) )
2699             CurrentType = cmsSigCurveType;
2700         else
2701         if (Curves[i] ->Segments[0].Type < 0)
2702             CurrentType = cmsSigCurveType;
2703 
2704         if (!_cmsWriteTypeBase(io, CurrentType)) return FALSE;
2705 
2706         switch (CurrentType) {
2707 
2708             case cmsSigCurveType:
2709                 if (!Type_Curve_Write(self, io, Curves[i], 1)) return FALSE;
2710                 break;
2711 
2712             case cmsSigParametricCurveType:
2713                 if (!Type_ParametricCurve_Write(self, io, Curves[i], 1)) return FALSE;
2714                 break;
2715 
2716             default:
2717                 {
2718                     char String[5];

4442     return TRUE;
4443 
4444     cmsUNUSED_PARAMETER(nItems);
4445     cmsUNUSED_PARAMETER(self);
4446 }
4447 
4448 
4449 
4450 static
4451 void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4452 {
4453     cmsStage* mpe = NULL;
4454     cmsUInt16Number InputChans, OutputChans;
4455     cmsUInt8Number Dimensions8[16];
4456     cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS];
4457     _cmsStageCLutData* clut;
4458 
4459     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4460     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4461 
4462     if (InputChans == 0) goto Error;
4463     if (OutputChans == 0) goto Error;
4464 
4465     if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
4466         goto Error;
4467 
4468     // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number
4469     nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? (cmsUInt32Number) MAX_INPUT_DIMENSIONS : InputChans;
4470 
4471     for (i = 0; i < nMaxGrids; i++) {
4472         if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least
4473         GridPoints[i] = (cmsUInt32Number)Dimensions8[i];
4474     }
4475 
4476     // Allocate the true CLUT
4477     mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
4478     if (mpe == NULL) goto Error;
4479 
4480     // Read and sanitize the data
4481     clut = (_cmsStageCLutData*) mpe ->Data;
4482     for (i=0; i < clut ->nEntries; i++) {
4483 

5233     if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
5234 
5235     *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, e ->Sizes[i]);
5236     return *mlu != NULL;
5237 }
5238 
5239 static
5240 cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, const cmsMLU* mlu, cmsUInt32Number BaseOffset)
5241 {
5242     cmsUInt32Number Before;
5243 
5244      // Special case for undefined strings (see ICC Votable
5245      // Proposal Submission, Dictionary Type and Metadata TAG Definition)
5246      if (mlu == NULL) {
5247         e ->Sizes[i] = 0;
5248         e ->Offsets[i] = 0;
5249         return TRUE;
5250     }
5251 
5252     Before = io ->Tell(io);
5253     e ->Offsets[i] = Before - BaseOffset;

5254 
5255     if (!Type_MLU_Write(self, io, (void*) mlu, 1)) return FALSE;
5256 
5257     e ->Sizes[i] = io ->Tell(io) - Before;

5258     return TRUE;
5259 }
5260 
5261 
5262 static
5263 void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
5264 {
5265    cmsHANDLE hDict = NULL;
5266    cmsUInt32Number i, Count, Length;
5267    cmsUInt32Number BaseOffset;
5268    _cmsDICarray a;
5269    wchar_t *NameWCS = NULL, *ValueWCS = NULL;
5270    cmsMLU *DisplayNameMLU = NULL, *DisplayValueMLU=NULL;
5271    cmsBool rc;
5272    cmsInt32Number SignedSizeOfTag = (cmsInt32Number)SizeOfTag;
5273 
5274     *nItems = 0;
5275     memset(&a, 0, sizeof(a));
5276 
5277     // Get actual position as a basis for element offsets

5482     return TRUE;
5483 
5484     cmsUNUSED_PARAMETER(self);
5485     cmsUNUSED_PARAMETER(nItems);
5486 }
5487 
5488 void* Type_VideoSignal_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
5489 {
5490     return _cmsDupMem(self->ContextID, Ptr, sizeof(cmsVideoSignalType));
5491 
5492     cmsUNUSED_PARAMETER(n);
5493 }
5494 
5495 
5496 static
5497 void Type_VideoSignal_Free(struct _cms_typehandler_struct* self, void* Ptr)
5498 {
5499     _cmsFree(self->ContextID, Ptr);
5500 }
5501 


















































































































































































































5502 // ********************************************************************************
5503 // Type support main routines
5504 // ********************************************************************************
5505 
5506 
5507 // This is the list of built-in types
5508 static const _cmsTagTypeLinkedList SupportedTagTypes[] = {
5509 
5510 {TYPE_HANDLER(cmsSigChromaticityType,          Chromaticity),       (_cmsTagTypeLinkedList*) &SupportedTagTypes[1] },
5511 {TYPE_HANDLER(cmsSigColorantOrderType,         ColorantOrderType),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[2] },
5512 {TYPE_HANDLER(cmsSigS15Fixed16ArrayType,       S15Fixed16),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[3] },
5513 {TYPE_HANDLER(cmsSigU16Fixed16ArrayType,       U16Fixed16),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[4] },
5514 {TYPE_HANDLER(cmsSigTextType,                  Text),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[5] },
5515 {TYPE_HANDLER(cmsSigTextDescriptionType,       Text_Description),   (_cmsTagTypeLinkedList*) &SupportedTagTypes[6] },
5516 {TYPE_HANDLER(cmsSigCurveType,                 Curve),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[7] },
5517 {TYPE_HANDLER(cmsSigParametricCurveType,       ParametricCurve),    (_cmsTagTypeLinkedList*) &SupportedTagTypes[8] },
5518 {TYPE_HANDLER(cmsSigDateTimeType,              DateTime),           (_cmsTagTypeLinkedList*) &SupportedTagTypes[9] },
5519 {TYPE_HANDLER(cmsSigLut8Type,                  LUT8),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[10] },
5520 {TYPE_HANDLER(cmsSigLut16Type,                 LUT16),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[11] },
5521 {TYPE_HANDLER(cmsSigColorantTableType,         ColorantTable),      (_cmsTagTypeLinkedList*) &SupportedTagTypes[12] },
5522 {TYPE_HANDLER(cmsSigNamedColor2Type,           NamedColor),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[13] },
5523 {TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[14] },
5524 {TYPE_HANDLER(cmsSigProfileSequenceDescType,   ProfileSequenceDesc),(_cmsTagTypeLinkedList*) &SupportedTagTypes[15] },
5525 {TYPE_HANDLER(cmsSigSignatureType,             Signature),          (_cmsTagTypeLinkedList*) &SupportedTagTypes[16] },
5526 {TYPE_HANDLER(cmsSigMeasurementType,           Measurement),        (_cmsTagTypeLinkedList*) &SupportedTagTypes[17] },
5527 {TYPE_HANDLER(cmsSigDataType,                  Data),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[18] },
5528 {TYPE_HANDLER(cmsSigLutAtoBType,               LUTA2B),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[19] },
5529 {TYPE_HANDLER(cmsSigLutBtoAType,               LUTB2A),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[20] },
5530 {TYPE_HANDLER(cmsSigUcrBgType,                 UcrBg),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[21] },
5531 {TYPE_HANDLER(cmsSigCrdInfoType,               CrdInfo),            (_cmsTagTypeLinkedList*) &SupportedTagTypes[22] },
5532 {TYPE_HANDLER(cmsSigMultiProcessElementType,   MPE),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[23] },
5533 {TYPE_HANDLER(cmsSigScreeningType,             Screening),          (_cmsTagTypeLinkedList*) &SupportedTagTypes[24] },
5534 {TYPE_HANDLER(cmsSigViewingConditionsType,     ViewingConditions),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[25] },
5535 {TYPE_HANDLER(cmsSigXYZType,                   XYZ),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[26] },
5536 {TYPE_HANDLER(cmsCorbisBrokenXYZtype,          XYZ),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[27] },
5537 {TYPE_HANDLER(cmsMonacoBrokenCurveType,        Curve),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[28] },
5538 {TYPE_HANDLER(cmsSigProfileSequenceIdType,     ProfileSequenceId),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[29] },
5539 {TYPE_HANDLER(cmsSigDictType,                  Dictionary),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] },
5540 {TYPE_HANDLER(cmsSigcicpType,                  VideoSignal),        (_cmsTagTypeLinkedList*) &SupportedTagTypes[31] },
5541 {TYPE_HANDLER(cmsSigVcgtType,                  vcgt),                NULL }

5542 };
5543 
5544 
5545 _cmsTagTypePluginChunkType _cmsTagTypePluginChunk = { NULL };
5546 
5547 
5548 
5549 // Duplicates the zone of memory used by the plug-in in the new context
5550 static
5551 void DupTagTypeList(struct _cmsContext_struct* ctx,
5552                     const struct _cmsContext_struct* src,
5553                     int loc)
5554 {
5555    _cmsTagTypePluginChunkType newHead = { NULL };
5556    _cmsTagTypeLinkedList*  entry;
5557    _cmsTagTypeLinkedList*  Anterior = NULL;
5558    _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc];
5559 
5560    // Walk the list copying all nodes
5561    for (entry = head->TagTypes;

5717     { cmsSigDToB0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[49]},
5718     { cmsSigDToB1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[50]},
5719     { cmsSigDToB2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[51]},
5720     { cmsSigDToB3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[52]},
5721     { cmsSigBToD0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[53]},
5722     { cmsSigBToD1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[54]},
5723     { cmsSigBToD2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[55]},
5724     { cmsSigBToD3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[56]},
5725 
5726     { cmsSigScreeningDescTag,       { 1, 1, { cmsSigTextDescriptionType },    NULL}, &SupportedTags[57]},
5727     { cmsSigViewingConditionsTag,   { 1, 1, { cmsSigViewingConditionsType },  NULL}, &SupportedTags[58]},
5728 
5729     { cmsSigScreeningTag,           { 1, 1, { cmsSigScreeningType},          NULL }, &SupportedTags[59]},
5730     { cmsSigVcgtTag,                { 1, 1, { cmsSigVcgtType},               NULL }, &SupportedTags[60]},
5731     { cmsSigMetaTag,                { 1, 1, { cmsSigDictType},               NULL }, &SupportedTags[61]},
5732     { cmsSigProfileSequenceIdTag,   { 1, 1, { cmsSigProfileSequenceIdType},  NULL }, &SupportedTags[62]},
5733 
5734     { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]},
5735     { cmsSigcicpTag,                { 1, 1, { cmsSigcicpType},               NULL },   &SupportedTags[64]},
5736 
5737     { cmsSigArgyllArtsTag,          { 9, 1, { cmsSigS15Fixed16ArrayType},    NULL}, NULL}

5738 
5739 };
5740 
5741 /*
5742     Not supported                 Why
5743     =======================       =========================================
5744     cmsSigOutputResponseTag   ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT!
5745     cmsSigNamedColorTag       ==> Deprecated
5746     cmsSigDataTag             ==> Ancient, unused
5747     cmsSigDeviceSettingsTag   ==> Deprecated, useless
5748 */
5749 
5750 
5751 _cmsTagPluginChunkType _cmsTagPluginChunk = { NULL };
5752 
5753 
5754 // Duplicates the zone of memory used by the plug-in in the new context
5755 static
5756 void DupTagList(struct _cmsContext_struct* ctx,
5757                     const struct _cmsContext_struct* src)

 105     // Calling the function with NULL as plug-in would unregister the plug in.
 106     if (Data == NULL) {
 107 
 108         // There is no need to set free the memory, as pool is destroyed as a whole.
 109         ctx ->TagTypes = NULL;
 110         return TRUE;
 111     }
 112 
 113     // Registering happens in plug-in memory pool.
 114     pt = (_cmsTagTypeLinkedList*) _cmsPluginMalloc(id, sizeof(_cmsTagTypeLinkedList));
 115     if (pt == NULL) return FALSE;
 116 
 117     pt ->Handler   = Plugin ->Handler;
 118     pt ->Next      = ctx ->TagTypes;
 119 
 120     ctx ->TagTypes = pt;
 121 
 122     return TRUE;
 123 }
 124 
 125 // Return handler for a given type or NULL if not found. Shared between normal types and MPE. It first tries the additions
 126 // made by plug-ins and then the built-in defaults.
 127 static
 128 cmsTagTypeHandler* GetHandler(cmsTagTypeSignature sig, _cmsTagTypeLinkedList* PluginLinkedList, _cmsTagTypeLinkedList* DefaultLinkedList)
 129 {
 130     _cmsTagTypeLinkedList* pt;
 131 
 132     for (pt = PluginLinkedList;
 133          pt != NULL;
 134          pt = pt ->Next) {
 135 
 136             if (sig == pt -> Handler.Signature) return &pt ->Handler;
 137     }
 138 
 139     for (pt = DefaultLinkedList;
 140          pt != NULL;
 141          pt = pt ->Next) {
 142 
 143             if (sig == pt -> Handler.Signature) return &pt ->Handler;
 144     }
 145 

 937 
 938     return _cmsDupMem(self ->ContextID, Ptr, sizeof(cmsICCData) + BinData ->len - 1);
 939 
 940     cmsUNUSED_PARAMETER(n);
 941 }
 942 
 943 static
 944 void Type_Data_Free(struct _cms_typehandler_struct* self, void* Ptr)
 945 {
 946     _cmsFree(self ->ContextID, Ptr);
 947 }
 948 
 949 // ********************************************************************************
 950 // Type cmsSigTextDescriptionType
 951 // ********************************************************************************
 952 
 953 static
 954 void *Type_Text_Description_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
 955 {
 956     char* Text = NULL;
 957     wchar_t* UnicodeString = NULL;
 958     cmsMLU* mlu = NULL;
 959     cmsUInt32Number  AsciiCount;
 960     cmsUInt32Number  i, UnicodeCode, UnicodeCount;
 961     cmsUInt16Number  ScriptCodeCode, Dummy;
 962     cmsUInt8Number   ScriptCodeCount;
 963 
 964     *nItems = 0;
 965 
 966     //  One dword should be there
 967     if (SizeOfTag < sizeof(cmsUInt32Number)) return NULL;
 968 
 969     // Read len of ASCII
 970     if (!_cmsReadUInt32Number(io, &AsciiCount)) return NULL;
 971     SizeOfTag -= sizeof(cmsUInt32Number);
 972 
 973     // Check for size
 974     if (SizeOfTag < AsciiCount) return NULL;
 975 
 976     // All seems Ok, allocate the container
 977     mlu = cmsMLUalloc(self ->ContextID, 2);
 978     if (mlu == NULL) return NULL;
 979 
 980     // As many memory as size of tag
 981     Text = (char*) _cmsMalloc(self ->ContextID, AsciiCount + 1);
 982     if (Text == NULL) goto Error;
 983 
 984     // Read it
 985     if (io ->Read(io, Text, sizeof(char), AsciiCount) != AsciiCount) goto Error;
 986     SizeOfTag -= AsciiCount;
 987 
 988     // Make sure there is a terminator
 989     Text[AsciiCount] = 0;
 990 
 991     // Set the MLU entry. From here we can be tolerant to wrong types
 992     if (!cmsMLUsetASCII(mlu, cmsNoLanguage, cmsNoCountry, Text)) goto Error;
 993     _cmsFree(self ->ContextID, (void*) Text);
 994     Text = NULL;
 995 
 996     // Skip Unicode code
 997     if (SizeOfTag < 2* sizeof(cmsUInt32Number)) goto Done;
 998     if (!_cmsReadUInt32Number(io, &UnicodeCode)) goto Done;
 999     if (!_cmsReadUInt32Number(io, &UnicodeCount)) goto Done;
1000     SizeOfTag -= 2* sizeof(cmsUInt32Number);
1001 
1002     if (UnicodeCount == 0 || SizeOfTag < UnicodeCount*sizeof(cmsUInt16Number)) goto Done;
1003 
1004     UnicodeString = (wchar_t*)_cmsMallocZero(self->ContextID, (UnicodeCount + 1) * sizeof(wchar_t));
1005     if (UnicodeString == NULL) goto Done;
1006 
1007     if (!_cmsReadWCharArray(io, UnicodeCount, UnicodeString)) {
1008         _cmsFree(self->ContextID, (void*)UnicodeString);
1009         goto Done;
1010     }
1011 
1012     UnicodeString[UnicodeCount] = 0;
1013 
1014     if (!cmsMLUsetWide(mlu, cmsV2Unicode, cmsV2Unicode, UnicodeString)) {
1015         _cmsFree(self->ContextID, (void*)UnicodeString);
1016         goto Done;
1017     }
1018 
1019     _cmsFree(self->ContextID, (void*)UnicodeString);
1020     UnicodeString = NULL;
1021 
1022     SizeOfTag -= UnicodeCount*sizeof(cmsUInt16Number);
1023 
1024     // Skip ScriptCode code if present. Some buggy profiles does have less
1025     // data that strictly required. We need to skip it as this type may come
1026     // embedded in other types.
1027 
1028     if (SizeOfTag >= sizeof(cmsUInt16Number) + sizeof(cmsUInt8Number) + 67) {
1029 
1030         if (!_cmsReadUInt16Number(io, &ScriptCodeCode)) goto Done;
1031         if (!_cmsReadUInt8Number(io,  &ScriptCodeCount)) goto Done;
1032 
1033         // Skip rest of tag
1034         for (i=0; i < 67; i++) {
1035             if (!io ->Read(io, &Dummy, sizeof(cmsUInt8Number), 1)) goto Error;
1036         }
1037     }
1038 
1039 Done:
1040 
1041     *nItems = 1;
1042     return mlu;
1043 
1044 Error:
1045     if (UnicodeString)  _cmsFree(self->ContextID, (void*)UnicodeString);
1046     if (Text) _cmsFree(self ->ContextID, (void*) Text);
1047     if (mlu) cmsMLUfree(mlu);
1048     return NULL;
1049 }
1050 
1051 
1052 // This tag can come IN UNALIGNED SIZE. In order to prevent issues, we force zeros on description to align it
1053 static
1054 cmsBool  Type_Text_Description_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1055 {
1056     cmsMLU* mlu = (cmsMLU*) Ptr;
1057     char *Text = NULL;
1058     wchar_t *Wide = NULL;
1059     cmsUInt32Number len, len_text, len_tag_requirement, len_aligned;
1060     cmsBool  rc = FALSE;
1061     char Filler[68];
1062 
1063     // Used below for writing zeroes
1064     memset(Filler, 0, sizeof(Filler));
1065 

1078     // parser. The provided example (Table 69 on Page 60) makes this clear.
1079     // The padding only in the ASCII count is not sufficient for a aligned tag
1080     // size, with the same text size in ASCII and Unicode.
1081 
1082     // Null strings
1083     if (len <= 0) {
1084 
1085         Text = (char*)    _cmsDupMem(self ->ContextID, "", sizeof(char));
1086         Wide = (wchar_t*) _cmsDupMem(self ->ContextID, L"", sizeof(wchar_t));
1087     }
1088     else {
1089         // Create independent buffers
1090         Text = (char*) _cmsCalloc(self ->ContextID, len, sizeof(char));
1091         if (Text == NULL) goto Error;
1092 
1093         Wide = (wchar_t*) _cmsCalloc(self ->ContextID, len, sizeof(wchar_t));
1094         if (Wide == NULL) goto Error;
1095 
1096         // Get both representations.
1097         cmsMLUgetASCII(mlu, cmsNoLanguage, cmsNoCountry,  Text, len * sizeof(char));
1098         cmsMLUgetWide(mlu,  cmsV2Unicode,  cmsV2Unicode,  Wide, len * sizeof(wchar_t));
1099     }
1100 
1101     // Tell the real text len including the null terminator and padding
1102     len_text = (cmsUInt32Number) strlen(Text) + 1;
1103     // Compute an total tag size requirement
1104     len_tag_requirement = (8+4+len_text+4+4+2*len_text+2+1+67);
1105     len_aligned = _cmsALIGNLONG(len_tag_requirement);
1106 
1107   // * cmsUInt32Number       count;          * Description length
1108   // * cmsInt8Number         desc[count]     * NULL terminated ascii string
1109   // * cmsUInt32Number       ucLangCode;     * UniCode language code
1110   // * cmsUInt32Number       ucCount;        * UniCode description length
1111   // * cmsInt16Number        ucDesc[ucCount];* The UniCode description
1112   // * cmsUInt16Number       scCode;         * ScriptCode code
1113   // * cmsUInt8Number        scCount;        * ScriptCode count
1114   // * cmsInt8Number         scDesc[67];     * ScriptCode Description
1115 
1116     if (!_cmsWriteUInt32Number(io, len_text)) goto Error;
1117     if (!io ->Write(io, len_text, Text)) goto Error;
1118 

1577         if (((Offset + Len) < Len) || ((Offset + Len) > SizeOfTag + 8)) goto Error;
1578 
1579         // True begin of the string
1580         BeginOfThisString = Offset - SizeOfHeader - 8;
1581 
1582         // Adjust to wchar_t elements
1583         mlu ->Entries[i].Len = (Len * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1584         mlu ->Entries[i].StrW = (BeginOfThisString * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1585 
1586         // To guess maximum size, add offset + len
1587         EndOfThisString = BeginOfThisString + Len;
1588         if (EndOfThisString > LargestPosition)
1589             LargestPosition = EndOfThisString;
1590     }
1591 
1592     // Now read the remaining of tag and fill all strings. Subtract the directory
1593     SizeOfTag   = (LargestPosition * sizeof(wchar_t)) / sizeof(cmsUInt16Number);
1594     if (SizeOfTag == 0)
1595     {
1596         Block = NULL;


1597     }
1598     else
1599     {
1600         // Make sure this is an even utf16 size.
1601         if (SizeOfTag & 1) goto Error;
1602 
1603         Block = (wchar_t*) _cmsCalloc(self ->ContextID, 1, SizeOfTag);
1604         if (Block == NULL) goto Error;
1605 
1606         NumOfWchar = SizeOfTag / sizeof(wchar_t);
1607         if (!_cmsReadWCharArray(io, NumOfWchar, Block)) {
1608             _cmsFree(self->ContextID, Block);
1609             goto Error;
1610         }
1611     }
1612 
1613     mlu ->MemPool  = Block;
1614     mlu ->PoolSize = SizeOfTag;
1615     mlu ->PoolUsed = SizeOfTag;
1616 

1938         }
1939         _cmsFree(self ->ContextID, T);
1940     }
1941 
1942 
1943     // Get output tables
1944     if (!Read8bitTables(self ->ContextID, io,  NewLUT, OutputChannels)) goto Error;
1945 
1946     *nItems = 1;
1947     return NewLUT;
1948 
1949 Error:
1950     if (NewLUT != NULL) cmsPipelineFree(NewLUT);
1951     return NULL;
1952 
1953     cmsUNUSED_PARAMETER(SizeOfTag);
1954 }
1955 
1956 // We only allow a specific MPE structure: Matrix plus prelin, plus clut, plus post-lin.
1957 static
1958 cmsBool Type_LUT8_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
1959 {
1960     cmsUInt32Number j, nTabSize, i;
1961     cmsUInt8Number  val;
1962     cmsPipeline* NewLUT = (cmsPipeline*) Ptr;
1963     cmsStage* mpe;
1964     _cmsStageToneCurvesData* PreMPE = NULL, *PostMPE = NULL;
1965     _cmsStageMatrixData* MatMPE = NULL;
1966     _cmsStageCLutData* clut = NULL;
1967     cmsUInt32Number clutPoints;
1968 
1969     // Disassemble the LUT into components.
1970     mpe = NewLUT -> Elements;
1971 
1972     if (mpe == NULL) {  // Should never be empty. Corrupted?
1973         cmsSignalError(self->ContextID, cmsERROR_UNKNOWN_EXTENSION, "empty LUT8 is not supported");
1974         return FALSE;
1975     }
1976 
1977     if (mpe ->Type == cmsSigMatrixElemType) {
1978 
1979         if (mpe->InputChannels != 3 || mpe->OutputChannels != 3) return FALSE;
1980         MatMPE = (_cmsStageMatrixData*) mpe ->Data;
1981         mpe = mpe -> Next;
1982     }
1983 
1984     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
1985         PreMPE = (_cmsStageToneCurvesData*) mpe ->Data;
1986         mpe = mpe -> Next;
1987     }
1988 
1989     if (mpe != NULL && mpe ->Type == cmsSigCLutElemType) {
1990         clut  = (_cmsStageCLutData*) mpe -> Data;
1991         mpe = mpe ->Next;
1992     }
1993 
1994     if (mpe != NULL && mpe ->Type == cmsSigCurveSetElemType) {
1995         PostMPE = (_cmsStageToneCurvesData*) mpe ->Data;
1996         mpe = mpe -> Next;

2698 }
2699 
2700 
2701 // Write a set of curves
2702 static
2703 cmsBool WriteSetOfCurves(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsTagTypeSignature Type, cmsStage* mpe)
2704 {
2705     cmsUInt32Number i, n;
2706     cmsTagTypeSignature CurrentType;
2707     cmsToneCurve** Curves;
2708 
2709 
2710     n      = cmsStageOutputChannels(mpe);
2711     Curves = _cmsStageGetPtrToCurveSet(mpe);
2712 
2713     for (i=0; i < n; i++) {
2714 
2715         // If this is a table-based curve, use curve type even on V4
2716         CurrentType = Type;
2717 
2718         if ((Curves[i] ->nSegments == 0) ||                                         // 16 bits tabulated
2719             ((Curves[i]->nSegments == 3) && (Curves[i] ->Segments[1].Type == 0)) )  // Floating-point tabulated
2720             CurrentType = cmsSigCurveType;
2721         else
2722         if (Curves[i] ->Segments[0].Type < 0)
2723             CurrentType = cmsSigCurveType;
2724 
2725         if (!_cmsWriteTypeBase(io, CurrentType)) return FALSE;
2726 
2727         switch (CurrentType) {
2728 
2729             case cmsSigCurveType:
2730                 if (!Type_Curve_Write(self, io, Curves[i], 1)) return FALSE;
2731                 break;
2732 
2733             case cmsSigParametricCurveType:
2734                 if (!Type_ParametricCurve_Write(self, io, Curves[i], 1)) return FALSE;
2735                 break;
2736 
2737             default:
2738                 {
2739                     char String[5];

4463     return TRUE;
4464 
4465     cmsUNUSED_PARAMETER(nItems);
4466     cmsUNUSED_PARAMETER(self);
4467 }
4468 
4469 
4470 
4471 static
4472 void *Type_MPEclut_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
4473 {
4474     cmsStage* mpe = NULL;
4475     cmsUInt16Number InputChans, OutputChans;
4476     cmsUInt8Number Dimensions8[16];
4477     cmsUInt32Number i, nMaxGrids, GridPoints[MAX_INPUT_DIMENSIONS];
4478     _cmsStageCLutData* clut;
4479 
4480     if (!_cmsReadUInt16Number(io, &InputChans)) return NULL;
4481     if (!_cmsReadUInt16Number(io, &OutputChans)) return NULL;
4482 
4483     if (InputChans == 0 || InputChans >= cmsMAXCHANNELS) goto Error;
4484     if (OutputChans == 0 || OutputChans >= cmsMAXCHANNELS) goto Error;
4485 
4486     if (io ->Read(io, Dimensions8, sizeof(cmsUInt8Number), 16) != 16)
4487         goto Error;
4488 
4489     // Copy MAX_INPUT_DIMENSIONS at most. Expand to cmsUInt32Number
4490     nMaxGrids = InputChans > MAX_INPUT_DIMENSIONS ? (cmsUInt32Number) MAX_INPUT_DIMENSIONS : InputChans;
4491 
4492     for (i = 0; i < nMaxGrids; i++) {
4493         if (Dimensions8[i] == 1) goto Error; // Impossible value, 0 for no CLUT and then 2 at least
4494         GridPoints[i] = (cmsUInt32Number)Dimensions8[i];
4495     }
4496 
4497     // Allocate the true CLUT
4498     mpe = cmsStageAllocCLutFloatGranular(self ->ContextID, GridPoints, InputChans, OutputChans, NULL);
4499     if (mpe == NULL) goto Error;
4500 
4501     // Read and sanitize the data
4502     clut = (_cmsStageCLutData*) mpe ->Data;
4503     for (i=0; i < clut ->nEntries; i++) {
4504 

5254     if (!io -> Seek(io, e -> Offsets[i])) return FALSE;
5255 
5256     *mlu = (cmsMLU*) Type_MLU_Read(self, io, &nItems, e ->Sizes[i]);
5257     return *mlu != NULL;
5258 }
5259 
5260 static
5261 cmsBool WriteOneMLUC(struct _cms_typehandler_struct* self, cmsIOHANDLER* io,  _cmsDICelem* e, cmsUInt32Number i, const cmsMLU* mlu, cmsUInt32Number BaseOffset)
5262 {
5263     cmsUInt32Number Before;
5264 
5265      // Special case for undefined strings (see ICC Votable
5266      // Proposal Submission, Dictionary Type and Metadata TAG Definition)
5267      if (mlu == NULL) {
5268         e ->Sizes[i] = 0;
5269         e ->Offsets[i] = 0;
5270         return TRUE;
5271     }
5272 
5273     Before = io ->Tell(io);
5274     if (e->Offsets != NULL)
5275         e ->Offsets[i] = Before - BaseOffset;
5276 
5277     if (!Type_MLU_Write(self, io, (void*) mlu, 1)) return FALSE;
5278 
5279     if (e->Sizes != NULL)
5280         e ->Sizes[i] = io ->Tell(io) - Before;
5281     return TRUE;
5282 }
5283 
5284 
5285 static
5286 void *Type_Dictionary_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
5287 {
5288    cmsHANDLE hDict = NULL;
5289    cmsUInt32Number i, Count, Length;
5290    cmsUInt32Number BaseOffset;
5291    _cmsDICarray a;
5292    wchar_t *NameWCS = NULL, *ValueWCS = NULL;
5293    cmsMLU *DisplayNameMLU = NULL, *DisplayValueMLU=NULL;
5294    cmsBool rc;
5295    cmsInt32Number SignedSizeOfTag = (cmsInt32Number)SizeOfTag;
5296 
5297     *nItems = 0;
5298     memset(&a, 0, sizeof(a));
5299 
5300     // Get actual position as a basis for element offsets

5505     return TRUE;
5506 
5507     cmsUNUSED_PARAMETER(self);
5508     cmsUNUSED_PARAMETER(nItems);
5509 }
5510 
5511 void* Type_VideoSignal_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
5512 {
5513     return _cmsDupMem(self->ContextID, Ptr, sizeof(cmsVideoSignalType));
5514 
5515     cmsUNUSED_PARAMETER(n);
5516 }
5517 
5518 
5519 static
5520 void Type_VideoSignal_Free(struct _cms_typehandler_struct* self, void* Ptr)
5521 {
5522     _cmsFree(self->ContextID, Ptr);
5523 }
5524 
5525 
5526 // ********************************************************************************
5527 // Microsoft's MHC2 Type support
5528 // ********************************************************************************
5529 
5530 static
5531 void SetIdentity(cmsFloat64Number XYZ2XYZmatrix[3][4])
5532 {
5533     XYZ2XYZmatrix[0][0] = 1.0; XYZ2XYZmatrix[0][1] = 0.0; XYZ2XYZmatrix[0][2] = 0.0; XYZ2XYZmatrix[0][3] = 0.0;
5534     XYZ2XYZmatrix[1][0] = 0.0; XYZ2XYZmatrix[1][1] = 1.0; XYZ2XYZmatrix[1][2] = 0.0; XYZ2XYZmatrix[1][3] = 0.0;
5535     XYZ2XYZmatrix[2][0] = 0.0; XYZ2XYZmatrix[2][1] = 0.0; XYZ2XYZmatrix[2][2] = 1.0; XYZ2XYZmatrix[2][3] = 0.0;
5536 }
5537 
5538 static
5539 cmsBool CloseEnough(cmsFloat64Number a, cmsFloat64Number b)
5540 {
5541     return fabs(b - a) < (1.0 / 65535.0);
5542 }
5543 
5544 cmsBool IsIdentity(cmsFloat64Number XYZ2XYZmatrix[3][4])
5545 {
5546     cmsFloat64Number Identity[3][4];
5547     int i, j;
5548 
5549     SetIdentity(Identity);
5550 
5551     for (i = 0; i < 3; i++)
5552         for (j = 0; j < 4; j++)
5553             if (!CloseEnough(XYZ2XYZmatrix[i][j], Identity[i][j])) return FALSE;
5554 
5555     return TRUE;
5556 }
5557 
5558 static
5559 void Type_MHC2_Free(struct _cms_typehandler_struct* self, void* Ptr)
5560 {
5561     cmsMHC2Type* mhc2 = (cmsMHC2Type*)Ptr;
5562 
5563     if (mhc2->RedCurve != NULL) _cmsFree(self->ContextID, mhc2->RedCurve);
5564     if (mhc2->GreenCurve != NULL) _cmsFree(self->ContextID, mhc2->GreenCurve);
5565     if (mhc2->BlueCurve != NULL) _cmsFree(self->ContextID, mhc2->BlueCurve);
5566 
5567     _cmsFree(self->ContextID, Ptr);
5568 }
5569 
5570 void* Type_MHC2_Dup(struct _cms_typehandler_struct* self, const void* Ptr, cmsUInt32Number n)
5571 {
5572     cmsMHC2Type* mhc2 = _cmsDupMem(self->ContextID, Ptr, sizeof(cmsMHC2Type));
5573 
5574     mhc2->RedCurve = _cmsDupMem(self->ContextID,   mhc2->RedCurve, mhc2->CurveEntries*sizeof(cmsFloat64Number));
5575     mhc2->GreenCurve = _cmsDupMem(self->ContextID, mhc2->GreenCurve, mhc2->CurveEntries * sizeof(cmsFloat64Number));
5576     mhc2->BlueCurve = _cmsDupMem(self->ContextID,  mhc2->BlueCurve, mhc2->CurveEntries * sizeof(cmsFloat64Number));
5577 
5578     if (mhc2->RedCurve == NULL ||
5579         mhc2->GreenCurve == NULL ||
5580         mhc2->BlueCurve == NULL) {
5581 
5582         Type_MHC2_Free(self, mhc2);
5583         return NULL;
5584     }
5585 
5586     return mhc2;
5587 
5588     cmsUNUSED_PARAMETER(n);
5589 }
5590 
5591 
5592 static
5593 cmsBool WriteDoubles(cmsIOHANDLER* io, cmsUInt32Number n, cmsFloat64Number* Values)
5594 {
5595     cmsUInt32Number i;
5596 
5597     for (i = 0; i < n; i++) {
5598 
5599         if (!_cmsWrite15Fixed16Number(io, *Values++)) return FALSE;
5600     }
5601 
5602     return TRUE;
5603 }
5604 
5605 static
5606 cmsBool Type_MHC2_Write(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, void* Ptr, cmsUInt32Number nItems)
5607 {
5608     cmsMHC2Type* mhc2 = (cmsMHC2Type*)Ptr;
5609     cmsUInt32Number BaseOffset = io->Tell(io) - sizeof(_cmsTagBase);
5610     cmsUInt32Number TablesOffsetPos;
5611     cmsUInt32Number MatrixOffset;
5612     cmsUInt32Number OffsetRedTable, OffsetGreenTable, OffsetBlueTable;
5613 
5614     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;
5615     if (!_cmsWriteUInt32Number(io, mhc2->CurveEntries)) return FALSE;
5616 
5617     if (!_cmsWrite15Fixed16Number(io, mhc2->MinLuminance)) return FALSE;
5618     if (!_cmsWrite15Fixed16Number(io, mhc2->PeakLuminance)) return FALSE;
5619 
5620     TablesOffsetPos = io->Tell(io);
5621 
5622     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;    // Matrix
5623     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;    // Curve R
5624     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;    // Curve G
5625     if (!_cmsWriteUInt32Number(io, 0)) return FALSE;    // Curve B
5626 
5627 
5628     if (IsIdentity(mhc2->XYZ2XYZmatrix))
5629     {
5630         MatrixOffset = 0;
5631     }
5632     else
5633     {
5634         MatrixOffset = io->Tell(io) - BaseOffset;
5635         if (!WriteDoubles(io, 3 * 4, &mhc2->XYZ2XYZmatrix[0][0])) return FALSE;
5636     }
5637 
5638     OffsetRedTable = io->Tell(io) - BaseOffset;
5639     if (!WriteDoubles(io, mhc2->CurveEntries, mhc2->RedCurve)) return FALSE;
5640     OffsetGreenTable = io->Tell(io) - BaseOffset;
5641     if (!WriteDoubles(io, mhc2->CurveEntries, mhc2->GreenCurve)) return FALSE;
5642     OffsetBlueTable = io->Tell(io) - BaseOffset;
5643     if (!WriteDoubles(io, mhc2->CurveEntries, mhc2->BlueCurve)) return FALSE;
5644 
5645     if (!io->Seek(io, TablesOffsetPos)) return FALSE;
5646 
5647     if (!_cmsWriteUInt32Number(io, MatrixOffset)) return FALSE;
5648     if (!_cmsWriteUInt32Number(io, OffsetRedTable)) return FALSE;
5649     if (!_cmsWriteUInt32Number(io, OffsetGreenTable)) return FALSE;
5650     if (!_cmsWriteUInt32Number(io, OffsetBlueTable)) return FALSE;
5651 
5652     return TRUE;
5653 
5654     cmsUNUSED_PARAMETER(self);
5655     cmsUNUSED_PARAMETER(nItems);
5656 }
5657 
5658 
5659 static
5660 cmsBool ReadDoublesAt(cmsIOHANDLER* io, cmsUInt32Number At, cmsUInt32Number n, cmsFloat64Number* Values)
5661 {
5662     cmsUInt32Number CurrentPos = io->Tell(io);
5663     cmsUInt32Number i;
5664 
5665     if (!io->Seek(io, At)) return FALSE;
5666 
5667     for (i = 0; i < n; i++) {
5668 
5669         if (!_cmsRead15Fixed16Number(io, Values++)) return FALSE;
5670     }
5671 
5672     if (!io->Seek(io, CurrentPos)) return FALSE;
5673 
5674     return TRUE;
5675 }
5676 
5677 static
5678 void* Type_MHC2_Read(struct _cms_typehandler_struct* self, cmsIOHANDLER* io, cmsUInt32Number* nItems, cmsUInt32Number SizeOfTag)
5679 {
5680     cmsMHC2Type* mhc2 = NULL;
5681 
5682     cmsUInt32Number BaseOffset = io->Tell(io) - sizeof(_cmsTagBase);
5683     cmsUInt32Number MatrixOffset;
5684     cmsUInt32Number OffsetRedTable, OffsetGreenTable, OffsetBlueTable;
5685 
5686     if (!_cmsReadUInt32Number(io, NULL)) return NULL;
5687 
5688     mhc2 = (cmsMHC2Type*)_cmsCalloc(self->ContextID, 1, sizeof(cmsMHC2Type));
5689     if (mhc2 == NULL) return NULL;
5690 
5691     if (!_cmsReadUInt32Number(io,    &mhc2->CurveEntries)) goto Error;
5692 
5693     if (mhc2->CurveEntries > 4096) goto Error;
5694 
5695     mhc2->RedCurve = (cmsFloat64Number*)_cmsCalloc(self->ContextID, mhc2->CurveEntries, sizeof(cmsFloat64Number));
5696     mhc2->GreenCurve = (cmsFloat64Number*)_cmsCalloc(self->ContextID, mhc2->CurveEntries, sizeof(cmsFloat64Number));
5697     mhc2->BlueCurve = (cmsFloat64Number*)_cmsCalloc(self->ContextID, mhc2->CurveEntries, sizeof(cmsFloat64Number));
5698 
5699     if (mhc2->RedCurve == NULL ||
5700         mhc2->GreenCurve == NULL ||
5701         mhc2->BlueCurve == NULL)  goto Error;
5702 
5703     if (!_cmsRead15Fixed16Number(io, &mhc2->MinLuminance)) goto Error;
5704     if (!_cmsRead15Fixed16Number(io, &mhc2->PeakLuminance)) goto Error;
5705 
5706     if (!_cmsReadUInt32Number(io, &MatrixOffset)) goto Error;
5707     if (!_cmsReadUInt32Number(io, &OffsetRedTable)) goto Error;
5708     if (!_cmsReadUInt32Number(io, &OffsetGreenTable)) goto Error;
5709     if (!_cmsReadUInt32Number(io, &OffsetBlueTable)) goto Error;
5710 
5711     if (MatrixOffset == 0)
5712         SetIdentity(mhc2->XYZ2XYZmatrix);
5713     else
5714     {
5715         if (!ReadDoublesAt(io, BaseOffset + MatrixOffset, 3*4, &mhc2->XYZ2XYZmatrix[0][0])) goto Error;
5716     }
5717 
5718     if (!ReadDoublesAt(io, BaseOffset + OffsetRedTable, mhc2->CurveEntries, mhc2->RedCurve)) goto Error;
5719     if (!ReadDoublesAt(io, BaseOffset + OffsetGreenTable, mhc2->CurveEntries, mhc2->GreenCurve)) goto Error;
5720     if (!ReadDoublesAt(io, BaseOffset + OffsetBlueTable, mhc2->CurveEntries, mhc2->BlueCurve)) goto Error;
5721 
5722     // Success
5723     *nItems = 1;
5724     return mhc2;
5725 
5726 Error:
5727     Type_MHC2_Free(self, mhc2);
5728     return NULL;
5729 
5730     cmsUNUSED_PARAMETER(SizeOfTag);
5731 }
5732 
5733 
5734 
5735 // ********************************************************************************
5736 // Type support main routines
5737 // ********************************************************************************
5738 
5739 
5740 // This is the list of built-in types
5741 static const _cmsTagTypeLinkedList SupportedTagTypes[] = {
5742 
5743 {TYPE_HANDLER(cmsSigChromaticityType,          Chromaticity),       (_cmsTagTypeLinkedList*) &SupportedTagTypes[1] },
5744 {TYPE_HANDLER(cmsSigColorantOrderType,         ColorantOrderType),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[2] },
5745 {TYPE_HANDLER(cmsSigS15Fixed16ArrayType,       S15Fixed16),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[3] },
5746 {TYPE_HANDLER(cmsSigU16Fixed16ArrayType,       U16Fixed16),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[4] },
5747 {TYPE_HANDLER(cmsSigTextType,                  Text),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[5] },
5748 {TYPE_HANDLER(cmsSigTextDescriptionType,       Text_Description),   (_cmsTagTypeLinkedList*) &SupportedTagTypes[6] },
5749 {TYPE_HANDLER(cmsSigCurveType,                 Curve),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[7] },
5750 {TYPE_HANDLER(cmsSigParametricCurveType,       ParametricCurve),    (_cmsTagTypeLinkedList*) &SupportedTagTypes[8] },
5751 {TYPE_HANDLER(cmsSigDateTimeType,              DateTime),           (_cmsTagTypeLinkedList*) &SupportedTagTypes[9] },
5752 {TYPE_HANDLER(cmsSigLut8Type,                  LUT8),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[10] },
5753 {TYPE_HANDLER(cmsSigLut16Type,                 LUT16),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[11] },
5754 {TYPE_HANDLER(cmsSigColorantTableType,         ColorantTable),      (_cmsTagTypeLinkedList*) &SupportedTagTypes[12] },
5755 {TYPE_HANDLER(cmsSigNamedColor2Type,           NamedColor),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[13] },
5756 {TYPE_HANDLER(cmsSigMultiLocalizedUnicodeType, MLU),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[14] },
5757 {TYPE_HANDLER(cmsSigProfileSequenceDescType,   ProfileSequenceDesc),(_cmsTagTypeLinkedList*) &SupportedTagTypes[15] },
5758 {TYPE_HANDLER(cmsSigSignatureType,             Signature),          (_cmsTagTypeLinkedList*) &SupportedTagTypes[16] },
5759 {TYPE_HANDLER(cmsSigMeasurementType,           Measurement),        (_cmsTagTypeLinkedList*) &SupportedTagTypes[17] },
5760 {TYPE_HANDLER(cmsSigDataType,                  Data),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[18] },
5761 {TYPE_HANDLER(cmsSigLutAtoBType,               LUTA2B),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[19] },
5762 {TYPE_HANDLER(cmsSigLutBtoAType,               LUTB2A),             (_cmsTagTypeLinkedList*) &SupportedTagTypes[20] },
5763 {TYPE_HANDLER(cmsSigUcrBgType,                 UcrBg),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[21] },
5764 {TYPE_HANDLER(cmsSigCrdInfoType,               CrdInfo),            (_cmsTagTypeLinkedList*) &SupportedTagTypes[22] },
5765 {TYPE_HANDLER(cmsSigMultiProcessElementType,   MPE),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[23] },
5766 {TYPE_HANDLER(cmsSigScreeningType,             Screening),          (_cmsTagTypeLinkedList*) &SupportedTagTypes[24] },
5767 {TYPE_HANDLER(cmsSigViewingConditionsType,     ViewingConditions),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[25] },
5768 {TYPE_HANDLER(cmsSigXYZType,                   XYZ),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[26] },
5769 {TYPE_HANDLER(cmsCorbisBrokenXYZtype,          XYZ),                (_cmsTagTypeLinkedList*) &SupportedTagTypes[27] },
5770 {TYPE_HANDLER(cmsMonacoBrokenCurveType,        Curve),              (_cmsTagTypeLinkedList*) &SupportedTagTypes[28] },
5771 {TYPE_HANDLER(cmsSigProfileSequenceIdType,     ProfileSequenceId),  (_cmsTagTypeLinkedList*) &SupportedTagTypes[29] },
5772 {TYPE_HANDLER(cmsSigDictType,                  Dictionary),         (_cmsTagTypeLinkedList*) &SupportedTagTypes[30] },
5773 {TYPE_HANDLER(cmsSigcicpType,                  VideoSignal),        (_cmsTagTypeLinkedList*) &SupportedTagTypes[31] },
5774 {TYPE_HANDLER(cmsSigVcgtType,                  vcgt),               (_cmsTagTypeLinkedList*) &SupportedTagTypes[32] },
5775 {TYPE_HANDLER(cmsSigMHC2Type,                  MHC2),                NULL }
5776 };
5777 
5778 
5779 _cmsTagTypePluginChunkType _cmsTagTypePluginChunk = { NULL };
5780 
5781 
5782 
5783 // Duplicates the zone of memory used by the plug-in in the new context
5784 static
5785 void DupTagTypeList(struct _cmsContext_struct* ctx,
5786                     const struct _cmsContext_struct* src,
5787                     int loc)
5788 {
5789    _cmsTagTypePluginChunkType newHead = { NULL };
5790    _cmsTagTypeLinkedList*  entry;
5791    _cmsTagTypeLinkedList*  Anterior = NULL;
5792    _cmsTagTypePluginChunkType* head = (_cmsTagTypePluginChunkType*) src->chunks[loc];
5793 
5794    // Walk the list copying all nodes
5795    for (entry = head->TagTypes;

5951     { cmsSigDToB0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[49]},
5952     { cmsSigDToB1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[50]},
5953     { cmsSigDToB2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[51]},
5954     { cmsSigDToB3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[52]},
5955     { cmsSigBToD0Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[53]},
5956     { cmsSigBToD1Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[54]},
5957     { cmsSigBToD2Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[55]},
5958     { cmsSigBToD3Tag,               { 1, 1, { cmsSigMultiProcessElementType}, NULL}, &SupportedTags[56]},
5959 
5960     { cmsSigScreeningDescTag,       { 1, 1, { cmsSigTextDescriptionType },    NULL}, &SupportedTags[57]},
5961     { cmsSigViewingConditionsTag,   { 1, 1, { cmsSigViewingConditionsType },  NULL}, &SupportedTags[58]},
5962 
5963     { cmsSigScreeningTag,           { 1, 1, { cmsSigScreeningType},          NULL }, &SupportedTags[59]},
5964     { cmsSigVcgtTag,                { 1, 1, { cmsSigVcgtType},               NULL }, &SupportedTags[60]},
5965     { cmsSigMetaTag,                { 1, 1, { cmsSigDictType},               NULL }, &SupportedTags[61]},
5966     { cmsSigProfileSequenceIdTag,   { 1, 1, { cmsSigProfileSequenceIdType},  NULL }, &SupportedTags[62]},
5967 
5968     { cmsSigProfileDescriptionMLTag,{ 1, 1, { cmsSigMultiLocalizedUnicodeType}, NULL}, &SupportedTags[63]},
5969     { cmsSigcicpTag,                { 1, 1, { cmsSigcicpType},               NULL },   &SupportedTags[64]},
5970 
5971     { cmsSigArgyllArtsTag,          { 9, 1, { cmsSigS15Fixed16ArrayType},    NULL}, &SupportedTags[65]},
5972     { cmsSigMHC2Tag,                { 1, 1, { cmsSigMHC2Type },              NULL}, NULL}
5973 
5974 };
5975 
5976 /*
5977     Not supported                 Why
5978     =======================       =========================================
5979     cmsSigOutputResponseTag   ==> WARNING, POSSIBLE PATENT ON THIS SUBJECT!
5980     cmsSigNamedColorTag       ==> Deprecated
5981     cmsSigDataTag             ==> Ancient, unused
5982     cmsSigDeviceSettingsTag   ==> Deprecated, useless
5983 */
5984 
5985 
5986 _cmsTagPluginChunkType _cmsTagPluginChunk = { NULL };
5987 
5988 
5989 // Duplicates the zone of memory used by the plug-in in the new context
5990 static
5991 void DupTagList(struct _cmsContext_struct* ctx,
5992                     const struct _cmsContext_struct* src)
< prev index next >