commit
						a441603f57
					
				|  | @ -64,6 +64,7 @@ | ||||||
|     <ClInclude Include="..\src\kiwano\math\Vec2.hpp" /> |     <ClInclude Include="..\src\kiwano\math\Vec2.hpp" /> | ||||||
|     <ClInclude Include="..\src\kiwano\platform\Application.h" /> |     <ClInclude Include="..\src\kiwano\platform\Application.h" /> | ||||||
|     <ClInclude Include="..\src\kiwano\platform\modules.h" /> |     <ClInclude Include="..\src\kiwano\platform\modules.h" /> | ||||||
|  |     <ClInclude Include="..\src\kiwano\renderer\Brush.h" /> | ||||||
|     <ClInclude Include="..\src\kiwano\renderer\Color.h" /> |     <ClInclude Include="..\src\kiwano\renderer\Color.h" /> | ||||||
|     <ClInclude Include="..\src\kiwano\renderer\Font.h" /> |     <ClInclude Include="..\src\kiwano\renderer\Font.h" /> | ||||||
|     <ClInclude Include="..\src\kiwano\renderer\FontCollection.h" /> |     <ClInclude Include="..\src\kiwano\renderer\FontCollection.h" /> | ||||||
|  | @ -127,6 +128,7 @@ | ||||||
|     <ClCompile Include="..\src\kiwano\base\Window.cpp" /> |     <ClCompile Include="..\src\kiwano\base\Window.cpp" /> | ||||||
|     <ClCompile Include="..\src\kiwano\platform\Application.cpp" /> |     <ClCompile Include="..\src\kiwano\platform\Application.cpp" /> | ||||||
|     <ClCompile Include="..\src\kiwano\platform\modules.cpp" /> |     <ClCompile Include="..\src\kiwano\platform\modules.cpp" /> | ||||||
|  |     <ClCompile Include="..\src\kiwano\renderer\Brush.cpp" /> | ||||||
|     <ClCompile Include="..\src\kiwano\renderer\Color.cpp" /> |     <ClCompile Include="..\src\kiwano\renderer\Color.cpp" /> | ||||||
|     <ClCompile Include="..\src\kiwano\renderer\Font.cpp" /> |     <ClCompile Include="..\src\kiwano\renderer\Font.cpp" /> | ||||||
|     <ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp" /> |     <ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp" /> | ||||||
|  |  | ||||||
|  | @ -306,6 +306,9 @@ | ||||||
|     <ClInclude Include="..\src\kiwano\renderer\StrokeStyle.h"> |     <ClInclude Include="..\src\kiwano\renderer\StrokeStyle.h"> | ||||||
|       <Filter>renderer</Filter> |       <Filter>renderer</Filter> | ||||||
|     </ClInclude> |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\src\kiwano\renderer\Brush.h"> | ||||||
|  |       <Filter>renderer</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="..\src\kiwano\ui\Button.cpp"> |     <ClCompile Include="..\src\kiwano\ui\Button.cpp"> | ||||||
|  | @ -482,5 +485,8 @@ | ||||||
|     <ClCompile Include="..\src\kiwano\renderer\TextureCache.cpp"> |     <ClCompile Include="..\src\kiwano\renderer\TextureCache.cpp"> | ||||||
|       <Filter>renderer</Filter> |       <Filter>renderer</Filter> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\src\kiwano\renderer\Brush.cpp"> | ||||||
|  |       <Filter>renderer</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
|  | @ -131,8 +131,12 @@ namespace kiwano | ||||||
| 			Rect bounds = GetBounds(); | 			Rect bounds = GetBounds(); | ||||||
| 
 | 
 | ||||||
| 			rt->SetTransform(transform_matrix_); | 			rt->SetTransform(transform_matrix_); | ||||||
| 			rt->FillRectangle(bounds, Color(Color::Red, .4f)); | 
 | ||||||
| 			rt->DrawRectangle(bounds, Color(Color::Red, .8f), 2.f); | 			rt->SetDefaultBrushColor(Color(Color::Red, .4f)); | ||||||
|  | 			rt->FillRectangle(bounds); | ||||||
|  | 
 | ||||||
|  | 			rt->SetDefaultBrushColor(Color(Color::Red, .8f)); | ||||||
|  | 			rt->DrawRectangle(bounds, 2.f); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (auto child = children_.first_item(); child; child = child->next_item()) | 		for (auto child = children_.first_item(); child; child = child->next_item()) | ||||||
|  |  | ||||||
|  | @ -149,10 +149,10 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void Canvas::DrawLine(Point const& begin, Point const& end) | 	void Canvas::DrawLine(Point const& begin, Point const& end) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(stroke_color_); | ||||||
| 		rt_.DrawLine( | 		rt_.DrawLine( | ||||||
| 			begin, | 			begin, | ||||||
| 			end, | 			end, | ||||||
| 			stroke_color_, |  | ||||||
| 			stroke_width_, | 			stroke_width_, | ||||||
| 			stroke_style_ | 			stroke_style_ | ||||||
| 		); | 		); | ||||||
|  | @ -161,10 +161,10 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void Canvas::DrawCircle(Point const& center, Float32 radius) | 	void Canvas::DrawCircle(Point const& center, Float32 radius) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(stroke_color_); | ||||||
| 		rt_.DrawEllipse( | 		rt_.DrawEllipse( | ||||||
| 			center, | 			center, | ||||||
| 			Vec2(radius, radius), | 			Vec2(radius, radius), | ||||||
| 			stroke_color_, |  | ||||||
| 			stroke_width_, | 			stroke_width_, | ||||||
| 			stroke_style_ | 			stroke_style_ | ||||||
| 		); | 		); | ||||||
|  | @ -173,10 +173,10 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void Canvas::DrawEllipse(Point const& center, Vec2 const& radius) | 	void Canvas::DrawEllipse(Point const& center, Vec2 const& radius) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(stroke_color_); | ||||||
| 		rt_.DrawEllipse( | 		rt_.DrawEllipse( | ||||||
| 			center, | 			center, | ||||||
| 			radius, | 			radius, | ||||||
| 			stroke_color_, |  | ||||||
| 			stroke_width_, | 			stroke_width_, | ||||||
| 			stroke_style_ | 			stroke_style_ | ||||||
| 		); | 		); | ||||||
|  | @ -185,9 +185,9 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void Canvas::DrawRect(Rect const& rect) | 	void Canvas::DrawRect(Rect const& rect) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(stroke_color_); | ||||||
| 		rt_.DrawRectangle( | 		rt_.DrawRectangle( | ||||||
| 			rect, | 			rect, | ||||||
| 			stroke_color_, |  | ||||||
| 			stroke_width_, | 			stroke_width_, | ||||||
| 			stroke_style_ | 			stroke_style_ | ||||||
| 		); | 		); | ||||||
|  | @ -196,10 +196,10 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius) | 	void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(stroke_color_); | ||||||
| 		rt_.DrawRoundedRectangle( | 		rt_.DrawRoundedRectangle( | ||||||
| 			rect, | 			rect, | ||||||
| 			radius, | 			radius, | ||||||
| 			stroke_color_, |  | ||||||
| 			stroke_width_, | 			stroke_width_, | ||||||
| 			stroke_style_ | 			stroke_style_ | ||||||
| 		); | 		); | ||||||
|  | @ -208,39 +208,39 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void Canvas::FillCircle(Point const& center, Float32 radius) | 	void Canvas::FillCircle(Point const& center, Float32 radius) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(fill_color_); | ||||||
| 		rt_.FillEllipse( | 		rt_.FillEllipse( | ||||||
| 			center, | 			center, | ||||||
| 			Vec2(radius, radius), | 			Vec2(radius, radius) | ||||||
| 			fill_color_ |  | ||||||
| 		); | 		); | ||||||
| 		cache_expired_ = true; | 		cache_expired_ = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Canvas::FillEllipse(Point const& center, Vec2 const& radius) | 	void Canvas::FillEllipse(Point const& center, Vec2 const& radius) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(fill_color_); | ||||||
| 		rt_.FillEllipse( | 		rt_.FillEllipse( | ||||||
| 			center, | 			center, | ||||||
| 			radius, | 			radius | ||||||
| 			fill_color_ |  | ||||||
| 		); | 		); | ||||||
| 		cache_expired_ = true; | 		cache_expired_ = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Canvas::FillRect(Rect const& rect) | 	void Canvas::FillRect(Rect const& rect) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(fill_color_); | ||||||
| 		rt_.FillRectangle( | 		rt_.FillRectangle( | ||||||
| 			rect, | 			rect | ||||||
| 			fill_color_ |  | ||||||
| 		); | 		); | ||||||
| 		cache_expired_ = true; | 		cache_expired_ = true; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius) | 	void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius) | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(fill_color_); | ||||||
| 		rt_.FillRoundedRectangle( | 		rt_.FillRoundedRectangle( | ||||||
| 			rect, | 			rect, | ||||||
| 			radius, | 			radius | ||||||
| 			fill_color_ |  | ||||||
| 		); | 		); | ||||||
| 		cache_expired_ = true; | 		cache_expired_ = true; | ||||||
| 	} | 	} | ||||||
|  | @ -296,9 +296,9 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void Canvas::StrokePath() | 	void Canvas::StrokePath() | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(stroke_color_); | ||||||
| 		rt_.DrawGeometry( | 		rt_.DrawGeometry( | ||||||
| 			geo_sink_.GetGeometry(), | 			geo_sink_.GetGeometry(), | ||||||
| 			stroke_color_, |  | ||||||
| 			stroke_width_, | 			stroke_width_, | ||||||
| 			stroke_style_ | 			stroke_style_ | ||||||
| 		); | 		); | ||||||
|  | @ -307,9 +307,9 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void Canvas::FillPath() | 	void Canvas::FillPath() | ||||||
| 	{ | 	{ | ||||||
|  | 		rt_.SetDefaultBrushColor(fill_color_); | ||||||
| 		rt_.FillGeometry( | 		rt_.FillGeometry( | ||||||
| 			geo_sink_.GetGeometry(), | 			geo_sink_.GetGeometry() | ||||||
| 			fill_color_ |  | ||||||
| 		); | 		); | ||||||
| 		cache_expired_ = true; | 		cache_expired_ = true; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -78,7 +78,8 @@ namespace kiwano | ||||||
| 	{ | 	{ | ||||||
| 		PrepareRender(rt); | 		PrepareRender(rt); | ||||||
| 
 | 
 | ||||||
| 		rt->FillRoundedRectangle(GetBounds(), Vec2{ 5.f, 5.f }, background_color_); | 		rt->SetDefaultBrushColor(background_color_); | ||||||
|  | 		rt->FillRoundedRectangle(GetBounds(), Vec2{ 5.f, 5.f }); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void DebugActor::OnUpdate(Duration dt) | 	void DebugActor::OnUpdate(Duration dt) | ||||||
|  |  | ||||||
|  | @ -83,8 +83,6 @@ namespace kiwano | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Layer::Render(RenderTarget* rt) | 	void Layer::Render(RenderTarget* rt) | ||||||
| 	{ |  | ||||||
| 		if (!children_.empty()) |  | ||||||
| 	{ | 	{ | ||||||
| 		PrepareRender(rt); | 		PrepareRender(rt); | ||||||
| 
 | 
 | ||||||
|  | @ -92,7 +90,6 @@ namespace kiwano | ||||||
| 		Actor::Render(rt); | 		Actor::Render(rt); | ||||||
| 		rt->PopLayer(); | 		rt->PopLayer(); | ||||||
| 	} | 	} | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	void Layer::HandleMessages(Event const& evt) | 	void Layer::HandleMessages(Event const& evt) | ||||||
| 	{ | 	{ | ||||||
|  |  | ||||||
|  | @ -101,16 +101,16 @@ namespace kiwano | ||||||
| 		{ | 		{ | ||||||
| 			PrepareRender(rt); | 			PrepareRender(rt); | ||||||
| 
 | 
 | ||||||
|  | 			rt->SetDefaultBrushColor(stroke_color_); | ||||||
| 			rt->DrawGeometry( | 			rt->DrawGeometry( | ||||||
| 				geo_, | 				geo_, | ||||||
| 				stroke_color_, |  | ||||||
| 				stroke_width_ * 2,  // twice width for widening
 | 				stroke_width_ * 2,  // twice width for widening
 | ||||||
| 				stroke_style_ | 				stroke_style_ | ||||||
| 			); | 			); | ||||||
| 
 | 
 | ||||||
|  | 			rt->SetDefaultBrushColor(fill_color_); | ||||||
| 			rt->FillGeometry( | 			rt->FillGeometry( | ||||||
| 				geo_, | 				geo_ | ||||||
| 				fill_color_ |  | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -45,7 +45,7 @@ namespace kiwano | ||||||
| 			}; | 			}; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		static bool Check(UInt32 type); | 		static bool Check(Int32 type); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	// 键盘事件
 | 	// 键盘事件
 | ||||||
|  | @ -65,7 +65,7 @@ namespace kiwano | ||||||
| 			}; | 			}; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		static bool Check(UInt32 type); | 		static bool Check(Int32 type); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	// 窗口事件
 | 	// 窗口事件
 | ||||||
|  | @ -96,7 +96,7 @@ namespace kiwano | ||||||
| 			}; | 			}; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		static bool Check(UInt32 type); | 		static bool Check(Int32 type); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	// 自定义事件
 | 	// 自定义事件
 | ||||||
|  | @ -110,7 +110,7 @@ namespace kiwano | ||||||
| 	// 事件
 | 	// 事件
 | ||||||
| 	struct KGE_API Event | 	struct KGE_API Event | ||||||
| 	{ | 	{ | ||||||
| 		enum Type : UInt32 | 		enum Type : Int32 | ||||||
| 		{ | 		{ | ||||||
| 			First, | 			First, | ||||||
| 
 | 
 | ||||||
|  | @ -144,34 +144,34 @@ namespace kiwano | ||||||
| 			Last | 			Last | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		UInt32 type; | 		Int32 type; | ||||||
| 		Actor* target; | 		Actor* target; | ||||||
| 
 | 
 | ||||||
| 		union | 		union | ||||||
| 		{ | 		{ | ||||||
| 			MouseEvent mouse; | 			MouseEvent mouse; | ||||||
| 			KeyboardEvent key; | 			KeyboardEvent key; | ||||||
| 			WindowEvent win; | 			WindowEvent window; | ||||||
| 			CustomEvent custom; | 			CustomEvent custom; | ||||||
| 		}; | 		}; | ||||||
| 
 | 
 | ||||||
| 		Event(UInt32 type = Type::First) : type(type), target(nullptr) {} | 		Event(Int32 type = Type::First) : type(type), target(nullptr) {} | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| 	// Check-functions
 | 	// Check-functions
 | ||||||
| 
 | 
 | ||||||
| 	inline bool MouseEvent::Check(UInt32 type) | 	inline bool MouseEvent::Check(Int32 type) | ||||||
| 	{ | 	{ | ||||||
| 		return type > Event::MouseFirst && type < Event::MouseLast; | 		return type > Event::MouseFirst && type < Event::MouseLast; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	inline bool KeyboardEvent::Check(UInt32 type) | 	inline bool KeyboardEvent::Check(Int32 type) | ||||||
| 	{ | 	{ | ||||||
| 		return type > Event::KeyFirst && type < Event::KeyLast; | 		return type > Event::KeyFirst && type < Event::KeyLast; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	inline bool WindowEvent::Check(UInt32 type) | 	inline bool WindowEvent::Check(Int32 type) | ||||||
| 	{ | 	{ | ||||||
| 		return type > Event::WindowFirst && type < Event::WindowLast; | 		return type > Event::WindowFirst && type < Event::WindowLast; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -42,6 +42,7 @@ namespace kiwano | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon) | 	Config::Config(String const& title, UInt32 width, UInt32 height, UInt32 icon) | ||||||
|  | 		: debug(false) | ||||||
| 	{ | 	{ | ||||||
| 		window.title = title; | 		window.title = title; | ||||||
| 		window.width = width; | 		window.width = width; | ||||||
|  | @ -50,6 +51,7 @@ namespace kiwano | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config) | 	Config::Config(WindowConfig const& wnd_config, RenderConfig const& render_config) | ||||||
|  | 		: debug(false) | ||||||
| 	{ | 	{ | ||||||
| 		window = wnd_config; | 		window = wnd_config; | ||||||
| 		render = render_config; | 		render = render_config; | ||||||
|  | @ -382,8 +384,8 @@ namespace kiwano | ||||||
| 				Window::GetInstance()->UpdateWindowRect(); | 				Window::GetInstance()->UpdateWindowRect(); | ||||||
| 
 | 
 | ||||||
| 				Event evt(Event::WindowResized); | 				Event evt(Event::WindowResized); | ||||||
| 				evt.win.width = LOWORD(lparam); | 				evt.window.width = LOWORD(lparam); | ||||||
| 				evt.win.height = HIWORD(lparam); | 				evt.window.height = HIWORD(lparam); | ||||||
| 				app->DispatchEvent(evt); | 				app->DispatchEvent(evt); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -395,8 +397,8 @@ namespace kiwano | ||||||
| 			Int32 y = (Int32)(short)HIWORD(lparam); | 			Int32 y = (Int32)(short)HIWORD(lparam); | ||||||
| 
 | 
 | ||||||
| 			Event evt(Event::WindowMoved); | 			Event evt(Event::WindowMoved); | ||||||
| 			evt.win.x = x; | 			evt.window.x = x; | ||||||
| 			evt.win.y = y; | 			evt.window.y = y; | ||||||
| 			app->DispatchEvent(evt); | 			app->DispatchEvent(evt); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
|  | @ -408,7 +410,7 @@ namespace kiwano | ||||||
| 			Window::GetInstance()->SetActive(active); | 			Window::GetInstance()->SetActive(active); | ||||||
| 
 | 
 | ||||||
| 			Event evt(Event::WindowFocusChanged); | 			Event evt(Event::WindowFocusChanged); | ||||||
| 			evt.win.focus = active; | 			evt.window.focus = active; | ||||||
| 			app->DispatchEvent(evt); | 			app->DispatchEvent(evt); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
|  | @ -418,7 +420,7 @@ namespace kiwano | ||||||
| 			// KGE_LOG(L"Window title changed");
 | 			// KGE_LOG(L"Window title changed");
 | ||||||
| 
 | 
 | ||||||
| 			Event evt(Event::WindowTitleChanged); | 			Event evt(Event::WindowTitleChanged); | ||||||
| 			evt.win.title = reinterpret_cast<const WChar*>(lparam); | 			evt.window.title = reinterpret_cast<const WChar*>(lparam); | ||||||
| 			app->DispatchEvent(evt); | 			app->DispatchEvent(evt); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
|  | @ -0,0 +1,142 @@ | ||||||
|  | // Copyright (c) 2016-2018 Kiwano - 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 "Brush.h" | ||||||
|  | #include "Renderer.h" | ||||||
|  | #include "../base/Logger.h" | ||||||
|  | 
 | ||||||
|  | namespace kiwano | ||||||
|  | { | ||||||
|  | 	SolidColorStyle::SolidColorStyle(Color const& color) | ||||||
|  | 		: color(color) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	LinearGradientStyle::LinearGradientStyle(Point const& begin, Point const& end, Vector<GradientStop> const& stops, GradientExtendMode extend_mode) | ||||||
|  | 		: begin(begin) | ||||||
|  | 		, end(end) | ||||||
|  | 		, stops(stops) | ||||||
|  | 		, extend_mode(extend_mode) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	RadialGradientStyle::RadialGradientStyle(Point const& center, Vec2 const& offset, Vec2 const& radius, Vector<GradientStop> const& stops, GradientExtendMode extend_mode) | ||||||
|  | 		: center(center) | ||||||
|  | 		, offset(offset) | ||||||
|  | 		, radius(radius) | ||||||
|  | 		, stops(stops) | ||||||
|  | 		, extend_mode(extend_mode) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Brush::Brush() | ||||||
|  | 		: opacity_(1.f) | ||||||
|  | 		, type_(Type::Unknown) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Brush::Brush(Color const& color) | ||||||
|  | 		: Brush() | ||||||
|  | 	{ | ||||||
|  | 		SetColor(color); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Brush::Brush(SolidColorStyle const& style) | ||||||
|  | 		: Brush() | ||||||
|  | 	{ | ||||||
|  | 		SetStyle(style); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Brush::Brush(LinearGradientStyle const& style) | ||||||
|  | 		: Brush() | ||||||
|  | 	{ | ||||||
|  | 		SetStyle(style); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Brush::Brush(RadialGradientStyle const& style) | ||||||
|  | 		: Brush() | ||||||
|  | 	{ | ||||||
|  | 		SetStyle(style); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool Brush::IsValid() const | ||||||
|  | 	{ | ||||||
|  | 		return raw_ != nullptr; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Brush::Brush(ComPtr<ID2D1Brush> brush) | ||||||
|  | 		: Brush() | ||||||
|  | 	{ | ||||||
|  | 		SetBrush(brush); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	Float32 Brush::GetOpacity() const | ||||||
|  | 	{ | ||||||
|  | 		return opacity_; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Brush::SetOpacity(Float32 opacity) | ||||||
|  | 	{ | ||||||
|  | 		opacity_ = opacity; | ||||||
|  | 		if (raw_) | ||||||
|  | 		{ | ||||||
|  | 			raw_->SetOpacity(opacity); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Brush::SetStyle(SolidColorStyle const& style) | ||||||
|  | 	{ | ||||||
|  | 		if (type_ == Type::SolidColor && raw_) | ||||||
|  | 		{ | ||||||
|  | 			auto solid_brush = dynamic_cast<ID2D1SolidColorBrush*>(raw_.get()); | ||||||
|  | 			KGE_ASSERT(solid_brush != nullptr); | ||||||
|  | 			solid_brush->SetColor(DX::ConvertToColorF(style.color)); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		{ | ||||||
|  | 			Renderer::GetInstance()->CreateSolidBrush(*this, style.color); | ||||||
|  | 			type_ = Type::SolidColor; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Brush::SetStyle(LinearGradientStyle const& style) | ||||||
|  | 	{ | ||||||
|  | 		Renderer::GetInstance()->CreateLinearGradientBrush(*this, style.begin, style.end, style.stops, style.extend_mode); | ||||||
|  | 		type_ = Type::LinearGradient; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Brush::SetStyle(RadialGradientStyle const& style) | ||||||
|  | 	{ | ||||||
|  | 		Renderer::GetInstance()->CreateRadialGradientBrush(*this, style.center, style.offset, style.radius, style.stops, style.extend_mode); | ||||||
|  | 		type_ = Type::RadialGradient; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Brush::SetBrush(ComPtr<ID2D1Brush> const& brush) | ||||||
|  | 	{ | ||||||
|  | 		type_ = Type::Unknown; | ||||||
|  | 		raw_ = brush; | ||||||
|  | 
 | ||||||
|  | 		if (raw_) | ||||||
|  | 		{ | ||||||
|  | 			raw_->SetOpacity(opacity_); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,166 @@ | ||||||
|  | // Copyright (c) 2016-2018 Kiwano - 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.
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | #include "win32/D2DDeviceResources.h" | ||||||
|  | 
 | ||||||
|  | namespace kiwano | ||||||
|  | { | ||||||
|  | 	// 渐变转换点
 | ||||||
|  | 	struct GradientStop | ||||||
|  | 	{ | ||||||
|  | 		Float32 offset; | ||||||
|  | 		Color color; | ||||||
|  | 
 | ||||||
|  | 		GradientStop() : offset(0.f), color() {} | ||||||
|  | 
 | ||||||
|  | 		GradientStop(Float32 offset, Color color) : offset(offset), color(color) {} | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// 渐变扩充模式
 | ||||||
|  | 	// 该模式用于指定画笔如何绘制正常区域外的部分
 | ||||||
|  | 	// Clamp  (夹模式): 重复绘制边界颜色
 | ||||||
|  | 	// Wrap   (夹模式): 重复画笔内容
 | ||||||
|  | 	// Mirror (镜像模式): 反转画笔内容
 | ||||||
|  | 	enum class GradientExtendMode | ||||||
|  | 	{ | ||||||
|  | 		Clamp, | ||||||
|  | 		Wrap, | ||||||
|  | 		Mirror | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	// 纯色样式
 | ||||||
|  | 	struct SolidColorStyle | ||||||
|  | 	{ | ||||||
|  | 		Color color; | ||||||
|  | 
 | ||||||
|  | 		SolidColorStyle(Color const& color); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	// 线性渐变样式
 | ||||||
|  | 	struct LinearGradientStyle | ||||||
|  | 	{ | ||||||
|  | 		Point begin; | ||||||
|  | 		Point end; | ||||||
|  | 		Vector<GradientStop> stops; | ||||||
|  | 		GradientExtendMode extend_mode; | ||||||
|  | 
 | ||||||
|  | 		LinearGradientStyle( | ||||||
|  | 			Point const& begin, | ||||||
|  | 			Point const& end, | ||||||
|  | 			Vector<GradientStop> const& stops, | ||||||
|  | 			GradientExtendMode extend_mode = GradientExtendMode::Clamp | ||||||
|  | 		); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	// 径向渐变样式
 | ||||||
|  | 	struct RadialGradientStyle | ||||||
|  | 	{ | ||||||
|  | 		Point center; | ||||||
|  | 		Vec2 offset; | ||||||
|  | 		Vec2 radius; | ||||||
|  | 		Vector<GradientStop> stops; | ||||||
|  | 		GradientExtendMode extend_mode; | ||||||
|  | 
 | ||||||
|  | 		RadialGradientStyle( | ||||||
|  | 			Point const& center, | ||||||
|  | 			Vec2 const& offset, | ||||||
|  | 			Vec2 const& radius, | ||||||
|  | 			Vector<GradientStop> const& stops, | ||||||
|  | 			GradientExtendMode extend_mode = GradientExtendMode::Clamp | ||||||
|  | 		); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	// 画笔
 | ||||||
|  | 	class KGE_API Brush | ||||||
|  | 	{ | ||||||
|  | 	public: | ||||||
|  | 		Brush(); | ||||||
|  | 
 | ||||||
|  | 		Brush( | ||||||
|  | 			Color const& color | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		Brush( | ||||||
|  | 			SolidColorStyle const& style | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		Brush( | ||||||
|  | 			LinearGradientStyle const& style | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		Brush( | ||||||
|  | 			RadialGradientStyle const& style | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		bool IsValid() const; | ||||||
|  | 
 | ||||||
|  | 		inline void SetColor( | ||||||
|  | 			Color const& color | ||||||
|  | 		) | ||||||
|  | 		{ | ||||||
|  | 			SetStyle(SolidColorStyle{ color }); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		void SetStyle( | ||||||
|  | 			SolidColorStyle const& style | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		void SetStyle( | ||||||
|  | 			LinearGradientStyle const& style | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		void SetStyle( | ||||||
|  | 			RadialGradientStyle const& style | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		Float32 GetOpacity() const; | ||||||
|  | 
 | ||||||
|  | 		void SetOpacity(Float32 opacity); | ||||||
|  | 
 | ||||||
|  | 	public: | ||||||
|  | 		enum class Type | ||||||
|  | 		{ | ||||||
|  | 			Unknown, | ||||||
|  | 			SolidColor,			// 纯色填充
 | ||||||
|  | 			LinearGradient,		// 线性渐变
 | ||||||
|  | 			RadialGradient		// 径向渐变
 | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		Type GetType() const { return type_; } | ||||||
|  | 
 | ||||||
|  | 	public: | ||||||
|  | 		Brush( | ||||||
|  | 			ComPtr<ID2D1Brush> brush | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		void SetBrush(ComPtr<ID2D1Brush> const& brush); | ||||||
|  | 
 | ||||||
|  | 		inline ComPtr<ID2D1Brush> const& GetBrush() const { return raw_; } | ||||||
|  | 
 | ||||||
|  | 	protected: | ||||||
|  | 		Type type_; | ||||||
|  | 		Float32 opacity_; | ||||||
|  | 		ComPtr<ID2D1Brush> raw_; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -67,6 +67,11 @@ namespace kiwano | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			current_brush_ = default_brush_; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		return hr; | 		return hr; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -86,8 +91,6 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::BeginDraw() | 	void RenderTarget::BeginDraw() | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = E_FAIL; |  | ||||||
| 
 |  | ||||||
| 		if (collecting_status_) | 		if (collecting_status_) | ||||||
| 		{ | 		{ | ||||||
| 			status_.start = Time::Now(); | 			status_.start = Time::Now(); | ||||||
|  | @ -97,10 +100,7 @@ namespace kiwano | ||||||
| 		if (render_target_) | 		if (render_target_) | ||||||
| 		{ | 		{ | ||||||
| 			render_target_->BeginDraw(); | 			render_target_->BeginDraw(); | ||||||
| 			hr = S_OK; |  | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		ThrowIfFailed(hr); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::EndDraw() | 	void RenderTarget::EndDraw() | ||||||
|  | @ -113,26 +113,19 @@ namespace kiwano | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::DrawGeometry( | 	void RenderTarget::DrawGeometry(Geometry const& geometry, Float32 stroke_width, StrokeStyle stroke) const | ||||||
| 		Geometry const& geometry, |  | ||||||
| 		Color const& stroke_color, |  | ||||||
| 		Float32 stroke_width, |  | ||||||
| 		StrokeStyle stroke |  | ||||||
| 	) const |  | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr) && geometry.GetGeometry()) | 		if (SUCCEEDED(hr) && geometry.GetGeometry()) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); |  | ||||||
| 
 |  | ||||||
| 			render_target_->DrawGeometry( | 			render_target_->DrawGeometry( | ||||||
| 				geometry.GetGeometry().get(), | 				geometry.GetGeometry().get(), | ||||||
| 				default_brush_.get(), | 				current_brush_.get(), | ||||||
| 				stroke_width, | 				stroke_width, | ||||||
| 				GetStrokeStyle(stroke).get() | 				GetStrokeStyle(stroke).get() | ||||||
| 			); | 			); | ||||||
|  | @ -143,42 +136,39 @@ namespace kiwano | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::FillGeometry(Geometry const& geometry, Color const& fill_color) const | 	void RenderTarget::FillGeometry(Geometry const& geometry) const | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr) && geometry.GetGeometry()) | 		if (SUCCEEDED(hr) && geometry.GetGeometry()) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(fill_color)); |  | ||||||
| 			render_target_->FillGeometry( | 			render_target_->FillGeometry( | ||||||
| 				geometry.GetGeometry().get(), | 				geometry.GetGeometry().get(), | ||||||
| 				default_brush_.get() | 				current_brush_.get() | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::DrawLine(Point const& point1, Point const& point2, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const | 	void RenderTarget::DrawLine(Point const& point1, Point const& point2, Float32 stroke_width, StrokeStyle stroke) const | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); |  | ||||||
| 
 |  | ||||||
| 			render_target_->DrawLine( | 			render_target_->DrawLine( | ||||||
| 				DX::ConvertToPoint2F(point1), | 				DX::ConvertToPoint2F(point1), | ||||||
| 				DX::ConvertToPoint2F(point2), | 				DX::ConvertToPoint2F(point2), | ||||||
| 				default_brush_.get(), | 				current_brush_.get(), | ||||||
| 				stroke_width, | 				stroke_width, | ||||||
| 				GetStrokeStyle(stroke).get() | 				GetStrokeStyle(stroke).get() | ||||||
| 			); | 			); | ||||||
|  | @ -189,21 +179,20 @@ namespace kiwano | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::DrawRectangle(Rect const& rect, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const | 	void RenderTarget::DrawRectangle(Rect const& rect, Float32 stroke_width, StrokeStyle stroke) const | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 
 | ||||||
|  | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); |  | ||||||
| 
 |  | ||||||
| 			render_target_->DrawRectangle( | 			render_target_->DrawRectangle( | ||||||
| 				DX::ConvertToRectF(rect), | 				DX::ConvertToRectF(rect), | ||||||
| 				default_brush_.get(), | 				current_brush_.get(), | ||||||
| 				stroke_width, | 				stroke_width, | ||||||
| 				GetStrokeStyle(stroke).get() | 				GetStrokeStyle(stroke).get() | ||||||
| 			); | 			); | ||||||
|  | @ -214,45 +203,42 @@ namespace kiwano | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::FillRectangle(Rect const& rect, Color const& fill_color) const | 	void RenderTarget::FillRectangle(Rect const& rect) const | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(fill_color)); |  | ||||||
| 			render_target_->FillRectangle( | 			render_target_->FillRectangle( | ||||||
| 				DX::ConvertToRectF(rect), | 				DX::ConvertToRectF(rect), | ||||||
| 				default_brush_.get() | 				current_brush_.get() | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const | 	void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, Float32 stroke_width, StrokeStyle stroke) const | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); |  | ||||||
| 
 |  | ||||||
| 			render_target_->DrawRoundedRectangle( | 			render_target_->DrawRoundedRectangle( | ||||||
| 				D2D1::RoundedRect( | 				D2D1::RoundedRect( | ||||||
| 					DX::ConvertToRectF(rect), | 					DX::ConvertToRectF(rect), | ||||||
| 					radius.x, | 					radius.x, | ||||||
| 					radius.y | 					radius.y | ||||||
| 				), | 				), | ||||||
| 				default_brush_.get(), | 				current_brush_.get(), | ||||||
| 				stroke_width, | 				stroke_width, | ||||||
| 				GetStrokeStyle(stroke).get() | 				GetStrokeStyle(stroke).get() | ||||||
| 			); | 			); | ||||||
|  | @ -263,49 +249,46 @@ namespace kiwano | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& fill_color) const | 	void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius) const | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(fill_color)); |  | ||||||
| 			render_target_->FillRoundedRectangle( | 			render_target_->FillRoundedRectangle( | ||||||
| 				D2D1::RoundedRect( | 				D2D1::RoundedRect( | ||||||
| 					DX::ConvertToRectF(rect), | 					DX::ConvertToRectF(rect), | ||||||
| 					radius.x, | 					radius.x, | ||||||
| 					radius.y | 					radius.y | ||||||
| 				), | 				), | ||||||
| 				default_brush_.get() | 				current_brush_.get() | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, Color const& stroke_color, Float32 stroke_width, StrokeStyle stroke) const | 	void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, Float32 stroke_width, StrokeStyle stroke) const | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(stroke_color)); |  | ||||||
| 
 |  | ||||||
| 			render_target_->DrawEllipse( | 			render_target_->DrawEllipse( | ||||||
| 				D2D1::Ellipse( | 				D2D1::Ellipse( | ||||||
| 					DX::ConvertToPoint2F(center), | 					DX::ConvertToPoint2F(center), | ||||||
| 					radius.x, | 					radius.x, | ||||||
| 					radius.y | 					radius.y | ||||||
| 				), | 				), | ||||||
| 				default_brush_.get(), | 				current_brush_.get(), | ||||||
| 				stroke_width, | 				stroke_width, | ||||||
| 				GetStrokeStyle(stroke).get() | 				GetStrokeStyle(stroke).get() | ||||||
| 			); | 			); | ||||||
|  | @ -316,24 +299,23 @@ namespace kiwano | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius, Color const& fill_color) const | 	void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius) const | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_ || !render_target_) | 		if (!render_target_ || !current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			default_brush_->SetColor(DX::ConvertToColorF(fill_color)); |  | ||||||
| 			render_target_->FillEllipse( | 			render_target_->FillEllipse( | ||||||
| 				D2D1::Ellipse( | 				D2D1::Ellipse( | ||||||
| 					DX::ConvertToPoint2F(center), | 					DX::ConvertToPoint2F(center), | ||||||
| 					radius.x, | 					radius.x, | ||||||
| 					radius.y | 					radius.y | ||||||
| 				), | 				), | ||||||
| 				default_brush_.get() | 				current_brush_.get() | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -464,7 +446,7 @@ namespace kiwano | ||||||
| 	void RenderTarget::PushLayer(LayerArea& layer) | 	void RenderTarget::PushLayer(LayerArea& layer) | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!render_target_ || !default_brush_) | 		if (!render_target_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
|  | @ -540,6 +522,11 @@ namespace kiwano | ||||||
| 		return opacity_; | 		return opacity_; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	Brush RenderTarget::GetCurrentBrush() const | ||||||
|  | 	{ | ||||||
|  | 		return Brush( current_brush_ ); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	Matrix3x2 RenderTarget::GetGlobalTransform() const | 	Matrix3x2 RenderTarget::GetGlobalTransform() const | ||||||
| 	{ | 	{ | ||||||
| 		return global_transform_; | 		return global_transform_; | ||||||
|  | @ -569,7 +556,6 @@ namespace kiwano | ||||||
| 			if (fast_global_transform_) | 			if (fast_global_transform_) | ||||||
| 			{ | 			{ | ||||||
| 				render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); | 				render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix)); | ||||||
| 
 |  | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
| 			{ | 			{ | ||||||
|  | @ -602,7 +588,7 @@ namespace kiwano | ||||||
| 	void RenderTarget::SetOpacity(Float32 opacity) | 	void RenderTarget::SetOpacity(Float32 opacity) | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
| 		if (!default_brush_) | 		if (!current_brush_) | ||||||
| 		{ | 		{ | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
|  | @ -612,13 +598,24 @@ namespace kiwano | ||||||
| 			if (opacity_ != opacity) | 			if (opacity_ != opacity) | ||||||
| 			{ | 			{ | ||||||
| 				opacity_ = opacity; | 				opacity_ = opacity; | ||||||
| 				default_brush_->SetOpacity(opacity); | 				current_brush_->SetOpacity(opacity); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	void RenderTarget::SetCurrentBrush(Brush const& brush) | ||||||
|  | 	{ | ||||||
|  | 		current_brush_ = brush.GetBrush(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void RenderTarget::SetDefaultBrushColor(Color const& color) | ||||||
|  | 	{ | ||||||
|  | 		KGE_ASSERT(default_brush_); | ||||||
|  | 		default_brush_->SetColor(DX::ConvertToColorF(color)); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	void RenderTarget::SetAntialiasMode(bool enabled) | 	void RenderTarget::SetAntialiasMode(bool enabled) | ||||||
| 	{ | 	{ | ||||||
| 		HRESULT hr = S_OK; | 		HRESULT hr = S_OK; | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| #include "../base/time.h" | #include "../base/time.h" | ||||||
|  | #include "Brush.h" | ||||||
| #include "Texture.h" | #include "Texture.h" | ||||||
| #include "Geometry.h" | #include "Geometry.h" | ||||||
| #include "TextLayout.h" | #include "TextLayout.h" | ||||||
|  | @ -55,62 +56,53 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 		void DrawGeometry( | 		void DrawGeometry( | ||||||
| 			Geometry const& geometry, | 			Geometry const& geometry, | ||||||
| 			Color const& stroke_color, |  | ||||||
| 			Float32 stroke_width, | 			Float32 stroke_width, | ||||||
| 			StrokeStyle stroke = StrokeStyle::Miter | 			StrokeStyle stroke = StrokeStyle::Miter | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void FillGeometry( | 		void FillGeometry( | ||||||
| 			Geometry const& geometry, | 			Geometry const& geometry | ||||||
| 			Color const& fill_color |  | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void DrawLine( | 		void DrawLine( | ||||||
| 			Point const& point1, | 			Point const& point1, | ||||||
| 			Point const& point2, | 			Point const& point2, | ||||||
| 			Color const& stroke_color, |  | ||||||
| 			Float32 stroke_width, | 			Float32 stroke_width, | ||||||
| 			StrokeStyle stroke = StrokeStyle::Miter | 			StrokeStyle stroke = StrokeStyle::Miter | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void DrawRectangle( | 		void DrawRectangle( | ||||||
| 			Rect const& rect, | 			Rect const& rect, | ||||||
| 			Color const& stroke_color, |  | ||||||
| 			Float32 stroke_width, | 			Float32 stroke_width, | ||||||
| 			StrokeStyle stroke = StrokeStyle::Miter | 			StrokeStyle stroke = StrokeStyle::Miter | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void FillRectangle( | 		void FillRectangle( | ||||||
| 			Rect const& rect, | 			Rect const& rect | ||||||
| 			Color const& fill_color |  | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void DrawRoundedRectangle( | 		void DrawRoundedRectangle( | ||||||
| 			Rect const& rect, | 			Rect const& rect, | ||||||
| 			Vec2 const& radius, | 			Vec2 const& radius, | ||||||
| 			Color const& stroke_color, |  | ||||||
| 			Float32 stroke_width, | 			Float32 stroke_width, | ||||||
| 			StrokeStyle stroke = StrokeStyle::Miter | 			StrokeStyle stroke = StrokeStyle::Miter | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void FillRoundedRectangle( | 		void FillRoundedRectangle( | ||||||
| 			Rect const& rect, | 			Rect const& rect, | ||||||
| 			Vec2 const& radius, | 			Vec2 const& radius | ||||||
| 			Color const& fill_color |  | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void DrawEllipse( | 		void DrawEllipse( | ||||||
| 			Point const& center, | 			Point const& center, | ||||||
| 			Vec2 const& radius, | 			Vec2 const& radius, | ||||||
| 			Color const& stroke_color, |  | ||||||
| 			Float32 stroke_width, | 			Float32 stroke_width, | ||||||
| 			StrokeStyle stroke = StrokeStyle::Miter | 			StrokeStyle stroke = StrokeStyle::Miter | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void FillEllipse( | 		void FillEllipse( | ||||||
| 			Point const& center, | 			Point const& center, | ||||||
| 			Vec2 const& radius, | 			Vec2 const& radius | ||||||
| 			Color const& fill_color |  | ||||||
| 		) const; | 		) const; | ||||||
| 
 | 
 | ||||||
| 		void DrawTexture( | 		void DrawTexture( | ||||||
|  | @ -150,12 +142,22 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 		Float32 GetOpacity() const; | 		Float32 GetOpacity() const; | ||||||
| 
 | 
 | ||||||
|  | 		Brush GetCurrentBrush() const; | ||||||
|  | 
 | ||||||
| 		Matrix3x2 GetGlobalTransform() const; | 		Matrix3x2 GetGlobalTransform() const; | ||||||
| 
 | 
 | ||||||
| 		void SetOpacity( | 		void SetOpacity( | ||||||
| 			Float32 opacity | 			Float32 opacity | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
|  | 		void SetCurrentBrush( | ||||||
|  | 			Brush const& brush | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		void SetDefaultBrushColor( | ||||||
|  | 			Color const& color | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
| 		void SetTransform( | 		void SetTransform( | ||||||
| 			const Matrix3x2& matrix | 			const Matrix3x2& matrix | ||||||
| 		); | 		); | ||||||
|  |  | ||||||
|  | @ -35,7 +35,6 @@ namespace kiwano | ||||||
| 		: hwnd_(nullptr) | 		: hwnd_(nullptr) | ||||||
| 		, vsync_(true) | 		, vsync_(true) | ||||||
| 		, clear_color_(Color::Black) | 		, clear_color_(Color::Black) | ||||||
| 		, resolution_mode_(ResolutionMode::Fixed) |  | ||||||
| 	{ | 	{ | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -54,7 +53,7 @@ namespace kiwano | ||||||
| 		KGE_LOG(L"Creating device resources"); | 		KGE_LOG(L"Creating device resources"); | ||||||
| 
 | 
 | ||||||
| 		hwnd_ = Window::GetInstance()->GetHandle(); | 		hwnd_ = Window::GetInstance()->GetHandle(); | ||||||
| 		resolution_ = output_size_ = Window::GetInstance()->GetSize(); | 		output_size_ = Window::GetInstance()->GetSize(); | ||||||
| 
 | 
 | ||||||
| 		d2d_res_ = nullptr; | 		d2d_res_ = nullptr; | ||||||
| 		d3d_res_ = nullptr; | 		d3d_res_ = nullptr; | ||||||
|  | @ -71,19 +70,11 @@ namespace kiwano | ||||||
| 		// Direct3D device resources
 | 		// Direct3D device resources
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| #if defined(KGE_USE_DIRECTX10) | 			hr = ID3DDeviceResources::Create( | ||||||
| 			hr = ID3D10DeviceResources::Create( |  | ||||||
| 				&d3d_res_, | 				&d3d_res_, | ||||||
| 				d2d_res_.get(), | 				d2d_res_.get(), | ||||||
| 				hwnd_ | 				hwnd_ | ||||||
| 			); | 			); | ||||||
| #else |  | ||||||
| 			hr = ID3D11DeviceResources::Create( |  | ||||||
| 				&d3d_res_, |  | ||||||
| 				d2d_res_.get(), |  | ||||||
| 				hwnd_ |  | ||||||
| 			); |  | ||||||
| #endif |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		// DrawingStateBlock
 | 		// DrawingStateBlock
 | ||||||
|  | @ -161,12 +152,6 @@ namespace kiwano | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) |  | ||||||
| 		{ |  | ||||||
| 			render_target_->SaveDrawingState(drawing_state_block_.get()); |  | ||||||
| 			BeginDraw(); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			hr = d3d_res_->ClearRenderTarget(clear_color_); | 			hr = d3d_res_->ClearRenderTarget(clear_color_); | ||||||
|  | @ -174,8 +159,8 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			SetTransform(Matrix3x2{}); | 			render_target_->SaveDrawingState(drawing_state_block_.get()); | ||||||
| 			PushClipRect(Rect{ Point{}, resolution_ }); | 			BeginDraw(); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
|  | @ -190,11 +175,8 @@ namespace kiwano | ||||||
| 			hr = E_UNEXPECTED; | 			hr = E_UNEXPECTED; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 		if (SUCCEEDED(hr)) | 		if (SUCCEEDED(hr)) | ||||||
| 		{ | 		{ | ||||||
| 			PopClipRect(); |  | ||||||
| 
 |  | ||||||
| 			EndDraw(); | 			EndDraw(); | ||||||
| 
 | 
 | ||||||
| 			render_target_->RestoreDrawingState(drawing_state_block_.get()); | 			render_target_->RestoreDrawingState(drawing_state_block_.get()); | ||||||
|  | @ -890,29 +872,118 @@ namespace kiwano | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	void Renderer::CreateSolidBrush(Brush& brush, Color const& color) | ||||||
|  | 	{ | ||||||
|  | 		HRESULT hr = S_OK; | ||||||
|  | 		if (!d2d_res_) | ||||||
|  | 		{ | ||||||
|  | 			hr = E_UNEXPECTED; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ComPtr<ID2D1SolidColorBrush> output; | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			hr = d2d_res_->GetDeviceContext()->CreateSolidColorBrush(DX::ConvertToColorF(color), &output); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			brush.SetBrush(output); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ThrowIfFailed(hr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Renderer::CreateLinearGradientBrush(Brush& brush, Point const& begin, Point const& end, Vector<GradientStop> const& stops, GradientExtendMode extend_mode) | ||||||
|  | 	{ | ||||||
|  | 		HRESULT hr = S_OK; | ||||||
|  | 		if (!d2d_res_) | ||||||
|  | 		{ | ||||||
|  | 			hr = E_UNEXPECTED; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			ID2D1GradientStopCollection* collection = nullptr; | ||||||
|  | 			hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection( | ||||||
|  | 				reinterpret_cast<const D2D1_GRADIENT_STOP*>(&stops[0]), | ||||||
|  | 				stops.size(), | ||||||
|  | 				D2D1_GAMMA_2_2, | ||||||
|  | 				D2D1_EXTEND_MODE(extend_mode), | ||||||
|  | 				&collection | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			if (SUCCEEDED(hr)) | ||||||
|  | 			{ | ||||||
|  | 				ComPtr<ID2D1LinearGradientBrush> output; | ||||||
|  | 				hr = d2d_res_->GetDeviceContext()->CreateLinearGradientBrush( | ||||||
|  | 					D2D1::LinearGradientBrushProperties( | ||||||
|  | 						DX::ConvertToPoint2F(begin), | ||||||
|  | 						DX::ConvertToPoint2F(end) | ||||||
|  | 					), | ||||||
|  | 					collection, | ||||||
|  | 					&output | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				if (SUCCEEDED(hr)) | ||||||
|  | 				{ | ||||||
|  | 					brush.SetBrush(output); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ThrowIfFailed(hr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void Renderer::CreateRadialGradientBrush(Brush& brush, Point const& center, Vec2 const& offset, Vec2 const& radius, | ||||||
|  | 		Vector<GradientStop> const& stops, GradientExtendMode extend_mode) | ||||||
|  | 	{ | ||||||
|  | 		HRESULT hr = S_OK; | ||||||
|  | 		if (!d2d_res_) | ||||||
|  | 		{ | ||||||
|  | 			hr = E_UNEXPECTED; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (SUCCEEDED(hr)) | ||||||
|  | 		{ | ||||||
|  | 			ID2D1GradientStopCollection* collection = nullptr; | ||||||
|  | 			hr = d2d_res_->GetDeviceContext()->CreateGradientStopCollection( | ||||||
|  | 				reinterpret_cast<const D2D1_GRADIENT_STOP*>(&stops[0]), | ||||||
|  | 				stops.size(), | ||||||
|  | 				D2D1_GAMMA_2_2, | ||||||
|  | 				D2D1_EXTEND_MODE(extend_mode), | ||||||
|  | 				&collection | ||||||
|  | 			); | ||||||
|  | 
 | ||||||
|  | 			if (SUCCEEDED(hr)) | ||||||
|  | 			{ | ||||||
|  | 				ComPtr<ID2D1RadialGradientBrush> output; | ||||||
|  | 				hr = d2d_res_->GetDeviceContext()->CreateRadialGradientBrush( | ||||||
|  | 					D2D1::RadialGradientBrushProperties( | ||||||
|  | 						DX::ConvertToPoint2F(center), | ||||||
|  | 						DX::ConvertToPoint2F(offset), | ||||||
|  | 						radius.x, | ||||||
|  | 						radius.y | ||||||
|  | 					), | ||||||
|  | 					collection, | ||||||
|  | 					&output | ||||||
|  | 				); | ||||||
|  | 
 | ||||||
|  | 				if (SUCCEEDED(hr)) | ||||||
|  | 				{ | ||||||
|  | 					brush.SetBrush(output); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ThrowIfFailed(hr); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	void Renderer::SetVSyncEnabled(bool enabled) | 	void Renderer::SetVSyncEnabled(bool enabled) | ||||||
| 	{ | 	{ | ||||||
| 		vsync_ = enabled; | 		vsync_ = enabled; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Renderer::SetResolution(Size const& resolution) |  | ||||||
| 	{ |  | ||||||
| 		if (resolution_ != resolution) |  | ||||||
| 		{ |  | ||||||
| 			resolution_ = resolution; |  | ||||||
| 			UpdateResolution(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void Renderer::SetResolutionMode(ResolutionMode mode) |  | ||||||
| 	{ |  | ||||||
| 		if (resolution_mode_ != mode) |  | ||||||
| 		{ |  | ||||||
| 			resolution_mode_ = mode; |  | ||||||
| 			UpdateResolution(); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	void Renderer::SetClearColor(const Color& color) | 	void Renderer::SetClearColor(const Color& color) | ||||||
| 	{ | 	{ | ||||||
| 		clear_color_ = color; | 		clear_color_ = color; | ||||||
|  | @ -933,58 +1004,7 @@ namespace kiwano | ||||||
| 			hr = d3d_res_->SetLogicalSize(output_size_); | 			hr = d3d_res_->SetLogicalSize(output_size_); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (SUCCEEDED(hr)) |  | ||||||
| 		{ |  | ||||||
| 			UpdateResolution(); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		ThrowIfFailed(hr); | 		ThrowIfFailed(hr); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void Renderer::UpdateResolution() |  | ||||||
| 	{ |  | ||||||
| 		switch (resolution_mode_) |  | ||||||
| 		{ |  | ||||||
| 		case ResolutionMode::Fixed: |  | ||||||
| 		{ |  | ||||||
| 			SetGlobalTransform(nullptr); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		case ResolutionMode::Center: |  | ||||||
| 		{ |  | ||||||
| 			Float32 left = math::Ceil((output_size_.x - resolution_.x) / 2); |  | ||||||
| 			Float32 top = math::Ceil((output_size_.y - resolution_.y) / 2); |  | ||||||
| 			SetGlobalTransform(Matrix3x2::Translation(Vec2{ left, top })); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		case ResolutionMode::Stretch: |  | ||||||
| 		{ |  | ||||||
| 			Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100; |  | ||||||
| 			Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100; |  | ||||||
| 			SetGlobalTransform(Matrix3x2::Scaling(Vec2{ scalex, scaley })); |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		case ResolutionMode::Adaptive: |  | ||||||
| 		{ |  | ||||||
| 			Float32 scalex = Float32(Int32((output_size_.x / resolution_.x) * 100 + 0.5f)) / 100; |  | ||||||
| 			Float32 scaley = Float32(Int32((output_size_.y / resolution_.y) * 100 + 0.5f)) / 100; |  | ||||||
| 			if (scalex > scaley) |  | ||||||
| 			{ |  | ||||||
| 				Float32 left = math::Ceil((output_size_.x - resolution_.x * scaley) / 2); |  | ||||||
| 				SetGlobalTransform(Matrix3x2::SRT(Vec2{ left, 0 }, Vec2{ scaley, scaley }, 0)); |  | ||||||
| 			} |  | ||||||
| 			else |  | ||||||
| 			{ |  | ||||||
| 				Float32 top = math::Ceil((output_size_.y - resolution_.y * scalex) / 2); |  | ||||||
| 				SetGlobalTransform(Matrix3x2::SRT(Vec2{ 0, top }, Vec2{ scalex, scalex }, 0)); |  | ||||||
| 
 |  | ||||||
| 			} |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -51,20 +51,8 @@ namespace kiwano | ||||||
| 		); | 		); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	// 分辨率模式
 |  | ||||||
| 	// 分辨率模式决定了将画面渲染到视区上的方式
 |  | ||||||
| 	// Fixed (固定): 分辨率不随视区改变, 且画面始终与视区边界对齐(默认)
 |  | ||||||
| 	// Center (居中): 分辨率不随视区改变, 且画面始终在视区上居中
 |  | ||||||
| 	// Stretch (拉伸): 分辨率始终随视区等比例拉伸
 |  | ||||||
| 	// Adaptive (宽高自适应): 分辨率始终保持宽高比, 且尽可能的填充视区, 可能会出现黑色边界
 |  | ||||||
| 	enum class ResolutionMode |  | ||||||
| 	{ |  | ||||||
| 		Fixed,		/* 固定 */ |  | ||||||
| 		Center,		/* 居中 */ |  | ||||||
| 		Stretch,	/* 拉伸 */ |  | ||||||
| 		Adaptive,	/* 宽高自适应 */ |  | ||||||
| 	}; |  | ||||||
| 
 | 
 | ||||||
|  | 	// äÖȾÆ÷
 | ||||||
| 	class KGE_API Renderer | 	class KGE_API Renderer | ||||||
| 		: public Singleton<Renderer> | 		: public Singleton<Renderer> | ||||||
| 		, public Component | 		, public Component | ||||||
|  | @ -83,16 +71,6 @@ namespace kiwano | ||||||
| 			bool enabled | 			bool enabled | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
| 		// 设置画面分辨率
 |  | ||||||
| 		void SetResolution( |  | ||||||
| 			Size const& resolution |  | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 		// 设置分辨率模式
 |  | ||||||
| 		void SetResolutionMode( |  | ||||||
| 			ResolutionMode mode |  | ||||||
| 		); |  | ||||||
| 
 |  | ||||||
| 	public: | 	public: | ||||||
| 		void CreateTexture( | 		void CreateTexture( | ||||||
| 			Texture& texture, | 			Texture& texture, | ||||||
|  | @ -172,6 +150,28 @@ namespace kiwano | ||||||
| 			TextureRenderTarget& render_target | 			TextureRenderTarget& render_target | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
|  | 		void CreateSolidBrush( | ||||||
|  | 			Brush& brush, | ||||||
|  | 			Color const& color | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		void CreateLinearGradientBrush( | ||||||
|  | 			Brush& brush, | ||||||
|  | 			Point const& begin, | ||||||
|  | 			Point const& end, | ||||||
|  | 			Vector<GradientStop> const& stops, | ||||||
|  | 			GradientExtendMode extend_mode | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		void CreateRadialGradientBrush( | ||||||
|  | 			Brush& brush, | ||||||
|  | 			Point const& center, | ||||||
|  | 			Vec2 const& offset, | ||||||
|  | 			Vec2 const& radius, | ||||||
|  | 			Vector<GradientStop> const& stops, | ||||||
|  | 			GradientExtendMode extend_mode | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
| 	public: | 	public: | ||||||
| 		void Init(RenderConfig const& config); | 		void Init(RenderConfig const& config); | ||||||
| 
 | 
 | ||||||
|  | @ -190,8 +190,6 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 		inline Size const&				GetOutputSize() const			{ return output_size_; } | 		inline Size const&				GetOutputSize() const			{ return output_size_; } | ||||||
| 
 | 
 | ||||||
| 		inline Size const&				GetResolution() const			{ return resolution_; } |  | ||||||
| 
 |  | ||||||
| 		inline Color const&				GetClearColor() const			{ return clear_color_; } | 		inline Color const&				GetClearColor() const			{ return clear_color_; } | ||||||
| 
 | 
 | ||||||
| 		inline ID2DDeviceResources*		GetD2DDeviceResources() const	{ KGE_ASSERT(d2d_res_); return d2d_res_.get(); } | 		inline ID2DDeviceResources*		GetD2DDeviceResources() const	{ KGE_ASSERT(d2d_res_); return d2d_res_.get(); } | ||||||
|  | @ -209,15 +207,11 @@ namespace kiwano | ||||||
| 
 | 
 | ||||||
| 		void ResizeTarget(UInt32 width, UInt32 height); | 		void ResizeTarget(UInt32 width, UInt32 height); | ||||||
| 
 | 
 | ||||||
| 		void UpdateResolution(); |  | ||||||
| 
 |  | ||||||
| 	private: | 	private: | ||||||
| 		bool			vsync_; | 		bool			vsync_; | ||||||
| 		HWND			hwnd_; | 		HWND			hwnd_; | ||||||
| 		Color			clear_color_; | 		Color			clear_color_; | ||||||
| 		Size			output_size_; | 		Size			output_size_; | ||||||
| 		Size			resolution_; |  | ||||||
| 		ResolutionMode	resolution_mode_; |  | ||||||
| 
 | 
 | ||||||
| 		ComPtr<ID2DDeviceResources>		d2d_res_; | 		ComPtr<ID2DDeviceResources>		d2d_res_; | ||||||
| 		ComPtr<ID3DDeviceResources>		d3d_res_; | 		ComPtr<ID3DDeviceResources>		d3d_res_; | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue