*【編集中】 [#ref92ed9]
#contents

* 方針 [#d8342a00]
- コードで画像を出力したい。
- 特定用途なら専用言語で良い。
- 汎用用途ならコーディングし易さを考慮した汎用言語が良い。svg のタグ打ちはコーダーに優しくない。

* 仕様 [#j59f5d78]
- [[blockdiag>http://blockdiag.com/ja/index.html]]という便利な作図ツールが作られている。
-- http://blockdiag.com/ja/index.html
- Python で実装されているため、プラグイン扱いで拡張する。
- blockdiag、seqdiag、actdiag、nwdiag、packetdiag とコマンド名が分かれているが、コードから判別可能のため、プラグインは diag に統一。
- 出力は HTML と親和性の高い SVG 直埋め込みとする。ただ、IE8など非対応ブラウザには png で出すべし。

* 実装 [#gb40f8e7]
- plugin/diag.inc.php を新規作成。
###
<?php

function plugin_diag_convert()
{
    $arg = rtrim(join(func_get_args(), ','), ',');   // 末尾の「,」は波引数が空の場合に現れ、不要物。
    return '<div class="diag">'.plugin_diag_core($arg, 'convert').'</div>';
}

function plugin_diag_inline()
{
    $arg = rtrim(join(func_get_args(), ','), ',');   // 末尾の「,」は波引数が空の場合に現れ、不要物。
    return '<span class="diag">'.plugin_diag_core($arg, 'inline').'</span>';
}

function plugin_diag_core($arg, $mode)
{
    $diag_dir = './diag/';                                      // 数式と数式画像のパス
    $err_msg_end_phrase = 'No pages of output.'.PHP_EOL;    // エラー終了を示す文字列(platexの出力依存)
    
    $prefix_convert = 'diag-nc-';             //  ブロック用ファイル衝突を避けるための接頭語
    $prefix_inline  = 'diag-ni-';             // インライン用ファイル衝突を避けるための接頭語
    
    $key = ($mode=='inline') ? $prefix_inline.md5($arg) : $prefix_convert.md5($arg);
    
    $diag_euc = $key.'.euc.diag';       // 照合用引数出力(保存ファイル)
    $diag_utf = $key.'.utf.diag';       // コンパイル出力(保存ファイル)
    $img = $key.'.svg';                 // 数式の画像出力(保存ファイル)
    
    $old_dir = getcwd();
    chdir($diag_dir);
    
    if (!file_exists($img) || $arg != file_get_contents($diag_euc))
    {
        $std  = $key.'.std.log';   // Tex の標準出力、エラー出力用
        $euc  = $key.'.std.log';   // Tex の標準出力、エラー出力用
        
        flush();    // Timeout 対策
        
        //$arg = "diag {\n" . $arg . "\n}";      // コード補完
        //$arg = mb_convert_encoding($arg, 'utf8-win');
        
        $command = "blockdiag ";
        //$command = str_replace(";", ";\n", $command);
        if (preg_match(   '/^\s*seqdiag\b/', $arg)) {$command =    "seqdiag ";}
        if (preg_match(   '/^\s*actdiag\b/', $arg)) {$command =    "actdiag ";}
        if (preg_match(    '/^\s*nwdiag\b/', $arg)) {$command =     "nwdiag ";}
        if (preg_match(  '/^\s*rackdiag\b/', $arg)) {$command =   "rackdiag ";}
        if (preg_match('/^\s*packetdiag\b/', $arg)) {$command = "packetdiag ";}
        
        //$arg = mb_convert_encoding($arg,  'SJIS-WIN', 'UTF-8');
        //$arg = mb_convert_encoding(mb_convert_encoding($arg, 'sjis-win', 'eucJP-win'), 'UTF-8', 'sjis-win');
        
        file_put_contents($diag_euc, $arg);
        exec('nkf -w '.$diag_euc.' > '.$diag_utf);
        exec($command . $diag_utf.'  -f %windir%\fonts\msgothic.ttc -Tsvg -o '. $img . ' 2> ' . $std );
        exec('nkf -e --overwrite '.$img);
        
        flush();    // Timeout 対策
        if (!file_exists($img)) // Tex Error
        {
            $err_flag = false;
            $err_code = "diag Error:\n\n";
            
            if ($log_code = fopen($std, 'r'))
            {
                while (!feof($log_code)) 
                {
                    $msg = fgets($log_code);
                    $err_code .= $msg;
                }
                fclose($log_code);
            }
            chdir($old_dir);
            return '<pre class=diag_error_title>'.$arg.'</pre><pre class=diag_error_message>'.$err_code.'</pre>';
        }
        flush();    // Timeout 対策
    }
    
    $xml = file($img);
    array_shift($xml);
    array_shift($xml);
    $match = array();
    preg_match('/^<svg[^>]+viewBox\s*=\s*\"\s*\d+\s*\d+\s*(\d+)\s*(\d+)\s*\"/', $xml[0], $matches);
    $width  = $matches[1];
    $height = $matches[2];
    $svg = implode($xml);
    
    $agent = getenv('HTTP_USER_AGENT');
    chdir($old_dir);
//  return '<img style="width:'.$width.'em; height:'.$height.'em; vertical-align:'.$depth.'em;". src="'.$diag_dir.$img.'" alt="$$'.$arg.'$$" title="'.$arg.'">';
//  return '<img src="'.$diag_dir.$img.'" alt="'.htmlspecialchars ($arg).'" title="'.htmlspecialchars ($arg).'">';
//  return '<object type="image/svg+xml" data="'.$diag_dir.$img.'" style="width:'.$width.'; height:'.$height.';" alt="'.htmlspecialchars ($arg).'" title="'.htmlspecialchars ($arg).'"></object>';
//  return $svg.'<pre>'.htmlspecialchars(print_r($matches, TRUE)).'</pre>';
    return '<div style="width: '.$width.'px;" >'.$svg.'</div>';
}
?>
###

* 開発メモ [#n362f009]
*** 文字コード変換 [#z22d52cc]
- 日本語を扱うため、EUC ⇒ UTF8 ⇒ EUC と変換する必要がある
-- 流用した PukiWiki が EUC ベースなため、プラグイン引数は EUC
-- diag 達の標準エンコーディングは UTF8なため、コンパイル前に変換する必要がある。
-- PukiWiki で出力される HTML に直埋め込みするため、再度 EUC に変換する必要がある。
- 訳分からんが、PHP の mb 関数は変換してくれない。
-- http://www.asp-edita.jp/doda/one/doda5728_15.html
- とりあえず、nkf というツールがあるので、それで仮実装。
- とりあえず、nkf というツールがあったので、それで仮実装。
-- Tex にあった。

*** svg 非対応ブラウザ [#u0259b28]
- ブラウザ情報を解析して、png で出すべし。
- 技術的に実現可能と分かっているが、検証できそうにないので先延ばし…
-- ブラウザ情報を表示するページでも用意し、他力本願で報告フォームを使おうか?
    初基 一覧 検索 最新 バックアップ リンク元   ヘルプ   最終更新のRSS