When combining Latin with Asian, the Latin glyphs are shifted upwards on Windows

I’m experiencing a strange issue when combining Asian and Latin glyphs on Windows. I’m using CAIRO_FONT_TYPE_FT on Windows so I think it can’t be related to GDI or DirectWrite.

This is what it looks like on Linux: (as you can see both the Chinese and the Latin characters are nicely aligned)

But on Windows it looks like this: (the Latin characters are shifted upwards)

Is this a problem in my code or a bug in Pango or Cairo?

Here’s my test code:

#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_BITMAP_H

#include <pango/pangocairo.h>
#include <pango/pangoft2.h>

int main(int argc, char *argv[])
{
	PangoContext *context;
	PangoLayout *layout;
	PangoFont *font;
	PangoFontDescription *fontdesc;
	PangoFontMap *fontmap;
	PangoRectangle rc;
	cairo_surface_t *surf;
	cairo_t *cr;
	cairo_matrix_t cm;
	
	fontmap = pango_cairo_font_map_new_for_font_type(CAIRO_FONT_TYPE_FT);
	fontdesc = pango_font_description_from_string("Arial 144px");
	
	context = pango_font_map_create_context(fontmap);
	layout = pango_layout_new(context);
		
	pango_layout_set_font_description(layout, fontdesc);
	
	font = pango_font_map_load_font(fontmap, context, fontdesc);
				
	pango_layout_set_markup(layout, "德意志聯:Hello World", -1);
	pango_layout_get_pixel_extents(layout, &rc, NULL);

	surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rc.width, rc.height);

	cr = cairo_create(surf);
	
	cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
	
	cairo_matrix_init(&cm, 1, 0, 0, 1, -rc.x, -rc.y);
	cairo_set_matrix(cr, &cm);
	
	pango_cairo_show_layout(cr, layout);
	cairo_surface_flush(surf);
	
	cairo_surface_write_to_png(surf, "test.png");
	
	cairo_destroy(cr);
	cairo_surface_destroy(surf);
	
	g_object_unref(font);
	g_object_unref(layout);
	g_object_unref(context);
	g_object_unref(fontmap);
	pango_font_description_free(fontdesc);
	
	return 0;
}

Thanks for the report!

The issue is reproducible with the Arial font, but not with Segoe UI. So I started looking for differences between the two cases.

I tracked it down to pango-layout.c: apply_baseline_shift(). The calls to hb_ot_layout_get_baseline_with_fallback() return very different baseline offsets. Not sure if the issue is in Harfbuzz, will look further

See hb_ot_layout_get_baseline_with_fallback

By changing the main font, the fallback font changes as well. That is reasonable, since fallbacks are chosen to be similar to the main font. Using the steps outlined from How to find all fonts used in a PangoLayout - #3 by pangocoder we can see that:

  • When Arial is specified, the chinese item is rendered using MS Gothic 108
  • When Segoe UI is specified, the chinese item is rendered using Yu Gothic UI 108

Turns out hb_ot_layout_get_baseline_with_fallback returns a wrong baseline for MS Gothic. I have now opened Wrong value from hb_ot_layout_get_baseline_with_fallback() w/ MS Gothic font · Issue #4311 · harfbuzz/harfbuzz · GitHub

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.