0

I extract the font size of a form field to get the information about its size (using iText). This works well for most of the documents however for some I get a font size of 1 because in the appearance the font size is 1. However if I open the PDF in several different viewers the size of this text field is always 8. I thought a form field should be rendered according to its appearance? So why do PDF Viewers use the default appearance and not the font size defined in the appearance stream?

enter image description here

Update: As mentioned by MKL I did forget to consider the text matrix. I did implement my own RenderListener for the font. Does anyone know how to apply the scaling?

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?
    }
...
}
Lonzak
  • 9,334
  • 5
  • 57
  • 88
  • Concerning your update - which version of itext can we assume you use? – mkl Dec 22 '21 at 08:08
  • ~2.1.7. (nearly openPDF ;-) – Lonzak Dec 22 '21 at 13:07
  • Well, there is no `RenderListener` in 2.1.7 ;). That class was only introduced in the additions on the way to 4.2.0 (even though it itself says `@since 2.1.6`). Can we assume your `parser` package is in the state of 4.2.0? That `RenderListener` class is not present anymore in the current OpenPdf... – mkl Dec 24 '21 at 14:24
  • Ah ok didn't know that. Yes the class does exist. Does that help? – Lonzak Dec 29 '21 at 11:22
  • Well, see the edit to my answer... ;) – mkl Dec 29 '21 at 13:07

1 Answers1

2

But the effective font size is 8 even in the appearance stream!

Have a look at the whole text object:

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

The text matrix set at the start scales everything by a factor of 8. Thus, the text drawn thereafter has an effective font size of 8 × 1 = 8.


Admittedly, while you can see scaling text matrices in combination with size 1 Tf instructions in regular contents pretty often, I have not seen that in form field appearances yet. It's pretty uncommon, I'd assume.


Concerning your update...

Does anyone know how to apply the scaling?

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

Well, it depends on how you want to measure the transformed size.

One approach would be to take a vertical vector as long as the font size (as given in the Tf instruction), transform it by textToUserSpaceTransformMatrix, and take the length of the transformation result:

@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();
  }
...

If the transformation only consists of reflections, rotations and scaling, the result should be as desired. If skewing effects are involved, you might want to project that transformed vector onto the plane perpendicular to the transformed writing direction before taking the length.

Lonzak
  • 9,334
  • 5
  • 57
  • 88
mkl
  • 90,588
  • 15
  • 125
  • 265
  • Damn I didn't consider checking the matrix :-| Now I have to figure out a way to apply the scaling to the fontSize...Argh my matrix calculation times have been a while :-D – Lonzak Dec 21 '21 at 16:52
  • Perfect! I updated your post with the implementation which works. Thanks alot – Lonzak Jan 06 '22 at 11:48