Trzy biblioteki. Trzy różne zadania. Wybranie niewłaściwej kosztuje cię tygodnie obejść (workarounds), a wybranie wszystkich trzech, gdy potrzebujesz tylko jednej, kosztuje cię narzut na utrzymanie (maintenance overhead), którego nie uwzględniłeś w budżecie. Oto bezpośrednia relacja o tym, co właściwie robi każda biblioteka PDF losLab, gdzie pasuje i gdzie przekazuje pałeczkę swojemu rodzeństwu
HotPDF: pisanie PDF od zera w Delphi
HotPDF to natywny komponent VCL do generowania dokumentów PDF. Jego model jest imperatywny i skoncentrowany na stronie: tworzysz instancję THotPDF, ustawiasz właściwości dokumentu, wywołujesz BeginDoc, rysujesz na CurrentPage, dodajesz strony w miarę potrzeb i zamykasz za pomocą EndDoc. Kolejność ma znaczenie, ponieważ BeginDoc zatwierdza słownik szyfrowania i ustawienia kompresji w momencie jego uruchomienia; cokolwiek przypisanego po tym punkcie jest po cichu ignorowane, a nie stosowane z mocą wsteczną
Powierzchnia rysowania pokrywa pełny zestaw operatorów PDF na poziomie Delphi: TextOut do pozycjonowanego tekstu Unicode, SetFont z osadzaniem TrueType, elementy wektorowe (linie, krzywe Beziera, elipsy, prostokąty), umieszczanie obrazu z pliku lub pamięci oraz generowanie kodów kreskowych. Współrzędne są w punktach od lewego dolnego rogu z osią Y rosnącą w górę, co przynajmniej raz zaskoczy każdego. Stan czcionki nie przetrwa wywołania AddPage, więc po każdym podziale strony wymagane jest wywołanie SetFont
Pola AcroForm to obywatele pierwszej kategorii. Możesz dodać pola tekstowe, pola wyboru (checkbox), pola opcji (radio button), pola kombi (combo box), pola listy (list box) i przyciski do klikania bezpośrednio do obiektu strony za pomocą jednego wywołania dla każdego. HotPDF potrafi również załadować istniejący PDF poprzez LoadFromFile i wypełnić lub odczytać wartości pól, co czyni go użytecznym w dwóch oddzielnych przepływach pracy: budowaniu formularzy oraz automatyzacji ich populacji
Szyfrowanie jest również obsługiwane na poziomie dokumentu. CryptKeyLength wybiera schemat (od 40-bitowego RC4 do AES-256), ActivateProtection je uzbraja, a ProtectOptions ustawia flagi uprawnień ISO. Dwa tryby rewizji AES-256 (R5 i R6, kontrolowane przez UseAES256R6) istnieją, ponieważ rewizja 6 naprawia znaną słabość w rewizji 5, ale wymaga przeglądarki kompatybilnej z PDF 2.0; wybór między nimi to decyzja dotycząca kompatybilności, a nie wygody
Wsparcie dla podpisów cyfrowych w HotPDF obejmuje profile podstawowe (baseline profiles) PAdES, więc jest on odpowiedni dla przepływów pracy, w których podpis musi spełniać wymagania ETSI EN 319 142. Jeśli twoją potrzebą jest tylko generowanie pliku wyjściowego, HotPDF to biblioteka, po którą należy sięgnąć w pierwszej kolejności
PDFium Component: renderowanie, przeglądanie i czytanie istniejących plików PDF
PDFium Component owija silnik PDFium firmy Google jako komponent VCL, co nadaje mu fundamentalnie inną rolę niż HotPDF. Tam, gdzie HotPDF pisze, PDFium Component czyta i renderuje. Głównym obiektem jest TPdf, menedżer dokumentu, który otwiera plik poprzez ustawienie FileName i następnie Active := True. Niepowodzenia ładowania nie są rzucane jako wyjątki; Active po prostu pozostaje na wartości False, więc sprawdzanie jej po przypisaniu nie jest opcjonalne
Renderowanie przebiega poprzez TPdfView, wizualny komponent, który upuszczasz na formularzu i łączysz z instancją TPdf poprzez PdfView.Pdf := Pdf. Powiększenie (zoom) i tryb dopasowania (fit mode) żyją w widoku, a nie w dokumencie. Jedna subtelność, która wprawia ludzi w zakłopotanie: Pdf.PageNumber i PdfView.PageNumber są niezależnymi właściwościami. Ustawienie jednej nie aktualizuje drugiej, a bazujące na widoku API do wyodrębniania danych (bloki słów, jednostki czytania) używają bieżącej strony widoku, a nie dokumentu
Ekstrakcja tekstu to miejsce, w którym PDFium Component nie ma bezpośredniego konkurenta w ofercie losLab. ReadablePageContent zwraca ustrukturyzowany tekst ze świadomością kolejności czytania (reading-order), PageWordBoxes podaje na poziomie słów prostokąty otaczające (bounding rectangles), a DocumentReadingUnits przechodzi przez cały dokument. Do prac związanych z dostępnością (accessibility), IsTagged mówi ci, czy obecne jest drzewo struktury, a ValidatePdfUa wykonuje sprawdzanie zgodności UA. Te API sprawiają, że PDFium Component staje się naturalnym wyborem dla każdego przepływu pracy, który musi zrozumieć, co znajduje się wewnątrz istniejącego PDF-a, zamiast produkować nowy
Wypełnianie formularzy działa również po stronie PDFium, przez tę samą warstwę AcroForm, którą odsłania macierzysty silnik. Jest to odpowiednie rozwiązanie, gdy dokument źródłowy już istnieje, a ty automatyzujesz jego uzupełnianie, zamiast samemu konstruować pola formularza
PDFlibPas: manipulacja, podpisywanie zgodności i bezpośredni dostęp do pliku
PDFlibPas (wersja 3.73.0) plasuje się na drugim końcu spektrum skomplikowania. Wystawia trzy warstwy API na wierzchu tego samego modelu dokumentu: płaską fasadę bazującą na uchwytach (TPDFlib) kompatybilną z konwencją wywołań Quick-PDF, pełną warstwę drzewa obiektów (TPDFDocument) i parser strumieniowy (TSmartPDFReader / TSmartPDFWriter), który operuje wprost na bajtach pliku bez uprzedniego wczytania pełnego grafu powiązanych ze sobą obiektów (complete object graph)
Warstwa strumieniowa jest tym, co czyni PDFlibPas właściwym wyborem dla dużych dokumentów. TSmartPDFWriter może dołączyć do pliku na dysku aktualizację przyrostową (incremental update) bez rekonstrukcji całej tabeli odsyłaczy (cross-reference table), co jest mechanizmem leżącym u podstaw zarówno wydajnego ponownego zapisywania, jak i długoterminowych znaczników walidacji (long-term validation stamps) PAdES. W przypadku procesów podpisywania zapewniających rygorystyczne normy zgodności, gdzie podpisany hash musi obejmować określony zakres bajtów, a podpis jest stosowany bez przepisywania dokumentu, ta warstwa jest jedyną opłacalną ścieżką
Manipulacja dokumentem na poziomie TPDFDocument obejmuje łączenie (merging) za pomocą Merge, selektywne kopiowanie stron przez CopyPagesFromDoc z łańcuchem znaków określającym zakres oraz zarządzanie wersją za pomocą SetMinimumVersion i LockSaveVersion. Blokada wersji (version lock) zgłasza błąd 602, jeśli spróbujesz zapisać funkcjonalność, która popchnęłaby plik wyjściowy powyżej zablokowanej wersji, co jest przydatne, gdy musisz zagwarantować, że plik wyjściowy pozostanie w konkretnej rewizji PDF w celu zgodności archiwizacyjnej
Wsparcie dla PDF/A (ISO 19005) znajduje się w pulpicie roboczym zgodności (conformance workbench) biblioteki PDFlibPas. Zauważ, że szyfrowanie i PDF/A wzajemnie się wykluczają (mutually exclusive) zgodnie ze specyfikacją: nie możesz mieć obu w jednym pliku. Procesy, które potrzebują zaszyfrowanej kopii do dystrybucji i kopii archiwalnej PDF/A, muszą wyprodukować dwa osobne artefakty
Wybór między nimi
Typowe drzewo decyzyjne jest krótkie. Jeśli generujesz nowy dokument z danych, użyj HotPDF. Jeśli renderujesz lub wyodrębniasz tekst z istniejącego dokumentu w aplikacji Delphi VCL, użyj PDFium Component. Jeśli manipulujesz, łączysz lub podpisujesz zgodnie z normami istniejące pliki PDF na dużą skalę lub z wykorzystaniem konwencji aktualizacji przyrostowych (incremental-save semantics), użyj PDFlibPas. Wiele systemów produkcyjnych używa dwóch z tych trzech bibliotek: HotPDF do generowania wyników, a PDFlibPas do zastosowania na nim znacznika długoterminowej walidacji przed archiwizacją, na przykład, lub PDFium Component do podglądu tego, co wyprodukował HotPDF przed wysłaniem tego dalej w dół strumienia (downstream)
Wszystkie trzy są dostarczane jako natywny kod źródłowy Pascala dla Delphi i C++Builder, bez żadnych zależności w czasie działania (runtime dependencies) poza VCL. PDFium Component dodatkowo dołącza bibliotekę DLL PDFium, która pokrywa pracę silnika renderującego i parsującego. Strona produktu każdej z bibliotek zawiera pełną dokumentację API i historię aktualnych wersji
Szczegóły dotyczące poszczególnych bibliotek: HotPDF Component, PDFium Component oraz PDFlibPas