Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

New line pixel distance in FreeType?

I try to render text in OpenGL and FreeType2 and I don't know how to get the space (in pixels) between every line when I render fonts. When I parse the text I want to be able to do something like

const char *text = "some text\n here";

for(char *p = text; *p; p++)
{
  if(*p == '\n')
  {
    y -= newLineDistance;
    continue;
  }

  ...//render text here
}

At first I used

newLineDistance = face->glyph->metrics.vertAdvance >> 6;

But it doesn't work with some fonts as the docs also say it isn't reliable for non-vertical fonts (Chinese etc.)

like image 656
Pilpel Avatar asked Jan 18 '15 12:01

Pilpel


People also ask

What is glyph advance?

The advance of a glyph is the distance from the glyph's origin to the origin of the next glyph along the baseline, which is either vertical or horizontal. Note that, in a GlyphVector , the distance from a glyph to its following glyph might not be the glyph's advance, because of kerning or other positioning adjustments.


2 Answers

There is no need to calculate the line spacing because FreeType already provides it. Calculating it yourself might also produce erroneous results since it is artist defined. For example, the lowest part of a lower case 'g' may extend below the highest part of an upper case 'G' on the following line.

From the docs: http://www.freetype.org/freetype2/docs/tutorial/step2.html

height

This field represents a default line spacing (i.e., the baseline-to-baseline distance) when writing text with this font. Note that it usually is larger than the sum of the ascender and descender taken as absolute values. There is also no guarantee that no glyphs extend above or below subsequent baselines when using this distance – think of it as a value the designer of the font finds appropriate.

How to use it:

// initialise freetype
FT_Library ft; 
FT_Init_FreeType(&ft);
// load a font
FT_Face face;
FT_New_Face(ft, "path_to_font.ttf", 0, &face);
// set the font size, e.g. 48 pixels
FT_Set_Pixel_Sizes(face, 0, 48);
// get the default line spacing, note that it is measured in 64ths of a pixel
int line_spacing = face->height;
// get the scaled line spacing (for 48px), also measured in 64ths of a pixel
int scaled_line_spacing = face->size->metrics.height;
like image 113
Fibbs Avatar answered Oct 07 '22 14:10

Fibbs


What do you mean non-vertical fonts? Fonts are not really horizontal or vertical, but you can arrange the glyphs vertically or horizontally when you go to print some text. You will find that for most fonts, glyphs store both sets of properties (horizontal and vertical advance) so that you can arrange text horizontally or vertically at your choosing.

You would not use the glyph's advance if you are drawing your text horizontally, the advance is for spacing between characters in a string of text. For spacing between lines what you really want is to know the maximum ascent and descent (distance above / below the baseline) so that your lines do not overlap.

You can actually compute the required spacing between lines without knowing any of the characters in the string. This can be done if you know the character with the greatest ascent and descent in your font. In Roman fonts the character with the greatest ascent is generally T and the character with the greatest descent is g. I have zero familiarity with Chinese, so I could not tell you a general rule of thumb there, but I am sure there is one.

Take a close look at the following diagram from FreeType 2 (horizontal):

  http://www.freetype.org/freetype2/docs/tutorial/metrics.png

In the diagram above, the ascent for the letter g is measured by bearingY and the descent can be calculated as bearingY - height. The minimum spacing between lines will be the sum of the maximum ascent and descent for every glyph in the line. Keep in mind, it is better to generalize this for your entire font and keep the spacing consistent than to actually compute it for every string you print (your lines would wind up shifting vertical position depending on which characters they contained).

like image 32
Andon M. Coleman Avatar answered Oct 07 '22 16:10

Andon M. Coleman