Beispiel #1
0
def render_cluster_glyph_items(
        ctx: cairocffi.Context,
        layout: pangocffi.Layout
):
    """
    Renders each cluster within a layout with a unique rotation and color.

    Warning: Does not support bidirectional text.

    :param ctx:
        a Cairo context
    :param layout:
        a Pango layout
    """
    layout_run_iter = layout.get_iter()
    layout_cluster_iter = layout.get_iter()
    layout_text = layout.get_text()

    alternate = False
    while True:

        layout_run = layout_run_iter.get_run()
        layout_line_baseline = layout_run_iter.get_baseline()

        if layout_run is None:
            if not layout_run_iter.next_run():
                break
            continue

        clusters = get_clusters_from_glyph_item(layout_run, layout_text)
        for cluster in clusters:
            cluster_extents = layout_cluster_iter.get_cluster_extents()[1]
            layout_cluster_iter.next_cluster()
            alternate = not alternate
            ctx.set_source_rgba(0.5, 0, 1 if alternate else 0.5, 0.9)
            ctx.save()
            ctx.translate(
                pangocffi.units_to_double(cluster_extents.x),
                pangocffi.units_to_double(layout_line_baseline)
            )
            ctx.rotate(-0.05 if alternate else 0.05)
            pangocairocffi.show_glyph_item(
                ctx,
                layout_text,
                cluster
            )
            ctx.restore()

        if not layout_run_iter.next_run():
            break
Beispiel #2
0
    def test_layout_iter_properties():
        context = Context()
        layout = Layout(context)
        layout_iter = layout.get_iter()

        assert layout_iter.next_run() is False
        assert layout_iter.next_char() is False
        assert layout_iter.next_cluster() is False
        assert layout_iter.next_line() is False
        assert layout_iter.at_last_line() is True
        assert layout_iter.get_index() == 0
        assert layout_iter.get_baseline() == 0

        assert isinstance(layout_iter.get_char_extents(), Rectangle)

        cluster_ink, cluster_logical = layout_iter.get_cluster_extents()
        assert isinstance(cluster_ink, Rectangle)
        assert isinstance(cluster_logical, Rectangle)

        run_ink, run_logical = layout_iter.get_run_extents()
        assert isinstance(run_ink, Rectangle)
        assert isinstance(run_logical, Rectangle)

        y0, y1 = layout_iter.get_line_yrange()
        assert y0 == 0
        assert y1 == 0

        line_ink, line_logical = layout_iter.get_line_extents()
        assert isinstance(line_ink, Rectangle)
        assert isinstance(line_logical, Rectangle)

        layout_ink, layout_logical = layout_iter.get_layout_extents()
        assert isinstance(layout_ink, Rectangle)
        assert isinstance(layout_logical, Rectangle)
Beispiel #3
0
    def test_glyph_item_iterator(self):
        text = 'Hi from Παν語'
        layout = Layout(self.pango_context)
        layout.set_text(text)
        layout_iter = layout.get_iter()

        glyph_item_iter = GlyphItemIter()
        assert isinstance(glyph_item_iter.get_pointer(), ffi.CData)

        assert glyph_item_iter.init_start(
            layout_iter.get_run(),
            text
        )

        assert isinstance(glyph_item_iter.glyph_item, GlyphItem)
        assert glyph_item_iter.text == text

        # Verify first cluster
        assert glyph_item_iter.start_glyph == 0
        assert glyph_item_iter.start_index == 0
        assert glyph_item_iter.start_char == 0
        assert glyph_item_iter.end_glyph == 1
        assert glyph_item_iter.end_index == 1
        assert glyph_item_iter.end_char == 1

        assert not glyph_item_iter.prev_cluster()
        assert glyph_item_iter.next_cluster()

        # Verify second cluster
        assert glyph_item_iter.start_glyph == 1
        assert glyph_item_iter.start_index == 1
        assert glyph_item_iter.start_char == 1
        assert glyph_item_iter.end_glyph == 2
        assert glyph_item_iter.end_index == 2
        assert glyph_item_iter.end_char == 2

        assert glyph_item_iter.init_end(
            layout_iter.get_run(),
            text
        )

        # Verify last cluster
        assert glyph_item_iter.start_glyph == 7
        assert glyph_item_iter.start_index == 7
        assert glyph_item_iter.start_char == 7
        assert glyph_item_iter.end_glyph == 8
        assert glyph_item_iter.end_index == 8
        assert glyph_item_iter.end_char == 8

        assert not glyph_item_iter.next_cluster()
        assert glyph_item_iter.prev_cluster()

        # Verify second to last cluster
        assert glyph_item_iter.start_glyph == 6
        assert glyph_item_iter.start_index == 6
        assert glyph_item_iter.start_char == 6
        assert glyph_item_iter.end_glyph == 7
        assert glyph_item_iter.end_index == 7
        assert glyph_item_iter.end_char == 7
    def test_layout_run_properties(self):
        layout = Layout(self.pango_context)
        layout.set_text('Hello World')
        layout_iter = layout.get_iter()

        layout_run = layout_iter.get_run()
        layout_run_item = layout_run.item
        assert isinstance(layout_run_item, Item)
    def test_glyph_item_copies(self):
        text = 'Hi from Παν語'
        layout = Layout(self.pango_context)
        layout.set_text(text)
        layout_iter = layout.get_iter()
        layout_run = layout_iter.get_run()

        assert layout_run.copy().get_pointer() != layout_run.get_pointer()
    def test_layout_run_from_pointer(self):
        layout = Layout(self.pango_context)
        layout.set_text('Hello World')
        layout_iter = layout.get_iter()

        layout_run = layout_iter.get_run()
        same_layout = LayoutRun.from_pointer(layout_run.get_pointer())

        assert isinstance(same_layout, LayoutRun)
    def test_glyph_item_get_logical_widths(self):
        text = 'Hi from Παν語'
        layout = Layout(self.pango_context)
        layout.set_text(text)
        layout_iter = layout.get_iter()
        layout_run = layout_iter.get_run()
        logical_widths = layout_run.get_logical_widths(text)

        assert len(logical_widths) == 8
        assert isinstance(logical_widths[0], int)
Beispiel #8
0
    def test_layout_iter_pointer(self):
        layout = Layout(self.pango_context)
        layout_iter = layout.get_iter()
        assert isinstance(layout_iter, LayoutIter)
        assert isinstance(layout_iter.get_pointer(), ffi.CData)

        pointer_shallow_copy = layout_iter.get_pointer()
        layout_iter_shallow_copy = LayoutIter.from_pointer(
            pointer_shallow_copy
        )
        assert isinstance(layout_iter_shallow_copy, LayoutIter)
        assert isinstance(layout_iter_shallow_copy.get_pointer(), ffi.CData)
    def test_glyph_item_splits(self):
        text = 'Hi from Παν語'
        layout = Layout(self.pango_context)
        layout.set_text(text)
        layout_iter = layout.get_iter()
        layout_run = layout_iter.get_run()
        layout_run_hi = layout_run.split(text, 3)

        # Substring "Hi "
        assert layout_run_hi.item.num_chars == 3
        assert layout_run_hi.item.offset == 0

        # Substring "from "
        assert layout_run.item.num_chars == 5
        assert layout_run.item.offset == 3
Beispiel #10
0
def _show_layout_baseline(
        context: cairocffi.Context,
        layout: pangocffi.Layout
):
    layout_iter = layout.get_iter()
    context.set_line_width(0.5)
    context.set_dash([1, 1])
    while True:
        extents = layout_iter.get_line_extents()
        baseline = layout_iter.get_baseline()
        y_ranges = layout_iter.get_line_yrange()

        context.set_source_rgba(1, 0, 0, 0.9)
        context.move_to(
            pangocffi.units_to_double(extents[0].x),
            pangocffi.units_to_double(y_ranges[0])
        )
        context.line_to(
            pangocffi.units_to_double(extents[0].x + extents[0].width),
            pangocffi.units_to_double(y_ranges[0])
        )
        context.stroke()

        context.set_source_rgba(0, 1, 0, 0.9)
        context.stroke()
        context.move_to(
            pangocffi.units_to_double(extents[0].x),
            pangocffi.units_to_double(baseline)
        )
        context.line_to(
            pangocffi.units_to_double(extents[0].x + extents[0].width),
            pangocffi.units_to_double(baseline)
        )
        context.stroke()

        context.set_source_rgba(0, 0, 1, 0.9)
        context.move_to(
            pangocffi.units_to_double(extents[0].x),
            pangocffi.units_to_double(y_ranges[1])
        )
        context.line_to(
            pangocffi.units_to_double(extents[0].x + extents[0].width),
            pangocffi.units_to_double(y_ranges[1])
        )
        context.stroke()

        if not layout_iter.next_run():
            break
Beispiel #11
0
def _show_layout_line_logical_extents(
        context: cairocffi.Context,
        layout: pangocffi.Layout
):
    layout_iter = layout.get_iter()
    context.set_line_width(0.5)
    context.set_dash([1, 1])
    alternate = True
    while True:
        alternate = not alternate
        extents = layout_iter.get_line_extents()
        context.set_source_rgba(0, 0, 1 if alternate else 0.5, 0.9)
        _rectangle_path(context, extents[1])
        context.stroke()
        _coordinate_path(context, (extents[1].x, extents[1].y))
        context.fill()

        if not layout_iter.next_run():
            break
    def test_item_properties(self):
        layout = Layout(self.pango_context)
        layout.set_text('Hi from Παν語')
        layout_iter = layout.get_iter()

        layout_run = layout_iter.get_run()
        layout_run_item = layout_run.item

        assert layout_run_item.length == 8
        assert layout_run_item.offset == 0
        assert layout_run_item.num_chars == 8
        assert isinstance(layout_run_item.get_pointer(), ffi.CData)

        assert layout_iter.next_run()
        layout_run = layout_iter.get_run()
        layout_run_item = layout_run.item

        assert layout_run_item.length == 6
        assert layout_run_item.offset == 8
        assert layout_run_item.num_chars == 3
        assert isinstance(layout_run_item.get_pointer(), ffi.CData)
Beispiel #13
0
def render_run_glyph_items(
        ctx: cairocffi.Context,
        layout: pangocffi.Layout
) -> None:
    """
    Renders each layout run within a layout with a unique rotation and color.

    :param ctx:
        a Cairo context
    :param layout:
        a Pango layout
    """
    layout_iter = layout.get_iter()
    layout_text = layout.get_text()

    alternate = False
    while True:
        layout_run = layout_iter.get_run()
        layout_run_extents = layout_iter.get_run_extents()[1]
        layout_line_baseline = layout_iter.get_baseline()

        if layout_run is None:
            if not layout_iter.next_run():
                break
            continue

        alternate = not alternate
        ctx.set_source_rgba(0, 0.5, 1 if alternate else 0.5, 0.9)
        ctx.save()
        ctx.translate(
            pangocffi.units_to_double(layout_run_extents.x),
            pangocffi.units_to_double(layout_line_baseline)
        )
        ctx.rotate(0.05 if alternate else -0.05)
        pangocairocffi.show_glyph_item(ctx, layout_text, layout_run)
        ctx.restore()

        if not layout_iter.next_run():
            break
Beispiel #14
0
    def test_layout_iter_properties(self):
        layout = Layout(self.pango_context)
        layout_iter = layout.get_iter()

        assert layout_iter.next_run() is False
        assert layout_iter.next_char() is False
        assert layout_iter.next_cluster() is False
        assert layout_iter.next_line() is False
        assert layout_iter.at_last_line() is True
        assert layout_iter.get_index() == 0
        # Even with no text in the layout, the layout will still have a
        # baseline corresponding to the selected font description.
        assert layout_iter.get_baseline() > 0

        assert isinstance(layout_iter.get_char_extents(), Rectangle)

        cluster_ink, cluster_logical = layout_iter.get_cluster_extents()
        assert isinstance(cluster_ink, Rectangle)
        assert isinstance(cluster_logical, Rectangle)

        run_ink, run_logical = layout_iter.get_run_extents()
        assert isinstance(run_ink, Rectangle)
        assert isinstance(run_logical, Rectangle)

        y0, y1 = layout_iter.get_line_yrange()
        assert y0 == 0
        # Even with no text in the layout, the layout will still have a
        # y-range corresponding to the selected font description.
        assert y1 > 0

        line_ink, line_logical = layout_iter.get_line_extents()
        assert isinstance(line_ink, Rectangle)
        assert isinstance(line_logical, Rectangle)

        layout_ink, layout_logical = layout_iter.get_layout_extents()
        assert isinstance(layout_ink, Rectangle)
        assert isinstance(layout_logical, Rectangle)
Beispiel #15
0
def _show_layout_y_ranges(
        context: cairocffi.Context,
        layout: pangocffi.Layout
):
    layout_iter = layout.get_iter()
    context.set_line_width(0.5)
    context.set_dash([1, 1])
    alternate = True
    while True:
        alternate = not alternate
        extents = layout_iter.get_line_extents()
        y_ranges = layout_iter.get_line_yrange()

        context.set_source_rgba(0, 0, 1 if alternate else 0.5, 0.9)
        context.move_to(
            pangocffi.units_to_double(extents[0].x),
            pangocffi.units_to_double(y_ranges[0])
        )
        context.line_to(
            pangocffi.units_to_double(extents[0].x + extents[0].width),
            pangocffi.units_to_double(y_ranges[0])
        )
        context.stroke()

        context.move_to(
            pangocffi.units_to_double(extents[0].x),
            pangocffi.units_to_double(y_ranges[1])
        )
        context.line_to(
            pangocffi.units_to_double(extents[0].x + extents[0].width),
            pangocffi.units_to_double(y_ranges[1])
        )
        context.stroke()

        if not layout_iter.next_run():
            break
Beispiel #16
0
def compute_subtext_extents(layout: Layout, parsed_text,
                            id_index: int) -> Tuple[float, float]:
    """
    Returns the x coordinate and width of a subtext of a single line.
    """
    assert layout.get_line_count() == 1
    (start, end) = get_byte_range(parsed_text, id_index)
    iter = layout.get_iter()
    x = None
    width = 0

    while True:
        byte_offset = iter.get_index()
        if start <= byte_offset < end:
            extents = from_pango_rect(iter.get_char_extents())
            if x is None:
                assert start == byte_offset
                x = extents.x
            width += extents.width

        if byte_offset >= end or not iter.next_char():
            break
    assert x is not None
    return (x, width)
Beispiel #17
0
 def test_layout_iter_pointer():
     context = Context()
     layout = Layout(context)
     layout_iter = layout.get_iter()
     assert isinstance(layout_iter.get_pointer(), ffi.CData)
Beispiel #18
0
    def test_layout_iterator_run_returns_none(self):
        layout = Layout(self.pango_context)
        layout_iter = layout.get_iter()

        assert layout_iter.get_run() is None
Beispiel #19
0
    def test_layout_iterator_run_returns_none():
        context = Context()
        layout = Layout(context)
        layout_iter = layout.get_iter()

        assert layout_iter.get_run() is None