2

I am trying to predict how wide the text will appear rendered by pango library but I am trying to achieve it in bare Freetype for performance sake.

To answer the commenters - yes I measured performance with the callgrind tool. And pango is spending most of its time in fontconfig, which is impossible to work around. The pango_layout_get_extents is also not terribly fast. Meanwhile freetype's performance is blazingly fast - yet results inaccurate due to lack of proper settings perhaps. Unfortunately I am unable to post rendered bitmaps since I do only plain measurements - but it might be a worthwhile endeavour to implement is for comparison's sake. The rendering in my use case is done by a web browser in SVG and my only need is to predict what length the rendered text will be - hence not providing bitmaps in the question since I have no rendering code.

My test program run:

> ./freetype_text /usr/share/fonts/truetype/verdana.ttf "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
Width: 374

However .. the same text at font size 10 (72dpi) is rendered in pango with 340px. The measurement is by a common method of measuring the layout with:

PangoRectangle logical_rect = {0, 0};
pango_layout_get_extents (layout, NULL, &logical_rect);

What could be the reason for differences I am observing? The differences I observe range from 0%-15%.

Below is my freetype testing program (compile with gcc freetype_text.c $(pkg-config --cflags --libs freetype2))

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_OUTLINE_H
#include FT_STROKER_H
#include FT_GLYPH_H
#include FT_TRUETYPE_IDS_H

static FT_Library library;

int main(int argc, char** argv)
{
    FT_Error error = FT_Init_FreeType( &library );
    if ( error ) {
        return 1;
    }
    int i;

    FT_Face face;
    error = FT_New_Face( library, argv[1], 0, &face );
    if(error) {
        return 2;
    }
    FT_Set_Pixel_Sizes(face, 0, 10);

    char* str = argv[2];
    wchar_t ch = 0;
    FT_GlyphSlot  slot = face->glyph;
    int w = 0;
    int previous = 0;
    while( (ch = *str) != 0) {
        int glyph_index = FT_Get_Char_Index( face, ch );

        error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT|FT_LOAD_NO_BITMAP);
        str++;  
        w += slot->advance.x;
        if(previous && glyph_index )
    {
      FT_Vector  delta;
      FT_Get_Kerning( face, previous, glyph_index, FT_KERNING_DEFAULT, &delta );
            w += delta.x ;
    }
        previous = glyph_index;
    }
    printf("Width: %i\n", w/64);

    return 0;
}
RushPL
  • 4,732
  • 1
  • 34
  • 44
  • 1
    Post images showing the text rendered by both methods. I'm guessing kerning. Are you sure there is a performance difference? Are you sure it matters for you? Did you measure? – Jacob Parker Mar 16 '13 at 22:00
  • 2
    As an aside, you should be aware that FreeType alone is *not capable* of correct text rendering, since it requires as input a sequence of glyphs, not a sequence of characters. You'll at least need harfbuzz to convert character strings to glyph strings for you. It's possible that the discrepency has something to do with this, e.g. if the font in question has ligatures for some of the character sequences contained in your string. – R.. GitHub STOP HELPING ICE Mar 17 '13 at 00:14
  • Thanks for comments. As you see you I am trying to actually apply kerning. I have answered your comments in the question itself. I just read about harfbuzz - wouldn't it be an overkill for latin languages? As for the glyphs - `FT_Get_Char_Index` covers that. For 7-bit ASCII the `char` matches the `UTF-32` which this function requires. – RushPL Mar 17 '13 at 08:44
  • If you are worried about performance before you can even draw the text you are putting the cart before the horse. If you render the text you can see for yourself why the width is different and others can give tips. This is debugging 101. – Jacob Parker Mar 17 '13 at 13:48
  • With all due respect, you don't know about my use case - but for your information, rendering will not be done by me but by clients' machines. I would have written rendering code if I needed one but if I don't find a solution I will have to write it anyway (and scrap it). – RushPL Mar 17 '13 at 20:21
  • Rendering pango and freetype is easy and you won't have to guess why the width is different: you will be able to see. – Jacob Parker Mar 18 '13 at 17:22
  • Yes I am leaning to that approach, thanks. – RushPL Mar 18 '13 at 21:25
  • If rendering will be done elsewere, how can you be sure it will behave the same way as what you measured? There are many reasons why it would be different, for example different fonts or different configuration. – Uli Schlachter Mar 20 '13 at 12:56
  • Obviously I cannot be sure but from my tests, the results are good enough and close enough for the popular browsers and common font configurations. – RushPL Mar 20 '13 at 22:02
  • Kerning isn’t the answer — there wouldn’t be any kerning between capital W’s. Most likely the width differences are due to TrueType hinting, which changes the width of glyphs, most noticeably at small sizes. If I’m right, then the measurement discrepancy should abate at larger sizes (e.g., try 100 and 1000 pt rather than 10 pt). – Matthew Butterick May 22 '15 at 22:34

0 Answers0