Technisch artikel

losLab PDF-bibliotheken voor Delphi: HotPDF, PDFium-component en PDFlibPas vergeleken

Drie bibliotheken. Drie verschillende taken. De verkeerde kiezen kost je weken aan workarounds, en ze alle drie kiezen terwijl je er maar één nodig hebt, kost je onderhoudsoverhead die je niet had begroot. Hier is een direct verslag van wat elke losLab PDF-bibliotheek daadwerkelijk doet, waar het past en waar het overdraagt aan zijn broers of zussen

HotPDF: PDF vanaf nul schrijven in Delphi

HotPDF is een native VCL-component voor het genereren van PDF-documenten. Het model is imperatief en paginagericht: je construeert een THotPDF-instantie, stelt documenteigenschappen in, roept BeginDoc aan, tekent op CurrentPage, voegt naar behoefte pagina's toe en sluit af met EndDoc. De volgorde doet ertoe, omdat BeginDoc de versleutelingsdictionary en compressie-instellingen vastlegt op het moment dat het wordt uitgevoerd; alles wat daarna wordt toegewezen, wordt stilzwijgend genegeerd in plaats van met terugwerkende kracht toegepast

Het tekenoppervlak omvat de volledige set PDF-operatoren op Delphi-niveau: TextOut voor gepositioneerde Unicode-tekst, SetFont met TrueType-insluiting (embedding), vectorprimitieven (lijnen, Bézier-krommen, ellipsen, rechthoeken), het plaatsen van afbeeldingen vanuit bestand of geheugen en het genereren van barcodes. Coördinaten zijn in punten (points) vanaf de linkerbenedenhoek, waarbij Y naar boven toe toeneemt, wat iedereen wel een keer overkomt. De lettertypestatus overleeft AddPage niet, dus een aanroep naar SetFont is vereist na elke pagina-einde (page break)

AcroForm-velden zijn eersterangs burgers. Je kunt direct aan een pagina-object tekstvelden, selectievakjes (checkboxes), keuzerondjes (radio buttons), keuzelijsten met invoervak (combo boxes), keuzelijsten en drukknoppen toevoegen met elk één aanroep. HotPDF kan ook een bestaande PDF laden via LoadFromFile en veldwaarden invullen of lezen, wat het nuttig maakt in twee afzonderlijke workflows: het bouwen van formulieren en het automatiseren van de invulling ervan

Versleuteling wordt ook op documentniveau afgehandeld. CryptKeyLength selecteert het schema (40-bit RC4 tot en met AES-256), ActivateProtection activeert het, en ProtectOptions stelt de ISO-toestemmingsvlaggen in. De twee AES-256 revisiemodi (R5 en R6, aangestuurd door UseAES256R6) bestaan omdat revisie 6 een bekende zwakte in revisie 5 verhelpt, maar een PDF 2.0-compatibele viewer vereist; de keuze daartussen is een compatibiliteitsbeslissing, geen gemaksbeslissing

Ondersteuning voor digitale handtekeningen in HotPDF dekt de PAdES-basisprofielen (baseline profiles), dus het is geschikt voor workflows waarbij de handtekening moet voldoen aan de ETSI EN 319 142-vereisten. Als je alleen uitvoer hoeft te genereren, is HotPDF de bibliotheek waar je als eerste naar moet grijpen

PDFium-component: bestaande PDF's renderen, bekijken en lezen

De PDFium-component wikkelt Google’s PDFium-engine als een VCL-component, wat het een fundamenteel andere rol geeft dan HotPDF. Waar HotPDF schrijft, leest en rendert de PDFium-component. Het kernobject is TPdf, een documentbeheerder die een bestand opent door FileName in te stellen en vervolgens Active := True. Laadfouten worden niet als uitzonderingen (exceptions) opgeworpen; Active blijft simpelweg False, dus het controleren ervan na de toewijzing is niet optioneel

Renderen verloopt via TPdfView, een visuele component die je op een formulier (form) plaatst en koppelt aan een TPdf-instantie via PdfView.Pdf := Pdf. Zoom- en aanpassingsmodi (fit modes) bevinden zich op de weergave (view), niet op het document. Een subtiliteit waar mensen over struikelen: Pdf.PageNumber en PdfView.PageNumber zijn onafhankelijke eigenschappen. Het instellen van de ene werkt de andere niet bij, en de weergavegebaseerde extractie-API's (woordvakken, leeseenheden) gebruiken de huidige pagina van de weergave, niet die van het document

Bij tekstextractie heeft de PDFium-component geen directe concurrent in het losLab-aanbod. ReadablePageContent retourneert gestructureerde tekst met bewustzijn van de leesvolgorde, PageWordBoxes geeft begrenzende rechthoeken op woordniveau en DocumentReadingUnits doorloopt het hele document. Voor toegankelijkheidswerk (accessibility) vertelt IsTagged je of er een structuurboom aanwezig is en voert ValidatePdfUa een controle op UA-conformiteit uit. Deze API's maken de PDFium-component de logische keuze voor elke workflow die moet begrijpen wat er in een bestaande PDF zit, in plaats van een nieuwe te produceren

Het invullen van formulieren werkt ook aan de PDFium-kant, via dezelfde AcroForm-laag die de onderliggende engine blootlegt. Het is geschikt wanneer het brondocument al bestaat en je de invulling ervan automatiseert, in plaats van zelf de formuliervelden te construeren

PDFlibPas: manipulatie, compliance-ondertekening en directe bestandstoegang

PDFlibPas (versie 3.73.0) bevindt zich aan het andere uiteinde van het complexiteitsspectrum. Het ontsluit drie API-lagen bovenop hetzelfde documentmodel: een platte op handles gebaseerde façade (TPDFlib) die compatibel is met de Quick-PDF-aanroepconventie, een volledige objectboomlaag (TPDFDocument) en een streaming-parser (TSmartPDFReader / TSmartPDFWriter) die direct op de bestandsbytes werkt zonder de volledige objectgrafiek te laden

De streaming-laag is wat PDFlibPas de juiste keuze maakt voor grote documenten. TSmartPDFWriter kan een incrementele update toevoegen aan een bestand op de schijf zonder de hele kruisverwijzingstabel opnieuw te construeren, wat het mechanisme is dat ten grondslag ligt aan zowel efficiënt opnieuw opslaan als aan PAdES-stempels voor langdurige validatie. Voor ondertekeningsworkflows van compliance-kwaliteit (compliance-grade) waarbij de ondertekende hash een specifiek bytebereik moet bestrijken en de handtekening wordt toegepast zonder het document te herschrijven, is deze laag de enige levensvatbare weg

Documentmanipulatie op TPDFDocument-niveau omvat het samenvoegen met Merge, selectief pagina's kopiëren via CopyPagesFromDoc met een bereikstring, en versiebeheer door SetMinimumVersion en LockSaveVersion. De versievergrendeling werpt fout 602 op als je probeert een functie op te slaan die de uitvoer boven de vergrendelde versie zou tillen, wat nuttig is wanneer je moet garanderen dat de uitvoer binnen een specifieke PDF-revisie blijft voor archiveringsnaleving (archival compliance)

PDF/A-ondersteuning (ISO 19005) bevindt zich in de conformiteitswerkbank (conformance workbench) van PDFlibPas. Merk op dat versleuteling en PDF/A volgens specificatie elkaar uitsluiten: je kunt ze niet allebei in één bestand hebben. Workflows die een versleutelde distributiekopie en een PDF/A-archiefkopie nodig hebben, moeten twee afzonderlijke artefacten produceren

Kiezen tussen deze drie

De typische beslissingsboom is kort. Als je een nieuw document genereert uit gegevens, gebruik dan HotPDF. Als je tekst rendert of extraheert uit een bestaand document in een Delphi VCL-toepassing, gebruik dan de PDFium-component. Als je bestaande PDF's op schaal manipuleert, samenvoegt of met compliance ondertekent of incrementele opslag (incremental-save) semantiek nodig hebt, gebruik dan PDFlibPas. Veel productiesystemen gebruiken twee van de drie: bijvoorbeeld HotPDF om uitvoer te genereren en PDFlibPas om er vóór archivering een langdurig validatiestempel op aan te brengen, of de PDFium-component om te bekijken wat HotPDF heeft geproduceerd voordat het verder in de pijplijn (downstream) wordt gestuurd

Alle drie worden ze geleverd als native Pascal-broncode voor Delphi en C++Builder, zonder runtime-afhankelijkheden buiten de VCL. De PDFium-component bundelt bovendien de PDFium-DLL, die het render- en parseerwerk van de engine dekt. De productpagina van elke bibliotheek bevat de volledige API-referentie en de huidige versiegeschiedenis

Details over de individuele bibliotheken: HotPDF-component, PDFium-component en PDFlibPas