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-2017 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
59 // ----------------------------------------------------------------------------------
60 // Encoding & Decoding support functions
61 // ----------------------------------------------------------------------------------
62
63 // Little-Endian to Big-Endian
64
65 // Adjust a word value after being readed/ before being written from/to an ICC profile
66 cmsUInt16Number CMSEXPORT _cmsAdjustEndianess16(cmsUInt16Number Word)
67 {
68 #ifndef CMS_USE_BIG_ENDIAN
69
70 cmsUInt8Number* pByte = (cmsUInt8Number*) &Word;
71 cmsUInt8Number tmp;
72
73 tmp = pByte[0];
74 pByte[0] = pByte[1];
75 pByte[1] = tmp;
76 #endif
77
78 return Word;
79 }
80
81
82 // Transports to properly encoded values - note that icc profiles does use big endian notation.
83
84 // 1 2 3 4
85 // 4 3 2 1
111 #ifndef CMS_USE_BIG_ENDIAN
112
113 cmsUInt8Number* pIn = (cmsUInt8Number*) QWord;
114 cmsUInt8Number* pOut = (cmsUInt8Number*) Result;
115
116 _cmsAssert(Result != NULL);
117
118 pOut[7] = pIn[0];
119 pOut[6] = pIn[1];
120 pOut[5] = pIn[2];
121 pOut[4] = pIn[3];
122 pOut[3] = pIn[4];
123 pOut[2] = pIn[5];
124 pOut[1] = pIn[6];
125 pOut[0] = pIn[7];
126
127 #else
128 _cmsAssert(Result != NULL);
129
130 # ifdef CMS_DONT_USE_INT64
131 (*Result)[0] = QWord[0];
132 (*Result)[1] = QWord[1];
133 # else
134 *Result = *QWord;
135 # endif
136 #endif
137 }
138
139 // Auxiliary -- read 8, 16 and 32-bit numbers
140 cmsBool CMSEXPORT _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n)
141 {
142 cmsUInt8Number tmp;
143
144 _cmsAssert(io != NULL);
145
146 if (io -> Read(io, &tmp, sizeof(cmsUInt8Number), 1) != 1)
147 return FALSE;
148
149 if (n != NULL) *n = tmp;
150 return TRUE;
151 }
152
199 {
200 cmsUInt32Number tmp;
201
202 _cmsAssert(io != NULL);
203
204 if (io->Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
205 return FALSE;
206
207 if (n != NULL) {
208
209 tmp = _cmsAdjustEndianess32(tmp);
210 *n = *(cmsFloat32Number*)(void*)&tmp;
211
212 // Safeguard which covers against absurd values
213 if (*n > 1E+20 || *n < -1E+20) return FALSE;
214
215 #if defined(_MSC_VER) && _MSC_VER < 1800
216 return TRUE;
217 #elif defined (__BORLANDC__)
218 return TRUE;
219 #else
220
221 // fpclassify() required by C99 (only provided by MSVC >= 1800, VS2013 onwards)
222 return ((fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL));
223 #endif
224 }
225
226 return TRUE;
227 }
228
229
230 cmsBool CMSEXPORT _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)
231 {
232 cmsUInt64Number tmp;
233
234 _cmsAssert(io != NULL);
235
236 if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1)
237 return FALSE;
238
685 { NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0
686 };
687
688
689 // The context pool (linked list head)
690 static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER;
691 static struct _cmsContext_struct* _cmsContextPoolHead = NULL;
692
693 // Internal, get associated pointer, with guessing. Never returns NULL.
694 struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
695 {
696 struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID;
697 struct _cmsContext_struct* ctx;
698
699
700 // On 0, use global settings
701 if (id == NULL)
702 return &globalContext;
703
704 // Search
705 for (ctx = _cmsContextPoolHead;
706 ctx != NULL;
707 ctx = ctx ->Next) {
708
709 // Found it?
710 if (id == ctx)
711 return ctx; // New-style context,
712 }
713
714 return &globalContext;
715 }
716
717
718 // Internal: get the memory area associanted with each context client
719 // Returns the block assigned to the specific zone. Never return NULL.
720 void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)
721 {
722 struct _cmsContext_struct* ctx;
723 void *ptr;
724
725 if ((int) mc < 0 || mc >= MemoryClientMax) {
726
727 cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption");
728
729 // This is catastrophic. Should never reach here
730 _cmsAssert(0);
731
732 // Reverts to global context
733 return globalContext.chunks[UserPtr];
782
783 // Found!
784 return (cmsPluginMemHandler*) Plugin;
785 }
786 }
787
788 // Nope, revert to defaults
789 return NULL;
790 }
791
792
793 // Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined
794 // data that will be forwarded to plug-ins and logger.
795 cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)
796 {
797 struct _cmsContext_struct* ctx;
798 struct _cmsContext_struct fakeContext;
799
800 // See the comments regarding locking in lcms2_internal.h
801 // for an explanation of why we need the following code.
802 #ifdef CMS_IS_WINDOWS_
803 #ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
804 {
805 static HANDLE _cmsWindowsInitMutex = NULL;
806 static volatile HANDLE* mutex = &_cmsWindowsInitMutex;
807
808 if (*mutex == NULL)
809 {
810 HANDLE p = CreateMutex(NULL, FALSE, NULL);
811 if (p && InterlockedCompareExchangePointer((void **)mutex, (void*)p, NULL) != NULL)
812 CloseHandle(p);
813 }
814 if (*mutex == NULL || WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED)
815 return NULL;
816 if (((void **)&_cmsContextPoolHeadMutex)[0] == NULL)
817 InitializeCriticalSection(&_cmsContextPoolHeadMutex);
818 if (*mutex == NULL || !ReleaseMutex(*mutex))
819 return NULL;
820 }
821 #endif
822 #endif
823
824 _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);
825
826 fakeContext.chunks[UserPtr] = UserData;
827 fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
828
829 // Create the context structure.
830 ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct));
831 if (ctx == NULL)
832 return NULL; // Something very wrong happened!
833
834 // Init the structure and the memory manager
835 memset(ctx, 0, sizeof(struct _cmsContext_struct));
836
837 // Keep memory manager
838 memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk));
839
840 // Maintain the linked list (with proper locking)
841 _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
842 ctx ->Next = _cmsContextPoolHead;
925 _cmsAllocTagTypePluginChunk(ctx, src);
926 _cmsAllocMPETypePluginChunk(ctx, src);
927 _cmsAllocTagPluginChunk(ctx, src);
928 _cmsAllocIntentsPluginChunk(ctx, src);
929 _cmsAllocOptimizationPluginChunk(ctx, src);
930 _cmsAllocTransformPluginChunk(ctx, src);
931 _cmsAllocMutexPluginChunk(ctx, src);
932
933 // Make sure no one failed
934 for (i=Logger; i < MemoryClientMax; i++) {
935
936 if (src ->chunks[i] == NULL) {
937 cmsDeleteContext((cmsContext) ctx);
938 return NULL;
939 }
940 }
941
942 return (cmsContext) ctx;
943 }
944
945
946 /*
947 static
948 struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id)
949 {
950 struct _cmsContext_struct* prev;
951
952 // Search for previous
953 for (prev = _cmsContextPoolHead;
954 prev != NULL;
955 prev = prev ->Next)
956 {
957 if (prev ->Next == id)
958 return prev;
959 }
960
961 return NULL; // List is empty or only one element!
962 }
963 */
964
965 // Frees any resources associated with the given context,
966 // and destroys the context placeholder.
967 // The ContextID can no longer be used in any THR operation.
968 void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
969 {
970 if (ContextID != NULL) {
971
972 struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID;
973 struct _cmsContext_struct fakeContext;
974 struct _cmsContext_struct* prev;
975
976 memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
977
978 fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr];
979 fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
980
981 // Get rid of plugins
982 cmsUnregisterPluginsTHR(ContextID);
983
|
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-2020 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
59 // ----------------------------------------------------------------------------------
60 // Encoding & Decoding support functions
61 // ----------------------------------------------------------------------------------
62
63 // Little-Endian to Big-Endian
64
65 // Adjust a word value after being read/ before being written from/to an ICC profile
66 cmsUInt16Number CMSEXPORT _cmsAdjustEndianess16(cmsUInt16Number Word)
67 {
68 #ifndef CMS_USE_BIG_ENDIAN
69
70 cmsUInt8Number* pByte = (cmsUInt8Number*) &Word;
71 cmsUInt8Number tmp;
72
73 tmp = pByte[0];
74 pByte[0] = pByte[1];
75 pByte[1] = tmp;
76 #endif
77
78 return Word;
79 }
80
81
82 // Transports to properly encoded values - note that icc profiles does use big endian notation.
83
84 // 1 2 3 4
85 // 4 3 2 1
111 #ifndef CMS_USE_BIG_ENDIAN
112
113 cmsUInt8Number* pIn = (cmsUInt8Number*) QWord;
114 cmsUInt8Number* pOut = (cmsUInt8Number*) Result;
115
116 _cmsAssert(Result != NULL);
117
118 pOut[7] = pIn[0];
119 pOut[6] = pIn[1];
120 pOut[5] = pIn[2];
121 pOut[4] = pIn[3];
122 pOut[3] = pIn[4];
123 pOut[2] = pIn[5];
124 pOut[1] = pIn[6];
125 pOut[0] = pIn[7];
126
127 #else
128 _cmsAssert(Result != NULL);
129
130 # ifdef CMS_DONT_USE_INT64
131 (*Result)[0] = (*QWord)[0];
132 (*Result)[1] = (*QWord)[1];
133 # else
134 *Result = *QWord;
135 # endif
136 #endif
137 }
138
139 // Auxiliary -- read 8, 16 and 32-bit numbers
140 cmsBool CMSEXPORT _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n)
141 {
142 cmsUInt8Number tmp;
143
144 _cmsAssert(io != NULL);
145
146 if (io -> Read(io, &tmp, sizeof(cmsUInt8Number), 1) != 1)
147 return FALSE;
148
149 if (n != NULL) *n = tmp;
150 return TRUE;
151 }
152
199 {
200 cmsUInt32Number tmp;
201
202 _cmsAssert(io != NULL);
203
204 if (io->Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
205 return FALSE;
206
207 if (n != NULL) {
208
209 tmp = _cmsAdjustEndianess32(tmp);
210 *n = *(cmsFloat32Number*)(void*)&tmp;
211
212 // Safeguard which covers against absurd values
213 if (*n > 1E+20 || *n < -1E+20) return FALSE;
214
215 #if defined(_MSC_VER) && _MSC_VER < 1800
216 return TRUE;
217 #elif defined (__BORLANDC__)
218 return TRUE;
219 #elif !defined(_MSC_VER) && (defined(__STDC_VERSION__) && __STDC_VERSION__ < 199901L)
220 return TRUE;
221 #else
222
223 // fpclassify() required by C99 (only provided by MSVC >= 1800, VS2013 onwards)
224 return ((fpclassify(*n) == FP_ZERO) || (fpclassify(*n) == FP_NORMAL));
225 #endif
226 }
227
228 return TRUE;
229 }
230
231
232 cmsBool CMSEXPORT _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)
233 {
234 cmsUInt64Number tmp;
235
236 _cmsAssert(io != NULL);
237
238 if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1)
239 return FALSE;
240
687 { NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0
688 };
689
690
691 // The context pool (linked list head)
692 static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER;
693 static struct _cmsContext_struct* _cmsContextPoolHead = NULL;
694
695 // Internal, get associated pointer, with guessing. Never returns NULL.
696 struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
697 {
698 struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID;
699 struct _cmsContext_struct* ctx;
700
701
702 // On 0, use global settings
703 if (id == NULL)
704 return &globalContext;
705
706 // Search
707 _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
708
709 for (ctx = _cmsContextPoolHead;
710 ctx != NULL;
711 ctx = ctx ->Next) {
712
713 // Found it?
714 if (id == ctx)
715 {
716 _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
717 return ctx; // New-style context
718 }
719 }
720
721 _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
722 return &globalContext;
723 }
724
725
726 // Internal: get the memory area associanted with each context client
727 // Returns the block assigned to the specific zone. Never return NULL.
728 void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)
729 {
730 struct _cmsContext_struct* ctx;
731 void *ptr;
732
733 if ((int) mc < 0 || mc >= MemoryClientMax) {
734
735 cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption");
736
737 // This is catastrophic. Should never reach here
738 _cmsAssert(0);
739
740 // Reverts to global context
741 return globalContext.chunks[UserPtr];
790
791 // Found!
792 return (cmsPluginMemHandler*) Plugin;
793 }
794 }
795
796 // Nope, revert to defaults
797 return NULL;
798 }
799
800
801 // Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined
802 // data that will be forwarded to plug-ins and logger.
803 cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)
804 {
805 struct _cmsContext_struct* ctx;
806 struct _cmsContext_struct fakeContext;
807
808 // See the comments regarding locking in lcms2_internal.h
809 // for an explanation of why we need the following code.
810 #ifndef CMS_NO_PTHREADS
811 #ifdef CMS_IS_WINDOWS_
812 #ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
813 {
814 static HANDLE _cmsWindowsInitMutex = NULL;
815 static volatile HANDLE* mutex = &_cmsWindowsInitMutex;
816
817 if (*mutex == NULL)
818 {
819 HANDLE p = CreateMutex(NULL, FALSE, NULL);
820 if (p && InterlockedCompareExchangePointer((void **)mutex, (void*)p, NULL) != NULL)
821 CloseHandle(p);
822 }
823 if (*mutex == NULL || WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED)
824 return NULL;
825 if (((void **)&_cmsContextPoolHeadMutex)[0] == NULL)
826 InitializeCriticalSection(&_cmsContextPoolHeadMutex);
827 if (*mutex == NULL || !ReleaseMutex(*mutex))
828 return NULL;
829 }
830 #endif
831 #endif
832 #endif
833
834 _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);
835
836 fakeContext.chunks[UserPtr] = UserData;
837 fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
838
839 // Create the context structure.
840 ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct));
841 if (ctx == NULL)
842 return NULL; // Something very wrong happened!
843
844 // Init the structure and the memory manager
845 memset(ctx, 0, sizeof(struct _cmsContext_struct));
846
847 // Keep memory manager
848 memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk));
849
850 // Maintain the linked list (with proper locking)
851 _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
852 ctx ->Next = _cmsContextPoolHead;
935 _cmsAllocTagTypePluginChunk(ctx, src);
936 _cmsAllocMPETypePluginChunk(ctx, src);
937 _cmsAllocTagPluginChunk(ctx, src);
938 _cmsAllocIntentsPluginChunk(ctx, src);
939 _cmsAllocOptimizationPluginChunk(ctx, src);
940 _cmsAllocTransformPluginChunk(ctx, src);
941 _cmsAllocMutexPluginChunk(ctx, src);
942
943 // Make sure no one failed
944 for (i=Logger; i < MemoryClientMax; i++) {
945
946 if (src ->chunks[i] == NULL) {
947 cmsDeleteContext((cmsContext) ctx);
948 return NULL;
949 }
950 }
951
952 return (cmsContext) ctx;
953 }
954
955
956 // Frees any resources associated with the given context,
957 // and destroys the context placeholder.
958 // The ContextID can no longer be used in any THR operation.
959 void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
960 {
961 if (ContextID != NULL) {
962
963 struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID;
964 struct _cmsContext_struct fakeContext;
965 struct _cmsContext_struct* prev;
966
967 memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
968
969 fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr];
970 fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
971
972 // Get rid of plugins
973 cmsUnregisterPluginsTHR(ContextID);
974
|