cairo RSVG

GtkPixBuf は SVG 画像をもそのまま扱えて普通に描写できる。
線や図形の描写 – L’Isola di Niente
上記コードで普通に表示できると確認できます。
しかし拡大すると…

airplane

eog は綺麗に引き伸ばしされているのに対し、コッチは超ギザギザ!
MComix で試してもギザギザ、Shotwell は表示すらできない。

eog ってショボイと見せかけて実はこんなに優秀だったのかよ…
ではなく。
どうすれば綺麗に表示できるか考えて調べて色々試してみよう。

ーーーーー

自前ソースがギザギザなのは少し考えれば当然だと解る。
なにせ svg を一度 Bitmap 化して引伸す工程にしているのである。
これではベクターデータである svg での曲線が滑らかという恩恵が無い。
結果 jpeg 画像等と何も変わらないギザギザになる。

つまりベクターデータのまま拡縮して直接描写する必要がある。
メタデータを直接編集すればなんとかなる。
って、だからベクターデータの加工には面倒が付き纏うんだよ。

もしコレが特定ライブラリを使えば Easy Mode になるのだったら…
なんて誰でも考え付くよね。
いきなりそのものズバリを見つけてしまった。

RSVG Libary Reference Manual
librsvg – Wikipedia

GtkDrawingArea は GTK3 から cairo で描写している。
なので cairo から rsvg を使う方法を探す。

Cairo: A Vector Graphics Library: Cairo: A Vector Graphics Library

Fedora 21 で rsvg モジュールはデフォルトでは入っていない。
だけど gir には Rsvg が最初からあった、コレを使おう。

cairo って PostScript や PDF も扱えるのか。
面白そうだけど今回は細かいことは置いておいて。
Python 用 cairo ライブラリから SVG を描写する方法を。

Surfaces ? Pycairo v1.10.0 documentation

サーフェス(面)のサイズを変更するには Matrix を使うのか。
1,4 番目引数で x,y のサイズということみたい。
ということで、サーフェスなので paint でなくレンダリングする。

#!/usr/bin/env python3
 
from gi.repository import Gtk, Gdk, Gio, Rsvg
import cairo, sys
 
class Win(Gtk.ApplicationWindow):
    def __init__(self, app):
        """
            DnD SVG Viewer
        """
        Gtk.Window.__init__(self, application=app)
        # svg
        self.svg = None
        # DrawingArea
        self.da = Gtk.DrawingArea()
        self.da.connect("draw", self.on_draw)
        self.add(self.da)
        # DnD
        dnd_list = Gtk.TargetEntry.new("text/uri-list", 0, 0)
        self.drag_dest_set(
                Gtk.DestDefaults.MOTION |
                Gtk.DestDefaults.HIGHLIGHT |
                Gtk.DestDefaults.DROP,
                [dnd_list],
                Gdk.DragAction.MOVE )
        self.drag_dest_add_uri_targets()
        # self
        self.set_title("DnD SVG Viewer")
        self.resize(200, 200)
        self.show_all()
 
    def do_drag_data_received(self, drag_context, x, y, data, info, time):
        """
            On Drop
        """
        uris = data.get_uris()
        f = Gio.File.new_for_uri(uris[0])
        path = f.get_path()
        # Recreate svg
        self.svg = Rsvg.Handle.new_from_file(path)
        # invalidate
        self.da.queue_draw()
 
    def on_draw(self, widget, cr):
        """
            Draw x5 SVG
        """
        if self.svg:
            # x5 size
            matrix = cairo.Matrix(5, 0, 0, 5, 0, 0)
            cr.transform (matrix)
            # Render
            self.svg.render_cairo(cr)
 
class App(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self,
                application_id="apps.test.dnd",
                flags=Gio.ApplicationFlags.FLAGS_NONE)
         
    def do_activate(self):
        Win(app)

app = App()
app.run(sys.argv)

svg_5x

これならギザギザにならずに拡大することができる。
別途でインストールするものは何もないのに、Linux 恐るべし。
いやまあ全部 GNOME プロジェクトのおかげなんですけど。
結論、cairo って実はこんなに面白いんだyo!