タイミングチャート清書サービス のバックアップの現在との差分(No.6)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
* 設置アドレス [#s578cb5d]

SIZE(20){http://dora.bk.tsukuba.ac.jp/~takeuchi/tchart.html}
SIZE(20){https://rawgit.com/osamutake/tchart-coffee/master/bin/editor-offline.html}

*** スクリーンイメージ [#vb49705b]
&ref(screenshot.png,nolink,border,66%);

* 概要 [#td75a95f]

このようなテキストを入力すると、
 aclk    ~_~_~_~_~_~_~_~_~_~_
 awaddr  ==?X=A1==X=A2X=A3==X==?=X=A4X=?
 awvalid __~~~~~~~~~~____~~__
 awready ____[~~~~]__[~~]____[~~]__
 wdata   ====?X=D1X=D2X=?X=D3X=?X=D4==X=?
 wvalid  ____~~~~__~~__~~~~__
 wready  ____~~~~__~~____~~__
 bresp   ====00================
 bvalid  ____~~~~__~~____~~__
 bready  ~~~~~~~~~~~~~~~~~~1~~

こんなタイミングチャートを生成できるサービスです。

&tchart(
aclk    ~_~_~_~_~_~_~_~_~_~_
awaddr  ==?X=A1==X=A2X=A3==X==?=X=A4X=?
awvalid __~~~~~~~~~~____~~__
awready ____[~~~~]__[~~]____[~~]__
wdata   ====?X=D1X=D2X=?X=D3X=?X=D4==X=?
wvalid  ____~~~~__~~__~~~~__
wready  ____~~~~__~~____~~__
bresp   ====00================
bvalid  ____~~~~__~~____~~__
bready  ~~~~~~~~~~~~~~~~~~1~~
);

ソースコード編集中に、ほぼリアルタイムで清書結果を確認できるので、試行錯誤しているうちに正しく書けると思います。

清書したタイミングチャートは SVG または PNG 形式で保存できます。

入力内容がサーバーに送られることはなく、完全にブラウザ上だけで画像を生成していますので、守秘義務の問題も発生しません。心配であればリンク先の html を PC に保存して、そこから立ち上げても動作します。いくつかの javascript ライブラリへの参照さえ解決すれば、完全にオフラインでも作業が可能です。
入力内容がサーバーに送られることはなく、完全にブラウザ上だけで画像を生成していますので、守秘義務の問題も発生しません。心配であればリンク先の html を PC に保存して、そこから立ち上げれば、完全にオフラインの状態でも動作します。

設置アドレスはこちらです:~
  SIZE(20){http://dora.bk.tsukuba.ac.jp/~takeuchi/tchart.html}
  SIZE(20){https://rawgit.com/osamutake/tchart-coffee/master/bin/editor-offline.html}
~
~
[[>>>> 記述文法についてはこちらをご覧下さい。>#g7420e8f]]
[[>>>> 記述文法についてはこちらをご覧下さい。>https://rawgit.com/osamutake/tchart-coffee/master/doc/syntax.html]]

コメントや質問などがあれば[[このページの一番下に投稿フォームがあります>#m9652e62]]のでご活用下さい。
コメントや質問などがあれば [[GitHub で Issue を上げるか>https://github.com/osamutake/tchart-coffee/issues]]、[[このページの一番下の投稿フォームをご利用下さい>#m9652e62]]。

** 不具合 [#a0ceca1d]
このサービスで使っている javascript コードを既存システムに組み込むことで、
各種 Wiki や Markdown にタイミングチャート記述機能を追加できると思います。
下記 [[組み込み処理系>#e2debc9b]] を参照して下さい。

IE ではリンク先で議論されている問題のため、[Save as PNG] および [Generate Images for Copy] 
のボタンが正常に働きません。~
** WaveDrom : 似たようなコンセプトで、より凝ったチャートを書けるツールもあるようです [#s714eccc]

http://wavedrom.com/

&ref(wavedrom1.png,,50%);

チュートリアルはこちら:~
http://wavedrom.com/tutorial.html

** IE での不具合 [#a0ceca1d]

下記リンク先で議論されている問題のため、[Save as PNG] および [Generate Images for Copy] 
のボタンが IE では正常に働きません。~
https://connect.microsoft.com/IE/feedback/details/809823/draw-svg-image-on-canvas-context

代わりに、SVG 画像上で右クリックから [名前を付けて画像を保存] で形式を PNG にすれば保存できます。

同様に右クリックから [コピー] で画像をクリップボードへ入れられるので、
Word などへ貼り付ける用途ではむしろ IE の方が便利かもしれません。

** クリップボードへのコピーの仕方 [#m4d46332]
** IE 以外でクリップボードへのコピーの仕方 [#m4d46332]

セキュリティ上の制限のため、javascript からクリップボードへ
自動的にコピーすることはできないようになっているため、
手動で対応していただく必要があります。
自動的にコピーすることはできないようになっています。
そこで、手動で対応していただく必要があります。

[Generate Images for Copy] ボタンを押すと SVG ソースと PNG 画像が生成されます
- SVG ソースをご入り用であれば、SVG ソースにフォーカスが当たっている状況でそのまま Ctrl+V すればコピー可能です
- SVG ソースをご入り用であれば、SVG ソースにフォーカスが当たっている状況でそのまま Ctrl+C すればコピー可能です
- PNG 画像がご入り用であれば、PNG 画像上で右クリックから [画像をコピー] します
-- なぜか空の HTML も一緒にコピーされてしまうようで、なおかつこの空の HTML 
が優先的に貼り付けられるようなので、Word などへ貼り付ける際には 
[形式を選択して貼り付け]-[ビットマップ(DIB)] などとして下さい
-- Office でのショートカットは Alt+E,S です
[形式を選択して貼り付け]-[ビットマップ(DIB)] などとして下さい(Office でのショートカットは Alt+E,S です)
-- 上記の制限のため IE では [Generate Images for Copy] で PNG 画像が生成されません
-- 代わりに SVG 画像上の右クリックから [コピー] でコピーできますので、そちらをご利用下さい


* 謝辞 [#j084c7a9]

熊谷正朗さんの "Timing chart formatter by kumagai" ~
http://www.mech.tohoku-gakuin.ac.jp/rde/contents/library/tchart/indexframe.html

を大いに参考にさせていただきました。

記述文法はほぼ熊谷さんの tchart を踏襲しています。

大変有用なツールをご提供くださったことに感謝いたします。

* 目次 [#ad7e0323]
* 記述文法 [#g7420e8f]

#contents
[[こちらをご覧下さい。>https://rawgit.com/osamutake/tchart-coffee/master/doc/syntax.html]]

* タイミング記述テキストの文法 [#g7420e8f]
* ソースコード [#sc7a574d]

** # から始まる行はコメント行です [#ld750e11]
GitHub に上がっています:https://github.com/osamutake/tchart-coffee

 # This line will not appear in the chart
 clk    _~_~_~_~_~
 signal ___~~~~___
npm でも利用可能です:https://www.npmjs.com/package/tchart-coffee

&tchart(
# This line will not appear in the chart
clk    _~_~_~_~_~
signal ___~~~~___
);
* 組み込み処理系 [#e2debc9b]

** @ から始まる行で設定を変更できます [#q06c69eb]
このサービスで作成した svg を手で切り貼りして html に埋め込む代わりに、
html 中に以下のように直接タイミング図定義を書いておいて、
javascript で svg に変換して表示した方が、
あとから修正することなどを考えると便利です。

形式は次の通りです。
チャートを表示したい部分に次のように記述しておいて、

 @[設定値の名称][スペース][設定値]
 LANG:html
 <script type="text/tchart">
 aclk    ~_~_~_~_~_~_~_~_~_~_
 awaddr  ==?X=A1==X=A2X=A3==X==?=X=A4X=?
 awvalid __~~~~~~~~~~____~~__
 awready ____[~~~~]__[~~]____[~~]__
 wdata   ====?X=D1X=D2X=?X=D3X=?X=D4==X=?
 wvalid  ____~~~~__~~__~~~~__
 wready  ____~~~~__~~____~~__
 bresp   ====00================
 bvalid  ____~~~~__~~____~~__
 bready  ~~~~~~~~~~~~~~~~~~1~~
 </script>

[[設定可能な値としてどんな物があるかについてはこちらです。>#rd2a2e82]]
~</body> の直後に次のコードを置きます。

 @signal_style stroke-linecap="round" stroke-width="2" stroke="green" fill="none"
 clk    _~_~_~_~_~
 signal ___~~~~___
 LANG:html
 <script src='https://cdn.rawgit.com/osamutake/tchart-coffee/v1.1.1/lib/tchart.min.js'></script>
 <script>
 (function(){
   var codes = document.getElementsByTagName('script');
   for (var i = codes.length-1; i >= 0; i--){
     var code = codes[i];
     if(code.getAttribute('type')!=='text/tchart')
       continue;
     var svg = TimingChart.format(code.textContent);
     var div = document.createElement('div');
     div.className = 'tchart';
     div.innerHTML = svg;
     code.parentNode.replaceChild(div, code);
   }
 })();
 </script>

&tchart(
@signal_style stroke-linecap="round" stroke-width="2" stroke="green" fill="none"
clk    _~_~_~_~_~
signal ___~~~~___
);
似たような方法を使えば、Wiki や Blog をカスタマイズして、
タイミング図の表示機能を付けるようなことも簡単にできると思います。
Markdown なら[[こうでしょうか>#y9c3ed0a]]。

** % から始まる行で自由な位置に文字列を追加できます [#z209ee2f]
ちなみにこのサイト自身、[[タイミングチャートを処理するプラグイン>ソフトウェア/pukiwiki/tchart.inc.php]] を導入した pukiwiki で書いているため、
記事の中で自然にタイミング図を記述できています。

与えるパラメータは、次の通りです。
** 実行例 [#e2ad9fe5]

 %[x座標][スペース][y座標][スペース][文字列]
実行例はこちらをご覧下さい:~
http://jsbin.com/naxidurome/edit?html,output
** Markdown に組み込む [#y9c3ed0a]

 @margin 20
 %100 -7 test!
 clk    _~_~_~_~_~
Markdown に組み込む場合、

 ```tchart2svg
 clock  _~_~_~_~_~
 signal ___~~~~___
 ```

&tchart(
@margin 20
%100 -7 test!
clk    _~_~_~_~_~
signal ___~~~~___
);
と書いた物が

** 空行があれば1行分だけ空白が空きます [#le587f61]
 LANG:html
 <pre><code class="lang-tchart2svg">
 clock  _~_~_~_~_~
 signal ___~~~~___
 </code></pre>

 clk1   _~_~_~_~_~
 clk2   __~~__~~__
 
 signal ___~~_____
と変換される処理系であれば、

&tchart(
clk1   _~_~_~_~_~
clk2   __~~__~~__
 LANG:html
 <script src='https://cdn.rawgit.com/osamutake/tchart-coffee/v1.1.1/lib/tchart.min.js'></script>
 <script>
 (function(){
   var codes = document.getElementsByClassName('lang-tchart2svg');
   for (var i = codes.length-1; i >= 0; i--){
     var code = codes[i];
     var svg = TimingChart.format(code.textContent);
     var div = document.createElement('div');
     div.className = 'tchart';
     div.innerHTML = svg;
     var pre = code.parentNode
     pre.parentNode.replaceChild(div, pre);
   }
 })();
 </script>

signal ___~~_____
);
をレイアウトファイルの </body> の直後に組み込めば、自然な文法でタイミングチャートを記述できるようになります。

** その他の文字から始まる行が信号定義になります [#e6c10712]
実行例:~
http://jsbin.com/wicuvabalu/edit?html,output

フォーマットは
** 注意点 [#u566db26]

 信号名 [空白] タイミング定義
tchart.min.js を取り込む際、

の形です。
https://cdn.rawgit.com/osamutake/tchart-coffee/v1.1.1/lib/tchart.min.js

* タイミング定義の文法と用例 [#qdaa4e35]
ではなく

** _ と ~ で 0 と 1 を表します。 [#dd9965b7]
https://cdn.rawgit.com/osamutake/tchart-coffee/master/lib/tchart.min.js

** - がハイインピーダンス状態です。 [#x82e48ed]
としておけば常に最新版を使えて便利!

 clk    _~_~_~_~_~_~_~_~_~
 data   ___~~~~__~~____~~_
 enable ___~~~~~~~~~~_____
 output ---~~~~__~~__-----
と思いそうになるのですが、cdn.rawgit.com のサービスは github.com 
の内容をキャッシュするもので、URL と内容とが一対一に対応するため、
/master/ で読まれる内容はキャッシュがタイムアウトしない限り
新しいコミットがあっても更新されることはありません。

&tchart(
clk    _~_~_~_~_~_~_~_~_~
data   ___~~~~__~~____~~_
enable ___~~~~~~~~~~_____
output ---~~~~__~~__-----
);
https://rawgit.com/ にも書かれているとおり、

** バス信号や不定値を表すのに = を使えます。 [#r60d0319]
>Use a specific tag or commit hash in the URL (not a branch). Files are cached permanently based on the URL.

** X で値の切り替えを表せます。 [#uad781ca]
cdn.rawgit.com からの読み込みは必ず tag 名あるいはコミット ID で行うようにして下さい。

X は時間が進みます。イメージ的には X= のように働きます。
* コメント・質問 [#m9652e62]

 clk  _~_~_~_~_~
 data =X=X=X=X=X
バグ報告や改善要望などは、可能であれば [[GitHub で Issue を上げていただけると>https://github.com/osamutake/tchart-coffee/issues]]捗ります。よく分からなければ下記へご記入いただいて構いません。

&tchart(
clk  _~_~_~_~_~
data =X=X=X=X=X
);
#article_kcaptcha
**矢印付きの立ち上がりエッジ、立ち下がりエッジ [#k629795c]
>[[かとう]] (&timetag(2019-08-06T15:04:30+09:00, 2019-08-07 (水) 00:04:30);)~
~
もう一つ、お願いがあります。~
立ち上がりエッジ、立ち下がりエッジの時に、矢印を追加するオプションを追加できないでしょうか?~
こんな感じの矢印です。~
https://synapse.kyoto/glossary/dff/png/fig004_mag.png~
https://synapse.kyoto/glossary/dff/png/fig006_mag.png~
https://image.itmedia.co.jp/mn/articles/0805/22/ay_drill2_18_fig02.gif~
https://image.itmedia.co.jp/mn/articles/0805/22/ay_dr2_18_mon01.gif~
~
指定の方法は~
_^~ で矢印付きの立ち上がりエッジ~
~v_ で矢印付きの立ち下がりエッジ~
という方法はどうでしょうか?~

** 信号定義に文字列を書き入れることができます。 [#f601e0b1]
//
- ああ、URLが画像展開されてしまうんですね。すみません。目障りでしたらURLを削ってください。それと「矢印付きの立ち下がりエッジ」は「~v_」です。なぜか先頭の ~ が消えてしまいました。 -- [[かとう]] &new{2019-08-07 (水) 00:08:28};

文字列を書いても時間は進みません。
#comment_kcaptcha

 clk    _~_~_~_~_~_~_~_~_~
 enable ___~~~~~~~~~~_____
 output ---=D0=X=D1X=D2X=D3X=D4-----
**png 保存できません [#s69a6f10]
>[[かとう]] (&timetag(2019-08-06T06:48:14+09:00, 2019-08-06 (火) 15:48:14);)~
~
たびたびすみません。~
~
仕様なのかもしれませんが、信号名や文字列に日本語(非ASCII文字)が一文字でもあると、svg 保存はできますが、png 保存や Generate Images for Copy が効かない様です。~
ASCII のみなら、問題なく png 保存できます。~
小生の使用環境は Windows7 home SP1, Google Chrome v.76.0.3809.87 です。~
~
※"enable"だとはみ出すので"有効"に変更したら、とたんにpng保存できなくなってしまい、ちょっと悩んでしまいました。~

&tchart(
clk    _~_~_~_~_~_~_~_~_~
enable ___~~~~~~~~~~_____
output ---=D0=X=D1X=D2X=D3X=D4-----
);
//
- ご指摘ありがとうございます。http://js.studio-kingdom.com/javascript/window/btoa#unicode_strings こちらで解説されているようにUnicode文字列のwindow.btoa()の呼び出しで、 文字範囲外(Character Out Of Range)の例外が発生してしまっていることを確認しました。リンク先で解決策も提示されていますので、後ほど修正いたします。 -- [[武内(管理人)]] &new{2019-08-06 (火) 17:03:38};
- すみません、追加です。信号中に埋め込む文字列の方のみ "~" で括った時に空白文字(0x20)があると、png 保存できないようです(svg 保存はできます)。信号名の方は空白文字があっても問題ありません。 -- [[かとう]] &new{2019-08-06 (火) 21:08:55};
- 何となくわかりました。多分ですが、信号中に埋め込む文字列の方のみ、空白文字(0x20)が NBSP(0xA0)に変換されるので非ASCII文字になってしまい、日本語の時と同様に「文字範囲外エラー」になっているのだと思われます。 -- [[かとう]] &new{2019-08-06 (火) 21:53:24};

** 文字列に特殊文字を含めたい場合には " " でくくります [#wa93120b]
** " を含めたければ "" のように重ねます [#e669d881]
#comment_kcaptcha

スペースも入れられます
**信号名や文字列に上線(upper bar)をつけたい [#u810ea60]
>[[かとう]] (&timetag(2019-08-04T15:22:48+09:00, 2019-08-05 (月) 00:22:48);)~
~
負論理の時の信号名や文字列に上線をつけたいのですが~
どの様にすればよろしいのでしょうか?~

 "="   -======"A = B"-
 "     -======" ""A"" = ""B"" "-
 A     -======A-
 space -======"A      "-
//
- すみません、表示上だけ何とかしたければ、text-decoration="overline" を使って~
@caption_font text-decoration="overline"~
clock  _~_~_~_~_~_~_~_~_~_~_ ~
@caption_font text-decoration=""~
などとする手はありますが、現状では信号名に上線を付ける標準的な機能はありません。もし対応するとしたらどういう文法にするのが自然でしょうね・・・-- [[武内(管理人)]] &new{2019-08-05 (月) 08:01:31};
- ご返答ありがとうございます。 @caption_font, @signal_font で上線が付けられました。 ただ、毎回毎回、この方法だと記述が大変かな、という気もしました。 小生が使用している回路図エディタ BSch3V では、\R\E\S と書くと RES に上線が付いて表示されます。 同様な考えで !R!E!S で一文字一文字に上線が付くようにする、という方法はどうでしょうか? これなら上線を付けたい文字の直前だけに ! を追加するだけで済むので @caption_font, @signal_font よりは記述が楽かな、と思います。 あるいは ! が現れるたびに text-decoration="overline" と text-decoration="" をトグルする、という方法でも良いかもしれません。 -- [[かとう]] &new{2019-08-06 (火) 14:39:17};
- その文字を文字通りの記号として使うことがあり得ない、と確信できる記法にしたいですね。! は使う可能性があるようにも思うので、採用するなら \R\E\S の方でしょうか。WaveDrom だと <o>RES</o> のようですが、これはちょっと違いそう。ちょっと考えさせて下さい。 -- [[武内(管理人)]] &new{2019-08-06 (火) 15:03:13};
- \ ですと不定値部分の指定に使っている様ですので、(信号名の方は大丈夫だと思うのですが)信号中に埋め込む文字列の方で使えないのでは?と考えて、! にしました。! がまずければ、全角文字の ̄や¬(否定)などは、どうでしょうか? -- [[かとう]] &new{2019-08-06 (火) 15:59:17};
- すみません、¬記号はダメですね。Unix系や外国の Windows ですと U+00AC の方が入力されるのでしょうが、日本語Windows の IME ですと U+FFE2 の方が入力されてしまい、混乱してしまいますね… -- [[かとう]] &new{2019-08-06 (火) 16:13:03};
- 確かに信号中に埋め込む文字列ではそのままの \ は使えませんね。その場合には " " か ' ' で囲んでもらうということではどうでしょう?全角の ̄よりは良いような??? -- [[武内(管理人)]] &new{2019-08-06 (火) 17:07:57};

&tchart(
"="   -======"A = B"-
"     -======" ""A"" = ""B"" "-
A     -======A-
space -======"A      "-
);
#comment_kcaptcha

** 右寄せ、左寄せ [#d7e5f20d]
**信号名の文字数について [#d2ba024e]
>[[そうたろう]] (&timetag(2019-04-11T01:56:08+09:00, 2019-04-11 (木) 10:56:08);)~
~
はじめまして。~
タイミングチャート清書サービスのご提供ありがとうございます。~
使い始めたばかりなのですがすごい便利でこれから使っていこうと思っています。~
~
本題の信号名の文字数についてですが、~
信号名の文字数が長いと、出力されるタイミングチャートに信号名が入りきらないのですが、修正をしていただけますでしょうか。~
~
動作環境は下記になります。~
  OS      :windows10
  ブラウザ:Google Chrome(73.0.3683.86)
~
よろしくお願いいたします。~

文字列は通常センタリングされますが、_<_ あるいは _>_ から始めることで
左寄せ、右寄せにできます
//
- 信号名の幅を見て自動的に幅を調整する機能はないのですが、[[w_caption>https://rawgit.com/osamutake/tchart-coffee/master/doc/syntax.html#1-3-3]] を指定することで信号名称部分の幅を広げることは可能ですので、手動で調整していただけますでしょうか。そのような意味で合っているでしょうか? -- [[武内(管理人)]] &new{2019-04-11 (木) 11:03:09};
- 早急なご回答ありがとうございます。ご回答いただいたことがまさにやりたかったことです!文法説明をちゃんと読んでおらず、お手数おかけしてすみませんでした。これから末永く利用させていただきたいと思います。 -- [[そうたろう]] &new{2019-04-11 (木) 15:48:56};

 left   -======"_<_DATA"-
 middle -======DATA-
 right  -======"_>_DATA"-
#comment_kcaptcha

&tchart(
left   -======"_<_DATA"-
middle -======DATA-
right  -======"_>_DATA"-
);
**仕様かもしれませんが [#jd99ae7a]
>[[通りすがりで大丈夫ですか?]] (&timetag(2019-02-21T07:37:50+09:00, 2019-02-21 (木) 16:37:50);)~
~
こんにちは~
タイミングチャート清書サービスを便利に利用させてもらっています。~
その中で気になった点をお知らせいたします。~
タイミング定義中に記述できる文字列に半角スペースがあると~
エディター上は問題ないように見えますが、~
SVGで保存した後、正しく表示できません。~
半角スペースのエスケープに問題があるようです。~

** ? を一文字だけ書くと不定値を表すために色が付きます。 [#dc4c5057]
//
- コメントありがとうございます。全角スペースではなく半角スペースですよね・・・すみません、私が何か見落としているようでうまく再現できませんでした。お手数ですが、簡単な例を教えていただけませんでしょうか?試しに https://rawgit.com/osamutake/tchart-coffee/master/bin/editor-offline.html で表示される初期データの "DATA" を "D A T A" としてみましたが、問題ないように見えました。 -- [[武内(管理人)]] &new{2019-02-21 (木) 17:05:11};

 clk    _~_~_~_~_~_~
 data   =?==XDATA=====X=?=
 valid  ___~~~~~~___
#comment_kcaptcha

&tchart(
clk    _~_~_~_~_~_~
data   =?==XDATA=====X=?=
valid  ___~~~~~~___
);


** : を入れると空白を入れ、途切れさせることができます。 [#yb67ee5a]

 clk    _~_~_~_:...:~_~_~_~_~
 data   ___~~~~:...:~~____~~_

&tchart(
clk    _~_~_~_:...:~_~_~_~_~
data   ___~~~~:...:~~____~~_
);

** 不定値部分を表すのに、/ \ * が使えます。 [#b5b09f01]

 clk        _~_~_~_~_~_~_~
 rising     ___==/=/=~~~~~
 falling    ~~~==\=\=_____
 transition ___=D0=*=D1*=D2*=D3___

&tchart(
clk        _~_~_~_~_~_~_~
rising     ___==/=/=~~~~~
falling    ~~~==\=\=_____
transition ___=D0=*=D1*=D2*=D3___
);

** | を入れるとグリッド線を引けます。 [#d1263d2a]

** [ ] でくくるとハイライトできます。 [#d41e1c81]

 clk    _~_~_~_~_~_~_~_~_~
 data   ___~~~~~~~~|____~~_
 enable ___[~~~~~~~~~~]_____
 output ---~~~~~~~~__-----

&tchart(
clk    _~_~_~_~_~_~_~_~_~
data   ___~~~~~~~~|____~~_
enable ___[~~~~~~~~~~]_____
output ---~~~~~~~~__-----
);


** 全ての組み合わせを試してみます [#f93875da]

 # :-~_=/\X*
 0 _~_~_~_~_~_~_[~_~_]~_
 
 1 :::-:~:_:=:/:\:X:*:
 2 -:---~-_-=-/-\-X-*-
 3 ~:~-~~~_~=~/~\~X~*~
 4 _:_-_~___=_/_\_X_*_
 5 =:=-=|~=_===/=\=X=*=
 6 /:/-/~/_/=///\/X/*/
 7 \:\-\~\_\=\/\\\X\*\
 8 X:X-X~X_X=X/X\XXX*X
 9 *:*-*~*_*=*/*\*X***

&tchart(
# :-~_=/\X*
0 _~_~_~_~_~_~_[~_~_]~_

1 :::-:~:_:=:/:\:X:*:
2 -:---~-_-=-/-\-X-*-
3 ~:~-~~~_~=~/~\~X~*~
4 _:_-_~___=_/_\_X_*_
5 =:=-=|~=_===/=\=X=*=
6 /:/-/~/_/=///\/X/*/
7 \:\-\~\_\=\/\\\X\*\
8 X:X-X~X_X=X/X\XXX*X
9 *:*-*~*_*=*/*\*X***
);

** 不定値の塗り分けをテスト。 [#h695f4bc]

 @h_line 30
 @h_skip 20
 @w_transient 5
 @w_caption 60
 test =/=?\=\=?/=X=?X=*?=*=X=?-=?= =?X

&tchart(
@h_line 30
@h_skip 20
@w_transient 5
@w_caption 60
test =/=?\=\=?/=X=?X=*?=*=X=?-=?= =?X
);

** 遷移の傾きをなくすには @w_transient 0 とします [#l5475a84]

 @w_transient 0
 clk _~_~_~_~_~_~_~
 data ___|~~~~|_______

&tchart(
@w_transient 0
clk _~_~_~_~_~_~_~
data ___|~~~~|_______
);

** svg の特殊文字も正しくエスケープされます [#b0b8f714]

 clk _~_~_~_~_~_~_~
 data ---|===<D1>=X=<D2>==|---

&tchart(
clk _~_~_~_~_~_~_~
data ---|===<D1>=X=<D2>==|---
);

** 生成された svg には変換元のソースコードが埋め込まれます。 [#c058d952]

下記の CDATA の部分です。ソースコードに CDATA の終了を示す ]]> が現れる場合には、
]]&gt; にエンコードされます。

 LANG:xml
 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
      width="240pt" height="60pt" viewBox="-10 -10 220 40" version="1.1">
 <![CDATA[
 clk _~_~_~_~_~_~_~
 data ---|===<D1>=X=<D2>==|---
 ]]>
 <g>
 <text x="35" y="8.5" text-anchor="end" font-size="10" fill="black" font-family="Helvetica">clk</text>
 <path stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none" d="M42,10H52L54,0H64L66,10H76L78,0H88L90,10H100L102,0H112L114,10H124L126,0H136L138,10H148L150,0H160L162,10H172L174,0H184L186,10H196L198,0H208" />
 <text x="35" y="28.5" text-anchor="end" font-size="10" fill="black" font-family="Helvetica">data</text>
 <text x="101.0" y="28.5" text-anchor="middle" font-size="10" fill="black" font-family="Helvetica">&lt;D1&gt;</text>
 <text x="149.0" y="28.5" text-anchor="middle" font-size="10" fill="black" font-family="Helvetica">&lt;D2&gt;</text><path stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none" d="M42,25H52H54H64H66H76L78,20H88H90H100H102H112H114H124L126,30H136H138H148H150H160H162H172L174,25H184H186H196H198H208M76,25L78,30H88H90H100H102H112H114H124L126,20H136H138H148H150H160H162H172L174,25" />
 <path d="M77,-10V40" stroke-linecap="round" stroke-width="0.6" stroke="red" fill="none" />
 <path d="M173,-10V40" stroke-linecap="round" stroke-width="0.6" stroke="red" fill="none" />
 </g>
 </svg>

* 設定値 [#rd2a2e82]

括弧内が何も指定しないときの既定値です。
** scale (= 1.0) [#k3b33db2]

図のサイズを拡大・縮小します。
複数指定した場合、最後の値だけが意味を持ちます。

 @scale 1.4
 clk     _~_~_~_~_~_~_~_~
 data	==?=X=D0X=D1X=D2X=D3X=?===

&tchart(
@scale 1.4
clk     _~_~_~_~_~_~_~_~
data	==?=X=D0X=D1X=D2X=D3X=?===
);

 @scale 0.7
 clk     _~_~_~_~_~_~_~_~
 data	==?=X=D0X=D1X=D2X=D3X=?===

&tchart(
@scale 0.7
clk     _~_~_~_~_~_~_~_~
data	==?=X=D0X=D1X=D2X=D3X=?===
);

** margin (= 10) [#b7fe0b8a]
チャートの周囲の余白の幅を指定します。

** w_caption (= 40) [#ge8b8cec]
信号名称部分の幅を指定します。

 long_signal_name	_~~~~__~~~~______~~___

&tchart(
long_signal_name	_~~~~__~~~~______~~___
);

 @w_caption 100
 long_signal_name	_~~~~__~~~~______~~___

&tchart(
@w_caption 100
long_signal_name	_~~~~__~~~~______~~___
);

** w_hold (= 10) [#le7dd0fb]
信号の単位時間から遷移時間を引いた部分の幅を指定します。
途中で変更すれば異なるクロックドメインを表したりできます。

 @w_hold 10
 clock	_~_~_~_~_~_~_~_~_~_~_~
 @w_hold 22
 clock	~_~_~_~_~_~
 @w_hold 16
 clock	_~_~_~_~_~_~_~_

&tchart(
@w_hold 10
clock	_~_~_~_~_~_~_~_~_~_~_~
@w_hold 22
clock	~_~_~_~_~_~
@w_hold 16
clock	_~_~_~_~_~_~_~_
);

** w_transient (= 2) [#n3c4fb61]
信号の遷移時間の幅を指定します。
ゼロを指定すると、遷移のエッジは垂直になります。

 @w_transient 0
 clock	_~_~_~_~_~_~_~_~_~_~_~
 @w_transient 2
 clock	_~_~_~_~_~_~_~_~_~_~_~
 @w_transient 4
 clock	_~_~_~_~_~_~_~_~_~_~_~

&tchart(
@w_transient 0
clock	_~_~_~_~_~_~_~_~_~_~_~
@w_transient 2
clock	_~_~_~_~_~_~_~_~_~_~_~
@w_transient 4
clock	_~_~_~_~_~_~_~_~_~_~_~
);

** h_line (= 10) [#p7e6f34c]
1行の高さを指定します。信号名のフォントサイズもこの値に等しくなります。

 @h_line 10
 clock	_~_~_~_~_~_~_~_~_~_~_~
 @h_line 16
 clock	_~_~_~_~_~_~_~_~_~_~_~

&tchart(
@h_line 10
clock	_~_~_~_~_~_~_~_~_~_~_~
@h_line 16
clock	_~_~_~_~_~_~_~_~_~_~_~
);

** h_space (= 10) [#teb7c9f7]
行間のスペースを指定します。

 clock	_~_~_~_~_~_~_~_~_~_~_~
 data1	_~~~~__~~~~______~~___
 @h_space 20
 data2	_~~~~__~~~~______~~___
 data3	_~~~~__~~~~______~~___

&tchart(
clock	_~_~_~_~_~_~_~_~_~_~_~
data1	_~~~~__~~~~______~~___
@h_space 20
data2	_~~~~__~~~~______~~___
data3	_~~~~__~~~~______~~___
);

** signal_style [#v5ac38b6]
信号線のスタイルを svg の path の属性値の形で与えます。
規定値は次の通りです。

 stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none"

 data1	_~~~~__~~~~______~~___
 @signal_style stroke-linecap="round" stroke-width="2" stroke="green" fill="none"
 data2	_~~~~__~~~~______~~___

&tchart(
data1	_~~~~__~~~~______~~___
@signal_style stroke-linecap="round" stroke-width="2" stroke="green" fill="none"
data2	_~~~~__~~~~______~~___
);

** grid_style [#ra37b0f5]
グリッド線のスタイルを svg の path の属性値の形で与えます。
規定値は次の通りです。

 stroke-linecap="round" stroke-width="0.6" stroke="red" fill="none"



 @grid_style stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none"
 data1	_~~~~__|~~~~______~~___
 @grid_style stroke-linecap="round" stroke-width="0.6" stroke="#0CC" fill="none"
 data2	_~~~~__~~~~______|~~___

&tchart(
@grid_style stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none"
data1	_~~~~__|~~~~______~~___
@grid_style stroke-linecap="round" stroke-width="0.6" stroke="#0CC" fill="none"
data2	_~~~~__~~~~______|~~___
);

** highlight_style [#d1714e07]
ハイライト部分のスタイルを指定します。

規定値は次の通りです。

 stroke="none" fill="#ff8"


 data1	_~~~~__[~~~~]______~~___
 @highlight_style stroke="green" fill="#8f8" stroke-width="1"
 data2	_~~~~__~~~~______[~~]___

&tchart(
data1	_~~~~__[~~~~]______~~___
@highlight_style stroke="green" fill="#8f8" stroke-width="1"
data2	_~~~~__~~~~______[~~]___
);

** notcare_style [#r0fb27ce]

不定値部分のスタイルを指定します。

 fill="#ccc"

 clk     _~_~_~_~_~_~_~_~_~_~_~
 data1	====?=*========*=?======
 @notcare_style stroke="none" fill="#8f8"
 data1	====?=*========*=?======

&tchart(
clk     _~_~_~_~_~_~_~_~_~_~_~
data1	====?=*========*=?======
@notcare_style stroke="none" fill="#8f8"
data1	====?=*========*=?======
);

** caption_font [#z0c3eaff]

信号名のフォントを指定します。

規定値は次の通りです。

 fill="black" font-family="Helvetica"

 clk     _~_~_~_~_~_~_~_~_~_~_~
 @caption_font fill="red" font-family="Helvetica"
 @signal_style stroke="red" fill="none"
 data	_~~~~______~~____~~~~~

&tchart(
clk     _~_~_~_~_~_~_~_~_~_~_~
@caption_font fill="red" font-family="Helvetica"
@signal_style stroke="red" fill="none"
data	_~~~~______~~____~~~~~
);

** signal_font [#sfe73988]

信号部分で用いるフォントを指定します。

規定値は次の通りです。

 fill="black" font-family="Helvetica"

 clk     _~_~_~_~_~_~_~_~
 @signal_font fill="red" font-family="Helvetica"
 data	==?=X=D0X=D1X=D2X=D3X=?===

&tchart(
clk     _~_~_~_~_~_~_~_~
@signal_font fill="red" font-family="Helvetica"
data	==?=X=D0X=D1X=D2X=D3X=?===
);

** rotate (= 0) [#s041342a]

未実装


* ソースコード [#sc7a574d]

こちらでも参照可能です:http://jsbin.com/lezujowaba/1/edit?html,css,js,output

 LANG:html(linenumber)
 <!DOCTYPE html>
 <html>
 <head>
   <script src="https://code.jquery.com/jquery-2.1.4.js"></script>
   <script src="https://rawgit.com/eligrey/FileSaver.js/master/FileSaver.js"></script>
   <script src="https://rawgit.com/eligrey/canvas-toBlob.js/master/canvas-toBlob.js"></script>
   <meta charset="utf-8">
   <meta name="viewport" content="width=device-width">
   <title>Timing Chart Formatter</title>
 </head>
 <body>
   <h1>Timing Chart Formatter</h1>
   <textarea id="source" cols="60" rows="10" spellcheck="false">
 clock	_~_~_~_~_~_~_~_~_~_~_
 data	=?====X=DATA========X=?====
 valid	_____~~~~~~~~~~______
 ready	_____________[~~]______
   </textarea>
   <div id="result"></div>
   <input type="button" value="Download as SVG" id="as_svg" />
   <input type="button" value="Download as PNG" id="as_png" />
   Background: <input id="background" value="white" style="width:60px" />
 </div>
 </body>
 </html>

 LANG:scss(linenumber)
 @import "compass";
 
 textarea {
   font-size: 15px;
   $line-height: 18px;
   line-height: $line-height;
   padding: 0px 10px;
   @include background-image(
     linear-gradient(left, white 5px, transparent 5px), 
     linear-gradient(right, white 5px, transparent 5px), 
     linear-gradient(white $line-height - 1px, 
       #ddd $line-height - 1px, #ddd $line-height, white $line-height)
   );
   background-size: 100% 100%, 100% 100%, 100% $line-height;
 }

 LANG:coffeescript(linenumber)
 class SvgPath
   constructor: (style)->
     @segments = []
     @style = style
 
   draw: (x1, y1, x2, y2)->
     @segments.push([x1,y1,x2,y2])
 
   svg: ->
     for s in @segments
       s[4]= 0
       s[5]= null
       
     for s1 in @segments
       for s2 in @segments
         if s1[2]==s2[0] and s1[3]==s2[1]
           s1[4] += 1
           s2[4] += 1
 
     for s1 in @segments
       for s2 in @segments
         continue if s2[4]<2 or s1[2]!=s2[0] or s1[3]!=s2[1]
         s1[5]= s2
         s2[4]= -1
         break
       continue if s1[5]
       for s2 in @segments
         continue if s2[4]!=1 or s1[2]!=s2[0] or s1[3]!=s2[1]
         s1[5]= s2
         s2[4]= -1
         break
         
     path = []
     for s1 in @segments
       continue if s1[4]<0
       s = s1
       cx = s[0]
       cy = s[1]
       path.push "M#{cx},#{cy}"
       while s
         if cx == s[2] && cy == s[3]
         else if cx == s[2]
           if path[path.length-1][0]=='V'
             path[path.length-1]= "V#{s[3]}"
           else
             path.push "V#{s[3]}"
         else if cy == s[3]
           if path[path.length-1][0]=='H'
             path[path.length-1]= "H#{s[2]}"
           else
             path.push "H#{s[2]}"
         else 
           path.push "L#{s[2]},#{s[3]}"
         cx = s[2]
         cy = s[3]
         s = s[5]
       
     """<path #{@style} d="#{path.join('')}" />\n"""
 
 class TimeLine
   # : - ~ _ = 
   @transitions = [
     '          ', # :
     '  - 1 4 14', # -
     '  2 ~ / ~/', # ~
     '  3 ` _ _`', # _
     '  23`~/_= ', # =
     '  23`~/_=/', # /
     '  23`~/_=`', # \
     '  23`~/_X ', # X
     '  23`~/_=X', # *
   ]
 
   @transitionLines =
     ' ' : []
     '~' : [[1,1]]
     '_' : [[0,0]]
     '=' : [[1,1],[0,0]]
     'X' : [[1,0],[0,1]]
     '`' : [[1,0]]
     '/' : [[0,1]]
     '1' : [[1,0.5]]
     '2' : [[0.5,1]]
     '3' : [[0.5,0]]
     '4' : [[0,0.5]]
     '-' : [[0.5,0.5]]
 
   #                :  -     ~   _   =
   @stateLines = [[],[0.5],[1],[0],[0,1]]
 
   #
   @codes = ':-~_=/\\X*'
   
   constructor: (config, y)->
     @config = config
     @x = config.w_caption
     @y = y
     @path = new SvgPath(config.signal_style)
     @current = 0
     @crosses = []
     @strings = []
     @grids   = []
     @highlights = []
     
   ys: (s)->
     @y + (1-s) * @config.h_line
   y0: ->
     @y + @config.h_line
   y1: ->
     @y
   yz: ->
     @y + @config.h_line/2.0
   xh: ->
     @x + @config.w_transient/2.0
   xt: ->
     @x + @config.w_transient
   xr: ->
     @x + @config.w_transient + @config.w_hold
   
   parse: (line)->
     while line != ''
       if maches = /^\s+/.exec(line)
         ;
       else if maches = /^\|/.exec(line)
         @grids.push [@xh(), @config.grid_style]
       else if maches = /^\[/.exec(line)
         if @highlights.length==0 or Array.isArray(@highlights[@highlights.length-1])
           @highlights.push @xh()
       else if maches = /^\]/.exec(line)
         if @highlights.length>0 and not Array.isArray(@highlights[@highlights.length-1])
           @highlights[@highlights.length-1] = 
             [@highlights[@highlights.length-1], @xh(), @config.highlight_style]
       else if matches = /^([:\-~_=\/\\X*])/.exec(line)
         @addState(matches[1])
       else if matches = /^"(([^"]|"")*)"/.exec(line)
         @addString(matches[1].replace(/""/g, '"').replace(/[ ]/g, '&nbsp;'))
       else if matches = /([^:\-~_=\/\\X*\|\]\[]+)/.exec(line)
         @addString(matches[1])
       line = line.substr(matches[0].length, line.length-matches[0].length)
     
     @processStrings() + @path.svg()
 
   addState: (c)->
     s = TimeLine.codes.indexOf(c)
     crosses = @drawTransition(s)
     s = 4 if s > 4
     @drawState(s)
     @crosses.push([@x, crosses]) if crosses!=''
     if (@current == 0 and s != 0) or (@current != 0 and s == 0) or
        (@crosses.length==0 and s == 0)
       @crosses.push([@x, '|'])
     @current = s
     @x = @xr()
 
   addString: (s)->
     @strings.push [@crosses.length, s.replace(/^\s+|\s+$/g, '')]
 
   drawTransition: (s)->
     crosses = ''
     transitions = TimeLine.transitions[s].substr(2*@current,2)
     for i in [0..transitions.length-1]
       crosses += @drawTransitionSub(transitions[i])
     crosses
   
   drawTransitionSub: (c)->
     crosses = ''
     for line in TimeLine.transitionLines[c]
       @path.draw(@x,  @ys(line[0]), @xt(), @ys(line[1]))
       crosses += c if line[0] != line[1]
     crosses
 
   drawState: (s)->
     for line in TimeLine.stateLines[s]
       @path.draw(@xt(), @ys(line), @xr(), @ys(line))
   
   processStrings: ->
     svg = []
     @crosses.push [@x,'|']
     for string in @strings
       y0 = @ys(0)
       y1 = @ys(1)
       yz = @ys(0.5)
       x1 = @crosses[string[0]-1][0]
       x1t = x1 + @config.w_transient
       x1h = x1 + @config.w_transient/2.0
       x1r = x1t + @config.w_hold
       x2 = @crosses[string[0]  ][0]
       x2t = x2 + @config.w_transient
       x2h = x2 + @config.w_transient/2.0
       x2r = x2t + @config.w_hold
 
       if string[1]=='?'
         path= ["M#{x1t},#{y1}H#{x2}"]
         path.push switch @crosses[string[0]][1]
           when '|'  then ""
           when 'XX' then "L#{x2h},#{yz}"
           when '/'  then "H#{x2t}"
           when '`'  then "L#{x2t},#{y0}"
           when '23' then "H#{x2t}L#{x2},#{yz}L#{x2t},#{y0}"
           when '14' then "L#{x2t},#{yz}"
           when '1'  then "L#{x2t},#{yz}V#{y0}"
           when '2'  then "H#{x2t}L#{x2},#{yz}"
           when '3'  then "V#{yz}L#{x2t},#{y0}"
           when '4'  then "H#{x2t}V#{yz}"
         path.push "L#{x2},#{y0}H#{x1t}"
         path.push switch @crosses[string[0]-1][1]
           when '|'  then ""
           when 'XX' then "L#{x1h},#{yz}"
           when '/'  then "H#{x1}"
           when '`'  then "L#{x1},#{y1}"
           when '23' then "L#{x1},#{yz}"
           when '14' then "H#{x1}L#{x1t},#{yz}L#{x1},#{y1}"
           when '1'  then "V#{yz}L#{x1},#{y1}"
           when '2'  then "H#{x1}V#{yz}"
           when '3'  then "L#{x1},#{yz}V{y1}"
           when '4'  then "H#{x1}L#{xt},#{yz}"
         path.push "Z"
         svg.push """\n<path stroke="none" d="#{path.join('')}" #{@config.notcare_style}/>"""
 
       sanitized = string[1].replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
       if string[1].substr(0,3)=='_<_'
         x = x1t
         anchor = 'start'
         sanitized = sanitized.substring(6)
       else if string[1].substr(0,3)=='_>_'
         x = x2
         anchor = 'end'
         sanitized = sanitized.substring(6)
       else
         x = (x1h+x2h)/2.0
         anchor = 'middle'
 
       svg.push """<text x="#{x}" y="#{@ys(0)-1.5}" text-anchor="#{anchor}" """ +
                """font-size="#{@config.h_line}" #{@config.signal_font}>#{sanitized}</text>\n"""
 
     svg.join("")
     
 class TimingChart
   @config:
     scale:          1.0
     margin:         10
     w_caption:      40
     w_hold:         10
     w_transient:    2
     h_line:         10
     h_space:        10
     signal_style:   'stroke-linecap="round" stroke-width="0.6" stroke="black" fill="none"'
     grid_style:     'stroke-linecap="round" stroke-width="0.6" stroke="red" fill="none"'
     highlight_style:'stroke="none" fill="#ff8"'
     notcare_style:  'fill="#ccc"'
     rotate:         0
     caption_font:   'fill="black" font-family="Helvetica"'
     signal_font:    'fill="black" font-family="Helvetica"'
 
   constructor: (config= {})->
     @config= {}
     @setConfig(TimingChart.config)
     @setConfig(config)
 
   setConfig: (config)->
     @config[k]= v for own k,v of config
 
   parse: (source)->
     @svg= []
     @grids= []
     @highlights= []
     @y= -1
     @x_max= @config.w_caption
     source= source.replace(/^\n+/, '')
     source= source.replace(/\n+$/, '')
     for line in source.split("\n")
       @parseLine(line)
     @processGrids()
     @processHighlights()
     @formatSVG(source)
 
   formatSVG: (source)->
     m= @config.margin
     w= (@x_max + 2 * m) * @config.scale * 1.3
     h= (@y     + 2 * m) * @config.scale * 1.3
     @width = w
     @height = h
     """
     <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
       width="#{w}px" height="#{h}px" viewBox="#{-m} #{-m} #{@x_max+2*m} #{@y+2*m}" version="1.1">
     <![CDATA[
     #{source.replace(/\]\]\>/g, ']]&gt;')}
     ]]>
     <g>
     #{@svg.join("\n")}
     </g>
     </svg>
     """
 
   parseLine: (line)->
     return if line[0] == '#'  #### comment
 
     if line[0]=='@'           #### configuration
       if !(matches = /^@([^\s]+)[\s]+([^\s].*)$/.exec(line))
         throw new SyntaxError("Illegal Line: #{line}")
       if $.isNumeric(@config[matches[1]])
         @config[matches[1]] = Number(matches[2])
       else
         @config[matches[1]] = matches[2]
       return
 
     if line[0] == '%'         #### free string
       if !(matches = /^%(-?[\d\.]+)\s+(-?[\d\.]+)\s+?(.*)$/.exec(line))
         throw new SyntaxError("Illegal Line: #{line}")
       @svg.push("""<text x="#{matches[1]}" y="#{matches[2]}" text-anchor="middle" """ +
                 """font-size="#{@config.h_line}" #{@config.signal_font}>#{matches[3]}</text>""")
       return
     
     if @y<0
       @y= 0
     else
       @y+= @config.h_space
 
     line= line.replace(/\s*$/, '')
     return if line==''        #### empty line
 
     if !(matches = /^([^\s]+)[\s]+([^\s].*)$/.exec(line))
       throw new SyntaxError("Illegal Line: #{line}")
     
     @formatCaption(matches[1])
     @formatTimeline(matches[2])
     @y+= @config.h_line
 
   formatCaption: (caption)->
     sanitized = caption.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;')
     @svg.push(
       """<text x="#{@config.w_caption-5}" y="#{@y+@config.h_line-1.5}" text-anchor="end" """+
       """font-size="#{@config.h_line}" #{@config.caption_font}>#{sanitized}</text>"""
     )
 
   formatTimeline: (line)->
     tline= new TimeLine(@config, @y)
     @svg.push tline.parse(line)
     @x_max= tline.x if tline.x > @x_max
     for g in tline.grids
       @grids.push g
     for h in tline.highlights
       @highlights.push h 
   
   processGrids: ->
     t = -@config.margin/2.0
     b = @y+@config.margin/2.0
     for g in @grids
       @svg.push """<path d="M#{g[0]},#{t}V#{b}" #{g[1]} />"""
     
   processHighlights: ->
     t = -@config.margin/2.0
     b = @y+@config.margin/2.0
     for h in @highlights
       if Array.isArray(h)
         @svg.unshift """<path d="M#{h[0]},#{t}V#{b}H#{h[1]}V#{t}Z" #{h[2]} />"""
 
 download= (dataUrl, filename)->
   form = $('<form>')
   form.action = dataUrl
   form.target = '_blank'
   form.submit()
                   
 lastSource = ''
 update = ->
   source = $('#source').val()
   return if lastSource==source
   lastSource = source
   
   tchart= new TimingChart()
   svg= tchart.parse(source)
   $('#result').html(svg)
 
 $ ->
   $('#as_svg').on 'click', ->
     update()
     blob = new Blob([$('#result').html()], {type: "image/svg+xml"});
     saveAs(blob, 'timing-chart.svg')
 
   $('#as_png').on 'click', ->
     source = $('#source').val()
     tchart= new TimingChart()
     svg= tchart.parse(source)
 
     canvas = document.createElement('canvas')
     canvas.width = tchart.width
     canvas.height = tchart.height
 
     # http://nmi.jp/archives/223
     img = new Image()
     img.onload = ->
       ctx = canvas.getContext("2d")
       ctx.fillStyle = $('#background').val()
       ctx.fillRect(0, 0, canvas.width, canvas.height)
       ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
       url = canvas.toDataURL('image/png')
       link = document.createElement('a')
       link.href = url
       link.download = 'timing-chart.png'
       link.click()
 
     img.src = "data:image/svg+xml;base64," + btoa(svg)
 
   setInterval(update, 100)

* コメント・質問 [#m9652e62]

#article_kcaptcha


Counter: 65965 (from 2010/06/03), today: 2, yesterday: 0