XML Forms Architecture olan XFA kullanımdan kaldırılmıştır. ISO 32000-1, onu §12.7'de PDF 2.0'dan kaldırıldığına dair bir notla taşır ve modern görüntüleyiciler XFA motorlarını birer birer devre dışı bırakmaktadır. Bunların hiçbiri arşivleri boşaltmadı. Devlet başvuru formları, sigorta başvuruları ve banka ekstreler yaklaşık yirmi yıl boyunca XFA olarak yazıldı ve bu dosyalar bugün hâlâ gelen kutularına ve belge kanallarına ulaşıyor. Onları eskiden oluşturan görüntüleyici bunu yapmayı bıraktığında, form "lütfen farklı bir okuyucuda açın" yer tutucusuyla birlikte boş bir sayfaya dönüşür. Kalıcı çözüm, XFA'yı herhangi bir okuyucunun görüntüleyebileceği statik PDF içeriğine düzleştirmektir
Bu düzleştirmenin zor kısmı alanlar değildir. Metin kutuları ve onay kutuları AcroForm widget'larına yeterince temiz şekilde eşlenir. Zor kısım, XFA'nın bir draw öğesinin içinde, bir <exData contentType="text/html"> bloğunda depoladığı zengin metindir. Bu blok, satır içi stil ve çoğu zaman çıpalar içeren bir HTML alt kümesidir. Onu sayfaya aktarmak hem biçimlendirilmiş metni hem de canlı köprüleri yeniden oluşturmak anlamına gelir ve köprüler, çoğu uygulamanın sessizce vazgeçtiği kısımdır
XFA zengin metninin gerçekte nasıl göründüğü
Bir exData gövdesi küçük bir XHTML dilimidir. Bir paragraf bir <p>'dir; biçimlendirilmiş bir karakter aralığı, kalınlık, eğim, renk ve boyut için kendi satır içi CSS'i olan bir <span>'dir; ve bir köprü, görünür metnini saran bir <a href="...">'dir. Tek bir satır, her biri farklı stil içeren birkaç span'ı art arda tutabilir ve bunlardan biri bir çıpa olabilir. Stil, atılabilecek bir süsleme değildir. Yasal bir uyarı olduğu için koyu kırmızı işlenen bir madde, düzleştirme sonrasında da koyu ve kırmızı kalmalıdır; aksi takdirde düzleştirilmiş belge orijinali yanlış temsil eder
Dolayısıyla düzleştirme motoru bloğu tek bir dize olarak işleyemez. Satır içi yapıyı dolaşması, her çalışmanın etkin stilini span'ın satır içi CSS'ini draw öğesinin temel yazı tipiyle katmanlayarak çözmesi ve çalışmaları satır boyunca ard arda düzenlemesi gerekir. HotPDF bu yerleştirilen parçaların her birini dahili bir TXFARichRun kaydı olarak modeller. Kayıt, çalışmanın metnini, çözümlenen stilini, ölçülen kutusunu ve bir çıpa için işaret ettiği Href'i taşır
Çalışmaları soldan sağa düzenleme
Konumlandırma, zengin metnin bir ayrıştırma sorunu olmaktan çıkıp dizgi sorununa dönüştüğü yerdir. Çalışmalar bir satırı paylaşır; bu nedenle her çalışma bir öncekinin bittiği yerden başlar. Bu konumları kaydeden bir işaretleme yoktur; ölçülmeleri gerekir. Motorun dahili LayoutRichText rutini, her çalışmayı daha sonra onu boyayacak olan yazı tipi metrikleriyle ölçer, ardından çalışmanın yatay ofsetini tüm önceki çalışma genişliklerinin toplamına ayarlar. Birinci çalışma draw kutusu başlangıcından başlar, ikinci çalışma birinci çalışmanın genişliğinden, üçüncüsü ilk ikisinin birleşik genişliğinden ve böylece satır boyunca devam eder
Ölçüm yazı tipi hizalamasının bu kadar önemli olmasının nedeni budur. Düzenleme geçişi ilerleme değerlerini ölçer; ayrı bir işleme geçişi glyphleri çizer. Bu iki geçiş yazı tipi konusunda anlaşmazsa, düzenlemenin hesapladığı kutular işleyicinin boyayacağı glyphlerin altına oturmaz. HotPDF, her çalışmanın çözümlenen stilini dahili RunStyleToFontSpec yardımcısı aracılığıyla, işleyicinin kendi varsayılanları olan 10 punto Arial ile eşleşen bir yazı tipi spesifikasyonuna eşleyerek bunları senkronize tutar. Ölçülen ilerleme ve çizilen metin daha sonra uyuşur ve bir çalışmanın hesaplanmış kutusu gerçekten okuyucunun gördüğü karakterleri kapsar
// Conceptual shape of one laid-out run. The engine builds an array of these
// internally; you never construct them yourself, but the fields explain how a
// link's hit box is derived from measured geometry rather than from text.
type
TRichRunInfo = record
Dx, Dy : Double; // top-left, relative to the draw-box origin
W, H : Double; // measured run box (width from the layout pass)
Text : AnsiString; // the run's visible characters
Href : AnsiString; // URI target for an <a> run, '' otherwise
end;
Bir çıpa çalışmasından PDF Bağlantı açıklamasına
Bitmiş bir PDF'deki köprü, sayfa içeriğinin bir parçası değildir. ISO 32000-1 §12.5.6.5'te açıklanan ayrı bir nesne olan Bağlantı açıklamasıdır. Açıklamanın sayfada tıklanabilir dikdörtgeni tanımlayan bir /Rect'i ve dikdörtgen tıklandığında tetiklenen bir eylemi vardır. Harici bir bağlantı için eylem bir URI eylemidir: /S /URI ve hedef adres /URI dizesi olarak. Altındaki görünür metin olağan sayfa içeriğidir; açıklama onun üzerine yerleştirilen görünmez sıcak bölgedir
Düzleştirme yolu tam olarak bu modeli izler. Bir çalışma Href taşıdığında, HotPDF önce biçimlendirilmiş metni çizer, ardından çalışmanın kutusu üzerine bir Bağlantı açıklaması oluşturur. Bu açıklama için genel giriş noktası, /URI eylemiyle /Type /Annot /Subtype /Link nesnesini oluşturan ve açıklama sözlüğünü döndüren sayfa yöntemi AddURILink'tir. Dikdörtgeni, çalışmanın ölçülen kutusudur ve draw öğesinin yerel koordinatlarından sayfa koordinatlarına çevrilir. Sonuç, tam olarak çıpa metnine ve başka hiçbir yere yerleşen bir bağlantıdır
// The same public API the flatten path uses for each anchor run. It produces
// an ISO 32000-1 12.5.6.5 Link annotation: /Subtype /Link with a /URI action
// over the given rectangle. The optional description fills /Contents so a
// screen reader can announce the target.
var
LinkRect: TRect;
Annot: THPDFDictionaryObject;
begin
LinkRect := Rect(72, 690, 268, 706); // page-space hit box for the run
Annot := Pdf.CurrentPage.AddURILink(LinkRect,
'https://www.example.gov/appeal', 'File an appeal online');
end;
İsabet kutusunun neden ölçülen genişliklerden gelmesi gerektiği
Bağlantıyı görünür metnini sayfada arayarak ve dikdörtgeni bulunanın etrafına çizerek konumlandırmayı düşlemek cazip gelir. Bu işe yaramaz ve nedeni, düzleştirilmiş metnin nasıl depolandığına ilişkin temeldir. Biçimlendirilmiş çalışmalar gömülü alt küme yazı tipleriyle boyanır. Bir alt küme yazı tipi tuttuğu glyphleri yeniden numaralandırır; bu nedenle sayfa içerik akışı onaltılık CID kodları tutar, orijinal karakter kodlarını değil. Sayfadaki baytlar bir insanın okuduğu harfler değildir ve metin olarak aranabilir değildir. Çıpanın başlığı için yapılan bir arama hiçbir şey bulmaz; çünkü bu başlık akışta hiçbir yerde gerçek metin olarak bulunmaz
Dikdörtgen için tek güvenilir çıpa, düzenleme geçişinin zaten ürettiği geometridir. Her çalışmanın ofseti ve ölçülen genişliği, herhangi bir glyph yeniden numaralandırılmadan önce, satır akıtılırken hesaplanmıştır ve metnin fiziksel olarak nerede görüneceğini tanımlar. Bu nedenle HotPDF, bağlantı dikdörtgenini herhangi bir metin aramasından değil doğrudan çalışmanın yerleştirilmiş kutusundan alır. Ölçüm işleme yazı tipini kullandığından, kutu alt kümeleme ne olursa olsun doğrudur. Geometri kodlamadan sağ çıkar; metin sağ çıkmaz. Bu ölçülen genişlik konumlandırmasının tüm argümanıdır ve metin aramasıyla bağlantıları sonradan uyarlamaya çalışan bir düzleştiricinin kayıp veya kayan isabet bölgeleri üretmesinin nedenidir
Düzleştirmeyi kodunuzdan yönetme
Zaten bir XFA paketi içeren bir PDF için giriş noktası FlattenLoadedXFA'dır. Belgeyi yükleyin, yöntemi çağırın ve sonucu kaydedin. Editable parametresi form alanlarına ne olacağını belirler: çıktı doldurulabilir AcroForm widget'ları olarak tutmak için True, her widget'ı salt okunur olarak işaretleyerek çıktının dondurulmuş bir kayıt olmasını sağlamak için False geçirin. Biçimlendirilmiş çalışmaları ve bağlantı açıklamalarıyla zengin metin draw blokları her iki durumda da üretilir. Fonksiyon yayımladığı widget sayısını döndürür
var
Pdf: THotPDF;
Emitted, i: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.LoadFromFile('xfa_appeal_form.pdf');
// True keeps fields fillable; False freezes them read-only.
Emitted := Pdf.FlattenLoadedXFA(True);
// Anything the engine could not map is reported, not raised.
for i := 0 to Pdf.XFAFlattenWarnings.Count - 1 do
Writeln('XFA warning: ', Pdf.XFAFlattenWarnings[i]);
Pdf.SaveLoadedDocument('appeal_form_flat.pdf');
Writeln('Widgets emitted: ', Emitted);
finally
Pdf.Free;
end;
end;
Çağrıdan sonra her zaman XFAFlattenWarnings'ı okuyun. Liste her düzleştirmenin başında temizlenir ve motorun oluşturmayı reddettiği her öğe için bir satır biriktirir: desteklenmeyen bir alan türü, çözümlenemeyen bir draw görüntüsü, kullanılabilir span içermeyen bir exData bloğu. Bunların hiçbiri istisna oluşturmaz; bu nedenle boş bir uyarı listesi, her şeyin eşlendiğine dair kanıtınızdır ve boş olmayan bir liste hangi orijinalleri incelemeniz gerektiğini tam olarak söyler. Ham XFA'yı yüklü bir PDF yerine XDP baytları olarak tuttuğunuzda, kardeş yöntem ApplyXFAAsAcroForm bu baytları doğrudan alır ve aynı kod yolunu ve aynı uyarı davranışını paylaşır. Tamamlayıcı AddXFAPacket yöntemi ise tam tersini yapar ve oluşturmakta olduğunuz bir belgeye bir XFA paketi gömer
Sonucu bir okuyucuda doğrulama
Düzleştirilmiş dosyayı Acrobat'ta veya herhangi bir güncel görüntüleyicide açın ve iki şeyi kontrol edin. Birincisi, zengin metin stil bütünlüğüyle oluşturulmuştur: koyu çalışmalar koyu, renkli çalışmalar rengini taşır ve span'lar kutunun dışına taşmak veya üst üste binmek yerine satırda doğru sırada oturur. İkincisi, köprüler canlıdır. Bir çıpanın üzerine geldiğinizde durum çubuğu hedef adresi göstermelidir; tıkladığınızda URI eylemi onu açmalıdır. Her birinin gerçek bir /Link açıklaması olduğunu ve /Rect'inin çıpa metnini kucakladığını, artık form tarafından oluşturulan XFA yerine düz boyalı glyphler olan içerik üzerine oturduğunu doğrulamak için görüntüleyicinin açıklama denetçisini kullanın. Bu kombinasyon, biçimlendirilmiş statik metin artı doğru dikdörtgenler üzerindeki gerçek Bağlantı açıklamaları, düzleştirilmiş belgenin artık ihtiyaç duymadığı XFA motorlarından daha uzun ömürlü olmasını sağlayan şeydir
Alanların kendisini, bu zengin metni çevreleyen metin kutularını, onay kutularını ve seçim listelerini düzleştirme XFA formlarını AcroForm widget'larına düzleştirme konusundaki kılavuzumuzda ele alınmaktadır. Düzleştirme yolunun ürettiği bağlantıların ötesinde, Bağlantı açıklamalarını elle oluşturma ve yerleştirmenin daha geniş hikayesi için HotPDF'de PDF açıklamalarıyla çalışma konusuna bakın. Her ikisi de Delphi ve C++Builder için HotPDF Component'le birlikte gelen aynı açıklama ve form modeli üzerine kuruludur