////////////////////////////////////////////////////////////// /* Test the loading of application specific fonts. * Uses platform-specific coding and API's. */ #ifdef _WIN32 #define _WIN32_WINNT 0x0501 /* need at least WinXP for this API, I think */ #include #elif defined(__APPLE__) #include #else /* Assume X11 with XFT/fontconfig - this will break on systems using legacy Xlib fonts */ #include #define USE_XFT 1 #endif /* Fltk headers */ #include #include #include #include #include /*************************************************************/ static int loaded_font = 0; static Fl_Font test_font = (FL_FREE_FONT); typedef struct fontdef_ { const char *name; // FLTK font name (1st char = { ' ' | 'B' | 'I' | 'P' } const char *file; // system font (file) name to load } fontdef_t; static fontdef_t font[] = { #ifdef _WIN32 { " GFSArtemisia-Regular", "/transfer/weg/fonts/GFSArtemisia.otf" }, { "BGFSArtemisia-Bold", "/transfer/weg/fonts/GFSArtemisiaBold.otf" }, { "IGFSArtemisia-Italic", "/transfer/weg/fonts/GFSArtemisiaIt.otf" }, { "PGFSArtemisia-BoldItalic", "/transfer/weg/fonts/GFSArtemisiaBoldIt.otf" }, { " Palatino Linotype", "/transfer/weg/fonts/pala.ttf" }, { "BPalatino Linotype Fett", "/transfer/weg/fonts/palab.ttf" }, { "IPalatino Linotype Kursiv", "/transfer/weg/fonts/palai.ttf" }, { "PPalatino Linotype Fett Kursiv", "/transfer/weg/fonts/palabi.ttf" }, { " Gentium Plus", "/transfer/weg/fonts/GentiumPlus-R.ttf" }, { "BGentium Plus", "/transfer/weg/fonts/GentiumPlus-R.ttf" }, { "IGentium Plus Italic", "/transfer/weg/fonts/GentiumPlus-I.ttf" }, { "PGentium Plus Italic", "/transfer/weg/fonts/GentiumPlus-I.ttf" }, #else { " GFSArtemisia", "/transfer/weg/fonts/GFSArtemisia.otf" }, { "BGFSArtemisia", "/transfer/weg/fonts/GFSArtemisiaBold.otf" }, { "IGFSArtemisia", "/transfer/weg/fonts/GFSArtemisiaIt.otf" }, { "PGFSArtemisia", "/transfer/weg/fonts/GFSArtemisiaBoldIt.otf" }, { " Palatino Linotype", "/transfer/weg/fonts/pala.ttf" }, { "BPalatino Linotype", "/transfer/weg/fonts/palab.ttf" }, { "IPalatino Linotype", "/transfer/weg/fonts/palai.ttf" }, { "PPalatino Linotype", "/transfer/weg/fonts/palabi.ttf" }, { " Gentium Plus", "/transfer/weg/fonts/GentiumPlus-R.ttf" }, { "BGentium Plus", "/transfer/weg/fonts/GentiumPlus-R.ttf" }, { "IGentium Plus", "/transfer/weg/fonts/GentiumPlus-I.ttf" }, { "PGentium Plus", "/transfer/weg/fonts/GentiumPlus-I.ttf" }, #endif { NULL, NULL } }; /*************************************************************/ // Create some portability wrappers #ifdef _WIN32 #define i_load_private_font(PATH) AddFontResourceEx((PATH), FR_PRIVATE, 0) #define v_unload_private_font(PATH) RemoveFontResourceEx((PATH), FR_PRIVATE, 0) #elif defined(__APPLE__) #include // I use printf for error reporting in the Apple specific code! /* For the Apple case, we need to do a bit more work, since we need to convert * the PATH into a CFURLRef before we can call CTFontManagerRegisterFontsForURL() * with it. * Otherwise, all three systems would have basically the same structure here! */ static int i_load_private_font(const char *pf) { int result = 0; CFErrorRef err; // Make a URL from the font name given CFURLRef fontURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)pf, strlen(pf), false); // Try to load the font file if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &err)) { result = 1; // OK, we loaded the font, set this non-zero } else { printf("Failed loading font: %s\n", pf); } // discard the fontURL if (fontURL) CFRelease(fontURL); return result; } // i_load_private_font static void v_unload_private_font(const char *pf) { CFErrorRef err; // Make a URL from the font name given CFURLRef fontURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8 *)pf, strlen(pf), false); // Try to unregister the font CTFontManagerUnregisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &err); if (fontURL) CFRelease(fontURL); } // v_unload_private_font #else /* Assume X11 with XFT/fontconfig - will break on systems using legacy Xlib fonts */ #define i_load_private_font(PATH) (int)FcConfigAppFontAddFile(NULL, (const FcChar8 *)(PATH)) #define v_unload_private_font(PATH) FcConfigAppFontClear(NULL) #endif /*************************************************************/ class page_view : public Fl_Box { public: // constructor page_view(int x, int y, int w, int h) : Fl_Box(x, y, w, h), fn(0) {} int fn; // font number to use private: void draw(void); // draw method }; /*************************************************************/ void page_view::draw(void) { /* This is the "raw" UTF8 encoding for some symbols from the Supplementary Plane. Musical Notation in this case */ static const char notes[] = ":\xf0\x9d\x85\xa0-\xf0\x9d\x85\xa1-\xf0\x9d\x85\xa2-\xf0\x9d\x85\xa1-\xf0\x9d\x85\xa0:"; const char solo[] = "\xf0\x9d\x85\xa0"; char clefG[8]; // 1D11E /* Convert a Unicode value, 0x1D11E in this case (a G clef), into a UTF8 string using the fltk helper function */ int ll = fl_utf8encode(0x1d11e, clefG); clefG[ll] = 0; // make sure UTF8 string is NULL terminated const char *alphabet[] = { "abcdefghijklmnopqrstuvwxyz äöü ß 0123456789", "ABCDEFGHIJKLMNOPQRSTUVWXYZ ÄÖÜ", "!“§$%&/()=? € µ@ł€¶ŧ←↓→øþſðđŋħł\n" }; int x0 = x(); // origin is w.r.t. the Fl_Box int y0 = y(); int w0 = w(); int h0 = h(); fl_push_clip(x0, y0, w0, h0); // clip to the current page view // set the background colour fl_color(FL_WHITE); fl_rectf(x0, y0, w0, h0); // Basic string in default font test fl_font(FL_HELVETICA, 30); fl_color(FL_BLACK); fl_draw("This is the default font (FL_HELVETICA)", x0 + 25, y0 + 100); // Test the "private" font the application has loaded for its own use fl_font(fn, 40); fl_color(FL_BLACK); fl_draw("This is the private font we loaded", x0 + 25, y0 + 200); fl_font(fn, 25); fl_color(FL_DARK_RED); fl_draw("Here are some glyphs from the SMP using the test font", x0 + 25, y0 + 250); fl_font(fn, 40); fl_color(FL_BLACK); // Special notes test fl_draw(notes, x0 + 25, y0 + 300); // SINGLE note test fl_draw(solo, x0 + 225, y0 + 300); // CLEF test fl_draw(clefG, x0 + 300, y0 + 300); // clefG // Display of the "alphabet" including some special characters fl_font(fn, 24); fl_color(FL_BLUE); fl_draw(alphabet[0], x0 + 25, y0 + 400); // 1st line fl_draw(alphabet[1], x0 + 25, y0 + 430); // 2nd line fl_draw(alphabet[2], x0 + 25, y0 + 460); // 3rd line fl_pop_clip(); // restore the default clip region } // draw method /*****************************************************************************/ static int load_extra_font(int fn) { int maxfn = int(sizeof(font) / sizeof(fontdef_t)) - 2; if (fn < 0 || fn > maxfn) { fprintf(stderr, "Font number %d out of range (0 - %d)\n", fn, maxfn); return 0; } fontdef_t *ft = &font[fn]; // -> internal font definition /* Load the font using the appropriate platform API */ loaded_font = i_load_private_font(ft->file); /* set the extra font */ if (loaded_font) { Fl::set_font(test_font + fn, ft->name); fprintf(stderr, "Loaded font #%2d: '%-32.32s' = %s\n", fn, ft->name, ft->file); } else { fprintf(stderr, "Error loading font #%2d: '%-32.32s' = %s\n", fn, ft->name, ft->file); } return loaded_font; } // load_extra_font /*****************************************************************************/ static void free_extra_font(void) { if (loaded_font) { v_unload_private_font(font[0].file); } loaded_font = 0; } // free_extra_font /*****************************************************************************/ int main(int argc, char **argv) { setvbuf(stdout, NULL, _IONBF, 0); // set stdout unbuffered setvbuf(stderr, NULL, _IONBF, 0); // set stderr unbuffered int fn = 0; if (argc > 1) fn = atoi(argv[1]); static char title[512]; sprintf(title, "Font: '%s', File: '%s'", font[fn].name, font[fn].file); Fl_Window *main_win = new Fl_Window(750, 520, title); /* Load our additional fonts */ int numf = sizeof(font) / sizeof(fontdef_t) - 1; for (int i = 0; i < numf; i++) { int suc = load_extra_font(i); if (!suc) return 1; } page_view *test_page = new page_view(5, 5, (main_win->w() - 10), (main_win->h() - 10)); test_page->type(FL_FLAT_BOX); test_page->fn = test_font + fn; main_win->end(); main_win->resizable(test_page); // Show the test window main_win->show(1 /* argc */, argv); /* Run the fltk event loop */ int result = Fl::run(); /* Unload the private font we loaded earlier */ free_extra_font(); return result; } /* end of file */