diwhyyyyy
diwhyyyyy

Reputation: 6372

Enable font discretionary ligatures in Cairo

I am trying to render some text with Cairo (via PyCairo):

    with cairo.PSSurface("output.ps", 700, 100) as surface:

        context = cairo.Context(surface)
        context.set_source_rgb(0, 0, 0)

        context.set_font_size(25)

        # Font Style
        context.select_font_face(
            "Adobe Caslon Pro",
            cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)

        # TODO: turn on ligatures

        context.move_to(50, 50)
        context.show_text("dictum")

Which produces something like this:

enter image description here

However, I'd like to enable the discretionary ligatures (that the font definitely does have), so it looks like this (done in LibreOffice with the :dlig font suffix):

enter image description here

I have tried setting various values on FontOptions with no change in the output.

How do you enable discretionary ligatures in Cairo? Preferably Python, but C is OK too if it's not part of the Python binding.

Upvotes: 0

Views: 316

Answers (2)

diwhyyyyy
diwhyyyyy

Reputation: 6372

As @Uli Schlachter says, the answer is Pango.

Specifically, setting the font_features in the Pango markup:

import cairo
import gi
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
gi.require_version('Pango', '1.0')
gi.require_version('PangoCairo', '1.0')
from gi.repository import Pango, PangoCairo

def doText(text):
     with cairo.ImageSurface(cairo.Format.RGB24, w, h) as surface:
        features = [ "dlig" ]
        markup = f'<span font_features="{features}">' + text + '</span>'

        context = cairo.Context(surface)
        context.set_source_rgb(0, 0, 0)

        layout = PangoCairo.create_layout(context)

        font = "Adobe Caslon Pro"
        size = 25

        font_desc = Pango.font_description_from_string(f'{font} {size}')
        layout.set_font_description(font_desc)

        layout.set_markup(markup, -1)

        # position for the text
        context.move_to(100, 100)
        PangoCairo.show_layout(context, layout)

        surface.write_to_png(outfile)

Upvotes: 1

Uli Schlachter
Uli Schlachter

Reputation: 9877

How do you enable discretionary ligatures in Cairo?

You don't.

You are using cairo's toy text API. This only exists as an easy way to "get started" and show examples. It does not do complex things like shaping. And I guess ligeratures are also part of this.

The "real" API is cairo_show_text_glyphs. This function does not render a text, but instead a list of glyphs. The caller of the function has to turn the text into the corresponding glyphs itself.

A good way to do this is to use Pango. Pango does exactly this: Turning text into glyphs.

I bet that there are Python bindings for Pango, but I never used them. If you need, I could provide a C example for Pango + Cairo.

Upvotes: 1

Related Questions