diff --git a/src/kiwano/2d/GifSprite.cpp b/src/kiwano/2d/GifSprite.cpp index fa406a2f..7918f955 100644 --- a/src/kiwano/2d/GifSprite.cpp +++ b/src/kiwano/2d/GifSprite.cpp @@ -30,7 +30,6 @@ namespace kiwano , next_index_(0) , total_loop_count_(1) , loop_count_(0) - , disposal_type_(DisposalType::Unknown) { } @@ -45,9 +44,9 @@ namespace kiwano Load(res); } - GifSprite::GifSprite(GifImage texture) + GifSprite::GifSprite(GifImage gif) { - Load(texture); + Load(gif); } bool GifSprite::Load(String const& file_path) @@ -62,24 +61,24 @@ namespace kiwano return Load(texture); } - bool GifSprite::Load(GifImage texture) + bool GifSprite::Load(GifImage gif) { - if (texture.IsValid()) + if (gif.IsValid()) { - texture_ = texture; + gif_ = gif; next_index_ = 0; loop_count_ = 0; - disposal_type_ = DisposalType::None; + frame_.disposal_type = GifImage::DisposalType::None; - SetSize(Size{ static_cast(texture_.GetWidthInPixels()), static_cast(texture_.GetHeightInPixels()) }); + SetSize(Size{ static_cast(gif_.GetWidthInPixels()), static_cast(gif_.GetHeightInPixels()) }); if (!frame_rt_.IsValid()) { Renderer::GetInstance()->CreateTextureRenderTarget(frame_rt_); } - if (texture_.GetFramesCount() > 0) + if (gif_.GetFramesCount() > 0) { ComposeNextFrame(); } @@ -90,11 +89,11 @@ namespace kiwano void GifSprite::OnRender(RenderTarget* rt) { - if (frame_.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix())) + if (frame_.raw.IsValid() && rt->CheckVisibility(GetBounds(), GetTransformMatrix())) { PrepareRender(rt); - rt->DrawTexture(frame_); + rt->DrawTexture(frame_.raw, &frame_.rect, nullptr); } } @@ -102,24 +101,30 @@ namespace kiwano { Actor::Update(dt); - if (texture_.IsValid() && animating_) + if (gif_.IsValid() && animating_) { frame_elapsed_ += dt; - if (frame_delay_ <= frame_elapsed_) + if (frame_.delay <= frame_elapsed_) { - frame_delay_ -= frame_elapsed_; + frame_.delay -= frame_elapsed_; frame_elapsed_ = 0; ComposeNextFrame(); } } } + void GifSprite::SetGifImage(GifImage const& gif) + { + gif_ = gif; + RestartAnimation(); + } + void GifSprite::RestartAnimation() { animating_ = true; next_index_ = 0; loop_count_ = 0; - disposal_type_ = DisposalType::None; + frame_.disposal_type = GifImage::DisposalType::None; } void GifSprite::ComposeNextFrame() @@ -130,27 +135,27 @@ namespace kiwano { DisposeCurrentFrame(); OverlayNextFrame(); - } while (frame_delay_.IsZero() && !IsLastFrame()); + } while (frame_.delay.IsZero() && !IsLastFrame()); - animating_ = (!EndOfAnimation() && texture_.GetFramesCount() > 1); + animating_ = (!EndOfAnimation() && gif_.GetFramesCount() > 1); } } void GifSprite::DisposeCurrentFrame() { - switch (disposal_type_) + switch (frame_.disposal_type) { - case DisposalType::Unknown: - case DisposalType::None: + case GifImage::DisposalType::Unknown: + case GifImage::DisposalType::None: break; - case DisposalType::Background: + case GifImage::DisposalType::Background: { ClearCurrentFrameArea(); break; } - case DisposalType::Previous: + case GifImage::DisposalType::Previous: { RestoreSavedFrame(); break; @@ -163,43 +168,30 @@ namespace kiwano void GifSprite::OverlayNextFrame() { - Texture raw_texture; - - HRESULT hr = texture_.GetRawFrame(next_index_, raw_texture, frame_rect_, frame_delay_, disposal_type_); + Renderer::GetInstance()->CreateGifImageFrame(frame_, gif_, next_index_); - if (SUCCEEDED(hr)) + if (frame_.disposal_type == GifImage::DisposalType::Previous) { - if (disposal_type_ == DisposalType::Previous) - { - SaveComposedFrame(); - } + SaveComposedFrame(); } - if (SUCCEEDED(hr)) + if (frame_rt_.IsValid()) { frame_rt_.BeginDraw(); if (next_index_ == 0) { - // 重新绘制背景 - frame_rt_.Clear(texture_.GetBackgroundColor()); loop_count_++; } - frame_rt_.DrawTexture(raw_texture, nullptr, &frame_rect_); + frame_rt_.DrawTexture(frame_.raw, nullptr, &frame_.rect); frame_rt_.EndDraw(); - } - if (SUCCEEDED(hr)) - { Texture frame_to_render = frame_rt_.GetOutput(); - - hr = frame_to_render.IsValid() ? S_OK : E_FAIL; - - if (SUCCEEDED(hr)) + if (frame_to_render.IsValid()) { - frame_ = frame_to_render; - next_index_ = (++next_index_) % texture_.GetFramesCount(); + frame_.raw = frame_to_render; + next_index_ = (++next_index_) % gif_.GetFramesCount(); } } @@ -212,8 +204,6 @@ namespace kiwano { done_cb_(); } - - ThrowIfFailed(hr); } void GifSprite::SaveComposedFrame() @@ -270,8 +260,8 @@ namespace kiwano { frame_rt_.BeginDraw(); - frame_rt_.PushClipRect(frame_rect_); - frame_rt_.Clear(texture_.GetBackgroundColor()); + frame_rt_.PushClipRect(frame_.rect); + frame_rt_.Clear(); frame_rt_.PopClipRect(); return frame_rt_.EndDraw(); diff --git a/src/kiwano/2d/GifSprite.h b/src/kiwano/2d/GifSprite.h index 12f77ac4..f9c3f0bf 100644 --- a/src/kiwano/2d/GifSprite.h +++ b/src/kiwano/2d/GifSprite.h @@ -31,7 +31,6 @@ namespace kiwano : public Actor { public: - using DisposalType = GifImage::DisposalType; using LoopDoneCallback = Function; using DoneCallback = Function; @@ -46,7 +45,7 @@ namespace kiwano ); GifSprite( - GifImage texture + GifImage gif ); bool Load( @@ -58,7 +57,7 @@ namespace kiwano ); bool Load( - GifImage texture + GifImage gif ); // 设置 GIF 动画循环次数 @@ -70,12 +69,17 @@ namespace kiwano // 设置 GIF 动画结束回调函数 inline void SetDoneCallback(DoneCallback const& cb) { done_cb_ = cb; } + // 设置 GIF 图像 + void SetGifImage(GifImage const& gif); + // 重新播放动画 void RestartAnimation(); - inline LoopDoneCallback GetLoopDoneCallback() const { return loop_cb_; } + inline LoopDoneCallback GetLoopDoneCallback() const { return loop_cb_; } - inline DoneCallback GetDoneCallback() const { return done_cb_; } + inline DoneCallback GetDoneCallback() const { return done_cb_; } + + inline GifImage const& GetGifImage() const { return gif_; } void OnRender(RenderTarget* rt) override; @@ -103,14 +107,11 @@ namespace kiwano Int32 total_loop_count_; Int32 loop_count_; UInt32 next_index_; - Duration frame_delay_; Duration frame_elapsed_; - DisposalType disposal_type_; LoopDoneCallback loop_cb_; DoneCallback done_cb_; - GifImage texture_; - Texture frame_; - Rect frame_rect_; + GifImage gif_; + GifImage::Frame frame_; Texture saved_frame_; TextureRenderTarget frame_rt_; }; diff --git a/src/kiwano/base/Window.cpp b/src/kiwano/base/Window.cpp index 827bf20c..38b213bb 100644 --- a/src/kiwano/base/Window.cpp +++ b/src/kiwano/base/Window.cpp @@ -20,6 +20,7 @@ #include "Window.h" #include "Logger.h" +#include "../platform/Application.h" #define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX #define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX @@ -39,6 +40,16 @@ namespace kiwano void RestoreResolution(WCHAR* device_name); } + WindowConfig::WindowConfig(String const& title, UInt32 width, UInt32 height, UInt32 icon, bool resizable, bool fullscreen) + : title(title) + , width(width) + , height(height) + , icon(icon) + , resizable(resizable) + , fullscreen(fullscreen) + { + } + Window::Window() : handle_(nullptr) , width_(0) @@ -68,7 +79,7 @@ namespace kiwano } } - void Window::Init(String const& title, Int32 width, Int32 height, UInt32 icon, bool resizable, bool fullscreen, WNDPROC proc) + void Window::Init(WindowConfig const& config, WNDPROC proc) { HINSTANCE hinst = GetModuleHandleW(nullptr); WNDCLASSEX wcex = { 0 }; @@ -84,9 +95,10 @@ namespace kiwano wcex.lpszMenuName = nullptr; wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW); - if (icon) + if (config.icon) { - wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(icon), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); + wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(config.icon), IMAGE_ICON, 0, 0, + LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE); } ::RegisterClassExW(&wcex); @@ -105,22 +117,24 @@ namespace kiwano device_name_ = new WCHAR[len + 1]; lstrcpyW(device_name_, monitor_info_ex.szDevice); + UInt32 width = config.width; + UInt32 height = config.height; Int32 left = -1; Int32 top = -1; - resizable_ = resizable; - is_fullscreen_ = fullscreen; + resizable_ = config.resizable; + is_fullscreen_ = config.fullscreen; if (is_fullscreen_) { top = monitor_info_ex.rcMonitor.top; left = monitor_info_ex.rcMonitor.left; - if (width > monitor_info_ex.rcWork.right - left) - width = monitor_info_ex.rcWork.right - left; + if (width > static_cast(monitor_info_ex.rcWork.right - left)) + width = static_cast(monitor_info_ex.rcWork.right - left); - if (height > monitor_info_ex.rcWork.bottom - top) - height = monitor_info_ex.rcWork.bottom - top; + if (height > static_cast(monitor_info_ex.rcWork.bottom - top)) + height = static_cast(monitor_info_ex.rcWork.bottom - top); } else { @@ -145,7 +159,7 @@ namespace kiwano handle_ = ::CreateWindowExW( is_fullscreen_ ? WS_EX_TOPMOST : 0, KGE_WND_CLASS_NAME, - title.c_str(), + config.title.c_str(), GetWindowStyle(), left, top, @@ -417,4 +431,5 @@ namespace kiwano ::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL); } } + } diff --git a/src/kiwano/base/Window.h b/src/kiwano/base/Window.h index 60befce3..15b15ad5 100644 --- a/src/kiwano/base/Window.h +++ b/src/kiwano/base/Window.h @@ -38,6 +38,26 @@ namespace kiwano SizeWE, }; + // 窗口设置 + struct WindowConfig + { + String title; // 标题 + UInt32 width; // 宽度 + UInt32 height; // 高度 + UInt32 icon; // 图标资源 ID + bool resizable; // 窗口大小可拉伸 + bool fullscreen; // 全屏模式 + + WindowConfig( + String const& title = L"Kiwano Game", + UInt32 width = 640, + UInt32 height = 480, + UInt32 icon = 0, + bool resizable = false, + bool fullscreen = false + ); + }; + // 窗口 class KGE_API Window @@ -74,15 +94,7 @@ namespace kiwano void SetCursor(CursorType cursor); public: - void Init( - String const& title, - Int32 width, - Int32 height, - UInt32 icon, - bool resizable, - bool fullscreen, - WNDPROC proc - ); + void Init(WindowConfig const& config, WNDPROC proc); void Prepare(); diff --git a/src/kiwano/config.h b/src/kiwano/config.h index 9d562a56..a3999050 100644 --- a/src/kiwano/config.h +++ b/src/kiwano/config.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Compile-time options for Kiwano +// Compile-time configurations for Kiwano //----------------------------------------------------------------------------- #pragma once diff --git a/src/kiwano/platform/Application.cpp b/src/kiwano/platform/Application.cpp index 57fe2374..3b127c28 100644 --- a/src/kiwano/platform/Application.cpp +++ b/src/kiwano/platform/Application.cpp @@ -20,12 +20,10 @@ #include "Application.h" #include "modules.h" -#include "../base/Window.h" #include "../base/Logger.h" #include "../base/input.h" #include "../base/Director.h" #include "../renderer/TextureCache.h" -#include "../renderer/Renderer.h" #include "../utils/ResourceCache.h" #include // GET_X_LPARAM, GET_Y_LPARAM #include // ImmAssociateContext @@ -43,17 +41,19 @@ namespace kiwano Queue functions_to_perform_; } - Options::Options(String const& title, Int32 width, Int32 height, UInt32 icon, Color clear_color, bool vsync, bool resizable, bool fullscreen, bool debug) - : title(title) - , width(width) - , height(height) - , icon(icon) - , clear_color(clear_color) - , vsync(vsync) - , resizable(resizable) - , fullscreen(fullscreen) - , debug(debug) - {} + Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon) + { + window.title = title; + window.width = width; + window.height = height; + window.icon = icon; + } + + Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config) + { + window = wnd_config; + render = render_config; + } } namespace kiwano @@ -79,20 +79,10 @@ namespace kiwano ::CoUninitialize(); } - void Application::Init(const Options& options) + void Application::Init(const Config& config) { - Window::GetInstance()->Init( - options.title, - options.width, - options.height, - options.icon, - options.resizable, - options.fullscreen, - Application::WndProc - ); - - Renderer::GetInstance()->SetClearColor(options.clear_color); - Renderer::GetInstance()->SetVSyncEnabled(options.vsync); + Window::GetInstance()->Init(config.window, Application::WndProc); + Renderer::GetInstance()->Init(config.render); // Setup all components for (Component* c : components_) @@ -100,7 +90,7 @@ namespace kiwano c->SetupComponent(); } - if (options.debug) + if (config.debug) { Director::GetInstance()->ShowDebugInfo(true); Renderer::GetInstance()->SetCollectingStatus(true); @@ -299,10 +289,11 @@ namespace kiwano LRESULT CALLBACK Application::WndProc(HWND hwnd, UInt32 msg, WPARAM wparam, LPARAM lparam) { - Application * app = reinterpret_cast(static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))); - - if (!app) + Application* app = reinterpret_cast(static_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))); + if (app == nullptr) + { return ::DefWindowProcW(hwnd, msg, wparam, lparam); + } // Handle Message for (Component* c : app->components_) diff --git a/src/kiwano/platform/Application.h b/src/kiwano/platform/Application.h index 97de5da3..2b24c3dd 100644 --- a/src/kiwano/platform/Application.h +++ b/src/kiwano/platform/Application.h @@ -23,32 +23,27 @@ #include "../base/time.h" #include "../base/Component.h" #include "../base/Event.hpp" -#include "../renderer/Color.h" +#include "../base/Window.h" +#include "../renderer/Renderer.h" namespace kiwano { - struct Options + struct Config { - String title; // 标题 - Int32 width; // 宽度 - Int32 height; // 高度 - UInt32 icon; // 图标资源 ID - Color clear_color; // 清屏颜色 - bool vsync; // 垂直同步 - bool resizable; // 窗口大小可拉伸 - bool fullscreen; // 全屏模式 - bool debug; // 调试模式 + WindowConfig window; // 窗口设置 + RenderConfig render; // 渲染设置 + bool debug; // 调试模式 - Options( + Config( String const& title = L"Kiwano Game", - Int32 width = 640, - Int32 height = 480, - UInt32 icon = 0, - Color clear_color = Color::Black, - bool vsync = true, - bool resizable = false, - bool fullscreen = false, - bool debug = false + UInt32 width = 640, + UInt32 height = 480, + UInt32 icon = 0 + ); + + Config( + WindowConfig const& wnd_config, + RenderConfig const& render_config = RenderConfig() ); }; @@ -64,7 +59,7 @@ namespace kiwano // 初始化 void Init( - Options const& options = Options{} + Config const& config = Config() ); // 初始化成功时 diff --git a/src/kiwano/renderer/GifImage.cpp b/src/kiwano/renderer/GifImage.cpp index 028b6b02..9add1fd5 100644 --- a/src/kiwano/renderer/GifImage.cpp +++ b/src/kiwano/renderer/GifImage.cpp @@ -28,7 +28,6 @@ namespace kiwano : frames_count_(0) , width_in_pixels_(0) , height_in_pixels_(0) - , bg_color_{} { } @@ -82,15 +81,6 @@ namespace kiwano HRESULT GifImage::GetGlobalMetadata() { - UInt32 width = 0; - UInt32 height = 0; - - PROPVARIANT prop_val; - ::PropVariantInit(&prop_val); - - ComPtr metadata_reader; - - // 获取帧数量 HRESULT hr = decoder_ ? S_OK : E_FAIL; if (SUCCEEDED(hr)) @@ -100,317 +90,91 @@ namespace kiwano if (SUCCEEDED(hr)) { + ComPtr metadata_reader; hr = decoder_->GetMetadataQueryReader(&metadata_reader); - } - - if (SUCCEEDED(hr)) - { - // 获取背景色 - if (FAILED(GetBackgroundColor(metadata_reader.get()))) - { - // 如果未能获得颜色,则默认为透明 - bg_color_ = Color(0, 0.f); - } - } - - // 获取全局 frame 大小 - if (SUCCEEDED(hr)) - { - // 获取宽度 - hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Width", &prop_val); if (SUCCEEDED(hr)) { - hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); + UInt32 width = 0; + UInt32 height = 0; + + PROPVARIANT prop_val; + ::PropVariantInit(&prop_val); + + // 获取全局 frame 大小 if (SUCCEEDED(hr)) { - width = prop_val.uiVal; - } - ::PropVariantClear(&prop_val); - } - } + // 获取宽度 + hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Width", &prop_val); - if (SUCCEEDED(hr)) - { - // 获取高度 - hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Height", &prop_val); - - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); - if (SUCCEEDED(hr)) - { - height = prop_val.uiVal; - } - ::PropVariantClear(&prop_val); - } - } - - if (SUCCEEDED(hr)) - { - // 获得像素纵横比 - hr = metadata_reader->GetMetadataByName(L"/logscrdesc/PixelAspectRatio", &prop_val); - - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt == VT_UI1 ? S_OK : E_FAIL); - if (SUCCEEDED(hr)) - { - if (prop_val.bVal != 0) - { - // 需要计算比率 - // 最高像素 1:4,最宽像素 4:1,增量为 1/64 - Float32 pixel_asp_ratio = (prop_val.bVal + 15.f) / 64.f; - - // 根据像素长宽比计算像素中的图像宽度和高度,只缩小图像 - if (pixel_asp_ratio > 1.f) - { - width_in_pixels_ = width; - height_in_pixels_ = static_cast(height / pixel_asp_ratio); - } - else - { - width_in_pixels_ = static_cast(width * pixel_asp_ratio); - height_in_pixels_ = height; - } - } - else - { - // 值为 0, 所以像素比为 1 - width_in_pixels_ = width; - height_in_pixels_ = height; - } - } - ::PropVariantClear(&prop_val); - } - } - - ::PropVariantClear(&prop_val); - return hr; - } - - HRESULT GifImage::GetBackgroundColor(ComPtr metadata_reader) - { - UChar bg_index = 0; - WICColor bgcolors[256]; - UInt32 colors_copied = 0; - ComPtr wic_palette; - - PROPVARIANT prop_val; - PropVariantInit(&prop_val); - - HRESULT hr = metadata_reader->GetMetadataByName(L"/logscrdesc/GlobalColorTableFlag", &prop_val); - - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt != VT_BOOL || !prop_val.boolVal) ? E_FAIL : S_OK; - ::PropVariantClear(&prop_val); - } - - if (SUCCEEDED(hr)) - { - hr = metadata_reader->GetMetadataByName(L"/logscrdesc/BackgroundColorIndex", &prop_val); - - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt != VT_UI1) ? E_FAIL : S_OK; - if (SUCCEEDED(hr)) - { - bg_index = prop_val.bVal; - } - ::PropVariantClear(&prop_val); - } - } - - if (SUCCEEDED(hr)) - { - auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory(); - hr = factory->CreatePalette(&wic_palette); - } - - if (SUCCEEDED(hr)) - { - hr = decoder_->CopyPalette(wic_palette.get()); - } - - if (SUCCEEDED(hr)) - { - hr = wic_palette->GetColors( - ARRAYSIZE(bgcolors), - bgcolors, - &colors_copied); - } - - if (SUCCEEDED(hr)) - { - hr = (bg_index >= colors_copied) ? E_FAIL : S_OK; - } - - if (SUCCEEDED(hr)) - { - // 转换为 ARGB 格式 - Float32 alpha = (bgcolors[bg_index] >> 24) / 255.f; - bg_color_ = Color(bgcolors[bg_index], alpha); - } - return hr; - } - - HRESULT GifImage::GetRawFrame(UInt32 frame_index, Texture& raw_frame, Rect& frame_rect, Duration& delay, DisposalType& disposal_type) - { - ComPtr converter; - ComPtr wic_frame; - ComPtr metadata_reader; - - PROPVARIANT prop_val; - PropVariantInit(&prop_val); - - // Retrieve the current frame - HRESULT hr = decoder_->GetFrame(frame_index, &wic_frame); - if (SUCCEEDED(hr)) - { - // Format convert to 32bppPBGRA which D2D expects - auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory(); - hr = factory->CreateFormatConverter(&converter); - } - - if (SUCCEEDED(hr)) - { - hr = converter->Initialize( - wic_frame.get(), - GUID_WICPixelFormat32bppPBGRA, - WICBitmapDitherTypeNone, - nullptr, - 0.f, - WICBitmapPaletteTypeCustom); - } - - if (SUCCEEDED(hr)) - { - auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext(); - - // Create a D2DBitmap from IWICBitmapSource - ComPtr raw_bitmap; - hr = ctx->CreateBitmapFromWicBitmap( - converter.get(), - nullptr, - &raw_bitmap - ); - - if (SUCCEEDED(hr)) - { - raw_frame.SetBitmap(raw_bitmap); - } - } - - if (SUCCEEDED(hr)) - { - // Get Metadata Query Reader from the frame - hr = wic_frame->GetMetadataQueryReader(&metadata_reader); - } - - // Get the Metadata for the current frame - if (SUCCEEDED(hr)) - { - hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val); - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); - if (SUCCEEDED(hr)) - { - frame_rect.left_top.x = static_cast(prop_val.uiVal); - } - PropVariantClear(&prop_val); - } - } - - if (SUCCEEDED(hr)) - { - hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val); - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); - if (SUCCEEDED(hr)) - { - frame_rect.left_top.y = static_cast(prop_val.uiVal); - } - PropVariantClear(&prop_val); - } - } - - if (SUCCEEDED(hr)) - { - hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val); - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); - if (SUCCEEDED(hr)) - { - frame_rect.right_bottom.x = frame_rect.left_top.x + static_cast(prop_val.uiVal); - } - PropVariantClear(&prop_val); - } - } - - if (SUCCEEDED(hr)) - { - hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val); - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); - if (SUCCEEDED(hr)) - { - frame_rect.right_bottom.y = frame_rect.left_top.y + static_cast(prop_val.uiVal); - } - PropVariantClear(&prop_val); - } - } - - if (SUCCEEDED(hr)) - { - hr = metadata_reader->GetMetadataByName(L"/grctlext/Delay", &prop_val); - - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); - - if (SUCCEEDED(hr)) - { - UInt32 udelay = 0; - hr = UIntMult(prop_val.uiVal, 10, &udelay); if (SUCCEEDED(hr)) { - delay.SetMilliseconds(static_cast(udelay)); + hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); + if (SUCCEEDED(hr)) + { + width = prop_val.uiVal; + } + ::PropVariantClear(&prop_val); } } - PropVariantClear(&prop_val); - } - else - { - delay = 0; - } - } - if (SUCCEEDED(hr)) - { - hr = metadata_reader->GetMetadataByName(L"/grctlext/Disposal", &prop_val); - - if (SUCCEEDED(hr)) - { - hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { - disposal_type = DisposalType(prop_val.bVal); + // 获取高度 + hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Height", &prop_val); + + if (SUCCEEDED(hr)) + { + hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); + if (SUCCEEDED(hr)) + { + height = prop_val.uiVal; + } + ::PropVariantClear(&prop_val); + } + } + + if (SUCCEEDED(hr)) + { + // 获得像素纵横比 + hr = metadata_reader->GetMetadataByName(L"/logscrdesc/PixelAspectRatio", &prop_val); + + if (SUCCEEDED(hr)) + { + hr = (prop_val.vt == VT_UI1 ? S_OK : E_FAIL); + if (SUCCEEDED(hr)) + { + if (prop_val.bVal != 0) + { + // 需要计算比率 + // 最高像素 1:4,最宽像素 4:1,增量为 1/64 + Float32 pixel_asp_ratio = (prop_val.bVal + 15.f) / 64.f; + + // 根据像素长宽比计算像素中的图像宽度和高度,只缩小图像 + if (pixel_asp_ratio > 1.f) + { + width_in_pixels_ = width; + height_in_pixels_ = static_cast(height / pixel_asp_ratio); + } + else + { + width_in_pixels_ = static_cast(width * pixel_asp_ratio); + height_in_pixels_ = height; + } + } + else + { + // 值为 0, 所以像素比为 1 + width_in_pixels_ = width; + height_in_pixels_ = height; + } + } + ::PropVariantClear(&prop_val); + } } ::PropVariantClear(&prop_val); } - else - { - // 获取 DisposalType 失败,可能图片是只有一帧的图片 - disposal_type = DisposalType::Unknown; - } } - - ::PropVariantClear(&prop_val); return hr; } diff --git a/src/kiwano/renderer/GifImage.h b/src/kiwano/renderer/GifImage.h index 55500c8a..339c63f1 100644 --- a/src/kiwano/renderer/GifImage.h +++ b/src/kiwano/renderer/GifImage.h @@ -43,9 +43,7 @@ namespace kiwano inline UInt32 GetHeightInPixels() const { return height_in_pixels_; } - inline UInt32 GetFramesCount() const { return frames_count_; } - - inline Color GetBackgroundColor() const { return bg_color_; } + inline UInt32 GetFramesCount() const { return frames_count_; } public: enum class DisposalType @@ -56,13 +54,15 @@ namespace kiwano Previous }; - HRESULT GetRawFrame( - UInt32 frame_index, - Texture& raw_frame, - Rect& frame_rect, - Duration& delay, - DisposalType& disposal_type - ); + struct Frame + { + Duration delay; + Texture raw; + Rect rect; + DisposalType disposal_type; + + Frame() : disposal_type(DisposalType::Unknown) {} + }; inline ComPtr GetDecoder() const { return decoder_; } @@ -71,16 +71,11 @@ namespace kiwano protected: HRESULT GetGlobalMetadata(); - HRESULT GetBackgroundColor( - ComPtr metadata_reader - ); - protected: UInt32 frames_count_; UInt32 width_in_pixels_; UInt32 height_in_pixels_; - Color bg_color_; - ComPtr decoder_; + ComPtr decoder_; }; } diff --git a/src/kiwano/renderer/Renderer.cpp b/src/kiwano/renderer/Renderer.cpp index 795a42b0..6599abd2 100644 --- a/src/kiwano/renderer/Renderer.cpp +++ b/src/kiwano/renderer/Renderer.cpp @@ -25,6 +25,12 @@ namespace kiwano { + RenderConfig::RenderConfig(Color clear_color, bool vsync) + : clear_color(clear_color) + , vsync(vsync) + { + } + Renderer::Renderer() : hwnd_(nullptr) , vsync_(true) @@ -37,6 +43,12 @@ namespace kiwano { } + void Renderer::Init(RenderConfig const& config) + { + SetClearColor(config.clear_color); + SetVSyncEnabled(config.vsync); + } + void Renderer::SetupComponent() { KGE_LOG(L"Creating device resources"); @@ -253,14 +265,50 @@ namespace kiwano hr = E_UNEXPECTED; } + if (!FileUtil::ExistsFile(file_path)) + { + KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str()); + hr = E_FAIL; + } + if (SUCCEEDED(hr)) { - ComPtr bitmap; - hr = d2d_res_->CreateBitmapFromFile(bitmap, file_path); + ComPtr decoder; + hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path); if (SUCCEEDED(hr)) { - texture.SetBitmap(bitmap); + ComPtr source; + hr = decoder->GetFrame(0, &source); + + if (SUCCEEDED(hr)) + { + ComPtr converter; + hr = d2d_res_->CreateBitmapConverter( + converter, + source, + GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, + nullptr, + 0.f, + WICBitmapPaletteTypeMedianCut + ); + + if (SUCCEEDED(hr)) + { + ComPtr bitmap; + hr = d2d_res_->CreateBitmapFromConverter( + bitmap, + nullptr, + converter + ); + + if (SUCCEEDED(hr)) + { + texture.SetBitmap(bitmap); + } + } + } } } @@ -270,7 +318,7 @@ namespace kiwano } } - void Renderer::CreateTexture(Texture& texture, Resource const& res) + void Renderer::CreateTexture(Texture& texture, Resource const& resource) { HRESULT hr = S_OK; if (!d2d_res_) @@ -280,12 +328,42 @@ namespace kiwano if (SUCCEEDED(hr)) { - ComPtr bitmap; - hr = d2d_res_->CreateBitmapFromResource(bitmap, res); + ComPtr decoder; + hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource); if (SUCCEEDED(hr)) { - texture.SetBitmap(bitmap); + ComPtr source; + hr = decoder->GetFrame(0, &source); + + if (SUCCEEDED(hr)) + { + ComPtr converter; + hr = d2d_res_->CreateBitmapConverter( + converter, + source, + GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, + nullptr, + 0.f, + WICBitmapPaletteTypeMedianCut + ); + + if (SUCCEEDED(hr)) + { + ComPtr bitmap; + hr = d2d_res_->CreateBitmapFromConverter( + bitmap, + nullptr, + converter + ); + + if (SUCCEEDED(hr)) + { + texture.SetBitmap(bitmap); + } + } + } } } @@ -295,7 +373,7 @@ namespace kiwano } } - void Renderer::CreateGifImage(GifImage& texture, String const& file_path) + void Renderer::CreateGifImage(GifImage& gif, String const& file_path) { HRESULT hr = S_OK; if (!d2d_res_) @@ -312,17 +390,11 @@ namespace kiwano if (SUCCEEDED(hr)) { ComPtr decoder; - hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename( - file_path.c_str(), - nullptr, - GENERIC_READ, - WICDecodeMetadataCacheOnLoad, - &decoder - ); + hr = d2d_res_->CreateBitmapDecoderFromFile(decoder, file_path); if (SUCCEEDED(hr)) { - texture.SetDecoder(decoder); + gif.SetDecoder(decoder); } } @@ -332,7 +404,7 @@ namespace kiwano } } - void Renderer::CreateGifImage(GifImage& texture, Resource const& res) + void Renderer::CreateGifImage(GifImage& gif, Resource const& resource) { HRESULT hr = S_OK; if (!d2d_res_) @@ -340,37 +412,14 @@ namespace kiwano hr = E_UNEXPECTED; } - Resource::Data res_data = res.GetData(); - - hr = res_data ? S_OK : E_FAIL; - if (SUCCEEDED(hr)) { - ComPtr stream; - hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream); + ComPtr decoder; + hr = d2d_res_->CreateBitmapDecoderFromResource(decoder, resource); if (SUCCEEDED(hr)) { - hr = stream->InitializeFromMemory( - static_cast(res_data.buffer), - res_data.size - ); - } - - if (SUCCEEDED(hr)) - { - ComPtr decoder; - hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream( - stream.get(), - nullptr, - WICDecodeMetadataCacheOnLoad, - &decoder - ); - - if (SUCCEEDED(hr)) - { - texture.SetDecoder(decoder); - } + gif.SetDecoder(decoder); } } @@ -380,6 +429,173 @@ namespace kiwano } } + void Renderer::CreateGifImageFrame(GifImage::Frame& frame, GifImage const& gif, UInt32 frame_index) + { + HRESULT hr = S_OK; + if (!d2d_res_) + { + hr = E_UNEXPECTED; + } + + if (gif.GetDecoder() == nullptr) + { + hr = E_INVALIDARG; + } + + if (SUCCEEDED(hr)) + { + ComPtr wic_frame; + HRESULT hr = gif.GetDecoder()->GetFrame(frame_index, &wic_frame); + + if (SUCCEEDED(hr)) + { + ComPtr converter; + d2d_res_->CreateBitmapConverter( + converter, + wic_frame, + GUID_WICPixelFormat32bppPBGRA, + WICBitmapDitherTypeNone, + nullptr, + 0.f, + WICBitmapPaletteTypeCustom + ); + + if (SUCCEEDED(hr)) + { + ComPtr raw_bitmap; + hr = d2d_res_->CreateBitmapFromConverter( + raw_bitmap, + nullptr, + converter + ); + + if (SUCCEEDED(hr)) + { + frame.raw.SetBitmap(raw_bitmap); + } + } + } + + if (SUCCEEDED(hr)) + { + PROPVARIANT prop_val; + PropVariantInit(&prop_val); + + // Get Metadata Query Reader from the frame + ComPtr metadata_reader; + hr = wic_frame->GetMetadataQueryReader(&metadata_reader); + + // Get the Metadata for the current frame + if (SUCCEEDED(hr)) + { + hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val); + if (SUCCEEDED(hr)) + { + hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); + if (SUCCEEDED(hr)) + { + frame.rect.left_top.x = static_cast(prop_val.uiVal); + } + PropVariantClear(&prop_val); + } + } + + if (SUCCEEDED(hr)) + { + hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val); + if (SUCCEEDED(hr)) + { + hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); + if (SUCCEEDED(hr)) + { + frame.rect.left_top.y = static_cast(prop_val.uiVal); + } + PropVariantClear(&prop_val); + } + } + + if (SUCCEEDED(hr)) + { + hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val); + if (SUCCEEDED(hr)) + { + hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); + if (SUCCEEDED(hr)) + { + frame.rect.right_bottom.x = frame.rect.left_top.x + static_cast(prop_val.uiVal); + } + PropVariantClear(&prop_val); + } + } + + if (SUCCEEDED(hr)) + { + hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val); + if (SUCCEEDED(hr)) + { + hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); + if (SUCCEEDED(hr)) + { + frame.rect.right_bottom.y = frame.rect.left_top.y + static_cast(prop_val.uiVal); + } + PropVariantClear(&prop_val); + } + } + + if (SUCCEEDED(hr)) + { + hr = metadata_reader->GetMetadataByName(L"/grctlext/Delay", &prop_val); + + if (SUCCEEDED(hr)) + { + hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL); + + if (SUCCEEDED(hr)) + { + UInt32 udelay = 0; + hr = UIntMult(prop_val.uiVal, 10, &udelay); + if (SUCCEEDED(hr)) + { + frame.delay.SetMilliseconds(static_cast(udelay)); + } + } + PropVariantClear(&prop_val); + } + else + { + frame.delay = 0; + } + } + + if (SUCCEEDED(hr)) + { + hr = metadata_reader->GetMetadataByName(L"/grctlext/Disposal", &prop_val); + + if (SUCCEEDED(hr)) + { + hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL; + if (SUCCEEDED(hr)) + { + frame.disposal_type = GifImage::DisposalType(prop_val.bVal); + } + ::PropVariantClear(&prop_val); + } + else + { + frame.disposal_type = GifImage::DisposalType::Unknown; + } + } + + ::PropVariantClear(&prop_val); + } + } + + if (FAILED(hr)) + { + KGE_WARNING_LOG(L"Load GIF frame failed with HRESULT of %08X!", hr); + } + } + void Renderer::CreateFontCollection(FontCollection& collection, Vector const& file_paths) { HRESULT hr = S_OK; diff --git a/src/kiwano/renderer/Renderer.h b/src/kiwano/renderer/Renderer.h index 773b0f12..8802f593 100644 --- a/src/kiwano/renderer/Renderer.h +++ b/src/kiwano/renderer/Renderer.h @@ -39,6 +39,18 @@ namespace kiwano typedef ID3D11DeviceResources ID3DDeviceResources; #endif + // 渲染设置 + struct RenderConfig + { + Color clear_color; // 清屏颜色 + bool vsync; // 垂直同步 + + RenderConfig( + Color clear_color = Color::Black, + bool vsync = true + ); + }; + // 分辨率模式 // 分辨率模式决定了将画面渲染到视区上的方式 // Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认) @@ -89,17 +101,23 @@ namespace kiwano void CreateTexture( Texture& texture, - Resource const& res + Resource const& resource ); void CreateGifImage( - GifImage& texture, + GifImage& gif, String const& file_path ); void CreateGifImage( - GifImage& texture, - Resource const& res + GifImage& gif, + Resource const& resource + ); + + void CreateGifImageFrame( + GifImage::Frame& frame, + GifImage const& gif, + UInt32 frame_index ); void CreateFontCollection( @@ -156,6 +174,8 @@ namespace kiwano ); public: + void Init(RenderConfig const& config); + void SetupComponent() override; void DestroyComponent() override; diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.cpp b/src/kiwano/renderer/win32/D2DDeviceResources.cpp index 550fb3f5..ca062b00 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.cpp +++ b/src/kiwano/renderer/win32/D2DDeviceResources.cpp @@ -20,7 +20,6 @@ #include "D2DDeviceResources.h" #include "../../base/Logger.h" -#include "../../utils/FileUtil.h" #pragma comment(lib, "d2d1.lib") #pragma comment(lib, "dwrite.lib") @@ -38,14 +37,30 @@ namespace kiwano HRESULT CreateDeviceIndependentResources(); public: - HRESULT CreateBitmapFromFile( - _Out_ ComPtr& bitmap, - _In_ String const& file_path + HRESULT CreateBitmapConverter( + _Out_ ComPtr& converter, + _In_opt_ ComPtr source, + _In_ REFWICPixelFormatGUID format, + WICBitmapDitherType dither, + _In_opt_ ComPtr palette, + double alpha_threshold_percent, + WICBitmapPaletteType palette_translate ) override; - HRESULT CreateBitmapFromResource( + HRESULT CreateBitmapFromConverter( _Out_ ComPtr& bitmap, - _In_ Resource const& res + _In_opt_ const D2D1_BITMAP_PROPERTIES* properties, + _In_ ComPtr converter + ) override; + + HRESULT CreateBitmapDecoderFromFile( + _Out_ ComPtr& decoder, + const String& file_path + ) override; + + HRESULT CreateBitmapDecoderFromResource( + _Out_ ComPtr& decoder, + const Resource& resource ) override; HRESULT CreateTextFormat( @@ -189,16 +204,16 @@ namespace kiwano ComPtr imaging_factory; ComPtr dwrite_factory; - D2D1_FACTORY_OPTIONS options; - ZeroMemory(&options, sizeof(D2D1_FACTORY_OPTIONS)); + D2D1_FACTORY_OPTIONS config; + ZeroMemory(&config, sizeof(D2D1_FACTORY_OPTIONS)); #if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG) - options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; + config.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; #endif hr = D2D1CreateFactory( D2D1_FACTORY_TYPE_SINGLE_THREADED, __uuidof(ID2D1Factory1), - &options, + &config, reinterpret_cast(&d2d_factory) ); @@ -310,143 +325,113 @@ namespace kiwano device_context_->SetTarget(target_bitmap_.get()); } - HRESULT D2DDeviceResources::CreateBitmapFromFile(_Out_ ComPtr & bitmap, _In_ String const & file_path) + HRESULT D2DDeviceResources::CreateBitmapConverter(_Out_ ComPtr& converter, _In_opt_ ComPtr source, + _In_ REFWICPixelFormatGUID format, WICBitmapDitherType dither, _In_opt_ ComPtr palette, double alpha_threshold_percent, + WICBitmapPaletteType palette_translate + ) { - if (!imaging_factory_ || !device_context_) + if (!imaging_factory_) return E_UNEXPECTED; - if (!FileUtil::ExistsFile(file_path)) + ComPtr output; + HRESULT hr = imaging_factory_->CreateFormatConverter(&output); + + if (SUCCEEDED(hr)) { - KGE_WARNING_LOG(L"Texture file '%s' not found!", file_path.c_str()); - return E_FAIL; + hr = output->Initialize( + source.get(), + format, + dither, + palette.get(), + alpha_threshold_percent, + palette_translate + ); } - ComPtr decoder; - ComPtr source; - ComPtr stream; - ComPtr converter; - ComPtr bitmap_tmp; + if (SUCCEEDED(hr)) + { + converter = output; + } + return hr; + } + HRESULT D2DDeviceResources::CreateBitmapFromConverter(_Out_ ComPtr& bitmap, _In_opt_ const D2D1_BITMAP_PROPERTIES* properties, + _In_ ComPtr converter) + { + if (!device_context_) + return E_UNEXPECTED; + + ComPtr output; + HRESULT hr = device_context_->CreateBitmapFromWicBitmap( + converter.get(), + properties, + &output + ); + + if (SUCCEEDED(hr)) + { + bitmap = output; + } + return hr; + } + + HRESULT D2DDeviceResources::CreateBitmapDecoderFromFile(_Out_ ComPtr& decoder, const String& file_path) + { + if (!imaging_factory_) + return E_UNEXPECTED; + + ComPtr decoder_output; HRESULT hr = imaging_factory_->CreateDecoderFromFilename( file_path.c_str(), nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, - &decoder + &decoder_output ); if (SUCCEEDED(hr)) { - hr = decoder->GetFrame(0, &source); - } - - if (SUCCEEDED(hr)) - { - hr = imaging_factory_->CreateFormatConverter(&converter); - } - - if (SUCCEEDED(hr)) - { - // 图片格式转换成 32bppPBGRA - hr = converter->Initialize( - source.get(), - GUID_WICPixelFormat32bppPBGRA, - WICBitmapDitherTypeNone, - nullptr, - 0.f, - WICBitmapPaletteTypeMedianCut - ); - } - - if (SUCCEEDED(hr)) - { - hr = device_context_->CreateBitmapFromWicBitmap( - converter.get(), - nullptr, - &bitmap_tmp - ); - } - - if (SUCCEEDED(hr)) - { - bitmap = bitmap_tmp; + decoder = decoder_output; } return hr; } - HRESULT D2DDeviceResources::CreateBitmapFromResource(_Out_ ComPtr & bitmap, _In_ Resource const & res) + HRESULT D2DDeviceResources::CreateBitmapDecoderFromResource(_Out_ ComPtr& decoder, const Resource& resource) { - if (!imaging_factory_ || !device_context_) + if (!imaging_factory_) return E_UNEXPECTED; - ComPtr decoder; - ComPtr source; - ComPtr stream; - ComPtr converter; - ComPtr bitmap_tmp; - - // 加载资源 - Resource::Data res_data = res.GetData(); + Resource::Data res_data = resource.GetData(); HRESULT hr = res_data ? S_OK : E_FAIL; if (SUCCEEDED(hr)) { + ComPtr stream; hr = imaging_factory_->CreateStream(&stream); - } - if (SUCCEEDED(hr)) - { - hr = stream->InitializeFromMemory( - static_cast(res_data.buffer), - res_data.size - ); - } + if (SUCCEEDED(hr)) + { + hr = stream->InitializeFromMemory( + static_cast(res_data.buffer), + res_data.size + ); + } - if (SUCCEEDED(hr)) - { - hr = imaging_factory_->CreateDecoderFromStream( - stream.get(), - nullptr, - WICDecodeMetadataCacheOnLoad, - &decoder - ); - } + if (SUCCEEDED(hr)) + { + ComPtr decoder_output; + hr = imaging_factory_->CreateDecoderFromStream( + stream.get(), + nullptr, + WICDecodeMetadataCacheOnLoad, + &decoder_output + ); - if (SUCCEEDED(hr)) - { - hr = decoder->GetFrame(0, &source); - } - - if (SUCCEEDED(hr)) - { - hr = imaging_factory_->CreateFormatConverter(&converter); - } - - if (SUCCEEDED(hr)) - { - // 图片格式转换成 32bppPBGRA - hr = converter->Initialize( - source.get(), - GUID_WICPixelFormat32bppPBGRA, - WICBitmapDitherTypeNone, - nullptr, - 0.f, - WICBitmapPaletteTypeMedianCut - ); - } - - if (SUCCEEDED(hr)) - { - hr = device_context_->CreateBitmapFromWicBitmap( - converter.get(), - nullptr, - &bitmap_tmp - ); - } - - if (SUCCEEDED(hr)) - { - bitmap = bitmap_tmp; + if (SUCCEEDED(hr)) + { + decoder = decoder_output; + } + } } return hr; } diff --git a/src/kiwano/renderer/win32/D2DDeviceResources.h b/src/kiwano/renderer/win32/D2DDeviceResources.h index 0994a49b..419386ca 100644 --- a/src/kiwano/renderer/win32/D2DDeviceResources.h +++ b/src/kiwano/renderer/win32/D2DDeviceResources.h @@ -189,14 +189,30 @@ namespace kiwano public: static HRESULT Create(ID2DDeviceResources** device_resources); - virtual HRESULT CreateBitmapFromFile( - _Out_ ComPtr& bitmap, - _In_ String const& file_path + virtual HRESULT CreateBitmapConverter( + _Out_ ComPtr& converter, + _In_opt_ ComPtr source, + _In_ REFWICPixelFormatGUID format, + WICBitmapDitherType dither, + _In_opt_ ComPtr palette, + double alpha_threshold_percent, + WICBitmapPaletteType palette_translate ) = 0; - virtual HRESULT CreateBitmapFromResource( + virtual HRESULT CreateBitmapFromConverter( _Out_ ComPtr& bitmap, - _In_ Resource const& res + _In_opt_ const D2D1_BITMAP_PROPERTIES* properties, + _In_ ComPtr converter + ) = 0; + + virtual HRESULT CreateBitmapDecoderFromFile( + _Out_ ComPtr& decoder, + const String& file_path + ) = 0; + + virtual HRESULT CreateBitmapDecoderFromResource( + _Out_ ComPtr& decoder, + const Resource& resource ) = 0; virtual HRESULT CreateTextFormat(