MyGUI  3.2.1
MyGUI_ResourceTrueTypeFont.cpp
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 #include "MyGUI_Precompiled.h"
00008 #include "MyGUI_ResourceTrueTypeFont.h"
00009 #include "MyGUI_DataManager.h"
00010 #include "MyGUI_DataStreamHolder.h"
00011 #include "MyGUI_RenderManager.h"
00012 #include "MyGUI_Bitwise.h"
00013 
00014 #ifdef MYGUI_USE_FREETYPE
00015 
00016 #   include FT_GLYPH_H
00017 #   include FT_TRUETYPE_TABLES_H
00018 #   include FT_BITMAP_H
00019 #   include FT_WINFONTS_H
00020 
00021 //  The following macro enables a workaround for a bug in FreeType's bytecode interpreter that, when using certain fonts at
00022 //  certain sizes, causes FreeType to start measuring and rendering some glyphs inconsistently after certain other glyphs have
00023 //  been loaded. See FreeType bug #35374 for details: https://savannah.nongnu.org/bugs/?35374
00024 //
00025 //  To reproduce the bug, first disable the workaround by defining MYGUI_USE_FREETYPE_BYTECODE_BUG_FIX to 0. Then load the
00026 //  DejaVu Sans font at 10 pt using default values for all other properties. Observe that the glyphs for the "0", 6", "8", and
00027 //  "9" characters are now badly corrupted when rendered.
00028 //
00029 //  This bug still exists as of FreeType 2.4.8 and there are currently no plans to fix it. If the bug is ever fixed, this
00030 //  workaround should be disabled, as it causes fonts to take longer to load.
00031 //
00032 //  The bug can currently also be suppressed by disabling FreeType's bytecode interpreter altogether. To do so, remove the
00033 //  TT_CONFIG_OPTION_BYTECODE_INTERPRETER macro in the "ftoption.h" FreeType header file. Once this is done, this workaround can
00034 //  be safely disabled. Note that disabling FreeType's bytecode interpreter will cause rendered text to look somewhat different.
00035 //  Whether it looks better or worse is a matter of taste and may also depend on the font.
00036 #   ifndef MYGUI_USE_FREETYPE_BYTECODE_BUG_FIX
00037 #       define MYGUI_USE_FREETYPE_BYTECODE_BUG_FIX 1
00038 #   endif
00039 
00040 #endif // MYGUI_USE_FREETYPE
00041 
00042 namespace MyGUI
00043 {
00044 
00045 #ifndef MYGUI_USE_FREETYPE
00046     ResourceTrueTypeFont::ResourceTrueTypeFont()
00047     {
00048     }
00049 
00050     ResourceTrueTypeFont::~ResourceTrueTypeFont()
00051     {
00052     }
00053 
00054     void ResourceTrueTypeFont::deserialization(xml::ElementPtr _node, Version _version)
00055     {
00056         Base::deserialization(_node, _version);
00057         MYGUI_LOG(Error, "ResourceTrueTypeFont: TrueType font '" << getResourceName() << "' disabled. Define MYGUI_USE_FREETYE if you need TrueType fonts.");
00058     }
00059 
00060     GlyphInfo* ResourceTrueTypeFont::getGlyphInfo(Char _id)
00061     {
00062         return nullptr;
00063     }
00064 
00065     ITexture* ResourceTrueTypeFont::getTextureFont()
00066     {
00067         return nullptr;
00068     }
00069 
00070     int ResourceTrueTypeFont::getDefaultHeight()
00071     {
00072         return 0;
00073     }
00074 
00075     std::vector<std::pair<Char, Char> > ResourceTrueTypeFont::getCodePointRanges() const
00076     {
00077         return std::vector<std::pair<Char, Char> >();
00078     }
00079 
00080     Char ResourceTrueTypeFont::getSubstituteCodePoint() const
00081     {
00082         return Char();
00083     }
00084 
00085     void ResourceTrueTypeFont::initialise()
00086     {
00087     }
00088 
00089     void ResourceTrueTypeFont::setSource(const std::string& _value)
00090     {
00091     }
00092 
00093     void ResourceTrueTypeFont::setSize(float _value)
00094     {
00095     }
00096 
00097     void ResourceTrueTypeFont::setResolution(uint _value)
00098     {
00099     }
00100 
00101     void ResourceTrueTypeFont::setHinting(const std::string& _value)
00102     {
00103     }
00104 
00105     void ResourceTrueTypeFont::setAntialias(bool _value)
00106     {
00107     }
00108 
00109     void ResourceTrueTypeFont::setTabWidth(float _value)
00110     {
00111     }
00112 
00113     void ResourceTrueTypeFont::setOffsetHeight(int _value)
00114     {
00115     }
00116 
00117     void ResourceTrueTypeFont::setSubstituteCode(int _value)
00118     {
00119     }
00120 
00121     void ResourceTrueTypeFont::setDistance(int _value)
00122     {
00123     }
00124 
00125     void ResourceTrueTypeFont::addCodePointRange(Char _first, Char _second)
00126     {
00127     }
00128 
00129     void ResourceTrueTypeFont::removeCodePointRange(Char _first, Char _second)
00130     {
00131     }
00132 
00133 #else // MYGUI_USE_FREETYPE
00134     namespace
00135     {
00136 
00137         template<typename T>
00138         void setMax(T& _var, const T& _newValue)
00139         {
00140             if (_var < _newValue)
00141                 _var = _newValue;
00142         }
00143 
00144         std::pair<const Char, const uint8> charMaskData[] =
00145         {
00146             std::make_pair(FontCodeType::Selected, (const uint8)'\x88'),
00147             std::make_pair(FontCodeType::SelectedBack, (const uint8)'\x60'),
00148             std::make_pair(FontCodeType::Cursor, (const uint8)'\xFF'),
00149             std::make_pair(FontCodeType::Tab, (const uint8)'\x00')
00150         };
00151 
00152         const std::map<const Char, const uint8> charMask(charMaskData, charMaskData + sizeof charMaskData / sizeof(*charMaskData));
00153 
00154         const uint8 charMaskBlack = (const uint8)'\x00';
00155         const uint8 charMaskWhite = (const uint8)'\xFF';
00156 
00157         template<bool LAMode>
00158         struct PixelBase
00159         {
00160             // Returns PixelFormat::R8G8B8A8 when LAMode is false, or PixelFormat::L8A8 when LAMode is true.
00161             static PixelFormat::Enum getFormat();
00162 
00163             // Returns 4 when LAMode is false, or 2 when LAMode is true.
00164             static size_t getNumBytes();
00165 
00166         protected:
00167             // Sets a pixel in _dest as 4 or 2 bytes: L8L8L8A8 if LAMode is false, or L8A8 if LAMode is true.
00168             // Automatically advances _dest just past the pixel written.
00169             static void set(uint8*& _dest, uint8 _luminance, uint8 _alpha);
00170         };
00171 
00172         template<>
00173         struct PixelBase<false>
00174         {
00175             static size_t getNumBytes()
00176             {
00177                 return 4;
00178             }
00179 
00180             static PixelFormat::Enum getFormat()
00181             {
00182                 return PixelFormat::R8G8B8A8;
00183             }
00184 
00185         protected:
00186             static void set(uint8*& _dest, uint8 _luminance, uint8 _alpha)
00187             {
00188                 *_dest++ = _luminance;
00189                 *_dest++ = _luminance;
00190                 *_dest++ = _luminance;
00191                 *_dest++ = _alpha;
00192             }
00193         };
00194 
00195         template<>
00196         struct PixelBase<true>
00197         {
00198             static size_t getNumBytes()
00199             {
00200                 return 2;
00201             }
00202 
00203             static PixelFormat::Enum getFormat()
00204             {
00205                 return PixelFormat::L8A8;
00206             }
00207 
00208         protected:
00209             static void set(uint8*& _dest, uint8 _luminance, uint8 _alpha)
00210             {
00211                 *_dest++ = _luminance;
00212                 *_dest++ = _alpha;
00213             }
00214         };
00215 
00216         template<bool LAMode, bool FromSource = false, bool Antialias = false>
00217         struct Pixel : PixelBase<LAMode>
00218         {
00219             // Sets a pixel in _dest as 4 or 2 bytes: L8L8L8A8 if LAMode is false, or L8A8 if LAMode is true.
00220             // Sets luminance from _source if both FromSource and Antialias are true; otherwise, uses the specified value.
00221             // Sets alpha from _source if FromSource is true; otherwise, uses the specified value.
00222             // Automatically advances _source just past the pixel read if FromSource is true.
00223             // Automatically advances _dest just past the pixel written.
00224             static void set(uint8*& _dest, uint8 _luminance, uint8 _alpha, uint8*& _source);
00225         };
00226 
00227         template<bool LAMode, bool Antialias>
00228         struct Pixel<LAMode, false, Antialias> : PixelBase<LAMode>
00229         {
00230             // Sets the destination pixel using the specified luminance and alpha. Source is ignored, since FromSource is false.
00231             static void set(uint8*& _dest, uint8 _luminance, uint8 _alpha, uint8* = nullptr)
00232             {
00233                 PixelBase<LAMode>::set(_dest, _luminance, _alpha);
00234             }
00235         };
00236 
00237         template<bool LAMode>
00238         struct Pixel<LAMode, true, false> : PixelBase<LAMode>
00239         {
00240             // Sets the destination pixel using the specified _luminance and using the alpha from the specified source.
00241             static void set(uint8*& _dest, uint8 _luminance, uint8, uint8*& _source)
00242             {
00243                 PixelBase<LAMode>::set(_dest, _luminance, *_source++);
00244             }
00245         };
00246 
00247         template<bool LAMode>
00248         struct Pixel<LAMode, true, true> : PixelBase<LAMode>
00249         {
00250             // Sets the destination pixel using both the luminance and alpha from the specified source, since Antialias is true.
00251             static void set(uint8*& _dest, uint8, uint8, uint8*& _source)
00252             {
00253                 PixelBase<LAMode>::set(_dest, *_source, *_source);
00254                 ++_source;
00255             }
00256         };
00257 
00258     }
00259 
00260     const int ResourceTrueTypeFont::mDefaultGlyphSpacing = 1;
00261     const float ResourceTrueTypeFont::mDefaultTabWidth = 8.0f;
00262     const float ResourceTrueTypeFont::mSelectedWidth = 1.0f;
00263     const float ResourceTrueTypeFont::mCursorWidth = 2.0f;
00264 
00265     ResourceTrueTypeFont::ResourceTrueTypeFont() :
00266         mSize(0),
00267         mResolution(96),
00268         mHinting(HintingUseNative),
00269         mAntialias(false),
00270         mSpaceWidth(0.0f),
00271         mGlyphSpacing(-1),
00272         mTabWidth(0.0f),
00273         mOffsetHeight(0),
00274         mSubstituteCodePoint(static_cast<Char>(FontCodeType::NotDefined)),
00275         mDefaultHeight(0),
00276         mSubstituteGlyphInfo(nullptr),
00277         mTexture(nullptr)
00278     {
00279     }
00280 
00281     ResourceTrueTypeFont::~ResourceTrueTypeFont()
00282     {
00283         if (mTexture != nullptr)
00284         {
00285             RenderManager::getInstance().destroyTexture(mTexture);
00286             mTexture = nullptr;
00287         }
00288     }
00289 
00290     void ResourceTrueTypeFont::deserialization(xml::ElementPtr _node, Version _version)
00291     {
00292         Base::deserialization(_node, _version);
00293 
00294         xml::ElementEnumerator node = _node->getElementEnumerator();
00295         while (node.next())
00296         {
00297             if (node->getName() == "Property")
00298             {
00299                 const std::string& key = node->findAttribute("key");
00300                 const std::string& value = node->findAttribute("value");
00301                 if (key == "Source")
00302                     setSource(value);
00303                 else if (key == "Size")
00304                     setSize(utility::parseFloat(value));
00305                 else if (key == "Resolution")
00306                     setResolution(utility::parseUInt(value));
00307                 else if (key == "Antialias")
00308                     setAntialias(utility::parseBool(value));
00309                 else if (key == "TabWidth")
00310                     setTabWidth(utility::parseFloat(value));
00311                 else if (key == "OffsetHeight")
00312                     setOffsetHeight(utility::parseInt(value));
00313                 else if (key == "SubstituteCode")
00314                     setSubstituteCode(utility::parseInt(value));
00315                 else if (key == "Distance")
00316                     setDistance(utility::parseInt(value));
00317                 else if (key == "Hinting")
00318                     setHinting(value);
00319                 else if (key == "SpaceWidth")
00320                 {
00321                     mSpaceWidth = utility::parseFloat(value);
00322                     MYGUI_LOG(Warning, _node->findAttribute("type") << ": Property '" << key << "' in font '" << _node->findAttribute("name") << "' is deprecated; remove it to use automatic calculation.");
00323                 }
00324                 else if (key == "CursorWidth")
00325                 {
00326                     MYGUI_LOG(Warning, _node->findAttribute("type") << ": Property '" << key << "' in font '" << _node->findAttribute("name") << "' is deprecated; value ignored.");
00327                 }
00328             }
00329             else if (node->getName() == "Codes")
00330             {
00331                 // Range of inclusions.
00332                 xml::ElementEnumerator range = node->getElementEnumerator();
00333                 while (range.next("Code"))
00334                 {
00335                     std::string range_value;
00336                     if (range->findAttribute("range", range_value))
00337                     {
00338                         std::vector<std::string> parse_range = utility::split(range_value);
00339                         if (!parse_range.empty())
00340                         {
00341                             Char first = utility::parseUInt(parse_range[0]);
00342                             Char last = parse_range.size() > 1 ? utility::parseUInt(parse_range[1]) : first;
00343                             addCodePointRange(first, last);
00344                         }
00345                     }
00346                 }
00347 
00348                 // If no code points have been included, include the Unicode Basic Multilingual Plane by default before processing
00349                 //  any exclusions.
00350                 if (mCharMap.empty())
00351                     addCodePointRange(0, 0xFFFF);
00352 
00353                 // Range of exclusions.
00354                 range = node->getElementEnumerator();
00355                 while (range.next("Code"))
00356                 {
00357                     std::string range_value;
00358                     if (range->findAttribute("hide", range_value))
00359                     {
00360                         std::vector<std::string> parse_range = utility::split(range_value);
00361                         if (!parse_range.empty())
00362                         {
00363                             Char first = utility::parseUInt(parse_range[0]);
00364                             Char last = parse_range.size() > 1 ? utility::parseUInt(parse_range[1]) : first;
00365                             removeCodePointRange(first, last);
00366                         }
00367                     }
00368                 }
00369             }
00370         }
00371 
00372         initialise();
00373     }
00374 
00375     GlyphInfo* ResourceTrueTypeFont::getGlyphInfo(Char _id)
00376     {
00377         CharMap::const_iterator charIter = mCharMap.find(_id);
00378 
00379         if (charIter != mCharMap.end())
00380         {
00381             GlyphMap::iterator glyphIter = mGlyphMap.find(charIter->second);
00382 
00383             if (glyphIter != mGlyphMap.end())
00384                 return &glyphIter->second;
00385         }
00386 
00387         return mSubstituteGlyphInfo;
00388     }
00389 
00390     ITexture* ResourceTrueTypeFont::getTextureFont()
00391     {
00392         return mTexture;
00393     }
00394 
00395     int ResourceTrueTypeFont::getDefaultHeight()
00396     {
00397         return mDefaultHeight;
00398     }
00399 
00400     std::vector<std::pair<Char, Char> > ResourceTrueTypeFont::getCodePointRanges() const
00401     {
00402         std::vector<std::pair<Char, Char> > result;
00403 
00404         if (!mCharMap.empty())
00405         {
00406             CharMap::const_iterator iter = mCharMap.begin(), endIter = mCharMap.end();
00407 
00408             // Start the first range with the first code point in the map.
00409             Char rangeBegin = iter->first, rangeEnd = rangeBegin;
00410 
00411             // Loop over the rest of the map and find the contiguous ranges.
00412             for (++iter; iter != endIter; ++iter)
00413             {
00414                 if (iter->first == rangeEnd + 1)
00415                 {
00416                     // Extend the current range.
00417                     ++rangeEnd;
00418                 }
00419                 else
00420                 {
00421                     // Found the start of a new range. First, save the current range.
00422                     result.push_back(std::make_pair(rangeBegin, rangeEnd));
00423 
00424                     // Then start the new range.
00425                     rangeBegin = rangeEnd = iter->first;
00426                 }
00427             }
00428 
00429             // Save the final range.
00430             result.push_back(std::make_pair(rangeBegin, rangeEnd));
00431         }
00432 
00433         return result;
00434     }
00435 
00436     Char ResourceTrueTypeFont::getSubstituteCodePoint() const
00437     {
00438         return mSubstituteCodePoint;
00439     }
00440 
00441     void ResourceTrueTypeFont::addCodePoint(Char _codePoint)
00442     {
00443         mCharMap.insert(CharMap::value_type(_codePoint, 0));
00444     }
00445 
00446     void ResourceTrueTypeFont::removeCodePoint(Char _codePoint)
00447     {
00448         mCharMap.erase(_codePoint);
00449     }
00450 
00451     void ResourceTrueTypeFont::addCodePointRange(Char _first, Char _second)
00452     {
00453         CharMap::iterator positionHint = mCharMap.lower_bound(_first);
00454 
00455         if (positionHint != mCharMap.begin())
00456             --positionHint;
00457 
00458         for (Char i = _first; i <= _second; ++i)
00459             positionHint = mCharMap.insert(positionHint, CharMap::value_type(i, 0));
00460     }
00461 
00462     void ResourceTrueTypeFont::removeCodePointRange(Char _first, Char _second)
00463     {
00464         mCharMap.erase(mCharMap.lower_bound(_first), mCharMap.upper_bound(_second));
00465     }
00466 
00467     void ResourceTrueTypeFont::clearCodePoints()
00468     {
00469         mCharMap.clear();
00470     }
00471 
00472     void ResourceTrueTypeFont::initialise()
00473     {
00474         if (mGlyphSpacing == -1)
00475             mGlyphSpacing = mDefaultGlyphSpacing;
00476 
00477         // If L8A8 (2 bytes per pixel) is supported, use it; otherwise, use R8G8B8A8 (4 bytes per pixel) as L8L8L8A8.
00478         bool laMode = MyGUI::RenderManager::getInstance().isFormatSupported(Pixel<true>::getFormat(), TextureUsage::Static | TextureUsage::Write);
00479 
00480         // Select and call an appropriate initialisation method. By making this decision up front, we avoid having to branch on
00481         // these variables many thousands of times inside tight nested loops later. From this point on, the various function
00482         // templates ensure that all of the necessary branching is done purely at compile time for all combinations.
00483         int init = (laMode ? 2 : 0) | (mAntialias ? 1 : 0);
00484 
00485         switch (init)
00486         {
00487         case 0:
00488             ResourceTrueTypeFont::initialiseFreeType<false, false>();
00489             break;
00490         case 1:
00491             ResourceTrueTypeFont::initialiseFreeType<false, true>();
00492             break;
00493         case 2:
00494             ResourceTrueTypeFont::initialiseFreeType<true, false>();
00495             break;
00496         case 3:
00497             ResourceTrueTypeFont::initialiseFreeType<true, true>();
00498             break;
00499         }
00500     }
00501 
00502     template<bool LAMode, bool Antialias>
00503     void ResourceTrueTypeFont::initialiseFreeType()
00504     {
00505         //-------------------------------------------------------------------//
00506         // Initialise FreeType and load the font.
00507         //-------------------------------------------------------------------//
00508 
00509         FT_Library ftLibrary;
00510 
00511         if (FT_Init_FreeType(&ftLibrary) != 0)
00512             MYGUI_EXCEPT("ResourceTrueTypeFont: Could not init the FreeType library!");
00513 
00514         uint8* fontBuffer = nullptr;
00515 
00516         FT_Face ftFace = loadFace(ftLibrary, fontBuffer);
00517 
00518         if (ftFace == nullptr)
00519         {
00520             MYGUI_LOG(Error, "ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
00521             return;
00522         }
00523 
00524         //-------------------------------------------------------------------//
00525         // Calculate the font metrics.
00526         //-------------------------------------------------------------------//
00527 
00528         // The font's overall ascent and descent are defined in three different places in a TrueType font, and with different
00529         // values in each place. The most reliable source for these metrics is usually the "usWinAscent" and "usWinDescent" pair of
00530         // values in the OS/2 header; however, some fonts contain inaccurate data there. To be safe, we use the highest of the set
00531         // of values contained in the face metrics and the two sets of values contained in the OS/2 header.
00532         int fontAscent = ftFace->size->metrics.ascender >> 6;
00533         int fontDescent = -ftFace->size->metrics.descender >> 6;
00534 
00535         TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(ftFace, ft_sfnt_os2);
00536 
00537         if (os2 != nullptr)
00538         {
00539             setMax(fontAscent, os2->usWinAscent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
00540             setMax(fontDescent, os2->usWinDescent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
00541 
00542             setMax(fontAscent, os2->sTypoAscender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
00543             setMax(fontDescent, -os2->sTypoDescender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
00544         }
00545 
00546         // The nominal font height is calculated as the sum of its ascent and descent as specified by the font designer. Previously
00547         // it was defined by MyGUI in terms of the maximum ascent and descent of the glyphs currently in use, but this caused the
00548         // font's line spacing to change whenever glyphs were added to or removed from the font definition. Doing it this way
00549         // instead prevents a lot of layout problems, and it is also more typographically correct and more aesthetically pleasing.
00550         mDefaultHeight = fontAscent + fontDescent;
00551 
00552         // Set the load flags based on the specified type of hinting.
00553         FT_Int32 ftLoadFlags;
00554 
00555         switch (mHinting)
00556         {
00557         case HintingForceAuto:
00558             ftLoadFlags = FT_LOAD_FORCE_AUTOHINT;
00559             break;
00560         case HintingDisableAuto:
00561             ftLoadFlags = FT_LOAD_NO_AUTOHINT;
00562             break;
00563         case HintingDisableAll:
00564             // When hinting is completely disabled, glyphs must always be rendered -- even during layout calculations -- due to
00565             // discrepancies between the glyph metrics and the actual rendered bitmap metrics.
00566             ftLoadFlags = FT_LOAD_NO_HINTING | FT_LOAD_RENDER;
00567             break;
00568         //case HintingUseNative:
00569         default:
00570             ftLoadFlags = FT_LOAD_DEFAULT;
00571             break;
00572         }
00573 
00574         //-------------------------------------------------------------------//
00575         // Create the glyphs and calculate their metrics.
00576         //-------------------------------------------------------------------//
00577 
00578         GlyphHeightMap glyphHeightMap;
00579         int texWidth = 0;
00580 
00581         // Before creating the glyphs, add the "Space" code point to force that glyph to be created. For historical reasons, MyGUI
00582         // users are accustomed to omitting this code point in their font definitions.
00583         addCodePoint(FontCodeType::Space);
00584 
00585         // Create the standard glyphs.
00586         for (CharMap::iterator iter = mCharMap.begin(); iter != mCharMap.end(); )
00587         {
00588             const Char& codePoint = iter->first;
00589             FT_UInt glyphIndex = FT_Get_Char_Index(ftFace, codePoint);
00590 
00591             texWidth += createFaceGlyph(glyphIndex, codePoint, fontAscent, ftFace, ftLoadFlags, glyphHeightMap);
00592 
00593             // If the newly created glyph is the "Not Defined" glyph, it means that the code point is not supported by the font.
00594             // Remove it from the character map so that we can provide our own substitute instead of letting FreeType do it.
00595             if (iter->second != 0)
00596                 ++iter;
00597             else
00598                 mCharMap.erase(iter++);
00599         }
00600 
00601 #if MYGUI_USE_FREETYPE_BYTECODE_BUG_FIX
00602 
00603         bool isBytecodeAvailable = (ftFace->face_flags & FT_FACE_FLAG_HINTER) != 0;
00604         bool isBytecodeUsedByLoadFlags = (ftLoadFlags & (FT_LOAD_FORCE_AUTOHINT | FT_LOAD_NO_HINTING)) == 0;
00605 
00606         if (isBytecodeAvailable && isBytecodeUsedByLoadFlags)
00607         {
00608             for (GlyphMap::iterator iter = mGlyphMap.begin(); iter != mGlyphMap.end(); ++iter)
00609             {
00610                 if (FT_Load_Glyph(ftFace, iter->first, ftLoadFlags) == 0)
00611                 {
00612                     GlyphInfo& info = iter->second;
00613                     GlyphInfo newInfo = createFaceGlyphInfo(0, fontAscent, ftFace->glyph);
00614 
00615                     if (info.width != newInfo.width)
00616                     {
00617                         texWidth += (int)ceil(newInfo.width) - (int)ceil(info.width);
00618                         info.width = newInfo.width;
00619                     }
00620 
00621                     if (info.height != newInfo.height)
00622                     {
00623                         GlyphHeightMap::mapped_type oldHeightMap = glyphHeightMap[(FT_Pos)info.height];
00624                         GlyphHeightMap::mapped_type::iterator heightMapItem = oldHeightMap.find(iter->first);
00625                         glyphHeightMap[(FT_Pos)newInfo.height].insert(*heightMapItem);
00626                         oldHeightMap.erase(heightMapItem);
00627                         info.height = newInfo.height;
00628                     }
00629 
00630                     if (info.advance != newInfo.advance)
00631                         info.advance = newInfo.advance;
00632 
00633                     if (info.bearingX != newInfo.bearingX)
00634                         info.bearingX = newInfo.bearingX;
00635 
00636                     if (info.bearingY != newInfo.bearingY)
00637                         info.bearingY = newInfo.bearingY;
00638                 }
00639                 else
00640                 {
00641                     MYGUI_LOG(Warning, "ResourceTrueTypeFont: Cannot load glyph " << iter->first << " for character " << iter->second.codePoint << " in font '" << getResourceName() << "'.");
00642                 }
00643             }
00644         }
00645 
00646 #endif // MYGUI_USE_FREETYPE_BYTECODE_BUG_FIX
00647 
00648         // Do some special handling for the "Space" and "Tab" glyphs.
00649         GlyphInfo* spaceGlyphInfo = getGlyphInfo(FontCodeType::Space);
00650 
00651         if (spaceGlyphInfo != nullptr && spaceGlyphInfo->codePoint == FontCodeType::Space)
00652         {
00653             // Adjust the width of the "Space" glyph if it has been customized.
00654             if (mSpaceWidth != 0.0f)
00655             {
00656                 texWidth += (int)ceil(mSpaceWidth) - (int)ceil(spaceGlyphInfo->width);
00657                 spaceGlyphInfo->width = mSpaceWidth;
00658                 spaceGlyphInfo->advance = mSpaceWidth;
00659             }
00660 
00661             // If the width of the "Tab" glyph hasn't been customized, make it eight spaces wide.
00662             if (mTabWidth == 0.0f)
00663                 mTabWidth = mDefaultTabWidth * spaceGlyphInfo->advance;
00664         }
00665 
00666         // Create the special glyphs. They must be created after the standard glyphs so that they take precedence in case of a
00667         // collision. To make sure that the indices of the special glyphs don't collide with any glyph indices in the font, we must
00668         // use glyph indices higher than the highest glyph index in the font.
00669         FT_UInt nextGlyphIndex = (FT_UInt)ftFace->num_glyphs;
00670 
00671         float height = (float)mDefaultHeight;
00672 
00673         texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Tab), 0.0f, 0.0f, mTabWidth, 0.0f, 0.0f), glyphHeightMap);
00674         texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Selected), mSelectedWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);
00675         texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::SelectedBack), mSelectedWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);
00676         texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Cursor), mCursorWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);
00677 
00678         // If a substitute code point has been specified, check to make sure that it exists in the character map. If it doesn't,
00679         // revert to the default "Not Defined" code point. This is not a real code point but rather an invalid Unicode value that
00680         // is guaranteed to cause the "Not Defined" special glyph to be created.
00681         if (mSubstituteCodePoint != FontCodeType::NotDefined && mCharMap.find(mSubstituteCodePoint) == mCharMap.end())
00682             mSubstituteCodePoint = static_cast<Char>(FontCodeType::NotDefined);
00683 
00684         // Create the "Not Defined" code point (and its corresponding glyph) if it's in use as the substitute code point.
00685         if (mSubstituteCodePoint == FontCodeType::NotDefined)
00686             texWidth += createFaceGlyph(0, static_cast<Char>(FontCodeType::NotDefined), fontAscent, ftFace, ftLoadFlags, glyphHeightMap);
00687 
00688         // Cache a pointer to the substitute glyph info for fast lookup.
00689         mSubstituteGlyphInfo = &mGlyphMap.find(mCharMap.find(mSubstituteCodePoint)->second)->second;
00690 
00691         // Calculate the average height of all of the glyphs that are in use. This value will be used for estimating how large the
00692         // texture needs to be.
00693         double averageGlyphHeight = 0.0;
00694 
00695         for (GlyphHeightMap::const_iterator j = glyphHeightMap.begin(); j != glyphHeightMap.end(); ++j)
00696             averageGlyphHeight += j->first * j->second.size();
00697 
00698         averageGlyphHeight /= mGlyphMap.size();
00699 
00700         //-------------------------------------------------------------------//
00701         // Calculate the final texture size.
00702         //-------------------------------------------------------------------//
00703 
00704         // Round the current texture width and height up to the nearest powers of two.
00705         texWidth = Bitwise::firstPO2From(texWidth);
00706         int texHeight = Bitwise::firstPO2From((int)ceil(averageGlyphHeight) + mGlyphSpacing);
00707 
00708         // At this point, the texture is only one glyph high and is probably very wide. For efficiency reasons, we need to make the
00709         // texture as square as possible. If the texture cannot be made perfectly square, make it taller than it is wide, because
00710         // the height may decrease in the final layout due to height packing.
00711         while (texWidth > texHeight)
00712         {
00713             texWidth /= 2;
00714             texHeight *= 2;
00715         }
00716 
00717         // Calculate the final layout of all of the glyphs in the texture, packing them tightly by first arranging them by height.
00718         // We assume that the texture width is fixed but that the texture height can be adjusted up or down depending on how much
00719         // space is actually needed.
00720         // In most cases, the final texture will end up square or almost square. In some rare cases, however, we can end up with a
00721         // texture that's more than twice as high as it is wide; when this happens, we double the width and try again.
00722         do
00723         {
00724             if (texHeight > texWidth * 2)
00725                 texWidth *= 2;
00726 
00727             int texX = 0, texY = 0;
00728 
00729             for (GlyphHeightMap::const_iterator j = glyphHeightMap.begin(); j != glyphHeightMap.end(); ++j)
00730             {
00731                 for (GlyphHeightMap::mapped_type::const_iterator i = j->second.begin(); i != j->second.end(); ++i)
00732                 {
00733                     GlyphInfo& info = *i->second;
00734 
00735                     int glyphWidth = (int)ceil(info.width);
00736                     int glyphHeight = (int)ceil(info.height);
00737 
00738                     autoWrapGlyphPos(glyphWidth, texWidth, glyphHeight, texX, texY);
00739 
00740                     if (glyphWidth > 0)
00741                         texX += mGlyphSpacing + glyphWidth;
00742                 }
00743             }
00744 
00745             texHeight = Bitwise::firstPO2From(texY + glyphHeightMap.rbegin()->first);
00746         }
00747         while (texHeight > texWidth * 2);
00748 
00749         //-------------------------------------------------------------------//
00750         // Create the texture and render the glyphs onto it.
00751         //-------------------------------------------------------------------//
00752 
00753         mTexture = RenderManager::getInstance().createTexture(MyGUI::utility::toString((size_t)this, "_TrueTypeFont"));
00754 
00755         mTexture->createManual(texWidth, texHeight, TextureUsage::Static | TextureUsage::Write, Pixel<LAMode>::getFormat());
00756 
00757         uint8* texBuffer = static_cast<uint8*>(mTexture->lock(TextureUsage::Write));
00758 
00759         if (texBuffer != nullptr)
00760         {
00761             // Make the texture background transparent white.
00762             for (uint8* dest = texBuffer, * endDest = dest + texWidth * texHeight * Pixel<LAMode>::getNumBytes(); dest != endDest; )
00763                 Pixel<LAMode, false, false>::set(dest, charMaskWhite, charMaskBlack);
00764 
00765             renderGlyphs<LAMode, Antialias>(glyphHeightMap, ftLibrary, ftFace, ftLoadFlags, texBuffer, texWidth, texHeight);
00766 
00767             mTexture->unlock();
00768 
00769             MYGUI_LOG(Info, "ResourceTrueTypeFont: Font '" << getResourceName() << "' using texture size " << texWidth << " x " << texHeight << ".");
00770             MYGUI_LOG(Info, "ResourceTrueTypeFont: Font '" << getResourceName() << "' using real height " << mDefaultHeight << " pixels.");
00771         }
00772         else
00773         {
00774             MYGUI_LOG(Error, "ResourceTrueTypeFont: Error locking texture; pointer is nullptr.");
00775         }
00776 
00777         FT_Done_Face(ftFace);
00778         FT_Done_FreeType(ftLibrary);
00779 
00780         delete [] fontBuffer;
00781     }
00782 
00783     FT_Face ResourceTrueTypeFont::loadFace(const FT_Library& _ftLibrary, uint8*& _fontBuffer)
00784     {
00785         FT_Face result = nullptr;
00786 
00787         // Load the font file.
00788         IDataStream* datastream = DataManager::getInstance().getData(mSource);
00789 
00790         if (datastream == nullptr)
00791             return result;
00792 
00793         size_t fontBufferSize = datastream->size();
00794         _fontBuffer = new uint8[fontBufferSize];
00795         datastream->read(_fontBuffer, fontBufferSize);
00796 
00797         DataManager::getInstance().freeData(datastream);
00798         datastream = nullptr;
00799 
00800         // Determine how many faces the font contains.
00801         if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, -1, &result) != 0)
00802             MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
00803 
00804         FT_Long numFaces = result->num_faces;
00805         FT_Long faceIndex = 0;
00806 
00807         // Load the first face.
00808         if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
00809             MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
00810 
00811         if (result->face_flags & FT_FACE_FLAG_SCALABLE)
00812         {
00813             // The font is scalable, so set the font size by first converting the requested size to FreeType's 26.6 fixed-point
00814             // format.
00815             FT_F26Dot6 ftSize = (FT_F26Dot6)(mSize * (1 << 6));
00816 
00817             if (FT_Set_Char_Size(result, ftSize, 0, mResolution, mResolution) != 0)
00818                 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not set the font size for '" << getResourceName() << "'!");
00819 
00820             // If no code points have been specified, use the Unicode Basic Multilingual Plane by default.
00821             if (mCharMap.empty())
00822                 addCodePointRange(0, 0xFFFF);
00823         }
00824         else
00825         {
00826             // The font isn't scalable, so try to load it as a Windows FNT/FON file.
00827             FT_WinFNT_HeaderRec fnt;
00828 
00829             // Enumerate all of the faces in the font and select the smallest one that's at least as large as the requested size
00830             // (after adjusting for resolution). If none of the faces are large enough, use the largest one.
00831             std::map<float, FT_Long> faceSizes;
00832 
00833             do
00834             {
00835                 if (FT_Get_WinFNT_Header(result, &fnt) != 0)
00836                     MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
00837 
00838                 faceSizes.insert(std::make_pair((float)fnt.nominal_point_size * fnt.vertical_resolution / mResolution, faceIndex));
00839 
00840                 FT_Done_Face(result);
00841 
00842                 if (++faceIndex < numFaces)
00843                     if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
00844                         MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
00845             }
00846             while (faceIndex < numFaces);
00847 
00848             std::map<float, FT_Long>::const_iterator iter = faceSizes.lower_bound(mSize);
00849 
00850             faceIndex = (iter != faceSizes.end()) ? iter->second : faceSizes.rbegin()->second;
00851 
00852             if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
00853                 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
00854 
00855             // Select the first bitmap strike available in the selected face. This needs to be done explicitly even though Windows
00856             // FNT/FON files contain only one bitmap strike per face.
00857             if (FT_Select_Size(result, 0) != 0)
00858                 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not set the font size for '" << getResourceName() << "'!");
00859 
00860             // Windows FNT/FON files do not support Unicode, so restrict the code-point range to either ISO-8859-1 or ASCII,
00861             // depending on the font's encoding.
00862             if (mCharMap.empty())
00863             {
00864                 // No code points have been specified, so add the printable ASCII range by default.
00865                 addCodePointRange(0x20, 0x7E);
00866 
00867                 // Additionally, if the font's character set is CP-1252, add the range of non-ASCII 8-bit code points that are
00868                 // common between CP-1252 and ISO-8859-1; i.e., everything but 0x80 through 0x9F.
00869                 if (fnt.charset == FT_WinFNT_ID_CP1252)
00870                     addCodePointRange(0xA0, 0xFF);
00871             }
00872             else
00873             {
00874                 // Some code points have been specified, so remove anything in the non-printable ASCII range as well as anything
00875                 // over 8 bits.
00876                 removeCodePointRange(0, 0x1F);
00877                 removeCodePointRange(0x100, std::numeric_limits<Char>::max());
00878 
00879                 // Additionally, remove non-ASCII 8-bit code points (plus ASCII DEL, 0x7F). If the font's character set is CP-1252,
00880                 // remove only the code points that differ between CP-1252 and ISO-8859-1; otherwise, remove all of them.
00881                 if (fnt.charset == FT_WinFNT_ID_CP1252)
00882                     removeCodePointRange(0x7F, 0x9F);
00883                 else
00884                     removeCodePointRange(0x7F, 0xFF);
00885             }
00886         }
00887 
00888         return result;
00889     }
00890 
00891     void ResourceTrueTypeFont::autoWrapGlyphPos(int _glyphWidth, int _texWidth, int _lineHeight, int& _texX, int& _texY)
00892     {
00893         if (_glyphWidth > 0 && _texX + mGlyphSpacing + _glyphWidth > _texWidth)
00894         {
00895             _texX = 0;
00896             _texY += mGlyphSpacing + _lineHeight;
00897         }
00898     }
00899 
00900     GlyphInfo ResourceTrueTypeFont::createFaceGlyphInfo(Char _codePoint, int _fontAscent, FT_GlyphSlot _glyph)
00901     {
00902         float bearingX = _glyph->metrics.horiBearingX / 64.0f;
00903 
00904         // The following calculations aren't currently needed but are kept here for future use.
00905         // float ascent = _glyph->metrics.horiBearingY / 64.0f;
00906         // float descent = (_glyph->metrics.height / 64.0f) - ascent;
00907 
00908         return GlyphInfo(
00909             _codePoint,
00910             std::max((float)_glyph->bitmap.width, _glyph->metrics.width / 64.0f),
00911             std::max((float)_glyph->bitmap.rows, _glyph->metrics.height / 64.0f),
00912             (_glyph->advance.x / 64.0f) - bearingX,
00913             bearingX,
00914             floor(_fontAscent - (_glyph->metrics.horiBearingY / 64.0f) - mOffsetHeight));
00915     }
00916 
00917     int ResourceTrueTypeFont::createGlyph(FT_UInt _glyphIndex, const GlyphInfo& _glyphInfo, GlyphHeightMap& _glyphHeightMap)
00918     {
00919         int width = (int)ceil(_glyphInfo.width);
00920         int height = (int)ceil(_glyphInfo.height);
00921 
00922         mCharMap[_glyphInfo.codePoint] = _glyphIndex;
00923         GlyphInfo& info = mGlyphMap.insert(GlyphMap::value_type(_glyphIndex, _glyphInfo)).first->second;
00924         _glyphHeightMap[(FT_Pos)height].insert(std::make_pair(_glyphIndex, &info));
00925 
00926         return (width > 0) ? mGlyphSpacing + width : 0;
00927     }
00928 
00929     int ResourceTrueTypeFont::createFaceGlyph(FT_UInt _glyphIndex, Char _codePoint, int _fontAscent, const FT_Face& _ftFace, FT_Int32 _ftLoadFlags, GlyphHeightMap& _glyphHeightMap)
00930     {
00931         if (mGlyphMap.find(_glyphIndex) == mGlyphMap.end())
00932         {
00933             if (FT_Load_Glyph(_ftFace, _glyphIndex, _ftLoadFlags) == 0)
00934                 return createGlyph(_glyphIndex, createFaceGlyphInfo(_codePoint, _fontAscent, _ftFace->glyph), _glyphHeightMap);
00935             else
00936                 MYGUI_LOG(Warning, "ResourceTrueTypeFont: Cannot load glyph " << _glyphIndex << " for character " << _codePoint << " in font '" << getResourceName() << "'.");
00937         }
00938         else
00939         {
00940             mCharMap[_codePoint] = _glyphIndex;
00941         }
00942 
00943         return 0;
00944     }
00945 
00946     template<bool LAMode, bool Antialias>
00947     void ResourceTrueTypeFont::renderGlyphs(const GlyphHeightMap& _glyphHeightMap, const FT_Library& _ftLibrary, const FT_Face& _ftFace, FT_Int32 _ftLoadFlags, uint8* _texBuffer, int _texWidth, int _texHeight)
00948     {
00949         FT_Bitmap ftBitmap;
00950         FT_Bitmap_New(&ftBitmap);
00951 
00952         int texX = 0, texY = 0;
00953 
00954         for (GlyphHeightMap::const_iterator j = _glyphHeightMap.begin(); j != _glyphHeightMap.end(); ++j)
00955         {
00956             for (GlyphHeightMap::mapped_type::const_iterator i = j->second.begin(); i != j->second.end(); ++i)
00957             {
00958                 GlyphInfo& info = *i->second;
00959 
00960                 switch (info.codePoint)
00961                 {
00962                 case FontCodeType::Selected:
00963                 case FontCodeType::SelectedBack:
00964                 {
00965                     renderGlyph<LAMode, false, false>(info, charMaskWhite, charMaskBlack, charMask.find(info.codePoint)->second, j->first, _texBuffer, _texWidth, _texHeight, texX, texY);
00966 
00967                     // Manually adjust the glyph's width to zero. This prevents artifacts from appearing at the seams when
00968                     // rendering multi-character selections.
00969                     GlyphInfo* glyphInfo = getGlyphInfo(info.codePoint);
00970                     glyphInfo->width = 0.0f;
00971                     glyphInfo->uvRect.right = glyphInfo->uvRect.left;
00972                 }
00973                 break;
00974 
00975                 case FontCodeType::Cursor:
00976                 case FontCodeType::Tab:
00977                     renderGlyph<LAMode, false, false>(info, charMaskWhite, charMaskBlack, charMask.find(info.codePoint)->second, j->first, _texBuffer, _texWidth, _texHeight, texX, texY);
00978                     break;
00979 
00980                 default:
00981                     if (FT_Load_Glyph(_ftFace, i->first, _ftLoadFlags | FT_LOAD_RENDER) == 0)
00982                     {
00983                         if (_ftFace->glyph->bitmap.buffer != nullptr)
00984                         {
00985                             uint8* glyphBuffer = nullptr;
00986 
00987                             switch (_ftFace->glyph->bitmap.pixel_mode)
00988                             {
00989                             case FT_PIXEL_MODE_GRAY:
00990                                 glyphBuffer = _ftFace->glyph->bitmap.buffer;
00991                                 break;
00992 
00993                             case FT_PIXEL_MODE_MONO:
00994                                 // Convert the monochrome bitmap to 8-bit before rendering it.
00995                                 if (FT_Bitmap_Convert(_ftLibrary, &_ftFace->glyph->bitmap, &ftBitmap, 1) == 0)
00996                                 {
00997                                     // Go through the bitmap and convert all of the nonzero values to 0xFF (white).
00998                                     for (uint8* p = ftBitmap.buffer, * endP = p + ftBitmap.width * ftBitmap.rows; p != endP; ++p)
00999                                         *p ^= -*p ^ *p;
01000 
01001                                     glyphBuffer = ftBitmap.buffer;
01002                                 }
01003                                 break;
01004                             }
01005 
01006                             if (glyphBuffer != nullptr)
01007                                 renderGlyph<LAMode, true, Antialias>(info, charMaskWhite, charMaskWhite, charMaskWhite, j->first, _texBuffer, _texWidth, _texHeight, texX, texY, glyphBuffer);
01008                         }
01009                     }
01010                     else
01011                     {
01012                         MYGUI_LOG(Warning, "ResourceTrueTypeFont: Cannot render glyph " << i->first << " for character " << info.codePoint << " in font '" << getResourceName() << "'.");
01013                     }
01014                     break;
01015                 }
01016             }
01017         }
01018 
01019         FT_Bitmap_Done(_ftLibrary, &ftBitmap);
01020     }
01021 
01022     template<bool LAMode, bool UseBuffer, bool Antialias>
01023     void ResourceTrueTypeFont::renderGlyph(GlyphInfo& _info, uint8 _luminance0, uint8 _luminance1, uint8 _alpha, int _lineHeight, uint8* _texBuffer, int _texWidth, int _texHeight, int& _texX, int& _texY, uint8* _glyphBuffer)
01024     {
01025         int width = (int)ceil(_info.width);
01026         int height = (int)ceil(_info.height);
01027 
01028         autoWrapGlyphPos(width, _texWidth, _lineHeight, _texX, _texY);
01029 
01030         uint8* dest = _texBuffer + (_texY * _texWidth + _texX) * Pixel<LAMode>::getNumBytes();
01031 
01032         // Calculate how much to advance the destination pointer after each row to get to the start of the next row.
01033         ptrdiff_t destNextRow = (_texWidth - width) * Pixel<LAMode>::getNumBytes();
01034 
01035         for (int j = height; j > 0; --j)
01036         {
01037             int i;
01038             for (i = width; i > 1; i -= 2)
01039             {
01040                 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance0, _alpha, _glyphBuffer);
01041                 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance1, _alpha, _glyphBuffer);
01042             }
01043 
01044             if (i > 0)
01045                 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance0, _alpha, _glyphBuffer);
01046 
01047             dest += destNextRow;
01048         }
01049 
01050         // Calculate and store the glyph's UV coordinates within the texture.
01051         _info.uvRect.left = (float)_texX / _texWidth; // u1
01052         _info.uvRect.top = (float)_texY / _texHeight; // v1
01053         _info.uvRect.right = (float)(_texX + _info.width) / _texWidth; // u2
01054         _info.uvRect.bottom = (float)(_texY + _info.height) / _texHeight; // v2
01055 
01056         if (width > 0)
01057             _texX += mGlyphSpacing + width;
01058     }
01059 
01060     void ResourceTrueTypeFont::setSource(const std::string& _value)
01061     {
01062         mSource = _value;
01063     }
01064 
01065     void ResourceTrueTypeFont::setSize(float _value)
01066     {
01067         mSize = _value;
01068     }
01069 
01070     void ResourceTrueTypeFont::setResolution(uint _value)
01071     {
01072         mResolution = _value;
01073     }
01074 
01075     void ResourceTrueTypeFont::setHinting(const std::string& _value)
01076     {
01077         if (_value == "use_native")
01078             mHinting = HintingUseNative;
01079         else if (_value == "force_auto")
01080             mHinting = HintingForceAuto;
01081         else if (_value == "disable_auto")
01082             mHinting = HintingDisableAuto;
01083         else if (_value == "disable_all")
01084             mHinting = HintingDisableAll;
01085         else
01086             mHinting = HintingUseNative;
01087     }
01088 
01089     void ResourceTrueTypeFont::setAntialias(bool _value)
01090     {
01091         mAntialias = _value;
01092     }
01093 
01094     void ResourceTrueTypeFont::setTabWidth(float _value)
01095     {
01096         mTabWidth = _value;
01097     }
01098 
01099     void ResourceTrueTypeFont::setOffsetHeight(int _value)
01100     {
01101         mOffsetHeight = _value;
01102     }
01103 
01104     void ResourceTrueTypeFont::setSubstituteCode(int _value)
01105     {
01106         mSubstituteCodePoint = _value;
01107     }
01108 
01109     void ResourceTrueTypeFont::setDistance(int _value)
01110     {
01111         mGlyphSpacing = _value;
01112     }
01113 
01114 #endif // MYGUI_USE_FREETYPE
01115 
01116 } // namespace MyGUI