⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fontgen.c

📁 点阵字体产生工具以及相关显示函数。 在开发嵌入式系统时
💻 C
📖 第 1 页 / 共 2 页
字号:
/*----------------------------------------------
FONTGEN.C -- Create Font ver 1.1
(c) Emuman 2003
----------------------------------------------*/

#include <windows.h>
#include <mbstring.h>
#include <stdio.h>
#include "resource.h"

/***************************************************************************
Global variables
***************************************************************************/

static PTSTR	szAppName = TEXT ("FontGen");
static UINT		scalex, scaley, index, elecount;	//target scale x, y, current index, total entry
static POINT	ptOffset;							//offset when generating font bmp
static LOGFONT	lf;									//currently selected font

//DEBUG
static int ccc,h;

static LOGFONT	lf0;	//temp font for enum
static TCHAR	szFontList[32][LF_FACESIZE];

/***************************************************************************
Structures
***************************************************************************/

struct Tile
{
	WCHAR unicode;
	HBITMAP hBitmap;
};

/***************************************************************************
Function prototypes
***************************************************************************/

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

void Txt2TileArray (PTSTR, Tile[]);
HBITMAP Char2Bmp (PTSTR);
void TileArray2Byte (Tile[], PBYTE, int);
void Byte2TileArray (PBYTE, Tile[]);
void Txt2TileArrayCode (PTSTR, Tile[]);
void TileArrayCode2Txt (Tile[], PTSTR);
BOOL ReadTextFile (PTSTR, PTSTR);
int ReadXFile (PTSTR, LPVOID);
BOOL WriteXFile (PTSTR, LPCVOID, int);
void RemoveDupDBCS (PTSTR);
int CleanTileArray (Tile[]);
HBITMAP MakeShadow (HBITMAP);

int CALLBACK EnumFontFamExProc(ENUMLOGFONTEX *, NEWTEXTMETRICEX *, DWORD, LPARAM);

/***************************************************************************
Functions
***************************************************************************/

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
					PSTR szCmdLine, int iCmdShow)
{
	HWND     hwnd ;
	MSG      msg ;
	WNDCLASS wndclass ;

	wndclass.style         = CS_HREDRAW | CS_VREDRAW ;
	wndclass.lpfnWndProc   = WndProc ;
	wndclass.cbClsExtra    = 0 ;
	wndclass.cbWndExtra    = DLGWINDOWEXTRA ;    // Note!
	wndclass.hInstance     = hInstance ;
	wndclass.hIcon         = LoadIcon (NULL, IDI_APPLICATION) ;
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
	wndclass.hbrBackground = (HBRUSH) (COLOR_BTNSHADOW) ;
	wndclass.lpszMenuName  = szAppName ; 
	wndclass.lpszClassName = szAppName ;

	if (!RegisterClass (&wndclass))
	{
		MessageBox (NULL, TEXT ("This program requires Windows NT!"),
			szAppName, MB_ICONERROR) ;
		return 0 ;
	}

	hwnd = CreateDialog (hInstance, szAppName, 0, NULL) ;

	ShowWindow (hwnd, iCmdShow) ;

	while (GetMessage (&msg, NULL, 0, 0))
	{
		TranslateMessage (&msg) ;
		DispatchMessage (&msg) ;
	}
	return (int)msg.wParam ;
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static bool			is_init = 1;	//program init flag

	static OPENFILENAME	ofn;
	static TCHAR		szFileName[MAX_PATH];
	static TCHAR		szTextBuf[0xA00000];	//max 10M text
	static BYTE			byBuf[0xffff * 32];		//buffer to receive whole Tile bitmaps. UnicodeRange * 16px * 2bpp

	HWND				hCtrl;
	HDC					hdc, hdcMem, hdcMemShadow, hdcMemRaw;
	HGDIOBJ				hobj;
	static HBRUSH		hbrush;
	PAINTSTRUCT			ps;
	static COLORREF		cr0, cr1;

	static HBITMAP		hBitmap, hBitmapRaw, hBitmap0, hBitmapShadow;	//hBitmap0: original bitmap before edit
	static RECT			rc, rc2;	//redraw rect
	static POINT		pt;
	static Tile			aTile[0xffff], aTile2[0xffff];
	int					i;

	switch (message)
	{
	case WM_CREATE:
		// Initialize OPENFILENAME
		ZeroMemory(&ofn, sizeof(ofn));
		ofn.lStructSize = sizeof(ofn);
		ofn.hwndOwner = hwnd;
		ofn.lpstrFile = szFileName;
		// Set lpstrFile[0] to '\0' so that GetOpenFileName does not 
		// use the contents of szFile to initialize itself.
		ofn.lpstrFile[0] = '\0';
		ofn.nMaxFile = sizeof(szFileName);
		ofn.lpstrFilter =  '\0';
		ofn.nFilterIndex = 1;
		ofn.lpstrFileTitle = NULL;
		ofn.nMaxFileTitle = 0;
		ofn.lpstrInitialDir = NULL;
		ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
		return 0;

	case WM_SIZE:
		if (is_init)	//DLGWINDOWEXTRA can't init in WM_CREATE
		{
			//initialize font combobox
			hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL);
			memset(&lf0,0,sizeof(lf0));
			lf0.lfFaceName[0] = '\0';
			lf0.lfCharSet = GB2312_CHARSET;
			EnumFontFamiliesEx( hdc, &lf0, (FONTENUMPROC)EnumFontFamExProc, 0, 0 );
			lf0.lfCharSet = CHINESEBIG5_CHARSET;
			EnumFontFamiliesEx( hdc, &lf0, (FONTENUMPROC)EnumFontFamExProc, 0, 0 );
			lf0.lfCharSet = SHIFTJIS_CHARSET;
			EnumFontFamiliesEx( hdc, &lf0, (FONTENUMPROC)EnumFontFamExProc, 0, 0 );
			DeleteDC (hdc);

			i = 0;
			hCtrl = GetDlgItem(hwnd,IDC_FONT_COMBO);
			while (lstrcmp(szFontList[i],TEXT("")))
				SendMessage (hCtrl, CB_ADDSTRING,0,(LPARAM)(LPCTSTR)szFontList[i++]);

			SendMessage (hCtrl, CB_SETCURSEL,0,0);
			GetDlgItemText (hwnd, IDC_FONT_COMBO, lf.lfFaceName, LF_FACESIZE);

			//initialize font parameter
			SetDlgItemText (hwnd, IDC_SRC_HEIGHT_EDIT, (LPCTSTR)TEXT("13"));
			SetDlgItemText (hwnd, IDC_SCX_EDIT, (LPCTSTR)TEXT("7"));
			SetDlgItemText (hwnd, IDC_SCY_EDIT, (LPCTSTR)TEXT("13"));
			SetDlgItemText (hwnd, IDC_OFFSETY_EDIT, (LPCTSTR)TEXT("2"));
			SetDlgItemText (hwnd, IDC_SHADOW_EDIT, (LPCTSTR)TEXT("0"));

			//initialize scrollbar
			hCtrl = GetDlgItem (hwnd, IDC_NAVIGATE_SCROLLBAR) ;
			SetScrollRange (hCtrl, SB_CTL, 0, 0, FALSE) ;
			SetScrollPos   (hCtrl, SB_CTL, 0, FALSE) ;

			//disable controls
			hCtrl = GetDlgItem(hwnd, IDC_NAVIGATE_SCROLLBAR);
			EnableWindow (hCtrl, FALSE);
			hCtrl = GetDlgItem(hwnd, IDC_SAV_CHECK);
			EnableWindow (hCtrl, FALSE);

			//font rect for redraw
			rc.left = 300;
			rc.top = 50;
			rc.bottom = 300;
			rc.right = 500;

			//preview font rect for redraw
			rc2.left = 250;
			rc2.top = 100;
			rc2.right = 300;
			rc2.bottom = 150;

			hbrush = CreateSolidBrush(RGB (0xb8, 0xb8, 0xb8));

			is_init = 0;
		}
		return 0;

	case WM_COMMAND:
		switch (LOWORD (wParam))
		{
		case IDC_FONT_COMBO:
			if (HIWORD (wParam) == CBN_SELCHANGE)
			{
				if (!hBitmap0)	//current bmp never edited
					hBitmap0 = aTile[index].hBitmap; //backup current bmp
				else	//current bmp is edited (has backup)
					DeleteObject (aTile[index].hBitmap);

				GetDlgItemText (hwnd, IDC_FONT_COMBO, lf.lfFaceName, LF_FACESIZE);
				aTile[index].hBitmap = Char2Bmp(&aTile[index].unicode);	// put a new bmp to current bmp

				InvalidateRect (hwnd, &rc, TRUE) ;
				InvalidateRect (hwnd, &rc2, TRUE);
			}
			return 0 ;

		case IDC_SRC_HEIGHT_EDIT:
			if (HIWORD (wParam) == EN_UPDATE)
				lf.lfHeight = GetDlgItemInt (hwnd, IDC_SRC_HEIGHT_EDIT, NULL, FALSE);
			return 0 ;

		case IDC_SCX_EDIT:
			if (HIWORD (wParam) == EN_UPDATE)
			{
				scalex = GetDlgItemInt (hwnd, IDC_SCX_EDIT, NULL, FALSE);
				rc.right = (scalex>8)?570:500;
			}
			return 0 ;

		case IDC_SCY_EDIT:
			if (HIWORD (wParam) == EN_UPDATE)
				scaley = GetDlgItemInt (hwnd, IDC_SCY_EDIT, NULL, FALSE);
			return 0 ;

		case IDC_OFFSETY_EDIT:
			if (HIWORD (wParam) == EN_UPDATE)
				ptOffset.y = GetDlgItemInt (hwnd, IDC_OFFSETY_EDIT, NULL, TRUE);
			return 0 ;

		case IDM_FILE_OPENTXT:	//read txt, remove all duplicate kanji, generate tiles in memory
			ofn.lpstrFilter = TEXT("Text\0*.txt\0");
			if (GetOpenFileName(&ofn))
			{
				if (!ReadTextFile (szFileName, szTextBuf))
				{
					MessageBox (hwnd, TEXT ("Could not read txt file!"), 0, MB_OK | MB_ICONEXCLAMATION) ;
					szFileName[0]  = '\0' ;
					return 0;
				}
				RemoveDupDBCS(szTextBuf);
				elecount = 8 * ((lstrlen(szTextBuf) + 7) / 8);	//align 8

				CleanTileArray(aTile);	//clean all existing tiles
				Txt2TileArray(szTextBuf, aTile);

				hCtrl = GetDlgItem (hwnd, IDC_NAVIGATE_SCROLLBAR) ;
				SetScrollRange (hCtrl, SB_CTL, 0, elecount - 1, FALSE) ;
				EnableWindow (hCtrl, TRUE);
				hCtrl = GetDlgItem(hwnd, IDC_SAV_CHECK);
				EnableWindow (hCtrl, TRUE);

				InvalidateRect (hwnd, NULL, TRUE) ;
			}
			return 0 ;

		case ID_FILE_IMPORTTEXT:	//not finished
			ofn.lpstrFilter = TEXT("Text\0*.txt\0");
			if (GetOpenFileName(&ofn))
			{
				if (!ReadTextFile (szFileName, szTextBuf))
				{
					MessageBox (hwnd, TEXT ("Could not import txt file!"), 0, MB_OK | MB_ICONEXCLAMATION) ;
					szFileName[0]  = '\0' ;
					return 0;
				}
				RemoveDupDBCS(szTextBuf);

				int j;
				for (i = 0; i < lstrlen(szTextBuf); i++)
				{
					for (j = 0; j < elecount; j++)
					{
						if (CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, &szTextBuf[i], 1, &aTile[j].unicode, 1))
						{
							aTile2[i].hBitmap = aTile[j].hBitmap;
							break;
						}
					}
				}

				szFileName[wcsstr(szFileName,L".txt")-szFileName]='\0';	//cut off "*.txt"

				if (GetDlgItemInt (hwnd, IDC_SHADOW_EDIT, NULL, FALSE))
				{
					ZeroMemory (byBuf, 0xffff * 32);
					TileArray2Byte(aTile2, byBuf, 0);
					wcscat(szFileName,L"_noshadow.gb");	//concatenate w/ another file ext
					WriteXFile(szFileName, byBuf, lstrlen(szTextBuf) * 32 * 2);
					szFileName[wcsstr(szFileName,L"_noshadow.gb")-szFileName]='\0';
				}

				ZeroMemory (byBuf, 0xffff * 32);
				TileArray2Byte(aTile2, byBuf, GetDlgItemInt (hwnd, IDC_SHADOW_EDIT, NULL, FALSE));
				wcscat(szFileName,L".gb");
				WriteXFile(szFileName, byBuf, lstrlen(szTextBuf) * 32 * 2);
			}

			return 0;

		case ID_FILE_OPENROM:
			ofn.lpstrFilter = TEXT("2bpp .gb ROM with .txt index\0*.gb\0");
			if (GetOpenFileName(&ofn))
			{
				ZeroMemory (byBuf, 0xffff * 32);
				if ((elecount = ReadXFile (szFileName, byBuf) / (32 * 2)) < 0)
				{
					MessageBox (hwnd, TEXT ("Could not read .gb ROM"), 0, MB_OK | MB_ICONEXCLAMATION);
					szFileName[0]  = '\0';
					return 0;
				}
				CleanTileArray (aTile);
				Byte2TileArray (byBuf, aTile);

				szFileName[wcsstr(szFileName,L".gb")-szFileName]='\0';
				wcscat(szFileName,L".txt");
				if (!ReadTextFile (szFileName, szTextBuf))
				{
					MessageBox (hwnd, TEXT ("Could not read .txt index!"), 0, MB_OK | MB_ICONEXCLAMATION) ;
					szFileName[0]  = '\0' ;
					return 0;
				}
				Txt2TileArrayCode (szTextBuf, aTile);

				hCtrl = GetDlgItem (hwnd, IDC_NAVIGATE_SCROLLBAR) ;
				SetScrollRange (hCtrl, SB_CTL, 0, elecount - 1, FALSE) ;
				EnableWindow (hCtrl, TRUE);
				hCtrl = GetDlgItem(hwnd, IDC_SAV_CHECK);
				EnableWindow (hCtrl, TRUE);

				InvalidateRect (hwnd, NULL, TRUE) ;
			}
			return 0 ;

		case ID_FILE_MERGEROM:
			ofn.lpstrFilter = TEXT("2bpp .gb ROM with .txt index\0*.gb\0");
			if (GetOpenFileName(&ofn))
			{
				ZeroMemory (byBuf, 0xffff * 32);
				if (ReadXFile (szFileName, byBuf) / (32 * 2) < 0)
				{
					MessageBox (hwnd, TEXT ("Could not read .gb ROM"), 0, MB_OK | MB_ICONEXCLAMATION);
					szFileName[0]  = '\0';
					return 0;
				}
				CleanTileArray (aTile2);
				Byte2TileArray (byBuf, aTile2);

				szFileName[wcsstr(szFileName,L".gb")-szFileName]='\0';
				wcscat(szFileName,L".txt");
				if (!ReadTextFile (szFileName, szTextBuf))
				{
					MessageBox (hwnd, TEXT ("Could not read .txt index!"), 0, MB_OK | MB_ICONEXCLAMATION) ;
					szFileName[0]  = '\0' ;
					return 0;
				}
				Txt2TileArrayCode (szTextBuf, aTile2);

				int j;
				for (i = 0; i < lstrlen(szTextBuf); i++)
				{
					for (j = 0; j < elecount; j++)
					{
						if (CSTR_EQUAL == CompareString(LOCALE_USER_DEFAULT, 0, &szTextBuf[i], 1, &aTile[j].unicode, 1))
						{
							int y = DeleteObject(aTile[j].hBitmap);
							aTile[j].hBitmap = aTile2[i].hBitmap;
							break;
						}
						else
						{
							aTile[elecount] = aTile2[i];
							elecount++;
						}
					}
				}

				hCtrl = GetDlgItem (hwnd, IDC_NAVIGATE_SCROLLBAR) ;
				SetScrollRange (hCtrl, SB_CTL, 0, elecount - 1, FALSE) ;
			}

			return 0 ;

		case ID_FILE_SAVEROM:
			ofn.lpstrFilter = TEXT("2bpp .gb ROM with .txt index\0*.gb\0");
			if (GetSaveFileName(&ofn))
			{
				if (GetDlgItemInt (hwnd, IDC_SHADOW_EDIT, NULL, FALSE))
				{
					ZeroMemory (byBuf, 0xffff * 32);
					TileArray2Byte(aTile, byBuf, 0);
					WriteXFile(TEXT("noshadow.gb"), byBuf, elecount * 32 * 2);
				}
				ZeroMemory (byBuf, 0xffff * 32);
				TileArray2Byte(aTile, byBuf, GetDlgItemInt (hwnd, IDC_SHADOW_EDIT, NULL, FALSE));
				WriteXFile(szFileName, byBuf, elecount * 32 * 2);
				TileArrayCode2Txt (aTile, szTextBuf);
				szFileName[wcsstr(szFileName,L".gb")-szFileName]='\0';
				wcscat(szFileName,L".txt");
				WriteXFile(szFileName, szTextBuf, elecount * 2 + 2);
			}

			return 0;
		}
		break ;

	case WM_LBUTTONDOWN:
	case WM_RBUTTONDOWN:
		pt.x = LOWORD (lParam);
		pt.y = HIWORD (lParam);

		if (PtInRect(&rc, pt))
		{
			hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL);
			hdcMem = CreateCompatibleDC (hdc);
			SelectObject (hdcMem, aTile[index].hBitmap);

			cr0 = GetPixel(hdcMem, (pt.x-rc.left)*((scalex>8)?16:8)/(rc.right-rc.left), (pt.y-rc.top)*16/(rc.bottom-rc.top));
			if (wParam == MK_LBUTTON)
				SetPixel (hdcMem, (pt.x-rc.left)*((scalex>8)?16:8)/(rc.right-rc.left), (pt.y-rc.top)*16/(rc.bottom-rc.top), 0xffffff);
			else if (wParam == MK_RBUTTON)
				SetPixel (hdcMem, (pt.x-rc.left)*((scalex>8)?16:8)/(rc.right-rc.left), (pt.y-rc.top)*16/(rc.bottom-rc.top), 0x000000);
			cr1 = GetPixel(hdcMem, (pt.x-rc.left)*((scalex>8)?16:8)/(rc.right-rc.left), (pt.y-rc.top)*16/(rc.bottom-rc.top));

			if (cr0 != cr1)
			{
				InvalidateRect (hwnd, &rc, TRUE);
				InvalidateRect (hwnd, &rc2, TRUE);
			}

			DeleteDC (hdcMem);
			DeleteDC (hdc);
		}
		return 0;

	case WM_MOUSEMOVE:
		pt.x = LOWORD (lParam);
		pt.y = HIWORD (lParam);
		if (PtInRect(&rc, pt)&&((wParam == MK_SHIFT)||(wParam == MK_CONTROL)))
		{
			hdc = CreateIC (TEXT ("DISPLAY"), NULL, NULL, NULL);
			hdcMem = CreateCompatibleDC (hdc);
			SelectObject (hdcMem, aTile[index].hBitmap);

			cr0 = GetPixel(hdcMem, (pt.x-rc.left)*((scalex>8)?16:8)/(rc.right-rc.left), (pt.y-rc.top)*16/(rc.bottom-rc.top));
			if (wParam == MK_SHIFT)
				SetPixel (hdcMem, (pt.x-rc.left)*((scalex>8)?16:8)/(rc.right-rc.left), (pt.y-rc.top)*16/(rc.bottom-rc.top), 0xffffff);
			else if (wParam == MK_CONTROL)
				SetPixel (hdcMem, (pt.x-rc.left)*((scalex>8)?16:8)/(rc.right-rc.left), (pt.y-rc.top)*16/(rc.bottom-rc.top), 0x000000);
			cr1 = GetPixel(hdcMem, (pt.x-rc.left)*((scalex>8)?16:8)/(rc.right-rc.left), (pt.y-rc.top)*16/(rc.bottom-rc.top));

			if (cr0 != cr1)
			{
				InvalidateRect (hwnd, &rc, TRUE);
				InvalidateRect (hwnd, &rc2, TRUE);
			}

			DeleteDC (hdcMem);
			DeleteDC (hdc);
		}
		return 0;

	case WM_HSCROLL:
		if (hBitmap0)	//current bmp is edited (has backup)
		{
			if(BST_CHECKED == IsDlgButtonChecked (hwnd, IDC_SAV_CHECK))	//save edit?
			{
				DeleteObject (hBitmap0);
			}
			else
			{
				DeleteObject (aTile[index].hBitmap);
				aTile[index].hBitmap = hBitmap0;
			}
			hBitmap0 = 0;
		}

		hCtrl = (HWND) lParam ;
		switch (LOWORD (wParam))
		{
		case SB_THUMBPOSITION:
		case SB_THUMBTRACK:
			index = HIWORD (wParam) ;
			break;
		case SB_LINELEFT:
			index --;
			if (index < 0) index = 0;
			break;
		case SB_LINERIGHT:
			index ++;
			if (index > elecount - 1) index = elecount - 1;
			break;
		case SB_PAGELEFT:
			index -= 20;
			if (index < 0) index = 0;
			break;
		case SB_PAGERIGHT:
			index += 20;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -