增加Text描边功能(包括描边颜色、线宽、相交线样式)

This commit is contained in:
Nomango 2018-04-22 00:33:20 +08:00
parent f215632e60
commit eb8b7e5f7e
10 changed files with 335 additions and 118 deletions

View File

@ -61,10 +61,10 @@ bool e2d::Renderer::__createDeviceIndependentResources()
hr = s_pDWriteFactory->CreateTextFormat(
L"",
NULL,
DWRITE_FONT_WEIGHT_BOLD,
DWRITE_FONT_WEIGHT_NORMAL,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
22,
20,
L"",
&s_pTextFormat
);
@ -195,11 +195,13 @@ void e2d::Renderer::__render()
if (SUCCEEDED(hr))
{
s_pRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
s_pSolidBrush->SetOpacity(1.0f);
s_pTextRenderer->SetTextStyle(
D2D1::ColorF(D2D1::ColorF::White),
TRUE,
D2D1::ColorF(D2D1::ColorF::Black),
2.0f,
1.0f
1.0f,
D2D1_LINE_JOIN::D2D1_LINE_JOIN_ROUND
);
pTextLayout->Draw(NULL, s_pTextRenderer, 10, 0);

View File

@ -1,21 +0,0 @@
#include "..\e2dnode.h"
e2d::Font::Font()
: fontFamily("")
, size(22)
, color(Color::WHITE)
, weight(FontWeight::NORMAL)
, italic(false)
, underline(false)
, strikethrough(false)
{}
e2d::Font::Font(String fontFamily, double fontSize, UINT32 color, UINT32 fontWeight, bool italic, bool hasUnderline, bool hasStrikethrough)
: fontFamily(fontFamily)
, size(fontSize)
, color(color)
, weight(fontWeight)
, italic(italic)
, underline(hasUnderline)
, strikethrough(hasStrikethrough)
{}

41
core/Common/TextStyle.cpp Normal file
View File

@ -0,0 +1,41 @@
#include "..\e2dnode.h"
e2d::TextStyle::TextStyle()
: fontFamily("")
, fontSize(22)
, color(Color::WHITE)
, weight(FontWeight::NORMAL)
, italic(false)
, underline(false)
, strikethrough(false)
, showOutline(true)
, outlineColor(Color::BLACK)
, outlineWidth(1.0)
, outlineJoin(LineJoin::ROUND)
{}
e2d::TextStyle::TextStyle(
String fontFamily,
double fontSize,
UINT32 color,
UINT32 textStyleWeight,
bool italic,
bool hasUnderline,
bool hasStrikethrough,
bool showOutline,
UINT32 outlineColor,
UINT32 outlineWidth,
int outlineJoin
)
: fontFamily(fontFamily)
, fontSize(fontSize)
, color(color)
, weight(textStyleWeight)
, italic(italic)
, underline(hasUnderline)
, strikethrough(hasStrikethrough)
, showOutline(showOutline)
, outlineColor(outlineColor)
, outlineWidth(outlineWidth)
, outlineJoin(outlineJoin)
{}

View File

@ -1,4 +1,5 @@
#include "..\e2dcustom.h"
#include "..\e2dbase.h"
using namespace e2d;
@ -13,8 +14,9 @@ CustomTextRenderer::CustomTextRenderer(
, pBrush_(pBrush)
, sFillColor_()
, sOutlineColor_()
, fStrokeWidth_(1)
, fOpacity_(1)
, fOutlineWidth(1)
, bShowOutline_(TRUE)
, nOutlineJoin_(D2D1_LINE_JOIN::D2D1_LINE_JOIN_MITER)
{
pD2DFactory_->AddRef();
pRT_->AddRef();
@ -30,15 +32,17 @@ CustomTextRenderer::~CustomTextRenderer()
STDMETHODIMP_(void) CustomTextRenderer::SetTextStyle(
CONST D2D1_COLOR_F &fillColor,
BOOL showOutline,
CONST D2D1_COLOR_F &outlineColor,
FLOAT strokeWidth,
FLOAT opacity
FLOAT outlineWidth,
D2D1_LINE_JOIN outlineJoin
)
{
sFillColor_ = fillColor;
bShowOutline_ = showOutline;
sOutlineColor_ = outlineColor;
fStrokeWidth_ = strokeWidth;
fOpacity_ = opacity;
fOutlineWidth = 2 * outlineWidth;
nOutlineJoin_ = outlineJoin;
}
STDMETHODIMP CustomTextRenderer::DrawGlyphRun(
@ -101,16 +105,38 @@ STDMETHODIMP CustomTextRenderer::DrawGlyphRun(
);
}
ID2D1StrokeStyle * pStrokeStyle = NULL;
if (SUCCEEDED(hr))
{
pBrush_->SetOpacity(fOpacity_);
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fStrokeWidth_
hr = Renderer::getID2D1Factory()->CreateStrokeStyle(
D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
nOutlineJoin_,
2.0f,
D2D1_DASH_STYLE_SOLID,
0.0f),
NULL,
0,
&pStrokeStyle
);
}
if (SUCCEEDED(hr))
{
if (bShowOutline_)
{
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fOutlineWidth,
pStrokeStyle
);
}
pBrush_->SetColor(sFillColor_);
@ -166,16 +192,38 @@ STDMETHODIMP CustomTextRenderer::DrawUnderline(
);
}
ID2D1StrokeStyle * pStrokeStyle = NULL;
if (SUCCEEDED(hr))
{
pBrush_->SetOpacity(fOpacity_);
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fStrokeWidth_
hr = Renderer::getID2D1Factory()->CreateStrokeStyle(
D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
nOutlineJoin_,
2.0f,
D2D1_DASH_STYLE_SOLID,
0.0f),
NULL,
0,
&pStrokeStyle
);
}
if (SUCCEEDED(hr))
{
if (bShowOutline_)
{
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fOutlineWidth,
pStrokeStyle
);
}
pBrush_->SetColor(sFillColor_);
@ -230,16 +278,38 @@ STDMETHODIMP CustomTextRenderer::DrawStrikethrough(
);
}
ID2D1StrokeStyle * pStrokeStyle = NULL;
if (SUCCEEDED(hr))
{
pBrush_->SetOpacity(fOpacity_);
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fStrokeWidth_
hr = Renderer::getID2D1Factory()->CreateStrokeStyle(
D2D1::StrokeStyleProperties(
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
D2D1_CAP_STYLE_FLAT,
nOutlineJoin_,
2.0f,
D2D1_DASH_STYLE_SOLID,
0.0f),
NULL,
0,
&pStrokeStyle
);
}
if (SUCCEEDED(hr))
{
if (bShowOutline_)
{
pBrush_->SetColor(sOutlineColor_);
pRT_->DrawGeometry(
pTransformedGeometry,
pBrush_,
fOutlineWidth,
pStrokeStyle
);
}
pBrush_->SetColor(sFillColor_);

View File

@ -3,7 +3,7 @@
e2d::Text::Text()
: m_bWrappingEnable(false)
, m_Font()
, m_TextStyle()
, m_nAlign(TextAlign::LEFT)
, m_fLineSpacing(0.0f)
, m_fWrappingWidth(0.0f)
@ -14,7 +14,7 @@ e2d::Text::Text()
e2d::Text::Text(String text)
: m_bWrappingEnable(false)
, m_Font()
, m_TextStyle()
, m_nAlign(TextAlign::LEFT)
, m_fLineSpacing(0.0f)
, m_fWrappingWidth(0.0f)
@ -25,9 +25,9 @@ e2d::Text::Text(String text)
_reset();
}
e2d::Text::Text(Font font)
e2d::Text::Text(TextStyle textStyle)
: m_bWrappingEnable(false)
, m_Font(font)
, m_TextStyle(textStyle)
, m_nAlign(TextAlign::LEFT)
, m_fLineSpacing(0.0f)
, m_fWrappingWidth(0.0f)
@ -37,9 +37,9 @@ e2d::Text::Text(Font font)
_reset();
}
e2d::Text::Text(String text, Font font)
e2d::Text::Text(String text, TextStyle textStyle)
: m_bWrappingEnable(false)
, m_Font(font)
, m_TextStyle(textStyle)
, m_nAlign(TextAlign::LEFT)
, m_fLineSpacing(0.0f)
, m_fWrappingWidth(0.0f)
@ -50,9 +50,32 @@ e2d::Text::Text(String text, Font font)
_reset();
}
e2d::Text::Text(String text, String fontFamily, double fontSize, UINT32 color, UINT32 fontWeight, bool italic, bool hasUnderline, bool hasStrikethrough)
e2d::Text::Text(
String text,
String fontFamily,
double fontSize,
UINT32 color,
UINT32 fontWeight,
bool italic,
bool hasUnderline,
bool hasStrikethrough,
bool showOutline,
UINT32 outlineColor,
UINT32 outlineWidth
)
: m_bWrappingEnable(false)
, m_Font(Font(fontFamily, fontSize, color, fontWeight, italic, hasUnderline, hasStrikethrough))
, m_TextStyle(
fontFamily,
fontSize,
color,
fontWeight,
italic,
hasUnderline,
hasStrikethrough,
showOutline,
outlineColor,
outlineWidth
)
, m_nAlign(TextAlign::LEFT)
, m_fLineSpacing(0.0f)
, m_fWrappingWidth(0.0f)
@ -74,29 +97,44 @@ e2d::String e2d::Text::getText() const
return m_sText;
}
e2d::Font e2d::Text::getFont() const
e2d::TextStyle e2d::Text::getTextStyle() const
{
return m_Font;
return m_TextStyle;
}
e2d::String e2d::Text::getFontFamily() const
{
return m_Font.fontFamily;
return m_TextStyle.fontFamily;
}
double e2d::Text::getFontSize() const
{
return m_Font.size;
return m_TextStyle.fontSize;
}
UINT32 e2d::Text::getFontWeight() const
{
return m_Font.weight;
return m_TextStyle.weight;
}
UINT32 e2d::Text::getColor() const
{
return m_Font.color;
return m_TextStyle.color;
}
UINT32 e2d::Text::getOutlineColor() const
{
return m_TextStyle.outlineColor;
}
double e2d::Text::getOutlineWidth() const
{
return m_TextStyle.outlineWidth;
}
int e2d::Text::getOutlineJoin() const
{
return m_TextStyle.outlineJoin;
}
int e2d::Text::getLineCount() const
@ -115,7 +153,12 @@ int e2d::Text::getLineCount() const
bool e2d::Text::isItalic() const
{
return m_Font.italic;
return m_TextStyle.italic;
}
bool e2d::Text::isShowOutline() const
{
return m_TextStyle.showOutline;
}
void e2d::Text::setText(String text)
@ -124,38 +167,38 @@ void e2d::Text::setText(String text)
_reset();
}
void e2d::Text::setFont(Font font)
void e2d::Text::setTextStyle(TextStyle textStyle)
{
m_Font = font;
m_TextStyle = textStyle;
_reset();
}
void e2d::Text::setFontFamily(String fontFamily)
{
m_Font.fontFamily = fontFamily;
m_TextStyle.fontFamily = fontFamily;
_reset();
}
void e2d::Text::setFontSize(double fontSize)
{
m_Font.size = static_cast<float>(fontSize);
m_TextStyle.fontSize = static_cast<float>(fontSize);
_reset();
}
void e2d::Text::setFontWeight(UINT32 fontWeight)
void e2d::Text::setFontWeight(UINT32 textStyleWeight)
{
m_Font.weight = fontWeight;
m_TextStyle.weight = textStyleWeight;
_reset();
}
void e2d::Text::setColor(UINT32 color)
{
m_Font.color = color;
m_TextStyle.color = color;
}
void e2d::Text::setItalic(bool value)
{
m_Font.italic = value;
m_TextStyle.italic = value;
_reset();
}
@ -189,9 +232,9 @@ void e2d::Text::setAlignment(int nAlign)
void e2d::Text::setUnderline(bool hasUnderline)
{
if (m_Font.underline != hasUnderline)
if (m_TextStyle.underline != hasUnderline)
{
m_Font.underline = hasUnderline;
m_TextStyle.underline = hasUnderline;
if (!m_pDWriteTextFormat)
_createFormat();
_createLayout();
@ -200,29 +243,53 @@ void e2d::Text::setUnderline(bool hasUnderline)
void e2d::Text::setStrikethrough(bool hasStrikethrough)
{
if (m_Font.strikethrough != hasStrikethrough)
if (m_TextStyle.strikethrough != hasStrikethrough)
{
m_Font.strikethrough = hasStrikethrough;
m_TextStyle.strikethrough = hasStrikethrough;
if (!m_pDWriteTextFormat)
_createFormat();
_createLayout();
}
}
void e2d::Text::showOutline(bool showOutline)
{
m_TextStyle.showOutline = showOutline;
}
void e2d::Text::setOutlineColor(UINT32 outlineColor)
{
m_TextStyle.outlineColor = outlineColor;
}
void e2d::Text::setOutlineWidth(double outlineWidth)
{
m_TextStyle.outlineWidth = outlineWidth;
}
void e2d::Text::setOutlineJoin(int outlineJoin)
{
m_TextStyle.outlineJoin = outlineJoin;
}
void e2d::Text::onRender()
{
// 创建文本区域
D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, m_fWidth, m_fHeight);
// 设置画刷颜色和透明度
Renderer::getSolidColorBrush()->SetColor(D2D1::ColorF(m_Font.color, m_fDisplayOpacity));
// 渲染文字内容
if (m_pDWriteTextLayout)
{
Renderer::getRenderTarget()->DrawTextLayout(
D2D1::Point2F(0, 0),
m_pDWriteTextLayout,
Renderer::getSolidColorBrush()
// 创建文本区域
D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, m_fWidth, m_fHeight);
// 设置画刷颜色和透明度
Renderer::getSolidColorBrush()->SetOpacity(m_fDisplayOpacity);
// 获取文本渲染器
auto pTextRenderer = Renderer::getCustomTextRenderer();
pTextRenderer->SetTextStyle(
D2D1::ColorF(m_TextStyle.color),
m_TextStyle.showOutline,
D2D1::ColorF(m_TextStyle.outlineColor),
static_cast<FLOAT>(m_TextStyle.outlineWidth),
D2D1_LINE_JOIN(m_TextStyle.outlineJoin)
);
m_pDWriteTextLayout->Draw(NULL, pTextRenderer, 0, 0);
}
}
@ -239,12 +306,12 @@ void e2d::Text::_createFormat()
SafeReleaseInterface(&m_pDWriteTextFormat);
HRESULT hr = Renderer::getIDWriteFactory()->CreateTextFormat(
m_Font.fontFamily,
m_TextStyle.fontFamily,
NULL,
DWRITE_FONT_WEIGHT(m_Font.weight),
m_Font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_WEIGHT(m_TextStyle.weight),
m_TextStyle.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
static_cast<float>(m_Font.size),
static_cast<float>(m_TextStyle.fontSize),
L"",
&m_pDWriteTextFormat
);
@ -342,11 +409,11 @@ void e2d::Text::_createLayout()
// Ìí¼ÓÏ»®ÏߺÍɾ³ýÏß
DWRITE_TEXT_RANGE range = { 0, length };
if (m_Font.underline)
if (m_TextStyle.underline)
{
m_pDWriteTextLayout->SetUnderline(true, range);
}
if (m_Font.strikethrough)
if (m_TextStyle.strikethrough)
{
m_pDWriteTextLayout->SetStrikethrough(true, range);
}

View File

@ -413,6 +413,19 @@ public:
};
// ÏßÌõÏཻÑùʽ
class LineJoin
{
public:
enum : int
{
MITER = 0,
BEVEL = 1,
ROUND = 2
};
};
// 形状样式
class ShapeStyle
{
@ -440,27 +453,35 @@ public:
// 文本样式
struct Font
struct TextStyle
{
String fontFamily; // 字体
double size; // ×ÖºÅ
double fontSize; // ×ÖºÅ
UINT32 color; // 颜色
UINT32 weight; // 粗细值
bool italic; // 斜体
bool underline; // 下划线
bool strikethrough; // 删除线
bool showOutline; // ÏÔʾÃè±ß
UINT32 outlineColor; // Ãè±ßÑÕÉ«
double outlineWidth; // Ãè±ßÏß¿í
int outlineJoin; // Ãè±ßÏßÏཻÑùʽ
/* 构造函数 */
Font();
TextStyle();
Font(
TextStyle(
String fontFamily,
double fontSize = 22,
UINT32 color = Color::WHITE,
UINT32 fontWeight = FontWeight::NORMAL,
UINT32 textStyleWeight = FontWeight::NORMAL,
bool italic = false,
bool hasUnderline = false,
bool hasStrikethrough = false
bool hasStrikethrough = false,
bool showOutline = true,
UINT32 outlineColor = Color::BLACK,
UINT32 outlineWidth = 1.0,
int outlineJoin = LineJoin::ROUND
);
};

View File

@ -28,9 +28,10 @@ namespace e2d
STDMETHOD_(void, SetTextStyle)(
CONST D2D1_COLOR_F &fillColor,
BOOL showOutline,
CONST D2D1_COLOR_F &outlineColor,
FLOAT strokeWidth,
FLOAT opacity
FLOAT outlineWidth,
D2D1_LINE_JOIN outlineJoin
);
STDMETHOD(DrawGlyphRun)(
@ -96,8 +97,9 @@ namespace e2d
unsigned long cRefCount_;
D2D1_COLOR_F sFillColor_;
D2D1_COLOR_F sOutlineColor_;
FLOAT fStrokeWidth_;
FLOAT fOpacity_;
FLOAT fOutlineWidth;
BOOL bShowOutline_;
D2D1_LINE_JOIN nOutlineJoin_;
ID2D1Factory* pD2DFactory_;
ID2D1HwndRenderTarget* pRT_;
ID2D1SolidColorBrush* pBrush_;

View File

@ -548,16 +548,16 @@ public:
Text();
Text(
String text /* 文字内容 */
String text /* 文字内容 */
);
Text(
Font font /* 字体样式 */
TextStyle textStyle /* 文字样式 */
);
Text(
String text, /* 文字内容 */
Font font /* 字体样式 */
String text, /* 文字内容 */
TextStyle textStyle /* 文字样式 */
);
Text(
@ -568,7 +568,10 @@ public:
UINT32 fontWeight = FontWeight::NORMAL, /* 粗细值 */
bool italic = false, /* 斜体 */
bool hasUnderline = false, /* 下划线 */
bool hasStrikethrough = false /* 删除线 */
bool hasStrikethrough = false, /* 删除线 */
bool showOutline = true, /* 显示描边 */
UINT32 outlineColor = Color::BLACK, /* 描边颜色 */
UINT32 outlineWidth = 1.0 /* 描边线宽 */
);
virtual ~Text();
@ -577,7 +580,7 @@ public:
String getText() const;
// 获取文本样式
Font getFont() const;
TextStyle getTextStyle() const;
// 获取字体
String getFontFamily() const;
@ -591,20 +594,32 @@ public:
// 获取文字颜色
UINT32 getColor() const;
// 获取描边颜色
UINT32 getOutlineColor() const;
// 获取描边线宽
double getOutlineWidth() const;
// 获取描边线相交样式
int getOutlineJoin() const;
// 获取文本显示行数
int getLineCount() const;
// 是否是斜体
bool isItalic() const;
// 是否显示描边
bool isShowOutline() const;
// 设置文本
void setText(
String text
);
// 设置文本样式
void setFont(
Font pFont
void setTextStyle(
TextStyle pTextStyle
);
// 设置字体
@ -619,7 +634,7 @@ public:
// 设置字体粗细值(默认值为 FontWeight::NORMAL
void setFontWeight(
UINT32 fontWeight
UINT32 textStyleWeight
);
// 设置文字颜色(默认值为 Color::WHITE
@ -657,6 +672,26 @@ public:
bool hasStrikethrough
);
// 设置是否显示描边
void showOutline(
bool showOutline
);
// 设置描边颜色
void setOutlineColor(
UINT32 outlineColor
);
// 设置描边线宽
void setOutlineWidth(
double outlineWidth
);
// 设置描边线相交样式
void setOutlineJoin(
int outlineJoin
);
// 渲染文字
virtual void onRender() override;
@ -674,7 +709,7 @@ protected:
String m_sText;
bool m_bWrappingEnable;
float m_fWrappingWidth;
Font m_Font;
TextStyle m_TextStyle;
float m_fLineSpacing;
int m_nAlign;
IDWriteTextFormat * m_pDWriteTextFormat;

View File

@ -215,7 +215,7 @@
<ClCompile Include="..\..\core\Collider\ColliderCircle.cpp" />
<ClCompile Include="..\..\core\Collider\ColliderEllipse.cpp" />
<ClCompile Include="..\..\core\Collider\ColliderRect.cpp" />
<ClCompile Include="..\..\core\Common\Font.cpp" />
<ClCompile Include="..\..\core\Common\TextStyle.cpp" />
<ClCompile Include="..\..\core\Common\Object.cpp" />
<ClCompile Include="..\..\core\Common\Point.cpp" />
<ClCompile Include="..\..\core\Common\Scene.cpp" />

View File

@ -39,9 +39,6 @@
<ClCompile Include="..\..\core\Base\Input.cpp">
<Filter>Base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\Common\Font.cpp">
<Filter>Common</Filter>
</ClCompile>
<ClCompile Include="..\..\core\Action\Action.cpp">
<Filter>Action</Filter>
</ClCompile>
@ -225,6 +222,9 @@
<ClCompile Include="..\..\core\Custom\CustomTextRenderer.cpp">
<Filter>Custom</Filter>
</ClCompile>
<ClCompile Include="..\..\core\Common\TextStyle.cpp">
<Filter>Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\core\easy2d.h" />