Setiap string yang terlihat dalam dokumen HotPDF tiba melalui satu panggilan: TextOut(X, Y, angle, Text). Contoh Hello World menggunakannya pada bentuk paling polosnya, font disetel sekali dan empat argumen dibiarkan pada default yang masuk akal. Melewati halaman pertama itu empat argumen yang sama membawa seluruh bobot tata letak. Argumen ketiga memutar run. Font yang disetel tepat sebelumnya memutuskan ukuran dan gaya. Dan pasangan X, Y, diukur dari sudut halaman dalam poin, adalah satu-satunya yang berdiri di antara laporan yang bersih dan teks yang tumpang tindih, terpotong, atau menyimpang satu baris lebih rendah di printer orang lain. Di sinilah TextOut mendapat nilainya, dan di sinilah default berhenti cukup
Tanda tangan layak diingat sebelum hal lain: X dan Y adalah Single dalam poin, angle adalah Extended dalam derajat, dan Text adalah WideString, sehingga Unicode lewat tanpa panggilan terpisah. Overload kedua mengambil PWORD ditambah panjang untuk saat Anda sudah memegang kode glyph, tetapi untuk string biasa bentuk WideString adalah yang Anda jangkau
Ukuran dan gaya datang dari SetFont, bukan TextOut
TextOut tidak punya parameter ukuran. Ukuran, bobot, kemiringan, semuanya hidup dalam panggilan SetFont yang mendahului run, dan tetap berlaku sampai SetFont berikutnya menggantikannya. Itu satu fakta yang menjelaskan sebagian besar kebingungan hari-pertama: sebuah baris keluar tebal karena tiga panggilan sebelumnya sesuatu menyetel [fsBold] dan tidak ada yang membersihkannya
Pdf.CurrentPage.SetFont('Times New Roman', [], 24);
Pdf.CurrentPage.TextOut(72, 740, 0, 'Quarterly Report'); // 24pt regular
Pdf.CurrentPage.SetFont('Times New Roman', [fsBold], 12);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Revenue'); // 12pt bold
Pdf.CurrentPage.SetFont('Times New Roman', [fsItalic], 11);
Pdf.CurrentPage.TextOut(72, 694, 0, 'figures in thousands'); // 11pt italic
Pdf.CurrentPage.SetFont('Courier New', [fsBold, fsItalic], 10);
Pdf.CurrentPage.TextOut(72, 676, 0, ' +18.4% YoY'); // styles combine
Argumen kedua adalah himpunan TFontStyles, jadi [fsBold, fsItalic] adalah tebal miring dan [] adalah polos. Ukuran dalam poin, unit yang sama dengan koordinat, yang membuat spasi vertikal mudah dipikirkan: baris 12-poin menginginkan kira-kira 14 sampai 16 poin langkah vertikal untuk bernapas, jadi menurunkan Y sebesar 14 per baris adalah leading awal yang wajar. Tidak ada kemajuan baris otomatis. Anda menghitung setiap baseline sendiri, yang melelahkan untuk paragraf tetapi tepat untuk formulir, di mana setiap field duduk di koordinat tetap
Dua catatan praktis tentang nama font. Itu diselesaikan terhadap font yang dipasang di mesin build, dan apa pun yang dikembalikan OS yang menjadi tersemat, jadi nama yang terselesaikan di desktop Anda dan nama yang terselesaikan di server build tidak dijamin wajah yang sama. Dan font harus mencakup skrip dalam string. Run teks Cyrillic atau CJK di bawah wajah Latin-saja terender sebagai kotak glyph-hilang tanpa kesalahan, yang menjadi alasan halaman Hello World menjangkau wajah Unicode luas saat mencampur bahasa
Argumen sudut berputar di sekitar jangkar
Argumen ketiga adalah yang paling banyak kode dibiarkan di nol selamanya. Berikan nilai bukan-nol dan run berputar berlawanan-jarum-jam tentang jangkar (X, Y)-nya sendiri, kiri-bawah teks, sebanyak derajat itu. Jangkar itu sendiri tidak bergerak, jadi koordinat yang sama yang menempatkan label horizontal menempatkan kembarannya yang diputar; hanya arah glyph berbaris yang berubah
Pdf.CurrentPage.SetFont('Arial', [fsBold], 11);
// Label sumbu vertikal di margin kiri: 90 derajat terbaca dari bawah ke atas
Pdf.CurrentPage.TextOut(40, 300, 90, 'Units sold');
// Watermark DRAFT diagonal melintasi badan halaman
Pdf.CurrentPage.SetFont('Arial', [fsBold], 60);
Pdf.CurrentPage.TextOut(150, 250, 45, 'DRAFT');
// Header kolom dimiringkan 60 derajat agar label panjang muat di tabel sempit
Pdf.CurrentPage.SetFont('Arial', [], 9);
Pdf.CurrentPage.TextOut(120, 600, 60, 'Q1 actual');
Pdf.CurrentPage.TextOut(160, 600, 60, 'Q2 actual');
Sembilan puluh derajat adalah kasus umum, label berjalan ke atas sisi bagan atau judul punggung. Empat puluh lima derajat menangani tajuk kolom miring, trik yang membiarkan label lebar duduk di atas kolom sempit tanpa tumpah ke tetangganya. Rotasi tidak mengubah bagaimana jangkar ditafsirkan, yang menjebak orang: run 90-derajat masih dimulai di (X, Y) dan tumbuh ke atas dari sana, jadi untuk memusatkan label yang diputar Anda menyesuaikan jangkar, bukan sudutnya. Saat beberapa run diputar berbagi baseline, beri mereka Y yang sama dan langkah X, persis seperti Anda melangkah Y untuk baris horizontal bertumpuk
Menempatkan koordinat tanpa menebak
Koordinat adalah bagian yang bertahan tinjauan atau diam-diam gagal. HotPDF mengukur dari sudut kiri-bawah halaman, Y tumbuh ke atas, dalam poin pada 72 per inci. Halaman US Letter adalah 612 kali 792 poin; A4 adalah 595 kali 842. Margin atas satu-inci pada Letter karena itu menempatkan baseline pertama Anda dekat Y = 792 dikurangi 72 dikurangi ukuran font, bukan di beberapa angka kecil dekat atas. Siapa pun yang tiba dari koordinat layar, di mana Y tumbuh ke bawah dari nol, menulis baris pertama di luar tepi bawah dan menghabiskan sepuluh menit bertanya-tanya ke mana perginya
Perlakukan tata letak sebagai aritmetika terhadap jangkar bernama alih-alih kolom angka ajaib. Margin kiri, baseline berjalan yang Anda kurangi per baris, dan leading tetap mengubah blok label menjadi loop pendek alih-alih dinding literal:
const
LeftMargin = 72; // 1 inch in
TopBaseline = 720; // baris pertama, sekitar 1 inci ke bawah pada Letter
Leading = 16; // jarak vertikal antarbaris
var
Y: Single;
Line: string;
begin
Pdf.CurrentPage.SetFont('Arial', [], 11);
Y := TopBaseline;
for Line in ReportLines do
begin
Pdf.CurrentPage.TextOut(LeftMargin, Y, 0, Line);
Y := Y - Leading;
if Y < 72 then // margin bawah tercapai
begin
Pdf.AddPage;
Pdf.CurrentPage.SetFont('Arial', [], 11); // font direset pada halaman baru
Y := TopBaseline;
end;
end;
end;
Penjaga pemutusan-halaman adalah baris yang pertama dilupakan semua orang dan paling keras menbran. Tidak ada tata letak aliran di bawah TextOut. Kurangi melewati margin bawah dan teks terus menggambar ke selokan, keluar halaman, ke ketiadaan, tanpa peringatan. Jadi Anda mengawasi Y sendiri, memanggil AddPage saat melintasi lantai, dan mereset baseline. SetFont setelah AddPage bukan isian opsional: font saat ini tidak bertahan pemutusan halaman, dan run pertama di halaman baru keluar dalam wajah default penampil jika Anda melewatkannya
Spasi karakter dan kata untuk pencocokan dan perapian
Kadang sebuah string benar tetapi lebarnya salah: tajuk yang harus membentang aturan tetap, kode yang harus terbaca dengan digit lebih lapang, kolom yang perlu nilainya didorong untuk rapat. PDF membawa dua operator status-teks untuk ini, character spacing (Tc, ruang ekstra ditambahkan setelah setiap glyph) dan word spacing (Tw, ruang ekstra ditambahkan di setiap karakter spasi), dan keduanya dinyatakan dalam unit text-space tidak diskalakan, efektif poin pada ukuran font saat ini. Mereka adalah status, bukan argumen ke TextOut, jadi Anda menyetelnya, menggambar, dan menyetelnya kembali
// Atur jarak huruf heading pendek agar membentang sepanjang garis
Pdf.CurrentPage.SetCharacterSpacing(4);
Pdf.CurrentPage.SetFont('Arial', [fsBold], 14);
Pdf.CurrentPage.TextOut(72, 740, 0, 'S U M M A R Y');
Pdf.CurrentPage.SetCharacterSpacing(0); // reset sebelum teks isi normal
// Perlebar jarak antar kata pada satu baris lebar
Pdf.CurrentPage.SetWordSpacing(6);
Pdf.CurrentPage.SetFont('Arial', [], 11);
Pdf.CurrentPage.TextOut(72, 712, 0, 'Name Department Extension');
Pdf.CurrentPage.SetWordSpacing(0);
Word spacing hanya bertindak pada karakter spasi (kode 32), yang punya konsekuensi yang layak diketahui: ia tidak melakukan apa pun di dalam run CJK yang tidak punya spasi ASCII, dan berinteraksi aneh dengan teks yang dikodekan sebagai indeks glyph alih-alih byte. Untuk output tabular Latin itu cara murah melebarkan celah tanpa mengetik ulang string. Character spacing adalah alat yang lebih baik untuk tajuk yang harus mencapai lebar target, karena menyebarkan penyesuaian secara merata ke setiap glyph alih-alih mengumpulkannya di spasi
Reset adalah seluruh disiplin. Spasi, seperti font, adalah bagian dari status gambar halaman, dan status bertahan sampai Anda mengubahnya. Letter-space satu tajuk dan lupa menolenya, dan setiap paragraf di bawah mewarisi peregangan, yang terbaca sebagai keanehan halus-sulit-ditempatkan yang bertahan proofread kasual dan gagal yang hati-hati. Kebiasaan andal adalah menyetel nilai spasi, menggambar run yang membutuhkannya, dan menyetelnya kembali ke nol di baris berikutnya, sehingga tidak ada kode nanti yang harus tahu apa yang dilakukan bagian sebelumnya
Memeriksa output di mana ia benar-benar pecah
Tata letak teks gagal di mesin kedua, bukan pertama, jadi pemeriksaan yang penting terjadi jauh dari meja Anda. Buka file yang dihasilkan pada sistem tanpa set font pengembang Anda terpasang dan konfirmasi wajah yang tersemat masih merender, termasuk Latin beraksen, skrip non-Latin apa pun, dan tanda baca, dalam satu pase alih-alih mengecek karakter mudah secara spot. Pilih dan salin beberapa baris untuk mengkonfirmasi teks adalah teks nyata dan bukan kerangka, yang penting saat pencarian atau ekstraksi masuk cakupan. Beri tata letak data representatif, label Jerman terpanjang dan angka terlebar, bukan placeholder rapi, karena run yang meluap field selalu yang tidak Anda ketik dengan tangan. Dan jika halaman harus mendarat di formulir pra-cetak, cetak atau rasterisasi satu sampel dan letakkan terhadap aslinya; drift baseline seperempat-milimeter tidak terlihat di layar dan jelas di kertas
Jika Anda belum menulis satu halaman pun, mulailah dengan contoh HotPDF Hello World, yang menyiapkan dokumen, font, dan sistem koordinat kiri-bawah yang menjadi dasar semua di atas. Panggilan TextOut, SetFont, dan spasi yang ditunjukkan di sini adalah bagian dari HotPDF Delphi Component untuk Delphi dan C++Builder