Bug 399703 - Password manager offers to store logins with empty passwords. r=gavin
[wine-gecko.git] / modules / lcms / src / cmsio0.c
blob8d641fab0e49519e10b218f9b5a602e0774e123d
1 //
2 // Little cms
3 // Copyright (C) 1998-2007 Marti Maria
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining
6 // a copy of this software and associated documentation files (the "Software"),
7 // to deal in the Software without restriction, including without limitation
8 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 // and/or sell copies of the Software, and to permit persons to whom the Software
10 // is furnished to do so, subject to the following conditions:
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
17 // THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
24 // Generic I/O, tag dictionary management, profile struct
28 #include "lcms.h"
31 // Memory-based stream ---------------------------------------------------
33 typedef struct {
34 LPBYTE Block; // Points to allocated memory
35 size_t Size; // Size of allocated memory
36 int Pointer; // Points to current location
37 int FreeBlockOnClose; // As title
39 } FILEMEM;
41 static
42 LPVOID MemoryOpen(LPBYTE Block, size_t Size, char Mode)
44 FILEMEM* fm = (FILEMEM*) _cmsMalloc(sizeof(FILEMEM));
45 if (fm == NULL) return NULL;
47 ZeroMemory(fm, sizeof(FILEMEM));
49 if (Mode == 'r') {
51 fm ->Block = (LPBYTE) _cmsMalloc(Size);
52 if (fm ->Block == NULL) {
53 _cmsFree(fm);
54 return NULL;
57 CopyMemory(fm->Block, Block, Size);
58 fm ->FreeBlockOnClose = TRUE;
60 else {
61 fm ->Block = Block;
62 fm ->FreeBlockOnClose = FALSE;
65 fm ->Size = Size;
66 fm ->Pointer = 0;
68 return (LPVOID) fm;
72 static
73 size_t MemoryRead(LPVOID buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc)
75 FILEMEM* ResData = (FILEMEM*) Icc ->stream;
76 LPBYTE Ptr;
77 size_t len = size * count;
80 if (ResData -> Pointer + len > ResData -> Size){
82 len = (ResData -> Size - ResData -> Pointer);
83 cmsSignalError(LCMS_ERRC_ABORTED, "Read from memory error. Got %d bytes, block should be of %d bytes", len * size, count * size);
84 return 0;
87 Ptr = ResData -> Block;
88 Ptr += ResData -> Pointer;
89 CopyMemory(buffer, Ptr, len);
90 ResData -> Pointer += (int) len;
92 return count;
95 // SEEK_CUR is assumed
97 static
98 LCMSBOOL MemorySeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
100 FILEMEM* ResData = (FILEMEM*) Icc ->stream;
102 if (offset > ResData ->Size) {
103 cmsSignalError(LCMS_ERRC_ABORTED, "Pointer error; probably corrupted file");
104 return TRUE;
107 ResData ->Pointer = (DWORD) offset;
108 return FALSE;
111 // FTell
113 static
114 size_t MemoryTell(struct _lcms_iccprofile_struct* Icc)
116 FILEMEM* ResData = (FILEMEM*) Icc ->stream;
118 return ResData -> Pointer;
122 // Writes data to memory, also keeps used space for further reference. NO CHECK IS PERFORMED
124 static
125 LCMSBOOL MemoryWrite(struct _lcms_iccprofile_struct* Icc, size_t size, void *Ptr)
127 FILEMEM* ResData = (FILEMEM*) Icc ->stream;
129 if (size == 0) return TRUE;
131 if (ResData != NULL)
132 CopyMemory(ResData ->Block + Icc ->UsedSpace, Ptr, size);
134 Icc->UsedSpace += size;
136 return TRUE;
140 static
141 LCMSBOOL MemoryClose(struct _lcms_iccprofile_struct* Icc)
143 FILEMEM* ResData = (FILEMEM*) Icc ->stream;
145 if (ResData ->FreeBlockOnClose) {
147 if (ResData ->Block) _cmsFree(ResData ->Block);
149 _cmsFree(ResData);
150 return 0;
154 // File-based stream -------------------------------------------------------
156 static
157 LPVOID FileOpen(const char* filename)
159 return (void*) fopen(filename, "rb");
162 static
163 size_t FileRead(void *buffer, size_t size, size_t count, struct _lcms_iccprofile_struct* Icc)
165 size_t nReaded = fread(buffer, size, count, (FILE*) Icc->stream);
166 if (nReaded != count) {
167 cmsSignalError(LCMS_ERRC_ABORTED, "Read error. Got %d bytes, block should be of %d bytes", nReaded * size, count * size);
168 return 0;
171 return nReaded;
175 static
176 LCMSBOOL FileSeek(struct _lcms_iccprofile_struct* Icc, size_t offset)
178 if (fseek((FILE*) Icc ->stream, (long) offset, SEEK_SET) != 0) {
180 cmsSignalError(LCMS_ERRC_ABORTED, "Seek error; probably corrupted file");
181 return TRUE;
184 return FALSE;
188 static
189 size_t FileTell(struct _lcms_iccprofile_struct* Icc)
191 return ftell((FILE*) Icc ->stream);
194 // Writes data to stream, also keeps used space for further reference
197 static
198 LCMSBOOL FileWrite(struct _lcms_iccprofile_struct* Icc, size_t size, LPVOID Ptr)
200 if (size == 0) return TRUE;
202 Icc->UsedSpace += size;
204 if (Icc->stream == NULL) {
206 return TRUE;
209 return (fwrite(Ptr, size, 1, (FILE*) Icc->stream) == 1);
213 static
214 LCMSBOOL FileClose(struct _lcms_iccprofile_struct* Icc)
216 return fclose((FILE*) Icc ->stream);
219 // ----------------------------------------------------------------------------------------------------
222 // Creates an empty structure holding all required parameters
224 cmsHPROFILE _cmsCreateProfilePlaceholder(void)
227 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) _cmsMalloc(sizeof(LCMSICCPROFILE));
228 if (Icc == NULL) return NULL;
230 // Empty values
231 ZeroMemory(Icc, sizeof(LCMSICCPROFILE));
233 // Make sure illuminant is correct
234 Icc ->Illuminant = *cmsD50_XYZ();
236 // Set it to empty
237 Icc -> TagCount = 0;
239 // Return the handle
240 return (cmsHPROFILE) Icc;
244 // Return the number of tags
245 icInt32Number LCMSEXPORT cmsGetTagCount(cmsHPROFILE hProfile)
247 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
248 return Icc->TagCount;
251 // Return the tag signature of a given tag number
252 icTagSignature LCMSEXPORT cmsGetTagSignature(cmsHPROFILE hProfile, icInt32Number n)
254 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
256 if (n < 0 || n > Icc->TagCount) return (icTagSignature) 0; // Mark as not available
258 return Icc ->TagNames[n];
262 // Search for a specific tag in tag dictionary
263 // Returns position or -1 if tag not found
265 icInt32Number _cmsSearchTag(LPLCMSICCPROFILE Profile, icTagSignature sig, LCMSBOOL lSignalError)
267 icInt32Number i;
269 if (sig == 0) return -1; // 0 identifies a special tag holding raw memory.
271 for (i=0; i < Profile -> TagCount; i++) {
273 if (sig == Profile -> TagNames[i])
274 return i;
277 if (lSignalError)
278 cmsSignalError(LCMS_ERRC_ABORTED, "Tag '%lx' not found", sig);
280 return -1;
284 // Check existance
286 LCMSBOOL LCMSEXPORT cmsIsTag(cmsHPROFILE hProfile, icTagSignature sig)
288 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
289 return _cmsSearchTag(Icc, sig, FALSE) >= 0;
294 // Search for a particular tag, replace if found or add new one else
296 LPVOID _cmsInitTag(LPLCMSICCPROFILE Icc, icTagSignature sig, size_t size, const void* Init)
298 LPVOID Ptr;
299 icInt32Number i;
301 i = _cmsSearchTag(Icc, sig, FALSE);
303 if (i >=0) {
305 if (Icc -> TagPtrs[i]) _cmsFree(Icc -> TagPtrs[i]);
307 else {
309 i = Icc -> TagCount;
310 Icc -> TagCount++;
312 if (Icc ->TagCount >= MAX_TABLE_TAG) {
314 cmsSignalError(LCMS_ERRC_ABORTED, "Too many tags (%d)", MAX_TABLE_TAG);
315 Icc ->TagCount = MAX_TABLE_TAG-1;
316 return NULL;
321 Ptr = _cmsMalloc(size);
322 if (Ptr == NULL) return NULL;
324 CopyMemory(Ptr, Init, size);
326 Icc ->TagNames[i] = sig;
327 Icc ->TagSizes[i] = size;
328 Icc ->TagPtrs[i] = Ptr;
330 return Ptr;
337 // Creates a profile from file read placeholder
339 LPLCMSICCPROFILE _cmsCreateProfileFromFilePlaceholder(const char* FileName)
341 LPLCMSICCPROFILE NewIcc;
342 LPVOID ICCfile = FileOpen(FileName);
344 if (ICCfile == NULL) {
346 cmsSignalError(LCMS_ERRC_ABORTED, "File '%s' not found", FileName);
347 return NULL;
350 NewIcc = (LPLCMSICCPROFILE) _cmsCreateProfilePlaceholder();
351 if (NewIcc == NULL) return NULL;
353 strncpy(NewIcc -> PhysicalFile, FileName, MAX_PATH-1);
354 NewIcc -> PhysicalFile[MAX_PATH-1] = 0;
356 NewIcc ->stream = ICCfile;
358 NewIcc ->Read = FileRead;
359 NewIcc ->Seek = FileSeek;
360 NewIcc ->Tell = FileTell;
361 NewIcc ->Close = FileClose;
362 NewIcc ->Write = NULL;
364 NewIcc ->IsWrite = FALSE;
369 return NewIcc;
373 // Creates a profile from memory read placeholder
375 LPLCMSICCPROFILE _cmsCreateProfileFromMemPlaceholder(LPVOID MemPtr, DWORD dwSize)
378 LPLCMSICCPROFILE NewIcc;
379 LPVOID ICCfile = MemoryOpen((LPBYTE) MemPtr, (size_t) dwSize, 'r');
382 if (ICCfile == NULL) {
384 cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't allocate %ld bytes for profile", dwSize);
385 return NULL;
389 NewIcc = (LPLCMSICCPROFILE) _cmsCreateProfilePlaceholder();
390 if (NewIcc == NULL) return NULL;
392 NewIcc -> PhysicalFile[0] = 0;
393 NewIcc ->stream = ICCfile;
395 NewIcc ->Read = MemoryRead;
396 NewIcc ->Seek = MemorySeek;
397 NewIcc ->Tell = MemoryTell;
398 NewIcc ->Close = MemoryClose;
399 NewIcc ->Write = NULL;
401 NewIcc ->IsWrite = FALSE;
404 return NewIcc;
408 // Turn a placeholder into file writter
410 void _cmsSetSaveToDisk(LPLCMSICCPROFILE Icc, const char* FileName)
413 if (FileName == NULL) {
415 Icc ->stream = NULL;
417 else {
419 Icc ->stream = fopen(FileName, "wb");
420 if (Icc ->stream == NULL)
421 cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't write to file '%s'", FileName);
424 Icc ->Write = FileWrite; // Save to disk
425 Icc ->Close = FileClose;
430 // Turn a placeholder into memory writter
432 void _cmsSetSaveToMemory(LPLCMSICCPROFILE Icc, LPVOID MemPtr, size_t dwSize)
435 if (MemPtr == NULL) {
437 Icc ->stream = NULL;
439 else {
441 Icc ->stream = (FILEMEM*) MemoryOpen((LPBYTE) MemPtr, dwSize, 'w');
442 if (Icc ->stream == NULL)
443 cmsSignalError(LCMS_ERRC_ABORTED, "Couldn't write to memory");
446 Icc ->Write = MemoryWrite;
447 Icc ->Close = MemoryClose;
451 // ----------------------------------------------------------------------- Set/Get several struct members
456 LCMSBOOL LCMSEXPORT cmsTakeMediaWhitePoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
458 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
459 *Dest = Icc -> MediaWhitePoint;
460 return TRUE;
464 LCMSBOOL LCMSEXPORT cmsTakeMediaBlackPoint(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
466 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
467 *Dest = Icc -> MediaBlackPoint;
468 return TRUE;
471 LCMSBOOL LCMSEXPORT cmsTakeIluminant(LPcmsCIEXYZ Dest, cmsHPROFILE hProfile)
473 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
474 *Dest = Icc -> Illuminant;
475 return TRUE;
478 int LCMSEXPORT cmsTakeRenderingIntent(cmsHPROFILE hProfile)
480 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
481 return (int) Icc -> RenderingIntent;
484 void LCMSEXPORT cmsSetRenderingIntent(cmsHPROFILE hProfile, int RenderingIntent)
486 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
487 Icc -> RenderingIntent = (icRenderingIntent) RenderingIntent;
491 DWORD LCMSEXPORT cmsTakeHeaderFlags(cmsHPROFILE hProfile)
493 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
494 return (DWORD) Icc -> flags;
497 void LCMSEXPORT cmsSetHeaderFlags(cmsHPROFILE hProfile, DWORD Flags)
499 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
500 Icc -> flags = (icUInt32Number) Flags;
503 DWORD LCMSEXPORT cmsTakeHeaderAttributes(cmsHPROFILE hProfile)
505 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
506 return (DWORD) Icc -> attributes;
509 void LCMSEXPORT cmsSetHeaderAttributes(cmsHPROFILE hProfile, DWORD Flags)
511 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
512 Icc -> attributes = (icUInt32Number) Flags;
516 const BYTE* LCMSEXPORT cmsTakeProfileID(cmsHPROFILE hProfile)
518 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
519 return Icc ->ProfileID;
522 void LCMSEXPORT cmsSetProfileID(cmsHPROFILE hProfile, LPBYTE ProfileID)
524 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
525 CopyMemory(Icc -> ProfileID, ProfileID, 16);
529 LCMSBOOL LCMSEXPORT cmsTakeCreationDateTime(struct tm *Dest, cmsHPROFILE hProfile)
531 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
532 CopyMemory(Dest, &Icc ->Created, sizeof(struct tm));
533 return TRUE;
537 icColorSpaceSignature LCMSEXPORT cmsGetPCS(cmsHPROFILE hProfile)
539 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
540 return Icc -> PCS;
544 void LCMSEXPORT cmsSetPCS(cmsHPROFILE hProfile, icColorSpaceSignature pcs)
546 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
547 Icc -> PCS = pcs;
550 icColorSpaceSignature LCMSEXPORT cmsGetColorSpace(cmsHPROFILE hProfile)
552 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
553 return Icc -> ColorSpace;
556 void LCMSEXPORT cmsSetColorSpace(cmsHPROFILE hProfile, icColorSpaceSignature sig)
558 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
559 Icc -> ColorSpace = sig;
562 icProfileClassSignature LCMSEXPORT cmsGetDeviceClass(cmsHPROFILE hProfile)
564 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
565 return Icc -> DeviceClass;
568 DWORD LCMSEXPORT cmsGetProfileICCversion(cmsHPROFILE hProfile)
570 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
571 return (DWORD) Icc -> Version;
574 void LCMSEXPORT cmsSetProfileICCversion(cmsHPROFILE hProfile, DWORD Version)
576 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
577 Icc -> Version = Version;
581 void LCMSEXPORT cmsSetDeviceClass(cmsHPROFILE hProfile, icProfileClassSignature sig)
583 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) hProfile;
584 Icc -> DeviceClass = sig;
588 // --------------------------------------------------------------------------------------------------------------
591 static
592 int SizeOfGammaTab(LPGAMMATABLE In)
594 return sizeof(GAMMATABLE) + (In -> nEntries - 1)*sizeof(WORD);
598 // Creates a phantom tag holding a memory block
600 static
601 LPVOID DupBlock(LPLCMSICCPROFILE Icc, LPVOID Block, size_t size)
603 if (Block != NULL && size > 0)
604 return _cmsInitTag(Icc, (icTagSignature) 0, size, Block);
605 else
606 return NULL;
610 // This is tricky, since LUT structs does have pointers
612 LCMSBOOL LCMSEXPORT _cmsAddLUTTag(cmsHPROFILE hProfile, icTagSignature sig, const void* lut)
614 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
615 LPLUT Orig, Stored;
616 unsigned int i;
618 // The struct itself
620 Orig = (LPLUT) lut;
621 Stored = (LPLUT) _cmsInitTag(Icc, (icTagSignature) sig, sizeof(LUT), lut);
623 // dup' the memory blocks
624 for (i=0; i < Orig ->InputChan; i++)
625 Stored -> L1[i] = (LPWORD) DupBlock(Icc, (LPWORD) Orig ->L1[i],
626 sizeof(WORD) * Orig ->In16params.nSamples);
628 for (i=0; i < Orig ->OutputChan; i++)
629 Stored -> L2[i] = (LPWORD) DupBlock(Icc, (LPWORD) Orig ->L2[i],
630 sizeof(WORD) * Orig ->Out16params.nSamples);
632 Stored -> T = (LPWORD) DupBlock(Icc, (LPWORD) Orig ->T, Orig -> Tsize);
634 // Zero any additional pointer
635 Stored ->CLut16params.p8 = NULL;
636 return TRUE;
640 LCMSBOOL LCMSEXPORT _cmsAddXYZTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* XYZ)
642 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
644 _cmsInitTag(Icc, sig, sizeof(cmsCIEXYZ), XYZ);
645 return TRUE;
649 LCMSBOOL LCMSEXPORT _cmsAddTextTag(cmsHPROFILE hProfile, icTagSignature sig, const char* Text)
651 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
653 _cmsInitTag(Icc, sig, strlen(Text)+1, (LPVOID) Text);
654 return TRUE;
657 LCMSBOOL LCMSEXPORT _cmsAddGammaTag(cmsHPROFILE hProfile, icTagSignature sig, LPGAMMATABLE TransferFunction)
659 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
661 _cmsInitTag(Icc, sig, SizeOfGammaTab(TransferFunction), TransferFunction);
662 return TRUE;
666 LCMSBOOL LCMSEXPORT _cmsAddChromaticityTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsCIExyYTRIPLE Chrm)
668 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
670 _cmsInitTag(Icc, sig, sizeof(cmsCIExyYTRIPLE), Chrm);
671 return TRUE;
675 LCMSBOOL LCMSEXPORT _cmsAddSequenceDescriptionTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsSEQ pseq)
677 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
679 _cmsInitTag(Icc, sig, sizeof(int) + pseq -> n * sizeof(cmsPSEQDESC), pseq);
680 return TRUE;
685 LCMSBOOL LCMSEXPORT _cmsAddNamedColorTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
687 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
689 _cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc);
690 return TRUE;
694 LCMSBOOL LCMSEXPORT _cmsAddDateTimeTag(cmsHPROFILE hProfile, icTagSignature sig, struct tm *DateTime)
696 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
698 _cmsInitTag(Icc, sig, sizeof(struct tm), DateTime);
699 return TRUE;
703 LCMSBOOL LCMSEXPORT _cmsAddColorantTableTag(cmsHPROFILE hProfile, icTagSignature sig, LPcmsNAMEDCOLORLIST nc)
705 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
707 _cmsInitTag(Icc, sig, sizeof(cmsNAMEDCOLORLIST) + (nc ->nColors - 1) * sizeof(cmsNAMEDCOLOR), nc);
708 return TRUE;
712 LCMSBOOL LCMSEXPORT _cmsAddChromaticAdaptationTag(cmsHPROFILE hProfile, icTagSignature sig, const cmsCIEXYZ* mat)
714 LPLCMSICCPROFILE Icc = (LPLCMSICCPROFILE) (LPSTR) hProfile;
716 _cmsInitTag(Icc, sig, 3*sizeof(cmsCIEXYZ), mat);
717 return TRUE;