diff --git a/projects/kiwano/kiwano.vcxproj b/projects/kiwano/kiwano.vcxproj
index a04930cd..2fbffc54 100644
--- a/projects/kiwano/kiwano.vcxproj
+++ b/projects/kiwano/kiwano.vcxproj
@@ -28,7 +28,6 @@
-
@@ -61,10 +60,10 @@
-
+
@@ -126,7 +125,6 @@
-
diff --git a/projects/kiwano/kiwano.vcxproj.filters b/projects/kiwano/kiwano.vcxproj.filters
index 95f0f48c..e008fce2 100644
--- a/projects/kiwano/kiwano.vcxproj.filters
+++ b/projects/kiwano/kiwano.vcxproj.filters
@@ -48,9 +48,6 @@
2d
-
- 2d
-
2d
@@ -201,9 +198,6 @@
renderer
-
- renderer
-
2d
@@ -270,6 +264,9 @@
core
+
+ renderer
+
@@ -407,9 +404,6 @@
renderer
-
- renderer
-
2d
diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp
index 2cdeddcf..fa30f137 100644
--- a/src/kiwano/2d/Canvas.cpp
+++ b/src/kiwano/2d/Canvas.cpp
@@ -58,7 +58,7 @@ namespace kiwano
PrepareRender(rt);
Rect bitmap_rect(0.f, 0.f, texture_cached_->GetWidth(), texture_cached_->GetHeight());
- rt->DrawTexture(texture_cached_, bitmap_rect, bitmap_rect);
+ rt->DrawTexture(*texture_cached_, bitmap_rect, bitmap_rect);
}
}
@@ -82,11 +82,6 @@ namespace kiwano
stroke_style_ = stroke_style;
}
- void Canvas::SetTextFont(Font const& font)
- {
- text_font_ = font;
- }
-
void Canvas::SetTextStyle(TextStyle const & text_style)
{
text_style_ = text_style;
@@ -249,7 +244,7 @@ namespace kiwano
{
if (texture)
{
- rt_.DrawTexture(texture, src_rect, dest_rect);
+ rt_.DrawTexture(*texture, src_rect, dest_rect);
cache_expired_ = true;
}
}
@@ -259,7 +254,9 @@ namespace kiwano
if (text.empty())
return;
- TextLayout layout(text, text_font_, text_style_);
+ TextLayout layout;
+ layout.SetStyle(text_style_);
+ layout.SetText(text);
DrawTextLayout(layout, point);
}
diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h
index c9d1f39b..447a5013 100644
--- a/src/kiwano/2d/Canvas.h
+++ b/src/kiwano/2d/Canvas.h
@@ -198,11 +198,6 @@ namespace kiwano
/// @param stroke_style 轮廓样式
void SetStrokeStyle(StrokeStyle stroke_style);
- /// \~chinese
- /// @brief 设置文字字体
- /// @param font 文字字体
- void SetTextFont(Font const& font);
-
/// \~chinese
/// @brief 设置文字画刷样式
/// @param text_style 文字画刷样式
@@ -270,7 +265,6 @@ namespace kiwano
float stroke_width_;
Color fill_color_;
Color stroke_color_;
- Font text_font_;
TextStyle text_style_;
StrokeStyle stroke_style_;
GeometrySink geo_sink_;
diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp
index f740c0d5..893dbc1c 100644
--- a/src/kiwano/2d/DebugActor.cpp
+++ b/src/kiwano/2d/DebugActor.cpp
@@ -20,6 +20,7 @@
#include
#include
+#include
#include
#pragma comment(lib, "psapi.lib")
@@ -57,13 +58,10 @@ namespace kiwano
debug_text_->SetPosition(Point{ 10, 10 });
this->AddChild(debug_text_);
- Font font;
- font.family = L"Arial";
- font.size = 16.f;
- font.weight = FontWeight::Normal;
- debug_text_->SetFont(font);
-
TextStyle style;
+ style.font_family = L"Arial";
+ style.font_size = 16.f;
+ style.font_weight = FontWeight::Normal;
style.line_spacing = 20.f;
debug_text_->SetStyle(style);
diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp
index a500db01..69657b73 100644
--- a/src/kiwano/2d/GifSprite.cpp
+++ b/src/kiwano/2d/GifSprite.cpp
@@ -89,11 +89,11 @@ namespace kiwano
void GifSprite::OnRender(RenderTarget* rt)
{
- if (frame_.raw && frame_.raw->IsValid() && CheckVisibilty(rt))
+ if (frame_to_render_ && CheckVisibilty(rt))
{
PrepareRender(rt);
- rt->DrawTexture(frame_.raw, &frame_.rect, nullptr);
+ rt->DrawTexture(*frame_to_render_, &frame_.rect, nullptr);
}
}
@@ -188,13 +188,16 @@ namespace kiwano
loop_count_++;
}
- frame_rt_.DrawTexture(frame_.raw, nullptr, &frame_.rect);
+ if (frame_.raw)
+ {
+ frame_rt_.DrawTexture(*frame_.raw, nullptr, &frame_.rect);
+ }
+
frame_rt_.EndDraw();
- TexturePtr frame_to_render = frame_rt_.GetOutput();
- if (frame_to_render)
+ frame_to_render_ = frame_rt_.GetOutput();
+ if (frame_to_render_)
{
- frame_.raw = frame_to_render;
next_index_ = (++next_index_) % gif_->GetFramesCount();
}
}
diff --git a/src/kiwano/2d/GifSprite.h b/src/kiwano/2d/GifSprite.h
index ce70b01f..611473c9 100644
--- a/src/kiwano/2d/GifSprite.h
+++ b/src/kiwano/2d/GifSprite.h
@@ -161,6 +161,7 @@ namespace kiwano
GifImagePtr gif_;
GifImage::Frame frame_;
TexturePtr saved_frame_;
+ TexturePtr frame_to_render_;
TextureRenderTarget frame_rt_;
};
diff --git a/src/kiwano/2d/Sprite.cpp b/src/kiwano/2d/Sprite.cpp
index 319b2a92..d5ff9e8b 100644
--- a/src/kiwano/2d/Sprite.cpp
+++ b/src/kiwano/2d/Sprite.cpp
@@ -108,7 +108,7 @@ namespace kiwano
{
PrepareRender(rt);
- rt->DrawTexture(frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds());
+ rt->DrawTexture(*frame_->GetTexture(), &frame_->GetCropRect(), &GetBounds());
}
}
}
diff --git a/src/kiwano/2d/TextActor.cpp b/src/kiwano/2d/TextActor.cpp
index b1a1ed93..96f49c0e 100644
--- a/src/kiwano/2d/TextActor.cpp
+++ b/src/kiwano/2d/TextActor.cpp
@@ -26,186 +26,39 @@ namespace kiwano
{
namespace
{
- Font text_default_font;
TextStyle text_default_style;
}
- void kiwano::TextActor::SetDefaultFont(Font const & font)
- {
- text_default_font = font;
- }
-
- void kiwano::TextActor::SetDefaultStyle(TextStyle const & style)
+ void TextActor::SetDefaultStyle(TextStyle const & style)
{
text_default_style = style;
}
TextActor::TextActor()
- : font_(text_default_font)
- , layout_dirty_(false)
- , format_dirty_(false)
+ : TextActor(String())
{
- text_layout_.SetTextStyle(text_default_style);
}
TextActor::TextActor(String const& text)
- : TextActor(text, text_default_font, text_default_style)
- {
- }
-
- TextActor::TextActor(String const& text, const Font & font)
- : TextActor(text, font, text_default_style)
+ : TextActor(text, text_default_style)
{
}
TextActor::TextActor(String const& text, const TextStyle & style)
- : TextActor(text, text_default_font, style)
{
- }
-
- TextActor::TextActor(String const& text, const Font & font, const TextStyle & style)
- : font_(font)
- , text_(text)
- , layout_dirty_(true)
- , format_dirty_(true)
- {
- text_layout_.SetTextStyle(style);
+ SetText(text);
+ SetStyle(style);
}
TextActor::~TextActor()
{
}
- void TextActor::SetText(String const& text)
- {
- text_ = text;
- layout_dirty_ = true;
- }
-
- void TextActor::SetStyle(const TextStyle& style)
- {
- text_layout_.SetTextStyle(style);
- layout_dirty_ = true;
- }
-
- void TextActor::SetFont(const Font & font)
- {
- font_ = font;
- format_dirty_ = true;
- }
-
- void TextActor::SetFontFamily(String const& family)
- {
- if (font_.family != family)
- {
- font_.family = family;
- format_dirty_ = true;
- }
- }
-
- void TextActor::SetFontSize(float size)
- {
- if (font_.size != size)
- {
- font_.size = size;
- format_dirty_ = true;
- }
- }
-
- void TextActor::SetFontWeight(uint32_t weight)
- {
- if (font_.weight != weight)
- {
- font_.weight = weight;
- format_dirty_ = true;
- }
- }
-
- void TextActor::SetItalic(bool italic)
- {
- if (font_.italic != italic)
- {
- font_.italic = italic;
- format_dirty_ = true;
- }
- }
-
- void TextActor::SetWrapWidth(float wrap_width)
- {
- if (text_layout_.GetTextStyle().wrap_width != wrap_width)
- {
- text_layout_.GetTextStyle().wrap_width = wrap_width;
- layout_dirty_ = true;
- }
- }
-
- void TextActor::SetLineSpacing(float line_spacing)
- {
- if (text_layout_.GetTextStyle().line_spacing != line_spacing)
- {
- text_layout_.GetTextStyle().line_spacing = line_spacing;
- layout_dirty_ = true;
- }
- }
-
- void TextActor::SetAlignment(TextAlign align)
- {
- if (text_layout_.GetTextStyle().alignment != align)
- {
- text_layout_.GetTextStyle().alignment = align;
- layout_dirty_ = true;
- }
- }
-
- void TextActor::SetUnderline(bool underline)
- {
- if (text_layout_.GetTextStyle().underline != underline)
- {
- text_layout_.GetTextStyle().underline = underline;
- layout_dirty_ = true;
- }
- }
-
- void TextActor::SetStrikethrough(bool strikethrough)
- {
- if (text_layout_.GetTextStyle().strikethrough != strikethrough)
- {
- text_layout_.GetTextStyle().strikethrough = strikethrough;
- layout_dirty_ = true;
- }
- }
-
- void TextActor::SetColor(Color const& color)
- {
- text_layout_.GetTextStyle().color = color;
- text_layout_.GetTextStyle().color = color;
- }
-
- void TextActor::SetOutline(bool outline)
- {
- text_layout_.GetTextStyle().outline = outline;
- }
-
- void TextActor::SetOutlineColor(Color const&outline_color)
- {
- text_layout_.GetTextStyle().outline_color = outline_color;
- }
-
- void TextActor::SetOutlineWidth(float outline_width)
- {
- text_layout_.GetTextStyle().outline_width = outline_width;
- }
-
- void TextActor::SetOutlineStroke(StrokeStyle outline_stroke)
- {
- text_layout_.GetTextStyle().outline_stroke = outline_stroke;
- }
-
void TextActor::OnRender(RenderTarget* rt)
{
UpdateLayout();
- if (text_layout_ && CheckVisibilty(rt))
+ if (text_layout_.IsValid() && CheckVisibilty(rt))
{
PrepareRender(rt);
rt->DrawTextLayout(text_layout_);
@@ -214,16 +67,9 @@ namespace kiwano
void TextActor::UpdateLayout()
{
- if (format_dirty_)
+ if (text_layout_.IsDirty())
{
- format_dirty_ = false;
- text_layout_.UpdateFont(font_);
- }
-
- if (layout_dirty_)
- {
- layout_dirty_ = false;
- text_layout_.UpdateLayout(text_);
+ text_layout_.Update();
SetSize(text_layout_.GetLayoutSize());
}
}
diff --git a/src/kiwano/2d/TextActor.h b/src/kiwano/2d/TextActor.h
index 778c6e89..11e701f6 100644
--- a/src/kiwano/2d/TextActor.h
+++ b/src/kiwano/2d/TextActor.h
@@ -45,46 +45,33 @@ namespace kiwano
TextActor();
/// \~chinese
- /// @brief 构建空的文本角色
+ /// @brief 构建文本角色
/// @param text 文字内容
explicit TextActor(const String& text);
/// \~chinese
- /// @brief 构建空的文本角色
- /// @param text 文字内容
- /// @param font 字体
- TextActor(const String& text, const Font& font);
-
- /// \~chinese
- /// @brief 构建空的文本角色
+ /// @brief 构建文本角色
/// @param text 文字内容
/// @param style 文本样式
TextActor(const String& text, const TextStyle& style);
- /// \~chinese
- /// @brief 构建空的文本角色
- /// @param text 文字内容
- /// @param font 字体
- /// @param style 文本样式
- TextActor(const String& text, const Font& font, const TextStyle& style);
-
virtual ~TextActor();
/// \~chinese
/// @brief 获取文本
- String const& GetText() const;
-
- /// \~chinese
- /// @brief 获取字体
- Font GetFont() const;
+ const String& GetText() const;
/// \~chinese
/// @brief 获取文本样式
- TextStyle GetStyle() const;
+ const TextStyle& GetStyle() const;
/// \~chinese
/// @brief 获取文本布局
- TextLayout GetLayout() const;
+ const TextLayout& GetLayout() const;
+
+ /// \~chinese
+ /// @brief 获取字体
+ FontPtr GetFont() const;
/// \~chinese
/// @brief 设置文本
@@ -96,7 +83,7 @@ namespace kiwano
/// \~chinese
/// @brief 设置字体
- void SetFont(const Font& font);
+ void SetFont(FontPtr font);
/// \~chinese
/// @brief 设置字体族
@@ -104,9 +91,7 @@ namespace kiwano
/// \~chinese
/// @brief 设置字号(默认值为 18)
- void SetFontSize(
- float size
- );
+ void SetFontSize(float size);
/// \~chinese
/// @brief 设置字体粗细值(默认值为 FontWeight::Normal)
@@ -132,17 +117,9 @@ namespace kiwano
/// @brief 设置对齐方式(默认为 TextAlign::Left)
void SetAlignment(TextAlign align);
- /// \~chinese
- /// @brief 设置下划线(默认值为 false)
- void SetUnderline(bool underline);
-
- /// \~chinese
- /// @brief 设置删除线(默认值为 false)
- void SetStrikethrough(bool strikethrough);
-
/// \~chinese
/// @brief 设置是否显示描边
- void SetOutline(bool outline);
+ void SetOutline(bool enable);
/// \~chinese
/// @brief 设置描边颜色
@@ -157,12 +134,16 @@ namespace kiwano
void SetOutlineStroke(StrokeStyle outline_stroke);
/// \~chinese
- /// @brief 更新文本布局
- void UpdateLayout();
+ /// @brief 设置是否显示下划线(默认值为 false)
+ void SetUnderline(bool enable);
/// \~chinese
- /// @brief 设置默认字体
- static void SetDefaultFont(Font const& font);
+ /// @brief 设置是否显示删除线(默认值为 false)
+ void SetStrikethrough(bool enable);
+
+ /// \~chinese
+ /// @brief 更新文本布局
+ void UpdateLayout();
/// \~chinese
/// @brief 设置默认文字样式
@@ -171,21 +152,114 @@ namespace kiwano
void OnRender(RenderTarget* rt) override;
private:
- bool format_dirty_;
- bool layout_dirty_;
TextLayout text_layout_;
- String text_;
- Font font_;
};
/** @} */
- inline String const& TextActor::GetText() const { return text_; }
+ inline const String& TextActor::GetText() const
+ {
+ return text_layout_.GetText();
+ }
- inline Font TextActor::GetFont() const { return font_; }
+ inline FontPtr TextActor::GetFont() const
+ {
+ return text_layout_.GetStyle().font;
+ }
- inline TextStyle TextActor::GetStyle() const { return text_layout_.GetTextStyle(); }
+ inline const TextStyle& TextActor::GetStyle() const
+ {
+ return text_layout_.GetStyle();
+ }
- inline TextLayout TextActor::GetLayout() const { return text_layout_; }
+ inline const TextLayout& TextActor::GetLayout() const
+ {
+ return text_layout_;
+ }
+
+ inline void TextActor::SetText(String const& text)
+ {
+ text_layout_.SetText(text);
+ }
+
+ inline void TextActor::SetStyle(const TextStyle& style)
+ {
+ text_layout_.SetStyle(style);
+ }
+
+ inline void TextActor::SetFont(FontPtr font)
+ {
+ text_layout_.SetFont(font);
+ }
+
+ inline void TextActor::SetFontFamily(String const& family)
+ {
+ text_layout_.SetFontFamily(family);
+ }
+
+ inline void TextActor::SetFontSize(float size)
+ {
+ text_layout_.SetFontSize(size);
+ }
+
+ inline void TextActor::SetFontWeight(uint32_t weight)
+ {
+ text_layout_.SetFontWeight(weight);
+ }
+
+ inline void TextActor::SetItalic(bool italic)
+ {
+ text_layout_.SetItalic(italic);
+ }
+
+ inline void TextActor::SetWrapWidth(float wrap_width)
+ {
+ text_layout_.SetWrapWidth(wrap_width);
+ }
+
+ inline void TextActor::SetLineSpacing(float line_spacing)
+ {
+ text_layout_.SetLineSpacing(line_spacing);
+ }
+
+ inline void TextActor::SetAlignment(TextAlign align)
+ {
+ text_layout_.SetAlignment(align);
+ }
+
+ inline void TextActor::SetUnderline(bool enable)
+ {
+ text_layout_.SetUnderline(enable, 0, text_layout_.GetText().length());
+ }
+
+ inline void TextActor::SetStrikethrough(bool enable)
+ {
+ text_layout_.SetStrikethrough(enable, 0, text_layout_.GetText().length());
+ }
+
+ inline void TextActor::SetColor(Color const& color)
+ {
+ text_layout_.SetColor(color);
+ }
+
+ inline void TextActor::SetOutline(bool enable)
+ {
+ text_layout_.SetOutline(enable);
+ }
+
+ inline void TextActor::SetOutlineColor(Color const& outline_color)
+ {
+ text_layout_.SetOutlineColor(outline_color);
+ }
+
+ inline void TextActor::SetOutlineWidth(float outline_width)
+ {
+ text_layout_.SetOutlineWidth(outline_width);
+ }
+
+ inline void TextActor::SetOutlineStroke(StrokeStyle outline_stroke)
+ {
+ text_layout_.SetOutlineStroke(outline_stroke);
+ }
}
diff --git a/src/kiwano/core/EventDispatcher.cpp b/src/kiwano/core/EventDispatcher.cpp
index 54e7dd91..4e647d78 100644
--- a/src/kiwano/core/EventDispatcher.cpp
+++ b/src/kiwano/core/EventDispatcher.cpp
@@ -33,9 +33,9 @@ namespace kiwano
{
next = listener->next_item();
- if (listener->IsRunning() && listener->type_ == evt.GetType())
+ if (listener->IsRunning())
{
- listener->callback_(evt);
+ listener->Receive(evt);
}
if (listener->IsRemoveable())
diff --git a/src/kiwano/core/EventListener.cpp b/src/kiwano/core/EventListener.cpp
index 872c62ca..c8fd0dc7 100644
--- a/src/kiwano/core/EventListener.cpp
+++ b/src/kiwano/core/EventListener.cpp
@@ -35,6 +35,7 @@ namespace kiwano
: type_(type)
, callback_(callback)
, running_(true)
+ , removeable_(false)
{
}
diff --git a/src/kiwano/core/EventListener.h b/src/kiwano/core/EventListener.h
index 147c22e4..a0795530 100644
--- a/src/kiwano/core/EventListener.h
+++ b/src/kiwano/core/EventListener.h
@@ -140,6 +140,10 @@ namespace kiwano
SetEventType(KGE_EVENT(_EventTy));
}
+ /// \~chinese
+ /// @brief 接收消息
+ void Receive(Event& evt);
+
private:
bool running_;
bool removeable_;
@@ -193,4 +197,12 @@ namespace kiwano
type_ = type;
}
+ inline void EventListener::Receive(Event& evt)
+ {
+ if (type_ == evt.GetType() && callback_)
+ {
+ callback_(evt);
+ }
+ }
+
}
diff --git a/src/kiwano/core/win32/helper.h b/src/kiwano/core/win32/helper.h
index 940013ae..b7b5e0bf 100644
--- a/src/kiwano/core/win32/helper.h
+++ b/src/kiwano/core/win32/helper.h
@@ -28,12 +28,12 @@ namespace kiwano
{
if (FAILED(hr))
{
- KGE_ERROR(L"Fatal error with HRESULT of %08X", hr);
+ KGE_ERROR(L"Failed with HRESULT of %08X", hr);
StackWalker{}.ShowCallstack();
static char buffer[1024 + 1];
- sprintf_s(buffer, "Fatal error with HRESULT of %08X", hr);
+ sprintf_s(buffer, "Failed with HRESULT of %08X", hr);
throw std::runtime_error(buffer);
}
}
diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h
index 76a029d7..d99d537e 100644
--- a/src/kiwano/kiwano.h
+++ b/src/kiwano/kiwano.h
@@ -79,11 +79,8 @@
#include
-#include
-
#include
#include
-
#include
#include
#include
@@ -92,9 +89,7 @@
#include
#include
#include
-
#include
-
#include
#include
#include
diff --git a/src/kiwano/renderer/Font.cpp b/src/kiwano/renderer/Font.cpp
index 4a1508dc..46fe442b 100644
--- a/src/kiwano/renderer/Font.cpp
+++ b/src/kiwano/renderer/Font.cpp
@@ -19,25 +19,48 @@
// THE SOFTWARE.
#include
+#include
namespace kiwano
{
- Font::Font(String const& family, float size, uint32_t weight, bool italic)
- : family(family)
- , size(size)
- , weight(weight)
- , italic(italic)
- , collection()
+ Font::Font()
{
}
- Font::Font(FontCollection collection, String const& family, float size, uint32_t weight, bool italic)
- : family(family)
- , size(size)
- , weight(weight)
- , italic(italic)
- , collection(collection)
+ Font::Font(String const& font_file)
{
+ Load(font_file);
+ }
+
+ Font::Font(Resource const& font_resource)
+ {
+ Load(font_resource);
+ }
+
+ bool Font::Load(String const& font_file)
+ {
+ try
+ {
+ Renderer::instance().CreateFontCollection(*this, { font_file });
+ }
+ catch (std::runtime_error&)
+ {
+ return false;
+ }
+ return true;
+ }
+
+ bool Font::Load(Resource const& font_resource)
+ {
+ try
+ {
+ Renderer::instance().CreateFontCollection(*this, { font_resource });
+ }
+ catch (std::runtime_error&)
+ {
+ return false;
+ }
+ return true;
}
}
diff --git a/src/kiwano/renderer/Font.h b/src/kiwano/renderer/Font.h
index 16876b28..8e916b92 100644
--- a/src/kiwano/renderer/Font.h
+++ b/src/kiwano/renderer/Font.h
@@ -19,51 +19,50 @@
// THE SOFTWARE.
#pragma once
-#include
+#include
+#include
+#include
+#include
namespace kiwano
{
- // 字体粗细值
- struct FontWeight
- {
- enum Value : uint32_t
- {
- Thin = 100U,
- ExtraLight = 200U,
- Light = 300U,
- Normal = 400U,
- Medium = 500U,
- Bold = 700U,
- ExtraBold = 800U,
- Black = 900U,
- ExtraBlack = 950U
- };
- };
+ KGE_DECLARE_SMART_PTR(Font);
+
+ class Renderer;
// 字体
class Font
+ : public ObjectBase
{
- public:
- String family; // 字体族
- float size; // 字号
- uint32_t weight; // 粗细值
- bool italic; // 是否斜体
- FontCollection collection; // 字体集
+ friend class Renderer;
public:
- Font(
- String const& family = L"",
- float size = 18,
- uint32_t weight = FontWeight::Normal,
- bool italic = false
- );
+ Font();
- Font(
- FontCollection collection,
- String const& family = L"",
- float size = 18,
- uint32_t weight = FontWeight::Normal,
- bool italic = false
- );
+ Font(String const& font_file);
+
+ Font(Resource const& font_resource);
+
+ bool Load(String const& font_file);
+
+ bool Load(Resource const& font_resource);
+
+ private:
+ ComPtr GetCollection() const;
+
+ void SetCollection(ComPtr collection);
+
+ private:
+ ComPtr collection_;
};
+
+ inline ComPtr Font::GetCollection() const
+ {
+ return collection_;
+ }
+
+ inline void Font::SetCollection(ComPtr collection)
+ {
+ collection_ = collection;
+ }
}
diff --git a/src/kiwano/renderer/FontCollection.cpp b/src/kiwano/renderer/FontCollection.cpp
deleted file mode 100644
index df0118cc..00000000
--- a/src/kiwano/renderer/FontCollection.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (c) 2016-2018 Kiwano - 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
-#include
-
-namespace kiwano
-{
- FontCollection::FontCollection()
- {
- }
-
- FontCollection::FontCollection(String const& file)
- {
- Load(file);
- }
-
- FontCollection::FontCollection(Vector const& files)
- {
- Load(files);
- }
-
- FontCollection::FontCollection(Resource const& res)
- {
- Load(res);
- }
-
- FontCollection::FontCollection(Vector const& res_arr)
- {
- Load(res_arr);
- }
-
- bool FontCollection::Load(String const& file)
- {
- Renderer::instance().CreateFontCollection(*this, { file });
- return IsValid();
- }
-
- bool FontCollection::Load(Vector const& files)
- {
- Renderer::instance().CreateFontCollection(*this, files);
- return IsValid();
- }
-
- bool FontCollection::Load(Resource const& res)
- {
- Renderer::instance().CreateFontCollection(*this, { res });
- return IsValid();
- }
-
- bool FontCollection::Load(Vector const& res_arr)
- {
- Renderer::instance().CreateFontCollection(*this, res_arr);
- return IsValid();
- }
-
- bool FontCollection::IsValid() const
- {
- return collection_ != nullptr;
- }
-
-}
diff --git a/src/kiwano/renderer/FontCollection.h b/src/kiwano/renderer/FontCollection.h
deleted file mode 100644
index 89d9e856..00000000
--- a/src/kiwano/renderer/FontCollection.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2016-2018 Kiwano - 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
-#include
-#include
-
-namespace kiwano
-{
- // 字体集
- class FontCollection
- {
- public:
- FontCollection();
-
- FontCollection(String const& file);
-
- FontCollection(Vector const& files);
-
- FontCollection(Resource const& res);
-
- FontCollection(Vector const& res_arr);
-
- // 从本地文件加载字体
- bool Load(String const& file);
-
- // 从多个本地文件加载字体
- bool Load(Vector const& files);
-
- // 从资源加载字体
- bool Load(Resource const& res);
-
- // 从多个资源加载字体
- bool Load(Vector const& res_arr);
-
- bool IsValid() const;
-
- public:
- inline ComPtr GetFontCollection() const { return collection_; }
-
- inline void SetFontCollection(ComPtr collection) { collection_ = collection; }
-
- private:
- ComPtr collection_;
- };
-}
diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp
index fdc88be1..3a08161d 100644
--- a/src/kiwano/renderer/RenderTarget.cpp
+++ b/src/kiwano/renderer/RenderTarget.cpp
@@ -333,12 +333,12 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::DrawTexture(TexturePtr texture, Rect const& src_rect, Rect const& dest_rect)
+ void RenderTarget::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect)
{
DrawTexture(texture, &src_rect, &dest_rect);
}
- void RenderTarget::DrawTexture(TexturePtr texture, const Rect* src_rect, const Rect* dest_rect)
+ void RenderTarget::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect)
{
HRESULT hr = S_OK;
if (!render_target_)
@@ -346,19 +346,14 @@ namespace kiwano
hr = E_UNEXPECTED;
}
- if (!texture)
+ if (SUCCEEDED(hr) && texture.IsValid())
{
- hr = E_INVALIDARG;
- }
-
- if (SUCCEEDED(hr) && texture->IsValid())
- {
- auto mode = (texture->GetBitmapInterpolationMode() == InterpolationMode::Linear)
+ auto mode = (texture.GetBitmapInterpolationMode() == InterpolationMode::Linear)
? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
: D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
render_target_->DrawBitmap(
- texture->GetBitmap().get(),
+ texture.GetBitmap().get(),
dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
opacity_,
mode,
@@ -381,13 +376,14 @@ namespace kiwano
if (SUCCEEDED(hr))
{
+ const TextStyle& style = layout.GetStyle();
text_renderer_->SetTextStyle(
opacity_,
- DX::ConvertToColorF(layout.GetTextStyle().color),
- layout.GetTextStyle().outline,
- DX::ConvertToColorF(layout.GetTextStyle().outline_color),
- layout.GetTextStyle().outline_width,
- GetStrokeStyle(layout.GetTextStyle().outline_stroke).get()
+ DX::ConvertToColorF(style.color),
+ style.outline,
+ DX::ConvertToColorF(style.outline_color),
+ style.outline_width,
+ GetStrokeStyle(style.outline_stroke).get()
);
hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), offset.x, offset.y);
diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h
index 10b163f2..3d584fb0 100644
--- a/src/kiwano/renderer/RenderTarget.h
+++ b/src/kiwano/renderer/RenderTarget.h
@@ -20,6 +20,7 @@
#pragma once
#include
+#include
#include
#include
#include
@@ -106,13 +107,13 @@ namespace kiwano
);
void DrawTexture(
- TexturePtr texture,
+ Texture const& texture,
Rect const& src_rect,
Rect const& dest_rect
);
void DrawTexture(
- TexturePtr texture,
+ Texture const& texture,
const Rect* src_rect = nullptr,
const Rect* dest_rect = nullptr
);
diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp
index fac28939..f04f2d26 100644
--- a/src/kiwano/renderer/Renderer.cpp
+++ b/src/kiwano/renderer/Renderer.cpp
@@ -577,7 +577,7 @@ namespace kiwano
}
}
- void Renderer::CreateFontCollection(FontCollection& collection, Vector const& file_paths)
+ void Renderer::CreateFontCollection(Font& font, Vector const& file_paths)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@@ -620,18 +620,15 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- collection.SetFontCollection(font_collection);
+ font.SetCollection(font_collection);
}
}
}
- if (FAILED(hr))
- {
- KGE_WARN(L"Load font failed with HRESULT of %08X!", hr);
- }
+ ThrowIfFailed(hr);
}
- void Renderer::CreateFontCollection(FontCollection& collection, Vector const& res_arr)
+ void Renderer::CreateFontCollection(Font& font, Vector const& res_arr)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@@ -658,18 +655,15 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- collection.SetFontCollection(font_collection);
+ font.SetCollection(font_collection);
}
}
}
- if (FAILED(hr))
- {
- KGE_WARN(L"Load font failed with HRESULT of %08X!", hr);
- }
+ ThrowIfFailed(hr);
}
- void Renderer::CreateTextFormat(TextFormat& format, Font const& font)
+ void Renderer::CreateTextFormat(TextLayout& layout)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@@ -680,18 +674,28 @@ namespace kiwano
ComPtr output;
if (SUCCEEDED(hr))
{
- hr = d2d_res_->CreateTextFormat(output, font);
+ const TextStyle& style = layout.GetStyle();
+
+ hr = d2d_res_->CreateTextFormat(
+ output,
+ style.font_family,
+ style.font ? style.font->GetCollection() : nullptr,
+ DWRITE_FONT_WEIGHT(style.font_weight),
+ style.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
+ DWRITE_FONT_STRETCH_NORMAL,
+ style.font_size
+ );
}
if (SUCCEEDED(hr))
{
- format.SetTextFormat(output);
+ layout.SetTextFormat(output);
}
ThrowIfFailed(hr);
}
- void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextFormat const& format)
+ void Renderer::CreateTextLayout(TextLayout& layout)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@@ -704,8 +708,8 @@ namespace kiwano
{
hr = d2d_res_->CreateTextLayout(
output,
- text,
- format.GetTextFormat()
+ layout.GetText(),
+ layout.GetTextFormat()
);
}
diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h
index bab77019..23eb32d0 100644
--- a/src/kiwano/renderer/Renderer.h
+++ b/src/kiwano/renderer/Renderer.h
@@ -23,6 +23,8 @@
#include
#include
#include
+#include
+#include
#if defined(KGE_USE_DIRECTX10)
# include "win32/D3D10DeviceResources.h"
@@ -99,24 +101,21 @@ namespace kiwano
);
void CreateFontCollection(
- FontCollection& collection,
+ Font& font,
Vector const& file_paths
);
void CreateFontCollection(
- FontCollection& collection,
+ Font& font,
Vector const& res_arr
);
void CreateTextFormat(
- TextFormat& format,
- Font const& font
+ TextLayout& layout
);
void CreateTextLayout(
- TextLayout& layout,
- String const& text,
- TextFormat const& format
+ TextLayout& layout
);
void CreateLineGeometry(
diff --git a/src/kiwano/renderer/TextLayout.cpp b/src/kiwano/renderer/TextLayout.cpp
index 69d9b8cf..b48696fa 100644
--- a/src/kiwano/renderer/TextLayout.cpp
+++ b/src/kiwano/renderer/TextLayout.cpp
@@ -24,132 +24,109 @@
namespace kiwano
{
- //
- // TextFormat
- //
-
- TextFormat::TextFormat()
- {
- }
-
- TextFormat::TextFormat(Font const& font)
- {
- Update(font);
- }
-
- void TextFormat::Update(Font const& font)
- {
- Renderer::instance().CreateTextFormat(*this, font);
- }
-
-
- //
- // TextLayout
- //
-
TextLayout::TextLayout()
+ : dirty_flag_(DirtyFlag::Clean)
{
}
- TextLayout::TextLayout(String const& text, Font const& font, TextStyle const& style)
+ void TextLayout::Update()
{
- UpdateFont(font);
- SetTextStyle(style);
- UpdateLayout(text);
- }
+ if (!IsDirty())
+ return;
- void TextLayout::UpdateFont(Font const& font)
- {
- text_format_.Update(font);
- }
-
- void TextLayout::UpdateLayout(String const& text)
- {
- if (text.empty())
+ if (text_.empty())
{
- text_format_.SetTextFormat(nullptr);
- SetTextLayout(nullptr);
+ text_format_.reset();
+ text_layout_.reset();
return;
}
- Renderer::instance().CreateTextLayout(
- *this,
- text,
- text_format_
- );
-
- HRESULT hr = text_layout_ ? S_OK : E_FAIL;
-
- if (SUCCEEDED(hr))
+ if (!text_format_ || (dirty_flag_ & DirtyFlag::DirtyFormat))
{
- if (style_.line_spacing == 0.f)
+ Renderer::instance().CreateTextFormat(*this);
+ }
+
+ if (dirty_flag_ & DirtyFlag::DirtyLayout)
+ {
+ Renderer::instance().CreateTextLayout(*this);
+
+ if (text_layout_)
{
- hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
- }
- else
- {
- hr = text_layout_->SetLineSpacing(
- DWRITE_LINE_SPACING_METHOD_UNIFORM,
- style_.line_spacing,
- style_.line_spacing * 0.8f
- );
+ SetAlignment(style_.alignment);
+ SetWrapWidth(style_.wrap_width);
+ SetLineSpacing(style_.line_spacing);
}
}
- if (SUCCEEDED(hr))
- {
- hr = text_layout_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style_.alignment));
- }
-
- if (SUCCEEDED(hr))
- {
- hr = text_layout_->SetWordWrapping((style_.wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
- }
-
- if (SUCCEEDED(hr))
- {
- if (style_.underline)
- {
- hr = text_layout_->SetUnderline(true, { 0, UINT32(text.length()) });
- }
- }
-
- if (SUCCEEDED(hr))
- {
- if (style_.strikethrough)
- {
- text_layout_->SetStrikethrough(true, { 0, UINT32(text.length()) });
- }
- }
-
- if (SUCCEEDED(hr))
- {
- if (style_.wrap_width > 0)
- {
- hr = text_layout_->SetMaxWidth(style_.wrap_width);
- }
- else
- {
- // Fix the layout width when the text does not wrap
- DWRITE_TEXT_METRICS metrics;
- hr = text_layout_->GetMetrics(&metrics);
-
- if (SUCCEEDED(hr))
- {
- hr = text_layout_->SetMaxWidth(metrics.width);
- }
- }
- }
-
- ThrowIfFailed(hr);
+ dirty_flag_ = DirtyFlag::Clean;
}
- uint32_t TextLayout::GetLineCount()
+ void TextLayout::SetText(const String& text)
{
+ text_ = text;
+ dirty_flag_ |= DirtyFlag::DirtyLayout;
+ }
+
+ void TextLayout::SetStyle(const TextStyle& style)
+ {
+ style_ = style;
+ dirty_flag_ |= DirtyFlag::DirtyLayout;
+ }
+
+ void TextLayout::SetFont(FontPtr font)
+ {
+ if (style_.font != font)
+ {
+ style_.font = font;
+ dirty_flag_ |= DirtyFlag::DirtyFormat;
+ }
+ }
+
+ void TextLayout::SetFontFamily(String const& family)
+ {
+ if (style_.font_family != family)
+ {
+ style_.font_family = family;
+ dirty_flag_ |= DirtyFlag::DirtyFormat;
+ }
+ }
+
+ void TextLayout::SetFontSize(float size)
+ {
+ if (style_.font_size != size)
+ {
+ style_.font_size = size;
+ dirty_flag_ |= DirtyFlag::DirtyFormat;
+ }
+ }
+
+ void TextLayout::SetFontWeight(uint32_t weight)
+ {
+ if (style_.font_weight != weight)
+ {
+ style_.font_weight = weight;
+ dirty_flag_ |= DirtyFlag::DirtyFormat;
+ }
+ }
+
+ void TextLayout::SetItalic(bool italic)
+ {
+ if (style_.italic != italic)
+ {
+ style_.italic = italic;
+ dirty_flag_ |= DirtyFlag::DirtyFormat;
+ }
+ }
+
+ uint32_t TextLayout::GetLineCount() const
+ {
+ // Force to update layout
+ const_cast(this)->Update();
+
if (text_layout_)
{
DWRITE_TEXT_METRICS metrics;
- if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
+ if (SUCCEEDED(GetTextLayout()->GetMetrics(&metrics)))
{
return metrics.lineCount;
}
@@ -159,10 +136,13 @@ namespace kiwano
Size TextLayout::GetLayoutSize() const
{
+ // Force to update layout
+ const_cast(this)->Update();
+
if (text_layout_)
{
DWRITE_TEXT_METRICS metrics;
- if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
+ if (SUCCEEDED(GetTextLayout()->GetMetrics(&metrics)))
{
return (metrics.layoutWidth > 0) ? Size(metrics.layoutWidth, metrics.height) : Size(metrics.width, metrics.height);
}
@@ -170,4 +150,98 @@ namespace kiwano
return Size();
}
+ void TextLayout::SetWrapWidth(float wrap_width)
+ {
+ style_.wrap_width = wrap_width;
+
+ if (text_layout_)
+ {
+ HRESULT hr = S_OK;
+ bool enable_wrapping = (wrap_width > 0);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = text_layout_->SetWordWrapping(enable_wrapping ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (enable_wrapping)
+ {
+ hr = text_layout_->SetMaxWidth(wrap_width);
+ }
+ else
+ {
+ // Fix the layout width when the text does not wrap
+ DWRITE_TEXT_METRICS metrics;
+ hr = text_layout_->GetMetrics(&metrics);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = text_layout_->SetMaxWidth(metrics.width);
+ }
+ }
+ }
+ ThrowIfFailed(hr);
+ }
+ }
+
+ void TextLayout::SetLineSpacing(float line_spacing)
+ {
+ style_.line_spacing = line_spacing;
+
+ if (text_layout_)
+ {
+ HRESULT hr = S_OK;
+ if (line_spacing == 0.f)
+ {
+ hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
+ }
+ else
+ {
+ hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_UNIFORM, line_spacing, line_spacing * 0.8f);
+ }
+ ThrowIfFailed(hr);
+ }
+ }
+
+ void TextLayout::SetAlignment(TextAlign align)
+ {
+ style_.alignment = align;
+
+ if (text_layout_)
+ {
+ HRESULT hr = text_layout_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(align));
+ ThrowIfFailed(hr);
+ }
+ }
+
+ void TextLayout::SetUnderline(bool enable, uint32_t start, uint32_t length)
+ {
+ // Force to update layout
+ Update();
+
+ HRESULT hr = text_layout_ ? S_OK : E_FAIL;
+
+ if (SUCCEEDED(hr))
+ {
+ hr = text_layout_->SetUnderline(enable, { start, length });
+ }
+ ThrowIfFailed(hr);
+ }
+
+ void TextLayout::SetStrikethrough(bool enable, uint32_t start, uint32_t length)
+ {
+ // Force to update layout
+ Update();
+
+ HRESULT hr = text_layout_ ? S_OK : E_FAIL;
+
+ if (SUCCEEDED(hr))
+ {
+ hr = text_layout_->SetStrikethrough(enable, { start, length });
+ }
+ ThrowIfFailed(hr);
+ }
+
}
diff --git a/src/kiwano/renderer/TextLayout.h b/src/kiwano/renderer/TextLayout.h
index 58049bea..d6424eaa 100644
--- a/src/kiwano/renderer/TextLayout.h
+++ b/src/kiwano/renderer/TextLayout.h
@@ -20,63 +20,209 @@
#pragma once
#include
-#include
-#include
+#include
namespace kiwano
{
- // 文本格式化
- class KGE_API TextFormat
- {
- public:
- TextFormat();
-
- TextFormat(Font const& font);
-
- void Update(Font const& font);
-
- public:
- inline ComPtr GetTextFormat() const { return text_format_; }
-
- inline void SetTextFormat(ComPtr format) { text_format_ = format; }
-
- private:
- ComPtr text_format_;
- };
-
-
- // 文本布局
+ /// \~chinese
+ /// @brief 文本布局
class KGE_API TextLayout
{
public:
+ /// \~chinese
+ /// @brief 构造空的文本布局
TextLayout();
- TextLayout(String const& text, Font const& font, TextStyle const& style);
+ /// \~chinese
+ /// @brief 文本布局是否有效
+ bool IsValid() const;
- void UpdateFont(Font const& font);
+ /// \~chinese
+ /// @brief 文本布局是否陈旧
+ bool IsDirty() const;
- void UpdateLayout(String const& text);
+ /// \~chinese
+ /// @brief 更新文本布局
+ /// @note 文本布局是懒更新的,在修改文本布局的属性后需要手动更新
+ void Update();
- uint32_t GetLineCount();
+ /// \~chinese
+ /// @brief 获取文本
+ const String& GetText() const;
+ /// \~chinese
+ /// @brief 获取文本样式
+ const TextStyle& GetStyle() const;
+
+ /// \~chinese
+ /// @brief 获取文本行数
+ uint32_t GetLineCount() const;
+
+ /// \~chinese
+ /// @brief 获取文本布局大小
Size GetLayoutSize() const;
- inline TextStyle& GetTextStyle() { return style_; }
- inline TextStyle const& GetTextStyle() const { return style_; }
- inline void SetTextStyle(TextStyle const& style) { style_ = style; }
+ /// \~chinese
+ /// @brief 设置文本
+ void SetText(const String& text);
+
+ /// \~chinese
+ /// @brief 设置文本样式
+ void SetStyle(const TextStyle& style);
+
+ /// \~chinese
+ /// @brief 设置字体
+ void SetFont(FontPtr font);
+
+ /// \~chinese
+ /// @brief 设置字体族
+ void SetFontFamily(String const& family);
+
+ /// \~chinese
+ /// @brief 设置字号(默认值为 18)
+ void SetFontSize(float size);
+
+ /// \~chinese
+ /// @brief 设置字体粗细值(默认值为 FontWeight::Normal)
+ void SetFontWeight(uint32_t weight);
+
+ /// \~chinese
+ /// @brief 设置文字颜色(默认值为 Color::White)
+ void SetColor(Color const& color);
+
+ /// \~chinese
+ /// @brief 设置文字斜体(默认值为 false)
+ void SetItalic(bool italic);
+
+ /// \~chinese
+ /// @brief 设置文本自动换行的宽度
+ void SetWrapWidth(float wrap_width);
+
+ /// \~chinese
+ /// @brief 设置行间距(默认为 0)
+ void SetLineSpacing(float line_spacing);
+
+ /// \~chinese
+ /// @brief 设置对齐方式
+ void SetAlignment(TextAlign align);
+
+ /// \~chinese
+ /// @brief 设置是否显示描边
+ void SetOutline(bool enable);
+
+ /// \~chinese
+ /// @brief 设置描边颜色
+ void SetOutlineColor(Color const& outline_color);
+
+ /// \~chinese
+ /// @brief 设置描边线宽
+ void SetOutlineWidth(float outline_width);
+
+ /// \~chinese
+ /// @brief 设置描边线相交样式
+ void SetOutlineStroke(StrokeStyle outline_stroke);
+
+ /// \~chinese
+ /// @brief 设置下划线
+ /// @param enable 是否显示下划线
+ /// @param start 起始位置
+ /// @param length 长度
+ void SetUnderline(bool enable, uint32_t start, uint32_t length);
+
+ /// \~chinese
+ /// @brief 设置删除线
+ /// @param enable 是否显示删除线
+ /// @param start 起始位置
+ /// @param length 长度
+ void SetStrikethrough(bool enable, uint32_t start, uint32_t length);
public:
- inline TextFormat GetTextFormat() const { return text_format_; }
+ ComPtr GetTextFormat() const;
- inline ComPtr GetTextLayout() const { return text_layout_; }
+ void SetTextFormat(ComPtr format);
- inline void SetTextLayout(ComPtr layout) { text_layout_ = layout; }
+ ComPtr GetTextLayout() const;
- inline operator bool() const { return static_cast(text_layout_); }
+ void SetTextLayout(ComPtr layout);
private:
+ enum DirtyFlag : uint8_t
+ {
+ Clean = 0,
+ DirtyFormat = 1,
+ DirtyLayout = 1 << 1,
+ };
+ uint8_t dirty_flag_;
+
+ ComPtr text_format_;
+ ComPtr text_layout_;
+
+ String text_;
TextStyle style_;
- TextFormat text_format_;
- mutable ComPtr text_layout_;
};
+
+ inline bool TextLayout::IsValid() const
+ {
+ return !!text_layout_;
+ }
+
+ inline bool TextLayout::IsDirty() const
+ {
+ return dirty_flag_ != DirtyFlag::Clean;
+ }
+
+ inline const String& TextLayout::GetText() const
+ {
+ return text_;
+ }
+
+ inline const TextStyle& TextLayout::GetStyle() const
+ {
+ return style_;
+ }
+
+ inline ComPtr TextLayout::GetTextFormat() const
+ {
+ return text_format_;
+ }
+
+ inline ComPtr TextLayout::GetTextLayout() const
+ {
+ return text_layout_;
+ }
+
+ inline void TextLayout::SetColor(Color const& color)
+ {
+ style_.color = color;
+ }
+
+ inline void TextLayout::SetTextFormat(ComPtr format)
+ {
+ text_format_ = format;
+ }
+
+ inline void TextLayout::SetTextLayout(ComPtr layout)
+ {
+ text_layout_ = layout;
+ }
+
+ inline void TextLayout::SetOutline(bool enable)
+ {
+ style_.outline = enable;
+ }
+
+ inline void TextLayout::SetOutlineColor(Color const& outline_color)
+ {
+ style_.outline_color = outline_color;
+ }
+
+ inline void TextLayout::SetOutlineWidth(float outline_width)
+ {
+ style_.outline_width = outline_width;
+ }
+
+ inline void TextLayout::SetOutlineStroke(StrokeStyle outline_stroke)
+ {
+ style_.outline_stroke = outline_stroke;
+ }
}
diff --git a/src/kiwano/2d/TextStyle.hpp b/src/kiwano/renderer/TextStyle.hpp
similarity index 64%
rename from src/kiwano/2d/TextStyle.hpp
rename to src/kiwano/renderer/TextStyle.hpp
index b8471816..99c9c138 100644
--- a/src/kiwano/2d/TextStyle.hpp
+++ b/src/kiwano/renderer/TextStyle.hpp
@@ -21,6 +21,7 @@
#pragma once
#include
#include
+#include
namespace kiwano
{
@@ -35,6 +36,26 @@ namespace kiwano
Center ///< 居中对齐
};
+ /**
+ * \~chinese
+ * @brief 字体粗细值
+ */
+ struct FontWeight
+ {
+ enum Value : uint32_t
+ {
+ Thin = 100U,
+ ExtraLight = 200U,
+ Light = 300U,
+ Normal = 400U, ///< 正常
+ Medium = 500U,
+ Bold = 700U,
+ ExtraBold = 800U,
+ Black = 900U,
+ ExtraBlack = 950U
+ };
+ };
+
/**
* \~chinese
* @brief 文本样式
@@ -42,12 +63,15 @@ namespace kiwano
class KGE_API TextStyle
{
public:
+ FontPtr font; ///< 字体
+ String font_family; ///< 字体族
+ float font_size; ///< 字号
+ uint32_t font_weight; ///< 粗细值
+ bool italic; ///< 是否斜体
Color color; ///< 颜色
TextAlign alignment; ///< 对齐方式
float wrap_width; ///< 自动换行宽度
float line_spacing; ///< 行间距
- bool underline; ///< 下划线
- bool strikethrough; ///< 删除线
bool outline; ///< 描边
Color outline_color; ///< 描边颜色
float outline_width; ///< 描边线宽
@@ -57,35 +81,44 @@ namespace kiwano
/**
* \~chinese
* @brief 构建文本样式
+ * @param font 字体
+ * @param font_family 字体族
+ * @param font_size 字体大小
+ * @param font_weight 字体粗细
+ * @param italic 斜体
* @param color 颜色
* @param alignment 对齐方式
* @param wrap_width 自动换行宽度
* @param line_spacing 行间距
- * @param underline 下划线
- * @param strikethrough 删除线
* @param outline 描边
* @param outline_color 描边颜色
* @param outline_width 描边线宽
* @param outline_stroke 描边线相交样式
*/
TextStyle(
- Color color = Color::White,
- TextAlign alignment = TextAlign::Left,
- float wrap_width = 0.f,
- float line_spacing = 0.f,
- bool underline = false,
- bool strikethrough = false,
- bool outline = false,
- Color outline_color = Color(Color::Black, 0.5),
- float outline_width = 1.f,
- StrokeStyle outline_stroke = StrokeStyle::Round
+ FontPtr font = nullptr,
+ const String& font_family = String(),
+ float font_size = 18,
+ uint32_t font_weight = FontWeight::Normal,
+ bool italic = false,
+ Color color = Color::White,
+ TextAlign alignment = TextAlign::Left,
+ float wrap_width = 0.f,
+ float line_spacing = 0.f,
+ bool outline = false,
+ Color outline_color = Color(Color::Black, 0.5),
+ float outline_width = 1.f,
+ StrokeStyle outline_stroke = StrokeStyle::Round
)
- : color(color)
+ : font(nullptr)
+ , font_family(font_family)
+ , font_size(font_size)
+ , font_weight(font_weight)
+ , italic(italic)
+ , color(color)
, alignment(alignment)
, wrap_width(wrap_width)
, line_spacing(line_spacing)
- , underline(underline)
- , strikethrough(strikethrough)
, outline(outline)
, outline_color(outline_color)
, outline_width(outline_width)
diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp
index 0c1914d7..47c63a67 100644
--- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp
+++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp
@@ -65,7 +65,12 @@ namespace kiwano
HRESULT CreateTextFormat(
_Out_ ComPtr& text_format,
- _In_ Font const& font
+ _In_ String const& family,
+ _In_ ComPtr collection,
+ _In_ DWRITE_FONT_WEIGHT weight,
+ _In_ DWRITE_FONT_STYLE style,
+ _In_ DWRITE_FONT_STRETCH stretch,
+ _In_ FLOAT font_size
) override;
HRESULT CreateTextLayout(
@@ -435,19 +440,20 @@ namespace kiwano
return hr;
}
- HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, _In_ Font const & font)
+ HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, _In_ String const& family, _In_ ComPtr collection,
+ _In_ DWRITE_FONT_WEIGHT weight, _In_ DWRITE_FONT_STYLE style, _In_ DWRITE_FONT_STRETCH stretch, _In_ FLOAT font_size)
{
if (!dwrite_factory_)
return E_UNEXPECTED;
ComPtr output;
HRESULT hr = dwrite_factory_->CreateTextFormat(
- font.family.c_str(),
- font.collection.GetFontCollection().get(),
- DWRITE_FONT_WEIGHT(font.weight),
- font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
- DWRITE_FONT_STRETCH_NORMAL,
- font.size,
+ family.c_str(),
+ collection.get(),
+ weight,
+ style,
+ stretch,
+ font_size,
L"",
&output
);
diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.h b/src/kiwano/renderer/win32/D2DDeviceResources.h
index be14483d..04565b8b 100644
--- a/src/kiwano/renderer/win32/D2DDeviceResources.h
+++ b/src/kiwano/renderer/win32/D2DDeviceResources.h
@@ -19,10 +19,10 @@
// THE SOFTWARE.
#pragma once
-#include
-#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -216,7 +216,12 @@ namespace kiwano
virtual HRESULT CreateTextFormat(
_Out_ ComPtr& text_format,
- _In_ Font const& font
+ _In_ String const& family,
+ _In_ ComPtr collection,
+ _In_ DWRITE_FONT_WEIGHT weight,
+ _In_ DWRITE_FONT_STYLE style,
+ _In_ DWRITE_FONT_STRETCH stretch,
+ _In_ FLOAT font_size
) = 0;
virtual HRESULT CreateTextLayout(
diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp
index 415f0dfa..8c6c3b43 100644
--- a/src/kiwano/utils/ResourceCache.cpp
+++ b/src/kiwano/utils/ResourceCache.cpp
@@ -22,9 +22,6 @@
#include
#include
#include
-#include
-#include
-
namespace kiwano
{
@@ -187,29 +184,6 @@ namespace kiwano
return false;
}
- bool ResourceCache::AddFrame(String const& id, String const& file_path)
- {
- FramePtr ptr = new (std::nothrow) Frame;
- if (ptr)
- {
- if (ptr->Load(file_path))
- {
- return AddFrame(id, ptr);
- }
- }
- return false;
- }
-
- bool ResourceCache::AddFrame(String const & id, FramePtr frame)
- {
- if (frame)
- {
- object_cache_.insert(std::make_pair(id, frame));
- return true;
- }
- return false;
- }
-
size_t ResourceCache::AddFrameSequence(String const& id, Vector const& files)
{
if (files.empty())
@@ -233,7 +207,7 @@ namespace kiwano
if (!frames.empty())
{
FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames);
- return AddFrameSequence(id, fs);
+ return AddObject(id, fs);
}
return 0;
}
@@ -273,20 +247,10 @@ namespace kiwano
}
FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames);
- return AddFrameSequence(id, fs);
+ return AddObject(id, fs);
}
- size_t ResourceCache::AddFrameSequence(String const & id, FrameSequencePtr frames)
- {
- if (frames)
- {
- object_cache_.insert(std::make_pair(id, frames));
- return frames->GetFrames().size();
- }
- return 0;
- }
-
- bool ResourceCache::AddObjectBase(String const& id, ObjectBasePtr obj)
+ bool ResourceCache::AddObject(String const& id, ObjectBasePtr obj)
{
if (obj)
{
@@ -296,59 +260,6 @@ namespace kiwano
return false;
}
- bool ResourceCache::AddGifImage(String const& id, GifImagePtr gif)
- {
- if (gif && gif->IsValid())
- {
- object_cache_.insert(std::make_pair(id, gif));
- return true;
- }
- return false;
- }
-
- bool ResourceCache::AddGifImage(String const& id, String const& file_path)
- {
- GifImagePtr gif = new (std::nothrow) GifImage;
- if (gif && gif->Load(file_path))
- {
- return AddGifImage(id, gif);
- }
- return false;
- }
-
- bool ResourceCache::AddFontCollection(String const& id, FontCollection const& collection)
- {
- if (collection.IsValid())
- {
- font_collection_cache_.insert(std::make_pair(id, collection));
- return true;
- }
- return false;
- }
-
- FramePtr ResourceCache::GetFrame(String const & id) const
- {
- return Get(id);
- }
-
- FrameSequencePtr ResourceCache::GetFrameSequence(String const & id) const
- {
- return Get(id);
- }
-
- GifImagePtr ResourceCache::GetGifImage(String const& id) const
- {
- return Get(id);
- }
-
- FontCollection ResourceCache::GetFontCollection(String const& id) const
- {
- auto iter = font_collection_cache_.find(id);
- if (iter != font_collection_cache_.end())
- return iter->second;
- return FontCollection();
- }
-
void ResourceCache::Remove(String const & id)
{
object_cache_.erase(id);
@@ -357,7 +268,14 @@ namespace kiwano
void ResourceCache::Clear()
{
object_cache_.clear();
- font_collection_cache_.clear();
+ }
+
+ ObjectBasePtr ResourceCache::Get(String const& id) const
+ {
+ auto iter = object_cache_.find(id);
+ if (iter == object_cache_.end())
+ return nullptr;
+ return (*iter).second;
}
}
@@ -378,13 +296,21 @@ namespace kiwano
if (type && (*type) == L"gif")
{
// GIF image
- return loader->AddGifImage(*id, gdata->path + (*file));
+ GifImagePtr gif = new (std::nothrow) GifImage;
+ if (gif && gif->Load(gdata->path + (*file)))
+ {
+ return loader->AddObject(*id, gif);
+ }
}
if (file && !(*file).empty())
{
// Simple image
- return loader->AddFrame(*id, gdata->path + (*file));
+ FramePtr frame = new (std::nothrow) Frame;
+ if (frame && frame->Load(gdata->path + (*file)))
+ {
+ return loader->AddObject(*id, frame);
+ }
}
return false;
}
@@ -407,7 +333,7 @@ namespace kiwano
}
}
FrameSequencePtr frame_seq = new FrameSequence(frames);
- return !!loader->AddFrameSequence(*id, frame_seq);
+ return !!loader->AddObject(*id, frame_seq);
}
return false;
}
@@ -429,30 +355,27 @@ namespace kiwano
else
{
// Simple image
- return loader->AddFrame(*id, gdata->path + (*file));
+ FramePtr frame = new (std::nothrow) Frame;
+ if (frame && frame->Load(gdata->path + (*file)))
+ {
+ return loader->AddObject(*id, frame);
+ }
}
}
}
return false;
}
- bool LoadFontsFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const Vector* files)
+ bool LoadFontsFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* file)
{
if (!gdata || !id) return false;
- // Font Collection
- if (files)
+ if (file)
{
- Vector files_copy(*files);
- for (auto& file : files_copy)
+ FontPtr font = new (std::nothrow) Font;
+ if (font && font->Load(gdata->path + (*file)))
{
- file = gdata->path + file;
- }
-
- FontCollection collection;
- if (collection.Load(files_copy))
- {
- return loader->AddFontCollection(*id, collection);
+ return loader->AddObject(*id, font);
}
}
return false;
@@ -512,20 +435,13 @@ namespace kiwano
{
for (const auto& font : json_data[L"fonts"])
{
- String id;
+ const String *id = nullptr, *file = nullptr;
- if (font.count(L"id")) id = font[L"id"].as_string();
- if (font.count(L"files"))
- {
- Vector files;
- files.reserve(font[L"files"].size());
- for (const auto& file : font[L"files"])
- {
- files.push_back(file.as_string());
- }
- if (!LoadFontsFromData(loader, &global_data, &id, &files))
- return false;
- }
+ if (font.count(L"id")) id = &font[L"id"].as_string();
+ if (font.count(L"file")) file = &font[L"file"].as_string();
+
+ if (!LoadFontsFromData(loader, &global_data, id, file))
+ return false;
}
}
return true;
@@ -587,18 +503,11 @@ namespace kiwano
{
for (auto font = fonts->FirstChildElement(); font; font = font->NextSiblingElement())
{
- String id;
+ String id, file;
if (auto attr = font->Attribute(L"id")) id.assign(attr);
+ if (auto attr = font->Attribute(L"file")) file.assign(attr);
- Vector files_arr;
- for (auto file = font->FirstChildElement(); file; file = file->NextSiblingElement())
- {
- if (auto path = file->Attribute(L"path"))
- {
- files_arr.push_back(path);
- }
- }
- if (!LoadFontsFromData(loader, &global_data, &id, &files_arr))
+ if (!LoadFontsFromData(loader, &global_data, &id, &file))
return false;
}
}
diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h
index 40e3f60a..db4be9c9 100644
--- a/src/kiwano/utils/ResourceCache.h
+++ b/src/kiwano/utils/ResourceCache.h
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include <3rd-party/tinyxml2/tinyxml2.h>
namespace kiwano
@@ -46,11 +47,8 @@ namespace kiwano
// 从 XML 文档对象加载资源信息
bool LoadFromXml(const tinyxml2::XMLDocument* doc);
- // 添加帧图像
- bool AddFrame(String const& id, String const& file_path);
-
- // 添加帧图像
- bool AddFrame(String const& id, FramePtr frame);
+ // 添加对象
+ bool AddObject(String const& id, ObjectBasePtr obj);
// 添加序列帧
size_t AddFrameSequence(String const& id, Vector const& files);
@@ -59,46 +57,18 @@ namespace kiwano
// 按行列数裁剪图片
size_t AddFrameSequence(String const& id, String const& file_path, int cols, int rows = 1, float padding_x = 0, float padding_y = 0);
- // 添加序列帧
- size_t AddFrameSequence(String const& id, FrameSequencePtr frames);
-
- // 添加对象
- bool AddObjectBase(String const& id, ObjectBasePtr obj);
-
- // 添加 GIF 图像
- bool AddGifImage(String const& id, GifImagePtr gif);
-
- // 添加 GIF 图像
- bool AddGifImage(String const& id, String const& file_path);
-
- // 添加字体集
- bool AddFontCollection(String const& id, FontCollection const& collection);
-
- // 获取帧图像
- FramePtr GetFrame(String const& id) const;
-
- // 获取序列帧
- FrameSequencePtr GetFrameSequence(String const& id) const;
-
- // 获取 GIF 图像
- GifImagePtr GetGifImage(String const& id) const;
-
- // 获取字体集
- FontCollection GetFontCollection(String const& id) const;
-
// 删除指定资源
void Remove(String const& id);
// 清空所有资源
void Clear();
+ ObjectBasePtr Get(String const& id) const;
+
template
- _Ty* Get(String const& id) const
+ SmartPtr<_Ty> Get(String const& id) const
{
- auto iter = object_cache_.find(id);
- if (iter == object_cache_.end())
- return nullptr;
- return const_cast<_Ty*>(dynamic_cast((*iter).second.get()));
+ return dynamic_cast<_Ty*>(Get(id).get());
}
private:
@@ -107,7 +77,6 @@ namespace kiwano
virtual ~ResourceCache();
private:
- UnorderedMap object_cache_;
- UnorderedMap font_collection_cache_;
+ UnorderedMap object_cache_;
};
}