Teknik Makale

PDFlibPas: Delphi ile Heceleme ve Dengeli Metin Sütunları

PDFlibPas, saklanan bir metin parçasını DrawTextFlowColumns ile bir ile altmış dört eşit genişlikte sütuna akıtır ve SetTextFlowLanguage ile SetTextFlowHyphenation'ı çağırdığınızda satırlarını sınırlı, dil farkında hecelemeyle böler. Dokuz dil desteklenir ve dil, her akış için ayrı ayrı ayarlanmak yerine belge Catalog'undaki /Lang değerinden devralınabilir

Her iki özellik de aynı nedenle var: dar bir sütun, saf satır bölmenin dizgi gibi görünmeyi bırakıp bir hata raporu gibi görünmeye başladığı yerdir

İki yana yaslı metin dar sütunlarda neden dağılır?

Çünkü iki yana yaslama, artan boşluğu bir satırın kelime aralarına dağıtır ve ne kadar boşluk kaldığı neyin sığdığına bağlıdır. Geniş bir ölçüde artan boşluk küçüktür ve göz onu hiç fark etmez. Genişliği yarıya indirin ve sığmayan tek bir uzun kelime bir sonraki satıra kayar, öncekiler ise tüm o boşluğu emmek zorunda kalır. Art arda gelen üç böyle satır, tipografların nehir dediği dikey beyaz kanallar üretir; okuyucular bunu, nedenini bilmeden takip etmesi zor bir metin olarak deneyimler

Heceleme, sonucu değil nedeni düzelterek kelimenin içinde bir bölmeye izin verir. Almanca ve Hollandaca bileşik sözcükler bunu tartışmasız kılar: 60 milimetrelik bir sütunda 24 karakterlik bir ismin bölme noktası olmadan iyi bir sonucu yoktur. İngilizce bu eksikliğe daha iyi katlanır; İngilizce öncelikli ürünlerin bir Alman müşteri onu ilk çalıştırdığında çöken düzen kodunu sıkça göndermesinin nedeni de budur

Hangi diller ve dil nereden geliyor?

Heceleme İngilizce, Almanca, Hollandaca, Fransızca, İspanyolca, İtalyanca, Portekizce, Rusça ve Türkçeyi kapsar. Bunu her akış için SetTextFlowLanguage ile açıkça ayarlayın ya da etiketlenmiş ve erişilebilir bir belgenin zaten taşıdığı değer olan belge Catalog'undaki /Lang girdisinden devralınmasına izin verin

Bu devralma, geçersiz kılmak yerine kullanmaya değer. Dilini Catalog'da bildiren bir belge, ekran okuyuculara, arama dizinleyicilerine ve hecelemeye aynı gerçeği tek bir yerden söylüyor demektir ve bir gerçeğin yaşaması gereken yer de tek bir yerdir. Erişilebilir PDF'ler için otomatik etiketleme'de anlatıldığı gibi zaten etiketlenmiş çıktı üretiyorsanız, dil girdisi zaten ayarlıdır ve akış onu basitçe izleyebilir

var
  Lib: TPDFlib;
  Flow, Drawn: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.SetOrigin(1);
    Lib.AddTrueTypeFont('Georgia', 1);
    Lib.SetTextSize(10.5);

    Flow := Lib.NewTextFlow(ArticleBody);
    try
      Lib.SetTextFlowLanguage(Flow, 'de');
      // Etkinleştir, bölmeden önce en az 3 karakter, sonra 3 karakter
      Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);
      Lib.SetTextFlowMinLines(Flow, 2);   // tek bir satırı asla ortada bırakma

      repeat
        // 480 pt genişliğinde bir alanda üç sütun, 18 pt aralık, dengeli
        Drawn := Lib.DrawTextFlowColumns(Flow, 72, 720, 480, 620, 3, 18, 1);
        if (Drawn = 0) or (Lib.TextFlowFinished(Flow) = 1) then
          Break;
        Lib.NewPage;
      until False;
    finally
      Lib.ReleaseTextFlow(Flow);
    end;

    Lib.SaveToFile('newsletter.pdf');
  finally
    Lib.Free;
  end;
end;

MinPrefix ve MinSuffix tipografidir, doğrulama değil

Etkinleştirme bayrağından sonraki iki tam sayı, bir bölmeden önce ve sonra kalması gereken en az karakter sayısını belirler. Üç ve üç, çoğu kurum stilinin kabul ettiği tutucu bir varsayılandır. İki ve iki daha fazla bölme fırsatı üretir ve gözle görülür şekilde daha çirkin sonuçlar verir, çünkü bir satır sonunda sarkan iki harflik bir parça bir yazım hatası gibi okunur

Her parçanın görsel olarak belirgin olduğu büyük punto boyutlarında bu asgari değerleri artırın ve yalnızca sütun gerçekten darsa ve dar bir ölçünün temiz bir ölçüden daha önemli olduğuna karar verdiyseniz düşürün. Bu, teknik bir karar değil bir kurum stili kararıdır ve tam da bu yüzden bir sabit değil bir parametredir

Burada "dengeli" gerçekte ne anlama gelir?

Balance parametresi davranışı yalnızca bir parçanın sonunda değiştirir. Dengeleme açıkken, kalan her şey alan içine sığdığında sütunlar tam olarak eşit bir satır sayısına kısaltılır ki bu, son bir sayfanın iki tam sütun ve tek bir yalnız satır taşıyan üçüncü bir sütun göstermesini engelleyen şeydir. Parça sığmadığında ise her sütun tam yüksekliğini korur, böylece sayfa taşıyabildiği kadar metin taşır ve geri kalanı bir sonraki sayfada devam eder

Bu asimetri, sürekli belgeler için doğru varsayılandır. Akan bir makalenin ortasında dengeleme, kimsenin göremediği kozmetik bir etki için her sayfada dikey alan israf ederdi, çünkü sütunlar zaten doludur. Dengeleme, gözün gerçekten fark ettiği yerde, sonda uygulanır ve uygulandığı yer de tam olarak orasıdır

Satır bölme tam kelimeleri ölçer

Bölme algoritması, karakter genişliklerini biriktirmek yerine tam kelimeleri ölçer ve bir URL ya da bir hesap numarası gibi hiçbir satıra sığmayacak aşırı büyük belirteçler için sınırlı bir arama ayırır. Bu, olağan durumu hızlı, patolojik durumu ise tersi yerine sınırlı tutar

İsteğe bağlı yumuşak tireler ve otomatik tireler, yalnızca işaretledikleri bölme seçilen bölmeyse çizilir. Bu kulağa açık gelir ve klasik bir kusurdur: saf bir uygulama, ölçüm sırasında tire karakterini yazar ve bölme yer değiştirirse tire bir satırın ortasında geride kalır. Hiçbir şey, bir kelimenin içinde başıboş kalmış bir tireden daha çok bozuk bir metin motoruna benzemez

var
  Lib: TPDFlib;
  Flow, Needed: Integer;
begin
  // Herhangi bir şey çizmeden önce düzene karar ver
  Flow := Lib.NewTextFlow(ArticleBody);
  try
    Lib.SetTextFlowLanguage(Flow, 'fr');
    Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);

    // Parçanın geri kalanının tek bir sütun genişliğinde ihtiyaç duyduğu satır sayısı
    Needed := Lib.MeasureTextFlow(Flow, 148);
    if Needed > 3 * LinesPerColumn then
      UseTwoPageSpread
    else
      UseSinglePage;

    Lib.DrawTextFlowColumns(Flow, 72, 720, 480, 620, 3, 18, 1);

    if Lib.TextFlowFinished(Flow) <> 1 then
      CarryOver(Lib.GetTextFlowRemaining(Flow));
  finally
    Lib.ReleaseTextFlow(Flow);
  end;
end;

Yazı tipi ayarlarını kutular arasında aynı tutun

Akış tabanlı her düzeni tek bir kural yönetir ve bunu açıkça belirtmekte fayda var: DrawTextFlow, DrawTextFlowColumns ve MeasureTextFlow, satırları çağrıldıkları anda seçili olan yazı tipini kullanarak böler. Aynı akışın iki kutusu arasında yazı tipini ya da boyutunu değiştirin ya da yeni bir sayfaya birini yeniden seçmeden başlayın; ikinci kutu, birincinin ölçtüğünden farklı bölünür

Belirti, aralıklı görünmesi yüzünden can sıkıcıdır: birinci sayfaya sığan metin ikinci sayfada taşar ya da ölçülen bir satır sayısı çizilenle uyuşmaz. Yazı tipini döngüden önce bir kez seçin, her NewPage'den sonra yeniden seçin ve akış düzgün davranır. Aynı parçada karışık yazı sistemleri belirdiğinde, CJK ve emoji metni için otomatik yazı tipi yedekleme'de anlatılan çözüm hem ölçüme hem çizime uygulanır, böylece genişlikler yedekleme akışları boyunca da tutarlı kalır

Akışın başlıklar, alt bilgiler ve veri odaklı bloklar arasında tek bir öğe olduğu rapor düzenlerinde, veri kümesi rapor motorundaki kompozisyon desenleri sütun akışlarıyla temiz bir şekilde birleşir: önce ölçün, sabit donanımı yerleştirin, ardından akışa kalan alanı ne varsa verin

PDFlibPas bir Delphi, C++Builder ve Lazarus PDF kütüphanesidir ve TextFlow yaşam döngüsünün tamamı, oluşturma, çizim, ölçüm, inceleme, geri sarma ve serbest bırakma, DLL ve ActiveX arayüzleri üzerinden de sunulur. Tam belgeler PDFlibPas Delphi PDF kütüphane sayfasında bulunur