PDFium Component til Delphi validerer trykklare PDF/X-dokumenter via TPdf.ValidatePdfX, som implementerer ISO 15930-kontrol i to lag: Otte indholdskontroller på byte-niveau (forbudt LZW-komprimering, JavaScript, formularfelter, OPI-referencer, manglende TrimBox, manglende Trapped-nøgle med mere) samt en PDFium-objektmodelkørsel, der bruger FPDFFont_GetIsEmbedded to validerer skrifttypeindlejring på hvert tekstobjekt på hver side. Resultatet er en TPdfXValidationResult-post (record), der navngiver det registrerede overensstemmelsesniveau og viser hver overtrædelse som en typebestemt enum, så din Delphi-applikation kan fortælle kunden præcis, hvorfor en fil vil blive afvist på trykkeriet, før der fremstilles trykplader
Hvis du nogensinde har sendt en opgave til et kommercielt trykkeri og modtaget den retur med en afvisning på én linje — "ingen TrimBox", "skrifttyper ikke indlejret", "Trapped ikke indstillet" — kender du omkostningerne ved at finde ud af det for sen. PDF/X er prepress-modstykket til PDF/A: Hvor arkiverings-PDF/A garanterer, at et dokument gengives identisk om årtier, garanterer PDF/X, at et dokument separeres, belyses og beskæres identisk på en andens RIP i morgen tidlig. De to standarder deler mekanik (XMP-identifikation, OutputIntents, indlejrede ICC-profiler), men besvarer forskellige spørgsmål, hvorfor komponenten leveres med separate valideringsværktøjer til hver — PDF/A-siden er dækket i PDF/A-preflight-validering med PDFium Component
Hvad kræver ISO 15930 egentlig af en trykklar PDF?
ISO 15930 eksisterer for at gøre blind udveksling (blind exchange) mulig: En designer afleverer en fil to et trykkeri, de aldrig har talt med, og trykkeriet kan producere korrekt output uden telefonopkald, uden e-mails om manglende skrifttyper og uden tilknyttede billeder, der blev liggende på designerens bærbare computer. Enhver regel i standarden tjener dette mål. Skrifttyper skal indlejres, fordi modtagerens RIP ikke kan antages at eje dem. Eksterne referencer er forbudt, fordi filen skal være komplet i sig selv. Interaktive funktioner er forbudt, fordi trykfarve ikke har nogen onclick-håndtering
PDFium Component genkender tre overensstemmelsesfamilier og rapporterer dem via TPdfXConformance-enum i valideringsresultatet: pxc1a for PDF/X-1a:2001 (ISO 15930-1, den strenge CMYK-plus-spot-baseline på PDF 1.3/1.4), pxc3 for PDF/X-3:2002 (ISO 15930-3, som tillader RGB, Lab og ICC-styret farve) og pxc4 for PDF/X-4:2010 (ISO 15930-7, som endelig tillader levende gennemsigtighed og lag på en PDF 1.6 base). En fil, der slet ikke bærer nogen PDF/X-identifikation, returneres som pxcNone, hvilket i sig selv er et nyttigt svar: Dokumentet har aldrig hævdet at være trykklart, og alt andet, som valideringsværktøjet rapporterer, forklarer, hvad der skal til for at nå dertil
Forbuddene giver mening, når man tænker som en RIP-leverandør. /LZWDecode er forbudt i enhver PDF/X-variant, så en overensstemmende forbruger aldrig er afhængig af et filter med en kompatibilitets- og licenshistorik; Flate udfører det samme arbejde uden denne bagage. JavaScript, AcroForm-felter og /AA-ordbøger til yderligere handlinger er forbudt, fordi en trykfil skal være en fast beskrivelse af mærker på papir — alt, hvad der kan ændre udseende på åbningstidspunktet, bryder garantien for, at det, der blev godkendt, er det, der trykkes. OPI (Open Prepress Interface) stedfortrædere (placeholders) er forbudt, fordi de efter design er referencer til billeder i høj opløsning, der er gemt et andet sted, og "et andet sted" er præcis, hvad blind udveksling forbyder
Hvorfor afviser trykkerier PDF-filer uden en TrimBox?
TrimBox er den færdige side — det rektangel, der er tilbage efter guillotinesnittet. MediaBox, som enhver PDF-side har, er blot papiret: Den inkluderer beskæring (bleed), skæremærker, registreringsmærker og farvebjælker. Udskydningssoftware (imposition software) placerer sider på et trykark ud fra deres TrimBoxes; uden en TrimBox skal operatøren gætte, hvor dit visitkort reelt slutter, og et forkert gæt kan skære beskæringen af eller efterlade en hvid kant. Det er grunden til, at ISO 15930 kræver en TrimBox (or en ArtBox) på hver side, og hvorfor ValidatePdfX rejser pvxiMissingTrimBox, når der ikke findes nogen /TrimBox-nøgle på nogen side i dokumentet
Nøglen /Trapped besvarer et andet produktionsspørgsmål. Trapping er prepress-teknikken med at overlappe tilstødende farver en smule, så mikroskopiske presseregistreringsfejl ikke skaber hvide huller imellem dem. Trykkeriet har brug for at vide, om dette arbejde allerede er udført: Trapping af en i forvejen trappet fil fordobler overlapningerne, og at springe trapping over på en utrappet fil risikerer synlige huller. PDF/X kræver derfor, at Info-ordbogen eksplicit angiver /Trapped /True eller /Trapped /False — en manglende nøgle eller /Unknown tvinger et menneske til at inspicere filen, hvilket er præcis den samtale, blind udveksling var beregnet til at eliminere. Komponenten markerer dette som pvxiTrappedNotSet
Kørsel af to-lags valideringen med TPdf.ValidatePdfX
TPdf.ValidatePdfX tager ingen argumenter og returnerer en TPdfXValidationResult-post med tre elementer: Conformance (den registrerede PDF/X-variant), Issues (et Pascal-set af TPdfXValidationIssue-værdier) og en IsCompliant-hjælper. Internt serialiserer den det indlæste dokument til en hukommelsesstrøm, afvikler inspektionen på byte-niveau over det og gennemgår derefter PDFium-objektmodellen for indlejringskontrollen pr. skrifttype. En minimal preflight-kontrol ser således ud:
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: 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;
Fordi Issues er et almindeligt Pascal-set, kan du opdele det, som din arbejdsgang kræver — behandle strukturelle problemer som hårde afvisninger, behandle pvxiMissingTitle (et BØR i standarden, ikke et SKAL) som en advarsel, og logge resten. Den samme post-type føder også komponentens rapportgenerator, så hvis du hellere vil generere et menneskeligt læsbart dokument frem for at forgrene på enums, gælder mønsteret i opbygning af en batch-preflight-rapport CLI med PDFium Component uændret for PDF/X
Hvad byte-niveau-laget fanger — og hvad det overser
Byte-niveau-laget er en token-scanning over dokumentets strukturelle bytes, hvor strøm-indholdet (stream bodies) er maskeret, så en JPEG, der tilfældigvis indeholder byte-mønsteret /JavaScript, ikke kan udløse en falsk positiv. Oven i markørkontrollerne (XMP pdfxid:GTS_PDFXVersion, OutputIntent med en indlejret ICC-profil, trailer-/ID, forbuddet mod kryptering) tilføjer indholdskørslen otte kontroller, hver med sin egen enum-værdi:
pvxiLzwForbidden— et/LZWDecode-filter optræder et sted i filen (forbudt i alle PDF/X-varianter)pvxiJavaScriptForbidden— en/JavaScript-handling eller et navnetræ er til stedepvxiFormFieldsForbidden— en/AcroForm-ordbog eller/XFA-post eksistererpvxiAdditionalActions— en/AA-ordbog til yderligere handlinger er til stedepvxiEmbeddedFilesForbidden—/EmbeddedFileseller en/FileAttachment-annotering er til stedepvxiOpiForbidden— en/OPI- eller/Alternates-post refererer til udskifteligt billedindholdpvxiMissingTrimBox— ingen/TrimBoxfundet på nogen sidepvxiTrappedNotSet—/Trappedmangler eller er sat til/Unknown
Byte-scanning er hurtig og kræver ingen gengivelsesmotor, men den har et indbygget blindt punkt med hensyn til skrifttyper: På dette niveau kan inspektionen kun anvende en grov heuristik — den markerer et dokument som fejlbehæftet, hvis den overhovedet ikke finder noget indlejret skrifttypeprogram. En fil med ni indlejrede skrifttyper og én systemskrifttype, der er sneget ind, ser fin ud ved en byte-scanning. Dette enkeles hul er grunden til, at det andet lag eksisterer
Indlejring pr. skrifttype via PDFium-objektmodellen
PDFium Components objektmodel-lag besvarer skrifttypespørgsmålet præcist. Efter byte-niveau-kørslen gennemløber TPdf.ValidatePdfX hver side, spørger FPDFPage_CountObjects efter objektlisten, og for hvert tekstobjekt finder den skrifttypehåndtaget via FPDFTextObj_GetFont og forespørger FPDFFont_GetIsEmbedded. En enkelt ikke-indlejret skrifttype et hvilket som helst sted i dokumentet tilføjer pvxiPdfiumFontNotEmbedded to sættet af problemer. Gennemgangen afbrydes (short-circuits) på to niveauer — den stopper med at scanne objekter på en side, og stopper med at indlæse yderligere sider, i samme øjeblik problemet er bekræftet — så på et overtrædende katalog på 300 sider ankommer dommen ofte efter side et
To grænsenotater, der er værd at kende. For det første kræver dette lag, at PDFium-biblioteket er indlæst, og kræver versioner, der eksporterer FPDFFont_GetIsEmbedded; når eksporten mangler, springes kontrollen over frem for at fejle, så en ældre DLL aldrig producerer falske afvisninger. For det andet besvarer kontrollen "indlejret eller ej" og intet mere — den skelner ikke mellem fuld indlejring og delvis indlejring (subsetting), og den inspicerer heller ikke tegndækning. Når en fil fejler, og du har brug for at vide, hvilken skrifttype på hvilken side det drejer sig om, fortsætter de enumerationsteknikker, der beskrives i analyse af PDF-skrifttypeegenskaber med PDFium i Delphi, præcis hvor valideringsværktøjets boolean slipper
Validering af strømme uden at indlæse et dokument — eller DLL-filen
Byte-niveau-inspektøren er også eksponeret som en selvstændig funktion, ValidatePdfXCompliance(Source: TStream) i FPdfPdfx-enheden, og den er ren Object Pascal uden afhængighed af PDFium DLL. Det gør den anvendelig på steder, hvor en gengivelsesmotor er uønsket: En letvægts-uploadport på en webserver, et CI-job, der kontrollerer genererede grafiske filer, eller en Lazarus-tjeneste på en platform, hvor du foretrækker ikke at levere native binære filer. Fød den med en vilkårlig søgbar strøm (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;
Kompromiset er eksplicit: Den selvstændige sti afvikler markørkontrollerne og alle otte indholdskontroller, men ikke PDFium-laget pr. skrifttype, så dens dom over skrifttyper falder tilbage på den grove heuristik. En fornuftig arkitektur bruger ValidatePdfXCompliance som den billige første port og reserverer den fulde TPdf.ValidatePdfX til filer, der består den
Hvor dette valideringsværktøj slutter, og en fuld preflight begynder
Ærlighed betyder noget i preflight-værktøjer, så her er grænsen. ValidatePdfX verificerer identifikationsmarkører, strukturelle forbud, sidegeometrinøgler, Trapped-erklæringen og skrifttypeindlejring helt ned til individuelle tekstobjekter. Den måler ikke den samlede farvedækning (total ink coverage), validerer ikke, at ethvert farverum er tilladt for den hævdede variant (f.eks. X-1a's regel om kun CMYK), kontrollerer ikke billedopløsning mod rastertæthed (line screen) og evaluerer ikke overprint eller opførsel ved udfladning af gennemsigtighed (transparency flattening) — disse kræver en farvestyret preflight-motor, og enhedens egen dokumentation anbefaler at parre den med en sådan for endelig certificering. Hvad to-lags-kontrollen giver dig, er de 80% af afvisningerne, der er strukturelle og kan registreres tidligt — fanget på millisekunder i din egen Delphi-kode i stedet for i morgen i en e-mail fra trykkeriet
Begge valideringslag, PDF/X-markør-injektions-API'erne til at producere overensstemmende output samt PDF/A-, PDF/UA-, PDF/E- og PDF/VT-valideringsværktøjerne, der deler den samme arkitektur, leveres med PDFium Component til Delphi og C++Builder — én komponent, from gengivelse til prepress-kontrol