PDF Formfield 字体大小:默认外观与外观流

PDF Formfield font size: Default appearance vs. appearance stream

我提取表单字段的字体大小以获取有关其大小的信息(使用 iText)。这适用于大多数文档,但是对于某些文档,我得到的字体大小为 1,因为在外观上字体大小为 1。但是,如果我在几个不同的查看器中打开 PDF,该文本字段的大小始终为 8。我想表单字段应该根据其外观呈现?那么为什么 PDF 查看器使用默认外观而不是外观流中定义的字体大小?

更新:如 MKL 所述,我确实忘记考虑文本矩阵。 我确实为字体实现了自己的 RenderListener。有谁知道如何应用缩放?

public class PdfStreamFontExtractor implements RenderListener{

    @Override
    public void usedFont(DocumentFont font, float fontSize) {
        this.font=font;
        this.fontSize=fontSize;
    }

    @Override
    public void renderText(TextRenderInfo renderInfo) {
     //get scaling factor from textToUserSpaceTransformMatrix?
    }
...
}

但即使在外观流中,有效字号也是8!

查看整个文本对象:

BT
8 0 0 8 2 5.55 Tm
/TT1 1 Tf
[...] TJ
ET

开始设置的文本矩阵将所有内容缩放8倍。因此,此后绘制的文本的有效字体大小为8 × 1 = 8。


诚然,虽然您经常可以在常规内容中看到缩放文本矩阵与大小为 1 Tf 指令的组合,但我还没有在表单字段外观中看到它。我想这很不常见。


关于您的更新...

Does anyone know how to apply the scaling?

@Override
public void renderText(TextRenderInfo renderInfo) {
//get scaling factor from textToUserSpaceTransformMatrix?
}

好吧,这取决于你想如何测量转换后的大小。

一种方法是采用与字体大小一样长的垂直矢量(如 Tf 指令中给出的那样),通过 textToUserSpaceTransformMatrix 对其进行变换,然后取转换结果的长度:

@Override
public void renderText(TextRenderInfo renderInfo) {
  scaledfontSize=renderInfo.getTransformedFontSize(unScaledfontSize);
}

public class TextRenderInfo {
...
  public float getTransformedFontSize(float fontSize){
    return new Vector(0, fontSize, 0).cross(this.textToUserSpaceTransformMatrix).length();
  }
...

如果变换仅包含反射、旋转和缩放,则结果应该符合要求。如果涉及倾斜效果,您可能希望在获取长度之前将该变换后的矢量投影到垂直于变换后的书写方向的平面上。