Техническа статия

losLab PDF библиотеки за Delphi: HotPDF, PDFium Component и PDFlibPas в сравнение

Три библиотеки. Три различни задачи. Изборът на грешната ви струва седмици заобикаляния (workarounds), а изборът и на трите, когато се нуждаете само от една, ви струва режийни разходи за поддръжка, които не сте предвидили в бюджета си. Ето директен разказ за това какво всъщност прави всяка losLab PDF библиотека, къде се вписва и къде предава щафетата на своите събратя (siblings)

HotPDF: писане на PDF от нулата в Delphi

HotPDF е нативен VCL компонент за генериране на PDF документи. Неговият модел е императивен и центриран върху страниците: конструирате инстанция на THotPDF, задавате свойствата на документа, извиквате BeginDoc, рисувате върху CurrentPage, добавяте страници според нуждите и затваряте с EndDoc. Редът има значение, защото BeginDoc ангажира (commits) речника за криптиране и настройките за компресия в момента, в който се изпълнява; всичко присвоено след тази точка се игнорира мълчаливо, вместо да бъде приложено със задна дата

Повърхността за рисуване покрива пълния набор от PDF оператори на ниво Delphi: TextOut за позициониран Unicode текст, SetFont с вграждане на TrueType, векторни примитиви (линии, криви на Безие, елипси, правоъгълници), поставяне на изображения от файл или памет и генериране на баркодове. Координатите са в пунктове (points) от долния ляв ъгъл с Y, нарастващ нагоре, което хваща всеки по веднъж. Състоянието на шрифта не оцелява след AddPage, така че извикване на SetFont се изисква след всяко прекъсване на страница (page break)

Полетата на AcroForm са първокласни граждани (first-class citizens). Можете да добавяте текстови полета, отметки (checkboxes), радио бутони, падащи списъци (combo boxes), списъчни полета (list boxes) и бутони за натискане (push buttons) директно към обект на страница с по едно-единствено извикване за всяко. HotPDF може също така да зареди съществуващ PDF чрез LoadFromFile и да попълва или чете стойностите на полетата, което го прави полезен в два отделни работни процеса: изграждане на формуляри и автоматизиране на тяхното попълване

Криптирането също се обработва на ниво документ. CryptKeyLength избира схемата (40-битов RC4 до AES-256), ActivateProtection я активира (arms it), а ProtectOptions задава ISO флаговете за разрешение. Двата режима на ревизия на AES-256 (R5 и R6, управлявани от UseAES256R6) съществуват, защото ревизия 6 поправя известна слабост в ревизия 5, но изисква viewer, способен да работи с PDF 2.0; изборът между тях е решение за съвместимост, а не за удобство

Поддръжката на цифрови подписи в HotPDF покрива базовите профили на PAdES, така че е подходяща за работни процеси, при които подписът трябва да отговаря на изискванията на ETSI EN 319 142. Ако нуждата ви е само генериране на изход, HotPDF е библиотеката, към която да посегнете първо

PDFium Component: рендиране, преглеждане и четене на съществуващи PDF файлове

Компонентът PDFium обвива (wraps) PDFium енджина на Google като VCL компонент, което му придава фундаментално различна роля от HotPDF. Където HotPDF пише, компонентът PDFium чете и рендира. Основният обект е TPdf, мениджър на документи, който отваря файл чрез задаване на FileName и след това Active := True. Неуспехите при зареждане не се повдигат (raised) като изключения; Active просто остава False, така че проверката му след присвояването не е по избор

Рендирането преминава през TPdfView, визуален компонент, който пускате (drop) върху форма и свързвате с инстанция на TPdf чрез PdfView.Pdf := Pdf. Мащабирането и режимът на побиране (fit mode) живеят в изгледа (view), а не в документа. Една тънкост, която препъва хората: Pdf.PageNumber и PdfView.PageNumber са независими свойства. Задаването на едното не актуализира другото, а базираните на изгледа API-та за извличане (word boxes, reading units) използват текущата страница на изгледа, а не на документа

Извличането на текст е мястото, където компонентът PDFium няма пряк конкурент в състава (lineup) на losLab. ReadablePageContent връща структуриран текст с осведоменост за реда на четене (reading-order awareness), PageWordBoxes дава ограничаващи правоъгълници (bounding rectangles) на ниво дума, а DocumentReadingUnits обхожда целия документ. За работа по достъпността (accessibility), IsTagged ви казва дали присъства дърво на структурата (structure tree), а ValidatePdfUa изпълнява проверка за съответствие с UA. Тези API-та правят компонента PDFium естествения избор за всеки работен процес, който трябва да разбере какво има вътре в съществуващ PDF, вместо да произвежда нов

Попълването на формуляри работи и от страната на PDFium, чрез същия слой AcroForm, който основният (underlying) енджин излага. Това е подходящо, когато документът-източник вече съществува и вие автоматизирате попълването му, вместо да конструирате полетата на формуляра сами

PDFlibPas: манипулация, подписване за съответствие и директен достъп до файл

PDFlibPas (версия 3.73.0) седи на другия край на спектъра на сложността. Той излага три API слоя върху същия модел на документ: плоска фасада, базирана на манипулатори (TPDFlib), съвместима с конвенцията за извикване на Quick-PDF, пълен слой на дървото на обектите (TPDFDocument) и поточен парсер (TSmartPDFReader / TSmartPDFWriter), който оперира директно върху байтовете на файла, без да зарежда пълния граф от обекти

Поточният слой (streaming layer) е това, което прави PDFlibPas правилния избор за големи документи. TSmartPDFWriter може да добави (append) инкрементално обновяване към файл на диска, без да реконструира цялата таблица с кръстосани препратки, което е механизмът, лежащ в основата както на ефективното повторно запазване, така и на PAdES печатите за дългосрочно валидиране (long-term validation stamps). За работни процеси за подписване на ниво съответствие (compliance-grade), където подписаният хеш трябва да покрива специфичен диапазон от байтове и подписът се прилага без пренаписване на документа, този слой е единственият жизнеспособен път

Манипулацията на документи на ниво TPDFDocument включва сливане с Merge, селективно копиране на страници чрез CopyPagesFromDoc с низ за диапазон и управление на версиите (version governance) чрез SetMinimumVersion и LockSaveVersion. Заключването на версията повдига грешка 602, ако се опитате да запазите функция, която би изтласкала изхода над заключената версия, което е полезно, когато трябва да гарантирате, че изходът остава в рамките на специфична PDF ревизия за съответствие с архивирането

Поддръжката на PDF/A (ISO 19005) се намира в работната маса за съответствие (conformance workbench) на PDFlibPas. Имайте предвид, че криптирането и PDF/A са взаимно изключващи се по спецификация: не можете да имате и двете в един файл. Работните процеси, които се нуждаят от криптирано копие за разпространение и PDF/A архивно копие, трябва да произведат два отделни артефакта

Изборът между тях

Типичното дърво на решенията е кратко. Ако генерирате нов документ от данни, използвайте HotPDF. Ако рендирате или извличате текст от съществуващ документ в Delphi VCL приложение, използвайте компонента PDFium. Ако манипулирате, сливате или подписвате за съответствие съществуващи PDF-и в мащаб или със семантика на инкрементално запазване, използвайте PDFlibPas. Много производствени системи използват две от трите: HotPDF за генериране на изход и PDFlibPas за прилагане на печат за дългосрочно валидиране към него преди архивиране, например, или компонента PDFium за предварителен преглед на това, което HotPDF е произвел, преди да го изпрати по веригата (downstream)

И трите се доставят като нативен (native) Pascal изходен код за Delphi и C++Builder, без зависимости по време на изпълнение (runtime dependencies) извън VCL. Компонентът PDFium допълнително пакетира PDFium DLL, който покрива работата на енджина по рендиране и парсване. Продуктовата страница на всяка библиотека носи нейната пълна API референция и текущата история на версиите

Подробности за отделните библиотеки: HotPDF Component, PDFium Component и PDFlibPas