プロジェクト

全般

プロフィール

提案 #1581

未完了

Color Model

toshi_a 初音 さんが約2年前に追加. 約2年前に更新.

ステータス:
分類待ち
優先度:
通常
担当者:
対象バージョン:
プラグイン名:
color
ブランチ:

説明

mikutter上で色を表現するデータオブジェクトを標準提供する。

やりたいこと

現在、色情報を利用する場面は以下のとおりだが、色の表現方法が異なる:
名前 形式 値の範囲
UserConfig RGB 0..0xffff
Cairo::Color::RGB RGBA 0..1 (Float)
Gtk::Color RGB 0..0xffff
Gdk::RGBA RGBA 0..1 (Float)
CSS RGB 0..0xff

現状だと、色をどこで利用するかによって適切に変換しなければならない。
異なるクラスなのは仕方ないにしても、UserConfigからCairoに変換するために、各要素を0xffffで割るみたいな処理を毎回実装しなければならない。

レンダリングを行う層以外ではそういった詳細には立ち入りたくないし、現にGtk3移行のときに変換処理がバグっていたことがあった。

mikutterプラグインの共通の色の表現があると、こういった問題を解決できる。

インターフェイス

RGBAの要素のみを要求する。
精度は、各要素を8bitで返すインターフェイスと、0-1のFloatやRationalで返すインターフェイスが考えられる。
アルファブレンド値自体は、無いと困るケースがあるので、このデータオブジェクトで表現に対応する。

ディスプレイは1677万色の表現能力しか持っておらず、24bit (0-255)で十分表現できる。したがって、現在採用しているほとんどの表現形式が過剰である。
また、これは人間の識別精度を十分超えているらしく、mikutterのユーザは今のところ地球人のみであると考えているので、これ以上の精度は不要である。

以上のことから、各8bitでも十分である。

一方で、0-1で表現すると、計算が楽で、何をやっているのかわかりやすいというメリットがある。

uint16_t conv(uint8_t c) {
    return c * 0x101;
}

uint16_t conv(float c) {
    return c * 0xffff;
}

ん〜どうしよっかな〜

永続化について

UserConfigは古いバージョンとの互換性のために現在の形式を維持しなければならない。

表現

各データクラスは、異なる方法でデータを保持するが、同じインターフェイスを持っている。

TrueColor (32bit color)

Color.new(255, 0, 0) # red
Color.new(255, 0, 0, 0) # red
Color.parse('#FF0000') # red

ContinuouslyColor

ContinuouslyColor.new(1.0, 0, 0) # red
ContinuouslyColor.new(1.0, 0, 0, 0) # red

同じインターフェイスを実装しColor Modelの要件を満たす独自の実装をプラグインが行うことによって、mikutterの色の表現方法を拡張できるように注意する。

操作

spellを使った場合、結果は必ずPromiseを受け取ることになる。色の操作はリアルタイム性が求められることが多く、spellは不適切である。
よくありそうな操作についてはColor Pluginで用意する。

UserConfigの読み込み、書き出し

RGBAの各要素は同じ方法で取得できるため、UserConfigに書き出せるはず。
現実的には、今の所UserConfigはあらゆるModelを永続化するような機能はもっていないため、別のところに変換ルーチンを実装しなければならない。

c = Plugin::Color.new(255, 255, 255)
UserConfig[:color] = c # 理想
UserConfig[:color] = Color.export_to_user_config(c) # 現実

一方、読み込みはColor Modelだったらどんなものに復元しても良いため、もう少し直接的になりそう。
c = UserConfig[:color] # 理想
Plugin::UserConfigColor.new(:color) # こういうのがあってもよい?

印字、変換

例えばHTML形式で印字したいなど。すべてのColor Modelに実装を要求すると印字形式が拡張できないが、インターフェイスが統一されているのでどうとでもなる。

def html_color(color)
  '#%02f%02f%02f'.format(color.r, color.g, color.b)
end

Cairo::Colorに変換するといった処理は、gtk3プラグインなどが各々提供する。
Plugin::Gtk3.cairo_color(c)

比較

==で比較する場合、RGBA各要素を0-255で表現した値が等しければ等しいとする。
Color Modelインターフェイスの精度以上で比較する意味がないからである。

同様に、eql?とhashもすべてのColorModelが同じ計算式で値を算出しなければならない。

大小比較は、多分ソートすることがないので別にいいや

標準色

c = Plugin::Color::RED

16色とか256色とか用意する。

備考

red-colros gem は採用しない。
目的に対してできることが多すぎるため。
あと、色に対する複雑な演算をしたいわけじゃないので、その程度の理由で直接依存を増やしたくない。

Diva::Modelのatomic typeとして追加することも考えたが、wellknownではあるけどatomicではないかな


関連するチケット

関連している 提案 #1578: Emacsのfaceのように継承構造を持ったフォント・配色の設定機能が欲しい実装待ちShibafu Midorino操作
関連している バグ #1503: gtk3: 設定画面を開くとMiraclePainterの背景色がおかしくなる終了Shibafu Midorino操作

toshi_a 初音 さんが約2年前に更新

  • 関連している 提案 #1578: Emacsのfaceのように継承構造を持ったフォント・配色の設定機能が欲しい を追加

toshi_a 初音 さんが約2年前に更新

  • 関連している バグ #1503: gtk3: 設定画面を開くとMiraclePainterの背景色がおかしくなる を追加

Izumi Tsutsui さんが約2年前に更新

関連メモ

source:core/mui/gtk_postbox.rb@99251b4#L383
source:core/mui/gtk_extension.rb@99251b4#L382
において UserConfigの背景色 → CSSの変換実装がある。

      color = get_backgroundcolor(message)
      Gtk::CssProvider.new.tap do |provider|
        provider.load_from_data(<<~CSS)
          *, *:active, *:disabled, *:hover, *:focus {
            background-color: rgb(#{color[0] / 256}, #{color[1] / 256}, #{color[2] / 256});
          }
        CSS
      end

    Gtk::CssProvider.new.tap do |provider|
      styles = {}
      CSS_PSEUDO_CLASS_BY_STATE_TYPE.each do |type, pseudo_class|
        color = bg[type]
        if color
          selector = "*#{pseudo_class}" 
          styles[selector] ||= ''
          styles[selector] += "background-color: rgb(#{color[0] / 256}, #{color[1] / 256}, #{color[2] / 256});" 
        end
      end
      css = styles.map { |selector, style| "#{selector} { #{style} }" }.join(' ')
      provider.load_from_data(css)
    end

後者は「 # NOTE: gtk2向けコードとの後方互換のために用意したが使われないことを祈る 」のコメント付き。
これらはそのまま GTK2 (Gtk::Color ?) 互換用っぽい。 cce38377

これと同様の UserConfig → CSS変換が Twitter プラグインの message_detail_view (ツイートの詳細表示)プラグインにおける
ツイート本文部分のフォントの forground, background の色指定で必要になっていた。
https://github.com/mikutter/message_detail_view/pull/3

他の形式にエクスポート: Atom PDF