[BOOTVID_FONT_GEN]
authorHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 7 Jan 2016 00:29:41 +0000 (00:29 +0000)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Thu, 7 Jan 2016 00:29:41 +0000 (00:29 +0000)
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

rosapps/applications/devutils/bootvid_font_generator/bootvid_font_generator.c

index 8fc7817..5b4e794 100644 (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
- * 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>
  */
 
-#include <windows.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.
-#define FONT_NAME       L"Anonymous Pro"
-#define FONT_SIZE       10
-#define X_OFFSET        1
-#define Y_OFFSET        0
-#define HEIGHT          13
-#define WIDTH           8
+#define FONT_NAME_DEF   "Lucida Console" // "DejaVu Sans Mono" // "Anonymous Pro"
+#define FONT_SIZE_DEF   10
+#define X_OFFSET_DEF    0                // 0                  // 1
+#define Y_OFFSET_DEF    0
+
+#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.
  * 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 j;
+    int i, j;
 
     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.
  */
-void DumpCharacterFontData(DWORD BmpBits[])
+static void DumpCharacterFontData(DWORD BmpBits[])
 {
     static int iBegin = 0;
     int i;
 
-    printf("    ");
+    fprintf(stdout, "    ");
 
     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;
 }
+#endif
 
 /**
  * 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;
-    int iHeight;
+    HBITMAP hOldBmp;
+    HFONT hOldFont;
     HBITMAP hBmp = NULL;
-    HDC hDC = NULL;
-    HFONT hFont = NULL;
-    PBITMAPINFO pBmpInfo;
-
-    hDC = CreateCompatibleDC(NULL);
-    if (!hDC)
-    {
-        printf("CreateCompatibleDC failed with error %lu!\n", GetLastError());
-        goto Cleanup;
-    }
+    BYTE BmpInfo[sizeof(BITMAPINFO) + sizeof(RGBQUAD)];
+    PBITMAPINFO pBmpInfo = (PBITMAPINFO)&BmpInfo;
 
     hBmp = CreateCompatibleBitmap(hDC, WIDTH, HEIGHT);
     if (!hBmp)
     {
-        printf("CreateCompatibleBitmap failed with error %lu!\n", GetLastError());
-        goto Cleanup;
-    }
-
-    iHeight = -MulDiv(FONT_SIZE, GetDeviceCaps(hDC, LOGPIXELSY), 72);
-    hFont = CreateFontW(iHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET, 0, 0, NONANTIALIASED_QUALITY, FIXED_PITCH, FONT_NAME);
-    if (!hFont)
-    {
-        printf("CreateFontW failed with error %lu!\n", GetLastError());
+        fprintf(stderr, "CreateCompatibleBitmap failed with error %lu!\n", GetLastError());
         goto Cleanup;
     }
 
-    SelectObject(hDC, hBmp);
-    SelectObject(hDC, hFont);
+    hOldBmp  = SelectObject(hDC, hBmp);
+    hOldFont = SelectObject(hDC, hFont);
     SetBkColor(hDC, RGB(0, 0, 0));
     SetTextColor(hDC, RGB(255, 255, 255));
-    TextOutW(hDC, X_OFFSET, Y_OFFSET, &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).
-    pBmpInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFO) + sizeof(RGBQUAD));
-    ZeroMemory(pBmpInfo, sizeof(BITMAPINFO) + sizeof(RGBQUAD));
+    TextOutA(hDC, XOffset, YOffset, &Character, 1);
+
+    /*
+     * Use 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).
+     */
+    ZeroMemory(&BmpInfo, sizeof(BmpInfo));
     pBmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     pBmpInfo->bmiHeader.biHeight = -HEIGHT;
     pBmpInfo->bmiHeader.biWidth = WIDTH;
     pBmpInfo->bmiHeader.biBitCount = 1;
     pBmpInfo->bmiHeader.biPlanes = 1;
 
+    bReturnValue = TRUE;
+
     if (!GetDIBits(hDC, hBmp, 0, HEIGHT, BmpBits, pBmpInfo, 0))
     {
-        printf("GetDIBits failed with error %lu!\n", GetLastError());
-        goto Cleanup;
+        fprintf(stderr, "GetDIBits failed with error %lu!\n", GetLastError());
+        bReturnValue = FALSE;
     }
 
-    bReturnValue = TRUE;
+    SelectObject(hDC, hOldBmp);
+    SelectObject(hDC, hOldFont);
 
 Cleanup:
-    if (hFont)
-        DeleteObject(hFont);
-
     if (hBmp)
         DeleteObject(hBmp);
 
-    if (hDC)
-        DeleteDC(hDC);
-
     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];
-    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++)
     {
-        PlotCharacter(c, BmpBits);
+        PlotCharacter(hDC, hFont, XOffset, YOffset, (CHAR)c, BmpBits);
 
-#if 0
+#ifdef DUMP_CHAR_ON_SCREEN
         DumpCharacterOnScreen(BmpBits);
-        system("pause");
+        fprintf(stdout, "\nPress any key to continue...\n");
+        _getch();
         system("cls");
 #else
         DumpCharacterFontData(BmpBits);
 #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;
 }