Teknik Makale

Delphi ile PDF'te Dikey Japonca ve Çince Metin

「コード」'ü, her çağrıyı bir öncekinden bir em aşağıda yaparak tek tek karakter karakter çizerek bir sayfa aşağı indirin ve beş glifin üçü yanlış çıkar. İki köşe parantezi, sütunda yatay bir satırda oturdukları biçimde oturur; yanlara açılır. Uzun sesli harf işareti ー ise, Japon okuyucunun kısa bir dikey çizgi beklediği yerde sütunu enine kesen düz bir çizgidir. Yalnızca コ ile ド, o iki sıradan katakana, dizgicinin koyacağı gibi görünür

Bütün satırı doksan derece döndürmek parantezleri ve uzun sesli harf işaretini az çok tesadüfen düzeltir ve diğer her şeyi bozar: artık her kanji ve kana yan yatmıştır. Dikey yazma üç şeyi aynı anda yapar. Karakterler dik kalır, ilerleme sayfayı enine değil boyuna aşar ve bir avuç karakter başka çizimlere geçer. Üçünü de doğru yapmak; dikey biçimleri ve dikey metrikleri taşıyan bir yazı tipi ile bunları kullanacak şekilde kurulmuş bir PDF yazı tipi gerektirir

PDF Library for Delphi şeması: döndürülmüş yatay bir metin satırını gerçek dikey yazma moduyla karşılaştırır; dikey modda glifler dik kalır ve ilerleme sayfa boyunca aşağı akar
Dikey yazım, yatay bir satırı döndürmek yerine karakterleri dik konumda, yazı tipi başına dikey metriklerle yerleştirir; kopyalanan bir sütun yine de harf harf aynı okunur

PDF Library for Delphi'de dikey yazmayı açmak

PDF Library for Delphi dikey yazmayı bir çizim modu olarak ele alır. SetVerticalWritingMode(1) onu açar, ondan sonraki her DrawText çağrısı verdiğiniz noktadan sayfayı aşağı akar ve SetVerticalWritingMode(0) yatay metni geri getirir. Setter, çağrıdan önce geçerli olan modu döndürür ve GetVerticalWritingMode geçerli olanı okur; böylece bir yardımcı yordam modu değiştirip sonra bulduğu şeyi tam olarak geri koyabilir

İki koordinat, yatay metinden biraz farklı bir şey ifade eder. x değeri sütunun orta çizgisini adlandırır: her glif, yatay ortası o çizgide asılı kalır; böylece dar bir noktalama işareti ile tam genişlikte bir kanji aynı eksende hizalı kalır. y değeri ilk karakter hücresinin üstüdür ve sütun oradan aşağı doğru büyür. y = 0'ı sayfanın üst kenarına koyan SetOrigin(1) ile aritmetik, sayfayı kâğıt üzerinde yerleştireceğiniz şekilde okunur

var
  Lib: TPDFlib;
  H: Double;
begin
  Lib := TPDFlib.Create;
  try
    Lib.SetOrigin(1);
    Lib.AddTrueTypeFont('MS Mincho', 1);      // 1 = yüzü göm
    Lib.SetTextSize(12);
    Lib.SetVerticalWritingMode(1);            // sıradan DrawText artık aşağı doğru akar
    H := Lib.GetVerticalTextHeight('MS Mincho', 12, '第三章 保守点検');
    Lib.DrawText(480, 72, '第三章 保守点検');     // sütun y = 72'de başlar
    Lib.SetVerticalWritingMode(0);            // yatay moda geri dön
    // Origin 1, y = 0'ı üst kenara koyar; yani 72 + H sütunun ayağıdır;
    // yatay altyazı onun bir satır altında durur
    Lib.DrawText(456, 72 + H + 18, 'Chapter 3');
    Lib.SaveToFile('manual-ja.pdf');
  finally
    Lib.Free;
  end;
end;

GetVerticalTextHeight yüz adını, boyutu ve metni alır ve sütunun uzunluğunu punto olarak döndürür. Örnekte 72 + H sütunun ayağıdır ve İngilizce altyazı onun 18 punto altına, kısa Latin satırı kabaca sütunun altında dursun diye sütunun orta çizgisinin 24 punto solundan başlar. Fonksiyon, o adla bir yüz açamadığında 0 döndürür; sıfır yüksekliğe kurulan bir yerleşim altyazıyı sütunun üstüne koyar, bu yüzden değeri kullanmadan önce onu denetleyin

Parantezler dikey bir sütunda neden yan yatmıştır?

Çünkü yazı tipi bu tür her karakterin iki çizimini tutar ve yatay olan öntanımlıdır. OpenType yüzleri alternatifleri vert adlı bir GSUB özelliğinde listeler; dikey dizgi için hâlihazırda döndürülmüş gliflerle gelen yüzlerde ise vrt2. Bir metin satırını şekillendirmek yatay glifleri döndürür ve dikey özelliği ardından uygulamak bir şeye düşer: glife karşılık glif. Köşe parantezleri, parantezler ve uzun sesli harf işareti sütun boyunca uzanmaya döner; 、 ile 。 gibi küçük kanalar ve noktalama işaretleri karelerinin başka bir köşesine taşınır

PDF Library for Delphi o özelliği, çizim yaptığı yüzden okur ve her glifi, yazı tipinin adlandırdığı dikey biçimle değiştirir. Bir yüz her iki özelliği de taşıdığında vrt2 kazanır ve vert yok sayılır. Belirtim, vrt2'nin vert'in yerine geçmesini amaçlar; ikisini okumak, hangi aramanın önce yanıtladığına bağlı olarak bir karaktere iki farklı dikey glif verebilir. Ne biri ne diğeri olan bir yüz sıradan gliflerini korur. Biz o sonucu, gömülü bir ikame tablosuna tercih ederiz: tahminî bir tablo yaygın karakterleri doğru bilir ve bir karakteri farklı ele alan yüzlerin tasarımcılarının kararını sessizce ezer

Windows ile gelen kopyaların GSUB tablolarını dökerseniz sayılar epey açılır: MS Gothic'in dikey özelliği 979 glifi eşler, Yu Gothic 2.491, SimSun 72 ve Arial hiçbirini (kesin sayılar yazı tipi sürümleriyle oynar). Tesadüfen biraz kana içeren bir Latin yüzü, dik bir sütun çizer ama her parantez ve uzun sesli harf işareti yatay biçiminde kalır, çünkü yazı tipinde ikame edecek hiçbir şey yoktur

PDF Library for Delphi şeması: yazı tipinin dikey özelliğinin, sıradan karakterler değişmeden dururken dikey bir sütun boyunca uzanan parantez ve uzun ses işareti biçimlerini nasıl sağladığını gösterir; tümü GetVerticalTextHeight ile ölçülür
Yazı tipinin kendi dikey özelliği hangi gliflerin sütunda biçim değiştireceğine karar verir; GetVerticalTextHeight ise gerçekten çizilecek biçimleri ölçer

İkame ölçümü de değiştirir. Bir dikey biçim, yerine geçtiği yatay gliften farklı kendi ilerlemesine sahip olabilir; bu yüzden GetVerticalTextHeight, ilerlemeleri toplamadan önce aynı ikameyi uygular. Yatay biçimleri ölçüp dikey olanları çizerseniz sütun, ayırdığınız kutuyu parantez başına birkaç punto taşar

Bunların hiçbiri metnin kendisine dokunmaz. Sütunu bir görüntüleyiciden kopyalarsanız 「コード」 geri gelir, çünkü her dikey glif, geçtiğiniz karaktere eşlenir. Arama ve metin çıkarma kaynak dizginizi görür; döndürülmüş sunum biçimlerini asla

Dikey metrikler PDF'e nasıl girer

Dikey bir dizideki her karakter, yazı tipinin kendi dikey metriklerinin verdiği mesafe kadar ilerler. Çıktıyı bir PDF inceleicide açarsanız Identity-V kodlamalı bir Type0 yazı tipi bulursunuz; CIDFont'u, kullanılan her glif için bir W2 girişi taşır: yüzün vmtx tablosundan gelen dikey ilerleme, glifin genişliğinin yarısı sütunun orta çizgisine ofset olarak ve dikey orijin. ISO 32000-1 §9.7.4.3 o üç sayıyı tanımlar. Dikey metrikleri olmayan bir yüz için W2 dizisi yoktur ve DW2 öntanımlısı her karakteri tam olarak bir em ilerletir

Dikey orijin, üçüncü taraf yazı tiplerinin birbirinden ayrıştığı yerdir. vhea tablosunda, bariz kaynak gibi görünen ascender ve descender alanları vardır; ama descender'ın işaret kuralı yüzler arasında paylaşılmaz. Alanı Windows kopyalarından herhangi bir yazı tipi tablosu görüntüleyicisiyle okuyun: MS Gothic'te +140, Yu Gothic'te +120 çıkar; buna karşılık SimSun'da −144, MingLiU'da −500 ve değerler yazı tipi sürümleriyle değişebilir. O alandan türeyen her konum, her yüzde farklı miktarda sürüklenir. PDF Library for Delphi orijini dikey ascender'dan alır — yukarıda adı geçen CJK yüzleri bunu tutarlı bildirir — ve bir yüz makul bir şey bildirmediğinde 880 birime düşer; PDF belirtiminin kendisinin DW2'ye verdiği öntanımlı budur

Dikey glifleri elle konumlandırmak kendi tuzağını taşır. Yatay metin aralığı çoğu zaman bir TJ dizisinin içindeki sayılarla düzeltir. Dikey bir yazma modu altında ISO 32000-1 §9.4.4 o sayıları sütun boyunca uygular; yani yatay aralık için hesaplanmış bir düzeltme, her karakteri sayfada daha aşağı iter. Bu yüzden içerik akışındaki bir dikey dizi, hiç ayarlaması olmayan tek bir düz glif kodu dizesidir ve aralığın her biti W2'den gelir

Çıktıyı denetlerken sözlüklere değil mürekkebe bakın. Yazı tipinde /Identity-V bulmak, kodlamanın bildirildiğini kanıtlar; metnin gerçekte hangi yönde aktığı hakkında hiçbir şey söylemez. Sayfayı işleyip çizilen piksellerin sınırlayıcı kutusunu ölçmek söyler: yedi karakterlik bir dizi kabaca bir karakter genişliğinde ve yedi karakter yüksekliğinde çıkmalıdır

Yatay bir sayfada tek dikey dizi

DrawVerticalText tek bir diziyi dikey çizer ve yazma moduna dokunmaz. Konumu, yazı tipi adını, boyutu ve metni alır; dolayısıyla geçerli yazı tipi seçimi de el değmemiş kalır. Sırt etiketleri, mühür damgaları, bir tablonun yanında tek sütun ad: bunlar yatay bir belgenin içindeki dikey istisnalardır ve her birinin çevresinde genel bir modu açıp kapatmak, işin hak ettiğinden fazla durumdur

PDF Library for Delphi şeması: DrawVerticalText, paylaşılan bir sayfada genel yazma moduna dokunmadan sıradan yatay DrawText satırlarının yanına tek bir dik dikey dizi yerleştirir
DrawVerticalText kendi yazı tipini, boyutunu ve konumunu taşır; böylece tek bir dikey sütun çevresindeki yatay çağrılarla bir arada var olur
// Aksi halde yatay bir sayfa içindeki tek bir dikey akış
if Lib.DrawVerticalText(520, 96, 'MS Mincho', 14, '保守点検記録') = 0 then
begin
  // Yüz açılamadı ya da bu metni ayarlayamadı.
  // LogLayoutProblem sizin kendi yordamınız, kitaplığın parçası değil
  LogLayoutProblem('vertical label on page ' + IntToStr(Lib.SelectedPage));
end;
// Çevresindeki yatay metin etkilenmez
Lib.DrawText(72, 96, 'Maintenance inspection record');

İki yönü birden karıştıran bir sayfa, yüzü kaynaklarında iki kez taşır: bir kez yatay kodlamayla, bir kez Identity-V ile — aynı yazı tipi programından üretilmiş olarak. Her yön kendi metriklerini korur; böylece dikey gövde metni ile yatay sabit başlıklı bir Japon kitap sayfası ya da yatay ayrıntı satırlarının üzerinde dikey başlığı olan bir Çin sertifikası, iki yönde de doğru aralanmış çıkar

Dönüş değeri, çoğunluğu dikey olan belgelerde bile DrawVerticalText'e uzanmamızın nedenidir. Mod tabanlı çizimde, dikey ayarlanamayan bir dizi düşürülmek yerine sıradan yatay yolla çizilir ve DrawText her iki durumda da başarı bildirir. Gövde metni için daha iyi öntanımlı budur, çünkü başıboş bir yatay satır provada kolayca görünür, kayıp bir paragraf görünmez. Yönü tüm konu olan bir etiket için DrawVerticalText kullanın ve 0'ı bir yerleşim hatası sayın

Sütunları sağdan sola yerleştirmek

Sütun sırası size kalmıştır. Japonca ve geleneksel Çince dikey metin, sütun sütun sağdan sola okunur; bir sayfa sağ kenarından başlar ve her yeni sütun öncekinin soluna oturur. Hiçbir yazma modu ayarı bunu metinden çıkarsayamaz; sağdan ciltlenmiş bir kitaptaki sayfa sırası ile furigana, dipnotlar ve şekil altyazılarının yeri için de aynısı geçerlidir

Aşağıdaki yordam bir dizgiyi, sabit bir yüksekliğe sığan sütunlara böler; yolda GetVerticalTextHeight ile ölçer ve sütun başına bir buçuk em sola adımlar:

procedure DrawColumns(Lib: TPDFlib; const Face: WideString; Size: Double;
  const Text: WideString; Right, Top, BoxH: Double);
var
  Col, Trial: WideString;
  I: Integer;
  X: Double;
begin
  // Önerilen koruma, kitaplık denetimi değil: sıfır yükseklik, yüzün
  // açılamadığı anlamına gelir; aşağıdaki döngü hiçbir sütunu bölmezdi
  if Lib.GetVerticalTextHeight(Face, Size, Text) <= 0 then
    Exit;
  X := Right;                                  // ilk sütun sağ kenarda
  Col := '';
  for I := 1 to Length(Text) do                // vekil çiftleri varsaymaz
  begin
    Trial := Col + Text[I];
    if (Col <> '') and (Lib.GetVerticalTextHeight(Face, Size, Trial) > BoxH) then
    begin
      Lib.DrawVerticalText(X, Top, Face, Size, Col);
      X := X - Size * 1.5;                     // sonraki sütun solda
      Col := Text[I];
    end
    else
      Col := Trial;
  end;
  if Col <> '' then
    Lib.DrawVerticalText(X, Top, Face, Size, Col);
end;

Deneme dizgisini her karakterde yeniden ölçmek, ilerlemeleri toplamaktan yavaştır ama tam olarak çizilecek olanı ölçer; ikameler dâhil. Döngünün yapmadığı şey kinsoku kurallarını uygulamaktır. Bir sütunun tepesindeki kapanış parantezi ya da 。 ya da bir sütunun dibinde mahsur kalmış açılış parantezi, Japon okuyucuya bir dizgi hatasıdır ve düzeltmesi, çizmeden önce bir karakteri kırılımın karşısına çekmek ya da itmektir. Vekil çiftleri de aynı özeni ister: Text[I] ile indekslemek, Temel Çok Dilli Düzlem dışındaki bir karakteri ikiye böler; metniniz bir tane içerebiliyorsa kod noktası kod noktası ilerleyin

Veriden kurulan belgeler için metin arama ve sayfa öğesi numaralandırma yazısı, her sayfaya düşeni geri okumayı gösterir; bu, her sütunun kastettiğiniz karakterleri taşıdığını hızla doğrulamanın yoludur

Dikey bir belge hangi yazı tipini kullanmalı?

Kendi dikey metriklerine ve bir vert ya da vrt2 özelliğine sahip bir CJK yüzü. Olmadan dik duran karakterleri birer em ilerleyen ve hiç biçim değiştirmeyen çıktı alırsınız. Dikey metin hafifçe yanlış görünüyorsa kodu incelemeden önce yazı tipini inceleyin. Bir yüzün GSUB özellikleriyle vhea ve vmtx tablolarını listeleyen bir tablo görüntüleyicisi, yüzün işi yapıp yapamayacağını bir dakikada söyler

DrawVerticalText ile GetVerticalTextHeight, kurulu bir yüzü adıyla Windows üzerinden açar. Diğer platformlara yönelik Lazarus derlemelerinde dikey yazma SetVerticalWritingMode ile DrawText üzerinden gider; bunlar, yükleyip seçtiğiniz yazı tipinin programından çalışır, yani o yazı tipi kastettiğiniz CJK yüzü olduğu sürece aynı dikey biçimler ve metrikler geçerlidir

Gömme, her zamanki kuralları ve her zamanki maliyetleri izler. Tam bir CJK yazı tipi büyüktür, dolayısıyla her yere giden belgeler için alt kümeleme seçimlik değildir; PDF dosya boyutu iyileştirmesi ve yazı tipi alt kümeleme notları neler bekleyeceğinizi ele alır ve var olan bir PDF'e eksik yazı tiplerini gömme yazısı dikey bir belgenin yazı tipleri olmadan geldiği onarım durumunu ele alır

Dikey CJK yazma, PDF Library for Delphi'nin — Delphi, C++Builder ve Lazarus için yerel bir Pascal PDF kitaplığı — diğer metin fonksiyonlarıyla aynı çizim API'sinde durur. PDF Library for Delphi ürün sayfası, yanındaki yazı tipi ve metin özelliklerinin tam setini listeler