| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  | // Copyright (c) 2016-2018 Kiwano - Nomango
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | // 
 | 
					
						
							|  |  |  | // Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
					
						
							|  |  |  | // of this software and associated documentation files (the "Software"), to deal
 | 
					
						
							|  |  |  | // in the Software without restriction, including without limitation the rights
 | 
					
						
							|  |  |  | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
					
						
							|  |  |  | // copies of the Software, and to permit persons to whom the Software is
 | 
					
						
							|  |  |  | // furnished to do so, subject to the following conditions:
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // The above copyright notice and this permission notice shall be included in
 | 
					
						
							|  |  |  | // all copies or substantial portions of the Software.
 | 
					
						
							|  |  |  | // 
 | 
					
						
							|  |  |  | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
					
						
							|  |  |  | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
					
						
							|  |  |  | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
					
						
							|  |  |  | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
					
						
							|  |  |  | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
					
						
							|  |  |  | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
					
						
							|  |  |  | // THE SOFTWARE.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "D2DDeviceResources.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | #include "../../base/Logger.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #pragma comment(lib, "d2d1.lib")
 | 
					
						
							|  |  |  | #pragma comment(lib, "dwrite.lib")
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  | namespace kiwano | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 	struct D2DDeviceResources | 
					
						
							|  |  |  | 		: public ID2DDeviceResources | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 		D2DDeviceResources(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		virtual ~D2DDeviceResources(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HRESULT CreateDeviceIndependentResources(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	public: | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		HRESULT CreateBitmapConverter( | 
					
						
							|  |  |  | 			_Out_ ComPtr<IWICFormatConverter>& converter, | 
					
						
							|  |  |  | 			_In_opt_ ComPtr<IWICBitmapSource> source, | 
					
						
							|  |  |  | 			_In_ REFWICPixelFormatGUID format, | 
					
						
							|  |  |  | 			WICBitmapDitherType dither, | 
					
						
							|  |  |  | 			_In_opt_ ComPtr<IWICPalette> palette, | 
					
						
							|  |  |  | 			double alpha_threshold_percent, | 
					
						
							|  |  |  | 			WICBitmapPaletteType palette_translate | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 		) override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		HRESULT CreateBitmapFromConverter( | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 			_Out_ ComPtr<ID2D1Bitmap>& bitmap, | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 			_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 | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 		) override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HRESULT CreateTextFormat( | 
					
						
							|  |  |  | 			_Out_ ComPtr<IDWriteTextFormat>& text_format, | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  | 			_In_ Font const& font | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 		) const override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HRESULT CreateTextLayout( | 
					
						
							|  |  |  | 			_Out_ ComPtr<IDWriteTextLayout>& text_layout, | 
					
						
							|  |  |  | 			_In_ String const& text, | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  | 			_In_ ComPtr<IDWriteTextFormat> const& text_format | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 		) const override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HRESULT SetD2DDevice( | 
					
						
							|  |  |  | 			_In_ ComPtr<ID2D1Device> const& device | 
					
						
							|  |  |  | 		) override; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		void SetTargetBitmap( | 
					
						
							|  |  |  | 			_In_ ComPtr<ID2D1Bitmap1> const& target | 
					
						
							|  |  |  | 		) override; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 14:44:37 +08:00
										 |  |  | 		void DiscardResources() override; | 
					
						
							| 
									
										
										
										
											2019-08-05 10:00:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 	public: | 
					
						
							|  |  |  | 		unsigned long STDMETHODCALLTYPE AddRef(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		unsigned long STDMETHODCALLTYPE Release(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HRESULT STDMETHODCALLTYPE QueryInterface( | 
					
						
							|  |  |  | 			IID const& riid, | 
					
						
							|  |  |  | 			void** ppvObject | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	protected: | 
					
						
							|  |  |  | 		unsigned long ref_count_; | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  | 		Float32 dpi_; | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT ID2DDeviceResources::Create(ID2DDeviceResources** device_resources) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = E_FAIL; | 
					
						
							|  |  |  | 		if (device_resources) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			D2DDeviceResources* res = new (std::nothrow) D2DDeviceResources; | 
					
						
							|  |  |  | 			if (res) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hr = res->CreateDeviceIndependentResources(); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				res->AddRef(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 				if (*device_resources) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					(*device_resources)->Release(); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 				(*device_resources) = res; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				delete res; | 
					
						
							|  |  |  | 				res = nullptr; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	D2DDeviceResources::D2DDeviceResources() | 
					
						
							|  |  |  | 		: ref_count_(0) | 
					
						
							|  |  |  | 		, dpi_(96.f) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	D2DDeviceResources::~D2DDeviceResources() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		DiscardResources(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	STDMETHODIMP_(unsigned long) D2DDeviceResources::AddRef() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return InterlockedIncrement(&ref_count_); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	STDMETHODIMP_(unsigned long) D2DDeviceResources::Release() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		unsigned long newCount = InterlockedDecrement(&ref_count_); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (newCount == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			delete this; | 
					
						
							|  |  |  | 			return 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return newCount; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 	STDMETHODIMP D2DDeviceResources::QueryInterface(IID const& riid, void** object) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 		if (__uuidof(ID2DDeviceResources) == riid) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*object = this; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (__uuidof(IUnknown) == riid) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			*object = this; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			*object = nullptr; | 
					
						
							|  |  |  | 			return E_FAIL; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		AddRef(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return S_OK; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	void D2DDeviceResources::DiscardResources() | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  | 		factory_.reset(); | 
					
						
							|  |  |  | 		device_.reset(); | 
					
						
							|  |  |  | 		device_context_.reset(); | 
					
						
							|  |  |  | 		target_bitmap_.reset(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  | 		imaging_factory_.reset(); | 
					
						
							|  |  |  | 		dwrite_factory_.reset(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  | 		d2d_miter_stroke_style_.reset(); | 
					
						
							|  |  |  | 		d2d_bevel_stroke_style_.reset(); | 
					
						
							|  |  |  | 		d2d_round_stroke_style_.reset(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	HRESULT D2DDeviceResources::CreateDeviceIndependentResources() | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 		ComPtr<ID2D1Factory1>		d2d_factory; | 
					
						
							|  |  |  | 		ComPtr<IWICImagingFactory>	imaging_factory; | 
					
						
							|  |  |  | 		ComPtr<IDWriteFactory>		dwrite_factory; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		D2D1_FACTORY_OPTIONS config; | 
					
						
							|  |  |  | 		ZeroMemory(&config, sizeof(D2D1_FACTORY_OPTIONS)); | 
					
						
							| 
									
										
										
										
											2019-08-21 16:54:51 +08:00
										 |  |  | #if defined(KGE_DEBUG) && defined(KGE_ENABLE_DX_DEBUG)
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		config.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		hr = D2D1CreateFactory( | 
					
						
							|  |  |  | 			D2D1_FACTORY_TYPE_SINGLE_THREADED, | 
					
						
							|  |  |  | 			__uuidof(ID2D1Factory1), | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 			&config, | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 			reinterpret_cast<void**>(&d2d_factory) | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 			factory_ = d2d_factory; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			hr = CoCreateInstance( | 
					
						
							|  |  |  | 				CLSID_WICImagingFactory, | 
					
						
							|  |  |  | 				nullptr, | 
					
						
							|  |  |  | 				CLSCTX_INPROC_SERVER, | 
					
						
							|  |  |  | 				__uuidof(IWICImagingFactory), | 
					
						
							|  |  |  | 				reinterpret_cast<void**>(&imaging_factory) | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			imaging_factory_ = imaging_factory; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			hr = DWriteCreateFactory( | 
					
						
							|  |  |  | 				DWRITE_FACTORY_TYPE_SHARED, | 
					
						
							|  |  |  | 				__uuidof(IDWriteFactory), | 
					
						
							|  |  |  | 				reinterpret_cast<IUnknown**>(&dwrite_factory) | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			dwrite_factory_ = dwrite_factory; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			ComPtr<ID2D1StrokeStyle> d2d_miter_stroke_style; | 
					
						
							|  |  |  | 			ComPtr<ID2D1StrokeStyle> d2d_bevel_stroke_style; | 
					
						
							|  |  |  | 			ComPtr<ID2D1StrokeStyle> d2d_round_stroke_style; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			D2D1_STROKE_STYLE_PROPERTIES stroke_style = D2D1::StrokeStyleProperties( | 
					
						
							|  |  |  | 				D2D1_CAP_STYLE_FLAT, | 
					
						
							|  |  |  | 				D2D1_CAP_STYLE_FLAT, | 
					
						
							|  |  |  | 				D2D1_CAP_STYLE_FLAT, | 
					
						
							|  |  |  | 				D2D1_LINE_JOIN_MITER, | 
					
						
							|  |  |  | 				2.0f, | 
					
						
							|  |  |  | 				D2D1_DASH_STYLE_SOLID, | 
					
						
							|  |  |  | 				0.0f | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 			hr = factory_->CreateStrokeStyle( | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 				stroke_style, | 
					
						
							|  |  |  | 				nullptr, | 
					
						
							|  |  |  | 				0, | 
					
						
							|  |  |  | 				&d2d_miter_stroke_style | 
					
						
							|  |  |  | 			); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 				hr = factory_->CreateStrokeStyle( | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 					stroke_style, | 
					
						
							|  |  |  | 					nullptr, | 
					
						
							|  |  |  | 					0, | 
					
						
							|  |  |  | 					&d2d_bevel_stroke_style | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 				hr = factory_->CreateStrokeStyle( | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 					stroke_style, | 
					
						
							|  |  |  | 					nullptr, | 
					
						
							|  |  |  | 					0, | 
					
						
							|  |  |  | 					&d2d_round_stroke_style | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				d2d_miter_stroke_style_ = d2d_miter_stroke_style; | 
					
						
							|  |  |  | 				d2d_bevel_stroke_style_ = d2d_bevel_stroke_style; | 
					
						
							|  |  |  | 				d2d_round_stroke_style_ = d2d_round_stroke_style; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-05 10:00:30 +08:00
										 |  |  | 	HRESULT D2DDeviceResources::SetD2DDevice(_In_ ComPtr<ID2D1Device> const& device) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		ComPtr<ID2D1DeviceContext> d2d_device_ctx; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		HRESULT hr = device->CreateDeviceContext( | 
					
						
							|  |  |  | 			D2D1_DEVICE_CONTEXT_OPTIONS_NONE, | 
					
						
							|  |  |  | 			&d2d_device_ctx | 
					
						
							|  |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 			device_ = device; | 
					
						
							|  |  |  | 			device_context_ = d2d_device_ctx; | 
					
						
							|  |  |  | 			device_context_->SetDpi(dpi_, dpi_); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-05 10:00:30 +08:00
										 |  |  | 	void D2DDeviceResources::SetTargetBitmap(_In_ ComPtr<ID2D1Bitmap1> const& target) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  | 		target_bitmap_ = target; | 
					
						
							|  |  |  | 		if (device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  | 			device_context_->SetTarget(target_bitmap_.get()); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 	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 | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		if (!imaging_factory_) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		ComPtr<IWICFormatConverter> output; | 
					
						
							|  |  |  | 		HRESULT hr = imaging_factory_->CreateFormatConverter(&output); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 			hr = output->Initialize( | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  | 				source.get(), | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 				format, | 
					
						
							|  |  |  | 				dither, | 
					
						
							|  |  |  | 				palette.get(), | 
					
						
							|  |  |  | 				alpha_threshold_percent, | 
					
						
							|  |  |  | 				palette_translate | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 			); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 			converter = output; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 	HRESULT D2DDeviceResources::CreateBitmapFromConverter(_Out_ ComPtr<ID2D1Bitmap>& bitmap, _In_opt_ const D2D1_BITMAP_PROPERTIES* properties, | 
					
						
							|  |  |  | 		_In_ ComPtr<IWICFormatConverter> converter) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		ComPtr<ID2D1Bitmap> output; | 
					
						
							|  |  |  | 		HRESULT hr = device_context_->CreateBitmapFromWicBitmap( | 
					
						
							|  |  |  | 			converter.get(), | 
					
						
							|  |  |  | 			properties, | 
					
						
							|  |  |  | 			&output | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 			bitmap = output; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 	HRESULT D2DDeviceResources::CreateBitmapDecoderFromFile(_Out_ ComPtr<IWICBitmapDecoder>& decoder, const String& file_path) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!imaging_factory_) | 
					
						
							|  |  |  | 			return E_UNEXPECTED; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		ComPtr<IWICBitmapDecoder> decoder_output; | 
					
						
							|  |  |  | 		HRESULT hr = imaging_factory_->CreateDecoderFromFilename( | 
					
						
							|  |  |  | 			file_path.c_str(), | 
					
						
							|  |  |  | 			nullptr, | 
					
						
							|  |  |  | 			GENERIC_READ, | 
					
						
							|  |  |  | 			WICDecodeMetadataCacheOnLoad, | 
					
						
							|  |  |  | 			&decoder_output | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 			decoder = decoder_output; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 	HRESULT D2DDeviceResources::CreateBitmapDecoderFromResource(_Out_ ComPtr<IWICBitmapDecoder>& decoder, const Resource& resource) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (!imaging_factory_) | 
					
						
							|  |  |  | 			return E_UNEXPECTED; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 		Resource::Data res_data = resource.GetData(); | 
					
						
							|  |  |  | 		HRESULT hr = res_data ? S_OK : E_FAIL; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 			ComPtr<IWICStream> stream; | 
					
						
							|  |  |  | 			hr = imaging_factory_->CreateStream(&stream); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 13:00:43 +08:00
										 |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				hr = stream->InitializeFromMemory( | 
					
						
							|  |  |  | 					static_cast<WICInProcPointer>(res_data.buffer), | 
					
						
							|  |  |  | 					res_data.size | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				ComPtr<IWICBitmapDecoder> decoder_output; | 
					
						
							|  |  |  | 				hr = imaging_factory_->CreateDecoderFromStream( | 
					
						
							|  |  |  | 					stream.get(), | 
					
						
							|  |  |  | 					nullptr, | 
					
						
							|  |  |  | 					WICDecodeMetadataCacheOnLoad, | 
					
						
							|  |  |  | 					&decoder_output | 
					
						
							|  |  |  | 				); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					decoder = decoder_output; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  | 	HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat> & text_format, _In_ Font const & font) const | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		if (!dwrite_factory_) | 
					
						
							|  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  | 		ComPtr<IDWriteTextFormat> output; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		HRESULT hr = dwrite_factory_->CreateTextFormat( | 
					
						
							|  |  |  | 			font.family.c_str(), | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  | 			font.collection.GetFontCollection().get(), | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 			DWRITE_FONT_WEIGHT(font.weight), | 
					
						
							|  |  |  | 			font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, | 
					
						
							|  |  |  | 			DWRITE_FONT_STRETCH_NORMAL, | 
					
						
							|  |  |  | 			font.size, | 
					
						
							| 
									
										
										
										
											2019-08-21 12:47:19 +08:00
										 |  |  | 			L"", | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  | 			&output | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  | 			text_format = output; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-23 17:26:41 +08:00
										 |  |  | 	HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout>& text_layout, _In_ String const& text, | 
					
						
							|  |  |  | 		_In_ ComPtr<IDWriteTextFormat> const& text_format) const | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		if (!dwrite_factory_) | 
					
						
							|  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  | 		ComPtr<IDWriteTextLayout> output; | 
					
						
							| 
									
										
										
										
											2019-08-23 17:26:41 +08:00
										 |  |  | 		HRESULT hr = dwrite_factory_->CreateTextLayout( | 
					
						
							|  |  |  | 			text.c_str(), | 
					
						
							|  |  |  | 			static_cast<UINT32>(text.length()), | 
					
						
							|  |  |  | 			text_format.get(), | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			0, | 
					
						
							|  |  |  | 			&output | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			text_layout = output; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return hr; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 14:44:37 +08:00
										 |  |  | } |