optimize: Text class

This commit is contained in:
Haibo 2018-11-15 14:35:19 +08:00 committed by Nomango
parent 4ce0a470de
commit f2be349841
29 changed files with 393 additions and 349 deletions

View File

@ -88,7 +88,7 @@ namespace easy2d
{
SafeRelease(stroke_style_);
stroke_style_ = devices::Graphics::Instance().GetStrokeStyle(stroke);
stroke_style_ = devices::Graphics::Instance()->GetStrokeStyle(stroke);
if (stroke_style_)
stroke_style_->AddRef();

View File

@ -1,32 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "Font.h"
namespace easy2d
{
Font::Font(const std::wstring & family, float size, unsigned int weight, bool italic)
: family(family)
, size(size)
, weight(weight)
, italic(italic)
{
}
}

View File

@ -48,11 +48,17 @@ namespace easy2d
};
public:
explicit Font(
Font(
const std::wstring& family = L"",
float size = 22,
unsigned int weight = Font::Weight::Normal,
bool italic = false
);
)
: family(family)
, size(size)
, weight(weight)
, italic(italic)
{
}
};
}

View File

@ -61,10 +61,10 @@ namespace easy2d
debug_enabled_ = options.debug;
Window::Instance().Init(options.title, options.width, options.height, options.icon, debug_enabled_);
devices::Graphics::Instance().Init(Window::Instance().GetHandle(), debug_enabled_);
devices::Input::Instance().Init(debug_enabled_);
devices::Audio::Instance().Init(debug_enabled_);
Window::Instance()->Init(options.title, options.width, options.height, options.icon, debug_enabled_);
devices::Graphics::Instance()->Init(Window::Instance()->GetHandle(), debug_enabled_);
devices::Input::Instance()->Init(debug_enabled_);
devices::Audio::Instance()->Init(debug_enabled_);
HWND console = ::GetConsoleWindow();
if (debug_enabled_)
@ -95,7 +95,7 @@ namespace easy2d
}
::SetWindowLongPtrW(
Window::Instance().GetHandle(),
Window::Instance()->GetHandle(),
GWLP_USERDATA,
PtrToUlong(this)
);
@ -114,9 +114,9 @@ namespace easy2d
next_scene_ = nullptr;
}
const auto& window = Window::Instance();
::ShowWindow(window.GetHandle(), SW_SHOWNORMAL);
::UpdateWindow(window.GetHandle());
const auto window = Window::Instance();
::ShowWindow(window->GetHandle(), SW_SHOWNORMAL);
::UpdateWindow(window->GetHandle());
const int64_t min_interval = 5;
auto last = time::Now();
@ -132,10 +132,10 @@ namespace easy2d
const auto dt = now - last;
last = now;
devices::Input::Instance().Update(
window.GetHandle(),
window.GetContentScaleX(),
window.GetContentScaleY()
devices::Input::Instance()->Update(
window->GetHandle(),
window->GetContentScaleX(),
window->GetContentScaleY()
);
UpdateScene(dt);
@ -264,8 +264,8 @@ namespace easy2d
void Game::DrawScene()
{
auto& graphics = devices::Graphics::Instance();
graphics.BeginDraw(Window::Instance().GetHandle());
auto graphics = devices::Graphics::Instance();
graphics->BeginDraw(Window::Instance()->GetHandle());
if (transition_)
{
@ -280,20 +280,20 @@ namespace easy2d
{
if (curr_scene_)
{
graphics.SetTransform(math::Matrix());
graphics.SetBrushOpacity(1.f);
graphics->SetTransform(math::Matrix());
graphics->SetBrushOpacity(1.f);
curr_scene_->DrawBorder();
}
if (next_scene_)
{
graphics.SetTransform(math::Matrix());
graphics.SetBrushOpacity(1.f);
graphics->SetTransform(math::Matrix());
graphics->SetBrushOpacity(1.f);
next_scene_->DrawBorder();
}
graphics.DrawDebugInfo();
graphics->DrawDebugInfo();
}
graphics.EndDraw();
graphics->EndDraw();
}
}

View File

@ -69,7 +69,7 @@ namespace easy2d
bool Image::Load(Resource& res)
{
ID2D1Bitmap* bitmap;
HRESULT hr = devices::Graphics::Instance().CreateBitmapFromResource(res, &bitmap);
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromResource(res, &bitmap);
if (FAILED(hr))
{
logs::Trace(L"Load Image from resource failed!", hr);
@ -95,7 +95,7 @@ namespace easy2d
String image_file_path = image_file.GetPath();
ID2D1Bitmap* bitmap;
HRESULT hr = devices::Graphics::Instance().CreateBitmapFromFile(image_file_path, &bitmap);
HRESULT hr = devices::Graphics::Instance()->CreateBitmapFromFile(image_file_path, &bitmap);
if (FAILED(hr))
{
logs::Trace(L"Load Image from file failed!", hr);

View File

@ -32,19 +32,19 @@ namespace easy2d
float MouseEvent::GetX() const
{
return ((float)(short)LOWORD(l_param_)) * Window::Instance().GetContentScaleX();
return ((float)(short)LOWORD(l_param_)) * Window::Instance()->GetContentScaleX();
}
float MouseEvent::GetY() const
{
return ((float)(short)HIWORD(l_param_)) * Window::Instance().GetContentScaleY();
return ((float)(short)HIWORD(l_param_)) * Window::Instance()->GetContentScaleY();
}
Point MouseEvent::GetPosition() const
{
return Point(
((float)(short)LOWORD(l_param_)) * Window::Instance().GetContentScaleX(),
((float)(short)HIWORD(l_param_)) * Window::Instance().GetContentScaleY()
((float)(short)LOWORD(l_param_)) * Window::Instance()->GetContentScaleX(),
((float)(short)HIWORD(l_param_)) * Window::Instance()->GetContentScaleY()
);
}

View File

@ -87,7 +87,7 @@ namespace easy2d
return false;
}
hr = devices::Audio::Instance().CreateVoice(&voice_, transcoder.GetWaveFormatEx());
hr = devices::Audio::Instance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
if (FAILED(hr))
{
if (wave_data_)
@ -119,7 +119,7 @@ namespace easy2d
return false;
}
hr = devices::Audio::Instance().CreateVoice(&voice_, transcoder.GetWaveFormatEx());
hr = devices::Audio::Instance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
if (FAILED(hr))
{
if (wave_data_)

View File

@ -26,6 +26,18 @@
namespace easy2d
{
namespace
{
float default_pivot_x = 0.f;
float default_pivot_y = 0.f;
}
void Node::SetDefaultPivot(float pivot_x, float pivot_y)
{
default_pivot_x = pivot_x;
default_pivot_y = pivot_y;
}
Node::Node()
: visible_(true)
, parent_(nullptr)
@ -43,6 +55,8 @@ namespace easy2d
, final_matrix_()
, border_color_(Color::Red, 0.6f)
{
transform_.pivot.x = default_pivot_x;
transform_.pivot.y = default_pivot_y;
}
Node::~Node()
@ -55,16 +69,16 @@ namespace easy2d
if (!visible_)
return;
auto& graphics = devices::Graphics::Instance();
auto graphics = devices::Graphics::Instance();
if (clip_enabled_)
{
graphics.PushClip(final_matrix_, transform_.size);
graphics->PushClip(final_matrix_, transform_.size);
}
if (children_.empty())
{
graphics.SetTransform(final_matrix_);
graphics->SetTransform(final_matrix_);
OnDraw();
}
else
@ -96,7 +110,7 @@ namespace easy2d
}
}
graphics.SetTransform(final_matrix_);
graphics->SetTransform(final_matrix_);
OnDraw();
// 访问剩余节点
@ -106,7 +120,7 @@ namespace easy2d
if (clip_enabled_)
{
graphics.PopClip();
graphics->PopClip();
}
}
@ -153,7 +167,7 @@ namespace easy2d
{
if (border_)
{
devices::Graphics::Instance().DrawGeometry(border_, border_color_, 1.f, 1.5f);
devices::Graphics::Instance()->DrawGeometry(border_, border_color_, 1.f, 1.5f);
}
for (const auto& child : children_)
@ -184,7 +198,7 @@ namespace easy2d
// 重新构造轮廓
SafeRelease(border_);
ThrowIfFailed(
devices::Graphics::Instance().CreateRectGeometry(final_matrix_, transform_.size, &border_)
devices::Graphics::Instance()->CreateRectGeometry(final_matrix_, transform_.size, &border_)
);
for (auto& child : children_)

View File

@ -100,10 +100,10 @@ namespace easy2d
// 获取节点纵向缩放比例
float GetScaleY() const;
// 获取节点横向倾斜角度
// 获取节点横向错切角度
float GetSkewX() const;
// 获取节点纵向倾斜角度
// 获取节点纵向错切角度
float GetSkewY() const;
// 获取节点旋转角度
@ -191,19 +191,19 @@ namespace easy2d
float scale
);
// 设置横向倾斜角度
// 设置横向错切角度
// 默认为 0
void SetSkewX(
float skew_x
);
// 设置纵向倾斜角度
// 设置纵向错切角度
// 默认为 0
void SetSkewY(
float skew_y
);
// 设置倾斜角度
// 设置错切角度
// 默认为 (0, 0)
void SetSkew(
float skew_x,
@ -332,6 +332,12 @@ namespace easy2d
// 从父节点移除
void RemoveFromParent();
// 设置默认支点
static void SetDefaultPivot(
float pivot_x,
float pivot_y
);
protected:
virtual void Visit();

View File

@ -81,6 +81,24 @@ namespace easy2d
return (origin == rect.origin) && (size == rect.size);
}
inline Point GetCenter() const { return Point{ origin.x + size.width / 2, origin.y + size.height / 2 }; }
inline Point GetLeftTop() const { return origin; }
inline Point GetRightBottom() const { return Point{ GetRight(), GetBottom() }; }
inline Point GetRightTop() const { return Point{ GetRight(), GetTop() }; }
inline Point GetLeftBottom() const { return Point{ GetLeft(), GetBottom() }; }
inline float GetLeft() const { return origin.x; }
inline float GetTop() const { return origin.y; }
inline float GetRight() const { return origin.x + size.width; }
inline float GetBottom() const { return origin.y + size.height; }
// 判断点是否在矩形内
inline bool ContainsPoint(
const Point& point

View File

@ -27,7 +27,7 @@ namespace easy2d
class ISingleton
{
public:
static inline T& Instance();
static inline T* Instance();
private:
ISingleton() {}
@ -40,12 +40,12 @@ namespace easy2d
};
template<typename T>
inline T & easy2d::ISingleton<T>::Instance()
inline T* easy2d::ISingleton<T>::Instance()
{
static std::unique_ptr<T> instance_;
if (!instance_)
instance_.reset(new (std::nothrow) T);
return *instance_;
return instance_.get();
}
}
@ -60,5 +60,6 @@ namespace easy2d
#endif
#ifndef E2D_DECLARE_SINGLETON_TYPE
#define E2D_DECLARE_SINGLETON_TYPE( type, singleton_type ) using singleton_type = ::easy2d::ISingleton< type >
#define E2D_DECLARE_SINGLETON_TYPE( type, singleton_type ) \
using singleton_type = ::easy2d::ISingleton< type >
#endif

View File

@ -132,7 +132,7 @@ namespace easy2d
if (image_ && image_->GetBitmap())
{
auto crop_pos = image_->GetCropPos();
devices::Graphics::Instance().DrawImage(
devices::Graphics::Instance()->DrawImage(
image_,
GetDisplayOpacity(),
Rect(Point(), GetTransform().size),

View File

@ -24,72 +24,54 @@
namespace easy2d
{
//-------------------------------------------------------
// Style
//-------------------------------------------------------
namespace
{
Font text_default_font;
TextStyle text_default_style;
}
Text::Style::Style()
: color(Color::White)
, alignment(Align::Left)
, wrap(false)
, wrap_width(0.f)
, line_spacing(0.f)
, underline(false)
, strikethrough(false)
, outline(true)
, outline_color(Color(Color::Black, 0.5))
, outline_width(1.f)
, outline_stroke(StrokeStyle::Round)
{}
void easy2d::Text::SetDefaultFont(Font const & font)
{
text_default_font = font;
}
Text::Style::Style(
Color color,
Align alignment,
bool wrap,
float wrap_width,
float line_spacing,
bool underline,
bool strikethrough,
bool outline,
Color outline_color,
float outline_width,
StrokeStyle outline_stroke
)
: color(color)
, alignment(alignment)
, wrap(wrap)
, wrap_width(wrap_width)
, line_spacing(line_spacing)
, underline(underline)
, strikethrough(strikethrough)
, outline(outline)
, outline_color(outline_color)
, outline_width(outline_width)
, outline_stroke(outline_stroke)
{}
//-------------------------------------------------------
// Text
//-------------------------------------------------------
void easy2d::Text::SetDefaultStyle(TextStyle const & style)
{
text_default_style = style;
}
Text::Text()
: font_()
, style_()
: font_(text_default_font)
, style_(text_default_style)
, text_layout_(nullptr)
, text_format_(nullptr)
, dirty_layout_(false)
{
}
Text::Text(const String & text, const Font & font, const Style & style)
Text::Text(const String & text)
: Text(text, text_default_font, text_default_style)
{
}
Text::Text(const String & text, const Font & font)
: Text(text, font, text_default_style)
{
}
Text::Text(const String & text, const TextStyle & style)
: Text(text, text_default_font, style)
{
}
Text::Text(const String & text, const Font & font, const TextStyle & style)
: font_(font)
, style_(style)
, text_(text)
, text_layout_(nullptr)
, text_format_(nullptr)
, text_(text)
, dirty_layout_(true)
{
Reset();
}
Text::~Text()
@ -108,7 +90,7 @@ namespace easy2d
return font_;
}
const Text::Style& Text::GetStyle() const
const TextStyle& Text::GetStyle() const
{
return style_;
}
@ -123,7 +105,7 @@ namespace easy2d
return font_.size;
}
UINT Text::GetFontWeight() const
unsigned int Text::GetFontWeight() const
{
return font_.weight;
}
@ -150,16 +132,30 @@ namespace easy2d
int Text::GetLineCount() const
{
UpdateLayout();
if (text_layout_)
{
DWRITE_TEXT_METRICS metrics;
text_layout_->GetMetrics(&metrics);
return static_cast<int>(metrics.lineCount);
if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
{
return static_cast<int>(metrics.lineCount);
}
}
else
return 0;
}
Rect Text::GetContentBounds() const
{
UpdateLayout();
if (text_layout_)
{
return 0;
DWRITE_TEXT_METRICS metrics;
if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
{
return Rect(0.f, 0.f, metrics.layoutWidth, metrics.height);
}
}
return Rect{};
}
bool Text::IsItalic() const
@ -167,17 +163,17 @@ namespace easy2d
return font_.italic;
}
bool Text::strikethrough() const
bool Text::HasStrikethrough() const
{
return style_.strikethrough;
}
bool Text::underline() const
bool Text::HasUnderline() const
{
return style_.underline;
}
bool Text::outline() const
bool Text::HasOutline() const
{
return style_.outline;
}
@ -185,48 +181,60 @@ namespace easy2d
void Text::SetText(const String& text)
{
text_ = text;
Reset();
dirty_layout_ = true;
}
void Text::SetStyle(const Style& style)
void Text::SetStyle(const TextStyle& style)
{
style_ = style;
Reset();
dirty_layout_ = true;
}
void Text::SetFont(const Font & font)
{
font_ = font;
Reset();
dirty_layout_ = true;
}
void Text::SetFontFamily(const String& family)
{
font_.family = family;
Reset();
if (font_.family != family)
{
font_.family = family;
dirty_layout_ = true;
}
}
void Text::SetFontSize(float size)
{
font_.size = size;
Reset();
if (font_.size != size)
{
font_.size = size;
dirty_layout_ = true;
}
}
void Text::SetFontWeight(UINT weight)
void Text::SetFontWeight(unsigned int weight)
{
font_.weight = weight;
Reset();
if (font_.weight != weight)
{
font_.weight = weight;
dirty_layout_ = true;
}
}
void Text::SetColor(Color color)
void Text::SetColor(Color const& color)
{
style_.color = color;
}
void Text::SetItalic(bool val)
{
font_.italic = val;
Reset();
if (font_.italic != val)
{
font_.italic = val;
dirty_layout_ = true;
}
}
void Text::SetWrapEnabled(bool wrap)
@ -234,7 +242,7 @@ namespace easy2d
if (style_.wrap != wrap)
{
style_.wrap = wrap;
Reset();
dirty_layout_ = true;
}
}
@ -243,11 +251,7 @@ namespace easy2d
if (style_.wrap_width != wrap_width)
{
style_.wrap_width = std::max(wrap_width, 0.f);
if (style_.wrap)
{
Reset();
}
dirty_layout_ = true;
}
}
@ -256,16 +260,16 @@ namespace easy2d
if (style_.line_spacing != line_spacing)
{
style_.line_spacing = line_spacing;
Reset();
dirty_layout_ = true;
}
}
void Text::SetAlignment(Align align)
void Text::SetAlignment(TextAlign align)
{
if (style_.alignment != align)
{
style_.alignment = align;
Reset();
dirty_layout_ = true;
}
}
@ -274,9 +278,7 @@ namespace easy2d
if (style_.underline != underline)
{
style_.underline = underline;
if (!text_format_)
CreateFormat();
CreateLayout();
dirty_layout_ = true;
}
}
@ -285,9 +287,7 @@ namespace easy2d
if (style_.strikethrough != strikethrough)
{
style_.strikethrough = strikethrough;
if (!text_format_)
CreateFormat();
CreateLayout();
dirty_layout_ = true;
}
}
@ -296,7 +296,7 @@ namespace easy2d
style_.outline = outline;
}
void Text::SetOutlineColor(Color outline_color)
void Text::SetOutlineColor(Color const&outline_color)
{
style_.outline_color = outline_color;
}
@ -313,47 +313,43 @@ namespace easy2d
void Text::OnDraw() const
{
UpdateLayout();
if (text_layout_)
{
// 创建文本区域
D2D1_RECT_F textLayoutRect = D2D1::RectF(0, 0, GetTransform().size.width, GetTransform().size.height);
// 设置画刷颜色和透明度
devices::Graphics::Instance().SetBrushOpacity(GetDisplayOpacity());
// 获取文本渲染器
devices::Graphics::Instance().SetTextStyle(
auto graphics = devices::Graphics::Instance();
graphics->SetBrushOpacity(GetDisplayOpacity());
graphics->SetTextStyle(
style_.color,
style_.outline,
style_.outline_color,
style_.outline_width,
style_.outline_stroke
);
devices::Graphics::Instance().DrawTextLayout(text_layout_);
graphics->DrawTextLayout(text_layout_);
}
}
void Text::Reset()
void Text::UpdateLayout() const
{
// 创建文字格式化
CreateFormat();
// 创建文字布局
CreateLayout();
}
if (!dirty_layout_)
return;
void Text::CreateFormat()
{
SafeRelease(text_format_);
SafeRelease(text_layout_);
if (text_.empty())
return;
auto graphics = devices::Graphics::Instance();
ThrowIfFailed(
devices::Graphics::Instance().CreateTextFormat(
graphics->CreateTextFormat(
&text_format_,
font_
)
);
// 设置文字对齐方式
text_format_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style_.alignment));
// 设置行间距
if (style_.line_spacing == 0.f)
{
text_format_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
@ -366,57 +362,24 @@ namespace easy2d
style_.line_spacing * 0.8f
);
}
text_format_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style_.alignment));
text_format_->SetWordWrapping(style_.wrap ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
// 打开文本自动换行时,设置换行属性
if (style_.wrap)
{
text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_WRAP);
}
else
{
text_format_->SetWordWrapping(DWRITE_WORD_WRAPPING_NO_WRAP);
}
}
void Text::CreateLayout()
{
SafeRelease(text_layout_);
// 文本为空字符串时,重置属性
if (text_.empty())
{
this->SetSize(0, 0);
return;
}
if (text_format_ == nullptr)
{
E2D_WARNING("Text::CreateLayout failed! text_format_ NULL pointer exception.");
return;
}
// 对文本自动换行情况下进行处理
if (style_.wrap)
{
ThrowIfFailed(
devices::Graphics::Instance().CreateTextLayout(
graphics->CreateTextLayout(
&text_layout_,
text_,
text_format_,
style_.wrap_width
)
);
// 获取文本布局的宽度和高度
DWRITE_TEXT_METRICS metrics;
text_layout_->GetMetrics(&metrics);
// 重设文本宽高
this->SetSize(metrics.layoutWidth, metrics.height);
}
else
{
// 为防止文本对齐问题,根据先创建 layout 以获取宽度
ThrowIfFailed(
devices::Graphics::Instance().CreateTextLayout(
graphics->CreateTextLayout(
&text_layout_,
text_,
text_format_,
@ -424,25 +387,20 @@ namespace easy2d
)
);
// 获取文本布局的宽度和高度
DWRITE_TEXT_METRICS metrics;
text_layout_->GetMetrics(&metrics);
// 重设文本宽高
this->SetSize(metrics.width, metrics.height);
// 重新创建 layout
SafeRelease(text_layout_);
ThrowIfFailed(
devices::Graphics::Instance().CreateTextLayout(
graphics->CreateTextLayout(
&text_layout_,
text_,
text_format_,
GetTransform().size.width
metrics.width
)
);
}
// 添加下划线和删除线
DWRITE_TEXT_RANGE range = { 0, static_cast<UINT32>(text_.length()) };
if (style_.underline)
{
@ -452,5 +410,7 @@ namespace easy2d
{
text_layout_->SetStrikethrough(true, range);
}
dirty_layout_ = false;
}
}

View File

@ -20,7 +20,8 @@
#pragma once
#include "Node.h"
#include "Font.h"
#include "Font.hpp"
#include "TextStyle.hpp"
namespace easy2d
{
@ -30,56 +31,27 @@ namespace easy2d
{
E2D_DISABLE_COPY(Text);
public:
// 文本对齐方式
enum class Align
{
Left, /* 左对齐 */
Right, /* 右对齐 */
Center /* 居中对齐 */
};
// 文本样式
class Style
{
public:
Color color; // 颜色
Align alignment; // 对齐方式
bool wrap; // 打开自动换行
float wrap_width; // 自动换行宽度
float line_spacing; // 行间距
bool underline; // 下划线
bool strikethrough; // 删除线
bool outline; // 显示描边
Color outline_color; // 描边颜色
float outline_width; // 描边线宽
StrokeStyle outline_stroke; // 描边线相交样式
public:
Style();
Style(
Color color,
Align alignment = Align::Left,
bool wrap = false,
float wrap_width = 0.f,
float line_spacing = 0.f,
bool underline = false,
bool strikethrough = false,
bool outline = true,
Color outline_color = Color(Color::Black, 0.5),
float outline_width = 1.f,
StrokeStyle outline_stroke = StrokeStyle::Round
);
};
public:
Text();
explicit Text(
const String& text, /* 文字内容 */
const Font& font = Font(), /* 字体 */
const Style& style = Style() /* 文本样式 */
const String& text /* 文字内容 */
);
explicit Text(
const String& text, /* 文字内容 */
const Font& font /* 字体 */
);
explicit Text(
const String& text, /* 文字内容 */
const TextStyle& style /* 文本样式 */
);
explicit Text(
const String& text, /* 文字内容 */
const Font& font, /* 字体 */
const TextStyle& style /* 文本样式 */
);
virtual ~Text();
@ -91,7 +63,7 @@ namespace easy2d
const Font& GetFont() const;
// 获取文本样式
const Style& GetStyle() const;
const TextStyle& GetStyle() const;
// 获取字体族
const String& GetFontFamily() const;
@ -100,7 +72,7 @@ namespace easy2d
float GetFontSize() const;
// 获取当前字体粗细值
UINT GetFontWeight() const;
unsigned int GetFontWeight() const;
// 获取文字颜色
const Color& GetColor() const;
@ -117,17 +89,20 @@ namespace easy2d
// 获取文本显示行数
int GetLineCount() const;
// 获取文字包围盒
Rect GetContentBounds() const;
// 是否是斜体
bool IsItalic() const;
// 是否显示删除线
bool strikethrough() const;
bool HasStrikethrough() const;
// 是否显示下划线
bool underline() const;
bool HasUnderline() const;
// 是否显示描边
bool outline() const;
bool HasOutline() const;
// 设置文本
void SetText(
@ -136,7 +111,7 @@ namespace easy2d
// 设置文本样式
void SetStyle(
const Style& style
const TextStyle& style
);
// 设置字体
@ -156,12 +131,12 @@ namespace easy2d
// 设置字体粗细值(默认值为 Text::Font::Weight::Normal
void SetFontWeight(
UINT weight
unsigned int weight
);
// 设置文字颜色(默认值为 Color::WHITE
void SetColor(
Color color
Color const& color
);
// 设置文字斜体(默认值为 false
@ -184,9 +159,9 @@ namespace easy2d
float line_spacing
);
// 设置对齐方式(默认为 Align::Left
// 设置对齐方式(默认为 TextAlign::Left
void SetAlignment(
Align align
TextAlign align
);
// 设置下划线(默认值为 false
@ -206,7 +181,7 @@ namespace easy2d
// 设置描边颜色
void SetOutlineColor(
Color outline_color
Color const& outline_color
);
// 设置描边线宽
@ -219,24 +194,28 @@ namespace easy2d
StrokeStyle outline_stroke
);
// 设置默认字体
static void SetDefaultFont(
Font const& font
);
// 设置默认文字样式
static void SetDefaultStyle(
TextStyle const& style
);
// 渲染文字
virtual void OnDraw() const override;
private:
// 重新排版文字
void Reset();
// 创建文字格式化
void CreateFormat();
// 创建文字布局
void CreateLayout();
void UpdateLayout() const;
private:
String text_;
Font font_;
Style style_;
IDWriteTextFormat* text_format_;
IDWriteTextLayout* text_layout_;
Font font_;
TextStyle style_;
mutable bool dirty_layout_;
mutable IDWriteTextFormat* text_format_;
mutable IDWriteTextLayout* text_layout_;
};
}

View File

@ -73,7 +73,7 @@ namespace easy2d
bShowOutline_ = outline;
sOutlineColor_ = outline_color;
fOutlineWidth = 2 * outline_width;
pCurrStrokeStyle_ = devices::Graphics::Instance().GetStrokeStyle(StrokeStyle(outlineJoin));
pCurrStrokeStyle_ = devices::Graphics::Instance()->GetStrokeStyle(StrokeStyle(outlineJoin));
}
STDMETHODIMP ITextRenderer::DrawGlyphRun(

91
core/base/TextStyle.hpp Normal file
View File

@ -0,0 +1,91 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#pragma once
#include "base.h"
namespace easy2d
{
// 文本对齐方式
enum class TextAlign
{
Left, /* 左对齐 */
Right, /* 右对齐 */
Center /* 居中对齐 */
};
// 文本样式
class TextStyle
{
public:
Color color; // 颜色
TextAlign alignment; // 对齐方式
bool wrap; // 打开自动换行
float wrap_width; // 自动换行宽度
float line_spacing; // 行间距
bool underline; // 下划线
bool strikethrough; // 删除线
bool outline; // 显示描边
Color outline_color; // 描边颜色
float outline_width; // 描边线宽
StrokeStyle outline_stroke; // 描边线相交样式
public:
TextStyle()
: color(Color::White)
, alignment(TextAlign::Left)
, wrap(false)
, wrap_width(0.f)
, line_spacing(0.f)
, underline(false)
, strikethrough(false)
, outline(true)
, outline_color(Color(Color::Black, 0.5))
, outline_width(1.f)
, outline_stroke(StrokeStyle::Round)
{}
TextStyle(
Color color,
TextAlign alignment = TextAlign::Left,
bool wrap = false,
float wrap_width = 0.f,
float line_spacing = 0.f,
bool underline = false,
bool strikethrough = false,
bool outline = true,
Color outline_color = Color(Color::Black, 0.5),
float outline_width = 1.f,
StrokeStyle outline_stroke = StrokeStyle::Round
)
: color(color)
, alignment(alignment)
, wrap(wrap)
, wrap_width(wrap_width)
, line_spacing(line_spacing)
, underline(underline)
, strikethrough(strikethrough)
, outline(outline)
, outline_color(outline_color)
, outline_width(outline_width)
, outline_stroke(outline_stroke)
{}
};
}

View File

@ -67,18 +67,18 @@ namespace easy2d
if (in_scene_)
{
ThrowIfFailed(
devices::Graphics::Instance().CreateLayer(&in_layer_)
devices::Graphics::Instance()->CreateLayer(&in_layer_)
);
}
if (out_scene_)
{
ThrowIfFailed(
devices::Graphics::Instance().CreateLayer(&out_layer_)
devices::Graphics::Instance()->CreateLayer(&out_layer_)
);
}
window_size_ = Window::Instance().GetSize();
window_size_ = Window::Instance()->GetSize();
out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f };
}
@ -102,34 +102,34 @@ namespace easy2d
void Transition::Draw()
{
auto& graphics = devices::Graphics::Instance();
auto graphics = devices::Graphics::Instance();
if (out_scene_)
{
graphics.PushClip(
graphics->PushClip(
out_scene_->GetTransform().ToMatrix(),
window_size_
);
graphics.PushLayer(out_layer_, out_layer_prop_);
graphics->PushLayer(out_layer_, out_layer_prop_);
out_scene_->Visit();
graphics.PopLayer();
graphics.PopClip();
graphics->PopLayer();
graphics->PopClip();
}
if (in_scene_)
{
graphics.PushClip(
graphics->PushClip(
in_scene_->GetTransform().ToMatrix(),
window_size_
);
graphics.PushLayer(in_layer_, in_layer_prop_);
graphics->PushLayer(in_layer_, in_layer_prop_);
in_scene_->Visit();
graphics.PopLayer();
graphics.PopClip();
graphics->PopLayer();
graphics->PopClip();
}
}

View File

@ -45,7 +45,7 @@ namespace easy2d
{
Destroy();
devices::Audio::Instance().DeleteVoice(this);
devices::Audio::Instance()->DeleteVoice(this);
}
HRESULT Voice::Play(const BYTE * wave_data, UINT32 data_size, UINT32 loop_count)

View File

@ -21,7 +21,7 @@
#pragma once
#include "base.h"
#include "Singleton.hpp"
#include "Font.h"
#include "Font.hpp"
#include "Resource.h"
#include "TextRenderer.h"
#include "../math/Matrix.hpp"

View File

@ -308,7 +308,7 @@ namespace easy2d
// 如果程序接收到一个 WM_SIZE 消息,这个方法将调整渲染
// 目标的大小。它可能会调用失败,但是这里可以忽略有可能的
// 错误,因为这个错误将在下一次调用 EndDraw 时产生
devices::Graphics::Instance().Resize(width, height);
devices::Graphics::Instance()->Resize(width, height);
}
break;

View File

@ -42,7 +42,8 @@
#include "base/Size.h"
#include "base/Rect.hpp"
#include "base/Font.h"
#include "base/Font.hpp"
#include "base/TextStyle.hpp"
#include "base/Color.h"
#include "base/Resource.h"

View File

@ -227,7 +227,7 @@ namespace easy2d
if (IsVisible() &&
!enabled_ &&
normal_ &&
normal_->ContainsPoint(devices::Input::Instance().GetMousePos()))
normal_->ContainsPoint(devices::Input::Instance()->GetMousePos()))
{
HCURSOR hcursor = ::LoadCursor(nullptr, IDC_NO);
if (hcursor)

View File

@ -62,7 +62,7 @@ namespace easy2d
{
// 设置数据的保存路径
String local_app_data_path = Path::GetLocalAppDataPath();
String title = Window::Instance().GetTitle();
String title = Window::Instance()->GetTitle();
String folder_name = std::to_wstring(std::hash<String>{}(title));
if (!local_app_data_path.empty())
@ -90,7 +90,7 @@ namespace easy2d
{
// 设置临时文件保存路径
wchar_t path[_MAX_PATH];
String title = Window::Instance().GetTitle();
String title = Window::Instance()->GetTitle();
String folder_name = std::to_wstring(std::hash<String>{}(title));
if (0 != ::GetTempPath(_MAX_PATH, path))

View File

@ -30,7 +30,7 @@
<ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" />
<ClInclude Include="..\..\core\base\Font.h" />
<ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" />
@ -54,6 +54,7 @@
<ClInclude Include="..\..\core\base\TaskManager.h" />
<ClInclude Include="..\..\core\base\Text.h" />
<ClInclude Include="..\..\core\base\TextRenderer.h" />
<ClInclude Include="..\..\core\base\TextStyle.hpp" />
<ClInclude Include="..\..\core\base\time.h" />
<ClInclude Include="..\..\core\base\Transition.h" />
<ClInclude Include="..\..\core\base\window.h" />
@ -80,7 +81,6 @@
<ClCompile Include="..\..\core\base\CallFunc.cpp" />
<ClCompile Include="..\..\core\base\Canvas.cpp" />
<ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Font.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" />

View File

@ -29,9 +29,6 @@
<ClInclude Include="..\..\core\base\Color.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Font.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Game.h">
<Filter>base</Filter>
</ClInclude>
@ -152,6 +149,12 @@
<ClInclude Include="..\..\core\math\Transform.hpp">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\TextStyle.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Font.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="base">
@ -189,9 +192,6 @@
<ClCompile Include="..\..\core\base\Color.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Font.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Game.cpp">
<Filter>base</Filter>
</ClCompile>

View File

@ -30,7 +30,7 @@
<ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" />
<ClInclude Include="..\..\core\base\Font.h" />
<ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" />
@ -54,6 +54,7 @@
<ClInclude Include="..\..\core\base\TaskManager.h" />
<ClInclude Include="..\..\core\base\Text.h" />
<ClInclude Include="..\..\core\base\TextRenderer.h" />
<ClInclude Include="..\..\core\base\TextStyle.hpp" />
<ClInclude Include="..\..\core\base\time.h" />
<ClInclude Include="..\..\core\base\Transition.h" />
<ClInclude Include="..\..\core\base\window.h" />
@ -80,7 +81,6 @@
<ClCompile Include="..\..\core\base\CallFunc.cpp" />
<ClCompile Include="..\..\core\base\Canvas.cpp" />
<ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Font.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" />

View File

@ -29,9 +29,6 @@
<ClInclude Include="..\..\core\base\Color.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Font.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Game.h">
<Filter>base</Filter>
</ClInclude>
@ -152,6 +149,12 @@
<ClInclude Include="..\..\core\math\Transform.hpp">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\TextStyle.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Font.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="base">
@ -189,9 +192,6 @@
<ClCompile Include="..\..\core\base\Color.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Font.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Game.cpp">
<Filter>base</Filter>
</ClCompile>

View File

@ -30,7 +30,7 @@
<ClInclude Include="..\..\core\base\CallFunc.h" />
<ClInclude Include="..\..\core\base\Canvas.h" />
<ClInclude Include="..\..\core\base\Color.h" />
<ClInclude Include="..\..\core\base\Font.h" />
<ClInclude Include="..\..\core\base\Font.hpp" />
<ClInclude Include="..\..\core\base\Game.h" />
<ClInclude Include="..\..\core\base\Image.h" />
<ClInclude Include="..\..\core\base\Input.h" />
@ -54,6 +54,7 @@
<ClInclude Include="..\..\core\base\TaskManager.h" />
<ClInclude Include="..\..\core\base\Text.h" />
<ClInclude Include="..\..\core\base\TextRenderer.h" />
<ClInclude Include="..\..\core\base\TextStyle.hpp" />
<ClInclude Include="..\..\core\base\time.h" />
<ClInclude Include="..\..\core\base\Transition.h" />
<ClInclude Include="..\..\core\base\window.h" />
@ -80,7 +81,6 @@
<ClCompile Include="..\..\core\base\CallFunc.cpp" />
<ClCompile Include="..\..\core\base\Canvas.cpp" />
<ClCompile Include="..\..\core\base\Color.cpp" />
<ClCompile Include="..\..\core\base\Font.cpp" />
<ClCompile Include="..\..\core\base\Game.cpp" />
<ClCompile Include="..\..\core\base\Image.cpp" />
<ClCompile Include="..\..\core\base\Input.cpp" />

View File

@ -29,9 +29,6 @@
<ClInclude Include="..\..\core\base\Color.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Font.h">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Game.h">
<Filter>base</Filter>
</ClInclude>
@ -152,6 +149,12 @@
<ClInclude Include="..\..\core\math\Transform.hpp">
<Filter>math</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\TextStyle.hpp">
<Filter>base</Filter>
</ClInclude>
<ClInclude Include="..\..\core\base\Font.hpp">
<Filter>base</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="base">
@ -189,9 +192,6 @@
<ClCompile Include="..\..\core\base\Color.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Font.cpp">
<Filter>base</Filter>
</ClCompile>
<ClCompile Include="..\..\core\base\Game.cpp">
<Filter>base</Filter>
</ClCompile>