using namespace std; #include "stdafx.h" #include <afxwin.h> #include <afxext.h> #include <afxdisp.h> #include <afxdtctl.h> #include <afxcmn.h> #include <iostream> #include "FontMaker_Cli.h" #include "resource.h" int CALLBACK EnumFontFamExProc(ENUMLOGFONTEX* lpelfe, NEWTEXTMETRICEX* lpntme, DWORD FontType, LPARAM lParam) {return 100;} static int UTF8ToUnicode(const char* input, WCHAR* output, int size) { return MultiByteToWideChar(CP_UTF8, 0, input, -1, output, size); } BOOL is_fontface_exists() { CFont font; if (font.CreatePointFont(12, m_cmd_parser.fontface)) { LOGFONTW lf{}; lf.lfCharSet = DEFAULT_CHARSET; wcscpy_s(lf.lfFaceName, min(LF_FACESIZE, m_cmd_parser.fontface.GetLength() + 1), m_cmd_parser.fontface.GetBuffer()); int iRet = EnumFontFamiliesExW(GetWindowDC(GetConsoleWindow()), &lf, (FONTENUMPROC)EnumFontFamExProc, (LPARAM)0, 0); font.DeleteObject(); return iRet == 100 ? TRUE : FALSE; } return FALSE; } void init_font() { if (!is_fontface_exists()) { wcout << L"无法找到指定的字体文件:" << m_cmd_parser.fontface.GetString() << endl; exit(1); } ZeroMemory(&log_font, sizeof(log_font)); lstrcpy(log_font.lfFaceName, m_cmd_parser.fontface); log_font.lfCharSet = DEFAULT_CHARSET; log_font.lfWeight = m_cmd_parser.font_weight; log_font.lfItalic = m_cmd_parser.font_itatlic; log_font.lfHeight = m_cmd_parser.font_size; if (m_hFont != NULL) {DeleteObject(m_hFont);} m_hFont = CreateFontIndirect(&log_font); m_bitfont.SetFont(m_hFont); m_bitfont.SetSize(m_cmd_parser.font_width, m_cmd_parser.font_height); m_bitfont.SetOffset(m_cmd_parser.font_offset_x, m_cmd_parser.font_offset_y); } BOOL set_charset(int resource_id) { m_charset.Delete(); HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(resource_id), L"CHARSET"); if (!hRsrc) {return false;} HGLOBAL hGlobal = LoadResource(NULL, hRsrc); if (!hGlobal) {return false;} LPVOID pResourceData = LockResource(hGlobal); if (!pResourceData) {return false;} DWORD dwSize = SizeofResource(NULL, hRsrc); if (0 == dwSize) {return false;} FreeResource(hGlobal); m_charset.CreateFromResource((LPCTSTR) pResourceData, dwSize); return true; } CString dedup_customized_file(WCHAR *buffer, int size) { int cnt; WCHAR ch; WCHAR *buf; CString text; text = CString(buffer); cnt = 0; buf = (WCHAR *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (size + 1) * sizeof(WCHAR)); if (buf == NULL) { wcout << L"内存不足!" << endl; return L""; } for (int i = 0; i < size; i++) { ch = text.GetAt(i); if (ch >= 0x20 && ch <= 0x7f) {continue;} if (wcschr(buf, ch) == NULL) { buf[cnt] = ch; cnt++; } } text = CString(buf); HeapFree(GetProcessHeap(), 0, buf); return text; } BOOL set_customized_charset(CString filename) { int len; UINT size; char *buffer; WCHAR *text; CString content; CFile cf; if (!cf.Open(filename, CFile::modeRead | CFile::shareDenyNone)) { wcout << L"无法打开文件!" << endl; return false; } size = (UINT) cf.GetLength(); buffer = (char *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size + 1); if (buffer == NULL) { cf.Close(); wcout << L"内存不足!" << endl; return false; } if (cf.Read(buffer, size) != size) { cf.Close(); HeapFree(GetProcessHeap(), 0, buffer); wcout << L"读取文件时发生错误!" << endl; return false; } cf.Close(); len = UTF8ToUnicode(buffer, NULL, 0) + 1; text = (WCHAR *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR)); if (text == NULL) { HeapFree(GetProcessHeap(), 0, buffer); wcout << L"内存不足!" << endl; return false; } len = UTF8ToUnicode(buffer, text, len); content = dedup_customized_file(text, len); len = content.GetLength(); CFile customized_index_table; if (!customized_index_table.Open(customized_index_table_filename, CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone)) { wcout << L"创建目标文件 " << customized_index_table_filename.GetString() << L" 失败!" << endl; exit(1); } customized_index_table.Write(content, len * 2); customized_index_table.Close(); m_charset.Delete(); m_charset.Create(content); HeapFree(GetProcessHeap(), 0, text); return true; } BOOL make_file(CString output_filename) { CFile file; if (!file.Open(output_filename, CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone)) { wcout << L"创建目标文件 " << output_filename.GetString() << L" 失败!" << endl; exit(1); } // scan - 0: 水平, 1: 垂直 // msb - 1: 高位在前, 0: 低位在前 // var - 0: 固定宽带, 1: 可变宽度 maker.MakeBinFile(&m_bitfont, &m_charset, &file, m_cmd_parser.scan_mode, m_cmd_parser.byte_order, m_cmd_parser.char_width); m_character_count += m_charset.GetCharCount(); file.Close(); wcout << L"保存文件 " << output_filename.GetString() << L" 成功" << endl; return true; } /* * 合并的文件包括: * 文件头 [24]: * [4] 文件标识符 - FMUX * [4] 文件大小 * [1] 字体宽高 * [2] 有效字符数量 * [1] 是否包含 GB2312 索引表 * [1] 扫描模式 * [1] 字节顺序 * [4] ASCII 字模起始地址 * [4] GB2312 字模起始地址 * [2] 保留字 * GB2312 索引表 * ASCII 字模数据 * GB2312 字模数据 */ BOOL combine_files() { CFile ascii_file, gb2312_file, customized_file, customized_index_table_file, combined_file; DWORD index_table_size, gb2312_data_size; LPVOID pResourceData = nullptr; if (m_cmd_parser.using_customized_cst) { if (!customized_file.Open(customized_output_filename, CFile::modeRead | CFile::shareDenyNone)) { wcout << customized_output_filename.GetString() << L" 文件不存在" << endl; exit(1); } if (!customized_index_table_file.Open(m_cmd_parser.input_customized_cst, CFile::modeRead | CFile::shareDenyNone)) { wcout << m_cmd_parser.input_customized_cst.GetString() << L" 文件不存在" << endl; exit(1); } gb2312_data_size = (DWORD) customized_file.GetLength(); index_table_size = (DWORD) customized_index_table_file.GetLength(); } else { if (!ascii_file.Open(ascii_output_filename, CFile::modeRead | CFile::shareDenyNone)) { wcout << ascii_output_filename.GetString() << L" 文件不存在" << endl; exit(1); } if (m_cmd_parser.using_customized_file) { if (!customized_file.Open(customized_output_filename, CFile::modeRead | CFile::shareDenyNone)) { wcout << customized_output_filename.GetString() << L" 文件不存在" << endl; exit(1); } if (!customized_index_table_file.Open(customized_index_table_filename, CFile::modeRead | CFile::shareDenyNone)) { wcout << customized_index_table_filename.GetString() << L" 文件不存在" << endl; exit(1); } gb2312_data_size = (DWORD) customized_file.GetLength(); index_table_size = (DWORD) customized_index_table_file.GetLength(); } else { if (!gb2312_file.Open(gb2312_output_filename, CFile::modeRead | CFile::shareDenyNone)) { wcout << gb2312_output_filename.GetString() << L" 文件不存在" << endl; exit(1); } HRSRC hRsrc = FindResource(NULL, MAKEINTRESOURCE(IDR_NEW_GB2312), L"CHARSET"); if (!hRsrc) {return false;} HGLOBAL hGlobal = LoadResource(NULL, hRsrc); if (!hGlobal) {return false;} pResourceData = LockResource(hGlobal); if (!pResourceData) {return false;} index_table_size = SizeofResource(NULL, hRsrc); if (0 == index_table_size) {return false;} FreeResource(hGlobal); gb2312_data_size = (DWORD) gb2312_file.GetLength(); } } if (!combined_file.Open(m_cmd_parser.output_file, CFile::modeCreate | CFile::modeReadWrite | CFile::shareDenyNone)) { wcout << L"创建目标文件 " << m_cmd_parser.output_file.GetString() << L" 失败!" << endl; exit(1); } PFL_Header header = (PFL_Header)malloc(sizeof(FL_Header)); header->magic[0] = 'F'; header->magic[1] = 'M'; header->magic[2] = 'U'; header->magic[3] = m_cmd_parser.using_customized_file || m_cmd_parser.using_customized_cst ? 'Y' : 'X'; DWORD length = FL_Header_Size + // 文件头大小 index_table_size + // 自定义或 GB2312 索引表大小 gb2312_data_size; // 自定义或 GB2312 字符数据大小 length += m_cmd_parser.using_customized_cst ? 0 : (DWORD) ascii_file.GetLength(); // ASCII 字符数据大小 header->file_size = length; header->font_height = m_cmd_parser.font_size; header->char_count = m_character_count; header->has_index_table = m_cmd_parser.has_index_table; header->scan_mode = m_cmd_parser.scan_mode; header->byte_order = m_cmd_parser.byte_order; header->ascii_start = FL_Header_Size + (m_cmd_parser.has_index_table ? index_table_size : 0); header->gb2312_start = m_cmd_parser.using_customized_cst ? FL_Header_Size + index_table_size : header->ascii_start + (DWORD) ascii_file.GetLength(); header->reserved[0] = '\0'; header->reserved[1] = '\0'; combined_file.Write(&header->magic, sizeof(header->magic)); combined_file.Write(&header->file_size, sizeof(header->file_size)); combined_file.Write(&header->font_height, sizeof(header->font_height)); combined_file.Write(&header->char_count, sizeof(header->char_count)); combined_file.Write(&header->has_index_table, sizeof(header->has_index_table)); combined_file.Write(&header->scan_mode, sizeof(header->scan_mode)); combined_file.Write(&header->byte_order, sizeof(header->byte_order)); combined_file.Write(&header->ascii_start, sizeof(header->ascii_start)); combined_file.Write(&header->gb2312_start, sizeof(header->gb2312_start)); combined_file.Write(&header->reserved, sizeof(header->reserved)); free(header); char* buffer; DWORD file_length; if (m_cmd_parser.using_customized_file || m_cmd_parser.using_customized_cst) { buffer = new char[index_table_size + 1]; buffer[index_table_size] = 0; customized_index_table_file.Read(buffer, index_table_size); combined_file.Write(buffer, index_table_size); } else { combined_file.Write(pResourceData, index_table_size); } if (!m_cmd_parser.using_customized_cst) { file_length = (DWORD) ascii_file.GetLength(); buffer = new char[file_length + 1]; buffer[file_length] = 0; ascii_file.Read(buffer, file_length); combined_file.Write(buffer, file_length); } buffer = new char[gb2312_data_size + 1]; buffer[gb2312_data_size] = 0; if (m_cmd_parser.using_customized_file || m_cmd_parser.using_customized_cst) { customized_file.Read(buffer, gb2312_data_size); } else { gb2312_file.Read(buffer, gb2312_data_size); } combined_file.Write(buffer, gb2312_data_size); if (m_cmd_parser.using_customized_cst) { customized_file.Close(); customized_index_table_file.Close(); } else { if (m_cmd_parser.using_customized_file) { customized_file.Close(); customized_index_table_file.Close(); } else { gb2312_file.Close(); } ascii_file.Close(); } combined_file.Close(); return true; } int main() { wcout.imbue(locale("CHS")); BOOL output_file_generated = false; m_cmd_parser.parse(); // m_cmd_parser.print_params(); init_font(); if (m_cmd_parser.using_customized_cst) { m_charset.LoadFromFile(m_cmd_parser.input_customized_cst); output_file_generated = make_file(customized_output_filename); } else { if (set_charset(IDR_ASCII)) { output_file_generated = make_file(ascii_output_filename); } if (m_cmd_parser.using_customized_file) { if (set_customized_charset(m_cmd_parser.input_customized_file)) { output_file_generated = make_file(customized_output_filename); } } else { if (set_charset(IDR_NEW_GB2312)) { output_file_generated &= make_file(gb2312_output_filename); } } } if (!output_file_generated) { wcout << L"创建字库文件失败" << endl; exit(1); } if (combine_files()) { wcout << L"创建字库文件 " << m_cmd_parser.output_file.GetString() << L" 成功" << endl; m_cmd_parser.print_params(); } if (m_cmd_parser.using_customized_cst) { DeleteFile(customized_output_filename); } else { DeleteFile(ascii_output_filename); if (m_cmd_parser.using_customized_file) { DeleteFile(customized_index_table_filename); DeleteFile(customized_output_filename); } else { DeleteFile(gb2312_output_filename); } } return 0; }