Delphin PDFium-komponentti varmistaa tulostusvalmiit PDF/X-dokumentit TPdf.ValidatePdfX-metodin kautta, joka toteuttaa ISO 15930 -tarkistukset kahdessa kerroksessa: kahdeksan tavutason sisällöntarkistusta (kielletty LZW-pakkaus, JavaScript, lomakekentät, OPI-viittaukset, puuttuva TrimBox, määrittämätön Trapped-avain ja muita) sekä PDFium-objektimallin läpikäynti, joka varmistaa jokaisen sivun jokaisen tekstiobjektin fontin upotuksen FPDFFont_GetIsEmbedded-funktiolla. Tuloksena on TPdfXValidationResult-tietue, joka nimeää havaitun yhteensopivuustason ja luettelee kunkin rikkomuksen tyypitettynä enumina. Näin Delphi-sovelluksesi voi kertoa asiakkaalle täsmälleen, miksi tiedosto hylätään painotalossa, ennen kuin kukaan ehtii valottaa painolevyjä
Jos olet koskaan lähettänyt työn kaupalliseen painoon ja saanut sen takaisin yhden rivin hylkäysviestillä — "ei TrimBoxia", "fontteja ei ole upotettu", "Trapped-avainta ei ole määritetty" — tiedät, kuinka kalliiksi myöhäinen havaitseminen tulee. PDF/X on painovalmistelun (prepress) vastine PDF/A-standardille: kun arkistoitava PDF/A takaa, että dokumentti piirtyy identtisesti vuosikymmenien kuluttua, PDF/X takaa, että dokumentti värierotellaan, kuvataan ja leikataan identtisesti jonkun toisen RIP-laitteessa huomisaamuna. Nämä kaksi standardia jakavat saman koneiston (XMP-tunnistus, OutputIntents, upotetut ICC-profiilit), mutta vastaavat eri kysymyksiin. Siksi komponentti toimitetaan erillisillä validaattoreilla kumpaakin varten — PDF/A-puolta käsitellään artikkelissamme PDF/A-preflight-varmistuksesta PDFium-komponentilla
Mitä ISO 15930 todellisuudessa vaatii tulostusvalmiilta PDF:ltä?
Standardi ISO 15930 on olemassa, jotta sokea vaihto (blind exchange) olisi mahdollista: suunnittelija antaa tiedoston painajalle, jolle hän ei ole koskaan puhunut, ja painaja voi tuottaa oikean tuloksen ilman puheluita, puuttuvia fontteja koskevia sähköposteja tai linkitettyä kuvaa, joka jäi suunnittelijan kannettavalle tietokoneelle. Jokainen standardin sääntö palvelee tätä tavoitetta. Fonttien on oltava upotettuja, koska vastaanottavan RIP-laitteen ei voida olettaa omistavan niitä. Ulkoiset viittaukset on kielletty, koska tiedoston on oltava itsessään täydellinen. Interaktiiviset toiminnot on kielletty, koska musteella ei ole onclick-käsittelijää
PDFium-komponentti tunnistaa kolme yhteensopivuusperhettä ja raportoi ne TPdfXConformance-enumin kautta varmistustuloksessa: pxc1a tarkoittaa PDF/X-1a:2001-tasoa (ISO 15930-1, tiukka CMYK-plus-lisäväriperustaso PDF 1.3/1.4 -muodoissa), pxc3 tarkoittaa PDF/X-3:2002-tasoa (ISO 15930-3, joka sallii RGB-, Lab- ja ICC-hallitut värit) ja pxc4 tarkoittaa PDF/X-4:2010-tasoa (ISO 15930-7, joka lopulta sallii aidon läpinäkyvyyden ja tasot PDF 1.6 -pohjalla). Tiedosto, joka ei sisällä lainkaan PDF/X-tunnistusta, palauttaa arvon pxcNone, mikä on itsessään hyödyllinen vastaus: dokumentti ei koskaan väittänyt olevansa tulostusvalmis, ja kaikki muu validaattorin raportoima tieto selittää, mitä sinne pääseminen vaatisi
Kiellot ovat järkeviä, kun ajattelee kuin RIP-laitteen toimittaja. /LZWDecode on kielletty kaikissa PDF/X-versioissa, jotta yhteensopiva kuluttaja ei koskaan riippuisi suodattimesta, jolla on yhteensopivuus- ja lisensointihistoria; Flate tekee saman työn ilman tätä painolastia. JavaScript, AcroForm-kentät ja /AA-lisätoimintohakemistot on kielletty, koska tulostustiedoston on oltava kiinteä kuvaus paperilla olevista jäljistä — mikä tahansa, mikä voi muuttaa ulkoasua avaushetkellä, rikkoo takuun siitä, että vedostettu on se mikä tulostuu. OPI-paikkamerkit (Open Prepress Interface) on kielletty, koska ne ovat suunnitellusti viittauksia korkearesoluutioisiin kuviin, jotka on tallennettu jonnekin muualle, ja "jossain muualla" on juuri se, minkä sokea vaihto kieltää
Miksi painotalot hylkäävät PDF-tiedostot ilman TrimBoxia?
TrimBox on valmis sivu — suorakulmio, joka jää jäljelle giljotiinileikkauksen jälkeen. MediaBox, joka on jokaisella PDF-sivulla, on pelkkä arkki: se sisältää leikkuuvarat (bleed), leikkausmerkit, kohdistusmerkit ja väripalkit. Asemointiohjelmistot sijoittavat sivut painoarkille niiden TrimBoxien perusteella. Ilman sitä operaattorin on arvattava, mihin käyntikorttisi todella päättyy, ja väärä arvaus leikkaa pois leikkuuvarasi tai jättää valkoisen suikaleen yhteen reunaan. Siksi ISO 15930 vaatii TrimBoxin (tai ArtBoxin) jokaiselle sivulle, ja siksi ValidatePdfX nostaa poikkeuksen pvxiMissingTrimBox, jos /TrimBox-avainta ei löydy miltään dokumentin sivulta
/Trapped-avain vastaa toiseen tuotannolliseen kysymykseen. Lihotus (trapping) on painovalmistelutekniikka, jossa vierekkäisiä värejä limitetään hieman, jotta painokoneen pieni kohdistusvirhe ei avaa valkoisia rakoja niiden väliin. Painajan on tiedettävä, onko tämä työ jo tehty: jo lihotetun tiedoston lihottaminen kaksinkertaistaa limitykset, ja lihotuksen ohittaminen lihottamattomassa tiedostossa vaarantaa näkyvien rakojen syntymisen. Siksi PDF/X vaatii Info-hakemiston ilmoittavan /Trapped /True tai /Trapped /False nimenomaisesti — puuttuva avain tai /Unknown pakottaa ihmisen tarkastamaan tiedoston, mikä on juuri se keskustelu, jonka sokea vaihto oli tarkoitettu poistamaan. Komponentti merkitsee tämän tilaksi pvxiTrappedNotSet
Kaksikerroksisen varmistuksen suorittaminen TPdf.ValidatePdfX-metodilla
TPdf.ValidatePdfX ei ota argumentteja ja palauttaa TPdfXValidationResult-tietueen, jossa on kolme jäsentä: Conformance (havaittu PDF/X-tyyppi), Issues (Pascal-joukko TPdfXValidationIssue-arvoja) ja IsCompliant-apumuuttuja. Sisäisesti se sarjoittaa ladatun dokumentin muistivirtaan, ajaa tavutason tarkastuksen sen yli ja käy sitten läpi PDFium-objektimallin fonttikohtaista upotustarkistusta varten. Minimaalinen tarkistusportti näyttää tältä:
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: no /TrimBox on the pages');
if pvxiTrappedNotSet in Res.Issues then
Writeln('REJECT: /Trapped missing or /Unknown');
if pvxiPdfiumFontNotEmbedded in Res.Issues then
Writeln('REJECT: a page uses a non-embedded font');
if pvxiLzwForbidden in Res.Issues then
Writeln('REJECT: LZWDecode filter present');
end;
finally
Pdf.Free;
end;
end;
Koska Issues on tavallinen Pascal-joukko, voit jakaa sen työnkulkusi tarpeiden mukaan — käsitellä rakenteellisia ongelmia ehdottomina hylkäyksinä, käsitellä arvoa pvxiMissingTitle (standardin SHOULD, ei MUST) varoituksena ja kirjata loput lokiin. Sama tietuetyyppi syöttää myös komponentin raporttigeneraattoria, joten jos haluat mieluummin luottaa ihmisen luettavaan raporttiin enumeilla haarautumisen sijaan, esikatseluraportin eräajona suorittava komentorivikäyttöliittymä (CLI) toimii PDF/X:n kanssa muuttumattomana
Mitä tavutason kerros havaitsee — ja mitä se ei havaitse
Tavutason kerros on tunnisteiden (token) skannaus dokumentin rakennetavujen yli siten, että tietovirtasisällöt (stream bodies) on tyhjennetty. Siten esimerkiksi JPEG-kuva, joka sattuu sisältämään tavukuvion /JavaScript, ei voi aiheuttaa väärää positiivista tulosta. Merkkikohtaisten tarkistusten lisäksi (XMP pdfxid:GTS_PDFXVersion, OutputIntent upotetulla ICC-profiililla, trailerin /ID, salauksen kielto) sisällön läpikäynti lisää kahdeksan tarkistusta, joilla jokaisella on oma enum-arvonsa:
pvxiLzwForbidden— a/LZWDecodefilter appears anywhere in the file (forbidden in all PDF/X variants)pvxiJavaScriptForbidden— a/JavaScriptaction or name tree is presentpvxiFormFieldsForbidden— an/AcroFormdictionary or/XFAentry existspvxiAdditionalActions— an/AAadditional-actions dictionary is presentpvxiEmbeddedFilesForbidden—/EmbeddedFilesor a/FileAttachmentannotation is presentpvxiOpiForbidden— an/OPIor/Alternatesentry references replaceable image contentpvxiMissingTrimBox— no/TrimBoxfound on any pagepvxiTrappedNotSet—/Trappedis absent or set to/Unknown
Tavujen skannaus on nopeaa eikä se tarvitse piirtomoottoria, mutta sillä on luonnollinen sokea piste fonttien suhteen: tällä tasolla tarkastaja voi soveltaa vain karkeaa heuristiikkaa — se merkitsee dokumentin virheelliseksi vain silloin, kun se ei löydä mitään upotettua fonttiohjelmaa lainkaan. Tiedosto, jossa on yhdeksän upotettua fonttia ja yksi järjestelmäfontti eksynyt joukkoon, näyttää tavuskannauksessa kelvolliselta. Tämä aukko on syy sille, miksi toinen kerros on olemassa
Fonttikohtainen upotus PDFium-objektimallin kautta
PDFium-komponentin objektimallikerros vastaa fonttikysymykseen tarkasti. Tavutason vaiheen jälkeen TPdf.ValidatePdfX käy läpi jokaisen sivun, kysyy FPDFPage_CountObjects-metodilla objektiluettelon ja selvittää jokaiselle tekstiobjektille fonttikahvan FPDFTextObj_GetFont-funktiolla ja kysyy FPDFFont_GetIsEmbedded-arvon. Yksikin upottamaton fontti missä tahansa dokumentissa lisää arvon pvxiPdfiumFontNotEmbedded issue-joukkoon. Läpikäynti oikosuljetaan kahdella tasolla — se lopettaa objektien skannauksen sivulla ja lopettaa muiden sivujen lataamisen heti, kun virhe varmistuu. Siten virheellisen 300-sivuisen kuvaston kohdalla tuomio saapuu usein jo ensimmäisen sivun jälkeen
Kaksi rajoitusta on syytä tietää. Ensinnäkin tämä kerros vaatii PDFium-kirjaston lataamisen ja käännökset, jotka vievät (export) funktion FPDFFont_GetIsEmbedded. Jos funktiota ei ole viety, tarkistus ohitetaan hylkäämisen sijaan, joten vanhempi DLL ei koskaan tuota haamuhylkäyksiä. Toiseksi tarkistus vastaa vain kysymykseen "upotettu vai ei" — se ei erota täyttä upotusta osajoukko-upotuksesta (subsetting) eikä tarkasta glyyfimääriä. Kun tiedosto epäonnistuu ja haluat tietää, mikä fontti milläkin sivulla on kyseessä, PDF-fonttien ominaisuuksien analysointia käsittelevän artikkelimme luettelointitekniikat jatkavat täsmälleen siitä, mihin validaattorin totuusarvo päättyy
Tietovirtojen varmistaminen ilman dokumentin lataamista — tai DLL-tiedostoa
Tavutason tarkastaja on myös tuotu esiin itsenäisenä funktiona ValidatePdfXCompliance(Source: TStream) FPdfPdfx-yksikössä, ja se on puhdasta Object Pascalia ilman riippuvuutta PDFium DLL-tiedostosta. Tämä tekee siitä käyttöönotettavan paikoissa, joissa piirtomoottoria ei haluta: kevyessä latausportissa verkkopalvelimella, CI-tehtävässä joka tarkastaa luotua aineistoa tai Lazarus-palvelussa alustalla, jonne et halua toimittaa natiiveja binäärejä. Syötä sille mikä tahansa kelattava (seekable) virta:
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;
Vaihtokauppa on selvä: itsenäinen polku ajaa merkkien tarkistukset ja kaikki kahdeksan sisällöntarkistusta, mutta ei fonttikohtaista PDFium-kerrosta. Siten sen fonttituomio nojaa karkeaan heuristiikkaan. Järkevä arkkitehtuuri käyttää ValidatePdfXCompliance-funktiota edullisena ensimmäisenä porttina ja säästää täyden TPdf.ValidatePdfX-metodin tiedostoille, jotka läpäisevät sen
Mihin tämä validaattori päättyy ja mihin täysi preflight alkaa
Rehellisyys on tärkeää preflight-työkaluissa, joten tässä on raja. ValidatePdfX varmistaa tunnistemerkit, rakenteelliset kiellot, sivugeometrian avaimet, Trapped-ilmoituksen ja fonttien upotuksen aina yksittäisiin tekstiobjekteihin saakka. Se ei mittaa kokonaisväripeittoa (total ink coverage), varmista että jokainen väriavaruus on laillinen ilmoitetulle variantille (esimerkiksi X-1a:n vain-CMYK-sääntö), tarkista kuvaresoluutiota tai arvioi väripäällyksen (overprint) ja läpinäkyvyyden litistämisen käyttäytymistä — nämä vaativat värihallitun preflight-moottorin, ja yksikön oma dokumentaatio suosittelee sen yhdistämistä sellaiseen lopullista sertifiointia varten. Se, mitä tämä kaksikerroksinen tarkistus antaa, on 80 % hylkäyksistä, jotka ovat rakenteellisia ja havaittavissa ajoissa, mitattuna millisekunneissa omassa Delphi-koodissasi huomisen painajan hylkäyssähköpostin sijaan
Molemmat varmistuskerrokset, PDF/X-merkkien syöttö-API:t yhteensopivan tulosteen tuottamiseksi sekä saman arkkitehtuurin jakavat PDF/A-, PDF/UA-, PDF/E- ja PDF/VT-validaattorit toimitetaan PDFium Component -kirjastossa Delphille ja C++Builderille — yksi komponentti piirtämisestä aina painovalmistelun valvontaan