HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2018
0211
みけCATイタリック体の文字描画の右端が切れないように3解決


みけCAT

リンク

2018/2/11(Sun) 10:49:26|NO.82439

Hot Soup Processor ver3.5 (安定版) (フルセット・アーカイブ版)
において、mes命令を用いてイタリック体の文字列を描画すると、右端が切れるようです。
width命令やウィンドウの最小化→復帰をすると、切れていない表示になりました。
一応描画する文字列の右に空白を入れれば切れずに描画できますが、
空白が入っていなくても一発で切れないようにできないでしょうか?


font msgothic, 20, 2 mes "00000" mes "00000 "

実行結果 : https://i.imgur.com/8zfNgRh.png



この記事に返信する


チャーくん

リンク

2018/2/11(Sun) 11:49:54|NO.82440

こちらもHSP3.5で同様の現象を確認しました。
イタリック体で文字を描画すると ginfo_mesx (文字が描画された横幅)が実際より狭いみたいで、
その範囲でしか画面の更新が行われないのでこうなるようです。
最後に redraw を追加して手動で画面全体を更新させると大丈夫です。



Drip

リンク

2018/2/11(Sun) 17:54:31|NO.82443

こんにちは。横からですが、実はそのほかにも
gzoomで左右反転コピーしようとしたときも似たような更新領域不足が1ライン分発生します。
これは仕様というよりバグのような気がしますが…

color 255:line 100,10,100,220 color ,,255:line 539,10,539,220 pos 540,250:gzoom -440,220,0,100,10,440,220 objsize 100,40:pos 270,200:button "Redraw",*re stop *re redraw 1

フォントにまつわるお話ではアンチエイリアスONのオプションが逆転してしまう事があるなど…
マニュアル未記載のわかりにくい隠れ仕様が結構ありますね。

font "メイリオ",16,16:mes "○美しい日本語○(アンチエイリアス)" font "メイリオ",16:mes "○美しい日本語○(通常描画)" font "MS Pゴシック",24,16:mes "○美しい日本語○(アンチエイリアス)" font "MS Pゴシック",24:mes "○美しい日本語○(通常描画)" pos 0,240:gzoom 640,240,0,0,0,320,120



あまら

リンク

2018/2/12(Mon) 21:43:13|NO.82457

イタリックは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未満だとノーマルでした。
フォントによって閾値が違うので面倒ではありますね。



ONION software Copyright 1997-2021(c) All rights reserved.