Uniscribe API
介绍
Uniscribe API
含有
DC
的函数,除了
ScriptTextOut
和
ScriptStringOut
考虑
DC
布局外(
RTL
布局和
LTR
布局下结果不一致),其余的函数一律不考虑
DC
布局(
RTL
布局和
LTR
布局下结果一致)。
HRESULT WINAPI ScriptApplyDigitSubstitution(
const SCRIPT_DIGITSUBSTITUTE *psds,
SCRIPT_CONTROL *psc,
SCRIPT_STATE *pss
);
函数功能:应用数字替换
参数描述:
psds
:
输入参数,该结构由函数
ScriptRecordDigitSubstitution
获得
psc:
输出参数,脚本控制结构
pss:
输出参数,脚本状态结构
函数存在的目的?
我们知道(或许不知道),这个世界上并不是只有
0123456789
可以表示数字的,还有像
阿拉伯文
的数字,在一定环境下我们希望数字能有特殊的显示效果。比如在阿拉伯国家(此时系统的缺省语言是阿拉伯语),我们在阿拉伯非数字字符后侧输入数字应该显示成阿拉伯本地的数字。
HESULT WINAPI ScriptApplyLogicalWidth(
const int *piDx,
int cChars,
int cGlyphs,
const WORD *pwLogClust,
const SCRIPT_VISATTR *psva,
const int *piAdvance,
const SCRIPT_ANALYSIS *psa,
ABC *pABC,
int *piJustify,
);
没用过。
HRESULT WINAPI ScriptBreak(
const WCHAR *pwcChars,
int cChars,
const SCRIPT_ANALYSIS *psa,
SCRIPT_LOGATTR *psla
);
函数功能:
返回当前文本的截断信息
参数描述:
pwcChars:
输入参数,需要获取信息的文本段
cChars:
输入参数,文本字符个数
psa:
输入参数,文本分析结果,由
ScriptItemize
函数获得
psla:
输出参数,文本截断信息
函数存在目的?
我们在使用记事本时如果单词在本行无法显示完全,需要换到下一行,我们更希望能够将整个单词换到下一行,而不是部分。因此我们需要能够分析在何处换行的函数。
HRESULT WINAPI ScriptCacheGetHeight(
HDC hdc,
SCRIPT_CACHE *psc,
long *tmHeight
);
函数功能:
获取当前缓存中字体的建议高度
参数描述:
hdc:
输入参数,
dc
psc:
输入参数,缓存,由
ScriptShape
函数获得
tmHeight:
输出参数,建议高度
函数存在目的?
我们计算输出文本的大小,这个函数可以计算文本的高度。
HRESULT WINAPI ScriptCPtoX(
int iCP,
BOOL fTrailing,
int cChars,
int cGlyphs,
const WORD *pwLogClust,
const SCRIPT_VISATTR *psva,
const int *piAdvance,
const SCRIPT_ANALYSIS *psa,
int *piX
);
函数功能:
计算字符的位置
参数描述:
icp:
输入参数,字符索引值
fTrailing:
输入参数,位置偏向性
cChars:
输入参数,字符个数
cGlyphs:
输入参数,字形个数
pwLogClust:
输入参数,簇标记数组
psva:
输入参数,字形属性数组
piAdvance:
输入参数,字形宽度
psa:
输入参数,本段文本块(
item
)分析结果,由
ScriptItemize
获得
piDx:
输出参数,字符的位置
函数存在目的?
我们必须知道当前光标的有效位置,使用这个函数可以计算出精确位置
函数如何实现?
这个函数是针对每一个
Item
而言的(
Item
详见
ScriptItemSize
函数),每个
Item
均是由若干个簇组成,位置的计算是根据簇,而不是单纯的根据字符宽度或字形宽度。
首先会判断该
Item
是否是
RTL
方向绘制的文本,假设是
RTL
;
接着计算
icp + fTrailing
在哪个簇内;
找到指定的簇之后,位置即为该簇的右侧(
此处可能存在特殊情况,因为阿拉伯组合字符允许光标定位在组合字符中间部位,而泰文等其他大多数组合字符不允许在中间出现光标
)。
例
1
:
فُضُلي
在
Arial Unicode MS
字体下,
文本绘制方向:
RTL
字符码值(按显示顺序,最前面是最后一个字符):
U+064a, U+
0644, U+
064f, U+
0636, U+064f, U+
0641
字形值:
6610 6592 1230 6560 1230 6579
字形宽度:
10 3 0 10 0 6
簇标记:
5 5 3 3 1 0
簇信息:
第一簇:
字符范围
[5]
字形范围
[0]
宽度
10
第二簇:
字符范围
[4]
字形范围
[1]
宽度
3
第三簇:
字符范围
[2,3]
字形范围
[2,3]
宽度
10
第四簇:
字符范围
[0,1]
字形范围
[4,5]
宽度
6
我们可以很确定第三簇和第四簇均是组合字符。
现在我们给定参数
iCP = 1
,
fTrailing = FALSE
,实际求取字符位置是索引值为
1
的字符位置。
按上面所讲规则,索引在第四簇内,则光标位置应该在第四簇的右侧(前提是
RTL
文本),所以光标的位置应该是
29
,但是因为阿拉伯文本的特殊性,允许组合字符中部出现光标,所以光标的位置实际是
26
。最后一簇含有两个字符,索引相对簇开始字符的偏移是
1-0=1
,占比是
1/2 = 50%,
所以距簇开始字符处的偏移为
50% * 6 = 3,
因此实际位置是
29 – 3 = 26
。
例
2
:
ฆูีฟิฟ
字体选用:
Tahoma
文本绘制方向:
LTR
字符码值:
U+0e06, U+0e39, U+0e35, U+0e1d, U+0e34, U+0e1d
字形值:
2109 2160 3232 2134 5444 2134
字形宽度:
9 0 0 8 0 8
簇标记:
0 0 0 3 3 5
簇信息:
第一簇:
字符范围
[0,2],
字形范围
[0,2],
宽度
9
第二簇:
字符范围
[3,4],
字形范围
[3,4],
宽度
8
第三簇:
字符范围
[5],
字形范围
[5],
宽度
9
我们可以很确定第一簇和第二簇均是组合字符。
我们给定参数
iCP = 1
,
fTrailing = FALSE
,实际求取字符位置是索引值为
1
的字符位置。
因为
1
在第一簇的范围内,所以位置在第一簇的左侧(前提是
LTR
文本),即
0
我们给定参数
iCP = 1
,
fTrailing = TRUE
,实际求取字符位置是索引值为
2
的字符位置。
因为
2
在第一簇的范围内,所以位置在第一簇的左侧,即
0
我们给定参数
iCP = 3
,
fTrailing = FALSE
,实际求取字符位置是索引值为
2
的字符位置。
因为
3
在第二簇的范围内,所以位置在第二簇的左侧,即
9.
如果实际求取字符索引值大于等于本
Item
的字符个数,则光标位置在最后一个簇的右侧,即
25
。
HRESULT WINAPI ScriptFreeCache(
SCRIPT_CACHE *psc
);
函数功能:
释放
Uniscribe
为每一个
Item
分配的字体缓存空间