投稿者「sasakima-nao」のアーカイブ

Gmail…

google アカウントから「ブロックしました」と度々通知が来るようになった。
何だよ、筆者のアカウントなんかハッキングしてもたいしたもんは無いぞ?

何度も来るのでさすがにおかしいと思い通知の時間を元に色々検証。
って、その通知メールを受信している Sylpheed 自身が原因だった。
imap で既読を付けようとする毎にブロックされているようだ。
3.6 は Gmail が要求するセキュリティに合致していないってことかな。

Sylpheed – 軽快で使いやすいオープンソースのメールソフト

3.7 が出ているけどこの件には関係なさそうだなぁ。
安全性の低いアプリへのアクセスを許可もできるみたいだけど。。。。。
今は全アカウントで imap なので何を使ってもいいし。
他を探してもまたブロックされるかもしれないし。

ということで数年ぶりに Evolution を起動。
こいつはブロックされないようだ、当然だと思うけど。

あぁ、GNOME 純正でないのは KeePassX と google-chrome だけになってしまった。
実際 macOS ではこれに Visual Studio Code が入るだけで使ってるし。

十年くらい前に Linux を使い始めてからずっと使い続けているメーラーなのに。
まさかこんな理由で乗り換えするはめになるとはね。
今後もこんな感じでサードパーティの淘汰みたいな流れなんだろうな。

unzip escape

comipoli を gjs 化するので python3 の zipfile が使えない。
ということで unzip コマンドを使う方法に切り替えるのだが
展開する内部ファイル名にブラケット [, ] があると展開できないと気が付いた。

検索するとアスタリスクが駄目なことは皆気がついているようだ、他にもあるかな?
file-roller の GPL ソースを見るのが一番速い。

file-roller/fr-command-zip.c at master ? GNOME/file-roller ? GitHub

[]*?!^-\

こんなにあった、てか記号全部ではないのね。
駄目文字の前にバックスラッシュを付けるだけだし変換は簡単だね。

var ComipoliArchive = class ComipoliArchive {
    // etc...
    _zipEscape(str) {
        const ESCAPE = "[]*?!^-\\";
        let res = "";
        for (let s of str) {
            if (ESCAPE.includes(s)) res += "\\";
            res += s;
        }
        return res;
    }
    getItem(num) {
        let cmdArray = null;
        let pixbuf = null;
        switch (this.status) {
        case 1:
            cmdArray = ["unrar", "p", "-inul", "-@", "--", this.path, this.namelist[num]];
            break;
        case 2:
            cmdArray = ["7za", "x", "-so", this.path, this.namelist[num]];
            break;
        default:
            //cmdArray = ["unzip", "-pj", this.path, this.namelist[num]];
            cmdArray = ["unzip", "-pj", this.path, this._zipEscape(this.namelist[num])];
        }
        let sp = Gio.Subprocess.new(cmdArray, Gio.SubprocessFlags.STDOUT_PIPE);
        let stream = sp.get_stdout_pipe();
        try {
            pixbuf = GdkPixbuf.Pixbuf.new_from_stream(stream, null);
        }
        catch(e) {
            print("Error: " + this.namelist[num] + "\n" + e);
        }
        stream.close(null);
        return pixbuf;
    }
}

展開できた。

しかし cairo 描写に書き換えたら 3D で動く毎に draw シグナルが…
これでは clutter_actor_save_easing_state が使えないや。

yield @ Python3 and JavaScript

我が comipoli はどうせ cairo に書き換えるなら Gjs 化してしまおう。
ということで以前 ClutterImage 作成が遅過ぎでお蔵入りしたソースを引っ張りだした。
ES6 仕様に書き換えをしていて yield でハマったので覚書。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib

class Dlg(Gtk.Dialog):
    def __init__(self):
        Gtk.Dialog.__init__(self, transient_for=None, title="Comipoli Thumbnail")
        self.show_all()
        # idle
        self.iter = self.iter_func()
        GLib.idle_add(self.iter_idle)

    def iter_idle(self):
        try:
            n = next(self.iter)
            print(n)
            return True
        except Exception as e:
            return False

    def iter_func(self):
        for num in range(100):
            yield num

dlg = Dlg()
dlg.run()
dlg.destroy()

PyGObject

#!/usr/bin/gjs

const GObject = imports.gi.GObject;
const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;

var Dlg = GObject.registerClass({
    GTypeName: "Dlg"
}, class Dlg extends Gtk.Dialog {
    _init() {
        super._init({
            transient_for: null,
            title: "Comipoli Thumbnail"
        });
        this.show_all();
        // idle
        this.iter = this.iter_func();
        GLib.idle_add(GLib.PRIORITY_LOW, ()=> {
            let r = this.iter.next();
            if (r.done) return false;
            print(r.value);
            return true;
        });
    }
    * iter_func() {
        for (let i=0; i<100; i++) {
            yield i;
        }
    }
});
Gtk.init(null);
let dlg = new Dlg();
dlg.run();
dlg.destroy();

Gjs

g_idle_add の引数が違うことは置いておいて。
g_idle_add は何も処理を行っていない時に与えられた関数を実行し続ける関数。
false を戻さないかぎり動き続ける。

Python は例外で判別、JavaScript は next メソッドの戻り値で判別。
yield, next の使い方はまったく同じなので混乱してもーたがね。

検索すると個別で next() を呼んでいる人ばかりで困ったよ。
どう考えても yield でそんな使い方はしないと思うんですけど。
複数ファイル処理で一つ読み終わったらとっとと表示みたいな場合が主だよね。

あと JavaScript のジェネレーター関数はアスタリスクが必要。
無名関数にする手段は無いっぽい、JavaScript を筆者が使うようになった切っ掛けなのに。
でも Python には無名関数はいらないな、そんなの Python じゃない。
適材適所ってことですよ、何でもアリはコードを読み辛くするだけだ。

screentone 2D and 3D

コミックブックアーカイブビューアを作っている筆者でありますが。
スクリーントーンの描写が変になる場合があることに困っていた。

Clutter(OpenGL ES) でリサイズしているのが悪いのかな?
と思い GdkPixbuf をリサイズしてからレンダリングで解決した。
よかったよかった、じゃない!もう少し調べよう。

Jトーン 網点(ドットパターン) J-00|スクリーントーン 通販【ジェイトーン・ネットショッピング】

トーンは上記のサンプル画像をお借りしてと。

#!/usr/bin/env python3

import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Clutter", "1.0")
gi.require_version("GtkClutter", "1.0")
from gi.repository import Gtk, Gdk, GdkPixbuf, Clutter, GtkClutter, Cogl

class DrawWindow(Gtk.Window):
    """
        2D and 3D View Check
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # tone
        self.pixbuf = GdkPixbuf.Pixbuf.new_from_file("tone.jpg")
        # cairo (2D)
        self.da = Gtk.DrawingArea()
        self.da.connect("draw", self.on_draw)
        # OpenGL ES (3D)
        embed = GtkClutter.Embed()
        stage = embed.get_stage()
        stage.set_background_color(Clutter.Color.new(0, 0, 0, 255))
        stage.connect("allocation-changed", self.on_stage_allocation_changed)
        self.actor = Clutter.Actor()
        image = Clutter.Image()
        image.set_data(
            self.pixbuf.get_pixels(),
            Cogl.PixelFormat.RGBA_8888 if self.pixbuf.get_has_alpha() else Cogl.PixelFormat.RGB_888,
            self.pixbuf.get_width(),
            self.pixbuf.get_height(),
            self.pixbuf.get_rowstride()
        )
        self.actor.set_content(image)
        stage.add_child(self.actor)
        # set
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(self.da, True, True, 0)
        vbox.pack_start(embed, True, True, 0)
        self.add(vbox)
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()

    def on_stage_allocation_changed(self, actor, box, flags):
        aw = box.x2
        ah = box.y2
        w = self.pixbuf.get_width()
        h = self.pixbuf.get_height()
        if aw * h > ah * w:
            width = w * ah / h
            height = ah
            x = (aw - width) / 2
            y = 0
        else:
            width = aw
            height = h * aw / w
            x = 0
            y = (ah - height) / 2
        self.actor.set_size(width , height)
        self.actor.set_position(x, y)

    def on_draw(self, widget, cr):
        d_width = widget.get_allocated_width()
        d_height = widget.get_allocated_height()
        cr.set_source_rgb(0, 0, 0)
        cr.rectangle(0, 0, d_width, d_height)
        cr.fill()
        p_width = self.pixbuf.get_width()
        p_height = self.pixbuf.get_height()
        if (d_width * p_height) > (d_height * p_width):
            width = p_width * d_height / p_height
            height = d_height
        else:
            width = d_width
            height = p_height * d_width / p_width
        pixbuf = GdkPixbuf.Pixbuf.scale_simple(self.pixbuf, width, height, GdkPixbuf.InterpType.BILINEAR)
        Gdk.cairo_set_source_pixbuf(cr, pixbuf, (d_width-width)/2, (d_height-height)/2)
        cr.paint()

GtkClutter.init()
DrawWindow()
Gtk.main()

動かす。

上半分が cairo で下が Clutter です。
拡大はまったく同じ描写になるけど縮小は全然違うものになることが解る。
なんだよこの 3D 描写。。。。。

画像処理や 3D に詳しいわけではないので細かい解説はできないけど。
単なるラスターデータとして扱う 2D と RGB として扱う 3D の違いだろう。
網点を RGB 色として認識した結果こんな悲惨なことに。

とにかく 3D では小さめな画像かアニメ調のベタ塗りでないとこんなことになる。
スクリーントーンを多用するコミック表示には徹底的に向いていないようです。

Clutter で cairo が使える手段があるのはそういうことか。
cairo で作り替えしよ。

text/x-python3

Fedora 27 では ContentType に text/x-python3 が追加されていた。
…ことを昨日久々に Python ネタを書いてやっと気が付く筆者であった。
Gedit で python の所に登録したスニペットが流し込めなかったということで。

とうとう Python2 からの完全置き換えをあきらめたということかな。
ちなみに Gedit はモードラインが無いなら ContentType で見分けている。
どういう振り分けをしているのかしらべてみよう。

/usr/share/mime/magic
を Gedit で無理矢理開いて Ctrl+F から python3 を検索。

あぁシバンのみで判断しているってことね。
拡張子を py にしただけのファイルは text/x-python のままだ。

python3+15 って何だろと思ってアレコレ試してみた。
先頭から 15 文字目までにコレを見つけたら Python3 だと認識、でいいのかな。

#!!!!!!!!!!!/usr/bin/env python3

から ! を一文字増やし Ctrl+s で Gedit のステータスバー表記が Python に変わる。

いや実験です、この shebang は当然動作しません。
しかし 15 文字っていったいどんだけ変な場所に env があるんだよ。

とにかくこれで Python2/3 コードの振り分けが簡単になる。
いや現行の Fedora デフォルトに Python2 は含まれていませんけど。