首页 > 学院 > 开发设计 > 正文

SOUI GDI+渲染引擎下的字体特效,抛砖引玉

2019-11-08 01:26:43
字体:
来源:转载
供稿:网友

文章来源:http://www.cnblogs.com/koangel/p/5192603.html

由于SOUI是一种双渲染引擎的DUI库,默认在SKIA渲染引擎下是支持特效字体的,具体请参考DEMO中的源码

但是使用GDI+渲染时是没有这些特效的,着实比较苦恼,此代抛砖引玉,细节实现 请自己再去封装,此处只封装了STATIC控件。

部分效果使用了库:TextDesigner

CodePRoject: http://www.codeproject.com/Articles/42529/Outline-Text

此代码有一个小BUG,在使用SOUI布局时,POS必须4个参数都指定,类似如此:pos="15,20,-15,@25"

有兴趣的朋友可以自己实现一下。

先看下预览效果

我只实现了部分效果,由于效果组合太多,所以这里暂时把我常用的先贴出来。

参数说明:

drawMode: 1为描边 2阴影 3外发光 4双描边,具体特效请自己设置颜色和渲染效果

EffectColor: 特效的颜色数值

EffectColor2: 使用双效果时的第二个数值颜色

底层使用GDI+所以默认支持多行,但是请根据多行来设置对应的高宽,否则显示肯定错误。

头文件:

复制代码
 1 /*! 2  * /file SEffectStatic.h 3  * /date 2016/02/15 19:51 4  * 5  * /author koangel 6  * Contact: jackliu100@Gmail.com 7  * blog: http://www.cnblogs.com/koangel/ 8  * 9  * /brief GDI渲染模式下专用静态特效渲染库 10  *11  * /note GDI+渲染模式下专用,如果在SKIA模式下,直接切换为标准SSTAIC模式渲染12  *          效果使用GDI编写,暂不支持SKIA13  *        部分效果使用TextDesigner库编写。14  *          CodeProject: http://www.codeproject.com/Articles/42529/Outline-Text15  *          TextDesigner版权归原作者所有。16 */17 #pragma once18 #include <gdiplus.h>19 20 #pragma comment(lib,"gdiplus.lib")21 22 class SEffectStatic : public SStatic23 {24     SOUI_CLASS_NAME(SStatic, L"eff_text")25 public:26     SEffectStatic();27     virtual ~SEffectStatic();28     /**29     * SStatic::SDrawText30     * @brief    绘制文本31     * @param    IRenderTarget *pRT -- 绘制设备句柄32     * @param    LPCTSTR pszBuf -- 文本内容字符串33     * @param    int cchText -- 字符串长度34     * @param    LPRECT pRect -- 指向矩形结构RECT的指针35     * @param    UINT uFormat --  正文的绘制选项36     *37     * Describe  对DrawText封装38     */39     virtual void DrawText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);40 41 protected:42 43     void DrawMultiLine(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);44     void DrawShadowMultiLine(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);45 46     // 渲染带阴影的字体47     void DrawShadowText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);48     void DrawStrokeText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);49     void DrawDoubleStrokeText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);50     void DrawGowText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat);51 52     void    initGDIFont(IRenderTarget *pRT,Gdiplus::Font& gf);53 54     LOGFONT*    GetGDIFont(IRenderTarget *pRT);55     Gdiplus::StringFormat*    toFormat(UINT uFormat);56 57     int            m_nEffectDrawMode;            /**< 渲染模式 */58     COLORREF    m_nEffectColor;            /**< 效果颜色 */59     COLORREF    m_nEffectColor2;            /**< 效果颜色 */60     Word        m_StrokeSize;                /**< 描边大小 */61 62     SOUI_ATTRS_BEGIN()63         ATTR_INT(L"drawMode", m_nEffectDrawMode, FALSE)64         ATTR_COLOR(L"effectColor", m_nEffectColor, FALSE)65         ATTR_COLOR(L"effectColor2", m_nEffectColor2, FALSE)66         ATTR_INT(L"strokeSize", m_StrokeSize, FALSE)67     SOUI_ATTRS_END()68 };复制代码

实现文件:

复制代码
  1 /*!  2  * /file SEffectStatic.cpp  3  * /date 2016/02/16 13:00  4  *  5  * /author koangel  6  * Contact: jackliu100@gmail.com  7  *  8  * /brief 渲染对应的静态文本,多行文本渲染可能存在问题  9  * 10  * TODO: blog http://www.cnblogs.com/koangel/ 11  * 12  * /note 13 */ 14 #include "stdafx.h" 15 #include "SEffectStatic.h" 16 enum DRAW_EFFECT_MODE 17 { 18     DRAW_TEXT_NORMAL = 0, // 默认渲染 19     DRAW_TEXT_STROKE, // 渲染 描边 20     DRAW_TEXT_SHADOW, // 渲染 阴影 21     DRAW_TEXT_GROW,    // 渲染 外发光效果 22     DRAW_TEXT_DBSTROKE, // 渲染 双描边 23 }; 24  25 #define GR(rgb)      ((BYTE)(rgb)) 26 #define GG(rgb)      ((BYTE)(((WORD)(rgb)) >> 8)) 27 #define GB(rgb)      ((BYTE)((rgb)>>16)) 28  29 // 默认调用之前的构造函数 30 SEffectStatic::SEffectStatic() : SStatic(), 31     m_nEffectColor(0xFFFFFF), 32     m_nEffectColor2(0xFF0080), 33     m_nEffectDrawMode(0), 34     m_StrokeSize(1) 35 { 36 } 37  38  39 SEffectStatic::~SEffectStatic() 40 { 41  42 } 43  44 void SEffectStatic::DrawText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat) 45 { 46     if (!m_bMultiLines) 47     { 48         switch (m_nEffectDrawMode) 49         { 50         case DRAW_TEXT_NORMAL: 51             __super::DrawText(pRT, pszBuf, cchText, pRect, uFormat); 52             break; 53         case DRAW_TEXT_STROKE: 54             DrawStrokeText(pRT, pszBuf, cchText, pRect, uFormat); 55             break; 56         case DRAW_TEXT_SHADOW: 57             DrawShadowText(pRT, pszBuf, cchText, pRect, uFormat); 58             break; 59         case DRAW_TEXT_GROW: 60             DrawGowText(pRT, pszBuf, cchText, pRect, uFormat); 61             break; 62         case DRAW_TEXT_DBSTROKE: 63             DrawDoubleStrokeText(pRT, pszBuf, cchText, pRect, uFormat); 64             break; 65         } 66     } 67     else 68     { 69         switch (m_nEffectDrawMode) 70         { 71         case DRAW_TEXT_NORMAL: 72         { 73             if (uFormat&(DT_VCENTER | DT_BOTTOM) && !(uFormat & DT_CALCRECT)) 74             { 75                 //static 多行控件支持垂直居中及底对齐 76                 CRect rcText = *pRect; 77                 DrawMultiLine(pRT, pszBuf, cchText, &rcText, uFormat | DT_CALCRECT); 78                 CSize szTxt = rcText.Size(); 79                 rcText = *pRect; 80                 switch (GetStyle().GetTextAlign()&(DT_VCENTER | DT_BOTTOM)) 81                 { 82                 case DT_VCENTER: 83                     rcText.DeflateRect(0, (rcText.Height() - szTxt.cy) / 2); 84                     break; 85                 case DT_BOTTOM: 86                     rcText.DeflateRect(0, (rcText.Height() - szTxt.cy)); 87                     break; 88                 } 89                 DrawMultiLine(pRT, pszBuf, cchText, &rcText, uFormat); 90             } 91             else 92             { 93                 DrawMultiLine(pRT, pszBuf, cchText, pRect, uFormat); 94             } 95             break; 96         } 97         case DRAW_TEXT_STROKE: 98             DrawStrokeText(pRT, pszBuf, cchText, pRect, uFormat); 99             break;100         case DRAW_TEXT_SHADOW:101             DrawShadowMultiLine(pRT, pszBuf, cchText, pRect, uFormat);102             break;103         case DRAW_TEXT_GROW:104             DrawGowText(pRT, pszBuf, cchText, pRect, uFormat);105             break;106         case DRAW_TEXT_DBSTROKE:107             DrawDoubleStrokeText(pRT, pszBuf, cchText, pRect, uFormat);108             break;109         }    110     }111 }112 113 void SEffectStatic::DrawMultiLine(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)114 {115     SIZE szChar;116     int i = 0, nLine = 1;117     if (cchText == -1) cchText = _tcslen(pszBuf);118     LPCTSTR p1 = pszBuf;119     POINT pt = { pRect->left,pRect->top };120     pRT->MeasureText(_T("A"), 1, &szChar);121     int nLineHei = szChar.cy;122     int nRight = pRect->right;123     pRect->right = pRect->left;124     while (i<cchText)125     {126         LPTSTR p2 = CharNext(p1);127         if (*p1 == _T('//') && p2 && *p2 == _T('n'))128         {129             pt.y += nLineHei + m_nLineInter;130             pt.x = pRect->left;131             nLine++;132             i += p2 - p1;133             p1 = CharNext(p2);134             i += p1 - p2;135             continue;136         }137         pRT->MeasureText(p1, p2 - p1, &szChar);138         if (pt.x + szChar.cx > nRight)139         {140             pt.y += nLineHei + m_nLineInter;141             pt.x = pRect->left;142             nLine++;143             continue;144         }145         if (!(uFormat & DT_CALCRECT))146         {147             pRT->TextOut(pt.x, pt.y, p1, p2 - p1);148         }149         pt.x += szChar.cx;150         if (pt.x > pRect->right && uFormat & DT_CALCRECT) pRect->right = pt.x;151         i += p2 - p1;152         p1 = p2;153     }154     if (uFormat & DT_CALCRECT)155     {156         pRect->bottom = pt.y + nLineHei;157     }158 }159 160 void SEffectStatic::DrawShadowMultiLine(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)161 {162     COLORREF textColor = this->m_style.GetTextColor(0);163 164     Gdiplus::StringFormat   *strFmt = toFormat(uFormat);165 166     Gdiplus::Graphics           gs(pRT->GetDC());167     Gdiplus::Font               gf(pRT->GetDC(), GetGDIFont(pRT));168 169     gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);170     gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);171     gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);172 173     Gdiplus::Rect rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);174 175     Gdiplus::FontFamily ffamliy;176     gf.GetFamily(&ffamliy);177 178     Gdiplus::SolidBrush  br1(Gdiplus::Color(255, GR(textColor), GG(textColor), GB(textColor)));179 180     TextDesigner::OutlineText outtext;181     outtext.EnableShadow(true);182     outtext.TextNoOutline(br1);183     outtext.Shadow(Gdiplus::Color(128, GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)), 2, Gdiplus::Point(1,2));184     outtext.DrawString(&gs, &ffamliy, (Gdiplus::FontStyle) gf.GetStyle(), gf.GetSize(), pszBuf, rectF, strFmt);185 }186 187 void SEffectStatic::DrawShadowText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)188 {189     COLORREF textColor = this->m_style.GetTextColor(0);190 191     Gdiplus::StringFormat   *strFmt = toFormat(uFormat);192     Gdiplus::Graphics           gs(pRT->GetDC());193     Gdiplus::Font               gf(pRT->GetDC(), GetGDIFont(pRT));194 195     gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);196     gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);197     gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);198 199     Gdiplus::Rect rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);200 201     Gdiplus::FontFamily ffamliy;202     gf.GetFamily(&ffamliy);203 204     Gdiplus::SolidBrush  br1(Gdiplus::Color(255, GR(textColor), GG(textColor), GB(textColor)));205 206     TextDesigner::OutlineText outtext;207     outtext.EnableShadow(true);208     outtext.TextNoOutline(br1);209     outtext.Shadow(Gdiplus::Color(128, GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)), 2, Gdiplus::Point(1,2));210     outtext.DrawString(&gs, &ffamliy,(Gdiplus::FontStyle) gf.GetStyle(), gf.GetSize() , pszBuf, rectF, strFmt);211 }212 213 void SEffectStatic::DrawStrokeText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)214 {215     COLORREF textColor = this->m_style.GetTextColor(0);216     Gdiplus::Graphics           gs(pRT->GetDC());217     Gdiplus::Font               gf(pRT->GetDC(), GetGDIFont(pRT));218     Gdiplus::StringFormat   *strFmt = toFormat(uFormat);219 220     gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);221     gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);222     gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);223 224     Gdiplus::RectF rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);225 226     Gdiplus::SolidBrush  br1(Gdiplus::Color(255,GR(textColor), GG(textColor), GB(textColor)));227     Gdiplus::SolidBrush  br2(Gdiplus::Color(250,GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)));228 229     int nOffsetX[8] = { 1,1,1,0,-1,-1,-1,0 };230     int nOffsetY[8] = { -1,0,1,1,1,0,-1,-1 };231 232     for (int i = 0; i < 8;i++)233     {234         Gdiplus::RectF lRecf(rectF);235         lRecf.Offset(nOffsetX[i], nOffsetY[i]);236         gs.DrawString(pszBuf, cchText, &gf, lRecf, strFmt, &br2);237     }238 239     gs.DrawString(pszBuf, cchText, &gf, rectF, toFormat(uFormat), &br1);240 }241 242 void SEffectStatic::DrawDoubleStrokeText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)243 {244     COLORREF textColor = this->m_style.GetTextColor(0);245     Gdiplus::StringFormat   *strFmt = toFormat(uFormat);246     Gdiplus::Graphics           gs(pRT->GetDC());247     Gdiplus::Font               gf(pRT->GetDC(), GetGDIFont(pRT));248 249     gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);250     gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);251     gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);252 253     Gdiplus::Rect rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);254 255     Gdiplus::FontFamily ffamliy;256     gf.GetFamily(&ffamliy);257 258     Gdiplus::SolidBrush  br1(Gdiplus::Color(255, GR(textColor), GG(textColor), GB(textColor)));259 260     TextDesigner::OutlineText outtext;261     outtext.EnableShadow(false);262     outtext.TextDblOutline(br1, Gdiplus::Color(255, GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)),263         Gdiplus::Color(255, GR(m_nEffectColor2), GG(m_nEffectColor2), GB(m_nEffectColor2)), 3,3);264     outtext.DrawString(&gs, &ffamliy, (Gdiplus::FontStyle) gf.GetStyle(), gf.GetSize(), pszBuf, rectF, strFmt);265 }266 267 void SEffectStatic::DrawGowText(IRenderTarget *pRT, LPCTSTR pszBuf, int cchText, LPRECT pRect, UINT uFormat)268 {269     COLORREF textColor = this->m_style.GetTextColor(0);270     Gdiplus::StringFormat   *strFmt = toFormat(uFormat);271     Gdiplus::Graphics           gs(pRT->GetDC());272     Gdiplus::Font               gf(pRT->GetDC(), GetGDIFont(pRT));273 274     gs.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);275     gs.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAliasGridFit);276     gs.SetPixelOffsetMode(Gdiplus::PixelOffsetModeHighQuality);277 278     Gdiplus::Rect rectF(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);279 280     Gdiplus::FontFamily ffamliy;281     gf.GetFamily(&ffamliy);282 283     Gdiplus::SolidBrush  br1(Gdiplus::Color(255, GR(textColor), GG(textColor), GB(textColor)));284 285     TextDesigner::OutlineText outtext;286     outtext.EnableShadow(false);287     outtext.TextGlow(br1,Gdiplus::Color(64, GR(m_nEffectColor), GG(m_nEffectColor), GB(m_nEffectColor)),6);288     outtext.DrawString(&gs, &ffamliy, (Gdiplus::FontStyle) gf.GetStyle(), gf.GetSize(), pszBuf, rectF, strFmt);289 }290 291 LOGFONT* SEffectStatic::GetGDIFont(IRenderTarget *pRT)292 {293     SOUI::IFontPtr pFont = m_style.GetTextFont(0);294     SOUI::IFontPtr pDFont = (SOUI::IFontPtr)pRT->GetCurrentObject(OT_FONT);295     LOGFONT    *    logFont = NULL;296     if (pFont == NULL)297         logFont = (LOGFONT*)pDFont->LogFont();298     else299         logFont = (LOGFONT*)pFont->LogFont();300 301     return logFont;302 }303 304 Gdiplus::StringFormat* SEffectStatic::toFormat(UINT uFormat)305 {306     Gdiplus::StringFormat   *strFmt = Gdiplus::StringFormat::GenericTypographic()->Clone();307 308     if (uFormat&(DT_VCENTER | DT_BOTTOM))309     {310         strFmt->SetAlignment(Gdiplus::StringAlignmentCenter);311         strFmt->SetLineAlignment(Gdiplus::StringAlignmentCenter);312     }313     else314     {315         strFmt->SetAlignment(Gdiplus::StringAlignmentNear);316         strFmt->SetLineAlignment(Gdiplus::StringAlignmentNear);317     }318 319     return strFmt;320 }复制代码

以上代码抛砖引玉,希望各位发扬光大,多写一些组件库噢。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表