| 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 | |
| 786 | DataManager::getInstance().freeData(datastream); |
| 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 | |