Pau*_*aul 4 delphi unicode fonts range
我想获得Unicode字体字形范围(Delphi 6):
var GS:PGlyphSet;
GSSize:LongWord;
rng:TWCRange;
begin
GSSize := GetFontUnicodeRanges(Canvas.Handle, nil);
GetMem(Pointer(GS), GSSize);
try
GS.cbThis:=GSSize;
GS.flAccel:=0;
GS.cGlyphsSupported:=0;
GS.cRanges:=0;
if GetFontUnicodeRanges(Canvas.Handle, GS)<>0 then begin
for i:=0 to GS.cRanges-1 do begin
rng := GS.ranges[i];
Run Code Online (Sandbox Code Playgroud)
奇怪的是它Length(GS.ranges)是1,但GS.cRanges是309,当我尝试访问第二个范围时,GS.ranges[1]我得到的当然是范围检查错误.在我开启范围检查之前,它已经以某种神奇的方式运作.
供参考的类型(来自Windows模块):
PWCRange = ^TWCRange;
{$EXTERNALSYM tagWCRANGE}
tagWCRANGE = packed record
wcLow: WCHAR;
cGlyphs: SHORT;
end;
TWCRange = tagWCRANGE;
PGlyphSet = ^TGlyphSet;
{$EXTERNALSYM tagGLYPHSET}
tagGLYPHSET = packed record
cbThis: DWORD;
flAccel: DWORD;
cGlyphsSupported: DWORD;
cRanges: DWORD;
ranges: array[0..0] of TWCRange;
end;
TGlyphSet = tagGLYPHSET;
Run Code Online (Sandbox Code Playgroud)
这个结构使用了所谓的struct hack:
该ranges成员是一个可变长度数组,内嵌在结构中.但是你无法在静态C类型中实际编码.这就是为什么你调用函数来找出要分配多少内存,然后堆分配结构.如果你在堆栈上分配它,或者使用SizeOf(...)那么结构将太小.
最简单的方法是禁用访问代码的范围检查ranges.虽然类型声明说只有0一个有效的索引ranges,实际上0..cRanges-1是有效的.
如果您不想禁用相关代码的范围检查,则将指针指向元素0,然后在循环中使用指针算法.
var
rng: PWCRange;
....
rng := @GS.ranges[0];
for i:=0 to GS.cRanges-1 do begin
// use rng^
inc(rng);
end;
Run Code Online (Sandbox Code Playgroud)
在我看来,这是编写顺序访问代码的最简洁方法.对于随机访问,并且有效范围检查,您将被迫声明一些额外的类型以阻止范围检查:
type
TWCRangeArray = array [0..(MaxInt div SizeOf(TWCRange))-1] of TWCRange;
PWCRangeArray = ^TWCRangeArray;
Run Code Online (Sandbox Code Playgroud)
然后使用类型转换来访问各个元素:
rng := PWCRangeArray(@GS.ranges)[i];
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
376 次 |
| 最近记录: |