This is part of the old website. New website begins at fontforge.github.io

Are you a web developer? Help us migrate this page on Github

TrueType composites: Apple & MicroSoft differences

Apple and Microsoft rasterizers interpret some truetype composites differently and this can result in radically different displays of a character. Here is a character designed to be displayed on a Mac, the composite consists of two components, one of which has been rotated and scaled. If Apple's definition of composite behavior is followed then the two strokes will just barely touch at the left edge. If MicroSoft's is followed then the diagonal stroke will be offset from the vertical by a considerable amount.



	Glyph  11: off = 0x0000016E, len = 34
	  numberOfContours:	-1  (Composite)
	  xMin:			810
	  yMin:			-1
	  xMax:			1256
	  yMax:			446

	     0: Flags:		0x00A7
		Glyf Index:	6
		X WOffset:	810
		Y WOffset:	57
		X Scale:	 1.060608
		Scale 01:	-1.060669
		Scale 10:	 1.060608
		Y Scale:	 1.060608
		Other:		Round X,Y to Grid            

	     1: Flags:		0x0007
		Glyf Index:	6
		X WOffset:	1156
		Y WOffset:	0
		Other:		Round X,Y to Grid            

On the right is a dump (using microsoft's ttfdump program) of the corresponding glyph. As you can see it consists of two components, the first has been scaled by 1.5 and then rotated 45°, its horizontal offset is 810. The other is neither rotated nor scaled and its horizontal offset is 1156. According to Apple the first component should have its offset scaled by 1.5 (yielding an offset of 1215 which is just enough for the two glyphs to kiss). According to MicroSoft the offset is not scaled.

This problem only arises if a composite is scaled (actually: has a transformation matrix whose determinant is not 1, so skewing is also an issue but rotating and flipping are not), so it is fairly rare.

The OpenType spec now provides two bits (in the composite flags array) to disambiguate this case (neither bit is set in the above example, hence the problem). If bit 0x800 is set then the rasterizer should use Apple's definition, while if bit 0x1000 is set MicroSoft's (and now OpenType's default) definition. If neither bit is set then the platform's default will be used. Apple does not document these bits on their site, but they do support them (At least in Mac OS/9 and Mac OS/X). On the other hand, MicroSoft does document the bits, but the rasterizer on my Win/Me box does not support Apple's rules.

Apple documents a moderately complex algorithm for determining the factor by which each offset should be scaled. This algorithm does not match the behavior of Apple's rasterizer under Mac OS/9 and Mac OS/X. I have determined empirically that the proper scaling factors are:
        horizontalScale = sqrt(XScale*XScale + Scale01*Scale01)
        verticalScale   = sqrt(YScale*YScale + Scale10*Scale10)

(using the same notation as ttfdump). Basically, this means that the horizontal scale factor is the length of the vector that results from applying the transformation matrix to (1,0).

Sample Fonts:

Here is a collection of the permutations of a font which displays the problem. The characters B-L contain scaled or rotated or flipped components. They also contain another component to show where the transformed component should line up if Apple's rules are followed (as in the example at the top of the page, which may be found at "F").
Apple Rules MS Rules Unspecified

Windows font

CompositeMac.ttf CompositeMS.ttf CompositeAmbiguous.ttf

Mac resource font

CompositeMac.ttf.bin CompositeMS.ttf.bin CompositeAmbiguous.ttf.bin

Mac dfont (OS/X)

CompositeMac.dfont CompositeMS.dfont CompositeAmbiguous.dfont

(Do not try editing these fonts with PfaEdit. PfaEdit automagically will add the OpenType bit to the flags array).