Esempio n. 1
0
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);
}