Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting truetype glyphs to OpenGL polygons

I am trying to create a conversion library for any installed truetype font into a series of polygons that can be used to display text in OpenGL. I use the GetGlyphOutline function to convert glyphs into a series of contours then triangulate (tesselate) these contours with the glu library.

It usually works but not always and there are weird exceptions. GetGlyphOutline is supposed to return outer contours first in a CW winding order and inner contours (holes) in CCW winding order. Depending on the font and the glyph, this is not the case unfortunately. Sometimes the outer contour is in a CCW winding order and holes are in CW, or although the winding order is correct, the order of contours returned by GetGlyphOutline is wrong (e.g. I get the 'holes' first then the outer contour).

I tried to adjust the conversion to check for these weird cases and if necessary reverse the vertices and winding order of a contour but seemingly there is no rule and if a character with 1 or 2 holes in it is OK with a few fonts, I always find an exception. E.g. with a font named MinionPro-BoldCn even the glyph for the number '8' is returned by GetGlyphOutline wrong and I end up with only one hole inside instead of two.

I also tried to use another method instead of GetGlyphOutline. I use GDI to render text into a path, then get the contours of that path using the GetPath function. The result is the same. There are fonts where certain characters are returned by GetPath with the wrong order of contours and/or with the wrong winding.

Does anyone have any experience with this and is there anything I can do?

like image 300
aronsatie Avatar asked Sep 05 '12 13:09

aronsatie


1 Answers

Maybe not a perfect workaround, but one idea (haven't thought of any counterexamples):

  1. Ignore the winding order
  2. Draw all glyphs into the stencil buffer, incrementing the stencil value by 1 each time a fragment is drawn.
  3. Draw a quad over the scene, filling in any pixel where the stencil buffer == 1.

My thinking is that any area not covered by the glyph will have stencil value == 0, any area inside the glyph will have a stencil value == 1, and any holes inside the glyph will have a stencil value == 2 (as they are covered by the original glyph and the "hole"). You can then filter by this to only draw areas where the stencil is equal to 1.

like image 193
Tim Avatar answered Oct 17 '22 12:10

Tim