| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | // Copyright (c) 2016-2018 Easy2D - Nomango
 | 
					
						
							|  |  |  |  | // 
 | 
					
						
							|  |  |  |  | // 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 "Factory.h"
 | 
					
						
							|  |  |  |  | #include "logs.h"
 | 
					
						
							|  |  |  |  | #include "modules.h"
 | 
					
						
							|  |  |  |  | #include "Transform.hpp"
 | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | namespace easy2d | 
					
						
							|  |  |  |  | { | 
					
						
							|  |  |  |  | 	FactoryImpl::FactoryImpl() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	FactoryImpl::~FactoryImpl() | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		E2D_LOG("Destroying device independent resources"); | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 	HRESULT FactoryImpl::Init(bool debug) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		E2D_LOG("Creating device independent resources"); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		D2D1_FACTORY_OPTIONS fact_options; | 
					
						
							|  |  |  |  | 		fact_options.debugLevel = debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE; | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		HRESULT hr = modules::DirectX().D2D1CreateFactory( | 
					
						
							|  |  |  |  | 			D2D1_FACTORY_TYPE_SINGLE_THREADED, | 
					
						
							|  |  |  |  | 			__uuidof(ID2D1Factory), | 
					
						
							|  |  |  |  | 			&fact_options, | 
					
						
							|  |  |  |  | 			reinterpret_cast<void**>(&factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			CoCreateInstance( | 
					
						
							|  |  |  |  | 				CLSID_WICImagingFactory, | 
					
						
							|  |  |  |  | 				nullptr, | 
					
						
							|  |  |  |  | 				CLSCTX_INPROC_SERVER, | 
					
						
							|  |  |  |  | 				__uuidof(IWICImagingFactory), | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 				reinterpret_cast<void**>(&imaging_factory_) | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			modules::DirectX().DWriteCreateFactory( | 
					
						
							|  |  |  |  | 				DWRITE_FACTORY_TYPE_SHARED, | 
					
						
							|  |  |  |  | 				__uuidof(IDWriteFactory), | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 				reinterpret_cast<IUnknown**>(&write_factory_) | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			auto stroke_style = D2D1::StrokeStyleProperties( | 
					
						
							|  |  |  |  | 				D2D1_CAP_STYLE_FLAT, | 
					
						
							|  |  |  |  | 				D2D1_CAP_STYLE_FLAT, | 
					
						
							|  |  |  |  | 				D2D1_CAP_STYLE_FLAT, | 
					
						
							|  |  |  |  | 				D2D1_LINE_JOIN_MITER, | 
					
						
							|  |  |  |  | 				2.0f, | 
					
						
							|  |  |  |  | 				D2D1_DASH_STYLE_SOLID, | 
					
						
							|  |  |  |  | 				0.0f | 
					
						
							|  |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			hr = factory_->CreateStrokeStyle( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 				stroke_style, | 
					
						
							|  |  |  |  | 				nullptr, | 
					
						
							|  |  |  |  | 				0, | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 				&miter_stroke_style_ | 
					
						
							|  |  |  |  | 			); | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				stroke_style.lineJoin = D2D1_LINE_JOIN_BEVEL; | 
					
						
							|  |  |  |  | 				hr = factory_->CreateStrokeStyle( | 
					
						
							|  |  |  |  | 					stroke_style, | 
					
						
							|  |  |  |  | 					nullptr, | 
					
						
							|  |  |  |  | 					0, | 
					
						
							|  |  |  |  | 					&bevel_stroke_style_ | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				stroke_style.lineJoin = D2D1_LINE_JOIN_ROUND; | 
					
						
							|  |  |  |  | 				hr = factory_->CreateStrokeStyle( | 
					
						
							|  |  |  |  | 					stroke_style, | 
					
						
							|  |  |  |  | 					nullptr, | 
					
						
							|  |  |  |  | 					0, | 
					
						
							|  |  |  |  | 					&round_stroke_style_ | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateHwndRenderTarget(cpHwndRenderTarget & hwnd_render_target, D2D1_RENDER_TARGET_PROPERTIES const & properties, D2D1_HWND_RENDER_TARGET_PROPERTIES const & hwnd_rt_properties) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		cpHwndRenderTarget hwnd_render_target_tmp; | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		HRESULT hr = factory_->CreateHwndRenderTarget( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			properties, | 
					
						
							|  |  |  |  | 			hwnd_rt_properties, | 
					
						
							|  |  |  |  | 			&hwnd_render_target_tmp | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			hwnd_render_target = hwnd_render_target_tmp; | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateTextRenderer( | 
					
						
							|  |  |  |  | 		cpTextRenderer& text_renderer, | 
					
						
							|  |  |  |  | 		cpRenderTarget const& render_target, | 
					
						
							|  |  |  |  | 		cpSolidColorBrush const& brush | 
					
						
							|  |  |  |  | 	) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		cpTextRenderer text_renderer_tmp; | 
					
						
							|  |  |  |  | 		HRESULT hr = ITextRenderer::Create( | 
					
						
							|  |  |  |  | 			&text_renderer_tmp, | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			factory_.Get(), | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			render_target.Get(), | 
					
						
							|  |  |  |  | 			brush.Get() | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			text_renderer = text_renderer_tmp; | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateBitmapFromFile(cpBitmap & bitmap, cpRenderTarget const & rt, String const & file_path) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (imaging_factory_ == nullptr) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		using namespace intrusive; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		SmartPointer<IWICBitmapDecoder>		decoder; | 
					
						
							|  |  |  |  | 		SmartPointer<IWICBitmapFrameDecode>	source; | 
					
						
							|  |  |  |  | 		SmartPointer<IWICStream>			stream; | 
					
						
							|  |  |  |  | 		SmartPointer<IWICFormatConverter>	converter; | 
					
						
							|  |  |  |  | 		SmartPointer<ID2D1Bitmap>			bitmap_tmp; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		HRESULT hr = imaging_factory_->CreateDecoderFromFilename( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			file_path.c_str(), | 
					
						
							|  |  |  |  | 			nullptr, | 
					
						
							|  |  |  |  | 			GENERIC_READ, | 
					
						
							|  |  |  |  | 			WICDecodeMetadataCacheOnLoad, | 
					
						
							|  |  |  |  | 			&decoder | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = decoder->GetFrame(0, &source); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			hr = imaging_factory_->CreateFormatConverter(&converter); | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			// ͼƬ<CDBC><C6AC>ʽת<CABD><D7AA><EFBFBD><EFBFBD> 32bppPBGRA
 | 
					
						
							|  |  |  |  | 			hr = converter->Initialize( | 
					
						
							|  |  |  |  | 				source.Get(), | 
					
						
							|  |  |  |  | 				GUID_WICPixelFormat32bppPBGRA, | 
					
						
							|  |  |  |  | 				WICBitmapDitherTypeNone, | 
					
						
							|  |  |  |  | 				nullptr, | 
					
						
							|  |  |  |  | 				0.f, | 
					
						
							|  |  |  |  | 				WICBitmapPaletteTypeMedianCut | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = rt->CreateBitmapFromWicBitmap( | 
					
						
							|  |  |  |  | 				converter.Get(), | 
					
						
							|  |  |  |  | 				nullptr, | 
					
						
							|  |  |  |  | 				&bitmap_tmp | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			bitmap = bitmap_tmp; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateBitmapFromResource(cpBitmap & bitmap, cpRenderTarget const & rt, Resource const & res) | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (imaging_factory_ == nullptr) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		using namespace intrusive; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		SmartPointer<IWICBitmapDecoder>		decoder; | 
					
						
							|  |  |  |  | 		SmartPointer<IWICBitmapFrameDecode>	source; | 
					
						
							|  |  |  |  | 		SmartPointer<IWICStream>			stream; | 
					
						
							|  |  |  |  | 		SmartPointer<IWICFormatConverter>	converter; | 
					
						
							|  |  |  |  | 		SmartPointer<ID2D1Bitmap>			bitmap_tmp; | 
					
						
							|  |  |  |  | 		 | 
					
						
							|  |  |  |  | 		// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ
 | 
					
						
							|  |  |  |  | 		ResourceData buffer; | 
					
						
							|  |  |  |  | 		HRESULT hr = res.Load(&buffer) ? S_OK : E_FAIL; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			hr = imaging_factory_->CreateStream(&stream); | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = stream->InitializeFromMemory( | 
					
						
							|  |  |  |  | 				static_cast<WICInProcPointer>(buffer.buffer), | 
					
						
							|  |  |  |  | 				buffer.buffer_size | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			hr = imaging_factory_->CreateDecoderFromStream( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 				stream.Get(), | 
					
						
							|  |  |  |  | 				nullptr, | 
					
						
							|  |  |  |  | 				WICDecodeMetadataCacheOnLoad, | 
					
						
							|  |  |  |  | 				&decoder | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = decoder->GetFrame(0, &source); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			hr = imaging_factory_->CreateFormatConverter(&converter); | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			// ͼƬ<CDBC><C6AC>ʽת<CABD><D7AA><EFBFBD><EFBFBD> 32bppPBGRA
 | 
					
						
							|  |  |  |  | 			hr = converter->Initialize( | 
					
						
							|  |  |  |  | 				source.Get(), | 
					
						
							|  |  |  |  | 				GUID_WICPixelFormat32bppPBGRA, | 
					
						
							|  |  |  |  | 				WICBitmapDitherTypeNone, | 
					
						
							|  |  |  |  | 				nullptr, | 
					
						
							|  |  |  |  | 				0.f, | 
					
						
							|  |  |  |  | 				WICBitmapPaletteTypeMedianCut | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			hr = rt->CreateBitmapFromWicBitmap( | 
					
						
							|  |  |  |  | 				converter.Get(), | 
					
						
							|  |  |  |  | 				nullptr, | 
					
						
							|  |  |  |  | 				&bitmap_tmp | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			bitmap = bitmap_tmp; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateRectangleGeometry(cpRectangleGeometry & geo, Rect const& rect) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		cpRectangleGeometry rectangle; | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		HRESULT hr = factory_->CreateRectangleGeometry( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			rect, | 
					
						
							|  |  |  |  | 			&rectangle | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			geo = rectangle; | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateRoundedRectangleGeometry(cpRoundedRectangleGeometry & geo, Rect const & rect, float radius_x, float radius_y) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		cpRoundedRectangleGeometry rounded_rect; | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		HRESULT hr = factory_->CreateRoundedRectangleGeometry( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			D2D1::RoundedRect( | 
					
						
							|  |  |  |  | 				rect, | 
					
						
							|  |  |  |  | 				radius_x, | 
					
						
							|  |  |  |  | 				radius_y | 
					
						
							|  |  |  |  | 			), | 
					
						
							|  |  |  |  | 			&rounded_rect | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			geo = rounded_rect; | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateEllipseGeometry(cpEllipseGeometry & geo, Point const & center, float radius_x, float radius_y) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		cpEllipseGeometry ellipse; | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		HRESULT hr = factory_->CreateEllipseGeometry( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			D2D1::Ellipse( | 
					
						
							|  |  |  |  | 				center, | 
					
						
							|  |  |  |  | 				radius_x, | 
					
						
							|  |  |  |  | 				radius_y | 
					
						
							|  |  |  |  | 			), | 
					
						
							|  |  |  |  | 			&ellipse | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			geo = ellipse; | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateTransformedGeometry( | 
					
						
							|  |  |  |  | 		cpTransformedGeometry& transformed, | 
					
						
							|  |  |  |  | 		math::Matrix const& matrix, | 
					
						
							|  |  |  |  | 		cpGeometry const& geo | 
					
						
							|  |  |  |  | 	) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		cpTransformedGeometry transformed_tmp; | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		HRESULT hr = factory_->CreateTransformedGeometry( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			geo.Get(), | 
					
						
							|  |  |  |  | 			ConvertToD2DMatrix(matrix), | 
					
						
							|  |  |  |  | 			&transformed_tmp | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			transformed = transformed_tmp; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreatePathGeometry(cpPathGeometry & geometry) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		return factory_->CreatePathGeometry(&geometry); | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateTextFormat(cpTextFormat & text_format, Font const & font, TextStyle const & text_style) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!write_factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		cpTextFormat text_format_tmp; | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		HRESULT hr = write_factory_->CreateTextFormat( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			font.family.c_str(), | 
					
						
							|  |  |  |  | 			nullptr, | 
					
						
							|  |  |  |  | 			DWRITE_FONT_WEIGHT(font.weight), | 
					
						
							|  |  |  |  | 			font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL, | 
					
						
							|  |  |  |  | 			DWRITE_FONT_STRETCH_NORMAL, | 
					
						
							|  |  |  |  | 			font.size, | 
					
						
							|  |  |  |  | 			L"", | 
					
						
							|  |  |  |  | 			&text_format_tmp | 
					
						
							|  |  |  |  | 		); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			if (text_style.line_spacing == 0.f) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				text_format_tmp->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				text_format_tmp->SetLineSpacing( | 
					
						
							|  |  |  |  | 					DWRITE_LINE_SPACING_METHOD_UNIFORM, | 
					
						
							|  |  |  |  | 					text_style.line_spacing, | 
					
						
							|  |  |  |  | 					text_style.line_spacing * 0.8f | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			text_format_tmp->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(text_style.alignment)); | 
					
						
							|  |  |  |  | 			text_format_tmp->SetWordWrapping(text_style.wrap ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP); | 
					
						
							|  |  |  |  | 			text_format = text_format_tmp; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	HRESULT FactoryImpl::CreateTextLayout(cpTextLayout & text_layout, Size& layout_size, String const & text, cpTextFormat const& text_format, TextStyle const & text_style) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		if (!write_factory_) | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			return E_UNEXPECTED; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		text_layout = nullptr; | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		HRESULT hr; | 
					
						
							|  |  |  |  | 		cpTextLayout text_layout_tmp; | 
					
						
							|  |  |  |  | 		UINT32 length = static_cast<UINT32>(text.length()); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (text_style.wrap) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			hr = write_factory_->CreateTextLayout( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 				text.c_str(), | 
					
						
							|  |  |  |  | 				length, | 
					
						
							|  |  |  |  | 				text_format.Get(), | 
					
						
							|  |  |  |  | 				text_style.wrap_width, | 
					
						
							|  |  |  |  | 				0, | 
					
						
							|  |  |  |  | 				&text_layout_tmp | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		else | 
					
						
							|  |  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			hr = write_factory_->CreateTextLayout( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 				text.c_str(), | 
					
						
							|  |  |  |  | 				length, | 
					
						
							|  |  |  |  | 				text_format.Get(), | 
					
						
							|  |  |  |  | 				0, | 
					
						
							|  |  |  |  | 				0, | 
					
						
							|  |  |  |  | 				&text_layout_tmp | 
					
						
							|  |  |  |  | 			); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			DWRITE_TEXT_METRICS metrics; | 
					
						
							|  |  |  |  | 			text_layout_tmp->GetMetrics(&metrics); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				text_layout_tmp = nullptr; | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 				hr = write_factory_->CreateTextLayout( | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 					text.c_str(), | 
					
						
							|  |  |  |  | 					length, | 
					
						
							|  |  |  |  | 					text_format.Get(), | 
					
						
							|  |  |  |  | 					metrics.width, | 
					
						
							|  |  |  |  | 					0, | 
					
						
							|  |  |  |  | 					&text_layout_tmp | 
					
						
							|  |  |  |  | 				); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if (SUCCEEDED(hr)) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 			DWRITE_TEXT_METRICS metrics; | 
					
						
							|  |  |  |  | 			text_layout_tmp->GetMetrics(&metrics); | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if (text_style.wrap) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				layout_size = Size(metrics.layoutWidth, metrics.height); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			else | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				layout_size = Size(metrics.width, metrics.height); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			DWRITE_TEXT_RANGE range = { 0, length }; | 
					
						
							|  |  |  |  | 			if (text_style.underline) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				text_layout_tmp->SetUnderline(true, range); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			if (text_style.strikethrough) | 
					
						
							|  |  |  |  | 			{ | 
					
						
							|  |  |  |  | 				text_layout_tmp->SetStrikethrough(true, range); | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			text_layout = text_layout_tmp; | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return hr; | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	cpStrokeStyle const& FactoryImpl::GetStrokeStyle(StrokeStyle stroke) const | 
					
						
							|  |  |  |  | 	{ | 
					
						
							|  |  |  |  | 		switch (stroke) | 
					
						
							|  |  |  |  | 		{ | 
					
						
							|  |  |  |  | 		case StrokeStyle::Miter: | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			return miter_stroke_style_; | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		case StrokeStyle::Bevel: | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			return bevel_stroke_style_; | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		case StrokeStyle::Round: | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 			return round_stroke_style_; | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 			break; | 
					
						
							|  |  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-11-21 19:24:18 +08:00
										 |  |  |  | 		return miter_stroke_style_; | 
					
						
							| 
									
										
										
										
											2018-11-21 17:18:59 +08:00
										 |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | } |