Beispiel #1
0
def glyph_metrics(string: str) -> Iterable[Metrics]:
    font, upem, buffer = setup_harfbuzz()
    HarfBuzz.buffer_clear_contents(buffer)

    if False:
        HarfBuzz.buffer_add_utf8(buffer, string.encode("utf-8"), 0, -1)
    elif sys.maxunicode == 0x10FFFF:
        HarfBuzz.buffer_add_utf32(
            buffer,
            array.array("I", string.encode("utf-32"))[1:], 0, -1)
    else:
        HarfBuzz.buffer_add_utf16(
            buffer,
            array.array("H", string.encode("utf-16"))[1:], 0, -1)

    # If this doesn't get run, the Python interpreter crashes
    HarfBuzz.buffer_guess_segment_properties(buffer)

    HarfBuzz.shape(font, buffer, [])
    codepoints = [
        info.codepoint for info in HarfBuzz.buffer_get_glyph_infos(buffer)
    ]
    positions = HarfBuzz.buffer_get_glyph_positions(buffer)

    for extents, pos in zip(glyphs_extents(font, codepoints), positions):
        yield Metrics(
            Positions(pos.x_advance, pos.y_advance, pos.x_offset,
                      pos.y_offset),
            extents,
            upem,
        )
Beispiel #2
0
    def shape(self, text_="abvd", flag=False):
        text = text_
        # Need to create GLib.Bytes explicitly until this bug is fixed:
        # https://bugzilla.gnome.org/show_bug.cgi?id=729541

        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
        #
        if flag:
            # If you do not care about cluster values reflecting Python
            # string indices, then this is quickest way to add text to
            # buffer:
            #         void hb_buffer_add_utf8 (hb_buffer_t *buffer,
            #                     const char *text,
            #                     int text_length,
            #                     unsigned int item_offset,
            #                     int item_length);
            hb.buffer_add_utf8(buf, text.encode('utf-8'), 0, -1)
            # Otherwise, then following handles both narrow and wide
            # Python builds:
        elif sys.maxunicode == 0x10FFFF:
            hb.buffer_add_utf32(buf, array.array('I', text.encode('utf-32le')),
                                0, -1)
        else:
            hb.buffer_add_utf16(buf, array.array('H', text.encode('utf-16le')),
                                0, -1)

        hb.buffer_guess_segment_properties(buf)

        hb.shape(self.__font, buf, [])
        # del font

        infos = hb.buffer_get_glyph_infos(buf)
        # positions = hb.buffer_get_glyph_positions(buf)

        return [info.codepoint for info in infos]
Beispiel #3
0
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
Beispiel #4
0
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}")
Beispiel #5
0
#
# See https://github.com/harfbuzz/harfbuzz/pull/271
#
if False:
    # If you do not care about cluster values reflecting Python
    # string indices, then this is quickest way to add text to
    # buffer:
    hb.buffer_add_utf8(buf, text.encode('utf-8'), 0, -1)
    # Otherwise, then following handles both narrow and wide
    # Python builds:
elif sys.maxunicode == 0x10FFFF:
    hb.buffer_add_utf32(buf, array.array('I', text.encode('utf-32')), 0, -1)
else:
    hb.buffer_add_utf16(buf, array.array('H', text.encode('utf-16')), 0, -1)

hb.buffer_guess_segment_properties(buf)

hb.shape(font, buf, [])
del font

infos = hb.buffer_get_glyph_infos(buf)
positions = hb.buffer_get_glyph_positions(buf)

for info, pos in zip(infos, positions):
    gid = info.codepoint
    cluster = info.cluster
    x_advance = pos.x_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))
Beispiel #6
0
# See https://github.com/harfbuzz/harfbuzz/pull/271
#
if False:
	# If you do not care about cluster values reflecting Python
	# string indices, then this is quickest way to add text to
	# buffer:
	hb.buffer_add_utf8 (buf, text.encode('utf-8'), 0, -1)
	# Otherwise, then following handles both narrow and wide
	# Python builds:
elif sys.maxunicode == 0x10FFFF:
	hb.buffer_add_utf32 (buf, array.array('I', text.encode('utf-32')), 0, -1)
else:
	hb.buffer_add_utf16 (buf, array.array('H', text.encode('utf-16')), 0, -1)


hb.buffer_guess_segment_properties (buf)

hb.shape (font, buf, [])
del font

infos = hb.buffer_get_glyph_infos (buf)
positions = hb.buffer_get_glyph_positions (buf)

for info,pos in zip(infos, positions):
	gid = info.codepoint
	cluster = info.cluster
	x_advance = pos.x_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))