From 7039d00e61f8e91daa41303502f53acba1c8b505 Mon Sep 17 00:00:00 2001 From: Nomango Date: Wed, 21 Aug 2019 12:47:19 +0800 Subject: [PATCH 1/8] minor --- src/kiwano/renderer/RenderTarget.cpp | 39 +++++++++++++++---- src/kiwano/renderer/RenderTarget.h | 8 +++- src/kiwano/renderer/Renderer.cpp | 2 +- .../renderer/win32/D2DDeviceResources.cpp | 2 +- 4 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp index b516ea77..9e67c782 100644 --- a/src/kiwano/renderer/RenderTarget.cpp +++ b/src/kiwano/renderer/RenderTarget.cpp @@ -31,6 +31,7 @@ namespace kiwano : opacity_(1.f) , collecting_status_(false) , antialias_(true) + , fast_global_transform_(true) , text_antialias_(TextAntialias::GrayScale) { status_.primitives = 0; @@ -537,7 +538,7 @@ namespace kiwano Matrix3x2 RenderTarget::GetGlobalTransform() const { - return global_matrix_; + return global_transform_; } void RenderTarget::SetTransform(const Matrix3x2& matrix) @@ -550,8 +551,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 +568,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) @@ -638,9 +660,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) diff --git a/src/kiwano/renderer/RenderTarget.h b/src/kiwano/renderer/RenderTarget.h index f8c63c5e..59261cda 100644 --- a/src/kiwano/renderer/RenderTarget.h +++ b/src/kiwano/renderer/RenderTarget.h @@ -154,6 +154,10 @@ namespace kiwano const Matrix3x2& matrix ); + void SetGlobalTransform( + const Matrix3x2* matrix + ); + // 设置抗锯齿模式 void SetAntialiasMode( bool enabled @@ -164,6 +168,7 @@ namespace kiwano TextAntialias mode ); + // 检查边界是否在视区内 bool CheckVisibility( Rect const& bounds, Matrix3x2 const& transform @@ -200,6 +205,7 @@ namespace kiwano protected: Float32 opacity_; bool antialias_; + bool fast_global_transform_; mutable bool collecting_status_; mutable Status status_; TextAntialias text_antialias_; @@ -208,7 +214,7 @@ namespace kiwano ComPtr default_brush_; ComPtr current_brush_; ComPtr device_resources_; - Matrix3x2 global_matrix_; + Matrix3x2 global_transform_; }; diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index ccae9a87..a926b7b3 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -732,7 +732,7 @@ namespace kiwano { case ResolutionMode::Fixed: { - SetGlobalTransform(Matrix3x2{}); + SetGlobalTransform(nullptr); break; } diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp index a4cf4834..fc283d9b 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp @@ -470,7 +470,7 @@ namespace kiwano font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL, font.size, - L"en-us", + L"", &output ); From c626697ebf121e48a15da333849289d5ede00ed1 Mon Sep 17 00:00:00 2001 From: Nomango Date: Wed, 21 Aug 2019 16:33:41 +0800 Subject: [PATCH 2/8] Add InterpolationMode --- projects/kiwano.vcxproj | 10 +-- projects/kiwano.vcxproj.filters | 30 ++++---- src/kiwano-imgui/src/ImGuiModule.cpp | 20 ++--- src/kiwano/2d/Canvas.cpp | 20 ++--- src/kiwano/2d/Canvas.h | 12 +-- src/kiwano/2d/Frame.cpp | 32 ++++---- src/kiwano/2d/Frame.h | 26 +++---- src/kiwano/2d/FrameSequence.cpp | 4 +- src/kiwano/2d/GifSprite.cpp | 50 ++++++------- src/kiwano/2d/GifSprite.h | 12 +-- src/kiwano/2d/ShapeActor.h | 1 + src/kiwano/2d/Sprite.cpp | 2 +- src/kiwano/2d/TextStyle.hpp | 1 + src/kiwano/2d/include-forwards.h | 1 - src/kiwano/base/Window.cpp | 22 +++--- src/kiwano/base/Window.h | 22 +++++- src/kiwano/kiwano.h | 4 +- src/kiwano/platform/Application.cpp | 6 +- src/kiwano/renderer/GifImage.cpp | 2 +- src/kiwano/renderer/GifImage.h | 4 +- src/kiwano/renderer/RenderTarget.cpp | 63 ++++++++++------ src/kiwano/renderer/RenderTarget.h | 38 ++++++---- src/kiwano/renderer/Renderer.cpp | 28 +++---- src/kiwano/renderer/Renderer.h | 48 ++++++++---- .../{base/types.h => renderer/StrokeStyle.h} | 33 +-------- .../renderer/{Image.cpp => Texture.cpp} | 73 +++++++++++++------ src/kiwano/renderer/{Image.h => Texture.h} | 55 ++++++++++---- .../{ImageCache.cpp => TextureCache.cpp} | 52 ++++++------- .../renderer/{ImageCache.h => TextureCache.h} | 26 +++---- .../renderer/win32/D2DDeviceResources.cpp | 19 +---- .../renderer/win32/D2DDeviceResources.h | 10 ++- src/kiwano/ui/Button.cpp | 4 +- src/kiwano/utils/ResourceCache.cpp | 70 +++++++++--------- 33 files changed, 434 insertions(+), 366 deletions(-) rename src/kiwano/{base/types.h => renderer/StrokeStyle.h} (70%) rename src/kiwano/renderer/{Image.cpp => Texture.cpp} (63%) rename src/kiwano/renderer/{Image.h => Texture.h} (66%) rename src/kiwano/renderer/{ImageCache.cpp => TextureCache.cpp} (57%) rename src/kiwano/renderer/{ImageCache.h => TextureCache.h} (75%) 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-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/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..fa406a2f 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 @@ -45,41 +45,41 @@ namespace kiwano Load(res); } - GifSprite::GifSprite(GifImage image) + GifSprite::GifSprite(GifImage texture) { - Load(image); + Load(texture); } 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 texture) { - if (image.IsValid()) + if (texture.IsValid()) { - image_ = image; + texture_ = texture; next_index_ = 0; loop_count_ = 0; disposal_type_ = DisposalType::None; - SetSize(Size{ static_cast(image_.GetWidthInPixels()), static_cast(image_.GetHeightInPixels()) }); + SetSize(Size{ static_cast(texture_.GetWidthInPixels()), static_cast(texture_.GetHeightInPixels()) }); if (!frame_rt_.IsValid()) { - Renderer::GetInstance()->CreateImageRenderTarget(frame_rt_); + Renderer::GetInstance()->CreateTextureRenderTarget(frame_rt_); } - if (image_.GetFramesCount() > 0) + if (texture_.GetFramesCount() > 0) { ComposeNextFrame(); } @@ -94,7 +94,7 @@ namespace kiwano { PrepareRender(rt); - rt->DrawImage(frame_); + rt->DrawTexture(frame_); } } @@ -102,7 +102,7 @@ namespace kiwano { Actor::Update(dt); - if (image_.IsValid() && animating_) + if (texture_.IsValid() && animating_) { frame_elapsed_ += dt; if (frame_delay_ <= frame_elapsed_) @@ -132,7 +132,7 @@ namespace kiwano OverlayNextFrame(); } while (frame_delay_.IsZero() && !IsLastFrame()); - animating_ = (!EndOfAnimation() && image_.GetFramesCount() > 1); + animating_ = (!EndOfAnimation() && texture_.GetFramesCount() > 1); } } @@ -163,9 +163,9 @@ namespace kiwano void GifSprite::OverlayNextFrame() { - Image raw_image; + Texture raw_texture; - HRESULT hr = image_.GetRawFrame(next_index_, raw_image, frame_rect_, frame_delay_, disposal_type_); + HRESULT hr = texture_.GetRawFrame(next_index_, raw_texture, frame_rect_, frame_delay_, disposal_type_); if (SUCCEEDED(hr)) { @@ -182,24 +182,24 @@ namespace kiwano if (next_index_ == 0) { // 重新绘制背景 - frame_rt_.Clear(image_.GetBackgroundColor()); + frame_rt_.Clear(texture_.GetBackgroundColor()); loop_count_++; } - frame_rt_.DrawImage(raw_image, nullptr, &frame_rect_); + frame_rt_.DrawTexture(raw_texture, nullptr, &frame_rect_); frame_rt_.EndDraw(); } if (SUCCEEDED(hr)) { - Image frame_to_render = frame_rt_.GetOutput(); + Texture frame_to_render = frame_rt_.GetOutput(); hr = frame_to_render.IsValid() ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { frame_ = frame_to_render; - next_index_ = (++next_index_) % image_.GetFramesCount(); + next_index_ = (++next_index_) % texture_.GetFramesCount(); } } @@ -218,7 +218,7 @@ namespace kiwano 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 +253,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; @@ -271,7 +271,7 @@ namespace kiwano frame_rt_.BeginDraw(); frame_rt_.PushClipRect(frame_rect_); - frame_rt_.Clear(image_.GetBackgroundColor()); + frame_rt_.Clear(texture_.GetBackgroundColor()); frame_rt_.PopClipRect(); return frame_rt_.EndDraw(); diff --git a/src/kiwano/2d/GifSprite.h b/src/kiwano/2d/GifSprite.h index ee94ed99..12f77ac4 100644 --- a/src/kiwano/2d/GifSprite.h +++ b/src/kiwano/2d/GifSprite.h @@ -46,7 +46,7 @@ namespace kiwano ); GifSprite( - GifImage image + GifImage texture ); bool Load( @@ -58,7 +58,7 @@ namespace kiwano ); bool Load( - GifImage image + GifImage texture ); // 设置 GIF 动画循环次数 @@ -108,10 +108,10 @@ namespace kiwano DisposalType disposal_type_; LoopDoneCallback loop_cb_; DoneCallback done_cb_; - GifImage image_; - Image frame_; + GifImage texture_; + Texture frame_; Rect frame_rect_; - Image saved_frame_; - ImageRenderTarget frame_rt_; + 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/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/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..827bf20c 100644 --- a/src/kiwano/base/Window.cpp +++ b/src/kiwano/base/Window.cpp @@ -46,7 +46,7 @@ namespace kiwano , device_name_(nullptr) , is_fullscreen_(false) , resizable_(false) - , mouse_cursor_(MouseCursor::Arrow) + , mouse_cursor_(CursorType::Arrow) { } @@ -222,7 +222,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 +295,7 @@ namespace kiwano } } - void Window::SetMouseCursor(MouseCursor cursor) + void Window::SetCursor(CursorType cursor) { mouse_cursor_ = cursor; } @@ -327,14 +327,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)); } diff --git a/src/kiwano/base/Window.h b/src/kiwano/base/Window.h index b613b941..60befce3 100644 --- a/src/kiwano/base/Window.h +++ b/src/kiwano/base/Window.h @@ -22,10 +22,24 @@ #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, + }; + + + // 窗口 class KGE_API Window : public Singleton { @@ -56,8 +70,8 @@ namespace kiwano // 设置全屏模式 void SetFullscreen(bool fullscreen, Int32 width, Int32 height); - // 设置鼠标指针 - void SetMouseCursor(MouseCursor cursor); + // 设置鼠标指针类型 + void SetCursor(CursorType cursor); public: void Init( @@ -94,6 +108,6 @@ namespace kiwano Int32 width_; Int32 height_; WCHAR* device_name_; - MouseCursor mouse_cursor_; + CursorType mouse_cursor_; }; } 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..57fe2374 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -24,7 +24,7 @@ #include "../base/Logger.h" #include "../base/input.h" #include "../base/Director.h" -#include "../renderer/ImageCache.h" +#include "../renderer/TextureCache.h" #include "../renderer/Renderer.h" #include "../utils/ResourceCache.h" #include // GET_X_LPARAM, GET_Y_LPARAM @@ -150,7 +150,7 @@ namespace kiwano // Clear all resources Director::GetInstance()->ClearStages(); ResourceCache::GetInstance()->Clear(); - ImageCache::GetInstance()->Clear(); + TextureCache::GetInstance()->Clear(); if (inited_) { @@ -166,7 +166,7 @@ namespace kiwano // Destroy all instances Director::DestroyInstance(); ResourceCache::DestroyInstance(); - ImageCache::DestroyInstance(); + TextureCache::DestroyInstance(); Input::DestroyInstance(); Renderer::DestroyInstance(); Window::DestroyInstance(); diff --git a/src/kiwano/renderer/GifImage.cpp b/src/kiwano/renderer/GifImage.cpp index bea8a029..028b6b02 100644 --- a/src/kiwano/renderer/GifImage.cpp +++ b/src/kiwano/renderer/GifImage.cpp @@ -255,7 +255,7 @@ namespace kiwano return hr; } - HRESULT GifImage::GetRawFrame(UInt32 frame_index, Image& raw_frame, Rect& frame_rect, Duration& delay, DisposalType& disposal_type) + HRESULT GifImage::GetRawFrame(UInt32 frame_index, Texture& raw_frame, Rect& frame_rect, Duration& delay, DisposalType& disposal_type) { ComPtr converter; ComPtr wic_frame; diff --git a/src/kiwano/renderer/GifImage.h b/src/kiwano/renderer/GifImage.h index 1e05bc38..55500c8a 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 { @@ -58,7 +58,7 @@ namespace kiwano HRESULT GetRawFrame( UInt32 frame_index, - Image& raw_frame, + Texture& raw_frame, Rect& frame_rect, Duration& delay, DisposalType& disposal_type diff --git a/src/kiwano/renderer/RenderTarget.cpp b/src/kiwano/renderer/RenderTarget.cpp index 9e67c782..6bfe1eed 100644 --- a/src/kiwano/renderer/RenderTarget.cpp +++ b/src/kiwano/renderer/RenderTarget.cpp @@ -30,9 +30,9 @@ namespace kiwano RenderTarget::RenderTarget() : opacity_(1.f) , collecting_status_(false) - , antialias_(true) , fast_global_transform_(true) - , text_antialias_(TextAntialias::GrayScale) + , antialias_(true) + , text_antialias_(TextAntialiasMode::GrayScale) { status_.primitives = 0; } @@ -134,7 +134,7 @@ namespace kiwano geometry.GetGeometry().get(), default_brush_.get(), stroke_width, - device_resources_->GetStrokeStyle(stroke) + GetStrokeStyle(stroke).get() ); IncreasePrimitivesCount(); @@ -180,7 +180,7 @@ namespace kiwano DX::ConvertToPoint2F(point2), default_brush_.get(), stroke_width, - device_resources_->GetStrokeStyle(stroke) + GetStrokeStyle(stroke).get() ); IncreasePrimitivesCount(); @@ -205,7 +205,7 @@ namespace kiwano DX::ConvertToRectF(rect), default_brush_.get(), stroke_width, - device_resources_->GetStrokeStyle(stroke) + GetStrokeStyle(stroke).get() ); IncreasePrimitivesCount(); @@ -254,7 +254,7 @@ namespace kiwano ), default_brush_.get(), stroke_width, - device_resources_->GetStrokeStyle(stroke) + GetStrokeStyle(stroke).get() ); IncreasePrimitivesCount(); @@ -307,7 +307,7 @@ namespace kiwano ), default_brush_.get(), stroke_width, - device_resources_->GetStrokeStyle(stroke) + GetStrokeStyle(stroke).get() ); IncreasePrimitivesCount(); @@ -340,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_) @@ -353,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 ); @@ -385,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() ); } @@ -541,6 +545,17 @@ namespace kiwano 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) { HRESULT hr = S_OK; @@ -623,7 +638,7 @@ namespace kiwano ThrowIfFailed(hr); } - void RenderTarget::SetTextAntialiasMode(TextAntialias mode) + void RenderTarget::SetTextAntialiasMode(TextAntialiasMode mode) { HRESULT hr = S_OK; if (!render_target_) @@ -637,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: @@ -683,14 +698,14 @@ namespace kiwano // - // ImageRenderTarget + // TextureRenderTarget // - ImageRenderTarget::ImageRenderTarget() + TextureRenderTarget::TextureRenderTarget() { } - Image ImageRenderTarget::GetOutput() const + Texture TextureRenderTarget::GetOutput() const { HRESULT hr = E_FAIL; @@ -706,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 59261cda..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; @@ -165,7 +175,7 @@ namespace kiwano // 设置文字抗锯齿模式 void SetTextAntialiasMode( - TextAntialias mode + TextAntialiasMode mode ); // 检查边界是否在视区内 @@ -186,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(); @@ -208,7 +220,7 @@ namespace kiwano 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_; @@ -219,12 +231,12 @@ namespace kiwano // 位图渲染目标 - 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 a926b7b3..795a42b0 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -245,7 +245,7 @@ namespace kiwano return hr; } - void Renderer::CreateImage(Image& image, String const& file_path) + void Renderer::CreateTexture(Texture& texture, String const& file_path) { HRESULT hr = S_OK; if (!d2d_res_) @@ -260,17 +260,17 @@ namespace kiwano if (SUCCEEDED(hr)) { - image.SetBitmap(bitmap); + texture.SetBitmap(bitmap); } } if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr); + KGE_WARNING_LOG(L"Load texture failed with HRESULT of %08X!", hr); } } - void Renderer::CreateImage(Image& image, Resource const& res) + void Renderer::CreateTexture(Texture& texture, Resource const& res) { HRESULT hr = S_OK; if (!d2d_res_) @@ -285,17 +285,17 @@ namespace kiwano if (SUCCEEDED(hr)) { - image.SetBitmap(bitmap); + texture.SetBitmap(bitmap); } } if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr); + KGE_WARNING_LOG(L"Load texture failed with HRESULT of %08X!", hr); } } - void Renderer::CreateGifImage(GifImage& image, String const& file_path) + void Renderer::CreateGifImage(GifImage& texture, String const& file_path) { HRESULT hr = S_OK; if (!d2d_res_) @@ -305,7 +305,7 @@ 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"Gif texture file '%s' not found!", file_path.c_str()); hr = E_FAIL; } @@ -322,17 +322,17 @@ namespace kiwano if (SUCCEEDED(hr)) { - image.SetDecoder(decoder); + texture.SetDecoder(decoder); } } if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr); + KGE_WARNING_LOG(L"Load GIF texture failed with HRESULT of %08X!", hr); } } - void Renderer::CreateGifImage(GifImage& image, Resource const& res) + void Renderer::CreateGifImage(GifImage& texture, Resource const& res) { HRESULT hr = S_OK; if (!d2d_res_) @@ -369,14 +369,14 @@ namespace kiwano if (SUCCEEDED(hr)) { - image.SetDecoder(decoder); + texture.SetDecoder(decoder); } } } if (FAILED(hr)) { - KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr); + KGE_WARNING_LOG(L"Load GIF texture failed with HRESULT of %08X!", hr); } } @@ -653,7 +653,7 @@ namespace kiwano ThrowIfFailed(hr); } - void Renderer::CreateImageRenderTarget(ImageRenderTarget& render_target) + void Renderer::CreateTextureRenderTarget(TextureRenderTarget& render_target) { HRESULT hr = S_OK; if (!d2d_res_) diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index 7e59ff9a..773b0f12 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -39,6 +39,20 @@ namespace kiwano typedef ID3D11DeviceResources ID3DDeviceResources; #endif + // 分辨率模式 + // 分辨率模式决定了将画面渲染到视区上的方式 + // Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认) + // Center (居中): 分辨率不随视区改变, 且画面始终在视区上居中 + // Stretch (拉伸): 分辨率始终随视区等比例拉伸 + // Adaptive (宽高自适应): 分辨率始终保持宽高比, 且尽可能的填充视区, 可能会出现黑色边界 + enum class ResolutionMode + { + Fixed, /* 固定 */ + Center, /* 居中 */ + Stretch, /* 拉伸 */ + Adaptive, /* 宽高自适应 */ + }; + class KGE_API Renderer : public Singleton , public Component @@ -57,24 +71,34 @@ 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, + void CreateTexture( + Texture& texture, Resource const& res ); void CreateGifImage( - GifImage& image, + GifImage& texture, String const& file_path ); void CreateGifImage( - GifImage& image, + GifImage& texture, Resource const& res ); @@ -127,16 +151,8 @@ namespace kiwano GeometrySink& sink ); - void CreateImageRenderTarget( - ImageRenderTarget& render_target - ); - - void SetResolution( - Size const& resolution - ); - - void SetResolutionMode( - ResolutionMode mode + void CreateTextureRenderTarget( + TextureRenderTarget& render_target ); public: 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/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 fc283d9b..b4534e77 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp @@ -68,8 +68,6 @@ namespace kiwano _In_ ComPtr const& target ) override; - ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const override; - void DiscardResources() override; public: @@ -85,10 +83,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_; }; @@ -323,7 +317,7 @@ namespace kiwano if (!FileUtil::ExistsFile(file_path)) { - KGE_WARNING_LOG(L"Image file '%s' not found!", file_path.c_str()); + KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str()); return E_FAIL; } @@ -578,15 +572,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..0994a49b 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.h +++ b/src/kiwano/renderer/win32/D2DDeviceResources.h @@ -211,8 +211,6 @@ namespace kiwano _In_ ComPtr const& text_format ) const = 0; - virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0; - virtual HRESULT SetD2DDevice( _In_ ComPtr const& device ) = 0; @@ -230,6 +228,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 +240,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/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..324c0d69 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -201,8 +201,8 @@ namespace kiwano if (files.empty()) return 0; - Vector image_arr; - image_arr.reserve(files.size()); + Vector texture_arr; + texture_arr.reserve(files.size()); for (const auto& file : files) { @@ -211,14 +211,14 @@ namespace kiwano { if (ptr->Load(file)) { - image_arr.push_back(ptr); + texture_arr.push_back(ptr); } } } - if (!image_arr.empty()) + if (!texture_arr.empty()) { - FrameSequencePtr frames = new (std::nothrow) FrameSequence(image_arr); + FrameSequencePtr frames = new (std::nothrow) FrameSequence(texture_arr); return AddFrameSequence(id, frames); } return 0; @@ -238,23 +238,23 @@ namespace kiwano Float32 width = raw_width / cols; Float32 height = raw_height / rows; - Vector image_arr; - image_arr.reserve(rows * cols); + Vector texture_arr; + texture_arr.reserve(rows * cols); for (Int32 i = 0; i < rows; i++) { 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); + texture_arr.push_back(ptr); } } } - FrameSequencePtr frames = new (std::nothrow) FrameSequence(image_arr); + FrameSequencePtr frames = new (std::nothrow) FrameSequence(texture_arr); return AddFrameSequence(id, frames); } @@ -309,7 +309,7 @@ namespace kiwano String path; }; - bool LoadImagesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* type, + bool LoadTexturesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* type, const String* file, const Vector* files, Int32 rows, Int32 cols) { if (!gdata || !id) return false; @@ -325,7 +325,7 @@ namespace kiwano } else { - // Simple image + // Simple texture return loader->AddFrame(*id, gdata->path + (*file)); } } @@ -358,33 +358,33 @@ namespace kiwano global_data.path = json_data[L"path"]; } - if (json_data.count(L"images")) + if (json_data.count(L"textures")) { - for (const auto& image : json_data[L"images"]) + for (const auto& texture : json_data[L"textures"]) { const String* id = nullptr, * type = nullptr, * file = nullptr; Int32 rows = 0, cols = 0; - if (image.count(L"id")) id = &image[L"id"].as_string(); - if (image.count(L"type")) type = &image[L"type"].as_string(); - if (image.count(L"file")) file = &image[L"file"].as_string(); - if (image.count(L"rows")) rows = image[L"rows"].as_int(); - if (image.count(L"cols")) cols = image[L"cols"].as_int(); + if (texture.count(L"id")) id = &texture[L"id"].as_string(); + if (texture.count(L"type")) type = &texture[L"type"].as_string(); + if (texture.count(L"file")) file = &texture[L"file"].as_string(); + if (texture.count(L"rows")) rows = texture[L"rows"].as_int(); + if (texture.count(L"cols")) cols = texture[L"cols"].as_int(); - if (image.count(L"files")) + if (texture.count(L"files")) { Vector files; - files.reserve(image[L"files"].size()); - for (const auto& file : image[L"files"]) + files.reserve(texture[L"files"].size()); + for (const auto& file : texture[L"files"]) { 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, type, file, &files, rows, cols)) return false; } else { - if (!LoadImagesFromData(loader, &global_data, id, type, file, nullptr, rows, cols)) + if (!LoadTexturesFromData(loader, &global_data, id, type, file, nullptr, rows, cols)) return false; } } @@ -400,35 +400,35 @@ namespace kiwano global_data.path = path->GetText(); } - if (auto images = elem->FirstChildElement(L"images")) + if (auto textures = elem->FirstChildElement(L"textures")) { - for (auto image = images->FirstChildElement(); image; image = image->NextSiblingElement()) + for (auto texture = textures->FirstChildElement(); texture; texture = texture->NextSiblingElement()) { String id, type, file; Int32 rows = 0, cols = 0; - if (auto attr = image->Attribute(L"id")) id.assign(attr); // assign() copies attr content - if (auto attr = image->Attribute(L"type")) type = attr; // operator=() just holds attr pointer - if (auto attr = image->Attribute(L"file")) file = attr; - if (auto attr = image->IntAttribute(L"rows")) rows = attr; - if (auto attr = image->IntAttribute(L"cols")) cols = attr; + if (auto attr = texture->Attribute(L"id")) id.assign(attr); // assign() copies attr content + if (auto attr = texture->Attribute(L"type")) type = attr; // operator=() just holds attr pointer + if (auto attr = texture->Attribute(L"file")) file = attr; + if (auto attr = texture->IntAttribute(L"rows")) rows = attr; + if (auto attr = texture->IntAttribute(L"cols")) cols = attr; - if (file.empty() && !image->NoChildren()) + if (file.empty() && !texture->NoChildren()) { Vector files_arr; - for (auto file = image->FirstChildElement(); file; file = file->NextSiblingElement()) + for (auto file = texture->FirstChildElement(); file; file = file->NextSiblingElement()) { if (auto path = file->Attribute(L"path")) { files_arr.push_back(path); } } - if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols)) + if (!LoadTexturesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols)) return false; } else { - if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, nullptr, rows, cols)) + if (!LoadTexturesFromData(loader, &global_data, &id, &type, &file, nullptr, rows, cols)) return false; } } From 318eeff9c7802f17e2eeed71cd80044cc01b4545 Mon Sep 17 00:00:00 2001 From: Nomango Date: Wed, 21 Aug 2019 16:54:51 +0800 Subject: [PATCH 3/8] minor fixes --- src/kiwano/2d/action/Action.cpp | 2 +- src/kiwano/2d/action/ActionWalk.cpp | 2 +- src/kiwano/2d/action/Animation.cpp | 16 +++-- src/kiwano/config.h | 3 + .../renderer/win32/D2DDeviceResources.cpp | 2 +- .../renderer/win32/D3D10DeviceResources.cpp | 2 +- .../renderer/win32/D3D11DeviceResources.cpp | 2 +- src/kiwano/utils/ResourceCache.cpp | 62 +++++++++---------- 8 files changed, 49 insertions(+), 42 deletions(-) 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/config.h b/src/kiwano/config.h index c93cd824..9d562a56 100644 --- a/src/kiwano/config.h +++ b/src/kiwano/config.h @@ -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/renderer/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp index b4534e77..550fb3f5 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp @@ -191,7 +191,7 @@ namespace kiwano D2D1_FACTORY_OPTIONS options; ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); -#ifdef KGE_DEBUG +#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG) options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; #endif 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/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index 324c0d69..c016d362 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -201,8 +201,8 @@ namespace kiwano if (files.empty()) return 0; - Vector texture_arr; - texture_arr.reserve(files.size()); + Vector frames; + frames.reserve(files.size()); for (const auto& file : files) { @@ -211,15 +211,15 @@ namespace kiwano { if (ptr->Load(file)) { - texture_arr.push_back(ptr); + frames.push_back(ptr); } } } - if (!texture_arr.empty()) + if (!frames.empty()) { - FrameSequencePtr frames = new (std::nothrow) FrameSequence(texture_arr); - return AddFrameSequence(id, frames); + FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames); + return AddFrameSequence(id, fs); } return 0; } @@ -238,8 +238,8 @@ namespace kiwano Float32 width = raw_width / cols; Float32 height = raw_height / rows; - Vector texture_arr; - texture_arr.reserve(rows * cols); + Vector frames; + frames.reserve(rows * cols); for (Int32 i = 0; i < rows; i++) { @@ -249,13 +249,13 @@ namespace kiwano if (ptr) { ptr->SetCropRect(Rect{ j * width, i * height, (j + 1) * width, (i + 1) * height }); - texture_arr.push_back(ptr); + frames.push_back(ptr); } } } - FrameSequencePtr frames = new (std::nothrow) FrameSequence(texture_arr); - return AddFrameSequence(id, frames); + FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames); + return AddFrameSequence(id, fs); } UInt32 ResourceCache::AddFrameSequence(String const & id, FrameSequencePtr frames) @@ -325,7 +325,7 @@ namespace kiwano } else { - // Simple texture + // Simple image return loader->AddFrame(*id, gdata->path + (*file)); } } @@ -358,24 +358,24 @@ namespace kiwano global_data.path = json_data[L"path"]; } - if (json_data.count(L"textures")) + if (json_data.count(L"images")) { - for (const auto& texture : json_data[L"textures"]) + for (const auto& image : json_data[L"images"]) { const String* id = nullptr, * type = nullptr, * file = nullptr; Int32 rows = 0, cols = 0; - if (texture.count(L"id")) id = &texture[L"id"].as_string(); - if (texture.count(L"type")) type = &texture[L"type"].as_string(); - if (texture.count(L"file")) file = &texture[L"file"].as_string(); - if (texture.count(L"rows")) rows = texture[L"rows"].as_int(); - if (texture.count(L"cols")) cols = texture[L"cols"].as_int(); + if (image.count(L"id")) id = &image[L"id"].as_string(); + if (image.count(L"type")) type = &image[L"type"].as_string(); + if (image.count(L"file")) file = &image[L"file"].as_string(); + if (image.count(L"rows")) rows = image[L"rows"].as_int(); + if (image.count(L"cols")) cols = image[L"cols"].as_int(); - if (texture.count(L"files")) + if (image.count(L"files")) { Vector files; - files.reserve(texture[L"files"].size()); - for (const auto& file : texture[L"files"]) + files.reserve(image[L"files"].size()); + for (const auto& file : image[L"files"]) { files.push_back(file.as_string().c_str()); } @@ -400,23 +400,23 @@ namespace kiwano global_data.path = path->GetText(); } - if (auto textures = elem->FirstChildElement(L"textures")) + if (auto images = elem->FirstChildElement(L"images")) { - for (auto texture = textures->FirstChildElement(); texture; texture = texture->NextSiblingElement()) + for (auto image = images->FirstChildElement(); image; image = image->NextSiblingElement()) { String id, type, file; Int32 rows = 0, cols = 0; - if (auto attr = texture->Attribute(L"id")) id.assign(attr); // assign() copies attr content - if (auto attr = texture->Attribute(L"type")) type = attr; // operator=() just holds attr pointer - if (auto attr = texture->Attribute(L"file")) file = attr; - if (auto attr = texture->IntAttribute(L"rows")) rows = attr; - if (auto attr = texture->IntAttribute(L"cols")) cols = attr; + if (auto attr = image->Attribute(L"id")) id.assign(attr); // assign() copies attr content + if (auto attr = image->Attribute(L"type")) type = attr; // operator=() just holds attr pointer + if (auto attr = image->Attribute(L"file")) file = attr; + if (auto attr = image->IntAttribute(L"rows")) rows = attr; + if (auto attr = image->IntAttribute(L"cols")) cols = attr; - if (file.empty() && !texture->NoChildren()) + if (file.empty() && !image->NoChildren()) { Vector files_arr; - for (auto file = texture->FirstChildElement(); file; file = file->NextSiblingElement()) + for (auto file = image->FirstChildElement(); file; file = file->NextSiblingElement()) { if (auto path = file->Attribute(L"path")) { From 92e61ed2979b359b5de2ae40beb80fe2868ba5c6 Mon Sep 17 00:00:00 2001 From: Nomango Date: Wed, 21 Aug 2019 17:31:28 +0800 Subject: [PATCH 4/8] Add padding params in ResourceCache --- src/kiwano/utils/ResourceCache.cpp | 91 +++++++++++++++++++++--------- src/kiwano/utils/ResourceCache.h | 2 +- 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/kiwano/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index c016d362..cdeeea90 100644 --- a/src/kiwano/utils/ResourceCache.cpp +++ b/src/kiwano/utils/ResourceCache.cpp @@ -224,7 +224,7 @@ namespace kiwano 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,23 +235,27 @@ 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 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->GetTexture()); if (ptr) { - ptr->SetCropRect(Rect{ j * width, i * height, (j + 1) * width, (i + 1) * height }); + ptr->SetCropRect(Rect{ dtx, dty, dtx + width, dty + height }); frames.push_back(ptr); } + dtx += (width + padding_x); } + dty += (height + padding_y); } FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames); @@ -309,27 +313,21 @@ namespace kiwano String path; }; - bool LoadTexturesFromData(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 (file && !(*file).empty()) { - 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)); - } - } + // 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 +348,30 @@ 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 LoadJsonData(ResourceCache* loader, Json const& json_data) { GlobalData global_data; @@ -371,6 +393,15 @@ 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(); + + return LoadTexturesFromData(loader, &global_data, id, file, rows, cols, padding_x, padding_y); + } + if (image.count(L"files")) { Vector files; @@ -379,13 +410,11 @@ namespace kiwano { files.push_back(file.as_string().c_str()); } - if (!LoadTexturesFromData(loader, &global_data, id, type, file, &files, rows, cols)) - return false; + return LoadTexturesFromData(loader, &global_data, id, &files); } else { - if (!LoadTexturesFromData(loader, &global_data, id, type, file, nullptr, rows, cols)) - return false; + return LoadTexturesFromData(loader, &global_data, id, type, file); } } } @@ -413,6 +442,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,12 +462,12 @@ namespace kiwano files_arr.push_back(path); } } - if (!LoadTexturesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols)) + if (!LoadTexturesFromData(loader, &global_data, &id, &files_arr)) return false; } else { - if (!LoadTexturesFromData(loader, &global_data, &id, &type, &file, nullptr, rows, cols)) + if (!LoadTexturesFromData(loader, &global_data, &id, &type, &file)) return false; } } diff --git a/src/kiwano/utils/ResourceCache.h b/src/kiwano/utils/ResourceCache.h index 8a87c072..98e6d60b 100644 --- a/src/kiwano/utils/ResourceCache.h +++ b/src/kiwano/utils/ResourceCache.h @@ -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); From 66558a3bc4c7a2ba7f62b24d4ac2c5073cecc4a0 Mon Sep 17 00:00:00 2001 From: Nomango Date: Thu, 22 Aug 2019 17:16:32 +0800 Subject: [PATCH 5/8] ResourceCache supports Font and GifImage --- src/kiwano/2d/Stage.cpp | 4 +- src/kiwano/renderer/Font.cpp | 11 +- src/kiwano/renderer/Font.h | 13 ++- src/kiwano/renderer/FontCollection.cpp | 14 ++- src/kiwano/renderer/FontCollection.h | 2 + src/kiwano/utils/ResourceCache.cpp | 133 +++++++++++++++++++++++-- src/kiwano/utils/ResourceCache.h | 20 +++- 7 files changed, 179 insertions(+), 18 deletions(-) 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/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/utils/ResourceCache.cpp b/src/kiwano/utils/ResourceCache.cpp index cdeeea90..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) { @@ -282,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); @@ -292,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); @@ -317,6 +364,12 @@ namespace kiwano { if (!gdata || !id) return false; + if (type && (*type) == L"gif") + { + // GIF image + return loader->AddGifImage(*id, gdata->path + (*file)); + } + if (file && !(*file).empty()) { // Simple image @@ -372,6 +425,28 @@ namespace kiwano 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; @@ -399,7 +474,8 @@ namespace kiwano 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(); - return LoadTexturesFromData(loader, &global_data, id, file, rows, cols, padding_x, padding_y); + if (!LoadTexturesFromData(loader, &global_data, id, file, rows, cols, padding_x, padding_y)) + return false; } if (image.count(L"files")) @@ -410,18 +486,41 @@ namespace kiwano { files.push_back(file.as_string().c_str()); } - return LoadTexturesFromData(loader, &global_data, id, &files); + if(!LoadTexturesFromData(loader, &global_data, id, &files)) + return false; } else { - return LoadTexturesFromData(loader, &global_data, id, type, file); + 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; } } } 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")) @@ -472,6 +571,26 @@ namespace kiwano } } } + + 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 98e6d60b..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); @@ -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_; }; } From a5fe64fa2c0d4bfd7e0e5c4e2dfda8020b601863 Mon Sep 17 00:00:00 2001 From: Nomango Date: Fri, 23 Aug 2019 13:00:43 +0800 Subject: [PATCH 6/8] Refactor GifImage --- src/kiwano/2d/GifSprite.cpp | 84 ++-- src/kiwano/2d/GifSprite.h | 21 +- src/kiwano/base/Window.cpp | 35 +- src/kiwano/base/Window.h | 30 +- src/kiwano/config.h | 2 +- src/kiwano/platform/Application.cpp | 51 +-- src/kiwano/platform/Application.h | 37 +- src/kiwano/renderer/GifImage.cpp | 370 ++++-------------- src/kiwano/renderer/GifImage.h | 27 +- src/kiwano/renderer/Renderer.cpp | 302 ++++++++++++-- src/kiwano/renderer/Renderer.h | 28 +- .../renderer/win32/D2DDeviceResources.cpp | 217 +++++----- .../renderer/win32/D2DDeviceResources.h | 26 +- 13 files changed, 615 insertions(+), 615 deletions(-) diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp index fa406a2f..7918f955 100644 --- a/src/kiwano/2d/GifSprite.cpp +++ b/src/kiwano/2d/GifSprite.cpp @@ -30,7 +30,6 @@ namespace kiwano , next_index_(0) , total_loop_count_(1) , loop_count_(0) - , disposal_type_(DisposalType::Unknown) { } @@ -45,9 +44,9 @@ namespace kiwano Load(res); } - GifSprite::GifSprite(GifImage texture) + GifSprite::GifSprite(GifImage gif) { - Load(texture); + Load(gif); } bool GifSprite::Load(String const& file_path) @@ -62,24 +61,24 @@ namespace kiwano return Load(texture); } - bool GifSprite::Load(GifImage texture) + bool GifSprite::Load(GifImage gif) { - if (texture.IsValid()) + if (gif.IsValid()) { - texture_ = texture; + gif_ = gif; next_index_ = 0; loop_count_ = 0; - disposal_type_ = DisposalType::None; + frame_.disposal_type = GifImage::DisposalType::None; - SetSize(Size{ static_cast(texture_.GetWidthInPixels()), static_cast(texture_.GetHeightInPixels()) }); + SetSize(Size{ static_cast(gif_.GetWidthInPixels()), static_cast(gif_.GetHeightInPixels()) }); if (!frame_rt_.IsValid()) { Renderer::GetInstance()->CreateTextureRenderTarget(frame_rt_); } - if (texture_.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->DrawTexture(frame_); + rt->DrawTexture(frame_.raw, &frame_.rect, nullptr); } } @@ -102,24 +101,30 @@ namespace kiwano { Actor::Update(dt); - if (texture_.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() && texture_.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() { - Texture raw_texture; - - HRESULT hr = texture_.GetRawFrame(next_index_, raw_texture, 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(texture_.GetBackgroundColor()); loop_count_++; } - frame_rt_.DrawTexture(raw_texture, nullptr, &frame_rect_); + frame_rt_.DrawTexture(frame_.raw, nullptr, &frame_.rect); frame_rt_.EndDraw(); - } - if (SUCCEEDED(hr)) - { Texture frame_to_render = frame_rt_.GetOutput(); - - hr = frame_to_render.IsValid() ? S_OK : E_FAIL; - - if (SUCCEEDED(hr)) + if (frame_to_render.IsValid()) { - frame_ = frame_to_render; - next_index_ = (++next_index_) % texture_.GetFramesCount(); + frame_.raw = frame_to_render; + next_index_ = (++next_index_) % gif_.GetFramesCount(); } } @@ -212,8 +204,6 @@ namespace kiwano { done_cb_(); } - - ThrowIfFailed(hr); } void GifSprite::SaveComposedFrame() @@ -270,8 +260,8 @@ namespace kiwano { frame_rt_.BeginDraw(); - frame_rt_.PushClipRect(frame_rect_); - frame_rt_.Clear(texture_.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 12f77ac4..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 texture + GifImage gif ); bool Load( @@ -58,7 +57,7 @@ namespace kiwano ); bool Load( - GifImage texture + 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,14 +107,11 @@ 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 texture_; - Texture frame_; - Rect frame_rect_; + GifImage gif_; + GifImage::Frame frame_; Texture saved_frame_; TextureRenderTarget frame_rt_; }; diff --git a/src/kiwano/base/Window.cpp b/src/kiwano/base/Window.cpp index 827bf20c..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) @@ -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, @@ -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 60befce3..15b15ad5 100644 --- a/src/kiwano/base/Window.h +++ b/src/kiwano/base/Window.h @@ -38,6 +38,26 @@ namespace kiwano 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 @@ -74,15 +94,7 @@ namespace kiwano 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(); diff --git a/src/kiwano/config.h b/src/kiwano/config.h index 9d562a56..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 diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 57fe2374..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/TextureCache.h" -#include "../renderer/Renderer.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); @@ -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/GifImage.cpp b/src/kiwano/renderer/GifImage.cpp index 028b6b02..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, Texture& 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 55500c8a..339c63f1 100644 --- a/src/kiwano/renderer/GifImage.h +++ b/src/kiwano/renderer/GifImage.h @@ -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, - Texture& 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/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index 795a42b0..6599abd2 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"); @@ -253,14 +265,50 @@ namespace kiwano hr = E_UNEXPECTED; } + if (!FileUtil::ExistsFile(file_path)) + { + KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str()); + hr = E_FAIL; + } + if (SUCCEEDED(hr)) { - ComPtr bitmap; - hr = d2d_res_->CreateBitmapFromFile(bitmap, file_path); + ComPtr decoder; + hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path); if (SUCCEEDED(hr)) { - texture.SetBitmap(bitmap); + 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); + } + } + } } } @@ -270,7 +318,7 @@ namespace kiwano } } - void Renderer::CreateTexture(Texture& texture, Resource const& res) + void Renderer::CreateTexture(Texture& texture, Resource const& resource) { HRESULT hr = S_OK; if (!d2d_res_) @@ -280,12 +328,42 @@ namespace kiwano if (SUCCEEDED(hr)) { - ComPtr bitmap; - hr = d2d_res_->CreateBitmapFromResource(bitmap, res); + ComPtr decoder; + hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource); if (SUCCEEDED(hr)) { - texture.SetBitmap(bitmap); + 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); + } + } + } } } @@ -295,7 +373,7 @@ namespace kiwano } } - void Renderer::CreateGifImage(GifImage& texture, String const& file_path) + void Renderer::CreateGifImage(GifImage& gif, String const& file_path) { HRESULT hr = S_OK; if (!d2d_res_) @@ -312,17 +390,11 @@ namespace kiwano 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)) { - texture.SetDecoder(decoder); + gif.SetDecoder(decoder); } } @@ -332,7 +404,7 @@ namespace kiwano } } - void Renderer::CreateGifImage(GifImage& texture, Resource const& res) + void Renderer::CreateGifImage(GifImage& gif, Resource const& resource) { HRESULT hr = S_OK; if (!d2d_res_) @@ -340,37 +412,14 @@ 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 - ); - - if (SUCCEEDED(hr)) - { - texture.SetDecoder(decoder); - } + gif.SetDecoder(decoder); } } @@ -380,6 +429,173 @@ namespace kiwano } } + 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); + } + } + void Renderer::CreateFontCollection(FontCollection& collection, Vector const& file_paths) { HRESULT hr = S_OK; diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index 773b0f12..8802f593 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -39,6 +39,18 @@ namespace kiwano typedef ID3D11DeviceResources ID3DDeviceResources; #endif + // 渲染设置 + struct RenderConfig + { + Color clear_color; // 清屏颜色 + bool vsync; // 垂直同步 + + RenderConfig( + Color clear_color = Color::Black, + bool vsync = true + ); + }; + // 分辨率模式 // 分辨率模式决定了将画面渲染到视区上的方式 // Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认) @@ -89,17 +101,23 @@ namespace kiwano void CreateTexture( Texture& texture, - Resource const& res + Resource const& resource ); void CreateGifImage( - GifImage& texture, + GifImage& gif, String const& file_path ); void CreateGifImage( - GifImage& texture, - Resource const& res + GifImage& gif, + Resource const& resource + ); + + void CreateGifImageFrame( + GifImage::Frame& frame, + GifImage const& gif, + UInt32 frame_index ); void CreateFontCollection( @@ -156,6 +174,8 @@ namespace kiwano ); public: + void Init(RenderConfig const& config); + void SetupComponent() override; void DestroyComponent() override; diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp index 550fb3f5..ca062b00 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( @@ -189,16 +204,16 @@ namespace kiwano ComPtr imaging_factory; ComPtr dwrite_factory; - D2D1_FACTORY_OPTIONS options; - ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); + D2D1_FACTORY_OPTIONS config; + ZeroMemory(&config, sizeof(D2D1_FACTORY_OPTIONS)); #if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG) - options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; + config.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; #endif hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory1), - &options, + &config, reinterpret_cast(&d2d_factory) ); @@ -310,143 +325,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"Texture 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; } diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.h b/src/kiwano/renderer/win32/D2DDeviceResources.h index 0994a49b..419386ca 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( From 84ede8af45ccbe56b7b5069bc47fe21a342b4b86 Mon Sep 17 00:00:00 2001 From: Nomango Date: Fri, 23 Aug 2019 13:22:21 +0800 Subject: [PATCH 7/8] minor fixes --- src/kiwano-audio/src/Sound.cpp | 10 ++++------ src/kiwano/2d/DebugActor.cpp | 11 ++++++++++- 2 files changed, 14 insertions(+), 7 deletions(-) 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/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()); + } } } From 81503a33c95581f88fc834ea2cd44dbd407cf313 Mon Sep 17 00:00:00 2001 From: Nomango Date: Fri, 23 Aug 2019 17:26:41 +0800 Subject: [PATCH 8/8] update TextLayout --- src/kiwano/2d/Text.cpp | 6 +- src/kiwano/2d/Text.h | 2 +- src/kiwano/renderer/Renderer.cpp | 3 +- src/kiwano/renderer/Renderer.h | 1 - src/kiwano/renderer/TextLayout.cpp | 66 ++++++++++++- .../renderer/win32/D2DDeviceResources.cpp | 95 ++----------------- .../renderer/win32/D2DDeviceResources.h | 1 - 7 files changed, 80 insertions(+), 94 deletions(-) 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/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index 6599abd2..699ba874 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -706,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_) @@ -720,7 +720,6 @@ namespace kiwano hr = d2d_res_->CreateTextLayout( output, text, - style, format.GetTextFormat() ); } diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index 8802f593..4e14f017 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -138,7 +138,6 @@ namespace kiwano void CreateTextLayout( TextLayout& layout, String const& text, - TextStyle const& style, TextFormat const& format ); 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/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp index ca062b00..8a90e67e 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp @@ -71,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; @@ -460,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)) { diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.h b/src/kiwano/renderer/win32/D2DDeviceResources.h index 419386ca..5c117a29 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.h +++ b/src/kiwano/renderer/win32/D2DDeviceResources.h @@ -223,7 +223,6 @@ 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;