icon.library: Handle NewIcon images with fewer than 8 bits per pixel
[AROS.git] / workbench / libs / icon / diskobjNIio.c
blobcec7dcedc3d06c5fdcb4e4b98aebd9619a288685
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
8 #include <aros/debug.h>
10 #include "icon_intern.h"
12 /****************************************************************************************/
14 static STRPTR RemoveToolType(STRPTR *tt)
16 STRPTR ret = tt[0];
18 if (ret)
20 for(;;)
22 tt[0] = tt[1];
23 if (!tt[0]) break;
25 tt++;
29 return ret;
32 /****************************************************************************************/
34 /* DecodeNI() based on ModifyIcon by Dirk Stöcker */
36 /****************************************************************************************/
38 static char *DecodeNI(struct DiskObject *icon, STRPTR *tt, UBYTE *outbuffer, LONG bits, LONG entries, WORD which, BOOL is_palette, APTR IconBase)
40 LONG numbits = 0, curentry = 0, bitbuf = 0, loop = 0, mask, val;
41 UBYTE byte;
42 STRPTR src, dead = NULL;
44 if(is_palette)
46 src = *tt + 9;
47 dead = RemoveToolType(tt);
49 else
51 src = ""; /* a dummy start */
53 mask = (1 << bits) - 1;
55 while(curentry < entries)
57 if(loop)
59 byte = 0;
60 --loop;
62 else
64 if(!*src)
66 if (dead)
68 dead = NULL;
70 src = *tt;
71 if(!src || src[0] != 'I' || src[1] != 'M' || src[2] != '1' + which || src[3] != '=')
73 return "NewIcon data truncated";
75 else
77 src += 4; numbits = 0;
79 dead = RemoveToolType(tt);
82 byte = *(src++);
84 if(!byte)
86 return "NewIcon data invalid";
88 else if(byte < 0xA0)
90 byte -= 0x20;
92 else if(byte < 0xD1)
94 byte -= 0x51;
96 else
98 loop = byte - 0xD1;
99 byte = 0;
103 bitbuf = (bitbuf << 7) + byte;
104 numbits += 7;
106 while(numbits >= bits && curentry < entries)
108 val = (bitbuf >> (numbits - bits)) & mask;
110 *outbuffer++ = val;
112 numbits -= bits;
113 curentry++;
117 return 0;
120 /****************************************************************************************/
122 static BOOL ReadImageNI(struct NativeIcon *icon, WORD which, STRPTR *tooltypes,
123 struct IconBase *IconBase)
125 struct NativeIconImage *img;
126 STRPTR tt;
127 LONG width, height, numcols;
128 ULONG size;
129 BOOL transp;
130 int bits;
132 img = which ? &icon->ni_Image[1] : &icon->ni_Image[0];
134 while((tt = *tooltypes))
136 if (tt[0] == 'I' && tt[1] == 'M' && tt[2] == '1' + which && tt[3] == '=')
138 break;
140 tooltypes++;
143 if (!tt) return FALSE;
145 tt += 4;
147 if (strlen(tt) < 5) return FALSE;
149 width = tt[1] - 0x21;
150 height = tt[2] - 0x21;
152 /* Selected image must have same size as normal image otherwise ignore it. */
153 if (which && ((width != icon->ni_Width) || (height != icon->ni_Height)))
155 return FALSE;
158 numcols = (((tt[3] - 0x21) << 6) + (tt[4] - 0x21));
159 transp = (tt[0] =='B') ? TRUE : FALSE;
161 size = width * height;
163 img->ImageData = AllocMemIcon(&icon->ni_DiskObject, size, MEMF_PUBLIC);
164 if (!img->ImageData) return FALSE;
166 if (!which)
168 icon->ni_Width = width;
169 icon->ni_Height = height;
170 icon->ni_Frameless = TRUE;
171 icon->ni_Aspect = PACK_ICON_ASPECT_RATIO(1,1);
174 size = numcols * sizeof(struct ColorRegister);
175 img->Palette = AllocMemIcon(&icon->ni_DiskObject, size, MEMF_PUBLIC);
176 if (!img->Palette) return FALSE;
178 img->TransparentColor = transp ? -1 : 0;
179 img->Pens = numcols;
181 DecodeNI(&icon->ni_DiskObject, tooltypes, (UBYTE *)img->Palette, 8, img->Pens * sizeof(struct ColorRegister), which, TRUE, IconBase);
182 for (bits = 1; (1 << bits) < numcols; bits++);
183 DecodeNI(&icon->ni_DiskObject, tooltypes, (UBYTE *)img->ImageData, bits, width * height, which, FALSE, IconBase);
185 return TRUE;
189 /****************************************************************************************/
191 BOOL ReadIconNI(struct NativeIcon *icon, struct Hook *streamhook,
192 void *stream, struct IconBase *IconBase)
194 STRPTR *tooltypes, tt;
196 D(bug("ReadIconNI\n"));
198 if (icon->ni_Image[0].ImageData)
200 /* It's an 3.5 style icon. Ignore possible NewIcon */
201 return TRUE;
204 tooltypes = icon->ni_DiskObject.do_ToolTypes;
205 if ( ! tooltypes) return TRUE;
206 while ((tt = *tooltypes))
208 if (strcmp(tt, "*** DON'T EDIT THE FOLLOWING LINES!! ***") == 0)
210 break;
213 tooltypes++;
216 if (!tt) return TRUE;
218 if (!ReadImageNI(icon, 0, tooltypes, IconBase))
219 return FALSE;
221 if (!ReadImageNI(icon, 1, tooltypes, IconBase))
222 return FALSE;
224 return TRUE;
227 /****************************************************************************************/
229 BOOL WriteIconNI(struct NativeIcon *icon, struct Hook *streamhook,
230 void *stream, struct IconBase *IconBase)
232 D(bug("WriteIconNI\n"));
234 return TRUE;
237 /****************************************************************************************/
239 VOID FreeIconNI(struct NativeIcon *icon, struct IconBase *IconBase)
241 D(bug("FreeIconNI\n"));
243 /* Don't do anything */
246 /****************************************************************************************/