Tizen 2.0 Release
[external/lcms.git] / src / cmsplugin.c
1 //---------------------------------------------------------------------------------
2 //
3 //  Little Color Management System
4 //  Copyright (c) 1998-2010 Marti Maria Saguer
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining 
7 // a copy of this software and associated documentation files (the "Software"), 
8 // to deal in the Software without restriction, including without limitation 
9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 
10 // and/or sell copies of the Software, and to permit persons to whom the Software 
11 // is furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in 
14 // all copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
17 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
18 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
19 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
20 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
21 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //---------------------------------------------------------------------------------
25 //
26
27 #include "lcms2_internal.h"
28
29
30 // ----------------------------------------------------------------------------------
31 // Encoding & Decoding support functions
32 // ----------------------------------------------------------------------------------
33
34 //      Little-Endian to Big-Endian
35
36 // Adjust a word value after being readed/ before being written from/to an ICC profile
37 cmsUInt16Number CMSEXPORT  _cmsAdjustEndianess16(cmsUInt16Number Word)
38 {
39 #ifndef CMS_USE_BIG_ENDIAN
40
41     cmsUInt8Number* pByte = (cmsUInt8Number*) &Word;
42     cmsUInt8Number tmp;
43
44     tmp = pByte[0];
45     pByte[0] = pByte[1];
46     pByte[1] = tmp;
47 #endif      
48
49     return Word;
50 }
51
52
53 // Transports to properly encoded values - note that icc profiles does use big endian notation.
54
55 // 1 2 3 4
56 // 4 3 2 1
57
58 cmsUInt32Number CMSEXPORT  _cmsAdjustEndianess32(cmsUInt32Number DWord)
59 {
60 #ifndef CMS_USE_BIG_ENDIAN
61
62     cmsUInt8Number* pByte = (cmsUInt8Number*) &DWord;
63     cmsUInt8Number temp1;
64     cmsUInt8Number temp2;
65
66     temp1 = *pByte++;
67     temp2 = *pByte++;
68     *(pByte-1) = *pByte;
69     *pByte++ = temp2;
70     *(pByte-3) = *pByte;
71     *pByte = temp1;
72 #endif
73     return DWord;
74 }
75
76 // 1 2 3 4 5 6 7 8
77 // 8 7 6 5 4 3 2 1
78
79 void CMSEXPORT  _cmsAdjustEndianess64(cmsUInt64Number* Result, cmsUInt64Number QWord)
80 {
81     
82 #ifndef CMS_USE_BIG_ENDIAN
83     
84     cmsUInt8Number* pIn  = (cmsUInt8Number*) &QWord;
85     cmsUInt8Number* pOut = (cmsUInt8Number*) Result;
86
87     _cmsAssert(Result != NULL);
88
89     pOut[7] = pIn[0];
90     pOut[6] = pIn[1];
91     pOut[5] = pIn[2];
92     pOut[4] = pIn[3];
93     pOut[3] = pIn[4];
94     pOut[2] = pIn[5];   
95     pOut[1] = pIn[6];
96     pOut[0] = pIn[7];
97
98 #else
99
100     _cmsAssert(Result != NULL);
101
102     *Result = QWord;
103 #endif
104 }
105
106 // Auxiliar -- read 8, 16 and 32-bit numbers
107 cmsBool CMSEXPORT  _cmsReadUInt8Number(cmsIOHANDLER* io, cmsUInt8Number* n)
108 {
109     cmsUInt8Number tmp;
110
111     _cmsAssert(io != NULL);
112
113     if (io -> Read(io, &tmp, sizeof(cmsUInt8Number), 1) != 1) 
114             return FALSE;   
115
116     if (n != NULL) *n = tmp;
117     return TRUE;
118 }
119
120 cmsBool CMSEXPORT  _cmsReadUInt16Number(cmsIOHANDLER* io, cmsUInt16Number* n)
121 {
122     cmsUInt16Number tmp;
123
124     _cmsAssert(io != NULL);
125
126     if (io -> Read(io, &tmp, sizeof(cmsUInt16Number), 1) != 1) 
127             return FALSE;   
128
129     if (n != NULL) *n = _cmsAdjustEndianess16(tmp);
130     return TRUE;
131 }
132
133 cmsBool CMSEXPORT  _cmsReadUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, cmsUInt16Number* Array)
134 {
135     cmsUInt32Number i;
136
137     _cmsAssert(io != NULL);
138
139     for (i=0; i < n; i++) {
140
141         if (Array != NULL) {
142             if (!_cmsReadUInt16Number(io, Array + i)) return FALSE;
143         }
144         else {
145             if (!_cmsReadUInt16Number(io, NULL)) return FALSE;
146         }
147
148     }
149     return TRUE;
150 }
151
152 cmsBool CMSEXPORT  _cmsReadUInt32Number(cmsIOHANDLER* io, cmsUInt32Number* n)
153 {
154     cmsUInt32Number tmp;
155
156     _cmsAssert(io != NULL);
157
158     if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1) 
159             return FALSE;   
160
161     if (n != NULL) *n = _cmsAdjustEndianess32(tmp);
162     return TRUE;
163 }
164
165 cmsBool CMSEXPORT  _cmsReadFloat32Number(cmsIOHANDLER* io, cmsFloat32Number* n)
166 {
167     cmsUInt32Number tmp;
168
169     _cmsAssert(io != NULL);
170
171     if (io -> Read(io, &tmp, sizeof(cmsFloat32Number), 1) != 1) 
172             return FALSE;   
173
174     if (n != NULL) {
175
176         tmp = _cmsAdjustEndianess32(tmp);
177         *n = *(cmsFloat32Number*) &tmp;
178     }
179     return TRUE;
180 }
181
182
183 cmsBool CMSEXPORT   _cmsReadUInt64Number(cmsIOHANDLER* io, cmsUInt64Number* n)
184 {
185     cmsUInt64Number tmp;
186
187     _cmsAssert(io != NULL);
188
189     if (io -> Read(io, &tmp, sizeof(cmsUInt64Number), 1) != 1) 
190             return FALSE;   
191
192     if (n != NULL) _cmsAdjustEndianess64(n, tmp);
193     return TRUE;
194 }
195
196
197 cmsBool CMSEXPORT  _cmsRead15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number* n)
198 {
199     cmsUInt32Number tmp;
200
201     _cmsAssert(io != NULL);
202
203     if (io -> Read(io, &tmp, sizeof(cmsUInt32Number), 1) != 1) 
204             return FALSE;   
205
206     if (n != NULL) {
207         *n = _cms15Fixed16toDouble(_cmsAdjustEndianess32(tmp));
208     }
209
210     return TRUE;
211 }
212
213
214 // Jun-21-2000: Some profiles (those that comes with W2K) comes
215 // with the media white (media black?) x 100. Add a sanity check
216
217 static
218 void NormalizeXYZ(cmsCIEXYZ* Dest)
219 {
220     while (Dest -> X > 2. &&
221            Dest -> Y > 2. &&
222            Dest -> Z > 2.) {
223
224                Dest -> X /= 10.;
225                Dest -> Y /= 10.;
226                Dest -> Z /= 10.;
227        }
228 }
229
230 cmsBool CMSEXPORT  _cmsReadXYZNumber(cmsIOHANDLER* io, cmsCIEXYZ* XYZ)
231 {
232     cmsEncodedXYZNumber xyz;
233
234     _cmsAssert(io != NULL);
235
236     if (io ->Read(io, &xyz, sizeof(cmsEncodedXYZNumber), 1) != 1) return FALSE;
237
238     if (XYZ != NULL) {
239
240         XYZ->X = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.X));
241         XYZ->Y = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Y));
242         XYZ->Z = _cms15Fixed16toDouble(_cmsAdjustEndianess32(xyz.Z));
243
244         NormalizeXYZ(XYZ);
245     }
246     return TRUE;
247 }
248
249 cmsBool CMSEXPORT  _cmsWriteUInt8Number(cmsIOHANDLER* io, cmsUInt8Number n)
250 {
251     _cmsAssert(io != NULL);
252
253     if (io -> Write(io, sizeof(cmsUInt8Number), &n) != 1) 
254             return FALSE;   
255     
256     return TRUE;
257 }
258
259 cmsBool CMSEXPORT  _cmsWriteUInt16Number(cmsIOHANDLER* io, cmsUInt16Number n)
260 {
261     cmsUInt16Number tmp;
262
263     _cmsAssert(io != NULL);
264
265     tmp = _cmsAdjustEndianess16(n);
266     if (io -> Write(io, sizeof(cmsUInt16Number), &tmp) != 1) 
267             return FALSE;   
268     
269     return TRUE;
270 }
271
272 cmsBool CMSEXPORT  _cmsWriteUInt16Array(cmsIOHANDLER* io, cmsUInt32Number n, const cmsUInt16Number* Array)
273 {
274     cmsUInt32Number i;
275
276     _cmsAssert(io != NULL);
277     _cmsAssert(Array != NULL);
278
279     for (i=0; i < n; i++) {
280         if (!_cmsWriteUInt16Number(io, Array[i])) return FALSE;
281     }
282
283     return TRUE;
284 }
285
286 cmsBool CMSEXPORT  _cmsWriteUInt32Number(cmsIOHANDLER* io, cmsUInt32Number n)
287 {
288     cmsUInt32Number tmp;
289
290     _cmsAssert(io != NULL);
291
292     tmp = _cmsAdjustEndianess32(n);
293     if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) 
294             return FALSE;   
295     
296     return TRUE;
297 }
298
299
300 cmsBool CMSEXPORT  _cmsWriteFloat32Number(cmsIOHANDLER* io, cmsFloat32Number n)
301 {
302     cmsUInt32Number tmp;
303
304     _cmsAssert(io != NULL);
305
306     tmp = *(cmsUInt32Number*) &n;
307     tmp = _cmsAdjustEndianess32(tmp);
308     if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) 
309             return FALSE;   
310     
311     return TRUE;
312 }
313
314 cmsBool CMSEXPORT  _cmsWriteUInt64Number(cmsIOHANDLER* io, cmsUInt64Number n)
315 {
316     cmsUInt64Number tmp;
317
318     _cmsAssert(io != NULL);
319
320     _cmsAdjustEndianess64(&tmp, n);
321     if (io -> Write(io, sizeof(cmsUInt64Number), &tmp) != 1) 
322             return FALSE;   
323     
324     return TRUE;
325 }
326
327 cmsBool CMSEXPORT  _cmsWrite15Fixed16Number(cmsIOHANDLER* io, cmsFloat64Number n)
328 {
329     cmsUInt32Number tmp;
330
331     _cmsAssert(io != NULL);
332
333     tmp = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(n));
334     if (io -> Write(io, sizeof(cmsUInt32Number), &tmp) != 1) 
335             return FALSE;   
336     
337     return TRUE;
338 }
339
340 cmsBool CMSEXPORT  _cmsWriteXYZNumber(cmsIOHANDLER* io, const cmsCIEXYZ* XYZ)
341 {
342     cmsEncodedXYZNumber xyz;
343   
344     _cmsAssert(io != NULL);
345     _cmsAssert(XYZ != NULL);
346
347     xyz.X = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->X));
348     xyz.Y = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Y));
349     xyz.Z = _cmsAdjustEndianess32(_cmsDoubleTo15Fixed16(XYZ->Z));
350
351     return io -> Write(io,  sizeof(cmsEncodedXYZNumber), &xyz);
352 }
353
354 // from Fixed point 8.8 to double
355 cmsFloat64Number CMSEXPORT _cms8Fixed8toDouble(cmsUInt16Number fixed8)
356 {
357        cmsUInt8Number  msb, lsb;
358
359        lsb = (cmsUInt8Number) (fixed8 & 0xff);
360        msb = (cmsUInt8Number) (((cmsUInt16Number) fixed8 >> 8) & 0xff);
361
362        return (cmsFloat64Number) ((cmsFloat64Number) msb + ((cmsFloat64Number) lsb / 256.0));
363 }
364
365 cmsUInt16Number CMSEXPORT _cmsDoubleTo8Fixed8(cmsFloat64Number val)
366 {
367     cmsS15Fixed16Number GammaFixed32 = _cmsDoubleTo15Fixed16(val);
368     return  (cmsUInt16Number) ((GammaFixed32 >> 8) & 0xFFFF);       
369 }
370
371 // from Fixed point 15.16 to double
372 cmsFloat64Number CMSEXPORT _cms15Fixed16toDouble(cmsS15Fixed16Number fix32)
373 {
374     cmsFloat64Number floater, sign, mid;
375     int Whole, FracPart;
376
377     sign  = (fix32 < 0 ? -1 : 1);
378     fix32 = abs(fix32);
379
380     Whole     = (cmsUInt16Number)(fix32 >> 16) & 0xffff;
381     FracPart  = (cmsUInt16Number)(fix32 & 0xffff);
382
383     mid     = (cmsFloat64Number) FracPart / 65536.0;
384     floater = (cmsFloat64Number) Whole + mid;
385
386     return sign * floater;
387 }
388
389 // from double to Fixed point 15.16 
390 cmsS15Fixed16Number CMSEXPORT _cmsDoubleTo15Fixed16(cmsFloat64Number v)
391 {
392     return ((cmsS15Fixed16Number) floor((v)*65536.0 + 0.5));
393 }
394
395 // Date/Time functions 
396
397 void CMSEXPORT _cmsDecodeDateTimeNumber(const cmsDateTimeNumber *Source, struct tm *Dest)
398 {
399
400     _cmsAssert(Dest != NULL);
401     _cmsAssert(Source != NULL);
402
403     Dest->tm_sec   = _cmsAdjustEndianess16(Source->seconds);
404     Dest->tm_min   = _cmsAdjustEndianess16(Source->minutes);
405     Dest->tm_hour  = _cmsAdjustEndianess16(Source->hours);
406     Dest->tm_mday  = _cmsAdjustEndianess16(Source->day);
407     Dest->tm_mon   = _cmsAdjustEndianess16(Source->month) - 1;
408     Dest->tm_year  = _cmsAdjustEndianess16(Source->year) - 1900;
409     Dest->tm_wday  = -1;
410     Dest->tm_yday  = -1;
411     Dest->tm_isdst = 0;
412 }
413
414 void CMSEXPORT _cmsEncodeDateTimeNumber(cmsDateTimeNumber *Dest, const struct tm *Source)
415 {
416     _cmsAssert(Dest != NULL);
417     _cmsAssert(Source != NULL);
418
419     Dest->seconds = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_sec);
420     Dest->minutes = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_min);
421     Dest->hours   = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_hour);
422     Dest->day     = _cmsAdjustEndianess16((cmsUInt16Number) Source->tm_mday);
423     Dest->month   = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_mon + 1));
424     Dest->year    = _cmsAdjustEndianess16((cmsUInt16Number) (Source->tm_year + 1900));
425 }
426
427 // Read base and return type base
428 cmsTagTypeSignature CMSEXPORT _cmsReadTypeBase(cmsIOHANDLER* io)
429 {
430     _cmsTagBase Base;
431
432     _cmsAssert(io != NULL);
433
434     if (io -> Read(io, &Base, sizeof(_cmsTagBase), 1) != 1) 
435         return (cmsTagTypeSignature) 0;
436
437     return (cmsTagTypeSignature) _cmsAdjustEndianess32(Base.sig);
438 }
439
440 // Setup base marker
441 cmsBool  CMSEXPORT _cmsWriteTypeBase(cmsIOHANDLER* io, cmsTagTypeSignature sig)
442 {
443     _cmsTagBase  Base;
444
445     _cmsAssert(io != NULL);
446
447     Base.sig = (cmsTagTypeSignature) _cmsAdjustEndianess32(sig);
448     memset(&Base.reserved, 0, sizeof(Base.reserved));
449     return io -> Write(io, sizeof(_cmsTagBase), &Base);
450 }
451
452 cmsBool CMSEXPORT _cmsReadAlignment(cmsIOHANDLER* io)
453 {
454     cmsUInt8Number  Buffer[4];
455     cmsUInt32Number NextAligned, At;
456     cmsUInt32Number BytesToNextAlignedPos;
457     
458     _cmsAssert(io != NULL);
459
460     At = io -> Tell(io);
461     NextAligned = _cmsALIGNLONG(At);
462     BytesToNextAlignedPos = NextAligned - At;
463     if (BytesToNextAlignedPos == 0) return TRUE;
464     if (BytesToNextAlignedPos > 4)  return FALSE;
465
466     return (io ->Read(io, Buffer, BytesToNextAlignedPos, 1) == 1);
467 }
468
469 cmsBool CMSEXPORT _cmsWriteAlignment(cmsIOHANDLER* io)
470 {
471     cmsUInt8Number  Buffer[4];
472     cmsUInt32Number NextAligned, At;
473     cmsUInt32Number BytesToNextAlignedPos;
474
475     _cmsAssert(io != NULL);
476
477     At = io -> Tell(io);
478     NextAligned = _cmsALIGNLONG(At);
479     BytesToNextAlignedPos = NextAligned - At;
480     if (BytesToNextAlignedPos == 0) return TRUE;
481     if (BytesToNextAlignedPos > 4)  return FALSE;
482
483     memset(Buffer, 0, BytesToNextAlignedPos);
484     return io -> Write(io, BytesToNextAlignedPos, Buffer);
485 }
486
487
488 // To deal with text streams. 2K at most
489 cmsBool CMSEXPORT _cmsIOPrintf(cmsIOHANDLER* io, const char* frm, ...)
490 {
491     va_list args;
492     int len;
493     cmsUInt8Number Buffer[2048];
494     cmsBool rc;
495
496     _cmsAssert(io != NULL);
497     _cmsAssert(frm != NULL);
498
499     va_start(args, frm);
500
501     len = vsnprintf((char*) Buffer, 2047, frm, args);
502     if (len < 0) return FALSE;   // Truncated, which is a fatal error for us
503
504     rc = io ->Write(io, len, Buffer);
505     
506     va_end(args);
507
508     return rc;
509 }
510
511
512 // Plugin memory management -------------------------------------------------------------------------------------------------
513
514 static _cmsSubAllocator* PluginPool = NULL;
515
516 // Specialized malloc for plug-ins, that is freed upon exit.
517 void* _cmsPluginMalloc(cmsUInt32Number size)
518 {
519     if (PluginPool == NULL)
520         PluginPool = _cmsCreateSubAlloc(0, 4*1024);
521
522     return _cmsSubAlloc(PluginPool, size);
523 }
524
525
526 // Main plug-in dispatcher
527 cmsBool CMSEXPORT cmsPlugin(void* Plug_in)
528 {
529     cmsPluginBase* Plugin;
530
531     for (Plugin = (cmsPluginBase*) Plug_in; 
532          Plugin != NULL; 
533          Plugin = Plugin -> Next) {
534
535             if (Plugin -> Magic != cmsPluginMagicNumber) {
536                 cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin");
537                 return FALSE;
538             }
539
540             if (Plugin ->ExpectedVersion > LCMS_VERSION) {
541                 cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "plugin needs Little CMS %d, current  version is %d", 
542                     Plugin ->ExpectedVersion, LCMS_VERSION);
543                 return FALSE;
544             }
545
546             switch (Plugin -> Type) {
547
548                 case cmsPluginMemHandlerSig:
549                     if (!_cmsRegisterMemHandlerPlugin(Plugin)) return FALSE;
550                     break;
551
552                 case cmsPluginInterpolationSig:
553                     if (!_cmsRegisterInterpPlugin(Plugin)) return FALSE;
554                     break;
555                 
556                 case cmsPluginTagTypeSig:
557                     if (!_cmsRegisterTagTypePlugin(Plugin)) return FALSE;
558                     break;
559             
560                 case cmsPluginTagSig:
561                     if (!_cmsRegisterTagPlugin(Plugin)) return FALSE;
562                     break;
563
564                 case cmsPluginFormattersSig:
565                     if (!_cmsRegisterFormattersPlugin(Plugin)) return FALSE;
566                     break;
567
568                 case cmsPluginRenderingIntentSig:
569                     if (!_cmsRegisterRenderingIntentPlugin(Plugin)) return FALSE;
570                     break;
571
572                 case cmsPluginParametricCurveSig:
573                     if (!_cmsRegisterParametricCurvesPlugin(Plugin)) return FALSE;
574                     break;
575
576                 case cmsPluginMultiProcessElementSig:
577                     if (!_cmsRegisterMultiProcessElementPlugin(Plugin)) return FALSE;
578                     break;
579
580                 case cmsPluginOptimizationSig:
581                     if (!_cmsRegisterOptimizationPlugin(Plugin)) return FALSE;
582                     break;
583
584                 default:
585                     cmsSignalError(0, cmsERROR_UNKNOWN_EXTENSION, "Unrecognized plugin type '%X'", Plugin -> Type);
586                     return FALSE;
587             }            
588     }
589
590     // Keep a reference to the plug-in
591     return TRUE;
592 }
593
594
595 // Revert all plug-ins to default
596 void CMSEXPORT cmsUnregisterPlugins(void)
597 {
598     _cmsRegisterMemHandlerPlugin(NULL);
599     _cmsRegisterInterpPlugin(NULL);
600     _cmsRegisterTagTypePlugin(NULL);
601     _cmsRegisterTagPlugin(NULL);
602     _cmsRegisterFormattersPlugin(NULL);
603     _cmsRegisterRenderingIntentPlugin(NULL);
604     _cmsRegisterParametricCurvesPlugin(NULL);
605     _cmsRegisterMultiProcessElementPlugin(NULL);
606     _cmsRegisterOptimizationPlugin(NULL);
607
608     if (PluginPool != NULL)
609         _cmsSubAllocDestroy(PluginPool);
610
611     PluginPool = NULL;
612 }