Hello there,

I’m currently trying to fix Blender’s text vertical alignment feature. I originally implemented this feature in Blender for the e-interiores project. What I had was perfect for my needs at the time. However let’s look at one of the trickiest ones: centered alignment.

The expected result would be to have the text center to be in-between the lowercase texts give it or take, yet it’s way off. What happens is that the code is taking into account the line size, and making sure the text base-line is located mid-way into the line height. As an example, let’s see how Google Slides handles vertical alignment:

I changed the text background color, so it is more obvious what is going on. Basically we have a “box” where the text fits in, and then this box is vertically centralized. That rises the question, how to determine this box dimensions? As it turn out these are called ascent and descent.

Ascent: The recommended distance from the baseline to the line above.
Descent: The recommended distance from the baseline to the line below.

In this example, using the Indie Flower font we have descent of about 20%, and ascent the 80% left. According to FontForge this is indeed correct – there I get 819 and 205 as their values:

However, and now it is the caveat, with freetype2 I’m getting 994 and (-)500 (67% and 33%). And why does it matter? Well, Blender uses freetype2 for its internal font management, so it matters big time.

I even scrapped a simple freetype2 example to test it isolated from Blender, and the result is the same.

/**
 * Example of FreeType2 library usage.
 *
 * How to build:
 * gcc example.c -o example -I/usr/include/freetype2 -lfreetype example.c
 */


#include <ft2build.h>
#include FT_FREETYPE_H

int main(int argc, char** argv) {
  FT_Library library;
  FT_Face face;

  /* Error handling is non-existent in this example. */
  FT_Error error;

  char* filename;

  if (argc != 2) {
    fprintf(stderr, "usage: %s font\n", argv[0]);
    exit(1);
  }

  /* First argument. */
  filename = argv[1];

  /* Initialize library. */
  error = FT_Init_FreeType(&library);

  /* Create face object. */
  error = FT_New_Face(library, filename, 0, &face);

  const short em_size = face->ascender - face->descender;
  const float descender = -(float)face->descender / em_size;
  const float ascender = 1.0f - descender;

  printf("Descender: %d (%4.2f)\n"
         "Ascender: %d (%4.2f)\n",
         face->descender,
         descender,
         face->ascender, ascender);

  FT_Done_Face(face);
  FT_Done_FreeType(library);

  return 0;
}

For the records, the final alignment change is something like:

  /* Offset from baseline. */
  float y_offset = descent - (em_size * 0.5f);

But I still need to figure out the correct way to get the ascent/descent from freetype2.
 
My best guess at the moment is that face->ascender is not the ascent but something else altogether.

Wish me luck!

Update : I decided to contact the freetype developers, I will post an update here once I hear back from them.

Update 2 : I got a reply by FontForge developer Khaled Hosny.

As it turned out, FontForge was using the hardcoded values (80%) when opening ttf files, and the proper Font ascent could be found in a different tab there (Font Info → OS/2 → Metrics) instead of (Font Info → General).

The baffling part of all this, is that Google Slides do seem to be using the same 80% value for their internal padding. I may as well hardcode it in Blender and move on. The results may be good enough (definitively better than what I get from using the real ascent/descent).

つづく

3 Thoughts on “Font ascent, descent and freetype2

  1. Vivek Rajwanshi on August 29, 2018 at 5:20 am said:

    Good Work and Good Luck!!!

  2. Lawrence D’Oliveiro on August 29, 2018 at 10:18 pm said:

    You can do vertical alignment two ways, either using the overall font metrics or the specific metrics of the text you are trying to align.

    I did a comparison here https://www.deviantart.com/default-cube/art/Text-Vert-Align-520839470 of the two methods, and I think the font-metrics method is preferable (as well as being more consistent).

  3. dfelinto on August 31, 2018 at 1:25 pm said:

    Right, thanks. I end up implementing the “metric” method indeed. It was hard because I was using some random fonts and some of them behave really erradic.

    In the end I downloaded the Microsoft fonts (arial, verdana, Times, …) and I’m happy with the result. There is no silver bullet here, but I hope it works for most people.

    The patch was submitted for review here: https://developer.blender.org/D3666

Leave a Reply

Your email address will not be published. Required fields are marked *

Post Navigation