主题:使用skia渲染时一些特殊文字不能正常显示怎么办?

admin 2018年12月08日 104

skia渲染引擎速度比GDI快不少,在安装包体积允许的情况下尽可能的使用skia渲染。然而今天发现一个问题,skia在渲染文字时如果一些字符不在指定字体范围内,则显示不出来,但是GDI会自动匹配其它字体显示。如果要去修改skia,工作量很量估计,这里实现了一个临时的解决方案:采用GDI+来绘制这部分文字。通常这种情况是要显示的文字是由用户产生的,不受应用程序控制。针对这部分显示内容,采用GDI+来绘制,保留其它内容给skia绘制,这样即解决了文字显示问题也不影响渲染效率。

 代码见附件。Static_GDIP.h


#pragma once

#include <GdiPlus.h>

namespace SOUI
{
    class SStatic_GDIP: public SWindow
    {
        SOUI_CLASS_NAME(SStatic_GDIP,L"text_gdip")
    public:
        SStatic_GDIP(void);
        ~SStatic_GDIP(void);
        
    public:
        static BOOL Gdiplus_Startup();
        static void Gdiplus_Shutdown();

    protected:
        int  OnCreate(LPVOID);
        void OnPaint(IRenderTarget *pRT);
        
        CSize GetDesiredSize(LPCRECT pRcContainer);
        SOUI_MSG_MAP_BEGIN()
            MSG_WM_CREATE(OnCreate)
            MSG_WM_PAINT_EX(OnPaint)
        SOUI_MSG_MAP_END()
        
        Gdiplus::Font   *  m_font;
    };
}

Static_GDIP.cpp

#include "stdafx.h"
#include "SStatic_GDIP.h"
using namespace Gdiplus;
#pragma comment(lib,"gdiplus.lib")

namespace SOUI
{
    //////////////////////////////////////////////////////////////////////////
    static ULONG_PTR s_gdipToken=0;

    BOOL SStatic_GDIP::Gdiplus_Startup()
    {
        GdiplusStartupInput gdiplusStartupInput;
        Status st=GdiplusStartup(&s_gdipToken, &gdiplusStartupInput, NULL);
        return st==0;

    }

    void SStatic_GDIP::Gdiplus_Shutdown()
    {
        GdiplusShutdown(s_gdipToken);
    }

    //////////////////////////////////////////////////////////////////////////
    SStatic_GDIP::SStatic_GDIP(void):m_font(NULL)
    {
    }

    SStatic_GDIP::~SStatic_GDIP(void)
    {
        if(m_font) delete m_font;
    }

    void SStatic_GDIP::OnPaint(IRenderTarget *pRT)
    {
        HDC hdc = pRT->GetDC(0);
        COLORREF crTxt = pRT->GetTextColor();
        Graphics *g = new Graphics(hdc);
        
        CRect rcClient = GetClientRect();
        SStringW strText = S_CT2W(m_strText);
        Color cr(GetAValue(crTxt), GetRValue(crTxt), GetGValue(crTxt), GetBValue(crTxt));
        SolidBrush br(cr);
        PointF pt(rcClient.left,rcClient.top);
        g->DrawString(strText,strText.GetLength(),m_font,pt,StringFormat::GenericDefault(),&br);
        delete g;
        pRT->ReleaseDC(hdc);
    }

    int SStatic_GDIP::OnCreate(LPVOID)
    {
        __super::OnCreate(NULL);
        
        CAutoRefPtr<IRenderTarget> pRT;
        GETRENDERFACTORY->CreateRenderTarget(&pRT,0,0);
        SASSERT(pRT);
        BeforePaintEx(pRT);
        
        CAutoRefPtr<IFont> pFont = (IFont*)pRT->GetCurrentObject(OT_FONT);
        const LOGFONT *lf =  pFont->LogFont();
        
        
        HDC hdc = ::GetDC(NULL);
        m_font = new Gdiplus::Font(hdc,lf);
        ::ReleaseDC(NULL,hdc);
        
        return 0;
    }
    
    CSize SStatic_GDIP::GetDesiredSize(LPCRECT pRcContainer)
    {
        
        CSize szRet;
        if(m_layout.IsSpecifySize(PD_X))
        {
            szRet.cx = m_layout.GetSpecifySize(PD_X);
        }
        if(m_layout.IsSpecifySize(PD_Y))
        {
            szRet.cy = m_layout.GetSpecifySize(PD_Y);
        }

        if(szRet.cx && szRet.cy) 
            return szRet;
        
        HDC hdc = ::GetDC(NULL);
        Graphics *g = new Graphics(hdc);
        
        PointF pt;
        RectF  rcBound;
        SStringW strText = S_CT2W(m_strText);
        g->MeasureString(strText,strText.GetLength(),m_font,pt,&rcBound);
        delete g;
        ::ReleaseDC(NULL,hdc);
        
        if(!m_layout.IsSpecifySize(PD_X))
        {
            szRet.cx = (int)rcBound.Width;
        }
        if(!m_layout.IsSpecifySize(PD_Y))
        {
            szRet.cy = (int)rcBound.Height;
        }
        
        return szRet;
    }


}