大辞泉のためのレンダリングエンジン、Sayori


先日、『大辞泉』のデザインは紙に近くなったって話をした。明朝、ゴシックなど様々なフォントを混在させて誌面を作っている。

これって、紙やWebのデザインやっている人にはごく当たり前のことだけど、プログラムを組む人にとっては悪夢のような仕様だ。iOSでは文字を描画する基本的な部品として、UILabelというクラスが用意されている。これ、基本は同一フォントしか描画しない。いちおう、iOS 6からフォント混在したリッチテキストも描画できるようになった。でもNSAttributedString使わないといけないんだよなぁ。あれ、めんどくさいんだよなぁ。そもそも、今回の仕様は、約物字詰めあるし、ルビあるし、なにより縦書きあるし。UILabelとNSAttributedStringじゃ力不足だ。

じゃ、HTMLか?たしかに、HTMLとCSSなら、きちんと記述する事はできる。ルビはrubyタグで。縦書きはCSSのwriting modeで。でもその表示を行うWeb Kitが、どうにもイマイチ。いやもちろん、Web KitはWebブラウザとして使うなら、なんの問題はないよ。でも今回は、リッチテキストを表示するためのラベル的な使い方をしたいんだ。それだと、重いし、内部に簡単にアクセスできないし。ひとことで言えば、too muchだ。自転車でちょっとコンビニ行きたいだけなのに、新幹線を持ってくるようなもんだ。

ならば作るしかない!無いものは作る、がエンジニアの思想だ。というわけで、自前のHTMLレンダリングエンジンを開発した。それが、Sayoriレンダリングエンジンだ。ちなみに名前は、うちの会社は伝統的にプロジェクト名に魚の名前を採用するため、こうなった。

Sayoriレンダリングエンジンでは、SYLabelというクラスを提供している。UILabelのように、画面に文字を描画するものだ。通常のテキストではなくて、HTMLとCSSを指定できる。こんな感じで使う。

SYLabel* label;
label = [[SYLabel alloc] init];
label.html = @"<html><body><h1>りんご</h1><p>バラ科の落葉高木。また、その果実。</p></body></html>";
label.css = @"h1 { font-size: 2em; font-weight: bold; } p { line-height: 1.5em; }";
[label sizeToFit];
[self.view addSubview:label];

どうよ?!便利でしょう。

UIWebViewと比較すると、軽量である事、同期的に動作する事が、差異になる。UIWebViewの非同期動作は、ブラウザとして使う分にはいいんだけど、ユーザインタフェース部品として使うときはやっかいだからね。

また、内部の構造にObjective-C APIでアクセスできるのも便利だ。UIWebViewだとJava Scriptしか手段がないから、もう面倒でしょうがない。

その他にも、ルビ、縦書き、縦中横、約物字詰め、均等割付け、リンク、テーブル表示、グリフID指定なんかにも対応。けっこう独自の拡張している。

とにかく軽量だし使いやすいんで、『大辞泉』のあらゆるところで使っているよ。

このエンジン、公開するのはやぶさかではないんだけど、サポートの手間が大変な事になりそうなので、躊躇中。

大辞泉サポートページは、こちら
HMDT大辞泉Facebookページは、こちら

    • tky777
    • 2013年 5月24日

    いつも拝見しております。
    CustomViewにフォント別で描画してましたが、常々このような表現力豊かなラベルがあったら良いなと思っておりました。
    是非是非、公開してくださいませ。

    • Tiqe
    • 2013年 5月25日

    こう言うエンジンと言うか縦書き機能って標準でもほしいっすね!
    HMDTジャーナルで解説記事を載せて公開して欲しい。(使い方や縦書きCSSとか例を幾つか解説など踏まえられて)
    大辞泉で不便なのは縦書き選択とかコピペが出来ない事なんですがHTMLレンダリングエンジンですし難しい部分なんでしょうか。
    縦書き選択とかで悩んで詰まってるので、文字選択やコピペなどが可能になっていけばシェアエンジンでも書いたいですね。そんな高いと買えませんが(笑

      • mkino
      • 2013年 5月25日

      文字列の選択機能は、もう実装済みなので、1.1で登場する予定です。

        • Tiqe
        • 2013年 5月26日

        おお、凄い!
        ますますこのエンジン欲しいです(笑)

        こちらも負けずにABC記譜法を解釈して音楽を鳴らすって事やってます。
        もし、公開された際はABC記譜法から楽譜を起こすとか、楽譜選択の参考などにさせてもらいつつ、楽譜表示エンジンを作っていきたいですね。
        描画エンジンの作り方って全然解らないんで、連載再開時は今後そう言うのも連載していただきたいです。

        • Samejima
        • 2016年 6月25日

        いつも拝見しております。1.1はいつ登場する予定ですか?

    • Nakata
    • 2014年 11月5日

    いつも拝見しております。

    最近青空文庫のようなアプリを作っています、Sayori Labelの縦書き機能がとっても使いやすいと思います、でも文字数が多くなると、SYLabelの幅はiPhone画面サイズを超える場合があります、UIScrollViewの中に複数のSYLabelを配置して、これをスクロールさせるつもりですが、label.htmlの文字列はどう適当に分割できますか? 教えていただけますでしょうか、よろしくお願いします。

      • mkino
      • 2014年 11月5日

      HTMLの分割がページネーションを意味しているのでしたら、
      その機能は現在のSayoriにはないです。
      作りこむ必要があります。

      HTMLのレイアウトはSYTextLayoutというクラスでやっています。
      そのメソッドに手を入れて、画面の端までいったら分割する、
      という処理を付け加えることになるでしょうね。

        • Nakata
        • 2014年 11月6日

        ご回答ありとうございました。そうですね、ページネーションの意味です。

        SYTextLayoutクラスを見ています、

        第1507行に 「static float _maxSize = 2048.0f;」という定数があります、SYLabelの幅を決めたそうです。ページネーションを実現する際には、外部からiPhoneのスクリーンの幅によって_maxSizeを変更する必要がありますようね。

    • nakata
    • 2015年 1月10日

    いつもおせわになっております。

    2月から、新しいアプリをアップロードするとき64bitサポートが必要です、Sayori 1.1が期待しています。また カスタマイズフォントを使いたいです、ぜひよろしくお願いします。

  1. トラックバックはまだありません。