TrueType命令で遊ぶシリーズ。
- 初めてのTrueType命令: Windowsでは見えないフォントをつくる - にせねこメモ
- フォントサイズに合わせて回転するフォントを作る(1) - にせねこメモ
- PPEM・ポイントサイズを表示するフォント - にせねこメモ
- TrueType命令で三角関数(sin, cos)を計算する - にせねこメモ
はじめに
さて、前回作った回転するフォントでは回転の処理があまり賢くないので、それを改善するのがこの記事でやりたいことである。
そのために、三角関数のsin, cosの値を計算する関数を作成した。この関数を利用して回転行列の要素の値を計算し、それによって回転するという風にする。
成果物
イラレではあまり見たことのない動きをする。正直気持ち悪い。笑 pic.twitter.com/3jU229mSND
— にせねこ (@nixeneko) 2017年2月5日
きもい実にきもい。
ダウンロード
- Arotate.ttf (1.74 MB)
変更点
回転行列の値のStorage Areaへの格納
三角関数(sin, cos)を計算する関数を関数4としてもってきた。
他は、基本的に前回の回転するフォントそのままであるが、'prep'での回転行列の要素の値を格納する際に、PPEMの値を取得し、その角度に対する三角関数の計算を呼び出し、その結果を格納している。
'prep'
/* prep */ MPPEM /* |ppem(int)| */ PUSHW_1 4096 /* |ppem(int)|64.0| */ MUL /* |ppem(F26Dot6)| */ PUSHB_1 4 /* |ppem(F26Dot6)|4| */ CALL /* |64*sin|64*cos| */ PUSHB_2 2 3 /* |64*sin|64*cos|2|3| */ ROLL /* |64*sin|2|3|64*cos| */ WS /* |64*sin|2| */ /* StorageArea[3] = 64*cos */ SWAP /* |2|64*sin| */ WS /* | */ /* StorageArea[2] = 64*sin */
MPPEMで取得したppemの値に適当な係数を掛け算してやると、回転の度合いを調整できる。マイナスをかければ逆回転になる。
回転
関数2で回転した座標を計算する際に、前回はLOOPCALLを用いていたが、ここは今回は1回だけ回転させればいいので、CALLに変更している。
ついでに関数2で引数として余計なスタック要素が積まれてたのを削除している。
'fpgm'
PUSHB_1 0 FDEF /* ..| n-1 | *//* ← initial stack */ PUSHB_1 /* ..| n-1 | 2 | */ 2 ADD /* ..| n+1 | *//* n+1: phantom point n+1 に対応 */ SVTCA[x-axis] /* 座標の測定をx軸方向にする */ GC[orig] /* ..| x_(n+1) | *//* phantom point n+1の(X)座標取得 */ PUSHB_1 /* ..| x_(n+1) | 2.0 | *//* Uint 128 == F24Dot6 2.0 */ 128 DIV /* ..| x_(n+1) / 2 | */ PUSHB_1 /* ..| x_(n+1) / 2 | 0 | */ 0 SWAP /* ..| 0 | x_(n+1) / 2 | */ WS /* ..| *//* StorageArea[0] = x_(n+1) / 2 */ PUSHB_1 /* ..| 1 | */ 1 RCVT /* ..| CVT[1] | *//* read control value table */ PUSHB_1 /* ..| CVT[1] | 1 | */ /* CVT[1]は回転中心y_cに対応 */ 1 SWAP /* ..| 1 | CVT[1] | */ WS /* ..| *//* StorageArea[1] = CVT[1] */ ENDF /* Function 1: Calculates rotated coordinates with pre-defined angle T */ /* initial stack ..| y | x | x' = x*cosT - y*sinT */ /* final stack ..| y'| x'| while y' = x*sinT + y*cosT */ PUSHB_1 1 FDEF /* ..|y|x| */ DUP /* ..|y|x|x| */ ROLL /* ..|x|x|y| */ DUP /* ..|x|x|y|y| */ ROLL /* ..|x|y|y|x| */ PUSHB_1 /* ..|x|y|y|x|3| */ 3 RS /* ..|x|y|y|x|64*cosT| */ /* SA[3] = 64*cosT */ MUL /* ..|x|y|y|64*x*cosT| */ SWAP /* ..|x|y|64*x*cosT|y| */ PUSHB_1 /* ..|x|y|64*x*cosT|y|2| */ 2 RS /* ..|x|y|64*x*cosT|y|64*sinT| */ /* SA[2] = 64*sinT */ MUL /* ..|x|y|64*x*cosT|64*y*sinT| */ SUB /* ..|x|y|64*(x*cosT - y*sinT)| */ PUSHW_1 /* ..|x|y|64*(x*cosT - y*sinT)|64.0| */ 4096 DIV /* ..|x|y|x*cosT - y*sinT| */ ROLL /* ..|y|x*cosT - y*sinT|x| */ ROLL /* ..|x*cosT - y*sinT|x|y| */ PUSHB_1 /* ..|x*cosT - y*sinT|x|y|3| */ 3 RS /* ..|x*cosT - y*sinT|x|y|64*cosT| */ /* SA[3] = 64*cosT */ MUL /* ..|x*cosT - y*sinT|x|64*y*cosT| */ SWAP /* ..|x*cosT - y*sinT|64*y*cosT|x| */ PUSHB_1 /* ..|x*cosT - y*sinT|64*y*cosT|x|2| */ 2 RS /* ..|x*cosT - y*sinT|64*y*cosT|x|64*sinT| */ /* SA[2] = 64*sinT */ MUL /* ..|x*cosT - y*sinT|64*y*cosT|64*x*sinT| */ ADD /* ..|x*cosT - y*sinT|64*(x*sinT + y*cosT)| */ PUSHW_1 /* ..|x*cosT - y*sinT|64*(x*sinT + y*cosT)|64.0| */ 4096 DIV /* ..|x*cosT - y*sinT|x*sinT + y*cosT| */ SWAP /* ..|x*sinT + y*cosT|x*cosT - y*sinT| */ ENDF /* ↑関数呼び出し時とx, yの順番を合わせている */ /* Function 2: moves a control point k to the rotated coordinates */ /* initial stack ..| k | k: 編集する制御点番号 */ /* final stack ..| */ PUSHB_1 2 FDEF /* ..|k| */ DUP /* ..|k|k| */ DUP /* ..|k|k|k| */ SVTCA[x-axis] /* X座標に設定 */ GC[cur] /* ..|k|k|x_k| */ SWAP /* ..|k|x_k|k| */ SVTCA[y-axis] /* Y座標に設定 */ GC[cur] /* ..|k|x_k|y_k| */ PUSHB_1 /* ..|k|x_k|y_k|1| */ 1 RS /* ..|k|x_k|y_k|y_c| */ /* y_c = SA[1]: 回転中心Y座標 */ SUB /* ..|k|x_k|y_k-y_c| */ SWAP /* ..|k|y_k-y_c|x_k| */ PUSHB_1 /* ..|k|y_k-y_c|x_k|0| */ 0 RS /* ..|k|y_k-y_c|x_k|x_c| */ /* x_c = SA[0]: 回転中心X座標 */ SUB /* ..|k|y_k-y_c|x_k-x_c| */ PUSHB_1 /* ..|k|y_k-y_c|x_k-x_c|1|*/ 1 CALL /* ..|k|y_k-y_c|x_k-x_c| */ /* call function 1 */ /* y_k' = y_k-y_c, x_k' = x_k-x_c are changed to y_k'', x_k'' */ PUSHB_1 /* ..|k|y_k''|x_k''|0| */ 0 RS /* ..|k|y_k''|x_k''|x_c| */ /* x_c = SA[0]: 回転中心X座標 */ ADD /* ..|k|y_k''|x_k''+x_c| */ SWAP /* ..|k|x_k''+x_c|y_k''| */ PUSHB_1 /* ..|k|x_k''+x_c|y_k''|1| */ 1 RS /* ..|k|x_k''+x_c|y_k''|y_c| */ /* y_c = SA[1]: 回転中心Y座標 */ ADD /* ..|k|x_k''+x_c|y_k''+y_c| */ SVTCA[y-axis] /* Y座標に設定 */ PUSHB_1 /* ..|k|x_k''+x_c|y_k''+y_c|3| */ 3 CINDEX /* ..|k|x_k''+x_c|y_k''+y_c|k| * stack先頭から3番目をトップにコピー*/ SWAP /* ..|k|x_k''+x_c|k|y_k''+y_c| */ SCFS /* ..|k|x_k''+x_c| *//* 制御点kのY座標を y_k''+y_c に */ SVTCA[x-axis] /* X座標に設定 */ SCFS /* ..| *//* 制御点kのX座標を x_k''+x_c に */ ENDF PUSHB_1 3 FDEF /* ..|n-1| */ DUP /* ..|n-1|n-1| */ PUSHB_1 /* ..|n-1|n-1|0| */ 0 CALL /* ..|n-1| */ /* call function 0 */ DUP /* ..|n-1|i| */ /* i = n-1 とおく */ /* jump_to_here */ DUP /* ..|n-1|i|i| */ PUSHB_1 /* ..|n-1|i|i|0| */ 0 GTEQ /* ..|n-1|i|i<0| */ IF /* ..|n-1|i| */ /* if i<0 then */ DUP /* ..|n-1|i|i| */ PUSHB_1 /* ..|n-1|i|i|2| */ 2 CALL /* ..|n-1|i| */ /* call function 2 */ PUSHB_1 /* ..|n-1|i|1| */ 1 SUB /* ..|n-1|i-1| */ PUSHW_1 /* ..|n-1|i-1|-15| */ -15 JMPR /* ..|n-1|i-1| */ /* goto jump_to_here */ EIF /* end if */ POP /* ..|n-1| */ POP /* ..| */ ENDF /* function 4 は省略、前回の記事参照 */
ソース
'fpgm'
PUSHB_1 0 FDEF PUSHB_1 2 ADD SVTCA[x-axis] GC[orig] PUSHB_1 128 DIV PUSHB_1 0 SWAP WS PUSHB_1 1 RCVT PUSHB_1 1 SWAP WS ENDF PUSHB_1 1 FDEF DUP ROLL DUP ROLL PUSHB_1 3 RS MUL SWAP PUSHB_1 2 RS MUL SUB PUSHW_1 4096 DIV ROLL ROLL PUSHB_1 3 RS MUL SWAP PUSHB_1 2 RS MUL ADD PUSHW_1 4096 DIV SWAP ENDF PUSHB_1 2 FDEF DUP DUP SVTCA[x-axis] GC[cur] SWAP SVTCA[y-axis] GC[cur] PUSHB_1 1 RS SUB SWAP PUSHB_1 0 RS SUB PUSHB_1 1 CALL PUSHB_1 0 RS ADD SWAP PUSHB_1 1 RS ADD SVTCA[y-axis] PUSHB_1 3 CINDEX SWAP SCFS SVTCA[x-axis] SCFS ENDF PUSHB_1 3 FDEF DUP PUSHB_1 0 CALL DUP DUP PUSHB_1 0 GTEQ IF DUP PUSHB_1 2 CALL PUSHB_1 1 SUB PUSHW_1 -15 JMPR EIF POP POP ENDF PUSHB_1 4 FDEF DUP PUSHW_1 23040 GTEQ IF PUSHW_1 23040 SUB PUSHW_1 -13 JMPR EIF DUP PUSHB_1 0 LT IF PUSHW_1 23040 ADD PUSHW_1 -12 JMPR EIF PUSHB_2 64 64 ROLL DUP PUSHW_1 11520 GT IF PUSHW_1 23040 SWAP SUB ROLL NEG ROLL ROLL EIF DUP PUSHW_1 5760 GT IF PUSHW_1 11520 SWAP SUB SWAP NEG SWAP EIF DUP PUSHB_1 0 EQ IF POP PUSHW_2 0 4096 ELSE DUP PUSHW_1 5760 EQ IF POP PUSHW_2 4096 0 ELSE NPUSHW 10 57 114 229 458 916 1833 3666 7331 14648 29184 PUSHW_4 8340 3 16384 4096 MUL MUL ADD PUSHW_4 10506 6 16384 4096 MUL MUL ADD PUSHW_4 4096 11 16384 4096 MUL MUL ADD PUSHB_1 14 MINDEX PUSHW_1 4096 MUL PUSHW_2 4096 4096 PUSHB_1 0 PUSHB_1 64 PUSHB_1 6 MINDEX ROLL PUSHB_1 1 ADD ROLL PUSHB_1 128 MUL ROLL PUSHB_1 3 CINDEX PUSHB_1 12 LTEQ IF PUSHB_1 5 MINDEX PUSHB_1 5 MINDEX DUP PUSHB_1 5 CINDEX DIV PUSHB_1 3 CINDEX PUSHB_1 6 CINDEX DIV ROLL SWAP PUSHB_1 5 CINDEX PUSHB_1 9 CINDEX LT IF ADD ROLL ROLL SUB SWAP PUSHB_1 5 MINDEX PUSHB_1 5 MINDEX PUSHB_1 5 MINDEX PUSHB_1 7 MINDEX ADD ELSE SUB ROLL ROLL ADD SWAP PUSHB_1 5 MINDEX PUSHB_1 5 MINDEX PUSHB_1 5 MINDEX PUSHB_1 7 MINDEX SUB EIF PUSHW_1 -85 JMPR EIF POP POP POP PUSHW_1 6745 DUP ROLL PUSHW_1 4096 MUL SWAP DIV ROLL PUSHW_1 4096 MUL ROLL DIV ROLL POP EIF EIF ROLL MUL ROLL ROLL MUL SWAP ENDF
'prep'
MPPEM PUSHW_1 4096 MUL PUSHB_1 4 CALL PUSHB_2 2 3 ROLL WS SWAP WS
'cvt '
index | val |
0 | 0 |
1 | 379 |
グリフ固有のプログラム
PUSHB_2 11 3 CALL
11の部分にはそのグリフの最大の制御点番号が入る。