Kerning dengan cepat

10

Adakah yang tahu algoritma yang menghitung kerning karakter secara otomatis berdasarkan bentuk mesin terbang ketika pengguna mengetik teks?

Maksud saya bukan perhitungan sepele lebar muka atau serupa, maksud saya menganalisis bentuk mesin terbang untuk memperkirakan jarak visual yang optimal antara karakter. Sebagai contoh jika kita meletakkan tiga karakter secara berurutan dalam sebuah garis, karakter tengah harus TAMPAK berada di tengah garis meskipun bentuk karakter. Contoh mencerahkan fungsionalitas kerning-on-the-fly:

Contoh kerning-on-the-fly:

Tangkapan layar

Pada gambar di atas asepertinya terlalu tepat. Itu harus digeser jumlah tertentu ke arah Tsehingga tampaknya berada di tengah Tdan g. Algoritme harus memeriksa bentuk Tdan a(dan mungkin juga huruf lain) dan memutuskan berapa banyak yang aharus digeser ke kiri. Jumlah tertentu ini adalah hal yang harus dihitung algoritme - TANPA MEMERIKSA PASANG KERNING YANG MUNGKIN DARI FONT.

Saya sedang memikirkan pengkodean program javascript (+ svg + html) yang menggunakan font yang digambar tangan dan banyak dari mereka tidak memiliki pasangan kerning. Bidang teks akan dapat diedit dan dapat menyertakan teks dari banyak font. Saya pikir kerning-on-the-fly bisa menjadi salah satu cara untuk memastikan aliran teks rata-rata dalam kasus ini.

EDIT: Salah satu titik awal untuk ini bisa menggunakan font svg, jadi mudah untuk mendapatkan nilai path. Dalam font svg path didefinisikan dengan cara ini:

<glyph glyph-name="T" unicode="T" horiz-adv-x="1251" d="M531 0v1293h
-483v173h1162v-173h-485v-1293h-194z"/>

<glyph glyph-name="a" unicode="a" horiz-adv-x="1139" d="M828 131q-100 -85
-192.5 -120t-198.5 -35q-175 0 -269 85.5t-94 218.5q0 78 35.5 142.5t93
103.5t129.5 59q53 14 160 27q218 26 321 62q1 37 1 47q0 110 -51 155q-69 61
-205 61q-127 0 -187.5 -44.5t-89.5 -157.5l-176 24q24 113 79 182.5t159
107t241 37.5 q136 0 221 -32t125 -80.5t56 -122.5q9 -46 9 -166v-240q0
-251 11.5 -317.5t45.5 -127.5h-188q-28 56 -36 131zM813 533q-98 -40 -294
-68q-111 -16 -157 -36t-71 -58.5t-25 -85.5q0 -72 54.5 -120t159.5 -48q104
0 185 45.5t119 124.5q29 61 29 180v66z"/>

Algoritme (atau kode javascript) harus memeriksa jalur tersebut dengan cara tertentu dan menentukan jarak optimal di antara mereka.

Timo Kähkönen
sumber
1
Jika Anda mencari solusi pengkodean, ini akan lebih baik ditanyakan pada SO. Itukah yang kamu cari? Jika demikian, saya akan memigrasikan pertanyaan di sana.
Alan Gilbertson
2
Saya setuju bahwa ini adalah pertanyaan SO. Saya mengajukan pertanyaan yang sama di SO, tetapi ditutup sebagai off topic di sana. Kemudian bertanya pada math.stackexchange, tetapi penutupan yang sama terjadi. Ini adalah tempat ketiga, mungkin ini adalah tempat yang tepat, siapa pun yang tahu.
Timo Kähkönen
2
Saya tidak tahu bagaimana algoritme bekerja, tetapi InDesign dapat melakukan ini: "Kerning optik menyesuaikan jarak antara karakter yang berdekatan berdasarkan bentuknya. Beberapa font menyertakan spesifikasi kern-pair yang kuat. Namun, ketika sebuah font hanya menyertakan minimal built-in kerning atau tidak sama sekali, atau jika Anda menggunakan dua jenis huruf atau ukuran yang berbeda dalam satu kata atau lebih pada satu baris, Anda mungkin ingin menggunakan opsi kerning optik. " help.adobe.com/en_US/indesign/cs/using/…
e100
2
Saya pikir ini mungkin dalam ruang lingkup sejauh algoritma umum berjalan - urutan langkah yang harus dilakukan untuk menyelesaikan masalah. Tapi saya tidak berpikir spesifik implementasi dalam JS atau bahasa lain milik, dan saya mengedit hanya menyebutkan JS sebagai kasus penggunaan latar belakang.
e100
1
Saya pikir urutan bisnis pertama adalah mendefinisikan "optimal" dengan cara yang berguna untuk algoritma mesin.
horatio

Jawaban:

4

Saya tahu ini sudah tua. Saya sedang mengerjakan ini sekarang dalam implementasi WebGL dari teks goyah (apa pun). Solusi yang saya kerjakan berjalan seperti ini:

  1. Dapatkan versi bitmap dari mesin terbang (atau lakukan dengan vektor jika Anda mau)
  2. Untuk setiap baris piksel (atau unit vertikal sewenang-wenang jika Anda menggunakan vektor), periksa bahwa kedua mesin terbang memiliki setidaknya satu piksel yang ada
  3. Untuk setiap baris yang melewati langkah 2, hitung jarak antara piksel paling kanan dari mesin terbang pertama dan piksel paling kiri dari mesin terbang kedua
  4. Pindahkan mesin terbang kedua ke kiri sejauh mungkin sambil tetap memenuhi kriteria ini:
    • celah di baris piksel itu lebih besar dari beberapa celah minimum yang Anda tentukan
    • total area (mengabaikan baris tanpa pixel di salah satu mesin terbang) lebih besar dari beberapa area minimum yang Anda tentukan

Dengan begitu, 'area' kosong di antara huruf harus diperas ke rata-rata yang cukup umum. Tentukan kesenjangan minimum dan area minimum menggunakan coba-coba dan selera Anda sendiri, dan mungkin memungkinkan parameter tersebut untuk disesuaikan oleh beberapa agen lain juga ... seperti nilai kerning manual.

yay :)

Sunting: Saya berhasil menerapkan ini sekarang dan berfungsi dengan sangat baik :)

jaya
sumber
Jawaban bagus! Selamat datang di GD.SE :)
Yisela
Terima kasih atas sambutannya: D !! Saya harus menambahkan bahwa area tersebut harus dibagi dengan jumlah baris yang benar-benar diuji (yang sebenarnya hanya membuatnya menjadi kesenjangan rata-rata dan bukan benar-benar suatu area). Dan juga akan bagus untuk menguji apakah celah baris adalah pencilan statistik dan abaikan baris itu jika itu. Itu akan membantu menghindari meremas surat terlalu dekat ketika ada pembukaan besar seperti di 'G'
jaya
Tampaknya ada beberapa anak bermasalah di sana-sini, seperti T atau o 'misalnya dalam beberapa gaya font beberapa font. T-biarkan tanda hubung terlalu dekat dengan T, dan o 'tidak berbagi piksel dalam baris yang sama, jadi saya membuat mundur untuk menggunakan baris terdekat dengan masing-masing satu piksel saat itu terjadi. Untuk membuat algoritme di atas lebih kuat, Anda harus memeriksa masalah semacam ini, entah bagaimana. Demi tujuan saya, itu tidak perlu.
jaya
3

Ini adalah algoritma yang cukup sederhana yang saya coba sekali, dan mungkin cukup baik.

Render karakter dalam resolusi rendah - katakan tinggi enam atau tujuh piksel (tinggi modal khas) hampir sama secara horizontal. Anda ingin peta biner sederhana di mana ada ruang kosong vs bagian-bagian surat itu, di kotak res rendah sederhana.

"Fatten" memetakan surat-surat ini. Yaitu, isi setiap sel kosong yang berdekatan dengan sel yang diisi. Ini untuk mengklaim wilayah kosong yang paling dekat dengan tepi surat, sehingga surat tetangga tidak terlalu dekat.

Mainkan "Tetris horizontal" dengan peta surat yang dihasilkan. Biarkan gravitasi bergerak ke kiri. "Perut" kiri dari "a" akan "jatuh" ke dalam rongga di bawah bilah "T". Berapa banyak sel yang bergerak "a"? Tingkatkan itu sebanding dengan ukuran sebenarnya dari huruf-huruf itu dan sejauh itulah untuk melihat resolusi tinggi aktual "a" ke kiri.

DarW
sumber
1
Terima kasih! Untuk memvisualisasikan algoritma Anda, Anda bisa memberikan beberapa contoh gambar res rendah menggunakan pasangan "db", "AA", "Ta" dan "c-" menggunakan Arial.
Timo Kähkönen
Awal yang baik, tetapi saya berpikir bahwa ini mungkin terbatas di mana pasangan karakter protruberant tidak bersama-sama "Tetris", misalnya "bd", "TT", "pq", "gj"
e100
@ e100: Sekilas, pasangan itu tidak akan memiliki kotak pembatas yang tumpang tindih ...
horatio
Tetapi secara umum, mereka harus kerned lebih ketat daripada "MM", "NN" dll
e100
2

Algoritma untuk auto-kerning sudah ada. Tidak ada yang bodoh dan mereka cenderung membutuhkan sedikit pegangan tangan dan koreksi manual pada aspek-aspek tertentu, terutama jika pelacakan Anda relatif ketat.

Tetapi algoritma tersebut adalah untuk menerapkan kerning ke file font , bukan ke huruf karena dihasilkan dari file font.

Sudahkah Anda mempertimbangkan untuk menerapkan auto-kerning ke file font?

Fontforge (open source) dan Fontlab (komersial) mengandung algoritma auto-kerning. Mereka akan memiliki kurva belajar yang relatif curam - Anda harus terbiasa dengan aspek teknis tentang cara kerja font.

Ada juga iKern yang adalah seorang cowok yang menawarkan font-kerning komersial layanan dimana ia Kerns font untuk Anda dan melakukan pekerjaan yang lebih baik. Saya tidak tahu berapa biayanya.

thomasrutter
sumber
Tetapi pertanyaannya adalah "bagaimana cara kerja algoritma seperti itu?" - dapatkah Anda menambahkan detail tentang cara kerja FontForge?
e100
0

Saya belum punya waktu untuk memikirkan ini sepenuhnya, atau menggambar ilustrasi, tetapi saya memiliki ide setengah berdasarkan pertama membagi dua masing-masing mesin terbang secara vertikal.

Kemudian untuk setiap setengahnya, tentukan dua sumbu vertikal: - garis-bagi - persis setengah antara ekstrem kiri dan kanan - sumbu "berat" - tepat setengah dari tinta di setiap sisi

Kemudian pindahkan mesin terbang tetangga yang berdekatan ke arah atau menjauh dari uji setengah mesin terbang berdasarkan posisi relatif kedua sumbu.

Jadi, misalnya, dalam pasangan "AV", bagian kanan A adalah kiri-berat dan "menarik" V; separuh kiri dari V adalah benar-berat "menarik" A, sehingga mereka kerned bersama secara signifikan.

Namun, saya yakin ada kekurangan bahwa "AA" akan dikelompokkan bersama sebanyak "AV".

e100
sumber
0

Mengingat huruf besar dan kecil, ada beberapa 56X55=2652situasi font-pair yang harus Anda perhatikan , semua solusi mungkin mudah rusak karena jika Anda mengubah gaya font, semua aturan hilang.

Cara terbaik adalah menggunakan teknik pembelajaran mesin, mencoba membangun model studi jaringan saraf, dan mengimpor beberapa gambar teks atau vektor atau hal-hal seperti itu, melatih model itu dan menggunakan model yang terlatih itu untuk secara cerdas menyesuaikan segala jenis font.

karena tidak ada algoritma statis untuk menyesuaikan font secara sempurna di root, pembelajaran mesin akan menjadi solusi yang baik untuk masalah seperti ini!

Super-ilad
sumber
Tidak jika hanya ada sebagian besar kriteria subjektif. "Apakah ini anjing atau kucing?", Tidak peduli betapa anehnya anjing itu, masih memiliki jawaban yang pasti. (Bahkan jika dibutuhkan dokter hewan untuk memverifikasi.)
usr2564301