ujimushi(@旧sradjp(15364))の日記

旧スラドの日記の引越先です

Plots.jlのGRバックエンド用フォントパッチ(Linux用)

Plots.jlのGRバックエンド用フォントパッチ(Windows用)に引き続き,今度はLinux用を 実装してみた。基本的にはfc-listの出力を加工しているので,OSのfontconfigモジュールがないと実行できない。 サーバーとかでデスクトップ環境がないマシンでは実行できない可能性が高いので注意されたし。 juliaが実行できるunix系環境ではfc-listが実行できるのなら同じように使える可能性が高いと思います。

さて早速パッチを紹介してみよう。といっても,前回とほとんど同じ。

# plots_gr_font_patch_for_linux.jl
using Plots

@eval Plots begin
    function gr_custom_fontlist_linux()
        コマンド出力 = pipeline(`fc-list`, `egrep "[.](ttf|ttc|otf)"`,`cut -d : -f 1`)
        読込(x) = read(x, String)
        終端改行削除(x) = chomp(x)
        行分割(x) = split(x, "\n")
        ファイル名抽出(x) = basename(x)
        fnames = コマンド出力 |> 読込 |> 終端改行削除 |> 行分割 .|> ファイル名抽出
        Dict([(chopsuffix(f, r"[.](ttf|ttc|otf)") , f) for f in fnames])
    end
    
    """
        パッチで指定可能なフォント名 => ファイル名の辞書型

    `"フォント名" in keys(Plots.gr_custom_fontlist)`
    でフォントが選択可能か分かる
    """
    const gr_custom_fontlist = gr_custom_fontlist_linux()
    
    function gr_set_font(
        f::Font, s; halign = f.halign, valign = f.valign, color = f.color,
        rotation = f.rotation,)
        family = lowercase(f.family)
        GR.setcharheight(gr_point_mult(s) * f.pointsize)
        GR.setcharup(sincosd(-rotation)...)
        if !haskey(gr_font_family, family)
            # この辺を変更
            gr_font_family[family] = GR.loadfont(gr_custom_fontlist[f.family])
        end
        haskey(gr_font_family, family) && GR.settextfontprec(
            gr_font_family[family],
            gr_font_family[family]  200 ? 3 : GR.TEXT_PRECISION_STRING,
        )
        gr_set_textcolor(plot_color(color))
        GR.settextalign(gr_haligns[halign], gr_valigns[valign])
        nothing
    end
end

特に説明することもないので,使用例も続けて載せます。

using Plots
using Blink
using Interact

include("plots_gr_font_patch_for_linux.jl")

function my_plot(fontname)
    plot(sin; title="日本語のタイトル", titlefontfamily=fontname, gridalpha=0.5)
end

function real_main()
    fontnames = sort([fontname for fontname
                          in keys(Plots.gr_custom_fontlist)])
    
    menu = dropdown(fontnames; value="NotoSansCJK-Medium")
    win =Window(Dict(:width => 800, :height => 600,
                     :defaultEncoding=>"utf-8"))
    plt = map(my_plot, menu)
    ui = vbox(menu, plt)
    body!(win, ui)
    win
end

function julia_main()::Cint
    win = real_main()
    while Blink.AtomShell.active(win)
        sleep(1)
        yield()
    end
    return 0
end

スクリーンキャストをgifファイルに変換する時にデフォルトだと変換後の色がおかしくなるので, gridの色を少しはっきり目に変更しています。(gridapha=0.5)それ以外は特に説明することはありません。

次が実行例です。

このパッチを使うと特にフォントの種類を気にする必要なく使えるようになると思います。

追記:

特に説明することはないと書いたのですが色々ありました。

  • 文字のグリフがないフォントを選ぶと「とうふ」表示になります。ご注意。
  • GRの標準・OSのどちらにもないフォントを指定すると,パッチ前はスルーするだけですが,パッチ後はエラーで停止します。ご注意。