老眼鏡 JavaScript

漢詩作成支援のために漢字字典を引きまくっていると,画数が多くてよく読めない字にしばしば遭遇する。おまけに年を取って老眼が進んでいるせいか,虫眼鏡で拡大しないと字のつくりがよく見えないのだ。学研『漢字源』には文字の Unicode コードポイントが収録されており,GNU Emacs テキストエディタ ucs-insert 関数に対しコードポイントを与えることにより,文字の入力は簡単にできる。でも入力で出て来た多画数文字を,いちいちエディタのフォントを大きくして確認するのもやってられない。

そこで Web で簡易に文字を拡大表示する JavaScript を拵えた。自虐も込めて『老眼鏡』という名前にした。入力した文字をただただ大きくするだけの,ホントつまらないツールだけど,Emacs から文字をコピってすぐ確認できるので自分としては大いに役に立っている。文字とサイズを指定すると,そのサイズで文字を表示するだけ。一応 Unicode コードポイントも出力する。こんな感じ。

20120223-rogankyo.png

誰が使うのかわかりませんが, ボタンから試すことが出来る。初期状態では,上の画像のように,このアプリを作るきっかけになった文字「蠶」(かいこ)が設定されている。

ソースコードをあげておく。使い方の説明はコードのはじめのあたりにしるしてある。つまらないアプリの割に 100 行以上のコードになっているのは,拡張領域を含む UTF-8 符号をデコードし Unicode 十六進コードポイントを組立てるのに手間取ったからに過ぎない。

// -*- coding: utf-8; mode: js2; -*-
// 老眼鏡: 文字を拡大する
// - 表示したいブロックに以下を書いておく。
//     <script language="JavaScript">
//       magnifier('字', 100, 400);
//     </script>
//   引数: 初期値文字,文字の大きさ(px),表示枠サイズ幅(px) 
// 2012 (c) isao yasuda.
// 描画領域の作成/初期値表示
function magnifier(chr, size, width) {
    // 引数処理
    // size numeric check
    var msize   = 200;
    if (isNaN(size)) { }// 初期値を使う
    else { msize = size; }
    // width numeric check
    var mwidth  = 500;
    if (isNaN(width)) { }// 初期値を使う
    else { mwidth = width; }
    // 入力/出力エリアの描画
    document.write(
        // 全体枠
        '<div class="mag1" style="' +
            'width: ' + mwidth + 'px;">' +
            // 入力エリア
            '<div>' +
            '<table class="mag2"><tr><td>' +
            '文字:</td><td>' + 
            '<input id="magchr" type="text" size="4" maxlength="4"' +
            'value="' + chr + '" /></td><td>' + 
            'サイズ(px):</td><td>' + 
            '<input id="magsiz" type="text" size="3" maxlength="3"' + 
            'value="' + msize + '" /></td><td>' +
            '<input type="button" value="表 示"' +
            'onclick="magfocus(); magnifychar();" /> ' +
            '<input type="button" value="クリア"' +
            'onclick="magfocus(); magclear();" />' +
            '</td></tr></table></div>' +
            // 表示エリア
            '<div id="magdsp"><span style="font-size: ' + msize + 
            'px; line-height: 120%;">' + chr + '</span>' +
            '</div></div>');
    document.write('<div id="unic">Unicode <span class="code">U+' + 
                   unitohex(chr).toUpperCase() + '</span></div>');
    // 初期値文字の描画
    magnifychar();
    magfocus();
}
// 拡大文字の表示
function magnifychar() {
    var c = document.getElementById("magchr").value;
    if (c == "") {
        alert("文字が入力されていません");
        magfocus();
        return;
    }
    var size = document.getElementById("magsiz").value;
    // size numeric check
    if (isNaN(size)) {
        alert('文字サイズは数値(単位: px)でなければなりません');
        document.getElementById("magsiz").focus();
        return;
    }
    // 文字表示
    document.getElementById("magdsp").innerHTML 
        = '<span style="font-size: ' + size + 
        'px; line-height: 120%;">' + c + '</span>';
    document.getElementById("unic").innerHTML
        = 'Unicode <span class="code">' +
        'U+' + unitohex(c).toUpperCase() + '</span>';
}
// カーソルポイント
function magfocus() {
    document.getElementById("magchr").focus();
}
// 入力文字クリア
function magclear() {
    document.getElementById("magchr").value = ""; 
}
// Unicode 十六進コードポイント変換
function unitohex(c) {
    var w = encodeURI(c);
    if (w.length > 9) {// 4 オクテット以上の Unicode 文字
        // U+010000 - U+1FFFFF 拡張領域文字
        // UTF-8 デコード
        // 1. 符号化 UTF-8 ビットパターンの取得
        w = w.replace(/%/gi, "");
        var h = "";
        for (var i = 0; i < w.length; i++) {
            // 二進数文字列に変換
            var bstr = parseInt(w.charAt(i), 16).toString(2);
            // 4 bit 前ゼロ付加
            var dig0 = "";
            for (var j = 0; j < (4 - bstr.length); j++) {
                dig0 += "0";
            }
            h += dig0 + bstr;
        }
        // 2. Code Point 部の bit を抽出
        var uar = [];
        uar[0] = parseInt(h.charAt(5),2);
        uar[1] = parseInt(h.substring(6,8) + h.substring(10,12),2);
        uar[2] = parseInt(h.substring(12,16),2);
        uar[3] = parseInt(h.substring(18,22),2);
        uar[4] = parseInt(h.substring(22,24) + h.substring(26,28),2);
        uar[5] = parseInt(h.substr(28,4),2);
        // 3. Code Point digit (4 bit) 毎に十六進数文字列に変換
        w = "";
        if (uar[0] != 0) {// 0, 1 以外ありえない
            w = uar[0].toString(16);
        }
        for (var i = 1; i < uar.length; i++) {
            w += uar[i].toString(16);
        }
    } else {
        // U+FFFF までの BMP 領域文字
        w = (c.charCodeAt(0)).toString(16);
        var dt = 4 - w.length;
        for (var i = 0; i < dt; i++) {
            w = '0' + w;
        }
    }
    return w;
}