<?xml version="1.0"?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
]>
<article id="index">
  <articleinfo>
    <title>Icon Theme Specification</title>
    <releaseinfo>Version 0.7</releaseinfo>
    <date>September 22 2003</date>
    <authorgroup>
      <author>
	<firstname>Alexander</firstname>
	<surname>Larsson</surname>
	<affiliation>
	  <address>
	    <email>alexl@redhat.com</email>
	  </address>
	</affiliation>
      </author>
    </authorgroup>
  </articleinfo>

  <sect1 id="overview">
    <title>Overview</title>
    <para>
    An icon theme is a set of icons that share a common look and
    feel. The user can then select the icon theme that they want to
    use, and all apps use icons from the theme. The initial user of
    icon themes is the icon field of the desktop file specification,
    but in the future it can have other uses (such as mimetype
    icons).
    </para>
    <para>
    From a programmer perspective an icon theme is just a
    mapping. Given a set of directories to look for icons in and a theme
    name it maps from icon name and nominal icon size to an icon filename.
    </para>
  </sect1>

  <sect1 id="definitions">
    <title>Definitions</title>
    <variablelist>
      <varlistentry>
	<term>Icon Theme</term>
	<listitem>
	  <para>
          An icon theme is a named set of icons. It is used to map
          from an iconname and size to a file. Themes may inherit
          from other themes as a way to extend them.
	  </para>
	</listitem>
      </varlistentry>
      <varlistentry>
	<term>Icon file</term>
	<listitem>
	  <para>
          An icon file is an image that can be loaded and used as an
          icon. The supported image file formats are PNG, XPM and SVG.
          PNG is the recommended bitmap format, and SVG is for
          vectorized icons. XPM is supported due to backwards
          compability reasons, and it is not recommended that new
          themes use XPM files. Support for SVGs is optional. 
	  </para>
	</listitem>
      </varlistentry>
      <varlistentry>
	<term>Base Directory</term>
	<listitem>
	  <para>
          Icons and themes are searched for in a set of directories,
          called base directories. The themes are stored in
          subdirectories of the base directories.
	  </para>
	</listitem>
      </varlistentry>
    </variablelist>
  </sect1>

  <sect1 id="directory_layout">
    <title>Directory Layout</title>
    <para>
    Icons and themes are looked for in a set of directories. By
    default, apps should look in $HOME/.icons (for backwards compatibility),
    in $XDG_DATA_DIRS/icons and in /usr/share/pixmaps (in that order).
    Applications may further add
    their own icon directories to this list, and users may extend or
    change the list (in application/desktop specific ways).In each of
    these directories themes are stored as subdirectories. A theme can
    be spread across several base directories by having subdirectories of
    the same name. This way users can extend and override system 
    themes. 
    </para>
    <para>
    In order to have a place for third party applications to install
    their icons there should always exist a theme called "hicolor"
    <footnote><para>This name is chosen for backwards compatibility with the old
    KDE default theme</para></footnote>.
    The data for the hicolor theme is availible for download at:
    http://www.freedesktop.org/software/icon-theme/.
    Implementations are required to look in the "hicolor" theme if
    an icon was not found in the current theme.
    </para>
    <para>
    Each theme is stored as subdirectories of the base
    directories. The internal name of the theme is the name of the
    subdirectory, although the user-visible name as specified by the
    theme may be different. Hence, theme names are case sensitive, and
    are limited to ASCII characters. Theme names may also not contain
    comma or space.
    </para>
    <para>
    In at least one of the theme directories there must be a file
    called index.theme that describes the theme. The first index.theme
    found while searching the base directories in order is used. This
    file describes the general attributes of the theme.
    </para>
    <para>
    In the theme directory are also a set of subdirectories containing
    image files. Each directory contains icons designed for a certain
    nominal icon size, as described by the index.theme file. The
    subdirectories are allowed to be several levels deep, e.g. the
    subdirectory "48x48/apps" in the theme "hicolor" would end up at
    $basedir/hicolor/48x48/apps.
    </para>
    <para>
    The image files must be one of the types: PNG, XPM, or SVG, and
    the extension must be ".png", ".xpm", or ".svg" (lower case). The
    support for SVG files is optional. Implemenations that does not
    support SVGs should just ignore any ".svg" files. In
    addition to this there may be an additional file with extra
    icon-data for each file. It should have the same basename as the
    image file, with the extension ".icon". e.g. if the icon file is
    called "mime_source_c.png" the corresponding file would be named
    "mime_source_c.icon".
    </para>
  </sect1>

  <sect1 id="file_formats">
    <title>File Formats</title>
    <para>
    Both the icon theme description file and the icon data files are
    ini-style text files, as described in the desktop file
    specification. They don't have any encoding field, instead they 
    must always be stored in UTF8 encoding.
    </para>
    <para>
    The index.theme file must starts with a section called "Icon
    Theme", with contents according to table 1 below. All lists are
    comma-separated.
    <table>
      <title>Standard Keys</title>
      <tgroup cols="4">
	<thead>
	  <row>
	    <entry>Key</entry>
	    <entry>Description</entry>
	    <entry>Value Type</entry>
	    <entry>Required</entry>
	  </row>
	</thead>
	<tbody>
	  <row>
	    <entry>Name</entry>
	    <entry>
              short name of the icon theme, used in e.g. lists when
              selecting themes.
	    </entry>
	    <entry>localestring</entry>
	    <entry>YES</entry>
	  </row>
	  <row>
	    <entry>Comment</entry>
	    <entry>
              longer string describing the theme
	    </entry>
	    <entry>localestring</entry>
	    <entry>YES</entry>
	  </row>
	  <row>
	    <entry>Inherits</entry>
	    <entry>
              <para>
              The name of the theme that this theme inherits from. If an icon
              name is not found in the current theme, it is searched for in the
              inherited theme (and recursively in all the inherited themes).
              </para>
              <para>
              If no theme is specified implementations are required to add
              the "hicolor" theme to the inheritance tree. An implementation
              may optionally add other default themes in between the last
              specified theme and the hicolor theme.
              </para>
	    </entry>
	    <entry>strings</entry>
	    <entry>NO</entry>
	  </row>
	  <row>
	    <entry>Directories</entry>
	    <entry>
             list of subdirectories for this theme. For every
             subdirectory there must be a section in the index.theme
             file describing that directory.
	    </entry>
	    <entry>strings</entry>
	    <entry>YES</entry>
	  </row>
	  <row>
	    <entry>Hidden</entry>
	    <entry>
            Whether to hide the theme in a theme selection user interface.
            This is used for things such as fallback-themes that are not supposed
            to be visible to the user.
	    </entry>
	    <entry>boolean</entry>
	    <entry>NO</entry>
	  </row>
	  <row>
	    <entry>Example</entry>
	    <entry>
              The name of an icon that should be used as an example of
              how this theme looks.
	    </entry>
	    <entry>string</entry>
	    <entry>NO</entry>
	  </row>
	</tbody>
      </tgroup>
    </table>
    </para>
    <para>
    Each directory specified in the Directory key has a corresponding section
    with the same name as the directory. The contents of this section is
    listed in table 2 below.
    <table>
      <title>Per Directory Keys</title>
      <tgroup cols="4">
	<thead>
	  <row>
	    <entry>Key</entry>
	    <entry>Description</entry>
	    <entry>Value Type</entry>
	    <entry>Required</entry>
	    <entry>Type</entry>
	  </row>
	</thead>
	<tbody>
	  <row>
	    <entry>Size</entry>
	    <entry>
              Nominal size of the icons in this directory.
	    </entry>
	    <entry>integer</entry>
	    <entry>YES</entry>
	  </row>
	  <row>
	    <entry>Context</entry>
	    <entry>
              the context the icon is normally used in. This can be
              used to e.g. let the user pick an specific type of
              icon. Currently used contexts are: Actions,
              Applications, Devices, FileSystems, MimeTypes.
	    </entry>
	    <entry>string</entry>
	    <entry>NO</entry>
	  </row>
	  <row>
	    <entry>Type</entry>
	    <entry>
              The type of icon sizes for the icons in this
              directory. Valid types are Fixed, Scalable and
              Threshold. The type decides what other keys in the
              section are used. If not specified, the default is
              Threshold.
	    </entry>
	    <entry>string</entry>
	    <entry>NO</entry>
	  </row>
	  <row>
	    <entry>MaxSize</entry>
	    <entry>
              Specifies the maximum size that the icons in this
              directory can be scaled to. Defaults to the value
              of Size if not present.
	    </entry>
	    <entry>integer</entry>
	    <entry>NO</entry>
	    <entry>Scalable</entry>
	  </row>
	  <row>
	    <entry>MinSize</entry>
	    <entry>
              Specifies the minimum size that the icons in this
              directory can be scaled to. Defaults to the value
              of Size if not present.
	    </entry>
	    <entry>integer</entry>
	    <entry>NO</entry>
	    <entry>Scalable</entry>
	  </row>
	  <row>
	    <entry>Threshold</entry>
	    <entry>
              The icons in this directory can be used if the size differ
              at most this much from the desired size. Defaults to 2 if not
              present.
	    </entry>
	    <entry>integer</entry>
	    <entry>NO</entry>
	    <entry>Threshold</entry>
	  </row>
	</tbody>
      </tgroup>
    </table>
    </para>
    <para>
    In addition to these groups you may add extra groups to the
    index.theme file in order to extend it. These extensions must
    begin with "X-", and can be used to add desktop specific
    information to the theme file. Example group names would be "X-KDE
    Icon Theme" or "X-Gnome Icon Theme".
    </para>
    <para>
    The optional filename.icon file contains a group called "Icon
    Data", with the content listed in table 3.
    <table>
      <title>Icon Data Keys</title>
      <tgroup cols="4">
	<thead>
	  <row>
	    <entry>Key</entry>
	    <entry>Description</entry>
	    <entry>Value Type</entry>
	    <entry>Required</entry>
	  </row>
	</thead>
	<tbody>
	  <row>
	    <entry>DisplayName</entry>
	    <entry>
              A translated UTF8 string that can be used instead of the
              icon name when the icon is listen in e.g. a user interface.
	    </entry>
	    <entry>localestring</entry>
	    <entry>NO</entry>
	  </row>
	  <row>
	    <entry>EmbeddedTextRectangle</entry>
	    <entry>
              If this exist it specifies the four corners of a
              rectangle where the program displaying the icon can
              embedd text. This is normally used by e.g. file managers
              that want to display a preview of text file contents in
              the icon. The corners are specified by a list of for
              values: x0,y0,x1,y1. The values are pixel coordinates
              from the top left corner of the icon, except for SVG
              files, where they are specified in a 1000x1000
              coordinate space that is scaled to the final rendered
              size of the icon.
	    </entry>
	    <entry>integers</entry>
	    <entry>NO</entry>
	  </row>
	  <row>
	    <entry>AttachPoints</entry>
	    <entry>
              A list of points, separated by "|" that may be used as
              anchor points for emblems/overlays. The points are pixel
              coordinates from the top left corner of the icon, except
              for SVG files, where they are specified in a 1000x1000
              coordinate space that is scaled to the final rendered
              size of the icon.
	    </entry>
	    <entry>points</entry>
	    <entry>NO</entry>
	  </row>
	</tbody>
      </tgroup>
    </table>
    </para>
    <para>
    Extensions to the filename.icon file are allowed, but the
    keys must be begin with "X-" to avoid collisions with future
    standardized extensions to this format.
    </para>
  </sect1>

  <sect1 id="icon_lookup">
    <title>Icon Lookup</title>
    <para>
    The icon lookup mechanism has two global settings, the list of
    base directories and the internal name of the current theme. Given
    these we need to specify how to look up an icon file from the icon
    name and the nominal size.
    </para>
    <para>
    The lookup is done first in the current theme, and then
    recursively in each of the themes inherited the current theme, and
    finally in the default theme called "hicolor" (implementations may
    add more default themes before "hicolor", but "hicolor" must be
    last). As soon as there is an icon of any size that matches in a
    theme the search is stopped. Even if there may be an icon with a
    size closer to the correct one in an inherited theme we don't want
    to use it. Doing so may generate an inconsistant change in an icon
    when you change icon sizes (e.g. zoom in).
    </para>
    <para>
    The lookup inside a theme is done in three phases. First all the
    directories are scanned for an exact match, e.g. one where the
    allowed size of the icon files match what was looked up. Then all
    the directories are scanned for any icon that matches the name. If
    that fails we finally fall back on unthemed icons. If we fail to
    find any icon at all it is up to the application to pick a good
    fallback, as the correct choice depends on the context.
    </para>
    <para>
    The exact algorithm (in pseudocode) for looking up an icon in an
    implementation that supports SVG is:
    <programlisting>LookupIcon (iconname, size):
for each subdir in $(theme subdir list) {
    for each directory in $(basename list) {
        for extension in ("png", "svg", "xpm") {
            if DirectoryMatchesSize(subdir, size) {
                filename = directory/$(themename)/subdir/iconname.extension
                if exist filename
	            return filename
            }
	}
   }
}

minimal_size = MAXINT
for each subdir in $(theme subdir list) {
    for each directory in $(basename list) {
        for extension in ("png", "svg", "xpm") {
            filename = directory/$(themename)/subdir/iconname.extension
            if exist filename and DirectorySizeDistance(subdir, size) &lt; minimal_size
	        closest_filename = filename
		minimal_size = DirectorySizeDistance(subdir, size)
	}
   }
}
if closest_filename set
   return closest_filename
   
for each directory in $(basename list) {
    for extension in ("png", "svg", "xpm") {
	if exists directory/iconname.extension
	   return directory/iconname.extension
    }
}

return failed icon lookup
     </programlisting>
     With the following helper functions:
     <programlisting>DirectoryMatchesSize(subdir, iconsize):
read Type and size data from subdir
if Type is Fixed
    return Size == iconsize
if Type is Scaled
    return MinSize &lt;= iconsize &lt;= MaxSize
if Type is Threshold
    return Size - Threshold &lt;= iconsize &lt;= Size + Threshold

DirectorySizeDistance(subdir, size):
read Type and size data from subdir
if Type is Fixed
    return abs(Size - iconsize)
if Type is Scaled
    if iconsize &lt; MinSize
        return MinSize - iconsize
    if iconsize &gt; MaxSize
        return iconsize - MaxSize
    return 0
if Type is Threshold
    if iconsize &lt; Size - Threshold
        return MinSize - iconsize
    if iconsize &gt; Size + Threshold
        return iconsize - MaxSize
    return 0
</programlisting>
    </para>
  </sect1>

  <sect1 id="example">
    <title>Example</title>
    <para>
     Here is an example index.theme file:
     <programlisting>[Icon Theme]
Name=Birch
Name[sv]=Björk
Comment=Icon theme with a wooden look
Comment[sv]=Träinspirerat ikontema
Inherits=wood,default
Directories=48x48/apps,48x48/mimetypes,32x32/apps,scalable/apps,scalable/mimetypes

[scalable/apps]
Size=48
Type=Scalable
MinSize=1
MaxSize=256
Context=Applications

[scalable/mimetypes]
Size=48
Type=Scalable
MinSize=1
MaxSize=256
Context=MimeTypes

[32x32/apps]
Size=32
Type=Fixed
Context=Applications

[48x48/apps]
Size=48
Type=Fixed
Context=Applications

[48x48/mimetypes]
Size=48
Type=Fixed
Context=MimeTypes</programlisting>
     The corresponding directory tree in the /usr/share/icons
     directory could look like this:
     <programlisting>birch/index.theme
birch/scalable/apps/mozilla.svg
birch/scalable/mimetypes/mime_text_plain.svg
birch/scalable/mimetypes/mime_text_plain.icon
birch/48x48/apps/mozilla.png
birch/32x32/apps/mozilla.png
birch/48x48/mimetypes/mime_text_plain.png
birch/48x48/mimetypes/mime_text_plain.icon</programlisting>
Where birch/scalable/mimetypes/mime_text_plain.icon contains:
     <programlisting>[Icon Data]
DisplayName=Mime text/plain
EmbeddedTextRectangle=100,100,900,900
AttachPoints=200,200|800,200|500,500|200,800|800,800</programlisting>
And birch/48x48/mimetypes/mime_text_plain.icon contains:
     <programlisting>[Icon Data]
DisplayName=Mime text/plain
EmbeddedTextRectangle=8,8,40,40
AttachPoints=20,20|40,40|50,10|10,50</programlisting>
    </para>
    <para>
    In this example a lookup of "mozilla" would get the prerendered
    48x48 and 32x32 icons before the SVG icons due to the order of
    Directories.
    </para>

  </sect1>

  <sect1 id="install_icons">
    <title>Installing application icons</title>
    <para>
    So, You're an application author, and want to install application icons
    so that they work in the KDE and Gnome menus. Minimally you should install
    a 48x48 icon in the hicolor theme. This means installing a PNG file in
    $prefix/share/icons/hicolor/48x48/apps. Optionally you can install icons in different
    sizes. You might even want to install icons with a look that matches other
    well known themes so your application will fit in with some specific desktop
    environment. 
    </para>
    <para>
    It is recommended that the icons installed in the hicolor theme look neutral,
    since it is a fallback theme that will be used in combination with some very
    different looking themes. But if you don't have any neutral icon, please install
    whatever icon you have in the hicolor theme so that all applications get at
    least some icon in all themes.
    </para>
  </sect1>

  <sect1 id="implementation_notes">
    <title>Implementation Notes</title>
    <para>
    The algorithms as described in this document works by always
    looking up filenames in directories (a stat in unix
    terminology). A good implementation is expected to read the
    directories once, and do all lookups in memory using that
    information.
    </para>
    <para>
    This caching can make it impossible for users to add icons without
    having to restart applications. In order to handle this any
    implementation that does caching is required to look at the mtime
    of the toplevel icon directories when doing a cache lookup, unless
    it already did so less than 5 seconds ago. This means that any
    icon editor or theme installation program need only to change the
    mtime of the the toplevel directory where it changed the theme to
    make sure that the new icons will eventually get used.
    </para>
  </sect1>

  <appendix id="changes">
    <title>Change history</title>
    <formalpara>
      <title>Version 0.7, 13 September 2003, Heinrich Wendel</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
            Convertet to basedir spec.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Changed type of MaxSize, MinSize and Threshold to integer.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Removed typo in code example.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Corrected path to default-icon-theme.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
    <formalpara>
      <title>Version 0.6, 2 December 2002, Alexander Larsson</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
            Added Hidden key.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Removed multiple inheritance.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Renamed the default theme hicolor.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Added the application icon install section.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Fixed some xml issues.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
    <formalpara>
      <title>Version 0.5, 18 September 2002, Alexander Larsson</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
            Added DisplayName to icon data.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Fixed up example svg icon data.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Fixed some spelling and grammar errors.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
    <formalpara>
      <title>Version 0.4, 16 May 2002, Alexander Larsson</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
            Fixed some spelling and grammar errors.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
    <formalpara>
      <title>Version 0.3, 14 May 2002, Alexander Larsson</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
            Made support for SVGs optional.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Added a default fallback theme.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
            Changed the example directory layout a bit to
            match the default theme.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
    <formalpara>
      <title>Version 0.2, 29 April 2002, Alexander Larsson</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
              Changed search order to png, svg, xpm.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
              Added comment to say that xpm is supported for backwards
              compat and not recommended in new themes.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
              Default Type for a directory is now Threshold
	    </para>
	  </listitem>
	  <listitem>
	    <para>
              Added implementation notes section.
	    </para>
	  </listitem>
	  <listitem>
	    <para>
              Added Example key.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
    <formalpara>
      <title>Version 0.1, 22 April 2002, Alexander Larsson</title>    
      <para>
	<itemizedlist>
	  <listitem>
	    <para>
              Created initial draft.
	    </para>
	  </listitem>
	</itemizedlist>
      </para>
    </formalpara>
  </appendix>
</article>
