123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- #include "precomp.h"
- // ============================================================================================================================================================
- // Font abstract class + statics to install TT fonts and Bitmap fonts
- // ============================================================================================================================================================
- #include <api/font/font.h>
- #include <api/font/bitmapfont.h>
- #include <bfc/parse/pathparse.h>
- #ifdef WASABI_COMPILE_SKIN
- #include <api/skin/skin.h>
- #include <api/skin/skinparse.h>
- #endif
- #include <tataki/canvas/ifc_canvas.h>
- #include <api/wnd/fontdef.h>
- #ifdef WASABI_COMPILE_FONT
- #include <api/service/svcs/svc_font.h>
- //#include "services/svc_fontmaker.h"
- #endif
- #ifdef WASABI_API_CONFIG
- #include <api/config/options.h>
- #include <api/config/items/attrint.h>
- #include <api/config/items/attrstr.h>
- #include <api/config/items/attrbool.h>
- #endif
- #include <api/memmgr/api_memmgr.h>
- #include <api/font/FontSvcEnum.h>
- extern _bool cfg_options_usefontmapper;
- extern _string cfg_options_ttfoverridefont;
- extern _int cfg_options_defaultfontscale;
- PtrList<svc_font> Font::fontlist;
- PtrList<FontDef> Font::fontdefs;
- void Font::init()
- {
- #ifdef WASABI_API_CONFIG
- Wasabi::Std::setDefaultFont(cfg_options_defaultfont.getValue());
- Wasabi::Std::setDefaultFontScale(cfg_options_defaultfontscale.getValueAsInt());
- #endif
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- void Font::dispatchTextOut(ifc_canvas *c, int style, int x, int y, int w, int h, const wchar_t *txt)
- {
- int isoverride = 0;
- if (WASABI_API_APP->main_isShuttingDown()) return;
- int size = c->getTextSize();
- svc_font *f = requestSkinFont(c->getTextFont(), &size);
- ASSERT(f != NULL);
- // After we get the font we want, check to see if it is bitmap.
- // If bitmap fonts are disallowed, use the truetype override font.
- if (f->isBitmap() && useTrueTypeOverride(txt))
- {
- int gotdefault=0;
- svc_font *ttFont = requestSkinFont(getTrueTypeOverride(), &size, &gotdefault);
- if (ttFont != NULL)
- {
- if (!gotdefault)
- isoverride = 1;
- f = ttFont;
- }
- }
- if (isoverride)
- {
- double f = (double)getTrueTypeOverrideScale() / 100.0f;
- size = (int)(size*f);
- }
- int bold = c->getTextBold();
- int opaque = c->getTextOpaque();
- int underline = c->getTextUnderline();
- int italic = c->getTextItalic();
- int align = c->getTextAlign();
- int antialiased = c->getTextAntialias();
- ARGB32 color = c->getTextColor();
- ARGB32 bkcolor = c->getTextBkColor();
- int xoffset=0, yoffset=0;
- c->getOffsets(&xoffset, &yoffset);
- /* if (!f->isBitmap() && _intVal(Main::enumRootCfgItem(0), "Force antialias on all TTF"))
- antialiased = 1;*/
- switch (style)
- {
- case WA_FONT_TEXTOUT_NORMAL:
- f->textOut(c, x, y, txt, size, bold, opaque, underline, italic, color, bkcolor, xoffset, yoffset, antialiased);
- break;
- case WA_FONT_TEXTOUT_RECT:
- f->textOut(c, x, y, w, h, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased);
- break;
- case WA_FONT_TEXTOUT_ELLIPSED:
- f->textOutEllipsed(c, x, y, w, h, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased);
- break;
- case WA_FONT_TEXTOUT_WRAPPED:
- f->textOutWrapped(c, x, y, w, h, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased);
- break;
- case WA_FONT_TEXTOUT_WRAPPEDPATHED:
- f->textOutWrappedPathed(c, x, y, w, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased);
- break;
- case WA_FONT_TEXTOUT_CENTERED:
- RECT r;
- r.left = x;
- r.top = y;
- r.right = w;
- r.bottom = h;
- f->textOutCentered(c, &r, txt, size, bold, opaque, underline, italic, align, color, bkcolor, xoffset, yoffset, antialiased);
- break;
- }
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- int Font::dispatchGetInfo(ifc_canvas *c, const wchar_t *font, int infoid, const wchar_t *txt, int *w, int *h)
- {
- int isoverride = 0;
- if (WASABI_API_APP->main_isShuttingDown()) return 0;
- // mig: Let's not crash if we want to see how big a NULL pointer is.
- if (txt == NULL) {
- if ( infoid == WA_FONT_GETINFO_WIDTHHEIGHT ) {
- if (w != NULL) {
- *w = 0;
- }
- if (h != NULL) {
- *h = 0;
- }
- }
- return 0;
- }
- int size = c->getTextSize();
- svc_font *f = requestSkinFont(font, &size);
- ASSERT(f != NULL);
- // After we get the font we want, check to see if it is bitmap.
- // If bitmap fonts are disallowed, use the truetype override font.
- if (f->isBitmap() && useTrueTypeOverride(txt))
- {
- int gotdefault = 0;
- svc_font *ttFont = requestSkinFont(getTrueTypeOverride(), &size, &gotdefault);
- if (ttFont != NULL)
- {
- if (!gotdefault)
- isoverride = 1;
- f = ttFont;
- }
- }
- if (isoverride) {
- double f = (double)getTrueTypeOverrideScale() / 100.0f;
- size = (int)(size*f);
- }
- int bold = c->getTextBold();
- int underline = c->getTextUnderline();
- int italic = c->getTextItalic();
- int antialiased = c->getTextAntialias();
- switch (infoid) {
- case WA_FONT_GETINFO_WIDTH:
- return f->getTextWidth(c, txt, size, bold, underline, italic, antialiased);
- case WA_FONT_GETINFO_HEIGHT:
- return f->getTextHeight(c, txt, size, bold, underline, italic, antialiased);
- case WA_FONT_GETINFO_WIDTHHEIGHT:
- f->getTextExtent(c, txt, w, h, size, bold, underline, italic, antialiased);
- return 0;
- }
- return 0;
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Install a truetype font from its filename and associate a script_id to it
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- svc_font *Font::installTrueTypeFont(const wchar_t *filename, const wchar_t *path, const wchar_t *id, int scriptid, int allowmapping, int isttfreload) {
-
- if (!isttfreload)
- {
- FontDef *fd = new FontDef;
- fd->filename = filename;
- fd->path = path;
- fd->id = id;
- fd->scriptid = scriptid;
- fd->isbitmap = 0;
- fd->allowmapping = allowmapping;
- fontdefs.addItem(fd);
- }
- StringW file;
-
- OSFILETYPE ff=OPEN_FAILED;
- if (wcschr(filename, ':'))
- ff = WFOPEN(filename, WF_READONLY_BINARY);
- if (ff == OPEN_FAILED)
- {
- file = StringPathCombine(path, filename);
- ff = WFOPEN(file, WF_READONLY_BINARY);
- }
- #ifdef WASABI_COMPILE_SKIN
- if (ff == OPEN_FAILED)
- {
- file = StringPathCombine(SkinParser::getXmlRootPath(), filename);
- ff = WFOPEN(file, WF_READONLY_BINARY);
- if (ff == OPEN_FAILED)
- {
- file = StringPathCombine(Skin::getDefaultSkinPath(), filename);
- ff = WFOPEN(file, WF_READONLY_BINARY);
- if (ff == OPEN_FAILED)
- {
- DebugString("Font not found %s\n", filename);
- // todo: do something if still not found
- }
- }
- }
- #endif
- if (ff == OPEN_FAILED) {
- DebugString("Could not install font %s\n", filename);
- return 0;
- }
- StringW fs = filename;
- wchar_t *p = wcschr(fs.getNonConstVal(), '.');
- if (p)
- *p = 0;
- PathParserW pp(fs);
- fs = pp.getLastString();
- svc_font *f = newTrueTypeFont();
- if (f && f->addFontResource( ff, fs) )
- {
- f->setFontId(id);
- f->setScriptId(scriptid);
- fontlist.addItem(f);
- } else {
- DebugString("font.cpp ====== CAN'T LOAD FONT FILE.\n");
- }
- FCLOSE(ff);
- return f;
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Uninstall all installed fonts
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- void Font::uninstallAll(int ttfreload) {
- int i;
- // delete all by hand
- for (i = 0; i < fontlist.getNumItems(); i++) {
- svc_font *f = fontlist.enumItem(i);
- if (ttfreload && f->isBitmap()) continue;
- deleteFont(f);
- fontlist.removeByPos(i);
- i--;
- }
- if (!ttfreload) fontdefs.deleteAll();
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Uninstall by scriptid
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- void Font::uninstallByScriptId(int scriptid) {
- for (int i=0;i<fontlist.getNumItems();i++) {
- svc_font *f = fontlist.enumItem(i);
- if (f->getScriptId() == scriptid) {
- fontlist.removeByPos(i);
- deleteFont(f);
- i--;
- }
- }
- for (int i=0;i<fontdefs.getNumItems();i++) {
- FontDef *fd = fontdefs.enumItem(i);
- if (fd->scriptid == scriptid) {
- fontdefs.removeByPos(i);
- delete fd;
- i--;
- }
- }
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Install a bitmap font and associates a script_id to it
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- void Font::installBitmapFont(const wchar_t *filename, const wchar_t *path, const wchar_t *id, int cw, int ch, int hs, int vs, int scriptid, int allowmapping)
- {
- FontDef *fd = new FontDef;
- fd->filename = filename;
- fd->path = path;
- fd->id = id;
- fd->scriptid = scriptid;
- fd->isbitmap = 1;
- fd->allowmapping = allowmapping;
- fontdefs.addItem(fd);
- BitmapFont *f = new BitmapFont;
- f->setFontBitmap(filename, path);
- f->setFontId(id);
- f->setFontMetrics(cw, ch, hs, vs);
- f->setScriptId(scriptid);
- fontlist.addItem(f);
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Requests a Font* from its id
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- svc_font *Font::requestSkinFont(const wchar_t *id, int *size, int *gotdefault)
- {
- if (gotdefault) *gotdefault = 0;
- int oldsize = size ? *size : -1;
- const wchar_t *mapped_id = getFontMapping(id, size);
- if (mapped_id != NULL)
- id = mapped_id;
- // First try to get a font by that id
- foreach_reverse(fontlist)
- const wchar_t *thisid = fontlist.getfor()->getFontId();
- if (thisid && !WCSICMP(thisid, id))
- return fontlist.getfor();
- endfor
- // if it wasnt found, try to load a wa-installed ttfont with this face name
- foreach_reverse(fontlist)
- const wchar_t *facename=fontlist.getfor()->getFaceName();
- if (facename && !WCSICMP(facename, id)) return fontlist.getfor();
- endfor
- // not found, try to reload it front the list of fonts defined by the skin
- foreach(fontdefs)
- FontDef *fd = fontdefs.getfor();
- if (!WCSICMP(fd->id, id))
- {
- if (!fd->isbitmap)
- {
- svc_font *f = installTrueTypeFont(fd->filename, fd->path, fd->id, fd->scriptid, fd->allowmapping, 1);
- if (f) return f;
- }
- }
- endfor;
- /*
- for (i=fontlist.getNumItems()-1;i>=0;i--) {
- const char *thisid = fontlist.enumItem(i)->getFontId();
- if (thisid && STRCASEEQL(thisid, "wasabi.font.ttf.default" ))
- return fontlist.enumItem(i);
- }
- */
- // not found ? try to find it in the windows fonts directory
- {
- wchar_t *fp = WMALLOC(WA_MAX_PATH);
- Wasabi::Std::getFontPath(WA_MAX_PATH, fp);
- StringW file;
- file.own(fp);
- // FREE(fp); // benski> no need because we now own it
- file.AppendPath(StringPrintfW(L"%s%s", id, WCSCASESTR(id, L".ttf") == NULL ? L".ttf":L""));
- if (!WACCESS(file, 0))
- {
- svc_font *f = newTrueTypeFont();
- f->setFontFace(id);
- f->setFontId(id);
- OSFILETYPE ff = WFOPEN(file, WF_READONLY_BINARY);
- if (ff != OPEN_FAILED)
- {
- if (f->addFontResource(ff, id))
- {
- DebugStringW(L"font.cpp ====== FONT FOR ID=%s NOT FOUND. USING WIN FONT FILE:\n%s\n", id, file.getValue());
- fontlist.addItem(f);
- }
- } else {
- DebugStringW(L"font.cpp ====== FONT FOR ID=%s NOT FOUND. CANNOT OPEN WIN FONT FILE:\n%s\n", id, file.getValue());
- delete f;
- f = NULL;
- }
- return f;
- }
- }
- // not found ? ask the Std:: interface for the folder and the
- // default fontname (ie: one you know will always be in the OS)
- svc_font *f = newTrueTypeFont();
- if (f) {
- if (gotdefault) *gotdefault = 1;
- if (oldsize != -1 && size) {
- *size = oldsize;
- double f = (double)Wasabi::Std::getDefaultFontScale() / 100.0;
- *size = (int)(*size*f);
- }
- // Query Std:: and build the path to the default font file.
- wchar_t *fontPath = WMALLOC(WA_MAX_PATH);
- Wasabi::Std::getFontPath(WA_MAX_PATH, fontPath);
- wchar_t fontFile[WA_MAX_PATH] = {0};
- Wasabi::Std::getDefaultFont(WA_MAX_PATH, fontFile);
- StringW defaultFont;
- defaultFont.own(fontPath);
- defaultFont.AppendPath(fontFile);
- // FREE(fontFile);
- StringW fs = defaultFont;
- wchar_t *p = wcschr(fs.getNonConstVal(), '.');
- if (p) *p = 0;
- PathParserW pp(fs);
- fs = pp.getLastString();
- f->setFontFace(fs);
- f->setFontId(id);
- // Open it and load it as the font resource.
- OSFILETYPE ff = WFOPEN(defaultFont, WF_READONLY_BINARY);
- if (ff != OPEN_FAILED) {
- if (f->addFontResource(ff, fs))
- {
- DebugStringW(L"font.cpp ====== FONT FOR ID=%s NOT FOUND. USING DEFAULT FONT FILE:\n%s\n", id, defaultFont);
- fontlist.addItem(f);
- }
- } else {
- DebugStringW(L"font.cpp ====== FONT FOR ID=%s NOT FOUND. CANNOT OPEN FONT FILE:\n%s\n", id, defaultFont);
- delete f;
- f = NULL;
- }
- } else {
- DebugString("font.cpp ====== CAN'T GET NEW FONT FILE.\n");
- delete f;
- f = NULL;
- }
- #ifdef _WIN32
- if (f == NULL) {
- // not found :((((( grab the default font data and use this, whatever it is
- f = newTrueTypeFont();
- if (f)
- {
- HDC dc = GetDC(GetDesktopWindow());
- HDC dc2 = CreateCompatibleDC(dc);
- SelectObject(dc2, GetStockObject(DEFAULT_GUI_FONT));
-
- int datalen = GetFontData(dc2, 0, 0, NULL, 0);
- if (datalen > 0) {
- void *mem = WASABI_API_MEMMGR->sysMalloc(datalen+1); // freed by the service !!
- ASSERT(mem != NULL);
- GetFontData(dc2, 0, 0, mem, datalen);
-
- f->setFontFace(id);
- f->setFontId(id);
- f->addFontResource2(mem, datalen, id);
- ReleaseDC(GetDesktopWindow(), dc);
- DeleteDC(dc2);
- fontlist.addItem(f);
- return f;
- }
- delete f;
- f = NULL;
- }
- }
- #else
- #warning port me
- #endif
- if (f == NULL) {
- // ok, NOW I'm getting pissed
- wchar_t fp[WA_MAX_PATH] = {0};
- Wasabi::Std::getFontPath(WA_MAX_PATH, fp);
- #ifdef _WIN32
- Wasabi::Std::messageBox(StringPrintfW(L"Fatal error trying to load truetype fonts.\n\nYou need arial.ttf at the very least, but it does not appear to be in %s", fp), L"Fatal Error", MB_ICONERROR);
- #else
- #warning port me
- #endif
- }
- //if (f == NULL) DebugString("font.cpp ====== FALLBACK FOR FONT %s CANNOT BE FOUND IN OUR LISTS.\n",f->getFontId());
-
- return f;
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Intelligently delete the font
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- void Font::deleteFont(svc_font *f)
- {
- if (f)
- {
- if (f->isBitmap())
- {
- delete static_cast<BitmapFont *>(f); // we delete our own bitmap fonts.
- }
- else
- {
- SvcEnum::release(f);
- }
- }
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Intelligently make a new truetype font from the service interfaces
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- svc_font *Font::newTrueTypeFont()
- {
- /*#ifdef WASABI_COMPILE_CONFIG
- const GUID options_guid =
- { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
- CfgItem *options = WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid);
- #endif*/
- svc_font *retval = NULL;
- const wchar_t *name = NULL;
- #ifdef WASABI_COMPILE_CONFIG
- //const wchar_t *attr = L"Font Renderer";
- // First, try to find a font service that matches the attribute.
- // if (options) {
- // char buf[256]; // WHEEE for stack arrays
- // if (options->getData(attr, buf, sizeof buf)) {
- if (WASABI_API_SKIN->skin_getVersion() >= 1.3) // hardcode win32 renderer for v1.3+ skins
- retval = FontSvcEnum(L"Win32 TextOut").getFirst();
- else
- retval = FontSvcEnum(cfg_options_fontrenderer.getValue()).getFirst();
- #else
- #ifndef WASABI_FONT_RENDERER
- #error You need to define WASABI_FONT_RENDERER (ie: #define WASABI_FONT_RENDERER "Freetype")
- #endif
- retval = FontSvcEnum(WASABI_FONT_RENDERER).getFirst();
- #endif
- #ifdef WASABI_COMPILE_CONFIG
- // }
- // }
-
- // If we can't find one, fallback and just take the first.
- if (!retval)
- {
- retval = FontSvcEnum().getFirst();
- if (retval != NULL)
- name = retval->getFontSvcName();
- }
- // If we had to fallback, remember the fallback service in the attribute.
- if (name/* && options*/)
- {
- //options->setData(attr, name);
- cfg_options_fontrenderer.setValue(name);
- }
- #endif
- return retval;
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Test whether to forbid bitmap fonts.
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- int Font::useTrueTypeOverride(const wchar_t *txt)
- {
- if (cfg_options_no7bitsttfoverride.getValueAsInt())
- {
- const wchar_t *p = (const wchar_t *)txt;
- while (p && *p)
- {
- // TODO: benski> some characters above 127 can be handled by the bitmap fonts - it might be worth checking those explicitly
- if (*p & 0xFF80)
- break;
- p++;
- }
- if (!*p) return 0;
- }
- #ifdef WASABI_COMPILE_CONFIG
- /* // {280876CF-48C0-40bc-8E86-73CE6BB462E5}
- const GUID options_guid =
- { 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
- return !_intVal(WASABI_API_CONFIG->config_getCfgItemByGuid(options_guid), "Use bitmap fonts (no international support)", 1);*/
- return !cfg_options_allowbitmapfonts.getValueAsInt();
- #else
- return WASABI_FONT_TTFOVERRIDE;
- #endif
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Get the font to be used to override bitmap fonts.
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- const wchar_t *Font::getTrueTypeOverride()
- {
- #ifdef WASABI_COMPILE_CONFIG
- return cfg_options_ttfoverridefont.getValue();
- #else
- return L"Arial";
- #warning TODO
- #endif
- }
- int Font::getTrueTypeOverrideScale()
- {
- #ifdef WASABI_COMPILE_CONFIG
- return cfg_options_ttfoverridescale.getValueAsInt();
- #else
- return 1;
- #warning TODO
- #endif
- }
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- // Returns the font mapping for this font & skin, if font mapper is on and if there is a mapping, otherwise returns null
- // -------------------------------------------------------------------------------------------------------------------------------------------------------------
- const wchar_t *Font::getFontMapping(const wchar_t *id, int *size)
- {
- if (cfg_options_usefontmapper.getValueAsInt())
- {
- wchar_t t[256]=L"";
- StringW tmp;
- tmp.printf(L"Skin:%s/Font Mapping/%s",WASABI_API_SKIN->getSkinName(), id);
- WASABI_API_CONFIG->getStringPrivate(tmp, t, 256, L"");
- tmp.printf(L"Skin:%s/Font Mapping/%s_scale",WASABI_API_SKIN->getSkinName(), id);
- int v = WASABI_API_CONFIG->getIntPrivate(tmp, -1);
- if (!*t)
- {
- tmp.printf(L"Font Mapping/%s", id);
- WASABI_API_CONFIG->getStringPrivate(tmp, t, 256, L"");
- tmp.printf(L"Font Mapping/%s_scale", id);
- v = WASABI_API_CONFIG->getIntPrivate(tmp, -1);
- }
- mapping = t;
- if (mapping.isempty()) return NULL;
- if (size != NULL)
- {
- if (v != -1)
- {
- double f = (double)v / 100.0;
- *size = (int)((double)*size * f);
- }
- }
- return mapping;
- }
- return NULL;
- }
- StringW Font::mapping;
|