精简Unicode,按unicode编码方式存储检索,又称为Simple Unicode。主要目的:极致优化检索表空间

设置选项:Simple Unicode + Height Fixed

bin是什么格式的文件(BIN格式文件图文详解一)(1)

一 、分段图解

主要分4段:文件头编码表检索表点阵信息

bin是什么格式的文件(BIN格式文件图文详解一)(2)

补充说明:字符数决定编码表和检索表的大小。

适宜场景:编码不连续,且字符数少

文件头结构体

/*针对 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、文件头

bin是什么格式的文件(BIN格式文件图文详解一)(3)

说明:上图蓝色标记部分(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、编码表

bin是什么格式的文件(BIN格式文件图文详解一)(4)

说明:蓝色标记部分为编码表数据。按小端字节序存放,升序排列,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 "..\include\typedef.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 "..\include\font.h"
#include "..\include\font_file.h"
#include "..\include\unicode_simple.h"    


#ifdef WIN32
#include <stdio.h>
#include <stdlib.h>
#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!\n");
    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\n", offset);
  font_file_seek(offset);
  font_file_read(&dwCharInfo, sizeof(DWORD));  


  return dwCharInfo;
}