San Francisco フォントを探る

<img width="701" src="https://qiita-image-store.s3.amazonaws.com/0/3603/764b93bf-4411-a840-0397-7a41f7ef35d9.png">

# San Francisco Font Family

San Francisco はひとつの書体ではなく、SF Pro, SF Compact などと呼ばれ、それぞれに Text, Display, Rounded バージョンが存在します。Text よりも Display の方が多くのウェイトを揃えているのは、Text は視認性を重視した書体ゆえ、細いものは利用する想定にないからなのだと思われます。SFシリーズはVariable fontに対応しています。


<img width="960" src="https://qiita-image-store.s3.amazonaws.com/0/3603/95221cc2-61bc-b34f-0f27-61412c92932b.png">


## SF Pro vs. SF Compact

SF Pro は macOS や iOS, tvOS デバイスのシステムフォントとして採用されています。SF Compact は Apple Watch のシステムフォントとして採用されています。Compact は字が四角形に近い形をしていて、Apple Watch のような小さなデバイスでも視認しやすいようにデザインされています。

<img width="960" src="https://qiita-image-store.s3.amazonaws.com/0/3603/4001028c-ece4-c625-653f-0f33a7c3a298.png">


## SF Pro vs. SF UI

`SF UI` と名乗っていた書体がいつの間にか `SF Pro` と名乗るようになっていて、「SF UI はどこに行ったんだ？」と疑問に思っていました。詳しい事情はよくわかりませんが、San Francisco 書体は細かなアップデートを重ねていて、2017年6月の WWDC 2017 (macOS High Sierra / iOS 11) を境に SF UI が SF Pro に置き換わったようです。なので現在では **SF UI は旧版**という扱いになります。Font Book.app で情報を確認してみると、SF UI の方のコピーライトは 2015 でバージョン12系、対して SF Pro の方は 2015-2017 でバージョン13系となっていたので、今後は SF Pro を使っていきましょう。

公式の言及としては、過去のHIGに「以前はSF UIだった」との記述があり、すでに古い書体として扱われていることが読み取れます。（現在のHIGからはこの記述は削除されており、もはや言及する必要がないほど古い書体扱いになっているのかもしれません。）

![スクリーンショット 2023-06-04 1.09.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3603/034b1773-62fc-a795-dd37-aa3fba8a08ef.png)

https://web.archive.org/web/20170711081132/https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/
> In iOS 10, the San Francisco variants were SF UI Text and SF UI Display.

SF Pro も今後はアップデートされていくと予想されるので、WWDC 後くらいになったら Apple の [San Francisco フォントのページ](https://developer.apple.com/fonts/)で提供される最新の SF Pro 書体を手に入れると良いでしょう。

（GitHub で数多くの San Francisco が見つかりますが、おそらくは誰かが勝手にアップロードしているものと思われるので、必ず公式サイト https://developer.apple.com/fonts/ から入手するようにしましょう。）

参考として以下に歴代の SF のバージョン表を記しておきます。常にチェックしているわけでもなく、私が把握できた限りで記載しますので、抜けがある可能性は高いです。

|書体名|バージョン|備考
|:--|:--|:--|
|SF Pro Display|15.0d5e5; 2019-07-10|2019年7月版|
|SF Pro Text|15.0d5e5; 2019-07-10|2019年7月版|
|SF Pro Rounded|15.0d5e5; 2019-07-10|2019年7月版|
|SF Pro Display|13.0d1e33; 2017-05-30|2017年版|
|SF Pro Text|13.0d3e20; 2017-05-30|2017年版|
|SF UI Display|12.0d6e2; 2016-12-21|手元で確認できた最終版。iOS 10 まで|
|SF UI Text|12.0d6e2; 2016-12-21|手元で確認できた最終版。iOS 10 まで|
|SF UI Display|11.0d45e1--BETA; 2015-05-21|2015年ベータ版|
|SF UI Text|11.0d45e1--BETA; 2015-05-21|2015年ベータ版|
|SF Compact Display|15.0d5e5; 2019-07-10|2019年7月版|
|SF Compact Text|15.0d6e5; 2019-07-10|2019年7月版|
|SF Compact Rounded|15.0d5e5; 2019-07-10|2019年7月版|
|SF Compact Display|12.0d8e1; 2016-12-21|2016年12月版|
|SF Compact Text|12.0d8e1; 2016-12-21|2016年12月版|
|SF Mono|15.0d4e71; 2019-06-25|2019年6月版|
|SF Mono|13.1d0e1; 2017-05-04|2017年5月版（Xcode / Terminal バンドル版）|


## SF Mono

元々は Xcode や Terminal で採用されていた等幅の SF ですが、2019年8月にフォントファイルとして一般公開されました。SF 書体がベースですが、特にコードの可読性が良くなるようにデザインされています。

![](https://qiita-image-store.s3.amazonaws.com/0/3603/e67f81b2-fff1-68a2-aba1-e7d7d86ff490.jpeg)

Xcode や Terminal ではそれぞれ以下のディレクトリに配置されています。

```
Xcode.app/Contents/SharedFrameworks/DVTKit.framework/Versions/A/Resources/Fonts/
```
```
Terminal.app/Contents/Resources/Fonts/
```

## SF Arabic

アラビア語向けシステムフォントに採用されています。


## SF Pro JP

Apple の web や資料などで使われている日本語フォントです。web サイト上では SF Pro JP という名称の Web フォントであることが判明しています。現在のところ公にフォントファイルとしては一般提供されていません。見た目は AXIS にそっくりです。

<img width="825" src="https://qiita-image-store.s3.amazonaws.com/0/3603/58f5ee43-1729-ba5d-2b6c-16444394d781.png">

## System Font （システムフォント）

![screenshot_rectangles.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3603/1da80c33-d725-4678-452a-578dfc6a6118.png)


AppleプラットフォームのOSで採用されているメタフォント、公開・配布されているものではない。SF Proをベースとして、 **レンダリング内容が20pt未満の場合にTextに、20pt以上の場合にDisplayに自動で置き換え、トラッキング（間隔）やウェイト（太さ）にもUI上の視認性を考慮した自動調整が施されます。** （自動調節はSF Pro書体には備わっていない）

日本語環境においては、日本語書体部分はヒラギノ書体との組み合わせでレンダリングされます。同様に、ほかの言語環境の場合にも複数の書体が組み合わさる場合があるため、「SF Pro = System Font」と見るのは正確ではありません。

実体としては.AppleSystemUIFontなどの名称を持った隠しフォントと見えることがあります。

WebのCSSでは、次のような記述により「ネイティブと同じSystem Fontのレンダリング」を再現することができます。OSのUIとの適合を目的とする場合に効果的です。

```css:style.css
/* フォントに「System Font」を適用する */
font-family: -apple-system, BlinkMacSystemFont, system-ui;
```

`-apple-system`はSafari用、`BlinkMacSystemFont`はChrome用です。`system-ui`も基本的に同様の目的と効果を得るためのプロパティですが、ブラウザによって実装のばらつきがあるため、過渡期においては複数個記述するのが無難だと思います。

関連:

https://drafts.csswg.org/css-fonts-4/#system-ui-def

https://developer.apple.com/videos/play/wwdc2020/10175/?time=1293


## Display vs. Text

小さな文字は読みやすく、大きな文字は美しく描画されなければなりません。昨今はさまざまな大きさのディスプレイが存在しますから、それら環境ごとにフォントの課題というものも異なってくるというわけです。そのため、SF Pro, SF Compact にはそれぞれ `Display` と `Text` の2バージョンが用意されています。
2018年ごろからは丸い書体である `Rounded` も加わっています。

<img width="960" src="https://qiita-image-store.s3.amazonaws.com/0/3603/a92b7cb1-f3c6-e27f-249e-82d1571ffae8.png">

Text は小さな文字でも読みやすいよう字間や太さが調整されていますが、これを見出しなどに用いると逆にそれらが悪く目立ってしまい、美しさを損なってしまいます。そこで、システムフォントでは小さなテキストには Text, 大きなテキストには Display を用いるように自動的に切り替える仕組みになっています。**20pt 以上のテキストには Display、それ未満には Text** という具合です。
macOS/iOS ネイティブアプリでシステムフォントを利用しているなら自動的に行われる処理ですが、Sketch などのスクリーンデザインの現場ではこのことをデザイナーが意識する必要があります。

- **SF Pro Display** – 20pt 以上の大きなテキスト向け。これをそのまま縮小表示すると字が詰まって読みづらい
- **SF Pro Text** – 20pt 未満の小さなテキスト向け。Display よりも可読性に優れるが、これをそのまま拡大表示するとあまり美しくない
- **システムフォント** – macOS や iOS のユーザーインターフェイスに採用されているフォント。「システムフォント」は特定の書体ではなく、複数のフォントを内包したメタフォント。メタフォントは状況に応じて自動的に実体のフォントを切り替える。実体のフォントはよく `.AppleSystemUIFont` などで表されるがこの名称は固定値であるとは保証されないため、直に指定してはならない

# ウェイト

<img width="346" src="https://qiita-image-store.s3.amazonaws.com/0/3603/812e835f-3866-9eae-5281-b8c88e149689.png">

ウェイトの種類は次の通りです。Cocoa では [NSFont.Weight](https://developer.apple.com/documentation/appkit/nsfont.weight)、Cocoa Touch では  [UIFont.Weight](https://developer.apple.com/documentation/uikit/uifont.weight) として定義されています。

- Ultra Light （極細）
- Thin
- Light
- Regular （通常）
- Medium
- Semibold
- Bold
- Heavy
- Black （極太）

ただし、SF Pro Text の場合には上の `Family Tree` の画像が示すように次のものに限ります。

- Light
- Regular
- Medium
- Semibold
- Bold
- Heavy


ウェイト指定でシステムフォントを得るには、次のようにします。

```swift:macOS
let font = NSFont.systemFont(ofSize: 20, weight: NSFont.Weight.light)
```

```swift:iOS
let font = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight.light)
```

NSFont または UIFont オブジェクトからウェイト情報を得るには、いったん CTFont にキャストしてからその情報を抽出します。[CTFont と NSFont, UIFont は toll-free bridge の関係にある](https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/CoreText_Programming/Overview/Overview.html#//apple_ref/doc/uid/TP40005533-CH3-SW5)ので、このようにとても簡単にキャストすることができます。

```swift:macOS
let ctFont = font as CTFont
let traits = CTFontCopyTraits(ctFont) as Dictionary // CFDictionary もまた Dictionary にキャストできる
if let weightNum = traits[kCTFontWeightTrait] as? NSNumber {
    let weight = NSFont.Weight.init(CGFloat(weightNum.doubleValue))
  ...
}
```

# Tracking

「システムフォント」と SF Pro Display / SF Pro Text をならべてみても、それらの字間が異なることに気付くかと思います。システムフォントでは Tracking と呼ばれる Kerning に似た字間の調整が独自に行われています。Tracking の値はポイントサイズに応じて個別に定義されており、その Tracking Table は Apple からも提供されています。

<img width="960" src="https://qiita-image-store.s3.amazonaws.com/0/3603/5922f640-8d8f-75cb-1777-1b2c0ff1300c.png">

iOS HIG に SF の Tracking Table が記載されています。Tracking Table は SF のバージョンごとに異なる場合があるため、常に最新版を参照するようにしましょう。

Human Interface Guidelines - Typography
https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/

かつて San Francisco フォントのページにリンクがあった Tracking 対応表 (iOS & OS X Tracking Chart) なるファイルは SF Pro では値が異なるので役に立ちませんが、古い SF UI の Tracking が知りたければ役立つかもしれません。

iOS & OS X Tracking Chart
https://developer.apple.com/fonts/downloads/iOS-OSX.zip


## Tracking → Character Spacing

Tracking の値をそのまま利用できない環境もあるかと思います。例えば Sketch では Character Spacing という項目になっています。

次の記事によると、Tracking と Character Spacing の変換は単純な計算式によって行うことができます。

> http://devsign.co/notes/tracking-and-character-spacing
> I created lots of PSDs and Sketch files, comping up different tracking values and character spacing values, and doing pixel comparisons to figure out what lined up. Once I found a match between tracking, character spacing, and font size, I put it in a spreadsheet and worked out some theories as to how the two were related - and after a bit of algebra, I found that it was actually a very simple relationship:
> 
> `characterSpacing = fontSize * tracking / 1000`

Tracking を直接扱うことができない場合には、この式を使って Character Spacing の値を割り出す必要があります。


## システムフォント vs. SF Pro Display vs. SF Pro Text

実際に「システムフォント」、SF Pro Display、SF Pro Text とで結果にどのような違いがあるのか、簡単な macOS アプリを作って実験しました。

<img width="683" src="https://qiita-image-store.s3.amazonaws.com/0/3603/53c3e509-5115-bbe8-3783-ba877b66baca.png">

20pt 付近では、システムフォントと Display, Text それぞれの差が一番大きく現れます。`T` `e`の字間に注目すると、19pt から 20pt で Text だったのが Display に切り替わっていることがわかります。
そして、小さくなるほどシステムフォントと Text の差が縮まってゆき、目視でおよそ 12pt に達すると両者一致します。逆に大きくなるほどシステムフォントと Display の差が縮まってゆき、目視でおよそ 78pt で両者が一致しました。

この結果が意味するのは、システムフォントというのは SF Pro Display とも SF Pro Text とも異なる書体だということです。20pt で切り替わるルールを考慮したとしても、フォント名に `SF Pro Display` を指定してテキストを描画した場合は macOS や iOS ネイティブのそれとは異なる結果になってしまうでしょう。

このことは Sketch でも同様でした。システムフォントの描画を実現させられる[Sketch プラグイン](https://github.com/usagimaru/Sketch-AppleSystemFont-Plugin)を自作し、これと同様のことを試してみましたが、やはりシステムフォントというのは SF Pro ** とは異なる Tracking が適用されました。

![](https://qiita-image-store.s3.amazonaws.com/0/3603/3e650e4e-57ca-2548-3ed9-38ab1d5a45ae.png)


# SF のさまざまな機能を呼び出す

SF にはあまり知られていない多くの機能が備わっています。これらは Typographic Features, Font Features とも言います。

例えば数字で囲ったコロン `:` を中央に寄せて見栄えを良くする機能もその一つです。

<img width="320" src="https://qiita-image-store.s3.amazonaws.com/0/3603/768a5aca-0a57-aa90-72f5-becf6a1c7ce5.gif">

## TextEdit.app でタイポグラフィ機能を手動操作する

TextEdit.app でなくても良いのですが、Cocoa が提供するタイポグラフィの機能を備えており、かつリッチテキストを扱える身近なエディタだったのでこれを採用しました。

フォントパネルの歯車メニューから「タイポグラフィ…」を選択すると、その書体が持つさまざまな機能の一覧を表示することができます。

<img width="187" src="https://qiita-image-store.s3.amazonaws.com/0/3603/1558d509-26df-272d-af5f-d07815ab1c6a.png">

<img width="260" src="https://qiita-image-store.s3.amazonaws.com/0/3603/8ee79ef9-d4c8-a1e1-53c3-f11e2e433df1.png">

以下にいくつかご紹介します。

### 等幅数字

「等幅数字」にチェックを入れると、数字が等幅になります。日付や時刻、容量の表記などに使うと良いでしょう。

<img width="565" src="https://qiita-image-store.s3.amazonaws.com/0/3603/fab819d0-3c7e-d727-e3fd-f2a9bdbefea4.png">

![](https://qiita-image-store.s3.amazonaws.com/0/3603/9763dcd2-0062-eb89-24fc-be277176a005.gif)
*刻々と変化する数値は等幅の方が見栄えが良い。*

### 記号類を大文字の縦中央に合わせる

「大文字の字形」は、x-height に合わせられている記号類を大文字に合わせてくれるものです。

<img width="426" src="https://qiita-image-store.s3.amazonaws.com/0/3603/a07ed0be-5339-2c0c-0402-f898373b496a.png"> <img width="426" src="https://qiita-image-store.s3.amazonaws.com/0/3603/d452be1b-3989-5f09-0485-a163510bdd90.png">

### 上付き文字／下付き文字／a→ɑ

数式や化学式で用いられる小文字を表せます。また、a の右側がまっすぐな **ɑ** の字形にも対応しています。

<img width="330" src="https://qiita-image-store.s3.amazonaws.com/0/3603/a9ea247f-4111-e78d-52dc-a82f9944ff82.png">

## NSFont / UIFont で Font Features を利用する

NSFontDescriptor / UIFontDescriptor にはフォント属性を追加適用する API が備わっているので、これを利用します。

例えば、システムフォントに等幅数字の属性を追加するには次のようにします。

```swift:macOS/Cocoa
let size: CGFloat = 20.0
let systemFont = NSFont.systemFont(ofSize: size, weight: .regular)
let descriptor = systemFont.fontDescriptor()
let monoDigitDescriptor = descriptor.addingAttributes(
  [
    NSFontDescriptor.AttributeName.featureSettings : [
      [
			NSFontDescriptor.FeatureKey.typeIdentifier : kNumberSpacingType,
			NSFontDescriptor.FeatureKey.selectorIdentifier : kMonospacedNumbersSelector,
      ]
    ]
  ]
)

let monoDigitSystemFont = NSFont(descriptor: monoDigitDescriptor, size: size) ?? font
```

`typeIdentifier`, `selectorIdentifier` のペアごとに一つの配列を用意し、それを必要なだけ格納した配列を `NSFontDescriptor.AttributeName.featureSettings` をキーとして渡します。

`typeIdentifier` に対しては規定の属性名を表すキー、 `selectorIdentifier` に対しては規定のセレクタを渡します。これについては [About Apple Advanced Typography Fonts - Font Feature Registry](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html) もしくは ATSUI の [Font Features](https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/ATSUI_Concepts/atsui_app_features/atsui_appendixB.html#//apple_ref/doc/uid/TP30000035-TP1) に関するガイドがとても役立つでしょう。これらは AAT (Apple Advanced Typography) として TrueType の独自拡張として用意されたテーブルです。旧 Mac OS の QuickDraw GX の後継機能として開発され、Carbon でも利用された ATSUI (Apple Type Service for Unicode Imaging) に組み込まれました。AAT に関するリファレンスは現在の CoreText (SFNTLayoutTypes.h) にもあるので、ATSUI のガイドにあるキー名や効果はほぼ変わっていません。また、これらのドキュメントには実際の効果が画像付きで紹介されているので、とても有用だと思います。

SFNTLayoutTypes.h に記載されているキーが全て有効というわけではなく、フォントに備わっているもののみが効果があります。ヒラギノなら SF では利用できなかった日本語に関する属性が利用できます。先ほど紹介した TextEdit.app で効果を試す方法でなら、そのフォントが備える属性をタイポグラフィパネルに一覧することができます。

<img width="710" src="https://qiita-image-store.s3.amazonaws.com/0/3603/da11245f-bd9b-59d9-31b7-e7feb4a625ed.png">
*タイポグラフィパネル*

ここにある代替スタイルセットは `kStylisticAlternativesType` です。フォントにはグリフの異なる字形を代替するためのスタイルがあらかじめ用意されていて、好きに組み合わせて利用することができます。そのスタイル名は One, Two, Three といった具合にただの連番にしかなっていないため、一つひとつ手探りで効果を確認する必要がありました。


|スタイル名|効果|セレクタ名|
|:--|:--|:--|
|Straight-sided six and nine|直線の6, 9にする|kStylisticAltOneOnSelector|
|Open four|開いた4にする|kStylisticAltTwoOnSelector|
|Vertically centered colon|コロン `:` を中央寄せにする|kStylisticAltThreeOnSelector|
|High legibility|見やすくする。直線の6, 9、開いた4、斜線の0、ハネ付きの `l` など|kStylisticAltSixOnSelector|
|One storey a|a を右側がまっすぐな `ɑ` にする|kStylisticAltSevenOnSelector|

数字に囲まれたコロンを中央配置にする機能は、コンテクスト代替と呼ばれるものに組み込まれています。タイプのキーは `kContextualAlternatesType` です。これはデフォルトで有効なので、もしも無効化したいなら明示する必要があります。

|スタイル名|効果|セレクタ名|
|:--|:--|:--|
|（なし）|「数字に囲まれたコロンを中央配置にする」を無効化する|kContextualAlternatesOffSelector|


OpenType では `ss01` 〜 `ss20` といった具合に同等の仕組みが利用できるようです。Adobe の記事 [CSS での OpenType 機能の構文](https://helpx.adobe.com/jp/typekit/using/open-type-syntax.html) に書かれている「デザインのセット」のことです。

## Variation Axis Tag

これらのスタイル情報の参照には、AppleプラットフォームではCore Textの [CTFontCopyVariationAxes](https://developer.apple.com/documentation/coretext/1509987-ctfontcopyvariationaxes) APIを使って **Variation Axis Tag** という情報を取得する必要があります。
詳しくはこちらの記事およびサンプルコードを参考にしてください。

https://qiita.com/usagimaru/items/0d3c66618df43df93345

https://github.com/usagimaru/Variable-Font-Mac



# 参考資料

- WWDC 2015 Introducing the New System Fonts
 - https://developer.apple.com/videos/play/wwdc2015/804/
- Fonts - Apple Developer
 - https://developer.apple.com/fonts/
- Human Interface Guidelines - Typography
 - https://developer.apple.com/ios/human-interface-guidelines/visual-design/typography/
 - https://developer.apple.com/fonts/downloads/iOS-OSX.zip
- Tracking & Character Spacing in iOS
 - http://devsign.co/notes/tracking-and-character-spacing
- About Apple Advanced Typography Fonts - Font Feature Registry
 - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM09/AppendixF.html
- ATSUI Programming Guide - Font Features
 - https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/ATSUI_Concepts/atsui_app_features/atsui_appendixB.html#//apple_ref/doc/uid/TP30000035-TP1
- CSS での OpenType 機能の構文
 - https://helpx.adobe.com/jp/typekit/using/open-type-syntax.html
- get font-weight of an uitextview
 - https://stackoverflow.com/questions/18331388/get-font-weight-of-an-uitextview
- Core Text Programming Guide - Core Text Objects Are C-Language Opaque Types
 - https://developer.apple.com/library/content/documentation/StringsTextFonts/Conceptual/CoreText_Programming/Overview/Overview.html#//apple_ref/doc/uid/TP40005533-CH3-SW5