イタリックはABC幅の問題ですね。
内部ソースを確認しましたが、ABC幅は考慮されていませんでした。
http://dev.onionsoft.net/trac/openhsp/browser/trunk/hsp3/win32gui/hspwnd_win.cpp#L1217
モジュールで出来ないかと試してみたら恐ろしく面倒な事になってしまいました。
#uselib "user32.dll"
#define global TabbedTextOut TabbedTextOutA
#cfunc global TabbedTextOutA "TabbedTextOutA" sptr, sptr, sptr, sptr, sptr, sptr, sptr, sptr
#uselib "gdi32.dll"
#define global GetCharABCWidthsFloat GetCharABCWidthsFloatA
#func global GetCharABCWidthsFloatA "GetCharABCWidthsFloatA" sptr, sptr, sptr, sptr
#define global GetTextMetrics GetTextMetricsA
#func global GetTextMetricsA "GetTextMetricsA" sptr, sptr
#define global NULL 0
#define global TRUE 1
#define global FALSE 0
#module ITLMes
// int型float値をdowble型に変換
#defcfunc todouble int p1
temp = 0.0;
lpoke temp, 4, (p1 & 0x80000000) | (((p1 & 0x7fffffff) >> 3) + ((p1 & 0x7fffffff) ! 0) * 0x38000000);
lpoke temp, 0, p1 << 29;
return temp;
// 全角・半角チェック 半角ならば1 全角ならば2が戻り値になる
#defcfunc SjisChk str s00
s01 = s00;
rc = 1;
s02 = peek(s01, 0);
if( ((0x81<=s02)&&(s02<=0x9F)) || ((0xE0<=s02)&&(s02<=0xFC)) ) {
// 全角文字
rc = 2;
}
else: if( s02 == 0x0D ) {
// 改行コード
rc = 0;
}
return rc;
// 斜体字用ginfo 出力した最後の行の情報のみ返す 0:左上座標X 1:左上座標Y 2:幅 3:高さ その他は-1
#defcfunc ginfo2 int p
if( forginfoflag ) {
switch p
case 0;
rc = fordebug(0, linenum-1);
swbreak;
case 1;
rc = fordebug(1, linenum-1);
swbreak;
case 2;
rc = fordebug(2, linenum-1);
swbreak;
case 3;
rc = fordebug(3, linenum-1);
swbreak;
default
rc = -1;
swend
}
else {
rc = -1;
}
return rc;
// 斜体字用mes
#deffunc mes2 str s
strings = s;
notesel strings;
linenum = notemax; // 行数取得
byte = notesize; // バイト数取得
dim fordebug, 4, linenum; // デバッグ用座標取得配列
forginfoflag = TRUE;
dim tm, 14;
// フォント情報の取得
GetTextMetrics hdc, varptr(tm);
bottom = tm(0)+tm(4); // 改行用 文字の高さ+行間
iflag = FALSE;
if( (tm(12)&0xFF) != 0 ) {
iflag = TRUE; // イタリックフラグ
}
dim linewidth, linenum, 3; // 行ごとの情報取得 0:バイト数 1:文字数 2:末尾の文字のインデックス
sdim wline, notesize, notemax;
repeat linenum
noteget wline(cnt), cnt;
linewords = strlen(wline(cnt)); // 行単位のバイト数取得
len = 0;
idx = -1; // 空行の場合はマイナス値
repeat linewords
idx =cnt;
word = "";
poke word, 0, peek(wline(cnt), cnt);
poke word, 1, 0;
word2 = peek(wline(cnt), cnt);
r = SjisChk(word);
len++; // 文字数カウント
if( r == 2 ) {
continue cnt+2;
}
loop
linewidth(cnt, 0) = linewords;
linewidth(cnt, 1) = len;
linewidth(cnt, 2) = idx;
loop
noteunsel; // 対象バッファの復帰
max = 0; // 最大幅取得用
// 1行毎に処理
repeat linenum
l = cnt;
idx = linewidth(cnt, 2);
// 空行確認
if( idx >= 0 ) {
// 末尾文字の情報取得
word = "";
poke word, 0, peek(wline(cnt), idx);
poke word, 1, 0;
r = SjisChk(word);
word2 = peek(wline(cnt), idx);
if( r == 2 ) {
word2 = peek(wline(cnt), idx+1)|(word2<<8);
}
// ABC幅の取得
dim abc, 3;
GetCharABCWidthsFloat hdc, word2, word2, varptr(abc);
// Float値をDouble値に変換
abc0 = todouble(abc(0)): abc1 = todouble(abc(1)): abc2 = todouble(abc(2));
// 1行ずつテキスト描画
rlong = TabbedTextOut( hdc, ginfo_cx, ginfo_cy, wline(cnt) , linewidth(cnt, 0), 0, NULL, 0 );
swidth = rlong & 0xFFFF;
sheight = rlong >> 16;
//************************************
// イタリック幅の調整
if( iflag ) {
if( tm(8) == 0 ) {
swidth += absf(abc2);
}
else {
swidth += tm(8);
}
}
//************************************
fordebug(0,cnt) = ginfo_cx, ginfo_cy, swidth, sheight; // 左上座標、幅、高さを記録
}
else {
// 空行の場合
fordebug(0,cnt) = ginfo_cx, ginfo_cy, 0, bottom; // 左上座標、幅、高さを記録
}
if( fordebug(2,cnt) > fordebug(2,max) ) {
// 最大幅更新
max = cnt;
}
pos ginfo_cx, ginfo_cy+bottom; // 改行しておく
loop
// 現在の描画状態取得
mref bmscr, 67;
fl_udraw = bmscr(19) >> 16 & 0xFFFF;
// 描画を行なう場合
if( fl_udraw & 1 ) {
// 文字を描画した領域のみ再描画
redraw fl_udraw, fordebug(0,0), fordebug(1,0), fordebug(2,max), bottom*linenum;
}
return;
#global
font msgothic, 20, 2;
pos 0, 100;
mes "モジュール使用→"
pos 200, 100;
mes2 "あいうえおかきくけこ\n0123456789";
x1 = ginfo_cx:y1 = ginfo_cy;
pos 0, y1;
mes "標準命令→";
pos x1, y1;
mes "0123456789";
x2 = ginfo_mesx:y2 = ginfo_mesy;
// 文字枠表示
color 255, 0, 0;
// モジュール使用1行目
line fordebug@ITLMes(0,0), fordebug@ITLMes(1,0), fordebug@ITLMes(0,0)+fordebug@ITLMes(2,0), fordebug@ITLMes(1,0);
line fordebug@ITLMes(0,0)+fordebug@ITLMes(2,0), fordebug@ITLMes(1,0), fordebug@ITLMes(0,0)+fordebug@ITLMes(2,0), fordebug@ITLMes(1,0)+fordebug@ITLMes(3,0);
line fordebug@ITLMes(0,0)+fordebug@ITLMes(2,0), fordebug@ITLMes(1,0)+fordebug@ITLMes(3,0), fordebug@ITLMes(0,0), fordebug@ITLMes(1,0)+fordebug@ITLMes(3,0);
line fordebug@ITLMes(0,0), fordebug@ITLMes(1,0)+fordebug@ITLMes(3,0), fordebug@ITLMes(0,0), fordebug@ITLMes(1,0);
// モジュール使用2行目
line ginfo2(0), ginfo2(1), ginfo2(0)+ginfo2(2), ginfo2(1);
line ginfo2(0)+ginfo2(2), ginfo2(1), ginfo2(0)+ginfo2(2), ginfo2(1)+ginfo2(3);
line ginfo2(0)+ginfo2(2), ginfo2(1)+ginfo2(3), ginfo2(0), ginfo2(1)+ginfo2(3);
line ginfo2(0), ginfo2(1)+ginfo2(3), ginfo2(0), ginfo2(1);
// 標準命令
color 0, 0, 255;
line x1, y1, x1+x2, y1;
line x1+x2, y1, x1+x2, y1+y2;
line x1+x2, y1+y2, x1, y1+y2;
line x1, y1+y2, x1, y1;
ほぼ終盤で気づいたのですが、
モジュールだと結局最後にredrawを使うことになって
作った意味はなかったんですよね……
利点は幅が正確にわかるようになったって事だけでしょうか。。。
Dripさんのはどちらかと言うとWindowsのAPIの仕様とかハード的な問題な気がします。
gzoomはわかりませんが、
フォントに関しては一定の大きさより小さいとアンチエイリアスは環境に依存します。
私の環境では
メイリオだとサイズ18以上はスタイル設定に関係なく常にアンチエイリアスになり、
それより小さいサイズだとアンチエイリアスがかかりません。
MS Pゴシックの場合は25以上でアンチエイリアス、25未満だとノーマルでした。
フォントによって閾値が違うので面倒ではありますね。