def setup_harfbuzz() -> Tuple[HarfBuzz.font_t, HarfBuzz.buffer_t]: """ Finds a font for HarfBuzz to use, and creates a buffer Because this is wrapped with functools.lru_cache, the buffer returned may have text still in it, which means gi.repository.HarfBuzz.buffer_clear_contents() will need to be called on the buffer to return it to its empty state """ font_file = get_font_file() font_blob = HarfBuzz.glib_blob_create( GLib.Bytes.new(font_file.read_bytes())) face = HarfBuzz.face_create(font_blob, 0) del font_blob font = HarfBuzz.font_create(face) upem = HarfBuzz.face_get_upem(face) del face HarfBuzz.font_set_scale(font, 100, 100) HarfBuzz.ot_font_set_funcs(font) buffer = HarfBuzz.buffer_create() # HarfBuzz.buffer_set_message_func( # buffer, # lambda *args: True, # 1, # 0, # ) return (font, upem, buffer)
def buildCompatChars(sfd, ttf): zwj = u'\u200D' ranges = ( (0xfb50, 0xfbb1), (0xfbd3, 0xfd3d), (0xfd50, 0xfdf9), (0xfdfc, 0xfdfc), (0xfe70, 0xfefc), ) with open(ttf, "rb") as f: data = f.read() blob = HarfBuzz.glib_blob_create(GLib.Bytes.new(data)) face = HarfBuzz.face_create(blob, 0) hbfont = HarfBuzz.font_create(face) upem = HarfBuzz.face_get_upem(face) HarfBuzz.font_set_scale(hbfont, upem, upem) HarfBuzz.ot_font_set_funcs(hbfont) ttfont = TTFont(ttf) for r in ranges: for c in range(r[0], r[1] + 1): dec = ucd.decomposition(unichr(c)).split() if dec: keyword = dec[0] text = u'' for i in dec[1:]: text += unichr(int(str(i), 16)) if keyword == '<initial>': text = text + zwj elif keyword == '<final>': text = zwj + text elif keyword == '<medial>': text = zwj + text + zwj components = shape(text, hbfont) if components: glyph = sfd.createChar(c) glyph.clear() glyph.color = 0xff0000 # red color x = 0 for component in components: gid = component[0] name = ttfont.getGlyphName(gid) x_advance = component[1] x_offset = component[2] y_offset = component[3] matrix = psMat.translate(x + x_offset, y_offset) # ignore blank glyphs, e.g. space or ZWJ if sfd[name].foreground or sfd[name].references: glyph.addReference(name, matrix) x += x_advance glyph.width = x
def buildCompatChars(sfd, ttf): zwj = u'\u200D' ranges = ( (0xfb50, 0xfbb1), (0xfbd3, 0xfd3d), (0xfd50, 0xfdf9), (0xfdfc, 0xfdfc), (0xfe70, 0xfefc), ) with open(ttf, "rb") as f: data = f.read() blob = HarfBuzz.glib_blob_create(GLib.Bytes.new(data)) face = HarfBuzz.face_create(blob, 0) hbfont = HarfBuzz.font_create(face) upem = HarfBuzz.face_get_upem(face) HarfBuzz.font_set_scale(hbfont, upem, upem) HarfBuzz.ot_font_set_funcs(hbfont) ttfont = TTFont(ttf) for r in ranges: for c in range(r[0], r[1]+1): dec = ucd.decomposition(unichr(c)).split() if dec: keyword = dec[0] text = u'' for i in dec[1:]: text += unichr(int(str(i),16)) if keyword == '<initial>': text = text + zwj elif keyword == '<final>': text = zwj + text elif keyword == '<medial>': text = zwj + text + zwj components = shape(text, hbfont) if components: glyph = sfd.createChar(c) glyph.clear() glyph.color = 0xff0000 # red color x = 0 for component in components: gid = component[0] name = ttfont.getGlyphName(gid) x_advance = component[1] x_offset = component[2] y_offset = component[3] matrix = psMat.translate(x + x_offset, y_offset) # ignore blank glyphs, e.g. space or ZWJ if sfd[name].foreground or sfd[name].references: glyph.addReference(name, matrix) x += x_advance glyph.width = x
def getHbFont(fontname): font = open(fontname, "rb") data = font.read() font.close() blob = HarfBuzz.glib_blob_create(GLib.Bytes.new(data)) face = HarfBuzz.face_create(blob, 0) font = HarfBuzz.font_create(face) upem = HarfBuzz.face_get_upem(face) HarfBuzz.font_set_scale(font, upem, upem) HarfBuzz.ot_font_set_funcs(font) return font
def main(): font_file = barcode_wheel.get_font_file() font_blob = HarfBuzz.glib_blob_create(GLib.Bytes.new(font_file.read_bytes())) face = HarfBuzz.face_create(font_blob, 0) del font_blob font = HarfBuzz.font_create(face) upem = HarfBuzz.face_get_upem(face) del face HarfBuzz.font_set_scale(font, upem, upem) text = sys.argv[1] HarfBuzz.ot_font_set_funcs(font) buf = HarfBuzz.buffer_create() HarfBuzz.buffer_set_message_func( buf, # lambda *args: [print(x) for x in args] and True, lambda *args: True, 1, 0, ) if False: HarfBuzz.buffer_add_utf8(buf, text.encode("utf-8"), 0, -1) elif sys.maxunicode == 0x10FFFF: HarfBuzz.buffer_add_utf32( buf, array.array("I", text.encode("utf-32"))[1:], 0, -1 ) else: HarfBuzz.buffer_add_utf16( buf, array.array("H", text.encode("utf-16"))[1:], 0, -1 ) HarfBuzz.buffer_guess_segment_properties(buf) HarfBuzz.shape(font, buf, []) del font infos = HarfBuzz.buffer_get_glyph_infos(buf) positions = HarfBuzz.buffer_get_glyph_positions(buf) for info, pos in zip(infos, positions): gid = info.codepoint cluster = info.cluster print(f"gid {gid} = {cluster} @ {pos.x_advance}, {pos.x_offset}+{pos.y_offset}")
def get_ot_font(path, overwrite=False): if path not in _ot_type_registry or overwrite: # check if is sfd or binary fontname, ext = os.path.splitext(path) if ext == '.sfd': print('Warning: implicit OTF build triggered') os.system('fontforge -script IO/sfd2otf.pe ' + path) filepath = fontname + '.otf' else: filepath = path print('\033[92mLoading font\033[0m :', filepath) HB_face = _hb_face_from_path(filepath) HB_font = hb.font_create(HB_face) upem = hb.face_get_upem(HB_face) hb.font_set_scale(HB_font, upem, upem) hb.ot_font_set_funcs(HB_font) CR_face = fontloader.create_cairo_font_face_for_file(filepath) _ot_type_registry[path] = upem, HB_face, HB_font, CR_face return _ot_type_registry[path]
def __init__(self, font_path): try: assert os.path.isfile(font_path) font_file = open(font_path, "br") fontdata = font_file.read() blob = hb.glib_blob_create(GLib.Bytes.new(fontdata)) del fontdata face = hb.face_create(blob, 0) del blob self.__font = hb.font_create(face) upem = hb.face_get_upem(face) del face font_file.close() hb.font_set_scale(self.__font, upem, upem) #hb.ft_font_set_funcs (font) hb.ot_font_set_funcs(self.__font) except Exception: print(font_path)
return s fontdata = open(sys.argv[1], 'rb').read() text = tounicode(sys.argv[2]) # Need to create GLib.Bytes explicitly until this bug is fixed: # https://bugzilla.gnome.org/show_bug.cgi?id=729541 blob = hb.glib_blob_create(GLib.Bytes.new(fontdata)) face = hb.face_create(blob, 0) del blob font = hb.font_create(face) upem = hb.face_get_upem(face) del face hb.font_set_scale(font, upem, upem) #hb.ft_font_set_funcs (font) hb.ot_font_set_funcs(font) buf = hb.buffer_create() class Debugger(object): def message(self, buf, font, msg, data, _x_what_is_this): print(msg) return True debugger = Debugger() hb.buffer_set_message_func(buf, debugger.message, 1, 0) ## ## Add text to buffer
else: return s fontdata = open (sys.argv[1], 'rb').read () text = tounicode(sys.argv[2]) # Need to create GLib.Bytes explicitly until this bug is fixed: # https://bugzilla.gnome.org/show_bug.cgi?id=729541 blob = hb.glib_blob_create (GLib.Bytes.new (fontdata)) face = hb.face_create (blob, 0) del blob font = hb.font_create (face) upem = hb.face_get_upem (face) del face hb.font_set_scale (font, upem, upem) #hb.ft_font_set_funcs (font) hb.ot_font_set_funcs (font) buf = hb.buffer_create () class Debugger(object): def message (self, buf, font, msg, data, _x_what_is_this): print(msg) return True debugger = Debugger() hb.buffer_set_message_func (buf, debugger.message, 1, 0) ## ## Add text to buffer ## # # See https://github.com/harfbuzz/harfbuzz/pull/271 #