2008/02/02(土)アンチエイリアス文字描画モジュール
久しぶりに若干バージョンアップしたのでage.
2008. 2. 2 / ver 0.20 縦に描画位置がズレる問題修正と描画高速化。
2008. 5.14 / ver 0.21 描画クリップ枠が上に1pxズレていて落ちてしまう問題の修正。
mes命令に比較するとかなり重い(APIが重いから)ですが、
フォントからグリフを得て描画することにより、
綺麗で目に優しい文字を描画することができます。
このモジュールはスクリプトに組み込んで自由に使用できます。
/* ames.hsp */ // アンチエイリアス文字描画モジュール / 月影とも 2005. 9.11 // 2008. 2. 2 / ver 0.20 縦に描画位置がズレる問題修正。マシン語高速化。 // 2008. 5.14 / ver 0.21 描画クリップ枠が上に1pxズレていて落ちてしまう問題の修正。 #ifndef xdim #uselib "kernel32.dll" #func global VirtualProtect@_xdim "VirtualProtect" var,int,int,var #define global xdim(%1,%2) dim %1,%2: VirtualProtect@_xdim %1,%2*4,$40,x@_xdim #endif #module "mod_ames" ;// 追加命令 ; ames str "string" // メッセージを表示 ; text int delay // hsp3util 互換のテキストディレイモード。 ; ames_cancel // ディレイキャンセル。 onclick gosub 内などで使用可能。 #define ctype IsZenkaku(%1) ((((%1)^$20)-$a1&$ff)<=$3b) ;// Shift-Jis用 (日本語Windows) ;#define ctype IsZenkaku(%1) ((%1)<128) ;// 他言語(無保証)…… #uselib "gdi32.dll" #func GetTextMetrics "GetTextMetricsA" int,int #func GetGlyphOutline "GetGlyphOutlineA" int,int,int,var,int,int,var #deffunc _init_ames_ ;int WINAPI DrawGlyph(BMSCR *pBmscr, LPTEXTMETRIC lpTextMetric, LPGLYPHMETRICS lpGlyphMetrics, LPBYTE pbGryph, DWORD cbGryph) xdim f,111 f.$00=$8b28ec83,$53342454,$55085a8b,$57562a8b,$3c247c8b,$8b14478b,$5f03084f,$2444896c,$04478b28,$0340748d,$24244489,$2b70478b,$4c890c42,$4a8b1024,$24548b04,$04420340 f.$10=$1c246c89,$8303c583,$e583fce6,$89c985fc,$892c2474,$8930246c,$0f34245c,$0001448e,$24548b00,$24448948,$89d8f740,$89482454,$893c2444,$eb20244c,$24a48d07,$00000000 f.$20=$4024448b,$1024443b,$00fc8d0f,$c0850000,$00f48c0f,$d2330000,$1c245439,$14245489,$00e48e0f,$5c890000,$2c8d1824,$00498d5b,$4824448b,$100cb60f,$840fc985,$000000a3 f.$30=$24245c3b,$00998d0f,$db850000,$00918c0f,$448b0000,$5c8b3c24,$448d1024,$af0fff18,$03c503c6,$83282444,$5a7440f9,$a297b60f,$0f000000,$af0f18b6,$0040bed1,$f12b0000 f.$40=$03deaf0f,$58b60fd3,$06fac101,$88deaf0f,$97b60f10,$000000a1,$03d1af0f,$06fac1d3,$0f015088,$00a097b6,$af0f0000,$48b60fd1,$ceaf0f02,$2c24748b,$fac1d103,$02508806 f.$50=$1424548b,$b60f1deb,$0000a28f,$0f088800,$00a18fb6,$48880000,$8fb60f01,$000000a0,$8b024888,$8318245c,$c38301c2,$03c58301,$1c24543b,$14245489,$18245c89,$ff2e8c0f f.$60=$6c8bffff,$5c8b3024,$6c013424,$01b84824,$29000000,$013c2444,$29402444,$0f202444,$fffedb85,$24548bff,$42bf0f44,$6c470110,$335d5e5f,$c4835bc0,$0014c228 pfnDrawGlyph = varptr(f) : return #deffunc ames str _string _str = _string + "\\n" mref bmscr, 67 pos_startx = ginfo_cx redrawSw = wpeek(bmscr, 78) redraw 0 dim vGlyphmetrics,5 : vMat2=$10000,0,0,$10000 dim vTextMetric,7 : GetTextMetrics hdc, varptr(vTextMetric) delay = stwait@hsp3util repeat strlen(_str) code = peek(_str, cnt) if IsZenkaku(code) { code = code<<8 | peek(_str, cnt+1) } if code=$0D { bmscr.68 = ginfo_cx - pos_startx, bmscr.32 pos pos_startx, ginfo_cy+bmscr.32 continue cnt+2 } GetGlyphOutline hdc, code, 6, vGlyphmetrics, 0, 0, vMat2 : _sz = stat sdim bmpbuffer, _sz GetGlyphOutline hdc, code, 6, vGlyphmetrics, _sz, varptr(bmpbuffer) , vMat2 prm = varptr(bmscr), varptr(vTextMetric), varptr(vGlyphmetrics), varptr(bmpbuffer), _sz ret = callfunc(prm,pfnDrawGlyph,5) if delay : redraw redrawSw : await delay : redraw 0 if code>256 : continue cnt+2 loop redraw redrawSw return #deffunc drawglyph int char mref bmscr, 67 dim vGlyphmetrics,5 : vMat2=$10000,0,0,$10000 dim vTextMetric,7 : GetTextMetrics hdc, varptr(vTextMetric) GetGlyphOutline hdc, char, 6, vGlyphmetrics, 0, 0, vMat2 : _sz = stat sdim bmpbuffer, _sz GetGlyphOutline hdc, char, 6, vGlyphmetrics, _sz, varptr(bmpbuffer) , vMat2 prm = varptr(bmscr), varptr(vTextMetric), varptr(vGlyphmetrics), varptr(bmpbuffer), _sz ret = callfunc(prm,pfnDrawGlyph,5) redraw wpeek(bmscr, 78) return #ifndef text@ #define global text(%1) stwait@hsp3util=%1 #endif #define global ames_cancel delay@mod_ames = 0 #global _init_ames_
// 各種さんぷる #include "ames.hsp" // アンチエイリアス文字描画 font "MS 明朝",40 // 必ずフォントを指定してください。 redraw 0 color 255,0,0 : mes "アンチエイリアス文字描画" color 0,0,255 : ames "アンチエイリアス文字描画" color 255,0,0 : pos 0,80 : mes "アンチ アス文字 " color 0,0,255 : pos 0,80 : ames " エイリ 描画" redraw 1 // 500回描いて速度測定。 // 結局のところ GetGlyphOutline が遅いので…… font "MS P明朝",28 #uselib "winmm.dll" #cfunc timeGetTime "timeGetTime" title "描画速度計測中..." redraw 0 st = timegettime() repeat 500 pos 0,160 ames "文字の描画速度計測♪" loop gt = timegettime() redraw 1 mes "" title "描画速度計測中... 完了 : "+(gt-st)+"ms." // ディレイキャンセルのサンプル。 font "MS P明朝",28 text 150 // ディレイを設定。 onclick gosub *c ames {"クリックするとディレイキャンセルします。 画面をクリックしてみてください。 残りの文字を一気に表示することができます。 ちなみに、このパソコンは"}+ ((gt-st)/5 )+{"マイクロ秒くらいで 28pxの文字を1文字、描画できるみたいです。"} stop *c ames_cancel return
/* ames.c */ #include <windows.h> #include "j:/program files/hsp30/hspsdk/sample/hsp3plugin.h" int WINAPI DrawGlyph(BMSCR *pBmscr, LPTEXTMETRIC lpTextMetric, LPGLYPHMETRICS lpGlyphMetrics, LPBYTE pbGryph, DWORD cbGryph) { LPBYTE pBitmap = pBmscr->pBit; LPBYTE pColor = (LPBYTE)&pBmscr->color; int sx = pBmscr->sx; int sxa = sx*3+3&~3; int sy = pBmscr->sy; int lx = lpGlyphMetrics->gmBlackBoxX; int lxa = lx+3&~3; int ly = lpGlyphMetrics->gmBlackBoxY; int ox = pBmscr->cx + lpGlyphMetrics->gmptGlyphOrigin.x; int oy = pBmscr->cy - lpGlyphMetrics->gmptGlyphOrigin.y + lpTextMetric->tmAscent; for(int y=0; y<ly; y++) { int py = oy+y; if(py >= sy || py < 0) continue; for(int x=0; x<lx; x++) { int blend = pbGryph[y*lxa+x]; if(blend == 0) continue; int px = ox+x; if(px >= sx || px < 0) continue; LPBYTE pPx = pBitmap + (sy-py-1)*sxa + px*3; if(blend != 64) { int invblend = 64-blend; pPx[0] = (pColor[2]*blend + pPx[0]*invblend); pPx[1] = (pColor[1]*blend + pPx[1]*invblend); pPx[2] = (pColor[0]*blend + pPx[2]*invblend); } else { pPx[0] = pColor[2]; pPx[1] = pColor[1]; pPx[2] = pColor[0]; } } } pBmscr->cx += lpGlyphMetrics->gmCellIncX; return 0; }