Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/java2d/cmm/lcms/cmsplugin.c
38918 views
/*1* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.2*3* This code is free software; you can redistribute it and/or modify it4* under the terms of the GNU General Public License version 2 only, as5* published by the Free Software Foundation. Oracle designates this6* particular file as subject to the "Classpath" exception as provided7* by Oracle in the LICENSE file that accompanied this code.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 2 along with this work; if not, write to the Free Software Foundation,17* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.18*19* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*/2324// This file is available under and governed by the GNU General Public25// License version 2 only, as published by the Free Software Foundation.26// However, the following notice accompanied the original version of this27// file:28//29//---------------------------------------------------------------------------------30//31// Little Color Management System32// Copyright (c) 1998-2020 Marti Maria Saguer33//34// Permission is hereby granted, free of charge, to any person obtaining35// a copy of this software and associated documentation files (the "Software"),36// to deal in the Software without restriction, including without limitation37// the rights to use, copy, modify, merge, publish, distribute, sublicense,38// and/or sell copies of the Software, and to permit persons to whom the Software39// is furnished to do so, subject to the following conditions:40//41// The above copyright notice and this permission notice shall be included in42// all copies or substantial portions of the Software.43//44// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,45// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO46// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND47// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE48// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION49// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION50// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.51//52//---------------------------------------------------------------------------------53//5455#include "lcms2_internal.h"565758// ----------------------------------------------------------------------------------59// Encoding & Decoding support functions60// ----------------------------------------------------------------------------------6162// Little-Endian to Big-Endian6364// Adjust a word value after being read/ before being written from/to an ICC profile65cmsUInt16Number CMSEXPORT _cmsAdjustEndianess16(cmsUInt16Number Word)66{67#ifndef CMS_USE_BIG_ENDIAN6869cmsUInt8Number* pByte = (cmsUInt8Number*) &Word;70cmsUInt8Number tmp;7172tmp = pByte[0];73pByte[0] = pByte[1];74pByte[1] = tmp;75#endif7677return Word;78}798081// Transports to properly encoded values - note that icc profiles does use big endian notation.8283// 1 2 3 484// 4 3 2 18586cmsUInt32Number CMSEXPORT _cmsAdjustEndianess32(cmsUInt32Number DWord)87{88#ifndef CMS_USE_BIG_ENDIAN8990cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord;91cmsUInt8Number temp1;92cmsUInt8Number temp2;9394temp1 = *pByte++;95temp2 = *pByte++;96*(pByte-1) = *pByte;97*pByte++ = temp2;98*(pByte-3) = *pByte;99*pByte = temp1;100#endif101return DWord;102}103104// 1 2 3 4 5 6 7 8105// 8 7 6 5 4 3 2 1106107void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* QWord)108{109110#ifndef CMS_USE_BIG_ENDIAN111112cmsUInt8Number* pIn = (cmsUInt8Number*) QWord;113cmsUInt8Number* pOut = (cmsUInt8Number*) Result;114115_cmsAssert(Result != NULL);116117pOut[7] = pIn[0];118pOut[6] = pIn[1];119pOut[5] = pIn[2];120pOut[4] = pIn[3];121pOut[3] = pIn[4];122pOut[2] = pIn[5];123pOut[1] = pIn[6];124pOut[0] = pIn[7];125126#else127_cmsAssert(Result != NULL);128129# ifdef CMS_DONT_USE_INT64130(*Result)[0] = (*QWord)[0];131(*Result)[1] = (*QWord)[1];132# else133*Result = *QWord;134# endif135#endif136}137138// Auxiliary -- read 8, 16 and 32-bit numbers139cmsBool CMSEXPORT _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n)140{141cmsUInt8Number tmp;142143_cmsAssert(io != NULL);144145if (io -> Read(io, &tmp, sizeof(cmsUInt8Number), 1) != 1)146return FALSE;147148if (n != NULL) *n = tmp;149return TRUE;150}151152cmsBool CMSEXPORT _cmsReadUInt16Number(cmsIOHANDLER* io, cmsUInt16Number* n)153{154cmsUInt16Number tmp;155156_cmsAssert(io != NULL);157158if (io -> Read(io, &tmp, sizeof(cmsUInt16Number), 1) != 1)159return FALSE;160161if (n != NULL) *n = _cmsAdjustEndianess16(tmp);162return TRUE;163}164165cmsBool CMSEXPORT _cmsReadUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, cmsUInt16Number* Array)166{167cmsUInt32Number i;168169_cmsAssert(io != NULL);170171for (i=0; i < n; i++) {172173if (Array != NULL) {174if (!_cmsReadUInt16Number(io, Array + i)) return FALSE;175}176else {177if (!_cmsReadUInt16Number(io, NULL)) return FALSE;178}179180}181return TRUE;182}183184cmsBool CMSEXPORT _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n)185{186cmsUInt32Number tmp;187188_cmsAssert(io != NULL);189190if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)191return FALSE;192193if (n != NULL) *n = _cmsAdjustEndianess32(tmp);194return TRUE;195}196197cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n)198{199cmsUInt32Number tmp;200201_cmsAssert(io != NULL);202203if (io->Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)204return FALSE;205206if (n != NULL) {207208tmp = _cmsAdjustEndianess32(tmp);209*n = *(cmsFloat32Number*)(void*)&tmp;210211// Safeguard which covers against absurd values212if (*n > 1E+20 || *n < -1E+20) return FALSE;213214#if defined(_MSC_VER) && _MSC_VER < 1800215return TRUE;216#elif defined (__BORLANDC__)217return TRUE;218#elif !defined(_MSC_VER) && (defined(__STDC_VERSION__) && __STDC_VERSION__ < 199901L)219return TRUE;220#else221222// fpclassify() required by C99 (only provided by MSVC >= 1800, VS2013 onwards)223return ((fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL));224#endif225}226227return TRUE;228}229230231cmsBool CMSEXPORT _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)232{233cmsUInt64Number tmp;234235_cmsAssert(io != NULL);236237if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1)238return FALSE;239240if (n != NULL) {241242_cmsAdjustEndianess64(n, &tmp);243}244245return TRUE;246}247248249cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n)250{251cmsUInt32Number tmp;252253_cmsAssert(io != NULL);254255if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)256return FALSE;257258if (n != NULL) {259*n = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32(tmp));260}261262return TRUE;263}264265266cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ)267{268cmsEncodedXYZNumber xyz;269270_cmsAssert(io != NULL);271272if (io ->Read(io, &xyz, sizeof(cmsEncodedXYZNumber), 1) != 1) return FALSE;273274if (XYZ != NULL) {275276XYZ->X = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.X));277XYZ->Y = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.Y));278XYZ->Z = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.Z));279}280return TRUE;281}282283cmsBool CMSEXPORT _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n)284{285_cmsAssert(io != NULL);286287if (io -> Write(io, sizeof(cmsUInt8Number), &n) != 1)288return FALSE;289290return TRUE;291}292293cmsBool CMSEXPORT _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n)294{295cmsUInt16Number tmp;296297_cmsAssert(io != NULL);298299tmp = _cmsAdjustEndianess16(n);300if (io -> Write(io, sizeof(cmsUInt16Number), &tmp) != 1)301return FALSE;302303return TRUE;304}305306cmsBool CMSEXPORT _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array)307{308cmsUInt32Number i;309310_cmsAssert(io != NULL);311_cmsAssert(Array != NULL);312313for (i=0; i < n; i++) {314if (!_cmsWriteUInt16Number(io, Array[i])) return FALSE;315}316317return TRUE;318}319320cmsBool CMSEXPORT _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n)321{322cmsUInt32Number tmp;323324_cmsAssert(io != NULL);325326tmp = _cmsAdjustEndianess32(n);327if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)328return FALSE;329330return TRUE;331}332333334cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n)335{336cmsUInt32Number tmp;337338_cmsAssert(io != NULL);339340tmp = *(cmsUInt32Number*) (void*) &n;341tmp = _cmsAdjustEndianess32(tmp);342if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)343return FALSE;344345return TRUE;346}347348cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)349{350cmsUInt64Number tmp;351352_cmsAssert(io != NULL);353354_cmsAdjustEndianess64(&tmp, n);355if (io -> Write(io, sizeof(cmsUInt64Number), &tmp) != 1)356return FALSE;357358return TRUE;359}360361cmsBool CMSEXPORT _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n)362{363cmsUInt32Number tmp;364365_cmsAssert(io != NULL);366367tmp = _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(n));368if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)369return FALSE;370371return TRUE;372}373374cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ)375{376cmsEncodedXYZNumber xyz;377378_cmsAssert(io != NULL);379_cmsAssert(XYZ != NULL);380381xyz.X = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->X));382xyz.Y = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->Y));383xyz.Z = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->Z));384385return io -> Write(io, sizeof(cmsEncodedXYZNumber), &xyz);386}387388// from Fixed point 8.8 to double389cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8)390{391cmsUInt8Number msb, lsb;392393lsb = (cmsUInt8Number) (fixed8 & 0xff);394msb = (cmsUInt8Number) (((cmsUInt16Number) fixed8 >> 8) & 0xff);395396return (cmsFloat64Number) ((cmsFloat64Number) msb + ((cmsFloat64Number) lsb / 256.0));397}398399cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val)400{401cmsS15Fixed16Number GammaFixed32 = _cmsDoubleTo15Fixed16(val);402return (cmsUInt16Number) ((GammaFixed32 >> 8) & 0xFFFF);403}404405// from Fixed point 15.16 to double406cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32)407{408cmsFloat64Number floater, sign, mid;409int Whole, FracPart;410411sign = (fix32 < 0 ? -1 : 1);412fix32 = abs(fix32);413414Whole = (cmsUInt16Number)(fix32 >> 16) & 0xffff;415FracPart = (cmsUInt16Number)(fix32 & 0xffff);416417mid = (cmsFloat64Number) FracPart / 65536.0;418floater = (cmsFloat64Number) Whole + mid;419420return sign * floater;421}422423// from double to Fixed point 15.16424cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v)425{426return ((cmsS15Fixed16Number) floor((v)*65536.0 + 0.5));427}428429// Date/Time functions430431void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest)432{433434_cmsAssert(Dest != NULL);435_cmsAssert(Source != NULL);436437Dest->tm_sec = _cmsAdjustEndianess16(Source->seconds);438Dest->tm_min = _cmsAdjustEndianess16(Source->minutes);439Dest->tm_hour = _cmsAdjustEndianess16(Source->hours);440Dest->tm_mday = _cmsAdjustEndianess16(Source->day);441Dest->tm_mon = _cmsAdjustEndianess16(Source->month) - 1;442Dest->tm_year = _cmsAdjustEndianess16(Source->year) - 1900;443Dest->tm_wday = -1;444Dest->tm_yday = -1;445Dest->tm_isdst = 0;446}447448void CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source)449{450_cmsAssert(Dest != NULL);451_cmsAssert(Source != NULL);452453Dest->seconds = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_sec);454Dest->minutes = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_min);455Dest->hours = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_hour);456Dest->day = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_mday);457Dest->month = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_mon + 1));458Dest->year = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_year + 1900));459}460461// Read base and return type base462cmsTagTypeSignature CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io)463{464_cmsTagBase Base;465466_cmsAssert(io != NULL);467468if (io -> Read(io, &Base, sizeof(_cmsTagBase), 1) != 1)469return (cmsTagTypeSignature) 0;470471return (cmsTagTypeSignature) _cmsAdjustEndianess32(Base.sig);472}473474// Setup base marker475cmsBool CMSEXPORT _cmsWriteTypeBase(cmsIOHANDLER* io, cmsTagTypeSignature sig)476{477_cmsTagBase Base;478479_cmsAssert(io != NULL);480481Base.sig = (cmsTagTypeSignature) _cmsAdjustEndianess32(sig);482memset(&Base.reserved, 0, sizeof(Base.reserved));483return io -> Write(io, sizeof(_cmsTagBase), &Base);484}485486cmsBool CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io)487{488cmsUInt8Number Buffer[4];489cmsUInt32Number NextAligned, At;490cmsUInt32Number BytesToNextAlignedPos;491492_cmsAssert(io != NULL);493494At = io -> Tell(io);495NextAligned = _cmsALIGNLONG(At);496BytesToNextAlignedPos = NextAligned - At;497if (BytesToNextAlignedPos == 0) return TRUE;498if (BytesToNextAlignedPos > 4) return FALSE;499500return (io ->Read(io, Buffer, BytesToNextAlignedPos, 1) == 1);501}502503cmsBool CMSEXPORT _cmsWriteAlignment(cmsIOHANDLER* io)504{505cmsUInt8Number Buffer[4];506cmsUInt32Number NextAligned, At;507cmsUInt32Number BytesToNextAlignedPos;508509_cmsAssert(io != NULL);510511At = io -> Tell(io);512NextAligned = _cmsALIGNLONG(At);513BytesToNextAlignedPos = NextAligned - At;514if (BytesToNextAlignedPos == 0) return TRUE;515if (BytesToNextAlignedPos > 4) return FALSE;516517memset(Buffer, 0, BytesToNextAlignedPos);518return io -> Write(io, BytesToNextAlignedPos, Buffer);519}520521522// To deal with text streams. 2K at most523cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)524{525va_list args;526int len;527cmsUInt8Number Buffer[2048];528cmsBool rc;529530_cmsAssert(io != NULL);531_cmsAssert(frm != NULL);532533va_start(args, frm);534535len = vsnprintf((char*) Buffer, 2047, frm, args);536if (len < 0) {537va_end(args);538return FALSE; // Truncated, which is a fatal error for us539}540541rc = io ->Write(io, (cmsUInt32Number) len, Buffer);542543va_end(args);544545return rc;546}547548549// Plugin memory management -------------------------------------------------------------------------------------------------550551// Specialized malloc for plug-ins, that is freed upon exit.552void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size)553{554struct _cmsContext_struct* ctx = _cmsGetContext(ContextID);555556if (ctx ->MemPool == NULL) {557558if (ContextID == NULL) {559560ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024);561if (ctx->MemPool == NULL) return NULL;562}563else {564cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context");565return NULL;566}567}568569return _cmsSubAlloc(ctx->MemPool, size);570}571572573// Main plug-in dispatcher574cmsBool CMSEXPORT cmsPlugin(void* Plug_in)575{576return cmsPluginTHR(NULL, Plug_in);577}578579cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)580{581cmsPluginBase* Plugin;582583for (Plugin = (cmsPluginBase*) Plug_in;584Plugin != NULL;585Plugin = Plugin -> Next) {586587if (Plugin -> Magic != cmsPluginMagicNumber) {588cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");589return FALSE;590}591592if (Plugin ->ExpectedVersion > LCMS_VERSION) {593cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d",594Plugin ->ExpectedVersion, LCMS_VERSION);595return FALSE;596}597598switch (Plugin -> Type) {599600case cmsPluginMemHandlerSig:601if (!_cmsRegisterMemHandlerPlugin(id, Plugin)) return FALSE;602break;603604case cmsPluginInterpolationSig:605if (!_cmsRegisterInterpPlugin(id, Plugin)) return FALSE;606break;607608case cmsPluginTagTypeSig:609if (!_cmsRegisterTagTypePlugin(id, Plugin)) return FALSE;610break;611612case cmsPluginTagSig:613if (!_cmsRegisterTagPlugin(id, Plugin)) return FALSE;614break;615616case cmsPluginFormattersSig:617if (!_cmsRegisterFormattersPlugin(id, Plugin)) return FALSE;618break;619620case cmsPluginRenderingIntentSig:621if (!_cmsRegisterRenderingIntentPlugin(id, Plugin)) return FALSE;622break;623624case cmsPluginParametricCurveSig:625if (!_cmsRegisterParametricCurvesPlugin(id, Plugin)) return FALSE;626break;627628case cmsPluginMultiProcessElementSig:629if (!_cmsRegisterMultiProcessElementPlugin(id, Plugin)) return FALSE;630break;631632case cmsPluginOptimizationSig:633if (!_cmsRegisterOptimizationPlugin(id, Plugin)) return FALSE;634break;635636case cmsPluginTransformSig:637if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE;638break;639640case cmsPluginMutexSig:641if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE;642break;643644default:645cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);646return FALSE;647}648}649650// Keep a reference to the plug-in651return TRUE;652}653654655// Revert all plug-ins to default656void CMSEXPORT cmsUnregisterPlugins(void)657{658cmsUnregisterPluginsTHR(NULL);659}660661662// The Global storage for system context. This is the one and only global variable663// pointers structure. All global vars are referenced here.664static struct _cmsContext_struct globalContext = {665666NULL, // Not in the linked list667NULL, // No suballocator668{669NULL, // UserPtr,670&_cmsLogErrorChunk, // Logger,671&_cmsAlarmCodesChunk, // AlarmCodes,672&_cmsAdaptationStateChunk, // AdaptationState,673&_cmsMemPluginChunk, // MemPlugin,674&_cmsInterpPluginChunk, // InterpPlugin,675&_cmsCurvesPluginChunk, // CurvesPlugin,676&_cmsFormattersPluginChunk, // FormattersPlugin,677&_cmsTagTypePluginChunk, // TagTypePlugin,678&_cmsTagPluginChunk, // TagPlugin,679&_cmsIntentsPluginChunk, // IntentPlugin,680&_cmsMPETypePluginChunk, // MPEPlugin,681&_cmsOptimizationPluginChunk, // OptimizationPlugin,682&_cmsTransformPluginChunk, // TransformPlugin,683&_cmsMutexPluginChunk // MutexPlugin684},685686{ NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0687};688689690// The context pool (linked list head)691static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER;692static struct _cmsContext_struct* _cmsContextPoolHead = NULL;693694// Internal, get associated pointer, with guessing. Never returns NULL.695struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)696{697struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID;698struct _cmsContext_struct* ctx;699700701// On 0, use global settings702if (id == NULL)703return &globalContext;704705// Search706_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);707708for (ctx = _cmsContextPoolHead;709ctx != NULL;710ctx = ctx ->Next) {711712// Found it?713if (id == ctx)714{715_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);716return ctx; // New-style context717}718}719720_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);721return &globalContext;722}723724725// Internal: get the memory area associanted with each context client726// Returns the block assigned to the specific zone. Never return NULL.727void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)728{729struct _cmsContext_struct* ctx;730void *ptr;731732if ((int) mc < 0 || mc >= MemoryClientMax) {733734cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption");735736// This is catastrophic. Should never reach here737_cmsAssert(0);738739// Reverts to global context740return globalContext.chunks[UserPtr];741}742743ctx = _cmsGetContext(ContextID);744ptr = ctx ->chunks[mc];745746if (ptr != NULL)747return ptr;748749// A null ptr means no special settings for that context, and this750// reverts to Context0 globals751return globalContext.chunks[mc];752}753754755// This function returns the given context its default pristine state,756// as no plug-ins were declared. There is no way to unregister a single757// plug-in, as a single call to cmsPluginTHR() function may register758// many different plug-ins simultaneously, then there is no way to759// identify which plug-in to unregister.760void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID)761{762_cmsRegisterMemHandlerPlugin(ContextID, NULL);763_cmsRegisterInterpPlugin(ContextID, NULL);764_cmsRegisterTagTypePlugin(ContextID, NULL);765_cmsRegisterTagPlugin(ContextID, NULL);766_cmsRegisterFormattersPlugin(ContextID, NULL);767_cmsRegisterRenderingIntentPlugin(ContextID, NULL);768_cmsRegisterParametricCurvesPlugin(ContextID, NULL);769_cmsRegisterMultiProcessElementPlugin(ContextID, NULL);770_cmsRegisterOptimizationPlugin(ContextID, NULL);771_cmsRegisterTransformPlugin(ContextID, NULL);772_cmsRegisterMutexPlugin(ContextID, NULL);773}774775776// Returns the memory manager plug-in, if any, from the Plug-in bundle777static778cmsPluginMemHandler* _cmsFindMemoryPlugin(void* PluginBundle)779{780cmsPluginBase* Plugin;781782for (Plugin = (cmsPluginBase*) PluginBundle;783Plugin != NULL;784Plugin = Plugin -> Next) {785786if (Plugin -> Magic == cmsPluginMagicNumber &&787Plugin -> ExpectedVersion <= LCMS_VERSION &&788Plugin -> Type == cmsPluginMemHandlerSig) {789790// Found!791return (cmsPluginMemHandler*) Plugin;792}793}794795// Nope, revert to defaults796return NULL;797}798799800// Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined801// data that will be forwarded to plug-ins and logger.802cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)803{804struct _cmsContext_struct* ctx;805struct _cmsContext_struct fakeContext;806807// See the comments regarding locking in lcms2_internal.h808// for an explanation of why we need the following code.809#ifndef CMS_NO_PTHREADS810#ifdef CMS_IS_WINDOWS_811#ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT812{813static HANDLE _cmsWindowsInitMutex = NULL;814static volatile HANDLE* mutex = &_cmsWindowsInitMutex;815816if (*mutex == NULL)817{818HANDLE p = CreateMutex(NULL, FALSE, NULL);819if (p && InterlockedCompareExchangePointer((void **)mutex, (void*)p, NULL) != NULL)820CloseHandle(p);821}822if (*mutex == NULL || WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED)823return NULL;824if (((void **)&_cmsContextPoolHeadMutex)[0] == NULL)825InitializeCriticalSection(&_cmsContextPoolHeadMutex);826if (*mutex == NULL || !ReleaseMutex(*mutex))827return NULL;828}829#endif830#endif831#endif832833_cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);834835fakeContext.chunks[UserPtr] = UserData;836fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;837838// Create the context structure.839ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct));840if (ctx == NULL)841return NULL; // Something very wrong happened!842843// Init the structure and the memory manager844memset(ctx, 0, sizeof(struct _cmsContext_struct));845846// Keep memory manager847memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk));848849// Maintain the linked list (with proper locking)850_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);851ctx ->Next = _cmsContextPoolHead;852_cmsContextPoolHead = ctx;853_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);854855ctx ->chunks[UserPtr] = UserData;856ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;857858// Now we can allocate the pool by using default memory manager859ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 22 pointers860if (ctx ->MemPool == NULL) {861862cmsDeleteContext(ctx);863return NULL;864}865866_cmsAllocLogErrorChunk(ctx, NULL);867_cmsAllocAlarmCodesChunk(ctx, NULL);868_cmsAllocAdaptationStateChunk(ctx, NULL);869_cmsAllocMemPluginChunk(ctx, NULL);870_cmsAllocInterpPluginChunk(ctx, NULL);871_cmsAllocCurvesPluginChunk(ctx, NULL);872_cmsAllocFormattersPluginChunk(ctx, NULL);873_cmsAllocTagTypePluginChunk(ctx, NULL);874_cmsAllocMPETypePluginChunk(ctx, NULL);875_cmsAllocTagPluginChunk(ctx, NULL);876_cmsAllocIntentsPluginChunk(ctx, NULL);877_cmsAllocOptimizationPluginChunk(ctx, NULL);878_cmsAllocTransformPluginChunk(ctx, NULL);879_cmsAllocMutexPluginChunk(ctx, NULL);880881// Setup the plug-ins882if (!cmsPluginTHR(ctx, Plugin)) {883884cmsDeleteContext(ctx);885return NULL;886}887888return (cmsContext) ctx;889}890891// Duplicates a context with all associated plug-ins.892// Caller may specify an optional pointer to user-defined893// data that will be forwarded to plug-ins and logger.894cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)895{896int i;897struct _cmsContext_struct* ctx;898const struct _cmsContext_struct* src = _cmsGetContext(ContextID);899900void* userData = (NewUserData != NULL) ? NewUserData : src -> chunks[UserPtr];901902903ctx = (struct _cmsContext_struct*) _cmsMalloc(ContextID, sizeof(struct _cmsContext_struct));904if (ctx == NULL)905return NULL; // Something very wrong happened906907// Setup default memory allocators908memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));909910// Maintain the linked list911_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);912ctx ->Next = _cmsContextPoolHead;913_cmsContextPoolHead = ctx;914_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);915916ctx ->chunks[UserPtr] = userData;917ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;918919ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*));920if (ctx ->MemPool == NULL) {921922cmsDeleteContext(ctx);923return NULL;924}925926// Allocate all required chunks.927_cmsAllocLogErrorChunk(ctx, src);928_cmsAllocAlarmCodesChunk(ctx, src);929_cmsAllocAdaptationStateChunk(ctx, src);930_cmsAllocMemPluginChunk(ctx, src);931_cmsAllocInterpPluginChunk(ctx, src);932_cmsAllocCurvesPluginChunk(ctx, src);933_cmsAllocFormattersPluginChunk(ctx, src);934_cmsAllocTagTypePluginChunk(ctx, src);935_cmsAllocMPETypePluginChunk(ctx, src);936_cmsAllocTagPluginChunk(ctx, src);937_cmsAllocIntentsPluginChunk(ctx, src);938_cmsAllocOptimizationPluginChunk(ctx, src);939_cmsAllocTransformPluginChunk(ctx, src);940_cmsAllocMutexPluginChunk(ctx, src);941942// Make sure no one failed943for (i=Logger; i < MemoryClientMax; i++) {944945if (src ->chunks[i] == NULL) {946cmsDeleteContext((cmsContext) ctx);947return NULL;948}949}950951return (cmsContext) ctx;952}953954955// Frees any resources associated with the given context,956// and destroys the context placeholder.957// The ContextID can no longer be used in any THR operation.958void CMSEXPORT cmsDeleteContext(cmsContext ContextID)959{960if (ContextID != NULL) {961962struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID;963struct _cmsContext_struct fakeContext;964struct _cmsContext_struct* prev;965966memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));967968fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr];969fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;970971// Get rid of plugins972cmsUnregisterPluginsTHR(ContextID);973974// Since all memory is allocated in the private pool, all what we need to do is destroy the pool975if (ctx -> MemPool != NULL)976_cmsSubAllocDestroy(ctx ->MemPool);977ctx -> MemPool = NULL;978979// Maintain list980_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);981if (_cmsContextPoolHead == ctx) {982983_cmsContextPoolHead = ctx->Next;984}985else {986987// Search for previous988for (prev = _cmsContextPoolHead;989prev != NULL;990prev = prev ->Next)991{992if (prev -> Next == ctx) {993prev -> Next = ctx ->Next;994break;995}996}997}998_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);9991000// free the memory block itself1001_cmsFree(&fakeContext, ctx);1002}1003}10041005// Returns the user data associated to the given ContextID, or NULL if no user data was attached on context creation1006void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID)1007{1008return _cmsContextGetClientChunk(ContextID, UserPtr);1009}10101011101210131014