// /* * Source : mp3_14_hc_font.cpp * Date : 2020/08/14 * Update : * Comment : mp3_14_hc用フォントファイル作成 * FONTXをコードブロックテーブルなしで構成。ビットの並びをLCDに合うように並べ替え。半角・全角を1ファイルにまとめる。 */ #define _CRT_SECURE_NO_WARNINGS #include #include #include #include #include #include #include #include #include #define FONT_FILE_ZEN_16_16 _T("MYRCZ16B.FNT") #define FONT_FILE_HAN_8_16 _T("MYRCH16B.FNT") #define FONT_FILE_MP3_14_HC _T("MP314HC.FNT") // 出力ファイル #define BYTES_PER_HAN_OUTFILE 16 // 出力ファイル中の1文字あたりのバイト数(半角) #define BYTES_PER_ZEN_OUTFILE 32 // 出力ファイル中の1文字あたりのバイト数(全角) typedef struct _FontMetricsBlock { unsigned short StartCode; // 開始コード(SJIS文字コード) unsigned short EndCode; // 終了コード(SJIS文字コード) int Num; // コード数 BYTE* FontData; // フォントデータ int FontDataSize; // フォントデータサイズ(バイト数) } FONTMETRICSBLOCK; typedef struct _FontMetrics { int Width; // フォント幅(dot) int Height; // フォント高さ(dot) int BytesWidth; // フォントイメージの横バイト数 int BytesPerChar; // 1文字当たりバイト数(フォントデータ) int BytesPerCharWrk; // 1文字当たりバイト数(変換ワークデータ) int Code; // 文字コード int Blocks; // コードブロック数 FONTMETRICSBLOCK* Block; } FONTMETRICS; static FONTMETRICS FontZen_16_16; static FONTMETRICS FontHan_8_16; BOOL GetFontMetrics(const TCHAR* FontFile, FONTMETRICS* FontMetrics); void TransAxisBytes(BYTE* from, BYTE* to); int main() { FILE* fp; int blk; int i; unsigned short LastEndCode = 0; BYTE FontDataNull[BYTES_PER_ZEN_OUTFILE]; // フォントデータの無い文字コードを埋めるためのデータ if (GetFontMetrics(FONT_FILE_ZEN_16_16, &FontZen_16_16) == FALSE) { _tprintf(_T("GetFontMetrics error %s\n"), FONT_FILE_ZEN_16_16); return FALSE; } if (GetFontMetrics(FONT_FILE_HAN_8_16, &FontHan_8_16) == FALSE) { _tprintf(_T("GetFontMetrics error %s\n"), FONT_FILE_HAN_8_16); return FALSE; } if ((fp = _tfopen(FONT_FILE_MP3_14_HC, _T("wb"))) == NULL) { _tprintf(_T("フォントファイルオープンエラー\n")); return FALSE; } memset(FontDataNull, 0, BYTES_PER_ZEN_OUTFILE); for (blk = 0; blk < FontHan_8_16.Blocks; blk++) { printf("StartCode=%x\n", FontHan_8_16.Block[blk].StartCode); fwrite(FontHan_8_16.Block[blk].FontData, 1, FontHan_8_16.Block[blk].FontDataSize, fp); LastEndCode = FontHan_8_16.Block[blk].EndCode; printf("LastCode =%x\n", LastEndCode); } for (blk = 0; blk < FontZen_16_16.Blocks; blk++) { if (blk > 0) { for (i = 0; i < (FontZen_16_16.Block[blk].StartCode - LastEndCode - 1); i++) { fwrite(FontDataNull, 1, BYTES_PER_ZEN_OUTFILE, fp); } } printf("Position = %x\n", ftell(fp)); printf("StartCode=%x\n", FontZen_16_16.Block[blk].StartCode); fwrite(FontZen_16_16.Block[blk].FontData, 1, FontZen_16_16.Block[blk].FontDataSize, fp); LastEndCode = FontZen_16_16.Block[blk].EndCode; printf("LastCode =%x\n", LastEndCode); } fclose(fp); } /* * フォントファイルを読み取り、FONTMETRICSデータを作成する。 */ BOOL GetFontMetrics(const TCHAR* FontFile, FONTMETRICS* FontMetrics) { FILE* fp; BYTE buff[128]; BYTE work1[8], work[2]; int i, j, k; if ((fp = _tfopen(FontFile, _T("rb"))) == NULL) { _tprintf(_T("フォントファイルオープンエラー\n")); return FALSE; } fread(buff, 17, 1, fp); if (strncmp((char*)buff, "FONTX2", 6) != 0) { //if (_tcsncmp((char *)buff, _T("FONTX2"), 6) != 0){ _tprintf(_T("FONTXでない\n")); return FALSE; } FontMetrics->Width = buff[14]; FontMetrics->Height = buff[15]; FontMetrics->Code = buff[16]; if (FontMetrics->Code == 0) { // ANK FontMetrics->Blocks = 1; FontMetrics->BytesWidth = 1; FontMetrics->BytesPerCharWrk = BYTES_PER_HAN_OUTFILE; // 16; FontMetrics->BytesPerChar = FontMetrics->BytesWidth * FontMetrics->Height; FontMetrics->Block = (FONTMETRICSBLOCK*)malloc(FontMetrics->Blocks * sizeof(FONTMETRICSBLOCK)); i = 0; FontMetrics->Block[i].StartCode = 0; FontMetrics->Block[i].EndCode = 0xFF; FontMetrics->Block[i].Num = FontMetrics->Block[i].EndCode - FontMetrics->Block[i].StartCode + 1; FontMetrics->Block[i].FontDataSize = FontMetrics->Block[i].Num * FontMetrics->BytesPerCharWrk; FontMetrics->Block[i].FontData = (BYTE*)malloc(FontMetrics->Block[i].Num * FontMetrics->BytesPerCharWrk); memset(FontMetrics->Block[i].FontData, 0, FontMetrics->Block[i].FontDataSize); for (j = 0; j < FontMetrics->Block[i].Num; j++) { unsigned char to1[8], to2[8]; unsigned short* to_p; fread(buff, FontMetrics->BytesPerChar, 1, fp); // 上ブロック for (k = 0; k < 8; k++) { work1[k] = buff[k]; } //TransAxisBytes(work1, FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk)); TransAxisBytes(work1, to1); if (FontMetrics->Height > 8) { // 下ブロック for (k = 0; k < 8; k++) { work1[k] = buff[k + 8]; } //TransAxisBytes(work1, FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk) + 8); TransAxisBytes(work1, to2); to_p = (unsigned short*)(FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk)); for (k = 0; k < 8; k++) { *to_p++ = (to1[k] | (((unsigned short)to2[k]) << 8)); } } } } else { fread(buff, 1, 1, fp); FontMetrics->Blocks = buff[0]; FontMetrics->BytesWidth = ((FontMetrics->Width + 7) / 8); FontMetrics->BytesPerCharWrk = BYTES_PER_ZEN_OUTFILE; // 12x12, 16x16フォント(FontDataバッファ中の1文字当たりバイト数) FontMetrics->BytesPerChar = FontMetrics->BytesWidth * FontMetrics->Height; FontMetrics->Block = (FONTMETRICSBLOCK*)malloc(FontMetrics->Blocks * sizeof(FONTMETRICSBLOCK)); //_tprintf(_T("FontMetrics Width=%d\n"), FontMetrics->Width); //_tprintf(_T("FontMetrics BytesPerChar=%d\n"), FontMetrics->BytesPerChar); // コードブロックテーブル for (i = 0; i < FontMetrics->Blocks; i++) { fread(buff, 4, 1, fp); FontMetrics->Block[i].StartCode = (buff[0] | ((unsigned short)buff[1] << 8)); FontMetrics->Block[i].EndCode = (buff[2] | ((unsigned short)buff[3] << 8)); FontMetrics->Block[i].Num = FontMetrics->Block[i].EndCode - FontMetrics->Block[i].StartCode + 1; FontMetrics->Block[i].FontDataSize = FontMetrics->Block[i].Num * FontMetrics->BytesPerCharWrk; FontMetrics->Block[i].FontData = (BYTE*)malloc(FontMetrics->Block[i].Num * FontMetrics->BytesPerCharWrk); //_tprintf(_T("FontMetrics StartCode=%d num=%d\n"), FontMetrics->Block[i].StartCode, FontMetrics->Block[i].Num); } // フォントイメージ for (i = 0; i < FontMetrics->Blocks; i++) { for (j = 0; j < FontMetrics->Block[i].Num; j++) { fread(buff, FontMetrics->BytesPerChar, 1, fp); // 16x16フォントを1ブロック=8x8ドットの4ブロックに分割。 // // ABCDEFGH // IJKLMNOP // QRSTUVWX // abcdefgh // ijklmnop // qrstuvwx // 01234567 // アイウエオカキク // // フォントファイル中では ABCDEFGH, IJKLMNOP, ... で各バイトを構成している。これを // ア0qiaQIA, イ1rjbRJB, ... というバイト構成に変換する。ア,イ,...が上位ビットとなる。 if (FontMetrics->BytesWidth == 2) { unsigned char to1[8], to2[8], to3[8], to4[8]; unsigned short* to_p; // 左上ブロック for (k = 0; k < 8; k++) { work1[k] = buff[2 * k]; } //TransAxisBytes(work1, FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk)); TransAxisBytes(work1, to1); // 右上ブロック for (k = 0; k < 8; k++) { work1[k] = buff[2 * k + 1]; } //TransAxisBytes(work1, FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk) + 8); TransAxisBytes(work1, to2); if (FontMetrics->Height > 8) { // 左下ブロック for (k = 0; k < 8; k++) { // 12x12フォントでは4 work1[k] = buff[16 + 2 * k]; } //TransAxisBytes(work1, FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk) + 16); TransAxisBytes(work1, to3); // 右下ブロック for (k = 0; k < 8; k++) { // 12x12フォントでは4 work1[k] = buff[16 + 2 * k + 1]; } //TransAxisBytes(work1, FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk) + 24); TransAxisBytes(work1, to4); to_p = (unsigned short*)(FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk)); for (k = 0; k < 8; k++) { *to_p++ = (to1[k] | (((unsigned short)to3[k]) << 8)); } for (k = 0; k < 8; k++) { *to_p++ = (to2[k] | (((unsigned short)to4[k]) << 8)); } } } else if (FontMetrics->BytesWidth == 1) { // 上ブロック for (k = 0; k < 8; k++) { work1[k] = buff[k]; } TransAxisBytes(work1, FontMetrics->Block[i].FontData + (j * FontMetrics->BytesPerCharWrk)); // 下ブロック(?) if (FontMetrics->Height > 8) { // 必要になったら作成 } } //_tprintf(_T("FontMetrics i=%d j=%d\n"), i, j); } } } fclose(fp); return TRUE; } /* * 長さ8のバイト配列のビット位置を縦横入れ替え */ void TransAxisBytes(BYTE* from, BYTE* to) { int i, j; for (i = 0; i < 8; i++) to[i] = 0; to[0] |= ((from[0] & 0x80) >> 7); to[1] |= ((from[0] & 0x40) >> 6); to[2] |= ((from[0] & 0x20) >> 5); to[3] |= ((from[0] & 0x10) >> 4); to[4] |= ((from[0] & 0x08) >> 3); to[5] |= ((from[0] & 0x04) >> 2); to[6] |= ((from[0] & 0x02) >> 1); to[7] |= ((from[0] & 0x01) >> 0); to[0] |= ((from[1] & 0x80) >> 6); to[1] |= ((from[1] & 0x40) >> 5); to[2] |= ((from[1] & 0x20) >> 4); to[3] |= ((from[1] & 0x10) >> 3); to[4] |= ((from[1] & 0x08) >> 2); to[5] |= ((from[1] & 0x04) >> 1); to[6] |= ((from[1] & 0x02) >> 0); to[7] |= ((from[1] & 0x01) << 1); to[0] |= ((from[2] & 0x80) >> 5); to[1] |= ((from[2] & 0x40) >> 4); to[2] |= ((from[2] & 0x20) >> 3); to[3] |= ((from[2] & 0x10) >> 2); to[4] |= ((from[2] & 0x08) >> 1); to[5] |= ((from[2] & 0x04) >> 0); to[6] |= ((from[2] & 0x02) << 1); to[7] |= ((from[2] & 0x01) << 2); to[0] |= ((from[3] & 0x80) >> 4); to[1] |= ((from[3] & 0x40) >> 3); to[2] |= ((from[3] & 0x20) >> 2); to[3] |= ((from[3] & 0x10) >> 1); to[4] |= ((from[3] & 0x08) >> 0); to[5] |= ((from[3] & 0x04) << 1); to[6] |= ((from[3] & 0x02) << 2); to[7] |= ((from[3] & 0x01) << 3); to[0] |= ((from[4] & 0x80) >> 3); to[1] |= ((from[4] & 0x40) >> 2); to[2] |= ((from[4] & 0x20) >> 1); to[3] |= ((from[4] & 0x10) >> 0); to[4] |= ((from[4] & 0x08) << 1); to[5] |= ((from[4] & 0x04) << 2); to[6] |= ((from[4] & 0x02) << 3); to[7] |= ((from[4] & 0x01) << 4); to[0] |= ((from[5] & 0x80) >> 2); to[1] |= ((from[5] & 0x40) >> 1); to[2] |= ((from[5] & 0x20) >> 0); to[3] |= ((from[5] & 0x10) << 1); to[4] |= ((from[5] & 0x08) << 2); to[5] |= ((from[5] & 0x04) << 3); to[6] |= ((from[5] & 0x02) << 4); to[7] |= ((from[5] & 0x01) << 5); to[0] |= ((from[6] & 0x80) >> 1); to[1] |= ((from[6] & 0x40) >> 0); to[2] |= ((from[6] & 0x20) << 1); to[3] |= ((from[6] & 0x10) << 2); to[4] |= ((from[6] & 0x08) << 3); to[5] |= ((from[6] & 0x04) << 4); to[6] |= ((from[6] & 0x02) << 5); to[7] |= ((from[6] & 0x01) << 6); to[0] |= ((from[7] & 0x80) >> 0); to[1] |= ((from[7] & 0x40) << 1); to[2] |= ((from[7] & 0x20) << 2); to[3] |= ((from[7] & 0x10) << 3); to[4] |= ((from[7] & 0x08) << 4); to[5] |= ((from[7] & 0x04) << 5); to[6] |= ((from[7] & 0x02) << 6); to[7] |= ((from[7] & 0x01) << 7); } // プログラムの実行: Ctrl + F5 または [デバッグ] > [デバッグなしで開始] メニュー // プログラムのデバッグ: F5 または [デバッグ] > [デバッグの開始] メニュー // 作業を開始するためのヒント: // 1. ソリューション エクスプローラー ウィンドウを使用してファイルを追加/管理します // 2. チーム エクスプローラー ウィンドウを使用してソース管理に接続します // 3. 出力ウィンドウを使用して、ビルド出力とその他のメッセージを表示します // 4. エラー一覧ウィンドウを使用してエラーを表示します // 5. [プロジェクト] > [新しい項目の追加] と移動して新しいコード ファイルを作成するか、[プロジェクト] > [既存の項目の追加] と移動して既存のコード ファイルをプロジェクトに追加します // 6. 後ほどこのプロジェクトを再び開く場合、[ファイル] > [開く] > [プロジェクト] と移動して .sln ファイルを選択します