Updated PCI IDs to latest snapshot.
[tangerine.git] / workbench / libs / icon / diskobjPNGio.c
blobe86d71ac351ab9c841a66c63222b615d7740ba82
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 /****************************************************************************************/
8 #include <datatypes/datatypes.h>
9 #include <intuition/intuition.h>
11 #include <proto/dos.h>
12 #include <proto/alib.h>
13 #include <proto/png.h>
14 #include <proto/datatypes.h>
16 #include <aros/bigendianio.h>
17 #include <aros/asmcall.h>
19 #include "icon_intern.h"
21 #define DEBUG 1
22 #include <aros/debug.h>
24 #define ATTR_ICONX 0x80001001
25 #define ATTR_ICONY 0x80001002
26 #define ATTR_DRAWERX 0x80001003
27 #define ATTR_DRAWERY 0x80001004
28 #define ATTR_DRAWERWIDTH 0x80001005
29 #define ATTR_DRAWERHEIGHT 0x80001006
30 #define ATTR_DRAWERFLAGS 0x80001007
31 #define ATTR_UNKNOWN 0x80001008 /* probably toolwindow? */
32 #define ATTR_STACKSIZE 0x80001009
33 #define ATTR_DEFAULTTOOL 0x8000100a
34 #define ATTR_TOOLTYPE 0x8000100b
35 #define ATTR_VIEWMODES 0x8000100c //OS4 PNG use that
36 #define ATTR_DD_CURRENTX 0x8000100d //OS4 PNG use that
37 #define ATTR_DD_CURRENTY 0x8000100e //OS4 PNG use that
38 #define ATTR_TYPE 0x8000100f //OS4 PNG use that
39 #define ATTR_DRAWERFLAGS2 0x80001107 //writen from AFA to store needed dopus Magellan settings
41 #define EFFECT_NONE (0)
42 #define EFFECT_LIGHTEN (1)
43 #define EFFECT_TINT_BLUE (2)
44 #define EFFECT_XOR (3)
46 #define EFFECT EFFECT_LIGHTEN
48 /****************************************************************************************/
51 ATTR_DRAWERFLAGS: AAABC
53 C : 1-bit flag : 0 = showonlyicons 1 = showallfiles
54 B : 1-bit flag : 0 = viewastext 1 = view as icons
55 AA : 2-bit value : 0 = viewbyname, 1 = viewbydata, 2 = viewbysize, 3 = viewbytype
58 static ULONG flags_to_ddflags(ULONG flags)
60 ULONG ret = 0;
62 if (flags & 1)
64 ret = DDFLAGS_SHOWALL;
66 else
68 ret = DDFLAGS_SHOWICONS;
71 return ret;
74 static ULONG flags_to_ddviewmodes(ULONG flags)
76 ULONG ret = 0;
78 if (flags & 2)
80 ret = DDVM_BYICON;
82 else
84 ret = (flags >> 2) + DDVM_BYNAME;
87 return ret;
90 static ULONG dd_to_flags(struct DiskObject *dobj)
92 ULONG drawerflags = 0;
94 if (dobj->do_DrawerData->dd_Flags & DDFLAGS_SHOWALL)
96 drawerflags |= 1;
99 if (dobj->do_DrawerData->dd_ViewModes == DDVM_BYICON)
101 drawerflags |= 2;
103 else
105 drawerflags |= ((dobj->do_DrawerData->dd_ViewModes - 2) << 2);
108 return drawerflags;
111 /****************************************************************************************/
113 STATIC BOOL MakePlanarImage(struct NativeIcon *icon, struct Image **img,
114 UBYTE *src, struct IconBase *IconBase)
116 LONG width16 = (icon->iconPNG.width + 15) & ~15;
117 LONG bpr = width16 / 8;
118 LONG planesize = bpr * icon->iconPNG.height;
119 LONG x, y;
120 UWORD *p1, *p2;
121 ULONG *s = (ULONG *)src;
123 *img = (struct Image *)AllocPooled(icon->pool, sizeof(struct Image) + planesize * 2);
124 if (*img == NULL) return FALSE;
126 (*img)->Width = icon->iconPNG.width;
127 (*img)->Height = icon->iconPNG.height;
128 (*img)->Depth = 2;
129 (*img)->ImageData = (UWORD *)(*img + 1);
130 (*img)->PlanePick = 3;
132 p1 = (UWORD *)(*img)->ImageData;
133 p2 = p1 + planesize / 2;
135 for(y = 0; y < icon->iconPNG.height; y++)
137 ULONG pixelmask = 0x8000;
138 UWORD plane1dat = 0;
139 UWORD plane2dat = 0;
141 for(x = 0; x < icon->iconPNG.width; x++)
143 ULONG pixel = *s++;
145 #if AROS_BIG_ENDIAN
146 if ((pixel & 0xFF000000) > 0x80000000)
148 pixel = (((pixel & 0x00FF0000) >> 16) +
149 ((pixel & 0x0000FF00) >> 8) +
150 ((pixel & 0x000000FF)) +
151 127) / 256;
152 #else
153 if ((pixel & 0x000000FF) > 0x80)
155 pixel = (((pixel & 0x0000FF00) >> 8) +
156 ((pixel & 0x00FF0000) >> 16) +
157 ((pixel & 0xFF000000) >> 24) +
158 127) / 256;
159 #endif
161 if (pixel == 3)
163 /* Col 2: White */
164 plane2dat |= pixelmask;
166 else if ((pixel == 2) || (pixel == 1))
168 /* Col 3: Amiga Blue */
169 plane1dat |= pixelmask;
170 plane2dat |= pixelmask;
172 else
174 /* Col 1: Black */
175 plane1dat |= pixelmask;
179 pixelmask >>= 1;
180 if (!pixelmask)
182 pixelmask = 0x8000;
183 *p1++ = AROS_WORD2BE(plane1dat);
184 *p2++ = AROS_WORD2BE(plane2dat);
186 plane1dat = plane2dat = 0;
192 if (pixelmask != 0x8000)
194 *p1++ = AROS_WORD2BE(plane1dat);
195 *p2++ = AROS_WORD2BE(plane2dat);
199 } /* for(y = 0; y < icon->iconPNG.height; y++) */
201 return TRUE;
205 /****************************************************************************************/
207 STATIC BOOL MakePlanarImages(struct NativeIcon *icon, struct IconBase *IconBase)
209 if (!MakePlanarImage(icon,
210 (struct Image **)&icon->dobj.do_Gadget.GadgetRender,
211 icon->iconPNG.img1,
212 IconBase))
214 return FALSE;
217 icon->dobj.do_Gadget.Flags |= GFLG_GADGIMAGE;
219 if (!icon->iconPNG.img2) return TRUE;
221 if (MakePlanarImage(icon,
222 (struct Image **)&icon->dobj.do_Gadget.SelectRender,
223 icon->iconPNG.img1,
224 IconBase))
226 icon->dobj.do_Gadget.Flags |= GFLG_GADGHIMAGE;
229 return TRUE;
232 /****************************************************************************************/
234 BOOL ReadIconPNG(struct DiskObject **ret, BPTR file, struct IconBase *IconBase)
236 static STRPTR chunknames[] =
238 "icOn",
239 NULL
241 APTR chunkpointer[] =
243 NULL,
244 NULL
247 struct NativeIcon *icon;
248 ULONG filesize;
249 APTR pool;
251 if (Seek(file, 0, OFFSET_END) < 0) return FALSE;
252 if ((filesize = Seek(file, 0, OFFSET_BEGINNING)) < 0) return FALSE;
254 pool = CreatePool(MEMF_ANY | MEMF_CLEAR, 1024, 1024);
255 if (!pool) return FALSE;
257 icon = AllocPooled(pool, sizeof(struct NativeIcon) + filesize);
258 if (!icon)
260 DeletePool(pool);
261 return FALSE;
264 icon->pool = pool;
266 icon->iconPNG.filebuffer = (UBYTE *)(icon + 1);
267 icon->iconPNG.filebuffersize = filesize;
269 /* Need a copy of whole file in memory for icon saving :-\ Because
270 that should save file back as it was, only with modified or new
271 icOn chunk. And it must also work when loading an icon and then
272 saving it using another name. */
274 if (Read(file, icon->iconPNG.filebuffer, filesize) != filesize)
276 DeletePool(pool);
277 return FALSE;
280 icon->iconPNG.handle = PNG_LoadImageMEM(icon->iconPNG.filebuffer, filesize,
281 chunknames, chunkpointer, TRUE);
283 if (!icon->iconPNG.handle)
285 FreeIconPNG(&icon->dobj, IconBase);
286 return FALSE;
290 LONG width, height;
292 PNG_GetImageInfo(icon->iconPNG.handle, &width, &height, NULL, NULL);
294 icon->iconPNG.width = width;
295 icon->iconPNG.height = height;
297 PNG_GetImageData(icon->iconPNG.handle, (APTR *)&icon->iconPNG.img1, NULL);
299 #define DO(x) (&x->dobj)
301 DO(icon)->do_Magic = WB_DISKMAGIC;
302 DO(icon)->do_Version = (WB_DISKVERSION << 8) | WB_DISKREVISION;
303 DO(icon)->do_Type = WBPROJECT;
304 DO(icon)->do_CurrentX = NO_ICON_POSITION;
305 DO(icon)->do_CurrentY = NO_ICON_POSITION;
306 DO(icon)->do_Gadget.Width = width;
307 DO(icon)->do_Gadget.Height = height;
308 DO(icon)->do_StackSize = AROS_STACKSIZE;
310 if (chunkpointer[0])
312 UBYTE *chunkdata;
313 ULONG chunksize;
314 ULONG ttnum = 0;
315 ULONG ttarraysize = 0;
316 BOOL ok = TRUE;
318 PNG_GetChunkInfo(chunkpointer[0], (APTR *)&chunkdata, &chunksize);
320 while(chunksize >= 4)
322 ULONG attr;
323 IPTR val = 0;
324 BOOL need_drawerdata = FALSE;
326 attr = (chunkdata[0] << 24) | (chunkdata[1] << 16) | (chunkdata[2] << 8) | chunkdata[3];
327 chunksize -=4;
328 chunkdata += 4;
330 switch(attr)
332 case ATTR_DRAWERX:
333 case ATTR_DRAWERY:
334 case ATTR_DRAWERWIDTH:
335 case ATTR_DRAWERHEIGHT:
336 case ATTR_DRAWERFLAGS:
337 case ATTR_DRAWERFLAGS2:
338 case ATTR_VIEWMODES:
339 case ATTR_DD_CURRENTX:
340 case ATTR_DD_CURRENTY:
341 need_drawerdata = TRUE;
342 /* Fall through */
344 case ATTR_ICONX:
345 case ATTR_ICONY:
346 case ATTR_STACKSIZE:
347 case ATTR_TYPE:
348 if (chunksize >= 4)
350 val = (chunkdata[0] << 24) | (chunkdata[1] << 16) | (chunkdata[2] << 8) | chunkdata[3];
351 chunksize -=4;
352 chunkdata += 4;
354 else
356 ok = FALSE;
358 break;
360 /* case ATTR_UNKNOWN: */
361 case ATTR_DEFAULTTOOL:
362 case ATTR_TOOLTYPE:
363 val = (IPTR)chunkdata;
364 chunksize -= strlen((char *)val) + 1;
365 chunkdata += strlen((char *)val) + 1;
367 if (chunksize < 0)
369 ok = FALSE;
371 break;
373 default:
374 /* Unknown attribute/tag. Impossible to handle correctly
375 if we don't know if it's a string attribute or not. */
376 ok = FALSE;
377 break;
379 } /* switch(attr) */
381 if (!ok) break;
383 if (need_drawerdata && !(DO(icon)->do_DrawerData))
385 DO(icon)->do_DrawerData = AllocPooled(pool, sizeof(struct DrawerData));
386 if (!(DO(icon)->do_DrawerData))
388 ok = FALSE;
389 break;
392 DO(icon)->do_DrawerData->dd_NewWindow.LeftEdge = 20;
393 DO(icon)->do_DrawerData->dd_NewWindow.TopEdge = 20;
394 DO(icon)->do_DrawerData->dd_NewWindow.Width = 300;
395 DO(icon)->do_DrawerData->dd_NewWindow.Height = 200;
398 switch(attr)
400 case ATTR_ICONX:
401 DO(icon)->do_CurrentX = val;
402 break;
404 case ATTR_ICONY:
405 DO(icon)->do_CurrentY = val;
406 break;
408 case ATTR_STACKSIZE:
409 DO(icon)->do_StackSize = val;
410 break;
412 case ATTR_DRAWERX:
413 DO(icon)->do_DrawerData->dd_NewWindow.LeftEdge = (WORD)val;
414 break;
416 case ATTR_DRAWERY:
417 DO(icon)->do_DrawerData->dd_NewWindow.TopEdge = (WORD)val;
418 break;
420 case ATTR_DRAWERWIDTH:
421 DO(icon)->do_DrawerData->dd_NewWindow.Width = (WORD)val;
422 break;
424 case ATTR_DRAWERHEIGHT:
425 DO(icon)->do_DrawerData->dd_NewWindow.Height = (WORD)val;
426 break;
428 case ATTR_DRAWERFLAGS:
429 DO(icon)->do_DrawerData->dd_Flags = flags_to_ddflags(val);
430 DO(icon)->do_DrawerData->dd_ViewModes = flags_to_ddviewmodes(val);
431 break;
433 case ATTR_DEFAULTTOOL:
434 DO(icon)->do_DefaultTool = AllocPooled(pool, strlen((char *)val) + 1);
435 if (DO(icon)->do_DefaultTool)
437 strcpy(DO(icon)->do_DefaultTool, (char *)val);
439 else
441 ok = FALSE;
443 break;
445 case ATTR_TOOLTYPE:
446 ttnum++;
447 if (ttarraysize < ttnum + 1)
449 STRPTR *old_tooltypes = DO(icon)->do_ToolTypes;
450 ULONG old_ttarraysize = ttarraysize;
452 ttarraysize += 10;
454 DO(icon)->do_ToolTypes = AllocPooled(pool, ttarraysize * sizeof(APTR));
455 if (DO(icon)->do_ToolTypes)
457 if (old_tooltypes)
459 memcpy(DO(icon)->do_ToolTypes, old_tooltypes, (ttnum - 1) * sizeof(APTR));
462 else
464 ok = FALSE;
467 if (old_tooltypes) FreePooled(pool, old_tooltypes, old_ttarraysize * sizeof(APTR));
470 if (!ok) break;
472 DO(icon)->do_ToolTypes[ttnum - 1] = AllocPooled(pool, strlen((char *)val) + 1);
473 if (DO(icon)->do_ToolTypes[ttnum - 1])
475 strcpy(DO(icon)->do_ToolTypes[ttnum - 1], (char *)val);
477 else
479 ok = FALSE;
481 break;
483 } /* switch(attr) */
485 if (!ok) break;
487 } /* while(chunksize >= 4) */
489 PNG_FreeChunk(chunkpointer[0]);
491 if (!ok)
493 D(bug("=== Failure during icOn chunk parsing ===\n"));
494 FreeIconPNG(&icon->dobj, IconBase);
495 return FALSE;
499 } /* if (chunkpointer[0]) */
501 #undef DO
503 #warning "FIXME: Someone killed PNG Icon do_Type detection here which causes"
504 #warning " following lines to always free DrawerData even when it"
505 #warning " shouldn't be freed (only possible to know if do_Type is"
506 #warning " known). So for now following lines disabled and DrawerData"
507 #warning " is always kept (even when it shouldn't)."
509 #if 0
510 if (icon->dobj.do_DrawerData &&
511 (icon->dobj.do_Type != WBDISK) &&
512 (icon->dobj.do_Type != WBDRAWER) &&
513 (icon->dobj.do_Type != WBGARBAGE))
515 FreePooled(pool, icon->dobj.do_DrawerData, sizeof(struct DrawerData));
516 icon->dobj.do_DrawerData = NULL;
518 #endif
520 } /**/
522 /* Look for a possible 2nd PNG image attached onto the first one */
524 UBYTE *filepos = icon->iconPNG.filebuffer + 8;
525 BOOL done = FALSE;
527 while(!done)
529 ULONG chunksize = (filepos[0] << 24) | (filepos[1] << 16) |
530 (filepos[2] << 8) | filepos[3];
531 ULONG chunktype = (filepos[4] << 24) | (filepos[5] << 16) |
532 (filepos[6] << 8) | filepos[7];
534 chunksize += 12;
536 if (chunktype == MAKE_ID('I', 'E', 'N', 'D'))
538 done = TRUE;
541 filepos += chunksize;
544 if (filepos + 8 < icon->iconPNG.filebuffer + icon->iconPNG.filebuffersize)
546 ULONG offset = filepos - icon->iconPNG.filebuffer;
548 icon->iconPNG.handle2 = PNG_LoadImageMEM(filepos, filesize - offset, 0, 0, TRUE);
550 if (icon->iconPNG.handle2)
552 LONG width, height;
554 PNG_GetImageInfo(icon->iconPNG.handle2, &width, &height, NULL, NULL);
556 if ((width == icon->iconPNG.width) &&
557 (height == icon->iconPNG.height))
559 PNG_GetImageData(icon->iconPNG.handle2, (APTR *)&icon->iconPNG.img2, NULL);
561 else
563 PNG_FreeImage(icon->iconPNG.handle2);
564 icon->iconPNG.handle2 = NULL;
570 } /**/
572 /* If there's no image for selected-state, generate one */
573 if (!icon->iconPNG.img2)
575 ULONG size = icon->iconPNG.width * icon->iconPNG.height;
577 if ((icon->iconPNG.img2 = AllocPooled(pool, size * sizeof(ULONG))))
579 ULONG *src = (ULONG *)icon->iconPNG.img1;
580 ULONG *dst = (ULONG *)icon->iconPNG.img2;
582 while(size--)
584 ULONG pixel = *src++;
586 /* Effects like in changetoselectediconcolor.c */
588 #if EFFECT == EFFECT_LIGHTEN
589 #if AROS_BIG_ENDIAN
590 pixel = (pixel & 0xFF000000) +
591 ((pixel >> 1) & 0x007F7F7F) +
592 0x00808080;
593 #else
594 pixel = (pixel & 0x000000FF) +
595 ((pixel >> 1) & 0x7F7F7F00) +
596 0x80808000;
597 #endif
598 #elif EFFECT == EFFECT_TINT_BLUE
599 #if AROS_BIG_ENDIAN
600 pixel = (pixel & 0xFF000000) +
601 ((pixel >> 1) & 0x007F7F7F) +
602 0x00000080;
603 #else
604 pixel = (pixel & 0x000000FF) +
605 ((pixel >> 1) & 0x7F7F7F00) +
606 0x80000000;
607 #endif
609 #elif EFFECT == EFFECT_XOR
610 #if AROS_BIG_ENDIAN
611 pixel = (pixel & 0xFF000000) +
612 ((pixel & 0x00FFFFFF) ^ 0x00FFFFFF);
613 #else
614 pixel = (pixel & 0x000000FF) +
615 ((pixel & 0xFFFFFF00) ^ 0xFFFFFF00);
616 #endif
617 #endif
618 *dst++ = pixel;
623 /* Make fallback planar images */
625 if (!MakePlanarImages(icon, IconBase))
627 D(bug("Planar image creation failed\n"));
628 FreeIconPNG(&icon->dobj, IconBase);
629 return FALSE;
632 *ret = &icon->dobj;
634 return TRUE;
638 /****************************************************************************************/
640 STATIC VOID MakeCRCTable(struct IconBase *IconBase)
642 unsigned long c;
643 int n, k;
645 for (n = 0; n < 256; n++)
647 c = (unsigned long) n;
648 for (k = 0; k < 8; k++)
650 if (c & 1)
651 c = 0xedb88320L ^ (c >> 1);
652 else
653 c = c >> 1;
655 IconBase->ib_CRCTable[n] = c;
658 IconBase->ib_CRCTableComputed = TRUE;
662 /****************************************************************************************/
664 STATIC ULONG UpdateCRC(ULONG crc, UBYTE *buf, ULONG len, struct IconBase *IconBase)
666 ULONG c = crc;
667 ULONG n;
669 ObtainSemaphore(&IconBase->iconlistlock);
670 if (!IconBase->ib_CRCTableComputed)
672 MakeCRCTable(IconBase);
674 ReleaseSemaphore(&IconBase->iconlistlock);
676 for (n = 0; n < len; n++)
678 c = IconBase->ib_CRCTable[(c ^ buf[n]) & 0xff] ^ (c >> 8);
681 return c;
685 /****************************************************************************************/
687 STATIC BOOL WriteIconAttr(BPTR file, ULONG id, ULONG val, ULONG *chunksize,
688 ULONG *crc, struct IconBase *IconBase)
690 UBYTE buf[8];
692 buf[0] = id >> 24;
693 buf[1] = id >> 16;
694 buf[2] = id >> 8;
695 buf[3] = id;
696 buf[4] = val >> 24;
697 buf[5] = val >> 16;
698 buf[6] = val >> 8;
699 buf[7] = val;
701 if (Write(file, buf, 8) != 8) return FALSE;
703 *chunksize += 8;
704 *crc = UpdateCRC(*crc, buf, 8, IconBase);
705 return TRUE;
708 /****************************************************************************************/
710 STATIC BOOL WriteIconStrAttr(BPTR file, ULONG id, char *val, ULONG *chunksize,
711 ULONG *crc, struct IconBase *IconBase)
713 UBYTE buf[4];
714 ULONG len = strlen(val) + 1;
716 buf[0] = id >> 24;
717 buf[1] = id >> 16;
718 buf[2] = id >> 8;
719 buf[3] = id;
721 if (Write(file, buf, 4) != 4) return FALSE;
722 *crc = UpdateCRC(*crc, buf, 4, IconBase);
724 if (Write(file, val, len) != len) return FALSE;
725 *crc = UpdateCRC(*crc, val, len, IconBase);
727 *chunksize += 4 + len;
729 return TRUE;
732 /****************************************************************************************/
734 STATIC BOOL WriteIconChunk(BPTR file, struct DiskObject *dobj, struct IconBase *IconBase)
736 ULONG crc = 0xFFFFFFFF;
737 ULONG chunksize = 0;
738 ULONG sizeseek = Seek(file, 0, OFFSET_CURRENT);
739 UBYTE buf[] = {0x12, 0x34, 0x56, 0x78, 'i', 'c', 'O', 'n'};
741 if (sizeseek < 0) return FALSE;
743 /* Write Chunk size + chunk type */
744 if (Write(file, buf, 8) != 8) return FALSE;
746 crc = UpdateCRC(crc, buf + 4, 4, IconBase); /* chunksize is excluded from CRC */
748 /* Write Stack Size */
750 if (!WriteIconAttr(file, ATTR_STACKSIZE, dobj->do_StackSize, &chunksize, &crc, IconBase))
752 return FALSE;
755 /* Write Icon X Position */
756 if (dobj->do_CurrentX != NO_ICON_POSITION)
758 if (!WriteIconAttr(file, ATTR_ICONX, dobj->do_CurrentX, &chunksize, &crc, IconBase))
760 return FALSE;
764 /* Write Icon Y Position */
765 if (dobj->do_CurrentY != NO_ICON_POSITION)
767 if (!WriteIconAttr(file, ATTR_ICONY, dobj->do_CurrentY, &chunksize, &crc, IconBase))
769 return FALSE;
773 if (dobj->do_DrawerData)
775 if (!WriteIconAttr(file, ATTR_DRAWERX, dobj->do_DrawerData->dd_NewWindow.LeftEdge,
776 &chunksize, &crc, IconBase))
778 return FALSE;
781 if (!WriteIconAttr(file, ATTR_DRAWERY, dobj->do_DrawerData->dd_NewWindow.TopEdge,
782 &chunksize, &crc, IconBase))
784 return FALSE;
787 if (!WriteIconAttr(file, ATTR_DRAWERWIDTH, dobj->do_DrawerData->dd_NewWindow.Width,
788 &chunksize, &crc, IconBase))
790 return FALSE;
793 if (!WriteIconAttr(file, ATTR_DRAWERHEIGHT, dobj->do_DrawerData->dd_NewWindow.Height,
794 &chunksize, &crc, IconBase))
796 return FALSE;
799 if (!WriteIconAttr(file, ATTR_DRAWERFLAGS, dd_to_flags(dobj),
800 &chunksize, &crc, IconBase))
802 return FALSE;
805 } /* if (dobj->do_DrawerData) */
807 if (dobj->do_DefaultTool)
809 if (!WriteIconStrAttr(file, ATTR_DEFAULTTOOL, dobj->do_DefaultTool,
810 &chunksize, &crc, IconBase))
812 return FALSE;
817 if (dobj->do_ToolTypes)
819 STRPTR *tt = (STRPTR *)dobj->do_ToolTypes;
821 for(tt = (STRPTR *)dobj->do_ToolTypes; *tt; tt++)
823 if (!WriteIconStrAttr(file, ATTR_TOOLTYPE, *tt, &chunksize,
824 &crc, IconBase))
826 return FALSE;
831 /* Write CRC */
833 crc ^= 0xFFFFFFFF;
834 buf[0] = crc >> 24;
835 buf[1] = crc >> 16;
836 buf[2] = crc >> 8;
837 buf[3] = crc;
838 if (Write(file, buf, 4) != 4) return FALSE;
840 /* Write chunk's size */
841 if (Seek(file, sizeseek, OFFSET_BEGINNING) < 0) return FALSE;
843 buf[0] = chunksize >> 24;
844 buf[1] = chunksize >> 16;
845 buf[2] = chunksize >> 8;
846 buf[3] = chunksize;
847 if (Write(file, buf, 4) != 4) return FALSE;
849 if (Seek(file, 0, OFFSET_END) < 0) return FALSE;
851 return TRUE;
854 /****************************************************************************************/
856 BOOL WriteIconPNG(BPTR file, struct DiskObject *dobj, struct IconBase *IconBase)
858 struct NativeIcon *nativeicon = NATIVEICON(dobj);
859 struct IconPNG *iconpng = &nativeicon->iconPNG;
860 UBYTE *mempos = iconpng->filebuffer;
861 BOOL done = FALSE;
863 /* Write PNG header */
864 if (Write(file, iconpng->filebuffer, 8) != 8) return FALSE;
866 mempos += 8;
868 while(!done)
870 ULONG chunksize = (mempos[0] << 24) | (mempos[1] << 16) |
871 (mempos[2] << 8) | mempos[3];
872 ULONG chunktype = (mempos[4] << 24) | (mempos[5] << 16) |
873 (mempos[6] << 8) | mempos[7];
875 chunksize += 12;
877 if (chunktype == MAKE_ID('I', 'E', 'N', 'D'))
879 if (!WriteIconChunk(file, dobj, IconBase)) return FALSE;
880 done = TRUE;
883 if (chunktype != MAKE_ID('i', 'c', 'O', 'n'))
885 if (Write(file, mempos, chunksize) != chunksize)
887 return FALSE;
891 mempos += chunksize;
895 if (mempos < iconpng->filebuffer + iconpng->filebuffersize)
897 ULONG size = iconpng->filebuffer + iconpng->filebuffersize - mempos;
899 /* 2nd PNG Image attached */
901 if (Write(file, mempos, size) != size) return FALSE;
904 return TRUE;
907 /****************************************************************************************/
909 VOID FreeIconPNG(struct DiskObject *dobj, struct IconBase *IconBase)
911 if (dobj)
913 struct NativeIcon *nativeicon = NATIVEICON(dobj);
915 if (nativeicon->iconPNG.handle)
917 PNG_FreeImage(nativeicon->iconPNG.handle);
920 if (nativeicon->iconPNG.handle2)
922 PNG_FreeImage(nativeicon->iconPNG.handle2);
925 if (nativeicon->pool) DeletePool(nativeicon->pool);
929 /****************************************************************************************/