2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
6 /****************************************************************************************/
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>
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
)
71 ret
= DDFLAGS_SHOWALL
;
75 ret
= DDFLAGS_SHOWICONS
;
81 static ULONG
flags_to_ddviewmodes(ULONG flags
)
91 ret
= (flags
>> 2) + DDVM_BYNAME
;
97 static ULONG
dd_to_flags(struct DiskObject
*dobj
)
99 ULONG drawerflags
= 0;
101 if (dobj
->do_DrawerData
->dd_Flags
& DDFLAGS_SHOWALL
)
106 if (dobj
->do_DrawerData
->dd_ViewModes
== DDVM_BYICON
)
112 drawerflags
|= ((dobj
->do_DrawerData
->dd_ViewModes
- 2) << 2);
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);
129 D(bug("[%s] Can't open png.datatype\n", __func__
));
133 handle
= PNG_LoadImageMEM(stream
, -1, chunknames
, chunkpointer
, TRUE
);
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) {
147 PNG_GetImageData(handle
, (APTR
*)&src
, NULL
);
149 argb
= AllocMemIcon(icon
, (*width
) * (*height
) * sizeof(ULONG
), MEMF_PUBLIC
);
151 xoff
= ((*width
) - w
)/2;
152 yoff
= ((*height
) - h
)/2;
155 for (y
= 0; y
< *height
; y
++) {
164 for (x
= 0; x
< *width
; x
++, dst
++) {
178 PNG_FreeImage(handle
);
180 D(bug("[%s] PNG datatype can't parse data\n", __func__
));
183 CloseLibrary(PNGBase
);
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 /****************************************************************************************/
199 STATIC BOOL
MakePlanarImage(struct NativeIcon
*icon
, struct Image
**img
, UBYTE
*src
, struct IconBase
*IconBase
)
201 LONG width16
= (icon
->ni_DiskObject
.do_Gadget
.Width
+ 15) & ~15;
202 LONG bpr
= width16
/ 8;
203 LONG planesize
= bpr
* icon
->ni_DiskObject
.do_Gadget
.Height
;
206 ULONG
*s
= (ULONG
*) src
;
208 *img
= (struct Image
*) AllocMemIcon(&icon
->ni_DiskObject
, sizeof(struct Image
) + planesize
* 2,
209 MEMF_PUBLIC
| MEMF_CLEAR
);
213 (*img
)->Width
= icon
->ni_DiskObject
.do_Gadget
.Width
;
214 (*img
)->Height
= icon
->ni_DiskObject
.do_Gadget
.Height
;
216 (*img
)->ImageData
= (UWORD
*) (*img
+ 1);
217 (*img
)->PlanePick
= 3;
219 p1
= (UWORD
*) (*img
)->ImageData
;
220 p2
= p1
+ planesize
/ 2;
222 for (y
= 0; y
< (*img
)->Height
; y
++)
224 ULONG pixelmask
= 0x8000;
228 for (x
= 0; x
< (*img
)->Width
; x
++)
233 if ((pixel
& 0xFF000000) > 0x80000000)
235 pixel
= (((pixel
& 0x00FF0000) >> 16) +
236 ((pixel
& 0x0000FF00) >> 8) +
237 ((pixel
& 0x000000FF)) +
240 if ((pixel
& 0x000000FF) > 0x80)
242 pixel
= (((pixel
& 0x0000FF00) >> 8) + ((pixel
& 0x00FF0000) >> 16) + ((pixel
& 0xFF000000) >> 24) + 127) / 256;
248 plane2dat
|= pixelmask
;
250 else if ((pixel
== 2) || (pixel
== 1))
252 /* Col 3: Amiga Blue */
253 plane1dat
|= pixelmask
;
254 plane2dat
|= pixelmask
;
259 plane1dat
|= pixelmask
;
267 *p1
++ = AROS_WORD2BE(plane1dat
);
268 *p2
++ = AROS_WORD2BE(plane2dat
);
270 plane1dat
= plane2dat
= 0;
276 if (pixelmask
!= 0x8000)
278 *p1
++ = AROS_WORD2BE(plane1dat
);
279 *p2
++ = AROS_WORD2BE(plane2dat
);
283 } /* for(y = 0; y < icon->ni_Height; y++) */
289 /****************************************************************************************/
291 STATIC BOOL
MakePlanarImages(struct NativeIcon
*icon
, struct IconBase
*IconBase
)
293 if (!MakePlanarImage(icon
, (struct Image
**) &icon
->ni_DiskObject
.do_Gadget
.GadgetRender
,
294 (UBYTE
*)icon
->ni_Image
[0].ARGB
, IconBase
))
299 icon
->ni_DiskObject
.do_Gadget
.Flags
|= GFLG_GADGIMAGE
;
301 if (!icon
->ni_Image
[1].ARGB
)
304 if (MakePlanarImage(icon
, (struct Image
**) &icon
->ni_DiskObject
.do_Gadget
.SelectRender
,
305 (UBYTE
*)icon
->ni_Image
[1].ARGB
, IconBase
))
307 icon
->ni_DiskObject
.do_Gadget
.Flags
|= GFLG_GADGHIMAGE
;
313 /****************************************************************************************/
315 BOOL
ReadIconPNG(struct DiskObject
*dobj
, BPTR file
, struct IconBase
*IconBase
)
317 static CONST_STRPTR
const chunknames
[] =
322 APTR chunkpointer
[] =
328 struct NativeIcon
*icon
;
332 icon
= NATIVEICON(dobj
);
334 D(bug("%s: File stream %p\n", __func__
, file
));
336 if (Seek(file
, 0, OFFSET_END
) < 0) return FALSE
;
337 if ((filesize
= Seek(file
, 0, OFFSET_BEGINNING
)) < 0) return FALSE
;
339 D(bug("[%s] Inspecting a %d byte file\n", __func__
, filesize
));
341 /* Need a copy of whole file in memory for icon saving :-\ Because
342 that should save file back as it was, only with modified or new
343 icOn chunk. And it must also work when loading an icon and then
344 saving it using another name. */
346 data
= AllocMemIcon(&icon
->ni_DiskObject
, filesize
, MEMF_PUBLIC
);
350 if (Read(file
, data
, filesize
) != filesize
)
352 D(bug("[%s] Can't read from file\n", __func__
));
356 icon
->ni_Extra
.Data
= data
;
357 icon
->ni_Extra
.Size
= filesize
;
359 icon
->ni_Extra
.PNG
[0].Offset
= 0;
360 icon
->ni_Extra
.PNG
[0].Size
= filesize
;
362 ULONG width
= ~0, height
= ~0;
364 icon
->ni_Image
[0].ARGB
= ReadMemPNG(&icon
->ni_DiskObject
, icon
->ni_Extra
.Data
+ icon
->ni_Extra
.PNG
[0].Offset
, &width
, &height
, chunknames
, chunkpointer
, IconBase
);
365 if (icon
->ni_Image
[0].ARGB
== NULL
) {
366 D(bug("[%s] Can't parse PNG image at 0\n", __func__
));
370 icon
->ni_Face
.Width
= width
;
371 icon
->ni_Face
.Height
= height
;
372 icon
->ni_Face
.Aspect
= ICON_ASPECT_RATIO_UNKNOWN
;
374 #define DO(x) (&x->ni_DiskObject)
376 DO(icon
)->do_Magic
= WB_DISKMAGIC
;
377 DO(icon
)->do_Version
= (WB_DISKVERSION
<< 8) | WB_DISKREVISION
;
378 DO(icon
)->do_Type
= 0; /* Invalid */
379 DO(icon
)->do_CurrentX
= NO_ICON_POSITION
;
380 DO(icon
)->do_CurrentY
= NO_ICON_POSITION
;
381 DO(icon
)->do_Gadget
.Width
= width
;
382 DO(icon
)->do_Gadget
.Height
= height
;
383 DO(icon
)->do_StackSize
= AROS_STACKSIZE
;
390 ULONG ttarraysize
= 0;
393 GetChunkInfo(chunkpointer
[0], (APTR
*)&chunkdata
, &chunksize
);
395 while(chunksize
>= 4)
399 BOOL need_drawerdata
= FALSE
;
401 attr
= (chunkdata
[0] << 24) | (chunkdata
[1] << 16) | (chunkdata
[2] << 8) | chunkdata
[3];
409 case ATTR_DRAWERWIDTH
:
410 case ATTR_DRAWERHEIGHT
:
411 case ATTR_DRAWERFLAGS
:
412 case ATTR_DRAWERFLAGS2
:
413 case ATTR_DRAWERFLAGS3
:
415 case ATTR_VIEWMODES2
:
416 case ATTR_DD_CURRENTX
:
417 case ATTR_DD_CURRENTY
:
418 need_drawerdata
= TRUE
;
428 val
= (chunkdata
[0] << 24) | (chunkdata
[1] << 16) | (chunkdata
[2] << 8) | chunkdata
[3];
438 /* case ATTR_UNKNOWN: */
439 case ATTR_DEFAULTTOOL
:
441 val
= (IPTR
)chunkdata
;
442 chunksize
-= strlen((char *)val
) + 1;
443 chunkdata
+= strlen((char *)val
) + 1;
452 /* Unknown attribute/tag. Impossible to handle correctly
453 if we don't know if it's a string attribute or not. */
461 if (need_drawerdata
&& !(DO(icon
)->do_DrawerData
))
463 DO(icon
)->do_DrawerData
= AllocMemIcon(DO(icon
), sizeof(struct DrawerData
), MEMF_PUBLIC
| MEMF_CLEAR
);
464 if (!(DO(icon
)->do_DrawerData
))
470 DO(icon
)->do_DrawerData
->dd_NewWindow
.LeftEdge
= 20;
471 DO(icon
)->do_DrawerData
->dd_NewWindow
.TopEdge
= 20;
472 DO(icon
)->do_DrawerData
->dd_NewWindow
.Width
= 300;
473 DO(icon
)->do_DrawerData
->dd_NewWindow
.Height
= 200;
474 DO(icon
)->do_Gadget
.UserData
= (APTR
)1; /* See DupDiskObject logic */
480 DO(icon
)->do_CurrentX
= val
;
484 DO(icon
)->do_CurrentY
= val
;
488 DO(icon
)->do_StackSize
= val
;
492 DO(icon
)->do_DrawerData
->dd_NewWindow
.LeftEdge
= (WORD
)val
;
496 DO(icon
)->do_DrawerData
->dd_NewWindow
.TopEdge
= (WORD
)val
;
499 case ATTR_DRAWERWIDTH
:
500 DO(icon
)->do_DrawerData
->dd_NewWindow
.Width
= (WORD
)val
;
503 case ATTR_DRAWERHEIGHT
:
504 DO(icon
)->do_DrawerData
->dd_NewWindow
.Height
= (WORD
)val
;
507 case ATTR_DRAWERFLAGS
:
508 DO(icon
)->do_DrawerData
->dd_Flags
= flags_to_ddflags(val
);
509 DO(icon
)->do_DrawerData
->dd_ViewModes
= flags_to_ddviewmodes(val
);
512 case ATTR_DEFAULTTOOL
:
513 DO(icon
)->do_DefaultTool
= AllocMemIcon(DO(icon
), strlen((char *)val
) + 1, MEMF_PUBLIC
| MEMF_CLEAR
);
514 if (DO(icon
)->do_DefaultTool
)
516 strcpy(DO(icon
)->do_DefaultTool
, (char *)val
);
524 NATIVEICON(icon
)->ni_Frameless
= val
? TRUE
: FALSE
;
530 D(bug("[Icon.PNG] Got tooltype number %u : %s\n", ttnum
- 1, val
));
532 if (ttarraysize
< ttnum
+ 1)
534 STRPTR
*old_tooltypes
= DO(icon
)->do_ToolTypes
;
538 DO(icon
)->do_ToolTypes
= AllocMemIcon(DO(icon
), ttarraysize
* sizeof(APTR
), MEMF_PUBLIC
| MEMF_CLEAR
);
539 if (DO(icon
)->do_ToolTypes
)
541 D(bug("[Icon.PNG] Allocated array of %u entries @ 0x%p (old 0x%p)\n", ttarraysize
, DO(icon
)->do_ToolTypes
, old_tooltypes
));
544 CopyMemQuick(old_tooltypes
, DO(icon
)->do_ToolTypes
, (ttnum
- 1) * sizeof(APTR
));
546 /* TODO: Free old array */
557 DO(icon
)->do_ToolTypes
[ttnum
- 1] = AllocMemIcon(DO(icon
), strlen((char *)val
) + 1, MEMF_PUBLIC
| MEMF_CLEAR
);
558 if (DO(icon
)->do_ToolTypes
[ttnum
- 1])
560 strcpy(DO(icon
)->do_ToolTypes
[ttnum
- 1], (char *)val
);
572 } /* while(chunksize >= 4) */
576 D(bug("=== Failure during icOn chunk parsing ===\n"));
577 FreeIconPNG(&icon
->ni_DiskObject
, IconBase
);
582 } /* if (chunkpointer[0]) */
587 * FIXME: Someone killed PNG Icon do_Type detection here which causes
588 * following lines to always free DrawerData even when it
589 * shouldn't be freed (only possible to know if do_Type is
590 * known). So for now following lines disabled and DrawerData
591 * is always kept (even when it shouldn't).
595 if (icon
->ni_DiskObject
.do_DrawerData
&&
596 (icon
->ni_DiskObject
.do_Type
!= WBDISK
) &&
597 (icon
->ni_DiskObject
.do_Type
!= WBDRAWER
) &&
598 (icon
->ni_DiskObject
.do_Type
!= WBGARBAGE
))
600 FreePooled(pool
, icon
->ni_DiskObject
.do_DrawerData
, sizeof(struct DrawerData
));
601 icon
->ni_DiskObject
.do_DrawerData
= NULL
;
607 /* Look for a possible 2nd PNG image attached onto the first one */
609 UBYTE
*filepos
= icon
->ni_Extra
.Data
+ icon
->ni_Extra
.PNG
[0].Offset
+ 8;
612 while(!done
&& filepos
< ((UBYTE
*)icon
->ni_Extra
.Data
+ icon
->ni_Extra
.Size
))
614 ULONG chunksize
= (filepos
[0] << 24) | (filepos
[1] << 16) |
615 (filepos
[2] << 8) | filepos
[3];
616 ULONG chunktype
= (filepos
[4] << 24) | (filepos
[5] << 16) |
617 (filepos
[6] << 8) | filepos
[7];
621 if (chunktype
== MAKE_ID('I', 'E', 'N', 'D'))
626 filepos
+= chunksize
;
629 if (filepos
+ 8 < (UBYTE
*)icon
->ni_Extra
.Data
+ icon
->ni_Extra
.Size
)
631 ULONG offset
= filepos
- (UBYTE
*)icon
->ni_Extra
.Data
;
633 icon
->ni_Extra
.PNG
[0].Size
= offset
;
634 icon
->ni_Extra
.PNG
[1].Offset
= offset
;
635 icon
->ni_Extra
.PNG
[1].Size
= (filesize
- icon
->ni_Extra
.PNG
[0].Size
);
636 icon
->ni_Image
[1].ARGB
= ReadMemPNG(&icon
->ni_DiskObject
, filepos
, &icon
->ni_Face
.Width
, &icon
->ni_Face
.Height
, NULL
, NULL
, IconBase
);
641 /* If there's no image for selected-state, generate one */
642 if (!icon
->ni_Image
[1].ARGB
)
644 ULONG size
= icon
->ni_Face
.Width
* icon
->ni_Face
.Height
;
646 if ((icon
->ni_Image
[1].ARGB
= AllocMemIcon(&icon
->ni_DiskObject
, size
* sizeof(ULONG
), MEMF_PUBLIC
)))
648 ULONG
*src
= (ULONG
*)icon
->ni_Image
[0].ARGB
;
649 ULONG
*dst
= (ULONG
*)icon
->ni_Image
[1].ARGB
;
653 ULONG pixel
= *src
++;
655 /* Effects like in changetoselectediconcolor.c */
657 #if EFFECT == EFFECT_LIGHTEN
659 pixel
= (pixel
& 0xFF000000) +
660 ((pixel
>> 1) & 0x007F7F7F) +
663 pixel
= (pixel
& 0x000000FF) +
664 ((pixel
>> 1) & 0x7F7F7F00) +
667 #elif EFFECT == EFFECT_TINT_BLUE
669 pixel
= (pixel
& 0xFF000000) +
670 ((pixel
>> 1) & 0x007F7F7F) +
673 pixel
= (pixel
& 0x000000FF) +
674 ((pixel
>> 1) & 0x7F7F7F00) +
678 #elif EFFECT == EFFECT_XOR
680 pixel
= (pixel
& 0xFF000000) +
681 ((pixel
& 0x00FFFFFF) ^ 0x00FFFFFF);
683 pixel
= (pixel
& 0x000000FF) +
684 ((pixel
& 0xFFFFFF00) ^ 0xFFFFFF00);
693 * Support old-style AROS PNG icons. 3rd party applications
694 * will still be using them.
697 if (!MakePlanarImages(icon
, IconBase
))
699 D(bug("Planar image creation failed\n"));
700 FreeIconPNG(&icon
->ni_DiskObject
, IconBase
);
708 /****************************************************************************************/
710 STATIC VOID
MakeCRCTable(struct IconBase
*IconBase
)
715 IconBase
->ib_CRCTable
= AllocMem(256 * sizeof(ULONG
), MEMF_ANY
);
716 if (!IconBase
->ib_CRCTable
)
718 for (n
= 0; n
< 256; n
++)
720 c
= (unsigned long) n
;
721 for (k
= 0; k
< 8; k
++)
724 c
= 0xedb88320L
^ (c
>> 1);
728 IconBase
->ib_CRCTable
[n
] = c
;
732 /****************************************************************************************/
734 STATIC ULONG
UpdateCRC(ULONG crc
, UBYTE
*buf
, ULONG len
, struct IconBase
*IconBase
)
739 for (n
= 0; n
< len
; n
++)
741 c
= IconBase
->ib_CRCTable
[(c
^ buf
[n
]) & 0xff] ^ (c
>> 8);
748 /****************************************************************************************/
750 STATIC BOOL
WriteIconAttr(BPTR file
, ULONG id
, ULONG val
, ULONG
*chunksize
,
751 ULONG
*crc
, struct IconBase
*IconBase
)
764 if (Write(file
, buf
, 8) != 8) return FALSE
;
767 *crc
= UpdateCRC(*crc
, buf
, 8, IconBase
);
771 /****************************************************************************************/
773 STATIC BOOL
WriteIconStrAttr(BPTR file
, ULONG id
, char *val
, ULONG
*chunksize
,
774 ULONG
*crc
, struct IconBase
*IconBase
)
777 ULONG len
= strlen(val
) + 1;
784 if (Write(file
, buf
, 4) != 4) return FALSE
;
785 *crc
= UpdateCRC(*crc
, buf
, 4, IconBase
);
787 if (Write(file
, val
, len
) != len
) return FALSE
;
788 *crc
= UpdateCRC(*crc
, val
, len
, IconBase
);
790 *chunksize
+= 4 + len
;
795 /****************************************************************************************/
797 STATIC BOOL
WriteIconChunk(BPTR file
, struct DiskObject
*dobj
, struct IconBase
*IconBase
)
799 ULONG crc
= 0xFFFFFFFF;
801 ULONG sizeseek
= Seek(file
, 0, OFFSET_CURRENT
);
802 UBYTE buf
[] = {0x12, 0x34, 0x56, 0x78, 'i', 'c', 'O', 'n'};
804 if (sizeseek
< 0) return FALSE
;
806 /* Write Chunk size + chunk type */
807 if (Write(file
, buf
, 8) != 8) return FALSE
;
809 crc
= UpdateCRC(crc
, buf
+ 4, 4, IconBase
); /* chunksize is excluded from CRC */
811 /* Write Frameless */
812 if (!WriteIconAttr(file
, ATTR_FRAMELESS
, NATIVEICON(dobj
)->ni_Frameless
, &chunksize
, &crc
, IconBase
))
817 /* Write Stack Size */
819 if (!WriteIconAttr(file
, ATTR_STACKSIZE
, dobj
->do_StackSize
, &chunksize
, &crc
, IconBase
))
824 /* Write Icon X Position */
825 if (dobj
->do_CurrentX
!= NO_ICON_POSITION
)
827 if (!WriteIconAttr(file
, ATTR_ICONX
, dobj
->do_CurrentX
, &chunksize
, &crc
, IconBase
))
833 /* Write Icon Y Position */
834 if (dobj
->do_CurrentY
!= NO_ICON_POSITION
)
836 if (!WriteIconAttr(file
, ATTR_ICONY
, dobj
->do_CurrentY
, &chunksize
, &crc
, IconBase
))
842 if (dobj
->do_DrawerData
)
844 if (!WriteIconAttr(file
, ATTR_DRAWERX
, dobj
->do_DrawerData
->dd_NewWindow
.LeftEdge
,
845 &chunksize
, &crc
, IconBase
))
850 if (!WriteIconAttr(file
, ATTR_DRAWERY
, dobj
->do_DrawerData
->dd_NewWindow
.TopEdge
,
851 &chunksize
, &crc
, IconBase
))
856 if (!WriteIconAttr(file
, ATTR_DRAWERWIDTH
, dobj
->do_DrawerData
->dd_NewWindow
.Width
,
857 &chunksize
, &crc
, IconBase
))
862 if (!WriteIconAttr(file
, ATTR_DRAWERHEIGHT
, dobj
->do_DrawerData
->dd_NewWindow
.Height
,
863 &chunksize
, &crc
, IconBase
))
868 if (!WriteIconAttr(file
, ATTR_DRAWERFLAGS
, dd_to_flags(dobj
),
869 &chunksize
, &crc
, IconBase
))
874 } /* if (dobj->do_DrawerData) */
876 if (dobj
->do_DefaultTool
)
878 if (!WriteIconStrAttr(file
, ATTR_DEFAULTTOOL
, dobj
->do_DefaultTool
,
879 &chunksize
, &crc
, IconBase
))
886 if (dobj
->do_ToolTypes
)
888 STRPTR
*tt
= (STRPTR
*)dobj
->do_ToolTypes
;
890 for(tt
= (STRPTR
*)dobj
->do_ToolTypes
; *tt
; tt
++)
892 if (!WriteIconStrAttr(file
, ATTR_TOOLTYPE
, *tt
, &chunksize
,
907 if (Write(file
, buf
, 4) != 4) return FALSE
;
909 /* Write chunk's size */
910 if (Seek(file
, sizeseek
, OFFSET_BEGINNING
) < 0) return FALSE
;
912 buf
[0] = chunksize
>> 24;
913 buf
[1] = chunksize
>> 16;
914 buf
[2] = chunksize
>> 8;
916 if (Write(file
, buf
, 4) != 4) return FALSE
;
918 if (Seek(file
, 0, OFFSET_END
) < 0) return FALSE
;
923 /****************************************************************************************/
925 BOOL
WriteIconPNG(BPTR file
, struct DiskObject
*dobj
, struct IconBase
*IconBase
)
927 struct NativeIcon
*nativeicon
= NATIVEICON(dobj
);
928 UBYTE
*mempos
= nativeicon
->ni_Extra
.Data
+ nativeicon
->ni_Extra
.PNG
[0].Offset
;
931 D(bug("%s: ni=%p, ni->ni_Extra.Data = %p\n", __func__
, nativeicon
, nativeicon
->ni_Extra
.Data
));
932 if (nativeicon
->ni_Extra
.Data
== NULL
)
935 ObtainSemaphore(&IconBase
->iconlistlock
);
936 if (!IconBase
->ib_CRCTable
)
937 MakeCRCTable(IconBase
);
938 ReleaseSemaphore(&IconBase
->iconlistlock
);
939 if (!IconBase
->ib_CRCTable
)
942 /* Write PNG header */
943 if (Write(file
, mempos
, 8) != 8) return FALSE
;
949 ULONG chunksize
= (mempos
[0] << 24) | (mempos
[1] << 16) |
950 (mempos
[2] << 8) | mempos
[3];
951 ULONG chunktype
= (mempos
[4] << 24) | (mempos
[5] << 16) |
952 (mempos
[6] << 8) | mempos
[7];
956 if (chunktype
== MAKE_ID('I', 'E', 'N', 'D'))
958 if (!WriteIconChunk(file
, dobj
, IconBase
)) return FALSE
;
962 if (chunktype
!= MAKE_ID('i', 'c', 'O', 'n'))
964 if (Write(file
, mempos
, chunksize
) != chunksize
)
974 if (nativeicon
->ni_Extra
.PNG
[1].Offset
> 0)
976 ULONG size
= nativeicon
->ni_Extra
.PNG
[1].Size
;
978 /* 2nd PNG Image attached */
980 if (Write(file
, nativeicon
->ni_Extra
.Data
+ nativeicon
->ni_Extra
.PNG
[1].Offset
, size
) != size
) return FALSE
;
986 /****************************************************************************************/
988 VOID
FreeIconPNG(struct DiskObject
*dobj
, struct IconBase
*IconBase
)
992 /****************************************************************************************/