bool SizeParam::fromString(const std::string& str) { if (str.length() < 2) return false; std::string temp; if (str[ 0 ] == 'p') { temp = str.substr(1, str.length() - 1); px(utility::parseInt(temp)); } else if (str[ 0 ] == 'f') { if (str[ 1 ] == 'f') mFlMode = FM_FREE_SPACE; else if (str[ 1 ] == 'p') mFlMode = FM_PARENT; else MYGUI_EXCEPT("Second character of float mode in SizeParam is invalid!"); temp = str.substr(2, str.length() - 2); mFl = utility::parseFloat(temp); } else MYGUI_EXCEPT("First character in SizeParam is invalid!"); return true; }
void OverlappedLayer::destroyChildItemNode(ILayerNode* _item) { // если есть отец, то русть сам и удаляет ILayerNode* parent = _item->getParent(); if (parent) { parent->destroyChildItemNode(_item); mOutOfDate = true; return; } // айтем рутовый, мы удаляем for (VectorILayerNode::iterator iter = mChildItems.begin(); iter != mChildItems.end(); ++iter) { if ((*iter) == _item) { delete _item; mChildItems.erase(iter); mOutOfDate = true; return; } } MYGUI_EXCEPT("item node not found"); }
// поправить на виджет и проверять на рутовость void LayerManager::attachToLayerKeeper(const std::string& _name, WidgetPtr _item) { MYGUI_ASSERT(_item->isRootWidget(), "attached widget must be root"); // сначала отсоединяем detachFromLayerKeeper(_item); // а теперь аттачим for (VectorLayerKeeper::iterator iter=mLayerKeepers.begin(); iter!=mLayerKeepers.end(); ++iter) { if (_name == (*iter)->getName()) { // запоминаем в рутовом виджете хранитель лееров _item->mLayerKeeper = (*iter); // достаем из хранителя леер для себя _item->mLayerItemKeeper = (*iter)->getItem(); // подписываемся на пиккинг _item->mLayerItemKeeper->_addPeekItem(_item); // физически подсоединяем иерархию _item->_attachToLayerItemKeeper(_item->mLayerItemKeeper); return; } } MYGUI_EXCEPT("Layer '" << _name << "' is not found"); }
// удяляет неудачника void Gui::_destroyChildWidget(Widget* _widget) { MYGUI_ASSERT(nullptr != _widget, "invalid widget pointer"); VectorWidgetPtr::iterator iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget); if (iter != mWidgetChild.end()) { // сохраняем указатель MyGUI::Widget* widget = *iter; // удаляем из списка *iter = mWidgetChild.back(); mWidgetChild.pop_back(); // отписываем от всех mWidgetManager->unlinkFromUnlinkers(_widget); // непосредственное удаление WidgetManager::getInstance()._deleteWidget(widget); } else { MYGUI_EXCEPT("Widget '" << _widget->getName() << "' not found"); } }
void OverlappedLayer::upChildItemNode(ILayerNode* _item) { // если есть отец, то пусть сам рулит ILayerNode* parent = _item->getParent(); if (parent != nullptr) { parent->upChildItemNode(_item); mOutOfDate = true; return; } if ((2 > mChildItems.size()) || (mChildItems.back() == _item)) return; for (VectorILayerNode::iterator iter = mChildItems.begin(); iter != mChildItems.end(); ++iter) { if ((*iter) == _item) { mChildItems.erase(iter); mChildItems.push_back(_item); mOutOfDate = true; return; } } MYGUI_EXCEPT("item node not found"); }
void RenderItem::renderToTarget(IRenderTarget* _target, bool _update) { if (mTexture == nullptr) return; mRenderTarget = _target; mCurrentUpdate = _update; if (mOutOfDate || _update) { mCountVertex = 0; Vertex* buffer = mVertexBuffer->lock(); mOutOfDate = false; if (buffer != nullptr) { for (VectorDrawItem::iterator iter = mDrawItems.begin(); iter != mDrawItems.end(); ++iter) { // перед вызовом запоминаем позицию в буфере mCurrentVertex = buffer; mLastVertexCount = 0; (*iter).first->doRender(); // колличество отрисованных вершин MYGUI_DEBUG_ASSERT(mLastVertexCount <= (*iter).second, "It is too much vertexes"); buffer += mLastVertexCount; mCountVertex += mLastVertexCount; } mVertexBuffer->unlock(); } } // хоть с 0 не выводиться батч, но все равно не будем дергать стейт и операцию if (0 != mCountVertex) { #if MYGUI_DEBUG_MODE == 1 if (!RenderManager::getInstance().checkTexture(mTexture)) { mTexture = nullptr; MYGUI_EXCEPT("texture pointer is not valid, texture name '" << mTextureName << "'"); return; } #endif // непосредственный рендринг if (mManualRender) { for (VectorDrawItem::iterator iter = mDrawItems.begin(); iter != mDrawItems.end(); ++iter) (*iter).first->doManualRender(mVertexBuffer, mTexture, mCountVertex); } else { _target->doRender(mVertexBuffer, mTexture, mCountVertex); } } }
size_t MultiList::convertFromSort(size_t _index) { for (size_t pos=0; pos<mToSortIndex.size(); ++pos) { if (mToSortIndex[pos] == _index) return pos; } MYGUI_EXCEPT("index not found"); return ITEM_NONE; }
size_t MenuControl::getItemIndexById(const std::string& _id) { for (size_t index = 0; index < mItemsInfo.size(); index++) { if (mItemsInfo[index].id == _id) return index; } MYGUI_EXCEPT("item id (" << _id << ") not found, source 'MenuControl::getItemById'"); }
size_t MenuControl::getItemIndex(MenuItem* _item) { for (size_t pos = 0; pos < mItemsInfo.size(); pos++) { if (mItemsInfo[pos].item == _item) return pos; } MYGUI_EXCEPT("item (" << _item << ") not found, source 'MenuControl::getItemIndex'"); }
bool SizeDescription::checkBehaviour( uint8 _beh ) const { if( ( _beh & SB_MIN ) && ( _beh & SB_MAX ) ) { MYGUI_EXCEPT( "Can't be min and max!" ); return false; } return true; }
IResourcePtr ResourceManager::getByID(const Guid& _id, bool _throw) { MapResourceID::iterator iter = mResourcesID.find(_id); if (iter == mResourcesID.end()) { if (_throw) MYGUI_EXCEPT("resource '" << _id.print() << "' not found"); MYGUI_LOG(Warning, "resource '" << _id.print() << "' not found"); return nullptr; } return iter->second; }
void DynLib::unload() { // Log library unload MYGUI_LOG(Info, "Unloading library " << mName); #if MYGUI_PLATFORM == MYGUI_PLATFORM_APPLE //APPLE SPECIFIC CODE HERE #else if (MYGUI_DYNLIB_UNLOAD(mInstance)) { MYGUI_EXCEPT("Could not unload dynamic library '" << mName << "'. System Error: " << dynlibError()); } #endif }
void LayerNode::destroyChildItemNode(ILayerNode* _node) { for (VectorILayerNode::iterator iter=mChildItems.begin(); iter!=mChildItems.end(); ++iter) { if ((*iter) == _node) { delete _node; mChildItems.erase(iter); return; } } MYGUI_EXCEPT("item node not found"); }
Widget* WidgetManager::createWidget(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Widget* _parent, ICroppedRectangle* _cropeedParent, const std::string& _name) { IObject* object = FactoryManager::getInstance().createObject("Widget", _type); if (object != nullptr) { Widget* widget = object->castType<Widget>(); widget->_initialise(_style, _coord, _skin, _parent, _cropeedParent, _name); return widget; } MYGUI_EXCEPT("factory '" << _type << "' not found"); }
void LayerNode::upChildItemNode(ILayerNode* _item) { for (VectorILayerNode::iterator iter=mChildItems.begin(); iter!=mChildItems.end(); ++iter) { if ((*iter) == _item) { mChildItems.erase(iter); mChildItems.push_back(_item); return; } } MYGUI_EXCEPT("item node not found"); }
// удяляет только негодных батюшке государю void Widget::_destroyChildWidget(WidgetPtr _widget) { VectorWidgetPtr::iterator iter = std::find(mWidgetChild.begin(), mWidgetChild.end(), _widget); if(iter != mWidgetChild.end()) { delete *iter; // удаляем из списка *iter = mWidgetChild.back(); mWidgetChild.pop_back(); return; } MYGUI_EXCEPT("Widget not found"); }
MyGUI::Widget* Layout::getWidget(const std::string &_name) { for (MyGUI::VectorWidgetPtr::iterator iter=mListWindowRoot.begin(); iter!=mListWindowRoot.end(); ++iter) { MyGUI::Widget* find = (*iter)->findWidget(mPrefix + _name); if (nullptr != find) { return find; } } MYGUI_EXCEPT("widget name '" << _name << "' in layout '" << mLayoutName << "' not found."); }
void LayerNode::detachLayerItem(ILayerItem* _item) { for (VectorLayerItem::iterator iter=mLayerItems.begin(); iter!=mLayerItems.end(); ++iter) { if ((*iter) == _item) { (*iter) = mLayerItems.back(); mLayerItems.pop_back(); return; } } MYGUI_EXCEPT("layer item not found"); }
void LayerNode::detachLayerItem(ILayerItem* _item) { for (VectorLayerItem::iterator iter = mLayerItems.begin(); iter != mLayerItems.end(); ++iter) { if ((*iter) == _item) { mLayerItems.erase(iter); mOutOfDate = true; return; } } MYGUI_EXCEPT("layer item not found"); }
void BaseLayout::loadLayout(MyGUI::WidgetPtr _parent) { mParentWidget = _parent; mListWindowRoot = MyGUI::LayoutManager::getInstance().loadLayout(mLayoutName, mPrefix, _parent, GUI_RESOURCE_GROUP); //if (mParentWidget == null) { const std::string main_name = mPrefix + MAIN_WINDOW; for (MyGUI::VectorWidgetPtr::iterator iter=mListWindowRoot.begin(); iter!=mListWindowRoot.end(); ++iter) { if ((*iter)->getName() == main_name) { mMainWidget = (*iter); return; } } MYGUI_EXCEPT("root widget name '" << MAIN_WINDOW << "' in layout '" << mLayoutName << "' not found."); //} }
void RenderItem::reallockDrawItem(ISubWidget* _item, size_t _count) { for (VectorDrawItem::iterator iter=mDrawItems.begin(); iter!=mDrawItems.end(); ++iter) { if ((*iter).first == _item) { // если нужно меньше, то ниче не делаем if ((*iter).second < _count) { mNeedVertexCount -= (*iter).second; mNeedVertexCount += _count; (*iter).second = _count; mOutDate = true; mVertexBuffer->setVertextCount(mNeedVertexCount); } return; } } MYGUI_EXCEPT("DrawItem not found"); }
WidgetPtr WidgetManager::createWidget(const Ogre::String & _type, const Ogre::String & _skin, const IntCoord& _coord, Align _align, CroppedRectanglePtr _parent, const Ogre::String & _name) { Ogre::String name; if (false == _name.empty()) { MapWidgetPtr::iterator iter = mWidgets.find(_name); MYGUI_ASSERT(iter == mWidgets.end(), "widget with name '" << _name << "' already exist"); name = _name; } else { static long num=0; name = utility::toString(num++, "_", _type); } for (SetWidgetFactory::iterator factory = mFactoryList.begin(); factory != mFactoryList.end(); factory++) { if ( (*factory)->getType() == _type) { WidgetPtr widget = (*factory)->createWidget(_skin, _coord, _align, _parent, name); mWidgets[name] = widget; return widget; } } MYGUI_EXCEPT("factory '" << _type << "' not found"); return null; }
void RenderItem::removeDrawItem(ISubWidget* _item) { for (VectorDrawItem::iterator iter=mDrawItems.begin(); iter!=mDrawItems.end(); ++iter) { if ((*iter).first == _item) { mNeedVertexCount -= (*iter).second; mDrawItems.erase(iter); mOutDate = true; mVertexBuffer->setVertextCount(mNeedVertexCount); // если все отдетачились, расскажем отцу if (mDrawItems.empty()) { mTexture = nullptr; mCompression = true; } return; } } MYGUI_EXCEPT("DrawItem not found"); }
void ResourceTrueTypeFont::initialiseFreeType() { //-------------------------------------------------------------------// // Initialise FreeType and load the font. //-------------------------------------------------------------------// FT_Library ftLibrary; if (FT_Init_FreeType(&ftLibrary) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not init the FreeType library!"); uint8* fontBuffer = nullptr; FT_Face ftFace = loadFace(ftLibrary, fontBuffer); if (ftFace == nullptr) { MYGUI_LOG(Error, "ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); return; } //-------------------------------------------------------------------// // Calculate the font metrics. //-------------------------------------------------------------------// // The font's overall ascent and descent are defined in three different places in a TrueType font, and with different // values in each place. The most reliable source for these metrics is usually the "usWinAscent" and "usWinDescent" pair of // values in the OS/2 header; however, some fonts contain inaccurate data there. To be safe, we use the highest of the set // of values contained in the face metrics and the two sets of values contained in the OS/2 header. int fontAscent = ftFace->size->metrics.ascender >> 6; int fontDescent = -ftFace->size->metrics.descender >> 6; TT_OS2* os2 = (TT_OS2*)FT_Get_Sfnt_Table(ftFace, ft_sfnt_os2); if (os2 != nullptr) { setMax(fontAscent, os2->usWinAscent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM); setMax(fontDescent, os2->usWinDescent * ftFace->size->metrics.y_ppem / ftFace->units_per_EM); setMax(fontAscent, os2->sTypoAscender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM); setMax(fontDescent, -os2->sTypoDescender * ftFace->size->metrics.y_ppem / ftFace->units_per_EM); } // The nominal font height is calculated as the sum of its ascent and descent as specified by the font designer. Previously // it was defined by MyGUI in terms of the maximum ascent and descent of the glyphs currently in use, but this caused the // font's line spacing to change whenever glyphs were added to or removed from the font definition. Doing it this way // instead prevents a lot of layout problems, and it is also more typographically correct and more aesthetically pleasing. mDefaultHeight = fontAscent + fontDescent; // Set the load flags based on the specified type of hinting. FT_Int32 ftLoadFlags; switch (mHinting) { case HintingForceAuto: ftLoadFlags = FT_LOAD_FORCE_AUTOHINT; break; case HintingDisableAuto: ftLoadFlags = FT_LOAD_NO_AUTOHINT; break; case HintingDisableAll: // When hinting is completely disabled, glyphs must always be rendered -- even during layout calculations -- due to // discrepancies between the glyph metrics and the actual rendered bitmap metrics. ftLoadFlags = FT_LOAD_NO_HINTING | FT_LOAD_RENDER; break; case HintingUseNative: ftLoadFlags = FT_LOAD_DEFAULT; break; } //-------------------------------------------------------------------// // Create the glyphs and calculate their metrics. //-------------------------------------------------------------------// GlyphHeightMap glyphHeightMap; int texWidth = 0; // Before creating the glyphs, add the "Space" code point to force that glyph to be created. For historical reasons, MyGUI // users are accustomed to omitting this code point in their font definitions. addCodePoint(FontCodeType::Space); // Create the standard glyphs. for (CharMap::iterator iter = mCharMap.begin(); iter != mCharMap.end(); ) { const Char& codePoint = iter->first; FT_UInt glyphIndex = FT_Get_Char_Index(ftFace, codePoint); texWidth += createFaceGlyph(glyphIndex, codePoint, fontAscent, ftFace, ftLoadFlags, glyphHeightMap); // If the newly created glyph is the "Not Defined" glyph, it means that the code point is not supported by the font. // Remove it from the character map so that we can provide our own substitute instead of letting FreeType do it. if (iter->second != 0) ++iter; else mCharMap.erase(iter++); } // Do some special handling for the "Space" and "Tab" glyphs. GlyphInfo* spaceGlyphInfo = getGlyphInfo(FontCodeType::Space); if (spaceGlyphInfo != nullptr && spaceGlyphInfo->codePoint == FontCodeType::Space) { // Adjust the width of the "Space" glyph if it has been customized. if (mSpaceWidth != 0.0f) { texWidth += (int)std::ceil(mSpaceWidth) - (int)std::ceil(spaceGlyphInfo->width); spaceGlyphInfo->width = mSpaceWidth; spaceGlyphInfo->advance = mSpaceWidth; } // If the width of the "Tab" glyph hasn't been customized, make it eight spaces wide. if (mTabWidth == 0.0f) mTabWidth = mDefaultTabWidth * spaceGlyphInfo->advance; } // Create the special glyphs. They must be created after the standard glyphs so that they take precedence in case of a // collision. To make sure that the indices of the special glyphs don't collide with any glyph indices in the font, we must // use glyph indices higher than the highest glyph index in the font. FT_UInt nextGlyphIndex = (FT_UInt)ftFace->num_glyphs; float height = (float)mDefaultHeight; texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Tab), 0.0f, 0.0f, mTabWidth, 0.0f, 0.0f), glyphHeightMap); texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Selected), mSelectedWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap); texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::SelectedBack), mSelectedWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap); texWidth += createGlyph(nextGlyphIndex++, GlyphInfo(static_cast<Char>(FontCodeType::Cursor), mCursorWidth, height, 0.0f, 0.0f, 0.0f), glyphHeightMap); // If a substitute code point has been specified, check to make sure that it exists in the character map. If it doesn't, // revert to the default "Not Defined" code point. This is not a real code point but rather an invalid Unicode value that // is guaranteed to cause the "Not Defined" special glyph to be created. if (mSubstituteCodePoint != FontCodeType::NotDefined && mCharMap.find(mSubstituteCodePoint) == mCharMap.end()) mSubstituteCodePoint = static_cast<Char>(FontCodeType::NotDefined); // Create the "Not Defined" code point (and its corresponding glyph) if it's in use as the substitute code point. if (mSubstituteCodePoint == FontCodeType::NotDefined) texWidth += createFaceGlyph(0, static_cast<Char>(FontCodeType::NotDefined), fontAscent, ftFace, ftLoadFlags, glyphHeightMap); // Cache a pointer to the substitute glyph info for fast lookup. mSubstituteGlyphInfo = &mGlyphMap.find(mSubstituteCodePoint)->second; // Calculate the average height of all of the glyphs that are in use. This value will be used for estimating how large the // texture needs to be. double averageGlyphHeight = 0.0; for (GlyphHeightMap::const_iterator j = glyphHeightMap.begin(); j != glyphHeightMap.end(); ++j) averageGlyphHeight += j->first * j->second.size(); averageGlyphHeight /= mGlyphMap.size(); //-------------------------------------------------------------------// // Calculate the final texture size. //-------------------------------------------------------------------// // Round the current texture width and height up to the nearest powers of two. texWidth = Bitwise::firstPO2From(texWidth); int texHeight = Bitwise::firstPO2From((int)ceil(averageGlyphHeight) + mGlyphSpacing); // At this point, the texture is only one glyph high and is probably very wide. For efficiency reasons, we need to make the // texture as square as possible. If the texture cannot be made perfectly square, make it taller than it is wide, because // the height may decrease in the final layout due to height packing. while (texWidth > texHeight) { texWidth /= 2; texHeight *= 2; } // Calculate the final layout of all of the glyphs in the texture, packing them tightly by first arranging them by height. // We assume that the texture width is fixed but that the texture height can be adjusted up or down depending on how much // space is actually needed. // In most cases, the final texture will end up square or almost square. In some rare cases, however, we can end up with a // texture that's more than twice as high as it is wide; when this happens, we double the width and try again. do { if (texHeight > texWidth * 2) texWidth *= 2; int texX = mGlyphSpacing; int texY = mGlyphSpacing; for (GlyphHeightMap::const_iterator j = glyphHeightMap.begin(); j != glyphHeightMap.end(); ++j) { for (GlyphHeightMap::mapped_type::const_iterator i = j->second.begin(); i != j->second.end(); ++i) { GlyphInfo& info = *i->second; int glyphWidth = (int)std::ceil(info.width); int glyphHeight = (int)std::ceil(info.height); autoWrapGlyphPos(glyphWidth, texWidth, glyphHeight, texX, texY); if (glyphWidth > 0) texX += mGlyphSpacing + glyphWidth; } } texHeight = Bitwise::firstPO2From(texY + glyphHeightMap.rbegin()->first); } while (texHeight > texWidth * 2); //-------------------------------------------------------------------// // Create the texture and render the glyphs onto it. //-------------------------------------------------------------------// if (mTexture) { RenderManager::getInstance().destroyTexture( mTexture ); mTexture = nullptr; } mTexture = RenderManager::getInstance().createTexture(MyGUI::utility::toString((size_t)this, "_TrueTypeFont")); mTexture->createManual(texWidth, texHeight, TextureUsage::Static | TextureUsage::Write, Pixel<LAMode>::getFormat()); mTexture->setInvalidateListener(this); uint8* texBuffer = static_cast<uint8*>(mTexture->lock(TextureUsage::Write)); if (texBuffer != nullptr) { // Make the texture background transparent white. for (uint8* dest = texBuffer, * endDest = dest + texWidth * texHeight * Pixel<LAMode>::getNumBytes(); dest != endDest; ) Pixel<LAMode, false, false>::set(dest, charMaskWhite, charMaskBlack); renderGlyphs<LAMode, Antialias>(glyphHeightMap, ftLibrary, ftFace, ftLoadFlags, texBuffer, texWidth, texHeight); mTexture->unlock(); MYGUI_LOG(Info, "ResourceTrueTypeFont: Font '" << getResourceName() << "' using texture size " << texWidth << " x " << texHeight << "."); MYGUI_LOG(Info, "ResourceTrueTypeFont: Font '" << getResourceName() << "' using real height " << mDefaultHeight << " pixels."); } else { MYGUI_LOG(Error, "ResourceTrueTypeFont: Error locking texture; pointer is nullptr."); } FT_Done_Face(ftFace); FT_Done_FreeType(ftLibrary); delete [] fontBuffer; }
Widget* Spacer::baseCreateWidget(WidgetStyle _style, const std::string& _type, const std::string& _skin, const IntCoord& _coord, Align _align, const std::string& _layer, const std::string& _name) { MYGUI_EXCEPT("Have you ever seen that nothing has anything? I'm not sure that it's wright, so I put there exception that notify you (and me :) ) not to put anything here. Yes, don't put anything to Spacer!" ); }
FT_Face ResourceTrueTypeFont::loadFace(const FT_Library& _ftLibrary, uint8*& _fontBuffer) { FT_Face result = nullptr; // Load the font file. IDataStream* datastream = DataManager::getInstance().getData(mSource); if (datastream == nullptr) return result; size_t fontBufferSize = datastream->size(); _fontBuffer = new uint8[fontBufferSize]; datastream->read(_fontBuffer, fontBufferSize); DataManager::getInstance().freeData(datastream); datastream = nullptr; // Determine how many faces the font contains. if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, -1, &result) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); FT_Long numFaces = result->num_faces; FT_Long faceIndex = 0; // Load the first face. if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); if (result->face_flags & FT_FACE_FLAG_SCALABLE) { // The font is scalable, so set the font size by first converting the requested size to FreeType's 26.6 fixed-point // format. FT_F26Dot6 ftSize = (FT_F26Dot6)(mSize * (1 << 6)); if (FT_Set_Char_Size(result, ftSize, 0, mResolution, mResolution) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not set the font size for '" << getResourceName() << "'!"); // If no code points have been specified, use the Unicode Basic Multilingual Plane by default. if (mCharMap.empty()) addCodePointRange(0, 0xFFFF); } else { // The font isn't scalable, so try to load it as a Windows FNT/FON file. FT_WinFNT_HeaderRec fnt; // Enumerate all of the faces in the font and select the smallest one that's at least as large as the requested size // (after adjusting for resolution). If none of the faces are large enough, use the largest one. std::map<float, FT_Long> faceSizes; do { if (FT_Get_WinFNT_Header(result, &fnt) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); faceSizes.insert(std::make_pair((float)fnt.nominal_point_size * fnt.vertical_resolution / mResolution, faceIndex)); FT_Done_Face(result); if (++faceIndex < numFaces) if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); } while (faceIndex < numFaces); std::map<float, FT_Long>::const_iterator iter = faceSizes.lower_bound(mSize); faceIndex = (iter != faceSizes.end()) ? iter->second : faceSizes.rbegin()->second; if (FT_New_Memory_Face(_ftLibrary, _fontBuffer, (FT_Long)fontBufferSize, faceIndex, &result) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not load the font '" << getResourceName() << "'!"); // Select the first bitmap strike available in the selected face. This needs to be done explicitly even though Windows // FNT/FON files contain only one bitmap strike per face. if (FT_Select_Size(result, 0) != 0) MYGUI_EXCEPT("ResourceTrueTypeFont: Could not set the font size for '" << getResourceName() << "'!"); // Windows FNT/FON files do not support Unicode, so restrict the code-point range to either ISO-8859-1 or ASCII, // depending on the font's encoding. if (mCharMap.empty()) { // No code points have been specified, so add the printable ASCII range by default. addCodePointRange(0x20, 0x7E); // Additionally, if the font's character set is CP-1252, add the range of non-ASCII 8-bit code points that are // common between CP-1252 and ISO-8859-1; i.e., everything but 0x80 through 0x9F. if (fnt.charset == FT_WinFNT_ID_CP1252) addCodePointRange(0xA0, 0xFF); } else { // Some code points have been specified, so remove anything in the non-printable ASCII range as well as anything // over 8 bits. removeCodePointRange(0, 0x1F); removeCodePointRange(0x100, std::numeric_limits<Char>::max()); // Additionally, remove non-ASCII 8-bit code points (plus ASCII DEL, 0x7F). If the font's character set is CP-1252, // remove only the code points that differ between CP-1252 and ISO-8859-1; otherwise, remove all of them. if (fnt.charset == FT_WinFNT_ID_CP1252) removeCodePointRange(0x7F, 0x9F); else removeCodePointRange(0x7F, 0xFF); } } return result; }