Kerning on the fly


10

Kennt jemand einen Algorithmus, der das automatische Kerning von Zeichen basierend auf Glyphenformen berechnet, wenn der Benutzer Text eingibt?

Ich meine nicht die triviale Berechnung von Vorschubbreiten oder ähnlichem, sondern die Analyse der Form von Glyphen, um den visuell optimalen Abstand zwischen Zeichen abzuschätzen. Wenn wir beispielsweise drei Zeichen nacheinander in einer Zeile anordnen, sollte sich das mittlere Zeichen trotz der Formen des Zeichens in der Mitte der Zeile befinden. Ein Beispiel beleuchtet die Kerning-on-the-Fly-Funktionalität:

Ein Beispiel für Kerning-on-the-Fly:

Bildschirmfoto

Im obigen Bild ascheint es zu richtig zu sein. Es sollte eine verschoben wird bestimmte Menge auf , Tso dass es in der Mitte zu sein scheint Tund g. Der Algorithmus sollte die Formen von Tund a(und möglicherweise auch andere Buchstaben) untersuchen und entscheiden, wie viel anach links verschoben werden muss. Dieser bestimmte Betrag sollte vom Algorithmus berechnet werden - OHNE DIE MÖGLICHEN KERNING-PAARE DER SCHRIFT ZU PRÜFEN.

Ich denke darüber nach, ein Javascript-Programm (+ svg + html) zu codieren, das handgezeichnete Schriftarten verwendet, und vielen von ihnen fehlen Kerning-Paare. Die Textfelder können bearbeitet werden und können Text mit mehreren Schriftarten enthalten. Ich denke, dass Kerning-on-the-Fly in diesem Fall eine Möglichkeit sein könnte, einen mittleren Textfluss sicherzustellen.

BEARBEITEN: Ein Ausgangspunkt hierfür könnte die Verwendung der Schriftart svg sein, sodass es einfach ist, Pfadwerte abzurufen. In der Schriftart svg wird der Pfad folgendermaßen definiert:

<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"/>

Der Algorithmus (oder Javascript-Code) sollte diese Pfade auf irgendeine Weise untersuchen und den optimalen Abstand zwischen ihnen bestimmen.


1
Wenn Sie nach einer Codierungslösung suchen, ist dies bei SO besser gefragt. Ist es das, wonach du suchst? Wenn ja, werde ich die Frage dort migrieren.
Alan Gilbertson

2
Ich bin damit einverstanden, dass dies SO eine Frage ist. Ich habe die gleiche Frage in SO gestellt, aber sie wurde dort als Off-Topic geschlossen. Dann fragte auf math.stackexchange, aber das gleiche Schließen geschah. Dies ist der dritte Platz, vielleicht ist dies der richtige Ort, wer auch immer weiß.
Timo Kähkönen

2
Ich weiß nicht, wie der Algorithmus funktioniert, aber InDesign kann dies tun: "Optisches Kerning passt den Abstand zwischen benachbarten Zeichen basierend auf ihren Formen an. Einige Schriftarten enthalten robuste Kern-Pair-Spezifikationen. Wenn eine Schriftart jedoch nur minimale integrierte Funktionen enthält Kerning oder gar keine, oder wenn Sie zwei verschiedene Schriftarten oder Größen in einem oder mehreren Wörtern in einer Zeile verwenden, möchten Sie möglicherweise die optische Kerning-Option verwenden. " help.adobe.com/en_US/indesign/cs/using/…
e100

2
Ich denke, dies liegt wahrscheinlich im Rahmen eines allgemeinen Algorithmus - einer Abfolge von Schritten, die zur Lösung eines Problems ausgeführt werden müssen. Aber ich denke nicht, dass Einzelheiten der Implementierung in JS oder einer anderen Sprache dazu gehören, und bearbeite, um nur JS als Hintergrundanwendungsfall zu erwähnen.
e100

1
Ich denke, die erste Aufgabe besteht darin, "optimal" auf eine Weise zu definieren, die für einen Maschinenalgorithmus nützlich ist.
Horatio

Antworten:


4

Ich weiß, dass das alt ist. Ich arbeite gerade daran in einer WebGL-Implementierung von wackeligem Text (was auch immer). Die Lösung, an der ich arbeite, sieht folgendermaßen aus:

  1. Holen Sie sich eine Bitmap-Version des Glyphenpaars (oder machen Sie es mit Vektoren, wenn Sie möchten)
  2. Überprüfen Sie für jede Pixelreihe (oder eine beliebige vertikale Einheit, wenn Sie Vektoren verwenden), ob in beiden Glyphen mindestens ein Pixel vorhanden ist
  3. Berechnen Sie für jede Zeile, die Schritt 2 besteht, den Abstand zwischen dem Pixel ganz rechts des ersten Glyphen und dem Pixel ganz links des zweiten Glyphen
  4. Bewegen Sie die zweite Glyphe so weit wie möglich nach links, während Sie die folgenden Kriterien erfüllen:
    • Die Lücke in dieser Pixelreihe ist größer als die von Ihnen angegebene Mindestlücke
    • Die Gesamtfläche (Ignorieren von Zeilen ohne Pixel in einem der Glyphen) ist größer als die von Ihnen angegebene Mindestfläche

Auf diese Weise sollte der leere Bereich zwischen den Buchstaben auf einen ziemlich häufigen Durchschnitt gedrückt werden. Geben Sie die minimale Lücke und die minimale Fläche mithilfe von Versuch und Irrtum und Ihrem eigenen Geschmack an und lassen Sie diese Parameter möglicherweise auch von einem anderen Agenten anpassen ... wie einem manuellen Kerning-Wert.

Yay :)

Edit: Ich habe das jetzt erfolgreich implementiert und es funktioniert wirklich gut :)


Gute Antwort! Willkommen bei GD.SE :)
Yisela

Danke für die Begrüßung: D !! Ich sollte hinzufügen, dass der Bereich durch die Anzahl der tatsächlich getesteten Zeilen geteilt werden sollte (was eigentlich nur eine durchschnittliche Lücke und nicht wirklich einen Bereich darstellt). Außerdem wäre es gut zu testen, ob die Lücke einer Zeile ein statistischer Ausreißer ist, und diese Zeile zu ignorieren, wenn dies der Fall ist. Das hilft zu vermeiden, dass Buchstaben zu eng zusammengedrückt werden, wenn es eine große Öffnung wie in 'G' gibt
Jaya

Es scheint hier und da ein paar Problemkinder zu geben, wie T- oder o 'zum Beispiel in einigen Schriftstilen einiger Schriftarten. T- Lassen Sie den Bindestrich dem T viel zu nahe kommen, und o 'hat keine Pixel in derselben Zeile geteilt. Deshalb habe ich einen Fallback durchgeführt, um die nächsten Zeilen mit jeweils einem Pixel zu verwenden. Um den obigen Algorithmus robuster zu machen, müssten Sie irgendwie nach solchen Problemen suchen. Für meine Zwecke war es nicht notwendig.
Jaya

3

Dies ist ein ziemlich einfacher Algorithmus, den ich einmal ausprobiert habe und der möglicherweise gut genug ist.

Rendern Sie die Zeichen in niedriger Auflösung - sagen wir, sechs oder sieben Pixel hoch (Höhe des typischen Großbuchstaben) ungefähr gleich horizontal. Sie möchten eine einfache binäre Karte, in der der Leerraum gegenüber Teilen des Buchstabens in einem einfachen Raster mit niedriger Auflösung frei ist.

"Mästen" Sie diese Buchstabenkarten. Füllen Sie also jede leere Zelle, die an eine gefüllte Zelle angrenzt. Hiermit wird ein leeres Gebiet beansprucht, das den Buchstabenkanten am nächsten liegt, damit der benachbarte Buchstabe nicht zu nahe kommt.

Spielen Sie "horizontales Tetris" mit den resultierenden Buchstabenkarten. Lassen Sie die Schwerkraft nach links wirken. Der gewölbte linke "Bauch" des "a" "fällt" in den Hohlraum unter der Überstange des "T". Wie viele Zellen hat sich das "a" bewegt? Skalieren Sie das proportional zur tatsächlichen Größe der Buchstaben und so weit können Sie das tatsächliche hochauflösende "a" nach links kern.


1
Vielen Dank! Um Ihren Algorithmus zu visualisieren, können Sie ein Bildbeispiel mit niedriger Auflösung unter Verwendung der Paare "db", "AA", "Ta" und "c-" unter Verwendung von Arial bereitstellen.
Timo Kähkönen

Guter Start, aber ich denke, dass dies begrenzt sein kann, wenn Paare von hervorstehenden Zeichen nicht zusammen "Tetris" sind, z. B. "bd", "TT", "pq", "gj"
e100

@ e100: Auf den ersten Blick hätte diese bestimmte Paarung keine überlappenden Begrenzungsrahmen ...
Horatio

Aber im Allgemeinen sollten sie enger als "MM", "NN" usw.
e100

2

Algorithmen für das Auto-Kerning existieren bereits. Keiner ist narrensicher und erfordert in der Regel ein wenig Handhaltung und manuelle Korrektur bestimmter Aspekte, insbesondere wenn Ihre Verfolgung relativ eng ist.

Diese Algorithmen dienen jedoch dazu, den Kerning auf die Schriftartdatei anzuwenden , nicht auf die Buchstaben, wie sie aus der Schriftartdatei generiert werden.

Haben Sie darüber nachgedacht, Auto-Kerning auf die Schriftartdatei anzuwenden?

Fontforge (Open Source) und Fontlab (kommerziell) enthalten Auto-Kerning-Algorithmen. Sie hätten eine relativ steile Lernkurve - Sie müssen mit technischen Aspekten der Funktionsweise von Schriftarten vertraut sein.

Es gibt auch iKern , einen Typ, der einen kommerziellen Font-Kerning- Service anbietet, bei dem er Ihre Font für Sie kern und einen ziemlich guten Job macht. Ich weiß nicht, wie viel es kosten würde.


Aber die Frage ist wirklich: "Wie würde ein solcher Algorithmus funktionieren?" - Können Sie Einzelheiten zur Funktionsweise von FontForge hinzufügen?
e100


0

Ich habe keine Zeit, dies vollständig durchzudenken oder Illustrationen zu zeichnen, aber ich hatte eine halbe Idee, bei der es darum ging, jede Glyphe zuerst vertikal zu halbieren.

Bestimmen Sie dann für jede Hälfte zwei vertikale Achsen: - die Winkelhalbierende - genau die Hälfte zwischen den linken und rechten Extremen - die "Gewichts" -Achse - genau die Hälfte der Tinte auf jeder Seite

Bewegen Sie dann die benachbarte Nachbar-Glyphe basierend auf den relativen Positionen der beiden Achsen auf die Testhalbglyphe zu oder von dieser weg.

So ist beispielsweise im Paar "AV" die rechte Hälfte des A linkslastig und "zieht" das V an; Die linke Hälfte des V ist rechtslastig und "zieht" das A an, so dass sie signifikant miteinander verbunden sind.

Ich bin mir jedoch sicher, dass "AA" genauso fehlerhaft ist wie "AV".


0

In Anbetracht von Groß- und Kleinbuchstaben gibt es 56X55=2652Situationen, in denen Sie sich mit Schriftpaaren befassen sollten. Alle Lösungen können leicht beschädigt werden, wenn Sie den Schriftstil ändern und alle Regeln weg sind.

Der beste Weg ist, die Technik des maschinellen Lernens zu verwenden, zu versuchen, ein Studienmodell für neuronale Netze zu erstellen und mehrere Kerned-Text-Bilder oder -Vektoren oder ähnliches zu importieren, dieses Modell zu trainieren und dieses trainierte Modell zu verwenden, um jede Art von Schriftart intelligent anzupassen.

Da es keinen statischen Algorithmus gibt, mit dem die Schriftart in root perfekt angepasst werden kann, wäre maschinelles Lernen eine gute Lösung für diese Art von Problem!


Nicht, wenn es nur meist subjektive Kriterien gibt. "Ist das ein Hund oder eine Katze?", Egal wie komisch das Hündchen aussieht, hat immer noch eine genaue Antwort. (Auch wenn es eines Tierarztes bedarf, um dies zu überprüfen.)
usr2564301
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.