Добавление аннотации FreeText в PDF

я использую podofo для выполнения операций PDF, таких как добавление аннотаций, подписей и т. д. согласно моему требованию в моем приложении iOS. Я впервые попробовал единственный образец для библиотека подофо доступна который прекрасно работает Но проблема с образцом в том, что добавленные аннотации не отображаются ни в одном предварительном просмотре, как Google, Adobe Reader и т.д. Это проблема.

Согласно нескольким рекомендациям от Adobe, я обнаружил, что для этого требуется Appearance Key для FreeText 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;
}

Любой, кто находится в SO Universe, может сообщить мне, что не так с приведенным выше кодом, и как добавить правильную аннотацию FreeText, чтобы она появлялась правильно везде.

Большое спасибо.

1

Решение

Рассматриваемая аннотация выглядит так:

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

Три замечания:

  1. Оно имеет Внешний вид по умолчанию но нет APpearance потоки.
  2. Содержание Внешний вид по умолчанию являются недействительными
  3. Ресурсы по умолчанию находятся не в том объекте.

Элемент 1 может привести к тому, что внешний вид не будет отображаться во многих простых средствах просмотра, которые показывают только завершенные элементы (содержимое страницы, появления аннотаций и т. Д.), Но не создают отображения из Внешний вид по умолчанию. Поэтому вы также должны предоставить поток внешнего вида.

Элементы 2 и 3 могут привести к тому, что внешний вид не будет визуализироваться в более сложных средствах просмотра, которые пытаются создать внешний вид из Внешний вид по умолчанию а также Ресурсы по умолчанию но ожидать DA быть правильным и DR правильно расположен. Поэтому вы должны исправить DA и переместить DR.

В деталях…

1 — Внешний вид по умолчанию но нет APpearance потоки

Хотя согласно спецификации ISO 32000-1 DA требуется для свободной текстовой аннотации и AP Это не так, более простые средства просмотра PDF могут не иметь встроенного кода для создания потока внешнего вида из внешнего вида по умолчанию.

В этом нет ничего удивительного: хотя в случае с вашим PDF не так много дел, применение значения по умолчанию к некоторому контенту может подразумевать вычисление наилучшего размера текста, подходящего для некоторой области и аналогичных задач. Таким образом, простые, неполные зрители склонны не реализовывать это.

2 — Внешний вид по умолчанию содержимое недействительно

Ваш DA строка содержит BT а также ET операторы. Если вы посмотрите на раздел 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

Строка внешнего вида по умолчанию (DA) содержит любые операторы графического состояния или состояния текста, необходимые для установки параметров графического состояния, таких как размер и цвет текста, для отображения переменного текста поля. В этой строке должны присутствовать только те операторы, которые разрешены в текстовых объектах

Но BT а также ET не допускаются внутри другого BT .. ET текстовый объект!

Кроме того, вы добавляете текстовое содержимое в свой DA. Как вы видите выше, добавляются операции рисования текста сразу после ваш DA содержание. Таким образом, вы рискуете получить дубликаты текстов в конце концов.

3 — Ресурсы по умолчанию вывих

У тебя есть Ресурсы по умолчанию в аннотационном словаре. Но раздел 12.7.3.3 Переменный текст из ISO 32000-1 упомянутое выше указывает:

Указанный шрифт значение должно соответствовать имени ресурса в Шрифт запись словаря ресурсов по умолчанию (ссылка на DR запись словаря интерактивной формы).

Таким образом, ваш DR будут игнорироваться и ожидаются в другом месте. Таким образом, ваш выбор шрифта может в лучшем случае игнорироваться

3

Другие решения

Я работаю над подобными вещами. Я попытался создать поток внешнего вида вручную, но оказалось, что это сложно. На самом деле пример кода podofo, который вы публикуете выше, работает, но это неправильно в плане добавления потока внешнего вида. Вы не можете использовать SetAppearanceStream, что тоже неправильно.

PdfPainter podofo может рисовать текст. Он генерирует текстовый поток. Это похоже на работу только для PdfPage, но на самом деле это работает и для XObject. Это действительно скрытая особенность!

Мой пример кода:

PdfFont *pFont = ...;

// Add XObject
PdfXObject xObj(borderPdfRect, pPdfMemDocument);

PdfPainter painter;
painter.SetPage(&xObj);
painter.Save(); // Save graphics settings

// Draw text
painter.SetFont(pFont);
painter.GetFont()->SetFontSize(fontSize);
painter.SetColor(self.textColor.color.red, self.textColor.color.green, self.textColor.color.blue);
PdfString pdfStr(reinterpret_cast<const pdf_utf8*>([self.text UTF8String]));
painter.DrawMultiLineText(textPdfRect, pdfStr);
painter.Restore();
painter.FinishPage();

// Add xObj as appearance stream. Don't use SetAppearanceStream
PdfDictionary dict;
dict.AddKey("N", xObj.GetObject()->Reference());
pTextAnno->GetObject()->GetDictionary().AddKey("AP", dict);
0

По вопросам рекламы [email protected]