מאמר טכני

ספריות ה-PDF של losLab עבור Delphi: השוואה בין HotPDF, PDFium Component, ו-PDFlibPas

שלוש ספריות. שלוש עבודות נפרדות. בחירה בשגויה תעלה לך בשבועות של עקיפות (workarounds), ובחירה בכולן כשאתה צריך רק אחת תעלה לך בתקורת תחזוקה שלא תקצבת. הנה תיאור ישיר של מה שכל ספריית PDF של losLab עושה בפועל, היכן היא משתלבת, והיכן היא מעבירה את השרביט לאחיותיה

HotPDF: כתיבת PDF מאפס ב-Delphi

HotPDF הוא רכיב VCL טבעי (native) ליצירת מסמכי PDF. המודל שלו הוא אימפרטיבי וממוקד-עמוד: אתה בונה מופע של THotPDF, קובע מאפייני מסמך, קורא ל-BeginDoc, מצייר אל ה-CurrentPage, מוסיף עמודים לפי הצורך, וסוגר עם EndDoc. הסדר חשוב מכיוון ש-BeginDoc מקבע את מילון ההצפנה והגדרות הדחיסה ברגע שהוא פועל; כל דבר שיוקצה לאחר נקודה זו יזכה להתעלמות שקטה במקום להיות מוחל רטרואקטיבית

משטח הציור מכסה את מלוא קבוצת אופרטורי ה-PDF ברמת ה-Delphi: TextOut עבור טקסט Unicode ממוצב, SetFont עם הטמעת TrueType, פרימיטיבים וקטוריים (קווים, עקומות בזייה, אליפסות, מלבנים), הצבת תמונות מקובץ או מהזיכרון, ויצירת ברקודים. הקואורדינטות הן בנקודות מהפינה השמאלית-תחתונה עם Y עולה כלפי מעלה, משהו שתופס את כולם פעם אחת. מצב הגופן (font state) אינו שורד AddPage, כך שקריאה ל-SetFont נדרשת לאחר כל מעבר עמוד

שדות AcroForm הם אזרחים מסוג ראשון (first-class citizens). אתה יכול להוסיף שדות טקסט, תיבות סימון, כפתורי רדיו, תיבות משולבות, תיבות רשימה וכפתורי לחיצה ישירות לאובייקט עמוד בקריאה אחת כל אחד. HotPDF גם יכול לטעון PDF קיים דרך LoadFromFile ולמלא או לקרוא ערכי שדות, מה שהופך אותו לשימושי בשני זרמי-עבודה נפרדים: בניית טפסים ואוטומציה של האכלוס שלהם

הצפנה מטופלת גם היא ברמת המסמך. CryptKeyLength בוחר את הסכימה (40-bit RC4 ועד AES-256), ActivateProtection דורך אותה, ו-ProtectOptions קובע את דגלי ההרשאות של ISO. שני מצבי הרויזיה של AES-256 (הנקראים R5 ו-R6, נשלטים על ידי UseAES256R6) קיימים מכיוון שרויזיה 6 מתקנת חולשה ידועה ברויזיה 5 אך דורשת צופה תואם PDF 2.0; הבחירה ביניהם היא החלטת תאימות, לא החלטת נוחות

תמיכה בחתימות דיגיטליות ב-HotPDF מכסה את פרופילי הבסיס של PAdES, כך שהיא מתאימה לזרמי-עבודה שבהם החתימה חייבת לעמוד בדרישות ETSI EN 319 142. אם הצורך שלך הוא רק הפקת פלט, HotPDF היא הספרייה שיש להושיט אליה יד ראשונה

PDFium Component: רינדור, הצגה וקריאת קובצי PDF קיימים

PDFium Component עוטף את מנוע ה-PDFium של גוגל כרכיב VCL, מה שנותן לו תפקיד שונה ביסודו מ-HotPDF. במקום שבו HotPDF כותב, PDFium Component קורא ומרנדר. אובייקט הליבה הוא TPdf, מנהל מסמכים שפותח קובץ על ידי הגדרת FileName ולאחר מכן Active := True. כשלי טעינה אינם מועלים כחריגות (exceptions); Active פשוט נשאר False, כך שבדיקתו לאחר ההקצאה אינה אופציונלית

רינדור רץ דרך TPdfView, רכיב חזותי שאתה זורק על טופס ומקשר למופע TPdf דרך PdfView.Pdf := Pdf. תקריב (zoom) ומצב התאמה (fit mode) חיים על התצוגה, לא על המסמך. דקות אחת שמכשילה אנשים: Pdf.PageNumber ו-PdfView.PageNumber הם מאפיינים בלתי תלויים. הגדרת האחד אינה מעדכנת את השני, וממשקי ה-API של חילוץ מבוסס-תצוגה (תיבות מילים, יחידות קריאה) משתמשים בעמוד הנוכחי של התצוגה, לא בזה של המסמך

חילוץ טקסט הוא המקום שבו ל-PDFium Component אין מתחרה ישיר במערך (lineup) של losLab. ReadablePageContent מחזיר טקסט מובנה עם מודעות לסדר הקריאה, PageWordBoxes נותן מלבנים תוחמים ברמת מילה, ו-DocumentReadingUnits מטייל על פני כל המסמך. עבור עבודת נגישות (accessibility), IsTagged אומר לך האם קיים עץ מבנה ו-ValidatePdfUa מריץ בדיקת תאימות UA. ממשקי API אלו הופכים את PDFium Component לבחירה הטבעית עבור כל זרם-עבודה שצריך להבין מה נמצא בתוך PDF קיים במקום לייצר אחד חדש

מילוי טפסים עובד גם בצד של PDFium, דרך אותה שכבת AcroForm שהמנוע הבסיסי חושף. זה מתאים כאשר מסמך המקור כבר קיים ואתה עושה אוטומציה להשלמה שלו במקום לבנות את שדות הטופס בעצמך

PDFlibPas: מניפולציה, חתימת תאימות, וגישה ישירה לקובץ

PDFlibPas (גרסה 3.73.0) יושב בקצה השני של ספקטרום המורכבות. הוא חושף שלוש שכבות API על גבי אותו מודל מסמך: חזית (facade) שטוחה מבוססת-ידיות (TPDFlib) תואמת למוסכמת-הקריאה (calling convention) של Quick-PDF, שכבת עץ-אובייקטים מלאה (TPDFDocument), ומנתח מזרים (streaming parser) (TSmartPDFReader / TSmartPDFWriter) הפועל ישירות על בתי הקובץ (bytes) מבלי לטעון את גרף האובייקטים המלא

שכבת ההזרמה (streaming) היא מה שהופך את PDFlibPas לבחירה הנכונה עבור מסמכים גדולים. TSmartPDFWriter יכול להוסיף עדכון אינקרמנטלי לקובץ בדיסק מבלי לבנות מחדש את כל טבלת ההפניות המצטלבות (cross-reference table), וזהו המנגנון העומד בבסיס הן של שמירה-מחדש יעילה והן של חותמות אימות לטווח ארוך של PAdES. עבור זרמי-עבודה של חתימה ברמת-תאימות (compliance-grade) שבהם הגיבוב (hash) החתום חייב לכסות טווח בתים ספציפי והחתימה מוחלת מבלי לשכתב את המסמך, שכבה זו היא הנתיב היחיד האפשרי

מניפולציה של מסמכים ברמת TPDFDocument כוללת מיזוג עם Merge, העתקת עמודים סלקטיבית דרך CopyPagesFromDoc עם מחרוזת טווח, ומשילות גרסאות דרך SetMinimumVersion ו-LockSaveVersion. נעילת הגרסה מעלה שגיאה 602 אם אתה מנסה לשמור מאפיין שהיה דוחף את הפלט מעל הגרסה הנעולה, וזה שימושי כאשר אתה צריך להבטיח שהפלט יישאר בתוך רויזיית PDF ספציפית עבור תאימות ארכיונית (archival compliance)

תמיכה ב-PDF/A (תקן ISO 19005) יושבת בסביבת התאימות של PDFlibPas. שים לב שהצפנה ו-PDF/A הם מוציאים זה את זה הדדית (mutually exclusive) לפי המפרט: אינך יכול לקבל את שניהם בקובץ אחד. זרמי-עבודה שזקוקים לעותק הפצה מוצפן ולעותק ארכיון PDF/A חייבים לייצר שני ארטיפקטים נפרדים

הבחירה ביניהן

עץ ההחלטות הטיפוסי הוא קצר. אם אתה יוצר מסמך חדש מנתונים, השתמש ב-HotPDF. אם אתה מרנדר או מחלץ טקסט ממסמך קיים ביישום VCL של Delphi, השתמש ב-PDFium Component. אם אתה מבצע מניפולציה, ממזג, או חותם חתימת תאימות על קובצי PDF קיימים בקנה מידה גדול או עם סמנטיקה של שמירה אינקרמנטלית, השתמש ב-PDFlibPas. מערכות ייצור רבות משתמשות בשתיים מתוך השלוש: HotPDF כדי ליצור פלט ו-PDFlibPas כדי להחיל עליו חותמת אימות לטווח ארוך לפני ארכוב, למשל, או PDFium Component כדי להציג תצוגה מקדימה למה ש-HotPDF ייצר לפני שליחתו למורד הזרם

כל השלוש מסופקות כקוד מקור טבעי של Pascal עבור Delphi ו-C++Builder, ללא שום תלויות זמן ריצה (runtime dependencies) מעבר ל-VCL. רכיב PDFium Component גם אורז בנוסף את ה-DLL של PDFium, שמכסה את עבודת הרינדור והניתוח (parsing) של המנוע. עמוד המוצר של כל ספרייה נושא את הפניה המלאה (reference) לממשקי ה-API שלה ואת היסטוריית הגרסאות הנוכחית

פרטים על הספריות הבודדות: רכיב HotPDF, רכיב PDFium Component, ו-PDFlibPas