PDF-tiedosto on sisimmältään joukko objekteja, jotka osoittavat toisiinsa. Jos poistat pakkauksen, ristiviittausten kirjanpidon ja tavusiirtymät, jäljelle jää kaavio: pieni joukko tyypitettyjä arvoja, jotka on kytketty yhteen viittauksilla ja jotka juurtuvat yhteen objektiin, jonka lukija osaa löytää. Kaikki, mitä PDF voi ilmaista, tekstikappaleesta upotettuun fonttiin ja digitaaliseen allekirjoitukseen, rakentuu kahdeksasta primitiivisestä objektityypistä ja säännöstä, joka antaa yhden objektin viitata toiseen. Opi nämä, ja loppuformaatti on luettavissa ennemmin sommitteluna kuin mysteerinä
Tämä on PDF:n looginen kerros, joka on määritelty standardin ISO 32000-1 kohdassa 7.3, ja se sijaitsee yhden tason fyysisen tiedostoasettelun yläpuolella (otsikko, runko, ristiviittaustaulukko ja traileri, joka on oma aiheensa artikkelissa PDF-tiedoston rakenteen tekninen yleiskatsaus). Looginen malli on sitä, mitä nuo tavut tarkoittavat, kun ne on jäsennetty. Katseluohjelma lukee tiedostoa taaksepäin löytääkseen trailerin, seuraa sitä juureen, ja sieltä alkaen asiakirja avautuu objekteina, jotka viittaavat objekteihin. Tätä osaa mietit, kun selvität virheellistä sivua, kirjoitat jäsennintä tai luotat kirjaston kokoavan asiakirjan
Kahdeksan objektityyppiä, eikä mitään muuta
PDF määrittelee täsmälleen kahdeksan perusobjektityyppiä. Jokainen asiakirjan arvo on yksi niistä, mikä pitää muodon käsiteltävänä sen laajuudesta huolimatta
Totuusarvot ovat avainsanat true ja false. Ne kytkevät lippuja päälle ja pois, kuten esimerkiksi sen, tulostetaanko huomautus
Numeroita on kahta laatua, joita määritys käsittelee yhtenä tyyppinä: kokonaislukuja, kuten 42, ja reaalilukuja, kuten 3.14 tai -0.002. PDF:ssä ei ole eksponenttimerkintää, joten et koskaan näe arvoa 1e6 määritysten mukaisessa tiedostossa. Koordinaatit, fonttikoot ja kiertokulmat ovat kaikki numeroita
Merkkijonot sisältävät tavusekvenssejä, jotka on kirjoitettu joko sulkeisiin, (Hello), tai kulmasulkeisiin heksadesimaaleina, <48656C6C6F>. Molemmat merkintätavat koodaavat saman sisällön; heksadesimaali on pakotie tavuille, jotka ovat hankalia sulkeiden sisällä. Merkkijonot kuljettavat tekstiä, mutta ne ovat ensisijaisesti tavuja, millä on merkitystä sillä hetkellä, kun käsittelet mitään ASCII:n ulkopuolella
Nimet ovat jakamattomia merkkejä, jotka esitellään kauttaviivalla: /Type, /Pages, /MediaBox. Nimi ei ole merkkijono; se on tunniste, jota käytetään sanakirjan avaimena tai lueteltuna arvona, ja kaksi nimeä ovat yhtä suuret vain, jos ne vastaavat toisiaan tavu tavulta. Kauttaviiva on syntaksia, ei osa nimeä. Tämä kompastuttaa tulokkaita, jotka käsittelevät arvoja /Times-Roman ja merkkijonoa (Times-Roman) keskenään vaihdettavina; muoto ei niin tee
Taulukot ovat järjestettyjä, heterogeenisia luetteloita hakasulkeissa: [0 0 612 792] on sivun suorakulmio, ja taulukko voi sekoittaa tyyppejä vapaasti, mukaan lukien viittaukset muihin objekteihin. Sanakirjat ovat työjuhtia. Sanakirja, joka on kirjoitettu merkkien << ja >> väliin, yhdistää nimiavaimet minkä tahansa tyyppisiin arvoihin, ja lähes jokainen mielekäs rakenne PDF:ssä, sivu, hakemisto, fontti, huomautus, on sanakirja, jossa /Type-avain kertoo, mikä se on
Virrat ovat sanakirjoja, joiden perässä on raakatavuja avainsanojen stream ja endstream välissä. Sanakirja kuvailee tavuja (niiden pituuden ja mahdolliset suodattimet, kuten FlateDecode, jotka pakkaavat ne), ja tavut kuljettavat tilaa vievää hyötykuormaa: sivun sisällön ohjeita, upotettuja fonttiohjelmia, kuvia. Virta on paikka, johon PDF laittaa kaiken, mikä on liian suurta tai liian binääristä ollakseen linjassa
Kahdeksas tyyppi on null-objekti, avainsana null. Se on todellinen arvo, joka eroaa avaimen puuttumisesta. Sanakirjan merkintää, joka on asetettu null-tilaan, käsitellään ikään kuin sitä ei olisi olemassa, ja viittaus, joka ratkeaa olemattomaan objektiin, tuottaa myös arvon null virheen sijaan. Tämä anteeksiantava käyttäytyminen on tarkoituksellista: se antaa vaurioituneen tiedoston heikentyä sen sijaan, että se kieltäytyisi avautumasta. Yhdeksättä tyyppiä ei ole; kaikki, mitä PDF ilmaisee, syntyy näiden kahdeksan yhdistelmästä
Suorat arvot, epäsuorat objektit ja viittaukset
Mikä tahansa noista kahdeksasta tyypistä voi esiintyä kahdella tavalla. Suora objekti on kirjoitettu paikoilleen, kuten 612 MediaBox-taulukon sisällä. Epäsuoralle objektille annetaan identiteetti, jotta muut objektit voivat osoittaa siihen: kaksi kokonaislukua, objektinumero ja generaationumero, käärien määritelmän tunnisteiden obj ja endobj sisään:
12 0 obj
<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>
endobj
Tämä on objekti 12, generaatio 0, fonttisanakirja. Missä tahansa muualla tiedostossa toinen objekti viittaa siihen epäsuoralla viittauksella: samat kaksi numeroa, joita seuraa avainsana R, 12 0 R. Viittaus on osoitin. Kun sivun resurssisanakirja sanoo /Font << /F1 12 0 R >>, se nimeää objektin 12 fontiksi resurssinimen /F1 takana, kopioimatta fontin määritelmää sivulle
Generaationumero on olemassa poistoja ja uudelleenkäyttöä varten. Kun objekti vapautetaan ja sen paikka käytetään uudelleen, generaatio kasvaa, jotta vanhentunut 12 0 R ei voi viitata paikan 12 uuteen vuokralaiseen. Vasta kirjoitetut tiedostot ovat lähes kaikki generaatiota 0, mutta voimakkaasti muokattu tiedosto voi sisältää suurempia numeroita, ja jäsennin, joka jättää generaation huomiotta, lukee lopulta väärän objektin
Epäsuoruus tekee PDF:stä tehokkaan ja muokattavan. Yksi fontti, kuva tai väriavaruus voidaan määritellä kerran ja siihen voidaan viitata sadalta sivulta. Pieni muutos voidaan liittää uutena versiona, joka korvaa yksittäisen objektin koko tiedoston uudelleenkirjoittamisen sijaan. Ristiviittaustaulukko on hakemisto, joka muuttaa objektinumeron tavusiirtymäksi, joten lukija hyppää suoraan objektiin 12 0 obj ilman skannausta, mutta se on fyysinen optimointi. Loogisesti ainoa asia, joka sinun tarvitsee tietää, on se, että 12 0 R tarkoittaa "objektia, jonka tunniste on 12 0"
Hakemisto: mistä jokainen asiakirja alkaa
Viittausten ratkaisemisen on alettava jostain, ja tuo jokin paikka on trailerin /Root-merkintä, joka osoittaa asiakirjahakemistoon: objektikaavion juureen, sanakirjaan, jossa on /Type /Catalog. Lukija saavuttaa sen ensimmäisenä, koska traileri löytyy ensimmäisenä, ja sieltä käsin kaikki asiakirjan muut osat ovat saavutettavissa seuraamalla viittauksia
Hakemisto sisältää vain kaksi ehdottomasti vaadittua merkintää: sen /Type-arvon ja /Pages-arvon, joka on epäsuora viittaus sivupuun juureen. Loput ovat valinnaisia ja kuvaavat asiakirjan laajuista käyttäytymistä sisällön sijaan: /Outlines osoittaa kirjanmerkkipuuhun, /Names sisältää merkkijonolla avainnettuja nimipuita, /Metadata viittaa XMP-metadatavirtaan, ja /PageMode sekä /PageLayout ehdottavat, kuinka katseluohjelman tulisi avata asiakirja. Mitään niistä ei tarvita sivun renderöintiin; ne konfiguroivat sivujen ympärillä olevaa kokemusta. Hakemistosta roikkuvat kirjanmerkki-, metadata- ja huomautusrakenteet on käsitelty artikkelissa PDF:n metadata, kirjanmerkit ja huomautukset
Alla oleva kaavio näyttää, missä objektin runko sijaitsee ympäröivässä tiedostossa. Hakemisto ja sivupuu elävät tuon rungon sisällä tavallisina epäsuorina objekteina; otsikko, ristiviittaustaulukko ja traileri niiden ympärillä ovat fyysinen tukirakenne, jonka avulla lukija voi paikantaa ne

Sivupuu: sivujen tasapainoinen hierarkia
/Pages-kohdasta asiakirja haarautuu sivupuuhun, missä PDF:n valinta käyttää kaaviota litteän luettelon sijaan palkitsee. Sivuja ei tallenneta yksinkertaisena sarjana; ne roikkuvat puussa, jonka sisäiset solmut ovat sivupuusolmuja (/Type /Pages) ja jonka lehdet ovat sivuobjekteja (/Type /Page). Sisäinen solmu luettelee lapsensa /Kids-taulukossa ja tallentaa /Count-avainta käyttäen tiedon siitä, kuinka monta lehtisivua sen alapuolella on. Jokaiseen solmuun juurta lukuun ottamatta sisältyy /Parent-viittaus ylöspäin, joten puuta voi käydä läpi kumpaan tahansa suuntaan
2 0 obj % sivupuun juuri
<< /Type /Pages /Kids [3 0 R 4 0 R] /Count 3 >>
endobj
3 0 obj % lehtisivu
<< /Type /Page /Parent 2 0 R
/MediaBox [0 0 612 792]
/Resources << /Font << /F1 12 0 R >> >>
/Contents 5 0 R >>
endobj
4 0 obj % sisäinen solmu, joka ryhmittelee kaksi muuta sivua
<< /Type /Pages /Parent 2 0 R /Kids [6 0 R 7 0 R] /Count 2 >>
endobj
Tässä objekti 2 on juuri, ja sen alla on kolme sivua: lehtisivu 3 sekä kaksi muuta, jotka ovat saavutettavissa sisäisen solmun 4 kautta. Juuren /Count-arvon 3 on oltava yhtä suuri kuin sen alla olevien lehtien kokonaismäärä, ja määrä, joka on ristiriidassa todellisen rakenteen kanssa, on yleinen syy siihen, että käsin muokattu tiedosto menee pieleen. Puun tarkoitus on pääsyn paikallisuus. Lukija avatessaan tuhatsivuisen asiakirjan sivun 900 ei käy läpi 900 objektia; se laskeutuu kourallisen solmuja, koska oikein muotoiltu puu pysyy matalana ja tasapainoisena. Tällaisen puun rakentaminen käsin on tarpeeksi pikkutarkkaa, jotta sen näkeminen alusta loppuun on vaivan arvoista, minkä vuoksi läpikäynti artikkelissa PDF-asiakirjan rakentaminen alusta pitäen tekeekin juuri niin
Puu ansaitsee paikkansa myös perinnän ansiosta. Kourallinen sivuattribuutteja, /Resources, /MediaBox, /CropBox ja /Rotate, voidaan asettaa sisäiseen solmuun ja jättää pois yksittäisiltä sivuilta, jotka sitten perivät lähimmän esi-isän arvon. Aseta /MediaBox kerran juureen, ja jokainen lehti saa saman sivukoon ilman toistoa; sivu, jonka täytyy erota, ilmoittaa oman kokonsa. Tämä on se yksi paikka objektimallissa, jossa arvon merkitys riippuu objektin sijainnista puussa, ei pelkästään sen omasta sisällöstä
Mitä lehtisivu todella sisältää
Sivuobjekti on liitoskohta rakennemallin ja näkyvän sisällön välillä. Sen /Contents-merkintä viittaa yhteen tai useampaan sisältövirtaan, eli piirto-operaattoreihin, jotka maalaavat tekstiä ja grafiikkaa sivulle. Sen /Resources-sanakirja nimeää fontit, kuvat ja väriavaruudet, joihin nuo operaattorit tukeutuvat, jokaisen merkinnän ollessa epäsuora viittaus sivujen kesken jaettuun objektiin. /MediaBox antaa sivun suorakulmion pisteinä (1/72 tuumaa), ja merkinnät kuten /Rotate ja /CropBox säätävät sitä, kuinka se esitetään
Työnjako on koko malli pienoiskoossa. Sivusanakirja on rakenne: tyypitettyjä merkintöjä ja viittauksia, jotka kertovat, mikä sivu on ja millä se piirtää. Sisältövirta on ohjeita: erillinen, pakattava möykky, joka kertoo, kuinka piirtää. Fontti /F1:n takana on jaettu resurssi, joka on määritelty kerran ja johon osoitetaan kaikkialta, missä sitä käytetään. Sanakirja, virta ja viittaus tekevät yhteistyötä renderöidäkseen yhden sivun, ja samat kuviot skaalautuvat koko asiakirjaan. Tämän möykyn sisällä olevat sisältövirtakomento-operaattorit on käsitelty erikseen artikkeleissa tekstistä ja fonteista sekä grafiikasta ja visuaalisista elementeistä
/Count-kentässä ja voi periyttää attribuutteja, kuten /MediaBox, jokaiselle jälkeläiselleMiksi tämä malli on tuntemisen arvoinen
Useimmat kehittäjät kohtaavat objektimallin vasta, kun jokin menee rikki: sivu renderöityy tyhjänä, koska sen /Contents-viittaus roikkuu irrallaan, teksti näkyy laatikkoina, koska fonttiresurssia ei koskaan upotettu, työkalu ilmoittaa /Count-arvoksi sellaisen, joka ei vastaa sen löytämiä sivuja. Jokainen näistä on väittämä kaaviosta, ja kaavion lukeminen suoraan voittaa arvaamisen. Kahdeksan tyyppiä ja viittaussääntö muodostavat riittävän pienen sanaston, jotta sen voi pitää päässään, ja kun kerran näet PDF:n objekteina, jotka osoittavat objekteihin, vialliset tiedostot lakkaavat olemasta läpinäkymättömiä
Tästä huolimatta mallin kirjoittaminen käsin on harvoin oikea valinta oppimisen ulkopuolella. Ristiviittausten siirtymien, generaationumeroiden, sivupuun laskurien ja virran pituuksien pitäminen johdonmukaisina muokkauksien yli on juuri sellaista kirjanpitoa, jota kirjasto on olemassa hoitaakseen. Tuotannossa kypsä PDF-kehityskirjasto hallitsee objektikaaviota ja antaa sinun ajatella sivuina ja sisältönä. Mallin tunteminen palkitsee silti: ymmärrät, mitä kirjasto rakentaa konepellin alla, ja miksi