在做项目时,客户由于要求矢量字体,不得已研究下矢量字体,在此分享字库的制作
一.在vc6.0上安装freetype
a.向往http://download.savannah.gnu.org/releases/freetype/ 下载freetype安装包。
b.进入builds/文件夹下,在许多平台上都可以编译freetype.在这里选择win32\visualc\c.打开*.dsp文件,编译下,在freetype-2.4.0\objs\目录下会生成一个静态库文件freetype.lib和*.dll,在制作字库时会用的.
c.新建一个工程,拷贝freetype目录下include文件夹复制到自己工程中,把freetype.lib和freetype.dll文件拷贝到新建的工程中.
d.打开菜单project->settings->c/c++中,在category中选择preprocessor再添加指令文件的路径(如图1-2),选择Link项,在library modules:添加freetype.lib(如图1-1)
1-0
#include "ft2build.h"
#include FT_FREETYPE_H
void TestTrueType()
{
FT_Library m_pFTLib;
FT_Face m_pFTFace;
FT_Error error = FT_Init_FreeType(&m_pFTLib);
if(FT_New_Face(m_pFTLib, "C:/WINDOWS/Fonts/simkai.ttf", 0, &m_pFTFace))
{
return;
}
FT_Select_Charmap(m_pFTFace, FT_ENCODING_UNICODE);
FT_Set_Char_Size(m_pFTFace, 0, 12<<6, 300, 300);
// 此出将"A"改为汉字,则只显示出一个框;
error = FT_Load_Glyph(m_pFTFace, FT_Get_Char_Index(m_pFTFace, 'A'), FT_LOAD_DEFAULT);
// 第二个参数为渲染模式,这里渲染为1位位图(黑白位图),若为FT_RENDER_MODE_NORMAL则渲染为256级灰度图;
error = FT_Render_Glyph(m_pFTFace->glyph, FT_RENDER_MODE_NORMAL);
FT_Bitmap& bmp = m_pFTFace->glyph->bitmap;
int h = bmp.rows;
int w = bmp.width;
for(int i=0; i<h; i++)
{
for(int j=0; j<w; j++)
{
if((bmp.buffer[i * w + j]) == 0 ) {
printf("0");
}
else
{
printf("1");
}
}
printf("\n");
}
}
int main(int argc, char **argv)
{
TestTrueType();
return 0;
}
这里显示的是点阵字体,我们要做矢量字库。
二.在vc6.0上制作字库
网上关于矢量字体讲述很多这里不细说。
a.这里制作分别是英文字库和汉字字库(GB2312码)
b.关于字体,可以自己随便选择。
c.有时候制作矢量字体可能少了些笔画,需要程序相应的调整。
#include "ft2build.h"
//#include FT_FREETYPE_H
#include "freetype/freetype.h"
#include "freetype/ftglyph.h"
#include <graphics.h>
#include "Unicode.h"
#include <stdlib.h>
#include "testfont.h"
typedef unsigned short UINT16;
typedef short INT16;
typedef unsigned char UINT8;
typedef char INT8;
typedef unsigned int UINT32;
typedef int INT32;
#define GB_OFFSET_NUMBER 94 //the number of one GB zone.
#define GB_MIN_ZONE 0xA0 //min value of the zone number of GB code
#define GB_MAX_ZONE 0xF8 //max value of the zone number of GB code
#define GB_MIN_OFFSET 0xA1 //min value of the offset number of GB code
#define GB_MAX_OFFSET 0xFF //max value of the offset number of GB code
#define MAX_OFFSET_IN_TABLE 8272 //the max offset of the conversion table.
#define ENLISH_FONT 0
#define CHINA_FONT 1
#define MAX 50
UINT16 set_font_width = 0;
UINT16 set_font_higth = 0;
INT8 PATH_FONT_NAME[MAX];
UINT32 Ascender;
void initgr(void)
{
int gd = DETECT, gm = 0;
initgraph(&gd, &gm, "");
}
int writeAassicToFile( const char *file, const char *path)
{
FILE *fp = NULL;
FILE *fp1 =NULL;
FT_Library pFTLib = NULL;
FT_Face pFTFace = NULL;
FT_Glyph glyph;
FT_Error error = 0 ;
UINT8 buffer[4096];
UINT32 header[256];
UINT16 count = 0, assic_nu = 0, read_nu, i, j = 0, k;
UINT16 m, n;
UINT32 address = 0;
INT8 name[100];
UINT16 Font_w, Font_h;
UINT16 start_point = 0;
if( (fp = fopen(file, "wb")) == NULL ){
printf("fail open %s file!", file);
return 0;
}
#if 1
if( (fp1 = fopen("ASSIC_Info.txt", "w+")) == NULL ){
printf("fail open %s file!", file);
return 0;
}
#endif
if( FT_Init_FreeType( & pFTLib) ){
pFTLib = 0 ;
printf( " There is some error when Init Library " );
return - 1 ;
}
error = FT_New_Face(pFTLib, path , 0 , & pFTFace);
if( error ){
printf("fail open %s font file err num : %d \n", path, error);
return -1;
}
address = 1024; //存储字符码表的信息
FT_Set_Char_Size(pFTFace, set_font_width * 64 , set_font_higth*64, 72, 72);
Ascender = pFTFace->size->metrics.ascender >> 6;
printf("Vector font %s file running...\n", file);
for( k = 0x20; k < 128; k++)
{
FT_Load_Glyph(pFTFace, FT_Get_Char_Index(pFTFace, k), FT_LOAD_DEFAULT);
error = FT_Get_Glyph(pFTFace -> glyph, & glyph);
if(error){
printf("fail get %x data info\n", i);
return -1;
}
FT_Glyph_To_Bitmap( & glyph, ft_render_mode_normal, 0 , 1 );
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
FT_Bitmap &bitmap = bitmap_glyph -> bitmap;
if (bitmap_glyph->left < 0){
bitmap_glyph->left = 0;
}
header[k] = ((bitmap_glyph->left+bitmap.width)<< 24) | address;
Font_w = bitmap.width;
Font_h = bitmap.rows;// dy = Ascender-bitmap_glyph->top;
start_point = (Ascender- bitmap_glyph->top);//Ascender- bitmap_glyph->top
if (bitmap_glyph->top < bitmap.rows)
start_point -= (bitmap.rows - bitmap_glyph->top)/2 ;
for( m = 0; m < set_font_higth; ++m) //set_font_higth
{
for( n = 0; n < (bitmap.width+bitmap_glyph->left); ++ n){ //set_font_width
if(m < start_point) buffer[count++] = 0;
else if(m >= start_point +bitmap.rows) buffer[count++] = 0;
else{
if(n < bitmap_glyph->left)buffer[count++] = 0;
else if(n > bitmap_glyph->left+bitmap.width)buffer[count++] = 0;
else buffer[count++] = bitmap.buffer[(m - start_point) * bitmap.width + n -bitmap_glyph->left ];
}
}
}
fseek( fp, address, SEEK_SET);
read_nu = fwrite( buffer, count, 1, fp);
sprintf(name,"%c address:width: %d height :%d left:%d top:%d %x Ascender:%d\n", k, bitmap.width, bitmap.rows,bitmap_glyph->left,bitmap_glyph->top, address, Ascender);
fwrite(name, strlen(name), 1, fp1);
address += count;
count = 0;
FT_Done_Glyph(glyph);
glyph = NULL;
}
fclose(fp1);
fseek( fp, 0, SEEK_SET);
read_nu = fwrite( (UINT8 *)header, 1024, 1, fp);
fclose(fp);
printf("Generate complete vector fonts\n");
}
int writeHZToFile( const char *file, const char *path)
{
FILE *fp = NULL;
FILE *fp1 =NULL;
FT_Library pFTLib = NULL;
FT_Face pFTFace = NULL;
FT_Bitmap bitmap;
FT_Glyph glyph;
FT_Error error = 0 ;
UINT8 buffer[4096];
UINT32 header[256], dx, dy;
UINT32 count = 0, assic_nu = 0, read_nu, i, j = 0, k;
UINT32 m, n;
UINT32 address = 0;
UINT16 offset, ucs2_code;
INT8 name[100];
INT8 charbuff[3];
if( (fp = fopen(file, "wb")) == NULL ){
printf("fail open %s file!", file);
return 0;
}
#if 1
if( (fp1 = fopen("HZ_Info.txt", "w+")) == NULL ){
printf("fail open %s file!", file);
return 0;
}
#endif
if( FT_Init_FreeType( & pFTLib) ){
pFTLib = 0 ;
printf( " There is some error when Init Library " );
return - 1 ;
}
error = FT_New_Face(pFTLib, path , 0 , & pFTFace);
if( error ){ // //simhei.ttf
printf("fail open %s font file err num : %d \n", path, error);
return -1;
}//simfang.ttf
FT_Set_Char_Size(pFTFace, set_font_width * 64 , set_font_higth*64, 72, 72);
Ascender = pFTFace->size->metrics.ascender >> 6;
printf("start write data....\n Ascender:%d\n", Ascender);
address = 0;
printf("Vector font %s file running...\n", file);
for(i = GB_MIN_ZONE;i < GB_MAX_ZONE; i++ ){
for(j = GB_MIN_OFFSET;j < GB_MAX_OFFSET; j++ ){
charbuff[0] = i;
charbuff[1] = j;
charbuff[2] = '\0';
offset = (j - GB_MIN_OFFSET) + (i - GB_MIN_ZONE) * GB_OFFSET_NUMBER;
ucs2_code = (offset < MAX_OFFSET_IN_TABLE) ? gb2312_to_ucs2_table[offset] : 0x00;
FT_Load_Glyph(pFTFace, FT_Get_Char_Index(pFTFace, ucs2_code), FT_LOAD_DEFAULT);
if( (error = FT_Get_Glyph(pFTFace -> glyph, & glyph)) != 0){
printf("fail get %x data info\n", i);
return -1;
}
FT_Glyph_To_Bitmap( & glyph, ft_render_mode_normal, 0 , 1 );
FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph;
bitmap = bitmap_glyph ->bitmap;
// if (bitmap_glyph->left < 0){
// bitmap_glyph->left = 0;
// }
dy =Ascender - bitmap_glyph->top;//Ascender - bitmap_glyph->top
for( m = 0 ; m < set_font_higth; m++)
{
for( n = 0 ; n < set_font_width; n++)
{
if( m <= dy){
buffer[count] = 0;
}else if( m >= dy +bitmap.rows){
buffer[count] = 0;
}else {
if(n <= bitmap_glyph->left){
buffer[count] = 0;
}else if( n >= (bitmap_glyph->left + bitmap.width)){
buffer[count] = 0;
}else{
buffer[count] = bitmap.buffer[(m-dy) * bitmap.width + n-bitmap_glyph->left];
}
}
count++;
}
}
fseek( fp, address, SEEK_SET);
read_nu = fwrite( buffer, 1, count, fp);
sprintf(name,"%s address:width: %d height :%d left:%d top:%d %x Ascender:%d\n", charbuff, bitmap.width, bitmap.rows,bitmap_glyph->left,bitmap_glyph->top, address, Ascender);
fwrite(name, strlen(name), 1, fp1);
address += read_nu;
count = 0;
FT_Done_Glyph(glyph);
glyph = NULL;
}
}
fclose(fp1);
fclose(fp);
printf("Generate complete vector fonts\n");
}
int main(int argc, char* argv[])
{
char kind_font = 0;
char filename[50];
char i, buff[1];
char *path = "C:\\Windows\\Fonts\\simhei.ttf";//arial.ttf msyh.ttf simhei.ttf
initgr();
set_font_width =24;
set_font_higth = set_font_width;
kind_font = ENLISH_FONT;
if( kind_font == ENLISH_FONT){
sprintf(filename, "ASSIC_%d.bin", set_font_width);
printf("filename:%s\n", filename);
writeAassicToFile(filename, path);
displayAssic("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.,![]", filename, set_font_higth);
}else if( kind_font == CHINA_FONT ){
sprintf(filename, "HZ_%d.bin", set_font_width);
printf("filename:%s\n", filename);
writeHZToFile(filename, path);
displaystring("一二三四五六七八九十",filename, set_font_higth);
}
printf("font width %d height %d\n", set_font_width, set_font_higth);
getchar();
return 0;
}
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include "testfont.h"
#define RGBTranRGB565(x) ((((x) & 0xf80000) >> 19 << 11) | (((x)&0xfc00) >> 10 << 5) | (((x)&0xf8) >> 3)) & 0xffff //24位的RGB转化为RGB565十六位
UINT8 data[1024*4]; // 最大45号字体
UINT32 FontIndexTable[256];
void GetOneCharWidth(char *filename)
{ FILE *fp = NULL;
UINT16 len;
fp=fopen(filename, "rb");
len = fread( (UINT8 *)FontIndexTable,1 ,1024 ,fp );
// printf("read %s file head %d bytes!", filename, len);
fclose(fp);
return ;
}
int setcolor(UINT8 apha, UINT32 color ){
UINT16 temp;
UINT8 R, G, B;
UINT32 back_color = 0;
back_color = getbkcolor();
// printf("back_color:%x\n", back_color);
R = GetRValue(back_color) + (GetRValue(color) - GetRValue(back_color))*apha / 255;//( (color & 0xff) + ( (-color + WHITE) & 0xff) * apha / 255) & 0xff;
G = GetGValue(back_color) + (GetGValue(color) - GetGValue(back_color))*apha / 255;//( ((color >> 8)&0xff) + (( (-color + WHITE) >> 8)&0xff) *apha / 255) & 0xff;
B = GetBValue(back_color) + (GetBValue(color) - GetBValue(back_color))*apha / 255;//( ((color >> 16) &0xff) + (( (-color + WHITE) >> 16) &0xff) *apha / 255) & 0xff;
temp = B << 16 | G << 8 | R;
return temp;//RGBTranRGB565(temp)
}
void DisOneHZ(char *filename, int x, int y, int fontSize, char *hz){
UINT32 address = 0;
FILE *fp = NULL;
UINT16 read_byte_num, i, j;
UINT16 counter = 0;
address = ( ( (hz[0]&0xff) - 0xA0) * 94 + (hz[1] & 0xff) - 0xA1 )*fontSize*fontSize;
// printf("address:%x hz[0]: %x hz[1]:%x\n", address, hz[0], hz[1]);
if( (fp = fopen(filename, "rb")) == NULL ){
printf("fail open %s file\n", filename);
return ;
}
fseek(fp, address, SEEK_SET);
counter = fontSize*fontSize;
read_byte_num = fread(data, 1,counter, fp);
printf("from %s file read %d bytes\n", filename, read_byte_num);
for( i = y; i < fontSize + y; i++ ){
for( j = x; j < fontSize + x; j++ )
putpixel( j, i, setcolor( data[(i - y)*fontSize + (j - x)] , BROWN));
#if 0
if(data[(i - y)*fontSize + (j - x)]){//data[(i - y)*fontsize + (j - x)]){
printf("*");
}else{
printf("-");
}
#endif
}
fclose(fp);
}
void DisOneChar(int x, int y, int fontSize, UINT16 fontwidth, UINT8 c){
UINT16 i, j;
setcolor(WHITE);
rectangle(x - 2, y, x+fontwidth ,y + fontSize );
if( fontwidth > fontSize / 2){
printf("char ==> %c fontwidth:%d", c, fontwidth);
}
for( i = y; i < fontSize + y; i++ ){
for( j = x; j < fontwidth+ x; j++ ){
putpixel( j, i, setcolor( data[(i - y)*fontwidth + (j - x)] , LIGHTGREEN));
#if 0
if(data[(i - y)*fontwidth + (j - x)]){//data[(i - y)*fontsize + (j - x)]){
printf("*");
}else{
printf("-");
}
#endif
}
}
}
void displaystring(char *string, char *name, char size){
UINT32 i = 0, j = 0;
char temp[3];
while(*string){
if((*string)&0x80){
temp[0] = string[0];
temp[1] = string[1];
temp[2] = '\0';
DisOneHZ(name, i, j, size, temp);
i += size;
if(i > 25*24){
i = 0;
j += size;
}
printf("\n");
string += 2;
continue;
}
string += 1;
}
}
void displayAssic(char *str, char *name, char size)
{
char c = 0;
UINT16 i = 20, j = 20;
FILE *fp = NULL;
UINT32 charaddr, len;
int fontwidth;
GetOneCharWidth(name);
while(*str){
if( *str < 0x80 ){
c = *str;
if( (fp = fopen(name, "rb")) == NULL ){
printf("fail open %s file\n", name);
return ;
}
charaddr = FontIndexTable[c];
fontwidth = (charaddr>>24)&0xff;
charaddr &= 0x00ffffff;
fseek(fp, charaddr, SEEK_SET);
len = fread(data, 1, fontwidth*size, fp);
printf("read %s file %c size %d bytes!", name, c, len);
fclose(fp);
if( i + fontwidth > 480 ){
i = 20;
j += size;
}
DisOneChar(i, j, size, fontwidth, *str);
i += size;
}
str++;
}
}
测试英文显示如下图
测试汉字如下图
原代码已经上传到cdsn上
http://download.youkuaiyun.com/detail/wangyajietiegu/9542057