访问 iText 中的 OpenType 字形变体

2024-03-02

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


这在最新标签中似乎也是不可能的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,在创建字体时依赖于硬编码的类名。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

访问 iText 中的 OpenType 字形变体 的相关文章

  • 存根方法时出现 InvalidUseOfMatchersException

    我有这个 TestNG 测试方法代码 InjectMocks private FilmeService filmeService new FilmeServiceImpl Mock private FilmeDAO filmeDao Bef
  • Integer.parseInt("0x1F60A") 以 NumberformatException 结束

    我尝试从数据库中获取长字符串内的表情符号代码 格式如下 0x1F60A 所以我可以访问代码 但它将是String 起初 我尝试通过执行以下操作来转换变量tv setText beforeEmo getEmijoByUnicode int e
  • 大数据使用什么数据结构

    我有一个包含一百万行的 Excel 工作表 每行有 100 列 每行代表一个具有 100 个属性的类的实例 列值是这些属性的值 哪种数据结构最适合在这里使用来存储数百万个数据实例 Thanks 这实际上取决于您需要如何访问这些数据以及您想要
  • 如何根据运行的 jar 的结果让我的 ant 任务通过或失败?

    我正在运行 CrossCheck 无浏览器 js 单元测试 作为 ant 脚本的一部分 如果 CrossCheck 测试失败 我希望 ant 报告失败 这是 build xml 中的相关部分
  • 使用 JUnit 时,有没有办法验证测试方法中是否调用了 try/catch 指令的 Catch 部分?

    例如 如果我想测试以下课程 public class SomeClass public void someMethod try Some code where comething could go wrong catch Exception
  • 需要使用 joda 进行灵活的日期时间转换

    我想使用 joda 解析电子邮件中的日期时间字符串 不幸的是我得到了各种不同的格式 例如 Wed 19 Jan 2011 12 52 31 0600 Wed 19 Jan 2011 10 15 34 0800 PST Wed 19 Jan
  • 自动生成Flyway的迁移SQL

    当通过 Java 代码添加新模型 字段等时 JPA Hibernate 的自动模式生成是否可以生成新的 Flyway 迁移 捕获自动生成的 SQL 并将其直接保存到新的 Flyway 迁移中 以供审查 编辑 提交到项目存储库 这将很有用 预
  • 是否可以通过编程方式查找 logback 日志文件?

    自动附加日志文件以支持电子邮件会很有用 我可以以编程方式设置路径 如以编程方式设置 Logback Appender 路径 https stackoverflow com questions 3803184 setting logback
  • 套接字的读写如何同步?

    我们创建一个套接字 在套接字的一侧有一个 服务器 在另一侧有一个 客户端 服务器和客户端都可以向套接字写入和读取 这是我的理解 我不明白以下事情 如果服务器从套接字读取数据 它在套接字中是否只看到客户端写入套接字的内容 我的意思是 如果服务
  • 使用 Guice 优化注册表

    你好 今天思考了一种优化 有一些疑问 语境 我正在使用 Guice 2 进行 Java 开发 在我的网络应用程序中 我有一个转换器注册表 可以即时转换为某种类型 转换器描述如下 public class StringToBoolean im
  • 在另一个模块中使用自定义 gradle 插件模块

    我正在开发一个自定义插件 我希望能够在稍后阶段将其部署到存储库 因此我为其创建了一个独立的模块 在对其进行任何正式的 TDD 之前 我想手动进行某些探索性测试 因此 我创建了一个使用给定插件的演示模块 到目前为止 我发现执行此操作的唯一方法
  • 流中的非终结符 forEach() ?

    有时 在处理 Java Stream 时 我发现自己需要一个非终端 forEach 来触发副作用但不终止处理 我怀疑我可以用 map item gt f item 之类的方法来做到这一点 其中方法 f 执行副作用并将项目返回到流中 但这似乎
  • java库维护数据库结构

    我的应用程序一直在开发 所以偶尔 当版本升级时 需要创建 更改 删除一些表 修改一些数据等 通常需要执行一些sql代码 是否有一个 Java 库可用于使我的数据库结构保持最新 通过分析类似 db structure version 信息并执
  • 返回 Java 8 中的通用函数接口

    我想写一种函数工厂 它应该是一个函数 以不同的策略作为参数调用一次 它应该返回一个函数 该函数根据参数选择其中一种策略 该参数将由谓词实现 嗯 最好看看condition3为了更好的理解 问题是 它没有编译 我认为因为编译器无法弄清楚函数式
  • 使用布尔值进行冒泡排序以确定数组是否已排序

    我有以下用于冒泡排序的代码 但它根本不排序 如果我删除布尔值那么它工作正常 我知道 由于我的 a 0 小于所有其他元素 因此没有执行交换 任何人都可以帮助我解决这个问题 package com sample public class Bub
  • Hamcrest Matchers - 断言列表类型

    问题 我目前正在尝试使用 Hamcrest Matchers 来断言返回的列表类型是特定类型 例如 假设我的服务调用返回以下列表 List
  • 如何使用play框架上传多个文件?

    我在用play framework 2 1 2 使用java我正在创建视图来上传多个文件 我的代码在这里 form action routes upload up enctype gt multipart form data
  • org.apache.commons.net.io.CopyStreamException:复制时捕获 IOException

    我正在尝试使用以下方法中的代码将在我的服务器中创建的一些文件复制到 FTP 但奇怪的是我随机地低于错误 我无法弄清楚发生了什么 Exception org apache commons net io CopyStreamException
  • 泛型、数组和 ClassCastException

    我想这里一定发生了一些我不知道的微妙事情 考虑以下 public class Foo
  • 在java中使用多个bufferedImage

    我正在 java 小程序中制作游戏 并且正在尝试优化我的代码以减少闪烁 我已经实现了双缓冲 因此我尝试使用另一个 BufferedImage 来存储不改变的游戏背景元素的图片 这是我的代码的相关部分 public class QuizApp

随机推荐

  • Flutter:如何使整行可点击

    如何使整行在颤振中可点击 我将以下代码包装在 GestureDetector 中 行中的各个项目是可单击的 但小部件周围的空白区域不可单击 if auth isLoggedIn GestureDetector onTap auth sign
  • 如何生成sse4.2 popcnt机器指令

    使用c程序 int main int argc char argv return builtin popcountll 0xf0f0f0f0f0f0f0f0 和编译器行 gcc 4 4 Intel Xeon L3426 gcc msse4
  • org-mode 无法编辑 C 源代码

    当我使用 emacs 的 org mode 编辑 C 程序时 即编辑以下代码段 begin src c define MAX 100 end src 当我调用函数 org edit src code 在新缓冲区中编辑 C 代码后 出现错误
  • 如何用Java“正确”检测显示器的DPI?

    我有以下绘制规则的应用程序 public class Rule extends JComponent public static final long serialVersionUID 26362862L public static fin
  • SQL 对值求和

    我是 SQL 新手 我不知道如何做到这一点 我想对类似的对 vin action 求和一个名为 total spending 的coulmn 并选择第一个dealer name和参考月份年份 因此它不会创建重复项 并具有如下示例的输出 输入
  • 使用shell脚本删除文件夹内容

    我在尝试清空脚本中的文件夹时遇到问题 这在我的命令行中工作 rm r Folder1 Folder2 但如果在我的脚本中我这样做 DIR Folder1 Folder2 rm r DIR 它说 rm Folder1 Folder2 没有这样
  • Makefile:多重定义和未定义的引用错误

    我目前正在学习如何在没有 IDE 的情况下进行编码 因此我正在学习如何编写 makefile 这是我当前的测试项目 CoDstructor Makefile bin CoDstructor exe src cod main cpp type
  • Windows Azure 不生成 aspx 文件

    我设置了我的第一个 Azure Cloude 服务和 Web 角色 当我构建然后发布应用程序时 我只能看到包含所有 dll 的 bin 目录 我没有任何文件夹或 aspx 文件 ProjectName CloudService bin De
  • ASP.Net Core 2.0 中 [AllowHtml] 的替代品是什么[重复]

    这个问题在这里已经有答案了 我想将 CKEditor 集成到我的 MVC Core 2 0 应用程序中 在之前的版本中 我通过向字符串属性添加 AllowHTML 数据注释来使用它 但在 ASP Net Core 中我找不到将 HTML 插
  • 想要列表中不重复的元素

    从下面的列表中 我只需要 哇 和 退出 List
  • Rails 中的一对一或零关联

    Model I class TimeLog lt ActiveRecord Base has one custom time fields dependent gt destroy end Model II class CustomTime
  • 在代号一中使用 LocationManager 的正确方法

    我正在使用 LocationManager 来跟踪用户的位置并在 GoogleMaps 上显示相同的位置 我正在使用以下方法 但对此有一些疑问 为了第一次获取用户的位置 我使用 locationManager LocationManager
  • Microsoft VB.NET 命名约定

    VB NET 有标准命名约定吗 根据您的编程经验 想分享您对 VB NET 的命名约定吗 除了这种良好实践之外 还有任何指南吗 模式与实践 http www codeplex com Wiki View aspx ProjectName g
  • kubectl 端口转发和 NodePort 服务之间的区别

    kubectl port forwarding 将端口从本地主机转发到集群中的 pod 以获取对集群资源的访问权限 和 NodePort 服务类型之间有什么区别 您正在比较两个完全不同的事物 你应该compare https medium
  • 添加 google-play-services 后,您需要在此活动中使用 Theme.AppCompat 主题(或后代)

    在我目前正在开发的应用程序中 这是我的第一个 Android 应用程序 我使用 android maven plugin 和 maven android sdk deployer 应用程序一直运行良好 使用 ActionBarActivit
  • 类型类是必需的吗?

    我曾经问过一个问题哈斯克尔初学者 https groups google com forum topic haskell cafe C1zGMkYGTOY 是否使用 data newtype 还是类型类 在我的特殊情况下 事实证明不需要类型
  • Windows 上的 XNA 网络

    XNA 的内置网络功能有哪些 是否可以在Windows中使用XNA的内置网络 如果可以的话 有什么限制吗 如果您使用Microsoft Xna Framework Net 命名空间 http msdn microsoft com en us
  • Gem::Specification.reset 期间未解决的规范:

    启动 Guard 时 我得到以下输出 guard WARN Unresolved specs during Gem Specification reset lumberjack gt 1 0 2 ffi gt 0 5 0 WARN Clea
  • 重塑矩阵并将其转换为数据框,跟踪原始行和列索引

    我有一个大的 n m 矩阵 我想将其转换为 n m 3 数据框 我的矩阵类似于 1400 800 数据框的第一列应包含矩阵行索引 第二列应包含矩阵列索引 数据框的第三列应包含矩阵中每个单元格的值 我用 for 循环解决了这个问题 但我认为这
  • 访问 iText 中的 OpenType 字形变体

    在 iText 中使用 OpenType 字体构建 PDF 文档时 我想从字体内访问字形变体 特别是表格数字 由于 OpenType 字形变体没有 Unicode 索引 因此我不确定如何指定我想要使用一组特定的变体 表格数字 或通过其字形