| 
									
										
										
										
											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 "render.h"
 | 
					
						
							|  |  |  |  | #include "../base/logs.h"
 | 
					
						
							| 
									
										
										
										
											2019-07-30 15:27:01 +08:00
										 |  |  |  | #include "../base/window.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) | 
					
						
							|  |  |  |  | 		, antialias_(true) | 
					
						
							|  |  |  |  | 		, vsync_(true) | 
					
						
							| 
									
										
										
										
											2019-08-13 14:44:37 +08:00
										 |  |  |  | 		, text_antialias_(TextAntialias::GrayScale) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		, clear_color_(Color::Black) | 
					
						
							|  |  |  |  | 		, opacity_(1.f) | 
					
						
							| 
									
										
										
										
											2019-07-29 09:40:39 +08:00
										 |  |  |  | 		, collecting_status_(false) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		status_.primitives = 0; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	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-04-22 13:21:12 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hwnd_ ? S_OK : E_FAIL); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +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; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed( | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 			ID2DDeviceResources::Create( | 
					
						
							|  |  |  |  | 				&d2d_res_ | 
					
						
							|  |  |  |  | 			) | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed( | 
					
						
							|  |  |  |  | #if defined(KGE_USE_DIRECTX10)
 | 
					
						
							|  |  |  |  | 			ID3D10DeviceResources::Create( | 
					
						
							|  |  |  |  | 				&d3d_res_, | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 				d2d_res_.get(), | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 				hwnd_ | 
					
						
							|  |  |  |  | 			) | 
					
						
							|  |  |  |  | #else
 | 
					
						
							|  |  |  |  | 			ID3D11DeviceResources::Create( | 
					
						
							|  |  |  |  | 				&d3d_res_, | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 				d2d_res_.get(), | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 				hwnd_ | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 			) | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 		device_context_ = d2d_res_->GetDeviceContext(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 		ThrowIfFailed( | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 			d2d_res_->GetFactory()->CreateDrawingStateBlock( | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 				&drawing_state_block_ | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 			) | 
					
						
							|  |  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 13:21:12 +08:00
										 |  |  |  | 		ThrowIfFailed( | 
					
						
							|  |  |  |  | 			CreateDeviceResources() | 
					
						
							|  |  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 15:00:43 +08:00
										 |  |  |  | 		output_size_ = Window::GetInstance()->GetSize(); | 
					
						
							| 
									
										
										
										
											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-13 21:16:38 +08:00
										 |  |  |  | 		drawing_state_block_.reset(); | 
					
						
							|  |  |  |  | 		solid_color_brush_.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() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		ThrowIfFailed( | 
					
						
							|  |  |  |  | 			BeginDraw() | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::AfterRender() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		ThrowIfFailed( | 
					
						
							|  |  |  |  | 			EndDraw() | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		switch (msg) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 		case WM_SIZE: | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			UINT width = LOWORD(lparam); | 
					
						
							|  |  |  |  | 			UINT height = HIWORD(lparam); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			Resize(width, height); | 
					
						
							|  |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	HRESULT Renderer::CreateDeviceResources() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		solid_color_brush_.reset(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		hr = device_context_->CreateSolidColorBrush( | 
					
						
							|  |  |  |  | 			D2D1::ColorF(D2D1::ColorF::White), | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 			D2D1::BrushProperties(), | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 			&solid_color_brush_ | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 			text_renderer_.reset(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 			hr = ITextRenderer::Create( | 
					
						
							|  |  |  |  | 				&text_renderer_, | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 				device_context_.get() | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT Renderer::BeginDraw() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (!device_context_) | 
					
						
							|  |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-29 09:40:39 +08:00
										 |  |  |  | 		if (collecting_status_) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-04-09 02:25:17 +08:00
										 |  |  |  | 			status_.start = Time::Now(); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 			status_.primitives = 0; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 		device_context_->SaveDrawingState(drawing_state_block_.get()); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		device_context_->BeginDraw(); | 
					
						
							| 
									
										
										
										
											2019-08-07 20:47:41 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT Renderer::EndDraw() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		if (!device_context_) | 
					
						
							|  |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		HRESULT hr = device_context_->EndDraw(); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-13 21:16:38 +08:00
										 |  |  |  | 		device_context_->RestoreDrawingState(drawing_state_block_.get()); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 			hr = d3d_res_->Present(vsync_); | 
					
						
							| 
									
										
										
										
											2019-07-29 09:40:39 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		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(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-29 09:40:39 +08:00
										 |  |  |  | 		if (collecting_status_) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-04-09 02:25:17 +08:00
										 |  |  |  | 			status_.duration = Time::Now() - status_.start; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::IncreasePrimitivesCount() | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (collecting_status_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			++status_.primitives; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::CreateLayer(ComPtr<ID2D1Layer>& layer) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							|  |  |  |  | 		ComPtr<ID2D1Layer> new_layer; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = device_context_->CreateLayer(&new_layer); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			layer = new_layer; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  |  | 		if (!device_context_ || !d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			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; | 
					
						
							|  |  |  |  | 		if (!device_context_ || !d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			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; | 
					
						
							|  |  |  |  | 		if (!device_context_ || !d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			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; | 
					
						
							|  |  |  |  | 		if (!device_context_ || !d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			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; | 
					
						
							|  |  |  |  | 		if (!device_context_ || !d2d_res_) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			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-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::DrawGeometry( | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		Geometry const& geometry, | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		Color const& stroke_color, | 
					
						
							|  |  |  |  | 		float stroke_width, | 
					
						
							|  |  |  |  | 		StrokeStyle stroke | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!solid_color_brush_ || !device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr) && geometry.GetGeometry()) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color)); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			device_context_->DrawGeometry( | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 				geometry.GetGeometry().get(), | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 				solid_color_brush_.get(), | 
					
						
							|  |  |  |  | 				stroke_width, | 
					
						
							|  |  |  |  | 				d2d_res_->GetStrokeStyle(stroke) | 
					
						
							|  |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			IncreasePrimitivesCount(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	void Renderer::FillGeometry(Geometry const & geometry, Color const& fill_color) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!solid_color_brush_ || !device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr) && geometry.GetGeometry()) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color)); | 
					
						
							|  |  |  |  | 			device_context_->FillGeometry( | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 				geometry.GetGeometry().get(), | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 				solid_color_brush_.get() | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 	void Renderer::DrawRectangle(Rect const& rect, Color const& stroke_color, float stroke_width, StrokeStyle stroke) | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 		if (!solid_color_brush_ || !device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color)); | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			device_context_->DrawRectangle( | 
					
						
							|  |  |  |  | 				DX::ConvertToRectF(rect), | 
					
						
							|  |  |  |  | 				solid_color_brush_.get(), | 
					
						
							|  |  |  |  | 				stroke_width, | 
					
						
							|  |  |  |  | 				d2d_res_->GetStrokeStyle(stroke) | 
					
						
							|  |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			IncreasePrimitivesCount(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::FillRectangle(Rect const& rect, Color const& fill_color) | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 		if (!solid_color_brush_ || !device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color)); | 
					
						
							|  |  |  |  | 			device_context_->FillRectangle( | 
					
						
							|  |  |  |  | 				DX::ConvertToRectF(rect), | 
					
						
							|  |  |  |  | 				solid_color_brush_.get() | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::DrawBitmap(ComPtr<ID2D1Bitmap> const & bitmap, Rect const& src_rect, Rect const& dest_rect) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr) && bitmap) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			device_context_->DrawBitmap( | 
					
						
							|  |  |  |  | 				bitmap.get(), | 
					
						
							|  |  |  |  | 				DX::ConvertToRectF(dest_rect), | 
					
						
							|  |  |  |  | 				opacity_, | 
					
						
							|  |  |  |  | 				D2D1_BITMAP_INTERPOLATION_MODE_LINEAR, | 
					
						
							|  |  |  |  | 				DX::ConvertToRectF(src_rect) | 
					
						
							|  |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			IncreasePrimitivesCount(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::DrawTextLayout(ComPtr<IDWriteTextLayout> const& text_layout) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!text_renderer_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = text_layout->Draw(nullptr, text_renderer_.get(), 0, 0); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			IncreasePrimitivesCount(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::SetVSyncEnabled(bool enabled) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		vsync_ = enabled; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::PushClip(const Matrix & clip_matrix, const Size & clip_size) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			device_context_->SetTransform(DX::ConvertToMatrix3x2F(clip_matrix)); | 
					
						
							|  |  |  |  | 			device_context_->PushAxisAlignedClip( | 
					
						
							|  |  |  |  | 				D2D1::RectF(0, 0, clip_size.x, clip_size.y), | 
					
						
							|  |  |  |  | 				D2D1_ANTIALIAS_MODE_PER_PRIMITIVE | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::PopClip() | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			device_context_->PopAxisAlignedClip(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::PushLayer(ComPtr<ID2D1Layer> const& layer, LayerProperties const& properties) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_ || !solid_color_brush_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			device_context_->PushLayer( | 
					
						
							|  |  |  |  | 				D2D1::LayerParameters( | 
					
						
							|  |  |  |  | 					DX::ConvertToRectF(properties.area), | 
					
						
							|  |  |  |  | 					nullptr, | 
					
						
							|  |  |  |  | 					D2D1_ANTIALIAS_MODE_PER_PRIMITIVE, | 
					
						
							|  |  |  |  | 					D2D1::Matrix3x2F::Identity(), | 
					
						
							|  |  |  |  | 					properties.opacity, | 
					
						
							| 
									
										
										
										
											2019-08-14 21:38:37 +08:00
										 |  |  |  | 					nullptr, | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 					D2D1_LAYER_OPTIONS_NONE | 
					
						
							|  |  |  |  | 				), | 
					
						
							|  |  |  |  | 				layer.get() | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::PopLayer() | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			device_context_->PopLayer(); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::Resize(UINT width, UINT 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-14 08:52:01 +08:00
										 |  |  |  | 			output_size_.x = static_cast<float>(width); | 
					
						
							|  |  |  |  | 			output_size_.y = static_cast<float>(height); | 
					
						
							|  |  |  |  | 			hr = d3d_res_->SetLogicalSize(output_size_); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-29 09:40:39 +08:00
										 |  |  |  | 	void Renderer::SetCollectingStatus(bool collecting) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-07-29 09:40:39 +08:00
										 |  |  |  | 		collecting_status_ = collecting; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	void Renderer::SetClearColor(const Color & color) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		clear_color_ = color; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::SetTransform(const Matrix & matrix) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			device_context_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::SetOpacity(float opacity) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 		if (!solid_color_brush_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-07-31 10:12:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			if (opacity_ != opacity) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				opacity_ = opacity; | 
					
						
							|  |  |  |  | 				solid_color_brush_->SetOpacity(opacity); | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::SetTextStyle( | 
					
						
							| 
									
										
										
										
											2019-08-03 23:28:45 +08:00
										 |  |  |  | 		float opacity, | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		Color const& color, | 
					
						
							|  |  |  |  | 		bool has_outline, | 
					
						
							|  |  |  |  | 		Color const& outline_color, | 
					
						
							|  |  |  |  | 		float outline_width, | 
					
						
							|  |  |  |  | 		StrokeStyle outline_stroke | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-07-30 00:41:06 +08:00
										 |  |  |  | 		if (!text_renderer_ || !d3d_res_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			text_renderer_->SetTextStyle( | 
					
						
							|  |  |  |  | 				opacity, | 
					
						
							|  |  |  |  | 				DX::ConvertToColorF(color), | 
					
						
							|  |  |  |  | 				has_outline, | 
					
						
							|  |  |  |  | 				DX::ConvertToColorF(outline_color), | 
					
						
							|  |  |  |  | 				outline_width, | 
					
						
							|  |  |  |  | 				d2d_res_->GetStrokeStyle(outline_stroke) | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::SetAntialiasMode(bool enabled) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			device_context_->SetAntialiasMode( | 
					
						
							|  |  |  |  | 				enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 			antialias_ = enabled; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 	void Renderer::SetTextAntialiasMode(TextAntialias mode) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		HRESULT hr = S_OK; | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		if (!device_context_) | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 			text_antialias_ = mode; | 
					
						
							|  |  |  |  | 			D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; | 
					
						
							|  |  |  |  | 			switch (text_antialias_) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 			case TextAntialias::Default: | 
					
						
							|  |  |  |  | 				antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT; | 
					
						
							|  |  |  |  | 				break; | 
					
						
							|  |  |  |  | 			case TextAntialias::ClearType: | 
					
						
							|  |  |  |  | 				antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE; | 
					
						
							|  |  |  |  | 				break; | 
					
						
							|  |  |  |  | 			case TextAntialias::GrayScale: | 
					
						
							|  |  |  |  | 				antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE; | 
					
						
							|  |  |  |  | 				break; | 
					
						
							|  |  |  |  | 			case TextAntialias::None: | 
					
						
							|  |  |  |  | 				antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED; | 
					
						
							|  |  |  |  | 				break; | 
					
						
							|  |  |  |  | 			default: | 
					
						
							|  |  |  |  | 				break; | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			device_context_->SetTextAntialiasMode(antialias_mode); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-08-14 08:52:01 +08:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | 		ThrowIfFailed(hr); | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-14 00:28:25 +08:00
										 |  |  |  | 	bool Renderer::CheckVisibility(Size const& content_size, Matrix const& transform) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		return Rect{ Point{}, output_size_ }.Intersects( | 
					
						
							|  |  |  |  | 			transform.Transform(Rect{ Point{}, content_size }) | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-31 01:37:06 +08:00
										 |  |  |  | } |