PC 平台 因为自定义字体 卡顿 不完美解决方案

  • Creator 版本:2.1.0

  • 目标平台: PC

我们发现 把项目发布PC 版本之后非常卡顿,目前大致找到一个问题是我们用了一个自己的字体库,使用系统自带的字体就不卡顿,我们使用lua 的版本同样的字体就不卡顿 请问这个是什么问题

看了代码 当一个字体改变大小和颜色 的时候都会频繁的移除和添加字体,我感觉应该可以修改为当字体发生变化的时候在做这个操作,而不是一些简单的属性发生变化都去删除和添加字体

官方大大有解决方案吗?

经过几天的奋斗发现了大致bug 的地方,

    void updateFont(const std::string& fontName, float fontSize, bool bold = false)
    {
        bool bRet = false;
        do
        {
            _fontName = fontName;
            _fontSize = fontSize;
            std::string fontPath;
            HFONT       hDefFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
            LOGFONTA    tNewFont = { 0 };
            LOGFONTA    tOldFont = { 0 };
            GetObjectA(hDefFont, sizeof(tNewFont), &tNewFont);
            if (!_fontName.empty())
            {
                // firstly, try to create font from ttf file
                const auto& fontInfoMap = getFontFamilyNameMap();
                auto iter = fontInfoMap.find(_fontName);
                if (iter != fontInfoMap.end())
                {
                    fontPath = iter->second;
                    std::string tmpFontPath = fontPath;
                    int nFindPos = tmpFontPath.rfind("/");
                    tmpFontPath = &tmpFontPath[nFindPos + 1];
                    nFindPos = tmpFontPath.rfind(".");
                    // IDEA: draw ttf failed if font file name not equal font face name
                    // for example: "DejaVuSansMono-Oblique" not equal "DejaVu Sans Mono"  when using DejaVuSansMono-Oblique.ttf
                    _fontName = tmpFontPath.substr(0, nFindPos);
                }
                else
                {
                    auto nFindPos = fontName.rfind("/");
                    if (nFindPos != fontName.npos)
                    {
                        if (fontName.length() == nFindPos + 1)
                        {
                            _fontName = "";
                        }
                        else
                        {
                            _fontName = &_fontName[nFindPos + 1];
                        }
                    }
                }
                tNewFont.lfCharSet = DEFAULT_CHARSET;
                strcpy_s(tNewFont.lfFaceName, LF_FACESIZE, _fontName.c_str());
            }

            if (_fontSize)
            {
                tNewFont.lfHeight = -_fontSize;
            }

            if (bold)
            {
                tNewFont.lfWeight = FW_BOLD;
            }
            else
            {
                tNewFont.lfWeight = FW_NORMAL;
            }

            GetObjectA(_font, sizeof(tOldFont), &tOldFont);

            if (tOldFont.lfHeight == tNewFont.lfHeight
                && tOldFont.lfWeight == tNewFont.lfWeight
                && 0 == strcmp(tOldFont.lfFaceName, tNewFont.lfFaceName))
            {
                bRet = true;
                break;
            }

            // delete old font


           // 导致卡顿的地方1
            // 增加逻辑 当字体没有没有变换的时候不需要 移除
            _removeCustomFont();

            if (fontPath.size() > 0)
            {
                _curFontPath = fontPath;
                wchar_t * pwszBuffer = _utf8ToUtf16(_curFontPath);
                if (pwszBuffer)
                {
                    // 导致卡顿的地方2
                      // 增加逻辑 当字体没有没有变换的时候不需要 移除
                    if (AddFontResource(pwszBuffer))
                    {
                        SendMessage(_wnd, WM_FONTCHANGE, 0, 0);
                    }
                    delete[] pwszBuffer;
                    pwszBuffer = nullptr;
                }
            }

            _font = nullptr;

            // disable Cleartype
            tNewFont.lfQuality = ANTIALIASED_QUALITY;

            // create new font
            _font = CreateFontIndirectA(&tNewFont);
            if (!_font)
            {
                // create failed, use default font
                _font = hDefFont;
                break;
            }
            else
            {
                SelectObject(_DC, _font);
                SendMessage(_wnd, WM_FONTCHANGE, 0, 0);
            }

            bRet = true;

        } while (0);

    }
void CanvasRenderingContext2D::set_font(const std::string& font)
{
    if (_font != font)
    {
        _font = font;

        std::string boldStr;
        std::string fontName = "Arial";
        std::string fontSizeStr = "30";

        // support get font name from `60px American` or `60px "American abc-abc_abc"`
        std::regex re("(bold)?\\s*((\\d+)([\\.]\\d+)?)px\\s+([\\w-]+|\"[\\w -]+\"$)");
        std::match_results<std::string::const_iterator> results;
        if (std::regex_search(_font.cbegin(), _font.cend(), results, re))
        {
            boldStr = results[1].str();
            fontSizeStr = results[2].str();
            fontName = results[5].str();
        }

        float fontSize = atof(fontSizeStr.c_str());
        //SE_LOGD("CanvasRenderingContext2D::set_font: %s, Size: %f, isBold: %b\n", fontName.c_str(), fontSize, !boldStr.empty());
         //  这个是调用的地方
        _impl->updateFont(fontName, fontSize, !boldStr.empty());
    }
}
1赞