Toggle menu
Toggle preferences menu
Toggle personal menu
Not logged in
Log in or create an account to edit The Apple Wiki.
Example icon atlas

Since iOS 13, Apple Maps uses a custom binary format for map icons. There are files with .iconconfigpack, .iconmappack, and .icondatapack extensions, collectively known as "resource packs". These files contain image atlases with multiple icons and variants, and configuration for how to display them.

These files are parsed and rendered by the VectorKit private framework, in C++ classes like grl::codec::IconDataPack.

Example files:

Overview

All icon data is split into independent sets of files for each display scale: default (1x), @2x, and @3x. For each display scale, there is one iconmappack file with global information, and several iconconfigpack and icondatapack files, one pair for each "region".

Icons

Icons are identified by a tuple (iconID, variant, dataVariant, sizeGroup), called an "IconKey". Each iconID has an associated name defined in the IconMapPack.

Icons are not just individual bitmaps. IconConfigPacks specify an icon as a list of "layers" of different types. An "image layer" references an image by its imageID. An imageID then corresponds to a part of an image atlas in a IconDataPack. There can be other layers, such as a "path layer" defining a colored circle drawn behind the image.

Regions

"Regions" allow downloading only the icon packs needed for a certain area of the map, for example, only download Japan-specific public transport icons when you zoom into Japan. There is also a "Default Icons" region used globally.

However, there are also other regions like "Guides Icons Default" which don't correspond directly to "a region of the world", so the term is somewhat a misnomer. A region is really a pair of config+data pack files containing a set of icons.

There are two mechanisms to decide what "regions" are applicable, but the details are unclear (how do the two interact, etc):

  • The geo_manifest that lists available icon packs specifies one or more minX/maxX/minY/maxY/minZ/maxZ tuples for some packs. Presumably this marks an icon pack as only applying to some zoom levels and some rectangular areas of the map.
  • The IconMapPack file assigns a list of regions to each country. This seems to be used both for country-specific icons (like local landmarks), and for icons that look different in different countries. For example, bank POI icons have a $ or € or £ symbol depending on the country. The mappack file says "in Spain, use the Localized Poi INTL Euro Icons region", and the config/data packs for that region contain a bank icon with the € symbol.

Resource pack file format

All resource packs have the same outer format. They have a sequence of "chapters", which are usually zlib-compressed. Chapter type 1 "pack info" has the same format in all three file types. The contents of the other chapters are specific to each file type.

All integers and floating point numbers are stored in little-endian byte order.

The first 0x40 bytes of the file contain the "header name", which may be "ICONCONFIGPACK", "ICONDATAPACK", or "ICONMAPPACK", padded with zeros. Apple's decoder doesn't actually check if the padding has zeros, so it's possible they could use those bytes for extra fields in the future.

Next there is the list of chapters and their locations in the file.

struct ResourcePack {
    char headerName[0x40];
    u16 chapterCount;
    ChapterInfo chapters[chapterCount];
};
struct ChapterInfo {
    u16 chapterType;
    u64 byteStart;
};

It's probably invalid to have duplicate chapterTypes, or to have chapters in an unexpected order. For example, some chapters change their format slightly depending on the version number in the PackInfo chapter, so PackInfo has to be first. However, there is no explicit error checking for this in Apple's decoder.

The byteStart field in ChapterInfo specifies the offset where the chapter starts, from the beginning of the file.

At that offset, you find this structure:

struct Chapter {
    u64 rawSize;
    u64 compressedSize;
    u8 data[];
};

If compressedSize is non-zero, then the following data is of size compressedSize, and contains zlib-compressed data. Decompressing it should result in data of size rawSize.

If compressedSize is 0, then the following data is of size rawSize and contains the uncompressed chapter data directly.

All the rest of the format complexity is in the content of the chapters.

PackInfo chapter

All three resource file types have a PackInfo chapter (chapterType=1). The content is:

struct PackInfo {
    u16 packVersion;
    char region[];
    float contentScale;
};

The region string is variable size and null-terminated; the contentScale float appears immediately after the null terminator of the region string.

IconDataPack format

Data packs are resource pack files that contain image atlases, as embedded PNG images. They use the header name "ICONDATAPACK", and have three chapters:

  • 1: PackInfo
  • 13: ImageInfo
  • 14: Atlases

ImageInfo chapter

The ImageInfo chapter (chapterType=13) has a list of all the "images" in this file, specified as rectangular regions within atlases, and a list of all the atlases.

struct ImageInfoChapter {
    u32 numImages;
    Image images[numImages];
    u16 numIndices;
    AtlasIndex indices[numIndices];
};
struct Image {
    u32 imageID;
    u16 atlasIndex;
    float atlasOffsetX;
    float atlasOffsetY;
    float imageSizeX;
    float imageSizeY;
};
struct AtlasIndex {
    u16 atlasIndex;
    u32 byteStart;
    u32 byteLength;
};

The atlasOffset and imageSize fields are in floating-point format, but they appear to be always positive integer values in practice.

The Image structure specifies that the image identified by imageID is a rectangular region of atlas atlasIndex, starting at top left corner atlasOffset, with size imageSize in pixels.

Each AtlasIndex specifies that the PNG image data for atlas atlasIndex is at offset byteStart and length byteLength within the data of the atlas chapter.

Atlases chapter

The Atlases chapter (chapterType=14) contains the actual image data. It's not compressed at the chapter level; Apple's decoder checks for this and throws an error if compressedSize != 0.

struct AtlasesChapter {
    u32 numAtlases;
    Atlas atlases[numAtlases];
};
struct Atlas {
    u32 length;
    u8 pngData[length];
};

The bytes at pngData contain a PNG image.

In theory, you could find the atlas at index N by skipping over the previous N-1 atlases using their length. However, Apple's decoder uses the AtlasIndex list in the ImageInfo chapter, so the length and numAtlases fields here are not actually used.

IconConfigPack format

Config packs are resource pack files that contain definitions of icons. They use header name "ICONDATAPACK", and have four chapters:

  • 1: PackInfo
  • 11: PropertyInfo
  • 15: IconList
  • 16: IconData

The structure of IconData is quite complex. It contains multiple groups, each has multiple icons, each icon has multiple layers of different types, and each layer has multiple properties.

Layer property values can have different data types. The property types are:

Type ID Length Description
0 1 byte bool (0/1)
1 4 bytes float
2 4 bytes uint32
3 8 bytes 2D point or size, as a pair of floats
4 16 bytes unknown, not seen in use
5 4 bytes color, as 8-bit integer RGBA components
6 variable null-terminated string

PropertyInfo chapter

This chapter contains the list of property types used in the file and their lengths. It's used for forward compatibility. If the IconData chapter has a property type that isn't recognized by the decoder, the length in this chapter allows it to skip over the properties of that type correctly. In addition, a known property type with an unexpected length will also cause all properties of that type to be skipped and not parsed.

The format is:

struct PropertyInfoChapter {
    u8 numProperties;
    PropertyTypeInfo types;
};
struct PropertyTypeInfo
    u8 type;
    u8 length;
};

Property type 6 (string) has variable length, since it's null-terminated. It's listed here with length 0.

All known iconconfigpack files have the same content in this chapter, matching the table of property types mentioned above. In hex:

07  00 01  01 04  02 04  03 08  04 10  05 04  06 00

IconList chapter

IconData chapter