Stranica 1 u PDF-u nije objekt 1. Ta je razlika najčešći izvor pogrešaka pri izdvajanju stranica, a rješenje je čitati specifikaciju umjesto sirovih bajtova datoteke
Razgranavanje je odluka o performansama
PDF datoteka zbirka je numeriranih objekata. Svaki ima broj objekta i broj generacije, zapisan kao N G obj, dok reference među objektima koriste oblik N G R. Trailer pokazuje na korijenski katalog, a njegov unos /Pages vodi do stabla stranica. Tablica unakrsnih referenci ili tok unakrsnih referenci u PDF-u 1.5 i novijem mapira brojeve objekata na pomake u datoteci. Ta mapa služi nasumičnom pristupu, a ne određivanju redoslijeda stranica
Stablo stranica može imati mnogo djece po čvoru ili samo nekoliko. Taj fan-out je odluka o performansama jer veći čvorovi smanjuju dubinu obilaska, ali povećavaju količinu podataka koju čitač mora obraditi odjednom. Inkrementalno ažurirana datoteka može dodati nove objekte na kraj s većim brojevima, dok njihov logički položaj i dalje određuje niz /Kids. Zato redoslijed brojeva objekata nije redoslijed stranica
Unutarnji čvorovi nose naslijeđene atribute
Korijenski katalog sadrži referencu /Pages na čvor tipa /Pages. Njegov niz /Kids navodi djecu redoslijedom čitanja, a svako dijete može biti list tipa /Page ili drugi međučvor /Pages. Prva stranica je prvi list do kojeg se dolazi obilaskom nizova /Kids dubinom, slijeva nadesno
Najčešće naslijeđene stavke su /MediaBox, /CropBox, /Resources i /Rotate. List koji izostavi /MediaBox nije neispravan; preuzima vrijednost od najbližeg pretka koji je definira. Ako je definira sam list, njegova vrijednost nadjačava roditeljsku samo za tu stranicu. Ispravan čitač prolazi lanac /Parent, prikuplja još neviđene atribute i zaustavlja se u korijenu
Unos /Count u međučvoru predmemorira ukupan broj podređenih listova, pa preglednik može preskočiti cijelo podstablo pri skoku na udaljenu stranicu. Defenzivni parser ipak provjerava /Count prema stvarnom broju listova jer ga stari uređivači nakon izmjena na mjestu nisu uvijek ponovno izračunali
Legalno, uobičajeno, povremeno skupo izravnavanje
Specifikacija ne ograničava stablo na jednu razinu. Velik dokument može grupirati stranice pod međučvorovima koji približno odgovaraju poglavljima, a algoritam obilaska ostaje isti: posjeti djecu redom, rekurzivno uđi u svaki čvor /Pages i prikupi listove /Page
5 0 obj % document root
<< /Type /Pages /Count 6 /Kids [6 0 R 7 0 R] >>
endobj
6 0 obj % report body: portrait A4, body font
<< /Type /Pages /Parent 5 0 R /Count 3
/Kids [30 0 R 31 0 R 32 0 R]
/MediaBox [0 0 595 842]
/Resources << /Font << /F1 8 0 R >> >> >>
endobj
7 0 obj % appendix: landscape A4, rotated, its own font
<< /Type /Pages /Parent 5 0 R /Count 3
/Kids [40 0 R 41 0 R 42 0 R]
/MediaBox [0 0 842 595] /Rotate 90
/Resources << /Font << /F2 9 0 R >> >> >>
endobj
40 0 obj % appendix page: inherits size, rotation, fonts
<< /Type /Page /Parent 7 0 R /Contents 43 0 R >>
endobj
Ovaj raspored pokazuje zašto su objektni brojevi loš izvor redoslijeda. Niz /Kids određuje da je objekt 20 prva logička stranica, objekt 1 druga, a objekt 4 treća, iako bi obilazak brojeva od 1 naviše proizveo 1, 4, 20. Rezultat bi imao stranice u pogrešnom redoslijedu iako se svaka pojedinačna stranica može normalno prikazati
% Original revision
12 0 obj
<< /Type /Pages /Count 9 /Kids [13 0 R 14 0 R 15 0 R] >>
endobj
14 0 obj
<< /Type /Pages /Parent 12 0 R /Count 3
/Kids [50 0 R 51 0 R 52 0 R] >>
endobj
% Appended revision: one page inserted into the middle branch.
% Object 14 is superseded; object 12 is never rewritten
14 0 obj
<< /Type /Pages /Parent 12 0 R /Count 4
/Kids [50 0 R 51 0 R 90 0 R 52 0 R] >>
endobj
Izravnavanje stabla može pojednostaviti čitanje, ali nije uvijek besplatno. Čvorovi s mnogo djece mogu smanjiti dubinu, dok očuvanje prirodnih grupa može pomoći alatima koji rade po poglavljima. Pravilo je zadržati strukturu koja odgovara dokumentu i potvrditi stvarni broj listova umjesto slijepog povjerenja u predmemorirane brojače
Kad je broj stranice pogrešan
Pogreške redoslijeda najčešće se pojavljuju u dva scenarija. Prvi je prilagođeni parser koji skenira objekte tipa /Page umjesto da prati stablo. On pronađe sve stranice, ali po broju objekta, a ne po redoslijedu čitanja. Ispravan postupak uvijek počinje trailerom, razrješava korijenski katalog, prati /Pages i obilazi nizove /Kids
Drugi je inkrementalno ažurirana datoteka. Urednik može zamijeniti stranicu 5 novim objektom 143, dok niz /Kids sada pokazuje na 143 na istom logičkom mjestu. Hodanje po brojevima objekata tada bi zamjensku stranicu stavilo na pogrešan položaj
Linearizirani PDF-ovi dodaju još jednu zamku: sadržaj prve stranice fizički je blizu početka radi brzog prikaza preko spore veze, ali stablo stranica i dalje određuje redoslijed, dok xref preslikava nove fizičke pomake. Parser koji se oslanja na položaj u datoteci umjesto na xref može pogrešno pročitati i prvu stranicu
HotPDF Component interno obrađuje obilazak stabla stranica, razrješavanje nasljeđivanja i spajanje xref podataka iz inkrementalnih ažuriranja. Kada radite s njegovim objektima stranica, redoslijed niza /Kids već je primijenjen, pa indeksi stranica označavaju logičke stranice, a ne brojeve objekata