Fixed typos in comments.
[AROS.git] / workbench / libs / icon / diskobjPNGio.c
blobf706fa771b5fc36f8ea929e0f69db84efde69ba6
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
8 #define DTT(x)
10 #include <datatypes/datatypes.h>
11 #include <intuition/intuition.h>
13 #include <proto/dos.h>
14 #include <proto/alib.h>
15 #include <proto/png.h>
16 #include <proto/datatypes.h>
18 #include <aros/bigendianio.h>
19 #include <aros/asmcall.h>
21 #include "icon_intern.h"
23 #include <aros/debug.h>
25 #include <png.h>
27 #define ATTR_ICONX 0x80001001
28 #define ATTR_ICONY 0x80001002
29 #define ATTR_DRAWERX 0x80001003
30 #define ATTR_DRAWERY 0x80001004
31 #define ATTR_DRAWERWIDTH 0x80001005
32 #define ATTR_DRAWERHEIGHT 0x80001006
33 #define ATTR_DRAWERFLAGS 0x80001007
34 #define ATTR_TOOLWINDOW 0x80001008 //OS4: STRPTR, tool window string, length including the tag
35 //must be a multiple of 8
36 #define ATTR_STACKSIZE 0x80001009
37 #define ATTR_DEFAULTTOOL 0x8000100a
38 #define ATTR_TOOLTYPE 0x8000100b
39 #define ATTR_VIEWMODES 0x8000100c //OS4 PNG use that
40 #define ATTR_DD_CURRENTX 0x8000100d //OS4 ULONG, drawer view X offset
41 #define ATTR_DD_CURRENTY 0x8000100e //OS4 ULONG, drawer view Y offset
42 #define ATTR_TYPE 0x8000100f //OS4 icon type (WBDISK...WBKICK)
43 #define ATTR_FRAMELESS 0x80001010 //OS4 ULONG, frameless property
44 #define ATTR_DRAWERFLAGS3 0x80001011 //OS4 ULONG, drawer flags
45 #define ATTR_VIEWMODES2 0x80001012 //OS4 ULONG, drawer view modes
46 #define ATTR_DRAWERFLAGS2 0x80001107 //written from AFA to store needed dopus Magellan settings
48 #define EFFECT_NONE (0)
49 #define EFFECT_LIGHTEN (1)
50 #define EFFECT_TINT_BLUE (2)
51 #define EFFECT_XOR (3)
53 #define EFFECT EFFECT_LIGHTEN
55 /****************************************************************************************/
58 ATTR_DRAWERFLAGS: AAABC
60 C : 1-bit flag : 0 = showonlyicons 1 = showallfiles
61 B : 1-bit flag : 0 = viewastext 1 = view as icons
62 AA : 2-bit value : 0 = viewbyname, 1 = viewbydata, 2 = viewbysize, 3 = viewbytype
65 static ULONG flags_to_ddflags(ULONG flags)
67 ULONG ret = 0;
69 if (flags & 1)
71 ret = DDFLAGS_SHOWALL;
73 else
75 ret = DDFLAGS_SHOWICONS;
78 return ret;
81 static ULONG flags_to_ddviewmodes(ULONG flags)
83 ULONG ret = 0;
85 if (flags & 2)
87 ret = DDVM_BYICON;
89 else
91 ret = (flags >> 2) + DDVM_BYNAME;
94 return ret;
97 static ULONG dd_to_flags(struct DiskObject *dobj)
99 ULONG drawerflags = 0;
101 if (dobj->do_DrawerData->dd_Flags & DDFLAGS_SHOWALL)
103 drawerflags |= 1;
106 if (dobj->do_DrawerData->dd_ViewModes == DDVM_BYICON)
108 drawerflags |= 2;
110 else
112 drawerflags |= ((dobj->do_DrawerData->dd_ViewModes - 2) << 2);
115 return drawerflags;
118 /* Returns an ARGB image.
119 * Set &width == -1 and &height == -1 to get the size.
120 * Otherwise, sets the image size of width & height
122 ULONG *ReadMemPNG(struct DiskObject *icon, APTR stream, LONG *width, LONG *height, const CONST_STRPTR *chunknames, APTR *chunkpointer, struct IconBase *IconBase)
124 APTR PNGBase = OpenLibrary("SYS:Classes/datatypes/png.datatype", 41);
125 APTR handle;
126 ULONG *argb = NULL;
128 if (!PNGBase) {
129 D(bug("[%s] Can't open png.datatype\n", __func__));
130 return NULL;
133 handle = PNG_LoadImageMEM(stream, -1, chunknames, chunkpointer, TRUE);
134 if (handle) {
135 ULONG *src, *dst;
136 LONG w = 0, h = 0;
137 LONG x,y, xoff, yoff;
139 PNG_GetImageInfo(handle, &w, &h, NULL, NULL);
140 D(bug("[%s] Dest (%d x %d), Image (%d x %d)\n", __func__,
141 *width, *height, w, h));
142 if (*width == -1 && *height == -1) {
143 *width = w;
144 *height = h;
147 PNG_GetImageData(handle, (APTR *)&src, NULL);
149 argb = AllocMemIcon(icon, (*width) * (*height) * sizeof(ULONG), MEMF_PUBLIC);
150 if (argb) {
151 xoff = ((*width) - w)/2;
152 yoff = ((*height) - h)/2;
154 dst = argb;
155 for (y = 0; y < *height; y++) {
156 LONG sy = y + yoff;
158 if (sy < 0)
159 sy = 0;
161 if (sy >= h)
162 sy = h-1;
164 for (x = 0; x < *width; x++, dst++) {
165 LONG sx = x + xoff;
167 if (sx < 0)
168 sx = 0;
170 if (sx >= w)
171 sx = w-1;
173 *dst = src[sy*w+sx];
178 PNG_FreeImage(handle);
179 } else {
180 D(bug("[%s] PNG datatype can't parse data\n", __func__));
183 CloseLibrary(PNGBase);
184 return argb;
188 /****************************************************************************************/
190 static void GetChunkInfo(APTR stream, APTR *chunkdata, ULONG *chunksize)
192 png_unknown_chunkp chunkp = stream;
193 *chunksize = chunkp->size;
194 *chunkdata = chunkp->data;
197 BOOL ReadIconPNG(struct DiskObject *dobj, BPTR file, struct IconBase *IconBase)
199 static CONST_STRPTR const chunknames[] =
201 "icOn",
202 NULL
204 APTR chunkpointer[] =
206 NULL,
207 NULL
210 struct NativeIcon *icon;
211 ULONG filesize;
212 APTR data;
214 icon = NATIVEICON(dobj);
216 D(bug("%s: File stream %p\n", __func__, file));
218 if (Seek(file, 0, OFFSET_END) < 0) return FALSE;
219 if ((filesize = Seek(file, 0, OFFSET_BEGINNING)) < 0) return FALSE;
221 D(bug("[%s] Inspecting a %d byte file\n", __func__, filesize));
223 /* Need a copy of whole file in memory for icon saving :-\ Because
224 that should save file back as it was, only with modified or new
225 icOn chunk. And it must also work when loading an icon and then
226 saving it using another name. */
228 data = AllocMemIcon(&icon->ni_DiskObject, filesize, MEMF_PUBLIC);
229 if (!data)
230 return FALSE;
232 if (Read(file, data, filesize) != filesize)
234 D(bug("[%s] Can't read from file\n", __func__));
235 return FALSE;
238 icon->ni_Extra.Data = data;
239 icon->ni_Extra.Size = filesize;
241 icon->ni_Extra.PNG[0].Offset = 0;
242 icon->ni_Extra.PNG[0].Size = filesize;
244 ULONG width = ~0, height = ~0;
246 icon->ni_Image[0].ARGB = ReadMemPNG(&icon->ni_DiskObject, icon->ni_Extra.Data + icon->ni_Extra.PNG[0].Offset, &width, &height, chunknames, chunkpointer, IconBase);
247 if (icon->ni_Image[0].ARGB == NULL) {
248 D(bug("[%s] Can't parse PNG image at 0\n", __func__));
249 return FALSE;
252 icon->ni_Face.Width = width;
253 icon->ni_Face.Height = height;
254 icon->ni_Face.Aspect = ICON_ASPECT_RATIO_UNKNOWN;
256 #define DO(x) (&x->ni_DiskObject)
258 DO(icon)->do_Magic = WB_DISKMAGIC;
259 DO(icon)->do_Version = (WB_DISKVERSION << 8) | WB_DISKREVISION;
260 DO(icon)->do_Type = 0; /* Invalid */
261 DO(icon)->do_CurrentX = NO_ICON_POSITION;
262 DO(icon)->do_CurrentY = NO_ICON_POSITION;
263 DO(icon)->do_Gadget.Width = width;
264 DO(icon)->do_Gadget.Height = height;
265 DO(icon)->do_StackSize = AROS_STACKSIZE;
267 if (chunkpointer[0])
269 UBYTE *chunkdata;
270 ULONG chunksize;
271 ULONG ttnum = 0;
272 ULONG ttarraysize = 0;
273 BOOL ok = TRUE;
275 GetChunkInfo(chunkpointer[0], (APTR *)&chunkdata, &chunksize);
277 while(chunksize >= 4)
279 ULONG attr;
280 IPTR val = 0;
281 BOOL need_drawerdata = FALSE;
283 attr = (chunkdata[0] << 24) | (chunkdata[1] << 16) | (chunkdata[2] << 8) | chunkdata[3];
284 chunksize -=4;
285 chunkdata += 4;
287 switch(attr)
289 case ATTR_DRAWERX:
290 case ATTR_DRAWERY:
291 case ATTR_DRAWERWIDTH:
292 case ATTR_DRAWERHEIGHT:
293 case ATTR_DRAWERFLAGS:
294 case ATTR_DRAWERFLAGS2:
295 case ATTR_DRAWERFLAGS3:
296 case ATTR_VIEWMODES:
297 case ATTR_VIEWMODES2:
298 case ATTR_DD_CURRENTX:
299 case ATTR_DD_CURRENTY:
300 need_drawerdata = TRUE;
301 /* Fall through */
303 case ATTR_ICONX:
304 case ATTR_ICONY:
305 case ATTR_STACKSIZE:
306 case ATTR_TYPE:
307 case ATTR_FRAMELESS:
308 if (chunksize >= 4)
310 val = (chunkdata[0] << 24) | (chunkdata[1] << 16) | (chunkdata[2] << 8) | chunkdata[3];
311 chunksize -=4;
312 chunkdata += 4;
314 else
316 ok = FALSE;
318 break;
320 /* case ATTR_UNKNOWN: */
321 case ATTR_DEFAULTTOOL:
322 case ATTR_TOOLTYPE:
323 val = (IPTR)chunkdata;
324 chunksize -= strlen((char *)val) + 1;
325 chunkdata += strlen((char *)val) + 1;
327 if (chunksize < 0)
329 ok = FALSE;
331 break;
333 default:
334 /* Unknown attribute/tag. Impossible to handle correctly
335 if we don't know if it's a string attribute or not. */
336 ok = FALSE;
337 break;
339 } /* switch(attr) */
341 if (!ok) break;
343 if (need_drawerdata && !(DO(icon)->do_DrawerData))
345 DO(icon)->do_DrawerData = AllocMemIcon(DO(icon), sizeof(struct DrawerData), MEMF_PUBLIC | MEMF_CLEAR);
346 if (!(DO(icon)->do_DrawerData))
348 ok = FALSE;
349 break;
352 DO(icon)->do_DrawerData->dd_NewWindow.LeftEdge = 20;
353 DO(icon)->do_DrawerData->dd_NewWindow.TopEdge = 20;
354 DO(icon)->do_DrawerData->dd_NewWindow.Width = 300;
355 DO(icon)->do_DrawerData->dd_NewWindow.Height = 200;
356 DO(icon)->do_Gadget.UserData = (APTR)1; /* See DupDiskObject logic */
359 switch(attr)
361 case ATTR_ICONX:
362 DO(icon)->do_CurrentX = val;
363 break;
365 case ATTR_ICONY:
366 DO(icon)->do_CurrentY = val;
367 break;
369 case ATTR_STACKSIZE:
370 DO(icon)->do_StackSize = val;
371 break;
373 case ATTR_DRAWERX:
374 DO(icon)->do_DrawerData->dd_NewWindow.LeftEdge = (WORD)val;
375 break;
377 case ATTR_DRAWERY:
378 DO(icon)->do_DrawerData->dd_NewWindow.TopEdge = (WORD)val;
379 break;
381 case ATTR_DRAWERWIDTH:
382 DO(icon)->do_DrawerData->dd_NewWindow.Width = (WORD)val;
383 break;
385 case ATTR_DRAWERHEIGHT:
386 DO(icon)->do_DrawerData->dd_NewWindow.Height = (WORD)val;
387 break;
389 case ATTR_DRAWERFLAGS:
390 DO(icon)->do_DrawerData->dd_Flags = flags_to_ddflags(val);
391 DO(icon)->do_DrawerData->dd_ViewModes = flags_to_ddviewmodes(val);
392 break;
394 case ATTR_DEFAULTTOOL:
395 DO(icon)->do_DefaultTool = AllocMemIcon(DO(icon), strlen((char *)val) + 1, MEMF_PUBLIC | MEMF_CLEAR);
396 if (DO(icon)->do_DefaultTool)
398 strcpy(DO(icon)->do_DefaultTool, (char *)val);
400 else
402 ok = FALSE;
404 break;
405 case ATTR_FRAMELESS:
406 NATIVEICON(icon)->ni_Frameless = val ? TRUE : FALSE;
407 break;
409 case ATTR_TOOLTYPE:
410 ttnum++;
412 D(bug("[Icon.PNG] Got tooltype number %u : %s\n", ttnum - 1, val));
414 if (ttarraysize < ttnum + 1)
416 STRPTR *old_tooltypes = DO(icon)->do_ToolTypes;
418 ttarraysize += 10;
420 DO(icon)->do_ToolTypes = AllocMemIcon(DO(icon), ttarraysize * sizeof(APTR), MEMF_PUBLIC | MEMF_CLEAR);
421 if (DO(icon)->do_ToolTypes)
423 D(bug("[Icon.PNG] Allocated array of %u entries @ 0x%p (old 0x%p)\n", ttarraysize, DO(icon)->do_ToolTypes, old_tooltypes));
424 if (old_tooltypes)
426 CopyMemQuick(old_tooltypes, DO(icon)->do_ToolTypes, (ttnum - 1) * sizeof(APTR));
428 /* TODO: Free old array */
431 else
433 ok = FALSE;
437 if (!ok) break;
439 DO(icon)->do_ToolTypes[ttnum - 1] = AllocMemIcon(DO(icon), strlen((char *)val) + 1, MEMF_PUBLIC | MEMF_CLEAR);
440 if (DO(icon)->do_ToolTypes[ttnum - 1])
442 strcpy(DO(icon)->do_ToolTypes[ttnum - 1], (char *)val);
444 else
446 ok = FALSE;
448 break;
450 } /* switch(attr) */
452 if (!ok) break;
454 } /* while(chunksize >= 4) */
456 if (!ok)
458 D(bug("=== Failure during icOn chunk parsing ===\n"));
459 FreeIconPNG(&icon->ni_DiskObject, IconBase);
460 return FALSE;
464 } /* if (chunkpointer[0]) */
466 #undef DO
469 * FIXME: Someone killed PNG Icon do_Type detection here which causes
470 * following lines to always free DrawerData even when it
471 * shouldn't be freed (only possible to know if do_Type is
472 * known). So for now following lines disabled and DrawerData
473 * is always kept (even when it shouldn't).
476 #if 0
477 if (icon->ni_DiskObject.do_DrawerData &&
478 (icon->ni_DiskObject.do_Type != WBDISK) &&
479 (icon->ni_DiskObject.do_Type != WBDRAWER) &&
480 (icon->ni_DiskObject.do_Type != WBGARBAGE))
482 FreePooled(pool, icon->ni_DiskObject.do_DrawerData, sizeof(struct DrawerData));
483 icon->ni_DiskObject.do_DrawerData = NULL;
485 #endif
487 } /**/
489 /* Look for a possible 2nd PNG image attached onto the first one */
491 UBYTE *filepos = icon->ni_Extra.Data + icon->ni_Extra.PNG[0].Offset + 8;
492 BOOL done = FALSE;
494 while(!done && filepos < ((UBYTE *)icon->ni_Extra.Data + icon->ni_Extra.Size))
496 ULONG chunksize = (filepos[0] << 24) | (filepos[1] << 16) |
497 (filepos[2] << 8) | filepos[3];
498 ULONG chunktype = (filepos[4] << 24) | (filepos[5] << 16) |
499 (filepos[6] << 8) | filepos[7];
501 chunksize += 12;
503 if (chunktype == MAKE_ID('I', 'E', 'N', 'D'))
505 done = TRUE;
508 filepos += chunksize;
511 if (filepos + 8 < (UBYTE *)icon->ni_Extra.Data + icon->ni_Extra.Size)
513 ULONG offset = filepos - (UBYTE *)icon->ni_Extra.Data;
515 icon->ni_Extra.PNG[0].Size = offset;
516 icon->ni_Extra.PNG[1].Offset = offset;
517 icon->ni_Extra.PNG[1].Size = (filesize - icon->ni_Extra.PNG[0].Size);
518 icon->ni_Image[1].ARGB = ReadMemPNG(&icon->ni_DiskObject, filepos, &icon->ni_Face.Width, &icon->ni_Face.Height, NULL, NULL, IconBase);
521 } /**/
523 /* If there's no image for selected-state, generate one */
524 if (!icon->ni_Image[1].ARGB)
526 ULONG size = icon->ni_Face.Width * icon->ni_Face.Height;
528 if ((icon->ni_Image[1].ARGB = AllocMemIcon(&icon->ni_DiskObject, size * sizeof(ULONG), MEMF_PUBLIC)))
530 ULONG *src = (ULONG *)icon->ni_Image[0].ARGB;
531 ULONG *dst = (ULONG *)icon->ni_Image[1].ARGB;
533 while(size--)
535 ULONG pixel = *src++;
537 /* Effects like in changetoselectediconcolor.c */
539 #if EFFECT == EFFECT_LIGHTEN
540 #if AROS_BIG_ENDIAN
541 pixel = (pixel & 0xFF000000) +
542 ((pixel >> 1) & 0x007F7F7F) +
543 0x00808080;
544 #else
545 pixel = (pixel & 0x000000FF) +
546 ((pixel >> 1) & 0x7F7F7F00) +
547 0x80808000;
548 #endif
549 #elif EFFECT == EFFECT_TINT_BLUE
550 #if AROS_BIG_ENDIAN
551 pixel = (pixel & 0xFF000000) +
552 ((pixel >> 1) & 0x007F7F7F) +
553 0x00000080;
554 #else
555 pixel = (pixel & 0x000000FF) +
556 ((pixel >> 1) & 0x7F7F7F00) +
557 0x80000000;
558 #endif
560 #elif EFFECT == EFFECT_XOR
561 #if AROS_BIG_ENDIAN
562 pixel = (pixel & 0xFF000000) +
563 ((pixel & 0x00FFFFFF) ^ 0x00FFFFFF);
564 #else
565 pixel = (pixel & 0x000000FF) +
566 ((pixel & 0xFFFFFF00) ^ 0xFFFFFF00);
567 #endif
568 #endif
569 *dst++ = pixel;
574 return TRUE;
578 /****************************************************************************************/
580 STATIC VOID MakeCRCTable(struct IconBase *IconBase)
582 unsigned long c;
583 int n, k;
585 IconBase->ib_CRCTable = AllocMem(256 * sizeof(ULONG), MEMF_ANY);
586 if (!IconBase->ib_CRCTable)
587 return;
588 for (n = 0; n < 256; n++)
590 c = (unsigned long) n;
591 for (k = 0; k < 8; k++)
593 if (c & 1)
594 c = 0xedb88320L ^ (c >> 1);
595 else
596 c = c >> 1;
598 IconBase->ib_CRCTable[n] = c;
602 /****************************************************************************************/
604 STATIC ULONG UpdateCRC(ULONG crc, UBYTE *buf, ULONG len, struct IconBase *IconBase)
606 ULONG c = crc;
607 ULONG n;
609 for (n = 0; n < len; n++)
611 c = IconBase->ib_CRCTable[(c ^ buf[n]) & 0xff] ^ (c >> 8);
614 return c;
618 /****************************************************************************************/
620 STATIC BOOL WriteIconAttr(BPTR file, ULONG id, ULONG val, ULONG *chunksize,
621 ULONG *crc, struct IconBase *IconBase)
623 UBYTE buf[8];
625 buf[0] = id >> 24;
626 buf[1] = id >> 16;
627 buf[2] = id >> 8;
628 buf[3] = id;
629 buf[4] = val >> 24;
630 buf[5] = val >> 16;
631 buf[6] = val >> 8;
632 buf[7] = val;
634 if (Write(file, buf, 8) != 8) return FALSE;
636 *chunksize += 8;
637 *crc = UpdateCRC(*crc, buf, 8, IconBase);
638 return TRUE;
641 /****************************************************************************************/
643 STATIC BOOL WriteIconStrAttr(BPTR file, ULONG id, char *val, ULONG *chunksize,
644 ULONG *crc, struct IconBase *IconBase)
646 UBYTE buf[4];
647 ULONG len = strlen(val) + 1;
649 buf[0] = id >> 24;
650 buf[1] = id >> 16;
651 buf[2] = id >> 8;
652 buf[3] = id;
654 if (Write(file, buf, 4) != 4) return FALSE;
655 *crc = UpdateCRC(*crc, buf, 4, IconBase);
657 if (Write(file, val, len) != len) return FALSE;
658 *crc = UpdateCRC(*crc, val, len, IconBase);
660 *chunksize += 4 + len;
662 return TRUE;
665 /****************************************************************************************/
667 STATIC BOOL WriteIconChunk(BPTR file, struct DiskObject *dobj, struct IconBase *IconBase)
669 ULONG crc = 0xFFFFFFFF;
670 ULONG chunksize = 0;
671 ULONG sizeseek = Seek(file, 0, OFFSET_CURRENT);
672 UBYTE buf[] = {0x12, 0x34, 0x56, 0x78, 'i', 'c', 'O', 'n'};
674 if (sizeseek < 0) return FALSE;
676 /* Write Chunk size + chunk type */
677 if (Write(file, buf, 8) != 8) return FALSE;
679 crc = UpdateCRC(crc, buf + 4, 4, IconBase); /* chunksize is excluded from CRC */
681 /* Write Frameless */
682 if (!WriteIconAttr(file, ATTR_FRAMELESS, NATIVEICON(dobj)->ni_Frameless, &chunksize, &crc, IconBase))
684 return FALSE;
687 /* Write Stack Size */
689 if (!WriteIconAttr(file, ATTR_STACKSIZE, dobj->do_StackSize, &chunksize, &crc, IconBase))
691 return FALSE;
694 /* Write Icon X Position */
695 if (dobj->do_CurrentX != NO_ICON_POSITION)
697 if (!WriteIconAttr(file, ATTR_ICONX, dobj->do_CurrentX, &chunksize, &crc, IconBase))
699 return FALSE;
703 /* Write Icon Y Position */
704 if (dobj->do_CurrentY != NO_ICON_POSITION)
706 if (!WriteIconAttr(file, ATTR_ICONY, dobj->do_CurrentY, &chunksize, &crc, IconBase))
708 return FALSE;
712 if (dobj->do_DrawerData)
714 if (!WriteIconAttr(file, ATTR_DRAWERX, dobj->do_DrawerData->dd_NewWindow.LeftEdge,
715 &chunksize, &crc, IconBase))
717 return FALSE;
720 if (!WriteIconAttr(file, ATTR_DRAWERY, dobj->do_DrawerData->dd_NewWindow.TopEdge,
721 &chunksize, &crc, IconBase))
723 return FALSE;
726 if (!WriteIconAttr(file, ATTR_DRAWERWIDTH, dobj->do_DrawerData->dd_NewWindow.Width,
727 &chunksize, &crc, IconBase))
729 return FALSE;
732 if (!WriteIconAttr(file, ATTR_DRAWERHEIGHT, dobj->do_DrawerData->dd_NewWindow.Height,
733 &chunksize, &crc, IconBase))
735 return FALSE;
738 if (!WriteIconAttr(file, ATTR_DRAWERFLAGS, dd_to_flags(dobj),
739 &chunksize, &crc, IconBase))
741 return FALSE;
744 } /* if (dobj->do_DrawerData) */
746 if (dobj->do_DefaultTool)
748 if (!WriteIconStrAttr(file, ATTR_DEFAULTTOOL, dobj->do_DefaultTool,
749 &chunksize, &crc, IconBase))
751 return FALSE;
756 if (dobj->do_ToolTypes)
758 STRPTR *tt = (STRPTR *)dobj->do_ToolTypes;
760 for(tt = (STRPTR *)dobj->do_ToolTypes; *tt; tt++)
762 if (!WriteIconStrAttr(file, ATTR_TOOLTYPE, *tt, &chunksize,
763 &crc, IconBase))
765 return FALSE;
770 /* Write CRC */
772 crc ^= 0xFFFFFFFF;
773 buf[0] = crc >> 24;
774 buf[1] = crc >> 16;
775 buf[2] = crc >> 8;
776 buf[3] = crc;
777 if (Write(file, buf, 4) != 4) return FALSE;
779 /* Write chunk's size */
780 if (Seek(file, sizeseek, OFFSET_BEGINNING) < 0) return FALSE;
782 buf[0] = chunksize >> 24;
783 buf[1] = chunksize >> 16;
784 buf[2] = chunksize >> 8;
785 buf[3] = chunksize;
786 if (Write(file, buf, 4) != 4) return FALSE;
788 if (Seek(file, 0, OFFSET_END) < 0) return FALSE;
790 return TRUE;
793 /****************************************************************************************/
795 BOOL WriteIconPNG(BPTR file, struct DiskObject *dobj, struct IconBase *IconBase)
797 struct NativeIcon *nativeicon = NATIVEICON(dobj);
798 UBYTE *mempos = nativeicon->ni_Extra.Data + nativeicon->ni_Extra.PNG[0].Offset;
799 BOOL done = FALSE;
801 D(bug("%s: ni=%p, ni->ni_Extra.Data = %p\n", __func__, nativeicon, nativeicon->ni_Extra.Data));
802 if (nativeicon->ni_Extra.Data == NULL)
803 return FALSE;
805 ObtainSemaphore(&IconBase->iconlistlock);
806 if (!IconBase->ib_CRCTable)
807 MakeCRCTable(IconBase);
808 ReleaseSemaphore(&IconBase->iconlistlock);
809 if (!IconBase->ib_CRCTable)
810 return FALSE;
812 /* Write PNG header */
813 if (Write(file, mempos, 8) != 8) return FALSE;
815 mempos += 8;
817 while(!done)
819 ULONG chunksize = (mempos[0] << 24) | (mempos[1] << 16) |
820 (mempos[2] << 8) | mempos[3];
821 ULONG chunktype = (mempos[4] << 24) | (mempos[5] << 16) |
822 (mempos[6] << 8) | mempos[7];
824 chunksize += 12;
826 if (chunktype == MAKE_ID('I', 'E', 'N', 'D'))
828 if (!WriteIconChunk(file, dobj, IconBase)) return FALSE;
829 done = TRUE;
832 if (chunktype != MAKE_ID('i', 'c', 'O', 'n'))
834 if (Write(file, mempos, chunksize) != chunksize)
836 return FALSE;
840 mempos += chunksize;
844 if (nativeicon->ni_Extra.PNG[1].Offset > 0)
846 ULONG size = nativeicon->ni_Extra.PNG[1].Size;
848 /* 2nd PNG Image attached */
850 if (Write(file, nativeicon->ni_Extra.Data + nativeicon->ni_Extra.PNG[1].Offset, size) != size) return FALSE;
853 return TRUE;
856 /****************************************************************************************/
858 VOID FreeIconPNG(struct DiskObject *dobj, struct IconBase *IconBase)
862 /****************************************************************************************/