#ifndef __FONT_H__
#define __FONT_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif
#define DBG(fmt...) do\
{\
printf("%s: %d: ", __FUNCTION__, __LINE__);\
printf(fmt);\
}while(0)
#define CHECK(exp, ret, fmt...) do\
{\
if (!(exp))\
{\
DBG(fmt);\
return ret;\
}\
}while(0)
#define MAX_FONT_NUM 128
typedef struct
{
int reference;
int enc_len;
unsigned char enc[2];
int font_size;
int row;
int col;
unsigned char* array;
}font_s;
int font_init();
int font_exit();
int font_add(const unsigned char* enc, int len, char* src, int row, int col, int font_size);
font_s* font_get(const unsigned char* enc, int len, int font_size);
int font_release(font_s* font);
int font_get_num();
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
#include
#include
#include
#include
#include
#include
#include "font.h"
typedef struct
{
int valid_num;
font_s font[MAX_FONT_NUM];
}font_mgr_s;
static font_mgr_s font_mgr;
static int font_get_idle()
{
int index = -1;
unsigned int i = 0;
for (i = 0; i < MAX_FONT_NUM; i++)
{
if (font_mgr.font[i].enc_len == 0)
{
index = i;
break;
}
}
CHECK(i < MAX_FONT_NUM, -1, "failed to found idle node.max: %d\n", MAX_FONT_NUM);
return index;
}
static int font_clear()
{
unsigned int i = 0;
for (i = 0; i < MAX_FONT_NUM; i++)
{
if (font_mgr.font[i].reference == 0)
{
if (font_mgr.font[i].array)
{
free(font_mgr.font[i].array);
}
memset(&font_mgr.font[i], 0, sizeof(font_s));
font_mgr.valid_num--;
}
}
DBG("font lib clear ok\n");
return 0;
}
int font_add(const unsigned char* enc, int len, char* src, int row, int col, int font_size)
{
int ret = -1;
int index = font_get_idle();
if (-1 == index)
{
ret = font_clear();
CHECK(ret == 0, -1, "error with %#x\n", ret);
index = font_get_idle();
CHECK(index >= 0, -1, "error with %#x\n", ret);
}
font_mgr.font[index].enc_len = len;
memcpy(font_mgr.font[index].enc, enc, len);
font_mgr.font[index].row = row;
font_mgr.font[index].col = col;
font_mgr.font[index].font_size = font_size;
font_mgr.font[index].array = (unsigned char*)malloc(row*col);
CHECK(font_mgr.font[index].array, -1, "failed to malloc %d bytes\n", row*col);
memcpy(font_mgr.font[index].array, src, row*col);
font_mgr.valid_num++;
return 0;
}
int font_init()
{
memset(&font_mgr, 0, sizeof(font_mgr));
return 0;
}
int font_exit()
{
unsigned int i = 0;
for (i = 0; i < MAX_FONT_NUM; i++)
{
if (font_mgr.font[i].array)
{
free(font_mgr.font[i].array);
memset(&font_mgr.font[i], 0, sizeof(font_s));
}
}
return 0;
}
font_s* font_get(const unsigned char* enc, int len, int font_size)
{
unsigned int i = 0;
for (i = 0; i < MAX_FONT_NUM; i++)
{
if (font_mgr.font[i].enc_len == len && font_mgr.font[i].font_size == font_size)
{
if (!memcmp(font_mgr.font[i].enc, enc, len))
{
font_mgr.font[i].reference++;
return &font_mgr.font[i];
}
}
}
return NULL;
}
int font_release(font_s* font)
{
unsigned int i = 0;
for (i = 0; i < MAX_FONT_NUM; i++)
{
if (font_mgr.font[i].enc_len == font->enc_len && font_mgr.font[i].font_size == font->font_size)
{
if (!memcmp(font_mgr.font[i].enc, font->enc, font->enc_len))
{
font_mgr.font[i].reference--;
if (font_mgr.font[i].reference < 0)
{
font_mgr.font[i].reference = 0;
}
return 0;
}
}
}
return -1;
}
int font_get_num()
{
return font_mgr.valid_num;
}
#ifndef __BITMAP_H__
#define __BITMAP_H__
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif
#define FORE_GROUND 'X'
#define BACK_GROUND '-'
#define FONT_EDGE 'o'
#define MAX_LINE_NUM 20
#define MAX_LINE_PLL 100
typedef struct
{
int row;
int col;
char* bit_map;
}result_s;
int bitmap_create(const char* hz_path, int is_gbk, const char* asc_path);
int bitmap_destroy();
int bitmap_alloc(const unsigned char* chs, int font_size, int edge_enable, int gap, result_s* result);
int bitmap_free(result_s* result);
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif
#endif
#include
#include
#include
#include
#include
#include "font.h"
#include "bitmap.h"
typedef struct tag_bitmap_s
{
int inited;
int gbk;
char hz16x16[32];
FILE* hz_fp;
char asc16x8[32];
FILE* asc_fp;
}bitmap_s;
static bitmap_s bitmap;
static int bitmap_read_hzk16(const unsigned char *s, char* chs)
{
int ret = -1;
int size = 32;
unsigned long offset = ((s[0]-0xa1)*94+(s[1]-0xa1))*size;
ret = fseek(bitmap.hz_fp, offset, SEEK_SET);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
ret = fread(chs, 1, size, bitmap.hz_fp);
CHECK(ret == size, -1, "error: read %d bytes, expect %d bytes\n", ret, size);
return 0;
}
static int bitmap_read_gbk16(const unsigned char *s, char* chs)
{
int ret = -1;
int size = 32;
int qh = s[0] - 0x81;
int wh = (s[1] < 0x7f) ? (s[1] - 0x40) : (s[1] - 0x41);
unsigned long offset=(qh*190+wh)*size;
ret = fseek(bitmap.hz_fp, offset, SEEK_SET);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
ret = fread(chs, 1, size, bitmap.hz_fp);
CHECK(ret == size, -1, "error: read %d bytes, expect %d bytes\n", ret, size);
return 0;
}
static int bitmap_read_asc16(const unsigned char *s, char* asc)
{
int ret = -1;
int size = 16;
unsigned long offset=s[0]*size;
ret = fseek(bitmap.asc_fp, offset,SEEK_SET);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
ret = fread(asc,1,size, bitmap.asc_fp);
CHECK(ret == size, -1, "error: read %d bytes, expect %d bytes\n", ret, size);
return 0;
}
static int bitmap_show_str(const char* p, int row, int col)
{
int i = 0;
for (i = 0; i < row*col; i++)
{
if (i%col == 0)
{
printf("\n");
}
printf("%c", p[i]);
}
printf("\n\n");
return 0;
}
static int bitmap_show_hex(const unsigned char* begin)
{
int len = strlen((const char*)begin);
int i = 0;
for (i = 0; i < len; i++)
{
printf("%02x ", begin[i]);
}
printf("\n");
return 0;
}
static int bitmap_bit2char(const char* chs, int size, char* font)
{
int i = 0;
int j = 0;
int idx = 0;
for (i = 0; i < size; i++)
{
for (j = 7; j >= 0; j--)
{
if (chs[i]&(0x1<else
{
font[idx++] = BACK_GROUND;
}
}
}
return 0;
}
static int bitmap_add_edge(const char* src, int row, int col, char* dst)
{
row += 2;
col += 2;
memset(dst, BACK_GROUND, row*col);
int i = 0;
int j = 0;
int k = 0;
for (i = 1; i < row-1; i++)
{
for (j = 1; j < col-1; j++)
{
int idx = i*col+j;
dst[idx] = src[k++];
}
}
for (i = 1; i < row-1; i++)
{
for (j = 1; j < col-1; j++)
{
int idx = i*col+j;
if (dst[idx] == FORE_GROUND)
{
int top_idx = idx - col;
int bottom_idx = idx + col;
int left_idx = idx - 1;
int right_idx = idx + 1;
dst[top_idx] = (dst[top_idx] == FORE_GROUND) ? FORE_GROUND : FONT_EDGE;
dst[top_idx-1] = (dst[top_idx-1] == FORE_GROUND) ? FORE_GROUND : FONT_EDGE;
dst[top_idx+1] = (dst[top_idx+1] == FORE_GROUND) ? FORE_GROUND : FONT_EDGE;
dst[bottom_idx] = (dst[bottom_idx] == FORE_GROUND) ? FORE_GROUND : FONT_EDGE;
dst[bottom_idx-1] = (dst[bottom_idx-1] == FORE_GROUND) ? FORE_GROUND : FONT_EDGE;
dst[bottom_idx+1] = (dst[bottom_idx+1] == FORE_GROUND) ? FORE_GROUND : FONT_EDGE;
dst[left_idx] = (dst[left_idx] == FORE_GROUND) ? FORE_GROUND : FONT_EDGE;
dst[right_idx] = (dst[right_idx] == FORE_GROUND) ? FORE_GROUND : FONT_EDGE;
}
}
}
return 0;
}
static int bitmap_font_scale(char* src, int row, int col, char* dst, int font_size)
{
int i = 0;
int j = 0;
int m = 0;
int n = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
char c = src[i*col+j];
int x = i*font_size;
int y = j*font_size;
int dst_col = col*font_size;
int idx = x*dst_col+y;
for (m = idx; m < idx+font_size*dst_col; m += dst_col)
{
for (n = 0; n < font_size; n++)
{
dst[m+n] = c;
}
}
}
}
return 0;
}
static int bitmap_draw(font_s** sentence, int num, char* dst, int row, int col)
{
int i = 0;
int j = 0;
char* begin = dst;
int offset[MAX_LINE_PLL];
memset(offset, 0, sizeof(offset));
int total_col = 0;
for (i = 0; i < row; i++)
{
total_col = 0;
for (j = 0; j < num; j++)
{
if (!sentence[j])
{
if (total_col < col)
{
memset(begin, BACK_GROUND, col-total_col);
begin += col-total_col;
}
break;
}
memcpy(begin, sentence[j]->array+offset[j], sentence[j]->col);
offset[j] += sentence[j]->col;
begin += sentence[j]->col;
total_col += sentence[j]->col;
}
}
return 0;
}
static int bitmap_get_info(font_s** sentence, int total, int* size)
{
int i = 0;
int num = 0;
int sum = 0;
for (i = 0; i < total; i++)
{
if (!sentence[i])
{
break;
}
sum += sentence[i]->row * sentence[i]->col;
num++;
}
*size = sum;
return 0;
}
static int bitmap_font_add(const unsigned char* chs, int len, int font_size, int edge_enable)
{
int ret = -1;
char tmp[32];
memset(tmp, 0, sizeof(tmp));
char* out = NULL;
char font16x16[16*16];
char font16x8[16*8];
char* base_font = NULL;
int base_row = 16;
int base_col = 16;
if (len == 2)
{
base_font = font16x16;
ret = (bitmap.gbk) ? bitmap_read_gbk16(chs, tmp) : bitmap_read_hzk16(chs, tmp);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
ret = bitmap_bit2char(tmp, base_row*len, base_font);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
}
else if (len == 1)
{
base_col = 8;
base_font = font16x8;
ret = bitmap_read_asc16(chs, tmp);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
ret = bitmap_bit2char(tmp, base_row*len, base_font);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
}
else
{
printf("Unknow len: %d\n", len);
return -1;
}
int row = base_row*font_size;
int col = base_col*font_size;
char* fontWxH = (char*)malloc(row*col);
CHECK(fontWxH, -1, "failed to malloc %d bytes\n", row*col);
ret = bitmap_font_scale(base_font, base_row, base_col, fontWxH, font_size);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
out = fontWxH;
char* fontWxH_edge = NULL;
if (edge_enable)
{
row += 2;
col += 2;
fontWxH_edge = (char*)malloc(row*col);
CHECK(fontWxH_edge, -1, "failed to malloc %d bytes\n", row*col);
ret = bitmap_add_edge(fontWxH, row-2, col-2, fontWxH_edge);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
out = fontWxH_edge;
}
ret = font_add(chs, len, out, row, col, font_size);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
free(fontWxH_edge);
free(fontWxH);
return ret;
}
static int bitmap_font_get(const unsigned char* chs, int font_size, int edge_enable, font_s** sentence)
{
int ret = -1;
const unsigned char* begin = chs;
int len = strlen((const char*)chs);
int idx = 0;
while (len > 0)
{
int enc_len = 1;
if (*begin > 0x80)
{
enc_len = 2;
}
font_s* _font = font_get(begin, enc_len, font_size);
if (!_font)
{
ret = bitmap_font_add(begin, enc_len, font_size, edge_enable);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
_font = font_get(begin, enc_len, font_size);
CHECK(_font, -1, "Error: null pointer\n");
}
sentence[idx++] = _font;
begin += enc_len;
len -= enc_len;
}
return 0;
}
static int bitmap_font_release(font_s** sentence, int total)
{
int ret = -1;
int i = 0;
for (i = 0; i < total; i++)
{
if (!sentence[i])
{
break;
}
ret = font_release(sentence[i]);
CHECK(ret == 0, -1, "error with %#x\n", ret);
}
return 0;
}
static int bitmap_parse_line(unsigned char* src, int* maxlen, int* linecnt)
{
unsigned char* begin = (unsigned char*)src;
int linelen[MAX_LINE_NUM];
int max_line_len = 0;
int linecount = 0;
unsigned char *line_begin = (unsigned char*)src;
while (*begin)
{
if (*begin == '^')
{
linelen[linecount] = begin - line_begin;
if (max_line_len < linelen[linecount])
{
max_line_len = linelen[linecount];
}
linecount++;
line_begin = begin + 1;
}
begin++;
}
linelen[linecount] = strlen((const char*)line_begin);
if(max_line_len < linelen[linecount])
max_line_len = linelen[linecount];
linecount++;
*maxlen = max_line_len;
*linecnt = linecount;
return 0;
}
static int bitmap_get_matrix(unsigned char* src, unsigned char* dst, int* maxlen, int* linecnt)
{
int ret = -1;
ret= bitmap_parse_line(src, maxlen, linecnt);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
int size = (*maxlen)*(*linecnt);
memset(dst, ' ', size);
char* s_begin = (char*)src;
char* d_begin = (char*)dst;
char* find = NULL;
do
{
find = strstr((char*)s_begin, "^");
if (find)
{
memcpy(d_begin, s_begin, find-s_begin);
find++;
s_begin = find;
d_begin += (*maxlen);
}
else
{
memcpy(d_begin, s_begin, strlen(s_begin));
}
}while(find);
return 0;
}
int bitmap_create(const char* hz_path, int is_gbk, const char* asc_path)
{
CHECK(hz_path, -1, "Error with %p\n", hz_path);
CHECK(asc_path, -1, "Error with %p\n", asc_path);
CHECK(!bitmap.inited, -1, "Error with %#x\n", bitmap.inited);
int ret = -1;
memset(&bitmap, 0, sizeof(bitmap));
bitmap.gbk = (is_gbk) ? 1 : 0;
strcpy(bitmap.hz16x16, hz_path);
bitmap.hz_fp = fopen(hz_path, "r");
CHECK(bitmap.hz_fp, -1, "failed to open %s: %s\n", hz_path, strerror(errno));
strcpy(bitmap.asc16x8, asc_path);
bitmap.asc_fp = fopen(asc_path, "r");
CHECK(bitmap.asc_fp, -1, "failed to open %s: %s\n", asc_path, strerror(errno));
ret = font_init();
CHECK(ret == 0, -1, "Error with %#x\n", ret);
bitmap.inited = 1;
return 0;
}
int bitmap_destroy()
{
CHECK(bitmap.inited, -1, "Error with %#x\n", bitmap.inited);
int ret = -1;
if (bitmap.hz_fp)
{
fclose(bitmap.hz_fp);
bitmap.hz_fp = NULL;
}
if (bitmap.asc_fp)
{
fclose(bitmap.asc_fp);
bitmap.asc_fp = NULL;
}
ret = font_exit();
CHECK(ret == 0, -1, "Error with %#x\n", ret);
return 0;
}
int bitmap_alloc(const unsigned char* chs, int font_size, int edge_enable, int gap, result_s* result)
{
CHECK(bitmap.inited, -1, "Error with %#x\n", bitmap.inited);
int ret = -1;
memset(result, 0, sizeof(*result));
int linecnt = 0;
int maxlen = 0;
unsigned char dst[MAX_LINE_NUM*MAX_LINE_PLL+1];
memset(dst, 0, sizeof(dst));
ret = bitmap_get_matrix((unsigned char*)chs, dst, &maxlen, &linecnt);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
font_s* sentence[MAX_LINE_NUM][MAX_LINE_PLL];
memset(sentence, 0, sizeof(sentence));
int i = 0;
unsigned char tmp[MAX_LINE_PLL+1];
unsigned char* d_begin = dst;
int max_col = 0;
for (i = 0; i < linecnt; i++)
{
memset(tmp, 0, sizeof(tmp));
memcpy(tmp, d_begin, maxlen);
d_begin += maxlen;
ret= bitmap_font_get(tmp, font_size, edge_enable, sentence[i]);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
int size = 0;
ret = bitmap_get_info(sentence[i], MAX_LINE_PLL, &size);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
int col = size/sentence[i][0]->row;
if (max_col < col)
{
max_col = col;
}
}
result->row = sentence[0][0]->row*linecnt + (linecnt-1)*gap;
result->col = max_col;
result->bit_map = (char*)malloc(result->row*result->col);
CHECK(result->bit_map, -1, "failed to malloc %d bytes\n", result->row*result->col);
char* begin = result->bit_map;
for (i = 0; i < linecnt; i++)
{
ret = bitmap_draw(sentence[i], MAX_LINE_PLL, begin, sentence[i][0]->row, result->col);
CHECK(ret == 0, -1, "Error with %#x\n", ret);
begin += sentence[i][0]->row*result->col;
if (i < linecnt-1)
{
memset(begin, BACK_GROUND, result->col*gap);
begin += result->col*gap;
}
ret = bitmap_font_release(sentence[i], MAX_LINE_PLL);
CHECK(ret == 0, -1, "error with %#x\n", ret);
}
return 0;
}
int bitmap_free(result_s* result)
{
CHECK(bitmap.inited, -1, "Error with %#x\n", bitmap.inited);
if (result->bit_map)
{
free(result->bit_map);
}
return 0;
}
int bitmap_demo()
{
bitmap_create("gbk.dzk", 1, "asc16.dzk");
const unsigned char chs[] = "我们";
bitmap_show_hex(chs);
result_s result;
memset(&result, 0, sizeof(result));
bitmap_alloc(chs, 1, 0, 8, &result);
bitmap_show_str(result.bit_map, result.row, result.col);;
bitmap_free(&result);
bitmap_destroy();
return 0;
}
int main()
{
bitmap_demo();
return 0;
}
..
----------------------------
-------------------------
--------------------
--------------------------
---------------------------
-------------
--------------------------
-------------------------
------------------------
-------------------------
-------------------------
------------------------
-------------------------
-------------------------
----------------------
---------------------------