Vložte někam pod odkaz osmdesátimegabajtovou (80 MB) naskenovanou zprávu, otevřete ji v prohlížeči a sledujte, co se stane: prohlížeč civí na prázdný panel (blank pane) až do chvíle, dokud nedorazí velká část těchto dat, a teprve poté vykreslí rovnou úplně celou první stranu. Pokud u takto špatně sestaveného souboru skočíte na stránku 40, může dojít k restartování úplně celého stahování. Frustrující částí na tom je, že čtenář celou dobu chtěl vidět pouze onu první stránku. Strukturální odpověď na tento problém představuje linearizace (linearization). Ta přeskládá PDF soubor takovým způsobem, aby prohlížeč dokázal vykreslit úvodní stránku hned z malé úvodní části souboru (prefixu) a zbytek dočetl posléze jen na vyžádání. Proto společnost Adobe tuto funkčnost marketingově označuje jako "Fast Web View" (Rychlé zobrazování z webu)
Nic z tohoto procesu ovšem nepředstavuje odlišný formát souboru. Linearizované PDF je běžným standardním souborem PDF, který každá norma dodržující čtečka (conforming reader) bez problému otevře bez jakéhokoli speciálního zacházení. Trik spočívá kompletně v tom, v jakém pořadí (posloupnosti) jsou tyto datové jednotky uspořádány, a pak také v přítomnosti dvou dodatečných (extra) struktur, které takový dokument nese. Norma ISO 32000-1 přesně specifikuje celé toto rozvržení pod přílohou v Annexu F, a jakmile jednou uvidíte ono uspořádání na vlastní oči, přestane vám to připadat jako magie a začne vám to dávat smysl coby úmyslný promyšlený ústupek – obětování (trade) uspořádání sekvence prvků v souboru za získání prvotní rychlosti při vykreslení (first-paint latency)
Co linearizace vlastně přeskládá
Standardní PDF může své objekty uspořádat téměř v jakémkoliv rozptýleném pořadí. To, že takový zmatek vůbec funguje, zařizuje křížová referenční tabulka (cross-reference table) uschovaná na konci souboru: prohlížeč přeskočí rovnou na úplný závěr, přečte zde ukazatel startxref, přes něj načte tuto xref tabulku a teprve s její pomocí vyhledá přesné umístění všech objektů podle jejich posunu (offsetu). Tato koncepce je sice brilantní pro lokální soubory ležící na disku, u kterých hledání a přesouvání od konce nespotřebuje ani sekundu, ale zrovna tak funguje velmi neohrabaně v momentě odesílaného stahovaného toku dat přes síť. U stahovaného souboru představuje ten "konec" dokumentu zrovna ten fragment formátu dat, co k vám na cílový počítač projde v samotném závěru. K zobrazení první stránky obyčejný prohlížeč vyžaduje načíst objekt s danou stránkou, proud obsahu stránky, příslušné odkazované fonty a obrázky. U neoptimalizovaného nepřeskládaného souboru mohou tyto dílčí kousky pro první stránku viset kdekoliv uvnitř – reálně třeba i v posledním megabajtu celého PDF
Linearizace toto uspořádání pevně ukotví. Objekty, které jsou potřeba pro zobrazení první stránky, přesune do souvislého bloku k počátku souboru, hned za drobnou hlavičku, aby dorazily v datovém proudu dříve. Vše ostatní, včetně zbývajících stránek a sdílených zdrojů (resources), pak následuje v předvídatelném pořadí. Ta druhá a zcela kompletní křížová referenční tabulka stále zůstává uložená na samotném konci, a to kvůli těm prohlížečům, jež takovou optimalizaci ignorují. Linearizovaný soubor však umisťuje bezprostředně k začátku také křížovou referenční tabulku oné první strany (first-page cross-reference) společně se sadou těch parametrů, které streamovací čtečka k nahrání nutně potřebuje. Zpracovávající čtečce tedy už naprosto odpadá povinnost vyčkat s vykreslováním čehokoliv viditelného (before it can draw anything) až na přijetí ocasu (samého konce)
Sada objektů první stránky a slovník parametrů linearizace
Úplně prvním objektem v linearizovaném souboru, těsně za hlavičkou %PDF, je slovník parametrů linearizace (linearization parameter dictionary). Streamovací prohlížeče pátrají právě po něm, aby dokázaly rozeznat přítomnost dané optimalizace a pochopily, jak přesně s ní pracovat. Slovník zaznamenává celkovou bajtovou délku souboru, odstup (byte offset) počátku hlavní křížové referenční sekce (main cross-reference section), dále určuje objektové číslo pro objekt první stránky a zároveň dodává také lokaci včetně velikosti pro navazující "nápovědní" tok (hint stream). S těmito hodnotami, načtenými pouze ze zlomku úvodních kilobajtů celého souboru, dokáže prohlížeč snadno určit, kolik dat musí stáhnout pro úspěšné zobrazení úvodní strany a také, kam se má podívat po vyhledávacím rejstříku (indexu), jenž by mohl využít v situaci pro okamžitý přeskok jinam
Příloha F (Annex F) definuje zcela striktně, co onen termín „první stránka“ vlastně znamená. Sekce vyhrazená první straně musí nutně obsahovat samotný objekt strany, příslušné obsahové toky (content streams) i všechny navázané zdroje a odkazované prvky (resources those streams reference) takovým způsobem, aby strana byla plně soběstačná v momentě úspěšného stažení a načtení tohoto prefixu. U sdílených zdrojů – například písmo uplatňované pro každou stranu nebo logo trvale opakující se ve všech hlavičkách – se aplikuje speciální režim: tyto sdílené prostředky naběhnou včas k zaručení funkčnosti pro první stránku, ale zároveň na sobě ukrývají označení pomocí příznaku coby sdílené (flagged as shared). Tak se zabrání zbytečnému nechtěnému opětovnému stažení čtečkou, u které by jinak toto opětovné načítání zas hrozilo posléze, třeba u následného vykreslení 30. listu. Zmiňované rozlišování mezi ryze privátními prvky pro jednotlivé stránky (page-private) oproti navázaným vzájemně sdíleným objektům platí za zcela tu nejvíce ožehavou záležitost. Právě zde většina amatérsky zhotovených „optimalizátorů“ dělá spoustu chyb. Přesně tohle chybování ve specifikaci rovnou plodí soubory hlásající o sobě patřičnou linearizaci, ovšem přes tu domnělou přítomnost i tyto verze následně bez milosti při provádění drhnou a zcela pochopitelně se zasekávají (stalls)
Hint streams: index, díky němuž jsou skoky po stránkách nenáročné
Bleskurychlé zobrazení úvodní strany dává pochopitelně najevo teprve polovinu přidané hodnoty z této optimalizace. Tím druhým stěžejním benefitem je pohodlný nezávislý přeskok na naprosto libovolnou stránku, a to bez nutnosti stažení všeho ostatního, co se v souboru vyskytuje mezi počátkem a tímto cílem. Tuto úžasnou funkci zprostředkují nápovědní datové toky, takzvané hint streams. Linearizovaný soubor totiž nese v sobě orientační nápovědní tabulku pro odstupy stránek (page offset hint table) i doplňkovou nápovědní tabulku pro sdílené objekty (shared object hint table). Obojí se ukládá pospolu coby dodaný vkládaný nezávislý informační datový proud odkázaný ze slovníku parametrů (parameter dictionary). Detailní evidence z tabulky o offsetech stránek (page offset table) posléze záznam s evidencí rozepisuje ke každé stávající straně – kde přesně obsažené objekty se začátkem ukrytým v rámci ošetřovaného souboru začínají, včetně hodnot udávající velikost tohoto bloku (jak velký úsek paměti ten který objekt zabírá). Ztotožněnou vizi na uplatněném rovnocenném ošetřeném zavedeném ukotveném základu pak zavedená sdílená ošetřená specifikovaná tabulka na navazující orientačně doplňující obsažené objekty (shared object table) převezme nad všemi (se všemi zdroji užívanými napříč roztroušenou sadou většího spektra) ošetřených vícero propojených uplatňujících zadaných ucelených stran ze souboru (z dokumentu)
Vyzbrojena takovýmito tabulkami neparsuje čtečka soubor sekvenčně (krok za krokem), žádá-li zrovna obsah stránky 40. Vyhledá orientačně záznam v nápovědní tabulce ke zjištění rozsahu pro přesný datový okruh zabraných bajtů patřících onomu objektu čtyřicítky (byte range), vyžádá u obsaženého vzdáleného odesílatele (serveru) doručení odesílaného úseku jen u toho konkrétního formátovaného záznamového spektra ze sítě, a vybraný obsah stránky vyobrazí čtečka rovnou, jakmile poptávaná data bezpečně dorazí na své místo, k čemuž mimochodem prostřednictvím naprosto totožného formovaného mechanismu přitáhne k cíli dohledanou obsaženou sféru z veškerých spjatých chybějících složek o doplňujících sdílených zdrojích (resources), kterými do oné dané chvíle její systém nedisponoval. Nápovědní proud (hint stream) v důsledku hraje úlohu jakési mapy náhodného přístupu (random-access map) přetažené přes PDF dokument. Toto specifikované orientování uvnitř linearizovaného provedení zapracované formou spletitě sestavovaných nápovědních tabulek dává plnou odpověď proč uživatelem proklikaný poctivě poskládaný rozměrný soubor spojený linearizací na 500 stránek dodá na pomalém spojení velmi svižnou odezvu (feels responsive), kdežto neoptimalizovaný formát od totožné tloušťky na to patřičně znatelné svižné fungování bez vymezení vůbec nestačí
Proč server musí spolupracovat
Linearizace spoléhá na fakt, že doručovací mechanismus dokáže přenášet naprosto libovolné ukrojené části (úlomky/výřezy/slices) z daného souboru. Tuto domněnku se vyplatí překontrolovat dříve, než u případných ubohých výsledků ze samotného načítání ukážete prstem na chybu ve formátu. Tento mechanismus tkví v HTTP protokolu s podílem za rozdělování dodávaného datového servírování (HTTP byte-serving): prohlížeč vyšle žádosti směřující do přesně vyžádaného datového rozsahu (range requests) a vybraný ukotvený server je vyslyší ošetřenou formovanou doplňující zprávou odeslanou s kódem 206 Partial Content. Pakliže samotný webový obslužný dodávaný zástupce (server) postrádá ve vizi u oznámení nahlášené hlášení Accept-Ranges: bytes (nehlásí do provozu spojenou podporu/ advertise), případně zadané proxy rozhraní nebo doručovací CDN, nasazená rovnou před onen server z úmyslu slučování roztroušených požadavků za plné stahování do kompletních objemných blokových přenosů (collapses range requests do full transfers), dotyčná navazující čtečka ztrácí jakoukoliv volbu pro dodání požadované čtyřicítky ve stavu izolované podoby odděleného úlomku a nezvládne najít formát jiný pro funkční nouzovou vyžádanou variantu do fallback (a uchýlí se ke / falls back) ukotvovaného rovnou do stahování celého PDF dokumentu (celého souboru). Skrytá zanesená struktura v dokumentu odpovídá v tu chvíli perfektní formě navazující na preciznost (perfektně korektní formát), a přesto se z dodaných vkládaných spojených obsažených odevzdaných doplňků jedná o rovnou ztracenou snahu, jež přijde vniveč (entirely wasted)
Právě tato porucha bývá s naprostou převahou nesprávně diagnostikována formou falešných soudů o tom, že se tu údajně ukrývá zástupná chyba s oznámením „linearizace absolutně nefunguje“. Samotný zkoumaný dokument je zcela v pořádku; avšak ta doručovací síťová (delivery path) cesta ne. Pro včasnou kontrolu ve vizi k řešení k přebudovávání (rebuild) celistvého dodaného souboru z PDF k dohledu proto raději přes podmíněný dotaz (conditional request) s ujasněním k ošetřené formované dodané formátované sféře prověřte (že hostitel odesílá a/ returns partial content) uplatňující dílčí rozdělené obsahy za specifikovanou dotazovanou adresu ze (URL), na kterou z prohlížecí složky odkazujete. Většina statických webových serverů (static hosts) tento proces formuje implicitně pod (ve výchozím nastavení / by default); přičemž do odlišné neschopnosti skloubená nepřeberná sada zpackaných špatně nastavených (misconfigured) aplikačních serverů a vrstev mezipaměti (caching layers) tuto funkcionalitu ve sféře na stahování prostě vůbec neplní (do not)
Inkrementální aktualizace tiše rozbíjejí linearizaci
Tady se dostáváme k onomu omezení (constraint), ze kterého bývají tvůrci zhotovující korektně fungující linearizované verze souborů silně vyvedeni z míry při zjištění, proč optimalizace náhle záhadně vyprchá a zkrátka zmizí (evaporates). Linearizace v útrobách stojí na zprostředkovaném uspořádaném jediném (stojí na ukotveném jediném a vysoce citlivě rozvrženém sdíleném uspořádaném rozložení obsaženého/ carefully ordered layout) uspořádání s indexem v předních liniích (at the front). Inkrementální (dílčí a postupná) aktualizace (update) svým ústředním koncepčním podáním a návrhem takovou strukturu narušuje (violates that by design). Zásah prostřednictvím funkčně obsaženého nástrojového orientování pro přidání podpisu (adds a signature), vyplnění formulářových políček (fills a form field) anebo za vložení z obsažené ukotvené formované anotace prostřednictvím inkrementálního (postupného) uložení (incremental save), dokument v PDF zkrátka rovnou obsažený soubor vůbec orientačně celý nepřepisuje (does not rewrite the file). Připojuje zúčastněné změněné objekty, přidává dodanou uspořádanou odnož skrze křížově formovanou referenční sekci (a new cross-reference section) i s ukotveným novým koncovým trailerem na úplný konec (to the end), přičemž původní bajtové úseky ponechává nedotčené (untouched). Zrovna takovéto připojování (append) samo od sebe vytyčuje podstatu inkrementálních aktualizací: je to proces mimořádně rychlý (it is fast) a zároveň uvnitř souboru zanechává předchozí (dřívější) revizi uchovanou pro účely auditu nebo ověřování podpisů (signature validation)
Vedlejší efekt (side effect) takového jednání způsobuje znatelně dodanou (neblahou) skutečnost, že dotyčný PDF soubor do vize ukládá nejaktuálnější a nejnovější zadaná křížová referenční data na chvost formátu (at the tail), hned za onen pečlivě uspořádaný uplatněný zavedený dodaný blok u první strany (first-page block). Tím slovník pro parametry od linearizace v popředí (at the front) popisuje strukturu (rozložení), které s reálným obsaženým uspořádáním vůbec neodpovídá formátu za objektivní skutečností (no longer matches the file). Norma-dodržující čtečka (conforming reader) takovou neshodu s rozvržením odhalí (detects the mismatch) a v mžiku přistoupí k dokumentu stejně jako k normálnímu, nelinearizovanému PDF. Fast Web View zcela vyprchá (is gone), přestože původní linearizovaná struktura nadále zůstává uschována a sedí v první polovině souboru. Pakliže ve formátu připojíte (append) hned několik (vícero) takových aktualizací do úprav, každá (each one) taková úprava nastohuje a naskládá (stacks) další revizní formaci k závěru (on the end), a mezera (propast / gap) vzniklá mezi zastaralým neplatným úvodním indexem a reálným stavem PDF se ještě více rozšiřuje a zvětšuje (widens)
Potřebuje-li váš pracovní postup (workflow) obojí – jak úpravy, tak i optimalizaci přes Fast Web View – pravidlo vyplývá přímo ze samotné struktury: provádějte dílčí (inkrementální) úpravy v průběhu neustálých aktivních modifikací a změn, kdy je soubor ještě takříkajíc „v pohybu“ (is in flux), ale úplně na závěr to všechno jednorázově prolinearizujte (re-linearize once at the end). Pouze kompletní a úplné přepsání (full rewrite) celého souboru totiž dokáže obnovit pečlivě strukturované obsažené rozložení (layout). Z pohledu terminologie komponenty HotPDF to znamená, že rozepracovaná editace prochází za pomoci příkazů BeginIncrementalUpdate a SaveIncrementalUpdate, čímž do souboru připojujete pouze částečné změny a rozdíly (append a delta). Kdežto onen finální dokončovací krok načte sjednocený obsah z paměti pro celý dokument a následně jej zcela od znova zpracuje do plnohodnotného čerstvého zapsání skrze pokyn s voláním LoadFromFile a po něm spuštěné formované ukládání se SaveLoadedDocument. Tím se spolehlivě zahodí všechny staré nashromážděné nastřádané (postupné doplňované) revize a uvolní se cesta k jedinému zcela čistému formovanému uspořádání. Ten samý kompromis platí rovněž u toků a obsažených ošetřených vkládaných zástupců z objektových nasměrovaných toků (object streams): povolení vlastnosti přes UseObjectStreams formou ruku v ruce s povely obsaženými skrze povolující vlastnosti UseXRefStream plně zkomprimuje křížovou referenční vrstvu a vtěsná dodané objekty velmi blízko k sobě obsaženě pospolu (packs tightly). Z hlediska celkové kapacity to velikosti souboru v oněch datových hodnotách naprosto objektivně s navázaným ukotvovaným přínosem ulevuje, ale jako úplně každé podobné strukturální rozhodnutí musí být i tohle nasměrované objektivní uspořádání provedeno až během toho závěrečného přepisu (during that final rewrite), namísto toho, aby bylo "našroubované narychlo" jako pouze připojená (appended) doplňková revize k souboru
// Zásahy za chodu (In-flight edits): připojení dílčích změn formou ošetřené diference (delty),
// ponechání dřívějších revizí beze změny.
// Tímto krokem soubor ZŮSTÁVÁ nelinerizovaný.
Pdf.BeginIncrementalUpdate('report.pdf');
Pdf.AddPage;
Pdf.CurrentPage.TextOut(72, 760, 0, 'Addendum');
Pdf.SaveIncrementalUpdate('report.pdf');
// Dokončovací krok: plnohodnotná reserializace poskytuje čisté rozvržení,
// zahazující nastřádané revize. Nad výsledným souborem znovu spusťte váš linearizátor.
Pdf.LoadFromFile('report.pdf');
Pdf.SaveLoadedDocument('report-final.pdf');
Vzhledem k faktu, že komponenta HotPDF neposkytuje „jednorázovou“ rutinu typu "linearize", ukazuje se jako praktický vzor vygenerovat čistý, kompletně přepsaný soubor a následně nad ním spustit dedikovaný optimalizátor. Nástroje pro příkazový řádek tohle přeskládání zvládnou vyřídit obsažně a zcela přímo. Příkaz qpdf přepíše soubor do linearizované formované podoby pomocí jediného příznaku s parametrem:
qpdf --linearize report-final.pdf report-web.pdf
Jak bezpečně zjistit, zdali je soubor linearizovaný
Nedůvěřujte názvu souboru, ani nástrojům hlásajícím, že přesně oni ten soubor vytvořily; vždy prověřujte samotné bajty. Tou nejpřímější možnou kontrolou je hlavička souboru: otevřete ho a začněte hledat slovník s linearizačními parametry (linearization parameter dictionary) jakožto první objekt v pořadí hned za hlavičkou, který nese u sebe (carrying) parametr pro klíč /Linearized. Uživatelská obsažená uplatňovaná zkratka pro čtečky se představuje u dialogu Vlastnosti dokumentu (Document Properties) programu Acrobat, který hlásí zprávu "Fast Web View: Ano" (Fast Web View: Yes) pouze a jen tehdy, pokud je v souboru tato struktura fakticky (skutečně) obsažena a zároveň aktuálně odpovídá
Za účelem skriptovaných kontrol, příkaz qpdf hlásí do navázaného vnímajícího ohledu u vnořeného hlášení jak přítomnost, tak dodanou integritu (integrity) zkoumané dodané struktury, na čemž poměrně hodně sejde, protože soubor může nést obsažený slovník linearizace i v případě, kdy už rozvržení uspořádání formátově neodráží tu reálnou skutečnost v uplatnění (no longer reflects its layout), což představuje naprosto onen přesný stav (exactly the state), který za sebou s inkrementální formací zanechá inkrementální aktualizace (incremental update):
# Hlásí „File is linearized“ a validuje nápovědní tabulky proti uspořádání
qpdf --check report-web.pdf
# Zobrazí detailně parametry z linearizace a data s nápovědou (hint data) v detailním ošetřeném a orientačně nasměrovaném obsaženém náhledu
qpdf --show-linearization report-web.pdf
Krok validace je přesně tím prověřujícím úkonem, který má své skutečné opodstatnění (earns its keep). Zběžná kontrola (průchod), co u formátu z PDF dokumentu pouze potvrdí pouhou existenci obsaženého slovníku u parametrů, klidně formálně schválí (happily bless) i zcela poškozený soubor, do jehož naváděcí sféry ukazuje indexový odkaz na zcela chybné obsažené (falešné) odsazení za (wrong offsets). Až poctivý dohledávací uplatňovaný krok s porovnáním u tabulky nápověd (hint tables) vůči reálným skutečným křížovým formovaným pozicím pro objekty (actual object positions) vám naplno formátově řekne (objasní), zdali dotyčná optimalizace dokáže reálně fungovat a nerozsype se hned pod zatížením spjatým se skutečnými rozsahovými vyžádanými dotazy v režii od opravdové čtečky (real reader's range requests)
Linearizace si ovšem i nadále zaslouží (remains worth applying) implementovat u jakéhokoli velkého dokumentu odesílaného po síti (přes web), a to zejména s ohledem na mobilní uživatele nasazené na nerovnoměrném a kolísavém spojení (uneven connections), u kterých zapojovaná úleva za indexovou složku z počátku dokumentu do objemu s (front-loaded) indexem stojí objektivně pouhé procentuální zlomky z celkové kapacity z velikosti z (file size). U formátování je zapotřebí uplatňovat na dohledu jen ta stěžejní pravidla vnímání: za prvé ta dokumentová skrytá struktura uvnitř zkoumaného PDF a do toho za druhé ono ukotvené navazující doručování po bytech (byte-serving) na poskytujícím serveru vně (outside it) musí obojí dodržovat bezchybné chování (both have to be right), a za druhé pamatujte, že jakákoli následně uskutečněná ex post úprava (edit after the fact) vkládající úpravu z navázaných formátů okamžitě odbourává optimalizující sféru linearizace – a to až do momentu s ohledem dokud ten soubor kompletně neprolinearizujete formou nového přepisu celého formátu (until you rewrite the file). Přistupujte k re-linearizaci jako ke zcela poslednímu zástupnému kroku v uceleném produkčním nasazeném zpracování (in the pipeline), tedy formou do chvíle, kdy máte po spojených dohledech všechny ostatní úpravy nasazené a dokončené (is settled). Detailně popsané fungující orientované chování dodaných křížových referencí, objektových proudů (object streams) i inkrementálních formovaných úprav, popsané výše, představuje nedílnou součást strukturálního obsaženého navázaného zástupného modelu obsaženého z dokumentu, který u sebe dodaná knihovna a Komponenta HotPDF pro prostředí Delphi i C++Builder v rámci kódu zavádí do praxe (implements); pro získání širšího kontextu na zástupné ošetřené uspořádání (file-layout background) v souborech nahlédněte rovnou na článek jak funguje (jak je orientačně navržen) struktura ve formátovaných prvcích PDF dokumentu, a pro pochopení problematiky (a k pracovním postupům) nad inkrementálními formátovanými zástupnými aktualizacemi (incremental-update) s orientací nad dodanými rozměrnými (and large-file) dokumenty do praxe v kódu pro nahlédnutí a ošetření v prohlížeči pak zamiřte rovnou na zpracování rozsáhlých PDF dokumentů s nasazením do Delphi