PDFlibPas mengalirkan sebuah passage yang ditahan melalui satu hingga 64 kolom berlebar sama dengan DrawTextFlowColumns, dan memecah barisnya dengan hyphenation language-aware yang dibatasi begitu Anda memanggil SetTextFlowLanguage dan SetTextFlowHyphenation. Sembilan bahasa didukung, dan bahasanya bisa diwarisi dari nilai Catalog dokumen /Lang alih-alih diatur per flow
Kedua fitur itu ada karena alasan yang sama: sebuah kolom sempit adalah tempat line breaking yang naif berhenti terlihat seperti typesetting dan mulai terlihat seperti sebuah bug report
Mengapa teks justified berantakan di kolom sempit?
Karena justification mendistribusikan ruang sisa ke dalam celah antar kata pada sebuah baris, dan jumlah sisanya bergantung pada apa yang muat. Pada measure yang lebar, sisanya kecil dan mata tidak pernah menyadarinya. Bagi dua lebarnya dan sebuah kata panjang tunggal yang tidak muat akan terdorong ke baris berikutnya, meninggalkan kata-kata sebelumnya untuk menyerap seluruh ruang itu. Tiga baris semacam itu berturut-turut menghasilkan kanal putih vertikal yang oleh para typographer disebut rivers, dan dialami pembaca sebagai teks yang sulit diikuti tanpa tahu alasannya
Hyphenation memperbaiki penyebabnya, bukan gejalanya, dengan mengizinkan sebuah break di dalam kata. Kata majemuk bahasa Jerman dan Belanda membuat ini tidak bisa ditawar: sebuah kata benda 24-karakter dalam kolom 60-milimeter tidak punya hasil yang baik tanpa sebuah titik break. Bahasa Inggris lebih bisa mentolerir ketiadaannya, itulah sebabnya produk yang mengutamakan bahasa Inggris sering merilis kode layout yang berantakan pada kali pertama seorang pelanggan Jerman menjalankannya
Bahasa mana saja, dan dari mana bahasanya berasal?
Hyphenation mencakup bahasa Inggris, Jerman, Belanda, Prancis, Spanyol, Italia, Portugis, Rusia, dan Turki. Atur secara eksplisit per flow dengan SetTextFlowLanguage, atau biarkan diwarisi dari entri Catalog dokumen /Lang, yaitu nilai yang sudah dibawa oleh sebuah dokumen tagged dan accessible
Pewarisan itu layak dipakai, bukan di-override. Sebuah dokumen yang mendeklarasikan bahasanya di Catalog memberi tahu screen reader, search indexer, dan hyphenation fakta yang sama dari satu tempat, dan satu tempat adalah di mana seharusnya sebuah fakta berada. Jika Anda sudah menghasilkan output tagged seperti dijelaskan di automatic tagging untuk PDF accessible, entri bahasanya sudah diatur dan flow-nya cukup mengikutinya
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');
// Aktifkan, minimal 3 karakter sebelum break, 3 sesudah
Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);
Lib.SetTextFlowMinLines(Flow, 2); // jangan pernah menyisakan satu baris sendirian
repeat
// Tiga kolom di region 480 pt, gutter 18 pt, balanced
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 dan MinSuffix adalah soal tipografi, bukan validasi
Kedua integer setelah flag enable itu mengatur jumlah minimum karakter yang harus tersisa sebelum dan sesudah sebuah break. Tiga dan tiga adalah default konservatif yang diterima sebagian besar house style. Dua dan dua menghasilkan lebih banyak peluang break dan hasil yang jelas lebih jelek, karena sebuah fragmen dua-huruf yang menggantung di akhir sebuah baris terbaca seperti typo
Naikkan nilai minimumnya saat ukuran tipenya besar, di mana setiap fragmen tampak menonjol secara visual, dan turunkan hanya saat kolomnya benar-benar sempit dan Anda sudah memutuskan bahwa measure yang ketat lebih penting daripada yang bersih. Ini adalah keputusan house-style, bukan keputusan teknis, dan itulah persis sebabnya ini menjadi sebuah parameter, bukan sebuah konstanta
Apa sebenarnya arti "balanced" di sini?
Parameter Balance mengubah perilaku hanya di akhir sebuah passage. Dengan balancing aktif, kolom-kolom dipendekkan ke jumlah baris yang persis sama saat semua sisa teks muat di dalam region itu, dan itulah yang mencegah sebuah halaman terakhir menampilkan dua kolom penuh dan kolom ketiga hanya berisi satu baris kesepian. Saat passage-nya tidak muat, setiap kolom tetap mempertahankan tinggi penuhnya sehingga halaman itu membawa sebanyak mungkin teks dan sisanya dilanjutkan di halaman berikutnya
Asimetri itu adalah default yang benar untuk dokumen yang berkelanjutan. Balancing di tengah sebuah artikel yang mengalir akan membuang ruang vertikal di setiap halaman demi efek kosmetik yang tidak dilihat siapa pun, karena kolomnya toh sudah penuh. Balancing di akhir adalah tempat mata benar-benar menyadarinya, dan itulah persis tempat penerapannya
Line breaking mengukur kata secara utuh
Algoritma breaking-nya mengukur kata secara lengkap alih-alih mengakumulasi lebar karakter, dan mencadangkan sebuah pencarian terbatas untuk token yang terlalu besar yang sama sekali tidak muat dalam satu baris, seperti sebuah URL atau sebuah nomor akses. Itu menjaga kasus umum tetap cepat dan kasus patologis tetap terbatas, bukan sebaliknya
Soft hyphen diskresioner dan hyphen otomatis hanya dirender saat break yang mereka tandai adalah break yang benar-benar dipilih. Ini terdengar jelas dan merupakan sebuah cacat klasik: sebuah implementasi yang naif menulis karakter hyphen saat mengukur, dan jika break-nya berpindah, hyphen itu tertinggal di tengah-tengah sebuah baris. Tidak ada yang terlihat lebih seperti sebuah text engine yang rusak daripada sebuah hyphen nyasar di dalam sebuah kata
var
Lib: TPDFlib;
Flow, Needed: Integer;
begin
// Putuskan layout sebelum menggambar apa pun
Flow := Lib.NewTextFlow(ArticleBody);
try
Lib.SetTextFlowLanguage(Flow, 'fr');
Lib.SetTextFlowHyphenation(Flow, 1, 3, 3);
// Jumlah baris yang dibutuhkan sisa passage pada satu lebar kolom
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;
Jaga pengaturan font tetap identik di seluruh box
Satu aturan mengatur setiap layout berbasis flow dan layak dinyatakan secara terus terang: DrawTextFlow, DrawTextFlowColumns, dan MeasureTextFlow semuanya memecah baris memakai font yang terpilih pada saat mereka dipanggil. Ubah font atau ukurannya di antara dua box dari flow yang sama, atau mulai halaman baru tanpa memilih ulang font-nya, dan box kedua akan memecah dengan cara yang berbeda dari yang diukur box pertama
Gejalanya membuat frustrasi justru karena terlihat sebentar-sebentar: teks yang muat di halaman satu meluap di halaman dua, atau jumlah baris hasil pengukuran tidak sesuai dengan apa yang digambar. Pilih font sekali sebelum loop, pilih ulang setelah setiap NewPage, dan flow-nya akan berperilaku benar. Saat skrip campuran muncul dalam passage yang sama, resolusi yang dijelaskan di automatic font fallback untuk teks CJK dan emoji berlaku untuk pengukuran maupun penggambaran, sehingga lebar tetap konsisten di seluruh run fallback juga
Untuk layout report di mana flow hanyalah satu elemen di antara header, footer, dan block yang digerakkan data, pola komposisi di dalam dataset report engine berpadu dengan bersih bersama column flow: ukur dulu, tempatkan elemen tetapnya, lalu berikan flow itu region apa pun yang tersisa
PDFlibPas adalah pustaka PDF Delphi, C++Builder, dan Lazarus, dan seluruh siklus hidup TextFlow, pembuatan, penggambaran, pengukuran, inspeksi, rewind, dan release, juga diekspos lewat interface DLL dan ActiveX. Dokumentasi lengkap ada di halaman pustaka PDF Delphi PDFlibPas