java - 在 iText 中访问 OpenType 字形变体

标签 java pdf itext opentype

在 iText 中使用 OpenType 字体构建 PDF 文档时,我想从字体中访问字形变体——特别是表格图形。由于 OpenType 字形变体没有 Unicode 索引,我不确定如何指定我要使用一组特定的变体(表格图)或通过字形 ID 调用特定字形。只需寻找相关的 iText 类名(如果存在)。

最佳答案

这在最新的标签 5.5.8 中似乎都不可能。 , 也不在 master iText 的分支。

this article 中所述在微软的 OpenType font file specification , 字形变体存储在 Glyph Substitution Table (GSUB)的字体文件。访问字形变体需要从文件中读取这个表,这实际上是在类 com.itextpdf.text.pdf.fonts.otf.GlyphSubstitutionTableReader 中实现的。 ,虽然这个类现在被禁用了。

电话readGsubTable()在类(class) com.itextpdf.text.pdf.TrueTypeFontUnicode被注释掉了。

void process(byte ttfAfm[], boolean preload) throws DocumentException, IOException {
    super.process(ttfAfm, preload);
    //readGsubTable();
}

事实证明,该行被禁用是有原因的,因为如果您尝试激活它,代码实际上不起作用。

因此,很遗憾,没有办法使用字形变体,因为永远不会从字体文件中加载替换信息。

更新

最初的答案是关于使用 iText API 的可能性。用于访问开箱即用的字形变体,目前还没有。但是,低级代码已经到位,经过一些黑客攻击后可以使用它来访问字形替换映射表。

调用时read() , GlyphSubstitutionTableReader读取GSUB表并将所有特征的替换展平到一张 map 中Map<Integer, List<Integer>> rawLigatureSubstitutionMap . OpenTypeFontTableReader 当前丢弃了特征的符号名称。 . rawLigatureSubstitutionMap映射 glyphId基础变体glyphId , 或连字 glyphIdglyphIds 的序列像这样:

629 -> 66 // a.feature -> a
715 -> 71, 71, 77 // ffl ligature

可以反转此映射以获取基 glyphId 的所有变体.因此,所有具有未知 unicode 值的扩展字形都可以通过它们与基本字形或字形序列的连接来计算。

接下来,为了能够将字形写入 PDF,我们需要知道 glyphId 的 unicode 值。 .有关系unicode -> glyphIdcmap31 映射TrueTypeFont 中的字段.反转 map 通过 glyphId 提供 unicode。

调整

rawLigatureSubstitutionMap无法在 GlyphSubstitutionTableReader 中访问,因为它是 private成员并且没有 getter 访问器。最简单的 hack 是复制粘贴原始类并为 map 添加一个 getter:

public class HackedGlyphSubstitutionTableReader extends OpenTypeFontTableReader {

    // copy-pasted code ...

    public Map<Integer, List<Integer>> getRawSubstitutionMap() {
        return rawLigatureSubstitutionMap;
    }
}

下一个问题是 GlyphSubstitutionTableReader需要 GSUB 的偏移量表,存储在 protected HashMap<String, int[]> tables 中的信息的 TrueTypeFont类(class)。放置在同一个包中的帮助类将桥接对 TrueTypeFont 的 protected 成员的访问。 .

package com.itextpdf.text.pdf;

import com.itextpdf.text.pdf.fonts.otf.FontReadingException;
import java.io.IOException;
import java.util.List;
import java.util.Map;

public class GsubHelper {
    private Map<Integer, List<Integer>> rawSubstitutionMap;

    public GsubHelper(TrueTypeFont font) {
        // get tables offsets from the font instance
        Map<String, int[]> tables = font.tables;
        if (tables.get("GSUB") != null) {
            HackedGlyphSubstitutionTableReader gsubReader;
            try {
                gsubReader = new HackedGlyphSubstitutionTableReader(
                        font.rf, tables.get("GSUB")[0], glyphToCharacterMap, font.glyphWidthsByIndex);
                gsubReader.read();
            } catch (IOException | FontReadingException e) {
                throw new IllegalStateException(e.getMessage());
            }
            rawSubstitutionMap = gsubReader.getRawSubstitutionMap();
        }
    }

    /** Returns a glyphId substitution map
     */
    public Map<Integer, List<Integer>> getRawSubstitutionMap() {
        return rawSubstitutionMap;
    }
}

扩展TrueTypeFont 会更好,但这不适用于工厂方法createFont()BaseFont ,它在创建字体时依赖于硬编码的类名。

关于java - 在 iText 中访问 OpenType 字形变体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33748186/

相关文章:

java - 如何在 Java 中创建一个泛型数组?

java - 在 iframe 中搜索按钮

java - 匹配java Regex中特定html标签的选定选项

java - 检测文本字段溢出

pdf - 如何在我的pdf中读出JBIG2算法使用的符号字典的属性?

java - 如何使用 Flying Saucer 将大表格转换为 PDF?

java - 将注释(XFDF 格式)合并到 PDF 中

java - 服务器应用程序的 C++ 与 Java

pdf - 使用 iText 检测动态 XFA

jackson - java.io.IOException : UT010029: Stream is closed