2 Copyright © 1995-2014, 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/pngdt.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
),
150 MEMF_PUBLIC
, IconBase
);
152 xoff
= ((*width
) - w
)/2;
153 yoff
= ((*height
) - h
)/2;
156 for (y
= 0; y
< *height
; y
++) {
165 for (x
= 0; x
< *width
; x
++, dst
++) {
179 PNG_FreeImage(handle
);
181 D(bug("[%s] PNG datatype can't parse data\n", __func__
));
184 CloseLibrary(PNGBase
);
189 /****************************************************************************************/
191 static void GetChunkInfo(APTR stream
, APTR
*chunkdata
, ULONG
*chunksize
)
193 png_unknown_chunkp chunkp
= stream
;
194 *chunksize
= chunkp
->size
;
195 *chunkdata
= chunkp
->data
;
198 /****************************************************************************************/
200 STATIC BOOL
MakePlanarImage(struct NativeIcon
*icon
, struct Image
**img
, UBYTE
*src
, struct IconBase
*IconBase
)
202 LONG width16
= (icon
->ni_DiskObject
.do_Gadget
.Width
+ 15) & ~15;
203 LONG bpr
= width16
/ 8;
204 LONG planesize
= bpr
* icon
->ni_DiskObject
.do_Gadget
.Height
;
207 ULONG
*s
= (ULONG
*) src
;
209 *img
= (struct Image
*) AllocMemIcon(&icon
->ni_DiskObject
,
210 sizeof(struct Image
) + planesize
* 2, MEMF_PUBLIC
| MEMF_CLEAR
,
215 (*img
)->Width
= icon
->ni_DiskObject
.do_Gadget
.Width
;
216 (*img
)->Height
= icon
->ni_DiskObject
.do_Gadget
.Height
;
218 (*img
)->ImageData
= (UWORD
*) (*img
+ 1);
219 (*img
)->PlanePick
= 3;
221 p1
= (UWORD
*) (*img
)->ImageData
;
222 p2
= p1
+ planesize
/ 2;
224 for (y
= 0; y
< (*img
)->Height
; y
++)
226 ULONG pixelmask
= 0x8000;
230 for (x
= 0; x
< (*img
)->Width
; x
++)
235 if ((pixel
& 0xFF000000) > 0x80000000)
237 pixel
= (((pixel
& 0x00FF0000) >> 16) +
238 ((pixel
& 0x0000FF00) >> 8) +
239 ((pixel
& 0x000000FF)) +
242 if ((pixel
& 0x000000FF) > 0x80)
244 pixel
= (((pixel
& 0x0000FF00) >> 8) + ((pixel
& 0x00FF0000) >> 16) + ((pixel
& 0xFF000000) >> 24) + 127) / 256;
250 plane2dat
|= pixelmask
;
252 else if ((pixel
== 2) || (pixel
== 1))
254 /* Col 3: Amiga Blue */
255 plane1dat
|= pixelmask
;
256 plane2dat
|= pixelmask
;
261 plane1dat
|= pixelmask
;
269 *p1
++ = AROS_WORD2BE(plane1dat
);
270 *p2
++ = AROS_WORD2BE(plane2dat
);
272 plane1dat
= plane2dat
= 0;
278 if (pixelmask
!= 0x8000)
280 *p1
++ = AROS_WORD2BE(plane1dat
);
281 *p2
++ = AROS_WORD2BE(plane2dat
);
285 } /* for(y = 0; y < icon->ni_Height; y++) */
291 /****************************************************************************************/
293 STATIC BOOL
MakePlanarImages(struct NativeIcon
*icon
, struct IconBase
*IconBase
)
295 if (!MakePlanarImage(icon
, (struct Image
**) &icon
->ni_DiskObject
.do_Gadget
.GadgetRender
,
296 (UBYTE
*)icon
->ni_Image
[0].ARGB
, IconBase
))
301 icon
->ni_DiskObject
.do_Gadget
.Flags
|= GFLG_GADGIMAGE
;
303 if (!icon
->ni_Image
[1].ARGB
)
306 if (MakePlanarImage(icon
, (struct Image
**) &icon
->ni_DiskObject
.do_Gadget
.SelectRender
,
307 (UBYTE
*)icon
->ni_Image
[1].ARGB
, IconBase
))
309 icon
->ni_DiskObject
.do_Gadget
.Flags
|= GFLG_GADGHIMAGE
;
315 /****************************************************************************************/
317 BOOL
ReadIconPNG(struct DiskObject
*dobj
, BPTR file
, struct IconBase
*IconBase
)
319 static CONST_STRPTR
const chunknames
[] =
324 APTR chunkpointer
[] =
330 struct NativeIcon
*icon
;
334 icon
= NATIVEICON(dobj
);
336 D(bug("%s: File stream %p\n", __func__
, file
));
338 if (Seek(file
, 0, OFFSET_END
) < 0) return FALSE
;
339 if ((filesize
= Seek(file
, 0, OFFSET_BEGINNING
)) < 0) return FALSE
;
341 D(bug("[%s] Inspecting a %d byte file\n", __func__
, filesize
));
343 /* Need a copy of whole file in memory for icon saving :-\ Because
344 that should save file back as it was, only with modified or new
345 icOn chunk. And it must also work when loading an icon and then
346 saving it using another name. */
348 data
= AllocMemIcon(&icon
->ni_DiskObject
, filesize
, MEMF_PUBLIC
,
353 if (Read(file
, data
, filesize
) != filesize
)
355 D(bug("[%s] Can't read from file\n", __func__
));
359 icon
->ni_Extra
.Data
= data
;
360 icon
->ni_Extra
.Size
= filesize
;
362 icon
->ni_Extra
.PNG
[0].Offset
= 0;
363 icon
->ni_Extra
.PNG
[0].Size
= filesize
;
365 ULONG width
= ~0, height
= ~0;
367 icon
->ni_Image
[0].ARGB
= ReadMemPNG(&icon
->ni_DiskObject
, icon
->ni_Extra
.Data
+ icon
->ni_Extra
.PNG
[0].Offset
, &width
, &height
, chunknames
, chunkpointer
, IconBase
);
368 if (icon
->ni_Image
[0].ARGB
== NULL
) {
369 D(bug("[%s] Can't parse PNG image at 0\n", __func__
));
373 icon
->ni_Face
.Width
= width
;
374 icon
->ni_Face
.Height
= height
;
375 icon
->ni_Face
.Aspect
= ICON_ASPECT_RATIO_UNKNOWN
;
377 #define DO(x) (&x->ni_DiskObject)
379 DO(icon
)->do_Magic
= WB_DISKMAGIC
;
380 DO(icon
)->do_Version
= (WB_DISKVERSION
<< 8) | WB_DISKREVISION
;
381 DO(icon
)->do_Type
= 0; /* Invalid */
382 DO(icon
)->do_CurrentX
= NO_ICON_POSITION
;
383 DO(icon
)->do_CurrentY
= NO_ICON_POSITION
;
384 DO(icon
)->do_Gadget
.Width
= width
;
385 DO(icon
)->do_Gadget
.Height
= height
;
386 DO(icon
)->do_StackSize
= AROS_STACKSIZE
;
393 ULONG ttarraysize
= 0;
396 GetChunkInfo(chunkpointer
[0], (APTR
*)&chunkdata
, &chunksize
);
398 while(chunksize
>= 4)
402 BOOL need_drawerdata
= FALSE
;
404 attr
= (chunkdata
[0] << 24) | (chunkdata
[1] << 16) | (chunkdata
[2] << 8) | chunkdata
[3];
412 case ATTR_DRAWERWIDTH
:
413 case ATTR_DRAWERHEIGHT
:
414 case ATTR_DRAWERFLAGS
:
415 case ATTR_DRAWERFLAGS2
:
416 case ATTR_DRAWERFLAGS3
:
418 case ATTR_VIEWMODES2
:
419 case ATTR_DD_CURRENTX
:
420 case ATTR_DD_CURRENTY
:
421 need_drawerdata
= TRUE
;
431 val
= (chunkdata
[0] << 24) | (chunkdata
[1] << 16) | (chunkdata
[2] << 8) | chunkdata
[3];
441 /* case ATTR_UNKNOWN: */
442 case ATTR_DEFAULTTOOL
:
444 val
= (IPTR
)chunkdata
;
445 chunksize
-= strlen((char *)val
) + 1;
446 chunkdata
+= strlen((char *)val
) + 1;
455 /* Unknown attribute/tag. Impossible to handle correctly
456 if we don't know if it's a string attribute or not. */
464 if (need_drawerdata
&& !(DO(icon
)->do_DrawerData
))
466 DO(icon
)->do_DrawerData
=
467 AllocMemIcon(DO(icon
), sizeof(struct DrawerData
),
468 MEMF_PUBLIC
| MEMF_CLEAR
, IconBase
);
469 if (!(DO(icon
)->do_DrawerData
))
475 DO(icon
)->do_DrawerData
->dd_NewWindow
.LeftEdge
= 20;
476 DO(icon
)->do_DrawerData
->dd_NewWindow
.TopEdge
= 20;
477 DO(icon
)->do_DrawerData
->dd_NewWindow
.Width
= 300;
478 DO(icon
)->do_DrawerData
->dd_NewWindow
.Height
= 200;
479 DO(icon
)->do_Gadget
.UserData
= (APTR
)1; /* See DupDiskObject logic */
485 DO(icon
)->do_CurrentX
= val
;
489 DO(icon
)->do_CurrentY
= val
;
493 DO(icon
)->do_StackSize
= val
;
497 DO(icon
)->do_DrawerData
->dd_NewWindow
.LeftEdge
= (WORD
)val
;
501 DO(icon
)->do_DrawerData
->dd_NewWindow
.TopEdge
= (WORD
)val
;
504 case ATTR_DRAWERWIDTH
:
505 DO(icon
)->do_DrawerData
->dd_NewWindow
.Width
= (WORD
)val
;
508 case ATTR_DRAWERHEIGHT
:
509 DO(icon
)->do_DrawerData
->dd_NewWindow
.Height
= (WORD
)val
;
512 case ATTR_DRAWERFLAGS
:
513 DO(icon
)->do_DrawerData
->dd_Flags
= flags_to_ddflags(val
);
514 DO(icon
)->do_DrawerData
->dd_ViewModes
= flags_to_ddviewmodes(val
);
517 case ATTR_DEFAULTTOOL
:
518 DO(icon
)->do_DefaultTool
=
519 AllocMemIcon(DO(icon
), strlen((char *)val
) + 1,
520 MEMF_PUBLIC
| MEMF_CLEAR
, IconBase
);
521 if (DO(icon
)->do_DefaultTool
)
523 strcpy(DO(icon
)->do_DefaultTool
, (char *)val
);
531 NATIVEICON(icon
)->ni_Frameless
= val
? TRUE
: FALSE
;
537 D(bug("[Icon.PNG] Got tooltype number %u : %s\n", ttnum
- 1, val
));
539 if (ttarraysize
< ttnum
+ 1)
541 STRPTR
*old_tooltypes
= DO(icon
)->do_ToolTypes
;
545 DO(icon
)->do_ToolTypes
=
546 AllocMemIcon(DO(icon
),
547 ttarraysize
* sizeof(APTR
),
548 MEMF_PUBLIC
| MEMF_CLEAR
, IconBase
);
549 if (DO(icon
)->do_ToolTypes
)
551 D(bug("[Icon.PNG] Allocated array of %u entries @ 0x%p (old 0x%p)\n", ttarraysize
, DO(icon
)->do_ToolTypes
, old_tooltypes
));
554 CopyMemQuick(old_tooltypes
, DO(icon
)->do_ToolTypes
, (ttnum
- 1) * sizeof(APTR
));
556 /* TODO: Free old array */
567 DO(icon
)->do_ToolTypes
[ttnum
- 1] =
568 AllocMemIcon(DO(icon
), strlen((char *)val
) + 1,
569 MEMF_PUBLIC
| MEMF_CLEAR
, IconBase
);
570 if (DO(icon
)->do_ToolTypes
[ttnum
- 1])
572 strcpy(DO(icon
)->do_ToolTypes
[ttnum
- 1], (char *)val
);
584 } /* while(chunksize >= 4) */
588 D(bug("=== Failure during icOn chunk parsing ===\n"));
589 FreeIconPNG(&icon
->ni_DiskObject
, IconBase
);
594 } /* if (chunkpointer[0]) */
599 * FIXME: Someone killed PNG Icon do_Type detection here which causes
600 * following lines to always free DrawerData even when it
601 * shouldn't be freed (only possible to know if do_Type is
602 * known). So for now following lines disabled and DrawerData
603 * is always kept (even when it shouldn't).
607 if (icon
->ni_DiskObject
.do_DrawerData
&&
608 (icon
->ni_DiskObject
.do_Type
!= WBDISK
) &&
609 (icon
->ni_DiskObject
.do_Type
!= WBDRAWER
) &&
610 (icon
->ni_DiskObject
.do_Type
!= WBGARBAGE
))
612 FreePooled(pool
, icon
->ni_DiskObject
.do_DrawerData
, sizeof(struct DrawerData
));
613 icon
->ni_DiskObject
.do_DrawerData
= NULL
;
619 /* Look for a possible 2nd PNG image attached onto the first one */
621 UBYTE
*filepos
= icon
->ni_Extra
.Data
+ icon
->ni_Extra
.PNG
[0].Offset
+ 8;
624 while(!done
&& filepos
< ((UBYTE
*)icon
->ni_Extra
.Data
+ icon
->ni_Extra
.Size
))
626 ULONG chunksize
= (filepos
[0] << 24) | (filepos
[1] << 16) |
627 (filepos
[2] << 8) | filepos
[3];
628 ULONG chunktype
= (filepos
[4] << 24) | (filepos
[5] << 16) |
629 (filepos
[6] << 8) | filepos
[7];
633 if (chunktype
== MAKE_ID('I', 'E', 'N', 'D'))
638 filepos
+= chunksize
;
641 if (filepos
+ 8 < (UBYTE
*)icon
->ni_Extra
.Data
+ icon
->ni_Extra
.Size
)
643 ULONG offset
= filepos
- (UBYTE
*)icon
->ni_Extra
.Data
;
645 icon
->ni_Extra
.PNG
[0].Size
= offset
;
646 icon
->ni_Extra
.PNG
[1].Offset
= offset
;
647 icon
->ni_Extra
.PNG
[1].Size
= (filesize
- icon
->ni_Extra
.PNG
[0].Size
);
648 icon
->ni_Image
[1].ARGB
= ReadMemPNG(&icon
->ni_DiskObject
, filepos
, &icon
->ni_Face
.Width
, &icon
->ni_Face
.Height
, NULL
, NULL
, IconBase
);
653 /* If there's no image for selected-state, generate one */
654 if (!icon
->ni_Image
[1].ARGB
)
656 ULONG size
= icon
->ni_Face
.Width
* icon
->ni_Face
.Height
;
658 if ((icon
->ni_Image
[1].ARGB
=
659 AllocMemIcon(&icon
->ni_DiskObject
, size
* sizeof(ULONG
),
660 MEMF_PUBLIC
, IconBase
)))
662 ULONG
*src
= (ULONG
*)icon
->ni_Image
[0].ARGB
;
663 ULONG
*dst
= (ULONG
*)icon
->ni_Image
[1].ARGB
;
667 ULONG pixel
= *src
++;
669 /* Effects like in changetoselectediconcolor.c */
671 #if EFFECT == EFFECT_LIGHTEN
673 pixel
= (pixel
& 0xFF000000) +
674 ((pixel
>> 1) & 0x007F7F7F) +
677 pixel
= (pixel
& 0x000000FF) +
678 ((pixel
>> 1) & 0x7F7F7F00) +
681 #elif EFFECT == EFFECT_TINT_BLUE
683 pixel
= (pixel
& 0xFF000000) +
684 ((pixel
>> 1) & 0x007F7F7F) +
687 pixel
= (pixel
& 0x000000FF) +
688 ((pixel
>> 1) & 0x7F7F7F00) +
692 #elif EFFECT == EFFECT_XOR
694 pixel
= (pixel
& 0xFF000000) +
695 ((pixel
& 0x00FFFFFF) ^ 0x00FFFFFF);
697 pixel
= (pixel
& 0x000000FF) +
698 ((pixel
& 0xFFFFFF00) ^ 0xFFFFFF00);
707 * Support old-style AROS PNG icons. 3rd party applications
708 * will still be using them.
711 if (!MakePlanarImages(icon
, IconBase
))
713 D(bug("Planar image creation failed\n"));
714 FreeIconPNG(&icon
->ni_DiskObject
, IconBase
);
722 /****************************************************************************************/
724 STATIC VOID
MakeCRCTable(struct IconBase
*IconBase
)
729 IconBase
->ib_CRCTable
= AllocMem(256 * sizeof(ULONG
), MEMF_ANY
);
730 if (!IconBase
->ib_CRCTable
)
732 for (n
= 0; n
< 256; n
++)
734 c
= (unsigned long) n
;
735 for (k
= 0; k
< 8; k
++)
738 c
= 0xedb88320L
^ (c
>> 1);
742 IconBase
->ib_CRCTable
[n
] = c
;
746 /****************************************************************************************/
748 STATIC ULONG
UpdateCRC(ULONG crc
, UBYTE
*buf
, ULONG len
, struct IconBase
*IconBase
)
753 for (n
= 0; n
< len
; n
++)
755 c
= IconBase
->ib_CRCTable
[(c
^ buf
[n
]) & 0xff] ^ (c
>> 8);
762 /****************************************************************************************/
764 STATIC BOOL
WriteIconAttr(BPTR file
, ULONG id
, ULONG val
, ULONG
*chunksize
,
765 ULONG
*crc
, struct IconBase
*IconBase
)
778 if (Write(file
, buf
, 8) != 8) return FALSE
;
781 *crc
= UpdateCRC(*crc
, buf
, 8, IconBase
);
785 /****************************************************************************************/
787 STATIC BOOL
WriteIconStrAttr(BPTR file
, ULONG id
, char *val
, ULONG
*chunksize
,
788 ULONG
*crc
, struct IconBase
*IconBase
)
791 ULONG len
= strlen(val
) + 1;
798 if (Write(file
, buf
, 4) != 4) return FALSE
;
799 *crc
= UpdateCRC(*crc
, buf
, 4, IconBase
);
801 if (Write(file
, val
, len
) != len
) return FALSE
;
802 *crc
= UpdateCRC(*crc
, val
, len
, IconBase
);
804 *chunksize
+= 4 + len
;
809 /****************************************************************************************/
811 STATIC BOOL
WriteIconChunk(BPTR file
, struct DiskObject
*dobj
, struct IconBase
*IconBase
)
813 ULONG crc
= 0xFFFFFFFF;
815 ULONG sizeseek
= Seek(file
, 0, OFFSET_CURRENT
);
816 UBYTE buf
[] = {0x12, 0x34, 0x56, 0x78, 'i', 'c', 'O', 'n'};
818 if (sizeseek
< 0) return FALSE
;
820 /* Write Chunk size + chunk type */
821 if (Write(file
, buf
, 8) != 8) return FALSE
;
823 crc
= UpdateCRC(crc
, buf
+ 4, 4, IconBase
); /* chunksize is excluded from CRC */
825 /* Write Frameless */
826 if (!WriteIconAttr(file
, ATTR_FRAMELESS
, NATIVEICON(dobj
)->ni_Frameless
, &chunksize
, &crc
, IconBase
))
831 /* Write Stack Size */
833 if (!WriteIconAttr(file
, ATTR_STACKSIZE
, dobj
->do_StackSize
, &chunksize
, &crc
, IconBase
))
838 /* Write Icon X Position */
839 if (dobj
->do_CurrentX
!= NO_ICON_POSITION
)
841 if (!WriteIconAttr(file
, ATTR_ICONX
, dobj
->do_CurrentX
, &chunksize
, &crc
, IconBase
))
847 /* Write Icon Y Position */
848 if (dobj
->do_CurrentY
!= NO_ICON_POSITION
)
850 if (!WriteIconAttr(file
, ATTR_ICONY
, dobj
->do_CurrentY
, &chunksize
, &crc
, IconBase
))
856 if (dobj
->do_DrawerData
)
858 if (!WriteIconAttr(file
, ATTR_DRAWERX
, dobj
->do_DrawerData
->dd_NewWindow
.LeftEdge
,
859 &chunksize
, &crc
, IconBase
))
864 if (!WriteIconAttr(file
, ATTR_DRAWERY
, dobj
->do_DrawerData
->dd_NewWindow
.TopEdge
,
865 &chunksize
, &crc
, IconBase
))
870 if (!WriteIconAttr(file
, ATTR_DRAWERWIDTH
, dobj
->do_DrawerData
->dd_NewWindow
.Width
,
871 &chunksize
, &crc
, IconBase
))
876 if (!WriteIconAttr(file
, ATTR_DRAWERHEIGHT
, dobj
->do_DrawerData
->dd_NewWindow
.Height
,
877 &chunksize
, &crc
, IconBase
))
882 if (!WriteIconAttr(file
, ATTR_DRAWERFLAGS
, dd_to_flags(dobj
),
883 &chunksize
, &crc
, IconBase
))
888 } /* if (dobj->do_DrawerData) */
890 if (dobj
->do_DefaultTool
)
892 if (!WriteIconStrAttr(file
, ATTR_DEFAULTTOOL
, dobj
->do_DefaultTool
,
893 &chunksize
, &crc
, IconBase
))
900 if (dobj
->do_ToolTypes
)
902 STRPTR
*tt
= (STRPTR
*)dobj
->do_ToolTypes
;
904 for(tt
= (STRPTR
*)dobj
->do_ToolTypes
; *tt
; tt
++)
906 if (!WriteIconStrAttr(file
, ATTR_TOOLTYPE
, *tt
, &chunksize
,
921 if (Write(file
, buf
, 4) != 4) return FALSE
;
923 /* Trim any garbage at end of file */
924 if (SetFileSize(file
, 0, OFFSET_CURRENT
) < 0) return FALSE
;
926 /* Write chunk's size */
927 if (Seek(file
, sizeseek
, OFFSET_BEGINNING
) < 0) return FALSE
;
929 buf
[0] = chunksize
>> 24;
930 buf
[1] = chunksize
>> 16;
931 buf
[2] = chunksize
>> 8;
933 if (Write(file
, buf
, 4) != 4) return FALSE
;
935 if (Seek(file
, 0, OFFSET_END
) < 0) return FALSE
;
940 /****************************************************************************************/
942 BOOL
WriteIconPNG(BPTR file
, struct DiskObject
*dobj
, struct IconBase
*IconBase
)
944 struct NativeIcon
*nativeicon
= NATIVEICON(dobj
);
945 UBYTE
*mempos
= nativeicon
->ni_Extra
.Data
+ nativeicon
->ni_Extra
.PNG
[0].Offset
;
948 D(bug("%s: ni=%p, ni->ni_Extra.Data = %p\n", __func__
, nativeicon
, nativeicon
->ni_Extra
.Data
));
949 if (nativeicon
->ni_Extra
.Data
== NULL
)
952 ObtainSemaphore(&IconBase
->iconlistlock
);
953 if (!IconBase
->ib_CRCTable
)
954 MakeCRCTable(IconBase
);
955 ReleaseSemaphore(&IconBase
->iconlistlock
);
956 if (!IconBase
->ib_CRCTable
)
959 /* Write PNG header */
960 if (Write(file
, mempos
, 8) != 8) return FALSE
;
966 ULONG chunksize
= (mempos
[0] << 24) | (mempos
[1] << 16) |
967 (mempos
[2] << 8) | mempos
[3];
968 ULONG chunktype
= (mempos
[4] << 24) | (mempos
[5] << 16) |
969 (mempos
[6] << 8) | mempos
[7];
973 if (chunktype
== MAKE_ID('I', 'E', 'N', 'D'))
975 if (!WriteIconChunk(file
, dobj
, IconBase
)) return FALSE
;
979 if (chunktype
!= MAKE_ID('i', 'c', 'O', 'n'))
981 if (Write(file
, mempos
, chunksize
) != chunksize
)
991 if (nativeicon
->ni_Extra
.PNG
[1].Offset
> 0)
993 ULONG size
= nativeicon
->ni_Extra
.PNG
[1].Size
;
995 /* 2nd PNG Image attached */
997 if (Write(file
, nativeicon
->ni_Extra
.Data
+ nativeicon
->ni_Extra
.PNG
[1].Offset
, size
) != size
) return FALSE
;
1003 /****************************************************************************************/
1005 VOID
FreeIconPNG(struct DiskObject
*dobj
, struct IconBase
*IconBase
)
1009 /****************************************************************************************/