On Mon, 27 Apr 2026 21:08:16 GMT, Phil Race <[email protected]> wrote:

>> When rendering Thai text, scaling fonts via `deriveFont(float)` seems to 
>> always work correctly. However, when the font is scaled via 
>> `deriveFont(AffineTransform)`, the vowels above the main line of text are 
>> misplaced, mangling the meaning of the text.
>> 
>> This appears to be caused by GPOS adjustments performed by HarfBuzz which 
>> are calculated at the wrong scale if the full (point size + AffineTransform) 
>> scale is not provided to HarfBuzz upon font creation.
>> 
>> The fix must change both the FFM and JNI HarfBuzz integration code, so it 
>> looks a bit longer than it actually is. The FFM and JNI changes were made in 
>> separate commits, so it might be helpful to review only the FFM changes in a 
>> first pass, and then have a look at the corresponding JNI changes (which are 
>> in a separate commit).
>> 
>> Some observations:
>> 
>> - jdk_font_create_hbp() needs to incorporate font transform scaling, not 
>> just the font point size scaling
>> - jdk_font_create_hbp() needs two independent font scales / point sizes (x 
>> and y)
>> - jdk_font_create_hbp() applies devTx, only for it to be removed in 
>> store_layout_results(); we might as well leave devTx out from the start
>> 
>> Sequence of changes made to the FFM code:
>> 
>> - Replace SDCache.gtx (glyph transform = font transform without translation, 
>> plus point size scaling, plus device transform) with SDCache.ftx (font 
>> transform including translation, plus point size scaling)
>> - Remove SDCache.delta (just keep translation components in new ftx field 
>> instead)
>> - Remove SDCache.dtx (never used)
>> - Remove devScale from store_layout_results() parameters (dev scale no 
>> longer included during layout, so doesn't need to be undone here)
>> - Remove destroy function param from jdk_font_create_hbp() (never used, 
>> always NULL)
>> - Calculate x and y font point sizes in jdk_hb_shape (based on full font 
>> transform, including font pt size), instead of using only font pt size
>> - Pass these x and y point sizes into jdk_font_create_hbp()
>> - Remove now-unused ptSize parameter from jdk_font_create_hbp()
>> - Remove now-unused devScale parameter from jdk_font_create_hbp()
>> - Remove now-unused ptSize parameter from jdk_hb_shape()
>> - Remove now-unused ptSize parameter from HBShaper.shape()
>> 
>> Sequence of changes made to the JNI code:
>> 
>> - Remove destroy function from _hb_jdk_font_create(), not used just like in 
>> FFM code
>> - Use xPtSize and yPtSize in _hb_jdk_font_create(), instead of ptSize and 
>> devScale
>> - Remove devScale from storeGVData (not used during...
>
> JDK-8145901 has stuff in it I can't sanitize. 
> 
> This bug is from when we first integrated harfbuzz. My memory of this > 10 
> year old issue is extremely minimal.
> 
> The fix review thread is here
> https://mail.openjdk.org/archives/list/[email protected]/thread/RULT6RB3SW7DUXBU6YGFJ5FVHEJ6YJCL/
> 
> The problem was over-lapping text (plain old Latin) in Unix printing (ie our 
> postscript generation)
> So testing that would be the reequirement
> 
> Based on my comment in that review I probably thought people could read the 
> bug eval.
> I'll paste the pertinent part of it here (below).
> 
> ===
> 
> 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.
> 
> Everything needs to be consistent. The easiest thing to do
> is use the user space point size for the scale too.
> 
> The (maybe better) alternative is to make all the adjustments so that we
>  - keep xPtSize as the scale
>  - scale horizontal advance by xPtSize/ptSize
>  - de-scale the resulting glyph positions by the same
>  - make sure this is OK in the coretext code path too.
>  This would seem to cover most of what is reported above but Swing still
> does not "perfectly" print text due to using getJustifiedLayout after the 
> fact.
> ===

@prrace Thanks for the info. Can the test case in JDK-8145901 be run internally 
against this fix?

> The problem was over-lapping text (plain old Latin) in Unix printing (ie our 
> postscript generation)
> So testing that would be the reequirement

I did run `test/jdk/java/awt/print/PrinterJob/PrintTextTest.java` and use 
"print to file" on Linux both before and after this change, and the only 
difference seemed to be on "Page 10" (there are two printed pages generated per 
"page", so this was actually on pages 19 and 20) where the small ticks in the 
Devanagari text above the continuous horizontal line were actually slightly 
misplaced prior to this fix. They were also misplaced prior to this fix on the 
screen, but it's a bit harder to see on screen. So this PR actually fixes a 
hard-to-see issue in that test that affects both screen text and printed text. 
I didn't see any text overlap before or after the fix.

> Everything needs to be consistent.

Yep! This patch keeps things consistently in user space (simpler, because the 
existing code seems to try to adjust for device space and then undo it when the 
time comes to communicate results back to the Java layer in FFM-focused 
`store_layout_results` or JNI-focused `storeGVData`).

-------------

PR Comment: https://git.openjdk.org/jdk/pull/30953#issuecomment-4330814999

Reply via email to