13
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

iOSにフォントをいっぱいインストールしたい

Last updated at Posted at 2017-06-13

概要

 たくさんのフォントをiOSにインストールするためのスクリプトを書いたよ。

iOSにオリジナルのフォントをインストールするための選択肢

実際にやってみる

 Apple Configurator 2は、Apple公式のApp且つ無料ということで使ってみる。
「ファイル」>「新規プロファイル」で、あとはフォントを追加するだけ…
MyFonts.mobileconfig.png
…あれ?1つずつしかフォントファイルを追加できないんですが…1

あなたがプログラマーなら

 繰り返す単純作業は機械に任せますよね?

.mobileconfigってどんなファイル?

 さて、構成プロファイルは、*.mobileconfigというファイルとして保存されます。…そんなファイル形式知らない?
 では、調べてみましょう。「構成プロファイルリファレンス」という記事を読むと…なんと、中身は単なるXMLファイル(もっと言えばmacOSではお馴染みのproperty list)だとのこと。それならなんとかなりそうですね。macOS以外のOSで作成することも可能です。

.mobileconfigにフォントを埋め込むには

MyFont-001.TTFMyFont-002.TTFを埋め込んだ一例:

MyFont.mobileconfig
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>PayloadContent</key>
	<array>
		<dict>
			<key>Font</key>
			<data>
			[略]<!-- Base64エンコードされたフォントファイルのデータ -->
			</data>
			<key>Name</key>
			<string>MyFont-001.TTF</string>
			<key>PayloadDescription</key>
			<string>Configures Font settings</string>
			<key>PayloadDisplayName</key>
			<string>Font</string>
			<key>PayloadIdentifier</key>
			<string>com.apple.font.some-uuid-001</string>
			<key>PayloadType</key>
			<string>com.apple.font</string>
			<key>PayloadUUID</key>
			<string>some-uuid-001</string>
			<key>PayloadVersion</key>
			<integer>1</integer>
		</dict>
		<dict>
			<key>Font</key>
			<data>
			[略]<!-- Base64エンコードされたフォントファイルのデータ -->
			</data>
			<key>Name</key>
			<string>MyFont-002.TTF</string>
			<key>PayloadDescription</key>
			<string>Configures Font settings</string>
			<key>PayloadDisplayName</key>
			<string>Font</string>
			<key>PayloadIdentifier</key>
			<string>com.apple.font.some-uuid-002</string>
			<key>PayloadType</key>
			<string>com.apple.font</string>
			<key>PayloadUUID</key>
			<string>some-uuid-002</string>
			<key>PayloadVersion</key>
			<integer>1</integer>
		</dict>
	</array>
	<key>PayloadDescription</key>
	<string>Yes, My Fonts</string>
	<key>PayloadDisplayName</key>
	<string>My Fonts</string>
	<key>PayloadIdentifier</key>
	<string>com.example.fonts.my-fonts</string>
	<key>PayloadOrganization</key>
	<string>my company</string>
	<key>PayloadRemovalDisallowed</key>
	<false/>
	<key>PayloadType</key>
	<string>Configuration</string>
	<key>PayloadUUID</key>
	<string>some-payload-uuid</string>
	<key>PayloadVersion</key>
	<integer>1</integer>
</dict>
</plist>

.mobileconfigにフォントをいっぱい埋め込むには

 さて、プログラミングのお時間です。バイナリデータ(フォント)の読み込み・Base 64エンコード・テキストファイル(XMLファイル)への書き出しができればいいので、実装はなんでもいいでしょう。私はRubyを選びました。
 そんなに難しいことはないので、ソースだけどーん:

#!/usr/bin/env ruby

require 'pathname'
require 'base64'

filenames = ARGV.map {|filename| Pathname(filename) }

if filenames.size < 1
  $stderr.puts("No font files specified...")
  exit(false)
end

Directory = Pathname("~/Library/Mobile Documents/iCloud~com~apple~configurator~ui/Documents").expand_path

puts("Enter filename:")
output = $stdin.gets.chomp
output += '.mobileconfig' if output !~ /\.mobileconfig$/i
output = Directory + Pathname(output)
puts("-> Data will be written to '#{output.to_s}'.")

puts("Enter display name: (e.g. My Fonts)")
displayName = $stdin.gets.chomp

puts("Enter description: (e.g. These are my fonts.)")
description = $stdin.gets.chomp

puts("Enter identifier: (e.g. com.example.font.my-font)")
identifier = $stdin.gets.chomp

puts("Enter organization: (e.g. My Company)")
organization = $stdin.gets.chomp

puts("-----")
puts("Creating #{output.basename.to_s} ")

output.open('w'){|mobileconfig|
  mobileconfig.puts('<?xml version="1.0" encoding="UTF-8"?>')
  mobileconfig.puts('<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">')
  mobileconfig.puts('<plist version="1.0">')
  mobileconfig.puts('<dict>')
  mobileconfig.puts('	<key>PayloadContent</key>')
  mobileconfig.puts('	<array>')
  
  # Read, convert, and write fonts data.
  filenames.each {|filename|
    font_uuid = `uuidgen`.chomp
    
    mobileconfig.puts('		<dict>')
    mobileconfig.puts('			<key>Font</key>')
    mobileconfig.puts('			<data>')
    
    filename.open('rb') {|font|
      # Read data 52 * 6 bits (39 bytes) at a time.
      buffer = "\0" * 39
      while !font.read(39, buffer).nil?
        mobileconfig.puts("			#{Base64.strict_encode64(buffer)}")
      end
    }
    
    mobileconfig.puts('			</data>')
    mobileconfig.puts('			<key>Name</key>')
    mobileconfig.puts("			<string>#{filename.basename.to_s.encode(Encoding::UTF_8, :xml => :text)}</string>")
    mobileconfig.puts('			<key>PayloadDescription</key>')
    mobileconfig.puts('			<string>Configures Font settings</string>')
    mobileconfig.puts('			<key>PayloadDisplayName</key>')
    mobileconfig.puts('			<string>Font</string>')
    mobileconfig.puts('			<key>PayloadIdentifier</key>')
    mobileconfig.puts("			<string>com.apple.font.#{font_uuid}</string>")
    mobileconfig.puts('			<key>PayloadType</key>')
    mobileconfig.puts('			<string>com.apple.font</string>')
    mobileconfig.puts('			<key>PayloadUUID</key>')
    mobileconfig.puts("			<string>#{font_uuid}</string>")
    mobileconfig.puts('			<key>PayloadVersion</key>')
    mobileconfig.puts('			<integer>1</integer>')
    mobileconfig.puts('		</dict>')
  }
  
  
  mobileconfig.puts('	</array>')
  mobileconfig.puts('	<key>PayloadDescription</key>')
  mobileconfig.puts("	<string>#{description.encode(Encoding::UTF_8, :xml => :text)}</string>")
  mobileconfig.puts('	<key>PayloadDisplayName</key>')
  mobileconfig.puts("	<string>#{displayName.encode(Encoding::UTF_8, :xml => :text)}</string>")
  mobileconfig.puts('	<key>PayloadIdentifier</key>')
  mobileconfig.puts("	<string>#{identifier.encode(Encoding::UTF_8, :xml => :text)}</string>")
  mobileconfig.puts('	<key>PayloadOrganization</key>')
  mobileconfig.puts("	<string>#{organization.encode(Encoding::UTF_8, :xml => :text)}</string>")
  mobileconfig.puts('	<key>PayloadRemovalDisallowed</key>')
  mobileconfig.puts('	<false/>')
  mobileconfig.puts('	<key>PayloadType</key>')
  mobileconfig.puts('	<string>Configuration</string>')
  mobileconfig.puts('	<key>PayloadUUID</key>')
  mobileconfig.puts("	<string>" + `uuidgen`.chomp + "</string>")
  mobileconfig.puts('	<key>PayloadVersion</key>')
  mobileconfig.puts('	<integer>1</integer>')
  mobileconfig.puts('</dict>')
  mobileconfig.puts('</plist>')
}

puts('-- done.')

 コマンドライン引数としてフォントファイルのパスを複数受け取って処理するだけのスクリプトです。構成プロファイルはApple Configurator 2のiCloud Driveのフォルダに作成されるようになっています。
 個人用途なのでエラー処理とかはしていませんが、気になる人はしてみてもいいでしょう。

あとは出来上がった構成プロファイルを端末にインストールするだけ

 前述の「構成プロファイルリファレンス」には、こう書かれています:

構成プロファイルの配布方法は5通りあります。

  • App Storeから入手可能なApple Configurator 2を使用
  • 電子メールで配布
  • ウェブページ上で配布
  • 『無線経由のプロファイル配信と構成』で説明したワイヤレス構成を利用
  • Mobile Device Management Serverを利用(無線)

注意点・問題点

フォントのライセンス

 あなたがiOSにインストールしたいと思っているフォントは、本当にiOSにインストールしても大丈夫ですか?
 他人への配布??そんなのもってのほかではないですか?
 フォントのライセンスには気をつけましょう。

iOSのあらゆるAppでフォントを変えられる訳ではない

 これは仕方ありません。Appが対応している必要があります。
 “メモ”やPages, Numbers, KeynoteなどのApple公式のAppはもちろん、Word, ExcelなどMicrosoftのAppも対応しているようです。

.mobileconfigのファイルサイズが大きいとApple Configurator 2で転送できない

 ファイルサイズが20-30MBを越えるとApple Configurator 2で端末に転送できないようです2。その場合は、多少面倒でも電子メールやWebページ経由でやるしかありません。

.ttc, .otc, .dfontなどは使えない

 複数のフォントを収納した.ttc(TrueType Collection)は使えないようです3.otc, .dfontも同じ。一旦、複数の.ttfファイルや.otfファイルに分割してから構成プロファイルに埋め込む必要があります。

  1. バージョン2.4 (3E45)現在
     1つのプロファイルに複数のフォントを埋め込むことはできるけど、ファイル選択ダイアログで複数のフォントファイルを同時に選択できない。1つや2つならいいけど、たくさんのフォントを埋め込みたかったら、ファイル選択ダイアログを開いてファイルを選んで…ということをフォントの数だけ繰り返さなくてはいけない。これは面倒。

  2. バージョン2.4 (3E45)現在

  3. iOS 10.3.2現在

13
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?