PDFium Component untuk Delphi memvalidasi dokumen PDF/X siap cetak melalui TPdf.ValidatePdfX, yang mengimplementasikan pemeriksaan ISO 15930 dalam dua lapisan: delapan pemeriksaan konten tingkat bita (kompresi LZW terlarang, JavaScript, bidang formulir, referensi OPI, TrimBox yang hilang, kunci Trapped yang tidak disetel, dan banyak lagi) ditambah lintasan model-objek PDFium yang menggunakan FPDFFont_GetIsEmbedded untuk memverifikasi penyematan font pada setiap objek teks di setiap halaman. Hasilnya adalah catatan TPdfXValidationResult yang menyebutkan tingkat kesesuaian yang terdeteksi dan mencantumkan setiap pelanggaran sebagai enum bertipe, sehingga aplikasi Delphi Anda dapat memberi tahu pelanggan dengan tepat mengapa file akan ditolak di toko percetakan sebelum ada yang mencetak pelat
Jika Anda pernah mengirimkan pekerjaan ke percetakan komersial dan menerimanya kembali dengan penolakan satu baris — "tidak ada TrimBox", "font tidak disematkan", "Trapped tidak disetel" — Anda tahu biaya yang harus dibayar karena terlambat mengetahuinya. PDF/X adalah rekan pracetak untuk PDF/A: di mana arsip PDF/A menjamin dokumen dirender secara identik beberapa dekade dari sekarang, PDF/X menjamin dokumen dipisahkan, dicitrakan, dan dipotong secara identik pada RIP (Raster Image Processor) orang lain besok pagi. Kedua standar tersebut berbagi mesin (identifikasi XMP, OutputIntents, profil ICC tersemat) tetapi menjawab pertanyaan yang berbeda, itulah sebabnya komponen mengirimkan validator terpisah untuk masing-masing — sisi PDF/A dibahas dalam validasi pra-penerbangan PDF/A dengan PDFium Component
Apa yang sebenarnya disyaratkan ISO 15930 dari PDF siap cetak?
ISO 15930 ada untuk memungkinkan terjadinya blind exchange (pertukaran buta): seorang desainer menyerahkan file ke printer yang belum pernah mereka ajak bicara, dan percetakan tersebut dapat menghasilkan output yang benar tanpa panggilan telepon, tanpa email kehilangan font, dan tanpa gambar tertaut yang tertinggal di laptop desainer. Setiap aturan dalam standar melayani tujuan itu. Font harus disematkan karena RIP penerima tidak dapat diasumsikan memilikinya. Referensi eksternal dilarang karena file tersebut harus lengkap di dalamnya sendiri. Fitur interaktif dilarang karena tinta tidak memiliki penangan onclick
PDFium Component mengenali tiga keluarga kesesuaian dan melaporkannya melalui enum TPdfXConformance dalam hasil validasi: pxc1a untuk PDF/X-1a:2001 (ISO 15930-1, garis dasar CMYK-plus-spot yang ketat pada PDF 1.3/1.4), pxc3 untuk PDF/X-3:2002 (ISO 15930-3, yang menerima warna terkelola RGB, Lab, dan ICC), dan pxc4 untuk PDF/X-4:2010 (ISO 15930-7, yang akhirnya memungkinkan transparansi hidup dan lapisan pada basis PDF 1.6). File yang tidak membawa identifikasi PDF/X sama sekali kembali sebagai pxcNone, yang merupakan jawaban yang berguna: dokumen tersebut tidak pernah diklaim siap cetak, dan hal-hal lain yang dilaporkan validator menjelaskan apa yang diperlukan untuk mencapainya
Larangan tersebut masuk akal setelah Anda berpikir seperti vendor RIP. /LZWDecode dilarang di setiap varian PDF/X sehingga konsumen yang patuh tidak pernah bergantung pada filter dengan riwayat kompatibilitas dan lisensi; Flate melakukan pekerjaan yang sama tanpa beban tersebut. JavaScript, bidang AcroForm, dan kamus tindakan tambahan /AA dilarang karena file cetak harus berupa deskripsi tetap dari tanda di atas kertas — apa pun yang dapat mengubah tampilan pada saat dibuka akan merusak jaminan bahwa apa yang terbukti adalah apa yang dicetak. Penampung OPI (Open Prepress Interface) dilarang karena, secara desain, mereka merupakan referensi ke gambar resolusi tinggi yang disimpan di tempat lain, dan "tempat lain" adalah tepat apa yang dilarang oleh pertukaran buta (blind exchange)
Mengapa toko percetakan menolak PDF tanpa TrimBox?
TrimBox adalah halaman jadi — persegi panjang yang tersisa setelah pemotongan guillotine. MediaBox, yang dimiliki setiap halaman PDF, hanyalah lembaran: mencakup bleed, tanda potong (crop marks), target pendaftaran, dan bilah warna. Perangkat lunak imposisi memosisikan halaman pada lembaran pers berdasarkan TrimBox mereka; tanpa itu, operator harus menebak di mana kartu nama Anda sebenarnya berakhir, dan tebakan yang salah akan memotong bleed Anda atau menyisakan celah putih di satu sisi. Itulah mengapa ISO 15930 memerlukan TrimBox (atau ArtBox) pada setiap halaman, dan mengapa ValidatePdfX memunculkan pvxiMissingTrimBox ketika tidak ada kunci /TrimBox yang ditemukan di halaman mana pun dari dokumen
Kunci /Trapped menjawab pertanyaan produksi yang berbeda. Trapping adalah teknik pracetak yang sedikit menumpang-tindihkan warna yang berdekatan sehingga misregistrasi pers yang kecil tidak membuka celah putih di antara mereka. Percetakan perlu tahu apakah pekerjaan itu sudah dilakukan: trapping pada file yang sudah di-trapping akan melipatgandakan tumpang tindih, dan melewatkan trapping pada file yang tidak di-trapping berisiko memunculkan celah yang terlihat. Oleh karena itu, PDF/X mengharuskan kamus Info untuk menyatakan /Trapped /True atau /Trapped /False secara eksplisit — kunci yang hilang atau /Unknown memaksa manusia untuk memeriksa file tersebut, yang merupakan percakapan yang ingin dihilangkan oleh pertukaran buta. Komponen menandai ini sebagai pvxiTrappedNotSet
Menjalankan validasi dua lapisan dengan TPdf.ValidatePdfX
TPdf.ValidatePdfX mengambil no argumen dan mengembalikan catatan TPdfXValidationResult dengan tiga anggota: Conformance (varian PDF/X yang terdeteksi), Issues (set Pascal dari nilai-nilai TPdfXValidationIssue), dan pembantu IsCompliant. Secara internal, ia menyerialkan dokumen yang dimuat ke aliran memori, menjalankan inspektur tingkat bita di atasnya, dan kemudian berjalan melintasi model objek PDFium untuk pemeriksaan penyematan per font. Gerbang pra-penerbangan minimal tampak seperti ini:
uses PDFium, FPdfPdfx;
procedure CheckPrintReadiness(const FileName: string);
var
Pdf: TPdf;
Res: TPdfXValidationResult;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := FileName;
Pdf.Active := True;
Res := Pdf.ValidatePdfX;
Writeln('Detected conformance: ',
Ord(Res.Conformance)); // pxc1a, pxc3, pxc4, pxcNone...
if Res.IsCompliant then
Writeln('PDF/X checks passed')
else
begin
if pvxiMissingTrimBox in Res.Issues then
Writeln('REJECT: tidak ada /TrimBox pada halaman');
if pvxiTrappedNotSet in Res.Issues then
Writeln('REJECT: /Trapped hilang atau /Unknown');
if pvxiPdfiumFontNotEmbedded in Res.Issues then
Writeln('REJECT: halaman menggunakan font yang tidak disematkan');
if pvxiLzwForbidden in Res.Issues then
Writeln('REJECT: filter LZWDecode ada');
end;
finally
Pdf.Free;
end;
end;
Karena Issues adalah set Pascal biasa, Anda dapat mempartisinya sesuai kebutuhan alur kerja Anda — memperlakukan masalah struktural sebagai penolakan keras, memperlakukan pvxiMissingTitle (sebuah SHOULD dalam standar, bukan MUST) sebagai peringatan, dan mencatat sisanya. Jenis rekaman yang sama juga memberi makan generator laporan komponen, jadi jika Anda lebih suka memancarkan dokumen yang dapat dibaca manusia daripada bercabang pada enum, pola dalam membangun CLI laporan pra-penerbangan batch dengan PDFium Component berlaku untuk PDF/X tanpa perubahan
Apa yang ditangkap oleh lapisan tingkat bita — dan apa yang terlewatkan
Pemindaian bita cepat dan tidak memerlukan mesin rendering, tetapi memiliki titik buta bawaan pada font: pada tingkat itu inspektur hanya dapat menerapkan heuristik kasar — ia menandai dokumen ketika ia tidak menemukan program font tersemat sama sekali. File dengan sembilan font tersemat dan satu font sistem yang diselipkan terlihat baik-baik saja pada pemindaian bita. Kesenjangan tunggal itulah mengapa lapisan kedua ada
pvxiLzwForbidden— filter/LZWDecodemuncul di mana saja dalam file (dilarang di semua varian PDF/X)pvxiJavaScriptForbidden— tindakan atau pohon nama/JavaScripthadirpvxiFormFieldsForbidden— kamus/AcroFormatau entri/XFAadapvxiAdditionalActions— kamus tindakan tambahan/AAadapvxiEmbeddedFilesForbidden—/EmbeddedFilesatau anotasi/FileAttachmentadapvxiOpiForbidden— entri/OPIatau/Alternatesmerujuk ke konten gambar yang dapat digantipvxiMissingTrimBox— tidak ada/TrimBoxditemukan di halaman mana punpvxiTrappedNotSet—/Trappedabsen atau disetel ke/Unknown
Penyematan per font melalui model objek PDFium
Lapisan model objek PDFium Component menjawab pertanyaan font dengan tepat. Setelah lintasan tingkat bita, TPdf.ValidatePdfX melakukan iterasi di setiap halaman, meminta daftar objek dari FPDFPage_CountObjects, dan untuk setiap objek teks menyelesaikan handel font via FPDFTextObj_GetFont dan menanyakan FPDFFont_GetIsEmbedded. Satu font yang tidak disematkan di mana saja dalam dokumen menambahkan pvxiPdfiumFontNotEmbedded ke set masalah. Penelusuran melakukan hubungan singkat (short-circuit) pada dua tingkat — ia berhenti memindai objek pada suatu halaman, dan berhenti memuat halaman berikutnya, saat masalah dikonfirmasi — sehingga pada katalog 300 halaman yang melanggar, putusan sering kali tiba setelah halaman pertama
Dua catatan batas yang patut diketahui. Pertama, lapisan ini memerlukan pustaka PDFium dimuat dan memerlukan build yang mengekspor FPDFFont_GetIsEmbedded; ketika ekspor tidak ada, pemeriksaan dilewati alih-alih gagal, sehingga DLL lama tidak pernah menghasilkan penolakan semu (phantom). Kedua, pemeriksaan menjawab "disematkan atau tidak" dan tidak lebih dari itu — ia tidak membedakan penyematan penuh dari subsetting, juga tidak memeriksa cakupan glyph. Ketika file gagal dan Anda perlu tahu font mana pada halaman mana, teknik enumerasi dalam menganalisis properti font PDF dengan PDFium di Delphi mengambil alih tepat di mana boolean validator berakhir
Memvalidasi aliran tanpa memuat dokumen — atau DLL
Inspektur tingkat bita juga diekspos sebagai fungsi mandiri, ValidatePdfXCompliance(Source: TStream) di unit FPdfPdfx, dan ini adalah Object Pascal murni tanpa ketergantungan pada PDFium DLL. Hal itu membuatnya dapat diterapkan di tempat-tempat di mana mesin rendering tidak diinginkan: gerbang unggahan ringan di server web, pekerjaan CI yang memeriksa karya seni yang dihasilkan, atau layanan Lazarus di platform di mana Anda memilih untuk tidak mengirimkan biner asli. Beri makan aliran apa pun yang dapat dicari (seekable stream):
uses Classes, FPdfPdfx;
function QuickPdfXGate(const FileName: string): Boolean;
var
Fs: TFileStream;
Res: TPdfXValidationResult;
begin
Fs := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Res := ValidatePdfXCompliance(Fs);
Result := Res.IsCompliant and (Res.Conformance <> pxcNone);
finally
Fs.Free;
end;
end;
Pertukarannya sangat jelas: jalur mandiri (standalone path) menjalankan pemeriksaan penanda dan delapan pemeriksaan konten, tetapi tidak untuk lapisan PDFium per-font, sehingga putusan font-nya kembali ke heuristik kasar. Arsitektur yang bijaksana menggunakan ValidatePdfXCompliance sebagai gerbang pertama yang murah dan mencadangkan TPdf.ValidatePdfX lengkap untuk file yang lolos darinya
Di mana validator ini berakhir dan pra-penerbangan penuh dimulai
Kejujuran penting dalam alat pra-penerbangan, jadi inilah batasannya. ValidatePdfX memverifikasi penanda identifikasi, larangan struktural, kunci geometri halaman, deklarasi Trapped, dan penyematan font hingga ke objek teks individu. Ini tidak mengukur cakupan tinta total, memvalidasi bahwa setiap ruang warna sah untuk varian yang diklaim (misalnya aturan hanya CMYK dari X-1a), memeriksa resolusi gambar terhadap layar garis, atau mengevaluasi perilaku cetak tindih (overprint) dan perataan transparansi — itu memerlukan mesin pra-penerbangan dengan warna terkelola, dan dokumentasi unit sendiri menyarankan untuk memasangkannya dengan mesin tersebut untuk sertifikasi akhir. Apa yang diberikan oleh pemeriksaan dua lapisan ini adalah 80% penolakan yang bersifat struktural dan terdeteksi lebih awal, tertangkap dalam hitungan milidetik di dalam kode Delphi Anda sendiri alih-alih dalam email besok dari percetakan
Kedua lapisan validasi, API injeksi penanda PDF/X untuk menghasilkan output yang patuh, serta validator PDF/A, PDF/UA, PDF/E, dan PDF/VT yang berbagi arsitektur yang sama dikirimkan dalam PDFium Component untuk Delphi dan C++Builder — satu komponen, dari rendering hingga gerbang pracetak