JDK-8208377 : Soft hyphens render if not using TextLayout
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 9,10,11,12
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_10
  • CPU: x86_64
  • Submitted: 2018-07-26
  • Updated: 2025-05-12
  • Resolved: 2025-02-11
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 25
25 b10Fixed
Related Reports
Causes :  
Causes :  
Duplicate :  
Relates :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Java 9 or 10 (did not test Java 11 ea)

A DESCRIPTION OF THE PROBLEM :
If kerning is enabled for a java.awt.Font instance, soft hyphens are not painted and the width of them is measured as 0 in Java 9+.

REGRESSION : Last worked in version 8u181

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create an AWT font with enabled kerning. Get width of a soft hyphen or try to paint it.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Soft hyphens should be painted and width should be greater than 0.
ACTUAL -
Soft hyphens are not painted and measured width is 0.

---------- BEGIN SOURCE ----------
import java.awt.Font;
import java.awt.font.FontRenderContext;
import java.awt.font.TextAttribute;
import java.util.Collections;

public class Worker {
    public static void main(String[] args) throws Exception {
        String SOFT_HYPHEN = Character.toString((char)173);
        FontRenderContext frc = new FontRenderContext(null, false, true);
        
        Font font = new Font("Arial",0,16); // on non-windows system use propriate system font name
        Font kerningFont = font.deriveFont(Collections.singletonMap(TextAttribute.KERNING, TextAttribute.KERNING_ON));
        
        System.out.println(font.getStringBounds(SOFT_HYPHEN, frc).getWidth());
        System.out.println(kerningFont.getStringBounds(SOFT_HYPHEN, frc).getWidth()); //Should be same as above but is 0 in Java 9+
    }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Measure and paint soft hyphens with alternative instance of java.awt.Font.

FREQUENCY : always



Comments
Changeset: 41bdc47d Branch: master Author: Daniel Gredler <dgredler@openjdk.org> Committer: Phil Race <prr@openjdk.org> Date: 2025-02-11 00:39:09 +0000 URL: https://git.openjdk.org/jdk/commit/41bdc47d71340e5d7f4317a5040521868d4c4314
11-02-2025

A pull request was submitted for review. Branch: master URL: https://git.openjdk.org/jdk/pull/22670 Date: 2024-12-10 20:09:09 +0000
10-12-2024

Yes, performance matters here. Currently we have public static final int MIN_LAYOUT_CHARCODE = 0x0300; but unfortunately .. soft hyphen is U+00AD and we use MIN_LAYOUT_CHARCODE in other files too to short cut even calling isComplexCharCode() So there needs to be some thought about what to do here. MIN_LAYOUT_CHARCODE needs to be reduced or its usage eliminated or replaced.
09-12-2024

[~prr] I might take a stab at this one. Is it OK to check `Character.getType(code) == Character.FORMAT` in `sun.font.FontUtilities.isComplexCharCode(int)`, or do the code range checks need to be hard-coded because of performance concerns?
07-12-2024

In fact the behaviour being described for JDK 9 and kerning is correct. The bugs are that 1) JDK 8 did not do the same 2) We are not rendering identically in the cases of kerning vs no kerning Kerning is invoking layout functionality so harfbuzz gets to run the glyphs. It then correctly replaces it with a zero-width glyph. The only place that a soft hyphen may be visible is when it actually is rendered at a line break and even then whether and how it is rendered is script dependent. See https://bugs.openjdk.java.net/browse/JDK-6446472 which documents this and also https://www.unicode.org/L2/L2002/02279-muller.htm So the "fix" is probably not what the submitter wants - we need to send any string with this char down the TextLayout path so even if kerning isn't used we'll implicitly invoke layout and it will be rendered as invisible.
04-10-2021

When Font.getStringBounds() is called with KERNING text atribute, the check for "simple" text returns false so TextLayout is used instead of FontDesignMetrics. TextLayout calls fastInit() which calls TextLayout.fastCreateTextLine() to create a TextLine object which calls init() which gets the value of "Advance" by calling ExtendedTextSourceLabel.getAdvance(). The getAdvance() gets the logical bounds of the chosen GlyphVector by calling getGV().getLogicalBounds(). getGV() creates GlyphLayout which invokes "harfbuzz" layout engine via shape() native JNI call. Now, getAdvance() for this "-" string with kerning returns 0.0. It seems shape() harfbuzz method calls storeGVData() with advX, advY but those are 0. We do call hb_feature_from_string(kern, -1, &features[featureCount++]); to apply kerning if "kerning" attribute is present so not sure why it is not calculating the advance properly.
20-09-2018

> Interestingly, jdk12 fails for both icu and harfbuzz JDK 12 does not have ICU ! So the system property is a no-op. In fact it was removed in JDK 10 : https://bugs.openjdk.java.net/browse/JDK-8183978
10-08-2018

Regression of JDK-8143177 PRSADHUK-IN+prsadhuk@PRSADHUK-IN /cygdrive/d/Vbox_Shared/JDK $ ./jdk9-b96/bin/java -Dsun.font.layoutengine=icu Worker 5.328125 5.328125 PRSADHUK-IN+prsadhuk@PRSADHUK-IN /cygdrive/d/Vbox_Shared/JDK $ ./jdk9-b96/bin/java -Dsun.font.layoutengine=harfbuzz Worker 5.328125 0.0 Interestingly, jdk12 fails for both icu and harfbuzz PRSADHUK-IN+prsadhuk@PRSADHUK-IN /cygdrive/d/Vbox_Shared/JDK $ /cygdrive/d/jdk10/client/build/windows-x86_64-normal-server-fastdebug/jdk/bin/java -Dsun.font.layoutengine=icu Worker 5.328125 0.0 PRSADHUK-IN+prsadhuk@PRSADHUK-IN /cygdrive/d/Vbox_Shared/JDK $ /cygdrive/d/jdk10/client/build/windows-x86_64-normal-server-fastdebug/jdk/bin/java -Dsun.font.layoutengine=harfbuzz Worker 5.328125 0.0
31-07-2018

In JDK 9 and above with kerning enabled for a java.awt.Font instance, soft hyphens are not painted and the width is measured as 0. Results: =========================== 8u181: OK 9: Fail 10.0.2: Fail 11 ea b24: Fail 12 ea b04: Fail Output with JDK 8u181: JDK 8u181: >java Worker 5.328125 5.328125 Output with JDK 12 ea b04: >java Worker 5.328125 0.0 This is a regression in JDK 9 and above.
27-07-2018