使用Uniscribe 处理复杂文本(二)
站长推荐:NSetup一键部署软件
一键式完成美化安装包制作,自动增量升级,数据统计,数字签名。应对各种复杂场景,脚本模块化拆分,常规复杂的脚本代码,图形化设置。无需专业的研发经验,轻松完成项目部署。(www.nsetup.cn)
Uniscribe 处理文本的简单分析
Uniscribe 实际上可以看成一个工厂,它的原料是字符串文本、Unicode 编码表、各国语言习惯以及字体,产品是字符对应的字形集合、字形的宽度、字形的偏移值。
例:
A..你好吗
处理过程可分为三步:
第一步:纯洁化文本段
根据语言环境将文本段分为属性单一的文本段,属性一般考虑某国语言字符、某国语言标点符号、控制字符、数字等,如A 是拉丁字符,.. 是拉丁标点符号你好吗是中文字符,所以可以分为三部分。
对应ScriptItemize 函数
第二部:字符字形化
对已经纯洁化的文本段进行字形化处理,需要考虑“语境具体化”,即根据上下文决定某些字符的具体字形,此外还要考虑“组合字符”中的一些不能被显示的字符处理(为其指定无法显示的字形)
对应ScriptShape 函数
第三部:字形宽度和偏移计算
此处必须充分考虑“组合字符”,决定寄生字符与宿主字符的位置关系
对应ScriptPlace函数
下面看一个简单的实例:
原料:
字符串 A..你好吗
字体 华文琥珀
产品:
字形 36,17,17,3337,2365,3162
字形宽度 34,22,22,58,58,58
字形偏移 均为0,没有组合字符
我们使用ExtTextOut 来测试结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[cce_cpp] CDC* pDC = GetDC(); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); ::GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf); lf.lfHeight = 60; _tcscpy_s(lf.lfFaceName, _T("华文琥珀")); CFont font; font.CreateFontIndirect( &lf ); CFont* pOldFont = pDC->SelectObject( &font ); TCHAR array[] = {36,17,17,3337,2365,3162}; ExtTextOut( pDC->GetSafeHdc(), 0, 0, ETO_GLYPH_INDEX, NULL, array, 6, NULL ); pDC->SelectObject( pOldFont ); font.DeleteObject(); [/cce_cpp] |
输出结果是
此结果与直接使用
ExtTextOut( pDC->GetSafeHdc(), 0, 0, ETO_GLYPH_INDEX, NULL, TEXT(“A..你好吗”), 6, NULL ) 基本一致。
下面来个复杂的例子:
ڡُabc
字体选用Tahoma
这个字符串包含了组合字符,RTL 文本,够复杂了吧,现在分步处理,
第一步处理结果如下:
文本段1:ڡُ
文本段2:abc
第二步处理结果如下:
ڡُ 的字形 757,806
因为是RTL 文本,所以757 是后一个字符的字形,806 是前一个字符的字形
abc 的字形是68,69,70
第三部处理结果如下:
757 字形宽度为0 偏移为x = 8 y = -10
806 字形宽度为44 偏移为0
68 字形宽度为26 偏移为0
69 字形宽度为28 偏移为0
70 字形宽度为23 偏移为0
使用ExtTextOut 测试代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
[cce_cpp] CDC* pDC = GetDC(); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); ::GetObject((HFONT)GetStockObject(DEFAULT_GUI_FONT), sizeof(lf), &lf); lf.lfHeight = 60; _tcscpy_s(lf.lfFaceName, _T("Tahoma")); CFont font; font.CreateFontIndirect( &lf ); CFont* pOldFont = pDC->SelectObject( &font ); TCHAR array[] = {757,806,68,69,70}; int iWidth[] = { 0, 44, 26, 28, 23 }; struct OFFSET { int x; int y; }; OFFSET offsets[] = { 8, -10, 0,0, 0,0, 0,0, 0,0, }; pDC->SetBkMode( TRANSPARENT ); // 先处理前两个字形,因为它们是文本属性相同的 int iStartX = 0; int iStartY = 50; // 第一个字形,但却是第二个字符,根据偏移值输出字形 ExtTextOut( pDC->GetSafeHdc(), iStartX + offsets[0].x, iStartY - offsets[0].y, ETO_GLYPH_INDEX, NULL, array, 1, NULL ); // 第二个字形,第一个字形宽度为0,无偏移 ExtTextOut( pDC->GetSafeHdc(), iStartX + iWidth[0], iStartY, ETO_GLYPH_INDEX, NULL, array + 1, 1, NULL ); // 处理后三个字形,因为偏移值均为0,所以一次性处理 ExtTextOut( pDC->GetSafeHdc(), iStartX + iWidth[0] + iWidth[1], iStartY, ETO_GLYPH_INDEX, NULL, array + 2, 3, NULL ); ExtTextOut( pDC->GetSafeHdc(), iStartX, 100, 0, NULL, TEXT( "ڡُabc" ), 5, NULL ); pDC->SelectObject( pOldFont ); font.DeleteObject(); [/cce_cpp] |
显示结果如下:
上面一个是测试代码的显示结果,下面一个是使用ExtTextOut( pDC->GetSafeHdc(), iStartX, 100, 0, NULL, TEXT( “ڡُabc” ), 5, NULL ) 函数输出的结果,可以看出两者基本一致。
学习日记,兼职软件设计,软件修改,毕业设计。
本文出自 学习日记,转载时请注明出处及相应链接。
本文永久链接: https://www.softwareace.cn/?p=300