mirror of
https://github.com/freedoom/freedoom.git
synced 2025-09-04 04:25:46 -04:00
graphics: Add kerning for text generator.
Adjust character positions so that some pairs of characters can fit more closely together.
This commit is contained in:
parent
0948019b1a
commit
b37baf5abb
2 changed files with 69 additions and 8 deletions
|
@ -33,6 +33,41 @@
|
||||||
# that are generated, and the text to show in each one.
|
# that are generated, and the text to show in each one.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Adjustments for character position based on character pairs. Some
|
||||||
|
# pairs of characters can fit more snugly together, which looks more
|
||||||
|
# visually appealing. This is highly dependent on the font graphics,
|
||||||
|
# and if the font is changed this probably needs to be redone.
|
||||||
|
|
||||||
|
FONT_KERNING_RULES = {
|
||||||
|
# Right character fits under left character:
|
||||||
|
r'p[aj\.]': -3,
|
||||||
|
r'P[a\.]': -4,
|
||||||
|
r'[PVW][AJj\.]': -4,
|
||||||
|
r't[ajJ\.]': -4,
|
||||||
|
r'f[aj\.]': -2,
|
||||||
|
|
||||||
|
# Some capital letters have overhangs that the 'lower case'
|
||||||
|
# characters can fit under:
|
||||||
|
r'C[Ja-z\.]': -2,
|
||||||
|
r'F[Ja-z\.]': -3,
|
||||||
|
r'T[Ja-z\.]': -5,
|
||||||
|
r'W[Ja-z\.]': -2,
|
||||||
|
r'S[Ja-z\.]': -1,
|
||||||
|
r'V[a-z\.]': -3,
|
||||||
|
|
||||||
|
# Left character fits under right character:
|
||||||
|
r'[alAL][ty479]': -3,
|
||||||
|
r'a[vwVW]': -2,
|
||||||
|
r'A[VW]': -3,
|
||||||
|
r'A[vw]': -2,
|
||||||
|
r'r[ty479]': -2,
|
||||||
|
r'[vwVW][Aa]': -2,
|
||||||
|
r'[Yypv][jJ]': -2,
|
||||||
|
|
||||||
|
# Extra space needed:
|
||||||
|
r'[OUu][Pp]': +1,
|
||||||
|
}
|
||||||
|
|
||||||
white_graphics = {
|
white_graphics = {
|
||||||
'wibp1': 'P1',
|
'wibp1': 'P1',
|
||||||
'wibp2': 'P2',
|
'wibp2': 'P2',
|
||||||
|
|
|
@ -58,7 +58,7 @@ BACKGROUND_COLOR = '#00ffff'
|
||||||
FONT_HEIGHT = 16
|
FONT_HEIGHT = 16
|
||||||
|
|
||||||
# Width of a space character in pixels.
|
# Width of a space character in pixels.
|
||||||
SPACE_WIDTH = 14
|
SPACE_WIDTH = 10
|
||||||
|
|
||||||
# Output from 'identify' looks like this:
|
# Output from 'identify' looks like this:
|
||||||
# fontchars/font033.gif GIF 9x16 9x16+0+0 8-bit sRGB 32c 194B 0.000u 0:00.000
|
# fontchars/font033.gif GIF 9x16 9x16+0+0 8-bit sRGB 32c 194B 0.000u 0:00.000
|
||||||
|
@ -93,10 +93,19 @@ def invoke_command(command):
|
||||||
return subprocess.call(command)
|
return subprocess.call(command)
|
||||||
|
|
||||||
class Font(object):
|
class Font(object):
|
||||||
def __init__(self, fontdir):
|
def __init__(self, fontdir, kerning_table={}):
|
||||||
self.fontdir = fontdir
|
self.fontdir = fontdir
|
||||||
|
self.kerning_table = self.compile_kerning_table(kerning_table)
|
||||||
self.get_font_widths()
|
self.get_font_widths()
|
||||||
|
|
||||||
|
def compile_kerning_table(self, kerning_table):
|
||||||
|
"""Given a dictionary of kerning patterns, compile Regexps."""
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
for pattern, adjust in kerning_table.items():
|
||||||
|
result[re.compile(pattern)] = adjust
|
||||||
|
return result
|
||||||
|
|
||||||
def get_font_widths(self):
|
def get_font_widths(self):
|
||||||
charfiles = glob('%s/font*.gif' % self.fontdir)
|
charfiles = glob('%s/font*.gif' % self.fontdir)
|
||||||
self.char_widths = {}
|
self.char_widths = {}
|
||||||
|
@ -116,20 +125,37 @@ class Font(object):
|
||||||
def char_filename(self, c):
|
def char_filename(self, c):
|
||||||
return '%s/font%03d.gif' % (self.fontdir, ord(c))
|
return '%s/font%03d.gif' % (self.fontdir, ord(c))
|
||||||
|
|
||||||
|
def kerning_adjust(self, char_1, char_2):
|
||||||
|
"""Get kerning adjustment for pair of characters.
|
||||||
|
|
||||||
|
Zero means no adjustment. A negative value adjusts to the
|
||||||
|
left and a positive value adjusts to the right.
|
||||||
|
"""
|
||||||
|
for pattern, adjust in self.kerning_table.items():
|
||||||
|
if pattern.match(char_1 + char_2):
|
||||||
|
return adjust
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
def iterate_char_positions(self, text):
|
def iterate_char_positions(self, text):
|
||||||
"""Iterate over characters in string, yielding character with
|
"""Iterate over characters in string, yielding character with
|
||||||
position it should be placed at in the output file.
|
position it should be placed at in the output file.
|
||||||
"""
|
"""
|
||||||
x = 0
|
x = 0
|
||||||
|
last_c = ' '
|
||||||
for c in text:
|
for c in text:
|
||||||
if c == ' ':
|
if c == ' ':
|
||||||
x += SPACE_WIDTH
|
x += SPACE_WIDTH
|
||||||
if c not in self:
|
|
||||||
continue
|
|
||||||
yield c, x
|
|
||||||
|
|
||||||
# Characters overlap by one pixel.
|
if c in self:
|
||||||
x += self.char_width(c) - 1
|
x += self.kerning_adjust(last_c, c)
|
||||||
|
|
||||||
|
yield c, x
|
||||||
|
|
||||||
|
# Characters overlap by one pixel.
|
||||||
|
x += self.char_width(c) - 1
|
||||||
|
|
||||||
|
last_c = c
|
||||||
|
|
||||||
# We need to add back the missing pixel from the right side
|
# We need to add back the missing pixel from the right side
|
||||||
# of the last char.
|
# of the last char.
|
||||||
|
@ -198,7 +224,7 @@ def generate_graphics(graphics, color=COLOR_WHITE):
|
||||||
print("# %s.gif: '%s'" % (name, text))
|
print("# %s.gif: '%s'" % (name, text))
|
||||||
font.render_text(text, '%s.gif' % name, color=color)
|
font.render_text(text, '%s.gif' % name, color=color)
|
||||||
|
|
||||||
font = Font('fontchars')
|
font = Font('fontchars', kerning_table=FONT_KERNING_RULES)
|
||||||
|
|
||||||
generate_graphics(red_graphics, COLOR_RED)
|
generate_graphics(red_graphics, COLOR_RED)
|
||||||
generate_graphics(blue_graphics, COLOR_BLUE)
|
generate_graphics(blue_graphics, COLOR_BLUE)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue