追記
Issueが解決され、記事になっていた。今後は includeFontPadding=false
がデフォルトで適用されるようになるため
本記事の問題は影響しなくなるだろう。
medium.com
課題
これまでアプリでGoogle FontsからNotoフォントをダウンロードして使っていたが、Jetpack Composeに適用とすると上下に余白が出てしまう。
どうすればよいか。
対応
参考ページにもあるようにISSUE化はされているが現時点で対応されていない。
仕方がないのでフォントセット自体を修正して対応することに。
幸い同ISSUEの方にfonttoolsを使って上下幅を設定できるという投稿があり、それを試してみることにした。以下はその手順。
対応手順
前提条件:fonttoolsはpythonで書かれているのでpip3コマンドを使えるようにする。
- fonttoolsをインストール
- otfファイルのヘッダー情報を取得する
- ttxファイルを更新する
- otfファイルを作成する
- otfファイルを差し替え
fonttoolsをインストール
fonttoolsをインストールする
$ pip3 install fonttools
otfファイルのヘッダー情報を取得する。
以下のコマンド使ってotfファイルのヘッダー情報を取得する
$ ttx -t head noto_sans_jp_regular.otf
すると noto_sans_jp_regular.ttx
というファイルが生成される。
ttxファイルを更新する
ヘッダー情報を更新する。Robotoフォントの上下幅の設定を参考にする。以下は関係する部分の抜粋
- 1em辺りのデータサイズ(この辺は適当)が
unitsPerEm
で定義されている - roboto.ttxでは
unitsPerEm
が2048
に対して notoでは1000
が設定されている。なので設定値比率は2048 : 1000
である - roboto.ttxのyMinとyMaxを参考にnotoの値をセットする
// roboto.ttx <unitsPerEm value="2048"/> <yMin value="-555"/> <yMax value="2163"/>
2048 : 1000 なので -555 : yMin、 2163 : yMaxでRobotと同じ余白になるように合わせる
// noto_sans_jp_regular.ttx <unitsPerEm value="1000"/> <yMin value="-270"/> <yMax value="1056"/>
otfファイルを作成する
$ ttx -m noto_sans_jp_regular.otf -b noto_sans_jp_regular.ttx
するとnoto_sans_jp_regular#1.otf
というファイルが生成される。
otfファイルを差し替え
それをnoto_sans_jp_regular.otf
に上書きコピーすればOK
mv -f noto_sans_jp_regular#1.otf noto_sans_jp_regular.otf
備考
Style(Bold, Mediumなど)ごとに微妙にyMin
,yMax
が異なるのでそれに合わせて1ポイントずつ余白を少なくした方がいい感じになる。
使用される文字によってはおかしくなる場合があるかもしれない。
参考
- https://issuetracker.google.com/issues/171394808#comment32
- TrueType fundamentals (OpenType 1.9) - Typography | Microsoft Docs
検証に使ったコード
@Composable fun NotoText() { Text(text = "Noto Sans JP", fontFamily = NotoSansJpFamily, fontWeight = FontWeight.Medium) } @Composable fun RobotoText() { Text(text = "Roboto", fontFamily = RobotoFamily, fontWeight = FontWeight.Medium) } @Preview @Composable fun NotoPreview() { Surface(Modifier.background(Color.White)) { NotoText() } } @Preview @Composable fun RobotoPreview() { Surface(Modifier.background(Color.White)) { RobotoText() } }