Forward compatibility: build relative-base link libraries where needed
[AROS.git] / workbench / libs / icon / diskobj35io.c
bloba0f45b32f3b0365079b3aa2b693fd01fa023340c
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
8 #include <aros/debug.h>
10 #include <datatypes/pictureclass.h>
12 #include <proto/dos.h>
13 #include <proto/alib.h>
15 #include <zlib.h>
17 #include <aros/bigendianio.h>
18 #include <aros/asmcall.h>
20 #include "icon_intern.h"
22 /****************************************************************************************/
24 #define ID_ICON MAKE_ID('I','C','O','N')
25 #define ID_FACE MAKE_ID('F','A','C','E')
26 #define ID_IMAG MAKE_ID('I','M','A','G')
27 #define ID_png MAKE_ID('p','n','g',' ')
28 #define ID_ARGB MAKE_ID('A','R','G','B')
30 /****************************************************************************************/
32 struct FileFaceChunk
34 UBYTE Width;
35 UBYTE Height;
36 UBYTE Flags;
37 UBYTE Aspect;
38 UBYTE MaxPaletteBytes[2];
41 struct FileImageChunk
43 UBYTE TransparentColor;
44 UBYTE NumColors;
45 UBYTE Flags;
46 UBYTE ImageFormat;
47 UBYTE PaletteFormat;
48 UBYTE Depth;
49 UBYTE NumImageBytes[2];
50 UBYTE NumPaletteBytes[2];
53 /****************************************************************************************/
55 static LONG MyDOSStreamHandler(struct Hook *hook, struct IFFHandle * iff, struct IFFStreamCmd * cmd)
57 LONG error = 0;
59 struct IconBase *IconBase = hook->h_Data;
61 switch(cmd->sc_Command)
63 case IFFCMD_INIT:
64 case IFFCMD_CLEANUP:
65 error = 0;
66 break;
68 case IFFCMD_READ:
69 error = (FRead((BPTR)iff->iff_Stream, cmd->sc_Buf, 1, cmd->sc_NBytes)) != cmd->sc_NBytes;
70 break;
72 case IFFCMD_WRITE:
73 error = (FWrite((BPTR)iff->iff_Stream, cmd->sc_Buf, 1, cmd->sc_NBytes)) != cmd->sc_NBytes;
74 break;
76 case IFFCMD_SEEK:
77 Flush((BPTR)iff->iff_Stream);
78 error = (Seek((BPTR)iff->iff_Stream, cmd->sc_NBytes, OFFSET_CURRENT)) == -1;
79 break;
82 return error;
85 static LONG MyMemStreamHandler(struct Hook *hook, struct IFFHandle * iff, struct IFFStreamCmd * cmd)
87 LONG error = 0;
88 APTR *buffp = (APTR *)iff->iff_Stream;
89 APTR buff = *buffp;
91 switch(cmd->sc_Command)
93 case IFFCMD_INIT:
94 case IFFCMD_CLEANUP:
95 error = 0;
96 break;
98 case IFFCMD_READ:
99 error = 0;
100 CopyMem(buff, cmd->sc_Buf, cmd->sc_NBytes);
101 (*buffp) += cmd->sc_NBytes;
102 break;
104 case IFFCMD_WRITE:
105 error = 0;
106 CopyMem(cmd->sc_Buf, buff, cmd->sc_NBytes);
107 (*buffp) += cmd->sc_NBytes;
108 break;
110 case IFFCMD_SEEK:
111 (*buffp) += cmd->sc_NBytes;
112 error = 0;
113 break;
116 return error;
119 /****************************************************************************************/
121 /* Decode35() based on ModifyIcon by Dirk Stöcker */
123 /****************************************************************************************/
125 static char *Decode35(UBYTE *buffer, UBYTE *outbuffer, LONG numbytes, LONG bits, LONG entries)
127 int cop = 0, loop = 0, numbits = 0, mask, curentry = 0;
128 ULONG bitbuf = 0;
129 UBYTE byte;
131 mask = (1<<bits)-1;
133 while((numbytes || (cop && numbits >= bits)) && (curentry < entries))
135 if(!cop)
137 if(numbits < 8)
139 bitbuf = (bitbuf<<8)|*(buffer++); --numbytes;
140 numbits += 8;
143 byte = (bitbuf>>(numbits-8))&0xFF;
144 numbits -= 8;
146 if(byte <= 127) cop = byte+1;
147 else if(byte > 128) loop = 256-byte+1;
148 else continue;
151 if(cop) ++loop;
153 if(numbits < bits)
155 bitbuf = (bitbuf<<8)|*(buffer++); --numbytes;
156 numbits += 8;
159 byte = (bitbuf>>(numbits-bits))&mask;
161 while(loop && (curentry < entries))
163 *outbuffer++ = byte;
164 ++curentry;
165 --loop;
168 if(cop) --cop;
170 numbits -= bits;
173 return curentry != entries ? "error decoding new icon data" : 0;
176 /****************************************************************************************/
178 VOID MakeMask35(UBYTE *imgdata, UBYTE *imgmask, UBYTE transpcolor, LONG imagew, LONG imageh)
180 UBYTE *src, *dst;
181 WORD x, y, bpr, mask;
183 memset(imgmask, 0xFF, RASSIZE(imagew, imageh));
185 bpr = ((imagew + 15) & ~15) / 8;
186 src = imgdata;
187 dst = imgmask;
189 for(y = 0; y < imageh; y++)
191 UBYTE *dstx = dst;
193 mask = 0x80;
195 for(x = 0; x < imagew; x++)
197 if (*(src++) == transpcolor)
199 *dstx &= ~mask;
202 mask >>= 1;
203 if (!mask)
205 mask = 0x80;
206 dstx++;
209 dst += bpr;
215 /****************************************************************************************/
216 void *malloc(size_t size)
218 return AllocVec(size, MEMF_PUBLIC);
221 void free(void *ptr)
223 FreeVec(ptr);
226 STATIC BOOL ReadARGB35(struct DiskObject *icon, struct IFFHandle *iff, struct FileFaceChunk *fc,
227 LONG chunksize, UBYTE **argbptr,
228 struct IconBase *IconBase)
230 UBYTE *src, *mem, *argb = NULL;
231 LONG imagew, imageh;
232 ULONG zsize;
233 uLongf size;
234 int err;
236 imagew = fc->Width + 1;
237 imageh = fc->Height + 1;
238 size = imagew * imageh * 4;
240 D(bug("[%s] ARGB size is %dx%d, %d => %d bytes\n", __func__, imagew, imageh, chunksize, size));
242 src = mem = AllocMemIcon(icon, chunksize, MEMF_PUBLIC, IconBase);
243 if (!src) return FALSE;
245 if (ReadChunkBytes(iff, src, chunksize) != chunksize)
247 goto fail;
250 argb = AllocMemIcon(icon, size, MEMF_PUBLIC, IconBase);
251 if (!argb) goto fail;
253 zsize = AROS_BE2WORD(*((UWORD *)(src + 6))) + 1;
254 err = uncompress(argb, &size, src + 10, zsize);
255 if (err != Z_OK) {
256 D(bug("%s: Can't uncompress %d ARGB bytes: %s\n", __func__, zsize, zError(err)));
257 goto fail;
260 *argbptr = argb;
262 return TRUE;
264 fail:
265 return FALSE;
268 /****************************************************************************************/
270 STATIC BOOL ReadImage35(struct DiskObject *icon, struct IFFHandle *iff, struct FileFaceChunk *fc,
271 struct FileImageChunk *ic, UBYTE **imgdataptr,
272 struct ColorRegister **imgpalptr, struct IconBase *IconBase)
274 UBYTE *src, *mem, *imgdata = NULL;
275 struct ColorRegister *imgpal = NULL;
276 LONG size, imgsize, palsize, imagew, imageh, numcols;
278 imagew = fc->Width + 1;
279 imageh = fc->Height + 1;
280 numcols = ic->NumColors + 1;
282 imgsize = ic->NumImageBytes[0] * 256 + ic->NumImageBytes[1] + 1;
283 if (ic->Flags & IMAGE35F_HASPALETTE)
285 palsize = ic->NumPaletteBytes[0] * 256 + ic->NumPaletteBytes[1] + 1;
287 else
289 palsize = 0;
292 D(bug("[%s] Image size is %dx%d, %d bytes\n", __func__, imagew, imageh, imgsize));
293 D(bug("[%s] Palette size is %d colors, %d bytes\n", __func__, numcols, palsize));
295 size = imgsize + palsize;
297 src = mem = AllocMemIcon(icon, size, MEMF_PUBLIC, IconBase);
298 if (!src) return FALSE;
300 if (ReadChunkBytes(iff, src, size) != size)
302 return FALSE;
305 if (ic->Flags & IMAGE35F_HASPALETTE)
307 if (numcols < 1 || numcols > 256)
308 return FALSE;
310 size = numcols * sizeof(struct ColorRegister);
311 imgpal = AllocMemIcon(icon, size, MEMF_PUBLIC, IconBase);
312 if (!imgpal) goto fail;
315 size = imagew * imageh;
316 imgdata = AllocMemIcon(icon, size, MEMF_PUBLIC, IconBase);
317 if (!imgdata) goto fail;
319 if (ic->ImageFormat == 0)
321 memcpy(imgdata, src, imagew * imageh);
323 else
325 Decode35(src, imgdata, imgsize, ic->Depth, imagew * imageh);
327 src += imgsize;
329 if (ic->Flags & IMAGE35F_HASPALETTE)
331 struct ColorRegister *dst;
333 dst = imgpal;
335 D(bug("[%s] PaletteFormat %d, src %p\n", __func__, ic->PaletteFormat, src));
336 if (ic->PaletteFormat == 0)
338 ULONG i, r, g, b;
340 for(i = 0; i < numcols; i++)
342 r = *src++;
343 g = *src++;
344 b = *src++;
346 dst->red = r;
347 dst->green = g;
348 dst->blue = b;
349 dst++;
352 else
354 CONST_STRPTR err;
356 err = Decode35(src, (UBYTE *)imgpal, palsize, 8, 3 * numcols);
357 if (err) {
358 D(bug("[%s] Palette decode error: %s\n", __func__, err));
359 imgpal = NULL;
363 if (imgpal && sizeof(struct ColorRegister) != 3)
365 struct ColorRegister *dst;
366 UWORD i, r, g, b;
368 D(bug("[%s] Realigning ColorRegister\n", __func__));
370 src = (APTR)imgpal + 3 * numcols;
371 dst = (struct ColorRegister *)(imgpal + sizeof(struct ColorRegister) * numcols);
373 for (i = 0; i < numcols; i++)
375 b = *--src;
376 g = *--src;
377 r = *--src;
379 dst--;
381 dst->red = r;
382 dst->green = g;
383 dst->blue = b;
388 } /* if (ic->Flags & IMAGE35F_HASPALETTE) */
390 *imgdataptr = imgdata;
391 *imgpalptr = imgpal;
393 return TRUE;
395 fail:
396 return FALSE;
399 /****************************************************************************************/
401 BOOL ReadIcon35(struct NativeIcon *icon, struct Hook *streamhook,
402 void *stream, struct IconBase *IconBase)
404 static const LONG const stopchunks[] =
406 ID_ICON, ID_FACE,
407 ID_ICON, ID_IMAG,
408 ID_ICON, ID_png,
409 ID_ICON, ID_ARGB,
412 struct IFFHandle *iff;
413 struct Hook iffhook;
414 struct FileFaceChunk fc;
415 struct FileImageChunk ic1, ic2;
416 UBYTE *argb1data = NULL, *argb2data = NULL;
417 UBYTE *img1data = NULL, *img2data = NULL;
418 struct ColorRegister *img1pal = NULL, *img2pal = NULL;
419 BOOL have_face = FALSE, have_imag1 = FALSE, have_imag2 = FALSE;
420 BOOL have_argb1 = FALSE, have_argb2 = FALSE;
421 int have_png = 0;
422 LONG here, extrasize;
423 APTR data;
425 D(bug("ReadIcon35, stream %p\n", stream));
427 here = Seek((BPTR)stream, 0, OFFSET_CURRENT);
428 D(bug("[%s] Extra data starts at %d\n", __func__, here));
429 Seek((BPTR)stream, 0, OFFSET_END);
430 extrasize = Seek((BPTR)stream, 0, OFFSET_CURRENT);
431 D(bug("[%s] Extra data ends at %d\n", __func__, extrasize));
432 extrasize -= here;
433 Seek((BPTR)stream, here, OFFSET_BEGINNING);
434 D(bug("[%s] .. %d bytes\n", __func__, extrasize));
436 /* No extra data? That's fine. */
437 if (extrasize <= 0) {
438 D(bug("[%s] No extra data\n", __func__));
439 return TRUE;
442 if (IFFParseBase == NULL)
443 return FALSE;
445 data = AllocMemIcon(&icon->ni_DiskObject, extrasize, MEMF_PUBLIC,
446 IconBase);
447 if (data == NULL)
448 return FALSE;
450 if (Read((BPTR)stream, data, extrasize) != extrasize) {
451 D(bug("[%s] Can't read extra data\n", __func__));
452 return FALSE;
455 icon->ni_Extra.Data = data;
456 icon->ni_Extra.Size = extrasize;
458 iffhook.h_Entry = (HOOKFUNC)HookEntry;
459 iffhook.h_SubEntry = (HOOKFUNC)MyMemStreamHandler;
460 iffhook.h_Data = (APTR)IconBase;
462 if ((iff = AllocIFF()))
464 D(bug("ReadIcon35. AllocIFF okay\n"));
466 iff->iff_Stream = (IPTR)&data;
468 InitIFF(iff, IFFF_RSEEK, &iffhook);
470 if (!OpenIFF(iff, IFFF_READ))
472 D(bug("ReadIcon35. OpenIFF okay\n"));
474 if (!StopChunks(iff, stopchunks, 4))
476 LONG error;
478 D(bug("ReadIcon35. StopChunks okay\n"));
480 while(!(error = ParseIFF(iff, IFFPARSE_SCAN)))
482 struct ContextNode *cn;
484 cn = CurrentChunk(iff);
486 D(bug("inside ParseIFF loop\n"));
487 if ((cn->cn_ID == ID_FACE) && (cn->cn_Size >= sizeof(struct FileFaceChunk)))
489 D(bug("ReadIcon35. Found FACE chunk\n"));
490 if (ReadChunkBytes(iff, &fc, sizeof(fc)) == sizeof(fc))
492 have_face = TRUE;
495 else if (have_face && (cn->cn_ID == ID_IMAG) && (cn->cn_Size >= sizeof(struct FileImageChunk)))
497 D(bug("ReadIcon35. Found IMAG chunk\n"));
498 if (ReadChunkBytes(iff, (have_imag1 ? &ic2 : &ic1), sizeof(ic1)) == sizeof(ic1))
500 if (have_imag1)
502 if (ReadImage35(&icon->ni_DiskObject, iff, &fc, &ic2, &img2data, &img2pal, IconBase))
504 have_imag2 = TRUE;
507 else
509 if (ReadImage35(&icon->ni_DiskObject, iff, &fc, &ic1, &img1data, &img1pal, IconBase))
511 have_imag1 = TRUE;
516 } else if (cn->cn_ID == ID_ARGB) {
517 D(bug("ReadIcon35. Found ARGB chunk\n"));
518 if (have_argb1)
520 if (ReadARGB35(&icon->ni_DiskObject, iff, &fc, cn->cn_Size, &argb2data, IconBase))
522 have_argb2 = TRUE;
525 else
527 if (ReadARGB35(&icon->ni_DiskObject, iff, &fc, cn->cn_Size, &argb1data, IconBase))
529 have_argb1 = TRUE;
532 } else if (cn->cn_ID == ID_png) {
533 if (have_png < 2) {
534 LONG here = data - icon->ni_Extra.Data;
535 D(bug("[%s] Found PNG image %d\n", __func__, have_png));
536 icon->ni_Extra.PNG[have_png].Offset = here;
537 icon->ni_Extra.PNG[have_png].Size = cn->cn_Size;
538 } else {
539 D(bug("[%s] Ignoring PNG image %d\n", __func__, have_png));
541 have_png++;
542 } else {
543 D(bug("[%s] Unknown chunk ID 0x%08x\n", __func__, cn->cn_ID));
546 } /* while(!ParseIFF(iff, IFFPARSE_SCAN)) */
548 } /* if (!StopChunks(iff, stopchunks, 4)) */
550 } /* if (!OpenIFF(iff, IFFF_READ)) */
552 FreeIFF(iff);
554 } /* if ((iff = AllocIFF())) */
556 /* Only use the Width and Height fields of a FACE section
557 * if it also contains image data.
559 if (have_face) {
560 if (have_argb1 || have_argb2 || have_imag1 || have_imag2) {
561 icon->ni_Face.Width = fc.Width + 1;
562 icon->ni_Face.Height = fc.Height + 1;
564 //icon->icon35.flags = fc.Flags;
565 icon->ni_Face.Aspect = fc.Aspect;
568 if (have_argb1)
570 icon->ni_Image[0].ARGB = (APTR)argb1data;
573 if (have_argb2)
575 icon->ni_Image[1].ARGB = (APTR)argb2data;
578 if (have_imag1)
580 icon->ni_Image[0].ImageData = img1data;
581 icon->ni_Image[0].Palette = img1pal;
582 icon->ni_Image[0].Pens = ic1.NumColors + 1;
583 icon->ni_Image[0].TransparentColor = ic1.TransparentColor;
585 if (icon->ni_Image[0].Pens < 1 || icon->ni_Image[0].Pens > 256)
586 return FALSE;
588 if (have_imag2)
590 icon->ni_Image[1].ImageData = img2data;
591 icon->ni_Image[1].TransparentColor = ic2.TransparentColor;
593 if (img2pal)
595 icon->ni_Image[1].Palette = img2pal;
596 icon->ni_Image[1].Pens = ic2.NumColors + 1;
597 if (icon->ni_Image[1].Pens < 1 || icon->ni_Image[0].Pens > 256)
598 return FALSE;
601 else
603 icon->ni_Image[1].Palette = img1pal;
604 icon->ni_Image[1].Pens = ic1.NumColors + 1;
609 return TRUE;
612 /****************************************************************************************/
614 /* Encode35() based on ModifyIcon source by Dirk Stöcker */
616 /****************************************************************************************/
618 static UBYTE *Encode35(struct DiskObject *icon, ULONG depth, UBYTE *dtype, LONG *dsize, ULONG size, CONST UBYTE *src, APTR IconBase)
620 int i, j, k;
621 ULONG bitbuf, numbits;
622 UBYTE *buf;
623 LONG ressize, numcopy, numequal;
625 buf = AllocMemIcon(icon, size * 2, MEMF_PUBLIC, IconBase);
626 if (!buf) return NULL;
628 numcopy = 0;
629 numequal = 1;
630 bitbuf = 0;
631 numbits = 0;
632 ressize = 0;
633 k = 0; /* the really output pointer */
635 for(i = 1; numequal || numcopy;)
637 if(i < size && numequal && (src[i-1] == src[i]))
639 ++numequal; ++i;
641 else if(i < size && numequal*depth <= 16)
643 numcopy += numequal; numequal = 1; ++i;
645 else
647 /* care for end case, where it maybe better to join the two */
648 if(i == size && numcopy + numequal <= 128 && (numequal-1)*depth <= 8)
650 numcopy += numequal; numequal = 0;
653 if(numcopy)
655 if((j = numcopy) > 128) j = 128;
657 bitbuf = (bitbuf<<8) | (j-1);
658 numcopy -= j;
660 else
662 if((j = numequal) > 128) j = 128;
664 bitbuf = (bitbuf<<8) | (256-(j-1));
665 numequal -= j;
666 k += j-1;
667 j = 1;
670 buf[ressize++] = (bitbuf >> numbits);
672 while(j--)
674 numbits += depth;
675 bitbuf = (bitbuf<<depth) | src[k++];
677 if(numbits >= 8)
679 numbits -= 8;
680 buf[ressize++] = (bitbuf >> numbits);
684 if(i < size && !numcopy && !numequal)
686 numequal = 1; ++i;
691 if(numbits)
692 buf[ressize++] = bitbuf << (8-numbits);
694 if(ressize > size) /* no RLE */
696 ressize = size;
697 *dtype = 0;
698 for(i = 0; i < size; ++i)
699 buf[i]= src[i];
701 else
702 *dtype = 1;
704 *dsize = ressize;
706 return buf;
709 /****************************************************************************************/
711 static BOOL WriteARGB35(struct IFFHandle *iff, struct NativeIcon *icon,
712 APTR ARGB, struct IconBase *IconBase)
714 struct ARGB35_Header {
715 ULONG ztype; /* Always 1 */
716 ULONG zsize; /* Compressed size, -1 */
717 UWORD resv; /* Always 0 */
718 } ahdr;
719 Bytef *zdest;
720 uLongf zsize, size;
721 int err;
722 BOOL ok = FALSE;
724 /* Assume uncompressible.. */
725 zsize = size = icon->ni_Face.Width * icon->ni_Face.Height * 4;
727 zdest = AllocVec(zsize, MEMF_ANY);
728 if (!zdest)
729 return FALSE;
731 err = compress(zdest, &zsize, ARGB, size);
732 if (err != Z_OK) {
733 D(bug("%s: Can't compress %d ARGB bytes: %s\n", __func__, size, zError(err)));
734 goto exit;
737 ahdr.ztype = AROS_LONG2BE(1);
738 ahdr.zsize = AROS_LONG2BE(zsize - 1);
739 ahdr.resv = AROS_WORD2BE(0);
741 if (!PushChunk(iff, ID_ICON, ID_ARGB, IFFSIZE_UNKNOWN))
743 ok = TRUE;
745 if ((WriteChunkBytes(iff, &ahdr, sizeof(ahdr)) != sizeof(ahdr)) ||
746 (WriteChunkBytes(iff, zdest, zsize) != zsize))
748 ok = FALSE;
751 PopChunk(iff);
754 exit:
755 FreeVec(zdest);
756 return ok;
759 /****************************************************************************************/
761 static BOOL WriteImage35(struct IFFHandle *iff, struct NativeIcon *icon,
762 struct NativeIconImage *img, struct IconBase *IconBase)
764 struct FileImageChunk ic;
765 UBYTE *imagedata, *pal = NULL;
766 LONG imagesize, palsize = 0;
767 UBYTE imagepacked, palpacked = 0;
768 UBYTE imageflags = 0;
769 BOOL ok = FALSE;
771 if (img->Palette)
773 pal = Encode35(&icon->ni_DiskObject, 8, &palpacked, &palsize, img->Pens * 3, (APTR)img->Palette, IconBase);
774 if (!pal) return FALSE;
775 imageflags |= IMAGE35F_HASPALETTE;
778 if (img->TransparentColor >= 0)
779 imageflags |= IMAGE35F_HASTRANSPARENTCOLOR;
781 imagedata = Encode35(&icon->ni_DiskObject, 8, &imagepacked, &imagesize,
782 icon->ni_Face.Width * icon->ni_Face.Height, img->ImageData, IconBase);
784 if (!imagedata)
786 return FALSE;
789 ic.TransparentColor = (imageflags & IMAGE35F_HASTRANSPARENTCOLOR) ? 255 : img->TransparentColor;
790 ic.NumColors = img->Pens - 1;
791 ic.Flags = imageflags;
792 ic.ImageFormat = imagepacked;
793 ic.PaletteFormat = palpacked;
794 ic.Depth = 8;
795 ic.NumImageBytes[0] = (imagesize - 1) / 256;
796 ic.NumImageBytes[1] = (imagesize - 1) & 255;
797 ic.NumPaletteBytes[0] = (palsize - 1) / 256;
798 ic.NumPaletteBytes[1] = (palsize - 1) & 255;
800 if (!PushChunk(iff, ID_ICON, ID_IMAG, IFFSIZE_UNKNOWN))
802 ok = TRUE;
804 if (WriteChunkBytes(iff, &ic, sizeof(ic)) != sizeof(ic))
806 ok = FALSE;
809 if (ok)
811 if (WriteChunkBytes(iff, imagedata, imagesize) != imagesize)
813 ok = FALSE;
817 if (ok && pal)
819 if (WriteChunkBytes(iff, pal, palsize) != palsize)
821 ok = FALSE;
826 PopChunk(iff);
828 } /* if (!PushChunk(iff, ID_ICON, ID_IMAG, IFFSIZE_UNKNOWN)) */
830 return ok;
833 /****************************************************************************************/
835 BOOL WriteIcon35(struct NativeIcon *icon, struct Hook *streamhook,
836 void *stream, struct IconBase *IconBase)
838 struct IFFHandle *iff;
839 struct Hook iffhook;
840 struct FileFaceChunk fc;
841 BOOL ok = FALSE;
843 D(bug("WriteIcon35\n"));
845 if (IFFParseBase == NULL)
847 D(bug("%s: IFFParseBase is NULL\n", __func__));
848 return FALSE;
851 if (!GetNativeIcon(&icon->ni_DiskObject, IconBase))
853 D(bug("%s: No native icon data\n", __func__));
854 return TRUE;
857 /* If the extra imagery wasn't modified, just write it out. */
858 if (icon->ni_Extra.Size != 0) {
859 LONG len;
861 len = FWrite((BPTR)stream, icon->ni_Extra.Data, 1, icon->ni_Extra.Size);
862 if (len < 0 || (ULONG)len != icon->ni_Extra.Size)
863 return FALSE;
865 return TRUE;
868 D(bug("%s: Write Icon %p\n", __func__, icon));
869 D(bug("%s: n_Image[0].ImageData = %p\n", __func__, icon->ni_Image[0].ImageData));
870 D(bug("%s: n_Image[1].ImageData = %p\n", __func__, icon->ni_Image[1].ImageData));
871 D(bug("%s: n_Image[0].ARGB = %p\n", __func__, icon->ni_Image[0].ARGB));
872 D(bug("%s: n_Image[1].ARGB = %p\n", __func__, icon->ni_Image[1].ARGB));
874 if (icon->ni_Image[0].ImageData == NULL && icon->ni_Image[0].ARGB == NULL)
876 D(bug("%s: No image data to write\n", __func__));
877 return TRUE;
880 iffhook.h_Entry = (HOOKFUNC)HookEntry;
881 iffhook.h_SubEntry = (HOOKFUNC)MyDOSStreamHandler;
882 iffhook.h_Data = (APTR)IconBase;
884 if ((iff = AllocIFF()))
886 D(bug("WriteIcon35. AllocIFF okay\n"));
888 iff->iff_Stream = (IPTR)stream;
890 InitIFF(iff, IFFF_RSEEK, &iffhook);
892 if (!OpenIFF(iff, IFFF_WRITE))
894 D(bug("WriteIcon35. OpenIFF okay\n"));
896 if (!PushChunk(iff, ID_ICON, ID_FORM, IFFSIZE_UNKNOWN))
898 D(bug("WriteIcon35. PushChunk(ID_ICON, ID_FORM) okay\n"));
900 if (!PushChunk(iff, ID_ICON, ID_FACE, sizeof(struct FileFaceChunk)))
902 WORD cmapentries;
904 D(bug("WriteIcon35. PushChunk(ID_ICON, ID_FACE) okay\n"));
906 fc.Width = icon->ni_Face.Width - 1;
907 fc.Height = icon->ni_Face.Height - 1;
908 fc.Flags = (icon->ni_Frameless) ? ICON35F_FRAMELESS : 0;
909 fc.Aspect = icon->ni_Face.Aspect;
911 cmapentries = icon->ni_Image[0].Pens;
913 if (icon->ni_Image[1].ImageData &&
914 icon->ni_Image[1].Palette)
916 if (icon->ni_Image[1].Pens > cmapentries)
918 cmapentries = icon->ni_Image[1].Pens;
922 cmapentries = cmapentries * 3 - 1;
924 fc.MaxPaletteBytes[0] = cmapentries / 256;
925 fc.MaxPaletteBytes[1] = cmapentries & 255;
927 if (WriteChunkBytes(iff, &fc, sizeof(fc)) == sizeof(fc))
929 D(bug("WriteIcon35. WriteChunkBytes of FACE chunk ok.\n"));
931 PopChunk(iff);
933 if (icon->ni_Image[0].ImageData)
935 if (WriteImage35(iff, icon, &icon->ni_Image[0], IconBase))
937 D(bug("WriteIcon35. WriteImage35() of 1st image ok.\n"));
939 if (icon->ni_Image[1].ImageData)
941 if (WriteImage35(iff, icon, &icon->ni_Image[1], IconBase))
943 D(bug("WriteIcon35. WriteImage35() of 2nd image ok.\n"));
945 ok = TRUE;
948 } /* if (icon->ni_Image[1].ImageData) */
949 else
951 ok = TRUE;
954 } /* if (WriteImage35(iff, &icon, &icon->ni_Image[0], IconBase)) */
955 } /* if (icon->ni_Image[0].ImageData) */
957 if (icon->ni_Image[0].ARGB)
959 if (WriteARGB35(iff, icon, &icon->ni_Image[0].ARGB, IconBase))
961 D(bug("WriteIcon35. WriteImage35() of 1st image ok.\n"));
962 if (icon->ni_Image[1].ARGB)
964 if (WriteARGB35(iff, icon, &icon->ni_Image[1].ARGB, IconBase))
966 D(bug("WriteIcon35. WriteImage35() of 2nd image ok.\n"));
967 ok = TRUE;
969 } else {
970 ok = TRUE;
972 } /* if (WriteARGB35(iff, icon, &icon->ni_Image[0].ARGB, IconBase) */
973 } /* if (icon->ni_Image[0].ARGB) */
975 } /* if (WriteChunkBytes(iff, &fc, sizeof(fc)) == sizeof(fc)) */
976 else
978 PopChunk(iff);
981 } /* if (!PushChunk(iff, ID_ICON, ID_FACE, sizeof(struct FileFaceChunk))) */
983 if (icon->ni_Extra.PNG[0].Size &&
984 !PushChunk(iff, ID_ICON, ID_png, IFFSIZE_UNKNOWN)) {
985 WriteChunkBytes(iff, icon->ni_Extra.Data + icon->ni_Extra.PNG[0].Offset, icon->ni_Extra.PNG[0].Size);
987 PopChunk(iff);
990 if (icon->ni_Extra.PNG[1].Size &&
991 !PushChunk(iff, ID_ICON, ID_png, IFFSIZE_UNKNOWN)) {
992 WriteChunkBytes(iff, icon->ni_Extra.Data + icon->ni_Extra.PNG[1].Offset, icon->ni_Extra.PNG[1].Size);
994 PopChunk(iff);
997 PopChunk(iff);
999 } /* if (!PushChunk(iff, ID_ICON, ID_FORM, IFFSIZE_UNKNOWN)) */
1001 } /* if (!OpenIFF(iff, IFFF_READ)) */
1003 } /* if ((iff = AllocIFF())) */
1005 return ok;
1008 /****************************************************************************************/
1010 VOID FreeIcon35(struct NativeIcon *icon, struct IconBase *IconBase)
1014 /****************************************************************************************/