Get font and size of an acroform field

家住魔仙堡 提交于 2020-01-25 02:58:10

问题


I need to get access to the font style and size of an acroform text field. I have access to the Field object via pdfclown but can't work out how to access the font. Anyone know how to do this?


回答1:


I'm glad to announce you that today I committed to the PDF Clown's repository the fully-functional implementation of the FormFlattener, both on the current branch (0.1.2-Fix, rev 129, 131, 133) and on trunk (rev 130, 132, 134): I suggest you to download directly from that SVN repo to get the latest features & fixes.

Otherwise, in case you stick with the published release (0.1.2.0), here it is the relevant code (again, I recommend the committed version as it's more refined). First of all, we need some adjustment:

1) in XObject.java replace the wrap method:

public static XObject wrap(
  PdfDirectObject baseObject
  )
{
  if(baseObject == null)
    return null;

  PdfName subtype = (PdfName)((PdfStream)baseObject.resolve()).getHeader().get(PdfName.Subtype);
  if(PdfName.Form.equals(subtype))
    return FormXObject.wrap(baseObject);
  else if(PdfName.Image.equals(subtype))
    return ImageXObject.wrap(baseObject);
  else
    return null;
}

2) in FormXObject.java replace the wrap method:

public static FormXObject wrap(
  PdfDirectObject baseObject
  )
{
  if(baseObject == null)
    return null;

  PdfDictionary header = ((PdfStream)PdfObject.resolve(baseObject)).getHeader();
  PdfName subtype = (PdfName)header.get(PdfName.Subtype);
  /*
    NOTE: Sometimes the form stream's header misses the mandatory Subtype entry; therefore, here
    we force integrity for convenience (otherwise, content resource allocation may fail, for 
    example in case of Acroform flattening).
  */
  if(subtype == null && header.containsKey(PdfName.BBox))
  {header.put(PdfName.Subtype, PdfName.Form);}
  else if(!subtype.equals(PdfName.Form))
    return null;

  return new FormXObject(baseObject);
}

Then we can define the actual form flattener:

3) add FormFlattener.java to org.pdfclown.tools package:

package org.pdfclown.tools;

import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

import org.pdfclown.documents.Document;
import org.pdfclown.documents.Page;
import org.pdfclown.documents.PageAnnotations;
import org.pdfclown.documents.contents.xObjects.FormXObject;
import org.pdfclown.documents.interaction.annotations.Annotation.FlagsEnum;
import org.pdfclown.documents.interaction.annotations.Widget;
import org.pdfclown.documents.interaction.forms.Field;
import org.pdfclown.documents.interaction.forms.Fields;
import org.pdfclown.documents.interaction.forms.Form;
import org.pdfclown.objects.PdfArray;
import org.pdfclown.objects.PdfDictionary;
import org.pdfclown.objects.PdfDirectObject;
import org.pdfclown.objects.PdfName;
import org.pdfclown.objects.PdfObjectWrapper;
import org.pdfclown.objects.PdfReference;
import org.pdfclown.tools.PageStamper;
import org.pdfclown.util.math.geom.Dimension;

public class FormFlattener
{
  private boolean hiddenRendered;
  private boolean nonPrintableRendered;

  /**
    Replaces the Acroform fields with their corresponding graphics representation.

    @param document Document to flatten.
  */
  public void flatten(
    Document document
    )
  {
    Map<PdfDirectObject,PageStamper> pageStampers = new HashMap<PdfDirectObject,PageStamper>();
    Form form = document.getForm();
    Fields formFields = form.getFields();
    for(Field field : formFields.values())
    {
      for(Widget widget : field.getWidgets())
      {
        Page widgetPage = widget.getPage();
        EnumSet<FlagsEnum> flags = widget.getFlags();
        // Is the widget to be rendered?
        if((!flags.contains(FlagsEnum.Hidden) || hiddenRendered)
          && (flags.contains(FlagsEnum.Print) || nonPrintableRendered))
        {
          // Stamping the current state appearance of the widget...
          PdfName widgetCurrentState = (PdfName)widget.getBaseDataObject().get(PdfName.AS);
          FormXObject widgetCurrentAppearance = widget.getAppearance().getNormal().get(widgetCurrentState);
          if(widgetCurrentAppearance != null)
          {
            PageStamper widgetStamper = pageStampers.get(widgetPage.getBaseObject());
            if(widgetStamper == null)
            {pageStampers.put(widgetPage.getBaseObject(), widgetStamper = new PageStamper(widgetPage));}

            Rectangle2D widgetBox = widget.getBox();
            widgetStamper.getForeground().showXObject(widgetCurrentAppearance, new Point2D.Double(widgetBox.getX(), widgetBox.getY()), new Dimension(widgetBox.getWidth(), widgetBox.getHeight()));
          }
        }

        // Removing the widget from the page annotations...
        PageAnnotations widgetPageAnnotations = widgetPage.getAnnotations();
        widgetPageAnnotations.remove(widget);
        if(widgetPageAnnotations.isEmpty())
        {
          widgetPage.getBaseDataObject().put(PdfName.Annots, null);
          widgetPageAnnotations.delete();
        }

        // Removing the field references relating the widget...
        PdfDictionary fieldPartDictionary = widget.getBaseDataObject();
        while (fieldPartDictionary != null)
        {
          PdfDictionary parentFieldPartDictionary = (PdfDictionary)fieldPartDictionary.resolve(PdfName.Parent);

          PdfArray kidsArray;
          if(parentFieldPartDictionary != null)
          {kidsArray = (PdfArray)parentFieldPartDictionary.resolve(PdfName.Kids);}
          else
          {kidsArray = formFields.getBaseDataObject();}

          kidsArray.remove(fieldPartDictionary.getReference());
          fieldPartDictionary.getReference().delete();

          if(!kidsArray.isEmpty())
            break;

          fieldPartDictionary = parentFieldPartDictionary;
        }
      }
    }
    if(formFields.isEmpty())
    {
      // Removing the Acroform root...
      document.setForm(null);
      form.delete();
    }
    for(PageStamper pageStamper : pageStampers.values())
    {pageStamper.flush();}
  }

  /**
    Gets whether hidden fields have to be rendered.
  */
  public boolean isHiddenRendered(
    )
  {return hiddenRendered;}

  /**
    Gets whether non-printable fields have to be rendered.
  */
  public boolean isNonPrintableRendered(
    )
  {return nonPrintableRendered;}

  /**
    @see #isHiddenRendered()
  */
  public FormFlattener setHiddenRendered(
    boolean value
    )
  {
    hiddenRendered = value;
    return this;
  }

  /**
    @see #isNonPrintableRendered()
  */
  public FormFlattener setNonPrintableRendered(
    boolean value
    )
  {
    nonPrintableRendered = value;
    return this;
  }
}

And this is an example using it:

import java.io.IOException;

import org.pdfclown.documents.Document;
import org.pdfclown.files.File;
import org.pdfclown.tools.FormFlattener;

File file = null;
try
{
  // 1. Opening the PDF file...
  {
    try
    {file = new File(myFilePath);}
    catch(Exception e)
    {throw new RuntimeException(myFilePath + " file access error.",e);}
  }
  Document document = file.getDocument();

  // 2. Flatten the form!
  FormFlattener formFlattener = new FormFlattener();
  formFlattener.flatten(document);

  // 3. Serialize the PDF file!
  try
  {file.save(SerializationModeEnum.Standard);}
  catch(Exception e)
  {
    System.out.println("File writing failed: " + e.getMessage());
    e.printStackTrace();
  }
}
finally
{
  // 4. Closing the PDF file...
  if(file != null)
  {
    try
    {file.close();}
    catch(IOException e)
    {/* NOOP */}
  }
}

To keep yourself up-to-date with the activity about the project, you can follow PDF Clown on its site (pdfclown.org) and through its twitter stream (https://twitter.com/pdfclown).




回答2:


public void flatten(Document document) {
    Map<Page, PageStamper> pageStampers = new HashMap<Page, PageStamper>();
    Form form = document.getForm();
    Fields formFields = form.getFields();
    for (Field field : formFields.values()) {
        for (Widget widget : field.getWidgets()) {
            Page widgetPage = widget.getPage();             
            PageStamper widgetStamper = pageStampers.get(widgetPage);
            if (widgetStamper == null) {
                pageStampers.put(widgetPage,widgetStamper = new PageStamper(widgetPage));
            }
            PrimitiveComposer composer = widgetStamper.getForeground();
            composer.setFont(new StandardType1Font(document,StandardType1Font.FamilyEnum.Courier, false, false), 7);                                    
            composer.showText(field.getName(), new Point2D.Double(widget.getBox().getX()+3, widget.getBox().getY()+3));

        }
        field.delete();
    }
    if (formFields.isEmpty()) {
        // Removing the form root...
        document.setForm(null);
        form.delete();
    }
    for (PageStamper pageStamper : pageStampers.values()) {
        pageStamper.flush();
    }
}


来源:https://stackoverflow.com/questions/28109932/get-font-and-size-of-an-acroform-field

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!