Привет.

Подскажите, пожалуйста, как сделать с помощью библиотеки cairo (pycairo) поворот текста вокруг своего центра?

По умолчанию, можно повернуть его только вокруг своего, так называемого `origin` - точки, которая находится слева внизу будущего текста. То есть, при повороте, текст как бы заваливается на сторону.

Я уже две недели ищу в интернетах такую информацию и нигде найти не могу. По идее, можно использовать библиотеку pango, но там, для чего ведется разработка, нет и не будет возможности поставить эту либу :(

Я честно пробовал сделать транслейт (cr.translate(text_center_x, text_center_y)), но это не помогает. Вообще, в принципе, транслейт никак не влияет на рендеринг текста. Он влияет только на относительное позиционирование “курсора”.

Помогите, пожалуйста, товарищи!
Возможно, нужно иметь дело с матрицами трансформации, в кторых я, откровенно говоря, не силён, как не силён в линейной алгебре.

Вот картинка, как на данный момент выглядит ситуация и кусочек кода:


from utils import \
transparent_white as transparent, \
create_cairo_font_face_for_file, \
middle_center
from PIL.ImageColor import getrgb
from cairo import ImageSurface, Context, FontOptions, FORMAT_ARGB32
from math import radians, sin, cos, pi

font_files = [
"/WINDOWS/Fonts/cour.ttf",
"/WINDOWS/Fonts/arial.ttf",
"/WINDOWS/Fonts/times.ttf",
"/WINDOWS/Fonts/georgia.ttf",
"/WINDOWS/Fonts/DejaVuMonoSans.ttf",
"/WINDOWS/Fonts/DejaVuCondensedSerif.ttf",
]

font_size = 60
letter = u"Ж"
text_angle = 15
font_color = getrgb("black")
border_color = getrgb("magenta")

# нарисовать букву в 0, 0

WIDTH = 200
HEIGHT = 200

im = ImageSurface(FORMAT_ARGB32, WIDTH, HEIGHT)
cr = Context(im)
face = create_cairo_font_face_for_file(font_files[0], reinit = 0)

cr.set_font_face(face)
cr.set_font_size(font_size)

px = max(cr.device_to_user_distance(1, 1))

canvas_center = WIDTH * 0.5, HEIGHT * 0.5
rectangle_origin = canvas_center[0] * 0.5, canvas_center[1] * 0.5

# квадрат, ограничивающий 100x100 в серединке холста
cr.translate(*rectangle_origin)
cr.set_source_rgb(*border_color) # СИРЕНЕВЫЙ
cr.set_line_width(1 * px)
cr.rectangle(0, 0, WIDTH * 0.5, HEIGHT * 0.5)

# вспомогательные оси x, y, пересекающиеся в центре квадрата
cr.move_to(0, rectangle_origin[1])
cr.line_to(rectangle_origin[0] * 2, rectangle_origin[1])
cr.move_to(rectangle_origin[0], 0)
cr.line_to(rectangle_origin[1], rectangle_origin[1] * 2)
cr.stroke()

width, height = cr.text_extents(letter)[2:4]
text_origin = middle_center(rectangle_origin[0], rectangle_origin[1], width, height)

print "rectangle_origin:", rectangle_origin[0], rectangle_origin[1]
print "width, height:", width, height
print "text_origin:", text_origin

######## сначала рисуем без поворота
cr.set_source_rgb(*getrgb("red"))
# перемещаемся к месту, от которого рисовать
cr.move_to(*text_origin)
# рисуем текст
cr.show_text(letter)

cr.move_to(*text_origin)
cr.translate(width/2, -height/2)
cr.rotate(radians(text_angle))
cr.set_source_rgb(*getrgb("blue"))
cr.show_text(letter)

del cr
im.write_to_png("task_6.png")