Odmyslíte-li si popisy stránek, zůstane vám tenká vrstva struktury, kterou nikdo netiskne, ale na níž závisí každá čtečka, indexátor i archivační systém. Samotný objekt stránky neví nic o tom, do jaké kapitoly patří, o autorovi, který jej napsal, ani o poznámce pod čarou odkazující jinam. Tyto znalosti žijí o úroveň výš, ve třech strukturách připojených ke katalogu dokumentu: v tocích metadat (metadata streams), ve stromu osnovy (outline tree) a v polích anotací příslušících jednotlivým stránkám. Sdílejí vlastnost, kvůli níž se v nich snadno chybuje: žádná z nich nenese viditelné stopy na stránce. Soubor se tak může vykreslit naprosto bezchybně, a přesto může postrádat záložky, odporovat si ve vlastním poli autora nebo odkazovat na objekt stránky, který už dávno neexistuje
Toto je vrstva, kterou PDF knihovna odkrývá jako vlastnosti dokumentu, rozhraní API pro záložky a volání odkazů či anotací. Je to také vrstva, kterou prohledávače čtou, aby zjistily, o čem váš dokument pojednává. Objektový model, jenž se pod ní skrývá, je podrobně popsán v průvodci strukturou dokumentu PDF. Zde se zaměříme výhradně na to, co „visí“ na katalogu
Všechny tři struktury se připojují ke katalogu. Kompletní katalog, který je propojuje, vypadá takto:
1 0 obj
<< /Type /Catalog
/Pages 2 0 R
/Outlines 3 0 R
/Names << /EmbeddedFiles 4 0 R >>
/Metadata 5 0 R
>>
endobj
Čtyři položky představují čtyři nezávislé subsystémy. /Pages je viditelný dokument; /Outlines tvoří strom záložek; /Metadata ukazuje na tok (stream) XMP metadat; pomocí /Names se přistupuje k celodokumentovému slovníku jmen (name dictionary), který mimo jiné obsahuje vložené souborové přílohy. Každá položka je volitelná a prohlížeč, jenž nenalezne ani jednu z nich, stránky přesto zobrazí. Právě tato volitelnost je důvodem, proč navigační vrstva „zahnívá“ jako první, když je soubor upravován nástroji, které rozumějí pouze samotným stránkám
Dvě úložiště metadat, která se rozcházejí
PDF nese metadata dokumentu na dvou místech současně, a jakmile tato dvě místa tvrdí odlišné věci, nastávají potíže. Původním mechanismem je slovník informací o dokumentu, na nějž odkazuje /Info v traileru: plochá sada dvojic klíč-hodnota pro /Title, /Author, /Subject, /Keywords, /Creator, /Producer a dvě data. Je to prosté a načte to každý prohlížeč. PDF 2.0 většinu z toho odsuzuje k zániku (deprecates) ve prospěch druhého mechanismu: streamu XMP metadat
XMP je soběstačný dokument XML, psaný ve formátu RDF a uložený jako tok, k němuž katalog přistupuje prostřednictvím /Metadata a který je označen /Type /Metadata /Subtype /XML. Na rozdíl od slovníku Info, který je pohřben hluboko ve struktuře PDF objektů, je XMP paket navržen k samostatné extrakci a k parsování nástroji nevídanými s formátem PDF. Zde je reprezentativní balíček:
5 0 obj
<< /Type /Metadata /Subtype /XML /Length 1235 >>
stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about=""
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:xmp="http://ns.adobe.com/xap/1.0/"
xmlns:pdf="http://ns.adobe.com/pdf/1.3/">
<dc:title><rdf:Alt><rdf:li xml:lang="x-default">Quarterly Report</rdf:li></rdf:Alt></dc:title>
<dc:creator><rdf:Seq><rdf:li>A. Author</rdf:li></rdf:Seq></dc:creator>
<xmp:CreateDate>2026-06-16T10:46:27+08:00</xmp:CreateDate>
<xmp:CreatorTool>Reporting Service 4.2</xmp:CreatorTool>
<pdf:Producer>losLab PDF Library</pdf:Producer>
</rdf:Description>
</rdf:RDF>
</x:xmpmeta>
<?xpacket end="w"?>
endstream
endobj
Zda metadata přežijí kontakt s reálnými nástroji, určují v daném bloku tři detaily. Instrukce pro zpracování xpacket nejsou pouhou dekorací: rámují balíček tak, aby jej extraktor mohl nalézt uvnitř rozsáhlejšího bytestreamu. Nástroj, jenž při zápisu vynechá závěrečné <?xpacket end="w"?>, tak sice vygeneruje soubor, který se sice bez problému otevře, narazí však u striktních validátorů. Datové typy vlastností mají také svůj význam. dc:title je jazyková alternativa zabalená do rdf:Alt, naproti tomu dc:creator je uspořádaný seznam a přijímá rdf:Seq; zapsání kteréhokoliv z nich coby obyčejného textového uzlu je tou vůbec nejčastější chybou v XMP. Ta je navíc většinou prohlížečů tolerována až do doby, než narazíte na ten jeden prohlížeč, který ji neodpustí. Předpony jmenných prostorů (namespace prefixes) podléhají běžným konvencím, ale odpovídající URI představují ustálenou normu: parser se orientuje podle URI a nikoli podle prefixu
Tvrdé pravidlo práce se dvěma úložišti zní: musí se vzájemně shodovat. Pokud /Info říká, že autorem je určitá osoba, a dc:creator uvádí odlišné jméno, pak jste dodali dokument poskytující na tutéž otázku hned dvě odpovědi. O tom, která ze dvou odpovědí vyhraje, rozhodne pole, ze kterého čerpá nástroj, jenž dokument aktuálně zpracovává. Knihovny pro vás obvykle zapisují obě hodnoty současně, ovšem v momentě, kdy provedete úpravu jedné z nich ručně, případně jakmile začnete spojovat soubory z odlišných generátorů, začnou se tyto hodnoty odlišovat (rozejdou se). Přistupujte k slovníku Info jakožto k prvku zpětné kompatibility a k XMP jakožto ke zdroji pravdy. Obě z nich znovu generujte z jediné ucelené sady hodnot (source of truth), místo toho, abyste je nezávisle "záplatovali". U formátu PDF/A se takový postup stává dokonce požadavkem na shodu: ISO 19005 nařizuje XMP a přísně zakazuje výskyt jakékoliv vlastnosti Info, jež by byla v rozporu se svým odpovídajícím XMP protějškem
Strom osnovy na pozadí panelu záložek
To, co prohlížeč ukazuje coby panel záložek (bookmarks panel), je uvnitř souboru dvojitě zřetězený strom slovníků nazývaný osnova dokumentu (document outline). Katalog ukazuje na kořenový slovník osnovy prostřednictvím /Outlines; kořen ukazuje na první a poslední prvek nejvyšší úrovně a každý prvek se napojuje (je zřetězen) se svými sousedy i rodičem. Kdekoliv v souboru neexistuje žádné "pole záložek". Celá stavba se rekonstruuje sledováním odkazů, a to je přesně ten důvod, proč pouhý jeden chybný (zlomený) odkaz dokáže bez hlášení jakékoliv chyby zcela vymazat celou větev obsahu z panelu záložek
8 0 obj % the outline root
<< /Type /Outlines /Count 4 /First 9 0 R /Last 9 0 R >>
endobj
9 0 obj % top-level: a chapter
<< /Title (Chapter 1: Results)
/Parent 8 0 R /Count 2
/First 12 0 R /Last 15 0 R >>
endobj
12 0 obj % first child
<< /Title (Introduction)
/Parent 9 0 R /Next 15 0 R
/Dest [3 0 R /XYZ 72 720 0] >>
endobj
15 0 obj % second child, last sibling
<< /Title (Methodology)
/Parent 9 0 R /Prev 12 0 R
/Dest [3 0 R /Fit] >>
endobj
Prostudujte si odkazy a základní neměnné vlastnosti se stanou zjevnými. Každá položka směřuje zpět ke svému rodiči /Parent. Sourozenci skládají řetězec pomocí atributů /Prev a /Next, u první položky /Prev schází a naopak poslední postrádá /Next. Rodič pak vyjmenovává své první a poslední děti (potomky) skrze vlastnosti /First a /Last, takže děti nacházející se uprostřed lze dohledat jedině průchodem řetězcem příbuzných (sourozenců). Pokud uděláte v některém prvku chybu, selhání bude potichu: překonaný a neplatný zápis u /Next prostě zkrátí dotyčnou kapitolu a rodič s /Last neodpovídajícím faktuálně poslednímu článku řetězce zanechá tyto zbývající prvky osiřelé (orphaned), s tím, že onen prohlížeč (viewer) prostě vykreslí jen to podstatné, čeho se aktuálně reálně dosáhne (co nalezne)
Pole /Count nese stavovou informaci, která lidi často překvapuje. Na kořenovém uzlu a na jakékoli rozbalené položce obsahuje počet aktuálně viditelných potomků; u sbalené položky se jedná o záporné číslo, jehož absolutní hodnota udává, kolik potomků by se objevilo při rozbalení. Klíč /Count tedy není neměnným strukturálním faktem o stromu, představuje spíše uložený stav (otevřeno/zavřeno) panelu. Generátor, který by tuto hodnotu natvrdo zapsal jako kladný celkový součet, by tím znovu otevřel všechny větve, jež měl autor v úmyslu ponechat sbalené
Každá položka si své místo musí zasloužit tím, že někam odkazuje. Položka /Title udává, co se v panelu zobrazí; /Dest určuje, kam uživatel po kliknutí „dopadne“. Cíl (destinace) může být definován přímo uvnitř dané položky (viz výše), nebo může jít o jméno, které se vyhodnotí přes jmenný slovník dokumentu. Druhá možnost je mnohem lepší ve chvíli, kdy vícero záložek a odkazů směřuje na to samé místo, protože přesunutý cíl stačí upravit pouze na jednom místě. Knihovna obvykle skrývá tento strom za nějaký identifikátor kořene (outline-root) a metody pro přidávání podřízených položek (children). Dokument v knihovně HotPDF k těmto účelům odkrývá například prvek OutlineRoot typu THPDFDocOutlineObject a odkazy /Prev, /Next, /Parent či /Count propojuje automaticky ve chvíli, kdy připojujete jednotlivé položky. Tuto funkčnost se vyplatí naplno využít, protože ruční udržování těchto neměnných závislostí napříč úpravami je přesně tím místem, kde se osnovy (outlines) rozbíjejí
Cíle (Destinations): gramatika dopadu kliknutí
Jak záložky, tak anotace odkazů (link annotations) ukazují na cíle, a cíl znamená víc než jen pouhé číslo stránky. Jedná se o pole, které jmenuje objekt stránky a následně specifikuje prostřednictvím slovesa (akce) na druhé pozici, jak by jej měl prohlížeč ohraničit a zobrazit. Nejobvyklejším a také nejčastěji zneužívaným povelem je /XYZ, používaný ve formátu [stránka /XYZ doleva nahoru zoom]. Jeho tři operandy jsou na sobě nezávislé a každý z nich může mít hodnotu null ve smyslu „ponechte toto nastavení tak, jak ho měl uživatel“. Odpovídající příkaz [stránka /XYZ null null null] tak přeskočí na stránku, aniž by se dotkl pozice rolování nebo zvětšení, což je obvykle to chování, které od odkazu s instrukcí „jdi na stranu“ očekáváte. Zadávaná čísla vycházejí z výchozího uživatelského prostoru; začínají v levém dolním rohu, přičemž hodnoty osy y rostou směrem vzhůru. Stejný souřadnicový systém se využívá pro obsah stránky. Autoři uvyklí na formátování na obrazovce ovšem reflexivně odměřují z horního okraje, a pošlou tak čtenáře rovnou na opačný konec stránky
Skupina příkazů kolem /Fit mění naprosto přesné pozicování za houževnatost a odolnost (resilience). Příkaz [stránka /Fit] přizpůsobí rozměry celé stránky zobrazenému oknu, povel [stránka /FitH horní_okraj] uzpůsobí šířku stránky vůči zadané hraně nahoře, a [stránka /FitR levy spodni pravy horni] zvětší vybraný obdélník (výřez) tak, aby vyplnil celý pohled. Vzhledem k faktu, že uvedené parametry počítají výsledné měřítko z geometrie samotné stránky spíše než na základě pevných souřadnic, takový /Fit cíl dokáže smysluplně pracovat i poté, kdy změníte celkovou velikost stránky. Zcela naopak cíl zadaný zarážkou /XYZ mající natvrdo vložený parametr „zoom“ dokáže nechat uživatele nevěřícně civět kamsi do prázdného okraje. Konkrétně při sestavování obsahu zestárne sekvenční postup formovaný příkazem /FitH doplněným o hodnotu horní souřadnice konkrétního oddílu znatelně pomaleji (lépe) než povel /XYZ fungující s odhadnutým zoomem
Anotace: vše interaktivní, co není obsahem stránky
Anotace je objekt, který se vkládá (překrývá) na stránku, aniž by byl součástí jejího toku obsahu (content stream). Odkazy (linky), nalepovací lístečky (sticky notes), zvýraznění (highlights), interaktivní nástroje formulářů, ikony souborových příloh a grafická pečetidla (stamps): všechny tyto položky jsou anotace, sdružené v poli /Annots na stránce, kde sedí. Odebrání anotace z tohoto pole ji odstraní ze stránky bez ohledu na to, že obsah pod ní zůstává zcela nedotčen. Přesně o tom to celé je: anotace představují pouze editační vrstvu oddělenou od samotných značek, nad kterými sedí
Každá anotace sdílí určitou drobnou základní osu. Položka /Subtype pojmenovává druh (typ) anotace, parametr /Rect poskytuje její ohraničující prostor v souřadnicích stránky a do /Contents se ukládá text vystupující současně coby bezbariérový alternativní popis. Obzvláště případ anotace s odkazem (link annotation) stojí za podrobnější prozkoumání, vyskytuje se totiž ve dvou rozdílných podobách: buď coby holý cíl, anebo naopak ve formě operativní akce
12 0 obj % link to a destination
<< /Type /Annot /Subtype /Link
/Rect [100 200 300 250]
/Border [0 0 0]
/Dest [5 0 R /XYZ null null null] >>
endobj
13 0 obj % link that runs an action
<< /Type /Annot /Subtype /Link
/Rect [50 50 200 100]
/Border [0 0 0]
/A << /Type /Action /S /URI /URI (https://www.example.com) >> >>
endobj
Parametr /Rect definuje hotspot; kliknutí do jeho prostoru odešle čtečku k zadanému cíli za použití té samé gramatiky, kterou využívá celá osnova (outline). Vlastnost /Border [0 0 0] zde odvádí důležitou skutečnou práci: potlačuje odpudivý výchozí (defaultní) orámovací rámeček, kterým čtečky s oblibou lemují odkazy. Druhá z obou forem mění ten holý zadaný cíl přes parametr /Dest rovnou za aktivitu určovanou pod atributem pro vyjádření akce (action) skrze /A. Její příslušný podtyp na pozici /S posléze bezprostředně selektuje odpovídající chování: pomocí slova pro akci u /GoTo poskočí s orientací přesunem v rámci onoho aktuálního souboru, přes provedení parametrizované k /GoToR naváže k adresáři odkazujícímu za další doplňkový soubor, prostřednictvím příkazu přes zadané /URI míří k internetové adrese a při /Launch dokáže spustit venkovní odloučený program z jiné platformy (externí relaci programu). Právě to z posledně uvedených vyjmenovaných spuštění si nicméně zasluhuje mimořádnou opatrnost a podezíravost. Operace provádějící aktivitu do podoby k povelu o vyhlášení akce na /Launch zaručující ten start samotného spustitelného softwarového prostředku představuje chování, jenž vytváří z PDF v podstatě přenašečový vektor (malware vector) škodlivých kódů pro zařízení. Prohlížeče dodržující normy proto takový akt hned v základu blokují a nebo dost ostražitě zobrazují varování, kvůli čemuž daný odkaz posléze pro převážnou část čtenářů nefunguje (selhává). Sáhněte si po parametrech ukrytých za spínači u operací k /URI a případně o cestu pro funkční řešení vyvolané cestou volanou a provedenou k řešení pod nastavením ve variantě u odkazu s funkční výhodou pro vlastnost spojenou za provedení z /GoTo a ožehavému atributu do spuštění u parametrizace zaměřené u zadané volby pod instrukcí o volání cesty v povelu vkládaného z formátu spojeného pro variantu k řešené a definované specifikované podobě nasměrované do zástupce o spouštěči na vytyčené operaci u prvku /Launch se zdaleka zřekněte a vyhněte obloukem
Označovací anotace, jako zvýraznění (highlights) a nalepovací lístečky, nebo tvarové anotace jako /Square, s sebou nesou jeden háček: jejich vzhled na obrazovce rovnou nevyplývá z jejich typu. Prohlížeč si v základu vykreslí vlastní verzi, dokud jeho vzhled neukotvíte přes takzvaný proud vzhledu (appearance stream). Tuto roli plní položka /AP, která odkazuje na formulářový XObject obsahující kreslicí operátory. Pokud tuto položku vynecháte, jedno a to samé zvýraznění může ve dvou různých prohlížečích vypadat odlišně, případně se změní po obousměrném uložení (round-trip) v nějakém editoru. Pro každý prvek, jehož vizuální úprava tvoří nedílnou součást dokumentu, zajistěte doplnění položky /AP. Mimochodem, souborové přílohy (file attachments) používají naprosto stejný aparát: stream vloženého souboru a slovník specifikace k danému souboru, na něž se poukazuje buď přímo přes anotaci s formátem /FileAttachment, nebo z katalogu přes strom jmen ve větvi /EmbeddedFiles v hlavní nabídce pod /Names
Kde se tato vrstva láme a jak to odhalit
Opakujícím se defektem (selháním) v celém tomto systému zůstávají takzvané visící (slepé) odkazy. Záložky přestanou fungovat v momentě, kdy katalog ztratí položku /Outlines nebo když se řetězec navázaných sousedících prvků (sourozenců) v polovině stromu prostě přetrhne. Jakmile XMP toku schází parametr /Type /Metadata /Subtype /XML anebo obsahuje deformovanou (defektní) obalovou složku v elementu xpacket, zpracující software celá metadata okamžitě ignoruje. V každém z takovýchto případů zůstává reálný obsah samotné stránky absolutně v pořádku, takže běžné nahlížení s otevíráním souboru působí bezchybně a veškerý ten defekt prosvitne ven až ve chvíli v nahlížení na postranní navigační panel, do kterého ale většinou tak jako tak nikoho nenapadne nahlédnout a ani si ten vymezený okruh zkontrolovat
Nejčastěji tyhle chyby spolehlivě odchytí zavedení dvou nenáročných návyků. Nasazený soubor si nejdříve rozbalte ve skutečně fungujícím nativním prohlížeči, projděte panel vyhrazený u záložek a v krátkosti vyzkoušejte odkazování do menší zkušební sestavy u formátovaného obsahu nasměrované funkční (vzorkové) složky z okruhu dodaných (a použitých) zkušebních testovacích linků. Tím v zásadě celkový systém nasměrovaných odkazů prověříte formou, v jaké ho nakonec nasadí koncový čtenář. Záhy se doporučuje vzít oddělený nezávislý testovací prostředek ke zpracování zpětné dodané odezvy z analýzy v metadatech. Tak s ověřením zkontrolujete dohodnutý soulad podávající hodnoty mezi obsaženou hodnotou s info slovníkem i tím ukrytým obsahem vloženým ve sféře specifikující se do uceleného okruhu z XMP, přičemž tenhle ukrývaný ucelený a specifický chybující defektní nesoulad (jedinou obsaženou drobnou nesrovnalost) absolutně nepřizná a nevyčte uživatelský pokus ani s tím sebevíce navýšeným okruhem nekončícího testovacího vícenásobného prověřujícího proklikávání. Ideální a doporučovaná varianta rovnou spočívá v nasazení a zpracovávání generovaných ošetřených dokumentových vymezených vrstev přes integraci vně nasazené spolehlivé prověřené vázané sdružující ucelené integrované specifikované knihovny. Přisvojí-li si totiž tento vkladový balíček i vedení agendy (účetnictví s evidencí / bookkeeping) kolem vazeb přes obsluhu spjatou u funkčního formátu referencí (link), pak obvykle žádná z popsaných nástrah a pastí neotevře svá zubiska. Řešení jako HotPDF Component (Komponenta HotPDF) pro vývojová prostředí pro aplikace k platformě Delphi či C++Builder odkrývá z tohoto hlediska programovou infrastrukturu v zastoupení navázaných strukturovaných specifikací a ucelených vrstev s vkládáním přes osnovy (outlines), formátovaných prvků s anotacemi a doplňovaných definovaných úprav strukturovaných záznamových hodnot obsažených do metadat prostřednictvím specifikovaného API u úrovně a ošetřovaného parametrizování dokumentu (document-level APIs). Díky takovým procesům se bez starostí omezíte čistě na stanovený funkční popis do ucelených dodávaných složek v osnovové záložkové hierarchii, popíšete zástupné odkazy a integrovanou funkcionalitu ošetřující zbylé vázané funkce obstarávaných s ohledem cílícím pod zprostředkovatelské specifikované nastavení jednoduše zplnomocníte u celistvého zprostředkovatelského uschovaného mechanismu a o navléknutí těch odkazů do souvislého celku (proplétání referenční sítě / thread the references) se ta obslužná komponenta postará zcela sama. Z hlediska celkového určení nad problematikou sdružovanou a definující ukotvené navazované a vyvíjené složené dokumentové ošetřené objekty z objektového spjatého ošetřeného rozvrženého zřízeného celistvého a objektivně rozvrženého navazujícího stanoveného složeného a začleněného a pojatého uspořádání k ucelenému zobrazenému ohraničení tvořící orientaci z kruhu (For the object model), ze kterého se obsažené specifikované probádané nasměrované funkčně uplatňované zobrazené prvky do struktur formátovaným zohledněním zavedených a propojených definovaných funkčních zapojení připojují, odkazuje uvedený rozvržený technický přehled o ucelené sestavě z rozborů ke strukturálnímu uspořádání formátu souborů u platformy a orientace ve struktuře specifikované zástupci PDF vrstev (technický přehled struktury formátu PDF) rovnou do sféry dodávající přes spojenou specifikaci spjatou z ošetřeného zpracování i agendu a rozbor se seznámením kolem toho orientovaného nasměrovaného specifikovaného sdíleného (orientovaného a vybudovaného uceleného a nasazeného určeného) fungujícího a probíhajícího dokumentového ztvárnění u katalogu, stejně jako do obsahu tabulek od zanesených specifikovaných tabulek ukrývajících agendu ke křížovým formátovaným referencím (u odkazových formovaných tabulek pro záznamy ke stanoveným křížovým sdíleným referenčním bodům z ohraničených tabulek s odkazy (křížových odkazů / cross-reference table)), na kterých jsou tyto vyjmenované složky v naprosté obsažnosti plně bez zaváhání existenčně závislé a beze zbytku na tom postavené