Esempio n. 1
0
def get_Bound_Glyph(abc):

    # Setting Starting position of the first glyph
    glyph_pos = Vector(0, 0)

    # Resetting the buffer
    buf.reset()

    # adding string to buffer
    buf.add_str(abc)

    # Figuring out segmentation properties
    buf.guess_segment_properties()

    # Gernerating Shapes for the text in buffer using the font
    hb.shape(hb_font, buf)

    # Getting glyphs out of buffer (list format)
    glyphs, end_glyph_pos = buf.get_glyphs(glyph_pos)

    # Creating fontface
    qah_face = qah.FontFace.create_for_ft_face(ft_face)

    glyph_extents = (qah.Context.create_for_dummy().set_font_face(
        qah_face).set_font_size(text_size).glyph_extents(glyphs))

    # Getting the bound of the [glyphs]
    figure_bounds = math.ceil(glyph_extents.bounds)

    # Returning glyph and the figure bound
    return (figure_bounds, glyphs)
Esempio n. 2
0
def runHB(font, buf, direction, script, language, features, text, positions):
    buf.clear_contents()
    buf.add_str(text)
    buf.direction = hb.direction_from_string(direction)
    buf.script = hb.script_from_string(script)
    if language:
        buf.language = hb.Language.from_string(language)

    if features:
        features = [hb.Feature.from_string(fea) for fea in features.split(',')]
    else:
        features = []
    hb.shape(font, buf, features)

    info = buf.glyph_infos
    if positions:
        pos = buf.glyph_positions
        glyphs = []
        x = 0
        for i, p in zip(info, pos):
            glyph = font.get_glyph_name(i.codepoint)
            glyph += "@(%d,%d)" % (x + p.x_offset, p.y_offset)
            glyph += "+%d" % p.x_advance
            glyphs.append(glyph)
            x += p.x_advance
        out = "|".join(glyphs)
    else:
        out = "|".join([font.get_glyph_name(i.codepoint) for i in info])

    return "[%s]" % out
Esempio n. 3
0
    def process(self, text):
        if not text:
            return []
        if self._needsInternalUpdate:
            self._updateEngine()

        # TODO: reuse buffer?
        buf = hb.Buffer.create()
        if isinstance(text, list):
            unicodes = []
            for name in text:
                # TODO: use a dict instead?
                gid = self._glyphOrder.index(name)
                unicodes.append(CH_GID_PREFIX + gid)
            buf.add_codepoints(unicodes, len(unicodes), 0, len(unicodes))
        else:
            buf.add_str(text)
        buf.guess_segment_properties()
        hb.shape(self._hbFont, buf, list(self._fontFeatures.values()))

        glyphRecords = []
        for info, pos in zip(buf.glyph_infos, buf.glyph_positions):
            glyphName = self._glyphOrder[info.codepoint]
            if glyphName not in self.font:
                continue
            record = GlyphRecord()
            record.glyph = self.font[glyphName]
            record.cluster = info.cluster
            record.xOffset = pos.x_offset
            record.yOffset = pos.y_offset
            record.xAdvance = pos.x_advance
            record.yAdvance = pos.y_advance
            glyphRecords.append(record)
        del buf
        return glyphRecords
Esempio n. 4
0
    def reshape(self, glyphs, variations):
        font = self.make_font(variations, self._font_funcs)
        buf = self.clear_buffer()
        codepoints = [g.index + GID_OFFSET for g in reversed(glyphs)]
        buf.add_codepoints(codepoints, len(codepoints), 0, len(codepoints))
        hb.shape(font, buf)

        return buf.get_glyphs()[0]
Esempio n. 5
0
def adjust_widths_by_letter(boxes):
    buf = hb.Buffer.create()
    buf.add_str(''.join(b.letter for b in boxes))
    buf.guess_segment_properties()
    font_lib = ft.get_default_lib()
    face = font_lib.find_face('Arial')
    face.set_char_size(size=1, resolution=64)
    font = hb.Font.ft_create(face)
    hb.shape(font, buf)
    # at this point buf.glyph_positions has all the data we need
    for box, position in zip(boxes, buf.glyph_positions):
        box.w = position.x_advance
Esempio n. 6
0
def adjust_widths_by_letter(boxes):
    """Takes a list of boxes as arguments, and uses harfbuzz to
    adjust the width of each box to match the harfbuzz text shaping."""
    buf = hb.Buffer.create()
    buf.add_str(''.join(b.letter for b in boxes))
    buf.guess_segment_properties()
    font_lib = ft.get_default_lib()
    face = font_lib.find_face('Arial')
    face.set_char_size(size=1, resolution=64)
    font = hb.Font.ft_create(face)
    hb.shape(font, buf)
    # at this point buf.glyph_positions has all the data we need
    for box, position in zip(boxes, buf.glyph_positions):
        box.w = position.x_advance
    def shape_word(self, word):
        """
        Shapes a single word and returns the corresponding box. To speed things
        a bit, we cache the shaped words. We assume all our text is in Arabic
        script and language. The direction is almost always right-to-left,
        (we are cheating a bit to avoid doing proper bidirectional text as
        it is largely superfluous for us here).
        """

        assert word

        text = word
        if ord(word[0]) > Q_PUA:
            text = word[1:]

        if text not in self.doc.word_cache:
            self.buffer.clear_contents()
            self.buffer.add_str(text)
            # Everything is RTL except aya numbers and other digits-only words.
            if text[0] in ("\u06DD", "(") or text.isdigit():
                self.buffer.direction = hb.HARFBUZZ.DIRECTION_LTR
            else:
                self.buffer.direction = hb.HARFBUZZ.DIRECTION_RTL
            self.buffer.script = hb.HARFBUZZ.SCRIPT_ARABIC
            self.buffer.language = hb.Language.from_string("ar")
            self.buffer.cluster_level = (
                hb.HARFBUZZ.BUFFER_CLUSTER_LEVEL_MONOTONE_CHARACTERS)

            hb.shape(self.font, self.buffer)

            self.doc.word_cache[text] = Word(text, self.buffer)

        box = Box(self.doc, self.doc.word_cache[text])

        # Flag boxes with “quarter” symbol, as it needs some special
        # handling later.
        if ord(word[0]) > Q_PUA:
            box.quarter = ord(word[0]) - Q_PUA
        if word.startswith(P_STR):
            box.prostration = True

        return box
Esempio n. 8
0
def render_text(context, config, style, layer, text, center, rotation=None):
    if style.description_font is None:
        return
    font = config.fonts[style.description_font]

    context.save()

    buffer = harfbuzz.Buffer.create()
    buffer.add_str(text)
    buffer.guess_segment_properties()
    features = (
        harfbuzz.Feature(tag=harfbuzz.HB.TAG([ord(c) for c in 'kern']),
                         value=1),
        harfbuzz.Feature(tag=harfbuzz.HB.TAG([ord(c) for c in 'liga']),
                         value=1),
    )
    harfbuzz.shape(font.as_hb_font(), buffer, features)

    # reset context
    cliprect = context.clip_rectangle_list[0]
    matrix = context.matrix
    context.transform(matrix.inv())

    # project center into screenspace
    x = center.x - cliprect.left
    y = center.y - cliprect.top

    x *= config.width / cliprect.width
    y *= config.height / cliprect.height

    new_glyphs, endpos = buffer.get_glyphs()

    context.set_font_face(font.as_qah_font())
    context.set_font_size(font.size)
    extends = context.glyph_extents(new_glyphs)

    # attention y is flipped
    context.translate((x, config.height - y))
    if rotation is not None:
        context.rotate(rotation)
    context.translate((-extends.width / 2.0, -extends.y_bearing / 2.0))

    context.glyph_path(new_glyphs)
    path = context.copy_path().extents()

    # map boxes back to pixel space
    #mx = context.matrix.inv()

    mx = qah.Matrix.identity
    mx *= qah.Matrix.translate((-x, -(config.height - y)))
    if rotation is not None:
        mx *= qah.Matrix.rotate(rotation)
    mx *= qah.Matrix.translate(
        (-extends.width / 2.0, -extends.y_bearing / 2.0))

    p1 = mx.map((path.left, path.top))
    p2 = mx.map((path.right, path.top))
    p3 = mx.map((path.right, path.bottom))
    p4 = mx.map((path.left, path.bottom))

    poly = Polygon([
        (-p1.x, -p1.y),
        (-p2.x, -p2.y),
        (-p3.x, -p3.y),
        (-p4.x, -p4.y),
    ])

    if not config.is_occupied(poly, auto_register=True):
        context.source_colour = style.halo_color.color_value
        context.line_width = font.halo_size * 2
        context.stroke()

        context.source_colour = style.text_color.color_value
        context.show_glyphs(new_glyphs)
    else:
        context.new_path()

    # # calculate bounding box in pixel space
    # topleft = context.device_to_user(path.topleft)
    # bottomright = context.device_to_user(path.botright)

    # topleft.x *= -1
    # topleft.y *= -1
    # bottomright.x *= -1
    # bottomright.y *= -1

    # print(topleft, bottomright)
    # if not config.is_occupied(topleft, bottomright, auto_register=True):
    #     context.source_colour = style.halo_color.color_value
    #     context.line_width = font.halo_size * 2
    #     context.stroke()

    #     context.source_colour = style.text_color.color_value
    #     context.show_glyphs(new_glyphs)
    # else:
    #     print("  <> Space occupied")
    #     context.new_path()

    context.restore()
Esempio n. 9
0
import sys
import qahirah as qah
import harfbuzz as hb

ft = qah.get_ft_lib()
text = "kivy"
buf = hb.Buffer.create()
buf.add_str(text)
buf.guess_segment_properties()
ft_face = ft.find_face("Scheherazade")
ft_face.set_char_size(size=1,resolution = qah.base_dpi)
hb_font = hb.Font.ft_create(ft_face)
hb.shape(hb_font,buf)

print (buf.glyph_infos)
print (buf.glyph_positions) 
Esempio n. 10
0
    def shape(self, text, direction):
        buf = self.clear_buffer(direction)
        buf.add_str(text)
        hb.shape(self.font, buf)

        return buf