将 FreeText 注释添加到 PDF

iph*_*nic 2 c++ pdf annotations ios podofo

我正在使用podofo进行 PDF 操作,例如根据我在 iOS 应用程序中的要求添加注释、签名等。我首先尝试了可用podofo 库的唯一示例,该示例效果很好。但随着样本的问题是加入像任何预览不显示注解GoogleAdobe Reader等等。这就是一个问题。

按照一些方针从Adobe我发现,它需要有Appearance KeyFreeText annotation出现。我尝试在文本编辑器中分析原始 pdf 文件,以查看具有正确注释的 PDF 中的差异,podofo 创建了 PDF 注释。我发现有AP N一个带有stream用于注释的编码形式的对象的键,podofo 示例中缺少该对象。

然后在搜索之后我找到了 podofo 自己的示例并尝试使用代码,这似乎是正确的,但也没有工作,我知道我错过了一些东西,但不确定是什么,在哪里,请看一下下面的代码

+(void)createFreeTextAnnotationOnPage:(NSInteger)pageIndex doc:(PdfMemDocument*)aDoc rect:(CGRect)aRect borderWidth:(double)bWidth title:(NSString*)title content:(NSString*)content bOpen:(Boolean)bOpen color:(UIColor*)color {
    PoDoFo::PdfMemDocument *doc = (PoDoFo::PdfMemDocument *) aDoc;
    PoDoFo::PdfPage* pPage = doc->GetPage(pageIndex);
    if (! pPage) {
        // couldn't get that page
        return;
    }

    PoDoFo::PdfRect rect;
    rect.SetBottom(aRect.origin.y);
    rect.SetLeft(aRect.origin.x);
    rect.SetHeight(aRect.size.height);
    rect.SetWidth(aRect.size.width);


    PoDoFo::PdfString sTitle(reinterpret_cast<const PoDoFo::pdf_utf8*>([title UTF8String]));
    PoDoFo::PdfString sContent(reinterpret_cast<const PoDoFo::pdf_utf8*>([content UTF8String]));

    PoDoFo::PdfFont* pFont = doc->CreateFont( "Helvetica", new PoDoFo::PdfIdentityEncoding( 0, 0xffff, true ) );


    std::ostringstream  oss;
    oss << "BT" << std::endl << "/" <<   pFont->GetIdentifier().GetName()
    << " "  <<   pFont->GetFontSize()
    << " Tf " << std::endl;

    [APDFManager WriteStringToStream:sContent :oss :pFont];
    oss << "Tj ET" << std::endl;

    PoDoFo::PdfDictionary fonts;
    fonts.AddKey(pFont->GetIdentifier().GetName(), pFont->GetObject()->Reference());
    PoDoFo::PdfDictionary resources;
    resources.AddKey( PoDoFo::PdfName("Fonts"), fonts );

    PoDoFo::PdfAnnotation* pAnnotation =
    pPage->CreateAnnotation( PoDoFo::ePdfAnnotation_FreeText, rect );



    pAnnotation->SetTitle( sTitle );
    pAnnotation->SetContents( sContent );
    //pAnnotation->SetAppearanceStream( &xObj );
    pAnnotation->GetObject()->GetDictionary().AddKey( PoDoFo::PdfName("DA"), PoDoFo::PdfString(oss.str()) );
    pAnnotation->GetObject()->GetDictionary().AddKey( PoDoFo::PdfName("DR"), resources );
}

+(void) WriteStringToStream:(const PoDoFo::PdfString & )rsString :(std::ostringstream &)  oss :(PoDoFo::PdfFont*) pFont
{
    PoDoFo::PdfEncoding* pEncoding = new PoDoFo::PdfIdentityEncoding( 0, 0xffff, true );
    PoDoFo::PdfRefCountedBuffer buffer = pEncoding->ConvertToEncoding( rsString, pFont );
    PoDoFo::pdf_long  lLen    = 0;
    char* pBuffer = NULL;

    std::auto_ptr<PoDoFo::PdfFilter> pFilter = PoDoFo::PdfFilterFactory::Create( PoDoFo::ePdfFilter_ASCIIHexDecode );
    pFilter->Encode( buffer.GetBuffer(), buffer.GetSize(), &pBuffer, &lLen );

    oss << "<";
    oss << std::string( pBuffer, lLen );
    oss << ">";
    free( pBuffer );
    delete pEncoding;
}
Run Code Online (Sandbox Code Playgroud)

SO 宇宙中的任何人都可以告诉我上面的代码有什么问题,以及如何添加正确的自由文本注释,以便它在任何地方都能正确显示。

非常感谢。

mkl*_*mkl 5

有问题的注释如下所示:

19 0 obj
<<
  /Type/Annot
  /Contents(þÿ M Y   A N N O T A T I O N)
  /DA(BT\n/Ft18 12 Tf \n 1 0 0 rg \n<002D003900000021002E002E002F0034002100340029002F002E>Tj ET\n)
  /DR<</Fonts<</Ft18 18 0 R>>>>
  /M(D:20140616141406+05'00')
  /P 4 0 R
  /Rect[ 188.814117 748.970520 467.849731 795.476456]
  /Subtype/FreeText
  /T(þÿ A n n o t a t e P D F)
>>
endobj
Run Code Online (Sandbox Code Playgroud)

三个观察:

  1. 它有一个Default Appearance但没有APearance 流
  2. 默认外观的内容无效。
  3. 默认资源是在错误的对象。

项目 1 可能导致外观无法在许多仅显示最终内容(页面内容、注释外观等)但不从Default Appearance创建外观的简单查看器中呈现。因此,您还应该提供外观流。

第 2 项和第 3 项可能导致外观无法在更复杂的查看器中呈现,这些查看器确实尝试从默认外观默认资源创建外观,但希望DA正确且DR正确定位。因此,您应该更正DA并移动DR

详细...

1 -默认外观但不是外观流

虽然根据规范ISO 32000-1DA需要自由文本注释和AP是不是简单的PDF查看器可能没有内置的代码创建一个从默认外观的外观流。

这并不完全令人惊讶:虽然您的 PDF 没有太多可做的,但对某些内容应用默认值可能意味着计算文本的最佳大小以适合某些区域和类似任务。因此,简单的、不完整的查看器往往不会实现这一点。

2 -默认外观内容无效

您的DA字符串包含BTET运算符。如果你看一下部分12.7.3.3可变文本ISO 32000-1,不过,你会看到,外观创建过程中的内容DA嵌入到BT .. ET信封:

外观流包括以下标记内容部分,它表示绘制文本的流部分:

/Tx BMC          % Begin marked content with tag Tx 
  q              % Save graphics state 
      … Any required graphics state changes, such as clipping … 
    BT           % Begin text object 
      … Default appearance string ( DA ) … 
      … Text-positioning and text-showing operators to show the variable text … 
    ET           % End text object 
  Q              % Restore graphics state 
EMC              % End marked content 
Run Code Online (Sandbox Code Playgroud)

默认外观字符串 ( DA ) 包含建立图形状态参数(例如文本大小和颜色)所需的任何图形状态或文本状态运算符,以显示字段的可变文本。只有在文本对象中允许的操作符才会出现在这个字符串中

但是BTET不允许在另一个BT .. ET文本对象中!

此外,您在DA 中添加文本内容。正如您在上面看到的,文本绘制操作是您的DA内容之后添加的。因此,您最终会面临重复文本的危险。

3 -默认资源错位

您在注释字典中有默认资源。但部分12.7.3.3可变文本ISO 32000-1上述指示:

指定的字体值应与默认资源字典(从交互式表单字典的DR条目引用)的字体条目中的资源名称匹配。

因此,您的DR将被忽略并预计在其他地方。所以你选择的字体最多可能会被忽略