【问题标题】:StemV value of the TrueType fontTrueType 字体的 StemV 值
【发布时间】:2016-05-30 20:07:01
【问题描述】:

我将 TrueType 字体嵌入到 pdf 中,因此需要为其创建描述符字典。 StemV 是必填字段之一,我还没有找到 ttf 中存储此信息的位置。 我想我在某处看到了暗示,它是CVT 程序的一部分,但没有具体说明。

所以,我的问题是如何找出给定 TrueType 字体的 StemV 值。我想直接从 ttf 文件中读取这个值(而不是使用 ie windows API),因为我想编写跨平台解决方案。


更新

Grep-ed LibreOffice 5.1.0.3 源,似乎在导出为 pdf 时,FontDescriptor 是在 vcl/source/gdi/pdfwriter_impl.cxx 中生成的,方法 PDFWriterImpl::emitFontDescriptor()。在那里,大约第 3888 行是以下代码:

// According to PDF reference 1.4 StemV is required
// seems a tad strange to me, but well ...
aLine.append( "\n"
              "/StemV 80\n" );

现在的问题是为什么是80,而不是42?说真的,如果像 LibreOffice 这样的项目使用硬编码常量,这似乎表明该值要么没有存储到字体文件中,要么读取它的成本非常高(即需要实现 TrueType 字体引擎来解释字体程序)。

顺便说一句,对于那些想知道这个 StemV 是什么的人 - 在“PDF 参考 第六版”,它被描述为“字体中主要垂直词干的横向测量的粗细”。

【问题讨论】:

  • 在使用 InDesign(Adobe 当前的旗舰 DTP 应用程序)导出的随机 PDF 中,我发现 Minion Pro 的 StemV 值也为 80——这要么是一个奇妙的巧合,要么甚至是 Adob​​e 本身 并不真正关心该值。仅供参考,对于 Minion Pro Bold,其值为 128(可能是也可能不是因为它的 Boldness)。
  • @RadLexus 谢谢,很高兴知道。我测试过的所有普通阅读器(Acrobat Reader、Linux 的文档查看器、Foxit、pdf.js)在没有 StemV 值的情况下都可以正常工作。所以它似乎确实不是一个关键参数。但我想满足 PDF/A,所以我想看看有没有办法读取这个值......现在你关于“Minion Pro Bold”的评论让我想到 - 也许 StemV 值是字体重量的简单函数班级?即正常为 400,转换为 StemV 80。5*128 = 640,但在半粗体 (600) 和粗体 (700) 之间...
  • 字体粗细确实可以作为一个很好的指南。我现在在工作(真的不应该检查 SO)所以不能进行广泛的测试,但是如果你有一个有很多不同重量的字体,从超薄到超黑以及介于两者之间的所有东西,这个理论可以得到验证。
  • 是的,它可能会产生比“每种字体都为 80”更好的公式,但它需要一些“值得信赖”的 pdf 创建者用于收集数据......不幸的是我没有访问这样的工具。

标签: pdf truetype embedded-fonts


【解决方案1】:

根据 ISO 32000-1:2008,StemH 是可选的,StemV 是必需的(参见表 122)。唉,对于从哪里获取这些数据似乎没有明确的共识。

该变量可能源自 Adob​​e 最初的 Type 1 (CFF) 字体格式:

条目StdVW 是一个只有一个实数条目的数组 表示垂直茎的主要宽度(水平测量 以字符空间为单位)。通常,这将是宽度 小写字母的直词干。 (对于斜体字体程序, 给出以垂直角度测量的垂直茎的宽度 到词干方向。)例如:

/StdVW [85] def

(Adobe Type 1 字体格式,1993 年 2 月,1.1 版,第 42 页)

这是/Private CFF 字体字典中的一个可选条目。

但是,Werner Lemberg 指出 (http://blog.gmane.org/gmane.comp.fonts.freetype.devel/month=20130601)

如果嵌入字体,则 PDF 引擎不使用 StemV 值 是 Type 1 或 CFF 字体;在这种情况下,来自 私人词典被使用。对于 CID 字体,关联的值 使用字形的字体 DICT。

如果PDF中没有StemV值,下面的算法 适用...

这增加了混乱,因为它在 PDF 规范中被标记为“必需”。

其他一些工具包的尝试

Apache FOP 在其字体

下的“目标”中注明

..如果[重要],则在构建 FOP xml 度量文件时解析 .pfb 文件以提取它..

(http://www.cs.helsinki.fi/group/xmltools/formatters/fop/fop-0.20.5/build/site/dev/fonts.html)

PDFLib使用FreeType,头文件ft_font.h包含一个列表:

 +---------------------------------------------------------------------------+
Copyright (c) 1997-2006 Thomas Merz and PDFlib GmbH. All rights reserved. |
 +---------------------------------------------------------------------------+
(.. omitted..)    

/*
 * these defaults are used when the stem value
 * must be derived from the name (unused)
 */
#define FNT_STEMV_MIN        50     /* minimum StemV value */
#define FNT_STEMV_LIGHT      71     /* light StemV value */
#define FNT_STEMV_NORMAL    109     /* normal StemV value */
#define FNT_STEMV_MEDIUM    125     /* mediumbold StemV value */
#define FNT_STEMV_SEMIBOLD  135     /* semibold StemV value */
#define FNT_STEMV_BOLD      165     /* bold StemV value */
#define FNT_STEMV_EXTRABOLD 201     /* extrabold StemV value */
#define FNT_STEMV_BLACK     241     /* black StemV value */

注意“未使用”。此列表也仅出现在旧版本的 FreeType 中。

PrawnPDF 只是说 (http://prawnpdf.org/docs/0.11.1/Prawn/Font/TTF.html)

stemV()
不知道如何为真字体计算这个...

Apache FontBox 中的 TrueType 嵌入器做出有根据的猜测:

// StemV - there's no true TTF equivalent of this, so we estimate it
fd.setStemV(fd.getFontBoundingBox().getWidth() * .13f);

(https://pdfbox.apache.org/download.cgi) - 我觉得我必须补充一点,有总比没有好,但只有很小的差距。对于大多数字体来说,词干宽度和边界框之间的关系并不是这么简单的。还有一些著名的字体会“向内”变胖,因此它们的边界框实际上具有完全相同的值。

进一步的搜索让我回到了 1998 年的一篇 UseNet 帖子:

.ttf 表格,以及 PDF 的 StemV 值

发件人:约翰·布莱
日期:格林威治标准时间 1998 年 6 月 16 日星期二 17:09:19
在 PDF 中嵌入 TrueType 字体时,我需要一个垂直词干宽度值 - 我可以从各种 .ttf 表中获取我需要的所有其他值(上升、下降、斜体角度等),但我似乎无法定位或计算任何地方的平均或正常垂直(或水平)茎宽度。通过查看嵌入的 PDF 字体,我知道“OS/2”表中的“提示”是不够的——它是一个高度精确的值,而不是 1-10 的比例。有什么线索吗?感谢您的宝贵时间!

值不是 TrueType 字体。你必须通过分析,比如说,cap I glyph 来计算它。不要太担心输入一个精确的值:只有在 PDF 文件中不存在该字体时才会使用该值,而此时将使用一种模糊相似的字体。 -- 劳伦斯

(http://www.truetype-typography.com/ttqa_1998.htm)

“'OS/2'表”提示大概是usWeightClass。虽然它的值定义在 100 到 900 的范围内,但这不是一个连续的范围。仅使用整个 100,因此它是 1-9 的比例(不是上面问题中提到的 1-10)。比例源自微软的字体定义,它只有这 9 个不同的值。 (请注意,ft_font.h 文件仅列出 8 个预定义的词干值。还有一个问题。)


一个(不确定的)InDesign 测试

使用 Adob​​e InDesign CS4,我创建了一个小型测试 PDF,使用 Light、Regular 和 Bold 字体的 Aller,Regular、Bold 和 Black 粗体的 Arial(这些都是 TTF 字体)并发现 InDesign 写出了 StemV 的作为

Aller-Light      68
Aller-Regular   100
Aller-Bold      144
Arial            88
Arial-Bold      136
Arial-Black     200

这表明 InDesign 使用某种启发式方法来计算每个单独字体的字干宽度,而不依赖于基于固定权重的表格。它不像“大写'I'的宽度”那么简单,分别是69、102、147(Aller)和94.7、144.5、221.68(Arial)设计单位。我特意用无衬线字体进行了测试,因为衬线字体上的衬线需要估计字形一半的宽度。

我使用 InDesign CC 2014 导出了相同的文档并获得了完全相同的值。我对如何找出 InDesign 从何处获取这些值没有进一步的想法。

(稍后添加:)Minion Pro 是 CFF 风格的 OpenType 字体,因此它可能包含有效的 StdVW 值。经过测试,我发现确实如此:79 StdVW。非常值得注意:InDesign 使用此值,而是将其导出为 /StemV 80。 Minion Pro Bold, 128, 的值是正确的,但在这一点上,我很肯定这可能纯属巧合。由于这两个已经不同,我没有进一步的动力去检查 Minion Pro Semibold 或 Minion Black。


TL、DR 总结:

  • 如果您嵌入的是 Type 1 (CFF) 字体,您可以随意填写,实际值将从字体数据中读取
    • ...除非它不在里面。
  • 如果您要嵌入 TrueType 字体,则需要提供合适的值。

最糟糕的解决方案似乎是从 OS/2 标头中读取 usWeightClass 并将其直接映射到一个合理的值。

【讨论】:

  • 令人印象深刻的研究,非常感谢!似乎要求 ttf 字体的 StemV 是一种历史性的意外,但它已经出现在如此多的标准中,现在我们坚持使用它......或者至少他们也应该标准化如何计算 ttf 的这个值。
  • @ain:不客气——很有趣(也有点令人失望)发现在这个领域实际上做得很少。我同意这个值可能是在嵌入字体仍然是一个例外而不是规则的时候添加的。具有讽刺意味的是,即使您的最终目标“以正确的方式”嵌入字体,您仍需要经历所有这些。
  • 谢谢,根据您的研究,我将使用以下内容:stemv = 10 + 220 * ( weight - 50 ) / 900。这会将宽度 50-950 映射到一些合理的值。不确定我是否还应该查看 BBox 宽度?
【解决方案2】:

这是 PDFLib 实际使用的: (来自:https://fossies.org/dox/PDFlib-Lite-7.0.5p3/ft__font_8c_source.html

#define FNT_STEMV_WEIGHT 65.0
#define FNT_STEMV_MIN 50
fnt_weight2stemv(int weight)
{
    double w = weight / FNT_STEMV_WEIGHT;
    return (int) (FNT_STEMV_MIN + w * w + 0.5);
}

大概,使用的 'weight' 参数将是 'OS/2'.usWeightClass

【讨论】:

    猜你喜欢
    • 2012-03-18
    • 1970-01-01
    • 2015-02-01
    • 2012-11-26
    • 2012-03-22
    • 2010-10-06
    • 2013-11-20
    • 2010-10-11
    • 2011-03-11
    相关资源
    最近更新 更多