Icon Theme Specification

Alexander Larsson


Table of Contents
Overview
Definitions
Directory Layout
File Formats
Icon Lookup
Example
Implementation Notes
Change history

Overview

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).

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.


Definitions


Directory Layout

Icons and themes are looked for in a set of directories. By default, apps should look in $HOME/.icons, /usr/share/icons and /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.

In order to have a place for third party applications to install their icons there should always exist a theme called "default". The data for the default theme is availible for download at: http://www.freedesktop.org/standards/icon-theme-spec.html. Implementations are required to look in the "default" theme if an icon was not found in the current theme.

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.

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.

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.

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".


File Formats

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.

The index.theme file must starts with a section called "Icon Theme", with contents according to table 1 below. All lists are comma-separated.

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.

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".

The optional filename.icon file contains a group called "Icon Data", with the content listed in table 3.

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.


Icon Lookup

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.

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 theme called "default". 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).

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.

The exact algorithm (in pseudocode) for looking up an icon in an implementation that supports SVG is:

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)/subdirectory/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)/subdirectory/iconname.extension
            if exist filename and DirectorySizeDistance(subdir, size) < 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
     
With the following helper functions:
DirectoryMatchesSize(subdir, iconsize):
read Type and size data from subdir
if Type is Fixed
    return Size == iconsize
if Type is Scaled
    return MinSize <= iconsize <= MaxSize
if Type is Threshold
    return Size - Threshold <= iconsize <= 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 < MinSize
        return MinSize - iconsize
    if iconsize > MaxSize
        return iconsize - MaxSize
    return 0
if Type is Threshold
    if iconsize < Size - Threshold
        return MinSize - iconsize
    if iconsize > Size + Threshold
        return iconsize - MaxSize
    return 0


Example

Here is an example index.theme file:

[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
The corresponding directory tree in the /usr/share/icons directory could look like this:
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
Where birch/scalable/mimetypes/mime_text_plain.icon contains:
[Icon Data]
DisplayName=Mime text/plain
EmbeddedTextRectangle=100,100,900,900
AttachPoints=200,200|800,200|500,500|200,800|800,800
And birch/48x48/mimetypes/mime_text_plain.icon contains:
[Icon Data]
DisplayName=Mime text/plain
EmbeddedTextRectangle=8,8,40,40
AttachPoints=20,20|40,40|50,10|10,50

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.


Implementation Notes

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.

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.


Change history