Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong value from hb_ot_layout_get_baseline_with_fallback() w/ MS Gothic font #4311

Open
lb90 opened this issue Jul 6, 2023 · 3 comments
Open

Comments

@lb90
Copy link
Contributor

lb90 commented Jul 6, 2023

Hi! It seems that hb_ot_layout_get_baseline_with_fallback() is returning wrong baseline values for the MS Gothic font (C:\Windows\Fonts\msgothic.ttc). We discovered that while investigating an issue with text layout in Pango, see https://discourse.gnome.org/t/when-combining-latin-with-asian-the-latin-glyphs-are-shifted-upwards-on-windows/16010/2.

Consider the following sample:

#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <assert.h>

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

#define BASE_DIR \
"C:/Windows/Fonts"

#define FONT_PATH(filename) \
(BASE_DIR "/" filename)

#define NUM_ELEMENTS(arr) \
(sizeof (arr) / sizeof (arr[0]))

const int SCALE = 144 * 1024;
const float PTEM = 108.0f;

static void
print_baseline (const char *path,
                unsigned int index)
{
  hb_blob_t *blob = hb_blob_create_from_file (path);
  hb_face_t *face = hb_face_create(blob, index);
  hb_font_t *font = hb_font_create(face);
  hb_position_t baseline = 0;

  hb_font_set_scale (font, SCALE, SCALE);
  hb_font_set_ptem (font, PTEM);

  hb_ot_layout_get_baseline_with_fallback (font,
                                           HB_OT_LAYOUT_BASELINE_TAG_IDEO_FACE_BOTTOM_OR_LEFT,
                                           HB_DIRECTION_LTR,
                                           HB_TAG ('h','a','n','i'),
                                           0,
                                           &baseline);

  printf ("* %s (index %u)\n", path, index);
  printf ("  baseline BOTTOM_OR_LEFT: %d\n", (int) baseline);

  hb_blob_destroy (blob);
  hb_face_destroy (face);
  hb_font_destroy (font);
}

int main()
{
  struct {
    const char *path;
    unsigned int index;
  } tests[] = {
    {FONT_PATH ("msgothic.ttc"), 0},
    {FONT_PATH ("YuGothM.ttc"), 0},
    {FONT_PATH ("YuGothM.ttc"), 1},
    {FONT_PATH ("BIZ-UDGothicB.ttc"), 0},
    {FONT_PATH ("BIZ-UDGothicB.ttc"), 1},
    {FONT_PATH ("GOTHIC.TTF"), 0}
  };

  for (size_t i = 0; i < NUM_ELEMENTS (tests); i++)
    print_baseline (tests[i].path, tests[i].index);
}

Note: 📝 the code can run on Linux, just mount a Windows partition and change BASE_DIR accordingly UPDATE: nope, you really need Windows: https://bugzilla.redhat.com/show_bug.cgi?id=1377049. Try running stat /mnt/windows/Windows/Fonts/msgothic.ttc and see if you get unsupported reparse tag 0x80000017

We get the following values:

$ ./test-hb-get-baseline.exe
* C:/Windows/Fonts/msgothic.ttc (index 0)
  baseline BOTTOM_OR_LEFT: 14745
* C:/Windows/Fonts/YuGothM.ttc (index 0)
  baseline BOTTOM_OR_LEFT: -10296
* C:/Windows/Fonts/YuGothM.ttc (index 1)
  baseline BOTTOM_OR_LEFT: -10296
* C:/Windows/Fonts/BIZ-UDGothicB.ttc (index 0)
  baseline BOTTOM_OR_LEFT: -2967
* C:/Windows/Fonts/BIZ-UDGothicB.ttc (index 1)
  baseline BOTTOM_OR_LEFT: -2967
* C:/Windows/Fonts/GOTHIC.TTF (index 0)
  baseline BOTTOM_OR_LEFT: -14393

The first value doesn't seem right : 14745.

Interestingly, if we pass 'Hani' instead of 'hani', then the issue doesn't occur anymore:

$ ./test-hb-get-baseline.exe
* C:/Windows/Fonts/msgothic.ttc (index 0)
  baseline BOTTOM_OR_LEFT: -5991
* C:/Windows/Fonts/YuGothM.ttc (index 0)
  baseline BOTTOM_OR_LEFT: -10296
* C:/Windows/Fonts/YuGothM.ttc (index 1)
  baseline BOTTOM_OR_LEFT: -10296
* C:/Windows/Fonts/BIZ-UDGothicB.ttc (index 0)
  baseline BOTTOM_OR_LEFT: -2967
* C:/Windows/Fonts/BIZ-UDGothicB.ttc (index 1)
  baseline BOTTOM_OR_LEFT: -2967
* C:/Windows/Fonts/GOTHIC.TTF (index 0)
  baseline BOTTOM_OR_LEFT: -14393

However Pango relies on hb_ot_tags_from_script_and_language() to get the language and script tags, and that function returns 'hani'.

@behdad
Copy link
Member

behdad commented Jul 7, 2023

Humm. This seems to be a bad baseline value in the font. For script hani and baseline tag ideo it has value 0, which is wrong in my understanding. Other fonts I tried had negative values there.

Short of adding a conditional to filter out zero in the code, I don't see a way to fix this.

cc @matthiasclasen

@behdad
Copy link
Member

behdad commented Jul 7, 2023

BTW, you can get the same info using hb-info utility.

@behdad
Copy link
Member

behdad commented Jul 7, 2023

I'm actually now confused and not sure anymore, how the baseline numbers are to be used across fonts. See this section:
https://learn.microsoft.com/en-us/typography/opentype/spec/base#example-3b-baseline-values-for-four-scripts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants