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;
}