Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / libs / icon / diskobj35io.c
blob96c2a66bf7914da342abe0f16e27884858d69da7
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
8 #include <datatypes/pictureclass.h>
10 #include <proto/dos.h>
11 #include <proto/alib.h>
13 #include <aros/bigendianio.h>
14 #include <aros/asmcall.h>
16 #include "icon_intern.h"
18 # define DEBUG 0
19 # include <aros/debug.h>
21 /****************************************************************************************/
23 #define ID_ICON MAKE_ID('I','C','O','N')
24 #define ID_FACE MAKE_ID('F','A','C','E')
25 #define ID_IMAG MAKE_ID('I','M','A','G')
27 /****************************************************************************************/
29 struct FileFaceChunk
31 UBYTE Width;
32 UBYTE Height;
33 UBYTE Flags;
34 UBYTE Aspect;
35 UBYTE MaxPaletteBytes[2];
38 struct FileImageChunk
40 UBYTE TransparentColor;
41 UBYTE NumColors;
42 UBYTE Flags;
43 UBYTE ImageFormat;
44 UBYTE PaletteFormat;
45 UBYTE Depth;
46 UBYTE NumImageBytes[2];
47 UBYTE NumPaletteBytes[2];
50 /****************************************************************************************/
52 #if 1
53 LONG MyDOSStreamHandler(struct Hook *hook, struct IFFHandle * iff, struct IFFStreamCmd * cmd)
55 LONG error = 0;
57 switch(cmd->sc_Command)
59 case IFFCMD_INIT:
60 case IFFCMD_CLEANUP:
61 error = 0;
62 break;
64 case IFFCMD_READ:
65 error = (FRead((BPTR)iff->iff_Stream, cmd->sc_Buf, 1, cmd->sc_NBytes)) != cmd->sc_NBytes;
66 break;
68 case IFFCMD_WRITE:
69 error = (FWrite((BPTR)iff->iff_Stream, cmd->sc_Buf, 1, cmd->sc_NBytes)) != cmd->sc_NBytes;
70 break;
72 case IFFCMD_SEEK:
73 Flush((BPTR)iff->iff_Stream);
74 error = (Seek((BPTR)iff->iff_Stream, cmd->sc_NBytes, OFFSET_CURRENT)) == -1;
75 break;
78 return error;
80 #endif
82 /****************************************************************************************/
84 /* Decode35() based on ModifyIcon by Dirk Stöcker */
86 /****************************************************************************************/
88 static char *Decode35(UBYTE *buffer, UBYTE *outbuffer, LONG numbytes, LONG bits, LONG entries)
90 int cop = 0, loop = 0, numbits = 0, mask, curentry = 0;
91 ULONG bitbuf = 0;
92 UBYTE byte;
94 mask = (1<<bits)-1;
96 while((numbytes || (cop && numbits >= bits)) && (curentry < entries))
98 if(!cop)
100 if(numbits < 8)
102 bitbuf = (bitbuf<<8)|*(buffer++); --numbytes;
103 numbits += 8;
106 byte = (bitbuf>>(numbits-8))&0xFF;
107 numbits -= 8;
109 if(byte <= 127) cop = byte+1;
110 else if(byte > 128) loop = 256-byte+1;
111 else continue;
114 if(cop) ++loop;
116 if(numbits < bits)
118 bitbuf = (bitbuf<<8)|*(buffer++); --numbytes;
119 numbits += 8;
122 byte = (bitbuf>>(numbits-bits))&mask;
124 while(loop && (curentry < entries))
126 *outbuffer++ = byte;
127 ++curentry;
128 --loop;
131 if(cop) --cop;
133 numbits -= bits;
136 return curentry != entries ? "error decoding new icon data" : 0;
139 /****************************************************************************************/
141 VOID MakeMask35(UBYTE *imgdata, UBYTE *imgmask, UBYTE transpcolor, LONG imagew, LONG imageh)
143 UBYTE *src, *dst;
144 WORD x, y, bpr, mask;
146 memset(imgmask, 0xFF, RASSIZE(imagew, imageh));
148 bpr = ((imagew + 15) & ~15) / 8;
149 src = imgdata;
150 dst = imgmask;
152 for(y = 0; y < imageh; y++)
154 UBYTE *dstx = dst;
156 mask = 0x80;
158 for(x = 0; x < imagew; x++)
160 if (*src++ == transpcolor)
162 *dstx &= ~mask;
165 mask >>= 1;
166 if (!mask)
168 mask = 0x80;
169 dstx++;
172 dst += bpr;
178 /****************************************************************************************/
180 STATIC BOOL ReadImage35(struct IFFHandle *iff, struct FileFaceChunk *fc,
181 struct FileImageChunk *ic, UBYTE **imgdataptr,
182 UBYTE **imgpalptr, UBYTE **imgmaskptr, struct IconBase *IconBase)
184 UBYTE *src, *mem, *imgdata, *imgpal = NULL, *imgmask = NULL;
185 LONG size, imgsize, palsize, imagew, imageh, numcols;
187 imagew = fc->Width + 1;
188 imageh = fc->Height + 1;
189 numcols = ic->NumColors + 1;
191 imgsize = ic->NumImageBytes[0] * 256 + ic->NumImageBytes[1] + 1;
192 if (ic->Flags & IMAGE35F_HASPALETTE)
194 palsize = ic->NumPaletteBytes[0] * 256 + ic->NumPaletteBytes[1] + 1;
196 else
198 palsize = 0;
201 size = imgsize + palsize;
203 src = mem = AllocVec(size, MEMF_ANY);
204 if (!src) return FALSE;
206 if (ReadChunkBytes(iff, src, size) != size)
208 FreeVec(src);
209 return FALSE;
212 size = imagew * imageh;
214 if (ic->Flags & IMAGE35F_HASPALETTE)
216 size += numcols * sizeof(struct ColorRegister);
219 if (ic->Flags & IMAGE35F_HASTRANSPARENTCOLOR)
221 size += RASSIZE(imagew, imageh);
224 imgdata = AllocVec(size, MEMF_ANY);
225 if (!imgdata)
227 FreeVec(src);
228 return FALSE;
231 if (ic->ImageFormat == 0)
233 memcpy(imgdata, src, imagew * imageh);
235 else
237 Decode35(src, imgdata, imgsize, ic->Depth, imagew * imageh);
240 if (ic->Flags & IMAGE35F_HASPALETTE)
242 struct ColorRegister *dst;
244 src += imgsize;
246 imgpal = imgdata + imagew * imageh;
248 dst = (struct ColorRegister *)imgpal;
250 if (ic->PaletteFormat == 0)
252 ULONG i, r, g, b;
254 for(i = 0; i < numcols; i++)
256 r = *src++;
257 g = *src++;
258 b = *src++;
260 dst->red = r;
261 dst->green = g;
262 dst->blue = b;
263 dst++;
266 else
268 Decode35(src, imgpal, palsize, 8, 3 * numcols);
270 if (sizeof(struct ColorRegister) != 3)
272 struct ColorRegister *dst;
273 UWORD i, r, g, b;
275 src = imgpal + 3 * numcols;
276 dst = (struct ColorRegister *)(imgpal + sizeof(struct ColorRegister) * numcols);
278 for (i = 0; i < numcols; i++)
280 b = *--src;
281 g = *--src;
282 r = *--src;
284 dst--;
286 dst->red = r;
287 dst->green = g;
288 dst->blue = b;
293 } /* if (ic->Flags & IMAGE35F_HASPALETTE) */
295 if (ic->Flags & IMAGE35F_HASTRANSPARENTCOLOR)
297 imgmask = imgdata + imagew * imageh;
298 if (ic->Flags & IMAGE35F_HASPALETTE)
300 imgmask += numcols * sizeof(struct ColorRegister);
303 MakeMask35(imgdata, imgmask,ic->TransparentColor, imagew, imageh);
306 *imgdataptr = imgdata;
307 *imgpalptr = imgpal;
308 *imgmaskptr = imgmask;
310 FreeVec(mem);
312 return TRUE;
315 /****************************************************************************************/
317 BOOL ReadIcon35(struct NativeIcon *icon, struct Hook *streamhook,
318 void *stream, struct IconBase *IconBase)
320 static LONG stopchunks[] =
322 ID_ICON, ID_FACE,
323 ID_ICON, ID_IMAG
326 struct IFFHandle *iff;
327 struct Hook iffhook;
328 struct FileFaceChunk fc;
329 struct FileImageChunk ic1, ic2;
330 UBYTE *img1data = NULL, *img2data = NULL,
331 *img1pal = NULL, *img2pal = NULL,
332 *img1mask = NULL, *img2mask = NULL;
333 BOOL have_face = FALSE, have_imag1 = FALSE, have_imag2 = FALSE;
335 D(bug("ReadIcon35\n"));
337 iffhook.h_Entry = (HOOKFUNC)HookEntry;
338 iffhook.h_SubEntry = (HOOKFUNC)MyDOSStreamHandler;
340 if ((iff = AllocIFF()))
342 D(bug("ReadIcon35. AllocIFF okay\n"));
344 iff->iff_Stream = (IPTR)stream;
346 InitIFF(iff, IFFF_RSEEK, &iffhook);
348 if (!OpenIFF(iff, IFFF_READ))
350 D(bug("ReadIcon35. OpenIFF okay\n"));
352 if (!StopChunks(iff, stopchunks, 2))
354 LONG error;
356 D(bug("ReadIcon35. StopChunks okay\n"));
358 while(!(error = ParseIFF(iff, IFFPARSE_SCAN)))
360 struct ContextNode *cn;
362 cn = CurrentChunk(iff);
364 D(bug("inside ParseIFF loop\n"));
365 if ((cn->cn_ID == ID_FACE) && (cn->cn_Size >= sizeof(struct FileFaceChunk)))
367 D(bug("ReadIcon35. Found FACE chunk\n"));
368 if (ReadChunkBytes(iff, &fc, sizeof(fc)) == sizeof(fc))
370 have_face = TRUE;
373 else if (have_face && (cn->cn_ID == ID_IMAG) && (cn->cn_Size >= sizeof(struct FileImageChunk)))
375 D(bug("ReadIcon35. Found IMAG chunk\n"));
376 if (ReadChunkBytes(iff, (have_imag1 ? &ic2 : &ic1), sizeof(ic1)) == sizeof(ic1))
378 if (have_imag1)
380 if (ReadImage35(iff, &fc, &ic2, &img2data, &img2pal, &img2mask, IconBase))
382 have_imag2 = TRUE;
385 else
387 if (ReadImage35(iff, &fc, &ic1, &img1data, &img1pal, &img1mask, IconBase))
389 have_imag1 = TRUE;
398 } /* while(!ParseIFF(iff, IFFPARSE_SCAN)) */
400 } /* if (!StopChunks(iff, stopchunks, 2)) */
402 } /* if (!OpenIFF(iff, IFFF_READ)) */
404 FreeIFF(iff);
406 } /* if ((iff = AllocIFF())) */
408 if (have_imag1)
410 icon->icon35.width = fc.Width + 1;
411 icon->icon35.height = fc.Height + 1;
412 icon->icon35.flags = fc.Flags;
413 icon->icon35.aspect = fc.Aspect;
415 icon->icon35.img1.imagedata = img1data;
416 icon->icon35.img1.palette = img1pal;
417 icon->icon35.img1.mask = img1mask;
418 icon->icon35.img1.numcolors = ic1.NumColors + 1;
419 icon->icon35.img1.depth = ic1.Depth;
420 icon->icon35.img1.flags = ic1.Flags;
421 icon->icon35.img1.transparentcolor = ic1.TransparentColor;
423 if (have_imag2)
425 icon->icon35.img2.imagedata = img2data;
426 icon->icon35.img2.mask = img2mask;
427 icon->icon35.img2.depth = ic2.Depth;
428 icon->icon35.img2.flags = ic2.Flags;
429 icon->icon35.img2.transparentcolor = ic2.TransparentColor;
431 if (img2pal)
433 icon->icon35.img2.palette = img2pal;
434 icon->icon35.img2.numcolors = ic2.NumColors + 1;
436 else
438 icon->icon35.img2.palette = icon->icon35.img1.palette;
439 icon->icon35.img2.numcolors = icon->icon35.img1.numcolors;
444 return TRUE;
447 /****************************************************************************************/
449 /* Encode35() based on ModifyIcon source by Dirk Stöcker */
451 /****************************************************************************************/
453 static UBYTE *Encode35(ULONG depth, UBYTE *dtype, LONG *dsize, ULONG size, UBYTE *src)
455 int i, j, k;
456 ULONG bitbuf, numbits;
457 UBYTE *buf;
458 LONG ressize, numcopy, numequal;
460 buf = AllocVec(size * 2, MEMF_ANY);
461 if (!buf) return NULL;
463 numcopy = 0;
464 numequal = 1;
465 bitbuf = 0;
466 numbits = 0;
467 ressize = 0;
468 k = 0; /* the really output pointer */
470 for(i = 1; numequal || numcopy;)
472 if(i < size && numequal && (src[i-1] == src[i]))
474 ++numequal; ++i;
476 else if(i < size && numequal*depth <= 16)
478 numcopy += numequal; numequal = 1; ++i;
480 else
482 /* care for end case, where it maybe better to join the two */
483 if(i == size && numcopy + numequal <= 128 && (numequal-1)*depth <= 8)
485 numcopy += numequal; numequal = 0;
488 if(numcopy)
490 if((j = numcopy) > 128) j = 128;
492 bitbuf = (bitbuf<<8) | (j-1);
493 numcopy -= j;
495 else
497 if((j = numequal) > 128) j = 128;
499 bitbuf = (bitbuf<<8) | (256-(j-1));
500 numequal -= j;
501 k += j-1;
502 j = 1;
505 buf[ressize++] = (bitbuf >> numbits);
507 while(j--)
509 numbits += depth;
510 bitbuf = (bitbuf<<depth) | src[k++];
512 if(numbits >= 8)
514 numbits -= 8;
515 buf[ressize++] = (bitbuf >> numbits);
519 if(i < size && !numcopy && !numequal)
521 numequal = 1; ++i;
526 if(numbits)
527 buf[ressize++] = bitbuf << (8-numbits);
529 if(ressize > size) /* no RLE */
531 ressize = size;
532 *dtype = 0;
533 for(i = 0; i < size; ++i)
534 buf[i]= src[i];
536 else
537 *dtype = 1;
539 *dsize = ressize;
541 return buf;
544 /****************************************************************************************/
546 static BOOL WriteImage35(struct IFFHandle *iff, struct Icon35 *icon35,
547 struct Image35 *img, struct IconBase *IconBase)
549 struct FileImageChunk ic;
550 UBYTE *imagedata, *pal = NULL;
551 LONG imagesize, palsize = 0;
552 UBYTE imagepacked, palpacked = 0;
553 UBYTE imageflags;
554 BOOL ok = FALSE;
556 imageflags = img->flags;
558 if (img->palette && (img->flags & IMAGE35F_HASPALETTE))
560 pal = Encode35(8, &palpacked, &palsize, img->numcolors * 3, img->palette);
561 if (!pal) return FALSE;
563 else
565 imageflags &= ~IMAGE35F_HASPALETTE;
568 imagedata = Encode35(img->depth, &imagepacked, &imagesize,
569 icon35->width * icon35->height, img->imagedata);
571 if (!imagedata)
573 if (pal) FreeVec(pal);
574 return FALSE;
577 ic.TransparentColor = img->transparentcolor;
578 ic.NumColors = img->numcolors - 1;
579 ic.Flags = imageflags;
580 ic.ImageFormat = imagepacked;
581 ic.PaletteFormat = palpacked;
582 ic.Depth = img->depth;
583 ic.NumImageBytes[0] = (imagesize - 1) / 256;
584 ic.NumImageBytes[1] = (imagesize - 1) & 255;
585 ic.NumPaletteBytes[0] = (palsize - 1) / 256;
586 ic.NumPaletteBytes[1] = (palsize - 1) & 255;
588 if (!PushChunk(iff, ID_ICON, ID_IMAG, IFFSIZE_UNKNOWN))
590 ok = TRUE;
592 if (WriteChunkBytes(iff, &ic, sizeof(ic)) != sizeof(ic))
594 ok = FALSE;
597 if (ok)
599 if (WriteChunkBytes(iff, imagedata, imagesize) != imagesize)
601 ok = FALSE;
605 if (ok && pal)
607 if (WriteChunkBytes(iff, pal, palsize) != palsize)
609 ok = FALSE;
614 PopChunk(iff);
616 } /* if (!PushChunk(iff, ID_ICON, ID_IMAG, IFFSIZE_UNKNOWN)) */
618 FreeVec(imagedata);
619 if (pal) FreeVec(pal);
621 return ok;
624 /****************************************************************************************/
626 BOOL WriteIcon35(struct NativeIcon *icon, struct Hook *streamhook,
627 void *stream, struct IconBase *IconBase)
629 struct IFFHandle *iff;
630 struct Hook iffhook;
631 struct FileFaceChunk fc;
632 BOOL ok = FALSE;
634 D(bug("WriteIcon35\n"));
636 if (!GetNativeIcon(&icon->dobj, IconBase))
638 return TRUE;
641 iffhook.h_Entry = (HOOKFUNC)HookEntry;
642 iffhook.h_SubEntry = (HOOKFUNC)MyDOSStreamHandler;
644 if ((iff = AllocIFF()))
646 D(bug("WriteIcon35. AllocIFF okay\n"));
648 iff->iff_Stream = (IPTR)stream;
650 InitIFF(iff, IFFF_RSEEK, &iffhook);
652 if (!OpenIFF(iff, IFFF_WRITE))
654 D(bug("WriteIcon35. OpenIFF okay\n"));
656 if (!PushChunk(iff, ID_ICON, ID_FORM, IFFSIZE_UNKNOWN))
658 D(bug("WriteIcon35. PushChunk(ID_ICON, ID_FORM) okay\n"));
660 if (!PushChunk(iff, ID_ICON, ID_FACE, sizeof(struct FileFaceChunk)))
662 WORD cmapentries;
664 D(bug("WriteIcon35. PushChunk(ID_ICON, ID_FACE) okay\n"));
666 fc.Width = icon->icon35.width - 1;
667 fc.Height = icon->icon35.height - 1;
668 fc.Flags = icon->icon35.flags;
669 fc.Aspect = icon->icon35.aspect;
671 cmapentries = icon->icon35.img1.numcolors;
673 if (icon->icon35.img2.imagedata &&
674 icon->icon35.img2.palette &&
675 (icon->icon35.img2.flags & IMAGE35F_HASPALETTE))
677 if (icon->icon35.img2.numcolors > cmapentries)
679 cmapentries = icon->icon35.img2.numcolors;
683 cmapentries = cmapentries * 3 - 1;
685 fc.MaxPaletteBytes[0] = cmapentries / 256;
686 fc.MaxPaletteBytes[1] = cmapentries & 255;
688 if (WriteChunkBytes(iff, &fc, sizeof(fc)) == sizeof(fc))
690 D(bug("WriteIcon35. WriteChunkBytes of FACE chunk ok.\n"));
692 PopChunk(iff);
694 if (WriteImage35(iff, &icon->icon35, &icon->icon35.img1, IconBase))
696 D(bug("WriteIcon35. WriteImage35() of 1st image ok.\n"));
698 if (icon->icon35.img2.imagedata)
700 if (WriteImage35(iff, &icon->icon35, &icon->icon35.img2, IconBase))
702 D(bug("WriteIcon35. WriteImage35() of 2nd image ok.\n"));
704 ok = TRUE;
707 } /* if (icon->icon35.img2.imagedata) */
708 else
710 ok = TRUE;
713 } /* if (WriteImage35(iff, &icon->icon35, &icon->icon35.img1, IconBase)) */
715 } /* if (WriteChunkBytes(iff, &fc, sizeof(fc)) == sizeof(fc)) */
716 else
718 PopChunk(iff);
721 } /* if (!PushChunk(iff, ID_ICON, ID_FACE, sizeof(struct FileFaceChunk))) */
723 PopChunk(iff);
725 } /* if (!PushChunk(iff, ID_ICON, ID_FORM, IFFSIZE_UNKNOWN)) */
727 } /* if (!OpenIFF(iff, IFFF_READ)) */
729 } /* if ((iff = AllocIFF())) */
731 return ok;
734 /****************************************************************************************/
736 VOID FreeIcon35(struct NativeIcon *icon, struct IconBase *IconBase)
738 if (icon->icon35.img1.imagedata) FreeVec(icon->icon35.img1.imagedata);
739 if (icon->icon35.img2.imagedata) FreeVec(icon->icon35.img2.imagedata);
741 icon->icon35.img1.imagedata = NULL;
742 icon->icon35.img2.imagedata = NULL;
744 /* We don't free img.palette/img.mask because imagedata/palette/mask
745 were allocated together in one AllocVec() call */
749 /****************************************************************************************/