[BOOTVID_FONT_GEN]

Improve the bootvid font generator of Colin (see r70507) in many ways:
- Allow the user to specify the font name (optional), and optionally a font size and x- and y-offset so that (s)he doesn't have to recompile the generator each time (s)he wants to test a new font.
- The default settings (in case the user doesn't specify all or part of the font definition) are those of Windows' bootvid font (i.e. "Lucida Console", font size 10, x_offset = y_offset = 0).
- Create only once the DC and the font handle (to be used for all the generated characters) instead of each time a character is being generated. I still keep the recreation of the HBITMAP for each character (I don't know if we can also improve there by creating it once and zeroing it out before generating each character).

svn path=/trunk/; revision=70512
This commit is contained in:
Hermès Bélusca-Maïto 2016-01-07 00:29:41 +00:00
parent 0f3e09ea77
commit 4219c4eed0

View file

@ -1,29 +1,36 @@
/* /*
* PROJECT: ReactOS bootvid Font Generator Utility * PROJECT: ReactOS BootVid Font Generator Utility
* LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation * LICENSE: GNU GPLv2 or any later version as published by the Free Software Foundation
* PURPOSE: Generates the FontData array for the bootdata.c file of bootvid * PURPOSE: Generates the FontData array for the bootdata.c file of bootvid.sys
* COPYRIGHT: Copyright 2016 Colin Finck <colin@reactos.org> * COPYRIGHT: Copyright 2016 Colin Finck <colin@reactos.org>
*/ */
#include <windows.h>
#include <stdio.h> #include <stdio.h>
#include <conio.h>
#include <windows.h>
/*
* Enable this #define if you want to dump the generated character on screen
*/
// #define DUMP_CHAR_ON_SCREEN
// Windows original Blue Screen font is "Lucida Console" at FONT_SIZE 10 with no offsets. // Windows original Blue Screen font is "Lucida Console" at FONT_SIZE 10 with no offsets.
#define FONT_NAME L"Anonymous Pro" #define FONT_NAME_DEF "Lucida Console" // "DejaVu Sans Mono" // "Anonymous Pro"
#define FONT_SIZE 10 #define FONT_SIZE_DEF 10
#define X_OFFSET 1 #define X_OFFSET_DEF 0 // 0 // 1
#define Y_OFFSET 0 #define Y_OFFSET_DEF 0
#define HEIGHT 13
#define WIDTH 8
#define HEIGHT 13 // Must be == BOOTCHAR_HEIGHT (see reactos/drivers/base/bootvid/precomp.h)
#define WIDTH 8 // 8 bits == 1 byte
#ifdef DUMP_CHAR_ON_SCREEN
/** /**
* Sketch the character on the console screen using ASCII characters. * Sketch the character on the console screen using ASCII characters.
* Allows you to easily check if the font fits properly into the 8x13 box. * Allows you to easily check if the font fits properly into the 8x13 box.
*/ */
void DumpCharacterOnScreen(DWORD BmpBits[]) static void DumpCharacterOnScreen(DWORD BmpBits[])
{ {
int i; int i, j;
int j;
for (i = 0; i < HEIGHT; i++) for (i = 0; i < HEIGHT; i++)
{ {
@ -39,111 +46,149 @@ void DumpCharacterOnScreen(DWORD BmpBits[])
} }
} }
#else
/** /**
* Dump the FontData for the bootvid/i386/bootdata.c array. * Dump the FontData for the bootvid/i386/bootdata.c array.
*/ */
void DumpCharacterFontData(DWORD BmpBits[]) static void DumpCharacterFontData(DWORD BmpBits[])
{ {
static int iBegin = 0; static int iBegin = 0;
int i; int i;
printf(" "); fprintf(stdout, " ");
for (i = 0; i < HEIGHT; i++) for (i = 0; i < HEIGHT; i++)
printf("0x%02lX, ", BmpBits[i]); fprintf(stdout, "0x%02lX, ", BmpBits[i]);
printf(" // %d\n", iBegin); fprintf(stdout, " // %d\n", iBegin);
iBegin += HEIGHT; iBegin += HEIGHT;
} }
#endif
/** /**
* Use GDI APIs to load a monospace font and plot a single character into a bitmap. * Use GDI APIs to load a monospace font and plot a single character into a bitmap.
*/ */
BOOL PlotCharacter(WCHAR Character, DWORD BmpBits[]) static BOOL PlotCharacter(HDC hDC, HFONT hFont, INT XOffset, INT YOffset, CHAR Character, DWORD BmpBits[])
{ {
BOOL bReturnValue = FALSE; BOOL bReturnValue = FALSE;
int iHeight; HBITMAP hOldBmp;
HFONT hOldFont;
HBITMAP hBmp = NULL; HBITMAP hBmp = NULL;
HDC hDC = NULL; BYTE BmpInfo[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];
HFONT hFont = NULL; PBITMAPINFO pBmpInfo = (PBITMAPINFO)&BmpInfo;
PBITMAPINFO pBmpInfo;
hDC = CreateCompatibleDC(NULL);
if (!hDC)
{
printf("CreateCompatibleDC failed with error %lu!\n", GetLastError());
goto Cleanup;
}
hBmp = CreateCompatibleBitmap(hDC, WIDTH, HEIGHT); hBmp = CreateCompatibleBitmap(hDC, WIDTH, HEIGHT);
if (!hBmp) if (!hBmp)
{ {
printf("CreateCompatibleBitmap failed with error %lu!\n", GetLastError()); fprintf(stderr, "CreateCompatibleBitmap failed with error %lu!\n", GetLastError());
goto Cleanup; goto Cleanup;
} }
iHeight = -MulDiv(FONT_SIZE, GetDeviceCaps(hDC, LOGPIXELSY), 72); hOldBmp = SelectObject(hDC, hBmp);
hFont = CreateFontW(iHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 0, 0, NONANTIALIASED_QUALITY, FIXED_PITCH, FONT_NAME); hOldFont = SelectObject(hDC, hFont);
if (!hFont)
{
printf("CreateFontW failed with error %lu!\n", GetLastError());
goto Cleanup;
}
SelectObject(hDC, hBmp);
SelectObject(hDC, hFont);
SetBkColor(hDC, RGB(0, 0, 0)); SetBkColor(hDC, RGB(0, 0, 0));
SetTextColor(hDC, RGB(255, 255, 255)); SetTextColor(hDC, RGB(255, 255, 255));
TextOutW(hDC, X_OFFSET, Y_OFFSET, &Character, 1); TextOutA(hDC, XOffset, YOffset, &Character, 1);
// Allocate enough memory for BITMAPINFO and one additional color in the color table. /*
// BITMAPINFO already contains a color table entry for a single color and GetDIBits needs space for two colors (black and white). * Use enough memory for BITMAPINFO and one additional color in the color table.
pBmpInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFO) + sizeof(RGBQUAD)); * BITMAPINFO already contains a color table entry for a single color and
ZeroMemory(pBmpInfo, sizeof(BITMAPINFO) + sizeof(RGBQUAD)); * GetDIBits needs space for two colors (black and white).
*/
ZeroMemory(&BmpInfo, sizeof(BmpInfo));
pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBmpInfo->bmiHeader.biHeight = -HEIGHT; pBmpInfo->bmiHeader.biHeight = -HEIGHT;
pBmpInfo->bmiHeader.biWidth = WIDTH; pBmpInfo->bmiHeader.biWidth = WIDTH;
pBmpInfo->bmiHeader.biBitCount = 1; pBmpInfo->bmiHeader.biBitCount = 1;
pBmpInfo->bmiHeader.biPlanes = 1; pBmpInfo->bmiHeader.biPlanes = 1;
if (!GetDIBits(hDC, hBmp, 0, HEIGHT, BmpBits, pBmpInfo, 0))
{
printf("GetDIBits failed with error %lu!\n", GetLastError());
goto Cleanup;
}
bReturnValue = TRUE; bReturnValue = TRUE;
Cleanup: if (!GetDIBits(hDC, hBmp, 0, HEIGHT, BmpBits, pBmpInfo, 0))
if (hFont) {
DeleteObject(hFont); fprintf(stderr, "GetDIBits failed with error %lu!\n", GetLastError());
bReturnValue = FALSE;
}
SelectObject(hDC, hOldBmp);
SelectObject(hDC, hOldFont);
Cleanup:
if (hBmp) if (hBmp)
DeleteObject(hBmp); DeleteObject(hBmp);
if (hDC)
DeleteDC(hDC);
return bReturnValue; return bReturnValue;
} }
int main() static void DumpFont(LPSTR FontName, INT FontSize, INT XOffset, INT YOffset)
{ {
int iHeight;
HDC hDC = NULL;
HFONT hFont = NULL;
DWORD BmpBits[HEIGHT]; DWORD BmpBits[HEIGHT];
WCHAR c; USHORT c;
hDC = CreateCompatibleDC(NULL);
if (!hDC)
{
fprintf(stderr, "CreateCompatibleDC failed with error %lu!\n", GetLastError());
goto Cleanup;
}
iHeight = -MulDiv(FontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
hFont = CreateFontA(iHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
ANSI_CHARSET, 0, 0, NONANTIALIASED_QUALITY,
FIXED_PITCH, FontName);
if (!hFont)
{
fprintf(stderr, "CreateFont failed with error %lu!\n", GetLastError());
goto Cleanup;
}
for (c = 0; c < 256; c++) for (c = 0; c < 256; c++)
{ {
PlotCharacter(c, BmpBits); PlotCharacter(hDC, hFont, XOffset, YOffset, (CHAR)c, BmpBits);
#if 0 #ifdef DUMP_CHAR_ON_SCREEN
DumpCharacterOnScreen(BmpBits); DumpCharacterOnScreen(BmpBits);
system("pause"); fprintf(stdout, "\nPress any key to continue...\n");
_getch();
system("cls"); system("cls");
#else #else
DumpCharacterFontData(BmpBits); DumpCharacterFontData(BmpBits);
#endif #endif
} }
Cleanup:
if (hFont)
DeleteObject(hFont);
if (hDC)
DeleteDC(hDC);
}
int main(int argc, char** argv)
{
/* Validate the arguments */
if (argc > 5 || (argc >= 2 && strncmp(argv[1], "/?", 2) == 0))
{
fprintf(stdout,
"Usage: %s \"font name\" [font size] [X-offset] [Y-offset]\n"
"Default font name is: \"%s\"\n"
"Default font size is: %i\n"
"Default X-offset is: %i\n"
"Default Y-offset is: %i\n",
argv[0],
FONT_NAME_DEF, FONT_SIZE_DEF, X_OFFSET_DEF, Y_OFFSET_DEF);
return -1;
}
DumpFont((argc <= 1) ? FONT_NAME_DEF : argv[1],
(argc <= 2) ? FONT_SIZE_DEF : atoi(argv[2]),
(argc <= 3) ? X_OFFSET_DEF : atoi(argv[3]),
(argc <= 4) ? Y_OFFSET_DEF : atoi(argv[4]));
return 0; return 0;
} }