PDFium Component, Fast Web View (linearize edilmiş) PDF'leri TPdf.SaveAsLinearized üzerinden Delphi'den üretir. Metot, geçerli belgeyi PDFium ile kaydeder; sonra sonucu ISO 32000-1 Annex F'ye göre yeniden yazar: birinci sayfa nesneleri öne taşınır, iki cross-reference bölümü yazılır ve page offset ile shared object hint tabloları bir görüntüleyiciye herhangi bir sayfa için hangi bayt aralıklarının alınacağını söyler
Kimsenin umursamasının nedeni ağdır. Object storage ya da bir belge portalından servis edilen 40 MB'lık bir katalog, ilk birkaç kilobayttan sonra birinci sayfayı göstermeli; 380. sayfaya atlama birkaç HTTP Range isteğine mal olmalı, tam indirmeye değil. Görüntüleyiciler bunu yalnızca dosya linearize edildiğinde yapabilir. Bir düzenleme hattından çıkan PDF'lerin çoğu linearize değildir; çünkü PDF yazmanın doğal yolu, cross-reference tablosunu sona koyar ve page nesnelerini yazıcının tesadüfen ürettiği yerlere saçar
PDFium linearize edilmiş dosyaları neden okur da yazamaz?
PDFium'un linearization için eksiksiz bir okuyucusu vardır ve yazıcısı yoktur. FPDFAvail_* availability API'si linearization sözlüğünü saptar, hint tablolarını çözer ve koddan tam olarak ihtiyaç duyduğu bayt aralıklarını ister; PDFium Component'te progressive download ve iptal iş akışı bunun üzerine kuruludur. Genel save ABI'si ise yalnızca düz bir kopya kaydı ve hedef PDF sürümlü bir kayıt sunar. İçinde nesne yeniden sıralayan ya da hint stream üreten hiçbir şey yoktur
PDFium Component o boşluğu, PDFium'un hâlâ iyi yaptığı şeyi yeniden uygulamadan kapatır. TPdf.SaveAsLinearized önce mevcut SaveAsi çağırır; böylece semantic save PDFium'da kalır: düzenlenmiş sayfalar, form field durumu ve sürüm işleme yıllardır egzersiz yapılan kod yolundan gider. Bileşen sonra o stabil ara PDF üzerinde bir Annex F yeniden yapılandırma turu atar ve linearize edilmiş sonucu hedefinize yazar. İşi bu şekilde bölmek, linearization'ın bir annotation'ı ya da bir formu anlamak zorunda kalmaması demektir; yalnızca nesneler, referanslar ve bayt kaymaları
Delphi'den TPdf.SaveAsLinearized çağırmak
TPdf.SaveAsLinearizedin iki overload'u vardır: biri bir TStream için, biri bir dosya adı için; ve her ikisi de SaveAs ile aynı isteğe bağlı Option: TSaveOption ile PdfVersion: TPdfVersion parametrelerini alır. İkisi de başarı durumunda True döndürür. Dosya overload'u hedef dizindeki bir geçici dosyaya yazar ve hedefi atomik olarak değiştirir; böylece başarısız bir kayıt, eskiden iyi bir PDF'in durduğu yere yarım yazılmış bir PDF bırakmaz
var
Pdf: TPdf;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'catalog-2026.pdf';
Pdf.Active := True;
// ... sayfaları düzenleyin, formları doldurun, damga vurun, hattın yaptığı her neyse ...
if not Pdf.SaveAsLinearized('catalog-2026-web.pdf', saNoIncremental, pv17) then
raise Exception.Create('Linearized save failed');
finally
Pdf.Free;
end;
end;
Parametre kuralları bilerek katıdır. saIncremental hata yükseltir; çünkü artımlı bir güncelleme dosyanın sonuna yeni bir revizyon ekler ve öne yüklenmiş düzeni hemen yok eder. PDF 1.2 altı bir hedef sürüm de reddedilir; pvUnknown kaynak sürümü korur. Şifreli girdi saRemoveSecurity ister; çünkü yazıcı nesneleri yeniden numaralar ve PDF'in nesne seviyesi şifreleme anahtarları nesne numarasından türetilir. Ve linearization eksiksiz bir yeniden yazım olduğu için mevcut her dijital imza geçersizleşir. İmzalı ve linearize edilmiş teslim etmeniz gerekiyorsa önce linearize edin, sonra imzalayın
Yazıcı Fast Web View için nesneleri nasıl gruplar
Linearization, yalnızca birinci sayfayı dosyanın tepesine taşımak değildir. Yazıcı geçerli revizyonu ayrıştırır — cross-reference verisi klasik bir tablo mu, hibrit bir dosya mı, yoksa bir cross-reference stream mi — ve etkin bir object stream'in her üyesini bağımsız bir nesneye açar. Sonra bir referans grafiği kurar ve nesneleri beş gruba ayırır: dosyayı açmak için gereken belge seviyesi nesneler, birinci sayfa nesneleri, sonraki tek bir sayfaya özel nesneler, sonraki birkaç sayfa tarafından paylaşılan nesneler ve geri kalan her şey
O grafik gezinmesindeki tuzak /Parentdir. Her page dictionary, sayfa ağacında yukarı işaret eder ve naif bir gezinme o işaretçiyi parent düğümüne izler, sonra /Kids üzerinden her kardeş sayfaya ve onun content stream'lerine iner. Bir adım sonra birinci sayfa grubu bütün belgeyi içerir ve dosya teknik olarak linearizedir ama aralık öncelikli erişim için işe yaramaz. PDFium Component, sayfanın /Parent bağlantısını ve toplanmakta olan sayfanın dışındaki sayfa ağacı düğümlerini yok sayar; birinci sayfa bölümünü küçük tutan şey budur. Derin bir sayfa ağaçlı 51 sayfalık bir regresyon örneğinde birinci sayfa bölümü 5289 bayttır; 1105354 baytlık çıktının %0,48'i
Girdideki object stream'ler ve cross-reference stream'ler sıradan generation 0 dolaylı nesnelerine düzleştirilir, her referans yeni numaralara yeniden yazılır ve çıktı klasik cross-reference bölümleri kullanır. Bu, sıkıştırılmış object stream'lere kıyasla bir miktar dosya boyutuna mal olur; ama hint tablosu kapsamasını basitleştirir ve linearization bilincindeki her görüntüleyicinin hallettiği düzendir. Belirli bir çıktı için Fast Web View'tan çok küçüklük önemliyse PDFium Component'in o iş için ayrı bir object stream yazıcısı vardır
Linearization sözlüğüne ve iki xref bölümüne ne girer?
PDFium Component'in yazdığı linearize bir dosya, en ilk nesnede iki klasik cross-reference bölümü ve bir linearization sözlüğü taşır. İlk xref bölümü linearization sözlüğünü izler ve belge seviyesi ile birinci sayfa nesnelerini kapsar; böylece bir görüntüleyici birinci sayfayı yalnızca dosyanın önünden render edebilir. Ana xref bölümü sonda durur ve geri kalan her şeyi kapsar
Linearization sözlüğünün kendisi, bir görüntüleyicinin başka her şeyi okumadan önce ihtiyaç duyduğu sayıları tutar: dosya uzunluğu /L, hint stream kayması ve uzunluğu /H, birinci sayfa nesne numarası /O, birinci sayfa bölümünün sonu /E, sayfa sayısı /N ve ana xref tablosundaki ilk girişin kayması /T. Bunların hepsi son düzene bağlıdır ve sözlük, düzenin önünde durur. Onu doğal genişlikte sayılarla yazmak bir döngü kurar: 999999'dan 1000000'a büyüyen bir uzunluk bir bayt ekler, onu izleyen her kaymayı öteler; bu başka bir sayının genişliğini değiştirebilir ve böyle devam eder
PDFium Component döngüyü, linearization sözlüğü için sabit 320 bayt ayırarak kırar. Her nesne, hint stream, iki xref bölümü ve trailer'ler önce yazılır; bütün kaymalar kesinleştiğinde sözlük yerinde doldurulur ve ayrılan genişliğe kadar pad edilir. İnce bir ayrıntı /Tdir: ana xref tablosunun object 0 girişini işaret etmelidir, ondan önce gelen xref anahtar sözcüğünü değil. Katı doğrulayıcılar anahtar sözcük kaymasını işaretler; affedici görüntüleyiciler dosyayı yine de açar
Hint tablosu kaymaları hint stream'i neden yok sayar?
Linearize bir PDF'deki hint tablosu kaymaları, hint stream dosyada yokmuş gibi yorumlanır. Annex F bunu öyle tanımlar ki hint stream, birinci sayfa bölümü ile gerisi arasında kendi boyutu içerdiği sayılara geri beslenmeden durabilsin. Bir yazıcı için pratik sonucu yanlışlamak kolaydır: hint stream'den sonra duran her gerçek kayma, page offset ya da shared object hint tablosuna girmeden önce küçültülmek zorundadır
Soru, ne kadar küçültüleceğidir. Cazip cevap stream verisinin uzunluğudur; çünkü hint içeriği gibi hissettiren kısım odur. Doğru cevap, bütün hint dolaylı nesnesinin uzunluğudur: N 0 obj, stream sözlüğü, stream ile endstream anahtar sözcükleri ve endobj dâhil. Yalnızca veri uzunluğunu çıkarırsanız sonraki her kayma birkaç düzine bayt yanılır. Birinci sayfa yine render olur; çünkü hint stream'den önce yaşar; hata böylece hızlı bir görsel denetimi atlatır ve yalnızca bir görüntüleyici sonraki bir sayfaya atlayıp yanlış nesnenin ortasında başlayan bir aralık istediğinde ortaya çıkar
İki hint tablosu da bit paketlenir, en anlamlı bit önce; bu da Annex F gereğidir. Bileşen sonucu gerçek bir istemcinin yapacağı gibi doğrular: seyrek bir range deposu, 51 sayfalık örneğin yalnızca ilk 1 KiB'sini verir ve PDFium'un yerel hint işlemesi gerisini ister. Son sayfa, dosyanın tamamı hiçbir zaman mevcut olmadan açılır
Linearize edilmiş bir PDF'yi Delphi'de doğrulamak
En ucuz denetim, PDFium'un kendisine sormaktır. TPdf.InspectAvailability, availability API'sini belgeyi yüklemeden bir stream'e karşı çalıştırır ve Linearization alanı plnLinearized, plnNotLinearized ya da plnUnknown bildirir
function IsFastWebView(const FileName: string): Boolean;
var
Stream: TFileStream;
Info: TPdfAvailability;
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Info := TPdf.InspectAvailability(Stream);
Result := Info.Linearization = plnLinearized;
finally
Stream.Free;
end;
end;
Bu, PDFium'un düzeni tanıdığını teyit eder; hintlerin doğru olduğunu kanıtlamaz. Gerçek bir uçtan uca test için dosyayı aralık kısıtlı bir taşıyıcı üzerinden servis edin ve geç bir sayfayı TPdfProgressiveDocument ile açın; PDFium VCL ile büyük PDF'leri talep üzerine akıtma rehberinin yaptığı gibi. Sayfa, dosyanın yalnızca küçük bir kesrini aldıktan sonra render oluyorsa hint tabloları işini yapıyor demektir. Sürüm hattına ikinci bağımsız bir linearization denetleyicisi eklemek de değer; çünkü görüntüleyiciler, yanlış yerdeki bir /Tye ya da hafif yanlış bir kaymaya ne kadar affedici yaklaştıklarında ayrışırlar
Aklıda tutulacak iki sınır vardır. Object materializer hâlâ 2 GiB ve üzeri dizileri reddeder; son derece büyük belgeler şimdilik farklı bir strateji ister. Ve linearization yalnızca sunucu HTTP Range isteklerine uyduğunda kazandırır; Accept-Rangesi düşüren bir proxy arkasında linearize bir dosya, başka herhangi bir dosya gibi iner
FAQ
TPdf.SaveAsLinearized dijital imzaları geçerli tutar mı?
Hayır. TPdf.SaveAsLinearized her nesneyi yeniden numalar ve yeniden yazar; mevcut imzalar geçersizleşir. Önce linearize edin, sonra imzayı uygulayın
PDFium Component şifreli bir PDF'yi linearize edebilir mi?
Yalnızca saRemoveSecurity geçtiğinizde. Nesne seviyesi şifreleme anahtarları, yazıcının değiştirdiği nesne numaralarına bağlıdır; bu yüzden çıktı şifrelenmeden yazılır
Linearize çıktı hangi PDF sürümlerini destekler?
TPdf.SaveAsLinearized, kaynak sürümü korumak için pvUnknown ya da PDF 1.2 ve üstü herhangi bir hedefi kabul eder ve eklenmiş bir revizyon düzeni bozacağı için saIncrementali reddeder
Fast Web View çıktısı, progressive yükleme ve availability API'sinin hepsi, PDFium'u Delphi, C++Builder ve Lazarus projeleri için saran Delphi ve C++Builder için PDFium Component'in parçasıdır