Aros/Developer/Docs/Libraries/Icon
Contents |
[edit] Introduction
- OLD - OS1.x (4 col) - OS 2/3 (4 col)
- NEW - NewIcons (size 36x40 x 32 col) - GlowIcons (size 46x46 x 256 col)
- AROS - 24bit png
- SVG - Haiku HVIF has a reduced format.
Wanderer does not read anything directly itself - it relies on icon.library for "file" processing. The loading of PNG Icons does not happen using datatype *system*. It's done through libpng functions. To avoid that both icon.library and png.datatype have libpng statically linked in (double file/mem usage), it's done only for one of them: png.datatype. The png.datatype exposes some extra functions PNG_#?. See workbench/classes/datatypes/png/png.conf and directaccess.c in same directory.
In workbench/libs/icon/diskobjPNGio.c you can see how the PNG_ functions are used to read the PNG icon. In there you'll also see a function MakePlanarImage(). It's one function which will certainly slow down things a bit. What is does (in very unoptimized way) is to create a very simple realtime remapped planar version of the PNG image(s) to be used on low color (LUT) screens.
In libpng 1.5, png_ptr and info_ptr are opaque data types, and can't be dereferenced. Replace that code with the following (which works in both libpng 1.2 and 1.5) ... Write(png_get_io_ptr(png_ptr), data, length); ... The reason is that in a (near!) future version of libpng, the details of the png_ptr and info_ptr datastructures may change dramatically. Chnages are trivial, just grep for the old field name (ie 'io_ptr') in png.h, and use the appropriate accessor function.
merge icon35 and png icons
- png data would live in the IFF stream of the icon35 format (IFF type 'PNG ')
- 4 color and icon35 image formats would be precomputed by the ilbmtoicon tool
- AOS should be able to read and understand this format
Do OS4 and MorphOS use the same type of PNG icons as us, or a different variation? They use the same format (which PowerIcons originated), which is a plain PNG file named "*.info" with some extra PNG hunks in it to hold some icon data. (PNG is like IFF in that way).
Just to be clear, I am *not* planning on removing 'plain PNG' support. I am extending the Icon 3.5 to include PNG data, so that (a) our generated ICONs can work on any Amiga system, including OS 1.x to 3.x, and (b) my poor 68000 can choose a planar image from the icon file instead of spending approx 7 seconds per icon converting from ARGB to 4-color planar.
Existing PNG support will *not* be changed - so we should continue to be able to enjoy AmigaOS4 and Morphos icons sets on the faster processors.
[edit] ANSI-C(++) and shell-only applications
On AROS, you have your normal entry point as main(int argc, char **argv).
If argc == 0, then argv actually points to a struct WBStartup.
If argc > 0, then the program was started from CLI.
However, programs run from CLI *MUST* call Permit() for each Forbid() since the final 'rts' drops back to shell, and does not terminate the process.
Semaphores should be used when possible. Forbid()/Permit() should only be used when there is no alternative. Semaphores can be very useful for things like access to memory pools, lists that could be modified by other threads, etc. etc.
Some programs use the technique of starting a new process and clearing cli_Module in order to detach from the shell they are run from. At least for FileX (see contrib/aminet/disk/moni/filex/main.c), this doesn't seem to work anymore. FileX only works if the SYNC argument is used to disable this behaviour.
Does the standard startup code or shell support detaching like this? Perhaps the seglist is being unloaded regardless of the value placed in cli_Module.
Would it be feasible to keep libraries open at exit if cli_Module has been cleared by the program? And could they then be closed when the detached process exits? Not really because it wouldn't fix more common "split segment list" way of detaching.
How does that differ from what FileX does? :-| I presume the similarity of the SegmentSplit() function name is misleading. Yeah, FileX does not do any segment split tricks (perhaps it originally did?), it only clears cli_Module. "Standard" segment list split is to have 2 (or more) segments, code in first segment unlinks following segment(s) from single linked segment list -> only first segment is freed by dos.
Because IMHO we should be source-compatible with AmigaOS software wherever possible. There will presumably be other software being ported to AROS in future that uses similar techniques to detach, and it would be nice if they didn't all have to be manually patched. I agree up to a point but if supporting an old undocumented hack means introducing putting hacks in other parts of the code I would like to make an exception.
It is aroscbase that is set to NULL (I guess it is also freed) when original process exists. Which is of course still in use by detached process.. Ouch. I guess FileX doesn't use detach.o? It should to avoid such problems.
It implies to include aros/detach.h and to not link against the standard startup module but against detach.o as Fabio just said. It is done in the mmakefile.src by detach=yes assertion. One can even choose where the detachment has to occur by using the Detach() function.
AmigaOS libnix opens own console only for libc I/O. It does not reasign default dos.library streams to it. In other words: when the program is started from CLI, libc I/O (printf(), write(), stdin, stdout, etc) is directed into dos.library default streams. When program is started from Workbench, libc opens own window for own I/O, but does not touch dos.library streams. As a consequence, when started from WB, printf() will send a string to __stdiowin, but Printf() will send it to NIL:.
Our startup code just goes deeper and manipulates dos.library streams. This can not be considered a bug IMHO. It's more likely a flaw in original dos.library's implementation of arguments passing. It can be worked around in AROS dos.library. However if this code is executed on AmigaOS 3.1, it will still have this problem. I think we should not downgrade our startup code to support this behavior on AmigaOS. It's clearly a design flaw.
[edit] From Wanderer
start: wbmsg = NULL; task = FindTask(NULL) if (task->pr_CLI == 0 ) { WaitPort(&task->pr_MsgPort); wbmsg = GetMsg(&task->pr_MsgPort); } ; your code here if ( wbmsg != NULL ) { Forbid(); ReplyMsg(wbmsg); } return return_code;
Notes
That final Forbid() guarantees the Workbench don't have a change to UnLoadSeg() the seglist of the program while the program is still executes.
If there is no Forbid(), the ReplyMsg() results in task scheduling, and Workbench get change to run. Workbench UnLoadSeg() the seglist, and the last few instructions are executed on unallocated memory. This will lead into crashes.
There is no need for final Permit(), since the process will RemTask(NULL) itself eventually (default Task EndPC), and this completely removes the process anyway.
{ struct WBStartup *wbmsg; BPTR win; if (argc != 0) { Printf ("This program cannot be run in DOS mode :-)\n"); return (RETURN_ERROR); } wbmsg = (struct WBStartup *)argv; if (win = Open ("con:0/0/640/400/WB Icon/CLOSE/WAIT",MODE_NEWFILE)) { char buffer[256]; long i; NameFromLock (wbmsg->sm_ArgList->wa_Lock,buffer,256); AddPart (buffer,wbmsg->sm_ArgList->wa_Name,256); FPrintf (win,"Program name: <%s>\n",buffer); for (i = 1; i < wbmsg->sm_NumArgs; i++) { NameFromLock (wbmsg->sm_ArgList[i].wa_Lock,buffer,256); AddPart (buffer,wbmsg->sm_ArgList[i].wa_Name,256); FPrintf (win,"Argument #%ld: <%s>\n",i,buffer); } Close (win); } return (RETURN_OK); }
[edit] Tooltype
from http://utilitybase.com/forum/index.php?action=vthread&forum=2&topic=1252
Be very careful with modifying the tooltypeslist in an icon.
- Read in an icon (Icon->GetdiskObject())
- Build a new tooltypeslist
- Copy the address of the current tooltypelist to a safe place
- Copy the address of the NEW tooltypeslist to the icon
- Rewrite the icon (IIcon->PutDiskObject())
- Copy the address of the old tooltypeslist from the safe place BACK into the icon
- Free the diskobject (IIcon->FreeDiskObject())
Um, 6 and 7 are not actually necessary. icon.library keeps track of all the data associated with a loaded icon through a mechanism attached to the 'struct DiskObject' itself, in the private undocumented part of the structure. It does not follow the pointers or assume that they point somewhere meaningful.
In essence, this means that you can modify every bit of information in the documented portion of the 'struct DiskObject' without ill effects. But you have to be careful that the information is in itself consistent if you want to write it back to disk. While icon.library does perform some sanity checking, especially icon.library V44 and beyond, there is only so much you can do.
[edit] LayoutIcon
Currently, LayoutIcon is unimplemented, and an idea that could save me a lot of RAM for PNG images, when they are rendered on low-color screens. The idea is to use LayoutIcon() to render the icon into the Screen's bitmap layout, and use that as the gadget imagery for the icon, and FreeMem() the PNG or other high-color icon imagery.
This is similar to how AOS does things, but with one trick - I 'remember' what image format (and offset and size in the .icon file) was originally there, and when PutDiskObject() is called I carefully avoid scribbling on the image data, preserving the original image.
But you need update the images, when a user change the screen depth. In AFA layoutIcon is too unimplement, i add some times before a jump in debugger command when function is called to test.if a program use this function.I see that workbench not use this function.also other programs do not use. But a speedup of AROS iconlib and much less memory usage is possible, when you make a cache, so that all default Icons only load once.getdiskobject give then only a pointer to existing default icon.
The problem on AROS is, it load everytime the icon in and use new memory. For example if you show 100 jpg files, then 100* the icon def_jpg.info is load.so 100* memory usage and load time usage. As wanderer loads always all icons, even if only icon view is select.
[edit] Datatype Detection
The icon.library uses the datatype descriptors from sys:devs/datatypes to identify the file type. Then a default icon def_NAME.info is used for a file with a type of NAME. The AROS build-system uses the tool createdtdesc to create datatype descriptors from simple text files.
[edit] Bugs
After icons can be moved, it will be good to be able to snapshot their position.
And the position of the window in the drawer icon. But beware that IIRC there is a bug/unimplemented feature somewhere (in icon.library?) that prevents it to store properly DrawerData struct (dd_Flags and dd_NewWindow members) in all cases. So Wanderer suffers of the problem too currently, and you can't both save the "View All Files" state _and_ snapshot the window position of a drawer.
[edit] Reference
struct DiskObject *NewDiskObject(ULONG type) struct DiskObject *GetIconTagList(CONST_STRPTR name, const struct TagItem *tags) struct DiskObject *GetDiskObject(CONST_STRPTR name) BOOL PutDiskObject(CONST_STRPTR name, struct DiskObject *icon) void FreeDiskObject(struct DiskObject *diskobj) BOOL AddFreeList(struct FreeList *freelist, APTR mem, unsigned long size) void FreeFreeList(struct FreeList *freelist) UBYTE *FindToolType(const STRPTR *toolTypeArray, const STRPTR typeName) BOOL MatchToolValue(UBYTE *typeString, UBYTE *value) UBYTE *BumpRevision(UBYTE *newname, UBYTE *oldname) struct DiskObject *GetDefDiskObject(LONG type) BOOL PutDefDiskObject(struct DiskObject *icon) struct DiskObject *GetDiskObjectNew(CONST_STRPTR name) BOOL DeleteDiskObject(UBYTE *name) struct DiskObject *DupDiskObjectA(struct DiskObject *icon, struct TagItem *tags) ULONG IconControlA(struct DiskObject *icon, struct TagItem *tags) void DrawIconStateA(struct RastPort *rp, struct DiskObject *icon, STRPTR label, LONG leftEdge, LONG topEdge, ULONG state, struct TagItem *tags) BOOL GetIconRectangleA(struct RastPort *rp, struct DiskObject *icon, STRPTR label, struct Rectangle *rectangle, struct TagItem *tags) BOOL PutIconTagList(CONST_STRPTR name, struct DiskObject *icon, struct TagItem *tags) BOOL LayoutIconA(struct DiskObject *icon, struct Screen *screen, struct TagItem *tags) void ChangeToSelectedIconColor(struct ColorRegister *cr)