void ProcessFont(HWND hWnd, std::wstring const& fontName, int weight, int size, DWORD italic) { HDC hDC = GetDC(hWnd); SetTextColor(hDC, RGB(0, 0, 0)); SetBkColor(hDC, RGB(255, 255, 255)); // Create the font. HFONT hFont = CreateFont(size, 0, 0, 0, weight, italic, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, VARIABLE_PITCH, fontName.c_str()); HGDIOBJ oldFont = SelectObject(hDC, hFont); RECT r; r.left = r.top = 0; r.right = gWindowWidth - 1; r.bottom = gWindowHeight - 1; FillRect(hDC, &r, nullptr); wchar_t msg[256]; wsprintf(msg, L"Rendering %s, weight = %d, size = %d, italics = %d", fontName.c_str(), weight, size, italic); TextOut(hDC, 8, 3*size, msg, (int)wcslen(msg)); int width, height; unsigned char* texels; float characterData[257]; CreateFontData(hDC, width, height, texels, characterData); CreateHeaderFile(fontName, weight, size, italic); CreateSourceFile(fontName, weight, size, italic, width, height, texels, characterData); delete[] texels; SelectObject(hDC, oldFont); DeleteObject(hFont); ReleaseDC(hWnd, hDC); }
iResourceBase* cFontManager::Create(const tString& asName) { return CreateFontData(asName, 16, 32, 255); }
BOOL OnLoadFont() { int i; char path[260] = {0}; // Set up file name requester data OPENFILENAME ofn; memset(&ofn, 0, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = appWnd; ofn.lpstrFilter = appSaveFilter; ofn.lpstrFile = path; ofn.nMaxFile = sizeof(path); // Get open file name if (GetOpenFileName(&ofn)) { // Open the font file for read FILE *file = fopen(path, "rb"); // If the file couldn't be opened... if (!file) { // Exit return FALSE; } // Read the font header fread(&fontHeader, sizeof(fontHeader), 1, file); // If the font identifier doesn't match... if (fontHeader.fontIdent != FONT_ID) { // Bail out fclose(file); return FALSE; } // Create font data CreateFontData(fontHeader.numChar); // Read all the font character headers fread(charHeaderList, sizeof(CharHeader), fontHeader.numChar, file); // Read all character images for (i = 0; i < fontHeader.numChar; i++) { // Get character image size CharImage size; fread(&size, sizeof(size), 1, file); // Allocate character image CharImage *charImage = (CharImage *) new BYTE [sizeof(CharImage) + size.charWidth * size.charHeight]; // Add character image to list charImageList[i] = charImage; // Copy character image size charImage->charWidth = size.charWidth; charImage->charHeight = size.charHeight; // Read character image data fread(charImage->charData, 1, charImage->charWidth * charImage->charHeight, file); } // Close the font file fclose(file); // File was read successfully return TRUE; } else { // File was not read successfully return FALSE; } }
BOOL OnCaptureFont() { int i; CHOOSEFONT cf; // Init CHOOSEFONT structure memset(&cf, 0, sizeof(cf)); cf.lStructSize = sizeof(cf); cf.lpLogFont = &appLogFont; cf.hwndOwner = appWnd; cf.Flags = CF_SCREENFONTS; if (appFont) { cf.Flags |= CF_INITTOLOGFONTSTRUCT; } // Select a font if (ChooseFont(&cf)) { // if a font already exists... if (appFont) { // delete the old font DeleteObject(appFont); appFont = NULL; } // remember the point size int size = appLogFont.lfHeight; // scale the point size appLogFont.lfHeight = size * appFontScale; // create the new font appFont = CreateFontIndirect(&appLogFont); // restore the point size appLogFont.lfHeight = size; } else { return FALSE; } // Delete any existing font data DeleteFontData(); // Capture it now HDC hDC; if (!appFont) { return FALSE; } hDC = GetDC(appWnd); if (hDC) { EDispMode oldMode; /* { KERNINGPAIR kp[256]; DWORD np; np = GetKerningPairs(hDC, 256, kp); for (i = 0; i < np; i++) { LOG_DIAG(("Kerning pair: %c -> %c = %d", (char)kp[i].wFirst, (char)kp[i].wSecond, kp[i].iKernAmount)); } } */ oldMode = dispMode; dispMode = DISP_CAPTURE; // Set up DC SelectObject(hDC, appFont); SelectObject(hDC, GetStockObject(BLACK_BRUSH)); // Calculate max sizes of any font character TEXTMETRICW tmw; TEXTMETRIC tma; RECT cli; RECT win; int tmMaxCharWidth; int tmHeight; int tmLastChar; int tmFirstChar; int tmAscent; int tmDescent; int tmCharSet; GLYPHSET *gs = NULL; if (UnicodeMode()) { gs = (GLYPHSET *)malloc(sizeof(GLYPHSET) + sizeof(WCRANGE) * 5000); if (!fnGetFontUnicodeRanges || !fnGetFontUnicodeRanges(hDC, gs)) { MessageBox(appWnd, "GetFontUnicodeRanges failed", "Error", MB_OK); return (FALSE); } GetTextMetricsW(hDC, &tmw); tmMaxCharWidth = tmw.tmMaxCharWidth; tmHeight = tmw.tmHeight; tmLastChar = tmw.tmLastChar; tmFirstChar = tmw.tmFirstChar; tmAscent = tmw.tmAscent; tmDescent = tmw.tmDescent; tmCharSet = tmw.tmCharSet; // Create new font data CreateFontData(gs->cGlyphsSupported); } else { GetTextMetrics(hDC, &tma); tmMaxCharWidth = tma.tmMaxCharWidth; tmHeight = tma.tmHeight; tmLastChar = tma.tmLastChar; tmFirstChar = tma.tmFirstChar; tmAscent = tma.tmAscent; tmDescent = tma.tmDescent; tmCharSet = tma.tmCharSet; // Create new font data CreateFontData(tmLastChar - tmFirstChar + 1); } GetClientRect(appWnd, &cli); GetWindowRect(appWnd, &win); if (cli.right < tmMaxCharWidth || cli.bottom < tmHeight) { int newW;// = max(cli.right, tm.tmMaxCharWidth); int newH;// = max(cli.bottom, tm.tmHeight); newW = (win.right - win.left) - (cli.right - cli.left) + max(cli.right, tmMaxCharWidth); newH = (win.bottom - win.top) - (cli.bottom - cli.top) + max(cli.bottom, tmHeight); MoveWindow(appWnd, win.left, win.top, newW, newH, TRUE); } // Calculate y shift int yShift = -tmAscent % appFontScale; if (GetAsyncKeyState(VK_MENU) < 0) { char buf[1024]; char *chSet = "Unknown"; switch (tmCharSet) { case ANSI_CHARSET: chSet = "ANSI"; break; case DEFAULT_CHARSET: chSet = "DEFAULT"; break; case SYMBOL_CHARSET: chSet = "SYMBOL"; break; case SHIFTJIS_CHARSET: chSet = "SHIFTJIS"; break; case HANGUL_CHARSET: chSet = "HANGUL"; break; case GB2312_CHARSET: chSet = "GP2312"; break; case CHINESEBIG5_CHARSET: chSet = "CHINESEBIG5"; break; case OEM_CHARSET: chSet = "OEM"; break; case JOHAB_CHARSET: chSet = "JOHAB"; break; case HEBREW_CHARSET: chSet = "HEBREW"; break; case ARABIC_CHARSET: chSet = "ARABIC"; break; case GREEK_CHARSET: chSet = "GREEK"; break; case TURKISH_CHARSET: chSet = "TURKISH"; break; case VIETNAMESE_CHARSET: chSet = "VIETNAMESE"; break; case THAI_CHARSET: chSet = "THAI"; break; case EASTEUROPE_CHARSET: chSet = "EASTEUROPE"; break; case RUSSIAN_CHARSET: chSet = "RUSSIAN"; break; case MAC_CHARSET: chSet = "MAC"; break; case BALTIC_CHARSET: chSet = "BALTIC"; break; } if (gs) { wsprintf(buf, "size=%d\ncharset=%s\nranges=%d\ntotal=%d", tmHeight, chSet, gs->cRanges, gs->cGlyphsSupported); } else { wsprintf(buf, "size=%d\nchars range=%d .. %d\ncharset=%s\ntotal=%d", tmHeight, tmFirstChar, tmLastChar, chSet, fontHeader.numChar); } MessageBox(appWnd, buf, "Info", MB_OK); } // Fill in the font header fontHeader.fontHeight = (BYTE)((tmHeight + yShift) / appFontScale); fontHeader.fontAscent = (BYTE)((tmAscent + yShift) / appFontScale); fontHeader.fontDescent = (BYTE)((tmDescent) / appFontScale); S32 pct = -1; if (UnicodeMode()) { int i = 0; for (int range = 0; range < gs->cRanges; range++) { for (int gch = 0; gch < gs->ranges[range].cGlyphs; gch++) { CaptureOneChar(hDC, i, gch + gs->ranges[range].wcLow, yShift); i++; } } } else { for (i = 0; i < fontHeader.numChar; i++) { CaptureOneChar(hDC, i, i + tmFirstChar, yShift); } } /* // Display and capture each letter for (i = 0; i < fontHeader.numChar; i++) { int x, y, xx, yy; SIZE charSize; // Generate character value int charValue = i + tmFirstChar; // Display the character InvalidateRect(appWnd, NULL, TRUE); UpdateWindow(appWnd); if (UnicodeMode()) { CH str[2] = { CH(charValue), 0 }; GetTextExtentPoint32W(hDC, str, 1, &charSize); TextOutW(hDC, 0, 0, str, 1); } else { char str[2] = { char(charValue), 0}; GetTextExtentPoint32(hDC, str, 1, &charSize); TextOut(hDC, 0, 0, str, 1); } GdiFlush(); // Clear character rectangle RECT charRect; charRect.left = LONG_MAX; charRect.top = LONG_MAX; charRect.right = LONG_MIN; charRect.bottom = LONG_MIN; bool setRect = false; // Determine clipping rectangle for (y = 0; y < charSize.cy; y++) { for (x = 0; x < charSize.cx; x++) { // Capture the pixel COLORREF clr = GetPixel(hDC, x, y + yShift); // If the pixel is not white... if (GetRValue(clr) < 255) { // Update the character rectangle if (charRect.left > x) charRect.left = x; if (charRect.top > y) charRect.top = y; if (charRect.right < x) charRect.right = x; if (charRect.bottom < y) charRect.bottom = y; setRect = true; } } } if (setRect) { // Calculate x shift int xShift = charRect.left % appFontScale; // Rescale the size charSize.cx = (charSize.cx + appFontScale - 1) / appFontScale; charSize.cy = (charSize.cy + appFontScale - 1) / appFontScale; // Rescale the rectangle charRect.left = (charRect.left - xShift) / appFontScale; charRect.top = charRect.top / appFontScale; charRect.right = (charRect.right - xShift) / appFontScale + 1; charRect.bottom = (charRect.bottom) / appFontScale + 1; // Get width and height int w = charRect.right - charRect.left; int h = charRect.bottom - charRect.top; // Create a new character image CharImage *charImage = (CharImage *) new BYTE [sizeof(CharImage) + w * h]; // Push the character image into the character list charImageList[i] = charImage; // Store the character dimensions charImage->charWidth = (BYTE)w; charImage->charHeight = (BYTE)h; // Start in the upper left corner BYTE *pixel = charImage->charData; // Capture the character for (y = charRect.top; y < charRect.bottom; y++) { for (x = charRect.left; x < charRect.right; x++) { // Clear the pixel sum DWORD sum = 0; // Average value over block for (yy = (y) * appFontScale; yy < (y + 1) * appFontScale; yy++) { for (xx = (x) * appFontScale; xx < (x + 1) * appFontScale; xx++) { // Capture the pixel COLORREF clr = GetPixel(hDC, xx + xShift, yy + yShift); // Add pixel intensity to sum sum += GetRValue(clr); } } // Get the average pixel intensity sum = (sum + sum + appFontScale2) / (appFontScale2 + appFontScale2); // Store the pixel value *pixel++ = U8(0xFF - (BYTE)sum); } } // Get the current character header CharHeader *charHeader = &charHeaderList[i]; // Fill in the character header charHeader->charValue = (CH)charValue; charHeader->fullWidth = (BYTE)charSize.cx; charHeader->rectX0 = (BYTE)charRect.left; charHeader->rectY0 = (BYTE)charRect.top; charHeader->rectX1 = (BYTE)charRect.right; charHeader->rectY1 = (BYTE)charRect.bottom; } else { // Rescale the size charSize.cx = (charSize.cx + appFontScale - 1) / appFontScale; charSize.cy = (charSize.cy + appFontScale - 1) / appFontScale; // Create a new character image CharImage *charImage = (CharImage *) new BYTE [sizeof(CharImage)]; // Push the character image into the character list charImageList[i] = charImage; // Zero width and height charImage->charWidth = 0; charImage->charHeight = 0; // Get the current character header CharHeader *charHeader = &charHeaderList[i]; // Fill in the character header charHeader->charValue = (CH)charValue; charHeader->fullWidth = (BYTE)charSize.cx; charHeader->rectX0 = 0; charHeader->rectY0 = 0; charHeader->rectX1 = 0; charHeader->rectY1 = 0; } // Update window text S32 newPct = S32(F32(i) * 100.0F / F32(fontHeader.numChar)); if (pct != newPct) { char buf[256]; pct = newPct; sprintf(buf, ProgressCaption, fontHeader.numChar, pct); SetWindowText(appWnd, buf); } } */ // Restore window text SetWindowText(appWnd, DefaultCaption); dispMode = oldMode; InvalidateRect(appWnd, NULL, TRUE); ReleaseDC(appWnd, hDC); } return TRUE; }