diff --git a/projects/kiwano.vcxproj b/projects/kiwano.vcxproj
index cd2a541d..30e05eaf 100644
--- a/projects/kiwano.vcxproj
+++ b/projects/kiwano.vcxproj
@@ -12,7 +12,6 @@
-
@@ -70,8 +69,9 @@
-
-
+
+
+
@@ -132,8 +132,8 @@
-
-
+
+
diff --git a/projects/kiwano.vcxproj.filters b/projects/kiwano.vcxproj.filters
index 11b8653f..de732345 100644
--- a/projects/kiwano.vcxproj.filters
+++ b/projects/kiwano.vcxproj.filters
@@ -150,9 +150,6 @@
utils
-
- base
-
2d
@@ -258,12 +255,6 @@
renderer
-
- renderer
-
-
- renderer
-
renderer
@@ -306,6 +297,15 @@
2d
+
+ renderer
+
+
+ renderer
+
+
+ renderer
+
@@ -443,12 +443,6 @@
renderer
-
- renderer
-
-
- renderer
-
renderer
@@ -482,5 +476,11 @@
2d
+
+ renderer
+
+
+ renderer
+
\ No newline at end of file
diff --git a/src/kiwano-audio/src/Sound.cpp b/src/kiwano-audio/src/Sound.cpp
index 30d64e84..e9c3e11c 100644
--- a/src/kiwano-audio/src/Sound.cpp
+++ b/src/kiwano-audio/src/Sound.cpp
@@ -65,8 +65,7 @@ namespace kiwano
Close();
}
- Transcoder transcoder;
- HRESULT hr = transcoder.LoadMediaFile(file_path);
+ HRESULT hr = transcoder_.LoadMediaFile(file_path);
if (FAILED(hr))
{
@@ -74,7 +73,7 @@ namespace kiwano
return false;
}
- hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetBuffer().format);
+ hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder_.GetBuffer().format);
if (FAILED(hr))
{
Close();
@@ -94,8 +93,7 @@ namespace kiwano
Close();
}
- Transcoder transcoder;
- HRESULT hr = transcoder.LoadMediaResource(res);
+ HRESULT hr = transcoder_.LoadMediaResource(res);
if (FAILED(hr))
{
@@ -103,7 +101,7 @@ namespace kiwano
return false;
}
- hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetBuffer().format);
+ hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder_.GetBuffer().format);
if (FAILED(hr))
{
Close();
diff --git a/src/kiwano-imgui/src/ImGuiModule.cpp b/src/kiwano-imgui/src/ImGuiModule.cpp
index 7a571cdd..f4f1c41b 100644
--- a/src/kiwano-imgui/src/ImGuiModule.cpp
+++ b/src/kiwano-imgui/src/ImGuiModule.cpp
@@ -247,20 +247,20 @@ namespace kiwano
if (ImGui::GetIO().ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange)
return;
- MouseCursor cursor = MouseCursor::Arrow;
+ CursorType cursor = CursorType::Arrow;
switch (ImGui::GetMouseCursor())
{
- case ImGuiMouseCursor_Arrow: cursor = MouseCursor::Arrow; break;
- case ImGuiMouseCursor_TextInput: cursor = MouseCursor::TextInput; break;
- case ImGuiMouseCursor_ResizeAll: cursor = MouseCursor::SizeAll; break;
- case ImGuiMouseCursor_ResizeEW: cursor = MouseCursor::SizeWE; break;
- case ImGuiMouseCursor_ResizeNS: cursor = MouseCursor::SizeNS; break;
- case ImGuiMouseCursor_ResizeNESW: cursor = MouseCursor::SizeNESW; break;
- case ImGuiMouseCursor_ResizeNWSE: cursor = MouseCursor::SizeNWSE; break;
- case ImGuiMouseCursor_Hand: cursor = MouseCursor::Hand; break;
+ case ImGuiMouseCursor_Arrow: cursor = CursorType::Arrow; break;
+ case ImGuiMouseCursor_TextInput: cursor = CursorType::TextInput; break;
+ case ImGuiMouseCursor_ResizeAll: cursor = CursorType::SizeAll; break;
+ case ImGuiMouseCursor_ResizeEW: cursor = CursorType::SizeWE; break;
+ case ImGuiMouseCursor_ResizeNS: cursor = CursorType::SizeNS; break;
+ case ImGuiMouseCursor_ResizeNESW: cursor = CursorType::SizeNESW; break;
+ case ImGuiMouseCursor_ResizeNWSE: cursor = CursorType::SizeNWSE; break;
+ case ImGuiMouseCursor_Hand: cursor = CursorType::Hand; break;
}
- Window::GetInstance()->SetMouseCursor(cursor);
+ Window::GetInstance()->SetCursor(cursor);
}
void ImGuiModule::UpdateGamepads()
{
diff --git a/src/kiwano/2d/Canvas.cpp b/src/kiwano/2d/Canvas.cpp
index 4cf259f2..3a89408d 100644
--- a/src/kiwano/2d/Canvas.cpp
+++ b/src/kiwano/2d/Canvas.cpp
@@ -31,7 +31,7 @@ namespace kiwano
, stroke_color_(Color::White)
, stroke_style_(StrokeStyle::Miter)
{
- Renderer::GetInstance()->CreateImageRenderTarget(rt_);
+ Renderer::GetInstance()->CreateTextureRenderTarget(rt_);
}
Canvas::~Canvas()
@@ -53,12 +53,12 @@ namespace kiwano
{
UpdateCache();
- if (image_cached_.IsValid())
+ if (texture_cached_.IsValid())
{
PrepareRender(rt);
- Rect bitmap_rect(0.f, 0.f, image_cached_.GetWidth(), image_cached_.GetHeight());
- rt->DrawImage(image_cached_, bitmap_rect, bitmap_rect);
+ Rect bitmap_rect(0.f, 0.f, texture_cached_.GetWidth(), texture_cached_.GetHeight());
+ rt->DrawTexture(texture_cached_, bitmap_rect, bitmap_rect);
}
}
@@ -245,11 +245,11 @@ namespace kiwano
cache_expired_ = true;
}
- void Canvas::DrawImage(Image const& image, const Rect* src_rect, const Rect* dest_rect)
+ void Canvas::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect)
{
- if (image.IsValid())
+ if (texture.IsValid())
{
- rt_.DrawImage(image, src_rect, dest_rect);
+ rt_.DrawTexture(texture, src_rect, dest_rect);
cache_expired_ = true;
}
}
@@ -326,17 +326,17 @@ namespace kiwano
cache_expired_ = true;
}
- Image Canvas::ExportToImage() const
+ Texture Canvas::ExportToTexture() const
{
UpdateCache();
- return image_cached_;
+ return texture_cached_;
}
void Canvas::UpdateCache() const
{
if (cache_expired_)
{
- image_cached_ = rt_.GetOutput();
+ texture_cached_ = rt_.GetOutput();
cache_expired_ = false;
}
}
diff --git a/src/kiwano/2d/Canvas.h b/src/kiwano/2d/Canvas.h
index cf2a6f0d..78d76fcb 100644
--- a/src/kiwano/2d/Canvas.h
+++ b/src/kiwano/2d/Canvas.h
@@ -95,9 +95,9 @@ namespace kiwano
Vec2 const& radius
);
- // 画图片
- void DrawImage(
- Image const& image,
+ // 画图
+ void DrawTexture(
+ Texture const& texture,
const Rect* src_rect = nullptr,
const Rect* dest_rect = nullptr
);
@@ -232,7 +232,7 @@ namespace kiwano
Float32 GetBrushOpacity() const;
// 导出为图片
- Image ExportToImage() const;
+ Texture ExportToTexture() const;
void OnRender(RenderTarget* rt) override;
@@ -247,9 +247,9 @@ namespace kiwano
TextStyle text_style_;
StrokeStyle stroke_style_;
GeometrySink geo_sink_;
- ImageRenderTarget rt_;
+ TextureRenderTarget rt_;
mutable bool cache_expired_;
- mutable Image image_cached_;
+ mutable Texture texture_cached_;
};
}
diff --git a/src/kiwano/2d/DebugActor.cpp b/src/kiwano/2d/DebugActor.cpp
index 3ba2ea52..565fdc5d 100644
--- a/src/kiwano/2d/DebugActor.cpp
+++ b/src/kiwano/2d/DebugActor.cpp
@@ -127,7 +127,16 @@ namespace kiwano
}
debug_text_->SetText(ss.str());
- SetSize(Size{ 20 + debug_text_->GetSize().x, 20 + debug_text_->GetSize().y });
+
+ if (debug_text_->GetWidth() > GetWidth() - 20)
+ {
+ SetWidth(20 + debug_text_->GetWidth());
+ }
+
+ if (debug_text_->GetHeight() > GetHeight() - 20)
+ {
+ SetHeight(20 + debug_text_->GetHeight());
+ }
}
}
diff --git a/src/kiwano/2d/Frame.cpp b/src/kiwano/2d/Frame.cpp
index 88169c47..8a92765f 100644
--- a/src/kiwano/2d/Frame.cpp
+++ b/src/kiwano/2d/Frame.cpp
@@ -19,7 +19,7 @@
// THE SOFTWARE.
#include "Frame.h"
-#include "../renderer/ImageCache.h"
+#include "../renderer/TextureCache.h"
namespace kiwano
{
@@ -37,17 +37,17 @@ namespace kiwano
Load(res);
}
- Frame::Frame(Image const& image)
+ Frame::Frame(Texture const& texture)
{
- SetImage(image);
+ SetTexture(texture);
}
bool Frame::Load(String const& file_path)
{
- Image image = ImageCache::GetInstance()->AddOrGetImage(file_path);
- if (image.IsValid())
+ Texture texture = TextureCache::GetInstance()->AddOrGetTexture(file_path);
+ if (texture.IsValid())
{
- SetImage(image);
+ SetTexture(texture);
return true;
}
return false;
@@ -55,10 +55,10 @@ namespace kiwano
bool Frame::Load(Resource const& res)
{
- Image image = ImageCache::GetInstance()->AddOrGetImage(res);
- if (image.IsValid())
+ Texture texture = TextureCache::GetInstance()->AddOrGetTexture(res);
+ if (texture.IsValid())
{
- SetImage(image);
+ SetTexture(texture);
return true;
}
return false;
@@ -66,9 +66,9 @@ namespace kiwano
void Frame::SetCropRect(Rect const& crop_rect)
{
- if (image_.IsValid())
+ if (texture_.IsValid())
{
- auto bitmap_size = image_.GetSize();
+ auto bitmap_size = texture_.GetSize();
crop_rect_.left_top.x = std::min(std::max(crop_rect.left_top.x, 0.f), bitmap_size.x);
crop_rect_.left_top.y = std::min(std::max(crop_rect.left_top.y, 0.f), bitmap_size.y);
crop_rect_.right_bottom.x = std::min(std::max(crop_rect.right_bottom.x, 0.f), bitmap_size.x);
@@ -76,14 +76,14 @@ namespace kiwano
}
}
- void Frame::SetImage(Image const& image)
+ void Frame::SetTexture(Texture const& texture)
{
- image_ = image;
- if (image_.IsValid())
+ texture_ = texture;
+ if (texture_.IsValid())
{
crop_rect_.left_top.x = crop_rect_.left_top.y = 0;
- crop_rect_.right_bottom.x = image_.GetWidth();
- crop_rect_.right_bottom.y = image_.GetHeight();
+ crop_rect_.right_bottom.x = texture_.GetWidth();
+ crop_rect_.right_bottom.y = texture_.GetHeight();
}
}
}
diff --git a/src/kiwano/2d/Frame.h b/src/kiwano/2d/Frame.h
index 30295db4..1c58955f 100644
--- a/src/kiwano/2d/Frame.h
+++ b/src/kiwano/2d/Frame.h
@@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
-#include "../renderer/Image.h"
+#include "../renderer/Texture.h"
namespace kiwano
{
@@ -39,7 +39,7 @@ namespace kiwano
);
explicit Frame(
- Image const& image
+ Texture const& texture
);
bool Load(
@@ -55,31 +55,31 @@ namespace kiwano
Rect const& crop_rect /* 裁剪矩形 */
);
- // 设置位图
- void SetImage(
- Image const& image
+ // 设置纹理
+ void SetTexture(
+ Texture const& texture
);
// 获取宽度
- Float32 GetWidth() const { return crop_rect_.GetWidth(); }
+ Float32 GetWidth() const { return crop_rect_.GetWidth(); }
// 获取高度
- Float32 GetHeight() const { return crop_rect_.GetHeight(); }
+ Float32 GetHeight() const { return crop_rect_.GetHeight(); }
// 获取大小
- Size GetSize() const { return crop_rect_.GetSize(); }
+ Size GetSize() const { return crop_rect_.GetSize(); }
// 获取裁剪位置
- Point GetCropPoint() const { return crop_rect_.GetLeftTop(); }
+ Point GetCropPoint() const { return crop_rect_.GetLeftTop(); }
// 获取裁剪矩形
- inline Rect const& GetCropRect() const { return crop_rect_; }
+ inline Rect const& GetCropRect() const { return crop_rect_; }
- // 获取位图
- inline Image const& GetImage() const { return image_; }
+ // 获取纹理
+ inline Texture const& GetTexture() const { return texture_; }
protected:
- Image image_;
+ Texture texture_;
Rect crop_rect_;
};
}
diff --git a/src/kiwano/2d/FrameSequence.cpp b/src/kiwano/2d/FrameSequence.cpp
index 1546fd0a..728930f6 100644
--- a/src/kiwano/2d/FrameSequence.cpp
+++ b/src/kiwano/2d/FrameSequence.cpp
@@ -54,8 +54,8 @@ namespace kiwano
else
{
frames_.reserve(frames_.size() + frames.size());
- for (const auto& image : frames)
- AddFrame(image);
+ for (const auto& texture : frames)
+ AddFrame(texture);
}
}
diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp
index af8b9053..7918f955 100644
--- a/src/kiwano/2d/GifSprite.cpp
+++ b/src/kiwano/2d/GifSprite.cpp
@@ -20,7 +20,7 @@
#include "GifSprite.h"
#include "../base/Logger.h"
-#include "../renderer/ImageCache.h"
+#include "../renderer/TextureCache.h"
#include "../renderer/Renderer.h"
namespace kiwano
@@ -30,7 +30,6 @@ namespace kiwano
, next_index_(0)
, total_loop_count_(1)
, loop_count_(0)
- , disposal_type_(DisposalType::Unknown)
{
}
@@ -45,41 +44,41 @@ namespace kiwano
Load(res);
}
- GifSprite::GifSprite(GifImage image)
+ GifSprite::GifSprite(GifImage gif)
{
- Load(image);
+ Load(gif);
}
bool GifSprite::Load(String const& file_path)
{
- GifImage image = ImageCache::GetInstance()->AddOrGetGifImage(file_path);
- return Load(image);
+ GifImage texture = TextureCache::GetInstance()->AddOrGetGifImage(file_path);
+ return Load(texture);
}
bool GifSprite::Load(Resource const& res)
{
- GifImage image = ImageCache::GetInstance()->AddOrGetGifImage(res);
- return Load(image);
+ GifImage texture = TextureCache::GetInstance()->AddOrGetGifImage(res);
+ return Load(texture);
}
- bool GifSprite::Load(GifImage image)
+ bool GifSprite::Load(GifImage gif)
{
- if (image.IsValid())
+ if (gif.IsValid())
{
- image_ = image;
+ gif_ = gif;
next_index_ = 0;
loop_count_ = 0;
- disposal_type_ = DisposalType::None;
+ frame_.disposal_type = GifImage::DisposalType::None;
- SetSize(Size{ static_cast(image_.GetWidthInPixels()), static_cast(image_.GetHeightInPixels()) });
+ SetSize(Size{ static_cast(gif_.GetWidthInPixels()), static_cast(gif_.GetHeightInPixels()) });
if (!frame_rt_.IsValid())
{
- Renderer::GetInstance()->CreateImageRenderTarget(frame_rt_);
+ Renderer::GetInstance()->CreateTextureRenderTarget(frame_rt_);
}
- if (image_.GetFramesCount() > 0)
+ if (gif_.GetFramesCount() > 0)
{
ComposeNextFrame();
}
@@ -90,11 +89,11 @@ namespace kiwano
void GifSprite::OnRender(RenderTarget* rt)
{
- if (frame_.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix()))
+ if (frame_.raw.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix()))
{
PrepareRender(rt);
- rt->DrawImage(frame_);
+ rt->DrawTexture(frame_.raw, &frame_.rect, nullptr);
}
}
@@ -102,24 +101,30 @@ namespace kiwano
{
Actor::Update(dt);
- if (image_.IsValid() && animating_)
+ if (gif_.IsValid() && animating_)
{
frame_elapsed_ += dt;
- if (frame_delay_ <= frame_elapsed_)
+ if (frame_.delay <= frame_elapsed_)
{
- frame_delay_ -= frame_elapsed_;
+ frame_.delay -= frame_elapsed_;
frame_elapsed_ = 0;
ComposeNextFrame();
}
}
}
+ void GifSprite::SetGifImage(GifImage const& gif)
+ {
+ gif_ = gif;
+ RestartAnimation();
+ }
+
void GifSprite::RestartAnimation()
{
animating_ = true;
next_index_ = 0;
loop_count_ = 0;
- disposal_type_ = DisposalType::None;
+ frame_.disposal_type = GifImage::DisposalType::None;
}
void GifSprite::ComposeNextFrame()
@@ -130,27 +135,27 @@ namespace kiwano
{
DisposeCurrentFrame();
OverlayNextFrame();
- } while (frame_delay_.IsZero() && !IsLastFrame());
+ } while (frame_.delay.IsZero() && !IsLastFrame());
- animating_ = (!EndOfAnimation() && image_.GetFramesCount() > 1);
+ animating_ = (!EndOfAnimation() && gif_.GetFramesCount() > 1);
}
}
void GifSprite::DisposeCurrentFrame()
{
- switch (disposal_type_)
+ switch (frame_.disposal_type)
{
- case DisposalType::Unknown:
- case DisposalType::None:
+ case GifImage::DisposalType::Unknown:
+ case GifImage::DisposalType::None:
break;
- case DisposalType::Background:
+ case GifImage::DisposalType::Background:
{
ClearCurrentFrameArea();
break;
}
- case DisposalType::Previous:
+ case GifImage::DisposalType::Previous:
{
RestoreSavedFrame();
break;
@@ -163,43 +168,30 @@ namespace kiwano
void GifSprite::OverlayNextFrame()
{
- Image raw_image;
-
- HRESULT hr = image_.GetRawFrame(next_index_, raw_image, frame_rect_, frame_delay_, disposal_type_);
+ Renderer::GetInstance()->CreateGifImageFrame(frame_, gif_, next_index_);
- if (SUCCEEDED(hr))
+ if (frame_.disposal_type == GifImage::DisposalType::Previous)
{
- if (disposal_type_ == DisposalType::Previous)
- {
- SaveComposedFrame();
- }
+ SaveComposedFrame();
}
- if (SUCCEEDED(hr))
+ if (frame_rt_.IsValid())
{
frame_rt_.BeginDraw();
if (next_index_ == 0)
{
- // 重新绘制背景
- frame_rt_.Clear(image_.GetBackgroundColor());
loop_count_++;
}
- frame_rt_.DrawImage(raw_image, nullptr, &frame_rect_);
+ frame_rt_.DrawTexture(frame_.raw, nullptr, &frame_.rect);
frame_rt_.EndDraw();
- }
- if (SUCCEEDED(hr))
- {
- Image frame_to_render = frame_rt_.GetOutput();
-
- hr = frame_to_render.IsValid() ? S_OK : E_FAIL;
-
- if (SUCCEEDED(hr))
+ Texture frame_to_render = frame_rt_.GetOutput();
+ if (frame_to_render.IsValid())
{
- frame_ = frame_to_render;
- next_index_ = (++next_index_) % image_.GetFramesCount();
+ frame_.raw = frame_to_render;
+ next_index_ = (++next_index_) % gif_.GetFramesCount();
}
}
@@ -212,13 +204,11 @@ namespace kiwano
{
done_cb_();
}
-
- ThrowIfFailed(hr);
}
void GifSprite::SaveComposedFrame()
{
- Image frame_to_be_saved = frame_rt_.GetOutput();
+ Texture frame_to_be_saved = frame_rt_.GetOutput();
HRESULT hr = frame_to_be_saved.IsValid() ? S_OK : E_FAIL;
@@ -253,7 +243,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- Image frame_to_copy_to = frame_rt_.GetOutput();
+ Texture frame_to_copy_to = frame_rt_.GetOutput();
hr = frame_to_copy_to.IsValid() ? S_OK : E_FAIL;
@@ -270,8 +260,8 @@ namespace kiwano
{
frame_rt_.BeginDraw();
- frame_rt_.PushClipRect(frame_rect_);
- frame_rt_.Clear(image_.GetBackgroundColor());
+ frame_rt_.PushClipRect(frame_.rect);
+ frame_rt_.Clear();
frame_rt_.PopClipRect();
return frame_rt_.EndDraw();
diff --git a/src/kiwano/2d/GifSprite.h b/src/kiwano/2d/GifSprite.h
index ee94ed99..f9c3f0bf 100644
--- a/src/kiwano/2d/GifSprite.h
+++ b/src/kiwano/2d/GifSprite.h
@@ -31,7 +31,6 @@ namespace kiwano
: public Actor
{
public:
- using DisposalType = GifImage::DisposalType;
using LoopDoneCallback = Function;
using DoneCallback = Function;
@@ -46,7 +45,7 @@ namespace kiwano
);
GifSprite(
- GifImage image
+ GifImage gif
);
bool Load(
@@ -58,7 +57,7 @@ namespace kiwano
);
bool Load(
- GifImage image
+ GifImage gif
);
// 设置 GIF 动画循环次数
@@ -70,12 +69,17 @@ namespace kiwano
// 设置 GIF 动画结束回调函数
inline void SetDoneCallback(DoneCallback const& cb) { done_cb_ = cb; }
+ // 设置 GIF 图像
+ void SetGifImage(GifImage const& gif);
+
// 重新播放动画
void RestartAnimation();
- inline LoopDoneCallback GetLoopDoneCallback() const { return loop_cb_; }
+ inline LoopDoneCallback GetLoopDoneCallback() const { return loop_cb_; }
- inline DoneCallback GetDoneCallback() const { return done_cb_; }
+ inline DoneCallback GetDoneCallback() const { return done_cb_; }
+
+ inline GifImage const& GetGifImage() const { return gif_; }
void OnRender(RenderTarget* rt) override;
@@ -103,15 +107,12 @@ namespace kiwano
Int32 total_loop_count_;
Int32 loop_count_;
UInt32 next_index_;
- Duration frame_delay_;
Duration frame_elapsed_;
- DisposalType disposal_type_;
LoopDoneCallback loop_cb_;
DoneCallback done_cb_;
- GifImage image_;
- Image frame_;
- Rect frame_rect_;
- Image saved_frame_;
- ImageRenderTarget frame_rt_;
+ GifImage gif_;
+ GifImage::Frame frame_;
+ Texture saved_frame_;
+ TextureRenderTarget frame_rt_;
};
}
diff --git a/src/kiwano/2d/ShapeActor.h b/src/kiwano/2d/ShapeActor.h
index a710e45e..0ead7c30 100644
--- a/src/kiwano/2d/ShapeActor.h
+++ b/src/kiwano/2d/ShapeActor.h
@@ -21,6 +21,7 @@
#pragma once
#include "Actor.h"
#include "../renderer/Geometry.h"
+#include "../renderer/StrokeStyle.h"
namespace kiwano
{
diff --git a/src/kiwano/2d/Sprite.cpp b/src/kiwano/2d/Sprite.cpp
index 38f7e14c..ab331cfe 100644
--- a/src/kiwano/2d/Sprite.cpp
+++ b/src/kiwano/2d/Sprite.cpp
@@ -108,7 +108,7 @@ namespace kiwano
{
PrepareRender(rt);
- rt->DrawImage(frame_->GetImage(), &frame_->GetCropRect(), nullptr);
+ rt->DrawTexture(frame_->GetTexture(), &frame_->GetCropRect(), nullptr);
}
}
}
diff --git a/src/kiwano/2d/Stage.cpp b/src/kiwano/2d/Stage.cpp
index 5bdee64f..76d8c07b 100644
--- a/src/kiwano/2d/Stage.cpp
+++ b/src/kiwano/2d/Stage.cpp
@@ -38,12 +38,12 @@ namespace kiwano
void Stage::OnEnter()
{
- KGE_LOG(L"Stage entered");
+ // KGE_LOG(L"Stage entered");
}
void Stage::OnExit()
{
- KGE_LOG(L"Stage exited");
+ // KGE_LOG(L"Stage exited");
}
}
diff --git a/src/kiwano/2d/Text.cpp b/src/kiwano/2d/Text.cpp
index 6354d071..875bfdc2 100644
--- a/src/kiwano/2d/Text.cpp
+++ b/src/kiwano/2d/Text.cpp
@@ -126,11 +126,11 @@ namespace kiwano
style_.color = color;
}
- void Text::SetItalic(bool val)
+ void Text::SetItalic(bool italic)
{
- if (font_.italic != val)
+ if (font_.italic != italic)
{
- font_.italic = val;
+ font_.italic = italic;
format_dirty_ = true;
}
}
diff --git a/src/kiwano/2d/Text.h b/src/kiwano/2d/Text.h
index 7dd84ef8..286e96e8 100644
--- a/src/kiwano/2d/Text.h
+++ b/src/kiwano/2d/Text.h
@@ -102,7 +102,7 @@ namespace kiwano
// 设置文字斜体(默认值为 false)
void SetItalic(
- bool val
+ bool italic
);
// 设置文本自动换行的宽度(默认为 0)
diff --git a/src/kiwano/2d/TextStyle.hpp b/src/kiwano/2d/TextStyle.hpp
index b11c4c61..023ed954 100644
--- a/src/kiwano/2d/TextStyle.hpp
+++ b/src/kiwano/2d/TextStyle.hpp
@@ -20,6 +20,7 @@
#pragma once
#include "include-forwards.h"
+#include "../renderer/StrokeStyle.h"
namespace kiwano
{
diff --git a/src/kiwano/2d/action/Action.cpp b/src/kiwano/2d/action/Action.cpp
index 47b11755..fd1d5a6c 100644
--- a/src/kiwano/2d/action/Action.cpp
+++ b/src/kiwano/2d/action/Action.cpp
@@ -51,8 +51,8 @@ namespace kiwano
if (status_ == Status::NotStarted)
{
- Init(target);
status_ = delay_.IsZero() ? Status::Started : Status::Delayed;
+ Init(target);
}
switch (status_)
diff --git a/src/kiwano/2d/action/ActionWalk.cpp b/src/kiwano/2d/action/ActionWalk.cpp
index c6153ce5..41f61ffe 100644
--- a/src/kiwano/2d/action/ActionWalk.cpp
+++ b/src/kiwano/2d/action/ActionWalk.cpp
@@ -62,7 +62,7 @@ namespace kiwano
{
if (!path_)
{
- Complete(target);
+ Done();
return;
}
diff --git a/src/kiwano/2d/action/Animation.cpp b/src/kiwano/2d/action/Animation.cpp
index 12869a4b..5c5dd0f4 100644
--- a/src/kiwano/2d/action/Animation.cpp
+++ b/src/kiwano/2d/action/Animation.cpp
@@ -52,6 +52,7 @@ namespace kiwano
void Animation::Init(ActorPtr target)
{
+ KGE_ASSERT(frame_seq_ && "Animation::Init() failed: FrameSequence is NULL!");
if (!frame_seq_ || frame_seq_->GetFrames().empty())
{
Done();
@@ -59,6 +60,8 @@ namespace kiwano
}
auto sprite_target = dynamic_cast(target.get());
+ KGE_ASSERT(sprite_target && "Animation only supports Sprites!");
+
if (sprite_target && frame_seq_)
{
sprite_target->SetFrame(frame_seq_->GetFrames()[0]);
@@ -69,13 +72,14 @@ namespace kiwano
{
auto sprite_target = dynamic_cast(target.get());
- KGE_ASSERT(sprite_target && "Animation only supports Sprites");
+ if (sprite_target && frame_seq_)
+ {
+ const auto& frames = frame_seq_->GetFrames();
+ auto size = frames.size();
+ auto index = std::min(static_cast(math::Floor(size * percent)), size - 1);
- const auto& frames = frame_seq_->GetFrames();
- auto size = frames.size();
- auto index = std::min(static_cast(math::Floor(size * percent)), size - 1);
-
- sprite_target->SetFrame(frames[index]);
+ sprite_target->SetFrame(frames[index]);
+ }
}
ActionPtr Animation::Clone() const
diff --git a/src/kiwano/2d/include-forwards.h b/src/kiwano/2d/include-forwards.h
index edbbf0ae..bbe73ae7 100644
--- a/src/kiwano/2d/include-forwards.h
+++ b/src/kiwano/2d/include-forwards.h
@@ -24,7 +24,6 @@
#include "../base/RefCounter.hpp"
#include "../base/SmartPtr.hpp"
#include "../base/ObjectBase.h"
-#include "../base/types.h"
#include "../math/math.h"
#include "../renderer/Color.h"
diff --git a/src/kiwano/base/Window.cpp b/src/kiwano/base/Window.cpp
index e62121bb..38b213bb 100644
--- a/src/kiwano/base/Window.cpp
+++ b/src/kiwano/base/Window.cpp
@@ -20,6 +20,7 @@
#include "Window.h"
#include "Logger.h"
+#include "../platform/Application.h"
#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
#define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX
@@ -39,6 +40,16 @@ namespace kiwano
void RestoreResolution(WCHAR* device_name);
}
+ WindowConfig::WindowConfig(String const& title, UInt32 width, UInt32 height, UInt32 icon, bool resizable, bool fullscreen)
+ : title(title)
+ , width(width)
+ , height(height)
+ , icon(icon)
+ , resizable(resizable)
+ , fullscreen(fullscreen)
+ {
+ }
+
Window::Window()
: handle_(nullptr)
, width_(0)
@@ -46,7 +57,7 @@ namespace kiwano
, device_name_(nullptr)
, is_fullscreen_(false)
, resizable_(false)
- , mouse_cursor_(MouseCursor::Arrow)
+ , mouse_cursor_(CursorType::Arrow)
{
}
@@ -68,7 +79,7 @@ namespace kiwano
}
}
- void Window::Init(String const& title, Int32 width, Int32 height, UInt32 icon, bool resizable, bool fullscreen, WNDPROC proc)
+ void Window::Init(WindowConfig const& config, WNDPROC proc)
{
HINSTANCE hinst = GetModuleHandleW(nullptr);
WNDCLASSEX wcex = { 0 };
@@ -84,9 +95,10 @@ namespace kiwano
wcex.lpszMenuName = nullptr;
wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW);
- if (icon)
+ if (config.icon)
{
- wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(icon), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
+ wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(config.icon), IMAGE_ICON, 0, 0,
+ LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
::RegisterClassExW(&wcex);
@@ -105,22 +117,24 @@ namespace kiwano
device_name_ = new WCHAR[len + 1];
lstrcpyW(device_name_, monitor_info_ex.szDevice);
+ UInt32 width = config.width;
+ UInt32 height = config.height;
Int32 left = -1;
Int32 top = -1;
- resizable_ = resizable;
- is_fullscreen_ = fullscreen;
+ resizable_ = config.resizable;
+ is_fullscreen_ = config.fullscreen;
if (is_fullscreen_)
{
top = monitor_info_ex.rcMonitor.top;
left = monitor_info_ex.rcMonitor.left;
- if (width > monitor_info_ex.rcWork.right - left)
- width = monitor_info_ex.rcWork.right - left;
+ if (width > static_cast(monitor_info_ex.rcWork.right - left))
+ width = static_cast(monitor_info_ex.rcWork.right - left);
- if (height > monitor_info_ex.rcWork.bottom - top)
- height = monitor_info_ex.rcWork.bottom - top;
+ if (height > static_cast(monitor_info_ex.rcWork.bottom - top))
+ height = static_cast(monitor_info_ex.rcWork.bottom - top);
}
else
{
@@ -145,7 +159,7 @@ namespace kiwano
handle_ = ::CreateWindowExW(
is_fullscreen_ ? WS_EX_TOPMOST : 0,
KGE_WND_CLASS_NAME,
- title.c_str(),
+ config.title.c_str(),
GetWindowStyle(),
left,
top,
@@ -222,7 +236,7 @@ namespace kiwano
if (handle_)
{
HINSTANCE hinstance = GetModuleHandle(nullptr);
- HICON icon = (HICON)::LoadImage(
+ HICON icon = (HICON)::LoadImageW(
hinstance,
MAKEINTRESOURCE(icon_resource),
IMAGE_ICON,
@@ -295,7 +309,7 @@ namespace kiwano
}
}
- void Window::SetMouseCursor(MouseCursor cursor)
+ void Window::SetCursor(CursorType cursor)
{
mouse_cursor_ = cursor;
}
@@ -327,14 +341,14 @@ namespace kiwano
LPTSTR win32_cursor = IDC_ARROW;
switch (mouse_cursor_)
{
- case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break;
- case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break;
- case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break;
- case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break;
- case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break;
- case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break;
- case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
- case MouseCursor::Hand: win32_cursor = IDC_HAND; break;
+ case CursorType::Arrow: win32_cursor = IDC_ARROW; break;
+ case CursorType::TextInput: win32_cursor = IDC_IBEAM; break;
+ case CursorType::SizeAll: win32_cursor = IDC_SIZEALL; break;
+ case CursorType::SizeWE: win32_cursor = IDC_SIZEWE; break;
+ case CursorType::SizeNS: win32_cursor = IDC_SIZENS; break;
+ case CursorType::SizeNESW: win32_cursor = IDC_SIZENESW; break;
+ case CursorType::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
+ case CursorType::Hand: win32_cursor = IDC_HAND; break;
}
::SetCursor(::LoadCursorW(nullptr, win32_cursor));
}
@@ -417,4 +431,5 @@ namespace kiwano
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
}
}
+
}
diff --git a/src/kiwano/base/Window.h b/src/kiwano/base/Window.h
index b613b941..15b15ad5 100644
--- a/src/kiwano/base/Window.h
+++ b/src/kiwano/base/Window.h
@@ -22,10 +22,44 @@
#include "../macros.h"
#include "../core/core.h"
#include "../math/math.h"
-#include "types.h"
namespace kiwano
{
+ // 鼠标指针类型
+ enum class CursorType
+ {
+ Arrow, /* 指针 */
+ TextInput, /* 文本 */
+ Hand, /* 手指 */
+ SizeAll,
+ SizeNESW,
+ SizeNS,
+ SizeNWSE,
+ SizeWE,
+ };
+
+ // 窗口设置
+ struct WindowConfig
+ {
+ String title; // 标题
+ UInt32 width; // 宽度
+ UInt32 height; // 高度
+ UInt32 icon; // 图标资源 ID
+ bool resizable; // 窗口大小可拉伸
+ bool fullscreen; // 全屏模式
+
+ WindowConfig(
+ String const& title = L"Kiwano Game",
+ UInt32 width = 640,
+ UInt32 height = 480,
+ UInt32 icon = 0,
+ bool resizable = false,
+ bool fullscreen = false
+ );
+ };
+
+
+ // 窗口
class KGE_API Window
: public Singleton
{
@@ -56,19 +90,11 @@ namespace kiwano
// 设置全屏模式
void SetFullscreen(bool fullscreen, Int32 width, Int32 height);
- // 设置鼠标指针
- void SetMouseCursor(MouseCursor cursor);
+ // 设置鼠标指针类型
+ void SetCursor(CursorType cursor);
public:
- void Init(
- String const& title,
- Int32 width,
- Int32 height,
- UInt32 icon,
- bool resizable,
- bool fullscreen,
- WNDPROC proc
- );
+ void Init(WindowConfig const& config, WNDPROC proc);
void Prepare();
@@ -94,6 +120,6 @@ namespace kiwano
Int32 width_;
Int32 height_;
WCHAR* device_name_;
- MouseCursor mouse_cursor_;
+ CursorType mouse_cursor_;
};
}
diff --git a/src/kiwano/config.h b/src/kiwano/config.h
index c93cd824..a3999050 100644
--- a/src/kiwano/config.h
+++ b/src/kiwano/config.h
@@ -1,5 +1,5 @@
//-----------------------------------------------------------------------------
-// Compile-time options for Kiwano
+// Compile-time configurations for Kiwano
//-----------------------------------------------------------------------------
#pragma once
@@ -19,3 +19,6 @@
//---- Define DirectX version. Defaults to using Direct3D11
//#define KGE_USE_DIRECTX10
+
+//---- Define to enable DirectX debug layer
+//#define KGE_ENABLE_DX_DEBUG
diff --git a/src/kiwano/kiwano.h b/src/kiwano/kiwano.h
index 8581c7f0..59d9e3cf 100644
--- a/src/kiwano/kiwano.h
+++ b/src/kiwano/kiwano.h
@@ -61,12 +61,12 @@
#include "renderer/Color.h"
#include "renderer/Font.h"
-#include "renderer/Image.h"
+#include "renderer/Texture.h"
#include "renderer/GifImage.h"
#include "renderer/TextLayout.h"
#include "renderer/Geometry.h"
#include "renderer/LayerArea.h"
-#include "renderer/ImageCache.h"
+#include "renderer/TextureCache.h"
#include "renderer/Renderer.h"
diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp
index fbb81e70..3b127c28 100644
--- a/src/kiwano/platform/Application.cpp
+++ b/src/kiwano/platform/Application.cpp
@@ -20,12 +20,10 @@
#include "Application.h"
#include "modules.h"
-#include "../base/Window.h"
#include "../base/Logger.h"
#include "../base/input.h"
#include "../base/Director.h"
-#include "../renderer/ImageCache.h"
-#include "../renderer/Renderer.h"
+#include "../renderer/TextureCache.h"
#include "../utils/ResourceCache.h"
#include // GET_X_LPARAM, GET_Y_LPARAM
#include // ImmAssociateContext
@@ -43,17 +41,19 @@ namespace kiwano
Queue functions_to_perform_;
}
- Options::Options(String const& title, Int32 width, Int32 height, UInt32 icon, Color clear_color, bool vsync, bool resizable, bool fullscreen, bool debug)
- : title(title)
- , width(width)
- , height(height)
- , icon(icon)
- , clear_color(clear_color)
- , vsync(vsync)
- , resizable(resizable)
- , fullscreen(fullscreen)
- , debug(debug)
- {}
+ Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon)
+ {
+ window.title = title;
+ window.width = width;
+ window.height = height;
+ window.icon = icon;
+ }
+
+ Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config)
+ {
+ window = wnd_config;
+ render = render_config;
+ }
}
namespace kiwano
@@ -79,20 +79,10 @@ namespace kiwano
::CoUninitialize();
}
- void Application::Init(const Options& options)
+ void Application::Init(const Config& config)
{
- Window::GetInstance()->Init(
- options.title,
- options.width,
- options.height,
- options.icon,
- options.resizable,
- options.fullscreen,
- Application::WndProc
- );
-
- Renderer::GetInstance()->SetClearColor(options.clear_color);
- Renderer::GetInstance()->SetVSyncEnabled(options.vsync);
+ Window::GetInstance()->Init(config.window, Application::WndProc);
+ Renderer::GetInstance()->Init(config.render);
// Setup all components
for (Component* c : components_)
@@ -100,7 +90,7 @@ namespace kiwano
c->SetupComponent();
}
- if (options.debug)
+ if (config.debug)
{
Director::GetInstance()->ShowDebugInfo(true);
Renderer::GetInstance()->SetCollectingStatus(true);
@@ -150,7 +140,7 @@ namespace kiwano
// Clear all resources
Director::GetInstance()->ClearStages();
ResourceCache::GetInstance()->Clear();
- ImageCache::GetInstance()->Clear();
+ TextureCache::GetInstance()->Clear();
if (inited_)
{
@@ -166,7 +156,7 @@ namespace kiwano
// Destroy all instances
Director::DestroyInstance();
ResourceCache::DestroyInstance();
- ImageCache::DestroyInstance();
+ TextureCache::DestroyInstance();
Input::DestroyInstance();
Renderer::DestroyInstance();
Window::DestroyInstance();
@@ -299,10 +289,11 @@ namespace kiwano
LRESULT CALLBACK Application::WndProc(HWND hwnd, UInt32 msg, WPARAM wparam, LPARAM lparam)
{
- Application * app = reinterpret_cast(static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
-
- if (!app)
+ Application* app = reinterpret_cast(static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
+ if (app == nullptr)
+ {
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
+ }
// Handle Message
for (Component* c : app->components_)
diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h
index 97de5da3..2b24c3dd 100644
--- a/src/kiwano/platform/Application.h
+++ b/src/kiwano/platform/Application.h
@@ -23,32 +23,27 @@
#include "../base/time.h"
#include "../base/Component.h"
#include "../base/Event.hpp"
-#include "../renderer/Color.h"
+#include "../base/Window.h"
+#include "../renderer/Renderer.h"
namespace kiwano
{
- struct Options
+ struct Config
{
- String title; // 标题
- Int32 width; // 宽度
- Int32 height; // 高度
- UInt32 icon; // 图标资源 ID
- Color clear_color; // 清屏颜色
- bool vsync; // 垂直同步
- bool resizable; // 窗口大小可拉伸
- bool fullscreen; // 全屏模式
- bool debug; // 调试模式
+ WindowConfig window; // 窗口设置
+ RenderConfig render; // 渲染设置
+ bool debug; // 调试模式
- Options(
+ Config(
String const& title = L"Kiwano Game",
- Int32 width = 640,
- Int32 height = 480,
- UInt32 icon = 0,
- Color clear_color = Color::Black,
- bool vsync = true,
- bool resizable = false,
- bool fullscreen = false,
- bool debug = false
+ UInt32 width = 640,
+ UInt32 height = 480,
+ UInt32 icon = 0
+ );
+
+ Config(
+ WindowConfig const& wnd_config,
+ RenderConfig const& render_config = RenderConfig()
);
};
@@ -64,7 +59,7 @@ namespace kiwano
// 初始化
void Init(
- Options const& options = Options{}
+ Config const& config = Config()
);
// 初始化成功时
diff --git a/src/kiwano/renderer/Font.cpp b/src/kiwano/renderer/Font.cpp
index 24958349..2bb8de63 100644
--- a/src/kiwano/renderer/Font.cpp
+++ b/src/kiwano/renderer/Font.cpp
@@ -22,7 +22,16 @@
namespace kiwano
{
- Font::Font(const String& family, Float32 size, UInt32 weight, bool italic, FontCollection collection)
+ Font::Font(String const& family, Float32 size, UInt32 weight, bool italic)
+ : family(family)
+ , size(size)
+ , weight(weight)
+ , italic(italic)
+ , collection()
+ {
+ }
+
+ Font::Font(FontCollection collection, String const& family, Float32 size, UInt32 weight, bool italic)
: family(family)
, size(size)
, weight(weight)
diff --git a/src/kiwano/renderer/Font.h b/src/kiwano/renderer/Font.h
index c703c6d0..6d5cbfd8 100644
--- a/src/kiwano/renderer/Font.h
+++ b/src/kiwano/renderer/Font.h
@@ -49,11 +49,18 @@ namespace kiwano
public:
Font(
- const String& family = L"",
+ String const& family = L"",
Float32 size = 18,
UInt32 weight = FontWeight::Normal,
- bool italic = false,
- FontCollection collection = FontCollection()
+ bool italic = false
+ );
+
+ Font(
+ FontCollection collection,
+ String const& family = L"",
+ Float32 size = 18,
+ UInt32 weight = FontWeight::Normal,
+ bool italic = false
);
};
}
diff --git a/src/kiwano/renderer/FontCollection.cpp b/src/kiwano/renderer/FontCollection.cpp
index 87661691..532df86b 100644
--- a/src/kiwano/renderer/FontCollection.cpp
+++ b/src/kiwano/renderer/FontCollection.cpp
@@ -50,24 +50,30 @@ namespace kiwano
bool FontCollection::Load(String const& file)
{
Renderer::GetInstance()->CreateFontCollection(*this, { file });
- return false;
+ return IsValid();
}
bool FontCollection::Load(Vector const& files)
{
Renderer::GetInstance()->CreateFontCollection(*this, files);
- return false;
+ return IsValid();
}
bool FontCollection::Load(Resource const& res)
{
Renderer::GetInstance()->CreateFontCollection(*this, { res });
- return false;
+ return IsValid();
}
bool FontCollection::Load(Vector const& res_arr)
{
Renderer::GetInstance()->CreateFontCollection(*this, res_arr);
- return false;
+ return IsValid();
}
+
+ bool FontCollection::IsValid() const
+ {
+ return collection_ != nullptr;
+ }
+
}
diff --git a/src/kiwano/renderer/FontCollection.h b/src/kiwano/renderer/FontCollection.h
index e4297181..6d154587 100644
--- a/src/kiwano/renderer/FontCollection.h
+++ b/src/kiwano/renderer/FontCollection.h
@@ -51,6 +51,8 @@ namespace kiwano
// 从多个资源加载字体
bool Load(Vector const& res_arr);
+ bool IsValid() const;
+
public:
inline ComPtr GetFontCollection() const { return collection_; }
diff --git a/src/kiwano/renderer/GifImage.cpp b/src/kiwano/renderer/GifImage.cpp
index bea8a029..9add1fd5 100644
--- a/src/kiwano/renderer/GifImage.cpp
+++ b/src/kiwano/renderer/GifImage.cpp
@@ -28,7 +28,6 @@ namespace kiwano
: frames_count_(0)
, width_in_pixels_(0)
, height_in_pixels_(0)
- , bg_color_{}
{
}
@@ -82,15 +81,6 @@ namespace kiwano
HRESULT GifImage::GetGlobalMetadata()
{
- UInt32 width = 0;
- UInt32 height = 0;
-
- PROPVARIANT prop_val;
- ::PropVariantInit(&prop_val);
-
- ComPtr metadata_reader;
-
- // 获取帧数量
HRESULT hr = decoder_ ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
@@ -100,317 +90,91 @@ namespace kiwano
if (SUCCEEDED(hr))
{
+ ComPtr metadata_reader;
hr = decoder_->GetMetadataQueryReader(&metadata_reader);
- }
-
- if (SUCCEEDED(hr))
- {
- // 获取背景色
- if (FAILED(GetBackgroundColor(metadata_reader.get())))
- {
- // 如果未能获得颜色,则默认为透明
- bg_color_ = Color(0, 0.f);
- }
- }
-
- // 获取全局 frame 大小
- if (SUCCEEDED(hr))
- {
- // 获取宽度
- hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Width", &prop_val);
if (SUCCEEDED(hr))
{
- hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
+ UInt32 width = 0;
+ UInt32 height = 0;
+
+ PROPVARIANT prop_val;
+ ::PropVariantInit(&prop_val);
+
+ // 获取全局 frame 大小
if (SUCCEEDED(hr))
{
- width = prop_val.uiVal;
- }
- ::PropVariantClear(&prop_val);
- }
- }
+ // 获取宽度
+ hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Width", &prop_val);
- if (SUCCEEDED(hr))
- {
- // 获取高度
- hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Height", &prop_val);
-
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
- if (SUCCEEDED(hr))
- {
- height = prop_val.uiVal;
- }
- ::PropVariantClear(&prop_val);
- }
- }
-
- if (SUCCEEDED(hr))
- {
- // 获得像素纵横比
- hr = metadata_reader->GetMetadataByName(L"/logscrdesc/PixelAspectRatio", &prop_val);
-
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt == VT_UI1 ? S_OK : E_FAIL);
- if (SUCCEEDED(hr))
- {
- if (prop_val.bVal != 0)
- {
- // 需要计算比率
- // 最高像素 1:4,最宽像素 4:1,增量为 1/64
- Float32 pixel_asp_ratio = (prop_val.bVal + 15.f) / 64.f;
-
- // 根据像素长宽比计算像素中的图像宽度和高度,只缩小图像
- if (pixel_asp_ratio > 1.f)
- {
- width_in_pixels_ = width;
- height_in_pixels_ = static_cast(height / pixel_asp_ratio);
- }
- else
- {
- width_in_pixels_ = static_cast(width * pixel_asp_ratio);
- height_in_pixels_ = height;
- }
- }
- else
- {
- // 值为 0, 所以像素比为 1
- width_in_pixels_ = width;
- height_in_pixels_ = height;
- }
- }
- ::PropVariantClear(&prop_val);
- }
- }
-
- ::PropVariantClear(&prop_val);
- return hr;
- }
-
- HRESULT GifImage::GetBackgroundColor(ComPtr metadata_reader)
- {
- UChar bg_index = 0;
- WICColor bgcolors[256];
- UInt32 colors_copied = 0;
- ComPtr wic_palette;
-
- PROPVARIANT prop_val;
- PropVariantInit(&prop_val);
-
- HRESULT hr = metadata_reader->GetMetadataByName(L"/logscrdesc/GlobalColorTableFlag", &prop_val);
-
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt != VT_BOOL || !prop_val.boolVal) ? E_FAIL : S_OK;
- ::PropVariantClear(&prop_val);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = metadata_reader->GetMetadataByName(L"/logscrdesc/BackgroundColorIndex", &prop_val);
-
- if (SUCCEEDED(hr))
- {
- hr = (prop_val.vt != VT_UI1) ? E_FAIL : S_OK;
- if (SUCCEEDED(hr))
- {
- bg_index = prop_val.bVal;
- }
- ::PropVariantClear(&prop_val);
- }
- }
-
- if (SUCCEEDED(hr))
- {
- auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
- hr = factory->CreatePalette(&wic_palette);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = decoder_->CopyPalette(wic_palette.get());
- }
-
- if (SUCCEEDED(hr))
- {
- hr = wic_palette->GetColors(
- ARRAYSIZE(bgcolors),
- bgcolors,
- &colors_copied);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = (bg_index >= colors_copied) ? E_FAIL : S_OK;
- }
-
- if (SUCCEEDED(hr))
- {
- // 转换为 ARGB 格式
- Float32 alpha = (bgcolors[bg_index] >> 24) / 255.f;
- bg_color_ = Color(bgcolors[bg_index], alpha);
- }
- return hr;
- }
-
- HRESULT GifImage::GetRawFrame(UInt32 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.left_top.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.left_top.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.right_bottom.x = frame_rect.left_top.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.right_bottom.y = frame_rect.left_top.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))
- {
- UInt32 udelay = 0;
- hr = UIntMult(prop_val.uiVal, 10, &udelay);
if (SUCCEEDED(hr))
{
- delay.SetMilliseconds(static_cast(udelay));
+ hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
+ if (SUCCEEDED(hr))
+ {
+ width = prop_val.uiVal;
+ }
+ ::PropVariantClear(&prop_val);
}
}
- 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);
+ // 获取高度
+ hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Height", &prop_val);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
+ if (SUCCEEDED(hr))
+ {
+ height = prop_val.uiVal;
+ }
+ ::PropVariantClear(&prop_val);
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ // 获得像素纵横比
+ hr = metadata_reader->GetMetadataByName(L"/logscrdesc/PixelAspectRatio", &prop_val);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = (prop_val.vt == VT_UI1 ? S_OK : E_FAIL);
+ if (SUCCEEDED(hr))
+ {
+ if (prop_val.bVal != 0)
+ {
+ // 需要计算比率
+ // 最高像素 1:4,最宽像素 4:1,增量为 1/64
+ Float32 pixel_asp_ratio = (prop_val.bVal + 15.f) / 64.f;
+
+ // 根据像素长宽比计算像素中的图像宽度和高度,只缩小图像
+ if (pixel_asp_ratio > 1.f)
+ {
+ width_in_pixels_ = width;
+ height_in_pixels_ = static_cast(height / pixel_asp_ratio);
+ }
+ else
+ {
+ width_in_pixels_ = static_cast(width * pixel_asp_ratio);
+ height_in_pixels_ = height;
+ }
+ }
+ else
+ {
+ // 值为 0, 所以像素比为 1
+ width_in_pixels_ = width;
+ height_in_pixels_ = height;
+ }
+ }
+ ::PropVariantClear(&prop_val);
+ }
}
::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 1e05bc38..339c63f1 100644
--- a/src/kiwano/renderer/GifImage.h
+++ b/src/kiwano/renderer/GifImage.h
@@ -19,7 +19,7 @@
// THE SOFTWARE.
#pragma once
-#include "Image.h"
+#include "Texture.h"
namespace kiwano
{
@@ -43,9 +43,7 @@ namespace kiwano
inline UInt32 GetHeightInPixels() const { return height_in_pixels_; }
- inline UInt32 GetFramesCount() const { return frames_count_; }
-
- inline Color GetBackgroundColor() const { return bg_color_; }
+ inline UInt32 GetFramesCount() const { return frames_count_; }
public:
enum class DisposalType
@@ -56,13 +54,15 @@ namespace kiwano
Previous
};
- HRESULT GetRawFrame(
- UInt32 frame_index,
- Image& raw_frame,
- Rect& frame_rect,
- Duration& delay,
- DisposalType& disposal_type
- );
+ struct Frame
+ {
+ Duration delay;
+ Texture raw;
+ Rect rect;
+ DisposalType disposal_type;
+
+ Frame() : disposal_type(DisposalType::Unknown) {}
+ };
inline ComPtr GetDecoder() const { return decoder_; }
@@ -71,16 +71,11 @@ namespace kiwano
protected:
HRESULT GetGlobalMetadata();
- HRESULT GetBackgroundColor(
- ComPtr metadata_reader
- );
-
protected:
UInt32 frames_count_;
UInt32 width_in_pixels_;
UInt32 height_in_pixels_;
- Color bg_color_;
- ComPtr decoder_;
+ ComPtr decoder_;
};
}
diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp
index b516ea77..6bfe1eed 100644
--- a/src/kiwano/renderer/RenderTarget.cpp
+++ b/src/kiwano/renderer/RenderTarget.cpp
@@ -30,8 +30,9 @@ namespace kiwano
RenderTarget::RenderTarget()
: opacity_(1.f)
, collecting_status_(false)
+ , fast_global_transform_(true)
, antialias_(true)
- , text_antialias_(TextAntialias::GrayScale)
+ , text_antialias_(TextAntialiasMode::GrayScale)
{
status_.primitives = 0;
}
@@ -133,7 +134,7 @@ namespace kiwano
geometry.GetGeometry().get(),
default_brush_.get(),
stroke_width,
- device_resources_->GetStrokeStyle(stroke)
+ GetStrokeStyle(stroke).get()
);
IncreasePrimitivesCount();
@@ -179,7 +180,7 @@ namespace kiwano
DX::ConvertToPoint2F(point2),
default_brush_.get(),
stroke_width,
- device_resources_->GetStrokeStyle(stroke)
+ GetStrokeStyle(stroke).get()
);
IncreasePrimitivesCount();
@@ -204,7 +205,7 @@ namespace kiwano
DX::ConvertToRectF(rect),
default_brush_.get(),
stroke_width,
- device_resources_->GetStrokeStyle(stroke)
+ GetStrokeStyle(stroke).get()
);
IncreasePrimitivesCount();
@@ -253,7 +254,7 @@ namespace kiwano
),
default_brush_.get(),
stroke_width,
- device_resources_->GetStrokeStyle(stroke)
+ GetStrokeStyle(stroke).get()
);
IncreasePrimitivesCount();
@@ -306,7 +307,7 @@ namespace kiwano
),
default_brush_.get(),
stroke_width,
- device_resources_->GetStrokeStyle(stroke)
+ GetStrokeStyle(stroke).get()
);
IncreasePrimitivesCount();
@@ -339,12 +340,12 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::DrawImage(Image const& image, Rect const& src_rect, Rect const& dest_rect) const
+ void RenderTarget::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect) const
{
- DrawImage(image, &src_rect, &dest_rect);
+ DrawTexture(texture, &src_rect, &dest_rect);
}
- void RenderTarget::DrawImage(Image const& image, const Rect* src_rect, const Rect* dest_rect) const
+ void RenderTarget::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect) const
{
HRESULT hr = S_OK;
if (!render_target_)
@@ -352,13 +353,17 @@ namespace kiwano
hr = E_UNEXPECTED;
}
- if (SUCCEEDED(hr) && image.IsValid())
+ if (SUCCEEDED(hr) && texture.IsValid())
{
+ auto mode = (texture.GetBitmapInterpolationMode() == InterpolationMode::Linear)
+ ? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
+ : D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
+
render_target_->DrawBitmap(
- image.GetBitmap().get(),
+ texture.GetBitmap().get(),
dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
opacity_,
- D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
+ mode,
src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr
);
@@ -384,7 +389,7 @@ namespace kiwano
layout.GetTextStyle().outline,
DX::ConvertToColorF(layout.GetTextStyle().outline_color),
layout.GetTextStyle().outline_width,
- device_resources_->GetStrokeStyle(layout.GetTextStyle().outline_stroke)
+ GetStrokeStyle(layout.GetTextStyle().outline_stroke).get()
);
}
@@ -537,7 +542,18 @@ namespace kiwano
Matrix3x2 RenderTarget::GetGlobalTransform() const
{
- return global_matrix_;
+ return global_transform_;
+ }
+
+ ComPtr RenderTarget::GetStrokeStyle(StrokeStyle style) const
+ {
+ switch (style)
+ {
+ case StrokeStyle::Miter: return device_resources_->GetMiterStrokeStyle(); break;
+ case StrokeStyle::Bevel: return device_resources_->GetBevelStrokeStyle(); break;
+ case StrokeStyle::Round: return device_resources_->GetRoundStrokeStyle(); break;
+ }
+ return nullptr;
}
void RenderTarget::SetTransform(const Matrix3x2& matrix)
@@ -550,8 +566,16 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- Matrix3x2 result = matrix * global_matrix_;
- render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result));
+ if (fast_global_transform_)
+ {
+ render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
+
+ }
+ else
+ {
+ Matrix3x2 result = matrix * global_transform_;
+ render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result));
+ }
}
ThrowIfFailed(hr);
@@ -559,7 +583,20 @@ namespace kiwano
void RenderTarget::SetGlobalTransform(const Matrix3x2& matrix)
{
- global_matrix_ = matrix;
+ SetGlobalTransform(&matrix);
+ }
+
+ void RenderTarget::SetGlobalTransform(const Matrix3x2* matrix)
+ {
+ if (matrix)
+ {
+ global_transform_ = *matrix;
+ fast_global_transform_ = false;
+ }
+ else
+ {
+ fast_global_transform_ = true;
+ }
}
void RenderTarget::SetOpacity(Float32 opacity)
@@ -601,7 +638,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void RenderTarget::SetTextAntialiasMode(TextAntialias mode)
+ void RenderTarget::SetTextAntialiasMode(TextAntialiasMode mode)
{
HRESULT hr = S_OK;
if (!render_target_)
@@ -615,16 +652,16 @@ namespace kiwano
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
switch (text_antialias_)
{
- case TextAntialias::Default:
+ case TextAntialiasMode::Default:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
break;
- case TextAntialias::ClearType:
+ case TextAntialiasMode::ClearType:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
break;
- case TextAntialias::GrayScale:
+ case TextAntialiasMode::GrayScale:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
break;
- case TextAntialias::None:
+ case TextAntialiasMode::None:
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
break;
default:
@@ -638,9 +675,12 @@ namespace kiwano
bool RenderTarget::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform)
{
- return Rect{ Point{}, reinterpret_cast(render_target_->GetSize()) }.Intersects(
- Matrix3x2(transform * global_matrix_).Transform(bounds)
- );
+ Rect visible_size = { Point{}, reinterpret_cast(render_target_->GetSize()) };
+ if (fast_global_transform_)
+ {
+ return visible_size.Intersects(transform.Transform(bounds));
+ }
+ return visible_size.Intersects(Matrix3x2(transform * global_transform_).Transform(bounds));
}
void RenderTarget::SetCollectingStatus(bool collecting)
@@ -658,14 +698,14 @@ namespace kiwano
//
- // ImageRenderTarget
+ // TextureRenderTarget
//
- ImageRenderTarget::ImageRenderTarget()
+ TextureRenderTarget::TextureRenderTarget()
{
}
- Image ImageRenderTarget::GetOutput() const
+ Texture TextureRenderTarget::GetOutput() const
{
HRESULT hr = E_FAIL;
@@ -681,13 +721,13 @@ namespace kiwano
if (SUCCEEDED(hr))
{
- return Image(bitmap);
+ return Texture(bitmap);
}
}
}
ThrowIfFailed(hr);
- return Image();
+ return Texture();
}
}
diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h
index f8c63c5e..019ea940 100644
--- a/src/kiwano/renderer/RenderTarget.h
+++ b/src/kiwano/renderer/RenderTarget.h
@@ -20,7 +20,7 @@
#pragma once
#include "../base/time.h"
-#include "Image.h"
+#include "Texture.h"
#include "Geometry.h"
#include "TextLayout.h"
#include "LayerArea.h"
@@ -28,6 +28,16 @@
namespace kiwano
{
+ // 文字抗锯齿模式
+ enum class TextAntialiasMode
+ {
+ Default, // 系统默认
+ ClearType, // ClearType 抗锯齿
+ GrayScale, // 灰度抗锯齿
+ None // 不启用抗锯齿
+ };
+
+
// 渲染目标
class KGE_API RenderTarget
: public noncopyable
@@ -103,14 +113,14 @@ namespace kiwano
Color const& fill_color
) const;
- void DrawImage(
- Image const& image,
+ void DrawTexture(
+ Texture const& texture,
Rect const& src_rect,
Rect const& dest_rect
) const;
- void DrawImage(
- Image const& image,
+ void DrawTexture(
+ Texture const& texture,
const Rect* src_rect = nullptr,
const Rect* dest_rect = nullptr
) const;
@@ -154,6 +164,10 @@ namespace kiwano
const Matrix3x2& matrix
);
+ void SetGlobalTransform(
+ const Matrix3x2* matrix
+ );
+
// 设置抗锯齿模式
void SetAntialiasMode(
bool enabled
@@ -161,9 +175,10 @@ namespace kiwano
// 设置文字抗锯齿模式
void SetTextAntialiasMode(
- TextAntialias mode
+ TextAntialiasMode mode
);
+ // 检查边界是否在视区内
bool CheckVisibility(
Rect const& bounds,
Matrix3x2 const& transform
@@ -181,11 +196,13 @@ namespace kiwano
void IncreasePrimitivesCount() const;
- inline Status const& GetStatus() const { return status_; }
+ inline Status const& GetStatus() const { return status_; }
- inline ComPtr GetRenderTarget() const { KGE_ASSERT(render_target_); return render_target_; }
+ inline ComPtr GetRenderTarget() const { KGE_ASSERT(render_target_); return render_target_; }
- inline ComPtr GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_; }
+ inline ComPtr GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_; }
+
+ ComPtr GetStrokeStyle(StrokeStyle style) const;
public:
RenderTarget();
@@ -200,25 +217,26 @@ namespace kiwano
protected:
Float32 opacity_;
bool antialias_;
+ bool fast_global_transform_;
mutable bool collecting_status_;
mutable Status status_;
- TextAntialias text_antialias_;
+ TextAntialiasMode text_antialias_;
ComPtr text_renderer_;
ComPtr render_target_;
ComPtr default_brush_;
ComPtr current_brush_;
ComPtr device_resources_;
- Matrix3x2 global_matrix_;
+ Matrix3x2 global_transform_;
};
// 位图渲染目标
- class KGE_API ImageRenderTarget
+ class KGE_API TextureRenderTarget
: public RenderTarget
{
public:
- ImageRenderTarget();
+ TextureRenderTarget();
- Image GetOutput() const;
+ Texture GetOutput() const;
};
}
diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp
index ccae9a87..699ba874 100644
--- a/src/kiwano/renderer/Renderer.cpp
+++ b/src/kiwano/renderer/Renderer.cpp
@@ -25,6 +25,12 @@
namespace kiwano
{
+ RenderConfig::RenderConfig(Color clear_color, bool vsync)
+ : clear_color(clear_color)
+ , vsync(vsync)
+ {
+ }
+
Renderer::Renderer()
: hwnd_(nullptr)
, vsync_(true)
@@ -37,6 +43,12 @@ namespace kiwano
{
}
+ void Renderer::Init(RenderConfig const& config)
+ {
+ SetClearColor(config.clear_color);
+ SetVSyncEnabled(config.vsync);
+ }
+
void Renderer::SetupComponent()
{
KGE_LOG(L"Creating device resources");
@@ -245,57 +257,7 @@ namespace kiwano
return hr;
}
- void Renderer::CreateImage(Image& image, String const& file_path)
- {
- HRESULT hr = S_OK;
- if (!d2d_res_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- ComPtr bitmap;
- hr = d2d_res_->CreateBitmapFromFile(bitmap, file_path);
-
- if (SUCCEEDED(hr))
- {
- image.SetBitmap(bitmap);
- }
- }
-
- if (FAILED(hr))
- {
- KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr);
- }
- }
-
- void Renderer::CreateImage(Image& image, Resource const& res)
- {
- HRESULT hr = S_OK;
- if (!d2d_res_)
- {
- hr = E_UNEXPECTED;
- }
-
- if (SUCCEEDED(hr))
- {
- ComPtr bitmap;
- hr = d2d_res_->CreateBitmapFromResource(bitmap, res);
-
- if (SUCCEEDED(hr))
- {
- image.SetBitmap(bitmap);
- }
- }
-
- if (FAILED(hr))
- {
- KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr);
- }
- }
-
- void Renderer::CreateGifImage(GifImage& image, String const& file_path)
+ void Renderer::CreateTexture(Texture& texture, String const& file_path)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@@ -305,34 +267,58 @@ namespace kiwano
if (!FileUtil::ExistsFile(file_path))
{
- KGE_WARNING_LOG(L"Gif image file '%s' not found!", file_path.c_str());
+ KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str());
hr = E_FAIL;
}
if (SUCCEEDED(hr))
{
ComPtr decoder;
- hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename(
- file_path.c_str(),
- nullptr,
- GENERIC_READ,
- WICDecodeMetadataCacheOnLoad,
- &decoder
- );
+ hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path);
if (SUCCEEDED(hr))
{
- image.SetDecoder(decoder);
+ ComPtr source;
+ hr = decoder->GetFrame(0, &source);
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr converter;
+ hr = d2d_res_->CreateBitmapConverter(
+ converter,
+ source,
+ GUID_WICPixelFormat32bppPBGRA,
+ WICBitmapDitherTypeNone,
+ nullptr,
+ 0.f,
+ WICBitmapPaletteTypeMedianCut
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr bitmap;
+ hr = d2d_res_->CreateBitmapFromConverter(
+ bitmap,
+ nullptr,
+ converter
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ texture.SetBitmap(bitmap);
+ }
+ }
+ }
}
}
if (FAILED(hr))
{
- KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr);
+ KGE_WARNING_LOG(L"Load texture failed with HRESULT of %08X!", hr);
}
}
- void Renderer::CreateGifImage(GifImage& image, Resource const& res)
+ void Renderer::CreateTexture(Texture& texture, Resource const& resource)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@@ -340,43 +326,273 @@ namespace kiwano
hr = E_UNEXPECTED;
}
- Resource::Data res_data = res.GetData();
-
- hr = res_data ? S_OK : E_FAIL;
-
if (SUCCEEDED(hr))
{
- ComPtr stream;
- hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream);
+ ComPtr decoder;
+ hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
if (SUCCEEDED(hr))
{
- hr = stream->InitializeFromMemory(
- static_cast(res_data.buffer),
- res_data.size
- );
- }
-
- if (SUCCEEDED(hr))
- {
- ComPtr decoder;
- hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream(
- stream.get(),
- nullptr,
- WICDecodeMetadataCacheOnLoad,
- &decoder
- );
+ ComPtr source;
+ hr = decoder->GetFrame(0, &source);
if (SUCCEEDED(hr))
{
- image.SetDecoder(decoder);
+ ComPtr converter;
+ hr = d2d_res_->CreateBitmapConverter(
+ converter,
+ source,
+ GUID_WICPixelFormat32bppPBGRA,
+ WICBitmapDitherTypeNone,
+ nullptr,
+ 0.f,
+ WICBitmapPaletteTypeMedianCut
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr bitmap;
+ hr = d2d_res_->CreateBitmapFromConverter(
+ bitmap,
+ nullptr,
+ converter
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ texture.SetBitmap(bitmap);
+ }
+ }
}
}
}
if (FAILED(hr))
{
- KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr);
+ KGE_WARNING_LOG(L"Load texture failed with HRESULT of %08X!", hr);
+ }
+ }
+
+ void Renderer::CreateGifImage(GifImage& gif, String const& file_path)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (!FileUtil::ExistsFile(file_path))
+ {
+ KGE_WARNING_LOG(L"Gif texture file '%s' not found!", file_path.c_str());
+ hr = E_FAIL;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr decoder;
+ hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path);
+
+ if (SUCCEEDED(hr))
+ {
+ gif.SetDecoder(decoder);
+ }
+ }
+
+ if (FAILED(hr))
+ {
+ KGE_WARNING_LOG(L"Load GIF texture failed with HRESULT of %08X!", hr);
+ }
+ }
+
+ void Renderer::CreateGifImage(GifImage& gif, Resource const& resource)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr decoder;
+ hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
+
+ if (SUCCEEDED(hr))
+ {
+ gif.SetDecoder(decoder);
+ }
+ }
+
+ if (FAILED(hr))
+ {
+ KGE_WARNING_LOG(L"Load GIF texture failed with HRESULT of %08X!", hr);
+ }
+ }
+
+ void Renderer::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, UInt32 frame_index)
+ {
+ HRESULT hr = S_OK;
+ if (!d2d_res_)
+ {
+ hr = E_UNEXPECTED;
+ }
+
+ if (gif.GetDecoder() == nullptr)
+ {
+ hr = E_INVALIDARG;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr wic_frame;
+ HRESULT hr = gif.GetDecoder()->GetFrame(frame_index, &wic_frame);
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr converter;
+ d2d_res_->CreateBitmapConverter(
+ converter,
+ wic_frame,
+ GUID_WICPixelFormat32bppPBGRA,
+ WICBitmapDitherTypeNone,
+ nullptr,
+ 0.f,
+ WICBitmapPaletteTypeCustom
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ ComPtr raw_bitmap;
+ hr = d2d_res_->CreateBitmapFromConverter(
+ raw_bitmap,
+ nullptr,
+ converter
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ frame.raw.SetBitmap(raw_bitmap);
+ }
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ PROPVARIANT prop_val;
+ PropVariantInit(&prop_val);
+
+ // Get Metadata Query Reader from the frame
+ ComPtr metadata_reader;
+ 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.left_top.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.left_top.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.right_bottom.x = frame.rect.left_top.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.right_bottom.y = frame.rect.left_top.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))
+ {
+ UInt32 udelay = 0;
+ hr = UIntMult(prop_val.uiVal, 10, &udelay);
+ if (SUCCEEDED(hr))
+ {
+ frame.delay.SetMilliseconds(static_cast(udelay));
+ }
+ }
+ PropVariantClear(&prop_val);
+ }
+ else
+ {
+ frame.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))
+ {
+ frame.disposal_type = GifImage::DisposalType(prop_val.bVal);
+ }
+ ::PropVariantClear(&prop_val);
+ }
+ else
+ {
+ frame.disposal_type = GifImage::DisposalType::Unknown;
+ }
+ }
+
+ ::PropVariantClear(&prop_val);
+ }
+ }
+
+ if (FAILED(hr))
+ {
+ KGE_WARNING_LOG(L"Load GIF frame failed with HRESULT of %08X!", hr);
}
}
@@ -490,7 +706,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextStyle const& style, TextFormat const& format)
+ void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextFormat const& format)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@@ -504,7 +720,6 @@ namespace kiwano
hr = d2d_res_->CreateTextLayout(
output,
text,
- style,
format.GetTextFormat()
);
}
@@ -653,7 +868,7 @@ namespace kiwano
ThrowIfFailed(hr);
}
- void Renderer::CreateImageRenderTarget(ImageRenderTarget& render_target)
+ void Renderer::CreateTextureRenderTarget(TextureRenderTarget& render_target)
{
HRESULT hr = S_OK;
if (!d2d_res_)
@@ -732,7 +947,7 @@ namespace kiwano
{
case ResolutionMode::Fixed:
{
- SetGlobalTransform(Matrix3x2{});
+ SetGlobalTransform(nullptr);
break;
}
diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h
index 7e59ff9a..4e14f017 100644
--- a/src/kiwano/renderer/Renderer.h
+++ b/src/kiwano/renderer/Renderer.h
@@ -39,6 +39,32 @@ namespace kiwano
typedef ID3D11DeviceResources ID3DDeviceResources;
#endif
+ // 渲染设置
+ struct RenderConfig
+ {
+ Color clear_color; // 清屏颜色
+ bool vsync; // 垂直同步
+
+ RenderConfig(
+ Color clear_color = Color::Black,
+ bool vsync = true
+ );
+ };
+
+ // 分辨率模式
+ // 分辨率模式决定了将画面渲染到视区上的方式
+ // Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认)
+ // Center (居中): 分辨率不随视区改变, 且画面始终在视区上居中
+ // Stretch (拉伸): 分辨率始终随视区等比例拉伸
+ // Adaptive (宽高自适应): 分辨率始终保持宽高比, 且尽可能的填充视区, 可能会出现黑色边界
+ enum class ResolutionMode
+ {
+ Fixed, /* 固定 */
+ Center, /* 居中 */
+ Stretch, /* 拉伸 */
+ Adaptive, /* 宽高自适应 */
+ };
+
class KGE_API Renderer
: public Singleton
, public Component
@@ -57,25 +83,41 @@ namespace kiwano
bool enabled
);
+ // 设置画面分辨率
+ void SetResolution(
+ Size const& resolution
+ );
+
+ // 设置分辨率模式
+ void SetResolutionMode(
+ ResolutionMode mode
+ );
+
public:
- void CreateImage(
- Image& image,
+ void CreateTexture(
+ Texture& texture,
String const& file_path
);
- void CreateImage(
- Image& image,
- Resource const& res
+ void CreateTexture(
+ Texture& texture,
+ Resource const& resource
);
void CreateGifImage(
- GifImage& image,
+ GifImage& gif,
String const& file_path
);
void CreateGifImage(
- GifImage& image,
- Resource const& res
+ GifImage& gif,
+ Resource const& resource
+ );
+
+ void CreateGifImageFrame(
+ GifImage::Frame& frame,
+ GifImage const& gif,
+ UInt32 frame_index
);
void CreateFontCollection(
@@ -96,7 +138,6 @@ namespace kiwano
void CreateTextLayout(
TextLayout& layout,
String const& text,
- TextStyle const& style,
TextFormat const& format
);
@@ -127,19 +168,13 @@ namespace kiwano
GeometrySink& sink
);
- void CreateImageRenderTarget(
- ImageRenderTarget& render_target
- );
-
- void SetResolution(
- Size const& resolution
- );
-
- void SetResolutionMode(
- ResolutionMode mode
+ void CreateTextureRenderTarget(
+ TextureRenderTarget& render_target
);
public:
+ void Init(RenderConfig const& config);
+
void SetupComponent() override;
void DestroyComponent() override;
diff --git a/src/kiwano/base/types.h b/src/kiwano/renderer/StrokeStyle.h
similarity index 70%
rename from src/kiwano/base/types.h
rename to src/kiwano/renderer/StrokeStyle.h
index 8bc6aa8b..5afaac8a 100644
--- a/src/kiwano/base/types.h
+++ b/src/kiwano/renderer/StrokeStyle.h
@@ -23,41 +23,10 @@
namespace kiwano
{
// 线条样式
- enum class StrokeStyle : Int32
+ enum class StrokeStyle
{
Miter = 0, /* 斜切 */
Bevel = 1, /* 斜角 */
Round = 2 /* 圆角 */
};
-
- // 鼠标指针
- enum class MouseCursor : Int32
- {
- Arrow, /* 指针 */
- TextInput, /* 输入文本 */
- Hand, /* 手指 */
- SizeAll,
- SizeNESW,
- SizeNS,
- SizeNWSE,
- SizeWE,
- };
-
- // 文字抗锯齿属性
- enum class TextAntialias
- {
- Default, // 系统默认
- ClearType, // ClearType 抗锯齿
- GrayScale, // 灰度抗锯齿
- None // 不启用抗锯齿
- };
-
- // 分辨率模式
- enum class ResolutionMode
- {
- Fixed, /* 固定 */
- Center, /* 居中 */
- Stretch, /* 拉伸 */
- Adaptive, /* 宽高自适应 */
- };
}
diff --git a/src/kiwano/renderer/TextLayout.cpp b/src/kiwano/renderer/TextLayout.cpp
index c4033479..8a4f2eaa 100644
--- a/src/kiwano/renderer/TextLayout.cpp
+++ b/src/kiwano/renderer/TextLayout.cpp
@@ -76,9 +76,73 @@ namespace kiwano
Renderer::GetInstance()->CreateTextLayout(
*this,
text,
- style,
text_format_
);
+
+ HRESULT hr = text_layout_ ? S_OK : E_FAIL;
+
+ if (SUCCEEDED(hr))
+ {
+ if (style.line_spacing == 0.f)
+ {
+ hr = text_layout_->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
+ }
+ else
+ {
+ hr = text_layout_->SetLineSpacing(
+ DWRITE_LINE_SPACING_METHOD_UNIFORM,
+ style.line_spacing,
+ style.line_spacing * 0.8f
+ );
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = text_layout_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(style.alignment));
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ hr = text_layout_->SetWordWrapping((style.wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (style.underline)
+ {
+ hr = text_layout_->SetUnderline(true, { 0, text.length() });
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (style.strikethrough)
+ {
+ text_layout_->SetStrikethrough(true, { 0, text.length() });
+ }
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ if (style.wrap_width > 0)
+ {
+ hr = text_layout_->SetMaxWidth(style.wrap_width);
+ }
+ else
+ {
+ // Fix the layout width when the text does not wrap
+ DWRITE_TEXT_METRICS metrics;
+ hr = text_layout_->GetMetrics(&metrics);
+
+ if (SUCCEEDED(hr))
+ {
+ hr = text_layout_->SetMaxWidth(metrics.width);
+ }
+ }
+ }
+
+ ThrowIfFailed(hr);
}
UInt32 TextLayout::GetLineCount()
diff --git a/src/kiwano/renderer/Image.cpp b/src/kiwano/renderer/Texture.cpp
similarity index 63%
rename from src/kiwano/renderer/Image.cpp
rename to src/kiwano/renderer/Texture.cpp
index 39d9f253..ad53f8d3 100644
--- a/src/kiwano/renderer/Image.cpp
+++ b/src/kiwano/renderer/Texture.cpp
@@ -18,53 +18,59 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "Image.h"
+#include "Texture.h"
#include "Renderer.h"
#include "../base/Logger.h"
namespace kiwano
{
- Image::Image()
+ InterpolationMode Texture::default_interpolation_mode_ = InterpolationMode::Linear;
+
+ Texture::Texture()
+ : interpolation_mode_(default_interpolation_mode_)
{
}
- Image::Image(String const& file_path)
+ Texture::Texture(String const& file_path)
+ : Texture()
{
Load(file_path);
}
- Image::Image(Resource const& res)
+ Texture::Texture(Resource const& res)
+ : Texture()
{
Load(res);
}
- Image::Image(ComPtr const & bitmap)
+ Texture::Texture(ComPtr const & bitmap)
+ : Texture()
{
SetBitmap(bitmap);
}
- Image::~Image()
+ Texture::~Texture()
{
}
- bool Image::Load(String const& file_path)
+ bool Texture::Load(String const& file_path)
{
- Renderer::GetInstance()->CreateImage(*this, file_path);
+ Renderer::GetInstance()->CreateTexture(*this, file_path);
return IsValid();
}
- bool Image::Load(Resource const& res)
+ bool Texture::Load(Resource const& res)
{
- Renderer::GetInstance()->CreateImage(*this, res);
+ Renderer::GetInstance()->CreateTexture(*this, res);
return IsValid();
}
- bool Image::IsValid() const
+ bool Texture::IsValid() const
{
return bitmap_ != nullptr;
}
- Float32 Image::GetWidth() const
+ Float32 Texture::GetWidth() const
{
if (bitmap_)
{
@@ -73,7 +79,7 @@ namespace kiwano
return 0;
}
- Float32 Image::GetHeight() const
+ Float32 Texture::GetHeight() const
{
if (bitmap_)
{
@@ -82,7 +88,7 @@ namespace kiwano
return 0;
}
- Size Image::GetSize() const
+ Size Texture::GetSize() const
{
if (bitmap_)
{
@@ -92,7 +98,7 @@ namespace kiwano
return Size{};
}
- UInt32 Image::GetWidthInPixels() const
+ UInt32 Texture::GetWidthInPixels() const
{
if (bitmap_)
{
@@ -101,7 +107,7 @@ namespace kiwano
return 0;
}
- UInt32 Image::GetHeightInPixels() const
+ UInt32 Texture::GetHeightInPixels() const
{
if (bitmap_)
{
@@ -110,7 +116,7 @@ namespace kiwano
return 0;
}
- math::Vec2T Image::GetSizeInPixels() const
+ math::Vec2T Texture::GetSizeInPixels() const
{
if (bitmap_)
{
@@ -120,7 +126,12 @@ namespace kiwano
return math::Vec2T{};
}
- void Image::CopyFrom(Image const& copy_from)
+ InterpolationMode Texture::GetBitmapInterpolationMode() const
+ {
+ return interpolation_mode_;
+ }
+
+ void Texture::CopyFrom(Texture const& copy_from)
{
if (IsValid() && copy_from.IsValid())
{
@@ -130,7 +141,7 @@ namespace kiwano
}
}
- void Image::CopyFrom(Image const& copy_from, Rect const& src_rect, Point const& dest_point)
+ void Texture::CopyFrom(Texture const& copy_from, Rect const& src_rect, Point const& dest_point)
{
if (IsValid() && copy_from.IsValid())
{
@@ -148,7 +159,21 @@ namespace kiwano
}
}
- D2D1_PIXEL_FORMAT Image::GetPixelFormat() const
+ void Texture::SetInterpolationMode(InterpolationMode mode)
+ {
+ interpolation_mode_ = mode;
+ switch (mode)
+ {
+ case InterpolationMode::Linear:
+ break;
+ case InterpolationMode::Nearest:
+ break;
+ default:
+ break;
+ }
+ }
+
+ D2D1_PIXEL_FORMAT Texture::GetPixelFormat() const
{
if (bitmap_)
{
@@ -157,14 +182,18 @@ namespace kiwano
return D2D1_PIXEL_FORMAT();
}
- ComPtr Image::GetBitmap() const
+ ComPtr Texture::GetBitmap() const
{
return bitmap_;
}
- void Image::SetBitmap(ComPtr bitmap)
+ void Texture::SetBitmap(ComPtr bitmap)
{
bitmap_ = bitmap;
}
+ void Texture::SetDefaultInterpolationMode(InterpolationMode mode)
+ {
+ }
+
}
diff --git a/src/kiwano/renderer/Image.h b/src/kiwano/renderer/Texture.h
similarity index 66%
rename from src/kiwano/renderer/Image.h
rename to src/kiwano/renderer/Texture.h
index 86900c60..a2d80211 100644
--- a/src/kiwano/renderer/Image.h
+++ b/src/kiwano/renderer/Texture.h
@@ -23,25 +23,36 @@
namespace kiwano
{
- // 图像
- class KGE_API Image
+ // 插值模式
+ // 插值模式指定了位图在缩放和旋转时像素颜色的计算方式
+ // Linear (双线性插值): 对周围四个像素进行两次线性插值计算, 在图像放大时可能会模糊(默认)
+ // Nearest (最邻近插值): 取最邻近的像素点的颜色值
+ enum class InterpolationMode
+ {
+ Linear, // 双线性插值
+ Nearest, // 最邻近插值
+ };
+
+
+ // 纹理
+ class KGE_API Texture
{
public:
- Image();
+ Texture();
- explicit Image(
+ explicit Texture(
String const& file_path
);
- explicit Image(
+ explicit Texture(
Resource const& res
);
- explicit Image(
+ explicit Texture(
ComPtr const& bitmap
);
- virtual ~Image();
+ virtual ~Texture();
// 加载本地文件
bool Load(
@@ -56,29 +67,38 @@ namespace kiwano
// 资源是否有效
bool IsValid() const;
- // 获取位图宽度
+ // 获取宽度
Float32 GetWidth() const;
- // 获取位图高度
+ // 获取高度
Float32 GetHeight() const;
- // 获取位图大小
+ // 获取大小
Size GetSize() const;
- // 获取位图像素宽度
+ // 获取像素宽度
UInt32 GetWidthInPixels() const;
- // 获取位图像素高度
+ // 获取像素高度
UInt32 GetHeightInPixels() const;
- // 获取位图像素大小
+ // 获取像素大小
math::Vec2T GetSizeInPixels() const;
- // 拷贝位图内存
- void CopyFrom(Image const& copy_from);
+ // 获取像素插值方式
+ InterpolationMode GetBitmapInterpolationMode() const;
// 拷贝位图内存
- void CopyFrom(Image const& copy_from, Rect const& src_rect, Point const& dest_point);
+ void CopyFrom(Texture const& copy_from);
+
+ // 拷贝位图内存
+ void CopyFrom(Texture const& copy_from, Rect const& src_rect, Point const& dest_point);
+
+ // 设置像素插值方式
+ void SetInterpolationMode(InterpolationMode mode);
+
+ // 设置默认的像素插值方式
+ static void SetDefaultInterpolationMode(InterpolationMode mode);
public:
// 获取源位图
@@ -92,5 +112,8 @@ namespace kiwano
protected:
ComPtr bitmap_;
+ InterpolationMode interpolation_mode_;
+
+ static InterpolationMode default_interpolation_mode_;
};
}
diff --git a/src/kiwano/renderer/ImageCache.cpp b/src/kiwano/renderer/TextureCache.cpp
similarity index 57%
rename from src/kiwano/renderer/ImageCache.cpp
rename to src/kiwano/renderer/TextureCache.cpp
index 7ec0ea39..d4308916 100644
--- a/src/kiwano/renderer/ImageCache.cpp
+++ b/src/kiwano/renderer/TextureCache.cpp
@@ -18,7 +18,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-#include "ImageCache.h"
+#include "TextureCache.h"
#include "Renderer.h"
#include "../base/Logger.h"
@@ -33,12 +33,12 @@ namespace kiwano
return iter->second;
}
- _Ty image;
- if (image.Load(path))
+ _Ty texture;
+ if (texture.Load(path))
{
- cache.insert(std::make_pair(hash, image));
+ cache.insert(std::make_pair(hash, texture));
}
- return image;
+ return texture;
}
template
@@ -51,58 +51,58 @@ namespace kiwano
}
}
- ImageCache::ImageCache()
+ TextureCache::TextureCache()
{
}
- ImageCache::~ImageCache()
+ TextureCache::~TextureCache()
{
}
- Image ImageCache::AddOrGetImage(String const& file_path)
+ Texture TextureCache::AddOrGetTexture(String const& file_path)
{
- return CreateOrGetCache(image_cache_, file_path, file_path.hash());
+ return CreateOrGetCache(texture_cache_, file_path, file_path.hash());
}
- Image ImageCache::AddOrGetImage(Resource const& res)
+ Texture TextureCache::AddOrGetTexture(Resource const& res)
{
- return CreateOrGetCache(image_cache_, res, res.GetId());
+ return CreateOrGetCache(texture_cache_, res, res.GetId());
}
- GifImage ImageCache::AddOrGetGifImage(String const& file_path)
+ GifImage TextureCache::AddOrGetGifImage(String const& file_path)
{
- return CreateOrGetCache(gif_image_cache_, file_path, file_path.hash());
+ return CreateOrGetCache(gif_texture_cache_, file_path, file_path.hash());
}
- GifImage ImageCache::AddOrGetGifImage(Resource const& res)
+ GifImage TextureCache::AddOrGetGifImage(Resource const& res)
{
- return CreateOrGetCache(gif_image_cache_, res, res.GetId());
+ return CreateOrGetCache(gif_texture_cache_, res, res.GetId());
}
- void ImageCache::RemoveImage(String const& file_path)
+ void TextureCache::RemoveTexture(String const& file_path)
{
- RemoveCache(image_cache_, file_path.hash());
+ RemoveCache(texture_cache_, file_path.hash());
}
- void ImageCache::RemoveImage(Resource const& res)
+ void TextureCache::RemoveTexture(Resource const& res)
{
- RemoveCache(image_cache_, res.GetId());
+ RemoveCache(texture_cache_, res.GetId());
}
- void ImageCache::RemoveGifImage(String const& file_path)
+ void TextureCache::RemoveGifImage(String const& file_path)
{
- RemoveCache(gif_image_cache_, file_path.hash());
+ RemoveCache(gif_texture_cache_, file_path.hash());
}
- void ImageCache::RemoveGifImage(Resource const& res)
+ void TextureCache::RemoveGifImage(Resource const& res)
{
- RemoveCache(gif_image_cache_, res.GetId());
+ RemoveCache(gif_texture_cache_, res.GetId());
}
- void ImageCache::Clear()
+ void TextureCache::Clear()
{
- image_cache_.clear();
- gif_image_cache_.clear();
+ texture_cache_.clear();
+ gif_texture_cache_.clear();
}
}
diff --git a/src/kiwano/renderer/ImageCache.h b/src/kiwano/renderer/TextureCache.h
similarity index 75%
rename from src/kiwano/renderer/ImageCache.h
rename to src/kiwano/renderer/TextureCache.h
index e4a07abe..352f9ca4 100644
--- a/src/kiwano/renderer/ImageCache.h
+++ b/src/kiwano/renderer/TextureCache.h
@@ -19,39 +19,39 @@
// THE SOFTWARE.
#pragma once
-#include "Image.h"
+#include "Texture.h"
#include "GifImage.h"
namespace kiwano
{
- class KGE_API ImageCache
- : public Singleton
+ class KGE_API TextureCache
+ : public Singleton
{
- KGE_DECLARE_SINGLETON(ImageCache);
+ KGE_DECLARE_SINGLETON(TextureCache);
public:
- Image AddOrGetImage(String const& file_path);
- Image AddOrGetImage(Resource const& res);
+ Texture AddOrGetTexture(String const& file_path);
+ Texture AddOrGetTexture(Resource const& res);
GifImage AddOrGetGifImage(String const& file_path);
GifImage AddOrGetGifImage(Resource const& res);
- void RemoveImage(String const& file_path);
- void RemoveImage(Resource const& res);
+ void RemoveTexture(String const& file_path);
+ void RemoveTexture(Resource const& res);
void RemoveGifImage(String const& file_path);
void RemoveGifImage(Resource const& res);
void Clear();
protected:
- ImageCache();
+ TextureCache();
- virtual ~ImageCache();
+ virtual ~TextureCache();
protected:
- using ImageMap = UnorderedMap;
- ImageMap image_cache_;
+ using TextureMap = UnorderedMap;
+ TextureMap texture_cache_;
using GifImageMap = UnorderedMap;
- GifImageMap gif_image_cache_;
+ GifImageMap gif_texture_cache_;
};
}
diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp
index a4cf4834..8a90e67e 100644
--- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp
+++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp
@@ -20,7 +20,6 @@
#include "D2DDeviceResources.h"
#include "../../base/Logger.h"
-#include "../../utils/FileUtil.h"
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "dwrite.lib")
@@ -38,14 +37,30 @@ namespace kiwano
HRESULT CreateDeviceIndependentResources();
public:
- HRESULT CreateBitmapFromFile(
- _Out_ ComPtr& bitmap,
- _In_ String const& file_path
+ HRESULT CreateBitmapConverter(
+ _Out_ ComPtr& converter,
+ _In_opt_ ComPtr source,
+ _In_ REFWICPixelFormatGUID format,
+ WICBitmapDitherType dither,
+ _In_opt_ ComPtr palette,
+ double alpha_threshold_percent,
+ WICBitmapPaletteType palette_translate
) override;
- HRESULT CreateBitmapFromResource(
+ HRESULT CreateBitmapFromConverter(
_Out_ ComPtr& bitmap,
- _In_ Resource const& res
+ _In_opt_ const D2D1_BITMAP_PROPERTIES* properties,
+ _In_ ComPtr converter
+ ) override;
+
+ HRESULT CreateBitmapDecoderFromFile(
+ _Out_ ComPtr& decoder,
+ const String& file_path
+ ) override;
+
+ HRESULT CreateBitmapDecoderFromResource(
+ _Out_ ComPtr& decoder,
+ const Resource& resource
) override;
HRESULT CreateTextFormat(
@@ -56,7 +71,6 @@ namespace kiwano
HRESULT CreateTextLayout(
_Out_ ComPtr& text_layout,
_In_ String const& text,
- _In_ TextStyle const& text_style,
_In_ ComPtr const& text_format
) const override;
@@ -68,8 +82,6 @@ namespace kiwano
_In_ ComPtr const& target
) override;
- ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const override;
-
void DiscardResources() override;
public:
@@ -85,10 +97,6 @@ namespace kiwano
protected:
unsigned long ref_count_;
Float32 dpi_;
-
- ComPtr d2d_miter_stroke_style_;
- ComPtr d2d_bevel_stroke_style_;
- ComPtr d2d_round_stroke_style_;
};
@@ -195,16 +203,16 @@ namespace kiwano
ComPtr imaging_factory;
ComPtr dwrite_factory;
- D2D1_FACTORY_OPTIONS options;
- ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
-#ifdef KGE_DEBUG
- options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
+ D2D1_FACTORY_OPTIONS config;
+ ZeroMemory(&config, sizeof(D2D1_FACTORY_OPTIONS));
+#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
+ config.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
#endif
hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory1),
- &options,
+ &config,
reinterpret_cast(&d2d_factory)
);
@@ -316,143 +324,113 @@ namespace kiwano
device_context_->SetTarget(target_bitmap_.get());
}
- HRESULT D2DDeviceResources::CreateBitmapFromFile(_Out_ ComPtr & bitmap, _In_ String const & file_path)
+ HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtr& converter, _In_opt_ ComPtr source,
+ _In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither, _In_opt_ ComPtr palette, double alpha_threshold_percent,
+ WICBitmapPaletteType palette_translate
+ )
{
- if (!imaging_factory_ || !device_context_)
+ if (!imaging_factory_)
return E_UNEXPECTED;
- if (!FileUtil::ExistsFile(file_path))
+ ComPtr output;
+ HRESULT hr = imaging_factory_->CreateFormatConverter(&output);
+
+ if (SUCCEEDED(hr))
{
- KGE_WARNING_LOG(L"Image file '%s' not found!", file_path.c_str());
- return E_FAIL;
+ hr = output->Initialize(
+ source.get(),
+ format,
+ dither,
+ palette.get(),
+ alpha_threshold_percent,
+ palette_translate
+ );
}
- ComPtr decoder;
- ComPtr source;
- ComPtr stream;
- ComPtr converter;
- ComPtr bitmap_tmp;
+ if (SUCCEEDED(hr))
+ {
+ converter = output;
+ }
+ return hr;
+ }
+ HRESULT D2DDeviceResources::CreateBitmapFromConverter(_Out_ ComPtr& bitmap, _In_opt_ const D2D1_BITMAP_PROPERTIES* properties,
+ _In_ ComPtr converter)
+ {
+ if (!device_context_)
+ return E_UNEXPECTED;
+
+ ComPtr output;
+ HRESULT hr = device_context_->CreateBitmapFromWicBitmap(
+ converter.get(),
+ properties,
+ &output
+ );
+
+ if (SUCCEEDED(hr))
+ {
+ bitmap = output;
+ }
+ return hr;
+ }
+
+ HRESULT D2DDeviceResources::CreateBitmapDecoderFromFile(_Out_ ComPtr& decoder, const String& file_path)
+ {
+ if (!imaging_factory_)
+ return E_UNEXPECTED;
+
+ ComPtr decoder_output;
HRESULT hr = imaging_factory_->CreateDecoderFromFilename(
file_path.c_str(),
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnLoad,
- &decoder
+ &decoder_output
);
if (SUCCEEDED(hr))
{
- hr = decoder->GetFrame(0, &source);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = imaging_factory_->CreateFormatConverter(&converter);
- }
-
- if (SUCCEEDED(hr))
- {
- // 图片格式转换成 32bppPBGRA
- hr = converter->Initialize(
- source.get(),
- GUID_WICPixelFormat32bppPBGRA,
- WICBitmapDitherTypeNone,
- nullptr,
- 0.f,
- WICBitmapPaletteTypeMedianCut
- );
- }
-
- if (SUCCEEDED(hr))
- {
- hr = device_context_->CreateBitmapFromWicBitmap(
- converter.get(),
- nullptr,
- &bitmap_tmp
- );
- }
-
- if (SUCCEEDED(hr))
- {
- bitmap = bitmap_tmp;
+ decoder = decoder_output;
}
return hr;
}
- HRESULT D2DDeviceResources::CreateBitmapFromResource(_Out_ ComPtr & bitmap, _In_ Resource const & res)
+ HRESULT D2DDeviceResources::CreateBitmapDecoderFromResource(_Out_ ComPtr& decoder, const Resource& resource)
{
- if (!imaging_factory_ || !device_context_)
+ if (!imaging_factory_)
return E_UNEXPECTED;
- ComPtr decoder;
- ComPtr source;
- ComPtr stream;
- ComPtr converter;
- ComPtr bitmap_tmp;
-
- // 加载资源
- Resource::Data res_data = res.GetData();
+ Resource::Data res_data = resource.GetData();
HRESULT hr = res_data ? S_OK : E_FAIL;
if (SUCCEEDED(hr))
{
+ ComPtr stream;
hr = imaging_factory_->CreateStream(&stream);
- }
- if (SUCCEEDED(hr))
- {
- hr = stream->InitializeFromMemory(
- static_cast(res_data.buffer),
- res_data.size
- );
- }
+ if (SUCCEEDED(hr))
+ {
+ hr = stream->InitializeFromMemory(
+ static_cast(res_data.buffer),
+ res_data.size
+ );
+ }
- if (SUCCEEDED(hr))
- {
- hr = imaging_factory_->CreateDecoderFromStream(
- stream.get(),
- nullptr,
- WICDecodeMetadataCacheOnLoad,
- &decoder
- );
- }
+ if (SUCCEEDED(hr))
+ {
+ ComPtr decoder_output;
+ hr = imaging_factory_->CreateDecoderFromStream(
+ stream.get(),
+ nullptr,
+ WICDecodeMetadataCacheOnLoad,
+ &decoder_output
+ );
- if (SUCCEEDED(hr))
- {
- hr = decoder->GetFrame(0, &source);
- }
-
- if (SUCCEEDED(hr))
- {
- hr = imaging_factory_->CreateFormatConverter(&converter);
- }
-
- if (SUCCEEDED(hr))
- {
- // 图片格式转换成 32bppPBGRA
- hr = converter->Initialize(
- source.get(),
- GUID_WICPixelFormat32bppPBGRA,
- WICBitmapDitherTypeNone,
- nullptr,
- 0.f,
- WICBitmapPaletteTypeMedianCut
- );
- }
-
- if (SUCCEEDED(hr))
- {
- hr = device_context_->CreateBitmapFromWicBitmap(
- converter.get(),
- nullptr,
- &bitmap_tmp
- );
- }
-
- if (SUCCEEDED(hr))
- {
- bitmap = bitmap_tmp;
+ if (SUCCEEDED(hr))
+ {
+ decoder = decoder_output;
+ }
+ }
}
return hr;
}
@@ -470,7 +448,7 @@ namespace kiwano
font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
font.size,
- L"en-us",
+ L"",
&output
);
@@ -481,95 +459,21 @@ namespace kiwano
return hr;
}
- HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr & text_layout, _In_ String const & text,
- _In_ TextStyle const & text_style, _In_ ComPtr const& text_format) const
+ HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr& text_layout, _In_ String const& text,
+ _In_ ComPtr const& text_format) const
{
if (!dwrite_factory_)
return E_UNEXPECTED;
- HRESULT hr;
ComPtr output;
- UInt32 length = static_cast(text.length());
-
- if (text_style.wrap_width > 0)
- {
- hr = dwrite_factory_->CreateTextLayout(
- text.c_str(),
- length,
- text_format.get(),
- text_style.wrap_width,
- 0,
- &output
- );
- }
- else
- {
- hr = dwrite_factory_->CreateTextLayout(
- text.c_str(),
- length,
- text_format.get(),
- 0,
- 0,
- &output
- );
- }
-
- if (SUCCEEDED(hr))
- {
- if (text_style.line_spacing == 0.f)
- {
- hr = output->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
- }
- else
- {
- hr = output->SetLineSpacing(
- DWRITE_LINE_SPACING_METHOD_UNIFORM,
- text_style.line_spacing,
- text_style.line_spacing * 0.8f
- );
- }
- }
-
- if (SUCCEEDED(hr))
- {
- hr = output->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(text_style.alignment));
- }
-
- if (SUCCEEDED(hr))
- {
- hr = output->SetWordWrapping((text_style.wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
- }
-
- if (SUCCEEDED(hr))
- {
- if (text_style.underline)
- {
- hr = output->SetUnderline(true, { 0, length });
- }
- }
-
- if (SUCCEEDED(hr))
- {
- if (text_style.strikethrough)
- {
- output->SetStrikethrough(true, { 0, length });
- }
- }
-
- 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);
- }
- }
- }
+ HRESULT hr = dwrite_factory_->CreateTextLayout(
+ text.c_str(),
+ static_cast(text.length()),
+ text_format.get(),
+ 0,
+ 0,
+ &output
+ );
if (SUCCEEDED(hr))
{
@@ -578,15 +482,4 @@ namespace kiwano
return hr;
}
- ID2D1StrokeStyle* D2DDeviceResources::GetStrokeStyle(StrokeStyle stroke) const
- {
- switch (stroke)
- {
- case StrokeStyle::Miter: return d2d_miter_stroke_style_.get(); break;
- case StrokeStyle::Bevel: return d2d_bevel_stroke_style_.get(); break;
- case StrokeStyle::Round: return d2d_round_stroke_style_.get(); break;
- }
- return nullptr;
- }
-
}
diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.h b/src/kiwano/renderer/win32/D2DDeviceResources.h
index c3c73a24..5c117a29 100644
--- a/src/kiwano/renderer/win32/D2DDeviceResources.h
+++ b/src/kiwano/renderer/win32/D2DDeviceResources.h
@@ -189,14 +189,30 @@ namespace kiwano
public:
static HRESULT Create(ID2DDeviceResources** device_resources);
- virtual HRESULT CreateBitmapFromFile(
- _Out_ ComPtr& bitmap,
- _In_ String const& file_path
+ virtual HRESULT CreateBitmapConverter(
+ _Out_ ComPtr& converter,
+ _In_opt_ ComPtr source,
+ _In_ REFWICPixelFormatGUID format,
+ WICBitmapDitherType dither,
+ _In_opt_ ComPtr palette,
+ double alpha_threshold_percent,
+ WICBitmapPaletteType palette_translate
) = 0;
- virtual HRESULT CreateBitmapFromResource(
+ virtual HRESULT CreateBitmapFromConverter(
_Out_ ComPtr& bitmap,
- _In_ Resource const& res
+ _In_opt_ const D2D1_BITMAP_PROPERTIES* properties,
+ _In_ ComPtr converter
+ ) = 0;
+
+ virtual HRESULT CreateBitmapDecoderFromFile(
+ _Out_ ComPtr& decoder,
+ const String& file_path
+ ) = 0;
+
+ virtual HRESULT CreateBitmapDecoderFromResource(
+ _Out_ ComPtr& decoder,
+ const Resource& resource
) = 0;
virtual HRESULT CreateTextFormat(
@@ -207,12 +223,9 @@ namespace kiwano
virtual HRESULT CreateTextLayout(
_Out_ ComPtr& text_layout,
_In_ String const& text,
- _In_ TextStyle const& text_style,
_In_ ComPtr const& text_format
) const = 0;
- virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0;
-
virtual HRESULT SetD2DDevice(
_In_ ComPtr const& device
) = 0;
@@ -230,6 +243,10 @@ namespace kiwano
inline ID2D1DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.get(); }
inline ID2D1Bitmap1* GetTargetBitmap() const { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); }
+ inline ID2D1StrokeStyle* GetMiterStrokeStyle() const { KGE_ASSERT(d2d_miter_stroke_style_); return d2d_miter_stroke_style_.get(); }
+ inline ID2D1StrokeStyle* GetBevelStrokeStyle() const { KGE_ASSERT(d2d_bevel_stroke_style_); return d2d_bevel_stroke_style_.get(); }
+ inline ID2D1StrokeStyle* GetRoundStrokeStyle() const { KGE_ASSERT(d2d_round_stroke_style_); return d2d_round_stroke_style_.get(); }
+
protected:
ComPtr factory_;
ComPtr device_;
@@ -238,6 +255,10 @@ namespace kiwano
ComPtr imaging_factory_;
ComPtr dwrite_factory_;
+
+ ComPtr d2d_miter_stroke_style_;
+ ComPtr d2d_bevel_stroke_style_;
+ ComPtr d2d_round_stroke_style_;
};
}
diff --git a/src/kiwano/renderer/win32/D3D10DeviceResources.cpp b/src/kiwano/renderer/win32/D3D10DeviceResources.cpp
index 9278893c..59e4dfbe 100644
--- a/src/kiwano/renderer/win32/D3D10DeviceResources.cpp
+++ b/src/kiwano/renderer/win32/D3D10DeviceResources.cpp
@@ -217,7 +217,7 @@ namespace kiwano
// than the API default. It is required for compatibility with Direct2D.
UInt32 creation_flags = D3D10_CREATE_DEVICE_BGRA_SUPPORT;
-#if defined(KGE_DEBUG)
+#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
if (DX::SdkLayersAvailable())
{
creation_flags |= D3D10_CREATE_DEVICE_DEBUG;
diff --git a/src/kiwano/renderer/win32/D3D11DeviceResources.cpp b/src/kiwano/renderer/win32/D3D11DeviceResources.cpp
index 801ce3bb..11e64378 100644
--- a/src/kiwano/renderer/win32/D3D11DeviceResources.cpp
+++ b/src/kiwano/renderer/win32/D3D11DeviceResources.cpp
@@ -209,7 +209,7 @@ namespace kiwano
// than the API default. It is required for compatibility with Direct2D.
UInt32 creation_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
-#if defined(KGE_DEBUG)
+#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
if (DX::SdkLayersAvailable())
{
creation_flags |= D3D11_CREATE_DEVICE_DEBUG;
diff --git a/src/kiwano/ui/Button.cpp b/src/kiwano/ui/Button.cpp
index 9108b090..b91b67c4 100644
--- a/src/kiwano/ui/Button.cpp
+++ b/src/kiwano/ui/Button.cpp
@@ -112,7 +112,7 @@ namespace kiwano
if (evt.type == Event::MouseHover)
{
SetStatus(Status::Hover);
- Window::GetInstance()->SetMouseCursor(MouseCursor::Hand);
+ Window::GetInstance()->SetCursor(CursorType::Hand);
if (mouse_over_callback_)
mouse_over_callback_();
@@ -120,7 +120,7 @@ namespace kiwano
else if (evt.type == Event::MouseOut)
{
SetStatus(Status::Normal);
- Window::GetInstance()->SetMouseCursor(MouseCursor::Arrow);
+ Window::GetInstance()->SetCursor(CursorType::Arrow);
if (mouse_out_callback_)
mouse_out_callback_();
diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp
index 43dd40ff..7a8b8a67 100644
--- a/src/kiwano/utils/ResourceCache.cpp
+++ b/src/kiwano/utils/ResourceCache.cpp
@@ -23,6 +23,7 @@
#include "../2d/Frame.h"
#include "../2d/FrameSequence.h"
#include "../renderer/GifImage.h"
+#include "../renderer/FontCollection.h"
#include
namespace kiwano
@@ -30,7 +31,7 @@ namespace kiwano
namespace __resource_cache_01
{
bool LoadJsonData(ResourceCache* loader, Json const& json_data);
- bool LoadXmlData(ResourceCache* loader, tinyxml2::XMLElement* elem);
+ bool LoadXmlData(ResourceCache* loader, const tinyxml2::XMLElement* elem);
}
namespace
@@ -40,7 +41,7 @@ namespace kiwano
{ L"0.1", __resource_cache_01::LoadJsonData },
};
- Map> load_xml_funcs = {
+ Map> load_xml_funcs = {
{ L"latest", __resource_cache_01::LoadXmlData },
{ L"0.1", __resource_cache_01::LoadXmlData },
};
@@ -138,7 +139,7 @@ namespace kiwano
return LoadFromXml(&doc);
}
- bool ResourceCache::LoadFromXml(tinyxml2::XMLDocument* doc)
+ bool ResourceCache::LoadFromXml(const tinyxml2::XMLDocument* doc)
{
if (doc)
{
@@ -201,8 +202,8 @@ namespace kiwano
if (files.empty())
return 0;
- Vector image_arr;
- image_arr.reserve(files.size());
+ Vector frames;
+ frames.reserve(files.size());
for (const auto& file : files)
{
@@ -211,20 +212,20 @@ namespace kiwano
{
if (ptr->Load(file))
{
- image_arr.push_back(ptr);
+ frames.push_back(ptr);
}
}
}
- if (!image_arr.empty())
+ if (!frames.empty())
{
- FrameSequencePtr frames = new (std::nothrow) FrameSequence(image_arr);
- return AddFrameSequence(id, frames);
+ FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames);
+ return AddFrameSequence(id, fs);
}
return 0;
}
- UInt32 ResourceCache::AddFrameSequence(String const & id, String const& file_path, Int32 cols, Int32 rows)
+ UInt32 ResourceCache::AddFrameSequence(String const & id, String const& file_path, Int32 cols, Int32 rows, Float32 padding_x, Float32 padding_y)
{
if (cols <= 0 || rows <= 0)
return 0;
@@ -235,27 +236,31 @@ namespace kiwano
Float32 raw_width = raw->GetWidth();
Float32 raw_height = raw->GetHeight();
- Float32 width = raw_width / cols;
- Float32 height = raw_height / rows;
+ Float32 width = (raw_width - (cols - 1) * padding_x) / cols;
+ Float32 height = (raw_height - (rows - 1) * padding_y) / rows;
- Vector image_arr;
- image_arr.reserve(rows * cols);
+ Vector frames;
+ frames.reserve(rows * cols);
+ Float32 dty = 0;
for (Int32 i = 0; i < rows; i++)
{
+ Float32 dtx = 0;
for (Int32 j = 0; j < cols; j++)
{
- FramePtr ptr = new (std::nothrow) Frame(raw->GetImage());
+ FramePtr ptr = new (std::nothrow) Frame(raw->GetTexture());
if (ptr)
{
- ptr->SetCropRect(Rect{ j * width, i * height, (j + 1) * width, (i + 1) * height });
- image_arr.push_back(ptr);
+ ptr->SetCropRect(Rect{ dtx, dty, dtx + width, dty + height });
+ frames.push_back(ptr);
}
+ dtx += (width + padding_x);
}
+ dty += (height + padding_y);
}
- FrameSequencePtr frames = new (std::nothrow) FrameSequence(image_arr);
- return AddFrameSequence(id, frames);
+ FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames);
+ return AddFrameSequence(id, fs);
}
UInt32 ResourceCache::AddFrameSequence(String const & id, FrameSequencePtr frames)
@@ -278,6 +283,36 @@ namespace kiwano
return false;
}
+ bool ResourceCache::AddGifImage(String const& id, GifImage const& gif)
+ {
+ if (gif.IsValid())
+ {
+ gif_cache_.insert(std::make_pair(id, gif));
+ return true;
+ }
+ return false;
+ }
+
+ bool ResourceCache::AddGifImage(String const& id, String const& file_path)
+ {
+ GifImage gif;
+ if (gif.Load(file_path))
+ {
+ return AddGifImage(id, gif);
+ }
+ return false;
+ }
+
+ bool ResourceCache::AddFontCollection(String const& id, FontCollection const& collection)
+ {
+ if (collection.IsValid())
+ {
+ font_collection_cache_.insert(std::make_pair(id, collection));
+ return true;
+ }
+ return false;
+ }
+
FramePtr ResourceCache::GetFrame(String const & id) const
{
return Get(id);
@@ -288,6 +323,22 @@ namespace kiwano
return Get(id);
}
+ GifImage ResourceCache::GetGifImage(String const& id) const
+ {
+ auto iter = gif_cache_.find(id);
+ if (iter != gif_cache_.end())
+ return iter->second;
+ return GifImage();
+ }
+
+ FontCollection ResourceCache::GetFontCollection(String const& id) const
+ {
+ auto iter = font_collection_cache_.find(id);
+ if (iter != font_collection_cache_.end())
+ return iter->second;
+ return FontCollection();
+ }
+
void ResourceCache::Delete(String const & id)
{
cache_.erase(id);
@@ -309,28 +360,28 @@ namespace kiwano
String path;
};
- bool LoadImagesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* type,
- const String* file, const Vector* files, Int32 rows, Int32 cols)
+ bool LoadTexturesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* type, const String* file)
{
if (!gdata || !id) return false;
- if (file)
+ if (type && (*type) == L"gif")
{
- if (!(*file).empty())
- {
- if (rows || cols)
- {
- // Frame slices
- return !!loader->AddFrameSequence(*id, gdata->path + (*file), std::max(cols, 1), std::max(rows, 1));
- }
- else
- {
- // Simple image
- return loader->AddFrame(*id, gdata->path + (*file));
- }
- }
+ // GIF image
+ return loader->AddGifImage(*id, gdata->path + (*file));
}
+ if (file && !(*file).empty())
+ {
+ // Simple image
+ return loader->AddFrame(*id, gdata->path + (*file));
+ }
+ return false;
+ }
+
+ bool LoadTexturesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const Vector* files)
+ {
+ if (!gdata || !id) return false;
+
// Frames
if (files)
{
@@ -350,6 +401,52 @@ namespace kiwano
return false;
}
+ bool LoadTexturesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* file,
+ Int32 rows, Int32 cols, Float32 padding_x, Float32 padding_y)
+ {
+ if (!gdata || !id) return false;
+
+ if (file)
+ {
+ if (!(*file).empty())
+ {
+ if (rows || cols)
+ {
+ // Frame slices
+ return !!loader->AddFrameSequence(*id, gdata->path + (*file), std::max(cols, 1), std::max(rows, 1), padding_x, padding_y);
+ }
+ else
+ {
+ // Simple image
+ return loader->AddFrame(*id, gdata->path + (*file));
+ }
+ }
+ }
+ return false;
+ }
+
+ bool LoadFontsFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const Vector* files)
+ {
+ if (!gdata || !id) return false;
+
+ // Font Collection
+ if (files)
+ {
+ Vector files_copy(*files);
+ for (auto& file : files_copy)
+ {
+ file = gdata->path + file;
+ }
+
+ FontCollection collection;
+ if (collection.Load(files_copy))
+ {
+ return loader->AddFontCollection(*id, collection);
+ }
+ }
+ return false;
+ }
+
bool LoadJsonData(ResourceCache* loader, Json const& json_data)
{
GlobalData global_data;
@@ -371,6 +468,16 @@ namespace kiwano
if (image.count(L"rows")) rows = image[L"rows"].as_int();
if (image.count(L"cols")) cols = image[L"cols"].as_int();
+ if (rows || cols)
+ {
+ Float32 padding_x = 0, padding_y = 0;
+ if (image.count(L"padding-x")) padding_x = image[L"padding-x"].get();
+ if (image.count(L"padding-y")) padding_y = image[L"padding-y"].get();
+
+ if (!LoadTexturesFromData(loader, &global_data, id, file, rows, cols, padding_x, padding_y))
+ return false;
+ }
+
if (image.count(L"files"))
{
Vector files;
@@ -379,12 +486,33 @@ namespace kiwano
{
files.push_back(file.as_string().c_str());
}
- if (!LoadImagesFromData(loader, &global_data, id, type, file, &files, rows, cols))
+ if(!LoadTexturesFromData(loader, &global_data, id, &files))
return false;
}
else
{
- if (!LoadImagesFromData(loader, &global_data, id, type, file, nullptr, rows, cols))
+ if(!LoadTexturesFromData(loader, &global_data, id, type, file))
+ return false;
+ }
+ }
+ }
+
+ if (json_data.count(L"fonts"))
+ {
+ for (const auto& font : json_data[L"fonts"])
+ {
+ String id;
+
+ if (font.count(L"id")) id = font[L"id"].as_string();
+ if (font.count(L"files"))
+ {
+ Vector files;
+ files.reserve(font[L"files"].size());
+ for (const auto& file : font[L"files"])
+ {
+ files.push_back(file.as_string());
+ }
+ if (!LoadFontsFromData(loader, &global_data, &id, &files))
return false;
}
}
@@ -392,7 +520,7 @@ namespace kiwano
return true;
}
- bool LoadXmlData(ResourceCache* loader, tinyxml2::XMLElement* elem)
+ bool LoadXmlData(ResourceCache* loader, const tinyxml2::XMLElement* elem)
{
GlobalData global_data;
if (auto path = elem->FirstChildElement(L"path"))
@@ -413,6 +541,16 @@ namespace kiwano
if (auto attr = image->IntAttribute(L"rows")) rows = attr;
if (auto attr = image->IntAttribute(L"cols")) cols = attr;
+ if (rows || cols)
+ {
+ Float32 padding_x = 0, padding_y = 0;
+ if (auto attr = image->FloatAttribute(L"padding-x")) padding_x = attr;
+ if (auto attr = image->FloatAttribute(L"padding-y")) padding_y = attr;
+
+ if (!LoadTexturesFromData(loader, &global_data, &id, &file, rows, cols, padding_x, padding_y))
+ return false;
+ }
+
if (file.empty() && !image->NoChildren())
{
Vector files_arr;
@@ -423,16 +561,36 @@ namespace kiwano
files_arr.push_back(path);
}
}
- if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols))
+ if (!LoadTexturesFromData(loader, &global_data, &id, &files_arr))
return false;
}
else
{
- if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, nullptr, rows, cols))
+ if (!LoadTexturesFromData(loader, &global_data, &id, &type, &file))
return false;
}
}
}
+
+ if (auto fonts = elem->FirstChildElement(L"fonts"))
+ {
+ for (auto font = fonts->FirstChildElement(); font; font = font->NextSiblingElement())
+ {
+ String id;
+ if (auto attr = font->Attribute(L"id")) id.assign(attr);
+
+ Vector files_arr;
+ for (auto file = font->FirstChildElement(); file; file = file->NextSiblingElement())
+ {
+ if (auto path = file->Attribute(L"path"))
+ {
+ files_arr.push_back(path);
+ }
+ }
+ if (!LoadFontsFromData(loader, &global_data, &id, &files_arr))
+ return false;
+ }
+ }
return true;
}
}
diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h
index 8a87c072..1a6252c7 100644
--- a/src/kiwano/utils/ResourceCache.h
+++ b/src/kiwano/utils/ResourceCache.h
@@ -44,7 +44,7 @@ namespace kiwano
bool LoadFromXmlFile(String const& file_path);
// 从 XML 文档对象加载资源信息
- bool LoadFromXml(tinyxml2::XMLDocument* doc);
+ bool LoadFromXml(const tinyxml2::XMLDocument* doc);
// 添加帧图像
bool AddFrame(String const& id, String const& file_path);
@@ -57,7 +57,7 @@ namespace kiwano
// 添加序列帧
// 按行列数裁剪图片
- UInt32 AddFrameSequence(String const& id, String const& file_path, Int32 cols, Int32 rows = 1);
+ UInt32 AddFrameSequence(String const& id, String const& file_path, Int32 cols, Int32 rows = 1, Float32 padding_x = 0, Float32 padding_y = 0);
// 添加序列帧
UInt32 AddFrameSequence(String const& id, FrameSequencePtr frames);
@@ -65,12 +65,27 @@ namespace kiwano
// 添加对象
bool AddObjectBase(String const& id, ObjectBasePtr obj);
+ // 添加 GIF 图像
+ bool AddGifImage(String const& id, GifImage const& gif);
+
+ // 添加 GIF 图像
+ bool AddGifImage(String const& id, String const& file_path);
+
+ // 添加字体集
+ bool AddFontCollection(String const& id, FontCollection const& collection);
+
// 获取帧图像
FramePtr GetFrame(String const& id) const;
// 获取序列帧
FrameSequencePtr GetFrameSequence(String const& id) const;
+ // 获取 GIF 图像
+ GifImage GetGifImage(String const& id) const;
+
+ // 获取字体集
+ FontCollection GetFontCollection(String const& id) const;
+
// 删除指定资源
void Delete(String const& id);
@@ -93,5 +108,8 @@ namespace kiwano
protected:
UnorderedMap cache_;
+
+ UnorderedMap gif_cache_;
+ UnorderedMap font_collection_cache_;
};
}