def get_text_shape(text, font=None, weight=None, path=None, debug=False): if weight is not None: font = f'{font}:{weight}' if path is None: path = get_font_path(font) base, ext = os.path.splitext(path) ext = ext[1:] with open(path, 'rb') as fid: fontdata = fid.read() bdata = GLib.Bytes.new(fontdata) blob = hb.glib_blob_create(bdata) face = hb.face_create(blob, 0) font = hb.font_create(face) upem = hb.face_get_upem(face) hb.font_set_scale(font, upem, upem) # hb.font_set_ptem(font, font_size) if ext == 'woff': hb.ft_font_set_funcs(font) buf = hb.buffer_create() hb.buffer_add_utf8(buf, text.encode('utf-8'), 0, -1) hb.buffer_guess_segment_properties(buf) hb.shape(font, buf, []) infos = hb.buffer_get_glyph_infos(buf) positions = hb.buffer_get_glyph_positions(buf) extents = [hb.font_get_glyph_extents(font, i.codepoint) for i in infos] if debug: return font, infos, positions, extents norm = upem wh_extract = lambda ext: (ext.extents.width / norm, -ext.extents.height / norm) cluster = [(i.codepoint, i.cluster) for i in infos] shapes = [wh_extract(e) for e in extents] deltas = [(p.x_advance / norm, p.y_advance / norm) for p in positions] offsets = [(p.x_offset / norm, p.y_offset / norm) for p in positions] return cluster, shapes, deltas, offsets
max_iy = -upem for info,pos in zip(infos, positions): gid = info.codepoint cluster = info.cluster x_advance = pos.x_advance y_advance = pos.y_advance x_offset = pos.x_offset y_offset = pos.y_offset print("gid%d=%d@%d,%d+%d" % (gid, cluster, x_advance, x_offset, y_offset)) ### Derived from harfbuzz:src/sample.py ends. ##################################################################### (results, extents) = hb.font_get_glyph_extents(font, info.codepoint) glyph_extents.append(extents) if ((extents.width != 0) and (extents.height !=0)): # don't want invisible glyph to pin the ink box # https://github.com/harfbuzz/harfbuzz/issues/1208 # https://github.com/harfbuzz/harfbuzz/issues/1216 min_ix = min(min_ix, x + pos.x_offset + extents.x_bearing) max_ix = max(max_ix, x + pos.x_offset + extents.x_bearing + extents.width) max_iy = max(max_iy, y + pos.y_offset + extents.y_bearing) min_iy = min(min_iy, y + pos.y_offset + extents.y_bearing + extents.height) x += x_advance y += y_advance def sc(value): return (value * 256)/upem
def glyphs_extents(font: HarfBuzz.font_t, codepoints: Iterable[int]) -> Iterable[Extents]: for extent in (HarfBuzz.font_get_glyph_extents(font, codepoint)[1] for codepoint in codepoints): yield Extents(extent.x_bearing, extent.y_bearing, extent.width, extent.height)