使用以下代码,我尝试使用 cairocffi 绘制图形。由于在绘制图形之前我不知道图形有多大,因此我使用无界 RecordingSurface 来记录操作,然后将操作传输到正确尺寸的 SVGSurface。然而,当我这样做时,只有一小部分图表出现在输出图像的左上角。 (我执行此操作的特定图表最终大多带有负 x 和 y 坐标。)如何让整个图表显示在最终的 SVGSurface 中?
import cairocffi as cairo
# ...
def draw_line(ctx):
dx, dy = unit_vector(ctx.angle)
ctx.rel_line_to(dx, dy)
def eval_symbol(sym, ctx):
if sym == 'L':
ctx.angle -= ANGLE
elif sym == 'R':
ctx.angle += ANGLE
elif sym == 'F':
draw_line(ctx)
def graph(iteration):
rec_surf = cairo.RecordingSurface(cairo.CONTENT_COLOR, None)
ctx = cairo.Context(rec_surf)
ctx.move_to(0, 0)
ctx.angle = 0
for sym in iteration:
eval_symbol(sym, ctx)
ctx.stroke()
x, y, width, height = rec_surf.ink_extents()
print(x, y, width, height)
final_surf = cairo.SVGSurface(FILENAME, width, height)
final_ctx = cairo.Context(final_surf)
final_ctx.set_source_surface(rec_surf, 0, 0)
final_ctx.paint()
您已通过将记录表面设置为源表面,将其正确重播(绘制)为 svg 表面。
但是,您未能考虑墨水范围中的 x/y 偏移。
所有数据均输出为svg。您根本看不到它,因为您的图像查看器正在将输出裁剪为 svg 视口的大小。
设置源表面时,还要设置偏移量,以将所有着墨表面放入视口内。 (注意必须是-x,-y)
您可以在 Inkscape 中打开 svg 以查看视口之外的内容。
#!/bin/python3
import cairo
def draw(surface, S):
cr = cairo.Context(surface)
cr.set_source_rgba(1, 0, 0, 1)
cr.rectangle(0, 0, S, S)
cr.stroke()
# draw something partially outside of the target surface svg window
cr.set_source_rgba(0, 1, 0, 1)
cr.rectangle(-10, -10, 20, 20)
cr.fill()
# draw something entirely outside of the target surface svg window
cr.set_source_rgba(0, 1, 0, 1)
cr.rectangle(-100, -100, 20, 20)
cr.fill()
if __name__=='__main__':
S = 100
rec = cairo.RecordingSurface(cairo.CONTENT_COLOR, None)
#draw
draw(rec, S)
#replay
x, y, width, height = rec.ink_extents()
print(x, y, width, height)
svg = cairo.SVGSurface("out.svg", width, height)
cr = cairo.Context(svg)
cr.set_source_surface(rec, -x, -y)
cr.paint()
svg.flush()
svg.finish()
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="201pt" height="201pt" viewBox="0 0 201 201" version="1.1">
<defs>
<g id="surface7" clip-path="url(#clip1)">
<rect width="16777215" height="16777215" style="opacity:1;stroke:none;fill:rgb(0,0,0);"/>
<path style="fill:none;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke:rgb(100%,0%,0%);stroke-opacity:1;stroke-miterlimit:10;" d="M 0 0 L 100 0 L 100 100 L 0 100 Z M 0 0 " transform="matrix(1,0,0,1,-0,0)"/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,100%,0%);fill-opacity:1;" d="M -10 -10 L 10 -10 L 10 10 L -10 10 Z M -10 -10 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,100%,0%);fill-opacity:1;" d="M -100 -100 L -80 -100 L -80 -80 L -100 -80 Z M -100 -100 "/>
</g>
</defs>
<g id="surface4">
<use xlink:href="#surface7" transform="matrix(1,0,0,1,100,100)"/>
</g>
</svg>