如何使用Perl';s PDF::API2

如何使用Perl';s PDF::API2,perl,pdf,pdf-generation,acrofields,Perl,Pdf,Pdf Generation,Acrofields,几天来,我一直在尝试使用PDF::API2获取一个复选框或单选按钮以进行渲染,但一直未能实现 我已经详细介绍了PDFMark参考资料、PDF规范以及我能找到的所有示例。我可以得到简单的小部件注释来渲染,但无法得到任何需要外观流或外观字典才能正常工作的东西。下面是尝试设置复选框的测试代码选择: #/usr/bin/perl 使用PDF::API2; 使用PDF::API2::Basic::PDF::Utils; #设置pdf 我的$pdfOptions={}; my$pdf=pdf::API2->

几天来,我一直在尝试使用PDF::API2获取一个复选框或单选按钮以进行渲染,但一直未能实现

我已经详细介绍了PDFMark参考资料、PDF规范以及我能找到的所有示例。我可以得到简单的小部件注释来渲染,但无法得到任何需要外观流或外观字典才能正常工作的东西。下面是尝试设置复选框的测试代码选择:

#/usr/bin/perl
使用PDF::API2;
使用PDF::API2::Basic::PDF::Utils;
#设置pdf
我的$pdfOptions={};
my$pdf=pdf::API2->new(\$pdfOptions);
my$page=$pdf->page();
$page->mediabox('Letter');
my$AcroForm=PDFDict();
$AcroForm->{needAppearancess}=PDFBool('true');
$AcroForm->Realize;
我的@Annots;
我的@Fields;
my$resourceObj=PDFDict();
$resourceObj->{Type}=PDFName('Font');
$resourceObj->{Subtype}=PDFName('Type1');
$resourceObj->{Name}=PDFName('ZaDb');
$resourceObj->{BaseFont}=PDFName('ZapfDingbats');
$resourceObj->Realize();
$AcroForm->{DR}=PDFDict();
$AcroForm->{DR}->{Font}=PDFDict();
$AcroForm->{DR}->{ZaDb}=$resourceObj;
$AcroForm->Realize();
我的$item=PDFDict();
$item->{P}=$page;
$item->{Type}=PDFName('Annot');
$item->{Subtype}=PDFName('Widget');
$item->{FT}=PDFName('Btn');
我的$yes=PDFName('yes');
我的$off=PDFName('off');
$item->{P}=$page;
$item->{Type}=PDFName('Annot');
$item->{Subtype}=PDFName('Widget');
$item->{Rect}=PDF::API2::Basic::PDF::Literal->new(“[100300200400]”);
$item->{FT}=PDFName('Btn');
$item->{T}=PDFStr(‘紧急’);
$item->{V}=PDFName('Yes');
$item->{AS}=PDFName('Yes');
$item->{AP}=PDFDict();
$item->{AP}->{N}=PDFDict();
#我的理解是,这些将被取消,以便与需要的外观一起使用
$item->{AP}->{N}->{$yes}=PDFNull();
$item->{AP}->{N}->{$off}=PDFNull();
$item->realize();
推送@Annots,$item;
推送@Fields,$item if($AcroForm);
$page->{Annots}=PDFArray(@Annots);
$AcroForm->{Fields}=PDFArray(@Fields)if($AcroForm);
$pdf->{Root}->{AcroForm}=$AcroForm if($AcroForm);
打印$pdf->stringify();
出口

我希望看到一个复选框呈现在这个页面的中间,而我得到的是一个空的、不可用的注释。我正试图让NeedAppearancess标志起作用,因为我已经放弃尝试一个合适的外观流/外观字典,但我将感谢使用这两种方法的解决方案。

这是我最终在浏览器和Adobe Reader中正确呈现的代码。发布此消息是因为使用此模块进行小部件注释的工作示例很少

诀窍是:使用{pdf}->new_obj定义对象并捕获它们的引用,以及正确放置AcroForm,最后,将{'stream'}属性设置为空字符串,我想这会强制呈现stream/endstream标记,允许pdf阅读器在其中插入它们的外观流

我使用qpdf分析我的输出,这使我能够看到模块的各种方法如何影响最终的PDF输出

#/usr/bin/perl
#设置pdf
我的$pdfOptions={};
my$pdf=pdf::API2->new(\$pdfOptions);
my$page=$pdf->page();
$page->mediabox('Letter');
我的@Annots;
我的@Fields;
my$fontObj=PDFDict();
$fontObj->realize();
$fontObj->{Type}=PDFName('Font');
$fontObj->{Subtype}=PDFName('Type1');
$fontObj->{BaseFont}=PDFName('Times Roman');
$fontObj=$pdf->{pdf}->new_obj($fontObj);
my$resourceObj=PDFDict();
$resourceObj->Realize();
$resourceObj->{Font}=PDFDict();
$resourceObj->{Font}->Realize();
$resourceObj->{Font}->{F1}=$fontObj;
$resourceObj=$pdf->{pdf}->new_obj($resourceObj);
my$AcroForm=PDFDict();
$AcroForm->Realize();
$AcroForm->{DR}=$resourceObj;
$AcroForm->{needAppearancess}=PDFBool('true');
my$yesObj=PDF::API2::Resource::XObject::Form->new($PDF);
$yesObj->{Resources}=$resourceObj;
$yesObj->{BBox}=PDF::API2::Basic::PDF::Literal->new(“[100300200400]”);
$yesObj->Realize();
$yesObj->{'stream'}='';
$yesObj=$pdf->{pdf}->new_obj($yesObj);
我的$noObj=PDF::API2::Resource::XObject::Form->new($PDF);
$noObj->{Resources}=$resourceObj;
$noObj->{Subtype}=PDFName('Form');
$noObj->{BBox}=PDF::API2::Basic::PDF::Literal->new(“[100300200400]”);
$noObj->realize();
$noObj->{'stream'}='';
$noObj=$pdf->{pdf}->new_obj($noObj);
我的$item=PDFDict();
$item->{Type}=PDFName('Annot');
$item->{Subtype}=PDFName('Widget');
$item->{FT}=PDFName('Btn');
$item->{T}=PDFStr('checkbox1');
$item->{V}=PDFName('Yes');
$item->{P}=$page;
$item->{Rect}=PDF::API2::Basic::PDF::Literal->new(“[100300200400]”);
$item->{H}=PDFName('N');
$item->{AS}=PDFName('Yes');
$item->{AP}=PDFDict();
$item->{AP}->realize();
$item->{AP}->{N}=PDFDict();
$item->{AP}->{N}->realize();
$item->{AP}->{N}->{'Yes'}=$yesObj;
$item->{AP}->{N}->{'Off'}=$noObj;
$item=$pdf->{pdf}->new_obj($item);
$item->realize();
推送@Annots,$item;
推送@Fields,$item if($AcroForm);
$page->{Annots}=PDFArray(@Annots);
$AcroForm->{Fields}=PDFArray(@Fields)if($AcroForm);
$pdf->{catalog}->{'AcroForm'}=$AcroForm;
$pdf->{pdf}->out_obj($pdf->{catalog});
打印$pdf->stringify();
出口

以下代码将标记PDF复选框

#!/usr/bin/perl -w
use strict;
use CAM::PDF;
my $pdf = CAM::PDF->new('tenant.pdf') or die "Could not open PDF ($!)!";
my @fields = $pdf->getFormFieldList();
foreach my $field ( @fields ) {
 if ($field =~ /Female/) {
  my $ff_obj    = $pdf->getFormField($field);

  $ff_obj->{value}->{value}->{AS}->{value} = "On";
  }
  else {
    $pdf->fillFormFields($field => $field);
  }
}
$pdf->cleanoutput('afilled.pdf');

我不熟悉PDF规范,但使用
PDFName()
作为散列键似乎是错误的。例如,
$item->{AP}->{N}->{$off}=PDFNull()
其中,
$off
是一个
PDFName()
。查看它似乎是
$pdf->{Root}->{AcroForm}=。