Hi all, I'm trying to figure out a fix for JDK-8269888 [1]. The font that I'm using to replicate the issue, Google Noto Sans Thai Regular [2], uses the GPOS table internally. It looks like the GPOS adjustment in HB is a two-step process, where HB first sets the glyph position x_offset using anchor data from the GPOS table [3], and then adjusts that x_offset using existing x_advance data [4], all coordinated via the HB_BUFFER_SCRATCH_FLAG_HAS_GPOS_ATTACHMENT scratch flag.
Internally, OpenJDK is using the font_funcs virtual method functionality [5] to customize most of the font property callbacks [6]. Java provides users two ways to customize the size of a font: you can set the pt size, or you can set an affine transform (scale, rotate, shear, translate, etc). When you use the pt size approach, OpenJDK calls hb_font_set_scale with the appropriate pt size [7]. However, when a scaling affine transform is used, the pt size is technically unchanged, and a value of 1pt is used. Usually this works fine, because Java's font_funcs callbacks are providing scaled origin and advance numbers back to HB, but this breaks the two-step GPOS attachment logic: the first step is not aware of the scaling applied by the OpenJDK font_funcs callbacks (especially the hb_font_get_glyph_h_advance_func_t), but the second step uses a scaled advance value provided by an OpenJDK callback. In practice, at e.g. x50 scaling, this means that the first step sets the x_offset to a relatively small value (e.g. 32899), but the second step adjusts the x_offset by a relatively large value (e.g. 1612184). A possible fix would be for OpenJDK to take the affine transform scale into account when setting the font size via hb_font_set_scale, and the HarfBuzz team has confirmed that this seems like the sensible approach [8]. In fact, it seems like prior to 2016 this was indeed the case [9], but the logic was changed to fix JDK-8145901 (Printed content is overlapping). JDK-8145901 doesn't seem to be public in the bug tracker, and I'm not sure where to find the HB_NODEVTX trigger used to request initialization of devScale in HBShaper.c, so I'm not sure how to fix JDK-8269888 without risking a regression on JDK-8145901. Is devScale still needed? Can we use xPtSize and yPtSize (instead of ptSize*devScale) in _hb_jdk_font_create() and _hb_jdk_ct_font_create()? I've confirmed that using xPtSize and yPtSize fixes the Thai text rendering use case, at least. Thanks! Daniel [1] https://bugs.openjdk.java.net/browse/JDK-8269888 [2] https://www.google.com/get/noto/#sans-thai [3] https://github.com/harfbuzz/harfbuzz/blob/bbeb3a62b0efbb598d8683f7c4b6cc7069a58aeb/src/hb-ot-layout-gpos-table.hh#L708 [4] https://github.com/harfbuzz/harfbuzz/blob/bbeb3a62b0efbb598d8683f7c4b6cc7069a58aeb/src/hb-ot-layout-gpos-table.hh#L2922 [5] https://harfbuzz.github.io/fonts-and-faces-custom-functions.html [6] https://github.com/openjdk/jdk/blob/005d8a7fca8b4d9519d2bde0a7cdbbece1cd3981/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc#L271 [7] https://github.com/openjdk/jdk/blob/005d8a7fca8b4d9519d2bde0a7cdbbece1cd3981/src/java.desktop/share/native/libfontmanager/hb-jdk-font.cc#L422 [8] https://github.com/harfbuzz/harfbuzz/discussions/3191 [9] https://github.com/openjdk/jdk/commit/5935292ae022e970bd4075de4d704719f3b05575#diff-6a155985752d3cc5ca8a74d4bf51c899d80ea0337e30029a4fafe856893456f3L327-L328
