Windowsストア アプリ 縦書きビューワー Vol.4 ~プログラムの説明~

マイクロソフトの田中達彦です。
本連載では、過去の名作や自分の著書などをWindowsストア アプリ化するための縦書きビューワーについて説明します。

[WinRTでの縦書き]
Windowsストア アプリを作成するためのAPIであるWinRT(ARM用OSのWindows RTとは別のものです)は、縦書きに対応していません。
そのため、縦書きを実現させるために、TextBlockという文字を表示させるためのコントロールを、表示する文字数分だけ表示させる方法を使用しました。
以下の図の青い四角の部分が、それぞれTextBlockです。
空白を含め、原稿用紙のように画面一面にTextBlockを配置しています。

ふりがなの部分は、ふりがなとして表示する文字のところのみ小さなTextBlockを配置しています。

TextBlockコントロールは、最初から画面上に貼りつけているわけではありません。
画面の大きさにしたがって、プログラムによってTextBlockを貼りつけています。
原稿用紙のようにTextBlockを配置している部分は、MainPage.xaml.csの中のSetCharsメソッドです。
このメソッドで画面上の文字を表示するエリアの大きさを取得し、フォントサイズから縦と横の行数を計算しています。
そして、原稿用紙のマス目のようにTextBlockを配置しています。
これらのTextBlock1つずつに、文字を1つずつ設定していきます。
なお、縦の行数は、行頭禁則処理の関係で、文字を表示させるエリアよりも2文字分余分にTextBlockを配置しています。
例えば行頭に句読点が来るときは、その句読点を前の行の行末に表示させます。
句読点とそれに続いて閉じカッコがある場合は、閉じカッコも前の行の行末に表示させます。

Windowsストア アプリは、さまざまな解像度に対応させるだけではなく、スナップやポートレイト(縦長画面)にも対応させる必要があります。
それらの環境によって縦横の行数が変わってきます。
画面の状態が変化するたびに、TextBlockをマス目のように貼る作業を実行しています。

[文字の表示]
マス目のように配置されたTextBlockに文字を入れているのは、MainPage.xaml.csの中のSetTextというメソッドです。
表示させるべき文字列は、HonbunTextというstring型のフィールドに丸ごと入っています。
その中で表示を開始する位置を指定し、その位置にある文字を右上から順次表示させています。

このSetTextメソッドでは、どの文字を表示するかを判別し、特別な処理が必要かどうかを判断しています。
例えば、「」というようなカッコは、90度横に回転させて表示しています。
以下はその部分の処理です。
CompositeTransformを使用して、TextBlockを回転させたり、表示位置をずらしたりしています。

CompositeTransform ct = new CompositeTransform();
ct.TranslateX = 0;
ct.TranslateY = lineAdjust;
ct.CenterX = 0;
ct.CenterY = 0;
ct.Rotation = 0;
HonbunChar[x, y].RenderTransform = ct;
HonbunChar[x, y].Text = "";

if ("」≫』】〕)>]}:―…~ー-".IndexOf(HonbunText[index]) >= 0)
{
    ct.CenterX = HonbunFontWidth / 2;
    ct.CenterY = HonbunFontHeight / 2;

    ct.TranslateX = HonbunFontWidth / 6;
    ct.TranslateY += HonbunFontHeight / 8;

    ct.Rotation = 90;

    //

    HonbunChar[x, y].RenderTransform = ct;
}

if ("「≪『【〔(<[{".IndexOf(HonbunText[index]) >= 0)
{
    ct.CenterX = HonbunFontWidth / 2;
    ct.CenterY = HonbunFontHeight / 2;
    ct.Rotation = 90;

    ct.TranslateX = HonbunFontWidth / 6;
    ct.TranslateY += HonbunFontHeight / 6;

    HonbunChar[x, y].RenderTransform = ct;
}

以下のように、string型のオブジェクトのIndexOfメソッドを使用すると、その文字列に指定した文字が含まれているかどうかを判定できます。

if ("「≪『【〔(<[{".IndexOf(HonbunText[index]) >= 0)

この例では、カッコかどうかを判定しています。
CompositeTransformのCenterX、CenterYに回転の中心点を指定し、Rotationに角度を入れれば、TextBlockなどのコンポーネントを回転させることができます。
TranslateXやTranslateYを指定すると、そのコンポーネントをX方向またはY方向にずらすことができます。
WinRTでは縦書きフォントをサポートしていないため、このような方法で横書き用のフォントを縦書きで使用できるようにしています。

ゃ、ゅ、ょなどの拗音は、縦書きにあわせて右側に寄せるような処理をしています。
句読点も位置をずらして、縦書きとしておかしくない位置に表示させます。

[ふりがなの表示]
ふりがなについては、原稿用紙のマス目のように用意したTextBlockではなく、ふりがな用にTextBlockを追加します。
そのときに、TextBlockのTagプロパティに"rubi"という文字列を入れ、そのTextBlockがふりがな用であることを判別するようにしておきます。
なお、ふりがなを表す「ルビ」を英語で書くと"ruby"が正しいです。
ただ、rubyだとついつい「ルビー」と呼んでしまうので、コード中ではルビをローマ字表記したrubiという単語を使用しています。

Tagプロパティは、何を入れてもよいプロパティです。
自由に使うことができるため、今回はふりがなが入っているTextBlockかどうかの判定のために使用しています。
ふりがなの表示/非表示を切り替えるときは、使用しているTextBlockのTagプロパティを見て、そこにrubiと入っているTextBlockのみを表示/非表示にしています。

ふりがなは、表示する位置やふりがなとして表示させる文字列をSetRubiメソッドに渡すことにより、新たなTextBlockを貼りつけて、それを使用して表示させています。

(注) このプログラムは、当初に予定していた仕様よりも多くの機能を追加してしまいました。
そのため、後で追加した部分などはつぎはぎのようになっているところがあります。
本来であればきれいに書き直して公開したほうが良いものの、時間の問題で書き直さずに公開してしまいました。ご了承ください。

[連載記事一覧]
第1回 : アプリのテンプレート
https://blogs.msdn.com/b/ttanaka/archive/2013/04/11/windows-vol-1.aspx
アプリのテンプレートを提供するとともに、使用するときの注意事項、使用方法を説明しています。

第2回 : 青空文庫のアプリ化
https://blogs.msdn.com/b/ttanaka/archive/2013/04/12/windows-vol-2.aspx
文字下げ、文字上げなどの特殊処理を行う方法を説明しています。

第3回 : タイルの作成
https://blogs.msdn.com/b/ttanaka/archive/2013/04/12/windows-vol-3.aspx
アプリを公開する際に必ず用意しないといけないタイルの作成方法を説明します。

第4回 : プログラムの説明
https://blogs.msdn.com/b/ttanaka/archive/2013/04/15/windows-vol-4.aspx
どのような方法で縦書きを実現させているのかを説明します。

第5回 : 特殊処理の追加
https://blogs.msdn.com/b/ttanaka/archive/2013/04/17/windows-vol-5.aspx
独自に特殊処理を追加する方法を説明します。

マイクロソフト
田中達彦