精简Unicode,按unicode编码方式存储检索,又称为Simple Unicode。主要目的:极致优化检索表空间。
设置选项:Simple Unicode + Height Fixed
一 、分段图解
主要分4段:文件头,编码表,检索表,点阵信息。
补充说明:字符数决定编码表和检索表的大小。
适宜场景:编码不连续,且字符数少。
文件头结构体
/*针对 height fixed 存储格式*/
typedef struct gui_font_head_height_fixed{
BYTE magic[4]; //'S'('U'or ’M’), 'F', 'L', X---Unicode(or MBCS) Font Library, X: 表示版本号. 分高低4位。如 0x12表示 Ver 1.2
DWORD Size; // 文件大小
BYTE nSection; // 共分几段数据,主要针对 UNICODE 编码有效。
BYTE YSize; // 字体高度
WORD wCpFlag; // codepageflag: bit0~bit13 每个bit分别代表一个CodePage 标志,如果是1,则表示当前CodePage 被选定,否则为非选定。
WORD nTotalChars; // 总的字符数
BYTE ScanMode; // 扫描模式
BYTE bpp; // 位深度
} GUI_FONT_HEAD_HF, *PGUI_FONT_HEAD_HF;
要点:字体高度,字符数,扫描方式,位深度。
二、图例详解
1、文件头
说明:上图蓝色标记部分(16字节)为文件头。详解如下:
55 46 4C 12 - 标识头,判断是否为合法的字库文件。
53 = ‘S’,表示文件为Simple Unicode编码格式。
46 = ‘F’ , 4C = 'L'
12 表示该字库文件版本信息为 V1.2
20 6B 03 00 - 文件总长度。即文件长 = 0x00036B20
00 - 表示包含几个段。00则表示 0个段。
0C - 表示字体高度。 0C = 12,表示12像素。
02 00 - 表示当前字库包含了哪些字符集。
38 1D - 表示有效字符数。0x1D38 = 7480 个字符。
00 - 表示扫描模式(比对工具设置选项就明白了)
01 - 表示位深度 (参考值:1,2,4,8),bpp = 1
2、编码表
说明:蓝色标记部分为编码表数据。按小端字节序存放,升序排列,2个字节为1个编码。如 A4 00 A7 00 A8 00 ...,则表示第一个编码为 0x00A4,第二个编码为 0x00A7,第三个编码为 0x00A8,以此类推。
3、检索表
一条检索信息占4个字节,包含了字符宽度和点阵信息的起始偏移地址。检索信息结构体如下:
typedef struct tagUflCharInfo{
DWORD OffAddr : 26; // 当前字符点阵数据的起始地址
DWORD Width : 6; // 字符点阵的像素宽度( 目前最大支持点阵 < 64)
} UFL_CHAR_INDEX;
说明:高 6bit 记录字符宽度,低 26bit 记录点阵信息起始偏移地址。
4、点阵信息
当前字库中所有包含字符的点阵数据集合,数据存储方式与扫描方式有关,分横向,纵向,具体视情况而定。如:B3 1A, 即为 10110011 00011010,配合位深度,逐个处理即可。
三、参考代码
1、simple unicode.h
// unicode_simple.h
//
#if !defined(__FONT_UNICODE_SIMPLE_H__)
#define __FONT_UNICODE_SIMPLE_H__
#include "..includetypedef.h"
/***************************************
Func:读取编码列表,
Param:
nCodeNum:编码数量
dwHeadLen:文件头长度
Return:成功返回“0”, 否则返回“非0”.
****************************************/
int font_unicode_simple_read_codes(int nCodeNum, DWORD dwHeadLen);
// 释放编码列表相关内存
void font_unicode_simple_release_codes();
/***************************************
Func:定位字符,成功返回检索信息,否则返回0.
Param:
nCode:编码
dwHeadLen:文件头长度
Return:返回指定字符的偏移地址,若找到有效字符,则返回大于0的检索信息,否则返回0.
****************************************/
DWORD font_unicode_simple_find_char(WORD wCode, DWORD dwHeadLen);
#endif // (__FONT_UNICODE_SIMPLE_H__)
2、simple unicode.c
/***********************************************************
描述:用c语言写的一个如何从unicode编码格式的点阵字库中读取字符信息(像素宽 +点阵信息)
至于容错性和效率方面还得使用者自行改善。谢谢您的参阅!
作者:wujianguo
日期:20090516
MSN: wujianguo19@hotmail.com
qq:9599598
*************************************************************/
#include "..includefont.h"
#include "..includefont_file.h"
#include "..include?de_simple.h"
#ifdef WIN32
#include
#include
#endif
#define MAX_FIND_LIMIT 31 // 是否二分查找临界值
static int g_nCodeNum = 0;
WORD *g_pCodes = NULL;
// 读取编码列表
int font_unicode_simple_read_codes(int nCodeNum, DWORD dwHeadLen)
{
font_unicode_simple_release_codes();
g_nCodeNum = nCodeNum;
g_pCodes = (WORD *)malloc(nCodeNum*sizeof(WORD));
if(g_pCodes == NULL)
{
printf("Malloc is fail!
");
return -1;
}
font_file_seek(dwHeadLen);
font_file_read(g_pCodes, nCodeNum*sizeof(WORD));
return 0;
}
// 释放动态分配的内存
void font_unicode_simple_release_codes()
{
if(g_pCodes != NULL)
{
free(g_pCodes);
g_pCodes = NULL;
}
}
// 定位编码位置,若找到返回 >= 0的值,否则返回 -1.
int font_unicode_simple_find_code(WORD wCode)
{
if(g_nCodeNum > 0)
{
if(g_nCodeNum > MAX_FIND_LIMIT) // 二分查找
{
int low, high, mid;
low = 0;
high = g_nCodeNum -1;
while(low <= high)
{
mid = (high + low)/2;
if(g_pCodes[mid] == wCode)
return mid;
else if(wCode > g_pCodes[mid])
low = mid + 1;
else
high = mid - 1;
}
}
else // 顺序查找
{
int i = 0;
for(i = 0; i < g_nCodeNum; i++)
{
if(wCode == g_pCodes[i])
return i;
}
}
}
return -1;
}
// 根据编码获取检索信息
DWORD font_unicode_simple_find_char(WORD wCode, DWORD dwHeadLen)
{
DWORD offset = 0;
DWORD dwCharInfo = 0;
int nIdx = font_unicode_simple_find_code(wCode);
if(nIdx == -1) // 未找到该编码
return 0;
offset = dwHeadLen + g_nCodeNum * 2 + nIdx * 4; //dwHeadLen:文件头长度;g_nCodeNum * 2: 编码表长度;nIdx*4:检索表偏移
printf("offset = 0x%X
", offset);
font_file_seek(offset);
font_file_read(&dwCharInfo, sizeof(DWORD));
return dwCharInfo;
}