モブ沢工房

プログラミングとかLinux関連(特にOSSのグラフィックツール関連)とかレトロゲームとか3Dプリンタやら日曜大工等、色々。

PyGObject(PyGi)で「デフォルトのフォントサイズ」を取得する

PyGObject…でいいのでしょうか。PyGiなのか。未だによくわかりません。 とにかく新しい方のGtkpythonバインディングで、コンボボックスのカスタムレンダラーで使うデフォルトのフォントサイズを取得したくなりました。

これはMyPaintにOpenCVのgrabCut関数を使った新しいペイント方法(グラフカットを利用し穴の開きまくった線画を分離してペイントする)を実装した時、実験中は「真上のレイヤー」を線画レイヤーにしていたのですが、これは実際使いづらい。

そのため、コンボボックスで線画レイヤーを選べるようにしよう!とピコーンと思いついたんですが、カスタムレンダラーでフォントサイズを他のウィジェットと揃える方法が全く分からんのですね。

do_renderコールバックにおけるcairo contextでのtext_extents系関数でサイズを得ると、明らかに小さい文字が描画される…

しかしながら検索方法が悪いのか一向にそのものズバリにヒットしない…

そこでまぁ頑張っていろいろ調べ&試した結果がコレ

ただし、これが正しいのかどうかは不明、という…

from gi.repository import Gtk, Gdk, Pango

st = Gtk.ComboBox.get_default_style()
desc = st.font_desc
size_base = desc.get_size() / Pango.SCALE
if desc.get_size_is_absolute():
    # True == size is in device unit
    pass
else:
    # False == size is in Point.
    # pixel = Point * (DPI / 72.0)
    scr = Gdk.Screen.get_default()
    dpi = scr.get_resolution()
    if dpi < 0:
        dpi = 96.0
    size_base = math.floor(size_base * (dpi / 72.0))
  • スタイル構造体の中にfont_descがあるので、コンボボックスのデフォルトスタイルを得る。
  • font_descのget_size()でサイズを得られるが、これはPango.SCALEでスケーリングされた値であるため、割る。
  • それで得られた値はデバイス単位かポイント単位かに別れる。これはget_size_is_absolute()で区別できる。
  • ポイント単位であった場合、DPI設定 / 72.0 で得られた値を先ほどの値に掛けることでピクセル単位に変換できる。

これで変数size_baseにデフォルトのコンボボックスのフォントサイズ(ピクセル単位)が入る…はず