ELFIconSpec

Differences between revisions 2 and 3
Revision 2 as of 2008-03-27 22:01:14
Size: 5629
Editor: MP1800-193-ResNet
Comment:
Revision 3 as of 2008-03-27 22:54:04
Size: 10222
Editor: MP1800-193-ResNet
Comment:
Deletions are marked like this. Additions are marked like this.
Line 6: Line 6:

In addition, provided that this technology is adopted by different segments of the development community (GNOME, automake, and developers) then icon handling will no-longer require any action for packagers. GNOME could easily check the ELF binary for an icon, so no configuration file would be necessary for the appropriate icon to appear. By storing a GUID in the binary it would also be possible to theme icons for all system applications (over-riding the icon stored in the binary) by using the GUID as a unique id for matching the application with an icon stored in a theme.
Line 23: Line 25:
 * int libr_clear(libr_file *handle, char *resourcename); ===== Resource API =====
For generic resource handling the following API should be used:

* '''int libr_clear(libr_file *handle, char *resourcename);'''
Line 26: Line 31:
 * void libr_close(libr_file *handle);  * '''void libr_close(libr_file *handle);'''
Line 29: Line 34:
 * char *libr_list(libr_file *handle, unsigned int resourceid);  * '''char *libr_list(libr_file *handle, unsigned int resourceid);'''
Line 32: Line 37:
 * libr_file *libr_open(char *filename, libr_access_t access);
Open a file for the specified access (LIBR_READ, LIBR_WRITE, LIBR_READ_WRITE), the valid operations for the returned handle will be restricted based upon the requested access. Returns NULL on failure.
 * '''libr_file *libr_open(char *filename, libr_access_t access);'''
Open a file for the specified access (LIBR_READ, LIBR_WRITE, LIBR_READ_WRITE), the valid operations for the returned handle will be restricted based upon the requested access. Pass a NULL pointer to the filename parameter to access the calling binary, for obvious reasons the calling binary may only request LIBR_READ access.  Returns NULL on failure.
Line 35: Line 40:
 * int libr_read(libr_file *handle, char *resourcename, char *buffer);  * '''int libr_read(libr_file *handle, char *resourcename, char *buffer);'''
Line 38: Line 43:
 * unsigned int libr_resouces(libr_file *handle);  * '''unsigned int libr_resouces(libr_file *handle);'''
Line 41: Line 46:
 * int libr_size(libr_file *handle, char *resourcename, int *size);  * '''int libr_size(libr_file *handle, char *resourcename, int *size);'''
Line 44: Line 49:
 * int libr_write(libr_file *handle, char *resourcename, char *buffer, size_t size, libr_type_t *type, int overwrite);  * '''int libr_write(libr_file *handle, char *resourcename, char *buffer, size_t size, libr_type_t *type, int overwrite);'''
Line 46: Line 51:

===== Icon API =====
In order to allow applications to easily access their own icon for display, an icon-specific API is exported. For accessing icon data the following API should be used:

 * '''int libr_icon_close(libr_icon *icon);'''
Release the icon resource allocated by a call to libr_icon_geticon_byid(), libr_icon_geticon_byname(), libr_icon_geticon_bysize(), libr_icon_newicon_byfile(), or libr_icon_newicon_frombuffer().

 * '''libr_icon *libr_icon_geticon_byid(libr_file *handle, unsigned int iconid);'''
Return a resource handle to an icon stored in an ELF binary that is of an id less than the value returned by libr_icon_num(). Returns NULL on failure.

 * '''libr_icon *libr_icon_geticon_byname(libr_file *handle, char *iconname);'''
Return a resource handle to an icon stored in an ELF binary that is named exactly "iconname". Returns NULL on failure.

 * '''libr_icon *libr_icon_geticon_bysize(libr_file *handle, int iconsize);'''
Return a resource handle to an icon stored in an ELF binary that is closest to the size "iconsize", use size '0' to request an SVG icon. Returns NULL on failure.

 * '''int libr_icon_getguid(libr_file *handle, char *guid);'''
Returns the icon GUID in hex notation (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX), requires a 37 character buffer (36 data characters and a NULL terminator). Returns 1 (true) on success, 0 (false) on failure.

 * '''libr_icon *libr_icon_newicon_frombuffer(libr_icontype_t type, int iconsize, char *buffer, size_t size);'''
Create an icon handle to represent an icon file stored in the buffer "buffer". The file should be the same type as specified by "type" (LIBR_SVG, LIBR_PNG), where "iconsize" is ignored for SVG icons. Returns NULL on failure.

 * '''libr_icon *libr_icon_newicon_byfile(libr_icontype_t type, int iconsize, char *iconfile);'''
Create an icon handle to represent an icon file stored on disk. The file should be the same type as specified by "type" (LIBR_SVG, LIBR_PNG), where "iconsize" is ignored for SVG icons. Returns NULL on failure.

 * '''unsigned int libr_icon_num(libr_file *handle);'''
Returns the number of icons contained within the ELF binary. Returns 0 (false) on failure or when there are no icons.

 * '''int libr_icon_read(libr_icon *icon, char *buffer);'''
Stores the uncompressed buffer of the icon represented by the resource handle "icon" in "buffer". "buffer" must contain enough memory to hold the entire icon, use libr_icon_size() to discover how much memory is needed. Returns 1 (true) on success, 0 (false) on failure.

 * '''int libr_icon_size(libr_icon *icon, int *size);'''
Returns the uncompressed size of the icon represented by the resource handle "icon" in "size". Returns 1 (true) on success, 0 (false) on failure.

 * '''int libr_icon_save(libr_icon *icon, char *filename);'''
Save the icon represented by the resource handle "icon" to a file. Returns 1 (true) on success, 0 (false) on failure.

 * '''int libr_icon_setguid(libr_file *handle, char *guid);'''
Sets the icon GUID, the string should be in hex notation (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX) and contain 37 characters (36 data characters and a NULL terminator). Returns 1 (true) on success, 0 (false) on failure.

 * '''int libr_icon_write(libr_file *handle, libr_icon *icon, char *iconname, int overwrite);'''
Add the icon represented by the icon handle "icon" to the ELF binary as the icon resource named "iconname". The file should not exist unless overwrite is set to 1 (true). The ELF binary must have a GUID set by libr_icon_setguid() before calling this function. Returns 1 (true) on success, 0 (false) on failure.
Line 66: Line 113:
The "icon guid" is meant to be used by distributions to assign an icon to an application and keep that icon consistent between all ways to access the application, this field IS required even if you are not a distributor. The number of fields should be used to indicate the type and number of different icons stored in the ELF file, these fields should follow the header and should be structured as follows (S* is the entry size): The "icon guid" is meant to be used by distributions to assign an icon to an application and keep that icon consistent between all ways to access the application, this field IS required even if you are not a distributor and may be generated using the application "uuid. The number of fields should be used to indicate the type and number of different icons stored in the ELF file, these fields should follow the header and should be structured as follows (S* is the entry size):

Summary

As a seasoned user of the terminal, the issue of an application having an icon embedded into it is something that I didn't even notice until I started converting others to Ubuntu. I propose adding a non-obtrusive section to ELF applications that provides this functionality and can be accessed through GNOME's thumbnail capability. This idea is meant to compliment the icons provided through the package manager and take advantage of the extensibility of the ELF specification.

Many users expect applications that they've downloaded to have recognizable icons, this icon is usually something familiar from visiting the website for the program. A good example of an application that's not already included in the Ubuntu repo is "songbird", which has a large egg right next to the download link and for its Windows icon.

In addition, provided that this technology is adopted by different segments of the development community (GNOME, automake, and developers) then icon handling will no-longer require any action for packagers. GNOME could easily check the ELF binary for an icon, so no configuration file would be necessary for the appropriate icon to appear. By storing a GUID in the binary it would also be possible to theme icons for all system applications (over-riding the icon stored in the binary) by using the GUID as a unique id for matching the application with an icon stored in a theme.

For a technology demo and screenshots visit [http://www.compholio.com/elficon/].

To discuss this topic please visit [http://brainstorm.ubuntu.com/idea/5744/].

Preliminary Spec

A library to handle resource files should be used in order to store images in a standardized way, this will also allow applications to store other data (such as graphics and libglade XML files). Handling the icon resource in this way results in the following architecture:

http://www.compholio.com/elficon/architecture.png

libr (sorry, librc was taken)

A proposed new library for handling adding, removing, and retrieving simple resource files from ELF binaries.

API Spec

Resource API

For generic resource handling the following API should be used:

  • int libr_clear(libr_file *handle, char *resourcename);

Remove the resource named "resourcename" from the ELF binary, the resource must exist. Returns 1 (true) on success, 0 (false) on failure.

  • void libr_close(libr_file *handle);

Close the specified file handle.

  • char *libr_list(libr_file *handle, unsigned int resourceid);

Obtain the name of a resource by id in the ELF binary, use libr_resources() to obtain the number of total resources (only libr-compatible resources are returned). Returns NULL on failure.

  • libr_file *libr_open(char *filename, libr_access_t access);

Open a file for the specified access (LIBR_READ, LIBR_WRITE, LIBR_READ_WRITE), the valid operations for the returned handle will be restricted based upon the requested access. Pass a NULL pointer to the filename parameter to access the calling binary, for obvious reasons the calling binary may only request LIBR_READ access. Returns NULL on failure.

  • int libr_read(libr_file *handle, char *resourcename, char *buffer);

Read the resource named "resourcename" from the ELF binary, the resource must be saved in compliance with the binary spec. "buffer" must contain a string buffer with enough storage to hold the uncompressed contents of the resource, use libr_size() to obtain the necessary storage size. Returns 1 (true) on success, 0 (false) on failure.

  • unsigned int libr_resouces(libr_file *handle);

Returns the number of libr-compatible resources contained in the ELF binary.

  • int libr_size(libr_file *handle, char *resourcename, int *size);

Returns the uncompressed size of the specified resource ("resourcename"), use in conjuction with libr_read(). Returns 1 (true) on success, 0 (false) on failure.

  • int libr_write(libr_file *handle, char *resourcename, char *buffer, size_t size, libr_type_t *type, int overwrite);

Writes the resource named "resourcename" to the ELF binary, the resource should not exist unless "overwrite" is set to 1 (true). "buffer" must contain a string buffer with "size" bytes to write to the ELF binary. "type" specifies whether the data should be compressed by libr (LIBR_UNCOMPRESSED, LIBR_COMPRESSED). Returns 1 (true) on success, 0 (false) on failure.

Icon API

In order to allow applications to easily access their own icon for display, an icon-specific API is exported. For accessing icon data the following API should be used:

  • int libr_icon_close(libr_icon *icon);

Release the icon resource allocated by a call to libr_icon_geticon_byid(), libr_icon_geticon_byname(), libr_icon_geticon_bysize(), libr_icon_newicon_byfile(), or libr_icon_newicon_frombuffer().

  • libr_icon *libr_icon_geticon_byid(libr_file *handle, unsigned int iconid);

Return a resource handle to an icon stored in an ELF binary that is of an id less than the value returned by libr_icon_num(). Returns NULL on failure.

  • libr_icon *libr_icon_geticon_byname(libr_file *handle, char *iconname);

Return a resource handle to an icon stored in an ELF binary that is named exactly "iconname". Returns NULL on failure.

  • libr_icon *libr_icon_geticon_bysize(libr_file *handle, int iconsize);

Return a resource handle to an icon stored in an ELF binary that is closest to the size "iconsize", use size '0' to request an SVG icon. Returns NULL on failure.

  • int libr_icon_getguid(libr_file *handle, char *guid);

Returns the icon GUID in hex notation (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX), requires a 37 character buffer (36 data characters and a NULL terminator). Returns 1 (true) on success, 0 (false) on failure.

  • libr_icon *libr_icon_newicon_frombuffer(libr_icontype_t type, int iconsize, char *buffer, size_t size);

Create an icon handle to represent an icon file stored in the buffer "buffer". The file should be the same type as specified by "type" (LIBR_SVG, LIBR_PNG), where "iconsize" is ignored for SVG icons. Returns NULL on failure.

  • libr_icon *libr_icon_newicon_byfile(libr_icontype_t type, int iconsize, char *iconfile);

Create an icon handle to represent an icon file stored on disk. The file should be the same type as specified by "type" (LIBR_SVG, LIBR_PNG), where "iconsize" is ignored for SVG icons. Returns NULL on failure.

  • unsigned int libr_icon_num(libr_file *handle);

Returns the number of icons contained within the ELF binary. Returns 0 (false) on failure or when there are no icons.

  • int libr_icon_read(libr_icon *icon, char *buffer);

Stores the uncompressed buffer of the icon represented by the resource handle "icon" in "buffer". "buffer" must contain enough memory to hold the entire icon, use libr_icon_size() to discover how much memory is needed. Returns 1 (true) on success, 0 (false) on failure.

  • int libr_icon_size(libr_icon *icon, int *size);

Returns the uncompressed size of the icon represented by the resource handle "icon" in "size". Returns 1 (true) on success, 0 (false) on failure.

  • int libr_icon_save(libr_icon *icon, char *filename);

Save the icon represented by the resource handle "icon" to a file. Returns 1 (true) on success, 0 (false) on failure.

  • int libr_icon_setguid(libr_file *handle, char *guid);

Sets the icon GUID, the string should be in hex notation (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX) and contain 37 characters (36 data characters and a NULL terminator). Returns 1 (true) on success, 0 (false) on failure.

  • int libr_icon_write(libr_file *handle, libr_icon *icon, char *iconname, int overwrite);

Add the icon represented by the icon handle "icon" to the ELF binary as the icon resource named "iconname". The file should not exist unless overwrite is set to 1 (true). The ELF binary must have a GUID set by libr_icon_setguid() before calling this function. Returns 1 (true) on success, 0 (false) on failure.

Binary Spec

libelf is a good library for adding new sections to ELF files in a platform-independent way. Each resource stored in the ELF file should be named in the ELF string table using libelf and have the following header structure within the respective section:

R

E

S

<Version>

<Type>

At this time only "1" is supported for a version code, two binary "Type" values are supported:

  • 0 --- Uncompressed data follows
  • 1 --- Compressed data follows

If the data is compressed, then a 4-byte little-endian uncompressed size follows. After the header should contain zlib-compressed data, this results in the following format:

R

E

S

1

\001

<S1>

<S2>

<S3>

<S4>

...

elficon

In order to handle different icon sizes and possible access types a special section should define how all icon resources are stored. This section should be named ".icon" and contain a header, in addition to the header added by libr, with the little-endian representation of the number of entries (E*) and the "icon guid" (G*):

<E1>

<E2>

<E3>

<E4>

<G1>

<G2>

<G3>

<G4>

<G5>

<G6>

<G7>

<G8>

<G9>

<G10>

<G11>

<G12>

<G13>

<G14>

<G15>

<G16>

The "icon guid" is meant to be used by distributions to assign an icon to an application and keep that icon consistent between all ways to access the application, this field IS required even if you are not a distributor and may be generated using the application "uuid. The number of fields should be used to indicate the type and number of different icons stored in the ELF file, these fields should follow the header and should be structured as follows (S* is the entry size):

  • SVG Icon:

<S1>

<S2>

<S3>

<S4>

\000

<Icon Resource Name>

\000

  • PNG Icon:

<S1>

<S2>

<S3>

<S4>

\001

<I1>

<I2>

<I3>

<I4>

<Icon Resource Name>

\000

S* is a little-endian representation of the square icon size (16: 16x16, 32: 32x32, 48: 48x48, etc.)

ELFIconSpec (last edited 2009-09-09 22:13:40 by dhcp11-37)