XPS 0.95 Sideways Text Origin and Advance Width Clarification

The XPS spec was previously unclear about calculations of the origin and incomplete on the calculations of advance width for sideways text. Section 5.1.6.2 has been updated as follows:

5.1.6.2 Calculating Sideways Text Origin and Advance Width

The formulas below describe the method used to calculate each glyph’s nominal origin, which is used for positioning the glyphs on the fixed page and for calculating the default advance width for each glyph.

The origin is the top center of the unturned glyph. The x origin of the unturned glyph is calculated to be exactly one-half the advance width of the glyph, as specified in the horizontal metrics table of the font. This formula is expressed as follows (in pseudocode):

TopOriginX = hmtx.advanceWidth[GlyphIndex] / 2

If the font is a CFF OpenType font, the y origin of the unturned glyph is determined from the vertical origin (vorg) table for the font, which may be specified for a particular glyph index but falls back to the default vertical origin if the glyph index is not present in the vertical origin table. This formula is expressed as follows (in pseudocode):

TopOriginY = vorg.vertOriginY[glyphIndex]

or:

TopOriginY = vorg.defaultVertOriginY

If the vertical origin table is not present, the glyph data (glyf) and vertical metrics (vmtx) font tables are consulted. The glyph bounding box is retrieved from the glyph data table and added to the top side-bearing for the glyph, specified in the vertical metrics table. This formula is expressed as follows (in pseudocode):

TopOriginY = glyf.yMax[glyphIndex] + vmtx.topSideBearing[glyphIndex]

Note: CFF fonts do not contain the glyf.yMax information; instead the yMax for each glyph is computed by calculating the top of the glyph’s bounding box from the CFF charstring data.

If the vertical metrics font table does not exist but the Windows-specific metrics (OS/2) table does exist, the latter table is consulted and the sTypoAscender value is used. This formula is expressed as follows (in pseudocode):

TopOriginY = os/2.sTypoAscender

Descender = abs(os/2.typoDescender)

In all other circumstances, the Ascender value from the horizontal header (hhea) table is used. This formula is expressed as follows (in pseudocode):

TopOriginY = hhea.Ascender

Descender = abs(hhea.Descender)

Finally, the advance width for sideways text is computed as follows (in pseudocode), unless specifically overridden by the Indices attribute:

AdvanceWidth = TopOriginY + Descender