MyGUI 3.4.4
MyGUI_ResourceTrueTypeFont.cpp
Go to the documentation of this file.
1/*
2 * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3 * Distributed under the MIT License
4 * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5 */
6
7#include "MyGUI_Precompiled.h"
9#include "MyGUI_DataManager.h"
11#include "MyGUI_RenderManager.h"
12#include "MyGUI_Bitwise.h"
13
14#ifdef MYGUI_USE_FREETYPE
15
16 #include FT_GLYPH_H
17 #include FT_TRUETYPE_TABLES_H
18 #include FT_BITMAP_H
19 #include FT_WINFONTS_H
20
21 #ifdef MYGUI_MSDF_FONTS
22 #include "msdfgen/msdfgen.h"
23 #include "msdfgen/msdfgen-ext.h"
24 #endif
25
26#endif // MYGUI_USE_FREETYPE
27
28namespace MyGUI
29{
30
31#ifndef MYGUI_USE_FREETYPE
33
35 {
36 Base::deserialization(_node, _version);
38 Error,
39 "ResourceTrueTypeFont: TrueType font '"
40 << getResourceName() << "' disabled. Define MYGUI_USE_FREETYE if you need TrueType fonts.");
41 }
42
44 {
45 return nullptr;
46 }
47
49 {
50 return nullptr;
51 }
52
54 {
55 return 0;
56 }
57
61
62 std::vector<std::pair<Char, Char>> ResourceTrueTypeFont::getCodePointRanges() const
63 {
64 return std::vector<std::pair<Char, Char>>();
65 }
66
71
75
76 void ResourceTrueTypeFont::setSource(std::string_view _value)
77 {
78 }
79
80 void ResourceTrueTypeFont::setShader(std::string_view _value)
81 {
82 }
83
85 {
86 }
87
88 void ResourceTrueTypeFont::setResolution(unsigned int _value)
89 {
90 }
91
92 void ResourceTrueTypeFont::setHinting(std::string_view _value)
93 {
94 }
95
97 {
98 }
99
101 {
102 }
103
105 {
106 }
107
109 {
110 }
111
113 {
114 }
115
117 {
118 }
119
121 {
122 }
123
125 {
126 }
127
129 {
130 }
131
132#else // MYGUI_USE_FREETYPE
133 namespace
134 {
135
136 template<typename T>
137 void setMax(T& _var, const T& _newValue)
138 {
139 if (_var < _newValue)
140 _var = _newValue;
141 }
142
143 const std::map<const Char, const uint8> charMask{
146 {FontCodeType::Cursor, 0xFF},
147 {FontCodeType::Tab, 0x00}};
148 const uint8 charMaskBlack = 0x00;
149 const uint8 charMaskWhite = 0xFF;
150
151 template<bool LAMode>
152 struct PixelBase
153 {
154 static PixelFormat::Enum getFormat()
155 {
156 if constexpr (LAMode)
157 return PixelFormat::L8A8;
158 else
159 return PixelFormat::R8G8B8A8;
160 }
161
162 static size_t getNumBytes()
163 {
164 if constexpr (LAMode)
165 return 2;
166 else
167 return 4;
168 }
169
170 protected:
171 // Sets a pixel in _dest as 4 or 2 bytes: L8L8L8A8 if LAMode is false, or L8A8 if LAMode is true.
172 // Automatically advances _dest just past the pixel written.
173 static void set(uint8*& _dest, uint8 _luminance, uint8 _alpha)
174 {
175 if constexpr (LAMode)
176 {
177 *_dest++ = _luminance;
178 *_dest++ = _alpha;
179 }
180 else
181 {
182 *_dest++ = _luminance;
183 *_dest++ = _luminance;
184 *_dest++ = _luminance;
185 *_dest++ = _alpha;
186 }
187 }
188 };
189
190 template<bool LAMode, bool FromSource = false, bool Antialias = false>
191 struct Pixel : PixelBase<LAMode>
192 {
193 // Sets a pixel in _dest as 4 or 2 bytes: L8L8L8A8 if LAMode is false, or L8A8 if LAMode is true.
194 // Sets luminance from _source if both FromSource and Antialias are true; otherwise, uses the specified value.
195 // Sets alpha from _source if FromSource is true; otherwise, uses the specified value.
196 // Automatically advances _source just past the pixel read if FromSource is true.
197 // Automatically advances _dest just past the pixel written.
198 static void set(uint8*& _dest, uint8 _luminance, uint8 _alpha, uint8*& _source)
199 {
200 if constexpr (FromSource)
201 {
202 (void)_alpha;
203 if constexpr (Antialias)
204 {
205 (void)_luminance;
206 // Sets the destination pixel using both the luminance and alpha from the specified source.
207 PixelBase<LAMode>::set(_dest, *_source, *_source);
208 }
209 else
210 {
211 // Sets the destination pixel using the specified _luminance and alpha from the specified source.
212 PixelBase<LAMode>::set(_dest, _luminance, *_source);
213 }
214 ++_source;
215 }
216 else
217 {
218 (void)_source;
219 // Sets the destination pixel using the specified luminance and alpha. Source is ignored.
220 PixelBase<LAMode>::set(_dest, _luminance, _alpha);
221 }
222 }
223 };
224 }
225
226 const int ResourceTrueTypeFont::mDefaultGlyphSpacing = 1;
227 const float ResourceTrueTypeFont::mDefaultTabWidth = 8.0f;
228 const float ResourceTrueTypeFont::mSelectedWidth = 1.0f;
229 const float ResourceTrueTypeFont::mCursorWidth = 2.0f;
230
232 {
233 if (mTexture != nullptr)
234 {
236 mTexture = nullptr;
237 }
238 }
239
241 {
242 Base::deserialization(_node, _version);
243
244 xml::ElementEnumerator node = _node->getElementEnumerator();
245 while (node.next())
246 {
247 if (node->getName() == "Property")
248 {
249 std::string_view key = node->findAttribute("key");
250 std::string_view value = node->findAttribute("value");
251 if (key == "Source")
252 setSource(value);
253 else if (key == "Shader")
254 setShader(value);
255 else if (key == "Size")
257 else if (key == "Resolution")
259 else if (key == "Antialias")
261 else if (key == "TabWidth")
263 else if (key == "OffsetHeight")
265 else if (key == "SubstituteCode")
267 else if (key == "Distance")
269 else if (key == "Hinting")
270 setHinting(value);
271 else if (key == "SpaceWidth")
272 {
273 mSpaceWidth = utility::parseFloat(value);
274 MYGUI_LOG(
275 Warning,
276 _node->findAttribute("type")
277 << ": Property '" << key << "' in font '" << _node->findAttribute("name")
278 << "' is deprecated; remove it to use automatic calculation.");
279 }
280 else if (key == "CursorWidth")
281 {
282 MYGUI_LOG(
283 Warning,
284 _node->findAttribute("type")
285 << ": Property '" << key << "' in font '" << _node->findAttribute("name")
286 << "' is deprecated; value ignored.");
287 }
288 else if (key == "MsdfMode")
289 {
291 }
292 else if (key == "MsdfRange")
293 {
295 }
296 }
297 else if (node->getName() == "Codes")
298 {
299 // Range of inclusions.
300 xml::ElementEnumerator range = node->getElementEnumerator();
301 while (range.next("Code"))
302 {
303 std::string range_value;
304 if (range->findAttribute("range", range_value))
305 {
306 std::vector<std::string> parse_range = utility::split(range_value);
307 if (!parse_range.empty())
308 {
309 Char first = utility::parseUInt(parse_range[0]);
310 Char last = parse_range.size() > 1 ? utility::parseUInt(parse_range[1]) : first;
311 addCodePointRange(first, last);
312 }
313 }
314 }
315
316 // If no code points have been included, include the Unicode Basic Multilingual Plane by default before processing
317 // any exclusions.
318 if (mCharMap.empty())
319 addCodePointRange(0, 0xFFFF);
320
321 // Range of exclusions.
322 range = node->getElementEnumerator();
323 while (range.next("Code"))
324 {
325 std::string range_value;
326 if (range->findAttribute("hide", range_value))
327 {
328 std::vector<std::string> parse_range = utility::split(range_value);
329 if (!parse_range.empty())
330 {
331 Char first = utility::parseUInt(parse_range[0]);
332 Char last = parse_range.size() > 1 ? utility::parseUInt(parse_range[1]) : first;
333 removeCodePointRange(first, last);
334 }
335 }
336 }
337 }
338 }
339
340 initialise();
341 }
342
344 {
345 GlyphMap::const_iterator glyphIter = mGlyphMap.find(_id);
346
347 if (glyphIter != mGlyphMap.end())
348 {
349 return &glyphIter->second;
350 }
351
352 return mSubstituteGlyphInfo;
353 }
354
356 {
357 return mTexture;
358 }
359
361 {
362 return mDefaultHeight;
363 }
364
366 {
367 mGlyphMap.clear();
368 initialise();
369 }
370
371 std::vector<std::pair<Char, Char>> ResourceTrueTypeFont::getCodePointRanges() const
372 {
373 std::vector<std::pair<Char, Char>> result;
374
375 if (!mCharMap.empty())
376 {
377 CharMap::const_iterator iter = mCharMap.begin();
378 CharMap::const_iterator endIter = mCharMap.end();
379
380 // Start the first range with the first code point in the map.
381 Char rangeBegin = iter->first;
382 Char rangeEnd = rangeBegin;
383
384 // Loop over the rest of the map and find the contiguous ranges.
385 for (++iter; iter != endIter; ++iter)
386 {
387 if (iter->first == rangeEnd + 1)
388 {
389 // Extend the current range.
390 ++rangeEnd;
391 }
392 else
393 {
394 // Found the start of a new range. First, save the current range.
395 result.emplace_back(rangeBegin, rangeEnd);
396
397 // Then start the new range.
398 rangeBegin = rangeEnd = iter->first;
399 }
400 }
401
402 // Save the final range.
403 result.emplace_back(rangeBegin, rangeEnd);
404 }
405
406 return result;
407 }
408
410 {
411 return mSubstituteCodePoint;
412 }
413
414 void ResourceTrueTypeFont::addCodePoint(Char _codePoint)
415 {
416 mCharMap.insert(CharMap::value_type(_codePoint, 0));
417 }
418
420 {
421 CharMap::iterator positionHint = mCharMap.lower_bound(_first);
422
423 if (positionHint != mCharMap.begin())
424 --positionHint;
425
426 for (Char i = _first; i <= _second; ++i)
427 positionHint = mCharMap.insert(positionHint, CharMap::value_type(i, 0));
428 }
429
431 {
432 mCharMap.erase(mCharMap.lower_bound(_first), mCharMap.upper_bound(_second));
433 }
434
436 {
437 if (mGlyphSpacing == -1)
438 mGlyphSpacing = mDefaultGlyphSpacing;
439
440 // If L8A8 (2 bytes per pixel) is supported, use it; otherwise, use R8G8B8A8 (4 bytes per pixel) as L8L8L8A8.
442 Pixel<true>::getFormat(),
444 if (mMsdfMode)
445 laMode = false;
446
447 // Select and call an appropriate initialisation method. By making this decision up front, we avoid having to branch on
448 // these variables many thousands of times inside tight nested loops later. From this point on, the various function
449 // templates ensure that all the necessary branching is done purely at compile time for all combinations.
450 if (laMode)
451 {
452 if (mAntialias)
453 ResourceTrueTypeFont::initialiseFreeType<true, true>();
454 else
455 ResourceTrueTypeFont::initialiseFreeType<true, false>();
456 }
457 else
458 {
459 if (mAntialias)
460 ResourceTrueTypeFont::initialiseFreeType<false, true>();
461 else
462 ResourceTrueTypeFont::initialiseFreeType<false, false>();
463 }
464 }
465
466 template<bool LAMode, bool Antialias>
467 void ResourceTrueTypeFont::initialiseFreeType()
468 {
469 //-------------------------------------------------------------------//
470 // Initialise FreeType and load the font.
471 //-------------------------------------------------------------------//
472
473 FT_Library ftLibrary;
474
475 if (FT_Init_FreeType(&ftLibrary) != 0)
476 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not init the FreeType library!");
477
478 uint8* fontBuffer = nullptr;
479
480 FT_Face ftFace = loadFace(ftLibrary, fontBuffer);
481
482 if (ftFace == nullptr)
483 {
484 MYGUI_LOG(Error, "ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
485 FT_Done_FreeType(ftLibrary);
486 return;
487 }
488
489 #ifdef MYGUI_MSDF_FONTS
490 msdfgen::FontHandle* msdfFont = nullptr;
491
492 if (mMsdfMode)
493 {
494 msdfFont = msdfgen::adoptFreetypeFont(ftFace);
495 }
496 #endif
497
498 //-------------------------------------------------------------------//
499 // Calculate the font metrics.
500 //-------------------------------------------------------------------//
501
502 // The font's overall ascent and descent are defined in three different places in a TrueType font, and with different
503 // values in each place. The most reliable source for these metrics is usually the "usWinAscent" and "usWinDescent" pair of
504 // values in the OS/2 header; however, some fonts contain inaccurate data there. To be safe, we use the highest of the set
505 // of values contained in the face metrics and the two sets of values contained in the OS/2 header.
506 int fontAscent = ftFace->size->metrics.ascender >> 6;
507 int fontDescent = -ftFace->size->metrics.descender >> 6;
508
509 TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(ftFace, ft_sfnt_os2);
510
511 if (os2 != nullptr)
512 {
513 setMax(fontAscent, os2->usWinAscent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
514 setMax(fontDescent, os2->usWinDescent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
515
516 setMax(fontAscent, os2->sTypoAscender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
517 setMax(fontDescent, -os2->sTypoDescender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM);
518 }
519
520 // The nominal font height is calculated as the sum of its ascent and descent as specified by the font designer. Previously
521 // it was defined by MyGUI in terms of the maximum ascent and descent of the glyphs currently in use, but this caused the
522 // font's line spacing to change whenever glyphs were added to or removed from the font definition. Doing it this way
523 // instead prevents a lot of layout problems, and it is also more typographically correct and more aesthetically pleasing.
524 mDefaultHeight = fontAscent + fontDescent;
525
526 // Set the load flags based on the specified type of hinting.
527 FT_Int32 ftLoadFlags = FT_LOAD_DEFAULT;
528
529 switch (mHinting)
530 {
531 case HintingForceAuto: ftLoadFlags = FT_LOAD_FORCE_AUTOHINT; break;
532 case HintingDisableAuto: ftLoadFlags = FT_LOAD_NO_AUTOHINT; break;
533 case HintingDisableAll:
534 // When hinting is completely disabled, glyphs must always be rendered -- even during layout calculations -- due to
535 // discrepancies between the glyph metrics and the actual rendered bitmap metrics.
536 ftLoadFlags = FT_LOAD_NO_HINTING | FT_LOAD_RENDER;
537 break;
538 case HintingUseNative: ftLoadFlags = FT_LOAD_DEFAULT; break;
539 }
540
541 //-------------------------------------------------------------------//
542 // Create the glyphs and calculate their metrics.
543 //-------------------------------------------------------------------//
544
545 GlyphHeightMap glyphHeightMap;
546 int texWidth = 0;
547
548 // Before creating the glyphs, add the "Space" code point to force that glyph to be created. For historical reasons, MyGUI
549 // users are accustomed to omitting this code point in their font definitions.
550 addCodePoint(FontCodeType::Space);
551
552 // Create the standard glyphs.
553 for (CharMap::iterator iter = mCharMap.begin(); iter != mCharMap.end();)
554 {
555 const Char& codePoint = iter->first;
556 FT_UInt glyphIndex = FT_Get_Char_Index(ftFace, codePoint);
557
558 if (!mMsdfMode)
559 texWidth += createFaceGlyph(glyphIndex, codePoint, fontAscent, ftFace, ftLoadFlags, glyphHeightMap);
560 #ifdef MYGUI_MSDF_FONTS
561 else
562 texWidth += createMsdfFaceGlyph(codePoint, fontAscent, msdfFont, glyphHeightMap);
563 #endif
564
565 // If the newly created glyph is the "Not Defined" glyph, it means that the code point is not supported by the font.
566 // Remove it from the character map so that we can provide our own substitute instead of letting FreeType do it.
567 if (iter->second != 0)
568 ++iter;
569 else
570 mCharMap.erase(iter++);
571 }
572
573 // Do some special handling for the "Space" and "Tab" glyphs.
574 GlyphMap::iterator spaceGlyphIter = mGlyphMap.find(FontCodeType::Space);
575
576 if (spaceGlyphIter != mGlyphMap.end())
577 {
578 // Adjust the width of the "Space" glyph if it has been customized.
579 if (mSpaceWidth != 0.0f)
580 {
581 texWidth += (int)std::ceil(mSpaceWidth) - (int)std::ceil(spaceGlyphIter->second.width);
582 spaceGlyphIter->second.width = mSpaceWidth;
583 spaceGlyphIter->second.advance = mSpaceWidth;
584 }
585
586 // If the width of the "Tab" glyph hasn't been customized, make it eight spaces wide.
587 if (mTabWidth == 0.0f)
588 mTabWidth = mDefaultTabWidth * spaceGlyphIter->second.advance;
589 }
590
591 // Create the special glyphs. They must be created after the standard glyphs so that they take precedence in case of a
592 // collision. To make sure that the indices of the special glyphs don't collide with any glyph indices in the font, we must
593 // use glyph indices higher than the highest glyph index in the font.
594 FT_UInt nextGlyphIndex = (FT_UInt)ftFace->num_glyphs;
595
596 float height = (float)mDefaultHeight;
597
598 texWidth += createGlyph(
599 nextGlyphIndex++,
600 GlyphInfo(static_cast<Char>(FontCodeType::Tab), 0.0f, 0.0f, mTabWidth, 0.0f, 0.0f),
601 glyphHeightMap);
602 texWidth += createGlyph(
603 nextGlyphIndex++,
604 GlyphInfo(static_cast<Char>(FontCodeType::Selected), mSelectedWidth, height, 0.0f, 0.0f, 0.0f),
605 glyphHeightMap);
606 texWidth += createGlyph(
607 nextGlyphIndex++,
608 GlyphInfo(static_cast<Char>(FontCodeType::SelectedBack), mSelectedWidth, height, 0.0f, 0.0f, 0.0f),
609 glyphHeightMap);
610 texWidth += createGlyph(
611 nextGlyphIndex++,
612 GlyphInfo(static_cast<Char>(FontCodeType::Cursor), mCursorWidth, height, 0.0f, 0.0f, 0.0f),
613 glyphHeightMap);
614
615 // If a substitute code point has been specified, check to make sure that it exists in the character map. If it doesn't,
616 // revert to the default "Not Defined" code point. This is not a real code point but rather an invalid Unicode value that
617 // is guaranteed to cause the "Not Defined" special glyph to be created.
618 if (mSubstituteCodePoint != FontCodeType::NotDefined && mCharMap.find(mSubstituteCodePoint) == mCharMap.end())
619 mSubstituteCodePoint = static_cast<Char>(FontCodeType::NotDefined);
620
621 // Create the "Not Defined" code point (and its corresponding glyph) if it's in use as the substitute code point.
622 if (mSubstituteCodePoint == FontCodeType::NotDefined)
623 {
624 if (!mMsdfMode)
625 texWidth += createFaceGlyph(
626 0,
627 static_cast<Char>(FontCodeType::NotDefined),
628 fontAscent,
629 ftFace,
630 ftLoadFlags,
631 glyphHeightMap);
632 #ifdef MYGUI_MSDF_FONTS
633 else
634 texWidth += createMsdfFaceGlyph(
635 static_cast<Char>(FontCodeType::NotDefined),
636 fontAscent,
637 msdfFont,
638 glyphHeightMap);
639 #endif
640 }
641
642 // Cache a pointer to the substitute glyph info for fast lookup.
643 mSubstituteGlyphInfo = &mGlyphMap.find(mSubstituteCodePoint)->second;
644
645 // Calculate the average height of all of the glyphs that are in use. This value will be used for estimating how large the
646 // texture needs to be.
647 double averageGlyphHeight = 0.0;
648
649 for (const auto& heightItem : glyphHeightMap)
650 averageGlyphHeight += heightItem.first * heightItem.second.size();
651
652 averageGlyphHeight /= mGlyphMap.size();
653
654 //-------------------------------------------------------------------//
655 // Calculate the final texture size.
656 //-------------------------------------------------------------------//
657
658 // Round the current texture width and height up to the nearest powers of two.
659 texWidth = Bitwise::firstPO2From(texWidth);
660 int texHeight = Bitwise::firstPO2From((int)ceil(averageGlyphHeight) + mGlyphSpacing);
661
662 // At this point, the texture is only one glyph high and is probably very wide. For efficiency reasons, we need to make the
663 // texture as square as possible. If the texture cannot be made perfectly square, make it taller than it is wide, because
664 // the height may decrease in the final layout due to height packing.
665 while (texWidth > texHeight)
666 {
667 texWidth /= 2;
668 texHeight *= 2;
669 }
670
671 // Calculate the final layout of all of the glyphs in the texture, packing them tightly by first arranging them by height.
672 // We assume that the texture width is fixed but that the texture height can be adjusted up or down depending on how much
673 // space is actually needed.
674 // In most cases, the final texture will end up square or almost square. In some rare cases, however, we can end up with a
675 // texture that's more than twice as high as it is wide; when this happens, we double the width and try again.
676 do
677 {
678 if (texHeight > texWidth * 2)
679 texWidth *= 2;
680
681 int texX = mGlyphSpacing;
682 int texY = mGlyphSpacing;
683
684 for (const auto& heightItem : glyphHeightMap)
685 {
686 for (const auto& [key, info] : heightItem.second)
687 {
688 int glyphWidth = (int)std::ceil(info->width);
689 int glyphHeight = (int)std::ceil(info->height);
690
691 autoWrapGlyphPos(glyphWidth, texWidth, glyphHeight, texX, texY);
692
693 if (glyphWidth > 0)
694 texX += mGlyphSpacing + glyphWidth;
695 }
696 }
697
698 texHeight = Bitwise::firstPO2From(texY + glyphHeightMap.rbegin()->first);
699 } while (texHeight > texWidth * 2);
700
701 //-------------------------------------------------------------------//
702 // Create the texture and render the glyphs onto it.
703 //-------------------------------------------------------------------//
704
705 if (mTexture)
706 {
708 mTexture = nullptr;
709 }
710
711 mTexture = RenderManager::getInstance().createTexture(MyGUI::utility::toString((size_t)this, "_TrueTypeFont"));
712
713 mTexture
714 ->createManual(texWidth, texHeight, TextureUsage::Static | TextureUsage::Write, Pixel<LAMode>::getFormat());
715 mTexture->setInvalidateListener(this);
716
717 if (!mShader.empty())
718 mTexture->setShader(mShader);
719
720 uint8* texBuffer = static_cast<uint8*>(mTexture->lock(TextureUsage::Write));
721
722 if (texBuffer != nullptr)
723 {
724 // Make the texture background transparent white (or black for msdf mode).
725 for (uint8 *dest = texBuffer, *endDest = dest + texWidth * texHeight * Pixel<LAMode>::getNumBytes();
726 dest != endDest;)
727 Pixel<LAMode, false, false>::set(dest, mMsdfMode ? charMaskBlack : charMaskWhite, charMaskBlack, dest);
728
729 if (!mMsdfMode)
730 renderGlyphs<LAMode, Antialias>(
731 glyphHeightMap,
732 ftLibrary,
733 ftFace,
734 ftLoadFlags,
735 texBuffer,
736 texWidth,
737 texHeight);
738 #ifdef MYGUI_MSDF_FONTS
739 else
740 renderMsdfGlyphs(glyphHeightMap, msdfFont, texBuffer, texWidth, texHeight);
741 #endif
742
743 mTexture->unlock();
744
745 MYGUI_LOG(
746 Info,
747 "ResourceTrueTypeFont: Font '"
748 << getResourceName() << "' using texture size " << texWidth << " x " << texHeight << ".");
749 MYGUI_LOG(
750 Info,
751 "ResourceTrueTypeFont: Font '"
752 << getResourceName() << "' using real height " << mDefaultHeight << " pixels.");
753 }
754 else
755 {
756 MYGUI_LOG(Error, "ResourceTrueTypeFont: Error locking texture; pointer is nullptr.");
757 }
758
759 #ifdef MYGUI_MSDF_FONTS
760 if (mMsdfMode)
761 {
762 msdfgen::destroyFont(msdfFont);
763 }
764 #endif
765
766 FT_Done_Face(ftFace);
767 FT_Done_FreeType(ftLibrary);
768
769 delete[] fontBuffer;
770 }
771
772 FT_Face ResourceTrueTypeFont::loadFace(const FT_Library& _ftLibrary, uint8*& _fontBuffer)
773 {
774 FT_Face result = nullptr;
775
776 // Load the font file.
777 IDataStream* datastream = DataManager::getInstance().getData(mSource);
778
779 if (datastream == nullptr)
780 return result;
781
782 size_t fontBufferSize = datastream->size();
783 _fontBuffer = new uint8[fontBufferSize];
784 datastream->read(_fontBuffer, fontBufferSize);
785
787 datastream = nullptr;
788
789 // Determine how many faces the font contains.
790 if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, -1, &result) != 0)
791 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
792
793 FT_Long numFaces = result->num_faces;
794 FT_Long faceIndex = 0;
795
796 // Load the first face.
797 if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
798 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
799
800 if (result->face_flags & FT_FACE_FLAG_SCALABLE)
801 {
802 // The font is scalable, so set the font size by first converting the requested size to FreeType's 26.6 fixed-point
803 // format.
804 FT_F26Dot6 ftSize = (FT_F26Dot6)(mSize * (1 << 6));
805
806 if (FT_Set_Char_Size(result, ftSize, 0, mResolution, mResolution) != 0)
807 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not set the font size for '" << getResourceName() << "'!");
808
809 // If no code points have been specified, use the Unicode Basic Multilingual Plane by default.
810 if (mCharMap.empty())
811 addCodePointRange(0, 0xFFFF);
812 }
813 else
814 {
815 // The font isn't scalable, so try to load it as a Windows FNT/FON file.
816 FT_WinFNT_HeaderRec fnt;
817
818 // Enumerate all of the faces in the font and select the smallest one that's at least as large as the requested size
819 // (after adjusting for resolution). If none of the faces are large enough, use the largest one.
820 std::map<float, FT_Long> faceSizes;
821
822 do
823 {
824 if (FT_Get_WinFNT_Header(result, &fnt) != 0)
825 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
826
827 faceSizes.insert(
828 std::make_pair((float)fnt.nominal_point_size * fnt.vertical_resolution / mResolution, faceIndex));
829
830 FT_Done_Face(result);
831
832 if (++faceIndex < numFaces)
833 if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
834 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
835 } while (faceIndex < numFaces);
836
837 std::map<float, FT_Long>::const_iterator iter = faceSizes.lower_bound(mSize);
838
839 faceIndex = (iter != faceSizes.end()) ? iter->second : faceSizes.rbegin()->second;
840
841 if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0)
842 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!");
843
844 // Select the first bitmap strike available in the selected face. This needs to be done explicitly even though Windows
845 // FNT/FON files contain only one bitmap strike per face.
846 if (FT_Select_Size(result, 0) != 0)
847 MYGUI_EXCEPT("ResourceTrueTypeFont: Could not set the font size for '" << getResourceName() << "'!");
848
849 // Windows FNT/FON files do not support Unicode, so restrict the code-point range to either ISO-8859-1 or ASCII,
850 // depending on the font's encoding.
851 if (mCharMap.empty())
852 {
853 // No code points have been specified, so add the printable ASCII range by default.
854 addCodePointRange(0x20, 0x7E);
855
856 // Additionally, if the font's character set is CP-1252, add the range of non-ASCII 8-bit code points that are
857 // common between CP-1252 and ISO-8859-1; i.e., everything but 0x80 through 0x9F.
858 if (fnt.charset == FT_WinFNT_ID_CP1252)
859 addCodePointRange(0xA0, 0xFF);
860 }
861 else
862 {
863 // Some code points have been specified, so remove anything in the non-printable ASCII range as well as anything
864 // over 8 bits.
865 removeCodePointRange(0, 0x1F);
866 removeCodePointRange(0x100, std::numeric_limits<Char>::max());
867
868 // Additionally, remove non-ASCII 8-bit code points (plus ASCII DEL, 0x7F). If the font's character set is CP-1252,
869 // remove only the code points that differ between CP-1252 and ISO-8859-1; otherwise, remove all of them.
870 if (fnt.charset == FT_WinFNT_ID_CP1252)
871 removeCodePointRange(0x7F, 0x9F);
872 else
873 removeCodePointRange(0x7F, 0xFF);
874 }
875 }
876
877 return result;
878 }
879
880 void ResourceTrueTypeFont::autoWrapGlyphPos(int _glyphWidth, int _texWidth, int _lineHeight, int& _texX, int& _texY)
881 const
882 {
883 if (_glyphWidth > 0 && _texX + mGlyphSpacing + _glyphWidth > _texWidth)
884 {
885 _texX = mGlyphSpacing;
886 _texY += mGlyphSpacing + _lineHeight;
887 }
888 }
889
890 GlyphInfo ResourceTrueTypeFont::createFaceGlyphInfo(Char _codePoint, int _fontAscent, FT_GlyphSlot _glyph) const
891 {
892 float bearingX = _glyph->metrics.horiBearingX / 64.0f;
893
894 // The following calculations aren't currently needed but are kept here for future use.
895 // float ascent = _glyph->metrics.horiBearingY / 64.0f;
896 // float descent = (_glyph->metrics.height / 64.0f) - ascent;
897
898 return {
899 _codePoint,
900 std::max((float)_glyph->bitmap.width, _glyph->metrics.width / 64.0f),
901 std::max((float)_glyph->bitmap.rows, _glyph->metrics.height / 64.0f),
902 (_glyph->advance.x / 64.0f) - bearingX,
903 bearingX,
904 std::floor(_fontAscent - (_glyph->metrics.horiBearingY / 64.0f) - mOffsetHeight)};
905 }
906
907 int ResourceTrueTypeFont::createGlyph(
908 FT_UInt _glyphIndex,
909 const GlyphInfo& _glyphInfo,
910 GlyphHeightMap& _glyphHeightMap)
911 {
912 int width = (int)std::ceil(_glyphInfo.width);
913 int height = (int)std::ceil(_glyphInfo.height);
914
915 mCharMap[_glyphInfo.codePoint] = _glyphIndex;
916 GlyphInfo& info = mGlyphMap.insert(GlyphMap::value_type(_glyphInfo.codePoint, _glyphInfo)).first->second;
917 _glyphHeightMap[height].insert(std::make_pair(_glyphIndex, &info));
918
919 return (width > 0) ? mGlyphSpacing + width : 0;
920 }
921
922 int ResourceTrueTypeFont::createFaceGlyph(
923 FT_UInt _glyphIndex,
924 Char _codePoint,
925 int _fontAscent,
926 const FT_Face& _ftFace,
927 FT_Int32 _ftLoadFlags,
928 GlyphHeightMap& _glyphHeightMap)
929 {
930 if (mGlyphMap.find(_codePoint) == mGlyphMap.end())
931 {
932 if (FT_Load_Glyph(_ftFace, _glyphIndex, _ftLoadFlags) == 0)
933 return createGlyph(
934 _glyphIndex,
935 createFaceGlyphInfo(_codePoint, _fontAscent, _ftFace->glyph),
936 _glyphHeightMap);
937 MYGUI_LOG(
938 Warning,
939 "ResourceTrueTypeFont: Cannot load glyph "
940 << _glyphIndex << " for character " << _codePoint << " in font '" << getResourceName() << "'.");
941 }
942 else
943 {
944 mCharMap[_codePoint] = _glyphIndex;
945 }
946
947 return 0;
948 }
949
950 template<bool LAMode, bool Antialias>
951 void ResourceTrueTypeFont::renderGlyphs(
952 const GlyphHeightMap& _glyphHeightMap,
953 const FT_Library& _ftLibrary,
954 const FT_Face& _ftFace,
955 FT_Int32 _ftLoadFlags,
956 uint8* _texBuffer,
957 int _texWidth,
958 int _texHeight)
959 {
960 FT_Bitmap ftBitmap;
961 FT_Bitmap_New(&ftBitmap);
962
963 int texX = mGlyphSpacing;
964 int texY = mGlyphSpacing;
965
966 for (const auto& sameHeightGlyphs : _glyphHeightMap)
967 {
968 int glyphHeight = sameHeightGlyphs.first;
969 for (const auto& glyph : sameHeightGlyphs.second)
970 {
971 GlyphInfo& info = *glyph.second;
972
973 switch (info.codePoint)
974 {
977 {
978 renderGlyph<LAMode, false, false>(
979 info,
980 charMaskWhite,
981 charMaskBlack,
982 charMask.find(info.codePoint)->second,
983 glyphHeight,
984 _texBuffer,
985 _texWidth,
986 _texHeight,
987 texX,
988 texY);
989
990 // Manually adjust the glyph's width to zero. This prevents artifacts from appearing at the seams when
991 // rendering multi-character selections.
992 GlyphMap::iterator glyphIter = mGlyphMap.find(info.codePoint);
993 if (glyphIter != mGlyphMap.end())
994 {
995 glyphIter->second.width = 0.0f;
996 glyphIter->second.uvRect.right = glyphIter->second.uvRect.left;
997 }
998 }
999 break;
1000
1002 case FontCodeType::Tab:
1003 renderGlyph<LAMode, false, false>(
1004 info,
1005 charMaskWhite,
1006 charMaskBlack,
1007 charMask.find(info.codePoint)->second,
1008 glyphHeight,
1009 _texBuffer,
1010 _texWidth,
1011 _texHeight,
1012 texX,
1013 texY);
1014 break;
1015
1016 default:
1017 if (FT_Load_Glyph(_ftFace, glyph.first, _ftLoadFlags | FT_LOAD_RENDER) == 0)
1018 {
1019 if (_ftFace->glyph->bitmap.buffer != nullptr)
1020 {
1021 uint8* glyphBuffer = nullptr;
1022
1023 switch (_ftFace->glyph->bitmap.pixel_mode)
1024 {
1025 case FT_PIXEL_MODE_GRAY: glyphBuffer = _ftFace->glyph->bitmap.buffer; break;
1026
1027 case FT_PIXEL_MODE_MONO:
1028 // Convert the monochrome bitmap to 8-bit before rendering it.
1029 if (FT_Bitmap_Convert(_ftLibrary, &_ftFace->glyph->bitmap, &ftBitmap, 1) == 0)
1030 {
1031 // Go through the bitmap and convert all of the nonzero values to 0xFF (white).
1032 for (uint8 *p = ftBitmap.buffer, *endP = p + ftBitmap.width * ftBitmap.rows;
1033 p != endP;
1034 ++p)
1035 *p = *p ? 0xFF : 0;
1036
1037 glyphBuffer = ftBitmap.buffer;
1038 }
1039 break;
1040 }
1041
1042 if (glyphBuffer != nullptr)
1043 renderGlyph<LAMode, true, Antialias>(
1044 info,
1045 charMaskWhite,
1046 charMaskWhite,
1047 charMaskWhite,
1048 glyphHeight,
1049 _texBuffer,
1050 _texWidth,
1051 _texHeight,
1052 texX,
1053 texY,
1054 glyphBuffer);
1055 }
1056 }
1057 else
1058 {
1059 MYGUI_LOG(
1060 Warning,
1061 "ResourceTrueTypeFont: Cannot render glyph "
1062 << glyph.first << " for character " << info.codePoint << " in font '"
1063 << getResourceName() << "'.");
1064 }
1065 break;
1066 }
1067 }
1068 }
1069
1070 FT_Bitmap_Done(_ftLibrary, &ftBitmap);
1071 }
1072
1073 template<bool LAMode, bool UseBuffer, bool Antialias>
1074 void ResourceTrueTypeFont::renderGlyph(
1075 GlyphInfo& _info,
1076 uint8 _luminance0,
1077 uint8 _luminance1,
1078 uint8 _alpha,
1079 int _lineHeight,
1080 uint8* _texBuffer,
1081 int _texWidth,
1082 int _texHeight,
1083 int& _texX,
1084 int& _texY,
1085 uint8* _glyphBuffer)
1086 {
1087 int width = (int)std::ceil(_info.width);
1088 int height = (int)std::ceil(_info.height);
1089
1090 autoWrapGlyphPos(width, _texWidth, _lineHeight, _texX, _texY);
1091
1092 uint8* dest = _texBuffer + (_texY * _texWidth + _texX) * Pixel<LAMode>::getNumBytes();
1093
1094 // Calculate how much to advance the destination pointer after each row to get to the start of the next row.
1095 ptrdiff_t destNextRow = (_texWidth - width) * Pixel<LAMode>::getNumBytes();
1096
1097 if (!mMsdfMode || !UseBuffer)
1098 {
1099 for (int j = height; j > 0; --j)
1100 {
1101 int i;
1102 for (i = width; i > 1; i -= 2)
1103 {
1104 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance0, _alpha, _glyphBuffer);
1105 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance1, _alpha, _glyphBuffer);
1106 }
1107
1108 if (i > 0)
1109 Pixel<LAMode, UseBuffer, Antialias>::set(dest, _luminance0, _alpha, _glyphBuffer);
1110
1111 dest += destNextRow;
1112 }
1113 }
1114 else
1115 {
1116 for (int y = 0; y < height; ++y)
1117 {
1118 for (int x = 0; x < width; ++x)
1119 {
1120 for (int i = 0; i < 3; ++i)
1121 {
1122 *dest++ = *_glyphBuffer++;
1123 }
1124 *dest++ = 255;
1125 }
1126
1127 dest += destNextRow;
1128 }
1129 }
1130
1131 // Calculate and store the glyph's UV coordinates within the texture.
1132 _info.uvRect.left = (float)_texX / _texWidth; // u1
1133 _info.uvRect.top = (float)_texY / _texHeight; // v1
1134 _info.uvRect.right = (float)(_texX + _info.width) / _texWidth; // u2
1135 _info.uvRect.bottom = (float)(_texY + _info.height) / _texHeight; // v2
1136
1137 if (width > 0)
1138 _texX += mGlyphSpacing + width;
1139 }
1140
1141 #ifdef MYGUI_MSDF_FONTS
1142 GlyphInfo ResourceTrueTypeFont::createMsdfFaceGlyphInfo(
1143 Char _codePoint,
1144 const msdfgen::Shape& _shape,
1145 double _advance,
1146 int _fontAscent)
1147 {
1148 msdfgen::Shape::Bounds bounds = _shape.getBounds();
1149 double range = mMsdfRange / 2.0;
1150 if (_shape.contours.empty())
1151 {
1152 bounds = {0, 0, 0, 0};
1153 range = 0;
1154 }
1155
1156 double bearingX = bounds.l;
1157
1158 return GlyphInfo(
1159 _codePoint,
1160 bounds.r - bounds.l + 2 * range,
1161 bounds.t - bounds.b + 2 * range,
1162 _advance - bearingX + range,
1163 bearingX - range,
1164 std::floor(_fontAscent - bounds.t - mOffsetHeight - range));
1165 }
1166
1167 int ResourceTrueTypeFont::createMsdfGlyph(const GlyphInfo& _glyphInfo, GlyphHeightMap& _glyphHeightMap)
1168 {
1169 int width = (int)std::ceil(_glyphInfo.width);
1170 int height = (int)std::ceil(_glyphInfo.height);
1171
1172 mCharMap[_glyphInfo.codePoint] = _glyphInfo.codePoint;
1173 GlyphInfo& info = mGlyphMap.insert(GlyphMap::value_type(_glyphInfo.codePoint, _glyphInfo)).first->second;
1174 _glyphHeightMap[height].insert(std::make_pair(_glyphInfo.codePoint, &info));
1175
1176 return (width > 0) ? mGlyphSpacing + width : 0;
1177 }
1178
1179 int ResourceTrueTypeFont::createMsdfFaceGlyph(
1180 Char _codePoint,
1181 int _fontAscent,
1182 msdfgen::FontHandle* _fontHandle,
1183 GlyphHeightMap& _glyphHeightMap)
1184 {
1185 if (mGlyphMap.find(_codePoint) == mGlyphMap.end())
1186 {
1187 msdfgen::Shape shape;
1188 double advance;
1189 if (msdfgen::loadGlyph(shape, _fontHandle, _codePoint, &advance))
1190 createMsdfGlyph(createMsdfFaceGlyphInfo(_codePoint, shape, advance, _fontAscent), _glyphHeightMap);
1191 else
1192 MYGUI_LOG(
1193 Warning,
1194 "ResourceTrueTypeFont: Cannot load msdf glyph for character "
1195 << _codePoint << " in font '" << getResourceName() << "'.");
1196 }
1197 else
1198 {
1199 mCharMap[_codePoint] = _codePoint;
1200 }
1201
1202 return 0;
1203 }
1204
1205 void ResourceTrueTypeFont::renderMsdfGlyphs(
1206 const GlyphHeightMap& _glyphHeightMap,
1207 msdfgen::FontHandle* _fontHandle,
1208 uint8* _texBuffer,
1209 int _texWidth,
1210 int _texHeight)
1211 {
1212 int texX = mGlyphSpacing, texY = mGlyphSpacing;
1213
1214 for (const auto& sameHeightGlyphs : _glyphHeightMap)
1215 {
1216 int glyphHeight = sameHeightGlyphs.first;
1217 for (const auto& glyph : sameHeightGlyphs.second)
1218 {
1219 GlyphInfo& info = *glyph.second;
1220
1221 switch (info.codePoint)
1222 {
1225 {
1226 renderGlyph<false, false, false>(
1227 info,
1228 charMaskWhite,
1229 charMaskBlack,
1230 charMask.find(info.codePoint)->second,
1231 glyphHeight,
1232 _texBuffer,
1233 _texWidth,
1234 _texHeight,
1235 texX,
1236 texY);
1237
1238 // Manually adjust the glyph's width to zero. This prevents artifacts from appearing at the seams when
1239 // rendering multi-character selections.
1240 GlyphMap::iterator glyphIter = mGlyphMap.find(info.codePoint);
1241 if (glyphIter != mGlyphMap.end())
1242 {
1243 glyphIter->second.width = 0.0f;
1244 glyphIter->second.uvRect.right = glyphIter->second.uvRect.left;
1245 }
1246 }
1247 break;
1248
1250 case FontCodeType::Tab:
1251 renderGlyph<false, false, false>(
1252 info,
1253 charMaskWhite,
1254 charMaskBlack,
1255 charMask.find(info.codePoint)->second,
1256 glyphHeight,
1257 _texBuffer,
1258 _texWidth,
1259 _texHeight,
1260 texX,
1261 texY);
1262 break;
1263
1264 default:
1265 msdfgen::Shape shape;
1266 if (loadGlyph(shape, _fontHandle, info.codePoint))
1267 {
1268 msdfgen::Shape::Bounds bounds = shape.getBounds();
1269 double range = mMsdfRange / 2.0;
1270 if (shape.contours.empty())
1271 {
1272 bounds = {0, 0, 0, 0};
1273 range = 0;
1274 }
1275
1276 shape.normalize();
1277 edgeColoringSimple(shape, 3.0);
1278
1279 msdfgen::Bitmap<float, 3> msdf(
1280 std::ceil(bounds.r - bounds.l + 2 * range),
1281 std::ceil(bounds.t - bounds.b + 2 * range));
1282 msdfgen::generateMSDF(
1283 msdf,
1284 shape,
1285 mMsdfRange,
1286 1,
1287 msdfgen::Vector2(-bounds.l + range, -bounds.b + range));
1288 // double error = msdfgen::estimateSDFError(
1289 // msdfgen::BitmapConstRef<float, 3>{(float*)msdf, msdf.width(), msdf.height()},
1290 // shape,
1291 // 1,
1292 // msdfgen::Vector2(-bounds.l + range, -bounds.b + range),
1293 // 33);
1294 // if (100000 * error > 1)
1295 // MYGUI_LOG(Warning, "Error for '" << char(info.codePoint) << "' is :" << (int) 100000 * error);
1296
1297 uint8* glyphBuffer = new uint8[msdf.width() * msdf.height() * 3];
1298 uint8* glyphBufferPointer = glyphBuffer;
1299 for (int y = 0; y < msdf.height(); ++y)
1300 {
1301 for (int x = 0; x < msdf.width(); ++x)
1302 {
1303 for (int i = 0; i < 3; ++i)
1304 {
1305 // upside-down and RGB->BGR
1306 *glyphBufferPointer++ =
1307 msdfgen::pixelFloatToByte(msdf(x, msdf.height() - y - 1)[2 - i]);
1308 }
1309 }
1310 }
1311
1312 renderGlyph<false, true, false>(
1313 info,
1314 charMaskWhite,
1315 charMaskWhite,
1316 charMaskWhite,
1317 glyphHeight,
1318 _texBuffer,
1319 _texWidth,
1320 _texHeight,
1321 texX,
1322 texY,
1323 glyphBuffer);
1324 delete[] glyphBuffer;
1325 }
1326 else
1327 {
1328 MYGUI_LOG(
1329 Warning,
1330 "ResourceTrueTypeFont: Cannot render glyph for character "
1331 << info.codePoint << " in font '" << getResourceName() << "'.");
1332 }
1333 break;
1334 }
1335 }
1336 }
1337 }
1338 #endif
1339
1340 void ResourceTrueTypeFont::setSource(std::string_view _value)
1341 {
1342 mSource = _value;
1343 }
1344
1345 void ResourceTrueTypeFont::setShader(std::string_view _value)
1346 {
1347 mShader = _value;
1348 }
1349
1350 void ResourceTrueTypeFont::setSize(float _value)
1351 {
1352 mSize = _value;
1353 }
1354
1355 void ResourceTrueTypeFont::setResolution(unsigned int _value)
1356 {
1357 mResolution = _value;
1358 }
1359
1360 void ResourceTrueTypeFont::setHinting(std::string_view _value)
1361 {
1362 if (_value == "use_native")
1363 mHinting = HintingUseNative;
1364 else if (_value == "force_auto")
1365 mHinting = HintingForceAuto;
1366 else if (_value == "disable_auto")
1367 mHinting = HintingDisableAuto;
1368 else if (_value == "disable_all")
1369 mHinting = HintingDisableAll;
1370 else
1371 mHinting = HintingUseNative;
1372 }
1373
1374 void ResourceTrueTypeFont::setAntialias(bool _value)
1375 {
1376 mAntialias = _value;
1377 }
1378
1379 void ResourceTrueTypeFont::setTabWidth(float _value)
1380 {
1381 mTabWidth = _value;
1382 }
1383
1385 {
1386 mOffsetHeight = _value;
1387 }
1388
1390 {
1391 mSubstituteCodePoint = _value;
1392 }
1393
1394 void ResourceTrueTypeFont::setDistance(int _value)
1395 {
1396 mGlyphSpacing = _value;
1397 }
1398
1399 void ResourceTrueTypeFont::setMsdfMode(bool _value)
1400 {
1401 #ifndef MYGUI_MSDF_FONTS
1402 if (_value)
1403 MYGUI_LOG(
1404 Error,
1405 "MsdfMode flag ignored Define MYGUI_MSDF_FONTS if you need msdf fonts, msdf mode ignored.");
1406 #else
1407 mMsdfMode = _value;
1408 #endif
1409 }
1410
1411 void ResourceTrueTypeFont::setMsdfRange(int _value)
1412 {
1413 mMsdfRange = _value;
1414 }
1415
1416#endif // MYGUI_USE_FREETYPE
1417
1418} // namespace MyGUI
#define MYGUI_EXCEPT(dest)
#define MYGUI_LOG(level, text)
virtual void freeData(IDataStream *_data)=0
virtual IDataStream * getData(const std::string &_name) const =0
static DataManager & getInstance()
virtual size_t size()=0
const std::string & getResourceName() const
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 setShader(std::string_view _value)
void setResolution(unsigned int _value)
void setSource(std::string_view _value)
void textureInvalidate(ITexture *_texture) override
const GlyphInfo * getGlyphInfo(Char _id) const override
void removeCodePointRange(Char _first, Char _second)
void addCodePointRange(Char _first, Char _second)
void setHinting(std::string_view _value)
ITexture * getTextureFont() const override
std::vector< std::pair< Char, Char > > getCodePointRanges() const
void deserialization(xml::ElementPtr _node, Version _version) override
static Type firstPO2From(Type _value)
unsigned int parseUInt(std::string_view _value)
bool parseBool(std::string_view _value)
float parseFloat(std::string_view _value)
std::vector< std::string > split(std::string_view _source, std::string_view _delims="\t\n ")
std::string toString(T _value)
int parseInt(std::string_view _value)
Element * ElementPtr
uint8_t uint8
Definition MyGUI_Types.h:46
unsigned int Char
Definition MyGUI_Types.h:50