Ich versuche, ein Python -Programm zu schreiben, um den Markdown, wie es durch Stack Exchange direkt in Bilder verwendet wird, umzuwandeln. Die Logik des Markdowns ist recht einfach, ich finde Mathjax eine Herausforderung, das Rendern zu rendern, aber ich habe das gefunden. Ich möchte die totale Kontrolle darüber haben, welcher individuelle Charakter mit welcher Schriftart gerendert wird. Genauer gesagt mag ich diese Andika -Schriftart. Es ist ohne SeriF, und die meisten Sans-Serif-Schriftarten sind schuldig, dass sie nicht unterhalb des Falles mit L-unter-Fall L, in Andika zwei Balken auf dem oberen Fall I und sein unteres Case A keine "Haare" haben. Auf dem Kopf ... < /p>
und es unterstützt auch griechische und kyrillische Skripte, aber leider unterstützt es Hiragana, Katakana, Hangul, Chinese usw.
Ich werde das verwenden Skript zu "serialisieren" Text aus vielen verschiedenen Sprachen, vorwiegend ist der Text in englischer Sprache, enthält jedoch häufig ganze Texte von Songs in anderen Sprachen. Ich habe vor, Andika für europäische Sprachen und Noto Sans SC für das ostasiatische Skript zu verwenden, aber keiner von ihnen unterstützt Emojis, da ich noch eine Schriftart brauche. Eine ausgewählte Schriftart hat Glyphe für einen bestimmten Charakter. Dies muss für jeden einzelnen Charakter erfolgen. Ein Charakter wird zuerst gegen Andika überprüft, um zu überprüfen, ob sie mit Andika mit Fallo sans sc und dann mit Noto Color Emoji, mit den Fallbacks gerendert werden kann, gerendert werden kann. und wenn alle drei ausfallen, muss eine Ausnahme angehoben werden, die gehandhabt werden ...
Für englischen Text ist dies einfach genug, nur ord (c) = 0 und b> = a, und beide Enden sind beispielsweise enthalten (0, 0) ein gültiger Bereich, der nur 0 enthält, und natürlich enthält (5, 9) (5, 6, 7,. 8, 9). Bereich. < /p>
Ich habe Folgendes gemacht (Sie benötigen Fonttools und Unicodedata2): < /p>
import unicodedata2
from bisect import bisect_right
from fontTools.ttLib import TTFont
def get_glyphs_in_font(font_path):
return sorted(
{code for cmap in TTFont(font_path)["cmap"].tables for code in cmap.cmap}
)
def group_consecutive(lst):
result = []
start = end = -1e309
for i in lst:
if i == end + 1:
end = i
else:
if end != -1e309:
result.append((start, end))
start = end = i
result.append((start, end))
return result
def get_glyph_ranges(font_path):
return group_consecutive(get_glyphs_in_font(font_path))
Die Ausgabe ist korrekt, hat jedoch 129 Elemente in der Ausgabe für "andika-regular.ttf" . Es wäre ineffizient, dies für jedes einzelne Zeichen zu tun. von ihnen ungültig, und das folgende findet alle: < /p>
INVALID_UNICODE = [
i
for i in range(1114112)
if unicodedata2.category(chr(i)) in {"Cc", "Cf", "Cn", "Co", "Cs", "Zl", "Zp", "Zs"}
]
INVALID_UNICODE_SET = set(INVALID_UNICODE)
< /code>
Lassen Sie mich nun die Regeln erklären: Lassen Sie (a, b) (c, d) zwei Bereiche sein, d> = c> b> = a, nun, falls eine der folgenden Angaben ist, ist Eine Untergruppe von Invalid_unicode: (b, c), (b + 1, c), (b + 1, c - 1), (b, c - 1), dann sollten sich die beiden Bereiche mit Form (a, d) verbinden, um (a, d) zu kombinieren . Wenn die oben genannten nicht zutreffen, aber C / B CodePoints im Bereich (B + 1, C - 1) akkretiert werden als Ausnahmen.[(32, 126),
(160, 328),
(330, 800),
(803, 831),
(838, 879),
(903, 903),
(915, 916),
(920, 920),
(926, 926),
(928, 928),
]
< /code>
Die erste befindet sich neben dem Bereich (0, 32), sodass die erste Iteration (0, 126) haben sollte, danach (127, 160) sind alle ungültig, also sollte es also sollte Kombinieren Sie den zweiten Bereich, um zu bilden (0, 328). Dann gibt es eine Diskontinuität zwischen (0, 328) und (330, 800), aber gemäß der zweiten Regel sollten sie verbunden werden und [329] als Ausnahme festgestellt werden. < /P>
die Das Ergebnis für das Beispiel sollte: < /p>
sein((0, 928),
[329,
801,
802,
832,
833,
834,
835,
836,
837,
880,
881,
882,
883,
884,
885,
886,
887,
890,
891,
892,
893,
894,
895,
900,
901,
902,
904,
905,
906,
908,
910,
911,
912,
913,
914,
917,
918,
919,
921,
922,
923,
924,
925,
927])
< /code>
Ich hatte dieses halbe Dutzend Mal ausprobiert, konnte aber das beabsichtigte Ergebnis nicht erzielen. Dies ist mein letzter Versuch, es ist sowohl klug als auch dumm gleichzeitig: < /p>
def get_glyph_groups1(font_path):
ranges = group_consecutive(get_glyphs_in_font(font_path))
result = {}
cur_start, cur_end = 0, 32
cur_missing = []
for start, end in ranges:
s1 = cur_end + cur_end not in INVALID_UNICODE_SET
e1 = start - start not in INVALID_UNICODE_SET
i1 = bisect_right(INVALID_UNICODE, e1)
i2 = bisect_right(INVALID_UNICODE, s1)
if i1 - i2 == e1 - s1 and bool(i1 - i2) == bool(e1 - s1):
cur_end = end
continue
if start / cur_end
Unnötig zu sagen, dass es nicht funktioniert: < /p>
In [36]: get_glyph_groups1("C:/Windows/Fonts/Andika-Regular.ttf")
Out[36]: {(0, 122654): []}
< /code>
Wie kann ich es funktionieren? Br />INVALID_UNICODE = [
i
for i in range(1114112)
if unicodedata2.category(chr(i)) in {"Cc", "Cf", "Cn", "Co", "Cs", "Zl", "Zp", "Zs"}
]
INVALID_UNICODE_RANGES = group_consecutive(INVALID_UNICODE)
INVALID_UNICODE_STARTS = [start for start, _ in INVALID_UNICODE_RANGES]
INVALID_UNICODE_RANGES = dict(INVALID_UNICODE_RANGES)
def should_combine(a, b):
i = bisect_right(INVALID_UNICODE_STARTS, a)
start = INVALID_UNICODE_STARTS[max(i - 1, 0)]
end = INVALID_UNICODE_RANGES[start]
if not start
Ich versuche, ein Python -Programm zu schreiben, um den Markdown, wie es durch Stack Exchange direkt in Bilder verwendet wird, umzuwandeln. Die Logik des Markdowns ist recht einfach, ich finde Mathjax eine Herausforderung, das Rendern zu rendern, aber ich habe das gefunden. Ich möchte die totale Kontrolle darüber haben, welcher individuelle Charakter mit welcher Schriftart gerendert wird. Genauer gesagt mag ich diese Andika -Schriftart. Es ist ohne SeriF, und die meisten Sans-Serif-Schriftarten sind schuldig, dass sie nicht unterhalb des Falles mit L-unter-Fall L, in Andika zwei Balken auf dem oberen Fall I und sein unteres Case A keine "Haare" haben. Auf dem Kopf ... < /p> und es unterstützt auch griechische und kyrillische Skripte, aber leider unterstützt es Hiragana, Katakana, Hangul, Chinese usw. Ich werde das verwenden Skript zu "serialisieren" Text aus vielen verschiedenen Sprachen, vorwiegend ist der Text in englischer Sprache, enthält jedoch häufig ganze Texte von Songs in anderen Sprachen. Ich habe vor, Andika für europäische Sprachen und Noto Sans SC für das ostasiatische Skript zu verwenden, aber keiner von ihnen unterstützt Emojis, da ich noch eine Schriftart brauche. Eine ausgewählte Schriftart hat Glyphe für einen bestimmten Charakter. Dies muss für jeden einzelnen Charakter erfolgen. Ein Charakter wird zuerst gegen Andika überprüft, um zu überprüfen, ob sie mit Andika mit Fallo sans sc und dann mit Noto Color Emoji, mit den Fallbacks gerendert werden kann, gerendert werden kann. und wenn alle drei ausfallen, muss eine Ausnahme angehoben werden, die gehandhabt werden ... Für englischen Text ist dies einfach genug, nur ord (c) = 0 und b> = a, und beide Enden sind beispielsweise enthalten (0, 0) ein gültiger Bereich, der nur 0 enthält, und natürlich enthält (5, 9) (5, 6, 7,. 8, 9). Bereich. < /p> Ich habe Folgendes gemacht (Sie benötigen Fonttools und Unicodedata2): < /p> [code]import unicodedata2 from bisect import bisect_right from fontTools.ttLib import TTFont
def get_glyphs_in_font(font_path): return sorted( {code for cmap in TTFont(font_path)["cmap"].tables for code in cmap.cmap} )
def group_consecutive(lst): result = [] start = end = -1e309 for i in lst: if i == end + 1: end = i else: if end != -1e309: result.append((start, end))
start = end = i
result.append((start, end)) return result
def get_glyph_ranges(font_path): return group_consecutive(get_glyphs_in_font(font_path)) [/code] Die Ausgabe ist korrekt, hat jedoch 129 Elemente in der Ausgabe für "andika-regular.ttf" . Es wäre ineffizient, dies für jedes einzelne Zeichen zu tun. von ihnen ungültig, und das folgende findet alle: < /p> [code]INVALID_UNICODE = [ i for i in range(1114112) if unicodedata2.category(chr(i)) in {"Cc", "Cf", "Cn", "Co", "Cs", "Zl", "Zp", "Zs"} ]
INVALID_UNICODE_SET = set(INVALID_UNICODE) < /code> Lassen Sie mich nun die Regeln erklären: Lassen Sie (a, b) (c, d) zwei Bereiche sein, d> = c> b> = a, nun, falls eine der folgenden Angaben ist, ist Eine Untergruppe von Invalid_unicode: (b, c), (b + 1, c), (b + 1, c - 1), (b, c - 1), dann sollten sich die beiden Bereiche mit Form (a, d) verbinden, um (a, d) zu kombinieren . Wenn die oben genannten nicht zutreffen, aber C / B CodePoints im Bereich (B + 1, C - 1) akkretiert werden als Ausnahmen.[(32, 126), (160, 328), (330, 800), (803, 831), (838, 879), (903, 903), (915, 916), (920, 920), (926, 926), (928, 928), ] < /code> Die erste befindet sich neben dem Bereich (0, 32), sodass die erste Iteration (0, 126) haben sollte, danach (127, 160) sind alle ungültig, also sollte es also sollte Kombinieren Sie den zweiten Bereich, um zu bilden (0, 328). Dann gibt es eine Diskontinuität zwischen (0, 328) und (330, 800), aber gemäß der zweiten Regel sollten sie verbunden werden und [329] als Ausnahme festgestellt werden. < /P> die Das Ergebnis für das Beispiel sollte: < /p> sein((0, 928), [329, 801, 802, 832, 833, 834, 835, 836, 837, 880, 881, 882, 883, 884, 885, 886, 887, 890, 891, 892, 893, 894, 895, 900, 901, 902, 904, 905, 906, 908, 910, 911, 912, 913, 914, 917, 918, 919, 921, 922, 923, 924, 925, 927]) < /code> Ich hatte dieses halbe Dutzend Mal ausprobiert, konnte aber das beabsichtigte Ergebnis nicht erzielen. Dies ist mein letzter Versuch, es ist sowohl klug als auch dumm gleichzeitig: < /p> def get_glyph_groups1(font_path): ranges = group_consecutive(get_glyphs_in_font(font_path)) result = {} cur_start, cur_end = 0, 32 cur_missing = [] for start, end in ranges: s1 = cur_end + cur_end not in INVALID_UNICODE_SET e1 = start - start not in INVALID_UNICODE_SET i1 = bisect_right(INVALID_UNICODE, e1) i2 = bisect_right(INVALID_UNICODE, s1)
if i1 - i2 == e1 - s1 and bool(i1 - i2) == bool(e1 - s1): cur_end = end continue
if start / cur_end Unnötig zu sagen, dass es nicht funktioniert: < /p> In [36]: get_glyph_groups1("C:/Windows/Fonts/Andika-Regular.ttf") Out[36]: {(0, 122654): []} < /code> Wie kann ich es funktionieren? Br />INVALID_UNICODE = [ i for i in range(1114112) if unicodedata2.category(chr(i)) in {"Cc", "Cf", "Cn", "Co", "Cs", "Zl", "Zp", "Zs"} ]
INVALID_UNICODE_RANGES = group_consecutive(INVALID_UNICODE) INVALID_UNICODE_STARTS = [start for start, _ in INVALID_UNICODE_RANGES] INVALID_UNICODE_RANGES = dict(INVALID_UNICODE_RANGES)
def should_combine(a, b): i = bisect_right(INVALID_UNICODE_STARTS, a) start = INVALID_UNICODE_STARTS[max(i - 1, 0)] end = INVALID_UNICODE_RANGES[start] if not start
Es wurde gesagt, dass Sie immer Ausnahmen im Programm haben sollten. Aber in letzter Zeit habe ich gehört, dass Sie jetzt immer Laufzeitausnahmen bearbeiten sollten , Ausnahmen wie...
Offensichtlich beschließt Google Chrome on Android, den Text zu ändern, wenn der Text eine bestimmte Länge erreicht hat, um den Text zu ändern und ihn größer zu machen (was alle Arten von Spaß...
Offensichtlich beschließt Google Chrome on Android, den Text zu ändern, wenn der Text eine bestimmte Länge erreicht hat, um den Text zu ändern und ihn größer zu machen (was alle Arten von Spaß...
Offensichtlich beschließt Google Chrome on Android, den Text zu ändern, wenn der Text eine bestimmte Länge erreicht hat, um den Text zu ändern und ihn größer zu machen (was alle Arten von Spaß...