pdfitextopenpdfpdf-specification

PDF Formfield font size: Default appearance vs. appearance stream


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?
    }
...
}

Solution

  • 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.