ばらばらにしませう…
突然梅雨が明けて酷暑が続いております。みなさん体調管理には充分ご注意下さい。わたしも先日プールに行ってきたのですが、曇っていたので油断しました。いまだにひりひりします。
まあ、そんな事は置いておいてフォントの続きです。個々のTableを解説していこうと思っていたのですが、fontファイルをダイレクトにいじってるとややこしくなる場合が多々あります。というかテーブルそれぞれにルーチンが必要ですので、のぞき見コードがふくれあがって面倒くさくなってきたというのが真相なわけですが(^^;
そこで、今回はこのfont自体を解析する前にバラバラにしてしまうツールを用意しました。
何をするかと言うとオフセットテーブルを読み込みテーブルディレクトリを解析し、各テーブルのオフセットと長さを取り込み、その情報に従ってバイナリを読み込んでバイナリファイルとしてテーブルごとに保存してしまうと言った感じです。
var fn = File.openDialog (“Select Font file.”);
var fnm = String(fn).match(/\/([^\/]+?)\.[a-zA-Z\s]+$/);
var currentPath = “~/desktop/” + RegExp.$1;
var crrntFolder = new Folder (currentPath);
if (!crrntFolder.exists) crrntFolder.create();
var dat = new Array();
var f = new File(fn);
f.encoding = ‘BINARY’;
if (f.open(“r”)){
ot = readOfstTbl();
readTD (ot[1]);
f.close();
}
function readOfstTbl(){
var dt = [“”,0,0,0,0];
var d;
var a = f.readch();
if (a==”O”){
dt[0] = a;
for (i=0;i<3;i++) {
dt[0] += f.readch();
}
} else {
dt[0] = “0x0” + a.charCodeAt(0).toString (16);
for (i=0;i<3;i++) {
a = f.readch();
d = a.charCodeAt(0).toString (16);
if (d.length==1) d = “0” + d;
dt[0] += d;
}
}
dt[1] = readBytes();
dt[2] = readBytes();
dt[3] = readBytes();
dt[4] = readBytes();
return dt;
}
function readTD(num){
var a=0;
var tw = new Window(‘palette’,’Table Directory’,
[100,100,430,24*ot[1]+140]);
for (j=0;j<num;j++){
dat[j] = [“”,0,0,0,””,””,””];
for (i=0;i<4;i++) dat[j][0] += f.readch();
$.write(dat[j][0]+” “);
dat[j][1] += f.readch().charCodeAt (0) *16777216;
dat[j][1] += f.readch().charCodeAt (0) *65536;
dat[j][1] += f.readch().charCodeAt (0) *256;
dat[j][1] += f.readch().charCodeAt (0) ;
dat[j][2] += f.readch().charCodeAt (0) *16777216;
dat[j][2] += f.readch().charCodeAt (0) *65536;
dat[j][2] += f.readch().charCodeAt (0) *256;
dat[j][2] += f.readch().charCodeAt (0) ;
dat[j][3] += f.readch().charCodeAt (0) *16777216;
dat[j][3] += f.readch().charCodeAt (0) *65536;
dat[j][3] += f.readch().charCodeAt (0) *256;
dat[j][3] += f.readch().charCodeAt (0) ;
$.write(dat[j][1]+” “+dat[j][2]+” “+dat[j][3]+”\n”);
tw.add(‘statictext’,[5,5+24*j,300,5+24*(j+1)],dat[j][0]
+” “+dat[j][1]+” “+dat[j][2]+” “+dat[j][3]);
}
var clstw = tw.add(‘button’,[10,ot[1]*24
+10,80,ot[1]*24+25],’close’,{name:’cancel’});
clstw.onClick = function(){tw.close()};
tw.show();
for (j=0;j<dat.length;j++)
saveTables (dat[j][0], dat[j][2], dat[j][3]);
}
function saveTables(nam, offset, len) {
if (nam==”OS/2″) nam = “OS_2”;
var fn = new File(currentPath + ‘/’ + nam + “.table”);
fn.encoding = ‘BINARY’;
f.seek(offset);
fn.open(“w”);
var chr = f.readch().charCodeAt(0);
fn.write(String.fromCharCode (chr));
fn.close();
fn.open(“a”);
for (var i=1;i<len;i++){
chr = f.readch().charCodeAt(0);
fn.write (String.fromCharCode(chr));
}
fn.close();
}
function readBytes(){
var a = f.readch().charCodeAt (0);
var d = a << 8;
a = f.readch().charCodeAt (0);
d += a;
return d;
}
ExtendScriptというのはけっこう良く出来ていて画像等を扱う為にBINARYモードでのファイルアクセスが設けられています。データの読み出しはreadch()メソッドを利用します。このメソッドは通常1文字ファイルから読み出す為の物です。ですからUTF-8のエンコーディングのテキストファイルのひらがななんかを読み出す場合3byteのデータが一気に読み出されます。しかし、エンコーディングをBINARYにセットした場合、このメソッドは読み出し幅を1byteに固定し、文字コードとしておかしくてもそのまま1byte文字として読み出します。これをバイナリ値に変換するにはcharCodeAt(index)メソッドを利用します。
データを書き戻す場合はString.fromCharCode(a)メソッドを利用しますが、一文字書き込むと言ったメソッドはありませんので、書き込む場合はファイルを追記モードで開き、お尻に追記していく必要があります。これはopen()メソッドの引数に「a」を指定します。