gFont.cpp
Classes:
class
Used for repacking in GFont::importStrip.
Public Functions
DefineEngineFunction(dumpFontCacheStatus , void , () , "Dumps <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the console <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> full description of all cached fonts, along with " "info on the codepoints each <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">contains.\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(duplicateCachedFont , void , (const char *oldFontName, S32 oldFontSize, const char *newFontName) , "Copy the specified old font <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> name. The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> copy will not have <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "platform font backing it, and so will never have characters added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> it. " "But this is useful <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> making copies of fonts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add postprocessing effects " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> via <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exportCachedFont.\n</a>" " @param oldFontName The name of the font face <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">copy.\n</a>" " @param oldFontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">copy.\n</a>" " @param newFontName The name of the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(exportCachedFont , void , (const char *faceName, S32 fontSize, const char *fileName, S32 padding, S32 kerning) , "Export specified font <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the specified filename as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> PNG. The " "image can then be processed in Photoshop or another tool and " "reimported using importCachedFont. Characters in the font are " "exported as one long <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">strip.\n</a>" "@param faceName The name of the font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" "@param fontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param fileName The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name and path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the output <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PNG.\n</a>" "@param padding The padding between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">characters.\n</a>" "@param kerning The kerning between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">characters.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(importCachedFont , void , (const char *faceName, S32 fontSize, const char *fileName, S32 padding, S32 kerning) , "Import an image strip from exportCachedFont. Call with the " "same parameters you called <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exportCachedFont.\n</a>" "@param faceName The name of the font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" "@param fontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param fileName The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name and path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the input <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PNG.\n</a>" "@param padding The padding between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">characters.\n</a>" "@param kerning The kerning between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">characters.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(populateAllFontCacheRange , void , (U32 rangeStart, U32 rangeEnd) , "Populate the font cache <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> all fonts with Unicode code points in the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">range.\n</a>" "@param rangeStart The start Unicode <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">point.\n</a>" "@param rangeEnd The end Unicode <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">point.\n</a>" "@note We only support BMP- 0, so code points range from 0 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 65535.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(populateAllFontCacheString , void , (const char *string) , "Populate the font cache <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> all fonts with characters from the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">string.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(populateFontCacheRange , void , (const char *faceName, S32 fontSize, U32 rangeStart, U32 rangeEnd) , "Populate the font cache <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the specified font with Unicode code points in the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">range.\n</a>" "@param faceName The name of the font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" "@param fontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param rangeStart The start Unicode <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">point.\n</a>" "@param rangeEnd The end Unicode <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">point.\n</a>" "@note We only support BMP- 0, so code points range from 0 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 65535.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(populateFontCacheString , void , (const char *faceName, S32 fontSize, const char *string) , "Populate the font cache <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the specified font with characters from the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">string.\n</a>" "@param faceName The name of the font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" "@param fontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param string The string <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">populate.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(writeFontCache , void , () , "Force all cached fonts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> serialize themselves <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">cache.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
GFX_ImplementTextureProfile(GFXFontTextureProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da23d780ef2bcc57521a4945415ce5207f">GFXTextureProfile::Static</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daa6bb823fc92adbec55ba4c34cd586062">GFXTextureProfile::KeepBitmap</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap , GFXTextureProfile::NONE )
GlyphMapCompare(const void * a, const void * b)
Detailed Description
Public Functions
DefineEngineFunction(dumpFontCacheStatus , void , () , "Dumps <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the console <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> full description of all cached fonts, along with " "info on the codepoints each <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">contains.\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(duplicateCachedFont , void , (const char *oldFontName, S32 oldFontSize, const char *newFontName) , "Copy the specified old font <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> name. The <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> copy will not have <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> " "platform font backing it, and so will never have characters added <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> it. " "But this is useful <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> making copies of fonts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add postprocessing effects " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> via <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exportCachedFont.\n</a>" " @param oldFontName The name of the font face <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">copy.\n</a>" " @param oldFontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">copy.\n</a>" " @param newFontName The name of the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(exportCachedFont , void , (const char *faceName, S32 fontSize, const char *fileName, S32 padding, S32 kerning) , "Export specified font <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the specified filename as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> PNG. The " "image can then be processed in Photoshop or another tool and " "reimported using importCachedFont. Characters in the font are " "exported as one long <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">strip.\n</a>" "@param faceName The name of the font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" "@param fontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param fileName The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name and path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the output <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PNG.\n</a>" "@param padding The padding between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">characters.\n</a>" "@param kerning The kerning between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">characters.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(importCachedFont , void , (const char *faceName, S32 fontSize, const char *fileName, S32 padding, S32 kerning) , "Import an image strip from exportCachedFont. Call with the " "same parameters you called <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">exportCachedFont.\n</a>" "@param faceName The name of the font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" "@param fontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param fileName The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name and path <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the input <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PNG.\n</a>" "@param padding The padding between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">characters.\n</a>" "@param kerning The kerning between <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">characters.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(populateAllFontCacheRange , void , (U32 rangeStart, U32 rangeEnd) , "Populate the font cache <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> all fonts with Unicode code points in the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">range.\n</a>" "@param rangeStart The start Unicode <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">point.\n</a>" "@param rangeEnd The end Unicode <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">point.\n</a>" "@note We only support BMP- 0, so code points range from 0 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 65535.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(populateAllFontCacheString , void , (const char *string) , "Populate the font cache <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> all fonts with characters from the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">string.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(populateFontCacheRange , void , (const char *faceName, S32 fontSize, U32 rangeStart, U32 rangeEnd) , "Populate the font cache <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the specified font with Unicode code points in the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">range.\n</a>" "@param faceName The name of the font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" "@param fontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param rangeStart The start Unicode <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">point.\n</a>" "@param rangeEnd The end Unicode <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">point.\n</a>" "@note We only support BMP- 0, so code points range from 0 <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> 65535.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(populateFontCacheString , void , (const char *faceName, S32 fontSize, const char *string) , "Populate the font cache <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the specified font with characters from the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">string.\n</a>" "@param faceName The name of the font <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">face.\n</a>" "@param fontSize The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1ab7d671599a7b25ca99a487fa341bc33a">size</a> of the font in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">pixels.\n</a>" "@param string The string <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">populate.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
DefineEngineFunction(writeFontCache , void , () , "Force all cached fonts <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> serialize themselves <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">cache.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Font\n</a>" )
GFX_ImplementTextureProfile(GFXFontTextureProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da23d780ef2bcc57521a4945415ce5207f">GFXTextureProfile::Static</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daa6bb823fc92adbec55ba4c34cd586062">GFXTextureProfile::KeepBitmap</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap , GFXTextureProfile::NONE )
GlyphMapCompare(const void * a, const void * b)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "gfx/gFont.h" 26 27#include "core/resourceManager.h" 28#include "core/stream/fileStream.h" 29#include "core/strings/unicode.h" 30#include "core/strings/findMatch.h" 31#include "core/strings/stringFunctions.h" 32#include "core/util/endian.h" 33#include "core/util/safeDelete.h" 34#include "console/console.h" 35#include "console/engineAPI.h" 36#include "platform/threads/mutex.h" 37#include "zlib/zlib.h" 38 39 40GFX_ImplementTextureProfile(GFXFontTextureProfile, 41 GFXTextureProfile::DiffuseMap, 42 GFXTextureProfile::PreserveSize | 43 GFXTextureProfile::Static | 44 GFXTextureProfile::KeepBitmap | 45 GFXTextureProfile::NoMipmap, 46 GFXTextureProfile::NONE); 47 48template<> void *Resource<GFont>::create(const Torque::Path &path) 49{ 50#ifdef TORQUE_DEBUG_RES_MANAGER 51 Con::printf( "Resource<GFont>::create - [%s]", path.getFullPath().c_str() ); 52#endif 53 54 return GFont::load( path ); 55} 56 57template<> ResourceBase::Signature Resource<GFont>::signature() 58{ 59 return MakeFourCC('f','o','n','t'); 60} 61 62/// Used for repacking in GFont::importStrip. 63struct GlyphMap 64{ 65 U32 charId; 66 GBitmap *bitmap; 67}; 68 69static S32 QSORT_CALLBACK GlyphMapCompare(const void *a, const void *b) 70{ 71 S32 ha = ((GlyphMap *) a)->bitmap->getHeight(); 72 S32 hb = ((GlyphMap *) b)->bitmap->getHeight(); 73 74 return hb - ha; 75} 76 77 78const U32 GFont::csm_fileVersion = 3; 79 80String GFont::getFontCacheFilename(const String &faceName, U32 size) 81{ 82 return String::ToString("%s/%s %d (%s).uft", 83 Con::getVariable("$GUI::fontCacheDirectory"), faceName.c_str(), size, getCharSetName(0)); 84} 85 86GFont* GFont::load( const Torque::Path& path ) 87{ 88 FileStream stream; 89 90 stream.open( path.getFullPath(), Torque::FS::File::Read ); 91 if ( stream.getStatus() != Stream::Ok ) 92 return NULL; 93 94 GFont *ret = new GFont; 95 ret->mGFTFile = path; 96 97 if(!ret->read(stream)) 98 { 99 Con::errorf( "GFont::load - error reading '%s'", path.getFullPath().c_str() ); 100 SAFE_DELETE(ret); 101 } 102 else 103 { 104 PlatformFont *platFont = createPlatformFont(ret->getFontFaceName(), ret->getFontSize(), ret->getFontCharSet()); 105 106 if ( platFont == NULL ) 107 { 108 Con::errorf( "GFont::load - error creating platform font for '%s'", path.getFullPath().c_str() ); 109 SAFE_DELETE(ret); 110 } 111 else 112 ret->setPlatformFont(platFont); 113 } 114 115 return ret; 116} 117 118Resource<GFont> GFont::create(const String &faceName, U32 size, const char *cacheDirectory, U32 charset /* = TGE_ANSI_CHARSET */) 119{ 120 if( !cacheDirectory ) 121 cacheDirectory = Con::getVariable( "$GUI::fontCacheDirectory" ); 122 123 const Torque::Path path( String::ToString("%s/%s %d (%s).uft", 124 cacheDirectory, faceName.c_str(), size, getCharSetName(charset)) ); 125 126 Resource<GFont> ret; 127 128 // If the file already exists attempt to load it 129 if (Platform::isFile(path.getFullPath().c_str())) 130 { 131 ret = ResourceManager::get().load(path); 132 133 if (ret != NULL) 134 { 135 ret->mGFTFile = path; 136 return ret; 137 } 138 } 139 140 // Otherwise attempt to have the platform generate a new font 141 PlatformFont *platFont = createPlatformFont(faceName, size, charset); 142 143 if (platFont == NULL) 144 { 145 String fontName; 146 147#ifdef _XBOX 148 //AssertFatal( false, "Font creation is not supported on the Xbox platform. Create the font files (*.uft) using the Windows/MacOS build of the project." ); 149 if(!faceName.equal("arial", String::NoCase) || size != 14) 150 { 151 return create("Arial", 14, cacheDirectory, charset); 152 } 153 return ret; 154#endif 155 156 // Couldn't load the requested font. This probably will be common 157 // since many unix boxes don't have arial or lucida console installed. 158 // Attempt to map the font name into a font we're pretty sure exist 159 // Lucida Console is a common code & console font on windows, and 160 // Monaco is the recommended code & console font on mac. 161 if (faceName.equal("arial", String::NoCase)) 162 fontName = "Helvetica"; 163 else if (faceName.equal("lucida console", String::NoCase)) 164 fontName = "Monaco"; 165 else if (faceName.equal("monaco", String::NoCase)) 166 fontName = "Courier"; 167 else 168 return ret; 169 170 return create(fontName, size, cacheDirectory, charset); 171 } 172 173 // Create the actual GFont and set some initial properties 174 GFont *font = new GFont; 175 font->mPlatformFont = platFont; 176 font->mGFTFile = path; 177 font->mFaceName = faceName; 178 font->mSize = size; 179 font->mCharSet = charset; 180 181 font->mHeight = platFont->getFontHeight(); 182 font->mBaseline = platFont->getFontBaseLine(); 183 font->mAscent = platFont->getFontBaseLine(); 184 font->mDescent = platFont->getFontHeight() - platFont->getFontBaseLine(); 185 186 // Flag it to save when we exit 187 font->mNeedSave = true; 188 189 // Load the newly created font into the ResourceManager 190 ret.setResource(ResourceManager::get().load(path), font); 191 192 return ret; 193} 194 195//------------------------------------------------------------------------- 196 197GFont::GFont() 198{ 199 VECTOR_SET_ASSOCIATION(mCharInfoList); 200 VECTOR_SET_ASSOCIATION(mTextureSheets); 201 202 std::fill_n(mRemapTable, Font_Table_MAX,-1); 203 204 mCurX = mCurY = mCurSheet = -1; 205 206 mPlatformFont = NULL; 207 mSize = 0; 208 mCharSet = 0; 209 mHeight = 0; 210 mBaseline = 0; 211 mAscent = 0; 212 mDescent = 0; 213 mNeedSave = false; 214 215 mMutex = Mutex::createMutex(); 216} 217 218GFont::~GFont() 219{ 220 if(mNeedSave) 221 { 222 AssertFatal( mGFTFile.getFullPath().isNotEmpty(), "GFont::~GFont - path not set" ); 223 224 FileStream stream; 225 stream.open(mGFTFile, Torque::FS::File::Write); 226 227 if(stream.getStatus() == Stream::Ok) 228 write(stream); 229 230 stream.close(); 231 } 232 233 S32 i; 234 235 for(i = 0;i < mCharInfoList.size();i++) 236 { 237 SAFE_DELETE_ARRAY(mCharInfoList[i].bitmapData); 238 } 239 240 for(i=0; i<mTextureSheets.size(); i++) 241 mTextureSheets[i] = NULL; 242 243 SAFE_DELETE(mPlatformFont); 244 245 Mutex::destroyMutex(mMutex); 246} 247 248void GFont::dumpInfo() const 249{ 250 // Number and extent of mapped characters? 251 U32 mapCount = 0, mapBegin=0xFFFF, mapEnd=0; 252 for(U32 i=0; i<0x10000; i++) 253 { 254 if(mRemapTable[i] != -1) 255 { 256 mapCount++; 257 if(i<mapBegin) mapBegin = i; 258 if(i>mapEnd) mapEnd = i; 259 } 260 } 261 262 263 // Let's write out all the info we can on this font. 264 Con::printf(" '%s' %dpt", mFaceName.c_str(), mSize); 265 Con::printf(" - %d texture sheets, %d mapped characters.", mTextureSheets.size(), mapCount); 266 267 if(mapCount) 268 Con::printf(" - Codepoints range from 0x%x to 0x%x.", mapBegin, mapEnd); 269 else 270 Con::printf(" - No mapped codepoints."); 271 Con::printf(" - Platform font is %s.", (mPlatformFont ? "present" : "not present") ); 272} 273 274//----------------------------------------------------------------------------- 275 276bool GFont::loadCharInfo(const UTF16 ch) 277{ 278 PROFILE_SCOPE(GFont_loadCharInfo); 279 280 if(mRemapTable[ch] != -1) 281 return true; // Not really an error 282 283 if(mPlatformFont && mPlatformFont->isValidChar(ch)) 284 { 285 Mutex::lockMutex(mMutex); // the CharInfo returned by mPlatformFont is static data, must protect from changes. 286 PlatformFont::CharInfo &ci = mPlatformFont->getCharInfo(ch); 287 if(ci.bitmapData) 288 addBitmap(ci); 289 290 mCharInfoList.push_back(ci); 291 mRemapTable[ch] = mCharInfoList.size() - 1; 292 293 mNeedSave = true; 294 295 Mutex::unlockMutex(mMutex); 296 return true; 297 } 298 299 return false; 300} 301 302void GFont::addBitmap(PlatformFont::CharInfo &charInfo) 303{ 304 U32 nextCurX = U32(mCurX + charInfo.width ); /*7) & ~0x3;*/ 305 U32 nextCurY = U32(mCurY + mPlatformFont->getFontHeight()); // + 7) & ~0x3; 306 307 // These are here for postmortem debugging. 308 bool routeA = false, routeB = false; 309 310 if(mCurSheet == -1 || nextCurY >= TextureSheetSize) 311 { 312 routeA = true; 313 addSheet(); 314 315 // Recalc our nexts. 316 nextCurX = U32(mCurX + charInfo.width); // + 7) & ~0x3; 317 nextCurY = U32(mCurY + mPlatformFont->getFontHeight()); // + 7) & ~0x3; 318 } 319 320 if( nextCurX >= TextureSheetSize) 321 { 322 routeB = true; 323 mCurX = 0; 324 mCurY = nextCurY; 325 326 // Recalc our nexts. 327 nextCurX = U32(mCurX + charInfo.width); // + 7) & ~0x3; 328 nextCurY = U32(mCurY + mPlatformFont->getFontHeight()); // + 7) & ~0x3; 329 } 330 331 // Check the Y once more - sometimes we advance to a new row and run off 332 // the end. 333 if(nextCurY >= TextureSheetSize) 334 { 335 routeA = true; 336 addSheet(); 337 338 // Recalc our nexts. 339 nextCurX = U32(mCurX + charInfo.width); // + 7) & ~0x3; 340 nextCurY = U32(mCurY + mPlatformFont->getFontHeight()); // + 7) & ~0x3; 341 } 342 343 charInfo.bitmapIndex = mCurSheet; 344 charInfo.xOffset = mCurX; 345 charInfo.yOffset = mCurY; 346 347 mCurX = nextCurX; 348 349 S32 x, y; 350 GBitmap *bmp = mTextureSheets[mCurSheet].getBitmap(); 351 352 AssertFatal(bmp->getFormat() == GFXFormatA8, "GFont::addBitmap - cannot added characters to non-greyscale textures!"); 353 354 for(y = 0;y < charInfo.height;y++) 355 for(x = 0;x < charInfo.width;x++) 356 *bmp->getAddress(x + charInfo.xOffset, y + charInfo.yOffset) = charInfo.bitmapData[y * charInfo.width + x]; 357 358 mTextureSheets[mCurSheet].refresh(); 359} 360 361void GFont::addSheet() 362{ 363 GBitmap *bitmap = new GBitmap(TextureSheetSize, TextureSheetSize, false, GFXFormatA8 ); 364 365 // Set everything to transparent. 366 U8 *bits = bitmap->getWritableBits(); 367 dMemset(bits, 0, sizeof(U8) *TextureSheetSize*TextureSheetSize); 368 369 GFXTexHandle handle = GFXTexHandle( bitmap, &GFXFontTextureProfile, true, avar("%s() - (line %d)", __FUNCTION__, __LINE__) ); 370 mTextureSheets.increment(); 371 mTextureSheets.last() = handle; 372 373 mCurX = 0; 374 mCurY = 0; 375 mCurSheet = mTextureSheets.size() - 1; 376} 377 378//----------------------------------------------------------------------------- 379 380const PlatformFont::CharInfo &GFont::getCharInfo(const UTF16 in_charIndex) 381{ 382 PROFILE_SCOPE(GFont_getCharInfo); 383 384 AssertFatal(in_charIndex, "GFont::getCharInfo - can't get info for char 0!"); 385 386 if(mRemapTable[in_charIndex] == -1) 387 loadCharInfo(in_charIndex); 388 389 AssertFatal(mRemapTable[in_charIndex] != -1, "No remap info for this character"); 390 391 return mCharInfoList[mRemapTable[in_charIndex]]; 392} 393 394const PlatformFont::CharInfo &GFont::getDefaultCharInfo() 395{ 396 static PlatformFont::CharInfo c; 397 // c is initialized by the CharInfo default constructor. 398 return c; 399} 400 401//----------------------------------------------------------------------------- 402 403U32 GFont::getStrWidth(const UTF8* in_pString) 404{ 405 AssertFatal(in_pString != NULL, "GFont::getStrWidth: String is NULL, height is undefined"); 406 // If we ain't running debug... 407 if (in_pString == NULL || *in_pString == '\0') 408 return 0; 409 410 return getStrNWidth(in_pString, dStrlen(in_pString)); 411} 412 413U32 GFont::getStrWidthPrecise(const UTF8* in_pString) 414{ 415 AssertFatal(in_pString != NULL, "GFont::getStrWidth: String is NULL, height is undefined"); 416 // If we ain't running debug... 417 if (in_pString == NULL) 418 return 0; 419 420 return getStrNWidthPrecise(in_pString, dStrlen(in_pString)); 421} 422 423//----------------------------------------------------------------------------- 424U32 GFont::getStrNWidth(const UTF8 *str, U32 n) 425{ 426 // UTF8 conversion is expensive. Avoid converting in a tight loop. 427 FrameTemp<UTF16> str16(n + 1); 428 convertUTF8toUTF16N(str, str16, n + 1); 429 return getStrNWidth(str16, dStrlen(str16)); 430} 431 432U32 GFont::getStrNWidth(const UTF16 *str, U32 n) 433{ 434 AssertFatal(str != NULL, "GFont::getStrNWidth: String is NULL"); 435 436 if (str == NULL || str[0] == '\0' || n == 0) 437 return 0; 438 439 U32 totWidth = 0; 440 UTF16 curChar; 441 U32 charCount; 442 443 for(charCount = 0; charCount < n; charCount++) 444 { 445 curChar = str[charCount]; 446 if(curChar == '\0') 447 break; 448 449 if(isValidChar(curChar)) 450 { 451 const PlatformFont::CharInfo& rChar = getCharInfo(curChar); 452 totWidth += rChar.xIncrement; 453 } 454 else if (curChar == dT('\t')) 455 { 456 const PlatformFont::CharInfo& rChar = getCharInfo(dT(' ')); 457 totWidth += rChar.xIncrement * TabWidthInSpaces; 458 } 459 } 460 461 return(totWidth); 462} 463 464U32 GFont::getStrNWidthPrecise(const UTF8 *str, U32 n) 465{ 466 FrameTemp<UTF16> str16(n + 1); 467 convertUTF8toUTF16N(str, str16, n + 1); 468 return getStrNWidthPrecise(str16, dStrlen(str16)); 469} 470 471U32 GFont::getStrNWidthPrecise(const UTF16 *str, U32 n) 472{ 473 AssertFatal(str != NULL, "GFont::getStrNWidth: String is NULL"); 474 475 if (str == NULL || str[0] == '\0' || n == 0) 476 return(0); 477 478 U32 totWidth = 0; 479 UTF16 curChar; 480 U32 charCount = 0; 481 482 for(charCount = 0; charCount < n; charCount++) 483 { 484 curChar = str[charCount]; 485 if(curChar == '\0') 486 break; 487 488 if(isValidChar(curChar)) 489 { 490 const PlatformFont::CharInfo& rChar = getCharInfo(curChar); 491 totWidth += rChar.xIncrement; 492 } 493 else if (curChar == dT('\t')) 494 { 495 const PlatformFont::CharInfo& rChar = getCharInfo(dT(' ')); 496 totWidth += rChar.xIncrement * TabWidthInSpaces; 497 } 498 } 499 500 UTF16 endChar = str[getMin(charCount,n-1)]; 501 502 if (isValidChar(endChar)) 503 { 504 const PlatformFont::CharInfo& rChar = getCharInfo(endChar); 505 if (rChar.width != rChar.xIncrement) 506 totWidth += (rChar.width - rChar.xIncrement); 507 } 508 509 return(totWidth); 510} 511 512U32 GFont::getBreakPos(const UTF16 *str16, U32 slen, U32 width, bool breakOnWhitespace) 513{ 514 // Some early out cases. 515 if(slen==0) 516 return 0; 517 518 U32 ret = 0; 519 U32 lastws = 0; 520 UTF16 c; 521 U32 charCount = 0; 522 523 for( charCount=0; charCount < slen; charCount++) 524 { 525 c = str16[charCount]; 526 if(c == '\0') 527 break; 528 529 if(c == dT('\t')) 530 c = dT(' '); 531 532 if(!isValidChar(c)) 533 { 534 ret++; 535 continue; 536 } 537 538 if(c == dT(' ')) 539 lastws = ret+1; 540 541 const PlatformFont::CharInfo& rChar = getCharInfo(c); 542 if(rChar.width > width || rChar.xIncrement > width) 543 { 544 if(lastws && breakOnWhitespace) 545 return lastws; 546 return ret; 547 } 548 549 width -= rChar.xIncrement; 550 551 ret++; 552 } 553 return ret; 554} 555 556void GFont::wrapString(const UTF8 *txt, U32 lineWidth, Vector<U32> &startLineOffset, Vector<U32> &lineLen) 557{ 558 // TODO: Is this error still true? 559 //Con::errorf("GFont::wrapString(): Not yet converted to be UTF-8 safe"); 560 561 startLineOffset.clear(); 562 lineLen.clear(); 563 564 if (!txt || !txt[0] || lineWidth < getCharWidth('W')) //make sure the line width is greater then a single character 565 return; 566 567 U32 len = dStrlen(txt); 568 569 U32 startLine; 570 571 for (U32 i = 0; i < len;) 572 { 573 U32 wide = 0; 574 startLine = i; 575 startLineOffset.push_back(startLine); 576 577 // loop until the string is too large 578 bool needsNewLine = false; 579 U32 lineStrWidth = 0; 580 for (; i < len; i++) 581 { 582 if( txt[ i ] == '\n' ) 583 { 584 needsNewLine = true; 585 break; 586 } 587 else if(isValidChar(txt[i])) 588 { 589 lineStrWidth += getCharInfo(txt[i]).xIncrement; 590 if(txt[i] < 0) // symbols which code > 127 591 { 592 wide++; i++; 593 } 594 if( lineStrWidth > lineWidth ) 595 { 596 needsNewLine = true; 597 break; 598 } 599 } 600 } 601 602 if (!needsNewLine) 603 { 604 // we are done! 605 lineLen.push_back(i - startLine - wide); 606 return; 607 } 608 609 S32 j; 610 611 // Did we hit a hardwrap (newline character) in the string. 612 bool hardwrap = ( txt[i] == '\n' ); 613 614 if ( hardwrap ) 615 { 616 j = i; 617 } 618 // determine where to put the newline 619 // we need to backtrack until we find a space character 620 // we don't do this for hardwrap(s) 621 else 622 { 623 for (j = i - 1; j >= startLine; j--) 624 { 625 if ( dIsspace(txt[j]) || txt[i] == '\n' ) 626 break; 627 } 628 629 if (j < startLine) 630 { 631 // the line consists of a single word! 632 // So, just break up the word 633 634 j = i - 1; 635 } 636 } 637 638 lineLen.push_back(j - startLine - wide); 639 i = j; 640 641 // Now we need to increment through any space characters at the 642 // beginning of the next line. 643 // We don't skip spaces after a hardwrap because they were obviously intended. 644 for (i++; i < len; i++) 645 { 646 if ( txt[i] == '\n' ) 647 continue; 648 649 if ( dIsspace( txt[i] ) && !hardwrap ) 650 continue; 651 652 break; 653 } 654 } 655} 656 657//----------------------------------------------------------------------------- 658 659bool GFont::read(Stream& io_rStream) 660{ 661 // Handle versioning 662 U32 version; 663 io_rStream.read(&version); 664 if(version != csm_fileVersion) 665 return false; 666 667 char buf[256]; 668 io_rStream.readString(buf); 669 mFaceName = buf; 670 671 io_rStream.read(&mSize); 672 io_rStream.read(&mCharSet); 673 674 io_rStream.read(&mHeight); 675 io_rStream.read(&mBaseline); 676 io_rStream.read(&mAscent); 677 io_rStream.read(&mDescent); 678 679 U32 size = 0; 680 io_rStream.read(&size); 681 mCharInfoList.setSize(size); 682 U32 i; 683 for(i = 0; i < size; i++) 684 { 685 PlatformFont::CharInfo *ci = &mCharInfoList[i]; 686 io_rStream.read(&ci->bitmapIndex); 687 io_rStream.read(&ci->xOffset); 688 io_rStream.read(&ci->yOffset); 689 io_rStream.read(&ci->width); 690 io_rStream.read(&ci->height); 691 io_rStream.read(&ci->xOrigin); 692 io_rStream.read(&ci->yOrigin); 693 io_rStream.read(&ci->xIncrement); 694 ci->bitmapData = NULL; 695 } 696 697 U32 numSheets = 0; 698 io_rStream.read(&numSheets); 699 700 for(i = 0; i < numSheets; i++) 701 { 702 GBitmap *bmp = new GBitmap; 703 if(!bmp->readBitmap("png", io_rStream)) 704 { 705 delete bmp; 706 return false; 707 } 708 GFXTexHandle handle = GFXTexHandle(bmp, &GFXFontTextureProfile, true, avar("%s() - Read Font Sheet for %s %d (line %d)", __FUNCTION__, mFaceName.c_str(), mSize, __LINE__)); 709 //handle.setFilterNearest(); 710 mTextureSheets.push_back(handle); 711 } 712 713 // Read last position info 714 io_rStream.read(&mCurX); 715 io_rStream.read(&mCurY); 716 io_rStream.read(&mCurSheet); 717 718 // Read the remap table. 719 U32 minGlyph, maxGlyph; 720 io_rStream.read(&minGlyph); 721 io_rStream.read(&maxGlyph); 722 723 if(maxGlyph >= minGlyph) 724 { 725 // Length of buffer.. 726 U32 buffLen; 727 io_rStream.read(&buffLen); 728 729 // Read the buffer. 730 FrameTemp<S32> inBuff(buffLen); 731 io_rStream.read(buffLen, inBuff); 732 733 // Decompress. 734 uLongf destLen = (maxGlyph-minGlyph+1)*sizeof(S32); 735 uncompress((Bytef*)&mRemapTable[minGlyph], &destLen, (Bytef*)(S32*)inBuff, buffLen); 736 737 AssertISV(destLen == (maxGlyph-minGlyph+1)*sizeof(S32), "GFont::read - invalid remap table data!"); 738 739 // Make sure we've got the right endianness. 740 for(i = minGlyph; i <= maxGlyph; i++) 741 mRemapTable[i] = convertBEndianToHost(mRemapTable[i]); 742 } 743 744 return (io_rStream.getStatus() == Stream::Ok); 745} 746 747bool GFont::write(Stream& stream) 748{ 749 // Handle versioning 750 stream.write(csm_fileVersion); 751 752 // Write font info 753 stream.write(mFaceName); 754 stream.write(mSize); 755 stream.write(mCharSet); 756 757 stream.write(mHeight); 758 stream.write(mBaseline); 759 stream.write(mAscent); 760 stream.write(mDescent); 761 762 // Write char info list 763 stream.write(U32(mCharInfoList.size())); 764 U32 i; 765 for(i = 0; i < mCharInfoList.size(); i++) 766 { 767 const PlatformFont::CharInfo *ci = &mCharInfoList[i]; 768 stream.write(ci->bitmapIndex); 769 stream.write(ci->xOffset); 770 stream.write(ci->yOffset); 771 stream.write(ci->width); 772 stream.write(ci->height); 773 stream.write(ci->xOrigin); 774 stream.write(ci->yOrigin); 775 stream.write(ci->xIncrement); 776 } 777 778 stream.write(mTextureSheets.size()); 779 for(i = 0; i < mTextureSheets.size(); i++) 780 mTextureSheets[i].getBitmap()->writeBitmap("png", stream); 781 782 stream.write(mCurX); 783 stream.write(mCurY); 784 stream.write(mCurSheet); 785 786 // Get the min/max we have values for, and only write that range out. 787 S32 minGlyph = S32_MAX, maxGlyph = 0; 788 789 for(i = 0; i < 65536; i++) 790 { 791 if(mRemapTable[i] != -1) 792 { 793 if(i>maxGlyph) maxGlyph = i; 794 if(i<minGlyph) minGlyph = i; 795 } 796 } 797 798 stream.write(minGlyph); 799 stream.write(maxGlyph); 800 801 // Skip it if we don't have any glyphs to do... 802 if(maxGlyph >= minGlyph) 803 { 804 // Put everything big endian, to be consistent. Do this inplace. 805 for(i = minGlyph; i <= maxGlyph; i++) 806 mRemapTable[i] = convertHostToBEndian(mRemapTable[i]); 807 808 { 809 // Compress. 810 const U32 buffSize = 128 * 1024; 811 FrameTemp<S32> outBuff(buffSize); 812 uLongf destLen = buffSize * sizeof(S32); 813 compress2((Bytef*)(S32*)outBuff, &destLen, (Bytef*)(S32*)&mRemapTable[minGlyph], (maxGlyph-minGlyph+1)*sizeof(S32), 9); 814 815 // Write out. 816 stream.write((U32)destLen); 817 stream.write(destLen, outBuff); 818 } 819 820 // Put us back to normal. 821 for(i = minGlyph; i <= maxGlyph; i++) 822 mRemapTable[i] = convertBEndianToHost(mRemapTable[i]); 823 } 824 825 return (stream.getStatus() == Stream::Ok); 826} 827 828void GFont::exportStrip(const char *fileName, U32 padding, U32 kerning) 829{ 830 // Figure dimensions of our strip by iterating over all the char infos. 831 U32 totalHeight = 0; 832 U32 totalWidth = 0; 833 834 S32 heightMin=0, heightMax=0; 835 836 for(S32 i=0; i<mCharInfoList.size(); i++) 837 { 838 totalWidth += mCharInfoList[i].width + kerning + 2*padding; 839 heightMin = getMin((S32)heightMin, (S32)getBaseline() - (S32)mCharInfoList[i].yOrigin); 840 heightMax = getMax((S32)heightMax, (S32)getBaseline() - (S32)mCharInfoList[i].yOrigin + (S32)mCharInfoList[i].height); 841 } 842 843 totalHeight = heightMax - heightMin + 2*padding; 844 845 // Make the bitmap. 846 GBitmap gb(totalWidth, totalHeight, false, mTextureSheets[0].getBitmap()->getFormat()); 847 848 dMemset(gb.getWritableBits(), 0, sizeof(U8) * totalHeight * totalWidth ); 849 850 // Ok, copy some rects, taking into account padding, kerning, offset. 851 U32 curWidth = kerning + padding; 852 853 for(S32 i=0; i<mCharInfoList.size(); i++) 854 { 855 // Skip invalid stuff. 856 if(mCharInfoList[i].bitmapIndex == -1 || mCharInfoList[i].height == 0 || mCharInfoList[i].width == 0) 857 continue; 858 859 // Copy the rect. 860 U32 bitmap = mCharInfoList[i].bitmapIndex; 861 862 RectI ri(mCharInfoList[i].xOffset, mCharInfoList[i].yOffset, mCharInfoList[i].width, mCharInfoList[i].height ); 863 Point2I outRi(curWidth, padding + getBaseline() - mCharInfoList[i].yOrigin); 864 gb.copyRect(mTextureSheets[bitmap].getBitmap(), ri, outRi); 865 866 // Advance. 867 curWidth += mCharInfoList[i].width + kerning + 2*padding; 868 } 869 870 // Write the image! 871 FileStream fs; 872 873 fs.open( fileName, Torque::FS::File::Write ); 874 875 if(fs.getStatus() != Stream::Ok) 876 { 877 Con::errorf("GFont::exportStrip - failed to open '%s' for writing.", fileName); 878 return; 879 } 880 881 // Done! 882 gb.writeBitmap("png", fs); 883} 884 885void GFont::setPlatformFont(PlatformFont *inPlatformFont) 886{ 887 AssertFatal( mPlatformFont == NULL, "Trying to set platform font which already exists"); 888 889 mPlatformFont = inPlatformFont; 890} 891 892void GFont::importStrip(const char *fileName, U32 padding, U32 kerning) 893{ 894 // Wipe our texture sheets, and reload bitmap data from the specified file. 895 // Also deal with kerning. 896 // Also, we may have to load RGBA instead of RGB. 897 898 // Wipe our texture sheets. 899 mCurSheet = mCurX = mCurY = 0; 900 mTextureSheets.clear(); 901 902 // Now, load the font strip. 903 Resource<GBitmap> strip = GBitmap::load(fileName); 904 905 if(!strip) 906 { 907 Con::errorf("GFont::importStrip - could not load file '%s'!", fileName); 908 return; 909 } 910 911 // And get parsing and copying - load up all the characters as separate 912 // GBitmaps, sort, then pack. Not terribly efficient but this is basically 913 // on offline task anyway. 914 915 // Ok, snag some glyphs. 916 Vector<GlyphMap> glyphList; 917 glyphList.reserve(mCharInfoList.size()); 918 919 U32 curWidth = 0; 920 for(S32 i=0; i<mCharInfoList.size(); i++) 921 { 922 // Skip invalid stuff. 923 if(mCharInfoList[i].bitmapIndex == -1 || mCharInfoList[i].height == 0 || mCharInfoList[i].width == 0) 924 continue; 925 926 // Allocate a new bitmap for this glyph, taking into account kerning and padding. 927 glyphList.increment(); 928 GlyphMap& lastGlyphMap = glyphList.last(); 929 lastGlyphMap.bitmap = new GBitmap(mCharInfoList[i].width + kerning + 2 * padding, mCharInfoList[i].height + 2 * padding, false, strip->getFormat()); 930 lastGlyphMap.charId = i; 931 932 // Copy the rect. 933 RectI ri(curWidth, getBaseline() - mCharInfoList[i].yOrigin, lastGlyphMap.bitmap->getWidth(), lastGlyphMap.bitmap->getHeight()); 934 Point2I outRi(0,0); 935 lastGlyphMap.bitmap->copyRect(strip, ri, outRi); 936 937 // Update glyph attributes. 938 mCharInfoList[i].width = lastGlyphMap.bitmap->getWidth(); 939 mCharInfoList[i].height = lastGlyphMap.bitmap->getHeight(); 940 mCharInfoList[i].xOffset -= kerning + padding; 941 mCharInfoList[i].xIncrement += kerning; 942 mCharInfoList[i].yOffset -= padding; 943 944 // Advance. 945 curWidth += ri.extent.x; 946 } 947 948 // Ok, we have a big list of glyphmaps now. So let's sort them, then pack them. 949 dQsort(glyphList.address(), glyphList.size(), sizeof(GlyphMap), GlyphMapCompare); 950 951 // They're sorted by height, so now we can do some sort of awesome packing. 952 Point2I curSheetSize(256, 256); 953 Vector<U32> sheetSizes; 954 955 S32 curY = 0; 956 S32 curX = 0; 957 S32 curLnHeight = 0; 958 S32 maxHeight = 0; 959 for(U32 i = 0; i < glyphList.size(); i++) 960 { 961 PlatformFont::CharInfo *ci = &mCharInfoList[glyphList[i].charId]; 962 963 if(ci->height > maxHeight) 964 maxHeight = ci->height; 965 966 if(curX + ci->width > curSheetSize.x) 967 { 968 curY += curLnHeight; 969 curX = 0; 970 curLnHeight = 0; 971 } 972 973 if(curY + ci->height > curSheetSize.y) 974 { 975 sheetSizes.push_back(curSheetSize.y); 976 curX = 0; 977 curY = 0; 978 curLnHeight = 0; 979 } 980 981 if(ci->height > curLnHeight) 982 curLnHeight = ci->height; 983 984 ci->bitmapIndex = sheetSizes.size(); 985 ci->xOffset = curX; 986 ci->yOffset = curY; 987 curX += ci->width; 988 } 989 990 // Terminate the packing loop calculations. 991 curY += curLnHeight; 992 993 if(curY < 64) 994 curSheetSize.y = 64; 995 else if(curY < 128) 996 curSheetSize.y = 128; 997 998 sheetSizes.push_back(curSheetSize.y); 999 1000 if(getHeight() + padding * 2 > maxHeight) 1001 maxHeight = getHeight() + padding * 2; 1002 1003 // Allocate texture pages. 1004 for(S32 i=0; i<sheetSizes.size(); i++) 1005 { 1006 GBitmap *bitmap = new GBitmap(TextureSheetSize, TextureSheetSize, false, strip->getFormat()); 1007 1008 // Set everything to transparent. 1009 U8 *bits = bitmap->getWritableBits(); 1010 dMemset(bits, 0, sizeof(U8) *TextureSheetSize*TextureSheetSize * strip->getBytesPerPixel()); 1011 1012 GFXTexHandle handle = GFXTexHandle( bitmap, &GFXFontTextureProfile, true, avar("%s() - Font Sheet for %s (line %d)", __FUNCTION__, fileName, __LINE__) ); 1013 mTextureSheets.increment(); 1014 mTextureSheets.last() = handle; 1015 } 1016 1017 // Alright, we're ready to copy bits! 1018 for(S32 i=0; i<glyphList.size(); i++) 1019 { 1020 // Copy each glyph into the appropriate place. 1021 PlatformFont::CharInfo *ci = &mCharInfoList[glyphList[i].charId]; 1022 U32 bi = ci->bitmapIndex; 1023 mTextureSheets[bi]->getBitmap()->copyRect(glyphList[i].bitmap, RectI(0,0, glyphList[i].bitmap->getWidth(),glyphList[i].bitmap->getHeight()), Point2I(ci->xOffset, ci->yOffset)); 1024 } 1025 1026 // Ok, all done! Just refresh some textures and we're set. 1027 for(S32 i=0; i<sheetSizes.size(); i++) 1028 mTextureSheets[i].refresh(); 1029} 1030 1031DefineEngineFunction( populateFontCacheString, void, ( const char *faceName, S32 fontSize, const char *string ),, 1032 "Populate the font cache for the specified font with characters from the specified string.\n" 1033 "@param faceName The name of the font face.\n" 1034 "@param fontSize The size of the font in pixels.\n" 1035 "@param string The string to populate.\n" 1036 "@ingroup Font\n" ) 1037{ 1038 Resource<GFont> f = GFont::create(faceName, fontSize, Con::getVariable("$GUI::fontCacheDirectory")); 1039 1040 if(f == NULL) 1041 { 1042 Con::errorf("populateFontCacheString - could not load font '%s %d'", faceName, fontSize); 1043 return; 1044 } 1045 1046 if(!f->hasPlatformFont()) 1047 { 1048 Con::errorf("populateFontCacheString - font '%s %d' has no platform font. Cannot generate more characters.", faceName, fontSize); 1049 return; 1050 } 1051 1052 // This has the side effect of generating character info, including the bitmaps. 1053 f->getStrWidthPrecise( string ); 1054} 1055 1056DefineEngineFunction( populateFontCacheRange, void, ( const char *faceName, S32 fontSize, U32 rangeStart, U32 rangeEnd ),, 1057 "Populate the font cache for the specified font with Unicode code points in the specified range.\n" 1058 "@param faceName The name of the font face.\n" 1059 "@param fontSize The size of the font in pixels.\n" 1060 "@param rangeStart The start Unicode point.\n" 1061 "@param rangeEnd The end Unicode point.\n" 1062 "@note We only support BMP-0, so code points range from 0 to 65535.\n" 1063 "@ingroup Font\n" ) 1064{ 1065 Resource<GFont> f = GFont::create(faceName, fontSize, Con::getVariable("$GUI::fontCacheDirectory")); 1066 1067 if(f == NULL) 1068 { 1069 Con::errorf("populateFontCacheRange - could not load font '%s %d'", faceName, fontSize); 1070 return; 1071 } 1072 1073 if(rangeStart > rangeEnd) 1074 { 1075 Con::errorf("populateFontCacheRange - range start is after end"); 1076 return; 1077 } 1078 1079 if(!f->hasPlatformFont()) 1080 { 1081 Con::errorf("populateFontCacheRange - font '%s %d' has no platform font Cannot generate more characters.", faceName, fontSize); 1082 return; 1083 } 1084 1085 // This has the side effect of generating character info, including the bitmaps. 1086 for(U32 i=rangeStart; i<rangeEnd; i++) 1087 { 1088 if(f->isValidChar(i)) 1089 f->getCharWidth(i); 1090 else 1091 Con::warnf("populateFontCacheRange - skipping invalid char 0x%x", i); 1092 } 1093 1094 // All done! 1095} 1096 1097DefineEngineFunction( dumpFontCacheStatus, void, (),, 1098 "Dumps to the console a full description of all cached fonts, along with " 1099 "info on the codepoints each contains.\n" 1100 "@ingroup Font\n" ) 1101{ 1102 Resource<GFont> theFont = ResourceManager::get().startResourceList( Resource<GFont>::signature() ); 1103 1104 Con::printf("--------------------------------------------------------------------------"); 1105 Con::printf(" Font Cache Usage Report"); 1106 1107 while( theFont != NULL ) 1108 { 1109 theFont->dumpInfo(); 1110 1111 theFont = ResourceManager::get().nextResource(); 1112 } 1113} 1114 1115DefineEngineFunction( writeFontCache, void, (),, 1116 "Force all cached fonts to serialize themselves to the cache.\n" 1117 "@ingroup Font\n" ) 1118{ 1119 Resource<GFont> theFont = ResourceManager::get().startResourceList( Resource<GFont>::signature() ); 1120 1121 Con::printf("--------------------------------------------------------------------------"); 1122 Con::printf(" Writing font cache to disk"); 1123 1124 while( theFont != NULL ) 1125 { 1126 const String fileName( theFont.getPath() ); 1127 1128 FileStream stream; 1129 stream.open(fileName, Torque::FS::File::Write); 1130 1131 if(stream.getStatus() == Stream::Ok) 1132 { 1133 Con::printf(" o Writing '%s' to disk...", fileName.c_str()); 1134 theFont->write(stream); 1135 } 1136 else 1137 { 1138 Con::errorf(" o Could not open '%s' for write", fileName.c_str()); 1139 } 1140 1141 theFont = ResourceManager::get().nextResource(); 1142 } 1143} 1144 1145DefineEngineFunction( populateAllFontCacheString, void, ( const char *string ),, 1146 "Populate the font cache for all fonts with characters from the specified string.\n" 1147 "@ingroup Font\n" ) 1148{ 1149 Resource<GFont> theFont = ResourceManager::get().startResourceList( Resource<GFont>::signature() ); 1150 1151 Con::printf("Populating font cache with string '%s'", string); 1152 1153 while( theFont != NULL ) 1154 { 1155 if(theFont->hasPlatformFont()) 1156 { 1157 // This has the side effect of generating character info, including the bitmaps. 1158 theFont->getStrWidthPrecise( string ); 1159 } 1160 else 1161 { 1162 const String fileName( theFont.getPath() ); 1163 Con::errorf("populateAllFontCacheString - font '%s' has no platform font. Cannot generate more characters.", fileName.c_str()); 1164 } 1165 1166 theFont = ResourceManager::get().nextResource(); 1167 } 1168} 1169 1170DefineEngineFunction( populateAllFontCacheRange, void, ( U32 rangeStart, U32 rangeEnd ),, 1171 "Populate the font cache for all fonts with Unicode code points in the specified range.\n" 1172 "@param rangeStart The start Unicode point.\n" 1173 "@param rangeEnd The end Unicode point.\n" 1174 "@note We only support BMP-0, so code points range from 0 to 65535.\n" 1175 "@ingroup Font\n" ) 1176{ 1177 if(rangeStart > rangeEnd) 1178 { 1179 Con::errorf("populateAllFontCacheRange - range start is after end!"); 1180 return; 1181 } 1182 1183 Resource<GFont> theFont = ResourceManager::get().startResourceList( Resource<GFont>::signature() ); 1184 1185 Con::printf("Populating font cache with range 0x%x to 0x%x", rangeStart, rangeEnd); 1186 1187 while( theFont != NULL ) 1188 { 1189 const String fileName( theFont.getPath() ); 1190 1191 if(theFont->hasPlatformFont()) 1192 { 1193 // This has the side effect of generating character info, including the bitmaps. 1194 Con::printf(" o Populating font '%s'", fileName.c_str()); 1195 for(U32 i=rangeStart; i<rangeEnd; i++) 1196 { 1197 if(theFont->isValidChar(i)) 1198 theFont->getCharWidth(i); 1199 else 1200 Con::warnf("populateAllFontCacheRange - skipping invalid char 0x%x", i); 1201 } 1202 } 1203 else 1204 { 1205 Con::errorf("populateAllFontCacheRange - font '%s' has no platform font. Cannot generate more characters.", fileName.c_str()); 1206 } 1207 1208 theFont = ResourceManager::get().nextResource(); 1209 } 1210} 1211 1212DefineEngineFunction( exportCachedFont, void, 1213 ( const char *faceName, S32 fontSize, const char *fileName, S32 padding, S32 kerning ),, 1214 "Export specified font to the specified filename as a PNG. The " 1215 "image can then be processed in Photoshop or another tool and " 1216 "reimported using importCachedFont. Characters in the font are " 1217 "exported as one long strip.\n" 1218 "@param faceName The name of the font face.\n" 1219 "@param fontSize The size of the font in pixels.\n" 1220 "@param fileName The file name and path for the output PNG.\n" 1221 "@param padding The padding between characters.\n" 1222 "@param kerning The kerning between characters.\n" 1223 "@ingroup Font\n" ) 1224{ 1225 // Tell the font to export itself. 1226 Resource<GFont> f = GFont::create(faceName, fontSize, Con::getVariable("$GUI::fontCacheDirectory")); 1227 1228 if(f == NULL) 1229 { 1230 Con::errorf("exportCachedFont - could not load font '%s %d'", faceName, fontSize); 1231 return; 1232 } 1233 1234 f->exportStrip(fileName, padding, kerning); 1235} 1236 1237DefineEngineFunction( importCachedFont, void, 1238 ( const char *faceName, S32 fontSize, const char *fileName, S32 padding, S32 kerning ),, 1239 "Import an image strip from exportCachedFont. Call with the " 1240 "same parameters you called exportCachedFont.\n" 1241 "@param faceName The name of the font face.\n" 1242 "@param fontSize The size of the font in pixels.\n" 1243 "@param fileName The file name and path for the input PNG.\n" 1244 "@param padding The padding between characters.\n" 1245 "@param kerning The kerning between characters.\n" 1246 "@ingroup Font\n" ) 1247{ 1248 // Tell the font to import itself. 1249 Resource<GFont> f = GFont::create(faceName, fontSize, Con::getVariable("$GUI::fontCacheDirectory")); 1250 1251 if(f == NULL) 1252 { 1253 Con::errorf("importCachedFont - could not load font '%s %d'", faceName, fontSize); 1254 return; 1255 } 1256 1257 f->importStrip(fileName, padding, kerning); 1258} 1259 1260DefineEngineFunction( duplicateCachedFont, void, 1261 ( const char *oldFontName, S32 oldFontSize, const char *newFontName ),, 1262 "Copy the specified old font to a new name. The new copy will not have a " 1263 "platform font backing it, and so will never have characters added to it. " 1264 "But this is useful for making copies of fonts to add postprocessing effects " 1265 "to via exportCachedFont.\n" 1266 "@param oldFontName The name of the font face to copy.\n" 1267 "@param oldFontSize The size of the font to copy.\n" 1268 "@param newFontName The name of the new font face.\n" 1269 "@ingroup Font\n" ) 1270{ 1271 String newFontFile = GFont::getFontCacheFilename(newFontName, oldFontSize); 1272 1273 // Load the original font. 1274 Resource<GFont> font = GFont::create(oldFontName, oldFontSize, Con::getVariable("$GUI::fontCacheDirectory")); 1275 1276 // Deal with inexplicably missing or failed to load fonts. 1277 if (font == NULL) 1278 { 1279 Con::errorf(" o Couldn't find font : %s", oldFontName); 1280 return; 1281 } 1282 1283 // Ok, dump info! 1284 FileStream stream; 1285 stream.open( newFontFile, Torque::FS::File::Write ); 1286 if(stream.getStatus() == Stream::Ok) 1287 { 1288 Con::printf( " o Writing duplicate font '%s' to disk...", newFontFile.c_str() ); 1289 font->write(stream); 1290 stream.close(); 1291 } 1292 else 1293 { 1294 Con::errorf( " o Could not open '%s' for write", newFontFile.c_str() ); 1295 } 1296} 1297 1298