Arapça يوضح ملف PDF هذا cümlesini sade TextOut'a gönderin ve geri gelen sayfa aynı anda iki şekilde yanlıştır. Sözcükler sağdan sola değil soldan sağa akar ve harfler bağlı sözcüklere birleşmek yerine izole biçimlerinde ayrı ayrı durur. Hiçbir şey hata vermez. Delphi derlenir, dosya açılır ve Arapça okuyan bir gözden geçiren çıktının kullanılamaz olduğunu söyler. Çözüm bir kütüphane değişimi değil, tek bir çağrıdır: HotPDF, sağdan sola metni, sade TextOut'un ele almayacağı yeniden sıralamayı yöneten ayrı bir metot olan RtLTextOut'tan yönlendirir. Bu sayfa, o metot için çalışan referanstır: imza ve parametreleri, betiği seçen charset argümanı, belge düzeyindeki yan etki, önce gelmesi gereken yazı tipi kurulumu ve gerçekten desteğe ulaşan başarısızlıklar, her biri çözümüyle
İmza ve parametreler
procedure RtLTextOut(X, Y: Single; angle: Extended;
Text: WideString); overload;
procedure RtLTextOut(X, Y: Single; angle: Extended;
Text: PWORD; TextLength: Integer); overload;
X ve Y, satırı sayfanın kendi koordinat sisteminde, sol alt köşeden Y yukarı doğru büyüyecek şekilde ölçülen, her TextOut çağrısının kullandığı aynı başlangıç noktasında sabitler; RtLTextOut, sayfanın nereden ölçüldüğünü değil, glif sırasını değiştirir. angle, taban çizgisini tam olarak TextOut'ta olduğu gibi döndürür, bu yüzden 0 yatay bir satır çizer. Text, mantıksal sıradaki dizedir, yani yazacağınız sıradadır ve ikinci aşırı yükleme (overload), aynı UTF-16 verisini açık bir kod birimi sayısıyla ham bir PWORD tamponu olarak alır ki bu, metin bir Delphi dizesinden değil bir API'den geldiğinde kullanılacak biçimdir. Bu türler için aşırı yükleme çözümlemesinden önceki daha eski Delphi sürümlerinde, dize biçimi aynı parametre listesiyle RtLTextOutStr adı altında açığa çıkarılır
İki çıktı çağrısı arasındaki iş bölümü katıdır. TextOut, kod noktalarını geçtiğiniz sırada çizer ki bu Latin, Kiril ve CJK için doğru, Arapça ve İbranice için yanlıştır. RtLTextOut, önce her satırı görsel sağdan sola sıraya yeniden dizer, sonra çizer; gömülü Latin sözcükleri ve rakamları satırın içinde soldan sağa okunacak şekilde tutar. HotPDF, yönü karakterlerden tahmin etmek yerine iki metodu bilinçli olarak ayrı tutar, bu yüzden hangisini çağıracağınızın seçimi, hangi betik davranışını elde edeceğinizin seçimidir; sağdan sola diziler için RtLTextOut'u, diğer her şey için TextOut'u kullanın ve asla birini diğerinden yönlendirmeyin. Yeniden sıralamanın neden var olduğu, Unicode Çift Yönlü Algoritmasının ve Arapça bağlamsal birleşmenin gerçekte ne yaptığı ve HotPDF'in şekillendirmesinin nerede durduğu, HotPDF ile Arapça ve RTL metin şekillendirme üzerine tamamlayıcı yazının konusudur; aşağıdaki her şey pratik kurulumdur

Charset argümanı betiği belirler
RtLTextOut'a Arapça mı yoksa İbranice mi yerleştirdiğini söyleyen şey metot değil, yazı tipidir. SetFont, dördüncü argümanı olarak bir Windows charset alır ve o değer, betik kurallarını sağdan sola çağrıya taşır: 178 Arapçayı, 177 İbraniceyi seçer. Charset'i ayarlayın, sonra çizin ve aşağıdaki iki satır herhangi bir ek yapılandırma olmadan doğru okuma sırasında çıkar
// Arabic: charset 178 tells RtLTextOut to apply Arabic rules
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 700, 0, 'يوضح ملف PDF هذا');
// Hebrew: charset 177 switches the rules to Hebrew
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 177);
Pdf.CurrentPage.RtLTextOut(400, 660, 0, 'קובץ PDF זה');
Gözden kaçırması kolay bir sıralama ayrıntısı: SetFont önce gelmeli ve her AddPage'den sonra tekrarlanmalıdır, çünkü charset dâhil geçerli yazı tipi, bir sayfa geçişinden sağ çıkmaz. Tekrarı unutun ve ikinci sayfa etkin olan yazı tipine geri döner ki bu Arapça için genellikle boş kutular anlamına gelir
Zaten tersine çevirdiğiniz metni tersine çevirmez
Burada en çok hata ayıklama zamanını yutan tek hata, RtLTextOut'a elle önceden çevirdiğiniz bir dize beslemektir. İnsanlar bu metoda, sade TextOut ile ilk denemeleri ters çıktıktan sonra ulaşır ve yaygın bir geçici çözüm, çizmeden önce karakterleri kodda tersine çevirmektir. RtLTextOut kendi başına dahili olarak tersine çevirir, bu yüzden önceden tersine çevrilmiş bir dize ikinci kez tersine çevrilir ve tam olarak başladığı yere geri döner. Metni mantıksal sırada, yazacağınız ve yüksek sesle okuyacağınız sırada geçin ve yeniden sıralamayı çağrının yapmasına izin verin
Tuzak sade bir ters çevirmeden daha sinsidir, çünkü iki kez tersine çevrilmiş bir dize, tamamı Arapça bir test ifadesi için doğru görünebilir ve sonra bir satır Latin bir sözcük veya bir sayı taşıdığı anda bozulur. Sağdan sola bir satırın içinde o gömülü dizilerin soldan sağa okunması gerekir ve elle ters çevirme, saf Arapça durum bunu tesadüfen atlatırken bu yuvalamayı mahveder. Böylece hata, ilk duman testinizden geçer ve daha sonra içinde bir hesap numarası olan gerçek bir faturada ortaya çıkar. RtLTextOut'a geçtiğiniz an her elle ters çevirmeyi kaldırın
Bilmeye değer Direction yan etkisi
RtLTextOut'u çağırmak, çizdiğiniz satırdan fazlasını değiştirir. Ayrıca belgenin okuma-yönü tercihini sağdan sola çevirir ki bu, aksi takdirde Direction özelliği aracılığıyla kendiniz ayarlayacağınız aynı şeydir. O ayarlayıcı, belgenin ViewerPreferences'ına vpDirection ekler ki bu, bir görüntüleyiciye iki-yukarı yayılmaları nasıl düzenleyeceğini ve karşılıklı sayfa düzeninin hangi taraftan başlayacağını söyler. Belgenin tamamı Arapça veya İbranice olduğunda tam olarak istediğiniz budur ve bunu bedavaya elde edersiniz
Bunun bilinmeye değer olmasının nedeni tam olarak tek bir sayfada görünmez olmasıdır. Belge çoğunlukla soldan sağaysa ve tek bir sağdan sola blok içeriyorsa, ilk RtLTextOut çağrısı yine de tüm dosyanın tercihini yatıracaktır ve tek sayfalık kanıtınızdaki hiçbir şey bunu göstermez. Belirti, biri dupleks bir kitapçık yazdırdığında ve yayılmalar aynalanmış çıktığında haftalar sonra ortaya çıkar. İstediğiniz bu değilse, sağdan sola diziden sonra Direction'ı açıkça geri ayarlayın:
// RtLTextOut already set the document direction to RightToLeft;
// restore left-to-right if the document is predominantly LTR
Pdf.Direction := LeftToRight;
Gerçekten sağdan sola okunan bir belge için, ona dokunmayın. Amaç, çağrının belge genelinde bir etkisi olduğunu bilmektir, böylece kitapçık sürprizi asla gerçekleşmez
Kurulu olmasını umduğunuz değil, gönderdiğiniz yazı tipini kaydedin
Yazı tipinin çizecek glifi yoksa, yeniden sıralamanın hiçbiri önemli değildir. Klasik başarısızlık, Arial Unicode MS'in var olduğu geliştiricinin makinesinde kusursuzca işlenen ve Windows'un sessizce hiç Arapça kapsaması olmayan bir yazı tipiyle değiştirdiği bir müşterinin sunucusunda boş kutular halinde çıkan bir rapordur. Çözüm, kurulu sistem yazı tiplerine güvenmeyi bırakıp uygulamayla birlikte gönderdiğiniz bir tanesini kaydetmektir
// Ship a known Arabic font and register it before drawing
Pdf.RegisterUnicodeTTF('C:\Fonts\NotoSansArabic.ttf');
Pdf.CurrentPage.SetFont('NotoSansArabic', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 700, 0, 'يوضح ملف PDF هذا');
Kayıtla birlikte iki sınır gelir. RegisterUnicodeTTF aracılığıyla getirilen bir yazı tipi gömülür ve HotPDF'in gömülü Unicode işleyişi, belgenin PDF 1.5 veya sonrası olmasına ihtiyaç duyar; bu yalnızca aşağı akıştaki bir şey PDF 1.4'te ısrar ederse ısırır, ama ısırdığında başarısızlık sessizdir. Diğeri teknik değil hukukidir: TrueType dosyaları gömme-izni bitleri taşır ve ekranda gayet iyi görünen bir yazı yüzü, onu müşteri belgelerinin içinde göndermeyi yasaklayan bir şekilde lisanslanmış olabilir. Bir şikayetten sonra değil, gömmeden önce lisansı doğrulayın
Eksiksiz bir konsol örneği
Parçaları bir araya getirerek, işte bir Arapça satır, bir İbranice satır ve bir Latin ürün adı taşıyan karışık bir satırla tek bir sayfa yazan bağımsız bir program. Her blok kendi charset'ini ayarlar, sonra mantıksal sırada çizer
program RtLTextOutDemo;
{$APPTYPE CONSOLE}
uses
HPDFDoc; // HotPDF main unit
var
Pdf: THotPDF;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.FileName := 'RtLTextOut.pdf';
Pdf.BeginDoc;
// A Latin heading goes through the ordinary TextOut path
Pdf.CurrentPage.SetFont('Arial', [fsBold], 16);
Pdf.CurrentPage.TextOut(40, 780, 0, 'Right-to-left text with HotPDF');
// Arabic: charset 178, logical order, RtLTextOut does the reordering
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 720, 0,
'يوضح ملف PDF هذا كيفية التعامل مع النص العربي.');
// Hebrew: charset 177
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 177);
Pdf.CurrentPage.RtLTextOut(400, 680, 0,
'קובץ PDF זה מדגים טקסט עברי הזורם מימין לשמאל.');
// Mixed line: the embedded Latin word still reads left to right
Pdf.CurrentPage.SetFont('Arial Unicode MS', [], 12, 178);
Pdf.CurrentPage.RtLTextOut(400, 640, 0,
'مرحبا بالعالم! تم إنشاؤه بواسطة HotPDF');
Pdf.EndDoc;
Writeln('Wrote RtLTextOut.pdf');
finally
Pdf.Free;
end;
end.
Çalıştırın ve sonucu açın. Arapça ve İbranice satırlar sağdan sola okunur, betiğin birleştirdiği yerlerde harfler birleşir ve son satırda HotPDF belirteci Arapça dizinin içinde soldan sağa oturur. O yuvalama, ilk kez gözden geçirenler sıklıkla onu bir hata olarak bildirse de, bir hata değil doğru çift yönlü sonuçtur; yukarıda bağlanan şekillendirme yazısı, Unicode kurallarının bunu neden gerektirdiğini ve raporun asla açılmaması için kabul kriterlerinizi nasıl ifade edeceğinizi açıklar
Yaygın hatalar ve çözümleri
Aşağıdaki her başarısızlık gerçek bir destek başlığında ortaya çıkmıştır ve her biri yukarıdaki bölümlerden birine dayanır
- Çıktı ters okunuyor veya karışık satırlarda bozuluyor — dize çağrıdan önce elle tersine çevrilmişti, genellikle bir
TextOutdenemesinden kalan bir geçici çözüm. Her elle ters çevirmeyi silin ve mantıksal sırayı geçin;RtLTextOutdahili olarak tersine çevirir - Harfler izole biçimlerde bağlantısız yazdırılıyor — metin sade
TextOut'tan geçti veyaSetFontsağdan sola bir charset olmadan çağrıldı.RtLTextOutile çizin ve dördüncüSetFontargümanı olarak Arapça için 178, İbranice için 177 geçin - Müşterinin makinesinde boş kutular — Windows, Arapça veya İbranice kapsaması olmayan bir yazı tipiyle değiştirdi. Kurulu yazı tiplerini adlandırmayı bırakın;
RegisterUnicodeTTFile gönderdiğiniz bir yazı yüzünü kaydedin veSetFont'u o adla çağırın - İkinci sayfa yanlış yazı tipinde işleniyor — geçerli yazı tipi
AddPage'den sağ çıkmaz. Her sayfa geçişinden sonra charset dâhilSetFontçağrısını tekrarlayın - Çoğunlukla LTR bir belgede dupleks yayılmalar aynalanmış yazdırılıyor — ilk
RtLTextOutçağrısı bir yan etki olarak belgeninDirection'ını çevirdi. Sağdan sola diziden sonraPdf.Direction := LeftToRightayarlayın - Gömülü Unicode metni aşağı akışta sessizce bozuluyor — hattaki bir şey PDF 1.4'ü zorluyor ve HotPDF'in gömülü Unicode işleyişi 1.5 veya sonrasına ihtiyaç duyuyor. Belge sürümünü yükseltin veya aşağı akış kısıtlamasını kaldırın
Format gönderilmeden önce, göz kararından öteye doğrulayın: metni görüntüleyiciden geri kopyalayın, belge içi aramayı çalıştırın, dosyayı geliştirme yazı tipleriniz olmayan bir makinede açın ve gerçek bir belgeyi anadili konuşan bir okuyucunun önüne koyun. Tam doğrulama denetim listesi, betik başına kapsama haritası ve oluşturmaya değer test-dizesi külliyatı, HotPDF ile Arapça ve RTL metin şekillendirme üzerine tamamlayıcı yazıda yer alır
Burada gösterilen RtLTextOut, SetFont ve RegisterUnicodeTTF çağrıları, Delphi ve C++Builder için HotPDF Bileşeninin bir parçasıdır