вращать текст вокруг своего центра в pycairo

сообщества.

Я знаю, что есть много ответов здесь, руководства, руководства и ссылки по интернетам и больше об этом вопросе. Также я знаю, что знание линейной алгебры требуется. Но когда я думаю о времени, чтобы понять всю теорию и решения упражнений на практике – моя голова дует, и я не могу делать простейшие вещи 🙁

Пожалуйста, если вы знаете небольшое быстрое решение, как сделать поворот текста над его центром, прежде чем его отобразить, скажите мне, пожалуйста.

На данный момент у меня есть:

#... cr.move_to(*text_center) myX, myY = text_center[0] - (width / 2), text_center[1] + (height / 2) cr.save() cr.translate(myX, myY) cr.rotate(radians(text_angle)) cr.show_text(letter) cr.restore() #... 

Но мое письмо не вращается вокруг себя. Это похоже на падение справа 🙁 Я знаю, что мой код не прав. Может быть, я пропущу трансформацию, но я не знаю, как сделать все правильно.

UPDATE: К сожалению, на текст не влияют переводы, поэтому

 cr.translate(10000, 10000) cr.rotate(radians(15)) cr.show_text("hello") 

будет точно таким же, как

 cr.rotate(radians(15)) cr.show_text("hello") 

И я не знаю, как сделать поворот текста над его центром, не создавая новую поверхность или что-то (например, новый слой в графическом процессоре) 🙁

    По крайней мере, на версии cairo, доступной на моей машине (1.8.8), для меня работает следующий подход:

     def text(ctx, string, pos, theta = 0.0, face = 'Georgia', font_size = 18): ctx.save() # build up an appropriate font ctx.select_font_face(face , cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL) ctx.set_font_size(font_size) fascent, fdescent, fheight, fxadvance, fyadvance = ctx.font_extents() x_off, y_off, tw, th = ctx.text_extents(string)[:4] nx = -tw/2.0 ny = fheight/2 ctx.translate(pos[0], pos[1]) ctx.rotate(theta) ctx.translate(nx, ny) ctx.move_to(0,0) ctx.show_text(string) ctx.restore() 

    Которые можно использовать следующим образом:

     width = 500 height = 500 surface = cairo.ImageSurface(cairo.FORMAT_RGB24, width, height) ctx = cairo.Context(surface) ctx.set_source_rgb(1,1,1) rect(ctx, (0,0), (width, height), stroke=False) ctx.set_source_rgb(0,0,0) for i in xrange(5): for j in xrange(5): x = 100 * i + 20 y = 100 * j + 20 theta = math.pi*0.25*(5*i+j) text(ctx, 'hello world', (x, y), theta, font_size=15) surface.write_to_png('text-demo.png') 

    текст-demo.png

    ОК, поэтому cairo позволяет перемещать текст move_to и вращаться. Это означает, что вы хотите выяснить (x, y) для move_to (T), чтобы при повороте (R) центральная точка вашего текста находилась в нужном месте, c = (cx, cy):

    введите описание изображения здесь

    Таким образом, вам нужно решить уравнение Mv = c, где v – текстовый центр относительно исходного текста:

     M = T*R T = (1 0 x) (0 1 y) (0 0 1) R = (cos r -sin r 0) (sin r cos r 0) (0 0 1) v = (w/2, h', 1) c = (cx, cy, 1) h' = h/2 - (h - y_bearing) 

    Проверка работоспособности:

    • когда r равно 0 (без вращения), вы получаете x = cx-w / 2, y = cy-h ', который, как вы знаете, является правильным ответом
    • когда r = -90 (текст боком, с «вверх» вправо), вы получаете то, что ожидаете, то есть x = cx – h 'и y = cy + w / 2

    Для кода python вам придется переписать вышеупомянутое уравнение, чтобы вы закончили с A * t = b, где t = (x, y), и вы будете вычислять t = inv (A) * b. Тогда вы просто сделаете

     cr.move_to(x, y) cr.rotate(r) cr.show_text(yourtext) 

    Обратите внимание, что система координат в каире имеет + y, поэтому будет исправлена ​​пара знаков, и, возможно, y_bearing не верна, но вы получите эту идею.