For Developers

Photofont® technology for developers

The following is a draft specification of the Photofont® file format, version 1.0. Please contact us if you are interested to implement it, and we will offer you further assistance.

We also offer code for licensing, such as the photofont rasterizer/scaler. Please contact us for details.

Also note that em2 Solutions offers XcgfK, a text engine for mobile devices that implements the photofont format.

Photofont® format specification

Format version 1.0
Revision: June 2003

Introduction

The photofont specification is quite simple. Anyone with a text editor and a graphics program capable of exporting PNG files can create a photofont.

It works like this: The web page designer places special XML tags around photofont text. When a browser comes across these tags it automatically downloads and activates a plug-in which displays bitmaps from the photofont rather than vector characters from a host computer font. The result is that the end-viewer sees exactly what the web page designer intended. And the designer is not restricted to standard fonts present on all computers or to the particular fonts present on a user's computer.

At the same time, because it is still plain text on the HTML page, the text can be found by search engines, used in indexes, copied and pasted, spellchecked, and used for hypertext links - none of which would normally be possible for bitmap text.

A photofont is an XML document and consists of four sections: header, Unicode encoding & kerning, glyph metrics, and glyph images. We'll describe these in detail below.

The Header

<header>
<version type="string"></version>
<family type="string">AGBlue</family>
<full_name type="string">AGBlue</full_name>
<codepage type="string">MacOS Roman</codepage>
<ascender type="int">34</ascender>
<descender type="int">9</descender>
<upm type="int">36</upm>
</header>

The header begins with a <header> tag, consists of a few lines of descriptive information, called attributes, and ends with a </header> tag. attributes have the following format:
<attribute_id type="type_id">data</attribute_id>

where:

attribute_id
identifies the attribute being defined

type_id
specifies what kind of data is stored inside the attribute object

data
is the content of the attribute

In this example the version is blank and the family and full_name are the same. The MacOS Roman codepage is specified and the ascender and descender are given in font units. "upm" (units per eM) defines the font units.

The possible attributes are:

int: ascender
Ascender height of the font in font units (see below about font units). Optional, but highly recommended.

int: base_to_base
Distance between lines in font units. If not specified it is assumed to be the sum of ascender and descender.
In this example, the base_to_base attribute is set to 56:
<base_to_base type="int">56</base_to_base>

string: codepage
Defines the codepage for the font.

string: copyright
A string containing font copyright information.

int: descender
The descender depth of the font in font units. Optional, but highly recommended.

string: family
A mandatory attribute. The family attribute defines the family name of the font. It is used to combine fonts into families.

string: full_name
Defines the unique name of the font by which it is identified. If absent the family attribute value will be used instead. If there are two fonts with the same full name in the system, only one of them will be used.

string: style
Specifies the style of the font. If absent it is forced to "Regular".

int: upm
Another mandatory attribute. The font's UPM (units per eM) value. Defines the height of the font in logical units that are used to define the geometrical attributes of the font (ascender, descender, etc.). The upm is an arbitrary number, but it is convenient to use the pixel height of the bitmap. I.e. if you have 32 pixel high bitmaps in the font then a upm of 32 is convenient.
This works just the same way as regular fonts. All distances in the font are measured in abstract logical font units. The UPM tells you the size of the font measured in these units. Thus we must recalculate these units into real values for specific font point sizes. In photofont the UPM usually is equal to the PPM and thus these units are essentially the same as the pixels of the bitmap containing the glyph images.string: version
A string with information about the version of the font.

Encoding and Kerning

<globals>
<unicode_mapping type="array" subtype="map_unicode">
<map id="A" unc="65" />
<map id="B" unc="66" />
<map id="C" unc="67" />
...etc
...etc
<map id="zero" unc="48" />
</unicode_mapping>

The globals section begins and ends with <globals> tags and contains auxiliary data — particularly the Unicode mapping table and kerning table.

The Unicode mapping section begins with the <unicode_mapping> tag and ends with the corresponding closing tag. The body consists of a line for each mapping. In our example you see that the character with id="A" is mapped to Unicode 65; character "B" is mapped to Unicode 66, etc. Each character in the photofont is mapped to its Unicode in this section. In most Western fonts this section will not vary much from font to font if the designer sticks to standard names and Unicodes. I.e this code may be reusable from font to font.

Kerning Table

Like Unicode Mapping, the kerning table is represented by by an array of kerning pairs and has the following format:

<kerning type="array" subtype="kerning_pair">
<pair left="glyph_id" [ left_image="image_id" ]
right="glyph_id" [ right_image="image_id" ]
[ x="x_offset" ]
[ y="y_offset" ] />

...etc.
<kerning> where:

glyph_id
is the identifier of the Glyph

image_id
is the identifier of the Image within the glyph

x_offset
is an integer value representing the horizontal kerning amount (in font units as defined by the upm)

y_offset
is an integer value representing the vertical kerning amount (in font units)

The left and "left_image" attributes specify the first glyph in the kerning pair, while "right" and "right_image" define the second glyph. If the Image is not specified then kerning will be applied to all the Images of the Glyph. If one of the kerning values is omitted it is assumed to be zero.

For example:
<pair left="A" right="V" right_image="image1" x="-5" />

This pair instructs the browser that the "image1" Image of the Glyph "V" is to be shifted 5 units to the left if it follows any image of the Glyph "A".

A typical Kerning table in a photofont looks like this:
<kerning type="array" subtype="kerning_pair">
<pair left="A" right="V" x="-14" />
<pair left="A" right="T" x="-14" />
<pair left="A" right="O" x="-8" />

...etc
...etc
<pair left="V" right="A" x="-14" />
</kerning>
</globals>

Glyph Metrics

<glyphs>
<glyph id="A">
<image id="v0" type="photo">
<shape embedded="Image32">
<ppm int="36" />
<bbox x="0" y="-1" width="27" height="28" />
<base x="0" y="27" />
<delta x="26" y="0" />
</shape>
</image>
</glyph>

...etc
...etc
<glyph id="asciitilde">
<image id="v0" type="photo">
<shape embedded="Image93">
<ppm int="36" />
<bbox x="2" y="10" width="18" height="6" />
<base x="-2" y="16" />
<delta x="22" y="0" />
</shape>
</image>
</glyph>
</glyphs>

The glyph metrics section is set off by <glyphs> and </glyphs> tags. It contains an "object" for each character in which metrics and shape information is given. The glyph id corresponds to the id in the previous section. In the image tag, id="v0" identifies a particular image. A character can have more than one image in a photofont. Each image has an identifier, which is unique within the glyph. This allows specific images or glyphs to be referenced within the font (e.g. in the kerning table). In our case the type is always photo, which means a 32 bit bitmap with an alpha channel (like a PNG file). The shape (the actual image data) can be embedded, as it is in this font, which means that the graphics data for the shape will be found in the next section, or it can be referred, in which casea relative path to the graphics data is to be found will be given.
<shape bitmap_placement="../images/A.png">

The other attributes are:

ppm_value
PPeM of this image.

bbox_x
X offset of the bounding box left border relative to Base Point

bbox_y
Y offset of the bounding box top border relative to Base Point

bbox_width
Width of the bounding box

bbox_height
Height of the bounding box

base_x
X coordinate of the Base Point relative to the top side of the bitmap

base_y
Y coordinate of the Base Point relative to the left side of the bitmap

delta_x
horizontal metric

delta_y
vertical metric

Glyph Images

<data> <photo> <image id="Image32">
Content-Type: image/png; charset=US-ASCII; name=Image3
Content-transfer-encoding: base64
iVBORw0KGgoAAAANSUhEUgAAABsAAAAcCAYAAACQ0cTtAAAFSElEQVR4nIWWW1Ij2RGGP90R
CAlJICRA6IKE9O4tzMPEzNM4gi3MWnoL9hLwEmYL9utAX2jE3dCNoIGmaRjm80OVSkWH7VbE
CVWdypN//n/myXMSKt/7JRKJ/2ukJr7rJDSEpQP6SWkzhvyYPNLmPaur7wEMxqVwKCgLHwRd
ZTf89nc3C5abSAMpcxQuO6e4cgzDx+BdZZVH4B42DgDJbghlKbIXgS2goBmUtMJH2y2dBvPw
CoTSPmQlzw5DnmixD0iOiwCswBg4hswZpD4zbH2BoRFQHmXB4L+nrATAMHY9P4oAOxm7cEQG
meUMOIXem/DzYQC2WZBKGOBM5z3MnIYGk6jHllH4ZBZNonAiHAujGDu380h77XE6ldiDnJAI
ZawW34ZU78kVAqPNEKw4o1QvZEPhxnmUoVK8tobCtczsh57/age75CTBISSPYPUCKjKY5Gyz
OAnuglTvD9rN3YhVgXvhQua0t/peuDFb027tzBaaRpP9eO58VeUM+pOgvwD7kAzBEgXJIisI
M0IllDDxy1f4d5Cf3Adz7EvDALyiLB05nxub5ZPwNvDeVrDMnMAdVZ5h7ZrshNnSorR6Uh9c
ksvEcxUUQopPUn5rPv1zjAHS+sNa8aMrHMr6lF0uNfqVlLAo8Ai9EZTPA7Da6iULvTfUksL8
TUzCsOryI+FpCjIIHbfvhD2ZVZYfhB8FrOAYXpND6FxAWsiHzGoIrc9sIquTKmwo2UNZHocM
fw/B3pntOwZMsiXzCvuSmmyHSJW/wB6Zxa/h1F7YQVIHMXXCh/KlcCTsWOrGnOQepOSruNRD
dKn/LdjudmP9llb2DDggMclZJnXAsP0NGJeSPJT6N06aSuekOw1KaQU2kewgeQXpcMh65YDm
BGzAhOppCPZgh4tw4bWl0EF2XZnzt1RJWIkFVtPi3IENToSDGLubrQ4ynIogbIyAq+niyomN
Re3xktXM7NjUolv1wpsXKtR5bWWgZLXJ7RSsOtqmIin2SS1cB2Dl5SfI30WLN1Aa5ybLCjvR
4gZaRVrckEGqky7DY7D3uBMezcwFLSxTGsnSBT1uY8xmhcFtANYJ2CyUQlaZLQHXC7rU/LAN
J9A4ZbN+STdiN4r2JLwO29hEpautDCGGSiMZr8Izi4PTMMFX0aL0i0pDuucxKbVDIHtrQ2m+
aM5/KyEsh2DF/hRstnvkJtrjOCqMgPGX8Quw+Mjt2OHKRFXzXFqZ11T+JwGHnI1B+pGM/A5g
IvfTV7gNGd0K51EZNXA7eP7l6wBlTVnWjdq1FHciGedRsqemuRcIjya7uSlYwKyOQSNN6+by
tKqWeGcPtwBTaH/9xkTovLkQNOZydy8MTpl9ZyemyjL+SvNwAhZMLqDz/RubhKfyRKaVLzHZ
9m2hs5zZLgfspsVx4lpJqY7MF2Pr59xmci2YTK6jlM5tRcd+lOR//s98vRiaW7wz25z00qCS
m3nH1amM2NwIo8yOhUNnJ519Qcl8Di4zLe3zZ9Dl65oufJTkscNoL2qrvmu2finoSnioNgjP
uAlYqnllPWpRMVbzmu74w1r6BgbSRlIr08/59i2UY1uHkV20hubW7yPDKg8/REa5ngZ3w2c3
O59i0tzY4Yw6O8ARnXlZ4Znu3AhKh7TWPgdH1MS+di8zminvmooFne4/vYpF9N9HG/dYuqWf
FZaE7BWUhNwuJA8Yrj5T3dj9rp/+/NNvyeDqvPd+qXAFwwsYCNVn5pDk5i4J+BdzM7x9BO52
If+BwSegMGD4Z5LdZ7jcSwImKj3/Qf8Y2CO/IIOuzKQCvLvbdPc/D7U8SA5jwKcAAAAASUVO </image>
<image>

...etc
...etc
</image>
...etc
...etc
</photo>
</data>

The glyph images section (which is unnecessary if all the glyphs are referred) starts with <data> and <photo> tags. Then follows a series of <image> "objects" which contain the actual graphics data for the photofont glyphs. They start with an <image> tag in which the image is identified, and then have two lines of information which is usually always the same except for the name, which references the image name assigned in the previous section. So in our example you see that the image (and we have shown only one of the images here because of space considerations) is image32, which we know is the character "A" from the previous sections. Then follows the MIME-encoded data for the PNG bitmap of the glyph and then the closing </image> tag. Every embedded glyph should have an image in this section . Note that several glyphs can refer to the same bitmap. Also some of images may be embedded and some may be specified as separate resources.

Putting It All Together

Finally the whole font needs to be wrapped in a couple tags, and the end product looks something like this:

<?xml version="1.0" ?>
<PhF version="1.0">
<header>

...etc
</header>
<globals>

...etc
</globals>
<glyphs>

...etc
</glyphs>
<data>

...etc
</data>
</PhF>

Take a look at any of the free photofonts in any text editor to get a more detailed idea of what a full photofont is like.