HotPDF, Arapça, İbranice, birleştirici işaretli ve karışık yönlü metni, THPDFHeadlessDocument.SetTextFieldValueWithFamilies üzerinden AcroForm comb alanlarına doldurur. Comb ızgarası Unicode skalerlerinde sayılır; bir ligatür ya da işaretleriyle bir harf, skalerlerinin sahiplendiği k hücresine tek küme olarak ortalanır ve bütün satır, herhangi bir hücre atanmadan önce Unicode Bidirectional Algorithm'dan geçirilir
O üç kuralın her biri, Latin bir demoda kusursuz görünüp ilk gerçek formda dağılan bir kestirmenin yerine geçer. Adı Arapça yazılmış, on kutulu comb alanı olan bir devlet başvurusu düşünün. Karakter başına mantıkla doldurursanız harfler izole biçimlerinde soldan sağa dizilir, bir lam-alef ligatürü tek kutuya sıkışırken komşusu boş kalır ve bir fatha yanlış hücrenin üstünde uçar. O kusurların her biri, yanlış birimi saymaktan ya da metni yanlış anda düzenlemekten çıkar
Comb bayrağı bir PDF yazarından gerçekte ne ister?
Comb bayrağı, yazardan alanı tam olarak MaxLen adet eşit aralıklı konuma bölmesini ve her birine bir karakter koymasını ister. ISO 32000-1 §12.7.4.3, Comb'ı Tablo 228'deki bit 25 olarak tanımlar; yani metin alanlarına özgü alan bayrakları olarak ve yalnızca Tablo 229'dan gelen MaxLen girişi mevcutken ve Multiline, Password ile FileSelect bayrakları temizken anlamlıdır. Bitin kendisi, 32 bitlik /Ff değeri içinde $1000000'dır; comb alanlarını bir kayan nokta değişkeni üzerinden geçirdikten sonra ters davranırken gördüyseniz 32 bitlik AcroForm alan bayrakları yazısı, o bite neden ilk giden bit olduğunu anlatıyor
Belirtim "character" der ve orada durur. Sabit adımlı Latin kutuları düşünülerek yazılmıştır; bir Arapça harf çifti tek glifte birleştiğinde ya da bir sesli işaretin kendi genişliği olmadığında bir karakterin ne olduğunu söylemez. HotPDF bir birim seçmek zorundadır ve yapısal kuralları seçerken katı uygular: aynı zamanda multiline olan ya da pozitif bir MaxLen taşımayan bir comb alanı bir teşhisle reddedilir ve parola alanları hiçbir biçimde comb alanı olamaz
UTF-16 birimleri, glyphler ya da grafemler yerine neden Unicode skalerleri sayılıyor?
HotPDF comb hücrelerini Unicode skalerlerinde sayar, çünkü MaxLen'i zorunlu kılmak için kullandığı birim aynıdır; ızgara ile uzunluk kontrolünün uyuşması gerekir, yoksa doğrulamayı geçen bir değer kutularına sığmaz. Cazip üç alternatifin her biri o uyumu başka bir şekilde bozar
- UTF-16 kod birimleri, Delphi'nin
Lengthişlevinin döndürdüğü şeydir; U+20BB7 gibi bir tamamlayıcı karakter iki kutu ve alan bütçesinin iki yerini yer - Glyph sayısı fonte bağlıdır: çoğu Arapça fontu lam ile alef'i tek glifte çevirir; dolayısıyla hücre sayısı, yazı tipini değiştirdiğiniz an değişirdi
- Grafem sayısı, taban harfi işaretleriyle birleştirir; bu da ızgaranın, kullanıcının yazdığı her skalere sayan bir
MaxLenkontrolüyle anlaşmazlığa düşmesi demektir
THPDFHeadlessDocument içindeki MaxLen doğrulaması, dizgeyi yalnızca UTF-16 uzunluğu sınırı aştığında gezdirir ve o zaman geçerli bir surrogate çiftini bir kez sayar, eşleşmemiş bir surrogate'i ise açıkça reddeder. Arayüzünüz çağrıdan sonra istisna yakalamak yerine önceden uyarmak istiyorsa aynı şekilde sayın
// Comb ızgarasının yaptığı gibi Unicode skalerlerini sayar:
// geçerli bir surrogate çifti bir skalerdir
function CountScalars(const S: UnicodeString): Integer;
var
I: Integer;
begin
Result := 0;
I := 1;
while I <= Length(S) do
begin
if (Ord(S[I]) >= $D800) and (Ord(S[I]) <= $DBFF) and
(I < Length(S)) and
(Ord(S[I + 1]) >= $DC00) and (Ord(S[I + 1]) <= $DFFF) then
Inc(I, 2)
else
Inc(I);
Inc(Result);
end;
end;
Birkaç değer, birimlerin ne kadar açıldığını ve neden yalnızca skaler sütununun comb alanının bütçelediğiyle eşleştiğini gösteriyor
| Değer | UTF-16 birimi | Skaler (hücre) | Tipik glyph |
|---|---|---|---|
| Lam + alef (لا) | 2 | 2 | 1 ligatür |
| Beh + fatha (بَ) | 2 | 2 | 2, işaret harfe ekli |
| U+20BB7 (𠮷) | 2 | 1 | 1 |
| Ayrıştırılmış e + U+0301 | 2 | 2 | 1 ya da 2, fonta bağlı |
Ligatürler ve birleştirici işaretler hücrelerini nasıl paylaşıyor?
k skalere yayılan şekillendirilmiş bir küme, k bitişik hücre kaplar ve tek bir birim olarak bunların ortasına yerleşir. Şekillendirme sonrası her küme, geldiği kaynak metnin tam aralığına geri eşlenir; böylece HotPDF hangi skalerleri ve dolayısıyla hangi hücreleri sahiplendiğini bilir. Yukarıdaki lam-alef ligatürü iki kutu alır ve ikisinin de ortasında durur. Shadda ve fatha taşıyan bir beh üç skalerdir; üç kutu alır, işaretler harfe ekli kalır
Ortalama, bariz uygulamanın yanlış gittiği yerdir. Her glifi kendi kutusunda ortalamak, işareti tabanından koparır; çünkü işaretin konumu, yalnızca süslediği harfe göreliyken anlam taşır. HotPDF her glifi, küme içinde şekillendirilmiş ilerlemesi ile X ve Y ofsetlerinde tutar ve kümeyi, doğal ilerlemenin, konumlanmış glif kökenlerinin ve gerçek glif mürekkebinin birleşik yatay kapsamıyla ortalar. Küme blok olarak taşınır; içindeki hiçbir şey yeniden dizilmez
Bir sonucu gözden kaçması kolaydır. U+200F RIGHT-TO-LEFT MARK, U+061C ARABIC LETTER MARK ve embedding ile isolate kontrol karakterleri gibi yönsel kontroller, glifsiz Unicode skalerleridir. MaxLen'e sayılır ve boş kalan bir hücre tutarlar. Kaynak veriniz bu işaretleri isimlere serpiştiren bir sistemden geliyorsa doldurmadan önce temizleyin; yoksa alan boşluk gösterir ve değerleri, kullanıcının beklediğinden bir karakter önce reddeder
Bidi yeniden düzenlemesi neden hücreler atanmadan önce yapılmalı?
HotPDF bütün satırı önce Unicode Bidirectional Algorithm'dan (UAX #9) geçirir ve ancak ondan sonra her skalere, görsel konumundaki hücreyi verir. Hücreleri mantıksal düzende atayıp sonucu sonra çevirmek, saf Arapça bir dizge için çalışır; satır rakam ya da bir Latin parçası içerir misiniz bozulur, çünkü o parçalar sağdan sola akan satırın içinde soldan sağa okunmayı sürdürmek zorundadır. Arapça önekli ve numaralı bir referans kodu gibi bir değer, rakamlarını yalnızca yeniden düzenleme bütün satırı birden görürse doğru sırada tutar. Karmaşık yazı sistemi metin şekillendirme genel bakışı, mantıksal ve görsel düzen sorununu daha derinden ele alıyor
Hizalama, sonra kullanılan hücrelerin bütün ızgarasını alanın içinde konumlandırır. Alanın kalıtsal /Q girişi, mevcutken kazanır; Options.Alignment yalnızca formda hiçbiri yokken uygulanır. Sağdan sola formlar için bu önemlidir: sola hizalı bir comb alanında kısa bir Arapça değer, en soldaki kutuları doldurur; bu belirtim uyarınca doğrudur ve form tasarımcısının kastettiği şey neredeyse hiçbir zaman değildir. Formun /Q değerini düzeltin ya da alanın kendi quadding'i yokken htaRight kurun. Widget dönüşü /MK içindeki /R girişinden gelir ve 90 ya da 270 derecede mantıksal metin görünüm alanı genişlik ile yüksekliği değiştirirken hücre mantığı aynı kalır
Delphi'den karışık fontlu bir comb alanı doldurmak
Karışık fontlu comb metni, verilen her font için tek hücre ızgarası, tek font boyutu ve tek taban çizgisi kullanır. FallbackFontFamilies değeri True iken HotPDF her tam grafem için, verilen ailelerden yapılandırılmış sıralarında bir font seçer; böylece Arapça bir yüz harfleri taşıyabilirken Latin bir yüz gömülü ASCII'yi taşıyabilir. Her font parçası bütün satır bağlamıyla şekillendirilir, bir işaret fontlar arasında asla tabanından ayrılmaz ve bir font sınırının ötesinde ligatür icat edilmez. Her parçayı kendi yerel ızgarasıyla dizmek ya da kendi sınırlama kutusuna ölçeklemek daha basit olurdu; ama font düşüşü satır ortasında font değiştirdiği an hem hücre konumlarını hem döndürülmüş alanları bozardı
uses
System.SysUtils, System.IOUtils,
HPDFHeadlessDocument, HPDFHeadlessAppearance;
procedure FillArabicComb(const SourceFile, TargetFile, Value: string);
var
Doc: THPDFHeadlessDocument;
Field: THPDFHeadlessFormField;
Families: THPDFHeadlessRichTextFontFamilies;
Options: THPDFHeadlessTextAppearanceOptions;
FieldIndex: Integer;
begin
Doc := THPDFHeadlessDocument.Create;
try
Doc.LoadFromFile(SourceFile);
FieldIndex := Doc.FindFormField('applicant.name_ar');
if FieldIndex < 0 then
raise Exception.Create('Field not found');
Field := Doc.GetFormField(FieldIndex);
if (Field.Flags and $1000000) = 0 then // bit 25: Comb
raise Exception.Create('Not a comb field');
SetLength(Families, 2); // birden on altıya aile
Families[0].FamilyName := 'Noto Naskh Arabic';
Families[0].Fonts[hrfsRegular] :=
TFile.ReadAllBytes('NotoNaskhArabic-Regular.ttf');
Families[1].FamilyName := 'Noto Sans';
Families[1].Fonts[hrfsRegular] :=
TFile.ReadAllBytes('NotoSans-Regular.ttf');
Options := THPDFHeadlessTextAppearanceOptions.Default;
Options.ShapeComplexText := True; // zaten varsayılan
Options.FallbackFontFamilies := True; // varsayılan False
Options.FontSize := 0; // otomatik sığdırma, 12 ile sınırlı
Options.Alignment := htaRight; // yalnızca /Q yokken kullanılır
Doc.SetTextFieldValueWithFamilies(FieldIndex, Value, Families, Options);
Doc.SaveToFile(TargetFile); // SourceFile'dan farklı olmalı
finally
Doc.Free;
end;
end;
Örneğin ne kurmadığına dikkat edin. Belge doldurma sırasında Width, Height, Rotation ve CombCells, her widget dikdörtgeninden, /MK girişinden ve alanın MaxLen değerinden türetilir; o üyelere koyduğunuz değerlerin üzerine yazılır. Sıfır bir FontSize otomatik boyutlama ister; otomatik boyutlama her kümenin kapsamını, k hücresinin genişliğiyle katılan tüm fontların paylaşılan metrik ve mürekkep yüksekliğiyle karşılaştırır; sabit bir boyut basitçe widget içine kırpar. CharacterSpacing ve WordSpacing comb konumlarını hiçbir zaman kaydırmaz; bir kümenin nereye düşeceğine yalnızca ızgara karar verir. HotPDF HarfBuzz ve FriBidi çalışma zamanlarını yalnızca bir değer gerçekten şekillendirme istediğinde yükler ve şekillendirme gerektirmeyen değerler, mevcut doğrudan comb dizilimini değişmeden korur. Genel yüklenmiş PDF doldurma iş akışı, izinler ve kaydetme dahil, bkz. yüklenmiş bir PDF'te form alan değerlerini ayarlama
Şekillendirilmiş bir comb görünümü neyi garanti etmez?
Şekillendirilmiş bir comb görünümü, doğru hücre atamasını, bozulmamış kümeleri ve korunmuş mantıksal değeri garanti eder; her araçta kusursuz bitişik el yazısı bağlantılarını ya da kusursuz metin çıkarımını garanti etmez. İki sınır da comb alanının ne olduğundan çıkar ve bir müşteriye bir şey vaat etmeden önce bilmenizde fayda var
İlki, hücreler arası bitişik el yazısı bağlantılarıdır. Arapça harfler yine de bütün satır bağlamıyla şekillendirilir; her biri doğru başlangıç, orta ya da son biçimini alır, ama sabit hücre adımı ayrı kümeler arasında boşluk bırakır ve bağlayan darbeler, akan metinde birleştikleri gibi birleşmez. Birleştiren bir yazı sistemini kutulara çizmenin doğal sonucudur; ne kadar ortalarsa ortalasın gizlenmez
İkincisi metin çıkarımıdır. Alanın /V değeri sade mantıksal değeri tutar ve görünümün ana Form XObject'i girdinin tamamını taşıyan tek bir /ActualText parçası barındırır (ISO 32000-1 §14.9.4); çocuk Formlar hiçbirini taşımaz. ActualText'e saygı duyan çıkarıcılar orijinal dizgeyi geri kazanır. Yok sayan çıkarıcılar metni glif konumlarından yeniden kurar ve farklı bir düzen ya da kopyalanmış küme metni döndürebilir; çünkü çok glifli bir kümenin glif başına tek bariz Unicode değeri yoktur. Aşağı akış bir sistemin değere ihtiyacı varsa alanı okuyun, sayfa metnini değil
Kalan sınırlar mekaniktir. Comb metni sekmeler içermeyen tek satır olmak zorundadır ve hücrelerden daha çok skalere sahip bir değer kırpılmak yerine başarısız olur. Başarısızlıklar işlemseldir: eksik bir glif, geçersiz bir font, bütçe aşımı ya da bir iptal, önceki değeri ve görünümleri olduğu gibi bırakır; reddedilen bir doldurma asla yarısı çizilmiş bir alan arkasında bırakmaz
try
Doc.SetTextFieldValueWithFamilies(FieldIndex, Value, Families, Options);
except
on E: EHPDFHeadlessDocumentError do
if E.Code = hdLimitExceeded then
ShowFieldError('The value has more characters than the field allows')
else
raise;
on E: EHPDFHeadlessAppearanceError do
if E.Failure = haMissingGlyph then
ShowFieldError('None of the supplied fonts covers this text')
else
raise;
end;
// İki hatada da alan önceki değerini ve görünümünü korur
Şekillendirilmiş comb desteği bir form hattında nereye oturuyor?
Şekillendirilmiş comb desteği en çok, çoktan var olan formlar için önem taşır: kutulu alanlarla tasarlanmış ve şimdi Arapça, İbranice, Farsça ya da Urduca doldurulan vergi beyannameleri, vize başvuruları, banka açılış paketleri ve kimlik kayıtları. Skalerde sayın, orijinal değeri /V içinde tutun, her fontu tek ızgaraya tabi tutun ve sağdan sola harfleri, rakamları ve bir birleştirici işareti karıştıran bir değerle test edin; o tek dizge bu yazıdaki her kuralı çalıştırır. Burada anlatılan headless belge API'si, comb şekillendirme ve font düşüşü, HotPDF Delphi PDF bileşeninin bir parçasıdır