Composite glyphs


Javascript Editor

We rendered all Ascii characters.

Javascript Editor

But how did it render accented characters?

Javascript Editor

It seems to work because we used Computer Modern Unicode (CMU) fonts, we mapped to Latin-1 characterset. We use the file CMUSerif-Italic,ttf.

But how about the original Computer Modern fonts cmti10.ttf ?

With the following code snippets, you can switch between the two fonts

Javascript Editor

Javascript Editor

Switch the fonts and render again above.

Wow, the mapping is completely different. It does not even render the ascii characters right. We need to inspect the cmap.

Javascript Editor

We see that the old font does not use idDelta but only idRangeOffset. Did we fail to implement the offsets properly

unicodeOffset(unicode) {
for(var i = 0; i < this.cmap.format.segCountX2 / 2 ; i++) {
if (unicode >= this.cmap.format.startCode[i] && unicode <= this.cmap.format.endCode[i] ) {
return unicode + this.cmap.format.idDelta[i];
}
}
return 0; //missing glyph
}

Ha. We do not use idRangeOffset at all. It has to be applied together with idDelta.

We rewrite rpnTTF

Javascript Editor

We get the correct encoding values, but the accents are not rendered.

Javascript Editor

This is because the accents are composite glyphs. We did not handle them yet. We look again the documentation
https://learn.microsoft.com/en-us/typography/opentype/spec/glyf

If the number of contours is greater than or equal to zero, this is a simple glyph. If negative, this is a composite glyph — the value -1 should be used for composite glyphs.

The composite glyph record has 4 components

  • flags uint16
  • glyphIndex uint16
  • argument1 (x-offset) uint8, int8, uint16 or int16
  • argument2 (y-yoffset) uint8, int8, uint16 or int16
  • transformdata optional

How long 3-5 are and if that is the last record, depends on the flags

  • bit 0 ARG_1_AND_2_ARE_WORDS: arguments are 2 bytes, else 1 byte
  • bit 1 ARGS_ARE_XY_VALUES: arguments are signed, else unsigned
  • bit 2 ROUND_XY_TO_GRID: rounding
  • bit 3 WE_HAVE_A_SCALE: scale present, else scale = 1.0
  • bit 4 not used
  • bit 5 MORE_COMPONENTS: this is not the last glyph
  • bit 6 WE_HAVE_AN_X_AND_Y_SCALE: xscale and yscale are different
  • bit 7 WE_HAVE_A_TWO_BY_TWO There is a 2 by 2 transformation that will be used to scale the component
  • bit 8 WE_HAVE_INSTRUCTIONS: there are instructions after the last component
  • bit 9 USE_MY_METRICS: use metric of this component (kerning)
  • bit 10 OVERLAP_COMPOUND: components overlap
  • bit 11 SCALED_COMPONENT_OFFSET: The composite is designed to have the component offset scaled. Ignored if ARGS_ARE_XY_VALUES is not set.
  • bit 12 UNSCALED_COMPONENT_OFFSET: The composite is designed not to have the component offset scaled. Ignored if ARGS_ARE_XY_VALUES is not set.

Sounds intimidating. Let's look what happens if we ignore the position and use only bit 5 and grab all components.

Javascript Editor

Unfortunately it still does not work.

Javascript Editor

The original Computer Modern TrueType font does not have composing glyphs. There are glyphs for accents, but the font does not compose it. Unicode knows the concept of combining letters, but the accents are at position 0x300 ff, not where they are in the Computer Modern font. I am afraid we will not use the original fonts, but create light variations of the CMU fonts containing only Latin characters.

My Journey to PostScript