当前位置: 首页 > 面试题库 >

在iText中访问OpenType字形变体

西门嘉澍
2023-03-14
问题内容

在iText中使用OpenType字体html" target="_blank">构建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 -> a
715 -> 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[]> tablesTrueTypeFont类。放在同一包中的帮助程序类将桥接对的受保护成员的访问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,创建一种字体时依赖于硬编码的类名称。



 类似资料:
  • Photoshop 中拥有包括 emoji 在内的 OpenType SVG 字体。了解如何使用它们。 Photoshop 支持 OpenType SVG 字体,并且随附了 Trajan Color Concept 和 EmojiOne 字体。OpenType SVG 字体在一种字形中提供了多种颜色和渐变。在 Mac OS 平台上,Apple Color Emoji 字体的受支持程度有限,即使它不

  • 问题内容: 我想解析Web请求的响应,但是在以字符串形式访问它时遇到了麻烦。 如何以字符串形式访问响应?将响应正确地写入文件。 我已经检查过包参考,但并没有真正的帮助。 问题答案: 应该足以给你一个字符串。 从那里,您可以将其用作常规字符串。 有点像这个线程: 另请参阅GoByExample。 如下所述在zzn的答案中,这是一次转换 (请参阅spec)。 有些转换与强制转换相同,例如,只是重新解释

  • 问题内容: 我有一个使用Foxit表单设计器创建的pdf文件。在我的设计系统上,我安装了条形码字体。条形码字体在AcroField之一中使用。foxit似乎没有在文档中嵌入字体。 我也有一些客户的计算机上未安装条形码字体,因此我想将该字体嵌入到PDF中。我是否可以使用iText将AcroFields中使用的字体嵌入到PDF中? 编辑: 字体似乎包含在文本中,但没有包含在字段中,因此字体(条形码)将

  • 问题内容: 我正在为基于Web的幻灯片显示构建应用程序,其中一个“主”用户可以在幻灯片之间移动,每个人的浏览器都可以跟随。为此,我使用websockets和Redis作为全局通道来发送消息。每个连接的客户端都将信息存储在数组中。然后,我有一个单独的线程用于订阅Redis通道,其中定义了一个“ on.message”块,该块应将消息发送给数组中的每个人,但是该数组在此块内为空(在该块中的其他任何地方

  • 问题内容: 我有两个变量,范围是: 现在,由于我的应用程序的大小开始增加,因此我决定将网站的每个模块放入其自己的程序包中,就像子目录一样: 我该如何解决从其他软件包访问和全局变量的问题?这是错误的做法吗?我有一种感觉。 在这种情况下,我怎么会在声明自己的命名空间功能,所以我没有发疯具有固定其名称和所有的时间。 问题答案: 大写的变量名导出为其他包访问,因此并会工作。但是,一般不建议使用子包进行名称

  • 问题内容: 我有服务 即使在控制器中也可访问 有人可以解释一下为什么在angular.foreach中无法访问“ this.list”吗?如何访问“ this.list”? 问题答案: (请参阅http://docs.angularjs.org/api/angular.forEach)函数中的最后一个参数是的上下文。因此,您需要这样的东西: