这在最新标签中似乎也是不可能的5.5.8 https://github.com/itext/itextpdf/tree/5.5.8,也不在master https://github.com/itext/itextpdf/tree/masteriText 的分支。
正如中所解释的本文 http://ilovetypography.com/OpenType/opentype-features.html并在微软的OpenType 字体文件规范 https://www.microsoft.com/typography/otspec/gsub.htm,字形变体存储在Glyph Substitution Table (GSUB)
字体文件的。访问字形变体需要从文件中读取此表,该表实际上是在类中实现的com.itextpdf.text.pdf.fonts.otf.GlyphSubstitutionTableReader
,尽管该类目前已禁用。
电话readGsubTable()
在课堂里com.itextpdf.text.pdf.TrueTypeFontUnicode
被注释掉了。
void process(byte ttfAfm[], boolean preload) throws DocumentException, IOException {
super.process(ttfAfm, preload);
//readGsubTable();
}
事实证明,该行被禁用是有原因的,因为如果您尝试激活它,代码实际上不起作用。
因此,不幸的是,无法使用字形变体,因为替换信息永远不会从字体文件中加载。
Update
最初的答案是关于使用的可能性iText API
用于访问开箱即用的字形变体,目前尚不存在。然而,低级代码已经就位,并且可以在一些黑客攻击后使用来访问字形替换映射表。
被叫时read()
, the GlyphSubstitutionTableReader
读到GSUB
表并将所有特征的替换展平到一张地图中Map<Integer, List<Integer>> rawLigatureSubstitutionMap
。目前,功能的符号名称已被丢弃OpenTypeFontTableReader
. The rawLigatureSubstitutionMap
maps a glyphId
基础的变体glyphId
,或连字glyphId
到一个序列glyphIds
像这样:
629 -> 66 // a.feature -> a
715 -> 71, 71, 77 // ffl ligature
可以反转此映射以获得基础的所有变体glyphId
。因此,所有具有未知 unicode 值的扩展字形都可以通过它们与基本字形或字形序列的连接来计算出来。
接下来,为了能够将字形写入 PDF,我们需要知道该字形的 unicode 值glyphId
。一种关系unicode -> glyphId
被映射为cmap31
领域在TrueTypeFont
。反转映射通过 glyphId 给出 unicode。
Tweaking
rawLigatureSubstitutionMap
无法访问GlyphSubstitutionTableReader
,因为它是一个private
成员并且没有 getter 访问器。最简单的技巧是复制粘贴原始类并为地图添加 getter:
public class HackedGlyphSubstitutionTableReader extends OpenTypeFontTableReader {
// copy-pasted code ...
public Map<Integer, List<Integer>> getRawSubstitutionMap() {
return rawLigatureSubstitutionMap;
}
}
下一个问题是GlyphSubstitutionTableReader
需要一个偏移量GSUB
表,存储的信息protected HashMap<String, int[]> tables
of TrueTypeFont
班级。放置在同一包中的辅助类将桥接对受保护成员的访问TrueTypeFont
.
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()
of BaseFont
,在创建字体时依赖于硬编码的类名。