在iText中访问OpenType字形变体
在iText中使用OpenType字体构建PDF文档时,我想从字体内访问字形变体-
特别是表格图形。由于OpenType字形变体没有Unicode索引,因此我不确定如何指定我要使用一组特定的变体(表格形式)还是通过其字形ID调用特定字形。如果存在,只需寻找相关的iText类名称。
回答:
在最新的标记5.5.8和iText
的master分支中似乎都无法做到这一点。
如本文和Microsoft的OpenType字体文件规范中所述,字形变体存储在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();
}
事实证明,此行被禁用是有原因的,因为如果您尝试激活它,该代码实际上将无法工作。
因此,不幸的是,由于从未从字体文件中加载替代信息,因此无法使用字形变体。
最初的答案是关于iText
API开箱即用访问字形变体的可能性,目前尚不存在。但是,低级代码已经就位,并且在经过一些黑客攻击后可以用于访问字形替换映射表。
调用时read()
,GlyphSubstitutionTableReader
读取GSUB
表并将所有要素的替换展平到一张地图中Map<Integer,
List<Integer>>
rawLigatureSubstitutionMap。目前,功能的符号名称已被丢弃OpenTypeFontTableReader
。该rawLigatureSubstitutionMap
映射将一个glyphId
变体映射到base
glyphId
,或者将一个连字映射glyphId
到这样的序列glyphIds
:
629 -> 66 // a.feature -> a715 -> 71, 71, 77 // ffl ligature
可以颠倒此映射关系以获得base的所有变体glyphId
。因此,具有未知unicode值的所有扩展字形都可以通过与基本字形或一系列字形的连接来找出。
接下来,要能够将字形写入PDF,我们需要知道该字符的unicode值glyphId
。关系unicode ->
glyphId由中的cmap31
字段映射TrueTypeFont
。反向映射通过glyphId给出unicode。
rawLigatureSubstitutionMap
无法在中进行访问GlyphSubstitutionTableReader
,因为它是private
成员,并且没有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
类。放在同一包中的帮助程序类将桥接对的受保护成员的访问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()
的BaseFont
,创建一种字体时依赖于硬编码的类名称。
以上是 在iText中访问OpenType字形变体 的全部内容, 来源链接: utcz.com/qa/401156.html