aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/win/graphics/direct/CMakeLists.txt2
-rw-r--r--src/win/graphics/direct/Factory.cpp7
-rw-r--r--src/win/graphics/direct/Image.cpp15
-rw-r--r--src/win/graphics/direct/ImageFactory.cpp52
-rw-r--r--src/win/graphics/direct/Painter.cpp11
5 files changed, 87 insertions, 0 deletions
diff --git a/src/win/graphics/direct/CMakeLists.txt b/src/win/graphics/direct/CMakeLists.txt
index 84c2af61..39f9802a 100644
--- a/src/win/graphics/direct/CMakeLists.txt
+++ b/src/win/graphics/direct/CMakeLists.txt
@@ -2,6 +2,8 @@ add_library(cru_win_graphics_direct SHARED
Brush.cpp
Font.cpp
Geometry.cpp
+ Image.cpp
+ ImageFactory.cpp
Factory.cpp
Painter.cpp
Resource.cpp
diff --git a/src/win/graphics/direct/Factory.cpp b/src/win/graphics/direct/Factory.cpp
index 4c4f1a9a..86ca01b9 100644
--- a/src/win/graphics/direct/Factory.cpp
+++ b/src/win/graphics/direct/Factory.cpp
@@ -5,6 +5,7 @@
#include "cru/win/graphics/direct/Exception.hpp"
#include "cru/win/graphics/direct/Font.hpp"
#include "cru/win/graphics/direct/Geometry.hpp"
+#include "cru/win/graphics/direct/ImageFactory.hpp"
#include "cru/win/graphics/direct/TextLayout.hpp"
#include <cstdlib>
@@ -74,6 +75,8 @@ DirectGraphicsFactory::DirectGraphicsFactory() {
ThrowIfFailed(dwrite_factory_->GetSystemFontCollection(
&dwrite_system_font_collection_));
+
+ image_factory_ = std::make_unique<WinImageFactory>(this);
}
DirectGraphicsFactory::~DirectGraphicsFactory() { UninitializeCom(); }
@@ -106,4 +109,8 @@ std::unique_ptr<ITextLayout> DirectGraphicsFactory::CreateTextLayout(
return std::make_unique<DWriteTextLayout>(this, std::move(font),
std::move(text));
}
+
+IImageFactory* DirectGraphicsFactory::GetImageFactory() {
+ return image_factory_.get();
+}
} // namespace cru::platform::graphics::win::direct
diff --git a/src/win/graphics/direct/Image.cpp b/src/win/graphics/direct/Image.cpp
new file mode 100644
index 00000000..46b763be
--- /dev/null
+++ b/src/win/graphics/direct/Image.cpp
@@ -0,0 +1,15 @@
+#include "cru/win/graphics/direct/Image.hpp"
+
+namespace cru::platform::graphics::win::direct {
+Direct2DImage::Direct2DImage(DirectGraphicsFactory* graphics_factory,
+ ID2D1Image* d2d_image, bool auto_release)
+ : DirectGraphicsResource(graphics_factory),
+ d2d_image_(d2d_image),
+ auto_release_(auto_release) {}
+
+Direct2DImage::~Direct2DImage() {
+ if (auto_release_) {
+ d2d_image_->Release();
+ }
+}
+} // namespace cru::platform::graphics::win::direct
diff --git a/src/win/graphics/direct/ImageFactory.cpp b/src/win/graphics/direct/ImageFactory.cpp
new file mode 100644
index 00000000..dc43a9b9
--- /dev/null
+++ b/src/win/graphics/direct/ImageFactory.cpp
@@ -0,0 +1,52 @@
+#include "cru/win/graphics/direct/ImageFactory.hpp"
+#include "cru/win/graphics/direct/Exception.hpp"
+#include "cru/win/graphics/direct/Factory.hpp"
+#include "cru/win/graphics/direct/Image.hpp"
+
+#include <wincodec.h>
+
+namespace cru::platform::graphics::win::direct {
+WinImageFactory::WinImageFactory(DirectGraphicsFactory* graphics_factory)
+ : DirectGraphicsResource(graphics_factory) {
+ HRESULT hr =
+ CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&wic_imaging_factory_));
+ ThrowIfFailed(hr);
+}
+
+WinImageFactory::~WinImageFactory() {}
+
+std::unique_ptr<IImage> WinImageFactory::DecodeFromStream(io::Stream* stream) {
+ // TODO: The correct way to do this is to implement a IStream wrapper.
+
+ auto buffer = stream->ReadAll();
+
+ HRESULT hr;
+
+ Microsoft::WRL::ComPtr<IWICStream> wic_stream;
+ hr = wic_imaging_factory_->CreateStream(&wic_stream);
+ ThrowIfFailed(hr);
+
+ hr = wic_stream->InitializeFromMemory(
+ reinterpret_cast<unsigned char*>(buffer.data()), buffer.size());
+ ThrowIfFailed(hr);
+
+ Microsoft::WRL::ComPtr<IWICBitmapDecoder> wic_bitmap_decoder;
+ hr = wic_imaging_factory_->CreateDecoderFromStream(
+ wic_stream.Get(), NULL, WICDecodeMetadataCacheOnDemand,
+ &wic_bitmap_decoder);
+ ThrowIfFailed(hr);
+
+ Microsoft::WRL::ComPtr<IWICBitmapFrameDecode> wic_bitmap_frame_decode;
+ hr = wic_bitmap_decoder->GetFrame(0, &wic_bitmap_frame_decode);
+ ThrowIfFailed(hr);
+
+ auto d2d_context = graphics_factory_->GetDefaultD2D1DeviceContext();
+
+ ID2D1Bitmap* d2d_image;
+ d2d_context->CreateBitmapFromWicBitmap(wic_bitmap_frame_decode.Get(), NULL,
+ &d2d_image);
+
+ return std::make_unique<Direct2DImage>(graphics_factory_, d2d_image, true);
+}
+} // namespace cru::platform::graphics::win::direct
diff --git a/src/win/graphics/direct/Painter.cpp b/src/win/graphics/direct/Painter.cpp
index 1a43d1d0..4af8a09a 100644
--- a/src/win/graphics/direct/Painter.cpp
+++ b/src/win/graphics/direct/Painter.cpp
@@ -5,6 +5,7 @@
#include "cru/win/graphics/direct/ConvertUtil.hpp"
#include "cru/win/graphics/direct/Exception.hpp"
#include "cru/win/graphics/direct/Geometry.hpp"
+#include "cru/win/graphics/direct/Image.hpp"
#include "cru/win/graphics/direct/TextLayout.hpp"
#include <type_traits>
@@ -101,6 +102,16 @@ void D2DPainter::DrawText(const Point& offset, ITextLayout* text_layout,
b->GetD2DBrushInterface());
}
+void D2DPainter::DrawImage(const Point& offset, IImage* image) {
+ CheckValidation();
+ const auto i = CheckPlatform<Direct2DImage>(image, GetPlatformId());
+
+ ID2D1DeviceContext* device_context;
+
+ render_target_->QueryInterface(&device_context);
+ device_context->DrawImage(i->GetD2DImage(), Convert(offset));
+}
+
void D2DPainter::PushLayer(const Rect& bounds) {
CheckValidation();