diff --git a/lib/plot.py b/lib/plot.py index fa3ed89..8e3e0dd 100644 --- a/lib/plot.py +++ b/lib/plot.py @@ -2,6 +2,7 @@ import cairo import numpy as np +from HersheyFonts import HersheyFonts class Paper: @@ -135,6 +136,17 @@ A6_PORTRAIT = Paper(105, 148, 8) A6_LANDSCAPE = Paper(148, 105, 8) +def _measure_text(hf, text): + points = np.array([point for stroke in hf.strokes_for_text(text) + for point in stroke]) + return { + 'x': points[:, 0].min(), + 'y': points[:, 1].min(), + 'width': points[:, 0].max() - points[:, 0].min(), + 'height': points[:, 1].max() - points[:, 1].min(), + } + + class Plotter: def __init__(self, paper, line_width=0, colour=[0, 0, 0, 1]): @@ -174,6 +186,49 @@ class Plotter: self.line_to(self.paper.top_left()) self.line_to(self.paper.bottom_left()) + def draw_text(self, text, position, font='futural', height=10, x_scale=1, + fit_width=None, fixed_height=True, spacing=None, + v_align='baseline', h_align='left'): + x, y = position + hf = HersheyFonts() + hf.load_default_font(font) + hf.normalize_rendering(height) + hf.render_options['scaley'] *= -1 + hf.render_options['scalex'] *= x_scale + if spacing is not None: + hf.render_options['spacing'] = spacing + + hf.render_options['yofs'] -= hf.render_options['base_line'] + + metrics = _measure_text(hf, text) + + if fit_width is not None: + hf.render_options['scalex'] *= fit_width / metrics['width'] + hf.render_options['spacing'] *= fit_width / metrics['width'] + metrics['x'] *= fit_width / metrics['width'] + if not fixed_height: + hf.render_options['scaley'] *= fit_width / metrics['width'] + metrics['y'] *= fit_width / text_width + metrics['height'] *= fit_width / metrics['width'] + metrics['width'] = fit_width + + if h_align == 'centre': + x -= metrics['width'] / 2 + elif h_align == 'right': + x -= metrics['width'] + + x -= metrics['x'] + + if v_align == 'bottom': + y -= metrics['y'] + metrics['height'] + elif v_align == 'top': + y -= metrics['y'] + + for s in hf.strokes_for_text(text): + self.move_to((s[0][0] + x, s[0][1] + y)) + for p in s[1:]: + self.line_to((p[0] + x, p[1] + y)) + class SVGPlotter(Plotter): diff --git a/requirements.txt b/requirements.txt index c1787fd..10fd6d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,6 +20,7 @@ executing==1.2.0 fastjsonschema==2.16.2 fonttools==4.38.0 fqdn==1.5.1 +Hershey-Fonts==2.1.0 idna==3.4 ipykernel==6.19.2 ipython==8.7.0