CFont::CFont(CXMLTreeNode& fontNode, CGUI* gui) : CNamed(fontNode) , m_glyphs( MAX_GLYPHS_BATCH ) , m_gui(gui) , m_textAlign(Rectf::Alignment::TOP_LEFT) { auto mm = CEngine::GetSingleton().getMaterialManager(); auto tm = CEngine::GetSingleton().getTextureManager(); std::string fontFile = fontNode.GetPszProperty("path", "", false); std::string fontName = fontNode.GetPszProperty("name", "", false); DEBUG_ASSERT(fontFile.size() != 0 && fontName.size() != 0); if (fontFile.size() == 0 || fontName.size() == 0) { return; } for (int i = 0; i < fontNode.GetNumChildren(); ++i) { auto matNode = fontNode(i); if (matNode.GetName() == std::string("material")) { std::string matName = "font-material-" + fontName; CMaterial *mat = new CMaterial(matNode); mat->setName(matName); mm->add(matName, mat); m_material = mat; break; } } std::string fontPath; size_t pathEnd = fontFile.find_last_of('\\'); if (pathEnd == fontFile.npos) { pathEnd = fontFile.find_last_of('/'); } if (pathEnd != fontFile.npos) { fontPath = fontFile.substr(0, pathEnd+1); } CXMLTreeNode ff; if (!ff.LoadFile(fontFile.c_str())) { DEBUG_ASSERT(false); return; } CXMLTreeNode font = ff["font"]; CXMLTreeNode common = font["common"]; CXMLTreeNode info = font["info"]; Vect2f pageSize(common.GetFloatProperty("scaleW", 0, false), common.GetFloatProperty("scaleH", 0, false)); m_fontSize = info.GetFloatProperty( "size", 0, false ); DEBUG_ASSERT( m_fontSize != 0); m_lineHeight = common.GetFloatProperty( "lineHeight", m_fontSize, false ); m_base = common.GetFloatProperty( "base", m_fontSize, false ); CXMLTreeNode pages = font["pages"]; for (int i = 0; i < pages.GetNumChildren(); ++i) { auto page = pages(i); if (page.GetName() == std::string("page")) { std::string texFile = page.GetPszProperty("file", "", false); DEBUG_ASSERT(texFile.size() > 0); texFile = fontPath + texFile; CTexture *tex = new CTexture(); tex->load(texFile, false); tm->add(tex->getName(), tex); m_pages.push_back(tex); } } auto chars = font["chars"]; for (int i = 0; i < chars.GetNumChildren(); ++i) { auto ch = chars(i); if (ch.GetName() != std::string("char")) { continue; } uchar chId = ch.GetIntProperty("id"); CharDesc_t cdesc; cdesc.offset = Vect2f(ch.GetFloatProperty("xoffset", 0, false), ch.GetFloatProperty("yoffset", 0, false)); cdesc.page = ch.GetIntProperty("page"); cdesc.size = Vect2f(ch.GetFloatProperty("width", 0, false), ch.GetFloatProperty("height", 0, false)); cdesc.xAdvance = ch.GetFloatProperty("xadvance", 0, false); cdesc.uvRect.position = Vect2f(ch.GetFloatProperty("x", 0, false), ch.GetFloatProperty("y", 0, false)); cdesc.uvRect.position = Vect2f(cdesc.uvRect.position.x / pageSize.x, cdesc.uvRect.position.y / pageSize.y); cdesc.uvRect.size = Vect2f(cdesc.size.x / pageSize.x, cdesc.size.y / pageSize.y); m_chars[chId] = cdesc; } auto kerns = font["kernings"]; if (kerns.Exists()) { for (int i = 0; i < kerns.GetNumChildren(); ++i) { auto k = kerns(i); uchar f = k.GetIntProperty("first", 0, false); uchar s = k.GetIntProperty("second", 0, false); uchar a = k.GetIntProperty("amount", 0, false); m_kernings[std::make_pair(f, s)] = a; } } m_glyphsVtxs = new CPointsListRenderableVertexs<GUI_TEXT_VERTEX>(m_glyphs.data(), MAX_GLYPHS_BATCH, MAX_GLYPHS_BATCH, true); }