Cairo Matrix

前回の続き。
Cairo.Matrix で GdkPixbuf をリサイズできるんだよね。
それなら draw シグナルのハンドラでそのまま描写すればいいジャン!

でも Matrix のリサイズは RGBA ベースじゃないだろうな?
ClutterImage ではスクリーントーンが縮小で潰れたんだよね。
screentone 2D and 3D | PaePoi

OpenGL ではないから大丈夫だと思う、ただリサイズは超ヌルヌルだった。
速度といっしょにそんな所も見ていこう。

#!/usr/bin/env python3

import gi, sys, cairo, time
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib, GdkPixbuf

class AWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        self.d = Gtk.DrawingArea()
        self.d.connect('draw', self.on_draw)
        self.add(self.d)
        self.pixbuf1 = GdkPixbuf.Pixbuf.new_from_file('003.png')
        self.pixbuf2 = GdkPixbuf.Pixbuf.new_from_file('004.png')
        self.resize(1600, 900)
        self.show_all()

    def on_draw(self, widget, cr):
        aw = widget.get_allocated_width()
        ah = widget.get_allocated_height()
        # __do__
        t = time.time()
        # Save Matrix
        cr.save()
        # Right Page
        w = self.pixbuf1.get_width()
        h = self.pixbuf1.get_height()
        n = ah/h
        matrix = cairo.Matrix(n, 0, 0, n, aw/2, n)
        cr.transform(matrix) # no! cr.set_matrix(matrix)
        Gdk.cairo_set_source_pixbuf(cr, self.pixbuf1, 0, 0)
        cr.paint()
        # Reset
        cr.restore()
        # Left Page
        w = self.pixbuf2.get_width()
        h = self.pixbuf2.get_height()
        n = ah/h
        matrix = cairo.Matrix(n, 0, 0, n, aw/2-w*n, n)
        cr.transform(matrix)
        Gdk.cairo_set_source_pixbuf(cr, self.pixbuf2, 0, 0)
        cr.paint()
        # __done__
        print('matrix  : {}'.format(time.time() - t))

class AApplication(Gtk.Application):
    __gtype_name__ = 'AApplication'
    def __init__(self):
        GLib.set_prgname('AApplication')
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        AWindow(self)
    
    def do_activate(self):
        self.props.active_window.present()

AApplication().run(sys.argv)

Matrix 版

#!/usr/bin/env python3

import gi, sys, time
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, Gdk, GLib, GdkPixbuf

class AWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app)
        self.d = Gtk.DrawingArea()
        self.d.connect('draw', self.on_draw)
        self.add(self.d)
        self.pixbuf1 = GdkPixbuf.Pixbuf.new_from_file('003.png')
        self.pixbuf2 = GdkPixbuf.Pixbuf.new_from_file('004.png')
        self.resize(1600, 900)
        self.show_all()

    def on_draw(self, widget, cr):
        aw = widget.get_allocated_width()
        ah = widget.get_allocated_height()
        # __do__
        t = time.time()
        # Right Page
        w = self.pixbuf1.get_width()
        h = self.pixbuf1.get_height()
        n = ah*w/h
        buf = self.pixbuf1.scale_simple(n, ah, GdkPixbuf.InterpType.BILINEAR)
        Gdk.cairo_set_source_pixbuf(cr, buf, aw/2, 0)
        cr.paint()
        # Left Page
        w = self.pixbuf2.get_width()
        h = self.pixbuf2.get_height()
        n = ah*w/h
        buf = self.pixbuf2.scale_simple(n, ah, GdkPixbuf.InterpType.BILINEAR)
        Gdk.cairo_set_source_pixbuf(cr, buf, aw/2-n, 0)
        cr.paint()
        # __done__
        print('scale:  {}'.format(time.time() - t))

class AApplication(Gtk.Application):
    __gtype_name__ = 'AApplication'
    def __init__(self):
        GLib.set_prgname('AApplication')
        Gtk.Application.__init__(self)

    def do_startup(self):
        Gtk.Application.do_startup(self)
        AWindow(self)
    
    def do_activate(self):
        self.props.active_window.present()

AApplication().run(sys.argv)

scale_simple 版

差がなかった。
小さく描写だと scale_simple、大きく描写だと Matrix のほうがチビッと速い。
とはいえ人間の目で解るような違いは何をやっても出ない。

画質も違いが解らないレベル。
ただリサイズのスムースさは Matrix 版のほうが気のせいレベルで上かも。

cr.set_matrix(matrix) はしちゃだめよ。
原点がウインドウの枠どころか影までの所になってワケワカメになるよ。
GtkWindow の decorated property を False で使うならいいけど。

Matrix 版と ClutterImage 版 comipoli との比較、
スクリーントーンの縮小も問題無し、心配不要だった。

結論、変わらねー。
せっかく勉強したんだから次の comipoli は Matrix でいこう。