Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
148 views
in Technique[技术] by (71.8m points)

python - How to create a letter spacing attribute with pycairo?

I'm using Pango + Cairo (through GObject) to render text with python3.7, and would like to set the letter spacing by creating an attribute and attaching that attribute to my pango layout.

In the gnome documentation for pango, I can see that there should be a function called pango_attr_letter_spacing_new (since v1.6). However, if I run Pango.attr_letter_spacing_new, I get the error:

AttributeError: 'gi.repository.Pango' object has no attribute 'attr_letter_spacing_new'

This feels a bit strange, since I can use the pango_attr_type_get_name which should only have been available since v1.22.

I have a work-around by using markup with <span letter_spacing="1234"> but I would rather not go down this route.

Minimal "Working" Example

# pip install pycairo==1.18.0 pygobject==3.32.0

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

width, height = 328, 48

surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
context = cairo.Context(surface)
layout = PangoCairo.create_layout(context)

font_desc = Pango.font_description_from_string('Sans, 40px')
layout.set_font_description(font_desc)

# What I can do
layout.set_markup(f'<span letter_spacing="{1024 * 10}">Hello World</span>')

# What I would like to do
if False:
    letter_spacing_attr = Pango.attr_letter_spacing_new(1024 * 10)

    attr_list = Pango.AttrList()
    attr_list.insert(letter_spacing_attr)
    layout.set_attributes(attr_list)

    layout.set_text('Hello World')

PangoCairo.show_layout(context, layout)

with open('help-me.png', 'wb') as image_file:
    surface.write_to_png(image_file)

Manually creating a LetterSpacing attribute

I have been able to find the enum value Pango.AttrType.LETTER_SPACING, which allows me to do something like this:

c = Pango.AttrClass()
c.type = Pango.AttrType.LETTER_SPACING
a = Pango.Attribute()
a.init(c)

However, I haven't been able to find a way to set the value of it, and it makes me think it is the wrong way to approach things :|

Insert this into an Pango.AttrList, gave an error (not surprisingly) and made the python process segfault next time I did something with Pango:

** (process:17183): WARNING **: 12:00:56.985: (gi/pygi-struct-marshal.c:287):pygi_arg_struct_from_py_marshal: runtime check failed: (g_type_is_a (g_type, G_TYPE_VARIANT) || !is_pointer || transfer == GI_TRANSFER_NOTHING)

Other leads

.. that sadly have lead nowhere :(

  • pygtk listing a function pango.AttrLetterSpacing
    • Pango.AttrLetterSpacing => 'gi.repository.Pango' object has no attribute 'AttrLetterSpacing'
    • Pango.Attrbute.LetterSpacing => type object 'Attribute' has no attribute 'LetterSpacing'
  • the documentation for the pango packge for Vala (which seems to use GObject as well), also shows the attr_letter_spacing_new function -- this doesn't really help that much, but suggests that the function should be available through GObject, although I haven't tried.
question from:https://stackoverflow.com/questions/55533312/how-to-create-a-letter-spacing-attribute-with-pycairo

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Looks like this issue was already solved, using pycairo 1.20.0 and PyGObject 3.40.1:

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

width, height = 328, 48

surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
context = cairo.Context(surface)
layout = PangoCairo.create_layout(context)

font_desc = Pango.font_description_from_string('Sans, 40px')
layout.set_font_description(font_desc)

letter_spacing_attr = Pango.attr_letter_spacing_new(1024 * 10)

attr_list = Pango.AttrList()
attr_list.insert(letter_spacing_attr)
layout.set_attributes(attr_list)

layout.set_text('Hello World')

PangoCairo.show_layout(context, layout)

with open('help-me.png', 'wb') as image_file:
    surface.write_to_png(image_file)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...