我已经尝试了好几天了,以获取使用PDF :: API2呈现的CheckBox或单选按钮,但一直未能做到。
我已经遍历了PDFMark参考,PDF规范以及所有我能找到的示例。我可以获取简单的Widget注释以进行渲染,但无法获得需要外观流或外观字典才能正常工作的任何内容。以下是尝试设置复选框的测试代码的选择:
#!/usr/bin/perl
use PDF::API2;
use PDF::API2::Basic::PDF::Utils;
# set up pdf
my $pdfOptions = {};
my $pdf = PDF::API2->new( \$pdfOptions );
my $page = $pdf->page();
$page->mediabox( 'Letter' );
my $AcroForm = PDFDict();
$AcroForm->{NeedAppearances} = PDFBool( 'true' );
$AcroForm->realise;
my @Annots;
my @Fields;
my $resourceObj = PDFDict();
$resourceObj->{Type} = PDFName( 'Font' );
$resourceObj->{Subtype} = PDFName( 'Type1' );
$resourceObj->{Name} = PDFName( 'ZaDb' );
$resourceObj->{BaseFont} = PDFName( 'ZapfDingbats' );
$resourceObj->realise();
$AcroForm->{DR} = PDFDict();
$AcroForm->{DR}->{Font} = PDFDict();
$AcroForm->{DR}->{ZaDb} = $resourceObj;
$AcroForm->realise();
my $item = PDFDict();
$item->{P} = $page;
$item->{Type} = PDFName( 'Annot' );
$item->{Subtype} = PDFName( 'Widget' );
$item->{FT} = PDFName( 'Btn' );
my $yes = PDFName( 'Yes' );
my $off = PDFName( 'Off' );
$item->{P} = $page;
$item->{Type} = PDFName( 'Annot' );
$item->{Subtype} = PDFName( 'Widget' );
$item->{Rect} = PDF::API2::Basic::PDF::Literal->new( "[100 300 200 400]" );
$item->{FT} = PDFName( 'Btn' );
$item->{T} = PDFStr( 'Urgent' );
$item->{V} = PDFName( 'Yes' );
$item->{AS} = PDFName( 'Yes' );
$item->{AP} = PDFDict();
$item->{AP}->{N} = PDFDict();
# My understanding is that these would be nulled to be used with NeedAppearances
$item->{AP}->{N}->{$yes} = PDFNull();
$item->{AP}->{N}->{$off} = PDFNull();
$item->realise();
push @Annots, $item;
push @Fields, $item if( $AcroForm );
$page->{Annots} = PDFArray( @Annots );
$AcroForm->{Fields} = PDFArray(@Fields) if( $AcroForm );
$pdf->{Root}->{AcroForm} = $AcroForm if( $AcroForm );
print $pdf->stringify();
exit;
我希望看到在页面中间呈现一个复选框,相反,我得到一个空的,无法使用的注释。我正在尝试使NeedAppearances标志起作用,因为我已经放弃尝试使用适当的外观流/外观字典,但是对于使用这两种方法的解决方案,我将不胜感激。
答案 0 :(得分:1)
这是我最终必须在浏览器和Adobe Reader中正确呈现的代码。发布此内容是因为使用此模块进行小部件注释的工作示例很少。
诀窍是:使用{pdf}-> new_obj定义对象并捕获它们的引用以及AcroForm的正确放置,最后,将{'stream'}属性设置为空字符串,我想强制呈现流/结束流标签,从而使PDF阅读器可以在其中插入其外观流的锚点。
我使用qpdf分析了我的输出,这使我得以了解模块的各种方法如何影响最终的PDF输出。
#!/usr/bin/perl
# set up pdf
my $pdfOptions = {};
my $pdf = PDF::API2->new( \$pdfOptions );
my $page = $pdf->page();
$page->mediabox( 'Letter' );
my @Annots;
my @Fields;
my $fontObj = PDFDict();
$fontObj->realise();
$fontObj->{Type} = PDFName( 'Font' );
$fontObj->{Subtype} = PDFName( 'Type1' );
$fontObj->{BaseFont} = PDFName( 'Times-Roman' );
$fontObj = $pdf->{pdf}->new_obj( $fontObj );
my $resourceObj = PDFDict();
$resourceObj->realise();
$resourceObj->{Font} = PDFDict();
$resourceObj->{Font}->realise();
$resourceObj->{Font}->{F1} = $fontObj;
$resourceObj = $pdf->{pdf}->new_obj( $resourceObj );
my $AcroForm = PDFDict();
$AcroForm->realise();
$AcroForm->{DR} = $resourceObj;
$AcroForm->{NeedAppearances} = PDFBool( 'true' );
my $yesObj = PDF::API2::Resource::XObject::Form->new( $pdf );
$yesObj->{Resources} = $resourceObj;
$yesObj->{BBox} = PDF::API2::Basic::PDF::Literal->new( "[100 300 200 400]" );
$yesObj->realise();
$yesObj->{' stream'} = '';
$yesObj = $pdf->{pdf}->new_obj( $yesObj );
my $noObj = PDF::API2::Resource::XObject::Form->new( $pdf );
$noObj->{Resources} = $resourceObj;
$noObj->{Subtype} = PDFName( 'Form' );
$noObj->{BBox} = PDF::API2::Basic::PDF::Literal->new( "[100 300 200 400]" );
$noObj->realise();
$noObj->{' stream'} = '';
$noObj = $pdf->{pdf}->new_obj( $noObj );
my $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( "[100 300 200 400]" );
$item->{H} = PDFName( 'N' );
$item->{AS} = PDFName('Yes');
$item->{AP} = PDFDict();
$item->{AP}->realise();
$item->{AP}->{N} = PDFDict();
$item->{AP}->{N}->realise();
$item->{AP}->{N}->{'Yes'} = $yesObj;
$item->{AP}->{N}->{'Off'} = $noObj;
$item = $pdf->{pdf}->new_obj( $item );
$item->realise();
push @Annots, $item;
push @Fields, $item if( $AcroForm );
$page->{Annots} = PDFArray( @Annots );
$AcroForm->{Fields} = PDFArray(@Fields) if( $AcroForm );
$pdf->{catalog}->{'AcroForm'} = $AcroForm;
$pdf->{pdf}->out_obj($pdf->{catalog});
print $pdf->stringify();
exit;
答案 1 :(得分:0)
以下代码将标记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');