Skip to content

Differences in glyph advances between FreeType and internal font functions #255

@khaledhosny

Description

@khaledhosny

Here is a small test program to compare glyph advances from FreeType and internal font function. No matter what font I try, the FreeType advances are sometimes bigger than internal ones by 1 unit, except at EM size. It seems to be a difference in rounding strategy, FreeType font functions are always rounding up, though I’m not sure if it is a bug in the font functions or in my code.

#include <hb.h>
#include <hb-ot.h>
#include <hb-ft.h>

hb_font_t*
getFontOt(char *filename, int size)
{
  FILE* file = fopen(filename, "rb");
  fseek(file, 0, SEEK_END);
  unsigned int length = ftell(file);
  fseek(file, 0, SEEK_SET);

  char* data = malloc(length);
  fread(data, length, 1, file);
  fclose(file);

  hb_blob_t* blob = hb_blob_create(data, length, HB_MEMORY_MODE_WRITABLE, (void*)data, NULL);
  hb_face_t* face = hb_face_create(blob, 0);
  hb_font_t* font = hb_font_create(face);

  hb_ot_font_set_funcs(font);
  hb_font_set_scale(font, size, size);

  return font;
}

hb_font_t*
getFontFt(char *filename, int size)
{
  FT_Library library;
  FT_Init_FreeType(&library);
  FT_Face face;
  FT_New_Face(library, filename, 0, &face);
  FT_Set_Char_Size(face, size, size, 0, 0);

  hb_font_t* font = hb_ft_font_create_referenced(face);

  return font;
}

int
main(int argc, char **argv)
{
  if (argc <= 2)
  {
    printf("Usage: %s font size\n", argv[0]);
    return 1;
  }
  hb_font_t* fontOt = getFontOt(argv[1], strtol(argv[2], NULL, 10) * 64);
  hb_font_t* fontFt = getFontFt(argv[1], strtol(argv[2], NULL, 10) * 64);

  for (int c = 0; c < 0xFFFF; c++)
  {
    hb_codepoint_t gid = 0;
    if (hb_font_get_glyph(fontOt, c, 0, &gid))
    {
      hb_position_t advanceOt = hb_font_get_glyph_h_advance(fontOt, gid);
      hb_position_t advanceFt = hb_font_get_glyph_h_advance(fontFt, gid);
      printf ("gid: %d\t=> ft: %d, ot: %d, diff: %d\n",
               gid, advanceFt, advanceOt, advanceFt - advanceOt);
    }
  }
}

For example:

$ ./advance amiri-regular.ttf 12
gid: 1533   => ft: 531, ot: 531, diff: 0
gid: 1534   => ft: 494, ot: 493, diff: 1
gid: 1535   => ft: 531, ot: 531, diff: 0
gid: 1536   => ft: 494, ot: 493, diff: 1
gid: 1537   => ft: 531, ot: 531, diff: 0

Compared to:

$ ./advance amiri-regular.ttf 2048
gid: 1533   => ft: 90688, ot: 90688, diff: 0
gid: 1534   => ft: 84288, ot: 84288, diff: 0
gid: 1535   => ft: 90688, ot: 90688, diff: 0
gid: 1536   => ft: 84288, ot: 84288, diff: 0
gid: 1537   => ft: 90688, ot: 90688, diff: 0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions