-
-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
142 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
from pixel_font_knife.glyph_file_util import GlyphFlavorGroup | ||
|
||
_common_marks = {ord(c) for c in '"\',.'} | ||
|
||
|
||
def _get_latin_alphabet() -> set[int]: | ||
alphabet = set(_common_marks) | ||
|
||
# 0000-007F Basic Latin | ||
for code_point in range(ord('A'), ord('Z') + 1): | ||
alphabet.add(code_point) | ||
for code_point in range(ord('a'), ord('z') + 1): | ||
alphabet.add(code_point) | ||
|
||
# 0080-00FF Latin-1 Supplement | ||
for code_point in range(0x00C0, 0x00D6 + 1): | ||
alphabet.add(code_point) | ||
for code_point in range(0x00D8, 0x00F6 + 1): | ||
alphabet.add(code_point) | ||
for code_point in range(0x00F8, 0x00FF + 1): | ||
alphabet.add(code_point) | ||
|
||
# 0100-017F Latin Extended-A | ||
for code_point in range(0x0100, 0x017F + 1): | ||
alphabet.add(code_point) | ||
|
||
# 0180-024F Latin Extended-B | ||
for code_point in range(0x0180, 0x024F + 1): | ||
if code_point not in (0x01C0, 0x01C1, 0x01C2, 0x01C3): | ||
alphabet.add(code_point) | ||
|
||
# 2C60-2C7F Latin Extended-C | ||
for code_point in range(0x2C60, 0x2C7F + 1): | ||
if code_point not in (0x2C7C, 0x2C7D): | ||
alphabet.add(code_point) | ||
|
||
# A720-A7FF Latin Extended-D | ||
for code_point in range(0xA722, 0xA76F + 1): | ||
alphabet.add(code_point) | ||
for code_point in range(0xA771, 0xA787 + 1): | ||
alphabet.add(code_point) | ||
for code_point in range(0xA78B, 0xA78E + 1): | ||
alphabet.add(code_point) | ||
for code_point in range(0xA790, 0xA7FF + 1): | ||
if chr(code_point).isprintable(): | ||
alphabet.add(code_point) | ||
|
||
# AB30-AB6F Latin Extended-E | ||
for code_point in range(0xAB30, 0xAB5A + 1): | ||
alphabet.add(code_point) | ||
for code_point in range(0xAB60, 0xAB68 + 1): | ||
alphabet.add(code_point) | ||
|
||
# 1E00-1EFF Latin Extended Additional | ||
for code_point in range(0x1E00, 0x1EFF + 1): | ||
alphabet.add(code_point) | ||
|
||
return alphabet | ||
|
||
|
||
def _get_greek_and_coptic_alphabet() -> set[int]: | ||
alphabet = set(_common_marks) | ||
|
||
# 0370-03FF Greek and Coptic | ||
for code_point in range(0x0370, 0x03FF + 1): | ||
if chr(code_point).isprintable() and code_point not in (0x0374, 0x0375, 0x037A, 0x037E, 0x0384, 0x0385, 0x0387): | ||
alphabet.add(code_point) | ||
|
||
return alphabet | ||
|
||
|
||
def _get_cyrillic_alphabet() -> set[int]: | ||
alphabet = set(_common_marks) | ||
|
||
# 0400-04FF Cyrillic | ||
for code_point in range(0x0400, 0x0481 + 1): | ||
alphabet.add(code_point) | ||
for code_point in range(0x048A, 0x04FF + 1): | ||
alphabet.add(code_point) | ||
|
||
# 0500-052F Cyrillic Supplement | ||
for code_point in range(0x0500, 0x052F + 1): | ||
alphabet.add(code_point) | ||
|
||
return alphabet | ||
|
||
|
||
_alphabets = [ | ||
_get_latin_alphabet(), | ||
_get_greek_and_coptic_alphabet(), | ||
_get_cyrillic_alphabet(), | ||
] | ||
|
||
|
||
def calculate_kerning_pairs(context: dict[int, GlyphFlavorGroup]) -> dict[tuple[str, str], int]: | ||
kerning_pairs = {} | ||
for alphabet in _alphabets: | ||
for left_code_point in alphabet: | ||
if left_code_point not in context: | ||
continue | ||
left_glyph_file = context[left_code_point][None] | ||
|
||
if all(mask_row[-1] == 0 for mask_row in left_glyph_file.mask): | ||
continue | ||
mask = left_glyph_file.mask | ||
|
||
for right_code_point in alphabet: | ||
if right_code_point not in context: | ||
continue | ||
right_glyph_file = context[right_code_point][None] | ||
|
||
bitmap = right_glyph_file.bitmap | ||
if right_glyph_file.code_point in _common_marks: | ||
padding = bitmap.calculate_left_padding() | ||
bitmap = bitmap.resize(left=-padding, right=padding) | ||
|
||
offset = 0 | ||
while True: | ||
if mask != mask.plus(bitmap, x=left_glyph_file.width + offset - 1): | ||
break | ||
offset -= 1 | ||
if offset <= -(right_glyph_file.width - 1): | ||
break | ||
if offset < 0: | ||
kerning_pairs[(left_glyph_file.glyph_name, right_glyph_file.glyph_name)] = offset | ||
return kerning_pairs |