OpenPDF icon indicating copy to clipboard operation
OpenPDF copied to clipboard

CJKsc font text artifact

Open teoshibin opened this issue 6 months ago • 2 comments

Describe the bug

The number characters are visually glitched when a CJKsc font is used. More specifically it will only be glitched when the a english letter is placed in front of it (which is x within my example, it can be anything else).

Issue https://github.com/LibrePDF/OpenPDF/issues/71 could be related to this.

To Reproduce

Here's the kotlin code to reproduce the problem. The first function produce the glitched pdf, the second and third produce none-glitched pdf. Make sure to replace <PATH> to the unzipped location of the font.

    private fun glitched() {
        FontFactory.register("<PATH>/NotoSansCJKsc-Regular.otf")
        val font = FontFactory.getFont("NotoSansCJKsc-Regular.otf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 9f, Font.NORMAL)
        val document = Document()
        val output = File("glitched.pdf").outputStream().buffered()
        PdfWriter.getInstance(document, output)
        document.open()
        val phrase = Phrase()
        phrase.add(Chunk("你好世界x1234567890", font))
        document.add(phrase)
        document.close()
    }

    private fun problemGone1() {
        FontFactory.register("<PATH>/NotoSansCJKsc-Regular.otf")
        val font = FontFactory.getFont("NotoSansCJKsc-Regular.otf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 9f, Font.NORMAL)
        val document = Document()
        val output = File("problem_gone_1.pdf").outputStream().buffered()
        PdfWriter.getInstance(document, output)
        document.open()
        val phrase = Phrase()
        phrase.add(Chunk("你好世界1234567890", font))
        document.add(phrase)
        document.close()
    }

    private fun problemGone2() {
        FontFactory.register("<PATH>/NotoSansCJKsc-Regular.otf")
        val font = FontFactory.getFont("NotoSansCJKsc-Regular.otf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 9f, Font.NORMAL)
        val document = Document()
        val output =  File("problem_gone_2.pdf").outputStream().buffered()
        PdfWriter.getInstance(document, output)
        document.open()
        val phrase = Phrase()
        // Adding another chunk before or after it causes the issue to disappear somehow. The order does not matter.
        phrase.add(Chunk("你好世界x1234567890", font))
        phrase.add(Chunk("你好世界1234567890", font))
        document.add(phrase)
        document.close()
    }

The problem can also be fixed by forcefully disabling basefont.isSubset before using the font, which will increase the file size.

font.baseFont.isSubset = false

Expected behavior

No visual glitch.

The work around I found is to either

  • Disable the subsetting for this font which increases the file size.
  • Use a different font by splitting the text into other chunks that uses a different font (e.g. NotoSans-Regular.ttf) whenever a character can be supported by that font (with my own multilingual auto font selection logic).

Screenshots

glitched.pdf Image

problem_gone_1.pdf Image

problem_gone_2.pdf Image

System

  • OS: MacOS
  • Font name: NotoSansCJKsc-Regular.otf
  • Font download: https://github.com/notofonts/noto-cjk/releases/tag/NotoSansV2.001
  • OpenPDF version: 2.0.1

Your real name

Shi Bin Teo

teoshibin avatar Jul 31 '25 12:07 teoshibin

Pull requests welcome. 谢谢你

andreasrosdal avatar Jul 31 '25 16:07 andreasrosdal

You can try LayoutProcessor, see https://github.com/LibrePDF/OpenPDF/wiki/Accents,-DIN-91379,-non-Latin-scripts

vk-github18 avatar Aug 07 '25 20:08 vk-github18