PDFium bileşeninde metin şekillendirme kurulabilir tek bir nesneden geçer. ConfigureTextShaper, her şekillendirme giriş noktasının üzerinden geçtiği şekillendiriciyi kurar ve orada olanı değiştirip serbest bırakır; ActiveTextShaper kurulu olanı döndürür ve ilk kullanımda platform varsayılanını oluşturur; ActiveTextShaperName hangi arka ucun canlı olduğunu bildirir; ClearTextShaper kurulumu düşürür ve varsayılanın yeniden oluşturulmasına izin verir. Windows'ta varsayılan TPdfUniscribeTextShaper'dır. Free Pascal altında TPdfHarfBuzzTextShaper vardır; libharfbuzz'ı çalışma zamanında bağlar, böylece eksik bir kitaplık bir yükleme başarısızlığı değil bildirilen bir durumdur
Tek arayüz, işi tamamen farklı bölen iki arka uç. O asimetrinin anlaşılması, taşınabilir yolun doğru şekillendirilmiş ama yanlış konumlanmış metin üretmesini engelleyen şeydir
Windows arka ucu neden tek sınıf, taşınabilir olan neden üç parça?
Çünkü Uniscribe, tekmiş gibi görünen dört API'dir. ScriptItemize bir diziyi yazı sistemine göre parçalar ve çift yönlü düzeyleri çözer; ScriptShape karakterleri gliflere eşler; ScriptPlace ilerlemeleri ve ofsetleri hesaplar; ScriptLayout sonuçlanan çalıştırmaları görsel sıraya koyar. Üzerine kurulan bir arka ucun ekleyecek hiçbir şeyi kalmaz; Windows şekillendiricisinin tek yöntemli tek bir sınıf olmasının nedeni budur
HarfBuzz ortadaki ikisini kapsar. Çağıranın yönünü ve yazı sistemini önceden belirlediği bir çalıştırmayı şekillendirir ve yerleştirir; bir paragrafın çalıştırmalara nasıl bölüneceği ya da o çalıştırmaların hangi sırada görüneceği hakkında fikri yoktur. Dolayısıyla taşınabilir arka uç gerisini sağlar: çift yönlü algoritma gömme düzeylerini çözer, HarfBuzz Unicode işlevleri metni yazı sistemine göre parçalar ve çalıştırmalar, UAX #9 L2 kuralının ürettiği görsel sıraya dizilir. Çift yönlü yarısı, kendi birimi olmaya değer kadar büyüktür; UAX #9 gömme düzeyleri makalesinde betimlenir
Şekillendirici fontları çözmez ve bu bilinçlidir
Uniscribe, font ikilisini bir GDI aygıt bağlamından okur. Bunun taşınabilir bir eşdeğeri yoktur ve bir şekillendirme biriminin içinde bir tane icat etmek, her uygulama adına fontların fontconfig'den mi, CoreText'ten mi, bir uygulama font klasöründen mi yoksa bir veritabanından mı geleceğine karar vermek demek olurdu. Bu yüzden HarfBuzz arka ucu bir çözümleyici alır: bir font adını TrueType ya da OpenType baytlarına eşleyen bir geri çağrı. False döndürmek, şekillendirme isteğini Windows'ta okunamayan bir GDI fontunun başarısız kıldığı şekilde başarısız kılar
uses
FPdfTextShaping
{$IFDEF FPC}
, FPdfTextShapingHb
{$ENDIF}
;
function TFontCatalogue.Resolve(const FontName: WideString;
out FontData: TBytes): Boolean;
var
Path: string;
begin
// Politikanız: fontconfig, CoreText, bir uygulama font klasörü,
// bir veritabanı
Result := FLookup.TryGetValue(LowerCase(FontName), Path);
if Result then
FontData := TFile.ReadAllBytes(Path);
end;
procedure InstallShaper(Catalogue: TFontCatalogue);
begin
{$IFDEF FPC}
// Sahiplik birime geçer; başlangıçta, herhangi bir şey metni
// şekillendirmeden önce bir kez çağırın
ConfigureTextShaper(TPdfHarfBuzzTextShaper.Create(Catalogue.Resolve));
{$ENDIF}
// Delphi'de platform varsayılanı (Uniscribe) talep üzerine
// oluşturulur; dolayısıyla hiçbir kuruluma gerek yoktur
LogInfo('shaping backend: ' + ActiveTextShaperName);
end;
Font keşfini şekillendiricinin dışında tutmanın sunucularda ortaya çıkan ikinci bir yararı vardır: aynı işlem, makinede kurulu olanla hiçbir ilgisi olmayan gömülü bir font kümesiyle şekillendirebilir; çıktının makineler arasında bayt bakımından yeniden üretilebilir olması gerektiğinde isteyeceğiniz budur. Bileşen ayrıca, kurulu fontları gerçekten istediğiniz durumlar için bir ana sistem fontu sağlayıcısı açar; sistem fontu sağlayıcısı makalesinde kapsanır
Sonuç kaydı arka uçtan bağımsızdır ve bunun nedeni kümelerdir
İki arka uç da aynı TPdfShapedText kaydını doldurur: kaynak metin, font adı, boyut, font baytları, bir çalıştırma dizisi, toplam genişlik, glif sayısı ve mantıksal karakter sayısı. Her TPdfShapedRun, kaynak metindeki aralığını, görsel X konumunu, genişliğini, çift yönlü düzeyini ve sağdan sola bayrağını, artı gliflerini taşır. Her TPdfShapedGlyph, bir glif tanımlayıcısı, bir ilerleme, X ve Y ofsetleri ve ait olduğu kümeyi kaynak metinde bir başlangıç ile bir uzunluk olarak taşır
O küme alanları, kaydı yalnızca bilgilendirici olmaktan çıkarıp kullanılabilir kılan şeydir. Şekillendirme bire bir eşleme değildir: bir Devanagari hecesi dört karakterden tek bir glife dönüşür, bir Arapça ligatürü ikisini birleştirir ve tek bir karakter birkaç işaret üretebilir. Küme aralıkları olmadan bir şapka işareti koyamazsınız, bir tıklamaya çarpma testi yapamazsınız ya da bir seçimi vurgulayamazsınız; çünkü bir glifin hangi karakterlere ait olduğunu söyleyemezsiniz. Onlarla birlikte aritmetik yereldir ve aynı kod her iki arka uçta da çalışır
var
Shaped: TPdfShapedText;
R, G: Integer;
begin
if ShapePdfText(Line, 'Noto Sans Arabic', 14, ptdAuto, Shaped) then
for R := 0 to High(Shaped.Runs) do
begin
// Çalıştırmalar, VisualX doldurulmuş olarak zaten görsel sırada gelir
X := Shaped.Runs[R].VisualX;
for G := 0 to High(Shaped.Runs[R].Glyphs) do
begin
EmitGlyph(Shaped.Runs[R].Glyphs[G].GlyphID,
X + Shaped.Runs[R].Glyphs[G].OffsetX,
Shaped.Runs[R].Glyphs[G].OffsetY);
X := X + Shaped.Runs[R].Glyphs[G].Advance;
end;
end;
end;
Bütçeler seçenek kaydına aittir
TPdfTextShapingOptions, bir yön artı üç sınır taşır: en fazla karakter, en fazla glif ve en fazla çalıştırma; makul değerleri dolduran bir Default sınıf işleviyle. Sınırlar bozuk girdi paranoyası değildir; aritmetiktirler. Şekillendirme büyütür: agresif bağlamsal ikamesi olan bir font, girdi karakterlerinden daha çok glif yayabilir ve her birkaç karakterde yazı sistemi değiştiren bir paragraf her değişimde bir çalıştırma üretir. İkisini en üst düzeye çıkarmak için kurgulanmış bir belge, mütevazı bir diziyi büyük bir ayırmaya çevirir ve güvenilmeyen PDF'lerden metin şekillendiren bir hizmet, makinenin dayattığı bir sınır değil kendi seçtiği bir sınıra ihtiyaç duyar
Yönü otomatikte bırakmak yerine açıkça ayarlamak, zaten biliyorsanız yapmaya değer. Otomatik, paragraf yönü kurallarını ilk güçlü karakterden tahmin etmek için uygular; bu, serbest metin için doğrudur ve yönü, içine yazılan değerin değil alanın özelliği olan bir form alanı için yanlıştır
Derleme bağımlılığı değil, çalışma zamanı bağlaması
HarfBuzz arka ucu kitaplığı dinamik yükler. Bu, gerçek sonuçları olan bir dağıtım kararıdır: tek bir ikili, HarfBuzz'lı bir makinede de ondan yoksun makinede de çalışır ve ikinci durumda başlamayı başarısız kılmak yerine azaltılmış yetenek bildirir. Diğer geliştiricilere gönderilen bir kitaplık için çalışabilir tek düzen budur; çünkü bir PDF bileşeninin her tüketicisinden, ihtiyaç duymayabilecekleri bir şekillendirme kitaplığını edinmesini ve sürüm eşlemesini isteyemezsiniz
Çağıranlar için karşılık gelen kural denetlemektir. ActiveTextShaper, platformun varsayılanı olmadığında ve hiçbiri yapılandırılmamışken nil döndürür ve şekillendirme giriş noktası bunu bir şekillendirme başarısızlığı değil kullanılamaz şekillendirici olarak bildirir. Bunlar farklı sorunlardır ve farklı mesajları hak eder: biri bir dağıtım boşluğu, diğeri bir font ya da metin sorunudur
Bir kez kurun, herhangi bir şey şekillendirmeden önce
Kurulum önceki şekillendiriciyi değiştirir ve serbest bırakır; dolayısıyla onu tekrar tekrar çağırmak güvenlidir ama anlamsızdır ve başka bir iş parçacığı şekillendirirken çağırmak hiç güvenli değildir. Başlangıç sırasında yapın. Daha sonra platform varsayılanına geri düşmeniz gerekirse nil geçirin; bir testin sonunda test ikamesini geri almanın yolu da budur
Bir arka uç kurulduktan sonra ölçüm ile sarma her iki platformda da aynı davranır; çünkü platformu doğrudan çağırmak yerine çalıştırma ve glif metriklerini tüketirler. Sarma modeli metin ölçümü ve sözcük sarma makalesinde betimlenir. Bileşen için desteklenen platformlar ve araç zincirleri PDFium Delphi component ürün sayfasında listelenir