JDK-8269888: Thai text rendered incorrectly using some AffineTransform-derived fonts

Philip Race philip.race at oracle.com
Wed Oct 9 15:48:22 UTC 2024


That test was from an internal SQE test suite, and there's nothing I 
have to open source.
But it was reproducible with just things like printing a JTable and 
unrelated to Thai/complex text.
It is a painful issue where Swing needs to be told to layout text at 
printer resolution when "printing the UI contents".
If you don't, then glyphs overlap, even for simple Latin "abc" text. Or 
if they don't overlap the string is clipped.
So unrelated.

-phil

On 10/9/24 6:09 AM, Daniel Gredler wrote:
> Hi Phil,
>
> I've noticed that quite a few AWT / client lib tests have been open
> sourced over the past few weeks. That's great for those of us trying
> to contribute from outside of Oracle, so thanks for that!
>
> I wanted to follow up on this Thai rendering bug and check to see
> whether the tests for JDK-8145901 have been (or will be) open sourced
> as part of this effort. I'd still like to try to fix this bug at some
> point, and a fix would require less coordination if those tests were
> available publicly.
>
> Thanks!
>
> Daniel
>
>
>
>
> On Wed, Sep 8, 2021 at 8:39 PM Philip Race <philip.race at oracle.com> wrote:
>> JDK-8145901 isn't accessible because some confidential information is in the description and attachments ..
>> and in fact it was JCK failure so we need to be careful not to regress that
>> But I guess you found the changeset for it.
>>
>> The problem we were trying to solve there was
>> ===
>> The font interface supplied to harfbuzz is setting the point size (scale)
>> based on the device size font. When printing, this is scaled from the
>> user size font by (typically) around 4X.
>> So when performing a kerning adjustment the affected glyphs are
>> moved accordingly.
>>
>> But advances are being provided in user space and so the kerning
>> adjustment is too great relative to the advances.
>> ====
>>
>> I'd need to spend some time refreshing my memory on this 5 yr old issue
>> so I can't say offhand that what you propose won't need fix up elsewhere.
>>
>> But I can say that testing this will need to do on screen rendering as well as
>> printing of kerned and ligatured text under various tranforms .. inc. rotations, scales,
>>
>> -phil.
>>
>>
>> On 9/7/21 4:43 PM, Daniel Gredler wrote:
>>
>> 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
>>
>>



More information about the client-libs-dev mailing list