2010-02-23 4 views
7

이름으로 svg 파일의 일부를 렌더링하고 싶지만 나에게있어서 (python + gtk를 사용하여) 그렇게하는 방법을 모르겠습니다. http://david.bellot.free.fr/svg-cards/files/SVG-cards-2.0.1.tar.gz : 여기 svg 파일의 * parts *를 어떻게 렌더링합니까?

문제의 SVG 파일의 ( 이 업데이트 :이 파일이 더 이상 존재하지 않는,하지만 당신은 http://svg-cards.sourceforge.net/에 그것을 추적 할 수) 자신의 사이트에

, 데이비드는 말한다 :

파일을 픽스맵에 렌더링하고 은 각 카드를 수동으로 자르거나 은 DOM 인터페이스를 통해 카드 이름을 사용하여 카드를 그릴 수 있습니다. 모든 카드는 SVG 그룹 에 삽입됩니다.

DOM 인터페이스가 의미하는 바를 모르겠습니다. 좀 검색을 수행하고 최상의 결과 나는 그게 뭔지 내가 원하는 맞는 것 같다 발견은 Qt를위한 심지어 파이썬으로 작성되지

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")); 

주의 사항 그러나 있음.

#!/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() 

그것은 물론 작동하지 않습니다

이것은 내가 지금까지있는 것입니다.

무엇이 누락 되었습니까?

답변

9

RSVG라고 SVG 렌더링을위한 GTK 라이브러리를 참조하십시오. 그것은 파이썬 바인딩을 가지고 있지만 문서화되어 있지 않으며 보통 C에서 그 목적을 위해 사용하는 rsvg_handle_get_pixbuf_sub()rsvg_handle_render_cairo_sub() 함수를 포함하지 않습니다. 여기까지 내가 할 수있는 일은 다음과 같습니다. Adam Crossland가 제안한대로 XML 노드를 추출합니다. 를 렌더링하려면, 당신은 같은 것을 할 필요가 :

당신이 gtk.Image에 원하는 경우입니다
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()) 

가, 그렇지 않으면 pixbuf와 다른 뭔가. handle.render_cairo(cr)으로 카이로 컨텍스트로 렌더링 할 수도 있습니다. cr은 카이로 컨텍스트입니다.

편집 :

미안 해요, 난 처음에 밀접하게 충분한 파이썬 바인딩을 읽지 않았다.프로그램이 졸이다 수 있도록 _sub() 기능은 id= 인수를 사용하여 구현됩니다

#!/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() 

내가 이것을 테스트하고 그것을 작동합니다. 그러나 창은 전체 SVG 캔버스의 크기이며 화면 크기에 맞게 잘립니다 (코너에서 올라간 클럽의 에이스 대신 3 개의 다이아몬드를 렌더링 한 이유입니다). 그래서 당신은 여전히 당신이 원하는 카드 주위에 Pixbuf를 자르는 어떤 방법을 찾으려면, 너무 어렵지 않아야합니다.

+0

나는 실제로이 방법을 시도해 보았고, 그것이 무엇을하고 있었는지를 알 수 없었다. (그러므로 나는 비슷한 결과를 얻을 수 있는지 다른 해결책을 시도했다.) 창 크기가 전체 SVG 캔버스의 크기 임에도 불구하고이 솔루션은 내 질문에 답합니다 (물론 다른 질문을 제기하는 동안). :) –

+0

이것은 많은 도움이 유용했을 지 모르지만 매우 도움이되었습니다. SVG 이미지의 일부를 렌더링하려면 handle.render_cairo (cr = c, id = "# layer_5")를 사용할 수 있습니다. 여기서 "c"는 카이로 컨텍스트입니다. 나에게 분명하지 않은 부분은 ID의 시작 부분에 "#"이 필요하다는 것입니다. 내 SVG에는 'id = "layer_1"'와 같은 id가 있으며 render_cairo (cr = c, id = "# layer_1")로 개별 레이어를 렌더링 할 수 있습니다. – bodgesoc

2

내가 믿는 그는 SVG는 XML이기 때문에, 당신은 minidom, 또는 다른 파이썬 XML 파서에서 SVG 파일을로드 및 특정와 함께 XML 노드를 추출 할 수있다 '는 DOM 인터페이스를 통해'가 무엇을 의미하는지 당신이 찾고있는 이름. 해당 XML 노드는 렌더링 할 수있는 항목을 나타내야합니다.

+0

XML 노드를 어떻게 렌더링합니까? –

0

태그를 편집하면됩니다. 너비와 높이를 편집하고 기본 svg 요소의 viewBox 특성을 원하는 사각형으로 설정하고 렌더링하고 반복합니다.

How to show a subsection or "slice" of an SVG graphic?http://dingoskidneys.com/~dholth/svg/

+0

이것은 SVG 파일의 일부를 이름으로 검색 한 다음 렌더링하는 데 도움이되지 않습니다. –

+0

SVG 파일의 명명 된 부분에 대해 경계 상자를 가져 와서 그에 따라 viewBox를 설정할 수 있습니다. – joeforker

1

자르기 빈 공간 문제에 대한 답은 다음과 같습니다. 거친 해킹이지만 훌륭하게 작동했습니다. 이것은 또한 파이썬으로 카드 게임을 만드는 사람들을위한 카드를 얻기위한 좋은 출발점이 될 것입니다.

import gtk 
import rsvg 
svg = rsvg.Handle(file="/usr/share/gnome-games-common/cards/gnomangelo_bitmap.svg") 
w, h = 202.5, 315 
card_names = map(str, range(1,11)) + ["jack", "queen", "king"] 
suites = ["club", "diamond", "heart", "spade"] 
specials = [{"name":"black_joker","x":0, "y":4}, {"name":"red_joker","x":1, "y":4}, {"name":"back","x":2, "y":4}] 
for suite_number, suite in enumerate(suites): 
    for card_number, card in enumerate(card_names): 
     print "processing", suite, card, '#'+card+'_'+suite 
     pixbuf = svg.get_pixbuf(id='#'+card+'_'+suite) 
     pixbuf.subpixbuf(int(w*card_number), int(h*suite_number), int(w), int(h)).save("./"+card+"_"+suite+".png","png", {}) 
for special in specials: 
    print "processing", special["name"] 
    pixbuf = svg.get_pixbuf(id='#'+special["name"]) 
    card_number = special["x"] 
    suite_number = special["y"] 
    pixbuf.subpixbuf(int(w*card_number), int(h*suite_number), int(w), int(h)).save("./"+special["name"]+".png","png", {}) 
관련 문제