[deploy] Merge pull request #37 from KiwanoEngine/dev
Add InterpolationMode && ResourceCache supports Font and GifImage
This commit is contained in:
commit
f202cb2c57
|
|
@ -12,7 +12,6 @@
|
|||
<ClInclude Include="..\src\kiwano\2d\Frame.h" />
|
||||
<ClInclude Include="..\src\kiwano\2d\GifSprite.h" />
|
||||
<ClInclude Include="..\src\kiwano\base\Director.h" />
|
||||
<ClInclude Include="..\src\kiwano\base\types.h" />
|
||||
<ClInclude Include="..\src\kiwano\core\basic_json.hpp" />
|
||||
<ClInclude Include="..\src\kiwano\core\function.hpp" />
|
||||
<ClInclude Include="..\src\kiwano\core\core.h" />
|
||||
|
|
@ -70,8 +69,9 @@
|
|||
<ClInclude Include="..\src\kiwano\renderer\FontCollection.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\Geometry.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\GifImage.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\Image.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\ImageCache.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\StrokeStyle.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\Texture.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\TextureCache.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\LayerArea.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\Renderer.h" />
|
||||
<ClInclude Include="..\src\kiwano\renderer\RenderTarget.h" />
|
||||
|
|
@ -132,8 +132,8 @@
|
|||
<ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\Geometry.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\GifImage.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\Image.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\ImageCache.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\Texture.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\TextureCache.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\LayerArea.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\Renderer.cpp" />
|
||||
<ClCompile Include="..\src\kiwano\renderer\RenderTarget.cpp" />
|
||||
|
|
|
|||
|
|
@ -150,9 +150,6 @@
|
|||
<ClInclude Include="..\src\kiwano\utils\FileUtil.h">
|
||||
<Filter>utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\kiwano\base\types.h">
|
||||
<Filter>base</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\kiwano\2d\GifSprite.h">
|
||||
<Filter>2d</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -258,12 +255,6 @@
|
|||
<ClInclude Include="..\src\kiwano\renderer\GifImage.h">
|
||||
<Filter>renderer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\kiwano\renderer\Image.h">
|
||||
<Filter>renderer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\kiwano\renderer\ImageCache.h">
|
||||
<Filter>renderer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\kiwano\renderer\LayerArea.h">
|
||||
<Filter>renderer</Filter>
|
||||
</ClInclude>
|
||||
|
|
@ -306,6 +297,15 @@
|
|||
<ClInclude Include="..\src\kiwano\2d\Transform.h">
|
||||
<Filter>2d</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\kiwano\renderer\Texture.h">
|
||||
<Filter>renderer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\kiwano\renderer\TextureCache.h">
|
||||
<Filter>renderer</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\src\kiwano\renderer\StrokeStyle.h">
|
||||
<Filter>renderer</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\kiwano\ui\Button.cpp">
|
||||
|
|
@ -443,12 +443,6 @@
|
|||
<ClCompile Include="..\src\kiwano\renderer\GifImage.cpp">
|
||||
<Filter>renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\kiwano\renderer\Image.cpp">
|
||||
<Filter>renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\kiwano\renderer\ImageCache.cpp">
|
||||
<Filter>renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\kiwano\renderer\LayerArea.cpp">
|
||||
<Filter>renderer</Filter>
|
||||
</ClCompile>
|
||||
|
|
@ -482,5 +476,11 @@
|
|||
<ClCompile Include="..\src\kiwano\2d\Transform.cpp">
|
||||
<Filter>2d</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\kiwano\renderer\Texture.cpp">
|
||||
<Filter>renderer</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\src\kiwano\renderer\TextureCache.cpp">
|
||||
<Filter>renderer</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "GifSprite.h"
|
||||
#include "../base/Logger.h"
|
||||
#include "../renderer/ImageCache.h"
|
||||
#include "../renderer/TextureCache.h"
|
||||
#include "../renderer/Renderer.h"
|
||||
|
||||
namespace kiwano
|
||||
|
|
@ -30,7 +30,6 @@ namespace kiwano
|
|||
, next_index_(0)
|
||||
, total_loop_count_(1)
|
||||
, loop_count_(0)
|
||||
, disposal_type_(DisposalType::Unknown)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -45,41 +44,41 @@ namespace kiwano
|
|||
Load(res);
|
||||
}
|
||||
|
||||
GifSprite::GifSprite(GifImage image)
|
||||
GifSprite::GifSprite(GifImage gif)
|
||||
{
|
||||
Load(image);
|
||||
Load(gif);
|
||||
}
|
||||
|
||||
bool GifSprite::Load(String const& file_path)
|
||||
{
|
||||
GifImage image = ImageCache::GetInstance()->AddOrGetGifImage(file_path);
|
||||
return Load(image);
|
||||
GifImage texture = TextureCache::GetInstance()->AddOrGetGifImage(file_path);
|
||||
return Load(texture);
|
||||
}
|
||||
|
||||
bool GifSprite::Load(Resource const& res)
|
||||
{
|
||||
GifImage image = ImageCache::GetInstance()->AddOrGetGifImage(res);
|
||||
return Load(image);
|
||||
GifImage texture = TextureCache::GetInstance()->AddOrGetGifImage(res);
|
||||
return Load(texture);
|
||||
}
|
||||
|
||||
bool GifSprite::Load(GifImage image)
|
||||
bool GifSprite::Load(GifImage gif)
|
||||
{
|
||||
if (image.IsValid())
|
||||
if (gif.IsValid())
|
||||
{
|
||||
image_ = image;
|
||||
gif_ = gif;
|
||||
|
||||
next_index_ = 0;
|
||||
loop_count_ = 0;
|
||||
disposal_type_ = DisposalType::None;
|
||||
frame_.disposal_type = GifImage::DisposalType::None;
|
||||
|
||||
SetSize(Size{ static_cast<Float32>(image_.GetWidthInPixels()), static_cast<Float32>(image_.GetHeightInPixels()) });
|
||||
SetSize(Size{ static_cast<Float32>(gif_.GetWidthInPixels()), static_cast<Float32>(gif_.GetHeightInPixels()) });
|
||||
|
||||
if (!frame_rt_.IsValid())
|
||||
{
|
||||
Renderer::GetInstance()->CreateImageRenderTarget(frame_rt_);
|
||||
Renderer::GetInstance()->CreateTextureRenderTarget(frame_rt_);
|
||||
}
|
||||
|
||||
if (image_.GetFramesCount() > 0)
|
||||
if (gif_.GetFramesCount() > 0)
|
||||
{
|
||||
ComposeNextFrame();
|
||||
}
|
||||
|
|
@ -90,11 +89,11 @@ namespace kiwano
|
|||
|
||||
void GifSprite::OnRender(RenderTarget* rt)
|
||||
{
|
||||
if (frame_.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix()))
|
||||
if (frame_.raw.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix()))
|
||||
{
|
||||
PrepareRender(rt);
|
||||
|
||||
rt->DrawImage(frame_);
|
||||
rt->DrawTexture(frame_.raw, &frame_.rect, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -102,24 +101,30 @@ namespace kiwano
|
|||
{
|
||||
Actor::Update(dt);
|
||||
|
||||
if (image_.IsValid() && animating_)
|
||||
if (gif_.IsValid() && animating_)
|
||||
{
|
||||
frame_elapsed_ += dt;
|
||||
if (frame_delay_ <= frame_elapsed_)
|
||||
if (frame_.delay <= frame_elapsed_)
|
||||
{
|
||||
frame_delay_ -= frame_elapsed_;
|
||||
frame_.delay -= frame_elapsed_;
|
||||
frame_elapsed_ = 0;
|
||||
ComposeNextFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GifSprite::SetGifImage(GifImage const& gif)
|
||||
{
|
||||
gif_ = gif;
|
||||
RestartAnimation();
|
||||
}
|
||||
|
||||
void GifSprite::RestartAnimation()
|
||||
{
|
||||
animating_ = true;
|
||||
next_index_ = 0;
|
||||
loop_count_ = 0;
|
||||
disposal_type_ = DisposalType::None;
|
||||
frame_.disposal_type = GifImage::DisposalType::None;
|
||||
}
|
||||
|
||||
void GifSprite::ComposeNextFrame()
|
||||
|
|
@ -130,27 +135,27 @@ namespace kiwano
|
|||
{
|
||||
DisposeCurrentFrame();
|
||||
OverlayNextFrame();
|
||||
} while (frame_delay_.IsZero() && !IsLastFrame());
|
||||
} while (frame_.delay.IsZero() && !IsLastFrame());
|
||||
|
||||
animating_ = (!EndOfAnimation() && image_.GetFramesCount() > 1);
|
||||
animating_ = (!EndOfAnimation() && gif_.GetFramesCount() > 1);
|
||||
}
|
||||
}
|
||||
|
||||
void GifSprite::DisposeCurrentFrame()
|
||||
{
|
||||
switch (disposal_type_)
|
||||
switch (frame_.disposal_type)
|
||||
{
|
||||
case DisposalType::Unknown:
|
||||
case DisposalType::None:
|
||||
case GifImage::DisposalType::Unknown:
|
||||
case GifImage::DisposalType::None:
|
||||
break;
|
||||
|
||||
case DisposalType::Background:
|
||||
case GifImage::DisposalType::Background:
|
||||
{
|
||||
ClearCurrentFrameArea();
|
||||
break;
|
||||
}
|
||||
|
||||
case DisposalType::Previous:
|
||||
case GifImage::DisposalType::Previous:
|
||||
{
|
||||
RestoreSavedFrame();
|
||||
break;
|
||||
|
|
@ -163,43 +168,30 @@ namespace kiwano
|
|||
|
||||
void GifSprite::OverlayNextFrame()
|
||||
{
|
||||
Image raw_image;
|
||||
Renderer::GetInstance()->CreateGifImageFrame(frame_, gif_, next_index_);
|
||||
|
||||
HRESULT hr = image_.GetRawFrame(next_index_, raw_image, frame_rect_, frame_delay_, disposal_type_);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
if (frame_.disposal_type == GifImage::DisposalType::Previous)
|
||||
{
|
||||
if (disposal_type_ == DisposalType::Previous)
|
||||
{
|
||||
SaveComposedFrame();
|
||||
}
|
||||
SaveComposedFrame();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
if (frame_rt_.IsValid())
|
||||
{
|
||||
frame_rt_.BeginDraw();
|
||||
|
||||
if (next_index_ == 0)
|
||||
{
|
||||
// ÖØÐ»æÖƱ³¾°
|
||||
frame_rt_.Clear(image_.GetBackgroundColor());
|
||||
loop_count_++;
|
||||
}
|
||||
|
||||
frame_rt_.DrawImage(raw_image, nullptr, &frame_rect_);
|
||||
frame_rt_.DrawTexture(frame_.raw, nullptr, &frame_.rect);
|
||||
frame_rt_.EndDraw();
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
Image frame_to_render = frame_rt_.GetOutput();
|
||||
|
||||
hr = frame_to_render.IsValid() ? S_OK : E_FAIL;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
Texture frame_to_render = frame_rt_.GetOutput();
|
||||
if (frame_to_render.IsValid())
|
||||
{
|
||||
frame_ = frame_to_render;
|
||||
next_index_ = (++next_index_) % image_.GetFramesCount();
|
||||
frame_.raw = frame_to_render;
|
||||
next_index_ = (++next_index_) % gif_.GetFramesCount();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -212,13 +204,11 @@ namespace kiwano
|
|||
{
|
||||
done_cb_();
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void GifSprite::SaveComposedFrame()
|
||||
{
|
||||
Image frame_to_be_saved = frame_rt_.GetOutput();
|
||||
Texture frame_to_be_saved = frame_rt_.GetOutput();
|
||||
|
||||
HRESULT hr = frame_to_be_saved.IsValid() ? S_OK : E_FAIL;
|
||||
|
||||
|
|
@ -253,7 +243,7 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
Image frame_to_copy_to = frame_rt_.GetOutput();
|
||||
Texture frame_to_copy_to = frame_rt_.GetOutput();
|
||||
|
||||
hr = frame_to_copy_to.IsValid() ? S_OK : E_FAIL;
|
||||
|
||||
|
|
@ -270,8 +260,8 @@ namespace kiwano
|
|||
{
|
||||
frame_rt_.BeginDraw();
|
||||
|
||||
frame_rt_.PushClipRect(frame_rect_);
|
||||
frame_rt_.Clear(image_.GetBackgroundColor());
|
||||
frame_rt_.PushClipRect(frame_.rect);
|
||||
frame_rt_.Clear();
|
||||
frame_rt_.PopClipRect();
|
||||
|
||||
return frame_rt_.EndDraw();
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ namespace kiwano
|
|||
: public Actor
|
||||
{
|
||||
public:
|
||||
using DisposalType = GifImage::DisposalType;
|
||||
using LoopDoneCallback = Function<void(Int32)>;
|
||||
using DoneCallback = Function<void()>;
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ namespace kiwano
|
|||
);
|
||||
|
||||
GifSprite(
|
||||
GifImage image
|
||||
GifImage gif
|
||||
);
|
||||
|
||||
bool Load(
|
||||
|
|
@ -58,7 +57,7 @@ namespace kiwano
|
|||
);
|
||||
|
||||
bool Load(
|
||||
GifImage image
|
||||
GifImage gif
|
||||
);
|
||||
|
||||
// 设置 GIF 动画循环次数
|
||||
|
|
@ -70,12 +69,17 @@ namespace kiwano
|
|||
// 设置 GIF 动画结束回调函数
|
||||
inline void SetDoneCallback(DoneCallback const& cb) { done_cb_ = cb; }
|
||||
|
||||
// ÉèÖà GIF ͼÏñ
|
||||
void SetGifImage(GifImage const& gif);
|
||||
|
||||
// 重新播放动画
|
||||
void RestartAnimation();
|
||||
|
||||
inline LoopDoneCallback GetLoopDoneCallback() const { return loop_cb_; }
|
||||
inline LoopDoneCallback GetLoopDoneCallback() const { return loop_cb_; }
|
||||
|
||||
inline DoneCallback GetDoneCallback() const { return done_cb_; }
|
||||
inline DoneCallback GetDoneCallback() const { return done_cb_; }
|
||||
|
||||
inline GifImage const& GetGifImage() const { return gif_; }
|
||||
|
||||
void OnRender(RenderTarget* rt) override;
|
||||
|
||||
|
|
@ -103,15 +107,12 @@ namespace kiwano
|
|||
Int32 total_loop_count_;
|
||||
Int32 loop_count_;
|
||||
UInt32 next_index_;
|
||||
Duration frame_delay_;
|
||||
Duration frame_elapsed_;
|
||||
DisposalType disposal_type_;
|
||||
LoopDoneCallback loop_cb_;
|
||||
DoneCallback done_cb_;
|
||||
GifImage image_;
|
||||
Image frame_;
|
||||
Rect frame_rect_;
|
||||
Image saved_frame_;
|
||||
ImageRenderTarget frame_rt_;
|
||||
GifImage gif_;
|
||||
GifImage::Frame frame_;
|
||||
Texture saved_frame_;
|
||||
TextureRenderTarget frame_rt_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#pragma once
|
||||
#include "Actor.h"
|
||||
#include "../renderer/Geometry.h"
|
||||
#include "../renderer/StrokeStyle.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ namespace kiwano
|
|||
{
|
||||
PrepareRender(rt);
|
||||
|
||||
rt->DrawImage(frame_->GetImage(), &frame_->GetCropRect(), nullptr);
|
||||
rt->DrawTexture(frame_->GetTexture(), &frame_->GetCropRect(), nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ namespace kiwano
|
|||
|
||||
// 设置文字斜体(默认值为 false)
|
||||
void SetItalic(
|
||||
bool val
|
||||
bool italic
|
||||
);
|
||||
|
||||
// 设置文本自动换行的宽度(默认为 0)
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "include-forwards.h"
|
||||
#include "../renderer/StrokeStyle.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ namespace kiwano
|
|||
|
||||
if (status_ == Status::NotStarted)
|
||||
{
|
||||
Init(target);
|
||||
status_ = delay_.IsZero() ? Status::Started : Status::Delayed;
|
||||
Init(target);
|
||||
}
|
||||
|
||||
switch (status_)
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ namespace kiwano
|
|||
{
|
||||
if (!path_)
|
||||
{
|
||||
Complete(target);
|
||||
Done();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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<Sprite*>(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<Sprite*>(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<UInt32>(math::Floor(size * percent)), size - 1);
|
||||
|
||||
const auto& frames = frame_seq_->GetFrames();
|
||||
auto size = frames.size();
|
||||
auto index = std::min(static_cast<UInt32>(math::Floor(size * percent)), size - 1);
|
||||
|
||||
sprite_target->SetFrame(frames[index]);
|
||||
sprite_target->SetFrame(frames[index]);
|
||||
}
|
||||
}
|
||||
|
||||
ActionPtr Animation::Clone() const
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "Window.h"
|
||||
#include "Logger.h"
|
||||
#include "../platform/Application.h"
|
||||
|
||||
#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
|
||||
#define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX
|
||||
|
|
@ -39,6 +40,16 @@ namespace kiwano
|
|||
void RestoreResolution(WCHAR* device_name);
|
||||
}
|
||||
|
||||
WindowConfig::WindowConfig(String const& title, UInt32 width, UInt32 height, UInt32 icon, bool resizable, bool fullscreen)
|
||||
: title(title)
|
||||
, width(width)
|
||||
, height(height)
|
||||
, icon(icon)
|
||||
, resizable(resizable)
|
||||
, fullscreen(fullscreen)
|
||||
{
|
||||
}
|
||||
|
||||
Window::Window()
|
||||
: handle_(nullptr)
|
||||
, width_(0)
|
||||
|
|
@ -46,7 +57,7 @@ namespace kiwano
|
|||
, device_name_(nullptr)
|
||||
, is_fullscreen_(false)
|
||||
, resizable_(false)
|
||||
, mouse_cursor_(MouseCursor::Arrow)
|
||||
, mouse_cursor_(CursorType::Arrow)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +79,7 @@ namespace kiwano
|
|||
}
|
||||
}
|
||||
|
||||
void Window::Init(String const& title, Int32 width, Int32 height, UInt32 icon, bool resizable, bool fullscreen, WNDPROC proc)
|
||||
void Window::Init(WindowConfig const& config, WNDPROC proc)
|
||||
{
|
||||
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
||||
WNDCLASSEX wcex = { 0 };
|
||||
|
|
@ -84,9 +95,10 @@ namespace kiwano
|
|||
wcex.lpszMenuName = nullptr;
|
||||
wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW);
|
||||
|
||||
if (icon)
|
||||
if (config.icon)
|
||||
{
|
||||
wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(icon), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
|
||||
wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(config.icon), IMAGE_ICON, 0, 0,
|
||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
|
||||
}
|
||||
|
||||
::RegisterClassExW(&wcex);
|
||||
|
|
@ -105,22 +117,24 @@ namespace kiwano
|
|||
device_name_ = new WCHAR[len + 1];
|
||||
lstrcpyW(device_name_, monitor_info_ex.szDevice);
|
||||
|
||||
UInt32 width = config.width;
|
||||
UInt32 height = config.height;
|
||||
Int32 left = -1;
|
||||
Int32 top = -1;
|
||||
|
||||
resizable_ = resizable;
|
||||
is_fullscreen_ = fullscreen;
|
||||
resizable_ = config.resizable;
|
||||
is_fullscreen_ = config.fullscreen;
|
||||
|
||||
if (is_fullscreen_)
|
||||
{
|
||||
top = monitor_info_ex.rcMonitor.top;
|
||||
left = monitor_info_ex.rcMonitor.left;
|
||||
|
||||
if (width > monitor_info_ex.rcWork.right - left)
|
||||
width = monitor_info_ex.rcWork.right - left;
|
||||
if (width > static_cast<UInt32>(monitor_info_ex.rcWork.right - left))
|
||||
width = static_cast<UInt32>(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<UInt32>(monitor_info_ex.rcWork.bottom - top))
|
||||
height = static_cast<UInt32>(monitor_info_ex.rcWork.bottom - top);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -145,7 +159,7 @@ namespace kiwano
|
|||
handle_ = ::CreateWindowExW(
|
||||
is_fullscreen_ ? WS_EX_TOPMOST : 0,
|
||||
KGE_WND_CLASS_NAME,
|
||||
title.c_str(),
|
||||
config.title.c_str(),
|
||||
GetWindowStyle(),
|
||||
left,
|
||||
top,
|
||||
|
|
@ -222,7 +236,7 @@ namespace kiwano
|
|||
if (handle_)
|
||||
{
|
||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||
HICON icon = (HICON)::LoadImage(
|
||||
HICON icon = (HICON)::LoadImageW(
|
||||
hinstance,
|
||||
MAKEINTRESOURCE(icon_resource),
|
||||
IMAGE_ICON,
|
||||
|
|
@ -295,7 +309,7 @@ namespace kiwano
|
|||
}
|
||||
}
|
||||
|
||||
void Window::SetMouseCursor(MouseCursor cursor)
|
||||
void Window::SetCursor(CursorType cursor)
|
||||
{
|
||||
mouse_cursor_ = cursor;
|
||||
}
|
||||
|
|
@ -327,14 +341,14 @@ namespace kiwano
|
|||
LPTSTR win32_cursor = IDC_ARROW;
|
||||
switch (mouse_cursor_)
|
||||
{
|
||||
case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break;
|
||||
case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break;
|
||||
case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||
case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break;
|
||||
case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break;
|
||||
case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||
case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||
case MouseCursor::Hand: win32_cursor = IDC_HAND; break;
|
||||
case CursorType::Arrow: win32_cursor = IDC_ARROW; break;
|
||||
case CursorType::TextInput: win32_cursor = IDC_IBEAM; break;
|
||||
case CursorType::SizeAll: win32_cursor = IDC_SIZEALL; break;
|
||||
case CursorType::SizeWE: win32_cursor = IDC_SIZEWE; break;
|
||||
case CursorType::SizeNS: win32_cursor = IDC_SIZENS; break;
|
||||
case CursorType::SizeNESW: win32_cursor = IDC_SIZENESW; break;
|
||||
case CursorType::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
||||
case CursorType::Hand: win32_cursor = IDC_HAND; break;
|
||||
}
|
||||
::SetCursor(::LoadCursorW(nullptr, win32_cursor));
|
||||
}
|
||||
|
|
@ -417,4 +431,5 @@ namespace kiwano
|
|||
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,10 +22,44 @@
|
|||
#include "../macros.h"
|
||||
#include "../core/core.h"
|
||||
#include "../math/math.h"
|
||||
#include "types.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
// 鼠标指针类型
|
||||
enum class CursorType
|
||||
{
|
||||
Arrow, /* 指针 */
|
||||
TextInput, /* 文本 */
|
||||
Hand, /* 手指 */
|
||||
SizeAll,
|
||||
SizeNESW,
|
||||
SizeNS,
|
||||
SizeNWSE,
|
||||
SizeWE,
|
||||
};
|
||||
|
||||
// 窗口设置
|
||||
struct WindowConfig
|
||||
{
|
||||
String title; // 标题
|
||||
UInt32 width; // 宽度
|
||||
UInt32 height; // 高度
|
||||
UInt32 icon; // 图标资源 ID
|
||||
bool resizable; // 窗口大小可拉伸
|
||||
bool fullscreen; // 全屏模式
|
||||
|
||||
WindowConfig(
|
||||
String const& title = L"Kiwano Game",
|
||||
UInt32 width = 640,
|
||||
UInt32 height = 480,
|
||||
UInt32 icon = 0,
|
||||
bool resizable = false,
|
||||
bool fullscreen = false
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
// 窗口
|
||||
class KGE_API Window
|
||||
: public Singleton<Window>
|
||||
{
|
||||
|
|
@ -56,19 +90,11 @@ namespace kiwano
|
|||
// 设置全屏模式
|
||||
void SetFullscreen(bool fullscreen, Int32 width, Int32 height);
|
||||
|
||||
// 譜崔報炎峺寞
|
||||
void SetMouseCursor(MouseCursor cursor);
|
||||
// 设置鼠标指针类型
|
||||
void SetCursor(CursorType cursor);
|
||||
|
||||
public:
|
||||
void Init(
|
||||
String const& title,
|
||||
Int32 width,
|
||||
Int32 height,
|
||||
UInt32 icon,
|
||||
bool resizable,
|
||||
bool fullscreen,
|
||||
WNDPROC proc
|
||||
);
|
||||
void Init(WindowConfig const& config, WNDPROC proc);
|
||||
|
||||
void Prepare();
|
||||
|
||||
|
|
@ -94,6 +120,6 @@ namespace kiwano
|
|||
Int32 width_;
|
||||
Int32 height_;
|
||||
WCHAR* device_name_;
|
||||
MouseCursor mouse_cursor_;
|
||||
CursorType mouse_cursor_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Compile-time options for Kiwano
|
||||
// Compile-time configurations for Kiwano
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
|
@ -19,3 +19,6 @@
|
|||
|
||||
//---- Define DirectX version. Defaults to using Direct3D11
|
||||
//#define KGE_USE_DIRECTX10
|
||||
|
||||
//---- Define to enable DirectX debug layer
|
||||
//#define KGE_ENABLE_DX_DEBUG
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,12 +20,10 @@
|
|||
|
||||
#include "Application.h"
|
||||
#include "modules.h"
|
||||
#include "../base/Window.h"
|
||||
#include "../base/Logger.h"
|
||||
#include "../base/input.h"
|
||||
#include "../base/Director.h"
|
||||
#include "../renderer/ImageCache.h"
|
||||
#include "../renderer/Renderer.h"
|
||||
#include "../renderer/TextureCache.h"
|
||||
#include "../utils/ResourceCache.h"
|
||||
#include <windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
|
||||
#include <imm.h> // ImmAssociateContext
|
||||
|
|
@ -43,17 +41,19 @@ namespace kiwano
|
|||
Queue<FunctionToPerform> functions_to_perform_;
|
||||
}
|
||||
|
||||
Options::Options(String const& title, Int32 width, Int32 height, UInt32 icon, Color clear_color, bool vsync, bool resizable, bool fullscreen, bool debug)
|
||||
: title(title)
|
||||
, width(width)
|
||||
, height(height)
|
||||
, icon(icon)
|
||||
, clear_color(clear_color)
|
||||
, vsync(vsync)
|
||||
, resizable(resizable)
|
||||
, fullscreen(fullscreen)
|
||||
, debug(debug)
|
||||
{}
|
||||
Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon)
|
||||
{
|
||||
window.title = title;
|
||||
window.width = width;
|
||||
window.height = height;
|
||||
window.icon = icon;
|
||||
}
|
||||
|
||||
Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config)
|
||||
{
|
||||
window = wnd_config;
|
||||
render = render_config;
|
||||
}
|
||||
}
|
||||
|
||||
namespace kiwano
|
||||
|
|
@ -79,20 +79,10 @@ namespace kiwano
|
|||
::CoUninitialize();
|
||||
}
|
||||
|
||||
void Application::Init(const Options& options)
|
||||
void Application::Init(const Config& config)
|
||||
{
|
||||
Window::GetInstance()->Init(
|
||||
options.title,
|
||||
options.width,
|
||||
options.height,
|
||||
options.icon,
|
||||
options.resizable,
|
||||
options.fullscreen,
|
||||
Application::WndProc
|
||||
);
|
||||
|
||||
Renderer::GetInstance()->SetClearColor(options.clear_color);
|
||||
Renderer::GetInstance()->SetVSyncEnabled(options.vsync);
|
||||
Window::GetInstance()->Init(config.window, Application::WndProc);
|
||||
Renderer::GetInstance()->Init(config.render);
|
||||
|
||||
// Setup all components
|
||||
for (Component* c : components_)
|
||||
|
|
@ -100,7 +90,7 @@ namespace kiwano
|
|||
c->SetupComponent();
|
||||
}
|
||||
|
||||
if (options.debug)
|
||||
if (config.debug)
|
||||
{
|
||||
Director::GetInstance()->ShowDebugInfo(true);
|
||||
Renderer::GetInstance()->SetCollectingStatus(true);
|
||||
|
|
@ -150,7 +140,7 @@ namespace kiwano
|
|||
// Clear all resources
|
||||
Director::GetInstance()->ClearStages();
|
||||
ResourceCache::GetInstance()->Clear();
|
||||
ImageCache::GetInstance()->Clear();
|
||||
TextureCache::GetInstance()->Clear();
|
||||
|
||||
if (inited_)
|
||||
{
|
||||
|
|
@ -166,7 +156,7 @@ namespace kiwano
|
|||
// Destroy all instances
|
||||
Director::DestroyInstance();
|
||||
ResourceCache::DestroyInstance();
|
||||
ImageCache::DestroyInstance();
|
||||
TextureCache::DestroyInstance();
|
||||
Input::DestroyInstance();
|
||||
Renderer::DestroyInstance();
|
||||
Window::DestroyInstance();
|
||||
|
|
@ -299,10 +289,11 @@ namespace kiwano
|
|||
|
||||
LRESULT CALLBACK Application::WndProc(HWND hwnd, UInt32 msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
Application * app = reinterpret_cast<Application*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
|
||||
|
||||
if (!app)
|
||||
Application* app = reinterpret_cast<Application*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
|
||||
if (app == nullptr)
|
||||
{
|
||||
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
|
||||
// Handle Message
|
||||
for (Component* c : app->components_)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
);
|
||||
|
||||
// 初始化成功时
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<String> 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<Resource> const& res_arr)
|
||||
{
|
||||
Renderer::GetInstance()->CreateFontCollection(*this, res_arr);
|
||||
return false;
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
bool FontCollection::IsValid() const
|
||||
{
|
||||
return collection_ != nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ namespace kiwano
|
|||
// 从多个资源加载字体
|
||||
bool Load(Vector<Resource> const& res_arr);
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
public:
|
||||
inline ComPtr<IDWriteFontCollection> GetFontCollection() const { return collection_; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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<IWICMetadataQueryReader> metadata_reader;
|
||||
|
||||
// 获取帧数量
|
||||
HRESULT hr = decoder_ ? S_OK : E_FAIL;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
|
|
@ -100,317 +90,91 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICMetadataQueryReader> 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<UInt32>(height / pixel_asp_ratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
width_in_pixels_ = static_cast<UInt32>(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<IWICMetadataQueryReader> metadata_reader)
|
||||
{
|
||||
UChar bg_index = 0;
|
||||
WICColor bgcolors[256];
|
||||
UInt32 colors_copied = 0;
|
||||
ComPtr<IWICPalette> wic_palette;
|
||||
|
||||
PROPVARIANT prop_val;
|
||||
PropVariantInit(&prop_val);
|
||||
|
||||
HRESULT hr = metadata_reader->GetMetadataByName(L"/logscrdesc/GlobalColorTableFlag", &prop_val);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt != VT_BOOL || !prop_val.boolVal) ? E_FAIL : S_OK;
|
||||
::PropVariantClear(&prop_val);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/logscrdesc/BackgroundColorIndex", &prop_val);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt != VT_UI1) ? E_FAIL : S_OK;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bg_index = prop_val.bVal;
|
||||
}
|
||||
::PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
|
||||
hr = factory->CreatePalette(&wic_palette);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = decoder_->CopyPalette(wic_palette.get());
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = wic_palette->GetColors(
|
||||
ARRAYSIZE(bgcolors),
|
||||
bgcolors,
|
||||
&colors_copied);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (bg_index >= colors_copied) ? E_FAIL : S_OK;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 转换为 ARGB 格式
|
||||
Float32 alpha = (bgcolors[bg_index] >> 24) / 255.f;
|
||||
bg_color_ = Color(bgcolors[bg_index], alpha);
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GifImage::GetRawFrame(UInt32 frame_index, Image& raw_frame, Rect& frame_rect, Duration& delay, DisposalType& disposal_type)
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
ComPtr<IWICBitmapFrameDecode> wic_frame;
|
||||
ComPtr<IWICMetadataQueryReader> 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<ID2D1Bitmap> 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<Float32>(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<Float32>(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<Float32>(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<Float32>(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<long>(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<UInt32>(height / pixel_asp_ratio);
|
||||
}
|
||||
else
|
||||
{
|
||||
width_in_pixels_ = static_cast<UInt32>(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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// THE SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
#include "Image.h"
|
||||
#include "Texture.h"
|
||||
|
||||
namespace kiwano
|
||||
{
|
||||
|
|
@ -43,9 +43,7 @@ namespace kiwano
|
|||
|
||||
inline UInt32 GetHeightInPixels() const { return height_in_pixels_; }
|
||||
|
||||
inline UInt32 GetFramesCount() const { return frames_count_; }
|
||||
|
||||
inline Color GetBackgroundColor() const { return bg_color_; }
|
||||
inline UInt32 GetFramesCount() const { return frames_count_; }
|
||||
|
||||
public:
|
||||
enum class DisposalType
|
||||
|
|
@ -56,13 +54,15 @@ namespace kiwano
|
|||
Previous
|
||||
};
|
||||
|
||||
HRESULT GetRawFrame(
|
||||
UInt32 frame_index,
|
||||
Image& raw_frame,
|
||||
Rect& frame_rect,
|
||||
Duration& delay,
|
||||
DisposalType& disposal_type
|
||||
);
|
||||
struct Frame
|
||||
{
|
||||
Duration delay;
|
||||
Texture raw;
|
||||
Rect rect;
|
||||
DisposalType disposal_type;
|
||||
|
||||
Frame() : disposal_type(DisposalType::Unknown) {}
|
||||
};
|
||||
|
||||
inline ComPtr<IWICBitmapDecoder> GetDecoder() const { return decoder_; }
|
||||
|
||||
|
|
@ -71,16 +71,11 @@ namespace kiwano
|
|||
protected:
|
||||
HRESULT GetGlobalMetadata();
|
||||
|
||||
HRESULT GetBackgroundColor(
|
||||
ComPtr<IWICMetadataQueryReader> metadata_reader
|
||||
);
|
||||
|
||||
protected:
|
||||
UInt32 frames_count_;
|
||||
UInt32 width_in_pixels_;
|
||||
UInt32 height_in_pixels_;
|
||||
Color bg_color_;
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder_;
|
||||
ComPtr<IWICBitmapDecoder> decoder_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,9 @@ namespace kiwano
|
|||
RenderTarget::RenderTarget()
|
||||
: opacity_(1.f)
|
||||
, collecting_status_(false)
|
||||
, fast_global_transform_(true)
|
||||
, antialias_(true)
|
||||
, text_antialias_(TextAntialias::GrayScale)
|
||||
, text_antialias_(TextAntialiasMode::GrayScale)
|
||||
{
|
||||
status_.primitives = 0;
|
||||
}
|
||||
|
|
@ -133,7 +134,7 @@ namespace kiwano
|
|||
geometry.GetGeometry().get(),
|
||||
default_brush_.get(),
|
||||
stroke_width,
|
||||
device_resources_->GetStrokeStyle(stroke)
|
||||
GetStrokeStyle(stroke).get()
|
||||
);
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
|
|
@ -179,7 +180,7 @@ namespace kiwano
|
|||
DX::ConvertToPoint2F(point2),
|
||||
default_brush_.get(),
|
||||
stroke_width,
|
||||
device_resources_->GetStrokeStyle(stroke)
|
||||
GetStrokeStyle(stroke).get()
|
||||
);
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
|
|
@ -204,7 +205,7 @@ namespace kiwano
|
|||
DX::ConvertToRectF(rect),
|
||||
default_brush_.get(),
|
||||
stroke_width,
|
||||
device_resources_->GetStrokeStyle(stroke)
|
||||
GetStrokeStyle(stroke).get()
|
||||
);
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
|
|
@ -253,7 +254,7 @@ namespace kiwano
|
|||
),
|
||||
default_brush_.get(),
|
||||
stroke_width,
|
||||
device_resources_->GetStrokeStyle(stroke)
|
||||
GetStrokeStyle(stroke).get()
|
||||
);
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
|
|
@ -306,7 +307,7 @@ namespace kiwano
|
|||
),
|
||||
default_brush_.get(),
|
||||
stroke_width,
|
||||
device_resources_->GetStrokeStyle(stroke)
|
||||
GetStrokeStyle(stroke).get()
|
||||
);
|
||||
|
||||
IncreasePrimitivesCount();
|
||||
|
|
@ -339,12 +340,12 @@ namespace kiwano
|
|||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RenderTarget::DrawImage(Image const& image, Rect const& src_rect, Rect const& dest_rect) const
|
||||
void RenderTarget::DrawTexture(Texture const& texture, Rect const& src_rect, Rect const& dest_rect) const
|
||||
{
|
||||
DrawImage(image, &src_rect, &dest_rect);
|
||||
DrawTexture(texture, &src_rect, &dest_rect);
|
||||
}
|
||||
|
||||
void RenderTarget::DrawImage(Image const& image, const Rect* src_rect, const Rect* dest_rect) const
|
||||
void RenderTarget::DrawTexture(Texture const& texture, const Rect* src_rect, const Rect* dest_rect) const
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!render_target_)
|
||||
|
|
@ -352,13 +353,17 @@ namespace kiwano
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr) && image.IsValid())
|
||||
if (SUCCEEDED(hr) && texture.IsValid())
|
||||
{
|
||||
auto mode = (texture.GetBitmapInterpolationMode() == InterpolationMode::Linear)
|
||||
? D2D1_BITMAP_INTERPOLATION_MODE_LINEAR
|
||||
: D2D1_BITMAP_INTERPOLATION_MODE_NEAREST_NEIGHBOR;
|
||||
|
||||
render_target_->DrawBitmap(
|
||||
image.GetBitmap().get(),
|
||||
texture.GetBitmap().get(),
|
||||
dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
|
||||
opacity_,
|
||||
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
||||
mode,
|
||||
src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr
|
||||
);
|
||||
|
||||
|
|
@ -384,7 +389,7 @@ namespace kiwano
|
|||
layout.GetTextStyle().outline,
|
||||
DX::ConvertToColorF(layout.GetTextStyle().outline_color),
|
||||
layout.GetTextStyle().outline_width,
|
||||
device_resources_->GetStrokeStyle(layout.GetTextStyle().outline_stroke)
|
||||
GetStrokeStyle(layout.GetTextStyle().outline_stroke).get()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -537,7 +542,18 @@ namespace kiwano
|
|||
|
||||
Matrix3x2 RenderTarget::GetGlobalTransform() const
|
||||
{
|
||||
return global_matrix_;
|
||||
return global_transform_;
|
||||
}
|
||||
|
||||
ComPtr<ID2D1StrokeStyle> RenderTarget::GetStrokeStyle(StrokeStyle style) const
|
||||
{
|
||||
switch (style)
|
||||
{
|
||||
case StrokeStyle::Miter: return device_resources_->GetMiterStrokeStyle(); break;
|
||||
case StrokeStyle::Bevel: return device_resources_->GetBevelStrokeStyle(); break;
|
||||
case StrokeStyle::Round: return device_resources_->GetRoundStrokeStyle(); break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void RenderTarget::SetTransform(const Matrix3x2& matrix)
|
||||
|
|
@ -550,8 +566,16 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
Matrix3x2 result = matrix * global_matrix_;
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result));
|
||||
if (fast_global_transform_)
|
||||
{
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Matrix3x2 result = matrix * global_transform_;
|
||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&result));
|
||||
}
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
|
|
@ -559,7 +583,20 @@ namespace kiwano
|
|||
|
||||
void RenderTarget::SetGlobalTransform(const Matrix3x2& matrix)
|
||||
{
|
||||
global_matrix_ = matrix;
|
||||
SetGlobalTransform(&matrix);
|
||||
}
|
||||
|
||||
void RenderTarget::SetGlobalTransform(const Matrix3x2* matrix)
|
||||
{
|
||||
if (matrix)
|
||||
{
|
||||
global_transform_ = *matrix;
|
||||
fast_global_transform_ = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
fast_global_transform_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTarget::SetOpacity(Float32 opacity)
|
||||
|
|
@ -601,7 +638,7 @@ namespace kiwano
|
|||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void RenderTarget::SetTextAntialiasMode(TextAntialias mode)
|
||||
void RenderTarget::SetTextAntialiasMode(TextAntialiasMode mode)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!render_target_)
|
||||
|
|
@ -615,16 +652,16 @@ namespace kiwano
|
|||
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
switch (text_antialias_)
|
||||
{
|
||||
case TextAntialias::Default:
|
||||
case TextAntialiasMode::Default:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
|
||||
break;
|
||||
case TextAntialias::ClearType:
|
||||
case TextAntialiasMode::ClearType:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||
break;
|
||||
case TextAntialias::GrayScale:
|
||||
case TextAntialiasMode::GrayScale:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||
break;
|
||||
case TextAntialias::None:
|
||||
case TextAntialiasMode::None:
|
||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||
break;
|
||||
default:
|
||||
|
|
@ -638,9 +675,12 @@ namespace kiwano
|
|||
|
||||
bool RenderTarget::CheckVisibility(Rect const& bounds, Matrix3x2 const& transform)
|
||||
{
|
||||
return Rect{ Point{}, reinterpret_cast<const Size&>(render_target_->GetSize()) }.Intersects(
|
||||
Matrix3x2(transform * global_matrix_).Transform(bounds)
|
||||
);
|
||||
Rect visible_size = { Point{}, reinterpret_cast<const Size&>(render_target_->GetSize()) };
|
||||
if (fast_global_transform_)
|
||||
{
|
||||
return visible_size.Intersects(transform.Transform(bounds));
|
||||
}
|
||||
return visible_size.Intersects(Matrix3x2(transform * global_transform_).Transform(bounds));
|
||||
}
|
||||
|
||||
void RenderTarget::SetCollectingStatus(bool collecting)
|
||||
|
|
@ -658,14 +698,14 @@ namespace kiwano
|
|||
|
||||
|
||||
//
|
||||
// ImageRenderTarget
|
||||
// TextureRenderTarget
|
||||
//
|
||||
|
||||
ImageRenderTarget::ImageRenderTarget()
|
||||
TextureRenderTarget::TextureRenderTarget()
|
||||
{
|
||||
}
|
||||
|
||||
Image ImageRenderTarget::GetOutput() const
|
||||
Texture TextureRenderTarget::GetOutput() const
|
||||
{
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
|
|
@ -681,13 +721,13 @@ namespace kiwano
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
return Image(bitmap);
|
||||
return Texture(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThrowIfFailed(hr);
|
||||
return Image();
|
||||
return Texture();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#pragma once
|
||||
#include "../base/time.h"
|
||||
#include "Image.h"
|
||||
#include "Texture.h"
|
||||
#include "Geometry.h"
|
||||
#include "TextLayout.h"
|
||||
#include "LayerArea.h"
|
||||
|
|
@ -28,6 +28,16 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
// 文字抗锯齿模式
|
||||
enum class TextAntialiasMode
|
||||
{
|
||||
Default, // 系统默认
|
||||
ClearType, // ClearType 抗锯齿
|
||||
GrayScale, // 灰度抗锯齿
|
||||
None // 不启用抗锯齿
|
||||
};
|
||||
|
||||
|
||||
// 渲染目标
|
||||
class KGE_API RenderTarget
|
||||
: public noncopyable
|
||||
|
|
@ -103,14 +113,14 @@ namespace kiwano
|
|||
Color const& fill_color
|
||||
) const;
|
||||
|
||||
void DrawImage(
|
||||
Image const& image,
|
||||
void DrawTexture(
|
||||
Texture const& texture,
|
||||
Rect const& src_rect,
|
||||
Rect const& dest_rect
|
||||
) const;
|
||||
|
||||
void DrawImage(
|
||||
Image const& image,
|
||||
void DrawTexture(
|
||||
Texture const& texture,
|
||||
const Rect* src_rect = nullptr,
|
||||
const Rect* dest_rect = nullptr
|
||||
) const;
|
||||
|
|
@ -154,6 +164,10 @@ namespace kiwano
|
|||
const Matrix3x2& matrix
|
||||
);
|
||||
|
||||
void SetGlobalTransform(
|
||||
const Matrix3x2* matrix
|
||||
);
|
||||
|
||||
// 设置抗锯齿模式
|
||||
void SetAntialiasMode(
|
||||
bool enabled
|
||||
|
|
@ -161,9 +175,10 @@ namespace kiwano
|
|||
|
||||
// 设置文字抗锯齿模式
|
||||
void SetTextAntialiasMode(
|
||||
TextAntialias mode
|
||||
TextAntialiasMode mode
|
||||
);
|
||||
|
||||
// 检查边界是否在视区内
|
||||
bool CheckVisibility(
|
||||
Rect const& bounds,
|
||||
Matrix3x2 const& transform
|
||||
|
|
@ -181,11 +196,13 @@ namespace kiwano
|
|||
|
||||
void IncreasePrimitivesCount() const;
|
||||
|
||||
inline Status const& GetStatus() const { return status_; }
|
||||
inline Status const& GetStatus() const { return status_; }
|
||||
|
||||
inline ComPtr<ID2D1RenderTarget> GetRenderTarget() const { KGE_ASSERT(render_target_); return render_target_; }
|
||||
inline ComPtr<ID2D1RenderTarget> GetRenderTarget() const { KGE_ASSERT(render_target_); return render_target_; }
|
||||
|
||||
inline ComPtr<ITextRenderer> GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_; }
|
||||
inline ComPtr<ITextRenderer> GetTextRenderer() const { KGE_ASSERT(text_renderer_); return text_renderer_; }
|
||||
|
||||
ComPtr<ID2D1StrokeStyle> GetStrokeStyle(StrokeStyle style) const;
|
||||
|
||||
public:
|
||||
RenderTarget();
|
||||
|
|
@ -200,25 +217,26 @@ namespace kiwano
|
|||
protected:
|
||||
Float32 opacity_;
|
||||
bool antialias_;
|
||||
bool fast_global_transform_;
|
||||
mutable bool collecting_status_;
|
||||
mutable Status status_;
|
||||
TextAntialias text_antialias_;
|
||||
TextAntialiasMode text_antialias_;
|
||||
ComPtr<ITextRenderer> text_renderer_;
|
||||
ComPtr<ID2D1RenderTarget> render_target_;
|
||||
ComPtr<ID2D1SolidColorBrush> default_brush_;
|
||||
ComPtr<ID2D1Brush> current_brush_;
|
||||
ComPtr<ID2DDeviceResources> device_resources_;
|
||||
Matrix3x2 global_matrix_;
|
||||
Matrix3x2 global_transform_;
|
||||
};
|
||||
|
||||
|
||||
// 位图渲染目标
|
||||
class KGE_API ImageRenderTarget
|
||||
class KGE_API TextureRenderTarget
|
||||
: public RenderTarget
|
||||
{
|
||||
public:
|
||||
ImageRenderTarget();
|
||||
TextureRenderTarget();
|
||||
|
||||
Image GetOutput() const;
|
||||
Texture GetOutput() const;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,12 @@
|
|||
|
||||
namespace kiwano
|
||||
{
|
||||
RenderConfig::RenderConfig(Color clear_color, bool vsync)
|
||||
: clear_color(clear_color)
|
||||
, vsync(vsync)
|
||||
{
|
||||
}
|
||||
|
||||
Renderer::Renderer()
|
||||
: hwnd_(nullptr)
|
||||
, vsync_(true)
|
||||
|
|
@ -37,6 +43,12 @@ namespace kiwano
|
|||
{
|
||||
}
|
||||
|
||||
void Renderer::Init(RenderConfig const& config)
|
||||
{
|
||||
SetClearColor(config.clear_color);
|
||||
SetVSyncEnabled(config.vsync);
|
||||
}
|
||||
|
||||
void Renderer::SetupComponent()
|
||||
{
|
||||
KGE_LOG(L"Creating device resources");
|
||||
|
|
@ -245,57 +257,7 @@ namespace kiwano
|
|||
return hr;
|
||||
}
|
||||
|
||||
void Renderer::CreateImage(Image& image, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromFile(bitmap, file_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
image.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateImage(Image& image, Resource const& res)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromResource(bitmap, res);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
image.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateGifImage(GifImage& image, String const& file_path)
|
||||
void Renderer::CreateTexture(Texture& texture, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
|
|
@ -305,34 +267,58 @@ namespace kiwano
|
|||
|
||||
if (!FileUtil::ExistsFile(file_path))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Gif image file '%s' not found!", file_path.c_str());
|
||||
KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename(
|
||||
file_path.c_str(),
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&decoder
|
||||
);
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
image.SetDecoder(decoder);
|
||||
ComPtr<IWICBitmapFrameDecode> source;
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
hr = d2d_res_->CreateBitmapConverter(
|
||||
converter,
|
||||
source,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(
|
||||
bitmap,
|
||||
nullptr,
|
||||
converter
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr);
|
||||
KGE_WARNING_LOG(L"Load texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateGifImage(GifImage& image, Resource const& res)
|
||||
void Renderer::CreateTexture(Texture& texture, Resource const& resource)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
|
|
@ -340,43 +326,273 @@ namespace kiwano
|
|||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
Resource::Data res_data = res.GetData();
|
||||
|
||||
hr = res_data ? S_OK : E_FAIL;
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICStream> stream;
|
||||
hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream);
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = stream->InitializeFromMemory(
|
||||
static_cast<WICInProcPointer>(res_data.buffer),
|
||||
res_data.size
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream(
|
||||
stream.get(),
|
||||
nullptr,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&decoder
|
||||
);
|
||||
ComPtr<IWICBitmapFrameDecode> source;
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
image.SetDecoder(decoder);
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
hr = d2d_res_->CreateBitmapConverter(
|
||||
converter,
|
||||
source,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> bitmap;
|
||||
hr = d2d_res_->CreateBitmapFromConverter(
|
||||
bitmap,
|
||||
nullptr,
|
||||
converter
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
texture.SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr);
|
||||
KGE_WARNING_LOG(L"Load texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateGifImage(GifImage& gif, String const& file_path)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!FileUtil::ExistsFile(file_path))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Gif texture file '%s' not found!", file_path.c_str());
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
gif.SetDecoder(decoder);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Load GIF texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateGifImage(GifImage& gif, Resource const& resource)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
gif.SetDecoder(decoder);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Load GIF texture failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, UInt32 frame_index)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (gif.GetDecoder() == nullptr)
|
||||
{
|
||||
hr = E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapFrameDecode> wic_frame;
|
||||
HRESULT hr = gif.GetDecoder()->GetFrame(frame_index, &wic_frame);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
d2d_res_->CreateBitmapConverter(
|
||||
converter,
|
||||
wic_frame,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeCustom
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<ID2D1Bitmap> 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<IWICMetadataQueryReader> 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<Float32>(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<Float32>(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<Float32>(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<Float32>(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<long>(udelay));
|
||||
}
|
||||
}
|
||||
PropVariantClear(&prop_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.delay = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = metadata_reader->GetMetadataByName(L"/grctlext/Disposal", &prop_val);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
frame.disposal_type = GifImage::DisposalType(prop_val.bVal);
|
||||
}
|
||||
::PropVariantClear(&prop_val);
|
||||
}
|
||||
else
|
||||
{
|
||||
frame.disposal_type = GifImage::DisposalType::Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
::PropVariantClear(&prop_val);
|
||||
}
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Load GIF frame failed with HRESULT of %08X!", hr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -490,7 +706,7 @@ namespace kiwano
|
|||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextStyle const& style, TextFormat const& format)
|
||||
void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextFormat const& format)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
|
|
@ -504,7 +720,6 @@ namespace kiwano
|
|||
hr = d2d_res_->CreateTextLayout(
|
||||
output,
|
||||
text,
|
||||
style,
|
||||
format.GetTextFormat()
|
||||
);
|
||||
}
|
||||
|
|
@ -653,7 +868,7 @@ namespace kiwano
|
|||
ThrowIfFailed(hr);
|
||||
}
|
||||
|
||||
void Renderer::CreateImageRenderTarget(ImageRenderTarget& render_target)
|
||||
void Renderer::CreateTextureRenderTarget(TextureRenderTarget& render_target)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
if (!d2d_res_)
|
||||
|
|
@ -732,7 +947,7 @@ namespace kiwano
|
|||
{
|
||||
case ResolutionMode::Fixed:
|
||||
{
|
||||
SetGlobalTransform(Matrix3x2{});
|
||||
SetGlobalTransform(nullptr);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,32 @@ namespace kiwano
|
|||
typedef ID3D11DeviceResources ID3DDeviceResources;
|
||||
#endif
|
||||
|
||||
// 渲染设置
|
||||
struct RenderConfig
|
||||
{
|
||||
Color clear_color; // 清屏颜色
|
||||
bool vsync; // 垂直同步
|
||||
|
||||
RenderConfig(
|
||||
Color clear_color = Color::Black,
|
||||
bool vsync = true
|
||||
);
|
||||
};
|
||||
|
||||
// 分辨率模式
|
||||
// 分辨率模式决定了将画面渲染到视区上的方式
|
||||
// Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认)
|
||||
// Center (居中): 分辨率不随视区改变, 且画面始终在视区上居中
|
||||
// Stretch (拉伸): 分辨率始终随视区等比例拉伸
|
||||
// Adaptive (宽高自适应): 分辨率始终保持宽高比, 且尽可能的填充视区, 可能会出现黑色边界
|
||||
enum class ResolutionMode
|
||||
{
|
||||
Fixed, /* 固定 */
|
||||
Center, /* 居中 */
|
||||
Stretch, /* 拉伸 */
|
||||
Adaptive, /* 宽高自适应 */
|
||||
};
|
||||
|
||||
class KGE_API Renderer
|
||||
: public Singleton<Renderer>
|
||||
, public Component
|
||||
|
|
@ -57,25 +83,41 @@ namespace kiwano
|
|||
bool enabled
|
||||
);
|
||||
|
||||
// 设置画面分辨率
|
||||
void SetResolution(
|
||||
Size const& resolution
|
||||
);
|
||||
|
||||
// 设置分辨率模式
|
||||
void SetResolutionMode(
|
||||
ResolutionMode mode
|
||||
);
|
||||
|
||||
public:
|
||||
void CreateImage(
|
||||
Image& image,
|
||||
void CreateTexture(
|
||||
Texture& texture,
|
||||
String const& file_path
|
||||
);
|
||||
|
||||
void CreateImage(
|
||||
Image& image,
|
||||
Resource const& res
|
||||
void CreateTexture(
|
||||
Texture& texture,
|
||||
Resource const& resource
|
||||
);
|
||||
|
||||
void CreateGifImage(
|
||||
GifImage& image,
|
||||
GifImage& gif,
|
||||
String const& file_path
|
||||
);
|
||||
|
||||
void CreateGifImage(
|
||||
GifImage& image,
|
||||
Resource const& res
|
||||
GifImage& gif,
|
||||
Resource const& resource
|
||||
);
|
||||
|
||||
void CreateGifImageFrame(
|
||||
GifImage::Frame& frame,
|
||||
GifImage const& gif,
|
||||
UInt32 frame_index
|
||||
);
|
||||
|
||||
void CreateFontCollection(
|
||||
|
|
@ -96,7 +138,6 @@ namespace kiwano
|
|||
void CreateTextLayout(
|
||||
TextLayout& layout,
|
||||
String const& text,
|
||||
TextStyle const& style,
|
||||
TextFormat const& format
|
||||
);
|
||||
|
||||
|
|
@ -127,19 +168,13 @@ namespace kiwano
|
|||
GeometrySink& sink
|
||||
);
|
||||
|
||||
void CreateImageRenderTarget(
|
||||
ImageRenderTarget& render_target
|
||||
);
|
||||
|
||||
void SetResolution(
|
||||
Size const& resolution
|
||||
);
|
||||
|
||||
void SetResolutionMode(
|
||||
ResolutionMode mode
|
||||
void CreateTextureRenderTarget(
|
||||
TextureRenderTarget& render_target
|
||||
);
|
||||
|
||||
public:
|
||||
void Init(RenderConfig const& config);
|
||||
|
||||
void SetupComponent() override;
|
||||
|
||||
void DestroyComponent() override;
|
||||
|
|
|
|||
|
|
@ -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, /* 宽高自适应 */
|
||||
};
|
||||
}
|
||||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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<ID2D1Bitmap> const & bitmap)
|
||||
Texture::Texture(ComPtr<ID2D1Bitmap> 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<UInt32> Image::GetSizeInPixels() const
|
||||
math::Vec2T<UInt32> Texture::GetSizeInPixels() const
|
||||
{
|
||||
if (bitmap_)
|
||||
{
|
||||
|
|
@ -120,7 +126,12 @@ namespace kiwano
|
|||
return math::Vec2T<UInt32>{};
|
||||
}
|
||||
|
||||
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<ID2D1Bitmap> Image::GetBitmap() const
|
||||
ComPtr<ID2D1Bitmap> Texture::GetBitmap() const
|
||||
{
|
||||
return bitmap_;
|
||||
}
|
||||
|
||||
void Image::SetBitmap(ComPtr<ID2D1Bitmap> bitmap)
|
||||
void Texture::SetBitmap(ComPtr<ID2D1Bitmap> bitmap)
|
||||
{
|
||||
bitmap_ = bitmap;
|
||||
}
|
||||
|
||||
void Texture::SetDefaultInterpolationMode(InterpolationMode mode)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<ID2D1Bitmap> 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<UInt32> 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<ID2D1Bitmap> bitmap_;
|
||||
InterpolationMode interpolation_mode_;
|
||||
|
||||
static InterpolationMode default_interpolation_mode_;
|
||||
};
|
||||
}
|
||||
|
|
@ -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 <typename _CacheTy>
|
||||
|
|
@ -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>(image_cache_, file_path, file_path.hash());
|
||||
return CreateOrGetCache<Texture>(texture_cache_, file_path, file_path.hash());
|
||||
}
|
||||
|
||||
Image ImageCache::AddOrGetImage(Resource const& res)
|
||||
Texture TextureCache::AddOrGetTexture(Resource const& res)
|
||||
{
|
||||
return CreateOrGetCache<Image>(image_cache_, res, res.GetId());
|
||||
return CreateOrGetCache<Texture>(texture_cache_, res, res.GetId());
|
||||
}
|
||||
|
||||
GifImage ImageCache::AddOrGetGifImage(String const& file_path)
|
||||
GifImage TextureCache::AddOrGetGifImage(String const& file_path)
|
||||
{
|
||||
return CreateOrGetCache<GifImage>(gif_image_cache_, file_path, file_path.hash());
|
||||
return CreateOrGetCache<GifImage>(gif_texture_cache_, file_path, file_path.hash());
|
||||
}
|
||||
|
||||
GifImage ImageCache::AddOrGetGifImage(Resource const& res)
|
||||
GifImage TextureCache::AddOrGetGifImage(Resource const& res)
|
||||
{
|
||||
return CreateOrGetCache<GifImage>(gif_image_cache_, res, res.GetId());
|
||||
return CreateOrGetCache<GifImage>(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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<ImageCache>
|
||||
class KGE_API TextureCache
|
||||
: public Singleton<TextureCache>
|
||||
{
|
||||
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<UInt32, Image>;
|
||||
ImageMap image_cache_;
|
||||
using TextureMap = UnorderedMap<UInt32, Texture>;
|
||||
TextureMap texture_cache_;
|
||||
|
||||
using GifImageMap = UnorderedMap<UInt32, GifImage>;
|
||||
GifImageMap gif_image_cache_;
|
||||
GifImageMap gif_texture_cache_;
|
||||
};
|
||||
}
|
||||
|
|
@ -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<ID2D1Bitmap>& bitmap,
|
||||
_In_ String const& file_path
|
||||
HRESULT CreateBitmapConverter(
|
||||
_Out_ ComPtr<IWICFormatConverter>& converter,
|
||||
_In_opt_ ComPtr<IWICBitmapSource> source,
|
||||
_In_ REFWICPixelFormatGUID format,
|
||||
WICBitmapDitherType dither,
|
||||
_In_opt_ ComPtr<IWICPalette> palette,
|
||||
double alpha_threshold_percent,
|
||||
WICBitmapPaletteType palette_translate
|
||||
) override;
|
||||
|
||||
HRESULT CreateBitmapFromResource(
|
||||
HRESULT CreateBitmapFromConverter(
|
||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
||||
_In_ Resource const& res
|
||||
_In_opt_ const D2D1_BITMAP_PROPERTIES* properties,
|
||||
_In_ ComPtr<IWICFormatConverter> converter
|
||||
) override;
|
||||
|
||||
HRESULT CreateBitmapDecoderFromFile(
|
||||
_Out_ ComPtr<IWICBitmapDecoder>& decoder,
|
||||
const String& file_path
|
||||
) override;
|
||||
|
||||
HRESULT CreateBitmapDecoderFromResource(
|
||||
_Out_ ComPtr<IWICBitmapDecoder>& decoder,
|
||||
const Resource& resource
|
||||
) override;
|
||||
|
||||
HRESULT CreateTextFormat(
|
||||
|
|
@ -56,7 +71,6 @@ namespace kiwano
|
|||
HRESULT CreateTextLayout(
|
||||
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
|
||||
_In_ String const& text,
|
||||
_In_ TextStyle const& text_style,
|
||||
_In_ ComPtr<IDWriteTextFormat> const& text_format
|
||||
) const override;
|
||||
|
||||
|
|
@ -68,8 +82,6 @@ namespace kiwano
|
|||
_In_ ComPtr<ID2D1Bitmap1> const& target
|
||||
) override;
|
||||
|
||||
ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const override;
|
||||
|
||||
void DiscardResources() override;
|
||||
|
||||
public:
|
||||
|
|
@ -85,10 +97,6 @@ namespace kiwano
|
|||
protected:
|
||||
unsigned long ref_count_;
|
||||
Float32 dpi_;
|
||||
|
||||
ComPtr<ID2D1StrokeStyle> d2d_miter_stroke_style_;
|
||||
ComPtr<ID2D1StrokeStyle> d2d_bevel_stroke_style_;
|
||||
ComPtr<ID2D1StrokeStyle> d2d_round_stroke_style_;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -195,16 +203,16 @@ namespace kiwano
|
|||
ComPtr<IWICImagingFactory> imaging_factory;
|
||||
ComPtr<IDWriteFactory> dwrite_factory;
|
||||
|
||||
D2D1_FACTORY_OPTIONS options;
|
||||
ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
|
||||
#ifdef KGE_DEBUG
|
||||
options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
|
||||
D2D1_FACTORY_OPTIONS config;
|
||||
ZeroMemory(&config, sizeof(D2D1_FACTORY_OPTIONS));
|
||||
#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
|
||||
config.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
|
||||
#endif
|
||||
|
||||
hr = D2D1CreateFactory(
|
||||
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
||||
__uuidof(ID2D1Factory1),
|
||||
&options,
|
||||
&config,
|
||||
reinterpret_cast<void**>(&d2d_factory)
|
||||
);
|
||||
|
||||
|
|
@ -316,143 +324,113 @@ namespace kiwano
|
|||
device_context_->SetTarget(target_bitmap_.get());
|
||||
}
|
||||
|
||||
HRESULT D2DDeviceResources::CreateBitmapFromFile(_Out_ ComPtr<ID2D1Bitmap> & bitmap, _In_ String const & file_path)
|
||||
HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtr<IWICFormatConverter>& converter, _In_opt_ ComPtr<IWICBitmapSource> source,
|
||||
_In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither, _In_opt_ ComPtr<IWICPalette> 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<IWICFormatConverter> output;
|
||||
HRESULT hr = imaging_factory_->CreateFormatConverter(&output);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
KGE_WARNING_LOG(L"Image file '%s' not found!", file_path.c_str());
|
||||
return E_FAIL;
|
||||
hr = output->Initialize(
|
||||
source.get(),
|
||||
format,
|
||||
dither,
|
||||
palette.get(),
|
||||
alpha_threshold_percent,
|
||||
palette_translate
|
||||
);
|
||||
}
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
ComPtr<IWICBitmapFrameDecode> source;
|
||||
ComPtr<IWICStream> stream;
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
ComPtr<ID2D1Bitmap> bitmap_tmp;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
converter = output;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT D2DDeviceResources::CreateBitmapFromConverter(_Out_ ComPtr<ID2D1Bitmap>& bitmap, _In_opt_ const D2D1_BITMAP_PROPERTIES* properties,
|
||||
_In_ ComPtr<IWICFormatConverter> converter)
|
||||
{
|
||||
if (!device_context_)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
ComPtr<ID2D1Bitmap> output;
|
||||
HRESULT hr = device_context_->CreateBitmapFromWicBitmap(
|
||||
converter.get(),
|
||||
properties,
|
||||
&output
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bitmap = output;
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT D2DDeviceResources::CreateBitmapDecoderFromFile(_Out_ ComPtr<IWICBitmapDecoder>& decoder, const String& file_path)
|
||||
{
|
||||
if (!imaging_factory_)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
ComPtr<IWICBitmapDecoder> 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<ID2D1Bitmap> & bitmap, _In_ Resource const & res)
|
||||
HRESULT D2DDeviceResources::CreateBitmapDecoderFromResource(_Out_ ComPtr<IWICBitmapDecoder>& decoder, const Resource& resource)
|
||||
{
|
||||
if (!imaging_factory_ || !device_context_)
|
||||
if (!imaging_factory_)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
ComPtr<IWICBitmapDecoder> decoder;
|
||||
ComPtr<IWICBitmapFrameDecode> source;
|
||||
ComPtr<IWICStream> stream;
|
||||
ComPtr<IWICFormatConverter> converter;
|
||||
ComPtr<ID2D1Bitmap> 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<IWICStream> stream;
|
||||
hr = imaging_factory_->CreateStream(&stream);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = stream->InitializeFromMemory(
|
||||
static_cast<WICInProcPointer>(res_data.buffer),
|
||||
res_data.size
|
||||
);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = stream->InitializeFromMemory(
|
||||
static_cast<WICInProcPointer>(res_data.buffer),
|
||||
res_data.size
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = imaging_factory_->CreateDecoderFromStream(
|
||||
stream.get(),
|
||||
nullptr,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&decoder
|
||||
);
|
||||
}
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
ComPtr<IWICBitmapDecoder> decoder_output;
|
||||
hr = imaging_factory_->CreateDecoderFromStream(
|
||||
stream.get(),
|
||||
nullptr,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&decoder_output
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = decoder->GetFrame(0, &source);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = imaging_factory_->CreateFormatConverter(&converter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 图片格式转换成 32bppPBGRA
|
||||
hr = converter->Initialize(
|
||||
source.get(),
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = device_context_->CreateBitmapFromWicBitmap(
|
||||
converter.get(),
|
||||
nullptr,
|
||||
&bitmap_tmp
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
bitmap = bitmap_tmp;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
decoder = decoder_output;
|
||||
}
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
|
@ -470,7 +448,7 @@ namespace kiwano
|
|||
font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL,
|
||||
font.size,
|
||||
L"en-us",
|
||||
L"",
|
||||
&output
|
||||
);
|
||||
|
||||
|
|
@ -481,95 +459,21 @@ namespace kiwano
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout, _In_ String const & text,
|
||||
_In_ TextStyle const & text_style, _In_ ComPtr<IDWriteTextFormat> const& text_format) const
|
||||
HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout>& text_layout, _In_ String const& text,
|
||||
_In_ ComPtr<IDWriteTextFormat> const& text_format) const
|
||||
{
|
||||
if (!dwrite_factory_)
|
||||
return E_UNEXPECTED;
|
||||
|
||||
HRESULT hr;
|
||||
ComPtr<IDWriteTextLayout> output;
|
||||
UInt32 length = static_cast<UInt32>(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<UINT32>(text.length()),
|
||||
text_format.get(),
|
||||
0,
|
||||
0,
|
||||
&output
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
|
@ -578,15 +482,4 @@ namespace kiwano
|
|||
return hr;
|
||||
}
|
||||
|
||||
ID2D1StrokeStyle* D2DDeviceResources::GetStrokeStyle(StrokeStyle stroke) const
|
||||
{
|
||||
switch (stroke)
|
||||
{
|
||||
case StrokeStyle::Miter: return d2d_miter_stroke_style_.get(); break;
|
||||
case StrokeStyle::Bevel: return d2d_bevel_stroke_style_.get(); break;
|
||||
case StrokeStyle::Round: return d2d_round_stroke_style_.get(); break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,14 +189,30 @@ namespace kiwano
|
|||
public:
|
||||
static HRESULT Create(ID2DDeviceResources** device_resources);
|
||||
|
||||
virtual HRESULT CreateBitmapFromFile(
|
||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
||||
_In_ String const& file_path
|
||||
virtual HRESULT CreateBitmapConverter(
|
||||
_Out_ ComPtr<IWICFormatConverter>& converter,
|
||||
_In_opt_ ComPtr<IWICBitmapSource> source,
|
||||
_In_ REFWICPixelFormatGUID format,
|
||||
WICBitmapDitherType dither,
|
||||
_In_opt_ ComPtr<IWICPalette> palette,
|
||||
double alpha_threshold_percent,
|
||||
WICBitmapPaletteType palette_translate
|
||||
) = 0;
|
||||
|
||||
virtual HRESULT CreateBitmapFromResource(
|
||||
virtual HRESULT CreateBitmapFromConverter(
|
||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
||||
_In_ Resource const& res
|
||||
_In_opt_ const D2D1_BITMAP_PROPERTIES* properties,
|
||||
_In_ ComPtr<IWICFormatConverter> converter
|
||||
) = 0;
|
||||
|
||||
virtual HRESULT CreateBitmapDecoderFromFile(
|
||||
_Out_ ComPtr<IWICBitmapDecoder>& decoder,
|
||||
const String& file_path
|
||||
) = 0;
|
||||
|
||||
virtual HRESULT CreateBitmapDecoderFromResource(
|
||||
_Out_ ComPtr<IWICBitmapDecoder>& decoder,
|
||||
const Resource& resource
|
||||
) = 0;
|
||||
|
||||
virtual HRESULT CreateTextFormat(
|
||||
|
|
@ -207,12 +223,9 @@ namespace kiwano
|
|||
virtual HRESULT CreateTextLayout(
|
||||
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
|
||||
_In_ String const& text,
|
||||
_In_ TextStyle const& text_style,
|
||||
_In_ ComPtr<IDWriteTextFormat> const& text_format
|
||||
) const = 0;
|
||||
|
||||
virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0;
|
||||
|
||||
virtual HRESULT SetD2DDevice(
|
||||
_In_ ComPtr<ID2D1Device> const& device
|
||||
) = 0;
|
||||
|
|
@ -230,6 +243,10 @@ namespace kiwano
|
|||
inline ID2D1DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.get(); }
|
||||
inline ID2D1Bitmap1* GetTargetBitmap() const { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); }
|
||||
|
||||
inline ID2D1StrokeStyle* GetMiterStrokeStyle() const { KGE_ASSERT(d2d_miter_stroke_style_); return d2d_miter_stroke_style_.get(); }
|
||||
inline ID2D1StrokeStyle* GetBevelStrokeStyle() const { KGE_ASSERT(d2d_bevel_stroke_style_); return d2d_bevel_stroke_style_.get(); }
|
||||
inline ID2D1StrokeStyle* GetRoundStrokeStyle() const { KGE_ASSERT(d2d_round_stroke_style_); return d2d_round_stroke_style_.get(); }
|
||||
|
||||
protected:
|
||||
ComPtr<ID2D1Factory1> factory_;
|
||||
ComPtr<ID2D1Device> device_;
|
||||
|
|
@ -238,6 +255,10 @@ namespace kiwano
|
|||
|
||||
ComPtr<IWICImagingFactory> imaging_factory_;
|
||||
ComPtr<IDWriteFactory> dwrite_factory_;
|
||||
|
||||
ComPtr<ID2D1StrokeStyle> d2d_miter_stroke_style_;
|
||||
ComPtr<ID2D1StrokeStyle> d2d_bevel_stroke_style_;
|
||||
ComPtr<ID2D1StrokeStyle> d2d_round_stroke_style_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_();
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "../2d/Frame.h"
|
||||
#include "../2d/FrameSequence.h"
|
||||
#include "../renderer/GifImage.h"
|
||||
#include "../renderer/FontCollection.h"
|
||||
#include <fstream>
|
||||
|
||||
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<String, Function<bool(ResourceCache*, tinyxml2::XMLElement*)>> load_xml_funcs = {
|
||||
Map<String, Function<bool(ResourceCache*, const tinyxml2::XMLElement*)>> load_xml_funcs = {
|
||||
{ L"latest", __resource_cache_01::LoadXmlData },
|
||||
{ L"0.1", __resource_cache_01::LoadXmlData },
|
||||
};
|
||||
|
|
@ -138,7 +139,7 @@ namespace kiwano
|
|||
return LoadFromXml(&doc);
|
||||
}
|
||||
|
||||
bool ResourceCache::LoadFromXml(tinyxml2::XMLDocument* doc)
|
||||
bool ResourceCache::LoadFromXml(const tinyxml2::XMLDocument* doc)
|
||||
{
|
||||
if (doc)
|
||||
{
|
||||
|
|
@ -201,8 +202,8 @@ namespace kiwano
|
|||
if (files.empty())
|
||||
return 0;
|
||||
|
||||
Vector<FramePtr> image_arr;
|
||||
image_arr.reserve(files.size());
|
||||
Vector<FramePtr> frames;
|
||||
frames.reserve(files.size());
|
||||
|
||||
for (const auto& file : files)
|
||||
{
|
||||
|
|
@ -211,20 +212,20 @@ namespace kiwano
|
|||
{
|
||||
if (ptr->Load(file))
|
||||
{
|
||||
image_arr.push_back(ptr);
|
||||
frames.push_back(ptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!image_arr.empty())
|
||||
if (!frames.empty())
|
||||
{
|
||||
FrameSequencePtr frames = new (std::nothrow) FrameSequence(image_arr);
|
||||
return AddFrameSequence(id, frames);
|
||||
FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames);
|
||||
return AddFrameSequence(id, fs);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
UInt32 ResourceCache::AddFrameSequence(String const & id, String const& file_path, Int32 cols, Int32 rows)
|
||||
UInt32 ResourceCache::AddFrameSequence(String const & id, String const& file_path, Int32 cols, Int32 rows, Float32 padding_x, Float32 padding_y)
|
||||
{
|
||||
if (cols <= 0 || rows <= 0)
|
||||
return 0;
|
||||
|
|
@ -235,27 +236,31 @@ namespace kiwano
|
|||
|
||||
Float32 raw_width = raw->GetWidth();
|
||||
Float32 raw_height = raw->GetHeight();
|
||||
Float32 width = raw_width / cols;
|
||||
Float32 height = raw_height / rows;
|
||||
Float32 width = (raw_width - (cols - 1) * padding_x) / cols;
|
||||
Float32 height = (raw_height - (rows - 1) * padding_y) / rows;
|
||||
|
||||
Vector<FramePtr> image_arr;
|
||||
image_arr.reserve(rows * cols);
|
||||
Vector<FramePtr> frames;
|
||||
frames.reserve(rows * cols);
|
||||
|
||||
Float32 dty = 0;
|
||||
for (Int32 i = 0; i < rows; i++)
|
||||
{
|
||||
Float32 dtx = 0;
|
||||
for (Int32 j = 0; j < cols; j++)
|
||||
{
|
||||
FramePtr ptr = new (std::nothrow) Frame(raw->GetImage());
|
||||
FramePtr ptr = new (std::nothrow) Frame(raw->GetTexture());
|
||||
if (ptr)
|
||||
{
|
||||
ptr->SetCropRect(Rect{ j * width, i * height, (j + 1) * width, (i + 1) * height });
|
||||
image_arr.push_back(ptr);
|
||||
ptr->SetCropRect(Rect{ dtx, dty, dtx + width, dty + height });
|
||||
frames.push_back(ptr);
|
||||
}
|
||||
dtx += (width + padding_x);
|
||||
}
|
||||
dty += (height + padding_y);
|
||||
}
|
||||
|
||||
FrameSequencePtr frames = new (std::nothrow) FrameSequence(image_arr);
|
||||
return AddFrameSequence(id, frames);
|
||||
FrameSequencePtr fs = new (std::nothrow) FrameSequence(frames);
|
||||
return AddFrameSequence(id, fs);
|
||||
}
|
||||
|
||||
UInt32 ResourceCache::AddFrameSequence(String const & id, FrameSequencePtr frames)
|
||||
|
|
@ -278,6 +283,36 @@ namespace kiwano
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ResourceCache::AddGifImage(String const& id, GifImage const& gif)
|
||||
{
|
||||
if (gif.IsValid())
|
||||
{
|
||||
gif_cache_.insert(std::make_pair(id, gif));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ResourceCache::AddGifImage(String const& id, String const& file_path)
|
||||
{
|
||||
GifImage gif;
|
||||
if (gif.Load(file_path))
|
||||
{
|
||||
return AddGifImage(id, gif);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ResourceCache::AddFontCollection(String const& id, FontCollection const& collection)
|
||||
{
|
||||
if (collection.IsValid())
|
||||
{
|
||||
font_collection_cache_.insert(std::make_pair(id, collection));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
FramePtr ResourceCache::GetFrame(String const & id) const
|
||||
{
|
||||
return Get<Frame>(id);
|
||||
|
|
@ -288,6 +323,22 @@ namespace kiwano
|
|||
return Get<FrameSequence>(id);
|
||||
}
|
||||
|
||||
GifImage ResourceCache::GetGifImage(String const& id) const
|
||||
{
|
||||
auto iter = gif_cache_.find(id);
|
||||
if (iter != gif_cache_.end())
|
||||
return iter->second;
|
||||
return GifImage();
|
||||
}
|
||||
|
||||
FontCollection ResourceCache::GetFontCollection(String const& id) const
|
||||
{
|
||||
auto iter = font_collection_cache_.find(id);
|
||||
if (iter != font_collection_cache_.end())
|
||||
return iter->second;
|
||||
return FontCollection();
|
||||
}
|
||||
|
||||
void ResourceCache::Delete(String const & id)
|
||||
{
|
||||
cache_.erase(id);
|
||||
|
|
@ -309,28 +360,28 @@ namespace kiwano
|
|||
String path;
|
||||
};
|
||||
|
||||
bool LoadImagesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* type,
|
||||
const String* file, const Vector<const WChar*>* files, Int32 rows, Int32 cols)
|
||||
bool LoadTexturesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* type, const String* file)
|
||||
{
|
||||
if (!gdata || !id) return false;
|
||||
|
||||
if (file)
|
||||
if (type && (*type) == L"gif")
|
||||
{
|
||||
if (!(*file).empty())
|
||||
{
|
||||
if (rows || cols)
|
||||
{
|
||||
// Frame slices
|
||||
return !!loader->AddFrameSequence(*id, gdata->path + (*file), std::max(cols, 1), std::max(rows, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple image
|
||||
return loader->AddFrame(*id, gdata->path + (*file));
|
||||
}
|
||||
}
|
||||
// GIF image
|
||||
return loader->AddGifImage(*id, gdata->path + (*file));
|
||||
}
|
||||
|
||||
if (file && !(*file).empty())
|
||||
{
|
||||
// Simple image
|
||||
return loader->AddFrame(*id, gdata->path + (*file));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoadTexturesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const Vector<const WChar*>* files)
|
||||
{
|
||||
if (!gdata || !id) return false;
|
||||
|
||||
// Frames
|
||||
if (files)
|
||||
{
|
||||
|
|
@ -350,6 +401,52 @@ namespace kiwano
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LoadTexturesFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const String* file,
|
||||
Int32 rows, Int32 cols, Float32 padding_x, Float32 padding_y)
|
||||
{
|
||||
if (!gdata || !id) return false;
|
||||
|
||||
if (file)
|
||||
{
|
||||
if (!(*file).empty())
|
||||
{
|
||||
if (rows || cols)
|
||||
{
|
||||
// Frame slices
|
||||
return !!loader->AddFrameSequence(*id, gdata->path + (*file), std::max(cols, 1), std::max(rows, 1), padding_x, padding_y);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple image
|
||||
return loader->AddFrame(*id, gdata->path + (*file));
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoadFontsFromData(ResourceCache* loader, GlobalData* gdata, const String* id, const Vector<String>* files)
|
||||
{
|
||||
if (!gdata || !id) return false;
|
||||
|
||||
// Font Collection
|
||||
if (files)
|
||||
{
|
||||
Vector<String> files_copy(*files);
|
||||
for (auto& file : files_copy)
|
||||
{
|
||||
file = gdata->path + file;
|
||||
}
|
||||
|
||||
FontCollection collection;
|
||||
if (collection.Load(files_copy))
|
||||
{
|
||||
return loader->AddFontCollection(*id, collection);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LoadJsonData(ResourceCache* loader, Json const& json_data)
|
||||
{
|
||||
GlobalData global_data;
|
||||
|
|
@ -371,6 +468,16 @@ namespace kiwano
|
|||
if (image.count(L"rows")) rows = image[L"rows"].as_int();
|
||||
if (image.count(L"cols")) cols = image[L"cols"].as_int();
|
||||
|
||||
if (rows || cols)
|
||||
{
|
||||
Float32 padding_x = 0, padding_y = 0;
|
||||
if (image.count(L"padding-x")) padding_x = image[L"padding-x"].get<Float32>();
|
||||
if (image.count(L"padding-y")) padding_y = image[L"padding-y"].get<Float32>();
|
||||
|
||||
if (!LoadTexturesFromData(loader, &global_data, id, file, rows, cols, padding_x, padding_y))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (image.count(L"files"))
|
||||
{
|
||||
Vector<const WChar*> files;
|
||||
|
|
@ -379,12 +486,33 @@ namespace kiwano
|
|||
{
|
||||
files.push_back(file.as_string().c_str());
|
||||
}
|
||||
if (!LoadImagesFromData(loader, &global_data, id, type, file, &files, rows, cols))
|
||||
if(!LoadTexturesFromData(loader, &global_data, id, &files))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!LoadImagesFromData(loader, &global_data, id, type, file, nullptr, rows, cols))
|
||||
if(!LoadTexturesFromData(loader, &global_data, id, type, file))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (json_data.count(L"fonts"))
|
||||
{
|
||||
for (const auto& font : json_data[L"fonts"])
|
||||
{
|
||||
String id;
|
||||
|
||||
if (font.count(L"id")) id = font[L"id"].as_string();
|
||||
if (font.count(L"files"))
|
||||
{
|
||||
Vector<String> files;
|
||||
files.reserve(font[L"files"].size());
|
||||
for (const auto& file : font[L"files"])
|
||||
{
|
||||
files.push_back(file.as_string());
|
||||
}
|
||||
if (!LoadFontsFromData(loader, &global_data, &id, &files))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -392,7 +520,7 @@ namespace kiwano
|
|||
return true;
|
||||
}
|
||||
|
||||
bool LoadXmlData(ResourceCache* loader, tinyxml2::XMLElement* elem)
|
||||
bool LoadXmlData(ResourceCache* loader, const tinyxml2::XMLElement* elem)
|
||||
{
|
||||
GlobalData global_data;
|
||||
if (auto path = elem->FirstChildElement(L"path"))
|
||||
|
|
@ -413,6 +541,16 @@ namespace kiwano
|
|||
if (auto attr = image->IntAttribute(L"rows")) rows = attr;
|
||||
if (auto attr = image->IntAttribute(L"cols")) cols = attr;
|
||||
|
||||
if (rows || cols)
|
||||
{
|
||||
Float32 padding_x = 0, padding_y = 0;
|
||||
if (auto attr = image->FloatAttribute(L"padding-x")) padding_x = attr;
|
||||
if (auto attr = image->FloatAttribute(L"padding-y")) padding_y = attr;
|
||||
|
||||
if (!LoadTexturesFromData(loader, &global_data, &id, &file, rows, cols, padding_x, padding_y))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (file.empty() && !image->NoChildren())
|
||||
{
|
||||
Vector<const WChar*> files_arr;
|
||||
|
|
@ -423,16 +561,36 @@ namespace kiwano
|
|||
files_arr.push_back(path);
|
||||
}
|
||||
}
|
||||
if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, &files_arr, rows, cols))
|
||||
if (!LoadTexturesFromData(loader, &global_data, &id, &files_arr))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!LoadImagesFromData(loader, &global_data, &id, &type, &file, nullptr, rows, cols))
|
||||
if (!LoadTexturesFromData(loader, &global_data, &id, &type, &file))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto fonts = elem->FirstChildElement(L"fonts"))
|
||||
{
|
||||
for (auto font = fonts->FirstChildElement(); font; font = font->NextSiblingElement())
|
||||
{
|
||||
String id;
|
||||
if (auto attr = font->Attribute(L"id")) id.assign(attr);
|
||||
|
||||
Vector<String> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ namespace kiwano
|
|||
bool LoadFromXmlFile(String const& file_path);
|
||||
|
||||
// 从 XML 文档对象加载资源信息
|
||||
bool LoadFromXml(tinyxml2::XMLDocument* doc);
|
||||
bool LoadFromXml(const tinyxml2::XMLDocument* doc);
|
||||
|
||||
// 添加帧图像
|
||||
bool AddFrame(String const& id, String const& file_path);
|
||||
|
|
@ -57,7 +57,7 @@ namespace kiwano
|
|||
|
||||
// 添加序列帧
|
||||
// 按行列数裁剪图片
|
||||
UInt32 AddFrameSequence(String const& id, String const& file_path, Int32 cols, Int32 rows = 1);
|
||||
UInt32 AddFrameSequence(String const& id, String const& file_path, Int32 cols, Int32 rows = 1, Float32 padding_x = 0, Float32 padding_y = 0);
|
||||
|
||||
// 添加序列帧
|
||||
UInt32 AddFrameSequence(String const& id, FrameSequencePtr frames);
|
||||
|
|
@ -65,12 +65,27 @@ namespace kiwano
|
|||
// 添加对象
|
||||
bool AddObjectBase(String const& id, ObjectBasePtr obj);
|
||||
|
||||
// Ìí¼Ó GIF ͼÏñ
|
||||
bool AddGifImage(String const& id, GifImage const& gif);
|
||||
|
||||
// Ìí¼Ó GIF ͼÏñ
|
||||
bool AddGifImage(String const& id, String const& file_path);
|
||||
|
||||
// Ìí¼Ó×ÖÌ弯
|
||||
bool AddFontCollection(String const& id, FontCollection const& collection);
|
||||
|
||||
// 获取帧图像
|
||||
FramePtr GetFrame(String const& id) const;
|
||||
|
||||
// 获取序列帧
|
||||
FrameSequencePtr GetFrameSequence(String const& id) const;
|
||||
|
||||
// »ñÈ¡ GIF ͼÏñ
|
||||
GifImage GetGifImage(String const& id) const;
|
||||
|
||||
// »ñÈ¡×ÖÌ弯
|
||||
FontCollection GetFontCollection(String const& id) const;
|
||||
|
||||
// 删除指定资源
|
||||
void Delete(String const& id);
|
||||
|
||||
|
|
@ -93,5 +108,8 @@ namespace kiwano
|
|||
|
||||
protected:
|
||||
UnorderedMap<String, ObjectBasePtr> cache_;
|
||||
|
||||
UnorderedMap<String, GifImage> gif_cache_;
|
||||
UnorderedMap<String, FontCollection> font_collection_cache_;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue