Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Font Rendering with Glyph information

I call "GetCharABCWidthsFloatW" to get the width information for a character. With this I will get the leftside bearing, right side bearing and the advanced width.

For positioning each characters, I will start with a "xPlacement" variables that will begin at zero. I will first adjust the xPlacement variable by subtracting the "left side bearing". After the character is drawn, I will then advance it by the width of the character( I will show the calculation for this later). I will then move the xPlacement variable by adding the "right side bearing" information from the current "xPlacement".

This, in my opinion is all that should be code for character placement, correct?

An important thing is to correct the width of the characters. The width will be calculated by taking the advancedWidth, plus the POSITIVE version of the left side bearing and the POSITIVE version of the right side bearing. I will convert this values to positive, if they are negative so I can have the total width of the character.

Here is some pseudo code about how it is generated.

float xPlacement = 0.0f;
for(int i = 0; i < strlen(text); ++i)
{
 char charValue = text[i];
 GetCharWidthABC(.., .., charInfo);

 float posLeft = charInfo.leftSideBearing;
 if(charInfo.leftSideBearing < 0)
  posLeft = -charInfo.leftSideBearing;

 float posRight = charInfo.rightSideBearing;
 if(posRight < 0)
  posRight = -charInfo.rightSideBearing;

 float posWidth = posRight + posRight + charInfo.advancedWidth;

 float letterWidth = posWidth;

 xPlacement  -= charInfo.leftSideBearing;

 /* generated some vertex coordinates, using the xPlacement variable and letterWidth */

 xPlacement += letterWidth;
 xPlacement += charInfo.rightSideBearing
}

Does this appear to be the correct way to do this?

like image 584
jack Avatar asked Dec 23 '10 22:12

jack


2 Answers

Since C# is mentioned in the question tags, maybe you'll find some interest in looking at some very powerful classes that ship with .NET Framework (starting with version 3.0, in fact shipped with WPF core assemblies). They are:

  • GlyphTypeFace: Specifies a physical font face that corresponds to a font file on the disk., useful to parse a .TTF file and build glyphs from it.
  • GlyphRun: Represents a sequence of glyphs from a single face of a single font at a single size, and with a single rendering style, with many usefull properties and methods (for example, you can build a Geometry from it)
  • GlyphRunDrawing: Represents a Drawing object that renders a GlyphRun. Maybe less interesting for you because it's more tied to WPF rendering/composition system.

The two first classes are somewhat technology/device independant, except from the .NET Framework itself.

like image 147
Simon Mourier Avatar answered Sep 30 '22 20:09

Simon Mourier


Sounds about right, but the best way to see if it's right is to run it and look at the results with a variety of different fonts.

The left/right bearing values in the glyph metrics do not include kerning info. (kerning = allowing characters "snuggle up" or encroach upon the adjacent character cell box to eliminate distracting whitespace created by overhanging acenders or descenders).

Kerning data is specific to particular character pairs, and the order of the characters is significant. The kerning offset for "AV" may be different from the kerning offset for "VA" depending on the font. Some fonts do not include kerning data, some do.

For detailed info and rendering guidelines, check out the documentation of the FreeType library available for download on SourceForge. FreeType is a library of routines to handle loading of OpenType fonts (largely compatible with TrueType). The information in the FreeType docs is largely applicable to rendering TrueType in Win32 GDI.

Also test using bold and italic (and bold italic) font alternates, and mix and match fonts in the same line of text. This will show character spacing problems if your algorithm is missing something.

like image 42
dthorpe Avatar answered Sep 30 '22 19:09

dthorpe