且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在pycairo中围绕其中心旋转文本

更新时间:2023-02-02 17:45:36

至少在我的计算机上可用的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')

community.

I know that there are many answers here, manuals, tutorials and references over the internets and amny more about this question. Also I know that knowledge of linear algebra is required. But when I think about time to figuring out all the theory and solving exercises in practice - my head is blowing off and I can't do the simplest things :(

Please, if you know a little fast solution how to make rotation of text over its center before rendering it - tell me, pleeease.

For now I have:

#...
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()
#...

But my letter isn't rotating around itself. It's just like falling down to the right side :( I know that my code isn't right. Maybe I miss transformation but I don't know how to make it right.

UPDATE: Unfortunately, text are not affected by translations, so

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

will be exactly the same as

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

And I don't know how to make text rotation over its center without making new surface or something (like new layer in graphic processor) :(

At least on the version of cairo available on my machine (1.8.8), the following approach works for me:

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()

Which can be used in the following way:

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')