Skip to content

Instantly share code, notes, and snippets.

@hoehrmann
Created May 27, 2013 12:48
Show Gist options
  • Save hoehrmann/5656898 to your computer and use it in GitHub Desktop.
Save hoehrmann/5656898 to your computer and use it in GitHub Desktop.
The attached file is a simple program that uses the Windows GDI routine EnumFontFamiliesEx and the Uniscribe ScriptGetCMap procedure to enumerate all installed True Type fonts and for each font it lists all glyphs in the BMP it supports. Works only on NT-based Windows. Originally http://lists.w3.org/Archives/Public/www-archive/2007May/0072.html
////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2007 Bjoern Hoehrmann <[email protected]>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// $Id$
//
////////////////////////////////////////////////////////////////////
// Pretend to be Windows 2000 to ensure the NT-only functions
// are available; implies the program does not run elsewhere.
#define _WIN32_WINNT 0x0500
#define WINVER 0x0500
#include <windows.h>
#include <Windowsx.h>
#include <Usp10.h>
#include <stdio.h>
// Link to uniscribe
#pragma comment(lib, "Usp10")
int CALLBACK
MyFontProc(ENUMLOGFONTEXDV *lpelfe,
ENUMTEXTMETRIC *lpntme,
DWORD FontType,
LPARAM lParam) {
HDC hdc = (HDC)lParam;
SCRIPT_CACHE psc = NULL;
WORD out;
HRESULT hr;
HFONT hfont;
WCHAR c;
// Skip device and raster fonts, ScriptGetCMap returns bogus
// values for them; maybe there is a better check for this.
if (!(FontType & TRUETYPE_FONTTYPE))
return 1;
hfont = CreateFontIndirectEx(lpelfe);
if (hfont == NULL)
return 0;
if (SelectFont(hdc, hfont) == NULL) {
DeleteFont(hfont);
return 0;
}
// Use the Face Name rather than the full name to avoid some
// surprises in the area of localization and elsewhere.
printf("%s\n", lpelfe->elfEnumLogfontEx.elfLogFont.lfFaceName);
// It might be more efficient to build a string containing all
// characters and subsequently scan the result, but this is not
// meant to be efficient; also, this should be able to handle
// non-BMP characters, but going brute force over them is not
// cost effective.
for (c = 0; c < 0xFFFF; ++c) {
hr = ScriptGetCMap(hdc, &psc, &c, 1, 0, &out);
if (hr == S_FALSE)
continue;
if (hr == S_OK) {
printf("\tU+%04X\n", c);
continue;
}
fprintf(stderr, "An internal error occured\n");
DeleteFont(hfont);
return 0;
}
DeleteFont(hfont);
return 1;
}
int
main(void) {
HDC hdc = GetDC(NULL);
LOGFONT lf;
int rc;
if (hdc == NULL) {
fprintf(stderr, "An internal error occured\n");
return EXIT_FAILURE;
}
lf.lfCharSet = DEFAULT_CHARSET;
lf.lfFaceName[0] = 0;
lf.lfPitchAndFamily = 0;
rc = EnumFontFamiliesEx(hdc,
&lf,
(FONTENUMPROC)MyFontProc,
(LPARAM)hdc,
0);
ReleaseDC(NULL, hdc);
if (rc == 0) {
fprintf(stderr, "An internal error occured\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment