Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
12
Help us understand the problem. What is going on with this article?
@YOCKOW

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

More than 3 years have passed since last update.

概要

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

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

実際にやってみる

 Apple Configurator 2は、Apple公式のApp且つ無料ということで使ってみる。
「ファイル」>「新規プロファイル」で、あとはフォントを追加するだけ…
MyFonts.mobileconfig.png
…あれ?1つずつしかフォントファイルを追加できないんですが…1
 1つのプロファイルに複数のフォントを埋め込むことはできるけど、ファイル選択ダイアログで複数のフォントファイルを同時に選択できない。1つや2つならいいけど、たくさんのフォントを埋め込みたかったら、ファイル選択ダイアログを開いてファイルを選んで…ということをフォントの数だけ繰り返さなくてはいけない。これは面倒。

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

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

.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)現在 

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

  3. iOS 10.3.2現在 

12
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
YOCKOW
Hi, I'm YOCKOW.

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
12
Help us understand the problem. What is going on with this article?