我如何渲染svg文件的*部分? [英] How do I render *parts* of a svg file?

查看:189
本文介绍了我如何渲染svg文件的*部分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想按名称渲染一个svg文件的一部分,但对于我来说,我无法弄清楚如何去做(使用python + gtk)。



以下是有问题的svg文件: http ://david.bellot.free.fr/svg-cards/files/SVG-cards-2.0.1.tar.gz 更新:此文件不再存在,但您可以在 http://svg-cards.sourceforge.net/ )进行追踪



在他的网站上,David说:


你可以用
将文件渲染到像素图上,
手动剪切每张卡片,或者通过
通过DOM
接口使用卡片名称。所有的卡都嵌入到
一个SVG组中。


我不知道他是什么意思的DOM接口。我做了一些搜索,找到了最适合我想要做的事情的结果:

  QSvgRenderer * renderer =新的QSvgRenderer(QLatin1String(SvgCardDeck.svg)); 
QGraphicsSvgItem * black = new QGraphicsSvgItem();
QGraphicsSvgItem * red = new QGraphicsSvgItem();

black-> setSharedRenderer(renderer);
black-> setElementId(QLatin1String(black_joker));

red-> setSharedRenderer(renderer);
red-> setElementId(QLatin1String(red_joker));

请注意,它适用于Qt,甚至没有用python编写。



这是我到目前为止:

 #!/ usr / bin / env python 

from __future__ import absolute_import

导入cairo
导入gtk
导入rsvg

从xml导入xpath
from xml.dom import minidom

window = gtk.Window()
window.set_title(Foo)
window.set_size_request(256,256)
窗口.set_property(resizable,False)
window.set_position(gtk.WIN_POS_CENTER)
window.connect(destroy,gtk.main_quit)
window.show()

document = minidom.parse(cards.svg)
element = xpath.Evaluate(// * [@ id ='1_club'],document)[0]
xml = element.toxml()

svg = rsvg.Handle()
svg.write(xml)
$ b $ pixbuf = svg.get_pixbuf()

image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()

window.add(image)

gtk.main()

当然不行。



我是什么缺少?

解决方案

用于渲染SVG的GTK库称为RSVG。它有Python绑定,但它们未记录,并且它们不包的 rsvg_handle_get_pixbuf_sub() rsvg_handle_render_cairo_sub()你通常在C中用于这个目的的函数。就我所知,这就是你必须做的事情。您按Adam Crossland的建议提取XML节点。要显示它,你必须做这样的事情:

  import gtk 
import rsvg
handle = rsvg.Handle()
handle.write(buffer = xml_data)
#xml_data是所需对象的XML字符串
image = gtk.Image()
image.set_from_pixbuf (handle.get_pixbuf())

这就是如果你想在 gtk .Image ,否则用pixbuf做别的。您还可以使用 handle.render_cairo(cr)将其渲染到Cairo上下文,其中 cr 是您的Cairo上下文。



编辑:

对不起,我没有仔细阅读python绑定首先。 _sub()函数是使用 id = 参数实现的,所以你的程序可以归结为: p>

 #!/ usr / bin / env python 

导入gtk
导入rsvg

window = gtk.Window()
window.set_title(Foo)
window.connect(destroy,gtk.main_quit)
window.show()

svg = rsvg.Handle(file ='cards.svg')
pixbuf = svg.get_pixbuf(id ='#3_diamond')

image = gtk。 Image()
image.set_from_pixbuf(pixbuf)
image.show()

window.add(image)
$ b $ gtk.main()

我测试过了,它可以工作。然而,这个窗口是整个SVG画布的大小,并被剪裁成屏幕大小(这就是为什么我渲染了3颗钻石,而不是角落里的俱乐部的王牌。)所以你仍然会拥有找到一种方法来裁剪你想要的卡周围的pixbuf,但这应该不会太难。


I want to render parts of a svg file by name but for the life of me I cannot figure out how to do so (using python + gtk).

Here's the svg file in question: http://david.bellot.free.fr/svg-cards/files/SVG-cards-2.0.1.tar.gz (Update: this file no longer exists, but you can track it down at http://svg-cards.sourceforge.net/)

On his site, David, says:

You can draw a card either by rendering the file onto a pixmap and clipping each card manually or by using the card's name through a DOM interface. All cards are embedded into a SVG group.

I don't know what he means by a DOM interface. I have done some searching and the best result I found that seems to fit what I want to do is:

QSvgRenderer *renderer = new QSvgRenderer(QLatin1String("SvgCardDeck.svg"));
QGraphicsSvgItem *black = new QGraphicsSvgItem();
QGraphicsSvgItem *red   = new QGraphicsSvgItem();

black->setSharedRenderer(renderer);
black->setElementId(QLatin1String("black_joker"));

red->setSharedRenderer(renderer);
red->setElementId(QLatin1String("red_joker"));

Notice however that it is for Qt and is not even written in python.

This is what I have so far:

#!/usr/bin/env python

from __future__ import absolute_import

import cairo
import gtk
import rsvg

from xml import xpath
from xml.dom import minidom

window = gtk.Window()
window.set_title("Foo")
window.set_size_request(256, 256)
window.set_property("resizable", False)
window.set_position(gtk.WIN_POS_CENTER)
window.connect("destroy", gtk.main_quit)
window.show()

document = minidom.parse("cards.svg")
element = xpath.Evaluate("//*[@id='1_club']", document)[0]
xml = element.toxml()

svg = rsvg.Handle()
svg.write(xml)

pixbuf = svg.get_pixbuf()

image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()

window.add(image)

gtk.main()

It doesn't work, of course.

What am I missing?

解决方案

The GTK library for rendering SVG is called RSVG. It has python bindings, but they are undocumented, and they don't wrap the rsvg_handle_get_pixbuf_sub() and rsvg_handle_render_cairo_sub() functions which you would normally use for that purpose in C. Here's what you have to do as far as I can tell. You extract the XML node as Adam Crossland suggested. To render it, you have to do something like this:

import gtk
import rsvg
handle = rsvg.Handle()
handle.write(buffer=xml_data) 
# xml_data is the XML string for the object you want
image = gtk.Image()
image.set_from_pixbuf(handle.get_pixbuf())

That's if you want it in a gtk.Image, otherwise do something else with the pixbuf. You can also render it to a Cairo context with handle.render_cairo(cr) where cr is your Cairo context.

EDIT:

Sorry, I didn't read the python bindings closely enough at first. The _sub() functions are implemented using the id= argument, so your program can boil down to this:

#!/usr/bin/env python

import gtk
import rsvg

window = gtk.Window()
window.set_title("Foo")
window.connect("destroy", gtk.main_quit)
window.show()

svg = rsvg.Handle(file='cards.svg')
pixbuf = svg.get_pixbuf(id='#3_diamond')

image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()

window.add(image)

gtk.main()

I tested this and it works. However, the window is the size of the entire SVG canvas, and is clipped to the screen size (which is why I rendered the 3 of diamonds instead of the ace of clubs which is up in the corner.) So you'll still have to find some way to crop the pixbuf around the card that you want, but that shouldn't be too hard.

这篇关于我如何渲染svg文件的*部分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆