From ed79c69e7a7089a2bdecde1b7f6d972340b95f46 Mon Sep 17 00:00:00 2001
From: Nomango <569629550@qq.com>
Date: Thu, 15 Aug 2019 11:22:51 +0800
Subject: [PATCH 1/8] Add TextFormat && TextLayout
---
appveyor.yml | 25 ++--
projects/kiwano.vcxproj | 2 +
projects/kiwano.vcxproj.filters | 6 +
src/kiwano/2d/Actor.cpp | 2 +-
src/kiwano/2d/Canvas.cpp | 9 +-
src/kiwano/2d/DebugActor.cpp | 3 +-
src/kiwano/2d/Text.cpp | 165 +++------------------
src/kiwano/2d/Text.h | 67 ++-------
src/kiwano/2d/TextStyle.hpp | 6 +-
src/kiwano/base/Director.cpp | 2 +
src/kiwano/renderer/D2DDeviceResources.cpp | 117 +++++++--------
src/kiwano/renderer/D2DDeviceResources.h | 8 +-
src/kiwano/renderer/Renderer.cpp | 67 ++++++++-
src/kiwano/renderer/Renderer.h | 59 +++++---
src/kiwano/renderer/TextLayout.cpp | 110 ++++++++++++++
src/kiwano/renderer/TextLayout.h | 80 ++++++++++
16 files changed, 408 insertions(+), 320 deletions(-)
create mode 100644 src/kiwano/renderer/TextLayout.cpp
create mode 100644 src/kiwano/renderer/TextLayout.h
diff --git a/appveyor.yml b/appveyor.yml
index dc89cd0d..27df39b0 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -47,6 +47,14 @@ only_commits:
- scripts/**/*.ps1
- appveyor.yml
+for:
+-
+ branches:
+ except:
+ - master
+ only_commits:
+ message: /\[build\]/
+
configuration:
- Debug
- Release
@@ -67,19 +75,8 @@ build:
project: projects/Kiwano.sln
verbosity: minimal
-for:
--
- branches:
- except:
- - master
- only_commits:
- message: /\[build\]/
--
- branches:
- only:
- - master
- after_build:
- - ps: .\scripts\appveyor\wait_for_other_jobs.ps1
+after_build:
+- ps: .\scripts\appveyor\wait_for_other_jobs.ps1
artifacts:
- path: projects/output/**/*.lib
@@ -119,6 +116,6 @@ notifications:
- provider: Email
to:
- 569629550@qq.com
- on_build_success: false
+ on_build_success: true
on_build_failure: true
on_build_status_changed: false
\ No newline at end of file
diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj
index 2931f641..f7b0ef14 100644
--- a/projects/kiwano.vcxproj
+++ b/projects/kiwano.vcxproj
@@ -77,6 +77,7 @@
+
@@ -130,6 +131,7 @@
+
diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters
index 1be66a3b..ebebec18 100644
--- a/projects/kiwano.vcxproj.filters
+++ b/projects/kiwano.vcxproj.filters
@@ -288,6 +288,9 @@
renderer
+
+ renderer
+
@@ -443,5 +446,8 @@
renderer
+
+ renderer
+
\ No newline at end of file
diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp
index 2db554b4..0d2b740d 100644
--- a/src/kiwano/2d/Actor.cpp
+++ b/src/kiwano/2d/Actor.cpp
@@ -131,7 +131,7 @@ namespace kiwano
auto renderer = Renderer::GetInstance();
renderer->SetTransform(transform_matrix_);
renderer->FillRectangle(bounds, Color(Color::Red, .4f));
- renderer->DrawRectangle(bounds, Color(Color::Red, .8f), 4.f);
+ renderer->DrawRectangle(bounds, Color(Color::Red, .8f), 2.f);
}
for (auto child = children_.first_item(); child; child = child->next_item())
diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp
index c9f01d1b..61f8950a 100644
--- a/src/kiwano/2d/Canvas.cpp
+++ b/src/kiwano/2d/Canvas.cpp
@@ -275,21 +275,18 @@ namespace kiwano
ThrowIfFailed(
Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextFormat(
text_format_,
- text_font_,
- text_style_
+ text_font_
)
);
}
ComPtr text_layout;
- Size layout_size;
ThrowIfFailed(
Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextLayout(
text_layout,
- layout_size,
text,
- text_format_,
- text_style_
+ text_style_,
+ text_format_
)
);
diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp
index e7429567..0dbe72d3 100644
--- a/src/kiwano/2d/DebugActor.cpp
+++ b/src/kiwano/2d/DebugActor.cpp
@@ -46,7 +46,6 @@ namespace kiwano
debug_text_->SetFont(font);
TextStyle style;
- style.wrap = false;
style.line_spacing = 20.f;
debug_text_->SetStyle(style);
@@ -98,7 +97,7 @@ namespace kiwano
ss << "Memory: " << pmc.PrivateUsage / 1024 << "kb";
debug_text_->SetText(ss.str());
- SetSize(Size{ 20 + debug_text_->GetLayoutSize().x, 20 + debug_text_->GetLayoutSize().y });
+ SetSize(Size{ 20 + debug_text_->GetSize().x, 20 + debug_text_->GetSize().y });
}
}
diff --git a/src/kiwano/2d/Text.cpp b/src/kiwano/2d/Text.cpp
index 84fae7f8..1ea74555 100644
--- a/src/kiwano/2d/Text.cpp
+++ b/src/kiwano/2d/Text.cpp
@@ -44,6 +44,7 @@ namespace kiwano
: font_(text_default_font)
, style_(text_default_style)
, layout_dirty_(false)
+ , format_dirty_(false)
{
}
@@ -74,96 +75,6 @@ namespace kiwano
{
}
- String const& Text::GetText() const
- {
- return text_;
- }
-
- const Font& Text::GetFont() const
- {
- return font_;
- }
-
- const TextStyle& Text::GetStyle() const
- {
- return style_;
- }
-
- String const& Text::GetFontFamily() const
- {
- return font_.family;
- }
-
- float Text::GetFontSize() const
- {
- return font_.size;
- }
-
- unsigned int Text::GetFontWeight() const
- {
- return font_.weight;
- }
-
- const Color& Text::GetColor() const
- {
- return style_.color;
- }
-
- const Color& Text::GetOutlineColor() const
- {
- return style_.outline_color;
- }
-
- float Text::GetOutlineWidth() const
- {
- return style_.outline_width;
- }
-
- StrokeStyle Text::GetOutlineStroke() const
- {
- return style_.outline_stroke;
- }
-
- int Text::GetLineCount()
- {
- UpdateLayout();
- if (text_layout_)
- {
- DWRITE_TEXT_METRICS metrics;
- if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
- {
- return static_cast(metrics.lineCount);
- }
- }
- return 0;
- }
-
- Size const& Text::GetLayoutSize() const
- {
- UpdateLayout();
- return layout_size_;
- }
-
- bool Text::IsItalic() const
- {
- return font_.italic;
- }
-
- bool Text::HasStrikethrough() const
- {
- return style_.strikethrough;
- }
-
- bool Text::HasUnderline() const
- {
- return style_.underline;
- }
-
- bool Text::HasOutline() const
- {
- return style_.outline;
- }
-
void Text::SetText(String const& text)
{
text_ = text;
@@ -179,7 +90,7 @@ namespace kiwano
void Text::SetFont(const Font & font)
{
font_ = font;
- layout_dirty_ = true;
+ format_dirty_ = true;
}
void Text::SetFontFamily(String const& family)
@@ -187,7 +98,7 @@ namespace kiwano
if (font_.family != family)
{
font_.family = family;
- layout_dirty_ = true;
+ format_dirty_ = true;
}
}
@@ -196,7 +107,7 @@ namespace kiwano
if (font_.size != size)
{
font_.size = size;
- layout_dirty_ = true;
+ format_dirty_ = true;
}
}
@@ -205,7 +116,7 @@ namespace kiwano
if (font_.weight != weight)
{
font_.weight = weight;
- layout_dirty_ = true;
+ format_dirty_ = true;
}
}
@@ -219,16 +130,7 @@ namespace kiwano
if (font_.italic != val)
{
font_.italic = val;
- layout_dirty_ = true;
- }
- }
-
- void Text::SetWrapEnabled(bool wrap)
- {
- if (style_.wrap != wrap)
- {
- style_.wrap = wrap;
- layout_dirty_ = true;
+ format_dirty_ = true;
}
}
@@ -236,12 +138,12 @@ namespace kiwano
{
if (style_.wrap_width != wrap_width)
{
- style_.wrap_width = std::max(wrap_width, 0.f);
+ style_.wrap_width = wrap_width;
layout_dirty_ = true;
}
}
- void Text::SetLineacingPtr(float line_spacing)
+ void Text::SetLineSpacing(float line_spacing)
{
if (style_.line_spacing != line_spacing)
{
@@ -301,51 +203,26 @@ namespace kiwano
{
UpdateLayout();
- if (text_layout_ && renderer->CheckVisibility(layout_size_, transform_matrix_))
+ if (text_layout_ && renderer->CheckVisibility(size_, transform_matrix_))
{
PrepareRender(renderer);
- renderer->SetTextStyle(
- GetDisplayedOpacity(),
- style_.color,
- style_.outline,
- style_.outline_color,
- style_.outline_width,
- style_.outline_stroke
- );
renderer->DrawTextLayout(text_layout_);
}
}
- void Text::UpdateLayout() const
+ void Text::UpdateLayout()
{
- if (!layout_dirty_)
- return;
+ if (format_dirty_)
+ {
+ format_dirty_ = false;
+ text_layout_.Update(font_);
+ }
- layout_dirty_ = false;
- text_format_ = nullptr;
- text_layout_ = nullptr;
-
- if (text_.empty())
- return;
-
- auto renderer = Renderer::GetInstance();
-
- ThrowIfFailed(
- renderer->GetD2DDeviceResources()->CreateTextFormat(
- text_format_,
- font_,
- style_
- )
- );
-
- ThrowIfFailed(
- renderer->GetD2DDeviceResources()->CreateTextLayout(
- text_layout_,
- layout_size_,
- text_,
- text_format_,
- style_
- )
- );
+ if (layout_dirty_)
+ {
+ layout_dirty_ = false;
+ text_layout_.Update(text_, style_);
+ SetSize(text_layout_.GetLayoutSize());
+ }
}
}
diff --git a/src/kiwano/2d/Text.h b/src/kiwano/2d/Text.h
index d2c07ce3..1877b711 100644
--- a/src/kiwano/2d/Text.h
+++ b/src/kiwano/2d/Text.h
@@ -20,9 +20,7 @@
#pragma once
#include "Actor.h"
-#include "Font.hpp"
-#include "TextStyle.hpp"
-#include
+#include "../renderer/TextLayout.h"
namespace kiwano
{
@@ -56,52 +54,16 @@ namespace kiwano
virtual ~Text();
// 获取文本
- String const& GetText() const;
+ inline String const& GetText() const { return text_; }
// 获取字体
- const Font& GetFont() const;
+ inline Font GetFont() const { return font_; }
// 获取文本样式
- const TextStyle& GetStyle() const;
+ inline TextStyle GetStyle() const { return style_; }
- // 获取字体族
- String const& GetFontFamily() const;
-
- // 获取当前字号
- float GetFontSize() const;
-
- // 获取当前字体粗细值
- unsigned int GetFontWeight() const;
-
- // 获取文字颜色
- const Color& GetColor() const;
-
- // 获取描边颜色
- const Color& GetOutlineColor() const;
-
- // 获取描边线宽
- float GetOutlineWidth() const;
-
- // 获取描边线相交样式
- StrokeStyle GetOutlineStroke() const;
-
- // 获取文本显示行数
- int GetLineCount();
-
- // 获取文字布局大小
- Size const& GetLayoutSize() const;
-
- // 是否是斜体
- bool IsItalic() const;
-
- // 是否显示删除线
- bool HasStrikethrough() const;
-
- // 是否显示下划线
- bool HasUnderline() const;
-
- // 是否显示描边
- bool HasOutline() const;
+ // 获取文本布局
+ inline TextLayout GetLayout() const { return text_layout_; }
// 设置文本
void SetText(
@@ -143,18 +105,13 @@ namespace kiwano
bool val
);
- // 打开或关闭文本自动换行(默认为关闭)
- void SetWrapEnabled(
- bool wrap
- );
-
// 设置文本自动换行的宽度(默认为 0)
void SetWrapWidth(
float wrap_width
);
// 设置行间距(默认为 0)
- void SetLineacingPtr(
+ void SetLineSpacing(
float line_spacing
);
@@ -206,16 +163,14 @@ namespace kiwano
void OnRender(Renderer* renderer) override;
protected:
- void UpdateLayout() const;
+ void UpdateLayout();
protected:
+ bool format_dirty_;
+ bool layout_dirty_;
+ TextLayout text_layout_;
String text_;
Font font_;
TextStyle style_;
-
- mutable bool layout_dirty_;
- mutable Size layout_size_;
- mutable ComPtr text_format_;
- mutable ComPtr text_layout_;
};
}
diff --git a/src/kiwano/2d/TextStyle.hpp b/src/kiwano/2d/TextStyle.hpp
index 0cc3c51b..1e5a299d 100644
--- a/src/kiwano/2d/TextStyle.hpp
+++ b/src/kiwano/2d/TextStyle.hpp
@@ -37,7 +37,6 @@ namespace kiwano
public:
Color color; // 颜色
TextAlign alignment; // 对齐方式
- bool wrap; // 打开自动换行
float wrap_width; // 自动换行宽度
float line_spacing; // 行间距
bool underline; // 下划线
@@ -51,7 +50,6 @@ namespace kiwano
TextStyle()
: color(Color::White)
, alignment(TextAlign::Left)
- , wrap(false)
, wrap_width(0.f)
, line_spacing(0.f)
, underline(false)
@@ -65,7 +63,6 @@ namespace kiwano
TextStyle(
Color color,
TextAlign alignment = TextAlign::Left,
- bool wrap = false,
float wrap_width = 0.f,
float line_spacing = 0.f,
bool underline = false,
@@ -77,7 +74,6 @@ namespace kiwano
)
: color(color)
, alignment(alignment)
- , wrap(wrap)
, wrap_width(wrap_width)
, line_spacing(line_spacing)
, underline(underline)
@@ -88,4 +84,4 @@ namespace kiwano
, outline_stroke(outline_stroke)
{}
};
-}
\ No newline at end of file
+}
diff --git a/src/kiwano/base/Director.cpp b/src/kiwano/base/Director.cpp
index 89ee9fe4..39d5d36e 100644
--- a/src/kiwano/base/Director.cpp
+++ b/src/kiwano/base/Director.cpp
@@ -146,7 +146,9 @@ namespace kiwano
if (render_border_enabled_)
{
if (curr_scene_)
+ {
curr_scene_->RenderBorder();
+ }
}
}
diff --git a/src/kiwano/renderer/D2DDeviceResources.cpp b/src/kiwano/renderer/D2DDeviceResources.cpp
index e930829a..b94334c2 100644
--- a/src/kiwano/renderer/D2DDeviceResources.cpp
+++ b/src/kiwano/renderer/D2DDeviceResources.cpp
@@ -51,16 +51,14 @@ namespace kiwano
HRESULT CreateTextFormat(
_Out_ ComPtr& text_format,
- _In_ Font const& font,
- _In_ TextStyle const& text_style
+ _In_ Font const& font
) const override;
HRESULT CreateTextLayout(
_Out_ ComPtr& text_layout,
- _Out_ Size& layout_size,
_In_ String const& text,
- _In_ ComPtr const& text_format,
- _In_ TextStyle const& text_style
+ _In_ TextStyle const& text_style,
+ _In_ ComPtr const& text_format
) const override;
HRESULT SetD2DDevice(
@@ -460,13 +458,12 @@ namespace kiwano
return hr;
}
- HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format,
- _In_ Font const & font, _In_ TextStyle const & text_style) const
+ HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr & text_format, _In_ Font const & font) const
{
if (!dwrite_factory_)
return E_UNEXPECTED;
- ComPtr text_format_tmp;
+ ComPtr output;
HRESULT hr = dwrite_factory_->CreateTextFormat(
font.family.c_str(),
nullptr,
@@ -475,44 +472,27 @@ namespace kiwano
DWRITE_FONT_STRETCH_NORMAL,
font.size,
L"",
- &text_format_tmp
+ &output
);
if (SUCCEEDED(hr))
{
- if (text_style.line_spacing == 0.f)
- {
- text_format_tmp->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
- }
- else
- {
- text_format_tmp->SetLineSpacing(
- DWRITE_LINE_SPACING_METHOD_UNIFORM,
- text_style.line_spacing,
- text_style.line_spacing * 0.8f
- );
- }
- text_format_tmp->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(text_style.alignment));
- text_format_tmp->SetWordWrapping(text_style.wrap ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
- text_format = text_format_tmp;
+ text_format = output;
}
return hr;
}
- HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr & text_layout,
- _Out_ Size& layout_size, _In_ String const & text, _In_ ComPtr const& text_format,
- _In_ TextStyle const & text_style) const
+ HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr & text_layout, _In_ String const & text,
+ _In_ TextStyle const & text_style, _In_ ComPtr const& text_format) const
{
if (!dwrite_factory_)
return E_UNEXPECTED;
- text_layout = nullptr;
-
HRESULT hr;
- ComPtr text_layout_tmp;
+ ComPtr output;
UINT32 length = static_cast(text.length());
- if (text_style.wrap)
+ if (text_style.wrap_width > 0)
{
hr = dwrite_factory_->CreateTextLayout(
text.c_str(),
@@ -520,7 +500,7 @@ namespace kiwano
text_format.get(),
text_style.wrap_width,
0,
- &text_layout_tmp
+ &output
);
}
else
@@ -531,53 +511,70 @@ namespace kiwano
text_format.get(),
0,
0,
- &text_layout_tmp
+ &output
);
+ }
- DWRITE_TEXT_METRICS metrics;
- if (SUCCEEDED(hr))
+ if (SUCCEEDED(hr))
+ {
+ if (text_style.line_spacing == 0.f)
{
- hr = text_layout_tmp->GetMetrics(&metrics);
+ hr = output->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
}
-
- if (SUCCEEDED(hr))
+ else
{
- text_layout_tmp = nullptr;
- hr = dwrite_factory_->CreateTextLayout(
- text.c_str(),
- length,
- text_format.get(),
- metrics.width,
- 0,
- &text_layout_tmp
+ hr = output->SetLineSpacing(
+ DWRITE_LINE_SPACING_METHOD_UNIFORM,
+ text_style.line_spacing,
+ text_style.line_spacing * 0.8f
);
}
}
if (SUCCEEDED(hr))
{
- DWRITE_TEXT_METRICS metrics;
- text_layout_tmp->GetMetrics(&metrics);
+ hr = output->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(text_style.alignment));
+ }
- if (text_style.wrap)
- {
- layout_size = Size(metrics.layoutWidth, metrics.height);
- }
- else
- {
- layout_size = Size(metrics.width, metrics.height);
- }
+ if (SUCCEEDED(hr))
+ {
+ hr = output->SetWordWrapping((text_style.wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
+ }
- DWRITE_TEXT_RANGE range = { 0, length };
+ if (SUCCEEDED(hr))
+ {
if (text_style.underline)
{
- text_layout_tmp->SetUnderline(true, range);
+ hr = output->SetUnderline(true, { 0, length });
}
+ }
+
+ if (SUCCEEDED(hr))
+ {
if (text_style.strikethrough)
{
- text_layout_tmp->SetStrikethrough(true, range);
+ output->SetStrikethrough(true, { 0, length });
}
- text_layout = text_layout_tmp;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Fix the layout width when the text does not wrap
+ if (!(text_style.wrap_width > 0))
+ {
+ DWRITE_TEXT_METRICS metrics;
+ hr = output->GetMetrics(&metrics);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = output->SetMaxWidth(metrics.width);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ text_layout = output;
}
return hr;
}
diff --git a/src/kiwano/renderer/D2DDeviceResources.h b/src/kiwano/renderer/D2DDeviceResources.h
index f112b3ef..a425f806 100644
--- a/src/kiwano/renderer/D2DDeviceResources.h
+++ b/src/kiwano/renderer/D2DDeviceResources.h
@@ -48,16 +48,14 @@ namespace kiwano
virtual HRESULT CreateTextFormat(
_Out_ ComPtr& text_format,
- _In_ Font const& font,
- _In_ TextStyle const& text_style
+ _In_ Font const& font
) const = 0;
virtual HRESULT CreateTextLayout(
_Out_ ComPtr& text_layout,
- _Out_ Size& layout_size,
_In_ String const& text,
- _In_ ComPtr const& text_format,
- _In_ TextStyle const& text_style
+ _In_ TextStyle const& text_style,
+ _In_ ComPtr const& text_format
) const = 0;
virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0;
diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp
index 77361827..60c365dd 100644
--- a/src/kiwano/renderer/Renderer.cpp
+++ b/src/kiwano/renderer/Renderer.cpp
@@ -245,6 +245,55 @@ namespace kiwano
ThrowIfFailed(hr);
}
+ void Renderer::CreateTextFormat(TextFormat& format, Font const& font)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr output;
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->CreateTextFormat(output, font);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ format.SetTextFormat(output);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextStyle const& style, TextFormat const& format)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr output;
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->CreateTextLayout(
+ output,
+ text,
+ style,
+ format.GetTextFormat()
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ layout.SetTextLayout(output);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
void Renderer::CreateLineGeometry(Geometry& geo, Point const& begin_pos, Point const& end_pos)
{
HRESULT hr = S_OK;
@@ -500,7 +549,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void Renderer::DrawTextLayout(ComPtr const& text_layout)
+ void Renderer::DrawTextLayout(TextLayout const& layout)
{
HRESULT hr = S_OK;
if (!text_renderer_)
@@ -510,7 +559,19 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- hr = text_layout->Draw(nullptr, text_renderer_.get(), 0, 0);
+ SetTextStyle(
+ opacity_,
+ layout.GetTextStyle().color,
+ layout.GetTextStyle().outline,
+ layout.GetTextStyle().outline_color,
+ layout.GetTextStyle().outline_width,
+ layout.GetTextStyle().outline_stroke
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), 0, 0);
IncreasePrimitivesCount();
}
@@ -676,7 +737,7 @@ namespace kiwano
)
{
HRESULT hr = S_OK;
- if (!text_renderer_ || !d3d_res_)
+ if (!text_renderer_)
{
hr = E_UNEXPECTED;
}
diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h
index a365a6cb..aa4b88f0 100644
--- a/src/kiwano/renderer/Renderer.h
+++ b/src/kiwano/renderer/Renderer.h
@@ -23,11 +23,10 @@
#include "../base/Component.h"
#include "../base/Resource.h"
#include "../2d/include-forwards.h"
-#include "../2d/Font.hpp"
-#include "../2d/TextStyle.hpp"
#include "helper.hpp"
#include "Image.h"
#include "Geometry.h"
+#include "TextLayout.h"
#include "TextRenderer.h"
#if defined(KGE_USE_DIRECTX10)
@@ -51,11 +50,44 @@ namespace kiwano
{
KGE_DECLARE_SINGLETON(Renderer);
+ public:
+ // 设置清屏颜色
+ void SetClearColor(
+ Color const& clear_color
+ );
+
+ // 设置抗锯齿模式
+ void SetAntialiasMode(
+ bool enabled
+ );
+
+ // 设置文字抗锯齿模式
+ void SetTextAntialiasMode(
+ TextAntialias mode
+ );
+
+ // 开启或关闭垂直同步
+ void SetVSyncEnabled(
+ bool enabled
+ );
+
public:
void CreateLayer(
ComPtr& layer
);
+ void CreateTextFormat(
+ TextFormat& format,
+ Font const& font
+ );
+
+ void CreateTextLayout(
+ TextLayout& layout,
+ String const& text,
+ TextStyle const& style,
+ TextFormat const& format
+ );
+
void CreateLineGeometry(
Geometry& geo,
Point const& begin_pos,
@@ -114,30 +146,9 @@ namespace kiwano
);
void DrawTextLayout(
- ComPtr const& text_layout
+ TextLayout const& layout
);
- // 设置清屏颜色
- void SetClearColor(
- Color const& clear_color
- );
-
- // 设置抗锯齿模式
- void SetAntialiasMode(
- bool enabled
- );
-
- // 设置文字抗锯齿模式
- void SetTextAntialiasMode(
- TextAntialias mode
- );
-
- // 开启或关闭垂直同步
- void SetVSyncEnabled(
- bool enabled
- );
-
- // 设置画笔透明度
void SetOpacity(
float opacity
);
diff --git a/src/kiwano/renderer/TextLayout.cpp b/src/kiwano/renderer/TextLayout.cpp
new file mode 100644
index 00000000..a18247d6
--- /dev/null
+++ b/src/kiwano/renderer/TextLayout.cpp
@@ -0,0 +1,110 @@
+// 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 "TextLayout.h"
+#include "Renderer.h"
+#include "../base/Logger.h"
+
+namespace kiwano
+{
+ //
+ // TextFormat
+ //
+
+ TextFormat::TextFormat()
+ {
+ }
+
+ TextFormat::TextFormat(Font const& font)
+ {
+ Update(font);
+ }
+
+ void TextFormat::Update(Font const& font)
+ {
+ Renderer::GetInstance()->CreateTextFormat(*this, font);
+ }
+
+
+ //
+ // TextLayout
+ //
+
+ TextLayout::TextLayout()
+ {
+ }
+
+ TextLayout::TextLayout(String const& text, Font const& font, TextStyle const& style)
+ {
+ Update(font);
+ Update(text, style);
+ }
+
+ void TextLayout::Update(Font const& font)
+ {
+ text_format_.Update(font);
+ }
+
+ void TextLayout::Update(String const& text, TextStyle const& style)
+ {
+ style_ = style;
+
+ if (text.empty())
+ {
+ text_format_.SetTextFormat(nullptr);
+ SetTextLayout(nullptr);
+ return;
+ }
+
+ Renderer::GetInstance()->CreateTextLayout(
+ *this,
+ text,
+ style,
+ text_format_
+ );
+ }
+
+ UINT32 TextLayout::GetLineCount()
+ {
+ if (text_layout_)
+ {
+ DWRITE_TEXT_METRICS metrics;
+ if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
+ {
+ return metrics.lineCount;
+ }
+ }
+ return 0;
+ }
+
+ Size TextLayout::GetLayoutSize() const
+ {
+ if (text_layout_)
+ {
+ DWRITE_TEXT_METRICS metrics;
+ if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
+ {
+ return (metrics.layoutWidth > 0) ? Size(metrics.layoutWidth, metrics.height) : Size(metrics.width, metrics.height);
+ }
+ }
+ return Size();
+ }
+
+}
diff --git a/src/kiwano/renderer/TextLayout.h b/src/kiwano/renderer/TextLayout.h
new file mode 100644
index 00000000..a9aebe9c
--- /dev/null
+++ b/src/kiwano/renderer/TextLayout.h
@@ -0,0 +1,80 @@
+// 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 "D2DDeviceResources.h"
+#include "../2d/Font.hpp"
+#include "../2d/TextStyle.hpp"
+
+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; }
+
+ protected:
+ ComPtr text_format_;
+ };
+
+
+ // 文本布局
+ class KGE_API TextLayout
+ {
+ public:
+ TextLayout();
+
+ TextLayout(String const& text, Font const& font, TextStyle const& style);
+
+ void Update(Font const& font);
+
+ void Update(String const& text, TextStyle const& style);
+
+ UINT32 GetLineCount();
+
+ Size GetLayoutSize() const;
+
+ inline TextStyle const& GetTextStyle() const { return style_; }
+
+ public:
+ inline TextFormat GetTextFormat() const { return text_format_; }
+
+ inline ComPtr GetTextLayout() const { return text_layout_; }
+
+ inline void SetTextLayout(ComPtr layout) { text_layout_ = layout; }
+
+ inline operator bool() const { return static_cast(text_layout_); }
+
+ protected:
+ TextStyle style_;
+ TextFormat text_format_;
+ ComPtr text_layout_;
+ };
+}
From 7257ebf12b90030d4dceb440f6eabbf0ff9774df Mon Sep 17 00:00:00 2001
From: Nomango <569629550@qq.com>
Date: Fri, 16 Aug 2019 00:50:54 +0800
Subject: [PATCH 2/8] Add RenderTarget
---
projects/kiwano.vcxproj | 2 +
projects/kiwano.vcxproj.filters | 6 +
src/kiwano/2d/Canvas.cpp | 422 ++++++-----------
src/kiwano/2d/Canvas.h | 140 +++---
src/kiwano/2d/Frame.cpp | 20 +-
src/kiwano/2d/Frame.h | 10 +-
src/kiwano/2d/GifSprite.cpp | 188 +++++---
src/kiwano/2d/GifSprite.h | 47 +-
src/kiwano/2d/ShapeActor.cpp | 8 +-
src/kiwano/2d/ShapeActor.h | 12 +-
src/kiwano/2d/Sprite.cpp | 8 +-
src/kiwano/2d/Sprite.h | 2 +-
src/kiwano/2d/Text.cpp | 2 +-
src/kiwano/2d/Transition.cpp | 16 +-
src/kiwano/base/types.h | 4 +-
src/kiwano/kiwano.h | 25 +-
src/kiwano/renderer/GifImage.cpp | 513 ++++++++-------------
src/kiwano/renderer/GifImage.h | 69 ++-
src/kiwano/renderer/Image.cpp | 53 ++-
src/kiwano/renderer/Image.h | 21 +-
src/kiwano/renderer/ImageCache.cpp | 60 ++-
src/kiwano/renderer/ImageCache.h | 14 +-
src/kiwano/renderer/RenderTarget.cpp | 660 +++++++++++++++++++++++++++
src/kiwano/renderer/RenderTarget.h | 207 +++++++++
src/kiwano/renderer/Renderer.cpp | 581 ++++++-----------------
src/kiwano/renderer/Renderer.h | 125 +----
src/kiwano/utils/ResourceCache.cpp | 4 +-
27 files changed, 1814 insertions(+), 1405 deletions(-)
create mode 100644 src/kiwano/renderer/RenderTarget.cpp
create mode 100644 src/kiwano/renderer/RenderTarget.h
diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj
index f7b0ef14..c9958130 100644
--- a/projects/kiwano.vcxproj
+++ b/projects/kiwano.vcxproj
@@ -77,6 +77,7 @@
+
@@ -131,6 +132,7 @@
+
diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters
index ebebec18..b3b2d69d 100644
--- a/projects/kiwano.vcxproj.filters
+++ b/projects/kiwano.vcxproj.filters
@@ -291,6 +291,9 @@
renderer
+
+ renderer
+
@@ -449,5 +452,8 @@
renderer
+
+ renderer
+
\ No newline at end of file
diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp
index 61f8950a..cef8a6fb 100644
--- a/src/kiwano/2d/Canvas.cpp
+++ b/src/kiwano/2d/Canvas.cpp
@@ -27,35 +27,11 @@ namespace kiwano
Canvas::Canvas()
: cache_expired_(false)
, stroke_width_(1.0f)
+ , fill_color_(0, 0, 0)
+ , stroke_color_(Color::White)
+ , stroke_style_(StrokeStyle::Miter)
{
- auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
-
- ThrowIfFailed(
- ctx->CreateCompatibleRenderTarget(&render_target_)
- );
-
- ThrowIfFailed(
- render_target_->CreateSolidColorBrush(
- D2D1::ColorF(0, 0, 0, 0),
- D2D1::BrushProperties(),
- &fill_brush_)
- );
-
- ThrowIfFailed(
- render_target_->CreateSolidColorBrush(
- D2D1::ColorF(Color::White),
- D2D1::BrushProperties(),
- &stroke_brush_)
- );
-
- ThrowIfFailed(
- ITextRenderer::Create(
- &text_renderer_,
- render_target_.get()
- )
- );
-
- SetTextStyle(Font{}, TextStyle{});
+ Renderer::GetInstance()->CreateImageRenderTarget(rt_);
}
Canvas::Canvas(float width, float height)
@@ -75,45 +51,36 @@ namespace kiwano
void Canvas::BeginDraw()
{
- render_target_->BeginDraw();
+ rt_.BeginDraw();
}
void Canvas::EndDraw()
{
- ThrowIfFailed(
- render_target_->EndDraw()
- );
+ rt_.EndDraw();
cache_expired_ = true;
}
void Canvas::OnRender(Renderer* renderer)
{
- if (cache_expired_)
- {
- GetBitmap();
- }
+ UpdateCache();
- if (bitmap_cached_)
+ if (image_cached_.IsValid())
{
PrepareRender(renderer);
- Rect bitmap_rect(0.f, 0.f, bitmap_cached_->GetSize().width, bitmap_cached_->GetSize().height);
- renderer->DrawBitmap(
- bitmap_cached_,
- bitmap_rect,
- bitmap_rect
- );
+ Rect bitmap_rect(0.f, 0.f, image_cached_.GetWidth(), image_cached_.GetHeight());
+ renderer->DrawImage(image_cached_, bitmap_rect, bitmap_rect);
}
}
void Canvas::SetStrokeColor(Color const& color)
{
- stroke_brush_->SetColor(DX::ConvertToColorF(color));
+ stroke_color_ = color;
}
void Canvas::SetFillColor(Color const& color)
{
- fill_brush_->SetColor(DX::ConvertToColorF(color));
+ fill_color_ = color;
}
void Canvas::SetStrokeWidth(float width)
@@ -121,39 +88,34 @@ namespace kiwano
stroke_width_ = std::max(width, 0.f);
}
- void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join)
+ void Canvas::SetStrokeStyle(StrokeStyle stroke_style)
{
- outline_join_style_ = Renderer::GetInstance()->GetD2DDeviceResources()->GetStrokeStyle(outline_join);
+ stroke_style_ = stroke_style;
}
- void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style)
+ void Canvas::SetTextFont(Font const& font)
{
text_font_ = font;
+ }
+
+ void Canvas::SetTextStyle(TextStyle const & text_style)
+ {
text_style_ = text_style;
+ }
- text_renderer_->SetTextStyle(
- 1.f,
- DX::ConvertToColorF(text_style_.color),
- text_style_.outline,
- DX::ConvertToColorF(text_style_.outline_color),
- text_style_.outline_width,
- Renderer::GetInstance()->GetD2DDeviceResources()->GetStrokeStyle(text_style_.outline_stroke)
- );
-
- // clear text format
- text_format_ = nullptr;
+ void Canvas::SetBrushOpacity(float opacity)
+ {
+ rt_.SetOpacity(opacity);
}
Color Canvas::GetStrokeColor() const
{
- auto color_f = stroke_brush_->GetColor();
- return Color{ color_f.r, color_f.g, color_f.b, color_f.a };
+ return stroke_color_;
}
Color Canvas::GetFillColor() const
{
- auto color_f = fill_brush_->GetColor();
- return Color{ color_f.r, color_f.g, color_f.b, color_f.a };
+ return fill_color_;
}
float Canvas::GetStrokeWidth() const
@@ -161,321 +123,219 @@ namespace kiwano
return stroke_width_;
}
+ float Canvas::GetBrushOpacity() const
+ {
+ return rt_.GetOpacity();
+ }
+
+ void Canvas::SetBrushTransform(Transform const& transform)
+ {
+ Matrix3x2 matrix = Matrix3x2::SRT(transform.position, transform.scale, transform.rotation);
+ if (!transform.skew.IsOrigin())
+ {
+ matrix = Matrix3x2::Skewing(transform.skew) * matrix;
+ }
+
+ rt_.SetTransform(matrix);
+ }
+
void Canvas::SetBrushTransform(Matrix3x2 const & transform)
{
- render_target_->SetTransform(DX::ConvertToMatrix3x2F(transform));
+ rt_.SetTransform(transform);
}
- void Canvas::DrawLine(const Point & begin, const Point & end)
+ void Canvas::DrawLine(Point const& begin, Point const& end)
{
- render_target_->DrawLine(
- D2D1::Point2F(begin.x, begin.y),
- D2D1::Point2F(end.x, end.y),
- stroke_brush_.get(),
+ rt_.DrawLine(
+ begin,
+ end,
+ stroke_color_,
stroke_width_,
- outline_join_style_.get()
+ stroke_style_
);
cache_expired_ = true;
}
- void Canvas::DrawCircle(const Point & center, float radius)
+ void Canvas::DrawCircle(Point const& center, float radius)
{
- render_target_->DrawEllipse(
- D2D1::Ellipse(
- D2D1::Point2F(
- center.x,
- center.y
- ),
- radius,
- radius
- ),
- stroke_brush_.get(),
+ rt_.DrawEllipse(
+ center,
+ Vec2(radius, radius),
+ stroke_color_,
stroke_width_,
- outline_join_style_.get()
+ stroke_style_
);
cache_expired_ = true;
}
- void Canvas::DrawEllipse(const Point & center, float radius_x, float radius_y)
+ void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
{
- render_target_->DrawEllipse(
- D2D1::Ellipse(
- D2D1::Point2F(
- center.x,
- center.y
- ),
- radius_x,
- radius_y
- ),
- stroke_brush_.get(),
+ rt_.DrawEllipse(
+ center,
+ radius,
+ stroke_color_,
stroke_width_,
- outline_join_style_.get()
+ stroke_style_
);
cache_expired_ = true;
}
- void Canvas::DrawRect(const Rect & rect)
+ void Canvas::DrawRect(Rect const& rect)
{
- render_target_->DrawRectangle(
- D2D1::RectF(
- rect.origin.x,
- rect.origin.y,
- rect.origin.x + rect.size.x,
- rect.origin.y + rect.size.y
- ),
- stroke_brush_.get(),
+ rt_.DrawRectangle(
+ rect,
+ stroke_color_,
stroke_width_,
- outline_join_style_.get()
+ stroke_style_
);
cache_expired_ = true;
}
- void Canvas::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y)
+ void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
{
- render_target_->DrawRoundedRectangle(
- D2D1::RoundedRect(
- D2D1::RectF(
- rect.origin.x,
- rect.origin.y,
- rect.origin.x + rect.size.x,
- rect.origin.y + rect.size.y
- ),
- radius_x,
- radius_y
- ),
- stroke_brush_.get(),
+ rt_.DrawRoundedRectangle(
+ rect,
+ radius,
+ stroke_color_,
stroke_width_,
- outline_join_style_.get()
+ stroke_style_
);
cache_expired_ = true;
}
- void Canvas::DrawImage(ImagePtr image, float opacity)
+ void Canvas::FillCircle(Point const& center, float radius)
{
- if (image && image->GetBitmap())
+ rt_.FillEllipse(
+ center,
+ Vec2(radius, radius),
+ fill_color_
+ );
+ cache_expired_ = true;
+ }
+
+ void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
+ {
+ rt_.FillEllipse(
+ center,
+ radius,
+ fill_color_
+ );
+ cache_expired_ = true;
+ }
+
+ void Canvas::FillRect(Rect const& rect)
+ {
+ rt_.FillRectangle(
+ rect,
+ fill_color_
+ );
+ cache_expired_ = true;
+ }
+
+ void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
+ {
+ rt_.FillRoundedRectangle(
+ rect,
+ radius,
+ fill_color_
+ );
+ cache_expired_ = true;
+ }
+
+ void Canvas::DrawImage(Image const& image, const Rect* src_rect, const Rect* dest_rect)
+ {
+ if (image.IsValid())
{
- render_target_->DrawBitmap(
- image->GetBitmap().get(),
- D2D1::RectF(0, 0, image->GetWidth(), image->GetHeight()),
- opacity,
- D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
- D2D1::RectF(0, 0, image->GetWidth(), image->GetHeight())
- );
+ rt_.DrawImage(image, src_rect, dest_rect);
cache_expired_ = true;
}
}
- void Canvas::DrawText(String const & text, Point const & point)
+ void Canvas::DrawText(String const& text, Point const& point)
{
if (text.empty())
return;
- if (!text_format_)
- {
- ThrowIfFailed(
- Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextFormat(
- text_format_,
- text_font_
- )
- );
- }
+ TextLayout layout(text, text_font_, text_style_);
- ComPtr text_layout;
- ThrowIfFailed(
- Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextLayout(
- text_layout,
- text,
- text_style_,
- text_format_
- )
- );
-
- ThrowIfFailed(
- text_layout->Draw(nullptr, text_renderer_.get(), point.x, point.y)
- );
- }
-
- void Canvas::FillCircle(const Point & center, float radius)
- {
- render_target_->FillEllipse(
- D2D1::Ellipse(
- D2D1::Point2F(
- center.x,
- center.y
- ),
- radius,
- radius
- ),
- fill_brush_.get()
- );
- cache_expired_ = true;
- }
-
- void Canvas::FillEllipse(const Point & center, float radius_x, float radius_y)
- {
- render_target_->FillEllipse(
- D2D1::Ellipse(
- D2D1::Point2F(
- center.x,
- center.y
- ),
- radius_x,
- radius_y
- ),
- fill_brush_.get()
- );
- cache_expired_ = true;
- }
-
- void Canvas::FillRect(const Rect & rect)
- {
- render_target_->FillRectangle(
- D2D1::RectF(
- rect.origin.x,
- rect.origin.y,
- rect.origin.x + rect.size.x,
- rect.origin.y + rect.size.y
- ),
- fill_brush_.get()
- );
- cache_expired_ = true;
- }
-
- void Canvas::FillRoundedRect(const Rect & rect, float radius_x, float radius_y)
- {
- render_target_->FillRoundedRectangle(
- D2D1::RoundedRect(
- D2D1::RectF(
- rect.origin.x,
- rect.origin.y,
- rect.origin.x + rect.size.x,
- rect.origin.y + rect.size.y
- ),
- radius_x,
- radius_y
- ),
- fill_brush_.get()
- );
- cache_expired_ = true;
+ rt_.DrawTextLayout(layout, point);
}
void Canvas::BeginPath(Point const& begin_pos)
{
- current_geometry_ = nullptr;
-
- ThrowIfFailed(
- Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(¤t_geometry_)
- );
-
- ThrowIfFailed(
- current_geometry_->Open(¤t_sink_)
- );
-
- current_sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
+ geo_sink_.BeginPath(begin_pos);
}
void Canvas::EndPath(bool closed)
{
- if (current_sink_)
- {
- current_sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
- ThrowIfFailed(
- current_sink_->Close()
- );
- current_sink_ = nullptr;
- }
+ geo_sink_.EndPath(closed);
}
void Canvas::AddLine(Point const & point)
{
- if (current_sink_)
- current_sink_->AddLine(DX::ConvertToPoint2F(point));
+ geo_sink_.AddLine(point);
}
void Canvas::AddLines(Vector const& points)
{
- if (current_sink_ && !points.empty())
- {
- current_sink_->AddLines(
- reinterpret_cast(&points[0]),
- static_cast(points.size())
- );
- }
+ geo_sink_.AddLines(points);
}
void Canvas::AddBezier(Point const & point1, Point const & point2, Point const & point3)
{
- if (current_sink_)
- {
- current_sink_->AddBezier(
- D2D1::BezierSegment(
- DX::ConvertToPoint2F(point1),
- DX::ConvertToPoint2F(point2),
- DX::ConvertToPoint2F(point3)
- )
- );
- }
+ geo_sink_.AddBezier(point1, point2, point3);
}
void Canvas::AddArc(Point const & point, Point const & radius, float rotation, bool clockwise, bool is_small)
{
- if (current_sink_)
- {
- current_sink_->AddArc(
- D2D1::ArcSegment(
- DX::ConvertToPoint2F(point),
- DX::ConvertToSizeF(radius),
- rotation,
- clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
- is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
- )
- );
- }
+ geo_sink_.AddArc(point, radius, rotation, clockwise, is_small);
}
void Canvas::StrokePath()
{
- render_target_->DrawGeometry(
- current_geometry_.get(),
- stroke_brush_.get(),
+ rt_.DrawGeometry(
+ geo_sink_.GetGeometry(),
+ stroke_color_,
stroke_width_,
- outline_join_style_.get()
+ stroke_style_
);
cache_expired_ = true;
}
void Canvas::FillPath()
{
- render_target_->FillGeometry(
- current_geometry_.get(),
- fill_brush_.get()
+ rt_.FillGeometry(
+ geo_sink_.GetGeometry(),
+ fill_color_
);
cache_expired_ = true;
}
void Canvas::Clear()
{
- render_target_->Clear();
+ rt_.Clear();
cache_expired_ = true;
}
- ImagePtr Canvas::ExportToImage() const
+ void Canvas::Clear(Color const& clear_color)
{
- ImagePtr image = new Image(GetBitmap());
- return image;
+ rt_.Clear(clear_color);
+ cache_expired_ = true;
}
- ComPtr const& kiwano::Canvas::GetBitmap() const
+ Image Canvas::ExportToImage() const
+ {
+ UpdateCache();
+ return image_cached_;
+ }
+
+ void Canvas::UpdateCache() const
{
if (cache_expired_)
{
- bitmap_cached_ = nullptr;
- ThrowIfFailed(
- render_target_->GetBitmap(&bitmap_cached_)
- );
+ rt_.GetOutput(image_cached_);
cache_expired_ = false;
}
- return bitmap_cached_;
}
}
diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h
index add2a2c1..6508ebd0 100644
--- a/src/kiwano/2d/Canvas.h
+++ b/src/kiwano/2d/Canvas.h
@@ -20,10 +20,7 @@
#pragma once
#include "Actor.h"
-#include "Font.hpp"
-#include "TextStyle.hpp"
-#include "../renderer/Image.h"
-#include "../renderer/TextRenderer.h"
+#include "../renderer/RenderTarget.h"
#ifdef DrawText
# undef DrawText
@@ -57,39 +54,61 @@ namespace kiwano
// 画直线
void DrawLine(
- const Point& begin,
- const Point& end
+ Point const& begin,
+ Point const& end
);
// 画圆形边框
void DrawCircle(
- const Point& center,
+ Point const& center,
float radius
);
// 画椭圆形边框
void DrawEllipse(
- const Point& center,
- float radius_x,
- float radius_y
+ Point const& center,
+ Vec2 const& radius
);
// 画矩形边框
void DrawRect(
- const Rect& rect
+ Rect const& rect
);
// 画圆角矩形边框
void DrawRoundedRect(
- const Rect& rect,
- float radius_x,
- float radius_y
+ Rect const& rect,
+ Vec2 const& radius
+ );
+
+ // 填充圆形
+ void FillCircle(
+ Point const& center,
+ float radius
+ );
+
+ // 填充椭圆形
+ void FillEllipse(
+ Point const& center,
+ Vec2 const& radius
+ );
+
+ // 填充矩形
+ void FillRect(
+ Rect const& rect
+ );
+
+ // 填充圆角矩形
+ void FillRoundedRect(
+ Rect const& rect,
+ Vec2 const& radius
);
// 画图片
void DrawImage(
- ImagePtr image,
- float opacity = 1.f
+ Image const& image,
+ const Rect* src_rect = nullptr,
+ const Rect* dest_rect = nullptr
);
// 画文字
@@ -98,31 +117,6 @@ namespace kiwano
Point const& point /* 文字位置 */
);
- // 填充圆形
- void FillCircle(
- const Point& center,
- float radius
- );
-
- // 填充椭圆形
- void FillEllipse(
- const Point& center,
- float radius_x,
- float radius_y
- );
-
- // 填充矩形
- void FillRect(
- const Rect& rect
- );
-
- // 填充圆角矩形
- void FillRoundedRect(
- const Rect& rect,
- float radius_x,
- float radius_y
- );
-
// 开始绘制路径
void BeginPath(
Point const& begin_pos /* 路径起始点 */
@@ -168,14 +162,19 @@ namespace kiwano
// 清空画布
void Clear();
+ // 清空画布
+ void Clear(
+ Color const& clear_color
+ );
+
// 设置填充颜色
void SetFillColor(
- const Color& color
+ Color const& color
);
// 设置线条颜色
void SetStrokeColor(
- const Color& color
+ Color const& color
);
// 设置线条宽度
@@ -183,17 +182,26 @@ namespace kiwano
float width
);
- // 设置线条相交样式
- void SetOutlineJoinStyle(
- StrokeStyle outline_join
+ // 设置线条样式
+ void SetStrokeStyle(
+ StrokeStyle stroke_style
+ );
+
+ // 设置文字字体
+ void SetTextFont(
+ Font const& font
);
// 设置文字画刷样式
void SetTextStyle(
- Font const& font,
TextStyle const& text_style
);
+ // 设置画笔透明度
+ void SetBrushOpacity(
+ float opacity
+ );
+
// 获取填充颜色
Color GetFillColor() const;
@@ -203,34 +211,38 @@ namespace kiwano
// 获取线条宽度
float GetStrokeWidth() const;
- // 变换画笔
+ // 获取画笔透明度
+ float GetBrushOpacity() const;
+
+ // 画笔二维变换
+ void SetBrushTransform(
+ Transform const& transform
+ );
+
+ // 画笔二维变换
void SetBrushTransform(
Matrix3x2 const& transform
);
// 导出为图片
- ImagePtr ExportToImage() const;
+ Image ExportToImage() const;
void OnRender(Renderer* renderer) override;
protected:
- ComPtr const& GetBitmap() const;
+ void UpdateCache() const;
protected:
- float stroke_width_;
- Font text_font_;
- TextStyle text_style_;
+ float stroke_width_;
+ Color fill_color_;
+ Color stroke_color_;
+ Font text_font_;
+ TextStyle text_style_;
+ StrokeStyle stroke_style_;
+ GeometrySink geo_sink_;
+ ImageRenderTarget rt_;
- ComPtr current_geometry_;
- ComPtr current_sink_;
- ComPtr outline_join_style_;
- ComPtr fill_brush_;
- ComPtr stroke_brush_;
- ComPtr text_format_;
- ComPtr text_renderer_;
- ComPtr render_target_;
-
- mutable bool cache_expired_;
- mutable ComPtr bitmap_cached_;
+ mutable bool cache_expired_;
+ mutable Image image_cached_;
};
}
diff --git a/src/kiwano/2d/Frame.cpp b/src/kiwano/2d/Frame.cpp
index 97781255..9fbd506e 100644
--- a/src/kiwano/2d/Frame.cpp
+++ b/src/kiwano/2d/Frame.cpp
@@ -32,15 +32,15 @@ namespace kiwano
Load(res);
}
- Frame::Frame(ImagePtr image)
+ Frame::Frame(Image const& image)
: image_(image)
{
}
bool Frame::Load(Resource const& res)
{
- ImagePtr image = ImageCache::GetInstance()->AddImage(res);
- if (image && image->IsValid())
+ Image image = ImageCache::GetInstance()->AddImage(res);
+ if (image.IsValid())
{
SetImage(image);
return true;
@@ -48,11 +48,11 @@ namespace kiwano
return false;
}
- void Frame::Crop(Rect const& crop_rect)
+ void Frame::SetCropRect(Rect const& crop_rect)
{
- if (image_)
+ if (image_.IsValid())
{
- auto bitmap_size = image_->GetSize();
+ auto bitmap_size = image_.GetSize();
crop_rect_.origin.x = std::min(std::max(crop_rect.origin.x, 0.f), bitmap_size.x);
crop_rect_.origin.y = std::min(std::max(crop_rect.origin.y, 0.f), bitmap_size.y);
crop_rect_.size.x = std::min(std::max(crop_rect.size.x, 0.f), bitmap_size.x - crop_rect.origin.x);
@@ -60,14 +60,14 @@ namespace kiwano
}
}
- void Frame::SetImage(ImagePtr image)
+ void Frame::SetImage(Image const& image)
{
image_ = image;
- if (image_)
+ if (image_.IsValid())
{
crop_rect_.origin.x = crop_rect_.origin.y = 0;
- crop_rect_.size.x = image_->GetWidth();
- crop_rect_.size.y = image_->GetHeight();
+ crop_rect_.size.x = image_.GetWidth();
+ crop_rect_.size.y = image_.GetHeight();
}
}
}
diff --git a/src/kiwano/2d/Frame.h b/src/kiwano/2d/Frame.h
index 360cfd63..93569ee9 100644
--- a/src/kiwano/2d/Frame.h
+++ b/src/kiwano/2d/Frame.h
@@ -35,7 +35,7 @@ namespace kiwano
);
explicit Frame(
- ImagePtr image
+ Image const& image
);
bool Load(
@@ -43,7 +43,7 @@ namespace kiwano
);
// 裁剪矩形
- void Crop(
+ void SetCropRect(
Rect const& crop_rect /* 裁剪矩形 */
);
@@ -63,13 +63,13 @@ namespace kiwano
inline Rect const& GetCropRect() const { return crop_rect_; }
// 获取位图
- inline ImagePtr GetImage() const { return image_; }
+ inline Image const& GetImage() const { return image_; }
// 设置位图
- void SetImage(ImagePtr image);
+ void SetImage(Image const& image);
protected:
- ImagePtr image_;
+ Image image_;
Rect crop_rect_;
};
}
diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp
index bccf256c..e331fcf8 100644
--- a/src/kiwano/2d/GifSprite.cpp
+++ b/src/kiwano/2d/GifSprite.cpp
@@ -20,7 +20,8 @@
#include "GifSprite.h"
#include "../base/Logger.h"
-#include "../platform/modules.h"
+#include "../renderer/ImageCache.h"
+#include "../renderer/Renderer.h"
namespace kiwano
{
@@ -29,6 +30,7 @@ namespace kiwano
, next_index_(0)
, total_loop_count_(1)
, loop_count_(0)
+ , disposal_type_(DisposalType::Unknown)
{
}
@@ -45,12 +47,8 @@ namespace kiwano
bool GifSprite::Load(Resource const& res)
{
- GifImagePtr image = new (std::nothrow) GifImage;
- if (image->Load(res))
- {
- return Load(image);
- }
- return false;
+ GifImagePtr image = ImageCache::GetInstance()->AddGifImage(res);
+ return Load(image);
}
bool GifSprite::Load(GifImagePtr image)
@@ -61,18 +59,16 @@ namespace kiwano
next_index_ = 0;
loop_count_ = 0;
+ disposal_type_ = DisposalType::None;
SetSize(
static_cast(image_->GetWidthInPixels()),
static_cast(image_->GetHeightInPixels())
);
- if (!frame_rt_)
+ if (!frame_rt_.IsValid())
{
- auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
- ThrowIfFailed(
- ctx->CreateCompatibleRenderTarget(&frame_rt_)
- );
+ Renderer::GetInstance()->CreateImageRenderTarget(frame_rt_);
}
if (image_->GetFramesCount() > 0)
@@ -84,6 +80,16 @@ namespace kiwano
return false;
}
+ void GifSprite::OnRender(Renderer* renderer)
+ {
+ if (frame_.IsValid() && renderer->CheckVisibility(size_, transform_matrix_))
+ {
+ PrepareRender(renderer);
+
+ renderer->DrawImage(frame_);
+ }
+ }
+
void GifSprite::Update(Duration dt)
{
Actor::Update(dt);
@@ -100,84 +106,94 @@ namespace kiwano
}
}
- void GifSprite::OnRender(Renderer* renderer)
- {
- if (frame_to_render_ && renderer->CheckVisibility(size_, transform_matrix_))
- {
- PrepareRender(renderer);
-
- Rect bounds = GetBounds();
- renderer->DrawBitmap(frame_to_render_, bounds, bounds);
- }
- }
-
void GifSprite::RestartAnimation()
{
animating_ = true;
next_index_ = 0;
loop_count_ = 0;
- image_->SetDisposalType(GifImage::DisposalType::None);
+ disposal_type_ = DisposalType::None;
}
void GifSprite::ComposeNextFrame()
{
- if (frame_rt_)
+ if (frame_rt_.IsValid())
{
- // 找到延迟大于 0 的帧 (0 延迟帧是不可见的中间帧)
- HRESULT hr = E_FAIL;
do
{
- hr = image_->DisposeCurrentFrame(frame_rt_);
- if (SUCCEEDED(hr))
- {
- hr = OverlayNextFrame();
- }
-
- if (SUCCEEDED(hr))
- {
- frame_delay_.SetMilliseconds(static_cast(image_->GetFrameDelay()));
- }
- } while (SUCCEEDED(hr) && frame_delay_.IsZero() && !IsLastFrame());
+ DisposeCurrentFrame();
+ OverlayNextFrame();
+ } while (frame_delay_.IsZero() && !IsLastFrame());
- animating_ = (SUCCEEDED(hr) && !EndOfAnimation() && image_->GetFramesCount() > 1);
+ animating_ = (!EndOfAnimation() && image_->GetFramesCount() > 1);
}
}
- HRESULT GifSprite::OverlayNextFrame()
+ void GifSprite::DisposeCurrentFrame()
{
- HRESULT hr = image_->GetRawFrame(next_index_);
+ switch (disposal_type_)
+ {
+ case DisposalType::Unknown:
+ case DisposalType::None:
+ break;
+
+ case DisposalType::Background:
+ {
+ ClearCurrentFrameArea();
+ break;
+ }
+
+ case DisposalType::Previous:
+ {
+ RestoreSavedFrame();
+ break;
+ }
+
+ default:
+ ThrowIfFailed(E_FAIL);
+ }
+ }
+
+ void GifSprite::OverlayNextFrame()
+ {
+ Image raw_image;
+
+ HRESULT hr = image_->GetRawFrame(next_index_, raw_image, frame_rect_, frame_delay_, disposal_type_);
+
if (SUCCEEDED(hr))
{
- if (image_->GetDisposalType() == GifImage::DisposalType::Previous)
+ if (disposal_type_ == DisposalType::Previous)
{
- hr = image_->SaveComposedFrame(frame_rt_);
+ SaveComposedFrame();
}
}
if (SUCCEEDED(hr))
{
- frame_rt_->BeginDraw();
+ frame_rt_.BeginDraw();
if (next_index_ == 0)
{
// 重新绘制背景
- frame_rt_->Clear(image_->GetBackgroundColor());
+ frame_rt_.Clear(image_->GetBackgroundColor());
loop_count_++;
}
- frame_rt_->DrawBitmap(image_->GetRawFrame().get(), image_->GetFramePosition());
- hr = frame_rt_->EndDraw();
+ frame_rt_.DrawImage(raw_image, nullptr, &frame_rect_);
+ frame_rt_.EndDraw();
}
if (SUCCEEDED(hr))
{
- frame_to_render_ = nullptr;
- hr = frame_rt_->GetBitmap(&frame_to_render_);
- }
+ Image frame_to_render;
+ frame_rt_.GetOutput(frame_to_render);
- if (SUCCEEDED(hr))
- {
- next_index_ = (++next_index_) % image_->GetFramesCount();
+ hr = frame_to_render.IsValid() ? S_OK : E_FAIL;
+
+ if (SUCCEEDED(hr))
+ {
+ frame_ = frame_to_render;
+ next_index_ = (++next_index_) % image_->GetFramesCount();
+ }
}
if (IsLastFrame() && loop_cb_)
@@ -189,7 +205,71 @@ namespace kiwano
{
done_cb_();
}
- return hr;
+
+ ThrowIfFailed(hr);
+ }
+
+ void GifSprite::SaveComposedFrame()
+ {
+ Image frame_to_be_saved;
+ frame_rt_.GetOutput(frame_to_be_saved);
+
+ HRESULT hr = frame_to_be_saved.IsValid() ? S_OK : E_FAIL;
+
+ if (SUCCEEDED(hr))
+ {
+ if (!saved_frame_.IsValid())
+ {
+ auto size = frame_to_be_saved.GetSizeInPixels();
+ auto prop = D2D1::BitmapProperties(frame_to_be_saved.GetPixelFormat());
+
+ ComPtr saved_bitmap;
+ hr = frame_rt_.GetRenderTarget()->CreateBitmap(D2D1::SizeU(size.x, size.y), prop, &saved_bitmap);
+
+ if (SUCCEEDED(hr))
+ {
+ saved_frame_.SetBitmap(saved_bitmap);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ saved_frame_.CopyFrom(frame_to_be_saved);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void GifSprite::RestoreSavedFrame()
+ {
+ HRESULT hr = saved_frame_.IsValid() ? S_OK : E_FAIL;
+
+ if (SUCCEEDED(hr))
+ {
+ Image frame_to_copy_to;
+ frame_rt_.GetOutput(frame_to_copy_to);
+
+ hr = frame_to_copy_to.IsValid() ? S_OK : E_FAIL;
+
+ if (SUCCEEDED(hr))
+ {
+ frame_to_copy_to.CopyFrom(saved_frame_);
+ }
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void GifSprite::ClearCurrentFrameArea()
+ {
+ frame_rt_.BeginDraw();
+
+ frame_rt_.PushClipRect(frame_rect_);
+ frame_rt_.Clear(image_->GetBackgroundColor());
+ frame_rt_.PopClipRect();
+
+ return frame_rt_.EndDraw();
}
}
diff --git a/src/kiwano/2d/GifSprite.h b/src/kiwano/2d/GifSprite.h
index 0c730c7d..4e1f2a41 100644
--- a/src/kiwano/2d/GifSprite.h
+++ b/src/kiwano/2d/GifSprite.h
@@ -21,17 +21,19 @@
#pragma once
#include "Actor.h"
#include "../base/Resource.h"
-#include "../renderer/Renderer.h"
+#include "../renderer/RenderTarget.h"
#include "../renderer/GifImage.h"
namespace kiwano
{
+ // GIF 精灵
class KGE_API GifSprite
: public Actor
{
public:
- using LoopDoneCallback = Function;
- using DoneCallback = Function;
+ using DisposalType = GifImage::DisposalType;
+ using LoopDoneCallback = Function;
+ using DoneCallback = Function;
GifSprite();
@@ -72,27 +74,36 @@ namespace kiwano
protected:
void Update(Duration dt) override;
- void ComposeNextFrame();
-
- HRESULT OverlayNextFrame();
-
inline bool IsLastFrame() const { return (next_index_ == 0); }
inline bool EndOfAnimation() const { return IsLastFrame() && loop_count_ == total_loop_count_ + 1; }
- protected:
- bool animating_;
- int total_loop_count_;
- int loop_count_;
- unsigned int next_index_;
- Duration frame_delay_;
- Duration frame_elapsed_;
+ void ComposeNextFrame();
+ void DisposeCurrentFrame();
+
+ void OverlayNextFrame();
+
+ void SaveComposedFrame();
+
+ void RestoreSavedFrame();
+
+ void ClearCurrentFrameArea();
+
+ protected:
+ bool animating_;
+ int total_loop_count_;
+ int loop_count_;
+ UINT next_index_;
+ Duration frame_delay_;
+ Duration frame_elapsed_;
+ DisposalType disposal_type_;
LoopDoneCallback loop_cb_;
DoneCallback done_cb_;
-
- GifImagePtr image_;
- ComPtr frame_to_render_;
- ComPtr frame_rt_;
+ GifImagePtr image_;
+ Image frame_;
+ Rect frame_rect_;
+ Image saved_frame_;
+ ImageRenderTarget frame_rt_;
};
}
diff --git a/src/kiwano/2d/ShapeActor.cpp b/src/kiwano/2d/ShapeActor.cpp
index 3cab94c1..cd6963b3 100644
--- a/src/kiwano/2d/ShapeActor.cpp
+++ b/src/kiwano/2d/ShapeActor.cpp
@@ -28,7 +28,7 @@ namespace kiwano
: fill_color_(Color::White)
, stroke_color_(Color(Color::Black, 0))
, stroke_width_(1.f)
- , outline_join_(StrokeStyle::Miter)
+ , stroke_style_(StrokeStyle::Miter)
{
}
@@ -73,9 +73,9 @@ namespace kiwano
stroke_width_ = std::max(width, 0.f);
}
- void ShapeActor::SetOutlineJoinStyle(StrokeStyle outline_join)
+ void ShapeActor::SetStrokeStyle(StrokeStyle stroke_style)
{
- outline_join_ = outline_join;
+ stroke_style_ = stroke_style;
}
void ShapeActor::OnRender(Renderer* renderer)
@@ -93,7 +93,7 @@ namespace kiwano
geo_,
stroke_color_,
stroke_width_,
- outline_join_
+ stroke_style_
);
}
}
diff --git a/src/kiwano/2d/ShapeActor.h b/src/kiwano/2d/ShapeActor.h
index 940a34df..7ba2a3c4 100644
--- a/src/kiwano/2d/ShapeActor.h
+++ b/src/kiwano/2d/ShapeActor.h
@@ -46,8 +46,8 @@ namespace kiwano
// 获取线条宽度
float GetStrokeWidth() const { return stroke_width_; }
- // 获取线条相交样式
- StrokeStyle SetOutlineJoinStyle() const { return outline_join_; }
+ // 获取线条样式
+ StrokeStyle SetStrokeStyle() const { return stroke_style_; }
// 获取边界
Rect GetBounds() const override;
@@ -70,9 +70,9 @@ namespace kiwano
float width
);
- // 设置线条相交样式
- void SetOutlineJoinStyle(
- StrokeStyle outline_join
+ // 设置线条样式
+ void SetStrokeStyle(
+ StrokeStyle stroke_style
);
// 设置形状
@@ -87,7 +87,7 @@ namespace kiwano
Color fill_color_;
Color stroke_color_;
float stroke_width_;
- StrokeStyle outline_join_;
+ StrokeStyle stroke_style_;
Geometry geo_;
};
diff --git a/src/kiwano/2d/Sprite.cpp b/src/kiwano/2d/Sprite.cpp
index ac4ffcba..64331909 100644
--- a/src/kiwano/2d/Sprite.cpp
+++ b/src/kiwano/2d/Sprite.cpp
@@ -38,7 +38,7 @@ namespace kiwano
: frame_(nullptr)
{
Load(res);
- Crop(crop_rect);
+ SetCropRect(crop_rect);
}
Sprite::Sprite(FramePtr frame)
@@ -62,11 +62,11 @@ namespace kiwano
return false;
}
- void Sprite::Crop(const Rect& crop_rect)
+ void Sprite::SetCropRect(const Rect& crop_rect)
{
if (frame_)
{
- frame_->Crop(crop_rect);
+ frame_->SetCropRect(crop_rect);
SetSize(frame_->GetWidth(), frame_->GetHeight());
}
}
@@ -89,7 +89,7 @@ namespace kiwano
{
PrepareRender(renderer);
- renderer->DrawBitmap(frame_->GetImage()->GetBitmap(), frame_->GetCropRect(), GetBounds());
+ renderer->DrawImage(frame_->GetImage(), &frame_->GetCropRect(), nullptr);
}
}
}
diff --git a/src/kiwano/2d/Sprite.h b/src/kiwano/2d/Sprite.h
index 01940df6..8cd03aad 100644
--- a/src/kiwano/2d/Sprite.h
+++ b/src/kiwano/2d/Sprite.h
@@ -52,7 +52,7 @@ namespace kiwano
);
// 裁剪矩形
- void Crop(
+ void SetCropRect(
const Rect& crop_rect
);
diff --git a/src/kiwano/2d/Text.cpp b/src/kiwano/2d/Text.cpp
index 1ea74555..dc460d0b 100644
--- a/src/kiwano/2d/Text.cpp
+++ b/src/kiwano/2d/Text.cpp
@@ -206,7 +206,7 @@ namespace kiwano
if (text_layout_ && renderer->CheckVisibility(size_, transform_matrix_))
{
PrepareRender(renderer);
- renderer->DrawTextLayout(text_layout_);
+ renderer->DrawTextLayout(text_layout_);
}
}
diff --git a/src/kiwano/2d/Transition.cpp b/src/kiwano/2d/Transition.cpp
index af2876c5..d5353c05 100644
--- a/src/kiwano/2d/Transition.cpp
+++ b/src/kiwano/2d/Transition.cpp
@@ -99,30 +99,26 @@ namespace kiwano
{
if (out_scene_)
{
- renderer->PushClip(
- out_scene_->GetTransformMatrix(),
- window_size_
- );
+ renderer->SetTransform(out_scene_->GetTransformMatrix());
+ renderer->PushClipRect(Rect{ Point{}, window_size_ });
renderer->PushLayer(out_layer_, out_layer_prop_);
out_scene_->Render(renderer);
renderer->PopLayer();
- renderer->PopClip();
+ renderer->PopClipRect();
}
if (in_scene_)
{
- renderer->PushClip(
- in_scene_->GetTransformMatrix(),
- window_size_
- );
+ renderer->SetTransform(in_scene_->GetTransformMatrix());
+ renderer->PushClipRect(Rect{ Point{}, window_size_ });
renderer->PushLayer(in_layer_, in_layer_prop_);
in_scene_->Render(renderer);
renderer->PopLayer();
- renderer->PopClip();
+ renderer->PopClipRect();
}
}
diff --git a/src/kiwano/base/types.h b/src/kiwano/base/types.h
index 28e139e0..54531e14 100644
--- a/src/kiwano/base/types.h
+++ b/src/kiwano/base/types.h
@@ -23,7 +23,7 @@
namespace kiwano
{
- // 画笔样式
+ // 线条样式
enum class StrokeStyle : int
{
Miter = 0, /* 斜切 */
@@ -68,4 +68,4 @@ namespace kiwano
Rect area;
float opacity;
};
-}
\ No newline at end of file
+}
diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h
index 92597682..32e44077 100644
--- a/src/kiwano/kiwano.h
+++ b/src/kiwano/kiwano.h
@@ -56,12 +56,22 @@
//
-// base
+// renderer
//
-#include "renderer/Renderer.h"
#include "renderer/Image.h"
#include "renderer/GifImage.h"
+#include "renderer/TextLayout.h"
+#include "renderer/TextRenderer.h"
+#include "renderer/Geometry.h"
+#include "renderer/ImageCache.h"
+#include "renderer/RenderTarget.h"
+#include "renderer/Renderer.h"
+
+
+//
+// base
+//
#include "base/time.h"
#include "base/Window.h"
@@ -81,6 +91,11 @@
#include "base/AsyncTask.h"
#include "base/Resource.h"
+
+//
+// 2d
+//
+
#include "2d/Font.hpp"
#include "2d/Color.h"
#include "2d/Transform.hpp"
@@ -110,9 +125,15 @@
#include "2d/ShapeActor.h"
#include "2d/DebugActor.h"
+
+//
+// platform
+//
+
#include "platform/modules.h"
#include "platform/Application.h"
+
//
// utils
//
diff --git a/src/kiwano/renderer/GifImage.cpp b/src/kiwano/renderer/GifImage.cpp
index d2546c51..49c54acd 100644
--- a/src/kiwano/renderer/GifImage.cpp
+++ b/src/kiwano/renderer/GifImage.cpp
@@ -19,18 +19,15 @@
// THE SOFTWARE.
#include "GifImage.h"
+#include "Renderer.h"
#include "../base/Logger.h"
-#include "../utils/FileUtil.h"
namespace kiwano
{
GifImage::GifImage()
: frames_count_(0)
- , disposal_type_(DisposalType::Unknown)
, width_in_pixels_(0)
, height_in_pixels_(0)
- , frame_delay_(0)
- , frame_position_{}
, bg_color_{}
{
}
@@ -43,234 +40,23 @@ namespace kiwano
bool GifImage::Load(Resource const& res)
{
- HRESULT hr = S_OK;
+ Renderer::GetInstance()->CreateGifImage(*this, res);
- frames_count_ = 0;
- disposal_type_ = DisposalType::None;
-
- saved_frame_.reset();
- decoder_.reset();
-
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
-
- if (res.IsFileType())
+ if (IsValid())
{
-#ifdef KGE_DEBUG
- if (!FileUtil::ExistsFile(res.GetFileName().c_str()))
+ if (FAILED(GetGlobalMetadata()))
{
- KGE_WARNING_LOG(L"Gif file '%s' not found!", res.GetFileName().c_str());
+ SetDecoder(nullptr);
return false;
}
-#endif
-
- hr = factory->CreateDecoderFromFilename(
- res.GetFileName().c_str(),
- nullptr,
- GENERIC_READ,
- WICDecodeMetadataCacheOnLoad,
- &decoder_);
+ return true;
}
- else
- {
- LPVOID buffer;
- DWORD buffer_size;
- HRESULT hr = res.Load(buffer, buffer_size) ? S_OK : E_FAIL;
-
- ComPtr stream;
-
- if (SUCCEEDED(hr))
- {
- hr = factory->CreateStream(&stream);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = stream->InitializeFromMemory(
- static_cast(buffer),
- buffer_size
- );
- }
-
- if (SUCCEEDED(hr))
- {
- hr = factory->CreateDecoderFromStream(
- stream.get(),
- nullptr,
- WICDecodeMetadataCacheOnLoad,
- &decoder_
- );
- }
- }
-
- if (SUCCEEDED(hr))
- {
- hr = GetGlobalMetadata();
- }
-
- return SUCCEEDED(hr);
+ return false;
}
- HRESULT GifImage::GetRawFrame(UINT frame_index)
+ bool GifImage::IsValid() const
{
- ComPtr converter;
- ComPtr wic_frame;
- ComPtr metadata_reader;
-
- PROPVARIANT prop_val;
- PropVariantInit(&prop_val);
-
- // Retrieve the current frame
- HRESULT hr = decoder_->GetFrame(frame_index, &wic_frame);
- if (SUCCEEDED(hr))
- {
- // Format convert to 32bppPBGRA which D2D expects
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
- hr = factory->CreateFormatConverter(&converter);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = converter->Initialize(
- wic_frame.get(),
- GUID_WICPixelFormat32bppPBGRA,
- WICBitmapDitherTypeNone,
- nullptr,
- 0.f,
- WICBitmapPaletteTypeCustom);
- }
-
- if (SUCCEEDED(hr))
- {
- auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
-
- // Create a D2DBitmap from IWICBitmapSource
- raw_frame_.reset();
- hr = ctx->CreateBitmapFromWicBitmap(
- converter.get(),
- nullptr,
- &raw_frame_);
- }
-
- if (SUCCEEDED(hr))
- {
- // Get Metadata Query Reader from the frame
- hr = wic_frame->GetMetadataQueryReader(&metadata_reader);
- }
-
- // Get the Metadata for the current frame
- if (SUCCEEDED(hr))
- {
- hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val);
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
- if (SUCCEEDED(hr))
- {
- frame_position_.left = static_cast(prop_val.uiVal);
- }
- PropVariantClear(&prop_val);
- }
- }
-
- if (SUCCEEDED(hr))
- {
- hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val);
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
- if (SUCCEEDED(hr))
- {
- frame_position_.top = static_cast(prop_val.uiVal);
- }
- PropVariantClear(&prop_val);
- }
- }
-
- if (SUCCEEDED(hr))
- {
- hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val);
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
- if (SUCCEEDED(hr))
- {
- frame_position_.right = static_cast(prop_val.uiVal)
- + frame_position_.left;
- }
- PropVariantClear(&prop_val);
- }
- }
-
- if (SUCCEEDED(hr))
- {
- hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val);
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
- if (SUCCEEDED(hr))
- {
- frame_position_.bottom = static_cast(prop_val.uiVal)
- + frame_position_.top;
- }
- PropVariantClear(&prop_val);
- }
- }
-
- if (SUCCEEDED(hr))
- {
- frame_delay_ = 0;
-
- hr = metadata_reader->GetMetadataByName(
- L"/grctlext/Delay",
- &prop_val);
-
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
- if (SUCCEEDED(hr))
- {
- hr = UIntMult(prop_val.uiVal, 10, &frame_delay_);
- }
- PropVariantClear(&prop_val);
- }
- else
- {
- frame_delay_ = 0;
- }
-
- if (SUCCEEDED(hr))
- {
- // 插入一个强制延迟
- if (frame_delay_ < 90)
- {
- frame_delay_ = 90;
- }
- }
- }
-
- if (SUCCEEDED(hr))
- {
- hr = metadata_reader->GetMetadataByName(
- L"/grctlext/Disposal",
- &prop_val);
-
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL;
- if (SUCCEEDED(hr))
- {
- disposal_type_ = DisposalType(prop_val.bVal);
- }
- }
- else
- {
- // 获取 DisposalType 失败,可能图片是只有一帧的图片
- disposal_type_ = DisposalType::Unknown;
- }
- }
-
- ::PropVariantClear(&prop_val);
- return hr;
+ return decoder_ != nullptr;
}
HRESULT GifImage::GetGlobalMetadata()
@@ -284,7 +70,12 @@ namespace kiwano
ComPtr metadata_reader;
// 获取帧数量
- HRESULT hr = decoder_->GetFrameCount(&frames_count_);
+ HRESULT hr = decoder_ ? S_OK : E_FAIL;
+
+ if (SUCCEEDED(hr))
+ {
+ hr = decoder_->GetFrameCount(&frames_count_);
+ }
if (SUCCEEDED(hr))
{
@@ -297,7 +88,7 @@ namespace kiwano
if (FAILED(GetBackgroundColor(metadata_reader.get())))
{
// 如果未能获得颜色,则默认为透明
- bg_color_ = D2D1::ColorF(0, 0.f);
+ bg_color_ = Color(0, 0.f);
}
}
@@ -305,9 +96,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
// 获取宽度
- hr = metadata_reader->GetMetadataByName(
- L"/logscrdesc/Width",
- &prop_val);
+ hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Width", &prop_val);
if (SUCCEEDED(hr))
{
@@ -323,9 +112,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
// 获取高度
- hr = metadata_reader->GetMetadataByName(
- L"/logscrdesc/Height",
- &prop_val);
+ hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Height", &prop_val);
if (SUCCEEDED(hr))
{
@@ -341,9 +128,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
// 获得像素纵横比
- hr = metadata_reader->GetMetadataByName(
- L"/logscrdesc/PixelAspectRatio",
- &prop_val);
+ hr = metadata_reader->GetMetadataByName(L"/logscrdesc/PixelAspectRatio", &prop_val);
if (SUCCEEDED(hr))
{
@@ -383,101 +168,17 @@ namespace kiwano
return hr;
}
- HRESULT GifImage::DisposeCurrentFrame(ComPtr frame_rt)
+ HRESULT GifImage::GetBackgroundColor(ComPtr metadata_reader)
{
- HRESULT hr = S_OK;
-
- switch (disposal_type_)
- {
- case DisposalType::Unknown:
- case DisposalType::None:
- break;
- case DisposalType::Background:
- // 用背景颜色清除当前原始帧覆盖的区域
- hr = ClearCurrentFrameArea(frame_rt);
- break;
- case DisposalType::Previous:
- // 恢复先前构图的帧
- hr = RestoreSavedFrame(frame_rt);
- break;
- default:
- hr = E_FAIL;
- }
- return hr;
- }
-
- HRESULT GifImage::SaveComposedFrame(ComPtr frame_rt)
- {
- HRESULT hr = S_OK;
-
- ComPtr frame_to_be_saved;
-
- hr = frame_rt->GetBitmap(&frame_to_be_saved);
- if (SUCCEEDED(hr))
- {
- if (saved_frame_ == nullptr)
- {
- auto size = frame_to_be_saved->GetPixelSize();
- auto prop = D2D1::BitmapProperties(frame_to_be_saved->GetPixelFormat());
-
- hr = frame_rt->CreateBitmap(size, prop, &saved_frame_);
- }
- }
-
- if (SUCCEEDED(hr))
- {
- hr = saved_frame_->CopyFromBitmap(nullptr, frame_to_be_saved.get(), nullptr);
- }
- return hr;
- }
-
- HRESULT GifImage::RestoreSavedFrame(ComPtr frame_rt)
- {
- HRESULT hr = S_OK;
-
- ComPtr frame_to_copy_to;
-
- hr = saved_frame_ ? S_OK : E_FAIL;
-
- if (SUCCEEDED(hr))
- {
- hr = frame_rt->GetBitmap(&frame_to_copy_to);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = frame_to_copy_to->CopyFromBitmap(nullptr, saved_frame_.get(), nullptr);
- }
-
- return hr;
- }
-
- HRESULT GifImage::ClearCurrentFrameArea(ComPtr frame_rt)
- {
- frame_rt->BeginDraw();
-
- frame_rt->PushAxisAlignedClip(&frame_position_, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
- frame_rt->Clear(bg_color_);
- frame_rt->PopAxisAlignedClip();
-
- return frame_rt->EndDraw();
- }
-
- HRESULT GifImage::GetBackgroundColor(IWICMetadataQueryReader* metadata_reader)
- {
- DWORD bgcolor = 0;
BYTE bg_index = 0;
WICColor bgcolors[256];
UINT colors_copied = 0;
+ ComPtr wic_palette;
PROPVARIANT prop_val;
PropVariantInit(&prop_val);
- ComPtr wic_palette;
-
- HRESULT hr = metadata_reader->GetMetadataByName(
- L"/logscrdesc/GlobalColorTableFlag",
- &prop_val);
+ HRESULT hr = metadata_reader->GetMetadataByName(L"/logscrdesc/GlobalColorTableFlag", &prop_val);
if (SUCCEEDED(hr))
{
@@ -487,9 +188,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- hr = metadata_reader->GetMetadataByName(
- L"/logscrdesc/BackgroundColorIndex",
- &prop_val);
+ hr = metadata_reader->GetMetadataByName(L"/logscrdesc/BackgroundColorIndex", &prop_val);
if (SUCCEEDED(hr))
{
@@ -523,19 +222,175 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- // 检查下标
hr = (bg_index >= colors_copied) ? E_FAIL : S_OK;
}
if (SUCCEEDED(hr))
{
- bgcolor = bgcolors[bg_index];
-
// 转换为 ARGB 格式
- float alpha = (bgcolor >> 24) / 255.f;
- bg_color_ = D2D1::ColorF(bgcolor, alpha);
+ float alpha = (bgcolors[bg_index] >> 24) / 255.f;
+ bg_color_ = Color(bgcolors[bg_index], alpha);
}
return hr;
}
+ HRESULT GifImage::GetRawFrame(UINT frame_index, Image& raw_frame, Rect& frame_rect, Duration& delay, DisposalType& disposal_type)
+ {
+ ComPtr converter;
+ ComPtr wic_frame;
+ ComPtr metadata_reader;
+
+ PROPVARIANT prop_val;
+ PropVariantInit(&prop_val);
+
+ // Retrieve the current frame
+ HRESULT hr = decoder_->GetFrame(frame_index, &wic_frame);
+ if (SUCCEEDED(hr))
+ {
+ // Format convert to 32bppPBGRA which D2D expects
+ auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
+ hr = factory->CreateFormatConverter(&converter);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = converter->Initialize(
+ wic_frame.get(),
+ GUID_WICPixelFormat32bppPBGRA,
+ WICBitmapDitherTypeNone,
+ nullptr,
+ 0.f,
+ WICBitmapPaletteTypeCustom);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
+
+ // Create a D2DBitmap from IWICBitmapSource
+ ComPtr raw_bitmap;
+ hr = ctx->CreateBitmapFromWicBitmap(
+ converter.get(),
+ nullptr,
+ &raw_bitmap
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ raw_frame.SetBitmap(raw_bitmap);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // Get Metadata Query Reader from the frame
+ hr = wic_frame->GetMetadataQueryReader(&metadata_reader);
+ }
+
+ // Get the Metadata for the current frame
+ if (SUCCEEDED(hr))
+ {
+ hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val);
+ if (SUCCEEDED(hr))
+ {
+ hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
+ if (SUCCEEDED(hr))
+ {
+ frame_rect.origin.x = static_cast(prop_val.uiVal);
+ }
+ PropVariantClear(&prop_val);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val);
+ if (SUCCEEDED(hr))
+ {
+ hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
+ if (SUCCEEDED(hr))
+ {
+ frame_rect.origin.y = static_cast(prop_val.uiVal);
+ }
+ PropVariantClear(&prop_val);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val);
+ if (SUCCEEDED(hr))
+ {
+ hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
+ if (SUCCEEDED(hr))
+ {
+ frame_rect.size.x = static_cast(prop_val.uiVal);
+ }
+ PropVariantClear(&prop_val);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val);
+ if (SUCCEEDED(hr))
+ {
+ hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
+ if (SUCCEEDED(hr))
+ {
+ frame_rect.size.y = static_cast(prop_val.uiVal);
+ }
+ PropVariantClear(&prop_val);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = metadata_reader->GetMetadataByName(L"/grctlext/Delay", &prop_val);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
+
+ if (SUCCEEDED(hr))
+ {
+ UINT udelay = 0;
+ hr = UIntMult(prop_val.uiVal, 10, &udelay);
+ if (SUCCEEDED(hr))
+ {
+ delay.SetMilliseconds(static_cast(udelay));
+ }
+ }
+ PropVariantClear(&prop_val);
+ }
+ else
+ {
+ delay = 0;
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = metadata_reader->GetMetadataByName(L"/grctlext/Disposal", &prop_val);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL;
+ if (SUCCEEDED(hr))
+ {
+ disposal_type = DisposalType(prop_val.bVal);
+ }
+ ::PropVariantClear(&prop_val);
+ }
+ else
+ {
+ // 获取 DisposalType 失败,可能图片是只有一帧的图片
+ disposal_type = DisposalType::Unknown;
+ }
+ }
+
+ ::PropVariantClear(&prop_val);
+ return hr;
+ }
+
}
diff --git a/src/kiwano/renderer/GifImage.h b/src/kiwano/renderer/GifImage.h
index 556a2b82..b30fd113 100644
--- a/src/kiwano/renderer/GifImage.h
+++ b/src/kiwano/renderer/GifImage.h
@@ -19,8 +19,7 @@
// THE SOFTWARE.
#pragma once
-#include "../base/Resource.h"
-#include "Renderer.h"
+#include "Image.h"
namespace kiwano
{
@@ -32,21 +31,19 @@ namespace kiwano
public:
GifImage();
- GifImage(
- Resource const& res
- );
+ GifImage(Resource const& res);
- bool Load(
- Resource const& res
- );
+ bool Load(Resource const& res);
- inline unsigned int GetWidthInPixels() const { return width_in_pixels_; }
+ bool IsValid() const;
- inline unsigned int GetHeightInPixels() const { return height_in_pixels_; }
+ inline UINT GetWidthInPixels() const { return width_in_pixels_; }
- inline unsigned int GetFrameDelay() const { return frame_delay_; }
+ inline UINT GetHeightInPixels() const { return height_in_pixels_; }
- inline unsigned int GetFramesCount() const { return frames_count_; }
+ inline UINT GetFramesCount() const { return frames_count_; }
+
+ inline Color GetBackgroundColor() const { return bg_color_; }
public:
enum class DisposalType
@@ -57,37 +54,31 @@ namespace kiwano
Previous
};
- inline DisposalType GetDisposalType() const { return disposal_type_; }
+ HRESULT GetRawFrame(
+ UINT frame_index,
+ Image& raw_frame,
+ Rect& frame_rect,
+ Duration& delay,
+ DisposalType& disposal_type
+ );
- inline D2D1_COLOR_F GetBackgroundColor() const { return bg_color_; }
+ inline ComPtr GetDecoder() const { return decoder_; }
- inline D2D1_RECT_F const& GetFramePosition() const { return frame_position_; }
-
- inline ComPtr GetRawFrame() const { return raw_frame_; }
-
- inline void SetDisposalType(DisposalType type) { disposal_type_ = type; }
-
- public:
- HRESULT GetRawFrame(UINT frame_index);
- HRESULT GetGlobalMetadata();
- HRESULT GetBackgroundColor(IWICMetadataQueryReader* metadata_reader);
-
- HRESULT DisposeCurrentFrame(ComPtr frame_rt);
- HRESULT SaveComposedFrame(ComPtr frame_rt);
- HRESULT RestoreSavedFrame(ComPtr frame_rt);
- HRESULT ClearCurrentFrameArea(ComPtr frame_rt);
+ inline void SetDecoder(ComPtr decoder) { decoder_ = decoder; }
protected:
- ComPtr raw_frame_;
- ComPtr saved_frame_;
- ComPtr decoder_;
+ HRESULT GetGlobalMetadata();
- unsigned int frames_count_;
- unsigned int frame_delay_;
- unsigned int width_in_pixels_;
- unsigned int height_in_pixels_;
- DisposalType disposal_type_;
- D2D1_RECT_F frame_position_;
- D2D1_COLOR_F bg_color_;
+ HRESULT GetBackgroundColor(
+ ComPtr metadata_reader
+ );
+
+ protected:
+ UINT frames_count_;
+ UINT width_in_pixels_;
+ UINT height_in_pixels_;
+ Color bg_color_;
+
+ ComPtr decoder_;
};
}
diff --git a/src/kiwano/renderer/Image.cpp b/src/kiwano/renderer/Image.cpp
index d01a8d91..5fbd80ae 100644
--- a/src/kiwano/renderer/Image.cpp
+++ b/src/kiwano/renderer/Image.cpp
@@ -19,16 +19,20 @@
// THE SOFTWARE.
#include "Image.h"
+#include "Renderer.h"
#include "../base/Logger.h"
-#include "../platform/modules.h"
namespace kiwano
{
Image::Image()
- : bitmap_(nullptr)
{
}
+ Image::Image(Resource const& res)
+ {
+ Load(res);
+ }
+
Image::Image(ComPtr const & bitmap)
: Image()
{
@@ -39,9 +43,15 @@ namespace kiwano
{
}
+ bool Image::Load(Resource const& res)
+ {
+ Renderer::GetInstance()->CreateImage(*this, res);
+ return IsValid();
+ }
+
bool Image::IsValid() const
{
- return !!bitmap_;
+ return bitmap_ != nullptr;
}
float Image::GetWidth() const
@@ -100,6 +110,43 @@ namespace kiwano
return math::Vec2T{};
}
+ void Image::CopyFrom(Image const& copy_from)
+ {
+ if (IsValid() && copy_from.IsValid())
+ {
+ HRESULT hr = bitmap_->CopyFromBitmap(nullptr, copy_from.GetBitmap().get(), nullptr);
+
+ ThrowIfFailed(hr);
+ }
+ }
+
+ void Image::CopyFrom(Image const& copy_from, Rect const& src_rect, Point const& dest_point)
+ {
+ if (IsValid() && copy_from.IsValid())
+ {
+ HRESULT hr = bitmap_->CopyFromBitmap(
+ &D2D1::Point2U(UINT(dest_point.x), UINT(dest_point.y)),
+ copy_from.GetBitmap().get(),
+ &D2D1::RectU(
+ UINT(src_rect.GetLeft()),
+ UINT(src_rect.GetTop()),
+ UINT(src_rect.GetRight()),
+ UINT(src_rect.GetBottom()))
+ );
+
+ ThrowIfFailed(hr);
+ }
+ }
+
+ D2D1_PIXEL_FORMAT Image::GetPixelFormat() const
+ {
+ if (bitmap_)
+ {
+ return bitmap_->GetPixelFormat();
+ }
+ return D2D1_PIXEL_FORMAT();
+ }
+
ComPtr Image::GetBitmap() const
{
return bitmap_;
diff --git a/src/kiwano/renderer/Image.h b/src/kiwano/renderer/Image.h
index 295d1e72..86d4a71c 100644
--- a/src/kiwano/renderer/Image.h
+++ b/src/kiwano/renderer/Image.h
@@ -25,19 +25,26 @@
namespace kiwano
{
// 图像
- KGE_DECLARE_SMART_PTR(Image);
class KGE_API Image
- : public Object
{
public:
Image();
+ explicit Image(
+ Resource const& res
+ );
+
explicit Image(
ComPtr const& bitmap
);
virtual ~Image();
+ // 加载资源
+ bool Load(
+ Resource const& res
+ );
+
// 资源是否有效
bool IsValid() const;
@@ -59,12 +66,22 @@ namespace kiwano
// 获取位图像素大小
math::Vec2T GetSizeInPixels() const;
+ // 拷贝位图内存
+ void CopyFrom(Image const& copy_from);
+
+ // 拷贝位图内存
+ void CopyFrom(Image const& copy_from, Rect const& src_rect, Point const& dest_point);
+
+ public:
// 获取源位图
ComPtr GetBitmap() const;
// 设置源位图
void SetBitmap(ComPtr bitmap);
+ // 获取像素格式
+ D2D1_PIXEL_FORMAT GetPixelFormat() const;
+
protected:
ComPtr bitmap_;
};
diff --git a/src/kiwano/renderer/ImageCache.cpp b/src/kiwano/renderer/ImageCache.cpp
index 342f2268..e950d1bc 100644
--- a/src/kiwano/renderer/ImageCache.cpp
+++ b/src/kiwano/renderer/ImageCache.cpp
@@ -19,6 +19,7 @@
// THE SOFTWARE.
#include "ImageCache.h"
+#include "Renderer.h"
#include "../base/Logger.h"
namespace kiwano
@@ -32,43 +33,28 @@ namespace kiwano
{
}
- ImagePtr ImageCache::AddImage(Resource const& res)
+ Image ImageCache::AddImage(Resource const& res)
{
size_t hash_code = res.GetHashCode();
+
auto iter = image_cache_.find(hash_code);
if (iter != image_cache_.end())
{
return iter->second;
}
- HRESULT hr = S_OK;
- ComPtr bitmap;
-
- if (res.IsFileType())
+ Image image;
+ if (image.Load(res))
{
- hr = Renderer::GetInstance()->GetD2DDeviceResources()->CreateBitmapFromFile(bitmap, res.GetFileName());
+ image_cache_.insert(std::make_pair(hash_code, image));
}
- else
- {
- hr = Renderer::GetInstance()->GetD2DDeviceResources()->CreateBitmapFromResource(bitmap, res);
- }
-
- if (SUCCEEDED(hr))
- {
- ImagePtr ptr = new Image(bitmap);
- image_cache_.insert(std::make_pair(hash_code, ptr));
- return ptr;
- }
- else
- {
- KGE_ERROR_LOG(L"Load image file failed with HRESULT of %08X", hr);
- }
- return nullptr;
+ return image;
}
void ImageCache::RemoveImage(Resource const& res)
{
size_t hash_code = res.GetHashCode();
+
auto iter = image_cache_.find(hash_code);
if (iter != image_cache_.end())
{
@@ -76,9 +62,39 @@ namespace kiwano
}
}
+ GifImagePtr ImageCache::AddGifImage(Resource const& res)
+ {
+ size_t hash_code = res.GetHashCode();
+
+ auto iter = gif_image_cache_.find(hash_code);
+ if (iter != gif_image_cache_.end())
+ {
+ return iter->second;
+ }
+
+ GifImagePtr ptr = new GifImage;
+ if (ptr->Load(res))
+ {
+ gif_image_cache_.insert(std::make_pair(hash_code, ptr));
+ }
+ return ptr;
+ }
+
+ void ImageCache::RemoveGifImage(Resource const& res)
+ {
+ size_t hash_code = res.GetHashCode();
+
+ auto iter = gif_image_cache_.find(hash_code);
+ if (iter != gif_image_cache_.end())
+ {
+ gif_image_cache_.erase(iter);
+ }
+ }
+
void ImageCache::Clear()
{
image_cache_.clear();
+ gif_image_cache_.clear();
}
}
diff --git a/src/kiwano/renderer/ImageCache.h b/src/kiwano/renderer/ImageCache.h
index 2d8365df..0534704e 100644
--- a/src/kiwano/renderer/ImageCache.h
+++ b/src/kiwano/renderer/ImageCache.h
@@ -20,7 +20,8 @@
#pragma once
#include "../core/singleton.hpp"
-#include "Renderer.h"
+#include "Image.h"
+#include "GifImage.h"
namespace kiwano
{
@@ -30,10 +31,14 @@ namespace kiwano
KGE_DECLARE_SINGLETON(ImageCache);
public:
- ImagePtr AddImage(Resource const& res);
+ Image AddImage(Resource const& res);
void RemoveImage(Resource const& res);
+ GifImagePtr AddGifImage(Resource const& res);
+
+ void RemoveGifImage(Resource const& res);
+
void Clear();
protected:
@@ -42,7 +47,10 @@ namespace kiwano
virtual ~ImageCache();
protected:
- using ImageMap = UnorderedMap;
+ using ImageMap = UnorderedMap;
ImageMap image_cache_;
+
+ using GifImageMap = UnorderedMap;
+ GifImageMap gif_image_cache_;
};
}
diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp
new file mode 100644
index 00000000..5dcb8b35
--- /dev/null
+++ b/src/kiwano/renderer/RenderTarget.cpp
@@ -0,0 +1,660 @@
+// Copyright (c) 2016-2019 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 "RenderTarget.h"
+#include "../base/Logger.h"
+
+namespace kiwano
+{
+ //
+ // RenderTarget
+ //
+
+ RenderTarget::RenderTarget()
+ : opacity_(1.f)
+ , collecting_status_(false)
+ , antialias_(true)
+ , text_antialias_(TextAntialias::GrayScale)
+ {
+ status_.primitives = 0;
+ }
+
+ HRESULT RenderTarget::InitDeviceResources(ComPtr rt, ComPtr dev_res)
+ {
+ HRESULT hr = E_FAIL;
+
+ if (rt && dev_res)
+ {
+ render_target_ = rt;
+ d2d_res_ = dev_res;
+ hr = S_OK;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ text_renderer_.reset();
+ hr = ITextRenderer::Create(
+ &text_renderer_,
+ render_target_.get()
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ solid_color_brush_.reset();
+ hr = render_target_->CreateSolidColorBrush(
+ D2D1::ColorF(D2D1::ColorF::White),
+ D2D1::BrushProperties(),
+ &solid_color_brush_
+ );
+ }
+
+ return hr;
+ }
+
+ bool RenderTarget::IsValid() const
+ {
+ return render_target_ && d2d_res_;
+ }
+
+ void RenderTarget::BeginDraw()
+ {
+ HRESULT hr = E_FAIL;
+
+ if (collecting_status_)
+ {
+ status_.start = Time::Now();
+ status_.primitives = 0;
+ }
+
+ if (render_target_)
+ {
+ render_target_->BeginDraw();
+ hr = S_OK;
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::EndDraw()
+ {
+ ThrowIfFailed(render_target_->EndDraw());
+
+ if (collecting_status_)
+ {
+ status_.duration = Time::Now() - status_.start;
+ }
+ }
+
+ void RenderTarget::DrawGeometry(
+ Geometry const& geometry,
+ Color const& stroke_color,
+ float stroke_width,
+ StrokeStyle stroke
+ ) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr) && geometry.GetGeometry())
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
+
+ render_target_->DrawGeometry(
+ geometry.GetGeometry().get(),
+ solid_color_brush_.get(),
+ stroke_width,
+ d2d_res_->GetStrokeStyle(stroke)
+ );
+
+ IncreasePrimitivesCount();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::FillGeometry(Geometry const& geometry, Color const& fill_color) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr) && geometry.GetGeometry())
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
+ render_target_->FillGeometry(
+ geometry.GetGeometry().get(),
+ solid_color_brush_.get()
+ );
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::DrawLine(Point const& point1, Point const& point2, Color const& stroke_color, float stroke_width, StrokeStyle stroke) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
+
+ render_target_->DrawLine(
+ DX::ConvertToPoint2F(point1),
+ DX::ConvertToPoint2F(point2),
+ solid_color_brush_.get(),
+ stroke_width,
+ d2d_res_->GetStrokeStyle(stroke)
+ );
+
+ IncreasePrimitivesCount();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::DrawRectangle(Rect const& rect, Color const& stroke_color, float stroke_width, StrokeStyle stroke) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
+
+ render_target_->DrawRectangle(
+ DX::ConvertToRectF(rect),
+ solid_color_brush_.get(),
+ stroke_width,
+ d2d_res_->GetStrokeStyle(stroke)
+ );
+
+ IncreasePrimitivesCount();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::FillRectangle(Rect const& rect, Color const& fill_color) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
+ render_target_->FillRectangle(
+ DX::ConvertToRectF(rect),
+ solid_color_brush_.get()
+ );
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& stroke_color, float stroke_width, StrokeStyle stroke) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
+
+ render_target_->DrawRoundedRectangle(
+ D2D1::RoundedRect(
+ DX::ConvertToRectF(rect),
+ radius.x,
+ radius.y
+ ),
+ solid_color_brush_.get(),
+ stroke_width,
+ d2d_res_->GetStrokeStyle(stroke)
+ );
+
+ IncreasePrimitivesCount();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& fill_color) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
+ render_target_->FillRoundedRectangle(
+ D2D1::RoundedRect(
+ DX::ConvertToRectF(rect),
+ radius.x,
+ radius.y
+ ),
+ solid_color_brush_.get()
+ );
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, Color const& stroke_color, float stroke_width, StrokeStyle stroke) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
+
+ render_target_->DrawEllipse(
+ D2D1::Ellipse(
+ DX::ConvertToPoint2F(center),
+ radius.x,
+ radius.y
+ ),
+ solid_color_brush_.get(),
+ stroke_width,
+ d2d_res_->GetStrokeStyle(stroke)
+ );
+
+ IncreasePrimitivesCount();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius, Color const& fill_color) const
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_ || !render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
+ render_target_->FillEllipse(
+ D2D1::Ellipse(
+ DX::ConvertToPoint2F(center),
+ radius.x,
+ radius.y
+ ),
+ solid_color_brush_.get()
+ );
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::DrawImage(Image const& image, Rect const& src_rect, Rect const& dest_rect) const
+ {
+ DrawImage(image, &src_rect, &dest_rect);
+ }
+
+ void RenderTarget::DrawImage(Image const& image, const Rect* src_rect, const Rect* dest_rect) const
+ {
+ HRESULT hr = S_OK;
+ if (!render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr) && image.IsValid())
+ {
+ render_target_->DrawBitmap(
+ image.GetBitmap().get(),
+ dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
+ opacity_,
+ D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
+ src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr
+ );
+
+ IncreasePrimitivesCount();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::DrawTextLayout(TextLayout const& layout, Point const& offset) const
+ {
+ HRESULT hr = S_OK;
+ if (!text_renderer_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ text_renderer_->SetTextStyle(
+ opacity_,
+ DX::ConvertToColorF(layout.GetTextStyle().color),
+ layout.GetTextStyle().outline,
+ DX::ConvertToColorF(layout.GetTextStyle().outline_color),
+ layout.GetTextStyle().outline_width,
+ d2d_res_->GetStrokeStyle(layout.GetTextStyle().outline_stroke)
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), offset.x, offset.y);
+
+ IncreasePrimitivesCount();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::CreateLayer(ComPtr& layer) const
+ {
+ HRESULT hr = S_OK;
+ ComPtr new_layer;
+
+ if (!render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = render_target_->CreateLayer(&new_layer);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ layer = new_layer;
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::PushClipRect(Rect const& clip_rect)
+ {
+ HRESULT hr = S_OK;
+ if (!render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ render_target_->PushAxisAlignedClip(
+ DX::ConvertToRectF(clip_rect),
+ D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
+ );
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::PopClipRect()
+ {
+ HRESULT hr = S_OK;
+ if (!render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ render_target_->PopAxisAlignedClip();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::PushLayer(ComPtr const& layer, LayerProperties const& properties)
+ {
+ HRESULT hr = S_OK;
+ if (!render_target_ || !solid_color_brush_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ render_target_->PushLayer(
+ D2D1::LayerParameters(
+ DX::ConvertToRectF(properties.area),
+ nullptr,
+ D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
+ D2D1::Matrix3x2F::Identity(),
+ properties.opacity,
+ nullptr,
+ D2D1_LAYER_OPTIONS_NONE
+ ),
+ layer.get()
+ );
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::PopLayer()
+ {
+ HRESULT hr = S_OK;
+ if (!render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ render_target_->PopLayer();
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::Clear()
+ {
+ HRESULT hr = E_FAIL;
+
+ if (render_target_)
+ {
+ render_target_->Clear();
+ hr = S_OK;
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::Clear(Color const& clear_color)
+ {
+ HRESULT hr = E_FAIL;
+
+ if (render_target_)
+ {
+ render_target_->Clear(DX::ConvertToColorF(clear_color));
+ hr = S_OK;
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ float RenderTarget::GetOpacity() const
+ {
+ return opacity_;
+ }
+
+ void RenderTarget::SetTransform(const Matrix3x2& matrix)
+ {
+ HRESULT hr = S_OK;
+ if (!render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::SetOpacity(float opacity)
+ {
+ HRESULT hr = S_OK;
+ if (!solid_color_brush_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (opacity_ != opacity)
+ {
+ opacity_ = opacity;
+ solid_color_brush_->SetOpacity(opacity);
+ }
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::SetAntialiasMode(bool enabled)
+ {
+ HRESULT hr = S_OK;
+ if (!render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ render_target_->SetAntialiasMode(
+ enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
+ );
+ antialias_ = enabled;
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::SetTextAntialiasMode(TextAntialias mode)
+ {
+ HRESULT hr = S_OK;
+ if (!render_target_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ text_antialias_ = mode;
+ D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
+ switch (text_antialias_)
+ {
+ case TextAntialias::Default:
+ antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
+ break;
+ case TextAntialias::ClearType:
+ antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
+ break;
+ case TextAntialias::GrayScale:
+ antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
+ break;
+ case TextAntialias::None:
+ antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
+ break;
+ default:
+ break;
+ }
+ render_target_->SetTextAntialiasMode(antialias_mode);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+ void RenderTarget::SetCollectingStatus(bool collecting)
+ {
+ collecting_status_ = collecting;
+ }
+
+ void RenderTarget::IncreasePrimitivesCount() const
+ {
+ if (collecting_status_)
+ {
+ ++status_.primitives;
+ }
+ }
+
+
+ //
+ // ImageRenderTarget
+ //
+
+ ImageRenderTarget::ImageRenderTarget()
+ {
+ }
+
+ void ImageRenderTarget::GetOutput(Image& output) const
+ {
+ HRESULT hr = E_FAIL;
+
+ ComPtr bitmap_rt;
+ if (render_target_)
+ {
+ hr = render_target_->QueryInterface(&bitmap_rt);
+ }
+
+ ComPtr bitmap;
+ if (SUCCEEDED(hr))
+ {
+ hr = bitmap_rt->GetBitmap(&bitmap);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ output.SetBitmap(bitmap);
+ }
+
+ ThrowIfFailed(hr);
+ }
+
+}
diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h
new file mode 100644
index 00000000..5619bd30
--- /dev/null
+++ b/src/kiwano/renderer/RenderTarget.h
@@ -0,0 +1,207 @@
+// Copyright (c) 2016-2019 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 "D2DDeviceResources.h"
+#include "Image.h"
+#include "Geometry.h"
+#include "TextLayout.h"
+#include "TextRenderer.h"
+
+namespace kiwano
+{
+ // 渲染目标
+ class KGE_API RenderTarget
+ : public noncopyable
+ {
+ public:
+ void BeginDraw();
+
+ void EndDraw();
+
+ void CreateLayer(
+ ComPtr& layer
+ ) const;
+
+ void DrawGeometry(
+ Geometry const& geometry,
+ Color const& stroke_color,
+ float stroke_width,
+ StrokeStyle stroke = StrokeStyle::Miter
+ ) const;
+
+ void FillGeometry(
+ Geometry const& geometry,
+ Color const& fill_color
+ ) const;
+
+ void DrawLine(
+ Point const& point1,
+ Point const& point2,
+ Color const& stroke_color,
+ float stroke_width,
+ StrokeStyle stroke = StrokeStyle::Miter
+ ) const;
+
+ void DrawRectangle(
+ Rect const& rect,
+ Color const& stroke_color,
+ float stroke_width,
+ StrokeStyle stroke = StrokeStyle::Miter
+ ) const;
+
+ void FillRectangle(
+ Rect const& rect,
+ Color const& fill_color
+ ) const;
+
+ void DrawRoundedRectangle(
+ Rect const& rect,
+ Vec2 const& radius,
+ Color const& stroke_color,
+ float stroke_width,
+ StrokeStyle stroke = StrokeStyle::Miter
+ ) const;
+
+ void FillRoundedRectangle(
+ Rect const& rect,
+ Vec2 const& radius,
+ Color const& fill_color
+ ) const;
+
+ void DrawEllipse(
+ Point const& center,
+ Vec2 const& radius,
+ Color const& stroke_color,
+ float stroke_width,
+ StrokeStyle stroke = StrokeStyle::Miter
+ ) const;
+
+ void FillEllipse(
+ Point const& center,
+ Vec2 const& radius,
+ Color const& fill_color
+ ) const;
+
+ void DrawImage(
+ Image const& image,
+ Rect const& src_rect,
+ Rect const& dest_rect
+ ) const;
+
+ void DrawImage(
+ Image const& image,
+ const Rect* src_rect = nullptr,
+ const Rect* dest_rect = nullptr
+ ) const;
+
+ void DrawTextLayout(
+ TextLayout const& layout,
+ Point const& offset = Point{}
+ ) const;
+
+ void PushClipRect(
+ Rect const& clip_rect
+ );
+
+ void PopClipRect();
+
+ void PushLayer(
+ ComPtr const& layer,
+ LayerProperties const& properties
+ );
+
+ void PopLayer();
+
+ void Clear();
+
+ void Clear(
+ Color const& clear_color
+ );
+
+ float GetOpacity() const;
+
+ void SetOpacity(
+ float opacity
+ );
+
+ void SetTransform(
+ const Matrix3x2& matrix
+ );
+
+ // 设置抗锯齿模式
+ void SetAntialiasMode(
+ bool enabled
+ );
+
+ // 设置文字抗锯齿模式
+ void SetTextAntialiasMode(
+ TextAntialias mode
+ );
+
+ public:
+ struct Status
+ {
+ int primitives;
+ Time start;
+ Duration duration;
+ };
+
+ void SetCollectingStatus(bool collecting);
+
+ void IncreasePrimitivesCount() const;
+
+ inline Status const& GetStatus() const { return status_; }
+
+ inline ComPtr GetRenderTarget() const { return render_target_; }
+
+ public:
+ RenderTarget();
+
+ HRESULT InitDeviceResources(
+ ComPtr rt,
+ ComPtr dev_res
+ );
+
+ bool IsValid() const;
+
+ protected:
+ float opacity_;
+ bool antialias_;
+ mutable bool collecting_status_;
+ mutable Status status_;
+ TextAntialias text_antialias_;
+ ComPtr render_target_;
+ ComPtr text_renderer_;
+ ComPtr solid_color_brush_;
+ ComPtr d2d_res_;
+ };
+
+
+ // 位图渲染目标
+ class KGE_API ImageRenderTarget
+ : public RenderTarget
+ {
+ public:
+ ImageRenderTarget();
+
+ void GetOutput(Image& output) const;
+ };
+}
diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp
index 60c365dd..1688c879 100644
--- a/src/kiwano/renderer/Renderer.cpp
+++ b/src/kiwano/renderer/Renderer.cpp
@@ -21,19 +21,15 @@
#include "Renderer.h"
#include "../base/Logger.h"
#include "../base/Window.h"
+#include "../utils/FileUtil.h"
namespace kiwano
{
Renderer::Renderer()
: hwnd_(nullptr)
- , antialias_(true)
, vsync_(true)
- , text_antialias_(TextAntialias::GrayScale)
, clear_color_(Color::Black)
- , opacity_(1.f)
- , collecting_status_(false)
{
- status_.primitives = 0;
}
Renderer::~Renderer()
@@ -74,8 +70,6 @@ namespace kiwano
#endif
);
- device_context_ = d2d_res_->GetDeviceContext();
-
ThrowIfFailed(
d2d_res_->GetFactory()->CreateDrawingStateBlock(
&drawing_state_block_
@@ -101,16 +95,55 @@ namespace kiwano
void Renderer::BeforeRender()
{
- ThrowIfFailed(
- BeginDraw()
- );
+ HRESULT hr = S_OK;
+
+ if (!IsValid())
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ render_target_->SaveDrawingState(drawing_state_block_.get());
+ BeginDraw();
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = d3d_res_->ClearRenderTarget(clear_color_);
+ }
+
+ ThrowIfFailed(hr);
}
void Renderer::AfterRender()
{
- ThrowIfFailed(
- EndDraw()
- );
+ HRESULT hr = S_OK;
+
+ if (!IsValid())
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ EndDraw();
+
+ render_target_->RestoreDrawingState(drawing_state_block_.get());
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = d3d_res_->Present(vsync_);
+ }
+
+ if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
+ {
+ // 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
+ hr = HandleDeviceLost();
+ }
+
+ ThrowIfFailed(hr);
}
void Renderer::HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
@@ -130,24 +163,11 @@ namespace kiwano
HRESULT Renderer::CreateDeviceResources()
{
- HRESULT hr = S_OK;
-
- solid_color_brush_.reset();
- hr = device_context_->CreateSolidColorBrush(
- D2D1::ColorF(D2D1::ColorF::White),
- D2D1::BrushProperties(),
- &solid_color_brush_
+ HRESULT hr = InitDeviceResources(
+ d2d_res_->GetDeviceContext(),
+ d2d_res_
);
- if (SUCCEEDED(hr))
- {
- text_renderer_.reset();
- hr = ITextRenderer::Create(
- &text_renderer_,
- device_context_.get()
- );
- }
-
if (SUCCEEDED(hr))
{
SetAntialiasMode(antialias_);
@@ -167,82 +187,104 @@ namespace kiwano
return hr;
}
- HRESULT Renderer::BeginDraw()
- {
- if (!device_context_)
- return E_UNEXPECTED;
-
- if (collecting_status_)
- {
- status_.start = Time::Now();
- status_.primitives = 0;
- }
-
- device_context_->SaveDrawingState(drawing_state_block_.get());
-
- device_context_->BeginDraw();
-
- HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_);
-
- return hr;
- }
-
- HRESULT Renderer::EndDraw()
- {
- if (!device_context_)
- return E_UNEXPECTED;
-
- HRESULT hr = device_context_->EndDraw();
-
- device_context_->RestoreDrawingState(drawing_state_block_.get());
-
- if (SUCCEEDED(hr))
- {
- hr = d3d_res_->Present(vsync_);
- }
-
- if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
- {
- // 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
- hr = HandleDeviceLost();
- }
-
- if (collecting_status_)
- {
- status_.duration = Time::Now() - status_.start;
- }
- return hr;
- }
-
- void Renderer::IncreasePrimitivesCount()
- {
- if (collecting_status_)
- {
- ++status_.primitives;
- }
- }
-
- void Renderer::CreateLayer(ComPtr& layer)
+ void Renderer::CreateImage(Image& image, Resource const& res)
{
HRESULT hr = S_OK;
- ComPtr new_layer;
-
- if (!device_context_)
+ if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
- if (SUCCEEDED(hr))
+ ComPtr bitmap;
+ if (res.IsFileType())
{
- hr = device_context_->CreateLayer(&new_layer);
+ hr = d2d_res_->CreateBitmapFromFile(bitmap, res.GetFileName());
+ }
+ else
+ {
+ hr = d2d_res_->CreateBitmapFromResource(bitmap, res);
}
if (SUCCEEDED(hr))
{
- layer = new_layer;
+ image.SetBitmap(bitmap);
}
- ThrowIfFailed(hr);
+ if (FAILED(hr))
+ {
+ KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr);
+ }
+ }
+
+ void Renderer::CreateGifImage(GifImage& image, Resource const& res)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ ComPtr decoder;
+ if (res.IsFileType())
+ {
+ if (!FileUtil::ExistsFile(res.GetFileName().c_str()))
+ {
+ KGE_WARNING_LOG(L"Gif image file '%s' not found!", res.GetFileName().c_str());
+ hr = E_FAIL;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename(
+ res.GetFileName().c_str(),
+ nullptr,
+ GENERIC_READ,
+ WICDecodeMetadataCacheOnLoad,
+ &decoder
+ );
+ }
+ }
+ else
+ {
+ LPVOID buffer;
+ DWORD buffer_size;
+ HRESULT hr = res.Load(buffer, buffer_size) ? S_OK : E_FAIL;
+
+ ComPtr stream;
+
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = stream->InitializeFromMemory(
+ static_cast(buffer),
+ buffer_size
+ );
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream(
+ stream.get(),
+ nullptr,
+ WICDecodeMetadataCacheOnLoad,
+ &decoder
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ image.SetDecoder(decoder);
+ }
+
+ if (FAILED(hr))
+ {
+ KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr);
+ }
}
void Renderer::CreateTextFormat(TextFormat& format, Font const& font)
@@ -297,7 +339,7 @@ namespace kiwano
void Renderer::CreateLineGeometry(Geometry& geo, Point const& begin_pos, Point const& end_pos)
{
HRESULT hr = S_OK;
- if (!device_context_ || !d2d_res_)
+ if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
@@ -333,7 +375,7 @@ namespace kiwano
void Renderer::CreateRectGeometry(Geometry& geo, Rect const& rect)
{
HRESULT hr = S_OK;
- if (!device_context_ || !d2d_res_)
+ if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
@@ -355,7 +397,7 @@ namespace kiwano
void Renderer::CreateRoundedRectGeometry(Geometry& geo, Rect const& rect, Vec2 const& radius)
{
HRESULT hr = S_OK;
- if (!device_context_ || !d2d_res_)
+ if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
@@ -383,7 +425,7 @@ namespace kiwano
void Renderer::CreateEllipseGeometry(Geometry& geo, Point const& center, Vec2 const& radius)
{
HRESULT hr = S_OK;
- if (!device_context_ || !d2d_res_)
+ if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
@@ -411,7 +453,7 @@ namespace kiwano
void Renderer::CreatePathGeometrySink(GeometrySink& sink)
{
HRESULT hr = S_OK;
- if (!device_context_ || !d2d_res_)
+ if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
@@ -430,150 +472,23 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void Renderer::DrawGeometry(
- Geometry const& geometry,
- Color const& stroke_color,
- float stroke_width,
- StrokeStyle stroke
- )
+ void Renderer::CreateImageRenderTarget(ImageRenderTarget& render_target)
{
HRESULT hr = S_OK;
- if (!solid_color_brush_ || !device_context_)
+ if (!d2d_res_)
{
hr = E_UNEXPECTED;
}
- if (SUCCEEDED(hr) && geometry.GetGeometry())
+ ComPtr output;
+ if (SUCCEEDED(hr))
{
- solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
-
- device_context_->DrawGeometry(
- geometry.GetGeometry().get(),
- solid_color_brush_.get(),
- stroke_width,
- d2d_res_->GetStrokeStyle(stroke)
- );
-
- IncreasePrimitivesCount();
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::FillGeometry(Geometry const & geometry, Color const& fill_color)
- {
- HRESULT hr = S_OK;
- if (!solid_color_brush_ || !device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr) && geometry.GetGeometry())
- {
- solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
- device_context_->FillGeometry(
- geometry.GetGeometry().get(),
- solid_color_brush_.get()
- );
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::DrawRectangle(Rect const& rect, Color const& stroke_color, float stroke_width, StrokeStyle stroke)
- {
- HRESULT hr = S_OK;
- if (!solid_color_brush_ || !device_context_)
- {
- hr = E_UNEXPECTED;
+ hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(&output);
}
if (SUCCEEDED(hr))
{
- solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
-
- device_context_->DrawRectangle(
- DX::ConvertToRectF(rect),
- solid_color_brush_.get(),
- stroke_width,
- d2d_res_->GetStrokeStyle(stroke)
- );
-
- IncreasePrimitivesCount();
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::FillRectangle(Rect const& rect, Color const& fill_color)
- {
- HRESULT hr = S_OK;
- if (!solid_color_brush_ || !device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
- device_context_->FillRectangle(
- DX::ConvertToRectF(rect),
- solid_color_brush_.get()
- );
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::DrawBitmap(ComPtr const & bitmap, Rect const& src_rect, Rect const& dest_rect)
- {
- HRESULT hr = S_OK;
- if (!device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr) && bitmap)
- {
- device_context_->DrawBitmap(
- bitmap.get(),
- DX::ConvertToRectF(dest_rect),
- opacity_,
- D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
- DX::ConvertToRectF(src_rect)
- );
-
- IncreasePrimitivesCount();
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::DrawTextLayout(TextLayout const& layout)
- {
- HRESULT hr = S_OK;
- if (!text_renderer_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- SetTextStyle(
- opacity_,
- layout.GetTextStyle().color,
- layout.GetTextStyle().outline,
- layout.GetTextStyle().outline_color,
- layout.GetTextStyle().outline_width,
- layout.GetTextStyle().outline_stroke
- );
- }
-
- if (SUCCEEDED(hr))
- {
- hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), 0, 0);
-
- IncreasePrimitivesCount();
+ hr = render_target.InitDeviceResources(output, d2d_res_);
}
ThrowIfFailed(hr);
@@ -584,85 +499,6 @@ namespace kiwano
vsync_ = enabled;
}
- void Renderer::PushClip(const Matrix3x2 & clip_matrix, const Size & clip_size)
- {
- HRESULT hr = S_OK;
- if (!device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- device_context_->SetTransform(DX::ConvertToMatrix3x2F(clip_matrix));
- device_context_->PushAxisAlignedClip(
- D2D1::RectF(0, 0, clip_size.x, clip_size.y),
- D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
- );
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::PopClip()
- {
- HRESULT hr = S_OK;
- if (!device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- device_context_->PopAxisAlignedClip();
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::PushLayer(ComPtr const& layer, LayerProperties const& properties)
- {
- HRESULT hr = S_OK;
- if (!device_context_ || !solid_color_brush_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- device_context_->PushLayer(
- D2D1::LayerParameters(
- DX::ConvertToRectF(properties.area),
- nullptr,
- D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
- D2D1::Matrix3x2F::Identity(),
- properties.opacity,
- nullptr,
- D2D1_LAYER_OPTIONS_NONE
- ),
- layer.get()
- );
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::PopLayer()
- {
- HRESULT hr = S_OK;
- if (!device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- device_context_->PopLayer();
- }
-
- ThrowIfFailed(hr);
- }
-
void Renderer::Resize(UINT width, UINT height)
{
HRESULT hr = S_OK;
@@ -681,136 +517,11 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void Renderer::SetCollectingStatus(bool collecting)
- {
- collecting_status_ = collecting;
- }
-
- void Renderer::SetClearColor(const Color & color)
+ void Renderer::SetClearColor(const Color& color)
{
clear_color_ = color;
}
- void Renderer::SetTransform(const Matrix3x2 & matrix)
- {
- HRESULT hr = S_OK;
- if (!device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- device_context_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::SetOpacity(float opacity)
- {
- HRESULT hr = S_OK;
- if (!solid_color_brush_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- if (opacity_ != opacity)
- {
- opacity_ = opacity;
- solid_color_brush_->SetOpacity(opacity);
- }
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::SetTextStyle(
- float opacity,
- Color const& color,
- bool has_outline,
- Color const& outline_color,
- float outline_width,
- StrokeStyle outline_stroke
- )
- {
- HRESULT hr = S_OK;
- if (!text_renderer_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- text_renderer_->SetTextStyle(
- opacity,
- DX::ConvertToColorF(color),
- has_outline,
- DX::ConvertToColorF(outline_color),
- outline_width,
- d2d_res_->GetStrokeStyle(outline_stroke)
- );
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::SetAntialiasMode(bool enabled)
- {
- HRESULT hr = S_OK;
- if (!device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- device_context_->SetAntialiasMode(
- enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
- );
- antialias_ = enabled;
- }
-
- ThrowIfFailed(hr);
- }
-
- void Renderer::SetTextAntialiasMode(TextAntialias mode)
- {
- HRESULT hr = S_OK;
- if (!device_context_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- text_antialias_ = mode;
- D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
- switch (text_antialias_)
- {
- case TextAntialias::Default:
- antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
- break;
- case TextAntialias::ClearType:
- antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
- break;
- case TextAntialias::GrayScale:
- antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
- break;
- case TextAntialias::None:
- antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
- break;
- default:
- break;
- }
- device_context_->SetTextAntialiasMode(antialias_mode);
- }
-
- ThrowIfFailed(hr);
- }
-
bool Renderer::CheckVisibility(Size const& content_size, Matrix3x2 const& transform)
{
return Rect{ Point{}, output_size_ }.Intersects(
diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h
index aa4b88f0..16d8081e 100644
--- a/src/kiwano/renderer/Renderer.h
+++ b/src/kiwano/renderer/Renderer.h
@@ -24,10 +24,8 @@
#include "../base/Resource.h"
#include "../2d/include-forwards.h"
#include "helper.hpp"
-#include "Image.h"
-#include "Geometry.h"
-#include "TextLayout.h"
-#include "TextRenderer.h"
+#include "RenderTarget.h"
+#include "GifImage.h"
#if defined(KGE_USE_DIRECTX10)
# include "D3D10DeviceResources.h"
@@ -47,6 +45,7 @@ namespace kiwano
class KGE_API Renderer
: public Singleton
, public Component
+ , public RenderTarget
{
KGE_DECLARE_SINGLETON(Renderer);
@@ -56,24 +55,20 @@ namespace kiwano
Color const& clear_color
);
- // 设置抗锯齿模式
- void SetAntialiasMode(
- bool enabled
- );
-
- // 设置文字抗锯齿模式
- void SetTextAntialiasMode(
- TextAntialias mode
- );
-
// 开启或关闭垂直同步
void SetVSyncEnabled(
bool enabled
);
public:
- void CreateLayer(
- ComPtr& layer
+ void CreateImage(
+ Image& image,
+ Resource const& res
+ );
+
+ void CreateGifImage(
+ GifImage& image,
+ Resource const& res
);
void CreateTextFormat(
@@ -115,71 +110,10 @@ namespace kiwano
GeometrySink& sink
);
- void DrawGeometry(
- Geometry const& geometry,
- const Color& stroke_color,
- float stroke_width,
- StrokeStyle stroke = StrokeStyle::Miter
+ void CreateImageRenderTarget(
+ ImageRenderTarget& render_target
);
- void FillGeometry(
- Geometry const& geometry,
- Color const& fill_color
- );
-
- void DrawRectangle(
- Rect const& rect,
- Color const& stroke_color,
- float stroke_width,
- StrokeStyle stroke = StrokeStyle::Miter
- );
-
- void FillRectangle(
- Rect const& rect,
- Color const& fill_color
- );
-
- void DrawBitmap(
- ComPtr const& bitmap,
- Rect const& src_rect,
- Rect const& dest_rect
- );
-
- void DrawTextLayout(
- TextLayout const& layout
- );
-
- void SetOpacity(
- float opacity
- );
-
- void SetTransform(
- const Matrix3x2& matrix
- );
-
- void SetTextStyle(
- float opacity,
- const Color& color,
- bool has_outline,
- const Color& outline_color,
- float outline_width,
- StrokeStyle outline_stroke
- );
-
- void PushClip(
- const Matrix3x2& clip_matrix,
- const Size& clip_size
- );
-
- void PopClip();
-
- void PushLayer(
- ComPtr const& layer,
- LayerProperties const& properties
- );
-
- void PopLayer();
-
void Resize(
UINT width,
UINT height
@@ -201,20 +135,9 @@ namespace kiwano
void HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override;
- void SetCollectingStatus(bool collecting);
-
public:
- struct Status
- {
- Time start;
- Duration duration;
- int primitives;
- };
-
inline HWND GetTargetWindow() const { return hwnd_; }
- inline Status const& GetStatus() const { return status_; }
-
inline Size const& GetOutputSize() const { return output_size_; }
inline ID2DDeviceResources* GetD2DDeviceResources() const { KGE_ASSERT(d2d_res_); return d2d_res_.get(); }
@@ -234,28 +157,14 @@ namespace kiwano
HRESULT HandleDeviceLost();
- HRESULT BeginDraw();
-
- HRESULT EndDraw();
-
- void IncreasePrimitivesCount();
-
private:
- bool vsync_;
- bool antialias_;
- bool collecting_status_;
- float opacity_;
- HWND hwnd_;
- Size output_size_;
- Color clear_color_;
- TextAntialias text_antialias_;
- Status status_;
+ bool vsync_;
+ HWND hwnd_;
+ Size output_size_;
+ Color clear_color_;
ComPtr d2d_res_;
ComPtr d3d_res_;
- ComPtr device_context_;
ComPtr drawing_state_block_;
- ComPtr text_renderer_;
- ComPtr solid_color_brush_;
};
}
diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp
index b4c111c8..7d86fac6 100644
--- a/src/kiwano/utils/ResourceCache.cpp
+++ b/src/kiwano/utils/ResourceCache.cpp
@@ -280,7 +280,7 @@ namespace kiwano
FramePtr ptr = new (std::nothrow) Frame(raw->GetImage());
if (ptr)
{
- ptr->Crop(Rect{ j * width, i * height, width, height });
+ ptr->SetCropRect(Rect{ j * width, i * height, width, height });
image_arr.push_back(ptr);
}
}
@@ -304,7 +304,7 @@ namespace kiwano
FramePtr ptr = new (std::nothrow) Frame(raw->GetImage());
if (ptr)
{
- ptr->Crop(rect);
+ ptr->SetCropRect(rect);
image_arr.push_back(ptr);
}
}
From a3fad67bfa8ddaa1b6069422db4566323e776a58 Mon Sep 17 00:00:00 2001
From: Nomango <569629550@qq.com>
Date: Fri, 16 Aug 2019 10:12:34 +0800
Subject: [PATCH 3/8] Add LayerArea
---
appveyor.yml | 7 +-
projects/kiwano.vcxproj | 8 ++-
projects/kiwano.vcxproj.filters | 24 +++++--
src/kiwano/2d/Transition.cpp | 69 ++++++++++----------
src/kiwano/2d/Transition.h | 22 +++----
src/kiwano/2d/include-forwards.h | 4 +-
src/kiwano/base/types.h | 7 --
src/kiwano/kiwano.h | 6 +-
src/kiwano/platform/Application.h | 2 +-
src/kiwano/{2d => renderer}/Color.cpp | 0
src/kiwano/{2d => renderer}/Color.h | 0
src/kiwano/renderer/D2DDeviceResources.h | 2 +-
src/kiwano/renderer/D3DDeviceResourcesBase.h | 2 +-
src/kiwano/renderer/Font.cpp | 32 +++++++++
src/kiwano/{2d/Font.hpp => renderer/Font.h} | 28 ++++----
src/kiwano/renderer/LayerArea.cpp | 44 +++++++++++++
src/kiwano/renderer/LayerArea.h | 60 +++++++++++++++++
src/kiwano/renderer/RenderTarget.cpp | 30 ++++-----
src/kiwano/renderer/RenderTarget.h | 6 +-
src/kiwano/renderer/TextLayout.h | 2 +-
src/kiwano/renderer/helper.hpp | 2 +-
21 files changed, 251 insertions(+), 106 deletions(-)
rename src/kiwano/{2d => renderer}/Color.cpp (100%)
rename src/kiwano/{2d => renderer}/Color.h (100%)
create mode 100644 src/kiwano/renderer/Font.cpp
rename src/kiwano/{2d/Font.hpp => renderer/Font.h} (85%)
create mode 100644 src/kiwano/renderer/LayerArea.cpp
create mode 100644 src/kiwano/renderer/LayerArea.h
diff --git a/appveyor.yml b/appveyor.yml
index 27df39b0..9f7cf1bd 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -5,8 +5,8 @@ skip_tags: true
# fetch repository as zip archive
shallow_clone: true
-# pull_requests:
-# do_not_increment_build_number: true
+pull_requests:
+ do_not_increment_build_number: true
# Do not build feature branch with open Pull Requests
# skip_branch_with_pr: true
@@ -54,6 +54,9 @@ for:
- master
only_commits:
message: /\[build\]/
+ matrix:
+ - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
+ VS_PLATFORM_TOOLSET: v142
configuration:
- Debug
diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj
index c9958130..a1b790a9 100644
--- a/projects/kiwano.vcxproj
+++ b/projects/kiwano.vcxproj
@@ -28,7 +28,6 @@
-
@@ -67,15 +66,18 @@
+
+
+
@@ -98,7 +100,6 @@
-
@@ -124,13 +125,16 @@
+
+
+
diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters
index b3b2d69d..586733bf 100644
--- a/projects/kiwano.vcxproj.filters
+++ b/projects/kiwano.vcxproj.filters
@@ -48,9 +48,6 @@
2d
-
- 2d
-
2d
@@ -294,6 +291,15 @@
renderer
+
+ renderer
+
+
+ renderer
+
+
+ renderer
+
@@ -305,9 +311,6 @@
2d
-
- 2d
-
2d
@@ -455,5 +458,14 @@
renderer
+
+ renderer
+
+
+ renderer
+
+
+ renderer
+
\ No newline at end of file
diff --git a/src/kiwano/2d/Transition.cpp b/src/kiwano/2d/Transition.cpp
index d5353c05..8fe41b9c 100644
--- a/src/kiwano/2d/Transition.cpp
+++ b/src/kiwano/2d/Transition.cpp
@@ -39,10 +39,8 @@ namespace kiwano
, window_size_()
, out_scene_(nullptr)
, in_scene_(nullptr)
- , out_layer_(nullptr)
- , in_layer_(nullptr)
- , out_layer_prop_()
- , in_layer_prop_()
+ , out_layer_()
+ , in_layer_()
{
}
@@ -74,7 +72,8 @@ namespace kiwano
}
window_size_ = Renderer::GetInstance()->GetOutputSize();
- out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f };
+ out_layer_.SetAreaRect(Rect{ Point(), window_size_ });
+ in_layer_.SetAreaRect(Rect{ Point(), window_size_ });
}
void Transition::Update(Duration dt)
@@ -101,7 +100,7 @@ namespace kiwano
{
renderer->SetTransform(out_scene_->GetTransformMatrix());
renderer->PushClipRect(Rect{ Point{}, window_size_ });
- renderer->PushLayer(out_layer_, out_layer_prop_);
+ renderer->PushLayer(out_layer_);
out_scene_->Render(renderer);
@@ -113,7 +112,7 @@ namespace kiwano
{
renderer->SetTransform(in_scene_->GetTransformMatrix());
renderer->PushClipRect(Rect{ Point{}, window_size_ });
- renderer->PushLayer(in_layer_, in_layer_prop_);
+ renderer->PushLayer(in_layer_);
in_scene_->Render(renderer);
@@ -141,7 +140,7 @@ namespace kiwano
{
Transition::Init(prev, next);
- in_layer_prop_.opacity = 0;
+ in_layer_.SetOpacity(0.f);
}
void BoxTransition::Update(Duration dt)
@@ -150,22 +149,26 @@ namespace kiwano
if (process_ < .5f)
{
- out_layer_prop_.area = Rect(
- window_size_.x * process_,
- window_size_.y * process_,
- window_size_.x * (1 - process_ * 2),
- window_size_.y * (1 - process_ * 2)
+ out_layer_.SetAreaRect(
+ Rect(
+ window_size_.x * process_,
+ window_size_.y * process_,
+ window_size_.x * (1 - process_ * 2),
+ window_size_.y * (1 - process_ * 2)
+ )
);
}
else
{
- out_layer_prop_.opacity = 0;
- in_layer_prop_.opacity = 1;
- in_layer_prop_.area = Rect(
- window_size_.x * (1 - process_),
- window_size_.y * (1 - process_),
- window_size_.x * (2 * process_ - 1),
- window_size_.y * (2 * process_ - 1)
+ out_layer_.SetOpacity(0.f);
+ in_layer_.SetOpacity(1.f);
+ in_layer_.SetAreaRect(
+ Rect(
+ window_size_.x * (1 - process_),
+ window_size_.y * (1 - process_),
+ window_size_.x * (2 * process_ - 1),
+ window_size_.y * (2 * process_ - 1)
+ )
);
}
}
@@ -183,16 +186,16 @@ namespace kiwano
{
Transition::Init(prev, next);
- out_layer_prop_.opacity = 1;
- in_layer_prop_.opacity = 0;
+ out_layer_.SetOpacity(1.f);
+ in_layer_.SetOpacity(0.f);
}
void EmergeTransition::Update(Duration dt)
{
Transition::Update(dt);
- out_layer_prop_.opacity = 1 - process_;
- in_layer_prop_.opacity = process_;
+ out_layer_.SetOpacity(1 - process_);
+ in_layer_.SetOpacity(process_);
}
//-------------------------------------------------------
@@ -208,8 +211,8 @@ namespace kiwano
{
Transition::Init(prev, next);
- out_layer_prop_.opacity = 1;
- in_layer_prop_.opacity = 0;
+ out_layer_.SetOpacity(1.f);
+ in_layer_.SetOpacity(0.f);
}
void FadeTransition::Update(Duration dt)
@@ -218,13 +221,13 @@ namespace kiwano
if (process_ < 0.5)
{
- out_layer_prop_.opacity = 1 - process_ * 2;
- in_layer_prop_.opacity = 0;
+ out_layer_.SetOpacity(1 - process_ * 2);
+ in_layer_.SetOpacity(0.f);
}
else
{
- out_layer_prop_.opacity = 0;
- in_layer_prop_.opacity = (process_ - 0.5f) * 2;
+ out_layer_.SetOpacity(0.f);
+ in_layer_.SetOpacity((process_ - 0.5f) * 2);
}
}
@@ -336,7 +339,7 @@ namespace kiwano
in_scene_->SetAnchor(0.5f, 0.5f);
}
- in_layer_prop_.opacity = 0;
+ in_layer_.SetOpacity(0.f);
}
void RotationTransition::Update(Duration dt)
@@ -357,8 +360,8 @@ namespace kiwano
{
if (in_scene_)
{
- out_layer_prop_.opacity = 0;
- in_layer_prop_.opacity = 1;
+ out_layer_.SetOpacity(0.f);
+ in_layer_.SetOpacity(1.f);
auto transform = in_scene_->GetTransform();
transform.scale = Point{ (process_ - .5f) * 2, (process_ - .5f) * 2 };
diff --git a/src/kiwano/2d/Transition.h b/src/kiwano/2d/Transition.h
index 63cd9642..67dc8900 100644
--- a/src/kiwano/2d/Transition.h
+++ b/src/kiwano/2d/Transition.h
@@ -20,7 +20,7 @@
#pragma once
#include "include-forwards.h"
-#include
+#include "../renderer/LayerArea.h"
namespace kiwano
{
@@ -57,17 +57,15 @@ namespace kiwano
virtual void Reset() { };
protected:
- bool done_;
- float process_;
- Duration duration_;
- Duration delta_;
- Size window_size_;
- StagePtr out_scene_;
- StagePtr in_scene_;
- ComPtr out_layer_;
- ComPtr in_layer_;
- LayerProperties out_layer_prop_;
- LayerProperties in_layer_prop_;
+ bool done_;
+ float process_;
+ Duration duration_;
+ Duration delta_;
+ Size window_size_;
+ StagePtr out_scene_;
+ StagePtr in_scene_;
+ LayerArea out_layer_;
+ LayerArea in_layer_;
};
diff --git a/src/kiwano/2d/include-forwards.h b/src/kiwano/2d/include-forwards.h
index 98f832e4..97473233 100644
--- a/src/kiwano/2d/include-forwards.h
+++ b/src/kiwano/2d/include-forwards.h
@@ -19,15 +19,15 @@
// THE SOFTWARE.
#pragma once
-#include "Color.h"
#include "../core/core.h"
#include "../base/time.h"
#include "../base/RefCounter.hpp"
#include "../base/SmartPtr.hpp"
#include "../base/ComPtr.hpp"
#include "../base/Object.h"
-#include "../math/helper.h"
#include "../base/types.h"
+#include "../math/helper.h"
+#include "../renderer/Color.h"
namespace kiwano
{
diff --git a/src/kiwano/base/types.h b/src/kiwano/base/types.h
index 54531e14..b3045ffb 100644
--- a/src/kiwano/base/types.h
+++ b/src/kiwano/base/types.h
@@ -61,11 +61,4 @@ namespace kiwano
GrayScale, // 灰度抗锯齿
None // 不启用抗锯齿
};
-
- // 图层属性
- struct LayerProperties
- {
- Rect area;
- float opacity;
- };
}
diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h
index 32e44077..34ab234e 100644
--- a/src/kiwano/kiwano.h
+++ b/src/kiwano/kiwano.h
@@ -59,11 +59,14 @@
// renderer
//
+#include "renderer/Color.h"
+#include "renderer/Font.h"
#include "renderer/Image.h"
#include "renderer/GifImage.h"
#include "renderer/TextLayout.h"
#include "renderer/TextRenderer.h"
#include "renderer/Geometry.h"
+#include "renderer/LayerArea.h"
#include "renderer/ImageCache.h"
#include "renderer/RenderTarget.h"
#include "renderer/Renderer.h"
@@ -96,8 +99,7 @@
// 2d
//
-#include "2d/Font.hpp"
-#include "2d/Color.h"
+
#include "2d/Transform.hpp"
#include "2d/TextStyle.hpp"
diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h
index 595bbbb3..bb8804ee 100644
--- a/src/kiwano/platform/Application.h
+++ b/src/kiwano/platform/Application.h
@@ -23,7 +23,7 @@
#include "../base/time.h"
#include "../base/Component.h"
#include "../base/Event.hpp"
-#include "../2d/Color.h"
+#include "../renderer/Color.h"
namespace kiwano
{
diff --git a/src/kiwano/2d/Color.cpp b/src/kiwano/renderer/Color.cpp
similarity index 100%
rename from src/kiwano/2d/Color.cpp
rename to src/kiwano/renderer/Color.cpp
diff --git a/src/kiwano/2d/Color.h b/src/kiwano/renderer/Color.h
similarity index 100%
rename from src/kiwano/2d/Color.h
rename to src/kiwano/renderer/Color.h
diff --git a/src/kiwano/renderer/D2DDeviceResources.h b/src/kiwano/renderer/D2DDeviceResources.h
index a425f806..cd304459 100644
--- a/src/kiwano/renderer/D2DDeviceResources.h
+++ b/src/kiwano/renderer/D2DDeviceResources.h
@@ -20,8 +20,8 @@
#pragma once
#include "helper.hpp"
+#include "Font.h"
#include "../base/Resource.h"
-#include "../2d/Font.hpp"
#include "../2d/TextStyle.hpp"
#include
#include
diff --git a/src/kiwano/renderer/D3DDeviceResourcesBase.h b/src/kiwano/renderer/D3DDeviceResourcesBase.h
index d742c41f..e378649c 100644
--- a/src/kiwano/renderer/D3DDeviceResourcesBase.h
+++ b/src/kiwano/renderer/D3DDeviceResourcesBase.h
@@ -21,7 +21,7 @@
#pragma once
#include "../macros.h"
#include "../math/helper.h"
-#include "../2d/Color.h"
+#include "Color.h"
#include
namespace kiwano
diff --git a/src/kiwano/renderer/Font.cpp b/src/kiwano/renderer/Font.cpp
new file mode 100644
index 00000000..20ce297b
--- /dev/null
+++ b/src/kiwano/renderer/Font.cpp
@@ -0,0 +1,32 @@
+// 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 "Font.h"
+
+namespace kiwano
+{
+ Font::Font(const String& family, float size, unsigned int weight, bool italic)
+ : family(family)
+ , size(size)
+ , weight(weight)
+ , italic(italic)
+ {
+ }
+}
diff --git a/src/kiwano/2d/Font.hpp b/src/kiwano/renderer/Font.h
similarity index 85%
rename from src/kiwano/2d/Font.hpp
rename to src/kiwano/renderer/Font.h
index 091679a3..fc402f2b 100644
--- a/src/kiwano/2d/Font.hpp
+++ b/src/kiwano/renderer/Font.h
@@ -19,22 +19,22 @@
// THE SOFTWARE.
#pragma once
-#include
+#include "../core/core.h"
namespace kiwano
{
// 字体粗细值
enum FontWeight : unsigned int
{
- Thin = 100,
- ExtraLight = 200,
- Light = 300,
- Normal = 400,
- Medium = 500,
- Bold = 700,
- ExtraBold = 800,
- Black = 900,
- ExtraBlack = 950
+ Thin = 100,
+ ExtraLight = 200,
+ Light = 300,
+ Normal = 400,
+ Medium = 500,
+ Bold = 700,
+ ExtraBold = 800,
+ Black = 900,
+ ExtraBlack = 950
};
// 字体
@@ -52,12 +52,6 @@ namespace kiwano
float size = 18,
unsigned int weight = FontWeight::Normal,
bool italic = false
- )
- : family(family)
- , size(size)
- , weight(weight)
- , italic(italic)
- {
- }
+ );
};
}
diff --git a/src/kiwano/renderer/LayerArea.cpp b/src/kiwano/renderer/LayerArea.cpp
new file mode 100644
index 00000000..a81ddddd
--- /dev/null
+++ b/src/kiwano/renderer/LayerArea.cpp
@@ -0,0 +1,44 @@
+// Copyright (c) 2016-2019 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 "LayerArea.h"
+
+namespace kiwano
+{
+ LayerArea::LayerArea()
+ : opacity_(1.f)
+ {
+ }
+
+ bool LayerArea::IsValid() const
+ {
+ return layer_ != nullptr;
+ }
+
+ Size LayerArea::GetSize() const
+ {
+ if (layer_)
+ {
+ return reinterpret_cast(layer_->GetSize());
+ }
+ return Size();
+ }
+
+}
diff --git a/src/kiwano/renderer/LayerArea.h b/src/kiwano/renderer/LayerArea.h
new file mode 100644
index 00000000..92e2848e
--- /dev/null
+++ b/src/kiwano/renderer/LayerArea.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2016-2019 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 "D2DDeviceResources.h"
+#include "Geometry.h"
+
+namespace kiwano
+{
+ // 图层
+ class KGE_API LayerArea
+ {
+ public:
+ LayerArea();
+
+ bool IsValid() const;
+
+ Size GetSize() const;
+
+ inline Rect const& GetAreaRect() const { return area_; }
+
+ inline void SetAreaRect(Rect const& area) { area_ = area; }
+
+ inline float GetOpacity() const { return opacity_; }
+
+ inline void SetOpacity(float opacity) { opacity_ = opacity; }
+
+ inline Geometry const& GetMaskGeometry() const { return mask_; }
+
+ inline void SetMaskGeometry(Geometry const& mask) { mask_ = mask; }
+
+ public:
+ inline ComPtr GetLayer() const { return layer_; }
+
+ inline void SetLayer(ComPtr layer) { layer_ = layer; }
+
+ protected:
+ Rect area_;
+ float opacity_;
+ Geometry mask_;
+ ComPtr layer_;
+ };
+}
diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp
index 5dcb8b35..1403d109 100644
--- a/src/kiwano/renderer/RenderTarget.cpp
+++ b/src/kiwano/renderer/RenderTarget.cpp
@@ -389,10 +389,9 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::CreateLayer(ComPtr& layer) const
+ void RenderTarget::CreateLayer(LayerArea& layer) const
{
HRESULT hr = S_OK;
- ComPtr new_layer;
if (!render_target_)
{
@@ -401,12 +400,13 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- hr = render_target_->CreateLayer(&new_layer);
- }
+ ComPtr output;
+ hr = render_target_->CreateLayer(&output);
- if (SUCCEEDED(hr))
- {
- layer = new_layer;
+ if (SUCCEEDED(hr))
+ {
+ layer.SetLayer(output);
+ }
}
ThrowIfFailed(hr);
@@ -424,7 +424,7 @@ namespace kiwano
{
render_target_->PushAxisAlignedClip(
DX::ConvertToRectF(clip_rect),
- D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
+ antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
);
}
@@ -447,7 +447,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::PushLayer(ComPtr const& layer, LayerProperties const& properties)
+ void RenderTarget::PushLayer(LayerArea const& layer)
{
HRESULT hr = S_OK;
if (!render_target_ || !solid_color_brush_)
@@ -455,19 +455,19 @@ namespace kiwano
hr = E_UNEXPECTED;
}
- if (SUCCEEDED(hr))
+ if (SUCCEEDED(hr) && layer.IsValid())
{
render_target_->PushLayer(
D2D1::LayerParameters(
- DX::ConvertToRectF(properties.area),
- nullptr,
- D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
+ DX::ConvertToRectF(layer.GetAreaRect()),
+ layer.GetMaskGeometry().GetGeometry().get(),
+ antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED,
D2D1::Matrix3x2F::Identity(),
- properties.opacity,
+ layer.GetOpacity(),
nullptr,
D2D1_LAYER_OPTIONS_NONE
),
- layer.get()
+ layer.GetLayer().get()
);
}
diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h
index 5619bd30..74ec7b51 100644
--- a/src/kiwano/renderer/RenderTarget.h
+++ b/src/kiwano/renderer/RenderTarget.h
@@ -24,6 +24,7 @@
#include "Geometry.h"
#include "TextLayout.h"
#include "TextRenderer.h"
+#include "LayerArea.h"
namespace kiwano
{
@@ -37,7 +38,7 @@ namespace kiwano
void EndDraw();
void CreateLayer(
- ComPtr& layer
+ LayerArea& layer
) const;
void DrawGeometry(
@@ -124,8 +125,7 @@ namespace kiwano
void PopClipRect();
void PushLayer(
- ComPtr const& layer,
- LayerProperties const& properties
+ LayerArea const& layer
);
void PopLayer();
diff --git a/src/kiwano/renderer/TextLayout.h b/src/kiwano/renderer/TextLayout.h
index a9aebe9c..3fc3add2 100644
--- a/src/kiwano/renderer/TextLayout.h
+++ b/src/kiwano/renderer/TextLayout.h
@@ -20,7 +20,7 @@
#pragma once
#include "D2DDeviceResources.h"
-#include "../2d/Font.hpp"
+#include "Font.h"
#include "../2d/TextStyle.hpp"
namespace kiwano
diff --git a/src/kiwano/renderer/helper.hpp b/src/kiwano/renderer/helper.hpp
index 3c781b1b..ace4bd9f 100644
--- a/src/kiwano/renderer/helper.hpp
+++ b/src/kiwano/renderer/helper.hpp
@@ -21,7 +21,7 @@
#pragma once
#include "../base/ComPtr.hpp"
#include "../math/helper.h"
-#include "../2d/Color.h"
+#include "Color.h"
#include
namespace kiwano
From aec069b167105ae9ed3132a827747d65174a2b4c Mon Sep 17 00:00:00 2001
From: Nomango <569629550@qq.com>
Date: Sun, 18 Aug 2019 10:23:54 +0800
Subject: [PATCH 4/8] Add FontCollection
---
appveyor.yml | 3 +-
projects/kiwano.vcxproj | 33 +-
projects/kiwano.vcxproj.filters | 168 ++--
src/kiwano-audio/src/Player.h | 4 +-
src/kiwano-audio/src/Sound.h | 4 +-
src/kiwano-audio/src/Transcoder.cpp | 2 +-
src/kiwano-network/src/HttpRequest.hpp | 4 +-
src/kiwano-network/src/HttpResponse.hpp | 4 +-
src/kiwano/2d/Actor.cpp | 10 +-
src/kiwano/2d/Actor.h | 2 +-
src/kiwano/2d/DebugActor.cpp | 4 +-
src/kiwano/2d/Frame.h | 2 +-
src/kiwano/2d/FrameSequence.h | 2 +-
src/kiwano/2d/Transition.h | 2 +-
src/kiwano/2d/action/Action.h | 2 +-
src/kiwano/2d/action/ActionGroup.cpp | 4 +-
src/kiwano/2d/action/ActionManager.cpp | 10 +-
src/kiwano/2d/include-forwards.h | 5 +-
src/kiwano/base/AsyncTask.h | 4 +-
src/kiwano/base/EventDispatcher.cpp | 2 +-
src/kiwano/base/EventListener.h | 4 +-
src/kiwano/base/Input.h | 2 +-
.../base/{Object.cpp => ObjectBase.cpp} | 36 +-
src/kiwano/base/{Object.h => ObjectBase.h} | 14 +-
src/kiwano/base/Resource.cpp | 16 +-
src/kiwano/base/Resource.h | 23 +-
src/kiwano/base/Timer.h | 4 +-
src/kiwano/base/TimerManager.cpp | 12 +-
src/kiwano/base/Window.h | 2 +-
src/kiwano/base/window.h | 2 +-
src/kiwano/core/intrusive_list.hpp | 2 +-
src/kiwano/kiwano.h | 7 +-
src/kiwano/math/Rect.hpp | 2 +-
src/kiwano/math/{helper.h => math.h} | 0
src/kiwano/platform/Application.cpp | 6 +-
src/kiwano/renderer/D2DDeviceResources.h | 90 --
src/kiwano/renderer/Font.cpp | 29 +-
src/kiwano/renderer/Font.h | 35 +-
src/kiwano/renderer/Geometry.h | 3 +-
src/kiwano/renderer/GifImage.h | 2 +-
src/kiwano/renderer/Image.h | 3 +-
src/kiwano/renderer/ImageCache.h | 1 -
src/kiwano/renderer/LayerArea.h | 1 -
src/kiwano/renderer/RenderTarget.h | 8 +-
src/kiwano/renderer/Renderer.cpp | 134 ++-
src/kiwano/renderer/Renderer.h | 16 +-
src/kiwano/renderer/TextLayout.h | 1 -
.../{base => renderer/win32}/ComPtr.hpp | 2 +-
.../{ => win32}/D2DDeviceResources.cpp | 28 +-
.../D2DDeviceResources.h} | 82 +-
.../{ => win32}/D3D10DeviceResources.cpp | 7 +-
.../{ => win32}/D3D10DeviceResources.h | 2 +-
.../{ => win32}/D3D11DeviceResources.cpp | 7 +-
.../{ => win32}/D3D11DeviceResources.h | 2 +-
.../{ => win32}/D3DDeviceResourcesBase.h | 6 +-
.../renderer/win32/FontCollectionLoader.cpp | 908 ++++++++++++++++++
.../renderer/win32/FontCollectionLoader.h | 99 ++
.../renderer/{ => win32}/TextRenderer.cpp | 40 +-
.../renderer/{ => win32}/TextRenderer.h | 7 +-
src/kiwano/utils/FileUtil.cpp | 2 +-
src/kiwano/utils/ResourceCache.cpp | 2 +-
src/kiwano/utils/ResourceCache.h | 4 +-
62 files changed, 1535 insertions(+), 389 deletions(-)
rename src/kiwano/base/{Object.cpp => ObjectBase.cpp} (78%)
rename src/kiwano/base/{Object.h => ObjectBase.h} (88%)
rename src/kiwano/math/{helper.h => math.h} (100%)
delete mode 100644 src/kiwano/renderer/D2DDeviceResources.h
rename src/kiwano/{base => renderer/win32}/ComPtr.hpp (97%)
rename src/kiwano/renderer/{ => win32}/D2DDeviceResources.cpp (96%)
rename src/kiwano/renderer/{helper.hpp => win32/D2DDeviceResources.h} (62%)
rename src/kiwano/renderer/{ => win32}/D3D10DeviceResources.cpp (99%)
rename src/kiwano/renderer/{ => win32}/D3D10DeviceResources.h (98%)
rename src/kiwano/renderer/{ => win32}/D3D11DeviceResources.cpp (99%)
rename src/kiwano/renderer/{ => win32}/D3D11DeviceResources.h (98%)
rename src/kiwano/renderer/{ => win32}/D3DDeviceResourcesBase.h (92%)
create mode 100644 src/kiwano/renderer/win32/FontCollectionLoader.cpp
create mode 100644 src/kiwano/renderer/win32/FontCollectionLoader.h
rename src/kiwano/renderer/{ => win32}/TextRenderer.cpp (99%)
rename src/kiwano/renderer/{ => win32}/TextRenderer.h (94%)
diff --git a/appveyor.yml b/appveyor.yml
index 9f7cf1bd..49c87f43 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -54,7 +54,8 @@ for:
- master
only_commits:
message: /\[build\]/
- matrix:
+ environment:
+ matrix:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
VS_PLATFORM_TOOLSET: v142
diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj
index a1b790a9..070d909b 100644
--- a/projects/kiwano.vcxproj
+++ b/projects/kiwano.vcxproj
@@ -11,7 +11,6 @@
-
@@ -48,7 +47,7 @@
-
+
@@ -58,7 +57,7 @@
-
+
@@ -67,21 +66,22 @@
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -116,7 +116,7 @@
-
+
@@ -126,9 +126,6 @@
-
-
-
@@ -138,7 +135,11 @@
-
+
+
+
+
+
@@ -201,7 +202,7 @@
Level3
Disabled
true
- None
+ EditAndContinue
true
false
@@ -218,7 +219,7 @@
true
false
true
- None
+ EditAndContinue
true
false
diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters
index 586733bf..e3db99d4 100644
--- a/projects/kiwano.vcxproj.filters
+++ b/projects/kiwano.vcxproj.filters
@@ -37,6 +37,9 @@
{86e2d0f2-a9d0-4456-b6a5-d480228bbf82}
+
+ {30333461-e9bc-4709-84bd-ce6e0e1a3079}
+
@@ -96,21 +99,6 @@
base
-
- renderer
-
-
- renderer
-
-
- renderer
-
-
- renderer
-
-
- renderer
-
math
@@ -140,9 +128,6 @@
-
- math
-
math
@@ -152,9 +137,6 @@
base
-
- base
-
utils
@@ -174,9 +156,6 @@
utils
-
- renderer
-
base
@@ -198,12 +177,6 @@
2d
-
- renderer
-
-
- renderer
-
2d\action
@@ -222,9 +195,6 @@
2d\action
-
- renderer
-
utils
@@ -255,9 +225,6 @@
core
-
- base
-
core
@@ -267,9 +234,6 @@
2d
-
- renderer
-
2d\action
@@ -282,14 +246,11 @@
base
-
- renderer
+
+ math
-
- renderer
-
-
- renderer
+
+ base
renderer
@@ -297,9 +258,51 @@
renderer
+
+ renderer
+
+
+ renderer
+
+
+ renderer
+
+
+ renderer
+
renderer
+
+ renderer
+
+
+ renderer
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer
+
@@ -335,18 +338,6 @@
base
-
- renderer
-
-
- renderer
-
-
- renderer
-
-
- renderer
-
platform
@@ -359,9 +350,6 @@
base
-
- base
-
utils
@@ -398,12 +386,6 @@
2d
-
- renderer
-
-
- renderer
-
2d\action
@@ -419,9 +401,6 @@
2d\action
-
- renderer
-
utils
@@ -434,9 +413,6 @@
2d
-
- renderer
-
2d\action
@@ -449,14 +425,8 @@
base
-
- renderer
-
-
- renderer
-
-
- renderer
+
+ base
renderer
@@ -464,8 +434,44 @@
renderer
+
+ renderer
+
+
+ renderer
+
+
+ renderer
+
+
+ renderer
+
renderer
+
+ renderer
+
+
+ renderer
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer\win32
+
+
+ renderer
+
\ No newline at end of file
diff --git a/src/kiwano-audio/src/Player.h b/src/kiwano-audio/src/Player.h
index 290c7de7..cb9da0a0 100644
--- a/src/kiwano-audio/src/Player.h
+++ b/src/kiwano-audio/src/Player.h
@@ -20,7 +20,7 @@
#pragma once
#include
-#include
+#include
#include "Sound.h"
namespace kiwano
@@ -31,7 +31,7 @@ namespace kiwano
// 音乐播放器
class KGE_API Player
- : protected Object
+ : protected ObjectBase
{
using MusicMap = Map;
diff --git a/src/kiwano-audio/src/Sound.h b/src/kiwano-audio/src/Sound.h
index fa505676..9cf9e71f 100644
--- a/src/kiwano-audio/src/Sound.h
+++ b/src/kiwano-audio/src/Sound.h
@@ -20,7 +20,7 @@
#pragma once
#include
-#include
+#include
#include
#include
@@ -32,7 +32,7 @@ namespace kiwano
// 音乐对象
class KGE_API Sound
- : public Object
+ : public ObjectBase
{
public:
Sound();
diff --git a/src/kiwano-audio/src/Transcoder.cpp b/src/kiwano-audio/src/Transcoder.cpp
index 4d2d7baf..7189690c 100644
--- a/src/kiwano-audio/src/Transcoder.cpp
+++ b/src/kiwano-audio/src/Transcoder.cpp
@@ -24,9 +24,9 @@
#include
#include
-#include
#include
#include
+#include
#include
#include "audio-modules.h"
#include "Transcoder.h"
diff --git a/src/kiwano-network/src/HttpRequest.hpp b/src/kiwano-network/src/HttpRequest.hpp
index 79335b4f..5f147e57 100644
--- a/src/kiwano-network/src/HttpRequest.hpp
+++ b/src/kiwano-network/src/HttpRequest.hpp
@@ -21,7 +21,7 @@
#pragma once
#include
#include
-#include
+#include
namespace kiwano
{
@@ -30,7 +30,7 @@ namespace kiwano
typedef Function ResponseCallback;
class KGE_API HttpRequest
- : public Object
+ : public ObjectBase
{
public:
enum class Type
diff --git a/src/kiwano-network/src/HttpResponse.hpp b/src/kiwano-network/src/HttpResponse.hpp
index 094361b4..c5d35ffe 100644
--- a/src/kiwano-network/src/HttpResponse.hpp
+++ b/src/kiwano-network/src/HttpResponse.hpp
@@ -21,14 +21,14 @@
#pragma once
#include
#include
-#include
+#include
namespace kiwano
{
namespace network
{
class KGE_API HttpResponse
- : public Object
+ : public ObjectBase
{
public:
inline HttpResponse(HttpRequestPtr request)
diff --git a/src/kiwano/2d/Actor.cpp b/src/kiwano/2d/Actor.cpp
index 0d2b740d..8ef488f5 100644
--- a/src/kiwano/2d/Actor.cpp
+++ b/src/kiwano/2d/Actor.cpp
@@ -71,7 +71,7 @@ namespace kiwano
OnUpdate(dt);
}
- if (!children_.is_empty())
+ if (!children_.item_empty())
{
ActorPtr next;
for (auto child = children_.first_item(); child; child = next)
@@ -89,7 +89,7 @@ namespace kiwano
UpdateTransform();
- if (children_.is_empty())
+ if (children_.item_empty())
{
OnRender(renderer);
}
@@ -407,7 +407,7 @@ namespace kiwano
{
if (!IsName(name))
{
- Object::SetName(name);
+ ObjectBase::SetName(name);
hash_name_ = std::hash{}(name);
}
}
@@ -609,7 +609,7 @@ namespace kiwano
{
KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception");
- if (children_.is_empty())
+ if (children_.item_empty())
return;
if (child)
@@ -622,7 +622,7 @@ namespace kiwano
void Actor::RemoveChildren(String const& child_name)
{
- if (children_.is_empty())
+ if (children_.item_empty())
{
return;
}
diff --git a/src/kiwano/2d/Actor.h b/src/kiwano/2d/Actor.h
index 55f8f105..e8764689 100644
--- a/src/kiwano/2d/Actor.h
+++ b/src/kiwano/2d/Actor.h
@@ -32,7 +32,7 @@ namespace kiwano
// 角色
class KGE_API Actor
- : public Object
+ : public ObjectBase
, public TimerManager
, public ActionManager
, public EventDispatcher
diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp
index 0dbe72d3..a2242f93 100644
--- a/src/kiwano/2d/DebugActor.cpp
+++ b/src/kiwano/2d/DebugActor.cpp
@@ -82,9 +82,9 @@ namespace kiwano
ss << "Fps: " << frame_time_.size() << std::endl;
#if defined(KGE_DEBUG)
- if (Object::IsTracingLeaks())
+ if (ObjectBase::IsTracingLeaks())
{
- ss << "Objects: " << Object::__GetTracingObjects().size() << std::endl;
+ ss << "Objects: " << ObjectBase::__GetTracingObjects().size() << std::endl;
}
#endif
diff --git a/src/kiwano/2d/Frame.h b/src/kiwano/2d/Frame.h
index 93569ee9..3ee92fb3 100644
--- a/src/kiwano/2d/Frame.h
+++ b/src/kiwano/2d/Frame.h
@@ -25,7 +25,7 @@ namespace kiwano
{
// 帧图像
class KGE_API Frame
- : public Object
+ : public ObjectBase
{
public:
Frame();
diff --git a/src/kiwano/2d/FrameSequence.h b/src/kiwano/2d/FrameSequence.h
index 863fa38e..09c0ccde 100644
--- a/src/kiwano/2d/FrameSequence.h
+++ b/src/kiwano/2d/FrameSequence.h
@@ -25,7 +25,7 @@ namespace kiwano
{
// 序列帧
class KGE_API FrameSequence
- : public Object
+ : public ObjectBase
{
public:
FrameSequence();
diff --git a/src/kiwano/2d/Transition.h b/src/kiwano/2d/Transition.h
index 67dc8900..a70b89cd 100644
--- a/src/kiwano/2d/Transition.h
+++ b/src/kiwano/2d/Transition.h
@@ -29,7 +29,7 @@ namespace kiwano
// 舞台过渡
class KGE_API Transition
- : public Object
+ : public ObjectBase
{
friend class Director;
diff --git a/src/kiwano/2d/action/Action.h b/src/kiwano/2d/action/Action.h
index 427bb215..ce7eb0c2 100644
--- a/src/kiwano/2d/action/Action.h
+++ b/src/kiwano/2d/action/Action.h
@@ -28,7 +28,7 @@ namespace kiwano
class ActionManager;
class KGE_API Action
- : public Object
+ : public ObjectBase
, protected intrusive_list_item
{
friend class ActionManager;
diff --git a/src/kiwano/2d/action/ActionGroup.cpp b/src/kiwano/2d/action/ActionGroup.cpp
index fd1a646a..0cd36d40 100644
--- a/src/kiwano/2d/action/ActionGroup.cpp
+++ b/src/kiwano/2d/action/ActionGroup.cpp
@@ -45,7 +45,7 @@ namespace kiwano
void ActionGroup::Init(ActorPtr target)
{
- if (actions_.is_empty())
+ if (actions_.item_empty())
{
Done();
return;
@@ -135,7 +135,7 @@ namespace kiwano
ActionPtr ActionGroup::Reverse() const
{
auto group = new (std::nothrow) ActionGroup();
- if (group && !actions_.is_empty())
+ if (group && !actions_.item_empty())
{
for (auto action = actions_.last_item(); action; action = action->prev_item())
{
diff --git a/src/kiwano/2d/action/ActionManager.cpp b/src/kiwano/2d/action/ActionManager.cpp
index 3428bd8a..2a0c5ac5 100644
--- a/src/kiwano/2d/action/ActionManager.cpp
+++ b/src/kiwano/2d/action/ActionManager.cpp
@@ -26,7 +26,7 @@ namespace kiwano
{
void ActionManager::UpdateActions(ActorPtr target, Duration dt)
{
- if (actions_.is_empty() || !target)
+ if (actions_.item_empty() || !target)
return;
ActionPtr next;
@@ -55,7 +55,7 @@ namespace kiwano
ActionPtr ActionManager::GetAction(String const & name)
{
- if (actions_.is_empty())
+ if (actions_.item_empty())
return nullptr;
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
@@ -66,7 +66,7 @@ namespace kiwano
void ActionManager::ResumeAllActions()
{
- if (actions_.is_empty())
+ if (actions_.item_empty())
return;
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
@@ -77,7 +77,7 @@ namespace kiwano
void ActionManager::PauseAllActions()
{
- if (actions_.is_empty())
+ if (actions_.item_empty())
return;
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
@@ -88,7 +88,7 @@ namespace kiwano
void ActionManager::StopAllActions()
{
- if (actions_.is_empty())
+ if (actions_.item_empty())
return;
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
diff --git a/src/kiwano/2d/include-forwards.h b/src/kiwano/2d/include-forwards.h
index 97473233..edbbf0ae 100644
--- a/src/kiwano/2d/include-forwards.h
+++ b/src/kiwano/2d/include-forwards.h
@@ -23,10 +23,9 @@
#include "../base/time.h"
#include "../base/RefCounter.hpp"
#include "../base/SmartPtr.hpp"
-#include "../base/ComPtr.hpp"
-#include "../base/Object.h"
+#include "../base/ObjectBase.h"
#include "../base/types.h"
-#include "../math/helper.h"
+#include "../math/math.h"
#include "../renderer/Color.h"
namespace kiwano
diff --git a/src/kiwano/base/AsyncTask.h b/src/kiwano/base/AsyncTask.h
index f1d31efa..15551475 100644
--- a/src/kiwano/base/AsyncTask.h
+++ b/src/kiwano/base/AsyncTask.h
@@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
-#include "Object.h"
+#include "ObjectBase.h"
#include
#include
@@ -31,7 +31,7 @@ namespace kiwano
typedef Function AsyncTaskCallback;
class AsyncTask
- : public Object
+ : public ObjectBase
{
public:
AsyncTask();
diff --git a/src/kiwano/base/EventDispatcher.cpp b/src/kiwano/base/EventDispatcher.cpp
index 8dc93e26..d46fbb3b 100644
--- a/src/kiwano/base/EventDispatcher.cpp
+++ b/src/kiwano/base/EventDispatcher.cpp
@@ -25,7 +25,7 @@ namespace kiwano
{
void EventDispatcher::Dispatch(Event& evt)
{
- if (listeners_.is_empty())
+ if (listeners_.item_empty())
return;
EventListenerPtr next;
diff --git a/src/kiwano/base/EventListener.h b/src/kiwano/base/EventListener.h
index 40ed7aa0..f07e83f3 100644
--- a/src/kiwano/base/EventListener.h
+++ b/src/kiwano/base/EventListener.h
@@ -21,7 +21,7 @@
#pragma once
#include "../core/core.h"
#include "../base/SmartPtr.hpp"
-#include "Object.h"
+#include "ObjectBase.h"
#include "Event.hpp"
namespace kiwano
@@ -34,7 +34,7 @@ namespace kiwano
// 事件监听器
class KGE_API EventListener
- : public Object
+ : public ObjectBase
, protected intrusive_list_item
{
friend class EventDispatcher;
diff --git a/src/kiwano/base/Input.h b/src/kiwano/base/Input.h
index e23b3796..2cbc24bc 100644
--- a/src/kiwano/base/Input.h
+++ b/src/kiwano/base/Input.h
@@ -21,7 +21,7 @@
#pragma once
#include "../macros.h"
#include "../core/core.h"
-#include "../math/helper.h"
+#include "../math/math.h"
#include "keys.hpp"
#include "Component.h"
diff --git a/src/kiwano/base/Object.cpp b/src/kiwano/base/ObjectBase.cpp
similarity index 78%
rename from src/kiwano/base/Object.cpp
rename to src/kiwano/base/ObjectBase.cpp
index 888e9108..b3020125 100644
--- a/src/kiwano/base/Object.cpp
+++ b/src/kiwano/base/ObjectBase.cpp
@@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "Object.h"
+#include "ObjectBase.h"
#include "Logger.h"
#include
@@ -27,12 +27,12 @@ namespace kiwano
namespace
{
bool tracing_leaks = false;
- Vector