Teknik Makale

PDF Doğrusallaştırma ve Fast Web View: Nasıl Çalışır

80 MB'lık taranmış bir raporu bir bağlantının arkasına koyun, tarayıcıda açın ve ne olduğunu izleyin: Görüntüleyici, bu baytların büyük bir kısmı gelene kadar boş bir bölmede bekler, ardından birinci sayfayı tek seferde çizer. 40. sayfaya atladığınızda, kötü oluşturulmuş bir dosyada tüm indirme işlemi yeniden başlayabilir. Sinir bozucu olan kısım, okuyucunun sadece ilk sayfayı istemiş olmasıdır. Doğrusallaştırma, bu sorunun yapısal cevabıdır. Görüntüleyicinin, dosyanın küçük bir başlangıç kısmından açılış sayfasını oluşturabilmesi ve geri kalanını talep üzerine getirebilmesi için bir PDF'yi yeniden düzenler; Adobe'nin bu özelliği "Fast Web View" (Hızlı Web Görünümü) olarak pazarlamasının nedeni de budur

Bunların hiçbiri farklı bir dosya formatı değildir. Doğrusallaştırılmış bir PDF, uyumlu bir okuyucunun hiçbir özel işlem yapmadan açacağı sıradan bir PDF'dir. İşin püf noktası tamamen baytların nasıl sıralandığında ve dosyanın taşıdığı iki ekstra yapıda yatmaktadır. ISO 32000-1, Ek F'de (Annex F) tüm bu düzenlemeyi belirtir ve düzeni bir kez gördüğünüzde, bu davranış bir sihir gibi görünmekten çıkar ve ilk boyama (first-paint) gecikmesi için dosya sırasının kasıtlı bir takası gibi görünmeye başlar

Doğrusallaştırma aslında neyi yeniden düzenler

Normal bir PDF, nesnelerini hemen hemen her sırada dağıtabilir. Dosyanın sonundaki çapraz başvuru (cross-reference) tablosu bunun çalışmasını sağlayan şeydir: Bir okuyucu sona gider, startxref işaretçisini okur, xref'i yükler ve oradan her nesneyi ofsetine (offset) göre bulabilir. Bu tasarım, sona gitmenin hiçbir maliyetinin olmadığı yerel dosyalar için mükemmeldir; ancak sonun tam olarak en son gelen kısım olduğu bir ağ üzerinden akan (streaming) bir dosya için yetersizdir. Birinci sayfayı oluşturmak için geleneksel bir okuyucu sayfa nesnesine, içerik akışına (content stream), başvurduğu yazı tiplerine ve çizdiği herhangi bir resme ihtiyaç duyar ve sırasız bir dosyada bunlar, son megabayt da dahil olmak üzere herhangi bir yerde bulunabilir

Doğrusallaştırma sırayı düzeltir. İlk sayfayı görüntülemek için gereken nesneler, küçük bir başlık bölümünden hemen sonra ön tarafa yakın bitişik bir blokta toplanır, böylece bayt akışında erken gelirler. Diğer her şey, kalan sayfalar ve paylaştıkları kaynaklar, öngörülebilir bir sırayı takip eder. Optimizasyonu görmezden gelen okuyucular için dosyanın sonunda hala ikinci ve tam bir çapraz başvuru tablosu bulunur, ancak doğrusallaştırılmış bir dosya ayrıca ilk sayfa çapraz başvurusunu ve akış sağlayan (streaming) bir okuyucunun ihtiyaç duyduğu parametreleri ön tarafa yerleştirir. Okuyucunun herhangi bir şey çizebilmesi için artık kuyruğa ulaşmasına gerek yoktur

İlk sayfa nesne kümesi ve doğrusallaştırma parametre sözlüğü

Doğrusallaştırılmış bir dosyada %PDF başlığından sonraki en ilk nesne, doğrusallaştırma parametre sözlüğüdür (linearization parameter dictionary). Akış okuyucusunun optimizasyonun mevcut olup olmadığına ve nasıl kullanılacağına karar vermek için aradığı şey budur. Sözlük, tüm dosyanın uzunluğunu, ana çapraz başvuru bölümünün başladığı bayt ofsetini, ilk sayfanın nesne numarasını ve onu izleyen ipucu akışının (hint stream) konumunu ve uzunluğunu kaydeder. Bir okuyucu sadece başlangıçtaki kilobaytlara bakarak, bu rakamlarla birinci sayfayı göstermek için ne kadar veri getirmesi gerektiğini ve başka bir yere atlamasını sağlayan dizin için nereye bakması gerektiğini bilir

Ek F (Annex F), burada "ilk sayfa"nın ne anlama geldiği konusunda katıdır. İlk sayfa bölümü, sayfa nesnesinin kendisini, içerik akışlarını ve bu akışların başvurduğu kaynakları içermelidir; böylece bu ön ek indirildiğinde sayfa kendi kendine yeterli hale gelir. Paylaşılan kaynaklar, her sayfada kullanılan bir yazı tipi, bir başlıkta tekrarlanan bir logo özel olarak ele alınır: Bunlar ilk sayfaya hizmet edecek kadar erken görünürler, ancak paylaşılan olarak işaretlenirler, böylece okuyucu daha sonra 30. sayfayı oluştururken bunları yeniden getirmez. Sayfaya özel ve paylaşılan nesneler arasındaki bu ayrım, çoğu ev yapımı "optimize edicilerin" (optimizers) yanlış yaptığı kısımdır ve bunu yanlış yapmak, doğrusallaştırılmış olduğunu iddia eden ancak yine de takılan bir dosya üretilmesine neden olur

İpucu akışları (Hint streams): sayfa atlamalarını ucuzlatan dizin

Birinci sayfayı hızlıca göstermek değerin sadece yarısıdır. Diğer yarısı, aradaki her şeyi indirmeden rastgele bir sayfaya atlamaktır ve ipucu akışlarının sağladığı şey de budur. Doğrusallaştırılmış bir dosya, parametre sözlüğünden referans verilen bir akış olarak depolanan bir sayfa ofset ipucu tablosu (page offset hint table) ve paylaşılan nesne ipucu tablosu (shared object hint table) taşır. Sayfa ofset tablosu, her sayfa için nesnelerinin dosyada nerede başladığını ve ne kadar sürdüğünü kaydeder. Paylaşılan nesne tablosu da birden çok sayfa boyunca kullanılan kaynaklar için aynısını yapar

Bu tablolar göz önüne alındığında, 40. sayfayı isteyen bir okuyucu dosyayı sırayla ayrıştırmaz. 40. sayfanın kapladığı bayt aralığını öğrenmek için ipucu tablosuna başvurur, sunucudan tam olarak o aralığı ister ve o baytlar geldiğinde sayfayı oluşturur, henüz elinde bulunmayan paylaşılan kaynakları da aynı mekanizma aracılığıyla çeker. İpucu akışı, aslında belgenin üzerine serilmiş rastgele erişimli bir haritadır ve iyi doğrusallaştırılmış 500 sayfalık bir dosyanın yavaş bir bağlantı üzerinden yanıt veriyormuş gibi hissettirmesinin, aynı boyuttaki optimize edilmemiş bir dosyanın ise böyle hissettirmemesinin nedeni budur

Sunucu neden işbirliği yapmak zorundadır

Doğrusallaştırma, aktarımın dosyanın rastgele dilimlerini teslim edebileceğini varsayar ve zayıf sonuçlar için formatı suçlamadan önce bu varsayımı kontrol etmeye değer. Mekanizma HTTP bayt sunumudur (byte-serving): Okuyucu aralık (range) istekleri yayınlar ve sunucu bunlara 206 Partial Content yanıtlarıyla cevap verir. Eğer sunucu Accept-Ranges: bytes beyanında bulunmazsa veya önündeki bir proxy veya CDN aralık isteklerini tam aktarımlara dönüştürürse (collapse), okuyucunun 40. sayfayı yalıtılmış bir şekilde getirmesinin hiçbir yolu kalmaz ve tüm dosyayı indirmeye geri döner. Bu durumda PDF'nin içindeki yapı tamamen doğrudur ancak tamamen boşa gitmiştir

Bu, çoğu zaman "doğrusallaştırma çalışmıyor" olarak yanlış teşhis edilen hatadır. Dosya iyidir; ancak teslimat yolu iyi değildir. Bir belgeyi yeniden oluşturmadan önce, okuyucunun ulaştığı URL için sunucunun (host) gerçekten kısmi içerik (partial content) döndürdüğünü koşullu bir istekle onaylayın. Çoğu statik sunucu bunu varsayılan olarak yapar; ancak yanlış yapılandırılmış birçok uygulama sunucusu ve önbellekleme katmanı yapmaz

Artımlı güncellemeler (Incremental updates) doğrusallaştırmayı sessizce bozar

Doğrusallaştırılmış dosyaları doğru bir şekilde üreten ve ardından optimizasyonun neden buharlaştığını merak eden kişileri şaşırtan kısıt buradadır. Doğrusallaştırma, dizini ön tarafta olan tek ve dikkatlice sıralanmış bir düzene bağlıdır. Artımlı bir güncelleme (incremental update) tasarımı gereği bunu ihlal eder. Bir araç artımlı kaydetme (incremental save) yoluyla bir imza eklediğinde, bir form alanını doldurduğunda veya bir notasyon eklediğinde, dosyayı yeniden yazmaz. Değiştirilen nesneleri, yeni bir çapraz başvuru bölümünü ve sonuna yeni bir kuyruk (trailer) ekler ve orijinal baytlara dokunmaz. Bu ekleme (append) işlemi artımlı güncellemelerin asıl amacıdır: Hızlıdır ve denetim veya imza doğrulaması için önceki revizyonu korur

Bunun yan etkisi, dosyanın artık en yeni çapraz başvuru verilerinin kuyrukta, özenle yerleştirilmiş ilk sayfa bloğundan sonra olması ve öndeki doğrusallaştırma parametre sözlüğünün artık dosyayla eşleşmeyen bir düzeni tanımlamasıdır. Uyumlu bir okuyucu bu uyuşmazlığı tespit eder ve belgeye normal, doğrusallaştırılmamış bir PDF gibi davranır. Orijinal doğrusallaştırılmış yapı hala dosyanın ilk yarısında duruyor olsa bile Fast Web View gitmiştir. Birkaç güncelleme eklerseniz, her biri sona başka bir revizyon yığar ve eski ön dizin ile gerçek durum arasındaki uçurum genişler

İş akışınız hem düzenlemelere hem de Fast Web View'a ihtiyaç duyuyorsa, kural doğrudan yapıdan gelir: Belge değişim halindeyken artımlı olarak düzenleyin, ardından en sonda bir kez yeniden doğrusallaştırın (re-linearize). Düzeni geri yükleyen şey tam bir yeniden yazma işlemidir. HotPDF terimleriyle bu, devam eden bir düzenlemenin bir delta ekleyen BeginIncrementalUpdate ve SaveIncrementalUpdate üzerinden geçmesi, bitirme adımının ise tüm belgeyi yükleyip LoadFromFile ve ardından SaveLoadedDocument ile baştan serileştirerek birikmiş eski revizyonları atması ve temiz bir düzen oluşturması anlamına gelir. Aynı durum nesne akışlarında (object streams) da görülür: UseObjectStreams'in UseXRefStream ile birlikte etkinleştirilmesi, çapraz başvuruyu sıkıştırır ve nesneleri sıkıca paketler, bu da dosya boyutuna yardımcı olur, ancak herhangi bir yapısal seçim gibi, eklenen bir revizyona iliştirilmek yerine bu son yeniden yazma işlemi sırasında uygulanmalıdır

// In-flight edits: append a delta, keep prior revisions intact.
// This leaves the file NOT linearized.
Pdf.BeginIncrementalUpdate('report.pdf');
Pdf.AddPage;
Pdf.CurrentPage.TextOut(72, 760, 0, 'Addendum');
Pdf.SaveIncrementalUpdate('report.pdf');

// Finishing step: full re-serialization produces one clean layout,
// dropping the stacked revisions. Re-run your linearizer on the output.
Pdf.LoadFromFile('report.pdf');
Pdf.SaveLoadedDocument('report-final.pdf');

HotPDF, tek çağrılık bir "doğrusallaştırma" (linearize) yordamı sunmaz, bu nedenle pratik yöntem, temiz, tamamen yeniden yazılmış bir dosya üretmek ve üzerinde özel bir optimize edici (optimizer) çalıştırmaktır. Komut satırı araçları yeniden düzenlemeyi doğrudan halleder. qpdf, bir dosyayı tek bir bayrakla (flag) doğrusallaştırılmış biçimde yeniden yazar:

qpdf --linearize report-final.pdf report-web.pdf

Bir dosyanın doğrusallaştırılıp doğrusallaştırılmadığı nasıl anlaşılır

Dosya adına veya onu ürettiğini iddia eden araca güvenmeyin; baytları doğrulayın. En doğrudan kontrol, dosyanın başıdır: Dosyayı açın ve başlıktan sonraki ilk nesne olarak, /Linearized anahtarını taşıyan doğrusallaştırma parametre sözlüğünü arayın. Okuyucuya dönük bir kısayol, yalnızca yapı gerçekten mevcut ve güncel olduğunda "Hızlı Web Görünümü: Evet" (Fast Web View: Yes) bildiren Acrobat'ın Belge Özellikleri iletişim kutusudur

Komut dosyası (script) tabanlı kontroller için qpdf, yapının hem varlığını hem de bütünlüğünü raporlar; bu önemlidir, çünkü bir dosya artık kendi düzenini yansıtmayan bir doğrusallaştırma sözlüğü taşıyabilir, ki bu tam olarak artımlı bir güncellemenin geride bıraktığı durumdur:

# Reports "File is linearized" and validates hint tables against the layout
qpdf --check report-web.pdf

# Dumps the linearization parameters and hint data in detail
qpdf --show-linearization report-web.pdf

Doğrulama adımı, hakkını veren (earns its keep) adımdır. Sadece sözlüğün var olduğunu doğrulayan bir geçiş (pass), dizini yanlış ofsetleri işaret eden bir dosyayı seve seve onaylayacaktır; ancak ipucu tablolarını gerçek nesne konumlarıyla uzlaştıran bir kontrol, optimizasyonun gerçek bir okuyucunun aralık istekleri altında dayanıp dayanmayacağını size söyleyen şeydir

Doğrusallaştırma, web üzerinden sunulan herhangi bir büyük belgeye, özellikle de düzensiz bağlantıları olan mobil okuyuculara uygulanmaya hala değerdir ve önden yüklenen (front-loaded) dizin için dosya boyutunun yüzde birkaçı kadar maliyeti vardır. Unutulmaması gereken iki şey, PDF'nin içindeki yapının ve dışındaki bayt sunumunun (byte-serving) her ikisinin de doğru olması gerektiği ve işlemden sonra yapılan herhangi bir düzenlemenin, siz dosyayı yeniden yazana kadar optimizasyonu geri alacağıdır. Yeniden doğrusallaştırmayı, diğer tüm değişiklikler oturduktan sonra, boru hattındaki (pipeline) son adım olarak görün. Burada açıklanan çapraz başvuru, nesne akışı ve artımlı güncelleme davranışı, Delphi ve C++Builder için HotPDF Component'in uyguladığı yapısal modelin bir parçasıdır; daha geniş dosya düzeni arka planı için bir PDF nasıl yapılandırılır (how a PDF is structured) bölümüne ve koddaki artımlı güncelleme ile büyük dosya iş akışı için Delphi'den büyük PDF'leri işleme (processing large PDFs from Delphi) bölümüne bakın