Teknisk artikkel

PDF-filstruktur: Hvordan formatet faktisk fungerer

PDF er ikke et dokumentformat på samme måte som Word eller RTF er det. Disse formatene lagrer en sekvens av innhold som en gjengiver tolker i det øyeblikket det vises, så utdataene avhenger av hvilke skrifttyper og hvilken layoutmotor som tilfeldigvis er til stede. PDF lagrer resultatet av den prosessen: presise gjengivelsesinstruksjoner, skrifttypeprogrammer, komprimerte bildestrømmer og en objektgraf som binder dem sammen til en selvstendig beskrivelse av hver side. Filen bærer nok informasjon til å reprodusere hver side identisk på enhver samsvarende gjengiver, noe som er både hoveddesignmålet og kilden til det meste av kompleksiteten du møter når du prøver å generere, tolke eller endre en programmeringsmessig

Objektmodellen

Hver PDF er en samling av nummererte objekter. Et objekt kan være en boolsk verdi, heltall, reelt tall, navn, streng, matrise, ordbok, strøm eller null. Nesten alt interessant er en ordbok, som er et sett med nøkkel-verdi-par der nøklene er navn og verdiene er en hvilken som helst annen objekttype, inkludert referanser til andre objekter etter nummer og generasjonstelling. En strøm er en ordbok etterfulgt av en bytesekvens, vanligvis komprimert

Katalogordboken er roten. Den peker på sidetreet, som organiserer sideordbøkene i en balansert trestruktur i stedet for en flat liste, slik at å navigere til side 5 000 i et 10 000-siders dokument ikke krever traversering av alle foregående sidebeskrivelser. Hver sideordbok refererer til sine innholdsstrømmer (én eller flere sekvenser av sidebeskrivende operatorer), sin ressursordbok (som igjen refererer til skrifttypebeskrivelser, fargerom og bilde-XObjects) og dens medieboks (koordinatrommet siden lever i). Koordinatopprinnelsen er i nedre venstre hjørne, med positiv Y som løper oppover, i enheter på 1/72 tomme

På slutten av filen sitter kryssreferansetabellen, som kartlegger hvert objektnummer til dets byteforskyvning i filen. Dette er det som muliggjør tilfeldig tilgang: et visningsprogram leser kryssreferansetabellen først, og søker deretter direkte til de objektene det trenger. PDF 1.5 introduserte kryssreferansestrømmer, som komprimerer tabellen til et strømobjekt og pakker relaterte objekter inn i objektstrømmer, noe som reduserer filstørrelsen merkbart for dokumenter med mange små objekter

Innholdsstrømmer og grafikkmodellen

Sideoppsettets visuelle innhold lever i én eller flere innholdsstrømmer. Hver strøm er en sekvens av PDF-operatorer ispedd deres operander. Tekstoperatøren BT begynner et tekstobjekt, Tf velger en skrifttype og størrelse fra ressursordboken, Td posisjonerer tekstmarkøren, Tj eller TJ maler en streng, og ET lukker tekstobjektet. Vektorgrafikk følger et lignende mønster: m setter et stistartpunkt, l legger til et linjesegment, c legger til en Bezier-kurve, og f eller S fyller eller stryker stien

Grafikktilstanden styrer alt som skjer mellom operatorer: gjeldende transformasjonsmatrise, linjebredde, fargerom, fyllfarge, strekfarge og klippebanen. Operatorer som q og Q dytter (push) og spretter (pop) grafikktilstanden på en stakk, noe som er hvordan PDF implementerer lokale koordinattransformasjoner og midlertidige tilstandsoverstyringer uten å påvirke konteksten rundt dem. Form XObjects generaliserer dette: en selvstendig innholdsstrøm med sin egen ressursordbok som kan males på en side på vilkårlige posisjoner og skaleringer med en enkelt Do-operator

Innbygging av skrifttyper og utvinning av tekst

PDF kan referere til skrifttyper ved navn og stole på at visningsprogrammet bytter inn noe, men i praksis må ethvert dokument du har tenkt å dele, bygge inn skrifttypedataene. En Type 1 eller TrueType/OpenType-skrifttype innebygd i en PDF bærer en skrifttypebeskrivelsesordbok som peker på en skrifttypefilstrøm. For TrueType-skrifttyper inneholder den strømmen det binære skrifttypeprogrammet; for Type 1 er det PFB-dataene. Å bruke delmengder (subsetting), som er det enhver seriøs PDF-generator gjør, fjerner glyfer som ikke refereres av dokumentet, og holder filstørrelsene håndterbare selv for store Unicode-skrifttyper

Tekstutvinning er der innbygging av skrifttyper biter tilbake. Den visuelle representasjonen av et tegn bestemmes av en glyf i det innebygde skrifttypeprogrammet. Unicode-verdien til det tegnet bestemmes av en ToUnicode CMap-strøm knyttet til skrifttypeordboken. Når ToUnicode CMap mangler eller er feil, kan et PDF-visningsprogram gjengi tekst leselig, men kan ikke trekke den ut som meningsfull Unicode, noe som er grunnen til at kopier-og-lim-inn fra noen PDF-er produserer søppel. Merket PDF (Tagged PDF, ISO 32000 §14.8) legger til et andre lag: et logisk strukturtre som kartlegger sideinnhold til dokument-semantiske roller som avsnitt, overskrifter og tabellceller. Skjermlesere og omløpsmotorer bruker strukturtreet i stedet for den rå innholdsstrømsrekkefølgen, noe som forklarer hvorfor en visuelt godt lagt opp PDF fortsatt kan være utilgjengelig hvis merkingen mangler eller er feil

Inkrementelle oppdateringer og digitale signaturer

Når du lagrer endringer i en eksisterende PDF uten å skrive den om fra bunnen av, legges de nye objektene til etter den opprinnelige filkroppen sammen med en ny kryssreferanseseksjon og en ny trailerordbok. Den oppdaterte traileren peker på de nye kryssreferansedataene, og erstattede objekter forblir i filen, men blir rett og slett ikke referert til av den nye kryssreferansekjeden. Dette er inkrementell oppdatering, og den har to vesentlige konsekvenser

For det første vokser filen med hver lagringssyklus. Et dokument som redigeres og lagres gjentatte ganger, samler lag av foreldede objekter. Verktøy som QPDF kan linearisere eller komprimere-og-skrive-om en fil for å gjenvinne det rommet, men standarden er akkumulering. For det andre avhenger digitale signaturer av inkrementelle oppdateringer for sin integritetsmodell. En ISO 32000-signatur dekker et byteområde av filen, typisk alt unntatt plassholderen for selve signaturverdien. Eventuelle endringer etter signering som fremstår som ytterligere inkrementelle oppdateringer, er synlige for en validerende leser som endringer gjort etter signering, noe som er akkurat det revisjonssporet du ønsker. Imidlertid betyr dette også at visse modifikasjoner, som å legge til en godkjenningssignatur eller fylle ut skjemafelt, er eksplisitt tillatt av standarden uten å ugyldiggjøre den opprinnelige signaturen, forutsatt at endringene er i samsvar med dokumentets tillatelsesinnstillinger (ISO 32000-2 §12.7.6). En endring som faller utenfor disse tillatelsene, blir flagget som uautorisert. Å få dette skillet riktig er viktig når du genererer dokumenter som vil bli medsignert nedstrøms

Samsvarsnivåer og ISO 32000-slekten

PDF startet som et proprietært Adobe-format i 1993, absorberte PostScripts bildemodell, og samlet funksjoner over femten versjoner: kryptering i 1.1, interaktive skjemaer i 1.2, digitale signaturer og logisk struktur i 1.3, åpenhet (transparency) i 1.4, objektstrømmer i 1.5, AES-kryptering i 1.6. Adobe sendte PDF 1.7 til ISO i 2007, og ISO 32000-1:2008 ble resultatet. ISO 32000-2:2020 dekker PDF 2.0, som strammet inn flere underspesifiserte områder, reviderte AES-256 nøkkelavledningen (revisjon 6 erstatter revisjon 5), og la til eksplisitt støtte for tilknyttede filer og rik media

Understandardene stammer fra samme base. PDF/A (ISO 19005) bytter funksjoner for arkivstabilitet: ingen kryptering, ingen eksterne innholdsavhengigheter, alle skrifttyper innebygd, fargerom uavhengig av enhet, XMP-metadata kreves. PDF/A-1 er basert på PDF 1.4, PDF/A-2 på PDF 1.7, PDF/A-3 tillater innebygde filer av ethvert format. PDF/X (ISO 15930) er undergruppen for utskriftsproduksjon: utskriftshensikter (output intents), blødnings- og beskjæringsbokser (bleed and trim boxes), ingen åpenhet i eldre samsvarsnivåer. PDF/UA (ISO 14289) krever merket struktur, Unicode-tilordninger og språkmetadata for tilgjengelighet. Dette er ikke konkurrerende formater; de er sett med tilleggsbegrensninger på toppen av kjerne-PDF, og en enkelt fil kan være i samsvar med mer enn én samtidig, forutsatt at begrensningene ikke er i konflikt

For alle som skriver kode som genererer eller behandler PDF, er den praktiske grunnlinjen ISO 32000-2 med nøye oppmerksomhet til seksjonene som dekker kryssreferansemodellen (§7.5), grafikktilstanden (§8.4), teksttilstandsoperatorer (§9.3), skrifttypebeskrivelser og ToUnicode (§9.6 og §9.10), interaktive skjemaer (§12.7) og digitale signaturer (§12.8). Standarden er lang, men det meste av programmatisk PDF-arbeid berører et smalt stykke av den gjentatte ganger. Å forstå objektmodellen og kryssreferansemekanismen er inngangspunktet; alt annet er spesialisering derfra