Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/liblcms/cmsplugin.c
41149 views
1
/*
2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3
*
4
* This code is free software; you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 2 only, as
6
* published by the Free Software Foundation. Oracle designates this
7
* particular file as subject to the "Classpath" exception as provided
8
* by Oracle in the LICENSE file that accompanied this code.
9
*
10
* This code is distributed in the hope that it will be useful, but WITHOUT
11
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
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
86
87
cmsUInt32Number CMSEXPORT _cmsAdjustEndianess32(cmsUInt32Number DWord)
88
{
89
#ifndef CMS_USE_BIG_ENDIAN
90
91
cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord;
92
cmsUInt8Number temp1;
93
cmsUInt8Number temp2;
94
95
temp1 = *pByte++;
96
temp2 = *pByte++;
97
*(pByte-1) = *pByte;
98
*pByte++ = temp2;
99
*(pByte-3) = *pByte;
100
*pByte = temp1;
101
#endif
102
return DWord;
103
}
104
105
// 1 2 3 4 5 6 7 8
106
// 8 7 6 5 4 3 2 1
107
108
void CMSEXPORT _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number* QWord)
109
{
110
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
153
cmsBool CMSEXPORT _cmsReadUInt16Number(cmsIOHANDLER* io, cmsUInt16Number* n)
154
{
155
cmsUInt16Number tmp;
156
157
_cmsAssert(io != NULL);
158
159
if (io -> Read(io, &tmp, sizeof(cmsUInt16Number), 1) != 1)
160
return FALSE;
161
162
if (n != NULL) *n = _cmsAdjustEndianess16(tmp);
163
return TRUE;
164
}
165
166
cmsBool CMSEXPORT _cmsReadUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, cmsUInt16Number* Array)
167
{
168
cmsUInt32Number i;
169
170
_cmsAssert(io != NULL);
171
172
for (i=0; i < n; i++) {
173
174
if (Array != NULL) {
175
if (!_cmsReadUInt16Number(io, Array + i)) return FALSE;
176
}
177
else {
178
if (!_cmsReadUInt16Number(io, NULL)) return FALSE;
179
}
180
181
}
182
return TRUE;
183
}
184
185
cmsBool CMSEXPORT _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n)
186
{
187
cmsUInt32Number tmp;
188
189
_cmsAssert(io != NULL);
190
191
if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
192
return FALSE;
193
194
if (n != NULL) *n = _cmsAdjustEndianess32(tmp);
195
return TRUE;
196
}
197
198
cmsBool CMSEXPORT _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n)
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
241
if (n != NULL) {
242
243
_cmsAdjustEndianess64(n, &tmp);
244
}
245
246
return TRUE;
247
}
248
249
250
cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n)
251
{
252
cmsUInt32Number tmp;
253
254
_cmsAssert(io != NULL);
255
256
if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1)
257
return FALSE;
258
259
if (n != NULL) {
260
*n = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32(tmp));
261
}
262
263
return TRUE;
264
}
265
266
267
cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ)
268
{
269
cmsEncodedXYZNumber xyz;
270
271
_cmsAssert(io != NULL);
272
273
if (io ->Read(io, &xyz, sizeof(cmsEncodedXYZNumber), 1) != 1) return FALSE;
274
275
if (XYZ != NULL) {
276
277
XYZ->X = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.X));
278
XYZ->Y = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.Y));
279
XYZ->Z = _cms15Fixed16toDouble((cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) xyz.Z));
280
}
281
return TRUE;
282
}
283
284
cmsBool CMSEXPORT _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n)
285
{
286
_cmsAssert(io != NULL);
287
288
if (io -> Write(io, sizeof(cmsUInt8Number), &n) != 1)
289
return FALSE;
290
291
return TRUE;
292
}
293
294
cmsBool CMSEXPORT _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n)
295
{
296
cmsUInt16Number tmp;
297
298
_cmsAssert(io != NULL);
299
300
tmp = _cmsAdjustEndianess16(n);
301
if (io -> Write(io, sizeof(cmsUInt16Number), &tmp) != 1)
302
return FALSE;
303
304
return TRUE;
305
}
306
307
cmsBool CMSEXPORT _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array)
308
{
309
cmsUInt32Number i;
310
311
_cmsAssert(io != NULL);
312
_cmsAssert(Array != NULL);
313
314
for (i=0; i < n; i++) {
315
if (!_cmsWriteUInt16Number(io, Array[i])) return FALSE;
316
}
317
318
return TRUE;
319
}
320
321
cmsBool CMSEXPORT _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n)
322
{
323
cmsUInt32Number tmp;
324
325
_cmsAssert(io != NULL);
326
327
tmp = _cmsAdjustEndianess32(n);
328
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
329
return FALSE;
330
331
return TRUE;
332
}
333
334
335
cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n)
336
{
337
cmsUInt32Number tmp;
338
339
_cmsAssert(io != NULL);
340
341
tmp = *(cmsUInt32Number*) (void*) &n;
342
tmp = _cmsAdjustEndianess32(tmp);
343
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
344
return FALSE;
345
346
return TRUE;
347
}
348
349
cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)
350
{
351
cmsUInt64Number tmp;
352
353
_cmsAssert(io != NULL);
354
355
_cmsAdjustEndianess64(&tmp, n);
356
if (io -> Write(io, sizeof(cmsUInt64Number), &tmp) != 1)
357
return FALSE;
358
359
return TRUE;
360
}
361
362
cmsBool CMSEXPORT _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n)
363
{
364
cmsUInt32Number tmp;
365
366
_cmsAssert(io != NULL);
367
368
tmp = _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(n));
369
if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1)
370
return FALSE;
371
372
return TRUE;
373
}
374
375
cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ)
376
{
377
cmsEncodedXYZNumber xyz;
378
379
_cmsAssert(io != NULL);
380
_cmsAssert(XYZ != NULL);
381
382
xyz.X = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->X));
383
xyz.Y = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->Y));
384
xyz.Z = (cmsS15Fixed16Number) _cmsAdjustEndianess32((cmsUInt32Number) _cmsDoubleTo15Fixed16(XYZ->Z));
385
386
return io -> Write(io, sizeof(cmsEncodedXYZNumber), &xyz);
387
}
388
389
// from Fixed point 8.8 to double
390
cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8)
391
{
392
cmsUInt8Number msb, lsb;
393
394
lsb = (cmsUInt8Number) (fixed8 & 0xff);
395
msb = (cmsUInt8Number) (((cmsUInt16Number) fixed8 >> 8) & 0xff);
396
397
return (cmsFloat64Number) ((cmsFloat64Number) msb + ((cmsFloat64Number) lsb / 256.0));
398
}
399
400
cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val)
401
{
402
cmsS15Fixed16Number GammaFixed32 = _cmsDoubleTo15Fixed16(val);
403
return (cmsUInt16Number) ((GammaFixed32 >> 8) & 0xFFFF);
404
}
405
406
// from Fixed point 15.16 to double
407
cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32)
408
{
409
cmsFloat64Number floater, sign, mid;
410
int Whole, FracPart;
411
412
sign = (fix32 < 0 ? -1 : 1);
413
fix32 = abs(fix32);
414
415
Whole = (cmsUInt16Number)(fix32 >> 16) & 0xffff;
416
FracPart = (cmsUInt16Number)(fix32 & 0xffff);
417
418
mid = (cmsFloat64Number) FracPart / 65536.0;
419
floater = (cmsFloat64Number) Whole + mid;
420
421
return sign * floater;
422
}
423
424
// from double to Fixed point 15.16
425
cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v)
426
{
427
return ((cmsS15Fixed16Number) floor((v)*65536.0 + 0.5));
428
}
429
430
// Date/Time functions
431
432
void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest)
433
{
434
435
_cmsAssert(Dest != NULL);
436
_cmsAssert(Source != NULL);
437
438
Dest->tm_sec = _cmsAdjustEndianess16(Source->seconds);
439
Dest->tm_min = _cmsAdjustEndianess16(Source->minutes);
440
Dest->tm_hour = _cmsAdjustEndianess16(Source->hours);
441
Dest->tm_mday = _cmsAdjustEndianess16(Source->day);
442
Dest->tm_mon = _cmsAdjustEndianess16(Source->month) - 1;
443
Dest->tm_year = _cmsAdjustEndianess16(Source->year) - 1900;
444
Dest->tm_wday = -1;
445
Dest->tm_yday = -1;
446
Dest->tm_isdst = 0;
447
}
448
449
void CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source)
450
{
451
_cmsAssert(Dest != NULL);
452
_cmsAssert(Source != NULL);
453
454
Dest->seconds = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_sec);
455
Dest->minutes = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_min);
456
Dest->hours = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_hour);
457
Dest->day = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_mday);
458
Dest->month = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_mon + 1));
459
Dest->year = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_year + 1900));
460
}
461
462
// Read base and return type base
463
cmsTagTypeSignature CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io)
464
{
465
_cmsTagBase Base;
466
467
_cmsAssert(io != NULL);
468
469
if (io -> Read(io, &Base, sizeof(_cmsTagBase), 1) != 1)
470
return (cmsTagTypeSignature) 0;
471
472
return (cmsTagTypeSignature) _cmsAdjustEndianess32(Base.sig);
473
}
474
475
// Setup base marker
476
cmsBool CMSEXPORT _cmsWriteTypeBase(cmsIOHANDLER* io, cmsTagTypeSignature sig)
477
{
478
_cmsTagBase Base;
479
480
_cmsAssert(io != NULL);
481
482
Base.sig = (cmsTagTypeSignature) _cmsAdjustEndianess32(sig);
483
memset(&Base.reserved, 0, sizeof(Base.reserved));
484
return io -> Write(io, sizeof(_cmsTagBase), &Base);
485
}
486
487
cmsBool CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io)
488
{
489
cmsUInt8Number Buffer[4];
490
cmsUInt32Number NextAligned, At;
491
cmsUInt32Number BytesToNextAlignedPos;
492
493
_cmsAssert(io != NULL);
494
495
At = io -> Tell(io);
496
NextAligned = _cmsALIGNLONG(At);
497
BytesToNextAlignedPos = NextAligned - At;
498
if (BytesToNextAlignedPos == 0) return TRUE;
499
if (BytesToNextAlignedPos > 4) return FALSE;
500
501
return (io ->Read(io, Buffer, BytesToNextAlignedPos, 1) == 1);
502
}
503
504
cmsBool CMSEXPORT _cmsWriteAlignment(cmsIOHANDLER* io)
505
{
506
cmsUInt8Number Buffer[4];
507
cmsUInt32Number NextAligned, At;
508
cmsUInt32Number BytesToNextAlignedPos;
509
510
_cmsAssert(io != NULL);
511
512
At = io -> Tell(io);
513
NextAligned = _cmsALIGNLONG(At);
514
BytesToNextAlignedPos = NextAligned - At;
515
if (BytesToNextAlignedPos == 0) return TRUE;
516
if (BytesToNextAlignedPos > 4) return FALSE;
517
518
memset(Buffer, 0, BytesToNextAlignedPos);
519
return io -> Write(io, BytesToNextAlignedPos, Buffer);
520
}
521
522
523
// To deal with text streams. 2K at most
524
cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
525
{
526
va_list args;
527
int len;
528
cmsUInt8Number Buffer[2048];
529
cmsBool rc;
530
cmsUInt8Number* ptr;
531
532
_cmsAssert(io != NULL);
533
_cmsAssert(frm != NULL);
534
535
va_start(args, frm);
536
537
len = vsnprintf((char*) Buffer, 2047, frm, args);
538
if (len < 0) {
539
va_end(args);
540
return FALSE; // Truncated, which is a fatal error for us
541
}
542
543
// setlocale may be active, no commas are needed in PS generator
544
// and PS generator is our only client
545
for (ptr = Buffer; *ptr; ptr++)
546
{
547
if (*ptr == ',') *ptr = '.';
548
}
549
550
rc = io ->Write(io, (cmsUInt32Number) len, Buffer);
551
552
va_end(args);
553
554
return rc;
555
}
556
557
558
// Plugin memory management -------------------------------------------------------------------------------------------------
559
560
// Specialized malloc for plug-ins, that is freed upon exit.
561
void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size)
562
{
563
struct _cmsContext_struct* ctx = _cmsGetContext(ContextID);
564
565
if (ctx ->MemPool == NULL) {
566
567
if (ContextID == NULL) {
568
569
ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024);
570
if (ctx->MemPool == NULL) return NULL;
571
}
572
else {
573
cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context");
574
return NULL;
575
}
576
}
577
578
return _cmsSubAlloc(ctx->MemPool, size);
579
}
580
581
582
// Main plug-in dispatcher
583
cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
584
{
585
return cmsPluginTHR(NULL, Plug_in);
586
}
587
588
cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in)
589
{
590
cmsPluginBase* Plugin;
591
592
for (Plugin = (cmsPluginBase*) Plug_in;
593
Plugin != NULL;
594
Plugin = Plugin -> Next) {
595
596
if (Plugin -> Magic != cmsPluginMagicNumber) {
597
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
598
return FALSE;
599
}
600
601
if (Plugin ->ExpectedVersion > LCMS_VERSION) {
602
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d",
603
Plugin ->ExpectedVersion, LCMS_VERSION);
604
return FALSE;
605
}
606
607
switch (Plugin -> Type) {
608
609
case cmsPluginMemHandlerSig:
610
if (!_cmsRegisterMemHandlerPlugin(id, Plugin)) return FALSE;
611
break;
612
613
case cmsPluginInterpolationSig:
614
if (!_cmsRegisterInterpPlugin(id, Plugin)) return FALSE;
615
break;
616
617
case cmsPluginTagTypeSig:
618
if (!_cmsRegisterTagTypePlugin(id, Plugin)) return FALSE;
619
break;
620
621
case cmsPluginTagSig:
622
if (!_cmsRegisterTagPlugin(id, Plugin)) return FALSE;
623
break;
624
625
case cmsPluginFormattersSig:
626
if (!_cmsRegisterFormattersPlugin(id, Plugin)) return FALSE;
627
break;
628
629
case cmsPluginRenderingIntentSig:
630
if (!_cmsRegisterRenderingIntentPlugin(id, Plugin)) return FALSE;
631
break;
632
633
case cmsPluginParametricCurveSig:
634
if (!_cmsRegisterParametricCurvesPlugin(id, Plugin)) return FALSE;
635
break;
636
637
case cmsPluginMultiProcessElementSig:
638
if (!_cmsRegisterMultiProcessElementPlugin(id, Plugin)) return FALSE;
639
break;
640
641
case cmsPluginOptimizationSig:
642
if (!_cmsRegisterOptimizationPlugin(id, Plugin)) return FALSE;
643
break;
644
645
case cmsPluginTransformSig:
646
if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE;
647
break;
648
649
case cmsPluginMutexSig:
650
if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE;
651
break;
652
653
default:
654
cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
655
return FALSE;
656
}
657
}
658
659
// Keep a reference to the plug-in
660
return TRUE;
661
}
662
663
664
// Revert all plug-ins to default
665
void CMSEXPORT cmsUnregisterPlugins(void)
666
{
667
cmsUnregisterPluginsTHR(NULL);
668
}
669
670
671
// The Global storage for system context. This is the one and only global variable
672
// pointers structure. All global vars are referenced here.
673
static struct _cmsContext_struct globalContext = {
674
675
NULL, // Not in the linked list
676
NULL, // No suballocator
677
{
678
NULL, // UserPtr,
679
&_cmsLogErrorChunk, // Logger,
680
&_cmsAlarmCodesChunk, // AlarmCodes,
681
&_cmsAdaptationStateChunk, // AdaptationState,
682
&_cmsMemPluginChunk, // MemPlugin,
683
&_cmsInterpPluginChunk, // InterpPlugin,
684
&_cmsCurvesPluginChunk, // CurvesPlugin,
685
&_cmsFormattersPluginChunk, // FormattersPlugin,
686
&_cmsTagTypePluginChunk, // TagTypePlugin,
687
&_cmsTagPluginChunk, // TagPlugin,
688
&_cmsIntentsPluginChunk, // IntentPlugin,
689
&_cmsMPETypePluginChunk, // MPEPlugin,
690
&_cmsOptimizationPluginChunk, // OptimizationPlugin,
691
&_cmsTransformPluginChunk, // TransformPlugin,
692
&_cmsMutexPluginChunk // MutexPlugin
693
},
694
695
{ NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0
696
};
697
698
699
// The context pool (linked list head)
700
static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER;
701
static struct _cmsContext_struct* _cmsContextPoolHead = NULL;
702
703
// Internal, get associated pointer, with guessing. Never returns NULL.
704
struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID)
705
{
706
struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID;
707
struct _cmsContext_struct* ctx;
708
709
710
// On 0, use global settings
711
if (id == NULL)
712
return &globalContext;
713
714
// Search
715
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
716
717
for (ctx = _cmsContextPoolHead;
718
ctx != NULL;
719
ctx = ctx ->Next) {
720
721
// Found it?
722
if (id == ctx)
723
{
724
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
725
return ctx; // New-style context
726
}
727
}
728
729
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
730
return &globalContext;
731
}
732
733
734
// Internal: get the memory area associanted with each context client
735
// Returns the block assigned to the specific zone. Never return NULL.
736
void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc)
737
{
738
struct _cmsContext_struct* ctx;
739
void *ptr;
740
741
if ((int) mc < 0 || mc >= MemoryClientMax) {
742
743
cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption");
744
745
// This is catastrophic. Should never reach here
746
_cmsAssert(0);
747
748
// Reverts to global context
749
return globalContext.chunks[UserPtr];
750
}
751
752
ctx = _cmsGetContext(ContextID);
753
ptr = ctx ->chunks[mc];
754
755
if (ptr != NULL)
756
return ptr;
757
758
// A null ptr means no special settings for that context, and this
759
// reverts to Context0 globals
760
return globalContext.chunks[mc];
761
}
762
763
764
// This function returns the given context its default pristine state,
765
// as no plug-ins were declared. There is no way to unregister a single
766
// plug-in, as a single call to cmsPluginTHR() function may register
767
// many different plug-ins simultaneously, then there is no way to
768
// identify which plug-in to unregister.
769
void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID)
770
{
771
_cmsRegisterMemHandlerPlugin(ContextID, NULL);
772
_cmsRegisterInterpPlugin(ContextID, NULL);
773
_cmsRegisterTagTypePlugin(ContextID, NULL);
774
_cmsRegisterTagPlugin(ContextID, NULL);
775
_cmsRegisterFormattersPlugin(ContextID, NULL);
776
_cmsRegisterRenderingIntentPlugin(ContextID, NULL);
777
_cmsRegisterParametricCurvesPlugin(ContextID, NULL);
778
_cmsRegisterMultiProcessElementPlugin(ContextID, NULL);
779
_cmsRegisterOptimizationPlugin(ContextID, NULL);
780
_cmsRegisterTransformPlugin(ContextID, NULL);
781
_cmsRegisterMutexPlugin(ContextID, NULL);
782
}
783
784
785
// Returns the memory manager plug-in, if any, from the Plug-in bundle
786
static
787
cmsPluginMemHandler* _cmsFindMemoryPlugin(void* PluginBundle)
788
{
789
cmsPluginBase* Plugin;
790
791
for (Plugin = (cmsPluginBase*) PluginBundle;
792
Plugin != NULL;
793
Plugin = Plugin -> Next) {
794
795
if (Plugin -> Magic == cmsPluginMagicNumber &&
796
Plugin -> ExpectedVersion <= LCMS_VERSION &&
797
Plugin -> Type == cmsPluginMemHandlerSig) {
798
799
// Found!
800
return (cmsPluginMemHandler*) Plugin;
801
}
802
}
803
804
// Nope, revert to defaults
805
return NULL;
806
}
807
808
809
// Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined
810
// data that will be forwarded to plug-ins and logger.
811
cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData)
812
{
813
struct _cmsContext_struct* ctx;
814
struct _cmsContext_struct fakeContext;
815
816
// See the comments regarding locking in lcms2_internal.h
817
// for an explanation of why we need the following code.
818
#ifndef CMS_NO_PTHREADS
819
#ifdef CMS_IS_WINDOWS_
820
#ifndef CMS_RELY_ON_WINDOWS_STATIC_MUTEX_INIT
821
{
822
static HANDLE _cmsWindowsInitMutex = NULL;
823
static volatile HANDLE* mutex = &_cmsWindowsInitMutex;
824
825
if (*mutex == NULL)
826
{
827
HANDLE p = CreateMutex(NULL, FALSE, NULL);
828
if (p && InterlockedCompareExchangePointer((void **)mutex, (void*)p, NULL) != NULL)
829
CloseHandle(p);
830
}
831
if (*mutex == NULL || WaitForSingleObject(*mutex, INFINITE) == WAIT_FAILED)
832
return NULL;
833
if (((void **)&_cmsContextPoolHeadMutex)[0] == NULL)
834
InitializeCriticalSection(&_cmsContextPoolHeadMutex);
835
if (*mutex == NULL || !ReleaseMutex(*mutex))
836
return NULL;
837
}
838
#endif
839
#endif
840
#endif
841
842
_cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager);
843
844
fakeContext.chunks[UserPtr] = UserData;
845
fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
846
847
// Create the context structure.
848
ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct));
849
if (ctx == NULL)
850
return NULL; // Something very wrong happened!
851
852
// Init the structure and the memory manager
853
memset(ctx, 0, sizeof(struct _cmsContext_struct));
854
855
// Keep memory manager
856
memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk));
857
858
// Maintain the linked list (with proper locking)
859
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
860
ctx ->Next = _cmsContextPoolHead;
861
_cmsContextPoolHead = ctx;
862
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
863
864
ctx ->chunks[UserPtr] = UserData;
865
ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;
866
867
// Now we can allocate the pool by using default memory manager
868
ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 22 pointers
869
if (ctx ->MemPool == NULL) {
870
871
cmsDeleteContext(ctx);
872
return NULL;
873
}
874
875
_cmsAllocLogErrorChunk(ctx, NULL);
876
_cmsAllocAlarmCodesChunk(ctx, NULL);
877
_cmsAllocAdaptationStateChunk(ctx, NULL);
878
_cmsAllocMemPluginChunk(ctx, NULL);
879
_cmsAllocInterpPluginChunk(ctx, NULL);
880
_cmsAllocCurvesPluginChunk(ctx, NULL);
881
_cmsAllocFormattersPluginChunk(ctx, NULL);
882
_cmsAllocTagTypePluginChunk(ctx, NULL);
883
_cmsAllocMPETypePluginChunk(ctx, NULL);
884
_cmsAllocTagPluginChunk(ctx, NULL);
885
_cmsAllocIntentsPluginChunk(ctx, NULL);
886
_cmsAllocOptimizationPluginChunk(ctx, NULL);
887
_cmsAllocTransformPluginChunk(ctx, NULL);
888
_cmsAllocMutexPluginChunk(ctx, NULL);
889
890
// Setup the plug-ins
891
if (!cmsPluginTHR(ctx, Plugin)) {
892
893
cmsDeleteContext(ctx);
894
return NULL;
895
}
896
897
return (cmsContext) ctx;
898
}
899
900
// Duplicates a context with all associated plug-ins.
901
// Caller may specify an optional pointer to user-defined
902
// data that will be forwarded to plug-ins and logger.
903
cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData)
904
{
905
int i;
906
struct _cmsContext_struct* ctx;
907
const struct _cmsContext_struct* src = _cmsGetContext(ContextID);
908
909
void* userData = (NewUserData != NULL) ? NewUserData : src -> chunks[UserPtr];
910
911
912
ctx = (struct _cmsContext_struct*) _cmsMalloc(ContextID, sizeof(struct _cmsContext_struct));
913
if (ctx == NULL)
914
return NULL; // Something very wrong happened
915
916
// Setup default memory allocators
917
memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
918
919
// Maintain the linked list
920
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
921
ctx ->Next = _cmsContextPoolHead;
922
_cmsContextPoolHead = ctx;
923
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
924
925
ctx ->chunks[UserPtr] = userData;
926
ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager;
927
928
ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*));
929
if (ctx ->MemPool == NULL) {
930
931
cmsDeleteContext(ctx);
932
return NULL;
933
}
934
935
// Allocate all required chunks.
936
_cmsAllocLogErrorChunk(ctx, src);
937
_cmsAllocAlarmCodesChunk(ctx, src);
938
_cmsAllocAdaptationStateChunk(ctx, src);
939
_cmsAllocMemPluginChunk(ctx, src);
940
_cmsAllocInterpPluginChunk(ctx, src);
941
_cmsAllocCurvesPluginChunk(ctx, src);
942
_cmsAllocFormattersPluginChunk(ctx, src);
943
_cmsAllocTagTypePluginChunk(ctx, src);
944
_cmsAllocMPETypePluginChunk(ctx, src);
945
_cmsAllocTagPluginChunk(ctx, src);
946
_cmsAllocIntentsPluginChunk(ctx, src);
947
_cmsAllocOptimizationPluginChunk(ctx, src);
948
_cmsAllocTransformPluginChunk(ctx, src);
949
_cmsAllocMutexPluginChunk(ctx, src);
950
951
// Make sure no one failed
952
for (i=Logger; i < MemoryClientMax; i++) {
953
954
if (src ->chunks[i] == NULL) {
955
cmsDeleteContext((cmsContext) ctx);
956
return NULL;
957
}
958
}
959
960
return (cmsContext) ctx;
961
}
962
963
964
// Frees any resources associated with the given context,
965
// and destroys the context placeholder.
966
// The ContextID can no longer be used in any THR operation.
967
void CMSEXPORT cmsDeleteContext(cmsContext ContextID)
968
{
969
if (ContextID != NULL) {
970
971
struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID;
972
struct _cmsContext_struct fakeContext;
973
struct _cmsContext_struct* prev;
974
975
memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager));
976
977
fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr];
978
fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager;
979
980
// Get rid of plugins
981
cmsUnregisterPluginsTHR(ContextID);
982
983
// Since all memory is allocated in the private pool, all what we need to do is destroy the pool
984
if (ctx -> MemPool != NULL)
985
_cmsSubAllocDestroy(ctx ->MemPool);
986
ctx -> MemPool = NULL;
987
988
// Maintain list
989
_cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
990
if (_cmsContextPoolHead == ctx) {
991
992
_cmsContextPoolHead = ctx->Next;
993
}
994
else {
995
996
// Search for previous
997
for (prev = _cmsContextPoolHead;
998
prev != NULL;
999
prev = prev ->Next)
1000
{
1001
if (prev -> Next == ctx) {
1002
prev -> Next = ctx ->Next;
1003
break;
1004
}
1005
}
1006
}
1007
_cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex);
1008
1009
// free the memory block itself
1010
_cmsFree(&fakeContext, ctx);
1011
}
1012
}
1013
1014
// Returns the user data associated to the given ContextID, or NULL if no user data was attached on context creation
1015
void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID)
1016
{
1017
return _cmsContextGetClientChunk(ContextID, UserPtr);
1018
}
1019
1020
1021
1022