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-2016 Marti Maria Saguer 34 // 35 // Permission is hereby granted, free of charge, to any person obtaining 36 // a copy of this software and associated documentation files (the "Software"), 37 // to deal in the Software without restriction, including without limitation 38 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 39 // and/or sell copies of the Software, and to permit persons to whom the Software 40 // is furnished to do so, subject to the following conditions: 41 // 42 // The above copyright notice and this permission notice shall be included in 43 // all copies or substantial portions of the Software. 44 // 45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 46 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 47 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 48 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 49 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 50 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 51 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 52 // 53 //--------------------------------------------------------------------------------- 54 // 55 56 #include "lcms2_internal.h" 57 58 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 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 return TRUE; 213 } 214 215 216 cmsBool CMSEXPORT _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n) 217 { 218 cmsUInt64Number tmp; 219 220 _cmsAssert(io != NULL); 221 222 if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1) 223 return FALSE; 224 225 if (n != NULL) _cmsAdjustEndianess64(n, &tmp); 226 return TRUE; 227 } 228 229 230 cmsBool CMSEXPORT _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n) 231 { 232 cmsUInt32Number tmp; 233 234 _cmsAssert(io != NULL); 235 236 if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1) 237 return FALSE; 238 239 if (n != NULL) { 240 *n = _cms15Fixed16toDouble(_cmsAdjustEndianess32(tmp)); 241 } 242 243 return TRUE; 244 } 245 246 247 cmsBool CMSEXPORT _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ) 248 { 249 cmsEncodedXYZNumber xyz; 250 251 _cmsAssert(io != NULL); 252 253 if (io ->Read(io, &xyz, sizeof(cmsEncodedXYZNumber), 1) != 1) return FALSE; 254 255 if (XYZ != NULL) { 256 257 XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X)); 258 XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y)); 259 XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z)); 260 } 261 return TRUE; 262 } 263 264 cmsBool CMSEXPORT _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n) 265 { 266 _cmsAssert(io != NULL); 267 268 if (io -> Write(io, sizeof(cmsUInt8Number), &n) != 1) 269 return FALSE; 270 271 return TRUE; 272 } 273 274 cmsBool CMSEXPORT _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n) 275 { 276 cmsUInt16Number tmp; 277 278 _cmsAssert(io != NULL); 279 280 tmp = _cmsAdjustEndianess16(n); 281 if (io -> Write(io, sizeof(cmsUInt16Number), &tmp) != 1) 282 return FALSE; 283 284 return TRUE; 285 } 286 287 cmsBool CMSEXPORT _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array) 288 { 289 cmsUInt32Number i; 290 291 _cmsAssert(io != NULL); 292 _cmsAssert(Array != NULL); 293 294 for (i=0; i < n; i++) { 295 if (!_cmsWriteUInt16Number(io, Array[i])) return FALSE; 296 } 297 298 return TRUE; 299 } 300 301 cmsBool CMSEXPORT _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n) 302 { 303 cmsUInt32Number tmp; 304 305 _cmsAssert(io != NULL); 306 307 tmp = _cmsAdjustEndianess32(n); 308 if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) 309 return FALSE; 310 311 return TRUE; 312 } 313 314 315 cmsBool CMSEXPORT _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n) 316 { 317 cmsUInt32Number tmp; 318 319 _cmsAssert(io != NULL); 320 321 tmp = *(cmsUInt32Number*) (void*) &n; 322 tmp = _cmsAdjustEndianess32(tmp); 323 if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) 324 return FALSE; 325 326 return TRUE; 327 } 328 329 cmsBool CMSEXPORT _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n) 330 { 331 cmsUInt64Number tmp; 332 333 _cmsAssert(io != NULL); 334 335 _cmsAdjustEndianess64(&tmp, n); 336 if (io -> Write(io, sizeof(cmsUInt64Number), &tmp) != 1) 337 return FALSE; 338 339 return TRUE; 340 } 341 342 cmsBool CMSEXPORT _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n) 343 { 344 cmsUInt32Number tmp; 345 346 _cmsAssert(io != NULL); 347 348 tmp = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(n)); 349 if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) 350 return FALSE; 351 352 return TRUE; 353 } 354 355 cmsBool CMSEXPORT _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ) 356 { 357 cmsEncodedXYZNumber xyz; 358 359 _cmsAssert(io != NULL); 360 _cmsAssert(XYZ != NULL); 361 362 xyz.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->X)); 363 xyz.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Y)); 364 xyz.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Z)); 365 366 return io -> Write(io, sizeof(cmsEncodedXYZNumber), &xyz); 367 } 368 369 // from Fixed point 8.8 to double 370 cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8) 371 { 372 cmsUInt8Number msb, lsb; 373 374 lsb = (cmsUInt8Number) (fixed8 & 0xff); 375 msb = (cmsUInt8Number) (((cmsUInt16Number) fixed8 >> 8) & 0xff); 376 377 return (cmsFloat64Number) ((cmsFloat64Number) msb + ((cmsFloat64Number) lsb / 256.0)); 378 } 379 380 cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val) 381 { 382 cmsS15Fixed16Number GammaFixed32 = _cmsDoubleTo15Fixed16(val); 383 return (cmsUInt16Number) ((GammaFixed32 >> 8) & 0xFFFF); 384 } 385 386 // from Fixed point 15.16 to double 387 cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32) 388 { 389 cmsFloat64Number floater, sign, mid; 390 int Whole, FracPart; 391 392 sign = (fix32 < 0 ? -1 : 1); 393 fix32 = abs(fix32); 394 395 Whole = (cmsUInt16Number)(fix32 >> 16) & 0xffff; 396 FracPart = (cmsUInt16Number)(fix32 & 0xffff); 397 398 mid = (cmsFloat64Number) FracPart / 65536.0; 399 floater = (cmsFloat64Number) Whole + mid; 400 401 return sign * floater; 402 } 403 404 // from double to Fixed point 15.16 405 cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v) 406 { 407 return ((cmsS15Fixed16Number) floor((v)*65536.0 + 0.5)); 408 } 409 410 // Date/Time functions 411 412 void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest) 413 { 414 415 _cmsAssert(Dest != NULL); 416 _cmsAssert(Source != NULL); 417 418 Dest->tm_sec = _cmsAdjustEndianess16(Source->seconds); 419 Dest->tm_min = _cmsAdjustEndianess16(Source->minutes); 420 Dest->tm_hour = _cmsAdjustEndianess16(Source->hours); 421 Dest->tm_mday = _cmsAdjustEndianess16(Source->day); 422 Dest->tm_mon = _cmsAdjustEndianess16(Source->month) - 1; 423 Dest->tm_year = _cmsAdjustEndianess16(Source->year) - 1900; 424 Dest->tm_wday = -1; 425 Dest->tm_yday = -1; 426 Dest->tm_isdst = 0; 427 } 428 429 void CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source) 430 { 431 _cmsAssert(Dest != NULL); 432 _cmsAssert(Source != NULL); 433 434 Dest->seconds = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_sec); 435 Dest->minutes = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_min); 436 Dest->hours = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_hour); 437 Dest->day = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_mday); 438 Dest->month = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_mon + 1)); 439 Dest->year = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_year + 1900)); 440 } 441 442 // Read base and return type base 443 cmsTagTypeSignature CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io) 444 { 445 _cmsTagBase Base; 446 447 _cmsAssert(io != NULL); 448 449 if (io -> Read(io, &Base, sizeof(_cmsTagBase), 1) != 1) 450 return (cmsTagTypeSignature) 0; 451 452 return (cmsTagTypeSignature) _cmsAdjustEndianess32(Base.sig); 453 } 454 455 // Setup base marker 456 cmsBool CMSEXPORT _cmsWriteTypeBase(cmsIOHANDLER* io, cmsTagTypeSignature sig) 457 { 458 _cmsTagBase Base; 459 460 _cmsAssert(io != NULL); 461 462 Base.sig = (cmsTagTypeSignature) _cmsAdjustEndianess32(sig); 463 memset(&Base.reserved, 0, sizeof(Base.reserved)); 464 return io -> Write(io, sizeof(_cmsTagBase), &Base); 465 } 466 467 cmsBool CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io) 468 { 469 cmsUInt8Number Buffer[4]; 470 cmsUInt32Number NextAligned, At; 471 cmsUInt32Number BytesToNextAlignedPos; 472 473 _cmsAssert(io != NULL); 474 475 At = io -> Tell(io); 476 NextAligned = _cmsALIGNLONG(At); 477 BytesToNextAlignedPos = NextAligned - At; 478 if (BytesToNextAlignedPos == 0) return TRUE; 479 if (BytesToNextAlignedPos > 4) return FALSE; 480 481 return (io ->Read(io, Buffer, BytesToNextAlignedPos, 1) == 1); 482 } 483 484 cmsBool CMSEXPORT _cmsWriteAlignment(cmsIOHANDLER* io) 485 { 486 cmsUInt8Number Buffer[4]; 487 cmsUInt32Number NextAligned, At; 488 cmsUInt32Number BytesToNextAlignedPos; 489 490 _cmsAssert(io != NULL); 491 492 At = io -> Tell(io); 493 NextAligned = _cmsALIGNLONG(At); 494 BytesToNextAlignedPos = NextAligned - At; 495 if (BytesToNextAlignedPos == 0) return TRUE; 496 if (BytesToNextAlignedPos > 4) return FALSE; 497 498 memset(Buffer, 0, BytesToNextAlignedPos); 499 return io -> Write(io, BytesToNextAlignedPos, Buffer); 500 } 501 502 503 // To deal with text streams. 2K at most 504 cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...) 505 { 506 va_list args; 507 int len; 508 cmsUInt8Number Buffer[2048]; 509 cmsBool rc; 510 511 _cmsAssert(io != NULL); 512 _cmsAssert(frm != NULL); 513 514 va_start(args, frm); 515 516 len = vsnprintf((char*) Buffer, 2047, frm, args); 517 if (len < 0) { 518 va_end(args); 519 return FALSE; // Truncated, which is a fatal error for us 520 } 521 522 rc = io ->Write(io, len, Buffer); 523 524 va_end(args); 525 526 return rc; 527 } 528 529 530 // Plugin memory management ------------------------------------------------------------------------------------------------- 531 532 // Specialized malloc for plug-ins, that is freed upon exit. 533 void* _cmsPluginMalloc(cmsContext ContextID, cmsUInt32Number size) 534 { 535 struct _cmsContext_struct* ctx = _cmsGetContext(ContextID); 536 537 if (ctx ->MemPool == NULL) { 538 539 if (ContextID == NULL) { 540 541 ctx->MemPool = _cmsCreateSubAlloc(0, 2*1024); 542 if (ctx->MemPool == NULL) return NULL; 543 } 544 else { 545 cmsSignalError(ContextID, cmsERROR_CORRUPTION_DETECTED, "NULL memory pool on context"); 546 return NULL; 547 } 548 } 549 550 return _cmsSubAlloc(ctx->MemPool, size); 551 } 552 553 554 // Main plug-in dispatcher 555 cmsBool CMSEXPORT cmsPlugin(void* Plug_in) 556 { 557 return cmsPluginTHR(NULL, Plug_in); 558 } 559 560 cmsBool CMSEXPORT cmsPluginTHR(cmsContext id, void* Plug_in) 561 { 562 cmsPluginBase* Plugin; 563 564 for (Plugin = (cmsPluginBase*) Plug_in; 565 Plugin != NULL; 566 Plugin = Plugin -> Next) { 567 568 if (Plugin -> Magic != cmsPluginMagicNumber) { 569 cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin"); 570 return FALSE; 571 } 572 573 if (Plugin ->ExpectedVersion > LCMS_VERSION) { 574 cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current version is %d", 575 Plugin ->ExpectedVersion, LCMS_VERSION); 576 return FALSE; 577 } 578 579 switch (Plugin -> Type) { 580 581 case cmsPluginMemHandlerSig: 582 if (!_cmsRegisterMemHandlerPlugin(id, Plugin)) return FALSE; 583 break; 584 585 case cmsPluginInterpolationSig: 586 if (!_cmsRegisterInterpPlugin(id, Plugin)) return FALSE; 587 break; 588 589 case cmsPluginTagTypeSig: 590 if (!_cmsRegisterTagTypePlugin(id, Plugin)) return FALSE; 591 break; 592 593 case cmsPluginTagSig: 594 if (!_cmsRegisterTagPlugin(id, Plugin)) return FALSE; 595 break; 596 597 case cmsPluginFormattersSig: 598 if (!_cmsRegisterFormattersPlugin(id, Plugin)) return FALSE; 599 break; 600 601 case cmsPluginRenderingIntentSig: 602 if (!_cmsRegisterRenderingIntentPlugin(id, Plugin)) return FALSE; 603 break; 604 605 case cmsPluginParametricCurveSig: 606 if (!_cmsRegisterParametricCurvesPlugin(id, Plugin)) return FALSE; 607 break; 608 609 case cmsPluginMultiProcessElementSig: 610 if (!_cmsRegisterMultiProcessElementPlugin(id, Plugin)) return FALSE; 611 break; 612 613 case cmsPluginOptimizationSig: 614 if (!_cmsRegisterOptimizationPlugin(id, Plugin)) return FALSE; 615 break; 616 617 case cmsPluginTransformSig: 618 if (!_cmsRegisterTransformPlugin(id, Plugin)) return FALSE; 619 break; 620 621 case cmsPluginMutexSig: 622 if (!_cmsRegisterMutexPlugin(id, Plugin)) return FALSE; 623 break; 624 625 default: 626 cmsSignalError(id, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type); 627 return FALSE; 628 } 629 } 630 631 // Keep a reference to the plug-in 632 return TRUE; 633 } 634 635 636 // Revert all plug-ins to default 637 void CMSEXPORT cmsUnregisterPlugins(void) 638 { 639 cmsUnregisterPluginsTHR(NULL); 640 } 641 642 643 // The Global storage for system context. This is the one and only global variable 644 // pointers structure. All global vars are referenced here. 645 static struct _cmsContext_struct globalContext = { 646 647 NULL, // Not in the linked list 648 NULL, // No suballocator 649 { 650 NULL, // UserPtr, 651 &_cmsLogErrorChunk, // Logger, 652 &_cmsAlarmCodesChunk, // AlarmCodes, 653 &_cmsAdaptationStateChunk, // AdaptationState, 654 &_cmsMemPluginChunk, // MemPlugin, 655 &_cmsInterpPluginChunk, // InterpPlugin, 656 &_cmsCurvesPluginChunk, // CurvesPlugin, 657 &_cmsFormattersPluginChunk, // FormattersPlugin, 658 &_cmsTagTypePluginChunk, // TagTypePlugin, 659 &_cmsTagPluginChunk, // TagPlugin, 660 &_cmsIntentsPluginChunk, // IntentPlugin, 661 &_cmsMPETypePluginChunk, // MPEPlugin, 662 &_cmsOptimizationPluginChunk, // OptimizationPlugin, 663 &_cmsTransformPluginChunk, // TransformPlugin, 664 &_cmsMutexPluginChunk // MutexPlugin 665 }, 666 667 { NULL, NULL, NULL, NULL, NULL, NULL } // The default memory allocator is not used for context 0 668 }; 669 670 671 // The context pool (linked list head) 672 static _cmsMutex _cmsContextPoolHeadMutex = CMS_MUTEX_INITIALIZER; 673 static struct _cmsContext_struct* _cmsContextPoolHead = NULL; 674 675 // Internal, get associated pointer, with guessing. Never returns NULL. 676 struct _cmsContext_struct* _cmsGetContext(cmsContext ContextID) 677 { 678 struct _cmsContext_struct* id = (struct _cmsContext_struct*) ContextID; 679 struct _cmsContext_struct* ctx; 680 681 682 // On 0, use global settings 683 if (id == NULL) 684 return &globalContext; 685 686 // Search 687 for (ctx = _cmsContextPoolHead; 688 ctx != NULL; 689 ctx = ctx ->Next) { 690 691 // Found it? 692 if (id == ctx) 693 return ctx; // New-style context, 694 } 695 696 return &globalContext; 697 } 698 699 700 // Internal: get the memory area associanted with each context client 701 // Returns the block assigned to the specific zone. Never return NULL. 702 void* _cmsContextGetClientChunk(cmsContext ContextID, _cmsMemoryClient mc) 703 { 704 struct _cmsContext_struct* ctx; 705 void *ptr; 706 707 if ((int) mc < 0 || mc >= MemoryClientMax) { 708 709 cmsSignalError(ContextID, cmsERROR_INTERNAL, "Bad context client -- possible corruption"); 710 711 // This is catastrophic. Should never reach here 712 _cmsAssert(0); 713 714 // Reverts to global context 715 return globalContext.chunks[UserPtr]; 716 } 717 718 ctx = _cmsGetContext(ContextID); 719 ptr = ctx ->chunks[mc]; 720 721 if (ptr != NULL) 722 return ptr; 723 724 // A null ptr means no special settings for that context, and this 725 // reverts to Context0 globals 726 return globalContext.chunks[mc]; 727 } 728 729 730 // This function returns the given context its default pristine state, 731 // as no plug-ins were declared. There is no way to unregister a single 732 // plug-in, as a single call to cmsPluginTHR() function may register 733 // many different plug-ins simultaneously, then there is no way to 734 // identify which plug-in to unregister. 735 void CMSEXPORT cmsUnregisterPluginsTHR(cmsContext ContextID) 736 { 737 _cmsRegisterMemHandlerPlugin(ContextID, NULL); 738 _cmsRegisterInterpPlugin(ContextID, NULL); 739 _cmsRegisterTagTypePlugin(ContextID, NULL); 740 _cmsRegisterTagPlugin(ContextID, NULL); 741 _cmsRegisterFormattersPlugin(ContextID, NULL); 742 _cmsRegisterRenderingIntentPlugin(ContextID, NULL); 743 _cmsRegisterParametricCurvesPlugin(ContextID, NULL); 744 _cmsRegisterMultiProcessElementPlugin(ContextID, NULL); 745 _cmsRegisterOptimizationPlugin(ContextID, NULL); 746 _cmsRegisterTransformPlugin(ContextID, NULL); 747 _cmsRegisterMutexPlugin(ContextID, NULL); 748 } 749 750 751 // Returns the memory manager plug-in, if any, from the Plug-in bundle 752 static 753 cmsPluginMemHandler* _cmsFindMemoryPlugin(void* PluginBundle) 754 { 755 cmsPluginBase* Plugin; 756 757 for (Plugin = (cmsPluginBase*) PluginBundle; 758 Plugin != NULL; 759 Plugin = Plugin -> Next) { 760 761 if (Plugin -> Magic == cmsPluginMagicNumber && 762 Plugin -> ExpectedVersion <= LCMS_VERSION && 763 Plugin -> Type == cmsPluginMemHandlerSig) { 764 765 // Found! 766 return (cmsPluginMemHandler*) Plugin; 767 } 768 } 769 770 // Nope, revert to defaults 771 return NULL; 772 } 773 774 775 // Creates a new context with optional associated plug-ins. Caller may also specify an optional pointer to user-defined 776 // data that will be forwarded to plug-ins and logger. 777 cmsContext CMSEXPORT cmsCreateContext(void* Plugin, void* UserData) 778 { 779 struct _cmsContext_struct* ctx; 780 struct _cmsContext_struct fakeContext; 781 782 _cmsInstallAllocFunctions(_cmsFindMemoryPlugin(Plugin), &fakeContext.DefaultMemoryManager); 783 784 fakeContext.chunks[UserPtr] = UserData; 785 fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager; 786 787 // Create the context structure. 788 ctx = (struct _cmsContext_struct*) _cmsMalloc(&fakeContext, sizeof(struct _cmsContext_struct)); 789 if (ctx == NULL) 790 return NULL; // Something very wrong happened! 791 792 // Init the structure and the memory manager 793 memset(ctx, 0, sizeof(struct _cmsContext_struct)); 794 795 // Keep memory manager 796 memcpy(&ctx->DefaultMemoryManager, &fakeContext.DefaultMemoryManager, sizeof(_cmsMemPluginChunk)); 797 798 // Maintain the linked list (with proper locking) 799 _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); 800 ctx ->Next = _cmsContextPoolHead; 801 _cmsContextPoolHead = ctx; 802 _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); 803 804 ctx ->chunks[UserPtr] = UserData; 805 ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; 806 807 // Now we can allocate the pool by using default memory manager 808 ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); // default size about 32 pointers 809 if (ctx ->MemPool == NULL) { 810 811 cmsDeleteContext(ctx); 812 return NULL; 813 } 814 815 _cmsAllocLogErrorChunk(ctx, NULL); 816 _cmsAllocAlarmCodesChunk(ctx, NULL); 817 _cmsAllocAdaptationStateChunk(ctx, NULL); 818 _cmsAllocMemPluginChunk(ctx, NULL); 819 _cmsAllocInterpPluginChunk(ctx, NULL); 820 _cmsAllocCurvesPluginChunk(ctx, NULL); 821 _cmsAllocFormattersPluginChunk(ctx, NULL); 822 _cmsAllocTagTypePluginChunk(ctx, NULL); 823 _cmsAllocMPETypePluginChunk(ctx, NULL); 824 _cmsAllocTagPluginChunk(ctx, NULL); 825 _cmsAllocIntentsPluginChunk(ctx, NULL); 826 _cmsAllocOptimizationPluginChunk(ctx, NULL); 827 _cmsAllocTransformPluginChunk(ctx, NULL); 828 _cmsAllocMutexPluginChunk(ctx, NULL); 829 830 // Setup the plug-ins 831 if (!cmsPluginTHR(ctx, Plugin)) { 832 833 cmsDeleteContext(ctx); 834 return NULL; 835 } 836 837 return (cmsContext) ctx; 838 } 839 840 // Duplicates a context with all associated plug-ins. 841 // Caller may specify an optional pointer to user-defined 842 // data that will be forwarded to plug-ins and logger. 843 cmsContext CMSEXPORT cmsDupContext(cmsContext ContextID, void* NewUserData) 844 { 845 int i; 846 struct _cmsContext_struct* ctx; 847 const struct _cmsContext_struct* src = _cmsGetContext(ContextID); 848 849 void* userData = (NewUserData != NULL) ? NewUserData : src -> chunks[UserPtr]; 850 851 852 ctx = (struct _cmsContext_struct*) _cmsMalloc(ContextID, sizeof(struct _cmsContext_struct)); 853 if (ctx == NULL) 854 return NULL; // Something very wrong happened 855 856 // Setup default memory allocators 857 memcpy(&ctx->DefaultMemoryManager, &src->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager)); 858 859 // Maintain the linked list 860 _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); 861 ctx ->Next = _cmsContextPoolHead; 862 _cmsContextPoolHead = ctx; 863 _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); 864 865 ctx ->chunks[UserPtr] = userData; 866 ctx ->chunks[MemPlugin] = &ctx->DefaultMemoryManager; 867 868 ctx ->MemPool = _cmsCreateSubAlloc(ctx, 22 * sizeof(void*)); 869 if (ctx ->MemPool == NULL) { 870 871 cmsDeleteContext(ctx); 872 return NULL; 873 } 874 875 // Allocate all required chunks. 876 _cmsAllocLogErrorChunk(ctx, src); 877 _cmsAllocAlarmCodesChunk(ctx, src); 878 _cmsAllocAdaptationStateChunk(ctx, src); 879 _cmsAllocMemPluginChunk(ctx, src); 880 _cmsAllocInterpPluginChunk(ctx, src); 881 _cmsAllocCurvesPluginChunk(ctx, src); 882 _cmsAllocFormattersPluginChunk(ctx, src); 883 _cmsAllocTagTypePluginChunk(ctx, src); 884 _cmsAllocMPETypePluginChunk(ctx, src); 885 _cmsAllocTagPluginChunk(ctx, src); 886 _cmsAllocIntentsPluginChunk(ctx, src); 887 _cmsAllocOptimizationPluginChunk(ctx, src); 888 _cmsAllocTransformPluginChunk(ctx, src); 889 _cmsAllocMutexPluginChunk(ctx, src); 890 891 // Make sure no one failed 892 for (i=Logger; i < MemoryClientMax; i++) { 893 894 if (src ->chunks[i] == NULL) { 895 cmsDeleteContext((cmsContext) ctx); 896 return NULL; 897 } 898 } 899 900 return (cmsContext) ctx; 901 } 902 903 904 /* 905 static 906 struct _cmsContext_struct* FindPrev(struct _cmsContext_struct* id) 907 { 908 struct _cmsContext_struct* prev; 909 910 // Search for previous 911 for (prev = _cmsContextPoolHead; 912 prev != NULL; 913 prev = prev ->Next) 914 { 915 if (prev ->Next == id) 916 return prev; 917 } 918 919 return NULL; // List is empty or only one element! 920 } 921 */ 922 923 // Frees any resources associated with the given context, 924 // and destroys the context placeholder. 925 // The ContextID can no longer be used in any THR operation. 926 void CMSEXPORT cmsDeleteContext(cmsContext ContextID) 927 { 928 if (ContextID != NULL) { 929 930 struct _cmsContext_struct* ctx = (struct _cmsContext_struct*) ContextID; 931 struct _cmsContext_struct fakeContext; 932 struct _cmsContext_struct* prev; 933 934 memcpy(&fakeContext.DefaultMemoryManager, &ctx->DefaultMemoryManager, sizeof(ctx->DefaultMemoryManager)); 935 936 fakeContext.chunks[UserPtr] = ctx ->chunks[UserPtr]; 937 fakeContext.chunks[MemPlugin] = &fakeContext.DefaultMemoryManager; 938 939 // Get rid of plugins 940 cmsUnregisterPluginsTHR(ContextID); 941 942 // Since all memory is allocated in the private pool, all what we need to do is destroy the pool 943 if (ctx -> MemPool != NULL) 944 _cmsSubAllocDestroy(ctx ->MemPool); 945 ctx -> MemPool = NULL; 946 947 // Maintain list 948 _cmsEnterCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); 949 if (_cmsContextPoolHead == ctx) { 950 951 _cmsContextPoolHead = ctx->Next; 952 } 953 else { 954 955 // Search for previous 956 for (prev = _cmsContextPoolHead; 957 prev != NULL; 958 prev = prev ->Next) 959 { 960 if (prev -> Next == ctx) { 961 prev -> Next = ctx ->Next; 962 break; 963 } 964 } 965 } 966 _cmsLeaveCriticalSectionPrimitive(&_cmsContextPoolHeadMutex); 967 968 // free the memory block itself 969 _cmsFree(&fakeContext, ctx); 970 } 971 } 972 973 // Returns the user data associated to the given ContextID, or NULL if no user data was attached on context creation 974 void* CMSEXPORT cmsGetContextUserData(cmsContext ContextID) 975 { 976 return _cmsContextGetClientChunk(ContextID, UserPtr); 977 } 978 979