14#ifdef MYGUI_USE_FREETYPE
17# include FT_TRUETYPE_TABLES_H
19# include FT_WINFONTS_H
21#ifdef MYGUI_MSDF_FONTS
22#include "msdfgen/msdfgen.h"
23#include "msdfgen/msdfgen-ext.h"
31#ifndef MYGUI_USE_FREETYPE
43 MYGUI_LOG(Error,
"ResourceTrueTypeFont: TrueType font '" <<
getResourceName() <<
"' disabled. Define MYGUI_USE_FREETYE if you need TrueType fonts.");
67 return std::vector<std::pair<Char, Char> >();
140 void setMax(T& _var,
const T& _newValue)
142 if (_var < _newValue)
146 std::pair<const Char, const uint8> charMaskData[] =
154 const std::map<const Char, const uint8> charMask(charMaskData, charMaskData +
sizeof charMaskData /
sizeof(*charMaskData));
156 const uint8 charMaskBlack = (
const uint8)
'\x00';
157 const uint8 charMaskWhite = (
const uint8)
'\xFF';
159 template<
bool LAMode>
166 static size_t getNumBytes();
175 struct PixelBase<false>
177 static size_t getNumBytes()
190 *_dest++ = _luminance;
191 *_dest++ = _luminance;
192 *_dest++ = _luminance;
198 struct PixelBase<true>
200 static size_t getNumBytes()
213 *_dest++ = _luminance;
218 template<
bool LAMode,
bool FromSource = false,
bool Antialias = false>
219 struct Pixel : PixelBase<LAMode>
229 template<
bool LAMode,
bool Antialias>
230 struct Pixel<LAMode, false, Antialias> : PixelBase<LAMode>
235 PixelBase<LAMode>::set(_dest, _luminance, _alpha);
239 template<
bool LAMode>
240 struct Pixel<LAMode, true, false> : PixelBase<LAMode>
245 PixelBase<LAMode>::set(_dest, _luminance, *_source++);
249 template<
bool LAMode>
250 struct Pixel<LAMode, true, true> : PixelBase<LAMode>
255 PixelBase<LAMode>::set(_dest, *_source, *_source);
262 const int ResourceTrueTypeFont::mDefaultGlyphSpacing = 1;
263 const float ResourceTrueTypeFont::mDefaultTabWidth = 8.0f;
264 const float ResourceTrueTypeFont::mSelectedWidth = 1.0f;
265 const float ResourceTrueTypeFont::mCursorWidth = 2.0f;
270 mHinting(HintingUseNative),
276 mSubstituteCodePoint(static_cast<
Char>(FontCodeType::
NotDefined)),
280 mSubstituteGlyphInfo(nullptr),
287 if (mTexture !=
nullptr)
298 xml::ElementEnumerator node = _node->getElementEnumerator();
301 if (node->getName() ==
"Property")
303 const std::string& key = node->findAttribute(
"key");
304 const std::string& value = node->findAttribute(
"value");
307 else if (key ==
"Shader")
309 else if (key ==
"Size")
311 else if (key ==
"Resolution")
313 else if (key ==
"Antialias")
315 else if (key ==
"TabWidth")
317 else if (key ==
"OffsetHeight")
319 else if (key ==
"SubstituteCode")
321 else if (key ==
"Distance")
323 else if (key ==
"Hinting")
325 else if (key ==
"SpaceWidth")
328 MYGUI_LOG(Warning, _node->findAttribute(
"type") <<
": Property '" << key <<
"' in font '" << _node->findAttribute(
"name") <<
"' is deprecated; remove it to use automatic calculation.");
330 else if (key ==
"CursorWidth")
332 MYGUI_LOG(Warning, _node->findAttribute(
"type") <<
": Property '" << key <<
"' in font '" << _node->findAttribute(
"name") <<
"' is deprecated; value ignored.");
334 else if (key ==
"MsdfMode")
338 else if (key ==
"MsdfRange")
343 else if (node->getName() ==
"Codes")
346 xml::ElementEnumerator range = node->getElementEnumerator();
347 while (range.next(
"Code"))
349 std::string range_value;
350 if (range->findAttribute(
"range", range_value))
352 std::vector<std::string> parse_range =
utility::split(range_value);
353 if (!parse_range.empty())
364 if (mCharMap.empty())
368 range = node->getElementEnumerator();
369 while (range.next(
"Code"))
371 std::string range_value;
372 if (range->findAttribute(
"hide", range_value))
374 std::vector<std::string> parse_range =
utility::split(range_value);
375 if (!parse_range.empty())
391 GlyphMap::const_iterator glyphIter = mGlyphMap.find(_id);
393 if (glyphIter != mGlyphMap.end())
395 return &glyphIter->second;
398 return mSubstituteGlyphInfo;
408 return mDefaultHeight;
419 std::vector<std::pair<Char, Char> > result;
421 if (!mCharMap.empty())
423 CharMap::const_iterator iter = mCharMap.begin(), endIter = mCharMap.end();
426 Char rangeBegin = iter->first, rangeEnd = rangeBegin;
429 for (++iter; iter != endIter; ++iter)
431 if (iter->first == rangeEnd + 1)
439 result.push_back(std::make_pair(rangeBegin, rangeEnd));
442 rangeBegin = rangeEnd = iter->first;
447 result.push_back(std::make_pair(rangeBegin, rangeEnd));
455 return mSubstituteCodePoint;
458 void ResourceTrueTypeFont::addCodePoint(
Char _codePoint)
460 mCharMap.insert(CharMap::value_type(_codePoint, 0));
463 void ResourceTrueTypeFont::removeCodePoint(
Char _codePoint)
465 mCharMap.erase(_codePoint);
470 CharMap::iterator positionHint = mCharMap.lower_bound(_first);
472 if (positionHint != mCharMap.begin())
475 for (
Char i = _first; i <= _second; ++i)
476 positionHint = mCharMap.insert(positionHint, CharMap::value_type(i, 0));
481 mCharMap.erase(mCharMap.lower_bound(_first), mCharMap.upper_bound(_second));
484 void ResourceTrueTypeFont::clearCodePoints()
491 if (mGlyphSpacing == -1)
492 mGlyphSpacing = mDefaultGlyphSpacing;
502 int init = (laMode ? 2 : 0) | (mAntialias ? 1 : 0);
507 ResourceTrueTypeFont::initialiseFreeType<false, false>();
510 ResourceTrueTypeFont::initialiseFreeType<false, true>();
513 ResourceTrueTypeFont::initialiseFreeType<true, false>();
516 ResourceTrueTypeFont::initialiseFreeType<true, true>();
521 template<
bool LAMode,
bool Antialias>
522 void ResourceTrueTypeFont::initialiseFreeType()
528 FT_Library ftLibrary;
530 if (FT_Init_FreeType(&ftLibrary) != 0)
531 MYGUI_EXCEPT(
"ResourceTrueTypeFont: Could not init the FreeType library!");
533 uint8* fontBuffer =
nullptr;
535 FT_Face ftFace = loadFace(ftLibrary, fontBuffer);
537 if (ftFace ==
nullptr)
540 FT_Done_FreeType(ftLibrary);
544#ifdef MYGUI_MSDF_FONTS
545 msdfgen::FontHandle* msdfFont =
nullptr;
549 msdfFont = msdfgen::adoptFreetypeFont(ftFace);
561 int fontAscent = ftFace->size->metrics.ascender >> 6;
562 int fontDescent = -ftFace->size->metrics.descender >> 6;
564 TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(ftFace, ft_sfnt_os2);
568 setMax(fontAscent, os2->usWinAscent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
569 setMax(fontDescent, os2->usWinDescent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
571 setMax(fontAscent, os2->sTypoAscender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
572 setMax(fontDescent, -os2->sTypoDescender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
579 mDefaultHeight = fontAscent + fontDescent;
582 FT_Int32 ftLoadFlags = FT_LOAD_DEFAULT;
586 case HintingForceAuto:
587 ftLoadFlags = FT_LOAD_FORCE_AUTOHINT;
589 case HintingDisableAuto:
590 ftLoadFlags = FT_LOAD_NO_AUTOHINT;
592 case HintingDisableAll:
595 ftLoadFlags = FT_LOAD_NO_HINTING | FT_LOAD_RENDER;
597 case HintingUseNative:
598 ftLoadFlags = FT_LOAD_DEFAULT;
606 GlyphHeightMap glyphHeightMap;
614 for (CharMap::iterator iter = mCharMap.begin(); iter != mCharMap.end(); )
616 const Char& codePoint = iter->first;
617 FT_UInt glyphIndex = FT_Get_Char_Index(ftFace, codePoint);
620 texWidth += createFaceGlyph(glyphIndex, codePoint, fontAscent, ftFace, ftLoadFlags, glyphHeightMap);
621#ifdef MYGUI_MSDF_FONTS
623 texWidth += createMsdfFaceGlyph(codePoint, fontAscent, msdfFont, glyphHeightMap);
628 if (iter->second != 0)
631 mCharMap.erase(iter++);
637 if (spaceGlyphIter != mGlyphMap.end())
640 if (mSpaceWidth != 0.0f)
642 texWidth += (int)std::ceil(mSpaceWidth) - (int)std::ceil(spaceGlyphIter->second.width);
643 spaceGlyphIter->second.width = mSpaceWidth;
644 spaceGlyphIter->second.advance = mSpaceWidth;
648 if (mTabWidth == 0.0f)
649 mTabWidth = mDefaultTabWidth * spaceGlyphIter->second.advance;
655 FT_UInt nextGlyphIndex = (FT_UInt)ftFace->num_glyphs;
657 float height = (
float)mDefaultHeight;
659 texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(
static_cast<Char>(
FontCodeType::Tab), 0.0f, 0.0f, mTabWidth, 0.0f, 0.0f), glyphHeightMap);
660 texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(
static_cast<Char>(
FontCodeType::Selected), mSelectedWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);
661 texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(
static_cast<Char>(
FontCodeType::SelectedBack), mSelectedWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);
662 texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(
static_cast<Char>(
FontCodeType::Cursor), mCursorWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap);
675#ifdef MYGUI_MSDF_FONTS
682 mSubstituteGlyphInfo = &mGlyphMap.find(mSubstituteCodePoint)->second;
686 double averageGlyphHeight = 0.0;
688 for (GlyphHeightMap::const_iterator j = glyphHeightMap.begin(); j != glyphHeightMap.end(); ++j)
689 averageGlyphHeight += j->first * j->second.size();
691 averageGlyphHeight /= mGlyphMap.size();
704 while (texWidth > texHeight)
717 if (texHeight > texWidth * 2)
720 int texX = mGlyphSpacing;
721 int texY = mGlyphSpacing;
723 for (GlyphHeightMap::const_iterator j = glyphHeightMap.begin(); j != glyphHeightMap.end(); ++j)
725 for (GlyphHeightMap::mapped_type::const_iterator i = j->second.begin(); i != j->second.end(); ++i)
727 GlyphInfo& info = *i->second;
729 int glyphWidth = (int)std::ceil(info.width);
730 int glyphHeight = (int)std::ceil(info.height);
732 autoWrapGlyphPos(glyphWidth, texWidth, glyphHeight, texX, texY);
735 texX += mGlyphSpacing + glyphWidth;
741 while (texHeight > texWidth * 2);
756 mTexture->setInvalidateListener(
this);
758 if (!mShader.empty())
759 mTexture->setShader(mShader);
763 if (texBuffer !=
nullptr)
766 for (
uint8* dest = texBuffer, * endDest = dest + texWidth * texHeight * Pixel<LAMode>::getNumBytes(); dest != endDest; )
767 Pixel<LAMode, false, false>::set(dest, mMsdfMode ? charMaskBlack : charMaskWhite, charMaskBlack);
770 renderGlyphs<LAMode, Antialias>(glyphHeightMap, ftLibrary, ftFace, ftLoadFlags, texBuffer, texWidth, texHeight);
771#ifdef MYGUI_MSDF_FONTS
773 renderMsdfGlyphs(glyphHeightMap, msdfFont, texBuffer, texWidth, texHeight);
778 MYGUI_LOG(Info,
"ResourceTrueTypeFont: Font '" <<
getResourceName() <<
"' using texture size " << texWidth <<
" x " << texHeight <<
".");
779 MYGUI_LOG(Info,
"ResourceTrueTypeFont: Font '" <<
getResourceName() <<
"' using real height " << mDefaultHeight <<
" pixels.");
783 MYGUI_LOG(Error,
"ResourceTrueTypeFont: Error locking texture; pointer is nullptr.");
786#ifdef MYGUI_MSDF_FONTS
789 msdfgen::destroyFont(msdfFont);
793 FT_Done_Face(ftFace);
794 FT_Done_FreeType(ftLibrary);
796 delete [] fontBuffer;
799 FT_Face ResourceTrueTypeFont::loadFace(
const FT_Library& _ftLibrary,
uint8*& _fontBuffer)
801 FT_Face result =
nullptr;
806 if (datastream ==
nullptr)
809 size_t fontBufferSize = datastream->
size();
810 _fontBuffer =
new uint8[fontBufferSize];
811 datastream->read(_fontBuffer, fontBufferSize);
814 datastream =
nullptr;
817 if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, -1, &result) != 0)
820 FT_Long numFaces = result->num_faces;
821 FT_Long faceIndex = 0;
824 if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
827 if (result->face_flags & FT_FACE_FLAG_SCALABLE)
831 FT_F26Dot6 ftSize = (FT_F26Dot6)(mSize * (1 << 6));
833 if (FT_Set_Char_Size(result, ftSize, 0, mResolution, mResolution) != 0)
837 if (mCharMap.empty())
843 FT_WinFNT_HeaderRec fnt;
847 std::map<float, FT_Long> faceSizes;
851 if (FT_Get_WinFNT_Header(result, &fnt) != 0)
854 faceSizes.insert(std::make_pair((
float)fnt.nominal_point_size * fnt.vertical_resolution / mResolution, faceIndex));
856 FT_Done_Face(result);
858 if (++faceIndex < numFaces)
859 if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
862 while (faceIndex < numFaces);
864 std::map<float, FT_Long>::const_iterator iter = faceSizes.lower_bound(mSize);
866 faceIndex = (iter != faceSizes.end()) ? iter->second : faceSizes.rbegin()->second;
868 if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
873 if (FT_Select_Size(result, 0) != 0)
878 if (mCharMap.empty())
885 if (fnt.charset == FT_WinFNT_ID_CP1252)
897 if (fnt.charset == FT_WinFNT_ID_CP1252)
907 void ResourceTrueTypeFont::autoWrapGlyphPos(
int _glyphWidth,
int _texWidth,
int _lineHeight,
int& _texX,
int& _texY)
const
909 if (_glyphWidth > 0 && _texX + mGlyphSpacing + _glyphWidth > _texWidth)
911 _texX = mGlyphSpacing;
912 _texY += mGlyphSpacing + _lineHeight;
916 GlyphInfo ResourceTrueTypeFont::createFaceGlyphInfo(
Char _codePoint,
int _fontAscent, FT_GlyphSlot _glyph)
const
918 float bearingX = _glyph->metrics.horiBearingX / 64.0f;
926 std::max((
float)_glyph->bitmap.width, _glyph->metrics.width / 64.0f),
927 std::max((
float)_glyph->bitmap.rows, _glyph->metrics.height / 64.0f),
928 (_glyph->advance.x / 64.0f) - bearingX,
930 std::floor(_fontAscent - (_glyph->metrics.horiBearingY / 64.0f) - mOffsetHeight));
933 int ResourceTrueTypeFont::createGlyph(FT_UInt _glyphIndex,
const GlyphInfo& _glyphInfo, GlyphHeightMap& _glyphHeightMap)
935 int width = (int)std::ceil(_glyphInfo.width);
936 int height = (int)std::ceil(_glyphInfo.height);
938 mCharMap[_glyphInfo.codePoint] = _glyphIndex;
939 GlyphInfo& info = mGlyphMap.insert(GlyphMap::value_type(_glyphInfo.codePoint, _glyphInfo)).first->second;
940 _glyphHeightMap[height].insert(std::make_pair(_glyphIndex, &info));
942 return (width > 0) ? mGlyphSpacing + width : 0;
945 int ResourceTrueTypeFont::createFaceGlyph(FT_UInt _glyphIndex,
Char _codePoint,
int _fontAscent,
const FT_Face& _ftFace, FT_Int32 _ftLoadFlags, GlyphHeightMap& _glyphHeightMap)
947 if (mGlyphMap.find(_codePoint) == mGlyphMap.end())
949 if (FT_Load_Glyph(_ftFace, _glyphIndex, _ftLoadFlags) == 0)
950 return createGlyph(_glyphIndex, createFaceGlyphInfo(_codePoint, _fontAscent, _ftFace->glyph), _glyphHeightMap);
952 MYGUI_LOG(Warning,
"ResourceTrueTypeFont: Cannot load glyph " << _glyphIndex <<
" for character " << _codePoint <<
" in font '" <<
getResourceName() <<
"'.");
956 mCharMap[_codePoint] = _glyphIndex;
962 template<
bool LAMode,
bool Antialias>
963 void ResourceTrueTypeFont::renderGlyphs(
const GlyphHeightMap& _glyphHeightMap,
const FT_Library& _ftLibrary,
const FT_Face& _ftFace, FT_Int32 _ftLoadFlags,
uint8* _texBuffer,
int _texWidth,
int _texHeight)
966 FT_Bitmap_New(&ftBitmap);
968 int texX = mGlyphSpacing, texY = mGlyphSpacing;
970 for (
const auto& sameHeightGlyphs : _glyphHeightMap)
972 int glyphHeight = sameHeightGlyphs.first;
973 for (
const auto& glyph : sameHeightGlyphs.second)
975 GlyphInfo& info = *glyph.second;
977 switch (info.codePoint)
982 renderGlyph<LAMode, false, false>(info, charMaskWhite, charMaskBlack, charMask.find(info.codePoint)->second, glyphHeight, _texBuffer, _texWidth, _texHeight, texX, texY);
986 GlyphMap::iterator glyphIter = mGlyphMap.find(info.codePoint);
987 if (glyphIter != mGlyphMap.end())
989 glyphIter->second.width = 0.0f;
990 glyphIter->second.uvRect.right = glyphIter->second.uvRect.left;
997 renderGlyph<LAMode, false, false>(info, charMaskWhite, charMaskBlack, charMask.find(info.codePoint)->second, glyphHeight, _texBuffer, _texWidth, _texHeight, texX, texY);
1001 if (FT_Load_Glyph(_ftFace, glyph.first, _ftLoadFlags | FT_LOAD_RENDER) == 0)
1003 if (_ftFace->glyph->bitmap.buffer !=
nullptr)
1005 uint8* glyphBuffer =
nullptr;
1007 switch (_ftFace->glyph->bitmap.pixel_mode)
1009 case FT_PIXEL_MODE_GRAY:
1010 glyphBuffer = _ftFace->glyph->bitmap.buffer;
1013 case FT_PIXEL_MODE_MONO:
1015 if (FT_Bitmap_Convert(_ftLibrary, &_ftFace->glyph->bitmap, &ftBitmap, 1) == 0)
1018 for (
uint8* p = ftBitmap.buffer, * endP = p + ftBitmap.width * ftBitmap.rows; p != endP; ++p)
1021 glyphBuffer = ftBitmap.buffer;
1026 if (glyphBuffer !=
nullptr)
1027 renderGlyph<LAMode, true, Antialias>(info, charMaskWhite, charMaskWhite, charMaskWhite, glyphHeight, _texBuffer, _texWidth, _texHeight, texX, texY, glyphBuffer);
1032 MYGUI_LOG(Warning,
"ResourceTrueTypeFont: Cannot render glyph " << glyph.first <<
" for character " << info.codePoint <<
" in font '" <<
getResourceName() <<
"'.");
1039 FT_Bitmap_Done(_ftLibrary, &ftBitmap);
1042 template<
bool LAMode,
bool UseBuffer,
bool Antialias>
1043 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)
1045 int width = (int)std::ceil(_info.width);
1046 int height = (int)std::ceil(_info.height);
1048 autoWrapGlyphPos(width, _texWidth, _lineHeight, _texX, _texY);
1050 uint8* dest = _texBuffer + (_texY * _texWidth + _texX) * Pixel<LAMode>::getNumBytes();
1053 ptrdiff_t destNextRow = (_texWidth - width) * Pixel<LAMode>::getNumBytes();
1055 if (!mMsdfMode || !UseBuffer)
1057 for (
int j = height; j > 0; --j)
1060 for (i = width; i > 1; i -= 2)
1062 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance0, _alpha, _glyphBuffer);
1063 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance1, _alpha, _glyphBuffer);
1067 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance0, _alpha, _glyphBuffer);
1069 dest += destNextRow;
1074 for (
int y = 0; y < height; ++y)
1076 for (
int x = 0; x < width; ++x)
1078 for (
int i = 0; i < 3; ++i)
1080 *dest++ = *_glyphBuffer++;
1085 dest += destNextRow;
1090 _info.uvRect.left = (float)_texX / _texWidth;
1091 _info.uvRect.top = (float)_texY / _texHeight;
1092 _info.uvRect.right = (float)(_texX + _info.width) / _texWidth;
1093 _info.uvRect.bottom = (float)(_texY + _info.height) / _texHeight;
1096 _texX += mGlyphSpacing + width;
1099#ifdef MYGUI_MSDF_FONTS
1100 GlyphInfo ResourceTrueTypeFont::createMsdfFaceGlyphInfo(
Char _codePoint,
const msdfgen::Shape& _shape,
double _advance,
int _fontAscent)
1102 msdfgen::Shape::Bounds bounds = _shape.getBounds();
1103 double range = mMsdfRange / 2.0;
1104 if (_shape.contours.empty())
1106 bounds = {0, 0, 0, 0};
1110 double bearingX = bounds.l;
1114 bounds.r - bounds.l + 2 * range,
1115 bounds.t - bounds.b + 2 * range,
1116 _advance - bearingX + range,
1118 std::floor(_fontAscent - bounds.t - mOffsetHeight - range));
1121 int ResourceTrueTypeFont::createMsdfGlyph(
const GlyphInfo& _glyphInfo, GlyphHeightMap& _glyphHeightMap)
1123 int width = (int)std::ceil(_glyphInfo.width);
1124 int height = (int)std::ceil(_glyphInfo.height);
1126 mCharMap[_glyphInfo.codePoint] = _glyphInfo.codePoint;
1127 GlyphInfo& info = mGlyphMap.insert(GlyphMap::value_type(_glyphInfo.codePoint, _glyphInfo)).first->second;
1128 _glyphHeightMap[height].insert(std::make_pair(_glyphInfo.codePoint, &info));
1130 return (width > 0) ? mGlyphSpacing + width : 0;
1133 int ResourceTrueTypeFont::createMsdfFaceGlyph(
Char _codePoint,
int _fontAscent, msdfgen::FontHandle* _fontHandle, GlyphHeightMap& _glyphHeightMap)
1135 if (mGlyphMap.find(_codePoint) == mGlyphMap.end())
1137 msdfgen::Shape shape;
1139 if (msdfgen::loadGlyph(shape, _fontHandle, _codePoint, &advance))
1140 createMsdfGlyph(createMsdfFaceGlyphInfo(_codePoint, shape, advance, _fontAscent), _glyphHeightMap);
1142 MYGUI_LOG(Warning,
"ResourceTrueTypeFont: Cannot load msdf glyph for character " << _codePoint <<
" in font '" <<
getResourceName() <<
"'.");
1146 mCharMap[_codePoint] = _codePoint;
1152 void ResourceTrueTypeFont::renderMsdfGlyphs(
const GlyphHeightMap& _glyphHeightMap, msdfgen::FontHandle* _fontHandle,
uint8* _texBuffer,
int _texWidth,
int _texHeight)
1154 int texX = mGlyphSpacing, texY = mGlyphSpacing;
1156 for (
const auto& sameHeightGlyphs : _glyphHeightMap)
1158 int glyphHeight = sameHeightGlyphs.first;
1159 for (
const auto& glyph : sameHeightGlyphs.second)
1161 GlyphInfo& info = *glyph.second;
1163 switch (info.codePoint)
1168 renderGlyph<false, false, false>(info, charMaskWhite, charMaskBlack, charMask.find(info.codePoint)->second, glyphHeight, _texBuffer, _texWidth, _texHeight, texX, texY);
1172 GlyphMap::iterator glyphIter = mGlyphMap.find(info.codePoint);
1173 if (glyphIter != mGlyphMap.end())
1175 glyphIter->second.width = 0.0f;
1176 glyphIter->second.uvRect.right = glyphIter->second.uvRect.left;
1183 renderGlyph<false, false, false>(info, charMaskWhite, charMaskBlack, charMask.find(info.codePoint)->second, glyphHeight, _texBuffer, _texWidth, _texHeight, texX, texY);
1187 msdfgen::Shape shape;
1188 if (loadGlyph(shape, _fontHandle, info.codePoint))
1190 msdfgen::Shape::Bounds bounds = shape.getBounds();
1191 double range = mMsdfRange / 2.0;
1192 if (shape.contours.empty())
1194 bounds = {0, 0, 0, 0};
1199 edgeColoringSimple(shape, 3.0);
1201 msdfgen::Bitmap<float, 3> msdf(
1202 std::ceil(bounds.r - bounds.l + 2 * range),
1203 std::ceil(bounds.t - bounds.b + 2 * range));
1204 msdfgen::generateMSDF(msdf, shape, mMsdfRange, 1, msdfgen::Vector2(-bounds.l + range, -bounds.b + range));
1214 uint8* glyphBuffer =
new uint8[msdf.width() * msdf.height() * 3];
1215 uint8* glyphBufferPointer = glyphBuffer;
1216 for (
int y = 0; y < msdf.height(); ++y)
1218 for (
int x = 0; x < msdf.width(); ++x)
1220 for (
int i = 0; i < 3; ++i)
1223 *glyphBufferPointer++ = msdfgen::pixelFloatToByte(msdf(x, msdf.height() - y - 1)[2 - i]);
1228 renderGlyph<false, true, false>(info, charMaskWhite, charMaskWhite, charMaskWhite, glyphHeight, _texBuffer, _texWidth, _texHeight, texX, texY, glyphBuffer);
1229 delete[] glyphBuffer;
1233 MYGUI_LOG(Warning,
"ResourceTrueTypeFont: Cannot render glyph for character " << info.codePoint <<
" in font '" <<
getResourceName() <<
"'.");
1259 mResolution = _value;
1264 if (_value ==
"use_native")
1265 mHinting = HintingUseNative;
1266 else if (_value ==
"force_auto")
1267 mHinting = HintingForceAuto;
1268 else if (_value ==
"disable_auto")
1269 mHinting = HintingDisableAuto;
1270 else if (_value ==
"disable_all")
1271 mHinting = HintingDisableAll;
1273 mHinting = HintingUseNative;
1278 mAntialias = _value;
1288 mOffsetHeight = _value;
1293 mSubstituteCodePoint = _value;
1298 mGlyphSpacing = _value;
1303#ifndef MYGUI_MSDF_FONTS
1305 MYGUI_LOG(Error,
"MsdfMode flag ignored Define MYGUI_MSDF_FONTS if you need msdf fonts, msdf mode ignored.");
1313 mMsdfRange = _value;
#define MYGUI_EXCEPT(dest)
#define MYGUI_LOG(level, text)
static Type firstPO2From(Type _value)
virtual void freeData(IDataStream *_data)=0
virtual IDataStream * getData(const std::string &_name) const =0
static DataManager & getInstance()
const std::string & getResourceName() const
void deserialization(xml::ElementPtr _node, Version _version) override
virtual void createManual(int _width, int _height, TextureUsage _usage, PixelFormat _format)=0
virtual ITexture * createTexture(const std::string &_name)=0
virtual void destroyTexture(ITexture *_texture)=0
static RenderManager & getInstance()
virtual bool isFormatSupported(PixelFormat _format, TextureUsage _usage)
void setAntialias(bool _value)
void setMsdfMode(bool _value)
void setMsdfRange(int _value)
void setResolution(unsigned int _value)
void textureInvalidate(ITexture *_texture) override
void setOffsetHeight(int _value)
void setSource(const std::string &_value)
void setShader(const std::string &_value)
const GlyphInfo * getGlyphInfo(Char _id) const override
void removeCodePointRange(Char _first, Char _second)
void setHinting(const std::string &_value)
void setSubstituteCode(int _value)
void addCodePointRange(Char _first, Char _second)
~ResourceTrueTypeFont() override
ITexture * getTextureFont() const override
std::vector< std::pair< Char, Char > > getCodePointRanges() const
void deserialization(xml::ElementPtr _node, Version _version) override
void setSize(float _value)
int getDefaultHeight() const override
Char getSubstituteCodePoint() const
void setDistance(int _value)
void setTabWidth(float _value)
std::vector< std::string > split(const std::string &_source, const std::string &_delims="\t\n ")
int parseInt(const std::string &_value)
bool parseBool(const std::string &_value)
unsigned int parseUInt(const std::string &_value)
std::string toString(T p)
float parseFloat(const std::string &_value)