sky’s 雑記

主にAndroidとサーバーサイドの技術について記事を書きます

フォースダークを支える技術でダークテーマ用style.xmlを生成する

qiitaに投稿したアドベントカレンダーの転載です。 https://qiita.com/iwsksky/items/dc27afab6a9a757ac5ba

TD;DL

はじめに

Android10から導入された機能にフォースダークというものがある。開発者向けオプションにあるフォースダークのオーバーライドという項目がそれにあたり、このオプションをONにした状態で既存のアプリを起動すると比較的高いクオリティでダークテーマを適用する技術である。この記事ではフォースダークを支える技術を利用して既存のcolors.xmlからダークテーマ用のcolors.xmlを生成する。

フォースダークを支える技術

Lab色空間

Lab色空間はCIE1931色空間をベースとして定義された色空間で明度を示す次元Lと補色a*bにより表される。開発時に利用されることで馴染みがあるRGB色空間と比べると次元Lが特徴的なパラメータでこれは人間の視覚の明度に近く設計されている。 [1]

Skia

Googleにより買収されたSkia incにより開発されていたchromiumfirefoxでも採用実績のある2Dレンダリングを目的としたグラフィックライブラリ。 Android 3 Honyecombまでレンダリングにデフォルトで使用されていたがパフォーマンス上の理由からレンダリング処理は後述するHwuiに置き換えられた。レンダリング用の構造体などは引き続きSkia定義のものが利用されている。

Hwui

おそらくHardwareUIの略。 Android 3 Honyecombでハードウェア アクセラレーテッドのオプションとして追加されIceCream Sandwitch以降デフォルトとなったグラフィックライブラリ。Android端末が高解像度になったことやアプリケーションでリッチなアニメーションが要求されるようになったといった背景でSkiaでは表現できないグラフィックを表現するために導入された。

Androidにおけるフォースダークの実現[3]

Androidでは以下のような手順を踏みダークテーマへ変換しグラフィックレンダリングを行っている、各行説明すると長くなるのでここでは省略する。

-> updateForceDarkMode

https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/view/ViewRootImpl.java#4449

-> setForceDark

https://android.googlesource.com/platform/frameworks/base/+/master/graphics/java/android/graphics/HardwareRenderer.java#512

-> applyColorTransform

https://android.googlesource.com/platform/frameworks/base/+/master/libs/hwui/CanvasTransform.cpp#68

-> transformColor

https://android.googlesource.com/platform/frameworks/base/+/master/libs/hwui/CanvasTransform.cpp#57

-> makeDark

https://android.googlesource.com/platform/frameworks/base/+/master/libs/hwui/CanvasTransform.cpp#46

非ダークテーマのRGBカラーをダークテーマRGBカラーへと変換する処理でフォースダークの実体はこのコード。 RGB色空間をLab色空間に変換し必要があれば明度を下げてRGB色空間へ再度変換する。

static SkColor makeDark(SkColor color) {
    Lab lab = sRGBToLab(color);
    float invertedL = std::min(110 - lab.L, 100.0f);
    if (invertedL < lab.L) {
        lab.L = invertedL;
        return LabToSRGB(lab, SkColorGetA(color));
    } else {
        return color;
    }
}

ダークテーマ用colors.xmlの生成

Skiaについては共有ライブラリを比較的簡単に生成できる[2]ので良いのだが、Hwuiについてはandroidソースコードが巨大すぎてコンパイルするのも大変そうだったので該当ファイルだけ抽出してヘッダーファイルを書き直す対応をした。

macOS Mojava
バージョン 10.14.3
clang++ --std=c++14 \
    -I ~/skia/include/core \
    -I ~/skia/include/config \
    -I ~/skia/include/utils \
    -I ~/skia/include/gpu \
    -I ~/skia \
    -I transform.h \
    -I Color.h \
    -I ColorSpace.h \
    -L ~/skia/out/Static \
    -lskia -lz transform.cpp Color.cpp ColorSpace.cpp main.cpp

実際のコードは以下 https://github.com/sdsd08013/dark_color_gen

結果

以下droidkaigi2018の公式アプリのcolors.xmlからダークテーマ用のcolors.xmlを生成してビルドした結果である。それっぽい色味にはなるがやはりこれだけだと完成度は低いなという印象で、実際のAndroidのフォースダークと比べても、リアルタイムでダークテーマ用のカラーを生成してレンダリングができるフォースダークのダークテーマのほうが完成度が高い。

refs

[1]wiki Lab色空間 [2]skia公式 [3]android Git repositories Learning about the Android graphics subsystem