craspberry-pifreetypefreetype2

Segmentation fault on FT_Set_Pixel_Sizes


I'm trying to build a program for a raspberry pi that prints text to a small SPI LCD screen and I want to set the font using truetype fonts and the FreeType API. When I try to set the font size I run into segmentation faults. If I don't include FT_Set_Pixel_Size then I get errors back from FT_Load_Glyph and other posts have linked this to not having the font size set.

#include <freetype2/ft2build.h>
#include FT_FREETYPE_H

void display_draw_text(int x, int y, const char* text) {
    FT_Library lib;
    FT_Face face;
    int error;
    error = FT_Init_FreeType (&lib); 
    if(error)
    {
        printf("Init FreeType error %d", error);
    } 
    error = FT_New_Face (lib, FONT_FILE, 0, &face);
    if(error)
    {
        printf("FT Face error %d", error);
    }
    error = FT_Set_Pixel_Sizes(
          face,    /* handle to face object         */
          (FT_UInt)0,      /* char_height in 1/64 of points */
          (FT_UInt)16);   /* vertical device resolution    */
    if(error)
        printf("Pixel Error %d", error);

    while (*text) 
    {
        char c = *text++;
        if (c < 32 || c > 126) c = '?';
        FT_UInt gi = FT_Get_Char_Index(face, c);
        printf ("%d -> %04X\n", gi, c);
        error = FT_Load_Glyph (face, (FT_UInt)gi, FT_LOAD_DEFAULT);
        if(error != 0)
            printf("Load Glyph Failed %d\n", error);
        int bbox_ymax = face->bbox.yMax / 64;
        int glyph_width = face->glyph->metrics.width / 64;
        int advance = face->glyph->metrics.horiAdvance / 64;
        int x_off = (advance - glyph_width) / 2;
        int y_off = bbox_ymax - face->glyph->metrics.horiBearingY / 64;
        for (int i = 0; i < (int)face->glyph->bitmap.rows; i++)
        {
            // row_offset is the distance from the top of the framebuffer
            //   of the text bounding box
            int row_offset = y + i + y_off;
            for (int j = 0; j < (int)face->glyph->bitmap.width; j++)
              {
              unsigned char p =
                face->glyph->bitmap.buffer [i * face->glyph->bitmap.pitch + j];

              // Don't draw a zero value, unless you want to fill the bounding
              //   box with black.
              if (p)
              {
                display_draw_pixel(x + j +x_off, row_offset, COLOR_BLACK);
            }
              }
        }
      // Move the x position, ready for the next character.
      x += advance;
    }
}     

Solution

  • The below line loads glyph as a vector contours. It does not rasterize the glyph image to a bitmap.

    error = FT_Load_Glyph (face, (FT_UInt)gi, FT_LOAD_DEFAULT);
    

    Therefore face->glyph->bitmap.buffer is NULL and access to it gives segmentation fault.

    You can rasterize glyph at the very load time:

    FT_Load_Glyph (face, (FT_UInt)gi, FT_LOAD_RENDER);
    

    BTW

    If you will turn on warning flags for compilation, it will give you many interesting insights. Most important ones is that your code freely converts between signed unsigned type values. This will result in problems later on.