| 
									
										
										
										
											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.
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 21:52:49 +08:00
										 |  |  |  | #include "Renderer.h"
 | 
					
						
							|  |  |  |  | #include "../base/Logger.h"
 | 
					
						
							|  |  |  |  | #include "../base/Window.h"
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | #include "../utils/FileUtil.h"
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  |  | namespace kiwano | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | { | 
					
						
							|  |  |  |  | 	Renderer::Renderer() | 
					
						
							|  |  |  |  | 		: hwnd_(nullptr) | 
					
						
							|  |  |  |  | 		, vsync_(true) | 
					
						
							|  |  |  |  | 		, clear_color_(Color::Black) | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 		, resolution_mode_(ResolutionMode::Fixed) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	Renderer::~Renderer() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-12 14:51:54 +08:00
										 |  |  |  | 	void Renderer::SetupComponent() | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  |  | 		KGE_LOG(L"Creating device resources"); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 15:00:43 +08:00
										 |  |  |  | 		hwnd_ = Window::GetInstance()->GetHandle(); | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 		resolution_ = output_size_ = Window::GetInstance()->GetSize(); | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 		d2d_res_ = nullptr; | 
					
						
							|  |  |  |  | 		d3d_res_ = nullptr; | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 		drawing_state_block_ = nullptr; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		HRESULT hr = hwnd_ ? S_OK : E_FAIL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// Direct2D device resources
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = ID2DDeviceResources::Create(&d2d_res_); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		// Direct3D device resources
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | #if defined(KGE_USE_DIRECTX10)
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			hr = ID3D10DeviceResources::Create( | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 				&d3d_res_, | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 				d2d_res_.get(), | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 				hwnd_ | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			hr = ID3D11DeviceResources::Create( | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 				&d3d_res_, | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 				d2d_res_.get(), | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 				hwnd_ | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		// DrawingStateBlock
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreateDrawingStateBlock( | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 				&drawing_state_block_ | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		// Other device resources
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = CreateDeviceResources(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		// FontFileLoader and FontCollectionLoader
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = IFontCollectionLoader::Create(&font_collection_loader_); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.get()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		// ResourceFontFileLoader and ResourceFontCollectionLoader
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = IResourceFontFileLoader::Create(&res_font_file_loader_); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.get()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, res_font_file_loader_.get()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(res_font_collection_loader_.get()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::DestroyComponent() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-04-11 14:40:54 +08:00
										 |  |  |  | 		KGE_LOG(L"Destroying device resources"); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 19:32:36 +08:00
										 |  |  |  | 		RenderTarget::DiscardDeviceResources(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get()); | 
					
						
							|  |  |  |  | 		res_font_file_loader_.reset(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get()); | 
					
						
							|  |  |  |  | 		res_font_collection_loader_.reset(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 		drawing_state_block_.reset(); | 
					
						
							|  |  |  |  | 		d2d_res_.reset(); | 
					
						
							|  |  |  |  | 		d3d_res_.reset(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 	void Renderer::BeforeRender() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (!IsValid()) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			render_target_->SaveDrawingState(drawing_state_block_.get()); | 
					
						
							|  |  |  |  | 			BeginDraw(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d3d_res_->ClearRenderTarget(clear_color_); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			SetTransform(Matrix3x2{}); | 
					
						
							|  |  |  |  | 			PushClipRect(Rect{ Point{}, resolution_ }); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::AfterRender() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		 | 
					
						
							|  |  |  |  | 		if (!IsValid()) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 			PopClipRect(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			EndDraw(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			render_target_->RestoreDrawingState(drawing_state_block_.get()); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d3d_res_->Present(vsync_); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			// <20><><EFBFBD><EFBFBD> Direct3D <20>豸<EFBFBD><E8B1B8>ִ<EFBFBD>й<EFBFBD><D0B9><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʧ<EFBFBD><CAA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD>豸<EFBFBD><E8B1B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
 | 
					
						
							|  |  |  |  | 			hr = HandleDeviceLost(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  |  | 	void Renderer::HandleMessage(HWND hwnd, UInt32 msg, WPARAM wparam, LPARAM lparam) | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		switch (msg) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 		case WM_SIZE: | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  |  | 			UInt32 width = LOWORD(lparam); | 
					
						
							|  |  |  |  | 			UInt32 height = HIWORD(lparam); | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 			ResizeTarget(width, height); | 
					
						
							| 
									
										
										
										
											2019-07-30 13:32:10 +08:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	HRESULT Renderer::CreateDeviceResources() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-20 19:32:36 +08:00
										 |  |  |  | 		KGE_ASSERT(d2d_res_); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		HRESULT hr = RenderTarget::CreateDeviceResources( | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			d2d_res_->GetDeviceContext(), | 
					
						
							|  |  |  |  | 			d2d_res_ | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			SetAntialiasMode(antialias_); | 
					
						
							|  |  |  |  | 			SetTextAntialiasMode(text_antialias_); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT Renderer::HandleDeviceLost() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 		HRESULT hr = d3d_res_->HandleDeviceLost(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = CreateDeviceResources(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 	void Renderer::CreateImage(Image& image, String const& file_path) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			ComPtr<ID2D1Bitmap> bitmap; | 
					
						
							|  |  |  |  | 			hr = d2d_res_->CreateBitmapFromFile(bitmap, file_path); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				image.SetBitmap(bitmap); | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-07-29 09:40:39 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (FAILED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateImage(Image& image, Resource const& res) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			ComPtr<ID2D1Bitmap> bitmap; | 
					
						
							|  |  |  |  | 			hr = d2d_res_->CreateBitmapFromResource(bitmap, res); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				image.SetBitmap(bitmap); | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (FAILED(hr)) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr); | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 	void Renderer::CreateGifImage(GifImage& image, String const& file_path) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		if (!FileUtil::ExistsFile(file_path)) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			KGE_WARNING_LOG(L"Gif image file '%s' not found!", file_path.c_str()); | 
					
						
							|  |  |  |  | 			hr = E_FAIL; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			ComPtr<IWICBitmapDecoder> decoder; | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename( | 
					
						
							|  |  |  |  | 				file_path.c_str(), | 
					
						
							|  |  |  |  | 				nullptr, | 
					
						
							|  |  |  |  | 				GENERIC_READ, | 
					
						
							|  |  |  |  | 				WICDecodeMetadataCacheOnLoad, | 
					
						
							|  |  |  |  | 				&decoder | 
					
						
							|  |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				image.SetDecoder(decoder); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (FAILED(hr)) | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 	void Renderer::CreateGifImage(GifImage& image, Resource const& res) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		Resource::Data res_data = res.GetData(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		hr = res_data ? S_OK : E_FAIL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			ComPtr<IWICStream> stream; | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream); | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				hr = stream->InitializeFromMemory( | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 					static_cast<WICInProcPointer>(res_data.buffer), | 
					
						
							|  |  |  |  | 					res_data.size | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 				); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				ComPtr<IWICBitmapDecoder> decoder; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 				hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream( | 
					
						
							|  |  |  |  | 					stream.get(), | 
					
						
							|  |  |  |  | 					nullptr, | 
					
						
							|  |  |  |  | 					WICDecodeMetadataCacheOnLoad, | 
					
						
							|  |  |  |  | 					&decoder | 
					
						
							|  |  |  |  | 				); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					image.SetDecoder(decoder); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (FAILED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 	void Renderer::CreateFontCollection(FontCollection& collection, Vector<String> const& file_paths) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			for (const auto& file_path : file_paths) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 				if (!FileUtil::ExistsFile(file_path)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					KGE_WARNING_LOG(L"Font file '%s' not found!", file_path.c_str()); | 
					
						
							|  |  |  |  | 					hr = E_FAIL; | 
					
						
							|  |  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			LPVOID collection_key = nullptr; | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  |  | 			UInt32 collection_key_size = 0; | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			hr = font_collection_loader_->AddFilePaths(file_paths, &collection_key, &collection_key_size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				ComPtr<IDWriteFontCollection> font_collection; | 
					
						
							|  |  |  |  | 				hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection( | 
					
						
							|  |  |  |  | 					font_collection_loader_.get(), | 
					
						
							|  |  |  |  | 					collection_key, | 
					
						
							|  |  |  |  | 					collection_key_size, | 
					
						
							|  |  |  |  | 					&font_collection | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					collection.SetFontCollection(font_collection); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (FAILED(hr)) | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			KGE_WARNING_LOG(L"Load font failed with HRESULT of %08X!", hr); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateFontCollection(FontCollection& collection, Vector<Resource> const& res_arr) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 			LPVOID collection_key = nullptr; | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  |  | 			UInt32 collection_key_size = 0; | 
					
						
							| 
									
										
										
										
											2019-08-18 17:49:13 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 			hr = res_font_collection_loader_->AddResources(res_arr, &collection_key, &collection_key_size); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				ComPtr<IDWriteFontCollection> font_collection; | 
					
						
							|  |  |  |  | 				hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection( | 
					
						
							|  |  |  |  | 					res_font_collection_loader_.get(), | 
					
						
							|  |  |  |  | 					collection_key, | 
					
						
							|  |  |  |  | 					collection_key_size, | 
					
						
							|  |  |  |  | 					&font_collection | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 				{ | 
					
						
							|  |  |  |  | 					collection.SetFontCollection(font_collection); | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-08-18 10:23:54 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (FAILED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			KGE_WARNING_LOG(L"Load font failed with HRESULT of %08X!", hr); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 	void Renderer::CreateTextFormat(TextFormat& format, Font const& font) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<IDWriteTextFormat> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->CreateTextFormat(output, font); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			format.SetTextFormat(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextStyle const& style, TextFormat const& format) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<IDWriteTextLayout> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->CreateTextLayout( | 
					
						
							|  |  |  |  | 				output, | 
					
						
							|  |  |  |  | 				text, | 
					
						
							|  |  |  |  | 				style, | 
					
						
							|  |  |  |  | 				format.GetTextFormat() | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			layout.SetTextLayout(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	void Renderer::CreateLineGeometry(Geometry& geo, Point const& begin_pos, Point const& end_pos) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1PathGeometry> path_geo; | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1GeometrySink> path_sink; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreatePathGeometry(&path_geo); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = path_geo->Open(&path_sink); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			path_sink->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED); | 
					
						
							|  |  |  |  | 			path_sink->AddLine(DX::ConvertToPoint2F(end_pos)); | 
					
						
							|  |  |  |  | 			path_sink->EndFigure(D2D1_FIGURE_END_OPEN); | 
					
						
							|  |  |  |  | 			hr = path_sink->Close(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			geo.SetGeometry(path_geo); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateRectGeometry(Geometry& geo, Rect const& rect) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1RectangleGeometry> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreateRectangleGeometry(DX::ConvertToRectF(rect), &output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			geo.SetGeometry(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateRoundedRectGeometry(Geometry& geo, Rect const& rect, Vec2 const& radius) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1RoundedRectangleGeometry> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreateRoundedRectangleGeometry( | 
					
						
							|  |  |  |  | 				D2D1::RoundedRect( | 
					
						
							|  |  |  |  | 					DX::ConvertToRectF(rect), | 
					
						
							|  |  |  |  | 					radius.x, | 
					
						
							|  |  |  |  | 					radius.y | 
					
						
							|  |  |  |  | 				), | 
					
						
							|  |  |  |  | 				&output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			geo.SetGeometry(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateEllipseGeometry(Geometry& geo, Point const& center, Vec2 const& radius) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1EllipseGeometry> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreateEllipseGeometry( | 
					
						
							|  |  |  |  | 				D2D1::Ellipse( | 
					
						
							|  |  |  |  | 					DX::ConvertToPoint2F(center), | 
					
						
							|  |  |  |  | 					radius.x, | 
					
						
							|  |  |  |  | 					radius.y | 
					
						
							|  |  |  |  | 				), | 
					
						
							|  |  |  |  | 				&output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			geo.SetGeometry(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreatePathGeometrySink(GeometrySink& sink) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1PathGeometry> output; | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = d2d_res_->GetFactory()->CreatePathGeometry(&output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			sink.SetPathGeometry(output); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 	void Renderer::CreateImageRenderTarget(ImageRenderTarget& render_target) | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		if (!d2d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 		ComPtr<ID2D1BitmapRenderTarget> output; | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-16 00:50:54 +08:00
										 |  |  |  | 			hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(&output); | 
					
						
							| 
									
										
										
										
											2019-08-15 11:22:51 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-20 19:32:36 +08:00
										 |  |  |  | 			hr = render_target.CreateDeviceResources(output, d2d_res_); | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::SetVSyncEnabled(bool enabled) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		vsync_ = enabled; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 	void Renderer::SetResolution(Size const& resolution) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (resolution_ != resolution) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			resolution_ = resolution; | 
					
						
							|  |  |  |  | 			UpdateResolution(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::SetResolutionMode(ResolutionMode mode) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (resolution_mode_ != mode) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			resolution_mode_ = mode; | 
					
						
							|  |  |  |  | 			UpdateResolution(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::SetClearColor(const Color& color) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		clear_color_ = color; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::ResizeTarget(UInt32 width, UInt32 height) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		if (!d3d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-18 22:49:44 +08:00
										 |  |  |  | 			output_size_.x = static_cast<Float32>(width); | 
					
						
							|  |  |  |  | 			output_size_.y = static_cast<Float32>(height); | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			hr = d3d_res_->SetLogicalSize(output_size_); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			UpdateResolution(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 	void Renderer::UpdateResolution() | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-20 23:51:12 +08:00
										 |  |  |  | 		switch (resolution_mode_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 		case ResolutionMode::Fixed: | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			SetGlobalTransform(Matrix3x2{}); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		case ResolutionMode::Center: | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			Float32 left = math::Ceil((output_size_.x - resolution_.x) / 2); | 
					
						
							|  |  |  |  | 			Float32 top = math::Ceil((output_size_.y - resolution_.y) / 2); | 
					
						
							|  |  |  |  | 			SetGlobalTransform(Matrix3x2::Translation(Vec2{ left, top })); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		case ResolutionMode::Stretch: | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100; | 
					
						
							|  |  |  |  | 			Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100; | 
					
						
							|  |  |  |  | 			SetGlobalTransform(Matrix3x2::Scaling(Vec2{ scalex, scaley })); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		case ResolutionMode::Adaptive: | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100; | 
					
						
							|  |  |  |  | 			Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100; | 
					
						
							|  |  |  |  | 			if (scalex > scaley) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				Float32 left = math::Ceil((output_size_.x - resolution_.x * scaley) / 2); | 
					
						
							|  |  |  |  | 				SetGlobalTransform(Matrix3x2::SRT(Vec2{ left, 0 }, Vec2{ scaley, scaley }, 0)); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				Float32 top = math::Ceil((output_size_.y - resolution_.y * scalex) / 2); | 
					
						
							|  |  |  |  | 				SetGlobalTransform(Matrix3x2::SRT(Vec2{ 0, top }, Vec2{ scalex, scalex }, 0)); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | } |