Created
October 21, 2023 10:43
-
-
Save petrblahos/a1be2f125b8ae541a2b78e7f772996a1 to your computer and use it in GitHub Desktop.
Drawing text with a font, using kerning info.
This file contains hidden or 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
from collections import defaultdict | |
import wx | |
from fontTools.pens.wxPen import WxPen | |
from fontTools.ttLib import TTFont | |
class MyFrame(wx.Frame): | |
def __init__(self, ttfont: TTFont): | |
wx.Frame.__init__(self, None, -1, "Font painter") | |
self.font = ttfont | |
self.prepare_kerning() | |
self.Bind(wx.EVT_PAINT, self.on_paint) | |
def prepare_kerning(self): | |
self.kerning_pairs = defaultdict(int) | |
if not "kern" in self.font: | |
return | |
for kern_table in self.font['kern'].kernTables: | |
assert kern_table.version == 0, "kern table version other than 0 not supported" | |
self.kerning_pairs.update(kern_table.kernTable) | |
def on_paint(self, evt): | |
evt.Skip() | |
t = "VAVA7FAT" | |
dc = wx.PaintDC(self) | |
gc = wx.GraphicsContext.Create(dc) | |
height = self.GetSize()[1] | |
units_per_em = self.font['head'].unitsPerEm | |
scale = height / 4 / units_per_em | |
m = gc.CreateMatrix() | |
m.Translate(0, height // 2) | |
m.Scale(scale, -scale) | |
cmap = self.font['cmap'].getBestCmap() | |
for unicode in t: | |
glyph_name = cmap.get(ord(unicode)) | |
if not glyph_name: | |
glyph_name = ".notdef" | |
glyph = self.draw_glyph(gc, glyph_name, m, wx.RED_BRUSH) | |
m.Translate(glyph.width, 0) | |
m = gc.CreateMatrix() | |
m.Translate(0, height // 2) | |
m.Scale(scale, -scale) | |
last = None | |
cmap = self.font['cmap'].getBestCmap() | |
for unicode in t: | |
glyph_name = cmap.get(ord(unicode)) | |
if not glyph_name: | |
glyph_name = ".notdef" | |
m.Translate(self.kerning_pairs[last, glyph_name], 0) | |
glyph = self.draw_glyph(gc, glyph_name, m, wx.BLACK_BRUSH) | |
m.Translate(glyph.width, 0) | |
last = glyph_name | |
def draw_glyph(self, gc, glyph_name, m, brush): | |
glyph = self.font.getGlyphSet()[glyph_name] | |
pen = WxPen(self.font.getGlyphSet()) | |
glyph.draw(pen) | |
pen.path.Transform(m) | |
gc.SetBrush(brush) | |
gc.FillPath(pen.path) | |
return glyph | |
def show_ui(font): | |
app = wx.App() | |
frame = MyFrame(font) | |
frame.Show() | |
frame.Maximize(True) | |
app.MainLoop() | |
if "__main__" == __name__: | |
show_ui(TTFont("/usr/share/fonts/truetype/liberation2/LiberationSans-Regular.ttf")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment