-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #912 from ryanoasis/feature/avoid-patching-proport…
…ional Avoid patching proportional sources
- Loading branch information
Showing
4 changed files
with
177 additions
and
5 deletions.
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,94 @@ | ||
#!/usr/bin/env python3 | ||
# coding=utf8 | ||
|
||
import sys | ||
import os.path | ||
import fontforge | ||
|
||
###### Some helpers (code from font-patcher) | ||
|
||
def check_panose_monospaced(font): | ||
""" Check if the font's Panose flags say it is monospaced """ | ||
# https://forum.high-logic.com/postedfiles/Panose.pdf | ||
panose = list(font.os2_panose) | ||
if panose[0] < 2 or panose[0] > 5: | ||
return -1 # invalid Panose info | ||
panose_mono = ((panose[0] == 2 and panose[3] == 9) or | ||
(panose[0] == 3 and panose[3] == 3)) | ||
return 1 if panose_mono else 0 | ||
|
||
def is_monospaced(font): | ||
""" Check if a font is probably monospaced """ | ||
# Some fonts lie (or have not any Panose flag set), spot check monospaced: | ||
width = -1 | ||
width_mono = True | ||
for glyph in [ 0x49, 0x4D, 0x57, 0x61, 0x69, 0x2E ]: # wide and slim glyphs 'I', 'M', 'W', 'a', 'i', '.' | ||
if not glyph in font: | ||
# A 'strange' font, believe Panose | ||
return check_panose_monospaced(font) == 1 | ||
# print(" -> {} {}".format(glyph, font[glyph].width)) | ||
if width < 0: | ||
width = font[glyph].width | ||
continue | ||
if font[glyph].width != width: | ||
# Exception for fonts like Code New Roman Regular or Hermit Light/Bold: | ||
# Allow small 'i' and dot to be smaller than normal | ||
# I believe the source fonts are buggy | ||
if glyph in [ 0x69, 0x2E ]: | ||
if width > font[glyph].width: | ||
continue | ||
(xmin, _, xmax, _) = font[glyph].boundingBox() | ||
if width > xmax - xmin: | ||
continue | ||
width_mono = False | ||
break | ||
# We believe our own check more then Panose ;-D | ||
return width_mono | ||
|
||
def get_advance_width(font, extended, minimum): | ||
""" Get the maximum/minimum advance width in the extended(?) range """ | ||
width = 0 | ||
if extended: | ||
end = 0x17f | ||
else: | ||
end = 0x07e | ||
for glyph in range(0x21, end): | ||
if not glyph in font: | ||
continue | ||
if glyph in range(0x7F, 0xBF): | ||
continue # ignore special characters like '1/4' etc | ||
if width == 0: | ||
width = font[glyph].width | ||
continue | ||
if not minimum and width < font[glyph].width: | ||
width = font[glyph].width | ||
elif minimum and width > font[glyph].width: | ||
width = font[glyph].width | ||
return width | ||
|
||
|
||
###### Let's go! | ||
|
||
if len(sys.argv) < 2: | ||
print('Usage: {} font_name [font_name ...]\n'.format(sys.argv[0])) | ||
sys.exit(1) | ||
|
||
print('Examining {} font files'.format(len(sys.argv) - 1)) | ||
|
||
|
||
for filename in sys.argv[1:]: | ||
fullfile = os.path.basename(filename) | ||
fname = os.path.splitext(fullfile)[0] | ||
|
||
font = fontforge.open(filename, 1) | ||
width_mono = is_monospaced(font) | ||
panose_mono = check_panose_monospaced(font) | ||
if (width_mono and panose_mono == 0) or (not width_mono and panose_mono == 1): | ||
print('[{:50.50}] Warning: Monospaced check: Panose assumed to be wrong; Glyph widths {} / {} - {} and Panose says "monospace {}" ({})'.format(fullfile, get_advance_width(font, False, True), | ||
get_advance_width(font, False, False), get_advance_width(font, True, False), panose_mono, list(font.os2_panose))) | ||
if not width_mono: | ||
print('[{:50.50}] Warning: Sourcefont is not monospaced - forcing to monospace not advisable, results might be useless; Glyph widths {} / {} - {}'.format(fullfile, get_advance_width(font, False, True), | ||
get_advance_width(font, False, False), get_advance_width(font, True, False), panose_mono, list(font.os2_panose))) | ||
else: | ||
print('[{:50.50}] OK'.format(fullfile)) | ||
font.close() |
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