Refactor GifImage
This commit is contained in:
parent
66558a3bc4
commit
a5fe64fa2c
|
|
@ -30,7 +30,6 @@ namespace kiwano
|
||||||
, next_index_(0)
|
, next_index_(0)
|
||||||
, total_loop_count_(1)
|
, total_loop_count_(1)
|
||||||
, loop_count_(0)
|
, loop_count_(0)
|
||||||
, disposal_type_(DisposalType::Unknown)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -45,9 +44,9 @@ namespace kiwano
|
||||||
Load(res);
|
Load(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
GifSprite::GifSprite(GifImage texture)
|
GifSprite::GifSprite(GifImage gif)
|
||||||
{
|
{
|
||||||
Load(texture);
|
Load(gif);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GifSprite::Load(String const& file_path)
|
bool GifSprite::Load(String const& file_path)
|
||||||
|
|
@ -62,24 +61,24 @@ namespace kiwano
|
||||||
return Load(texture);
|
return Load(texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GifSprite::Load(GifImage texture)
|
bool GifSprite::Load(GifImage gif)
|
||||||
{
|
{
|
||||||
if (texture.IsValid())
|
if (gif.IsValid())
|
||||||
{
|
{
|
||||||
texture_ = texture;
|
gif_ = gif;
|
||||||
|
|
||||||
next_index_ = 0;
|
next_index_ = 0;
|
||||||
loop_count_ = 0;
|
loop_count_ = 0;
|
||||||
disposal_type_ = DisposalType::None;
|
frame_.disposal_type = GifImage::DisposalType::None;
|
||||||
|
|
||||||
SetSize(Size{ static_cast<Float32>(texture_.GetWidthInPixels()), static_cast<Float32>(texture_.GetHeightInPixels()) });
|
SetSize(Size{ static_cast<Float32>(gif_.GetWidthInPixels()), static_cast<Float32>(gif_.GetHeightInPixels()) });
|
||||||
|
|
||||||
if (!frame_rt_.IsValid())
|
if (!frame_rt_.IsValid())
|
||||||
{
|
{
|
||||||
Renderer::GetInstance()->CreateTextureRenderTarget(frame_rt_);
|
Renderer::GetInstance()->CreateTextureRenderTarget(frame_rt_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (texture_.GetFramesCount() > 0)
|
if (gif_.GetFramesCount() > 0)
|
||||||
{
|
{
|
||||||
ComposeNextFrame();
|
ComposeNextFrame();
|
||||||
}
|
}
|
||||||
|
|
@ -90,11 +89,11 @@ namespace kiwano
|
||||||
|
|
||||||
void GifSprite::OnRender(RenderTarget* rt)
|
void GifSprite::OnRender(RenderTarget* rt)
|
||||||
{
|
{
|
||||||
if (frame_.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix()))
|
if (frame_.raw.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix()))
|
||||||
{
|
{
|
||||||
PrepareRender(rt);
|
PrepareRender(rt);
|
||||||
|
|
||||||
rt->DrawTexture(frame_);
|
rt->DrawTexture(frame_.raw, &frame_.rect, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,24 +101,30 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
Actor::Update(dt);
|
Actor::Update(dt);
|
||||||
|
|
||||||
if (texture_.IsValid() && animating_)
|
if (gif_.IsValid() && animating_)
|
||||||
{
|
{
|
||||||
frame_elapsed_ += dt;
|
frame_elapsed_ += dt;
|
||||||
if (frame_delay_ <= frame_elapsed_)
|
if (frame_.delay <= frame_elapsed_)
|
||||||
{
|
{
|
||||||
frame_delay_ -= frame_elapsed_;
|
frame_.delay -= frame_elapsed_;
|
||||||
frame_elapsed_ = 0;
|
frame_elapsed_ = 0;
|
||||||
ComposeNextFrame();
|
ComposeNextFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GifSprite::SetGifImage(GifImage const& gif)
|
||||||
|
{
|
||||||
|
gif_ = gif;
|
||||||
|
RestartAnimation();
|
||||||
|
}
|
||||||
|
|
||||||
void GifSprite::RestartAnimation()
|
void GifSprite::RestartAnimation()
|
||||||
{
|
{
|
||||||
animating_ = true;
|
animating_ = true;
|
||||||
next_index_ = 0;
|
next_index_ = 0;
|
||||||
loop_count_ = 0;
|
loop_count_ = 0;
|
||||||
disposal_type_ = DisposalType::None;
|
frame_.disposal_type = GifImage::DisposalType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifSprite::ComposeNextFrame()
|
void GifSprite::ComposeNextFrame()
|
||||||
|
|
@ -130,27 +135,27 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
DisposeCurrentFrame();
|
DisposeCurrentFrame();
|
||||||
OverlayNextFrame();
|
OverlayNextFrame();
|
||||||
} while (frame_delay_.IsZero() && !IsLastFrame());
|
} while (frame_.delay.IsZero() && !IsLastFrame());
|
||||||
|
|
||||||
animating_ = (!EndOfAnimation() && texture_.GetFramesCount() > 1);
|
animating_ = (!EndOfAnimation() && gif_.GetFramesCount() > 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifSprite::DisposeCurrentFrame()
|
void GifSprite::DisposeCurrentFrame()
|
||||||
{
|
{
|
||||||
switch (disposal_type_)
|
switch (frame_.disposal_type)
|
||||||
{
|
{
|
||||||
case DisposalType::Unknown:
|
case GifImage::DisposalType::Unknown:
|
||||||
case DisposalType::None:
|
case GifImage::DisposalType::None:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DisposalType::Background:
|
case GifImage::DisposalType::Background:
|
||||||
{
|
{
|
||||||
ClearCurrentFrameArea();
|
ClearCurrentFrameArea();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case DisposalType::Previous:
|
case GifImage::DisposalType::Previous:
|
||||||
{
|
{
|
||||||
RestoreSavedFrame();
|
RestoreSavedFrame();
|
||||||
break;
|
break;
|
||||||
|
|
@ -163,43 +168,30 @@ namespace kiwano
|
||||||
|
|
||||||
void GifSprite::OverlayNextFrame()
|
void GifSprite::OverlayNextFrame()
|
||||||
{
|
{
|
||||||
Texture raw_texture;
|
Renderer::GetInstance()->CreateGifImageFrame(frame_, gif_, next_index_);
|
||||||
|
|
||||||
HRESULT hr = texture_.GetRawFrame(next_index_, raw_texture, 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();
|
frame_rt_.BeginDraw();
|
||||||
|
|
||||||
if (next_index_ == 0)
|
if (next_index_ == 0)
|
||||||
{
|
{
|
||||||
// ÖØÐ»æÖƱ³¾°
|
|
||||||
frame_rt_.Clear(texture_.GetBackgroundColor());
|
|
||||||
loop_count_++;
|
loop_count_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame_rt_.DrawTexture(raw_texture, nullptr, &frame_rect_);
|
frame_rt_.DrawTexture(frame_.raw, nullptr, &frame_.rect);
|
||||||
frame_rt_.EndDraw();
|
frame_rt_.EndDraw();
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
Texture frame_to_render = frame_rt_.GetOutput();
|
Texture frame_to_render = frame_rt_.GetOutput();
|
||||||
|
if (frame_to_render.IsValid())
|
||||||
hr = frame_to_render.IsValid() ? S_OK : E_FAIL;
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
{
|
||||||
frame_ = frame_to_render;
|
frame_.raw = frame_to_render;
|
||||||
next_index_ = (++next_index_) % texture_.GetFramesCount();
|
next_index_ = (++next_index_) % gif_.GetFramesCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,8 +204,6 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
done_cb_();
|
done_cb_();
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifSprite::SaveComposedFrame()
|
void GifSprite::SaveComposedFrame()
|
||||||
|
|
@ -270,8 +260,8 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
frame_rt_.BeginDraw();
|
frame_rt_.BeginDraw();
|
||||||
|
|
||||||
frame_rt_.PushClipRect(frame_rect_);
|
frame_rt_.PushClipRect(frame_.rect);
|
||||||
frame_rt_.Clear(texture_.GetBackgroundColor());
|
frame_rt_.Clear();
|
||||||
frame_rt_.PopClipRect();
|
frame_rt_.PopClipRect();
|
||||||
|
|
||||||
return frame_rt_.EndDraw();
|
return frame_rt_.EndDraw();
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ namespace kiwano
|
||||||
: public Actor
|
: public Actor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using DisposalType = GifImage::DisposalType;
|
|
||||||
using LoopDoneCallback = Function<void(Int32)>;
|
using LoopDoneCallback = Function<void(Int32)>;
|
||||||
using DoneCallback = Function<void()>;
|
using DoneCallback = Function<void()>;
|
||||||
|
|
||||||
|
|
@ -46,7 +45,7 @@ namespace kiwano
|
||||||
);
|
);
|
||||||
|
|
||||||
GifSprite(
|
GifSprite(
|
||||||
GifImage texture
|
GifImage gif
|
||||||
);
|
);
|
||||||
|
|
||||||
bool Load(
|
bool Load(
|
||||||
|
|
@ -58,7 +57,7 @@ namespace kiwano
|
||||||
);
|
);
|
||||||
|
|
||||||
bool Load(
|
bool Load(
|
||||||
GifImage texture
|
GifImage gif
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置 GIF 动画循环次数
|
// 设置 GIF 动画循环次数
|
||||||
|
|
@ -70,12 +69,17 @@ namespace kiwano
|
||||||
// 设置 GIF 动画结束回调函数
|
// 设置 GIF 动画结束回调函数
|
||||||
inline void SetDoneCallback(DoneCallback const& cb) { done_cb_ = cb; }
|
inline void SetDoneCallback(DoneCallback const& cb) { done_cb_ = cb; }
|
||||||
|
|
||||||
|
// ÉèÖà GIF ͼÏñ
|
||||||
|
void SetGifImage(GifImage const& gif);
|
||||||
|
|
||||||
// 重新播放动画
|
// 重新播放动画
|
||||||
void RestartAnimation();
|
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;
|
void OnRender(RenderTarget* rt) override;
|
||||||
|
|
||||||
|
|
@ -103,14 +107,11 @@ namespace kiwano
|
||||||
Int32 total_loop_count_;
|
Int32 total_loop_count_;
|
||||||
Int32 loop_count_;
|
Int32 loop_count_;
|
||||||
UInt32 next_index_;
|
UInt32 next_index_;
|
||||||
Duration frame_delay_;
|
|
||||||
Duration frame_elapsed_;
|
Duration frame_elapsed_;
|
||||||
DisposalType disposal_type_;
|
|
||||||
LoopDoneCallback loop_cb_;
|
LoopDoneCallback loop_cb_;
|
||||||
DoneCallback done_cb_;
|
DoneCallback done_cb_;
|
||||||
GifImage texture_;
|
GifImage gif_;
|
||||||
Texture frame_;
|
GifImage::Frame frame_;
|
||||||
Rect frame_rect_;
|
|
||||||
Texture saved_frame_;
|
Texture saved_frame_;
|
||||||
TextureRenderTarget frame_rt_;
|
TextureRenderTarget frame_rt_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
|
#include "../platform/Application.h"
|
||||||
|
|
||||||
#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
|
#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
|
#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);
|
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()
|
Window::Window()
|
||||||
: handle_(nullptr)
|
: handle_(nullptr)
|
||||||
, width_(0)
|
, width_(0)
|
||||||
|
|
@ -68,7 +79,7 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::Init(String const& title, Int32 width, Int32 height, UInt32 icon, bool resizable, bool fullscreen, WNDPROC proc)
|
void Window::Init(WindowConfig const& config, WNDPROC proc)
|
||||||
{
|
{
|
||||||
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
||||||
WNDCLASSEX wcex = { 0 };
|
WNDCLASSEX wcex = { 0 };
|
||||||
|
|
@ -84,9 +95,10 @@ namespace kiwano
|
||||||
wcex.lpszMenuName = nullptr;
|
wcex.lpszMenuName = nullptr;
|
||||||
wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW);
|
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);
|
::RegisterClassExW(&wcex);
|
||||||
|
|
@ -105,22 +117,24 @@ namespace kiwano
|
||||||
device_name_ = new WCHAR[len + 1];
|
device_name_ = new WCHAR[len + 1];
|
||||||
lstrcpyW(device_name_, monitor_info_ex.szDevice);
|
lstrcpyW(device_name_, monitor_info_ex.szDevice);
|
||||||
|
|
||||||
|
UInt32 width = config.width;
|
||||||
|
UInt32 height = config.height;
|
||||||
Int32 left = -1;
|
Int32 left = -1;
|
||||||
Int32 top = -1;
|
Int32 top = -1;
|
||||||
|
|
||||||
resizable_ = resizable;
|
resizable_ = config.resizable;
|
||||||
is_fullscreen_ = fullscreen;
|
is_fullscreen_ = config.fullscreen;
|
||||||
|
|
||||||
if (is_fullscreen_)
|
if (is_fullscreen_)
|
||||||
{
|
{
|
||||||
top = monitor_info_ex.rcMonitor.top;
|
top = monitor_info_ex.rcMonitor.top;
|
||||||
left = monitor_info_ex.rcMonitor.left;
|
left = monitor_info_ex.rcMonitor.left;
|
||||||
|
|
||||||
if (width > monitor_info_ex.rcWork.right - left)
|
if (width > static_cast<UInt32>(monitor_info_ex.rcWork.right - left))
|
||||||
width = monitor_info_ex.rcWork.right - left;
|
width = static_cast<UInt32>(monitor_info_ex.rcWork.right - left);
|
||||||
|
|
||||||
if (height > monitor_info_ex.rcWork.bottom - top)
|
if (height > static_cast<UInt32>(monitor_info_ex.rcWork.bottom - top))
|
||||||
height = monitor_info_ex.rcWork.bottom - top;
|
height = static_cast<UInt32>(monitor_info_ex.rcWork.bottom - top);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -145,7 +159,7 @@ namespace kiwano
|
||||||
handle_ = ::CreateWindowExW(
|
handle_ = ::CreateWindowExW(
|
||||||
is_fullscreen_ ? WS_EX_TOPMOST : 0,
|
is_fullscreen_ ? WS_EX_TOPMOST : 0,
|
||||||
KGE_WND_CLASS_NAME,
|
KGE_WND_CLASS_NAME,
|
||||||
title.c_str(),
|
config.title.c_str(),
|
||||||
GetWindowStyle(),
|
GetWindowStyle(),
|
||||||
left,
|
left,
|
||||||
top,
|
top,
|
||||||
|
|
@ -417,4 +431,5 @@ namespace kiwano
|
||||||
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
|
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,26 @@ namespace kiwano
|
||||||
SizeWE,
|
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
|
class KGE_API Window
|
||||||
|
|
@ -74,15 +94,7 @@ namespace kiwano
|
||||||
void SetCursor(CursorType cursor);
|
void SetCursor(CursorType cursor);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(
|
void Init(WindowConfig const& config, WNDPROC proc);
|
||||||
String const& title,
|
|
||||||
Int32 width,
|
|
||||||
Int32 height,
|
|
||||||
UInt32 icon,
|
|
||||||
bool resizable,
|
|
||||||
bool fullscreen,
|
|
||||||
WNDPROC proc
|
|
||||||
);
|
|
||||||
|
|
||||||
void Prepare();
|
void Prepare();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Compile-time options for Kiwano
|
// Compile-time configurations for Kiwano
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
|
||||||
|
|
@ -20,12 +20,10 @@
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "modules.h"
|
#include "modules.h"
|
||||||
#include "../base/Window.h"
|
|
||||||
#include "../base/Logger.h"
|
#include "../base/Logger.h"
|
||||||
#include "../base/input.h"
|
#include "../base/input.h"
|
||||||
#include "../base/Director.h"
|
#include "../base/Director.h"
|
||||||
#include "../renderer/TextureCache.h"
|
#include "../renderer/TextureCache.h"
|
||||||
#include "../renderer/Renderer.h"
|
|
||||||
#include "../utils/ResourceCache.h"
|
#include "../utils/ResourceCache.h"
|
||||||
#include <windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
|
#include <windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
|
||||||
#include <imm.h> // ImmAssociateContext
|
#include <imm.h> // ImmAssociateContext
|
||||||
|
|
@ -43,17 +41,19 @@ namespace kiwano
|
||||||
Queue<FunctionToPerform> functions_to_perform_;
|
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)
|
Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon)
|
||||||
: title(title)
|
{
|
||||||
, width(width)
|
window.title = title;
|
||||||
, height(height)
|
window.width = width;
|
||||||
, icon(icon)
|
window.height = height;
|
||||||
, clear_color(clear_color)
|
window.icon = icon;
|
||||||
, vsync(vsync)
|
}
|
||||||
, resizable(resizable)
|
|
||||||
, fullscreen(fullscreen)
|
Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config)
|
||||||
, debug(debug)
|
{
|
||||||
{}
|
window = wnd_config;
|
||||||
|
render = render_config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
|
|
@ -79,20 +79,10 @@ namespace kiwano
|
||||||
::CoUninitialize();
|
::CoUninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::Init(const Options& options)
|
void Application::Init(const Config& config)
|
||||||
{
|
{
|
||||||
Window::GetInstance()->Init(
|
Window::GetInstance()->Init(config.window, Application::WndProc);
|
||||||
options.title,
|
Renderer::GetInstance()->Init(config.render);
|
||||||
options.width,
|
|
||||||
options.height,
|
|
||||||
options.icon,
|
|
||||||
options.resizable,
|
|
||||||
options.fullscreen,
|
|
||||||
Application::WndProc
|
|
||||||
);
|
|
||||||
|
|
||||||
Renderer::GetInstance()->SetClearColor(options.clear_color);
|
|
||||||
Renderer::GetInstance()->SetVSyncEnabled(options.vsync);
|
|
||||||
|
|
||||||
// Setup all components
|
// Setup all components
|
||||||
for (Component* c : components_)
|
for (Component* c : components_)
|
||||||
|
|
@ -100,7 +90,7 @@ namespace kiwano
|
||||||
c->SetupComponent();
|
c->SetupComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.debug)
|
if (config.debug)
|
||||||
{
|
{
|
||||||
Director::GetInstance()->ShowDebugInfo(true);
|
Director::GetInstance()->ShowDebugInfo(true);
|
||||||
Renderer::GetInstance()->SetCollectingStatus(true);
|
Renderer::GetInstance()->SetCollectingStatus(true);
|
||||||
|
|
@ -299,10 +289,11 @@ namespace kiwano
|
||||||
|
|
||||||
LRESULT CALLBACK Application::WndProc(HWND hwnd, UInt32 msg, WPARAM wparam, LPARAM lparam)
|
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)));
|
Application* app = reinterpret_cast<Application*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
|
||||||
|
if (app == nullptr)
|
||||||
if (!app)
|
{
|
||||||
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
|
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
|
||||||
|
}
|
||||||
|
|
||||||
// Handle Message
|
// Handle Message
|
||||||
for (Component* c : app->components_)
|
for (Component* c : app->components_)
|
||||||
|
|
|
||||||
|
|
@ -23,32 +23,27 @@
|
||||||
#include "../base/time.h"
|
#include "../base/time.h"
|
||||||
#include "../base/Component.h"
|
#include "../base/Component.h"
|
||||||
#include "../base/Event.hpp"
|
#include "../base/Event.hpp"
|
||||||
#include "../renderer/Color.h"
|
#include "../base/Window.h"
|
||||||
|
#include "../renderer/Renderer.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
struct Options
|
struct Config
|
||||||
{
|
{
|
||||||
String title; // 标题
|
WindowConfig window; // ´°¿ÚÉèÖÃ
|
||||||
Int32 width; // 宽度
|
RenderConfig render; // äÖȾÉèÖÃ
|
||||||
Int32 height; // 高度
|
bool debug; // µ÷ÊÔģʽ
|
||||||
UInt32 icon; // 图标资源 ID
|
|
||||||
Color clear_color; // 清屏颜色
|
|
||||||
bool vsync; // 垂直同步
|
|
||||||
bool resizable; // 窗口大小可拉伸
|
|
||||||
bool fullscreen; // 全屏模式
|
|
||||||
bool debug; // 调试模式
|
|
||||||
|
|
||||||
Options(
|
Config(
|
||||||
String const& title = L"Kiwano Game",
|
String const& title = L"Kiwano Game",
|
||||||
Int32 width = 640,
|
UInt32 width = 640,
|
||||||
Int32 height = 480,
|
UInt32 height = 480,
|
||||||
UInt32 icon = 0,
|
UInt32 icon = 0
|
||||||
Color clear_color = Color::Black,
|
);
|
||||||
bool vsync = true,
|
|
||||||
bool resizable = false,
|
Config(
|
||||||
bool fullscreen = false,
|
WindowConfig const& wnd_config,
|
||||||
bool debug = false
|
RenderConfig const& render_config = RenderConfig()
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -64,7 +59,7 @@ namespace kiwano
|
||||||
|
|
||||||
// 初始化
|
// 初始化
|
||||||
void Init(
|
void Init(
|
||||||
Options const& options = Options{}
|
Config const& config = Config()
|
||||||
);
|
);
|
||||||
|
|
||||||
// 初始化成功时
|
// 初始化成功时
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ namespace kiwano
|
||||||
: frames_count_(0)
|
: frames_count_(0)
|
||||||
, width_in_pixels_(0)
|
, width_in_pixels_(0)
|
||||||
, height_in_pixels_(0)
|
, height_in_pixels_(0)
|
||||||
, bg_color_{}
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,15 +81,6 @@ namespace kiwano
|
||||||
|
|
||||||
HRESULT GifImage::GetGlobalMetadata()
|
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;
|
HRESULT hr = decoder_ ? S_OK : E_FAIL;
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
|
@ -100,317 +90,91 @@ namespace kiwano
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
ComPtr<IWICMetadataQueryReader> metadata_reader;
|
||||||
hr = decoder_->GetMetadataQueryReader(&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))
|
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))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
width = prop_val.uiVal;
|
// 获取宽度
|
||||||
}
|
hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Width", &prop_val);
|
||||||
::PropVariantClear(&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, Texture& 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))
|
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))
|
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);
|
::PropVariantClear(&prop_val);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// 获取 DisposalType 失败,可能图片是只有一帧的图片
|
|
||||||
disposal_type = DisposalType::Unknown;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::PropVariantClear(&prop_val);
|
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,7 @@ namespace kiwano
|
||||||
|
|
||||||
inline UInt32 GetHeightInPixels() const { return height_in_pixels_; }
|
inline UInt32 GetHeightInPixels() const { return height_in_pixels_; }
|
||||||
|
|
||||||
inline UInt32 GetFramesCount() const { return frames_count_; }
|
inline UInt32 GetFramesCount() const { return frames_count_; }
|
||||||
|
|
||||||
inline Color GetBackgroundColor() const { return bg_color_; }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class DisposalType
|
enum class DisposalType
|
||||||
|
|
@ -56,13 +54,15 @@ namespace kiwano
|
||||||
Previous
|
Previous
|
||||||
};
|
};
|
||||||
|
|
||||||
HRESULT GetRawFrame(
|
struct Frame
|
||||||
UInt32 frame_index,
|
{
|
||||||
Texture& raw_frame,
|
Duration delay;
|
||||||
Rect& frame_rect,
|
Texture raw;
|
||||||
Duration& delay,
|
Rect rect;
|
||||||
DisposalType& disposal_type
|
DisposalType disposal_type;
|
||||||
);
|
|
||||||
|
Frame() : disposal_type(DisposalType::Unknown) {}
|
||||||
|
};
|
||||||
|
|
||||||
inline ComPtr<IWICBitmapDecoder> GetDecoder() const { return decoder_; }
|
inline ComPtr<IWICBitmapDecoder> GetDecoder() const { return decoder_; }
|
||||||
|
|
||||||
|
|
@ -71,16 +71,11 @@ namespace kiwano
|
||||||
protected:
|
protected:
|
||||||
HRESULT GetGlobalMetadata();
|
HRESULT GetGlobalMetadata();
|
||||||
|
|
||||||
HRESULT GetBackgroundColor(
|
|
||||||
ComPtr<IWICMetadataQueryReader> metadata_reader
|
|
||||||
);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UInt32 frames_count_;
|
UInt32 frames_count_;
|
||||||
UInt32 width_in_pixels_;
|
UInt32 width_in_pixels_;
|
||||||
UInt32 height_in_pixels_;
|
UInt32 height_in_pixels_;
|
||||||
Color bg_color_;
|
|
||||||
|
|
||||||
ComPtr<IWICBitmapDecoder> decoder_;
|
ComPtr<IWICBitmapDecoder> decoder_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,12 @@
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
RenderConfig::RenderConfig(Color clear_color, bool vsync)
|
||||||
|
: clear_color(clear_color)
|
||||||
|
, vsync(vsync)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Renderer::Renderer()
|
Renderer::Renderer()
|
||||||
: hwnd_(nullptr)
|
: hwnd_(nullptr)
|
||||||
, vsync_(true)
|
, vsync_(true)
|
||||||
|
|
@ -37,6 +43,12 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::Init(RenderConfig const& config)
|
||||||
|
{
|
||||||
|
SetClearColor(config.clear_color);
|
||||||
|
SetVSyncEnabled(config.vsync);
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::SetupComponent()
|
void Renderer::SetupComponent()
|
||||||
{
|
{
|
||||||
KGE_LOG(L"Creating device resources");
|
KGE_LOG(L"Creating device resources");
|
||||||
|
|
@ -253,14 +265,50 @@ namespace kiwano
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!FileUtil::ExistsFile(file_path))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str());
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
ComPtr<ID2D1Bitmap> bitmap;
|
ComPtr<IWICBitmapDecoder> decoder;
|
||||||
hr = d2d_res_->CreateBitmapFromFile(bitmap, file_path);
|
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
texture.SetBitmap(bitmap);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,7 +318,7 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::CreateTexture(Texture& texture, Resource const& res)
|
void Renderer::CreateTexture(Texture& texture, Resource const& resource)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!d2d_res_)
|
if (!d2d_res_)
|
||||||
|
|
@ -280,12 +328,42 @@ namespace kiwano
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
ComPtr<ID2D1Bitmap> bitmap;
|
ComPtr<IWICBitmapDecoder> decoder;
|
||||||
hr = d2d_res_->CreateBitmapFromResource(bitmap, res);
|
hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
texture.SetBitmap(bitmap);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -295,7 +373,7 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::CreateGifImage(GifImage& texture, String const& file_path)
|
void Renderer::CreateGifImage(GifImage& gif, String const& file_path)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!d2d_res_)
|
if (!d2d_res_)
|
||||||
|
|
@ -312,17 +390,11 @@ namespace kiwano
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
ComPtr<IWICBitmapDecoder> decoder;
|
ComPtr<IWICBitmapDecoder> decoder;
|
||||||
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename(
|
hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path);
|
||||||
file_path.c_str(),
|
|
||||||
nullptr,
|
|
||||||
GENERIC_READ,
|
|
||||||
WICDecodeMetadataCacheOnLoad,
|
|
||||||
&decoder
|
|
||||||
);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
texture.SetDecoder(decoder);
|
gif.SetDecoder(decoder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -332,7 +404,7 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::CreateGifImage(GifImage& texture, Resource const& res)
|
void Renderer::CreateGifImage(GifImage& gif, Resource const& resource)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!d2d_res_)
|
if (!d2d_res_)
|
||||||
|
|
@ -340,37 +412,14 @@ namespace kiwano
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource::Data res_data = res.GetData();
|
|
||||||
|
|
||||||
hr = res_data ? S_OK : E_FAIL;
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
ComPtr<IWICStream> stream;
|
ComPtr<IWICBitmapDecoder> decoder;
|
||||||
hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream);
|
hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = stream->InitializeFromMemory(
|
gif.SetDecoder(decoder);
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
texture.SetDecoder(decoder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -380,6 +429,173 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, UInt32 frame_index)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!d2d_res_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gif.GetDecoder() == nullptr)
|
||||||
|
{
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::CreateFontCollection(FontCollection& collection, Vector<String> const& file_paths)
|
void Renderer::CreateFontCollection(FontCollection& collection, Vector<String> const& file_paths)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,18 @@ namespace kiwano
|
||||||
typedef ID3D11DeviceResources ID3DDeviceResources;
|
typedef ID3D11DeviceResources ID3DDeviceResources;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// 斡횡<E696A1>零
|
||||||
|
struct RenderConfig
|
||||||
|
{
|
||||||
|
Color clear_color; // 헌팁奈<ED8C81>
|
||||||
|
bool vsync; // 뉩殮谿꼍
|
||||||
|
|
||||||
|
RenderConfig(
|
||||||
|
Color clear_color = Color::Black,
|
||||||
|
bool vsync = true
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// 分辨率模式
|
// 分辨率模式
|
||||||
// 分辨率模式决定了将画面渲染到视区上的方式
|
// 分辨率模式决定了将画面渲染到视区上的方式
|
||||||
// Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认)
|
// Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认)
|
||||||
|
|
@ -89,17 +101,23 @@ namespace kiwano
|
||||||
|
|
||||||
void CreateTexture(
|
void CreateTexture(
|
||||||
Texture& texture,
|
Texture& texture,
|
||||||
Resource const& res
|
Resource const& resource
|
||||||
);
|
);
|
||||||
|
|
||||||
void CreateGifImage(
|
void CreateGifImage(
|
||||||
GifImage& texture,
|
GifImage& gif,
|
||||||
String const& file_path
|
String const& file_path
|
||||||
);
|
);
|
||||||
|
|
||||||
void CreateGifImage(
|
void CreateGifImage(
|
||||||
GifImage& texture,
|
GifImage& gif,
|
||||||
Resource const& res
|
Resource const& resource
|
||||||
|
);
|
||||||
|
|
||||||
|
void CreateGifImageFrame(
|
||||||
|
GifImage::Frame& frame,
|
||||||
|
GifImage const& gif,
|
||||||
|
UInt32 frame_index
|
||||||
);
|
);
|
||||||
|
|
||||||
void CreateFontCollection(
|
void CreateFontCollection(
|
||||||
|
|
@ -156,6 +174,8 @@ namespace kiwano
|
||||||
);
|
);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void Init(RenderConfig const& config);
|
||||||
|
|
||||||
void SetupComponent() override;
|
void SetupComponent() override;
|
||||||
|
|
||||||
void DestroyComponent() override;
|
void DestroyComponent() override;
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
#include "D2DDeviceResources.h"
|
#include "D2DDeviceResources.h"
|
||||||
#include "../../base/Logger.h"
|
#include "../../base/Logger.h"
|
||||||
#include "../../utils/FileUtil.h"
|
|
||||||
|
|
||||||
#pragma comment(lib, "d2d1.lib")
|
#pragma comment(lib, "d2d1.lib")
|
||||||
#pragma comment(lib, "dwrite.lib")
|
#pragma comment(lib, "dwrite.lib")
|
||||||
|
|
@ -38,14 +37,30 @@ namespace kiwano
|
||||||
HRESULT CreateDeviceIndependentResources();
|
HRESULT CreateDeviceIndependentResources();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HRESULT CreateBitmapFromFile(
|
HRESULT CreateBitmapConverter(
|
||||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
_Out_ ComPtr<IWICFormatConverter>& converter,
|
||||||
_In_ String const& file_path
|
_In_opt_ ComPtr<IWICBitmapSource> source,
|
||||||
|
_In_ REFWICPixelFormatGUID format,
|
||||||
|
WICBitmapDitherType dither,
|
||||||
|
_In_opt_ ComPtr<IWICPalette> palette,
|
||||||
|
double alpha_threshold_percent,
|
||||||
|
WICBitmapPaletteType palette_translate
|
||||||
) override;
|
) override;
|
||||||
|
|
||||||
HRESULT CreateBitmapFromResource(
|
HRESULT CreateBitmapFromConverter(
|
||||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
_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;
|
) override;
|
||||||
|
|
||||||
HRESULT CreateTextFormat(
|
HRESULT CreateTextFormat(
|
||||||
|
|
@ -189,16 +204,16 @@ namespace kiwano
|
||||||
ComPtr<IWICImagingFactory> imaging_factory;
|
ComPtr<IWICImagingFactory> imaging_factory;
|
||||||
ComPtr<IDWriteFactory> dwrite_factory;
|
ComPtr<IDWriteFactory> dwrite_factory;
|
||||||
|
|
||||||
D2D1_FACTORY_OPTIONS options;
|
D2D1_FACTORY_OPTIONS config;
|
||||||
ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS));
|
ZeroMemory(&config, sizeof(D2D1_FACTORY_OPTIONS));
|
||||||
#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
|
#if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
|
||||||
options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
|
config.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hr = D2D1CreateFactory(
|
hr = D2D1CreateFactory(
|
||||||
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
||||||
__uuidof(ID2D1Factory1),
|
__uuidof(ID2D1Factory1),
|
||||||
&options,
|
&config,
|
||||||
reinterpret_cast<void**>(&d2d_factory)
|
reinterpret_cast<void**>(&d2d_factory)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -310,143 +325,113 @@ namespace kiwano
|
||||||
device_context_->SetTarget(target_bitmap_.get());
|
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;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
if (!FileUtil::ExistsFile(file_path))
|
ComPtr<IWICFormatConverter> output;
|
||||||
|
HRESULT hr = imaging_factory_->CreateFormatConverter(&output);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str());
|
hr = output->Initialize(
|
||||||
return E_FAIL;
|
source.get(),
|
||||||
|
format,
|
||||||
|
dither,
|
||||||
|
palette.get(),
|
||||||
|
alpha_threshold_percent,
|
||||||
|
palette_translate
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ComPtr<IWICBitmapDecoder> decoder;
|
if (SUCCEEDED(hr))
|
||||||
ComPtr<IWICBitmapFrameDecode> source;
|
{
|
||||||
ComPtr<IWICStream> stream;
|
converter = output;
|
||||||
ComPtr<IWICFormatConverter> converter;
|
}
|
||||||
ComPtr<ID2D1Bitmap> bitmap_tmp;
|
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(
|
HRESULT hr = imaging_factory_->CreateDecoderFromFilename(
|
||||||
file_path.c_str(),
|
file_path.c_str(),
|
||||||
nullptr,
|
nullptr,
|
||||||
GENERIC_READ,
|
GENERIC_READ,
|
||||||
WICDecodeMetadataCacheOnLoad,
|
WICDecodeMetadataCacheOnLoad,
|
||||||
&decoder
|
&decoder_output
|
||||||
);
|
);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = decoder->GetFrame(0, &source);
|
decoder = decoder_output;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return hr;
|
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;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
ComPtr<IWICBitmapDecoder> decoder;
|
Resource::Data res_data = resource.GetData();
|
||||||
ComPtr<IWICBitmapFrameDecode> source;
|
|
||||||
ComPtr<IWICStream> stream;
|
|
||||||
ComPtr<IWICFormatConverter> converter;
|
|
||||||
ComPtr<ID2D1Bitmap> bitmap_tmp;
|
|
||||||
|
|
||||||
// 加载资源
|
|
||||||
Resource::Data res_data = res.GetData();
|
|
||||||
HRESULT hr = res_data ? S_OK : E_FAIL;
|
HRESULT hr = res_data ? S_OK : E_FAIL;
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
ComPtr<IWICStream> stream;
|
||||||
hr = imaging_factory_->CreateStream(&stream);
|
hr = imaging_factory_->CreateStream(&stream);
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = stream->InitializeFromMemory(
|
hr = stream->InitializeFromMemory(
|
||||||
static_cast<WICInProcPointer>(res_data.buffer),
|
static_cast<WICInProcPointer>(res_data.buffer),
|
||||||
res_data.size
|
res_data.size
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = imaging_factory_->CreateDecoderFromStream(
|
ComPtr<IWICBitmapDecoder> decoder_output;
|
||||||
stream.get(),
|
hr = imaging_factory_->CreateDecoderFromStream(
|
||||||
nullptr,
|
stream.get(),
|
||||||
WICDecodeMetadataCacheOnLoad,
|
nullptr,
|
||||||
&decoder
|
WICDecodeMetadataCacheOnLoad,
|
||||||
);
|
&decoder_output
|
||||||
}
|
);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = decoder->GetFrame(0, &source);
|
decoder = decoder_output;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -189,14 +189,30 @@ namespace kiwano
|
||||||
public:
|
public:
|
||||||
static HRESULT Create(ID2DDeviceResources** device_resources);
|
static HRESULT Create(ID2DDeviceResources** device_resources);
|
||||||
|
|
||||||
virtual HRESULT CreateBitmapFromFile(
|
virtual HRESULT CreateBitmapConverter(
|
||||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
_Out_ ComPtr<IWICFormatConverter>& converter,
|
||||||
_In_ String const& file_path
|
_In_opt_ ComPtr<IWICBitmapSource> source,
|
||||||
|
_In_ REFWICPixelFormatGUID format,
|
||||||
|
WICBitmapDitherType dither,
|
||||||
|
_In_opt_ ComPtr<IWICPalette> palette,
|
||||||
|
double alpha_threshold_percent,
|
||||||
|
WICBitmapPaletteType palette_translate
|
||||||
) = 0;
|
) = 0;
|
||||||
|
|
||||||
virtual HRESULT CreateBitmapFromResource(
|
virtual HRESULT CreateBitmapFromConverter(
|
||||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
_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;
|
) = 0;
|
||||||
|
|
||||||
virtual HRESULT CreateTextFormat(
|
virtual HRESULT CreateTextFormat(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue