[deploy] Merge pull request #35 from KiwanoEngine/dev
Warp TextFormat, TextLayout, RenderTarget and so on
This commit is contained in:
commit
dab2f2c112
33
appveyor.yml
33
appveyor.yml
|
|
@ -5,8 +5,8 @@ skip_tags: true
|
||||||
# fetch repository as zip archive
|
# fetch repository as zip archive
|
||||||
shallow_clone: true
|
shallow_clone: true
|
||||||
|
|
||||||
# pull_requests:
|
pull_requests:
|
||||||
# do_not_increment_build_number: true
|
do_not_increment_build_number: true
|
||||||
|
|
||||||
# Do not build feature branch with open Pull Requests
|
# Do not build feature branch with open Pull Requests
|
||||||
# skip_branch_with_pr: true
|
# skip_branch_with_pr: true
|
||||||
|
|
@ -47,6 +47,18 @@ only_commits:
|
||||||
- scripts/**/*.ps1
|
- scripts/**/*.ps1
|
||||||
- appveyor.yml
|
- appveyor.yml
|
||||||
|
|
||||||
|
for:
|
||||||
|
-
|
||||||
|
branches:
|
||||||
|
except:
|
||||||
|
- master
|
||||||
|
# only_commits:
|
||||||
|
# message: /\[build\]/
|
||||||
|
environment:
|
||||||
|
matrix:
|
||||||
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||||
|
VS_PLATFORM_TOOLSET: v142
|
||||||
|
|
||||||
configuration:
|
configuration:
|
||||||
- Debug
|
- Debug
|
||||||
- Release
|
- Release
|
||||||
|
|
@ -67,19 +79,8 @@ build:
|
||||||
project: projects/Kiwano.sln
|
project: projects/Kiwano.sln
|
||||||
verbosity: minimal
|
verbosity: minimal
|
||||||
|
|
||||||
for:
|
after_build:
|
||||||
-
|
- ps: .\scripts\appveyor\wait_for_other_jobs.ps1
|
||||||
branches:
|
|
||||||
except:
|
|
||||||
- master
|
|
||||||
only_commits:
|
|
||||||
message: /\[build\]/
|
|
||||||
-
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- master
|
|
||||||
after_build:
|
|
||||||
- ps: .\scripts\appveyor\wait_for_other_jobs.ps1
|
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: projects/output/**/*.lib
|
- path: projects/output/**/*.lib
|
||||||
|
|
@ -119,6 +120,6 @@ notifications:
|
||||||
- provider: Email
|
- provider: Email
|
||||||
to:
|
to:
|
||||||
- 569629550@qq.com
|
- 569629550@qq.com
|
||||||
on_build_success: false
|
on_build_success: true
|
||||||
on_build_failure: true
|
on_build_failure: true
|
||||||
on_build_status_changed: false
|
on_build_status_changed: false
|
||||||
|
|
@ -11,7 +11,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\2d\action\Animation.h" />
|
<ClInclude Include="..\src\kiwano\2d\action\Animation.h" />
|
||||||
<ClInclude Include="..\src\kiwano\2d\Frame.h" />
|
<ClInclude Include="..\src\kiwano\2d\Frame.h" />
|
||||||
<ClInclude Include="..\src\kiwano\2d\GifSprite.h" />
|
<ClInclude Include="..\src\kiwano\2d\GifSprite.h" />
|
||||||
<ClInclude Include="..\src\kiwano\base\ComPtr.hpp" />
|
|
||||||
<ClInclude Include="..\src\kiwano\base\Director.h" />
|
<ClInclude Include="..\src\kiwano\base\Director.h" />
|
||||||
<ClInclude Include="..\src\kiwano\base\types.h" />
|
<ClInclude Include="..\src\kiwano\base\types.h" />
|
||||||
<ClInclude Include="..\src\kiwano\core\basic_json.hpp" />
|
<ClInclude Include="..\src\kiwano\core\basic_json.hpp" />
|
||||||
|
|
@ -28,7 +27,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\macros.h" />
|
<ClInclude Include="..\src\kiwano\macros.h" />
|
||||||
<ClInclude Include="..\src\kiwano\2d\include-forwards.h" />
|
<ClInclude Include="..\src\kiwano\2d\include-forwards.h" />
|
||||||
<ClInclude Include="..\src\kiwano\2d\Canvas.h" />
|
<ClInclude Include="..\src\kiwano\2d\Canvas.h" />
|
||||||
<ClInclude Include="..\src\kiwano\2d\Color.h" />
|
|
||||||
<ClInclude Include="..\src\kiwano\2d\DebugActor.h" />
|
<ClInclude Include="..\src\kiwano\2d\DebugActor.h" />
|
||||||
<ClInclude Include="..\src\kiwano\2d\Font.hpp" />
|
<ClInclude Include="..\src\kiwano\2d\Font.hpp" />
|
||||||
<ClInclude Include="..\src\kiwano\2d\FrameSequence.h" />
|
<ClInclude Include="..\src\kiwano\2d\FrameSequence.h" />
|
||||||
|
|
@ -49,7 +47,7 @@
|
||||||
<ClInclude Include="..\src\kiwano\base\Input.h" />
|
<ClInclude Include="..\src\kiwano\base\Input.h" />
|
||||||
<ClInclude Include="..\src\kiwano\base\keys.hpp" />
|
<ClInclude Include="..\src\kiwano\base\keys.hpp" />
|
||||||
<ClInclude Include="..\src\kiwano\base\Logger.h" />
|
<ClInclude Include="..\src\kiwano\base\Logger.h" />
|
||||||
<ClInclude Include="..\src\kiwano\base\Object.h" />
|
<ClInclude Include="..\src\kiwano\base\ObjectBase.h" />
|
||||||
<ClInclude Include="..\src\kiwano\base\RefCounter.hpp" />
|
<ClInclude Include="..\src\kiwano\base\RefCounter.hpp" />
|
||||||
<ClInclude Include="..\src\kiwano\base\Resource.h" />
|
<ClInclude Include="..\src\kiwano\base\Resource.h" />
|
||||||
<ClInclude Include="..\src\kiwano\base\SmartPtr.hpp" />
|
<ClInclude Include="..\src\kiwano\base\SmartPtr.hpp" />
|
||||||
|
|
@ -59,7 +57,7 @@
|
||||||
<ClInclude Include="..\src\kiwano\base\Window.h" />
|
<ClInclude Include="..\src\kiwano\base\Window.h" />
|
||||||
<ClInclude Include="..\src\kiwano\math\constants.hpp" />
|
<ClInclude Include="..\src\kiwano\math\constants.hpp" />
|
||||||
<ClInclude Include="..\src\kiwano\math\ease.hpp" />
|
<ClInclude Include="..\src\kiwano\math\ease.hpp" />
|
||||||
<ClInclude Include="..\src\kiwano\math\helper.h" />
|
<ClInclude Include="..\src\kiwano\math\math.h" />
|
||||||
<ClInclude Include="..\src\kiwano\math\Matrix.hpp" />
|
<ClInclude Include="..\src\kiwano\math\Matrix.hpp" />
|
||||||
<ClInclude Include="..\src\kiwano\math\rand.h" />
|
<ClInclude Include="..\src\kiwano\math\rand.h" />
|
||||||
<ClInclude Include="..\src\kiwano\math\Rect.hpp" />
|
<ClInclude Include="..\src\kiwano\math\Rect.hpp" />
|
||||||
|
|
@ -67,17 +65,24 @@
|
||||||
<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\D2DDeviceResources.h" />
|
<ClInclude Include="..\src\kiwano\renderer\Color.h" />
|
||||||
<ClInclude Include="..\src\kiwano\renderer\D3D10DeviceResources.h" />
|
<ClInclude Include="..\src\kiwano\renderer\Font.h" />
|
||||||
<ClInclude Include="..\src\kiwano\renderer\D3D11DeviceResources.h" />
|
<ClInclude Include="..\src\kiwano\renderer\FontCollection.h" />
|
||||||
<ClInclude Include="..\src\kiwano\renderer\D3DDeviceResourcesBase.h" />
|
|
||||||
<ClInclude Include="..\src\kiwano\renderer\Geometry.h" />
|
<ClInclude Include="..\src\kiwano\renderer\Geometry.h" />
|
||||||
<ClInclude Include="..\src\kiwano\renderer\GifImage.h" />
|
<ClInclude Include="..\src\kiwano\renderer\GifImage.h" />
|
||||||
<ClInclude Include="..\src\kiwano\renderer\helper.hpp" />
|
|
||||||
<ClInclude Include="..\src\kiwano\renderer\Image.h" />
|
<ClInclude Include="..\src\kiwano\renderer\Image.h" />
|
||||||
<ClInclude Include="..\src\kiwano\renderer\ImageCache.h" />
|
<ClInclude Include="..\src\kiwano\renderer\ImageCache.h" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\LayerArea.h" />
|
||||||
<ClInclude Include="..\src\kiwano\renderer\Renderer.h" />
|
<ClInclude Include="..\src\kiwano\renderer\Renderer.h" />
|
||||||
<ClInclude Include="..\src\kiwano\renderer\TextRenderer.h" />
|
<ClInclude Include="..\src\kiwano\renderer\RenderTarget.h" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\TextLayout.h" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\ComPtr.hpp" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\D2DDeviceResources.h" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\D3D10DeviceResources.h" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\D3D11DeviceResources.h" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\D3DDeviceResourcesBase.h" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\FontCollectionLoader.h" />
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\TextRenderer.h" />
|
||||||
<ClInclude Include="..\src\kiwano\third-party\StackWalker\StackWalker.h" />
|
<ClInclude Include="..\src\kiwano\third-party\StackWalker\StackWalker.h" />
|
||||||
<ClInclude Include="..\src\kiwano\third-party\tinyxml2\tinyxml2.h" />
|
<ClInclude Include="..\src\kiwano\third-party\tinyxml2\tinyxml2.h" />
|
||||||
<ClInclude Include="..\src\kiwano\ui\Button.h" />
|
<ClInclude Include="..\src\kiwano\ui\Button.h" />
|
||||||
|
|
@ -96,7 +101,6 @@
|
||||||
<ClCompile Include="..\src\kiwano\2d\action\ActionTween.cpp" />
|
<ClCompile Include="..\src\kiwano\2d\action\ActionTween.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\2d\action\Animation.cpp" />
|
<ClCompile Include="..\src\kiwano\2d\action\Animation.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\2d\Canvas.cpp" />
|
<ClCompile Include="..\src\kiwano\2d\Canvas.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\2d\Color.cpp" />
|
|
||||||
<ClCompile Include="..\src\kiwano\2d\DebugActor.cpp" />
|
<ClCompile Include="..\src\kiwano\2d\DebugActor.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\2d\Frame.cpp" />
|
<ClCompile Include="..\src\kiwano\2d\Frame.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\2d\FrameSequence.cpp" />
|
<ClCompile Include="..\src\kiwano\2d\FrameSequence.cpp" />
|
||||||
|
|
@ -113,7 +117,7 @@
|
||||||
<ClCompile Include="..\src\kiwano\base\EventListener.cpp" />
|
<ClCompile Include="..\src\kiwano\base\EventListener.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\base\Input.cpp" />
|
<ClCompile Include="..\src\kiwano\base\Input.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\base\Logger.cpp" />
|
<ClCompile Include="..\src\kiwano\base\Logger.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\base\Object.cpp" />
|
<ClCompile Include="..\src\kiwano\base\ObjectBase.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\base\Resource.cpp" />
|
<ClCompile Include="..\src\kiwano\base\Resource.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\base\Director.cpp" />
|
<ClCompile Include="..\src\kiwano\base\Director.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\base\Timer.cpp" />
|
<ClCompile Include="..\src\kiwano\base\Timer.cpp" />
|
||||||
|
|
@ -122,15 +126,22 @@
|
||||||
<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\D2DDeviceResources.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\Color.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\renderer\D3D10DeviceResources.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\Font.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\renderer\D3D11DeviceResources.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\renderer\Geometry.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\Geometry.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\renderer\GifImage.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\GifImage.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\renderer\Image.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\Image.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\renderer\ImageCache.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\ImageCache.cpp" />
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\LayerArea.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\renderer\Renderer.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\Renderer.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\renderer\TextRenderer.cpp" />
|
<ClCompile Include="..\src\kiwano\renderer\RenderTarget.cpp" />
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\TextLayout.cpp" />
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\D2DDeviceResources.cpp" />
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\D3D10DeviceResources.cpp" />
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\D3D11DeviceResources.cpp" />
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\FontCollectionLoader.cpp" />
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\TextRenderer.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\third-party\StackWalker\StackWalker.cpp" />
|
<ClCompile Include="..\src\kiwano\third-party\StackWalker\StackWalker.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\third-party\tinyxml2\tinyxml2.cpp" />
|
<ClCompile Include="..\src\kiwano\third-party\tinyxml2\tinyxml2.cpp" />
|
||||||
<ClCompile Include="..\src\kiwano\ui\Button.cpp" />
|
<ClCompile Include="..\src\kiwano\ui\Button.cpp" />
|
||||||
|
|
@ -193,7 +204,7 @@
|
||||||
<WarningLevel>Level3</WarningLevel>
|
<WarningLevel>Level3</WarningLevel>
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
<DebugInformationFormat>None</DebugInformationFormat>
|
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -210,7 +221,7 @@
|
||||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
<BufferSecurityCheck>false</BufferSecurityCheck>
|
<BufferSecurityCheck>false</BufferSecurityCheck>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
<DebugInformationFormat>None</DebugInformationFormat>
|
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@
|
||||||
<Filter Include="core">
|
<Filter Include="core">
|
||||||
<UniqueIdentifier>{86e2d0f2-a9d0-4456-b6a5-d480228bbf82}</UniqueIdentifier>
|
<UniqueIdentifier>{86e2d0f2-a9d0-4456-b6a5-d480228bbf82}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="renderer\win32">
|
||||||
|
<UniqueIdentifier>{30333461-e9bc-4709-84bd-ce6e0e1a3079}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\src\kiwano\ui\Button.h">
|
<ClInclude Include="..\src\kiwano\ui\Button.h">
|
||||||
|
|
@ -48,9 +51,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\2d\Canvas.h">
|
<ClInclude Include="..\src\kiwano\2d\Canvas.h">
|
||||||
<Filter>2d</Filter>
|
<Filter>2d</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\2d\Color.h">
|
|
||||||
<Filter>2d</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\2d\Font.hpp">
|
<ClInclude Include="..\src\kiwano\2d\Font.hpp">
|
||||||
<Filter>2d</Filter>
|
<Filter>2d</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -99,21 +99,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\base\time.h">
|
<ClInclude Include="..\src\kiwano\base\time.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\renderer\D2DDeviceResources.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\renderer\D3D10DeviceResources.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\renderer\D3D11DeviceResources.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\renderer\helper.hpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\renderer\TextRenderer.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\math\constants.hpp">
|
<ClInclude Include="..\src\kiwano\math\constants.hpp">
|
||||||
<Filter>math</Filter>
|
<Filter>math</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -143,9 +128,6 @@
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\config.h" />
|
<ClInclude Include="..\src\kiwano\config.h" />
|
||||||
<ClInclude Include="..\src\kiwano\macros.h" />
|
<ClInclude Include="..\src\kiwano\macros.h" />
|
||||||
<ClInclude Include="..\src\kiwano\math\helper.h">
|
|
||||||
<Filter>math</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\math\Vec2.hpp">
|
<ClInclude Include="..\src\kiwano\math\Vec2.hpp">
|
||||||
<Filter>math</Filter>
|
<Filter>math</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -155,9 +137,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\base\SmartPtr.hpp">
|
<ClInclude Include="..\src\kiwano\base\SmartPtr.hpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\base\Object.h">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\kiwano.h" />
|
<ClInclude Include="..\src\kiwano\kiwano.h" />
|
||||||
<ClInclude Include="..\src\kiwano\utils\DataUtil.h">
|
<ClInclude Include="..\src\kiwano\utils\DataUtil.h">
|
||||||
<Filter>utils</Filter>
|
<Filter>utils</Filter>
|
||||||
|
|
@ -177,9 +156,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\utils\FileUtil.h">
|
<ClInclude Include="..\src\kiwano\utils\FileUtil.h">
|
||||||
<Filter>utils</Filter>
|
<Filter>utils</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\renderer\D3DDeviceResourcesBase.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\base\types.h">
|
<ClInclude Include="..\src\kiwano\base\types.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -201,12 +177,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\2d\Frame.h">
|
<ClInclude Include="..\src\kiwano\2d\Frame.h">
|
||||||
<Filter>2d</Filter>
|
<Filter>2d</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\renderer\GifImage.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\renderer\Image.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\2d\action\Action.h">
|
<ClInclude Include="..\src\kiwano\2d\action\Action.h">
|
||||||
<Filter>2d\action</Filter>
|
<Filter>2d\action</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -225,9 +195,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\2d\action\Animation.h">
|
<ClInclude Include="..\src\kiwano\2d\action\Animation.h">
|
||||||
<Filter>2d\action</Filter>
|
<Filter>2d\action</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\renderer\ImageCache.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\utils\ResourceCache.h">
|
<ClInclude Include="..\src\kiwano\utils\ResourceCache.h">
|
||||||
<Filter>utils</Filter>
|
<Filter>utils</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -258,9 +225,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\core\vector.hpp">
|
<ClInclude Include="..\src\kiwano\core\vector.hpp">
|
||||||
<Filter>core</Filter>
|
<Filter>core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\base\ComPtr.hpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\core\core.h">
|
<ClInclude Include="..\src\kiwano\core\core.h">
|
||||||
<Filter>core</Filter>
|
<Filter>core</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -270,9 +234,6 @@
|
||||||
<ClInclude Include="..\src\kiwano\2d\ShapeActor.h">
|
<ClInclude Include="..\src\kiwano\2d\ShapeActor.h">
|
||||||
<Filter>2d</Filter>
|
<Filter>2d</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\renderer\Geometry.h">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\src\kiwano\2d\action\ActionDelay.h">
|
<ClInclude Include="..\src\kiwano\2d\action\ActionDelay.h">
|
||||||
<Filter>2d\action</Filter>
|
<Filter>2d\action</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
@ -285,9 +246,66 @@
|
||||||
<ClInclude Include="..\src\kiwano\base\Window.h">
|
<ClInclude Include="..\src\kiwano\base\Window.h">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\math\math.h">
|
||||||
|
<Filter>math</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\base\ObjectBase.h">
|
||||||
|
<Filter>base</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\Color.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\Font.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\Geometry.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\GifImage.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\Image.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\ImageCache.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\LayerArea.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="..\src\kiwano\renderer\Renderer.h">
|
<ClInclude Include="..\src\kiwano\renderer\Renderer.h">
|
||||||
<Filter>renderer</Filter>
|
<Filter>renderer</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\TextLayout.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\ComPtr.hpp">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\D2DDeviceResources.h">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\D3D10DeviceResources.h">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\D3D11DeviceResources.h">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\D3DDeviceResourcesBase.h">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\FontCollectionLoader.h">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\win32\TextRenderer.h">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\RenderTarget.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="..\src\kiwano\renderer\FontCollection.h">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\src\kiwano\ui\Button.cpp">
|
<ClCompile Include="..\src\kiwano\ui\Button.cpp">
|
||||||
|
|
@ -299,9 +317,6 @@
|
||||||
<ClCompile Include="..\src\kiwano\2d\Canvas.cpp">
|
<ClCompile Include="..\src\kiwano\2d\Canvas.cpp">
|
||||||
<Filter>2d</Filter>
|
<Filter>2d</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\kiwano\2d\Color.cpp">
|
|
||||||
<Filter>2d</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\2d\Layer.cpp">
|
<ClCompile Include="..\src\kiwano\2d\Layer.cpp">
|
||||||
<Filter>2d</Filter>
|
<Filter>2d</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -326,18 +341,6 @@
|
||||||
<ClCompile Include="..\src\kiwano\base\time.cpp">
|
<ClCompile Include="..\src\kiwano\base\time.cpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\kiwano\renderer\D2DDeviceResources.cpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\renderer\D3D10DeviceResources.cpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\renderer\D3D11DeviceResources.cpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\renderer\TextRenderer.cpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\platform\Application.cpp">
|
<ClCompile Include="..\src\kiwano\platform\Application.cpp">
|
||||||
<Filter>platform</Filter>
|
<Filter>platform</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -350,9 +353,6 @@
|
||||||
<ClCompile Include="..\src\kiwano\base\Input.cpp">
|
<ClCompile Include="..\src\kiwano\base\Input.cpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\kiwano\base\Object.cpp">
|
|
||||||
<Filter>base</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\utils\DataUtil.cpp">
|
<ClCompile Include="..\src\kiwano\utils\DataUtil.cpp">
|
||||||
<Filter>utils</Filter>
|
<Filter>utils</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -389,12 +389,6 @@
|
||||||
<ClCompile Include="..\src\kiwano\2d\Frame.cpp">
|
<ClCompile Include="..\src\kiwano\2d\Frame.cpp">
|
||||||
<Filter>2d</Filter>
|
<Filter>2d</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\kiwano\renderer\GifImage.cpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\renderer\Image.cpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\2d\action\Action.cpp">
|
<ClCompile Include="..\src\kiwano\2d\action\Action.cpp">
|
||||||
<Filter>2d\action</Filter>
|
<Filter>2d\action</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -410,9 +404,6 @@
|
||||||
<ClCompile Include="..\src\kiwano\2d\action\Animation.cpp">
|
<ClCompile Include="..\src\kiwano\2d\action\Animation.cpp">
|
||||||
<Filter>2d\action</Filter>
|
<Filter>2d\action</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\kiwano\renderer\ImageCache.cpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\utils\ResourceCache.cpp">
|
<ClCompile Include="..\src\kiwano\utils\ResourceCache.cpp">
|
||||||
<Filter>utils</Filter>
|
<Filter>utils</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -425,9 +416,6 @@
|
||||||
<ClCompile Include="..\src\kiwano\2d\ShapeActor.cpp">
|
<ClCompile Include="..\src\kiwano\2d\ShapeActor.cpp">
|
||||||
<Filter>2d</Filter>
|
<Filter>2d</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\kiwano\renderer\Geometry.cpp">
|
|
||||||
<Filter>renderer</Filter>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\src\kiwano\2d\action\ActionDelay.cpp">
|
<ClCompile Include="..\src\kiwano\2d\action\ActionDelay.cpp">
|
||||||
<Filter>2d\action</Filter>
|
<Filter>2d\action</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -440,8 +428,56 @@
|
||||||
<ClCompile Include="..\src\kiwano\base\Window.cpp">
|
<ClCompile Include="..\src\kiwano\base\Window.cpp">
|
||||||
<Filter>base</Filter>
|
<Filter>base</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\base\ObjectBase.cpp">
|
||||||
|
<Filter>base</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\Color.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\Font.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\Geometry.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\GifImage.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\Image.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\ImageCache.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\LayerArea.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\src\kiwano\renderer\Renderer.cpp">
|
<ClCompile Include="..\src\kiwano\renderer\Renderer.cpp">
|
||||||
<Filter>renderer</Filter>
|
<Filter>renderer</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\TextLayout.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\D2DDeviceResources.cpp">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\D3D10DeviceResources.cpp">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\D3D11DeviceResources.cpp">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\FontCollectionLoader.cpp">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\win32\TextRenderer.cpp">
|
||||||
|
<Filter>renderer\win32</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\RenderTarget.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\src\kiwano\renderer\FontCollection.cpp">
|
||||||
|
<Filter>renderer</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
. .\scripts\appveyor\appveyor_get_build.ps1
|
. .\scripts\appveyor\appveyor_get_build.ps1
|
||||||
|
|
||||||
|
# Ignore commits without APPVEYOR_API_TOKEN envrionment variable
|
||||||
|
if (-not ($env:APPVEYOR_API_TOKEN)) { return }
|
||||||
|
|
||||||
# Only deploy when commit message contains "[deploy]"
|
# Only deploy when commit message contains "[deploy]"
|
||||||
if (!(Get-AppVeyorBuild).build.message.Contains('[deploy]')) { return }
|
if (!(Get-AppVeyorBuild).build.message.Contains('[deploy]')) { return }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,33 @@ namespace kiwano
|
||||||
ClearCache();
|
ClearCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::Load(Resource const& res)
|
size_t Player::Load(String const& file_path)
|
||||||
{
|
{
|
||||||
size_t hash_code = res.GetHashCode();
|
size_t hash_code = file_path.hash();
|
||||||
if (sound_cache_.end() != sound_cache_.find(hash_code))
|
if (sound_cache_.end() != sound_cache_.find(hash_code))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
SoundPtr sound = new (std::nothrow) Sound();
|
SoundPtr sound = new (std::nothrow) Sound;
|
||||||
|
|
||||||
|
if (sound)
|
||||||
|
{
|
||||||
|
if (sound->Load(file_path))
|
||||||
|
{
|
||||||
|
sound->SetVolume(volume_);
|
||||||
|
sound_cache_.insert(std::make_pair(hash_code, sound));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Player::Load(Resource const& res)
|
||||||
|
{
|
||||||
|
size_t hash_code = res.GetId();
|
||||||
|
if (sound_cache_.end() != sound_cache_.find(hash_code))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
SoundPtr sound = new (std::nothrow) Sound;
|
||||||
|
|
||||||
if (sound)
|
if (sound)
|
||||||
{
|
{
|
||||||
|
|
@ -54,42 +74,39 @@ namespace kiwano
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::Play(Resource const& res, int loop_count)
|
void Player::Play(size_t id, int loop_count)
|
||||||
{
|
{
|
||||||
if (Load(res))
|
auto iter = sound_cache_.find(id);
|
||||||
{
|
if (sound_cache_.end() != iter)
|
||||||
size_t hash_code = res.GetHashCode();
|
iter->second->Play(loop_count);
|
||||||
if (sound_cache_.end() != sound_cache_.find(hash_code))
|
|
||||||
sound_cache_[hash_code]->Play(loop_count);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::Pause(Resource const& res)
|
void Player::Pause(size_t id)
|
||||||
{
|
{
|
||||||
size_t hash_code = res.GetHashCode();
|
auto iter = sound_cache_.find(id);
|
||||||
if (sound_cache_.end() != sound_cache_.find(hash_code))
|
if (sound_cache_.end() != iter)
|
||||||
sound_cache_[hash_code]->Pause();
|
iter->second->Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::Resume(Resource const& res)
|
void Player::Resume(size_t id)
|
||||||
{
|
{
|
||||||
size_t hash_code = res.GetHashCode();
|
auto iter = sound_cache_.find(id);
|
||||||
if (sound_cache_.end() != sound_cache_.find(hash_code))
|
if (sound_cache_.end() != iter)
|
||||||
sound_cache_[hash_code]->Resume();
|
iter->second->Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::Stop(Resource const& res)
|
void Player::Stop(size_t id)
|
||||||
{
|
{
|
||||||
size_t hash_code = res.GetHashCode();
|
auto iter = sound_cache_.find(id);
|
||||||
if (sound_cache_.end() != sound_cache_.find(hash_code))
|
if (sound_cache_.end() != iter)
|
||||||
sound_cache_[hash_code]->Stop();
|
iter->second->Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::IsPlaying(Resource const& res)
|
bool Player::IsPlaying(size_t id)
|
||||||
{
|
{
|
||||||
size_t hash_code = res.GetHashCode();
|
auto iter = sound_cache_.find(id);
|
||||||
if (sound_cache_.end() != sound_cache_.find(hash_code))
|
if (sound_cache_.end() != iter)
|
||||||
return sound_cache_[hash_code]->IsPlaying();
|
return iter->second->IsPlaying();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <kiwano/core/intrusive_ptr.hpp>
|
#include <kiwano/core/intrusive_ptr.hpp>
|
||||||
#include <kiwano/base/Object.h>
|
#include <kiwano/base/ObjectBase.h>
|
||||||
#include "Sound.h"
|
#include "Sound.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
|
|
@ -31,44 +31,47 @@ namespace kiwano
|
||||||
|
|
||||||
// 稜있꺄렴포
|
// 稜있꺄렴포
|
||||||
class KGE_API Player
|
class KGE_API Player
|
||||||
: protected Object
|
: protected ObjectBase
|
||||||
{
|
{
|
||||||
using MusicMap = Map<size_t, SoundPtr>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Player();
|
Player();
|
||||||
|
|
||||||
~Player();
|
~Player();
|
||||||
|
|
||||||
// 속潼稜있栗都
|
// 加载本地音频文件, 返回该资源标识符
|
||||||
bool Load(
|
size_t Load(
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
|
// 加载音乐资源, 返回该资源标识符
|
||||||
|
size_t Load(
|
||||||
Resource const& res /* 稜있栗都 */
|
Resource const& res /* 稜있栗都 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 꺄렴稜있
|
// 꺄렴稜있
|
||||||
void Play(
|
void Play(
|
||||||
Resource const& res, /* 稜있栗都 */
|
size_t id, /* 标识符 */
|
||||||
int loop_count = 0 /* 꺄렴琦뻔늴鑒 (-1 槨琦뻔꺄렴) */
|
int loop_count = 0 /* 꺄렴琦뻔늴鑒 (-1 槨琦뻔꺄렴) */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 董界稜있
|
// 董界稜있
|
||||||
void Pause(
|
void Pause(
|
||||||
Resource const& res /* 稜있栗都 */
|
size_t id /* 标识符 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 셨崎꺄렴稜있
|
// 셨崎꺄렴稜있
|
||||||
void Resume(
|
void Resume(
|
||||||
Resource const& res /* 稜있栗都 */
|
size_t id /* 标识符 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 界岺稜있
|
// 界岺稜있
|
||||||
void Stop(
|
void Stop(
|
||||||
Resource const& res /* 稜있栗都 */
|
size_t id /* 标识符 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 삿혤稜있꺄렴榴檄
|
// 삿혤稜있꺄렴榴檄
|
||||||
bool IsPlaying(
|
bool IsPlaying(
|
||||||
Resource const& res /* 稜있栗都 */
|
size_t id /* 标识符 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 삿혤稜좆
|
// 삿혤稜좆
|
||||||
|
|
@ -93,6 +96,8 @@ namespace kiwano
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float volume_;
|
float volume_;
|
||||||
|
|
||||||
|
using MusicMap = Map<size_t, SoundPtr>;
|
||||||
MusicMap sound_cache_;
|
MusicMap sound_cache_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,46 @@ namespace kiwano
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Sound::Load(String const& file_path)
|
||||||
|
{
|
||||||
|
if (opened_)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(KGE_DEBUG)
|
||||||
|
if (!FileUtil::ExistsFile(file_path))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Media file '%s' not found", file_path.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Transcoder transcoder;
|
||||||
|
HRESULT hr = transcoder.LoadMediaFile(file_path, &wave_data_, &size_);
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
KGE_ERROR_LOG(L"Load media file failed with HRESULT of %08X", hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
if (wave_data_)
|
||||||
|
{
|
||||||
|
delete[] wave_data_;
|
||||||
|
wave_data_ = nullptr;
|
||||||
|
}
|
||||||
|
KGE_ERROR_LOG(L"Create source voice failed with HRESULT of %08X", hr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
opened_ = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Sound::Load(Resource const& res)
|
bool Sound::Load(Resource const& res)
|
||||||
{
|
{
|
||||||
if (opened_)
|
if (opened_)
|
||||||
|
|
@ -56,28 +96,12 @@ namespace kiwano
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
Transcoder transcoder;
|
Transcoder transcoder;
|
||||||
|
HRESULT hr = transcoder.LoadMediaResource(res, &wave_data_, &size_);
|
||||||
if (res.IsFileType())
|
|
||||||
{
|
|
||||||
#if defined(KGE_DEBUG)
|
|
||||||
if (!FileUtil::ExistsFile(res.GetFileName()))
|
|
||||||
{
|
|
||||||
KGE_WARNING_LOG(L"Media file '%s' not found", res.GetFileName().c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
hr = transcoder.LoadMediaFile(res.GetFileName(), &wave_data_, &size_);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = transcoder.LoadMediaResource(res, &wave_data_, &size_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
KGE_ERROR_LOG(L"Load media file failed with HRESULT of %08X", hr);
|
KGE_ERROR_LOG(L"Load media resource failed with HRESULT of %08X", hr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <kiwano/core/intrusive_ptr.hpp>
|
#include <kiwano/core/intrusive_ptr.hpp>
|
||||||
#include <kiwano/base/Object.h>
|
#include <kiwano/base/ObjectBase.h>
|
||||||
#include <kiwano/base/Resource.h>
|
#include <kiwano/base/Resource.h>
|
||||||
#include <xaudio2.h>
|
#include <xaudio2.h>
|
||||||
|
|
||||||
|
|
@ -32,17 +32,26 @@ namespace kiwano
|
||||||
|
|
||||||
// 稜있뚤蹶
|
// 稜있뚤蹶
|
||||||
class KGE_API Sound
|
class KGE_API Sound
|
||||||
: public Object
|
: public ObjectBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Sound();
|
Sound();
|
||||||
|
|
||||||
|
Sound(
|
||||||
|
String const& file_path /* 本地音频文件 */
|
||||||
|
);
|
||||||
|
|
||||||
Sound(
|
Sound(
|
||||||
Resource const& res /* 稜있栗都 */
|
Resource const& res /* 稜있栗都 */
|
||||||
);
|
);
|
||||||
|
|
||||||
virtual ~Sound();
|
virtual ~Sound();
|
||||||
|
|
||||||
|
// 打开本地音频文件
|
||||||
|
bool Load(
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
// 댔역稜있栗都
|
// 댔역稜있栗都
|
||||||
bool Load(
|
bool Load(
|
||||||
Resource const& res /* 稜있栗都 */
|
Resource const& res /* 稜있栗都 */
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,9 @@
|
||||||
|
|
||||||
#include <kiwano/macros.h>
|
#include <kiwano/macros.h>
|
||||||
#include <kiwano/core/string.hpp>
|
#include <kiwano/core/string.hpp>
|
||||||
#include <kiwano/base/ComPtr.hpp>
|
|
||||||
#include <kiwano/base/Resource.h>
|
#include <kiwano/base/Resource.h>
|
||||||
#include <kiwano/base/Logger.h>
|
#include <kiwano/base/Logger.h>
|
||||||
|
#include <kiwano/renderer/win32/ComPtr.hpp>
|
||||||
#include <kiwano/platform/modules.h>
|
#include <kiwano/platform/modules.h>
|
||||||
#include "audio-modules.h"
|
#include "audio-modules.h"
|
||||||
#include "Transcoder.h"
|
#include "Transcoder.h"
|
||||||
|
|
@ -83,13 +83,12 @@ namespace kiwano
|
||||||
ComPtr<IMFByteStream> byte_stream;
|
ComPtr<IMFByteStream> byte_stream;
|
||||||
ComPtr<IMFSourceReader> reader;
|
ComPtr<IMFSourceReader> reader;
|
||||||
|
|
||||||
LPVOID buffer;
|
Resource::Data data = res.GetData();
|
||||||
DWORD buffer_size;
|
if (!data) { return E_FAIL; }
|
||||||
if (!res.Load(buffer, buffer_size)) { return E_FAIL; }
|
|
||||||
|
|
||||||
stream = kiwano::modules::Shlwapi::Get().SHCreateMemStream(
|
stream = kiwano::modules::Shlwapi::Get().SHCreateMemStream(
|
||||||
static_cast<const BYTE*>(buffer),
|
static_cast<const BYTE*>(data.buffer),
|
||||||
static_cast<UINT>(buffer_size)
|
static_cast<UINT>(data.size)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (stream == nullptr)
|
if (stream == nullptr)
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <kiwano/core/Function.hpp>
|
#include <kiwano/core/Function.hpp>
|
||||||
#include <kiwano/core/basic_json.hpp>
|
#include <kiwano/core/basic_json.hpp>
|
||||||
#include <kiwano/base/Object.h>
|
#include <kiwano/base/ObjectBase.h>
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -30,7 +30,7 @@ namespace kiwano
|
||||||
typedef Function<void(HttpRequestPtr, HttpResponsePtr)> ResponseCallback;
|
typedef Function<void(HttpRequestPtr, HttpResponsePtr)> ResponseCallback;
|
||||||
|
|
||||||
class KGE_API HttpRequest
|
class KGE_API HttpRequest
|
||||||
: public Object
|
: public ObjectBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class Type
|
enum class Type
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <kiwano/core/Function.hpp>
|
#include <kiwano/core/Function.hpp>
|
||||||
#include <kiwano/core/basic_json.hpp>
|
#include <kiwano/core/basic_json.hpp>
|
||||||
#include <kiwano/base/Object.h>
|
#include <kiwano/base/ObjectBase.h>
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
namespace network
|
namespace network
|
||||||
{
|
{
|
||||||
class KGE_API HttpResponse
|
class KGE_API HttpResponse
|
||||||
: public Object
|
: public ObjectBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
inline HttpResponse(HttpRequestPtr request)
|
inline HttpResponse(HttpRequestPtr request)
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ namespace kiwano
|
||||||
OnUpdate(dt);
|
OnUpdate(dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!children_.is_empty())
|
if (!children_.item_empty())
|
||||||
{
|
{
|
||||||
ActorPtr next;
|
ActorPtr next;
|
||||||
for (auto child = children_.first_item(); child; child = next)
|
for (auto child = children_.first_item(); child; child = next)
|
||||||
|
|
@ -89,7 +89,7 @@ namespace kiwano
|
||||||
|
|
||||||
UpdateTransform();
|
UpdateTransform();
|
||||||
|
|
||||||
if (children_.is_empty())
|
if (children_.item_empty())
|
||||||
{
|
{
|
||||||
OnRender(renderer);
|
OnRender(renderer);
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +131,7 @@ namespace kiwano
|
||||||
auto renderer = Renderer::GetInstance();
|
auto renderer = Renderer::GetInstance();
|
||||||
renderer->SetTransform(transform_matrix_);
|
renderer->SetTransform(transform_matrix_);
|
||||||
renderer->FillRectangle(bounds, Color(Color::Red, .4f));
|
renderer->FillRectangle(bounds, Color(Color::Red, .4f));
|
||||||
renderer->DrawRectangle(bounds, Color(Color::Red, .8f), 4.f);
|
renderer->DrawRectangle(bounds, Color(Color::Red, .8f), 2.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto child = children_.first_item(); child; child = child->next_item())
|
for (auto child = children_.first_item(); child; child = child->next_item())
|
||||||
|
|
@ -407,7 +407,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
if (!IsName(name))
|
if (!IsName(name))
|
||||||
{
|
{
|
||||||
Object::SetName(name);
|
ObjectBase::SetName(name);
|
||||||
hash_name_ = std::hash<String>{}(name);
|
hash_name_ = std::hash<String>{}(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -609,7 +609,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception");
|
KGE_ASSERT(child && "Actor::RemoveChild failed, NULL pointer exception");
|
||||||
|
|
||||||
if (children_.is_empty())
|
if (children_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (child)
|
if (child)
|
||||||
|
|
@ -622,7 +622,7 @@ namespace kiwano
|
||||||
|
|
||||||
void Actor::RemoveChildren(String const& child_name)
|
void Actor::RemoveChildren(String const& child_name)
|
||||||
{
|
{
|
||||||
if (children_.is_empty())
|
if (children_.item_empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ namespace kiwano
|
||||||
|
|
||||||
// ½ÇÉ«
|
// ½ÇÉ«
|
||||||
class KGE_API Actor
|
class KGE_API Actor
|
||||||
: public Object
|
: public ObjectBase
|
||||||
, public TimerManager
|
, public TimerManager
|
||||||
, public ActionManager
|
, public ActionManager
|
||||||
, public EventDispatcher
|
, public EventDispatcher
|
||||||
|
|
|
||||||
|
|
@ -27,35 +27,11 @@ namespace kiwano
|
||||||
Canvas::Canvas()
|
Canvas::Canvas()
|
||||||
: cache_expired_(false)
|
: cache_expired_(false)
|
||||||
, stroke_width_(1.0f)
|
, stroke_width_(1.0f)
|
||||||
|
, fill_color_(0, 0, 0)
|
||||||
|
, stroke_color_(Color::White)
|
||||||
|
, stroke_style_(StrokeStyle::Miter)
|
||||||
{
|
{
|
||||||
auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
|
Renderer::GetInstance()->CreateImageRenderTarget(rt_);
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
ctx->CreateCompatibleRenderTarget(&render_target_)
|
|
||||||
);
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
render_target_->CreateSolidColorBrush(
|
|
||||||
D2D1::ColorF(0, 0, 0, 0),
|
|
||||||
D2D1::BrushProperties(),
|
|
||||||
&fill_brush_)
|
|
||||||
);
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
render_target_->CreateSolidColorBrush(
|
|
||||||
D2D1::ColorF(Color::White),
|
|
||||||
D2D1::BrushProperties(),
|
|
||||||
&stroke_brush_)
|
|
||||||
);
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
ITextRenderer::Create(
|
|
||||||
&text_renderer_,
|
|
||||||
render_target_.get()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
SetTextStyle(Font{}, TextStyle{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::Canvas(float width, float height)
|
Canvas::Canvas(float width, float height)
|
||||||
|
|
@ -75,45 +51,36 @@ namespace kiwano
|
||||||
|
|
||||||
void Canvas::BeginDraw()
|
void Canvas::BeginDraw()
|
||||||
{
|
{
|
||||||
render_target_->BeginDraw();
|
rt_.BeginDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::EndDraw()
|
void Canvas::EndDraw()
|
||||||
{
|
{
|
||||||
ThrowIfFailed(
|
rt_.EndDraw();
|
||||||
render_target_->EndDraw()
|
|
||||||
);
|
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::OnRender(Renderer* renderer)
|
void Canvas::OnRender(Renderer* renderer)
|
||||||
{
|
{
|
||||||
if (cache_expired_)
|
UpdateCache();
|
||||||
{
|
|
||||||
GetBitmap();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bitmap_cached_)
|
if (image_cached_.IsValid())
|
||||||
{
|
{
|
||||||
PrepareRender(renderer);
|
PrepareRender(renderer);
|
||||||
|
|
||||||
Rect bitmap_rect(0.f, 0.f, bitmap_cached_->GetSize().width, bitmap_cached_->GetSize().height);
|
Rect bitmap_rect(0.f, 0.f, image_cached_.GetWidth(), image_cached_.GetHeight());
|
||||||
renderer->DrawBitmap(
|
renderer->DrawImage(image_cached_, bitmap_rect, bitmap_rect);
|
||||||
bitmap_cached_,
|
|
||||||
bitmap_rect,
|
|
||||||
bitmap_rect
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::SetStrokeColor(Color const& color)
|
void Canvas::SetStrokeColor(Color const& color)
|
||||||
{
|
{
|
||||||
stroke_brush_->SetColor(DX::ConvertToColorF(color));
|
stroke_color_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::SetFillColor(Color const& color)
|
void Canvas::SetFillColor(Color const& color)
|
||||||
{
|
{
|
||||||
fill_brush_->SetColor(DX::ConvertToColorF(color));
|
fill_color_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::SetStrokeWidth(float width)
|
void Canvas::SetStrokeWidth(float width)
|
||||||
|
|
@ -121,39 +88,34 @@ namespace kiwano
|
||||||
stroke_width_ = std::max(width, 0.f);
|
stroke_width_ = std::max(width, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::SetOutlineJoinStyle(StrokeStyle outline_join)
|
void Canvas::SetStrokeStyle(StrokeStyle stroke_style)
|
||||||
{
|
{
|
||||||
outline_join_style_ = Renderer::GetInstance()->GetD2DDeviceResources()->GetStrokeStyle(outline_join);
|
stroke_style_ = stroke_style;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::SetTextStyle(Font const& font, TextStyle const & text_style)
|
void Canvas::SetTextFont(Font const& font)
|
||||||
{
|
{
|
||||||
text_font_ = font;
|
text_font_ = font;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::SetTextStyle(TextStyle const & text_style)
|
||||||
|
{
|
||||||
text_style_ = text_style;
|
text_style_ = text_style;
|
||||||
|
}
|
||||||
|
|
||||||
text_renderer_->SetTextStyle(
|
void Canvas::SetBrushOpacity(float opacity)
|
||||||
1.f,
|
{
|
||||||
DX::ConvertToColorF(text_style_.color),
|
rt_.SetOpacity(opacity);
|
||||||
text_style_.outline,
|
|
||||||
DX::ConvertToColorF(text_style_.outline_color),
|
|
||||||
text_style_.outline_width,
|
|
||||||
Renderer::GetInstance()->GetD2DDeviceResources()->GetStrokeStyle(text_style_.outline_stroke)
|
|
||||||
);
|
|
||||||
|
|
||||||
// clear text format
|
|
||||||
text_format_ = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Canvas::GetStrokeColor() const
|
Color Canvas::GetStrokeColor() const
|
||||||
{
|
{
|
||||||
auto color_f = stroke_brush_->GetColor();
|
return stroke_color_;
|
||||||
return Color{ color_f.r, color_f.g, color_f.b, color_f.a };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Color Canvas::GetFillColor() const
|
Color Canvas::GetFillColor() const
|
||||||
{
|
{
|
||||||
auto color_f = fill_brush_->GetColor();
|
return fill_color_;
|
||||||
return Color{ color_f.r, color_f.g, color_f.b, color_f.a };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Canvas::GetStrokeWidth() const
|
float Canvas::GetStrokeWidth() const
|
||||||
|
|
@ -161,324 +123,219 @@ namespace kiwano
|
||||||
return stroke_width_;
|
return stroke_width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Canvas::GetBrushOpacity() const
|
||||||
|
{
|
||||||
|
return rt_.GetOpacity();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::SetBrushTransform(Transform const& transform)
|
||||||
|
{
|
||||||
|
Matrix3x2 matrix = Matrix3x2::SRT(transform.position, transform.scale, transform.rotation);
|
||||||
|
if (!transform.skew.IsOrigin())
|
||||||
|
{
|
||||||
|
matrix = Matrix3x2::Skewing(transform.skew) * matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_.SetTransform(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
void Canvas::SetBrushTransform(Matrix3x2 const & transform)
|
void Canvas::SetBrushTransform(Matrix3x2 const & transform)
|
||||||
{
|
{
|
||||||
render_target_->SetTransform(DX::ConvertToMatrix3x2F(transform));
|
rt_.SetTransform(transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawLine(const Point & begin, const Point & end)
|
void Canvas::DrawLine(Point const& begin, Point const& end)
|
||||||
{
|
{
|
||||||
render_target_->DrawLine(
|
rt_.DrawLine(
|
||||||
D2D1::Point2F(begin.x, begin.y),
|
begin,
|
||||||
D2D1::Point2F(end.x, end.y),
|
end,
|
||||||
stroke_brush_.get(),
|
stroke_color_,
|
||||||
stroke_width_,
|
stroke_width_,
|
||||||
outline_join_style_.get()
|
stroke_style_
|
||||||
);
|
);
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawCircle(const Point & center, float radius)
|
void Canvas::DrawCircle(Point const& center, float radius)
|
||||||
{
|
{
|
||||||
render_target_->DrawEllipse(
|
rt_.DrawEllipse(
|
||||||
D2D1::Ellipse(
|
center,
|
||||||
D2D1::Point2F(
|
Vec2(radius, radius),
|
||||||
center.x,
|
stroke_color_,
|
||||||
center.y
|
stroke_width_,
|
||||||
),
|
stroke_style_
|
||||||
|
);
|
||||||
|
cache_expired_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawEllipse(Point const& center, Vec2 const& radius)
|
||||||
|
{
|
||||||
|
rt_.DrawEllipse(
|
||||||
|
center,
|
||||||
radius,
|
radius,
|
||||||
radius
|
stroke_color_,
|
||||||
),
|
|
||||||
stroke_brush_.get(),
|
|
||||||
stroke_width_,
|
stroke_width_,
|
||||||
outline_join_style_.get()
|
stroke_style_
|
||||||
);
|
);
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawEllipse(const Point & center, float radius_x, float radius_y)
|
void Canvas::DrawRect(Rect const& rect)
|
||||||
{
|
{
|
||||||
render_target_->DrawEllipse(
|
rt_.DrawRectangle(
|
||||||
D2D1::Ellipse(
|
rect,
|
||||||
D2D1::Point2F(
|
stroke_color_,
|
||||||
center.x,
|
|
||||||
center.y
|
|
||||||
),
|
|
||||||
radius_x,
|
|
||||||
radius_y
|
|
||||||
),
|
|
||||||
stroke_brush_.get(),
|
|
||||||
stroke_width_,
|
stroke_width_,
|
||||||
outline_join_style_.get()
|
stroke_style_
|
||||||
);
|
);
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawRect(const Rect & rect)
|
void Canvas::DrawRoundedRect(Rect const& rect, Vec2 const& radius)
|
||||||
{
|
{
|
||||||
render_target_->DrawRectangle(
|
rt_.DrawRoundedRectangle(
|
||||||
D2D1::RectF(
|
rect,
|
||||||
rect.origin.x,
|
radius,
|
||||||
rect.origin.y,
|
stroke_color_,
|
||||||
rect.origin.x + rect.size.x,
|
|
||||||
rect.origin.y + rect.size.y
|
|
||||||
),
|
|
||||||
stroke_brush_.get(),
|
|
||||||
stroke_width_,
|
stroke_width_,
|
||||||
outline_join_style_.get()
|
stroke_style_
|
||||||
);
|
);
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawRoundedRect(const Rect & rect, float radius_x, float radius_y)
|
void Canvas::FillCircle(Point const& center, float radius)
|
||||||
{
|
{
|
||||||
render_target_->DrawRoundedRectangle(
|
rt_.FillEllipse(
|
||||||
D2D1::RoundedRect(
|
center,
|
||||||
D2D1::RectF(
|
Vec2(radius, radius),
|
||||||
rect.origin.x,
|
fill_color_
|
||||||
rect.origin.y,
|
|
||||||
rect.origin.x + rect.size.x,
|
|
||||||
rect.origin.y + rect.size.y
|
|
||||||
),
|
|
||||||
radius_x,
|
|
||||||
radius_y
|
|
||||||
),
|
|
||||||
stroke_brush_.get(),
|
|
||||||
stroke_width_,
|
|
||||||
outline_join_style_.get()
|
|
||||||
);
|
);
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawImage(ImagePtr image, float opacity)
|
void Canvas::FillEllipse(Point const& center, Vec2 const& radius)
|
||||||
{
|
{
|
||||||
if (image && image->GetBitmap())
|
rt_.FillEllipse(
|
||||||
{
|
center,
|
||||||
render_target_->DrawBitmap(
|
radius,
|
||||||
image->GetBitmap().get(),
|
fill_color_
|
||||||
D2D1::RectF(0, 0, image->GetWidth(), image->GetHeight()),
|
|
||||||
opacity,
|
|
||||||
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
|
||||||
D2D1::RectF(0, 0, image->GetWidth(), image->GetHeight())
|
|
||||||
);
|
);
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Canvas::FillRect(Rect const& rect)
|
||||||
|
{
|
||||||
|
rt_.FillRectangle(
|
||||||
|
rect,
|
||||||
|
fill_color_
|
||||||
|
);
|
||||||
|
cache_expired_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::FillRoundedRect(Rect const& rect, Vec2 const& radius)
|
||||||
|
{
|
||||||
|
rt_.FillRoundedRectangle(
|
||||||
|
rect,
|
||||||
|
radius,
|
||||||
|
fill_color_
|
||||||
|
);
|
||||||
|
cache_expired_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::DrawImage(Image const& image, const Rect* src_rect, const Rect* dest_rect)
|
||||||
|
{
|
||||||
|
if (image.IsValid())
|
||||||
|
{
|
||||||
|
rt_.DrawImage(image, src_rect, dest_rect);
|
||||||
|
cache_expired_ = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::DrawText(String const & text, Point const & point)
|
void Canvas::DrawText(String const& text, Point const& point)
|
||||||
{
|
{
|
||||||
if (text.empty())
|
if (text.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!text_format_)
|
TextLayout layout(text, text_font_, text_style_);
|
||||||
{
|
|
||||||
ThrowIfFailed(
|
|
||||||
Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextFormat(
|
|
||||||
text_format_,
|
|
||||||
text_font_,
|
|
||||||
text_style_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ComPtr<IDWriteTextLayout> text_layout;
|
rt_.DrawTextLayout(layout, point);
|
||||||
Size layout_size;
|
|
||||||
ThrowIfFailed(
|
|
||||||
Renderer::GetInstance()->GetD2DDeviceResources()->CreateTextLayout(
|
|
||||||
text_layout,
|
|
||||||
layout_size,
|
|
||||||
text,
|
|
||||||
text_format_,
|
|
||||||
text_style_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
text_layout->Draw(nullptr, text_renderer_.get(), point.x, point.y)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Canvas::FillCircle(const Point & center, float radius)
|
|
||||||
{
|
|
||||||
render_target_->FillEllipse(
|
|
||||||
D2D1::Ellipse(
|
|
||||||
D2D1::Point2F(
|
|
||||||
center.x,
|
|
||||||
center.y
|
|
||||||
),
|
|
||||||
radius,
|
|
||||||
radius
|
|
||||||
),
|
|
||||||
fill_brush_.get()
|
|
||||||
);
|
|
||||||
cache_expired_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Canvas::FillEllipse(const Point & center, float radius_x, float radius_y)
|
|
||||||
{
|
|
||||||
render_target_->FillEllipse(
|
|
||||||
D2D1::Ellipse(
|
|
||||||
D2D1::Point2F(
|
|
||||||
center.x,
|
|
||||||
center.y
|
|
||||||
),
|
|
||||||
radius_x,
|
|
||||||
radius_y
|
|
||||||
),
|
|
||||||
fill_brush_.get()
|
|
||||||
);
|
|
||||||
cache_expired_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Canvas::FillRect(const Rect & rect)
|
|
||||||
{
|
|
||||||
render_target_->FillRectangle(
|
|
||||||
D2D1::RectF(
|
|
||||||
rect.origin.x,
|
|
||||||
rect.origin.y,
|
|
||||||
rect.origin.x + rect.size.x,
|
|
||||||
rect.origin.y + rect.size.y
|
|
||||||
),
|
|
||||||
fill_brush_.get()
|
|
||||||
);
|
|
||||||
cache_expired_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Canvas::FillRoundedRect(const Rect & rect, float radius_x, float radius_y)
|
|
||||||
{
|
|
||||||
render_target_->FillRoundedRectangle(
|
|
||||||
D2D1::RoundedRect(
|
|
||||||
D2D1::RectF(
|
|
||||||
rect.origin.x,
|
|
||||||
rect.origin.y,
|
|
||||||
rect.origin.x + rect.size.x,
|
|
||||||
rect.origin.y + rect.size.y
|
|
||||||
),
|
|
||||||
radius_x,
|
|
||||||
radius_y
|
|
||||||
),
|
|
||||||
fill_brush_.get()
|
|
||||||
);
|
|
||||||
cache_expired_ = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::BeginPath(Point const& begin_pos)
|
void Canvas::BeginPath(Point const& begin_pos)
|
||||||
{
|
{
|
||||||
current_geometry_ = nullptr;
|
geo_sink_.BeginPath(begin_pos);
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
Renderer::GetInstance()->GetD2DDeviceResources()->GetFactory()->CreatePathGeometry(¤t_geometry_)
|
|
||||||
);
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
current_geometry_->Open(¤t_sink_)
|
|
||||||
);
|
|
||||||
|
|
||||||
current_sink_->BeginFigure(DX::ConvertToPoint2F(begin_pos), D2D1_FIGURE_BEGIN_FILLED);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::EndPath(bool closed)
|
void Canvas::EndPath(bool closed)
|
||||||
{
|
{
|
||||||
if (current_sink_)
|
geo_sink_.EndPath(closed);
|
||||||
{
|
|
||||||
current_sink_->EndFigure(closed ? D2D1_FIGURE_END_CLOSED : D2D1_FIGURE_END_OPEN);
|
|
||||||
ThrowIfFailed(
|
|
||||||
current_sink_->Close()
|
|
||||||
);
|
|
||||||
current_sink_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::AddLine(Point const & point)
|
void Canvas::AddLine(Point const & point)
|
||||||
{
|
{
|
||||||
if (current_sink_)
|
geo_sink_.AddLine(point);
|
||||||
current_sink_->AddLine(DX::ConvertToPoint2F(point));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::AddLines(Vector<Point> const& points)
|
void Canvas::AddLines(Vector<Point> const& points)
|
||||||
{
|
{
|
||||||
if (current_sink_ && !points.empty())
|
geo_sink_.AddLines(points);
|
||||||
{
|
|
||||||
current_sink_->AddLines(
|
|
||||||
reinterpret_cast<const D2D_POINT_2F*>(&points[0]),
|
|
||||||
static_cast<UINT32>(points.size())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::AddBezier(Point const & point1, Point const & point2, Point const & point3)
|
void Canvas::AddBezier(Point const & point1, Point const & point2, Point const & point3)
|
||||||
{
|
{
|
||||||
if (current_sink_)
|
geo_sink_.AddBezier(point1, point2, point3);
|
||||||
{
|
|
||||||
current_sink_->AddBezier(
|
|
||||||
D2D1::BezierSegment(
|
|
||||||
DX::ConvertToPoint2F(point1),
|
|
||||||
DX::ConvertToPoint2F(point2),
|
|
||||||
DX::ConvertToPoint2F(point3)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::AddArc(Point const & point, Point const & radius, float rotation, bool clockwise, bool is_small)
|
void Canvas::AddArc(Point const & point, Point const & radius, float rotation, bool clockwise, bool is_small)
|
||||||
{
|
{
|
||||||
if (current_sink_)
|
geo_sink_.AddArc(point, radius, rotation, clockwise, is_small);
|
||||||
{
|
|
||||||
current_sink_->AddArc(
|
|
||||||
D2D1::ArcSegment(
|
|
||||||
DX::ConvertToPoint2F(point),
|
|
||||||
DX::ConvertToSizeF(radius),
|
|
||||||
rotation,
|
|
||||||
clockwise ? D2D1_SWEEP_DIRECTION_CLOCKWISE : D2D1_SWEEP_DIRECTION_COUNTER_CLOCKWISE,
|
|
||||||
is_small ? D2D1_ARC_SIZE_SMALL : D2D1_ARC_SIZE_LARGE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::StrokePath()
|
void Canvas::StrokePath()
|
||||||
{
|
{
|
||||||
render_target_->DrawGeometry(
|
rt_.DrawGeometry(
|
||||||
current_geometry_.get(),
|
geo_sink_.GetGeometry(),
|
||||||
stroke_brush_.get(),
|
stroke_color_,
|
||||||
stroke_width_,
|
stroke_width_,
|
||||||
outline_join_style_.get()
|
stroke_style_
|
||||||
);
|
);
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::FillPath()
|
void Canvas::FillPath()
|
||||||
{
|
{
|
||||||
render_target_->FillGeometry(
|
rt_.FillGeometry(
|
||||||
current_geometry_.get(),
|
geo_sink_.GetGeometry(),
|
||||||
fill_brush_.get()
|
fill_color_
|
||||||
);
|
);
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::Clear()
|
void Canvas::Clear()
|
||||||
{
|
{
|
||||||
render_target_->Clear();
|
rt_.Clear();
|
||||||
cache_expired_ = true;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImagePtr Canvas::ExportToImage() const
|
void Canvas::Clear(Color const& clear_color)
|
||||||
{
|
{
|
||||||
ImagePtr image = new Image(GetBitmap());
|
rt_.Clear(clear_color);
|
||||||
return image;
|
cache_expired_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ComPtr<ID2D1Bitmap> const& kiwano::Canvas::GetBitmap() const
|
Image Canvas::ExportToImage() const
|
||||||
|
{
|
||||||
|
UpdateCache();
|
||||||
|
return image_cached_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Canvas::UpdateCache() const
|
||||||
{
|
{
|
||||||
if (cache_expired_)
|
if (cache_expired_)
|
||||||
{
|
{
|
||||||
bitmap_cached_ = nullptr;
|
rt_.GetOutput(image_cached_);
|
||||||
ThrowIfFailed(
|
|
||||||
render_target_->GetBitmap(&bitmap_cached_)
|
|
||||||
);
|
|
||||||
cache_expired_ = false;
|
cache_expired_ = false;
|
||||||
}
|
}
|
||||||
return bitmap_cached_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Font.hpp"
|
#include "../renderer/RenderTarget.h"
|
||||||
#include "TextStyle.hpp"
|
|
||||||
#include "../renderer/Image.h"
|
|
||||||
#include "../renderer/TextRenderer.h"
|
|
||||||
|
|
||||||
#ifdef DrawText
|
#ifdef DrawText
|
||||||
# undef DrawText
|
# undef DrawText
|
||||||
|
|
@ -57,39 +54,61 @@ namespace kiwano
|
||||||
|
|
||||||
// 画直线
|
// 画直线
|
||||||
void DrawLine(
|
void DrawLine(
|
||||||
const Point& begin,
|
Point const& begin,
|
||||||
const Point& end
|
Point const& end
|
||||||
);
|
);
|
||||||
|
|
||||||
// 画圆形边框
|
// 画圆形边框
|
||||||
void DrawCircle(
|
void DrawCircle(
|
||||||
const Point& center,
|
Point const& center,
|
||||||
float radius
|
float radius
|
||||||
);
|
);
|
||||||
|
|
||||||
// 画椭圆形边框
|
// 画椭圆形边框
|
||||||
void DrawEllipse(
|
void DrawEllipse(
|
||||||
const Point& center,
|
Point const& center,
|
||||||
float radius_x,
|
Vec2 const& radius
|
||||||
float radius_y
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 画矩形边框
|
// 画矩形边框
|
||||||
void DrawRect(
|
void DrawRect(
|
||||||
const Rect& rect
|
Rect const& rect
|
||||||
);
|
);
|
||||||
|
|
||||||
// 画圆角矩形边框
|
// 画圆角矩形边框
|
||||||
void DrawRoundedRect(
|
void DrawRoundedRect(
|
||||||
const Rect& rect,
|
Rect const& rect,
|
||||||
float radius_x,
|
Vec2 const& radius
|
||||||
float radius_y
|
);
|
||||||
|
|
||||||
|
// Ìî³äÔ²ÐÎ
|
||||||
|
void FillCircle(
|
||||||
|
Point const& center,
|
||||||
|
float radius
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ìî³äÍÖÔ²ÐÎ
|
||||||
|
void FillEllipse(
|
||||||
|
Point const& center,
|
||||||
|
Vec2 const& radius
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ìî³ä¾ØÐÎ
|
||||||
|
void FillRect(
|
||||||
|
Rect const& rect
|
||||||
|
);
|
||||||
|
|
||||||
|
// Ìî³äÔ²½Ç¾ØÐÎ
|
||||||
|
void FillRoundedRect(
|
||||||
|
Rect const& rect,
|
||||||
|
Vec2 const& radius
|
||||||
);
|
);
|
||||||
|
|
||||||
// 画图片
|
// 画图片
|
||||||
void DrawImage(
|
void DrawImage(
|
||||||
ImagePtr image,
|
Image const& image,
|
||||||
float opacity = 1.f
|
const Rect* src_rect = nullptr,
|
||||||
|
const Rect* dest_rect = nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
// 画文字
|
// 画文字
|
||||||
|
|
@ -98,31 +117,6 @@ namespace kiwano
|
||||||
Point const& point /* 文字位置 */
|
Point const& point /* 文字位置 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// Ìî³äÔ²ÐÎ
|
|
||||||
void FillCircle(
|
|
||||||
const Point& center,
|
|
||||||
float radius
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ìî³äÍÖÔ²ÐÎ
|
|
||||||
void FillEllipse(
|
|
||||||
const Point& center,
|
|
||||||
float radius_x,
|
|
||||||
float radius_y
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ìî³ä¾ØÐÎ
|
|
||||||
void FillRect(
|
|
||||||
const Rect& rect
|
|
||||||
);
|
|
||||||
|
|
||||||
// Ìî³äÔ²½Ç¾ØÐÎ
|
|
||||||
void FillRoundedRect(
|
|
||||||
const Rect& rect,
|
|
||||||
float radius_x,
|
|
||||||
float radius_y
|
|
||||||
);
|
|
||||||
|
|
||||||
// 开始绘制路径
|
// 开始绘制路径
|
||||||
void BeginPath(
|
void BeginPath(
|
||||||
Point const& begin_pos /* 路径起始点 */
|
Point const& begin_pos /* 路径起始点 */
|
||||||
|
|
@ -168,14 +162,19 @@ namespace kiwano
|
||||||
// 清空画布
|
// 清空画布
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
// Çå¿Õ»²¼
|
||||||
|
void Clear(
|
||||||
|
Color const& clear_color
|
||||||
|
);
|
||||||
|
|
||||||
// 设置填充颜色
|
// 设置填充颜色
|
||||||
void SetFillColor(
|
void SetFillColor(
|
||||||
const Color& color
|
Color const& color
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置线条颜色
|
// 设置线条颜色
|
||||||
void SetStrokeColor(
|
void SetStrokeColor(
|
||||||
const Color& color
|
Color const& color
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置线条宽度
|
// 设置线条宽度
|
||||||
|
|
@ -183,17 +182,26 @@ namespace kiwano
|
||||||
float width
|
float width
|
||||||
);
|
);
|
||||||
|
|
||||||
// ÉèÖÃÏßÌõÏཻÑùʽ
|
// ÉèÖÃÏßÌõÑùʽ
|
||||||
void SetOutlineJoinStyle(
|
void SetStrokeStyle(
|
||||||
StrokeStyle outline_join
|
StrokeStyle stroke_style
|
||||||
|
);
|
||||||
|
|
||||||
|
// ÉèÖÃÎÄ×Ö×ÖÌå
|
||||||
|
void SetTextFont(
|
||||||
|
Font const& font
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置文字画刷样式
|
// 设置文字画刷样式
|
||||||
void SetTextStyle(
|
void SetTextStyle(
|
||||||
Font const& font,
|
|
||||||
TextStyle const& text_style
|
TextStyle const& text_style
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ÉèÖû±Ê͸Ã÷¶È
|
||||||
|
void SetBrushOpacity(
|
||||||
|
float opacity
|
||||||
|
);
|
||||||
|
|
||||||
// 获取填充颜色
|
// 获取填充颜色
|
||||||
Color GetFillColor() const;
|
Color GetFillColor() const;
|
||||||
|
|
||||||
|
|
@ -203,34 +211,38 @@ namespace kiwano
|
||||||
// 获取线条宽度
|
// 获取线条宽度
|
||||||
float GetStrokeWidth() const;
|
float GetStrokeWidth() const;
|
||||||
|
|
||||||
// ±ä»»»±Ê
|
// »ñÈ¡»±Ê͸Ã÷¶È
|
||||||
|
float GetBrushOpacity() const;
|
||||||
|
|
||||||
|
// »±Ê¶þά±ä»»
|
||||||
|
void SetBrushTransform(
|
||||||
|
Transform const& transform
|
||||||
|
);
|
||||||
|
|
||||||
|
// »±Ê¶þά±ä»»
|
||||||
void SetBrushTransform(
|
void SetBrushTransform(
|
||||||
Matrix3x2 const& transform
|
Matrix3x2 const& transform
|
||||||
);
|
);
|
||||||
|
|
||||||
// 导出为图片
|
// 导出为图片
|
||||||
ImagePtr ExportToImage() const;
|
Image ExportToImage() const;
|
||||||
|
|
||||||
void OnRender(Renderer* renderer) override;
|
void OnRender(Renderer* renderer) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ComPtr<ID2D1Bitmap> const& GetBitmap() const;
|
void UpdateCache() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
float stroke_width_;
|
float stroke_width_;
|
||||||
|
Color fill_color_;
|
||||||
|
Color stroke_color_;
|
||||||
Font text_font_;
|
Font text_font_;
|
||||||
TextStyle text_style_;
|
TextStyle text_style_;
|
||||||
|
StrokeStyle stroke_style_;
|
||||||
ComPtr<ID2D1PathGeometry> current_geometry_;
|
GeometrySink geo_sink_;
|
||||||
ComPtr<ID2D1GeometrySink> current_sink_;
|
ImageRenderTarget rt_;
|
||||||
ComPtr<ID2D1StrokeStyle> outline_join_style_;
|
|
||||||
ComPtr<ID2D1SolidColorBrush> fill_brush_;
|
|
||||||
ComPtr<ID2D1SolidColorBrush> stroke_brush_;
|
|
||||||
ComPtr<IDWriteTextFormat> text_format_;
|
|
||||||
ComPtr<ITextRenderer> text_renderer_;
|
|
||||||
ComPtr<ID2D1BitmapRenderTarget> render_target_;
|
|
||||||
|
|
||||||
mutable bool cache_expired_;
|
mutable bool cache_expired_;
|
||||||
mutable ComPtr<ID2D1Bitmap> bitmap_cached_;
|
mutable Image image_cached_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,6 @@ namespace kiwano
|
||||||
debug_text_->SetFont(font);
|
debug_text_->SetFont(font);
|
||||||
|
|
||||||
TextStyle style;
|
TextStyle style;
|
||||||
style.wrap = false;
|
|
||||||
style.line_spacing = 20.f;
|
style.line_spacing = 20.f;
|
||||||
debug_text_->SetStyle(style);
|
debug_text_->SetStyle(style);
|
||||||
|
|
||||||
|
|
@ -83,9 +82,9 @@ namespace kiwano
|
||||||
ss << "Fps: " << frame_time_.size() << std::endl;
|
ss << "Fps: " << frame_time_.size() << std::endl;
|
||||||
|
|
||||||
#if defined(KGE_DEBUG)
|
#if defined(KGE_DEBUG)
|
||||||
if (Object::IsTracingLeaks())
|
if (ObjectBase::IsTracingLeaks())
|
||||||
{
|
{
|
||||||
ss << "Objects: " << Object::__GetTracingObjects().size() << std::endl;
|
ss << "Objects: " << ObjectBase::__GetTracingObjects().size() << std::endl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -98,7 +97,7 @@ namespace kiwano
|
||||||
ss << "Memory: " << pmc.PrivateUsage / 1024 << "kb";
|
ss << "Memory: " << pmc.PrivateUsage / 1024 << "kb";
|
||||||
|
|
||||||
debug_text_->SetText(ss.str());
|
debug_text_->SetText(ss.str());
|
||||||
SetSize(Size{ 20 + debug_text_->GetLayoutSize().x, 20 + debug_text_->GetLayoutSize().y });
|
SetSize(Size{ 20 + debug_text_->GetSize().x, 20 + debug_text_->GetSize().y });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,20 +27,25 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Frame::Frame(String const& file_path)
|
||||||
|
{
|
||||||
|
Load(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
Frame::Frame(Resource const& res)
|
Frame::Frame(Resource const& res)
|
||||||
{
|
{
|
||||||
Load(res);
|
Load(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame::Frame(ImagePtr image)
|
Frame::Frame(Image const& image)
|
||||||
: image_(image)
|
|
||||||
{
|
{
|
||||||
|
SetImage(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Frame::Load(Resource const& res)
|
bool Frame::Load(String const& file_path)
|
||||||
{
|
{
|
||||||
ImagePtr image = ImageCache::GetInstance()->AddImage(res);
|
Image image = ImageCache::GetInstance()->AddOrGetImage(file_path);
|
||||||
if (image && image->IsValid())
|
if (image.IsValid())
|
||||||
{
|
{
|
||||||
SetImage(image);
|
SetImage(image);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -48,11 +53,22 @@ namespace kiwano
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::Crop(Rect const& crop_rect)
|
bool Frame::Load(Resource const& res)
|
||||||
{
|
{
|
||||||
if (image_)
|
Image image = ImageCache::GetInstance()->AddOrGetImage(res);
|
||||||
|
if (image.IsValid())
|
||||||
{
|
{
|
||||||
auto bitmap_size = image_->GetSize();
|
SetImage(image);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Frame::SetCropRect(Rect const& crop_rect)
|
||||||
|
{
|
||||||
|
if (image_.IsValid())
|
||||||
|
{
|
||||||
|
auto bitmap_size = image_.GetSize();
|
||||||
crop_rect_.origin.x = std::min(std::max(crop_rect.origin.x, 0.f), bitmap_size.x);
|
crop_rect_.origin.x = std::min(std::max(crop_rect.origin.x, 0.f), bitmap_size.x);
|
||||||
crop_rect_.origin.y = std::min(std::max(crop_rect.origin.y, 0.f), bitmap_size.y);
|
crop_rect_.origin.y = std::min(std::max(crop_rect.origin.y, 0.f), bitmap_size.y);
|
||||||
crop_rect_.size.x = std::min(std::max(crop_rect.size.x, 0.f), bitmap_size.x - crop_rect.origin.x);
|
crop_rect_.size.x = std::min(std::max(crop_rect.size.x, 0.f), bitmap_size.x - crop_rect.origin.x);
|
||||||
|
|
@ -60,14 +76,14 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::SetImage(ImagePtr image)
|
void Frame::SetImage(Image const& image)
|
||||||
{
|
{
|
||||||
image_ = image;
|
image_ = image;
|
||||||
if (image_)
|
if (image_.IsValid())
|
||||||
{
|
{
|
||||||
crop_rect_.origin.x = crop_rect_.origin.y = 0;
|
crop_rect_.origin.x = crop_rect_.origin.y = 0;
|
||||||
crop_rect_.size.x = image_->GetWidth();
|
crop_rect_.size.x = image_.GetWidth();
|
||||||
crop_rect_.size.y = image_->GetHeight();
|
crop_rect_.size.y = image_.GetHeight();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,17 +25,25 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
// ֡ͼÏñ
|
// ֡ͼÏñ
|
||||||
class KGE_API Frame
|
class KGE_API Frame
|
||||||
: public Object
|
: public ObjectBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Frame();
|
Frame();
|
||||||
|
|
||||||
|
explicit Frame(
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
explicit Frame(
|
explicit Frame(
|
||||||
Resource const& res
|
Resource const& res
|
||||||
);
|
);
|
||||||
|
|
||||||
explicit Frame(
|
explicit Frame(
|
||||||
ImagePtr image
|
Image const& image
|
||||||
|
);
|
||||||
|
|
||||||
|
bool Load(
|
||||||
|
String const& file_path
|
||||||
);
|
);
|
||||||
|
|
||||||
bool Load(
|
bool Load(
|
||||||
|
|
@ -43,10 +51,15 @@ namespace kiwano
|
||||||
);
|
);
|
||||||
|
|
||||||
// ²Ã¼ô¾ØÐÎ
|
// ²Ã¼ô¾ØÐÎ
|
||||||
void Crop(
|
void SetCropRect(
|
||||||
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
|
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// ÉèÖÃλͼ
|
||||||
|
void SetImage(
|
||||||
|
Image const& image
|
||||||
|
);
|
||||||
|
|
||||||
// »ñÈ¡¿í¶È
|
// »ñÈ¡¿í¶È
|
||||||
float GetWidth() const { return crop_rect_.size.x; }
|
float GetWidth() const { return crop_rect_.size.x; }
|
||||||
|
|
||||||
|
|
@ -63,13 +76,10 @@ namespace kiwano
|
||||||
inline Rect const& GetCropRect() const { return crop_rect_; }
|
inline Rect const& GetCropRect() const { return crop_rect_; }
|
||||||
|
|
||||||
// »ñȡλͼ
|
// »ñȡλͼ
|
||||||
inline ImagePtr GetImage() const { return image_; }
|
inline Image const& GetImage() const { return image_; }
|
||||||
|
|
||||||
// ÉèÖÃλͼ
|
|
||||||
void SetImage(ImagePtr image);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ImagePtr image_;
|
Image image_;
|
||||||
Rect crop_rect_;
|
Rect crop_rect_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
// ÐòÁÐÖ¡
|
// ÐòÁÐÖ¡
|
||||||
class KGE_API FrameSequence
|
class KGE_API FrameSequence
|
||||||
: public Object
|
: public ObjectBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FrameSequence();
|
FrameSequence();
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,8 @@
|
||||||
|
|
||||||
#include "GifSprite.h"
|
#include "GifSprite.h"
|
||||||
#include "../base/Logger.h"
|
#include "../base/Logger.h"
|
||||||
#include "../platform/modules.h"
|
#include "../renderer/ImageCache.h"
|
||||||
|
#include "../renderer/Renderer.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -29,53 +30,59 @@ namespace kiwano
|
||||||
, next_index_(0)
|
, next_index_(0)
|
||||||
, total_loop_count_(1)
|
, total_loop_count_(1)
|
||||||
, loop_count_(0)
|
, loop_count_(0)
|
||||||
|
, disposal_type_(DisposalType::Unknown)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GifSprite::GifSprite(String const& file_path)
|
||||||
|
{
|
||||||
|
Load(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
GifSprite::GifSprite(Resource const& res)
|
GifSprite::GifSprite(Resource const& res)
|
||||||
: GifSprite()
|
: GifSprite()
|
||||||
{
|
{
|
||||||
Load(res);
|
Load(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
GifSprite::GifSprite(GifImagePtr image)
|
GifSprite::GifSprite(GifImage image)
|
||||||
{
|
{
|
||||||
Load(image);
|
Load(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GifSprite::Load(Resource const& res)
|
bool GifSprite::Load(String const& file_path)
|
||||||
{
|
|
||||||
GifImagePtr image = new (std::nothrow) GifImage;
|
|
||||||
if (image->Load(res))
|
|
||||||
{
|
{
|
||||||
|
GifImage image = ImageCache::GetInstance()->AddOrGetGifImage(file_path);
|
||||||
return Load(image);
|
return Load(image);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
bool GifSprite::Load(Resource const& res)
|
||||||
|
{
|
||||||
|
GifImage image = ImageCache::GetInstance()->AddOrGetGifImage(res);
|
||||||
|
return Load(image);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GifSprite::Load(GifImagePtr image)
|
bool GifSprite::Load(GifImage image)
|
||||||
{
|
{
|
||||||
if (image && image_ != image)
|
if (image.IsValid())
|
||||||
{
|
{
|
||||||
image_ = image;
|
image_ = image;
|
||||||
|
|
||||||
next_index_ = 0;
|
next_index_ = 0;
|
||||||
loop_count_ = 0;
|
loop_count_ = 0;
|
||||||
|
disposal_type_ = DisposalType::None;
|
||||||
|
|
||||||
SetSize(
|
SetSize(
|
||||||
static_cast<float>(image_->GetWidthInPixels()),
|
static_cast<float>(image_.GetWidthInPixels()),
|
||||||
static_cast<float>(image_->GetHeightInPixels())
|
static_cast<float>(image_.GetHeightInPixels())
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!frame_rt_)
|
if (!frame_rt_.IsValid())
|
||||||
{
|
{
|
||||||
auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
|
Renderer::GetInstance()->CreateImageRenderTarget(frame_rt_);
|
||||||
ThrowIfFailed(
|
|
||||||
ctx->CreateCompatibleRenderTarget(&frame_rt_)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image_->GetFramesCount() > 0)
|
if (image_.GetFramesCount() > 0)
|
||||||
{
|
{
|
||||||
ComposeNextFrame();
|
ComposeNextFrame();
|
||||||
}
|
}
|
||||||
|
|
@ -84,11 +91,21 @@ namespace kiwano
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GifSprite::OnRender(Renderer* renderer)
|
||||||
|
{
|
||||||
|
if (frame_.IsValid() && renderer->CheckVisibility(size_, transform_matrix_))
|
||||||
|
{
|
||||||
|
PrepareRender(renderer);
|
||||||
|
|
||||||
|
renderer->DrawImage(frame_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GifSprite::Update(Duration dt)
|
void GifSprite::Update(Duration dt)
|
||||||
{
|
{
|
||||||
Actor::Update(dt);
|
Actor::Update(dt);
|
||||||
|
|
||||||
if (image_ && animating_)
|
if (image_.IsValid() && animating_)
|
||||||
{
|
{
|
||||||
frame_elapsed_ += dt;
|
frame_elapsed_ += dt;
|
||||||
if (frame_delay_ <= frame_elapsed_)
|
if (frame_delay_ <= frame_elapsed_)
|
||||||
|
|
@ -100,84 +117,94 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifSprite::OnRender(Renderer* renderer)
|
|
||||||
{
|
|
||||||
if (frame_to_render_ && renderer->CheckVisibility(size_, transform_matrix_))
|
|
||||||
{
|
|
||||||
PrepareRender(renderer);
|
|
||||||
|
|
||||||
Rect bounds = GetBounds();
|
|
||||||
renderer->DrawBitmap(frame_to_render_, bounds, bounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GifSprite::RestartAnimation()
|
void GifSprite::RestartAnimation()
|
||||||
{
|
{
|
||||||
animating_ = true;
|
animating_ = true;
|
||||||
next_index_ = 0;
|
next_index_ = 0;
|
||||||
loop_count_ = 0;
|
loop_count_ = 0;
|
||||||
image_->SetDisposalType(GifImage::DisposalType::None);
|
disposal_type_ = DisposalType::None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GifSprite::ComposeNextFrame()
|
void GifSprite::ComposeNextFrame()
|
||||||
{
|
{
|
||||||
if (frame_rt_)
|
if (frame_rt_.IsValid())
|
||||||
{
|
{
|
||||||
// 找到延迟大于 0 的帧 (0 延迟帧是不可见的中间帧)
|
|
||||||
HRESULT hr = E_FAIL;
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
hr = image_->DisposeCurrentFrame(frame_rt_);
|
DisposeCurrentFrame();
|
||||||
if (SUCCEEDED(hr))
|
OverlayNextFrame();
|
||||||
{
|
} while (frame_delay_.IsZero() && !IsLastFrame());
|
||||||
hr = OverlayNextFrame();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
animating_ = (!EndOfAnimation() && image_.GetFramesCount() > 1);
|
||||||
{
|
|
||||||
frame_delay_.SetMilliseconds(static_cast<long>(image_->GetFrameDelay()));
|
|
||||||
}
|
|
||||||
} while (SUCCEEDED(hr) && frame_delay_.IsZero() && !IsLastFrame());
|
|
||||||
|
|
||||||
animating_ = (SUCCEEDED(hr) && !EndOfAnimation() && image_->GetFramesCount() > 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT GifSprite::OverlayNextFrame()
|
void GifSprite::DisposeCurrentFrame()
|
||||||
{
|
{
|
||||||
HRESULT hr = image_->GetRawFrame(next_index_);
|
switch (disposal_type_)
|
||||||
|
{
|
||||||
|
case DisposalType::Unknown:
|
||||||
|
case DisposalType::None:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DisposalType::Background:
|
||||||
|
{
|
||||||
|
ClearCurrentFrameArea();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DisposalType::Previous:
|
||||||
|
{
|
||||||
|
RestoreSavedFrame();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ThrowIfFailed(E_FAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GifSprite::OverlayNextFrame()
|
||||||
|
{
|
||||||
|
Image raw_image;
|
||||||
|
|
||||||
|
HRESULT hr = image_.GetRawFrame(next_index_, raw_image, frame_rect_, frame_delay_, disposal_type_);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
if (image_->GetDisposalType() == GifImage::DisposalType::Previous)
|
if (disposal_type_ == DisposalType::Previous)
|
||||||
{
|
{
|
||||||
hr = image_->SaveComposedFrame(frame_rt_);
|
SaveComposedFrame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
frame_rt_->BeginDraw();
|
frame_rt_.BeginDraw();
|
||||||
|
|
||||||
if (next_index_ == 0)
|
if (next_index_ == 0)
|
||||||
{
|
{
|
||||||
// ÖØÐ»æÖƱ³¾°
|
// ÖØÐ»æÖƱ³¾°
|
||||||
frame_rt_->Clear(image_->GetBackgroundColor());
|
frame_rt_.Clear(image_.GetBackgroundColor());
|
||||||
loop_count_++;
|
loop_count_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame_rt_->DrawBitmap(image_->GetRawFrame().get(), image_->GetFramePosition());
|
frame_rt_.DrawImage(raw_image, nullptr, &frame_rect_);
|
||||||
hr = frame_rt_->EndDraw();
|
frame_rt_.EndDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
frame_to_render_ = nullptr;
|
Image frame_to_render;
|
||||||
hr = frame_rt_->GetBitmap(&frame_to_render_);
|
frame_rt_.GetOutput(frame_to_render);
|
||||||
}
|
|
||||||
|
hr = frame_to_render.IsValid() ? S_OK : E_FAIL;
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
next_index_ = (++next_index_) % image_->GetFramesCount();
|
frame_ = frame_to_render;
|
||||||
|
next_index_ = (++next_index_) % image_.GetFramesCount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsLastFrame() && loop_cb_)
|
if (IsLastFrame() && loop_cb_)
|
||||||
|
|
@ -189,7 +216,71 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
done_cb_();
|
done_cb_();
|
||||||
}
|
}
|
||||||
return hr;
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GifSprite::SaveComposedFrame()
|
||||||
|
{
|
||||||
|
Image frame_to_be_saved;
|
||||||
|
frame_rt_.GetOutput(frame_to_be_saved);
|
||||||
|
|
||||||
|
HRESULT hr = frame_to_be_saved.IsValid() ? S_OK : E_FAIL;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (!saved_frame_.IsValid())
|
||||||
|
{
|
||||||
|
auto size = frame_to_be_saved.GetSizeInPixels();
|
||||||
|
auto prop = D2D1::BitmapProperties(frame_to_be_saved.GetPixelFormat());
|
||||||
|
|
||||||
|
ComPtr<ID2D1Bitmap> saved_bitmap;
|
||||||
|
hr = frame_rt_.GetRenderTarget()->CreateBitmap(D2D1::SizeU(size.x, size.y), prop, &saved_bitmap);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
saved_frame_.SetBitmap(saved_bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
saved_frame_.CopyFrom(frame_to_be_saved);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GifSprite::RestoreSavedFrame()
|
||||||
|
{
|
||||||
|
HRESULT hr = saved_frame_.IsValid() ? S_OK : E_FAIL;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
Image frame_to_copy_to;
|
||||||
|
frame_rt_.GetOutput(frame_to_copy_to);
|
||||||
|
|
||||||
|
hr = frame_to_copy_to.IsValid() ? S_OK : E_FAIL;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
frame_to_copy_to.CopyFrom(saved_frame_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GifSprite::ClearCurrentFrameArea()
|
||||||
|
{
|
||||||
|
frame_rt_.BeginDraw();
|
||||||
|
|
||||||
|
frame_rt_.PushClipRect(frame_rect_);
|
||||||
|
frame_rt_.Clear(image_.GetBackgroundColor());
|
||||||
|
frame_rt_.PopClipRect();
|
||||||
|
|
||||||
|
return frame_rt_.EndDraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,26 +21,36 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "../base/Resource.h"
|
#include "../base/Resource.h"
|
||||||
#include "../renderer/Renderer.h"
|
#include "../renderer/RenderTarget.h"
|
||||||
#include "../renderer/GifImage.h"
|
#include "../renderer/GifImage.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
// GIF ¾«Áé
|
||||||
class KGE_API GifSprite
|
class KGE_API GifSprite
|
||||||
: public Actor
|
: public Actor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
using DisposalType = GifImage::DisposalType;
|
||||||
using LoopDoneCallback = Function<void(int)>;
|
using LoopDoneCallback = Function<void(int)>;
|
||||||
using DoneCallback = Function<void()>;
|
using DoneCallback = Function<void()>;
|
||||||
|
|
||||||
GifSprite();
|
GifSprite();
|
||||||
|
|
||||||
|
GifSprite(
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
GifSprite(
|
GifSprite(
|
||||||
Resource const& res
|
Resource const& res
|
||||||
);
|
);
|
||||||
|
|
||||||
GifSprite(
|
GifSprite(
|
||||||
GifImagePtr image
|
GifImage image
|
||||||
|
);
|
||||||
|
|
||||||
|
bool Load(
|
||||||
|
String const& file_path
|
||||||
);
|
);
|
||||||
|
|
||||||
bool Load(
|
bool Load(
|
||||||
|
|
@ -48,7 +58,7 @@ namespace kiwano
|
||||||
);
|
);
|
||||||
|
|
||||||
bool Load(
|
bool Load(
|
||||||
GifImagePtr image
|
GifImage image
|
||||||
);
|
);
|
||||||
|
|
||||||
// ÉèÖà GIF ¶¯»Ñ»·´ÎÊý
|
// ÉèÖà GIF ¶¯»Ñ»·´ÎÊý
|
||||||
|
|
@ -72,27 +82,36 @@ namespace kiwano
|
||||||
protected:
|
protected:
|
||||||
void Update(Duration dt) override;
|
void Update(Duration dt) override;
|
||||||
|
|
||||||
void ComposeNextFrame();
|
|
||||||
|
|
||||||
HRESULT OverlayNextFrame();
|
|
||||||
|
|
||||||
inline bool IsLastFrame() const { return (next_index_ == 0); }
|
inline bool IsLastFrame() const { return (next_index_ == 0); }
|
||||||
|
|
||||||
inline bool EndOfAnimation() const { return IsLastFrame() && loop_count_ == total_loop_count_ + 1; }
|
inline bool EndOfAnimation() const { return IsLastFrame() && loop_count_ == total_loop_count_ + 1; }
|
||||||
|
|
||||||
|
void ComposeNextFrame();
|
||||||
|
|
||||||
|
void DisposeCurrentFrame();
|
||||||
|
|
||||||
|
void OverlayNextFrame();
|
||||||
|
|
||||||
|
void SaveComposedFrame();
|
||||||
|
|
||||||
|
void RestoreSavedFrame();
|
||||||
|
|
||||||
|
void ClearCurrentFrameArea();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool animating_;
|
bool animating_;
|
||||||
int total_loop_count_;
|
int total_loop_count_;
|
||||||
int loop_count_;
|
int loop_count_;
|
||||||
unsigned int next_index_;
|
UINT next_index_;
|
||||||
Duration frame_delay_;
|
Duration frame_delay_;
|
||||||
Duration frame_elapsed_;
|
Duration frame_elapsed_;
|
||||||
|
DisposalType disposal_type_;
|
||||||
LoopDoneCallback loop_cb_;
|
LoopDoneCallback loop_cb_;
|
||||||
DoneCallback done_cb_;
|
DoneCallback done_cb_;
|
||||||
|
GifImage image_;
|
||||||
GifImagePtr image_;
|
Image frame_;
|
||||||
ComPtr<ID2D1Bitmap> frame_to_render_;
|
Rect frame_rect_;
|
||||||
ComPtr<ID2D1BitmapRenderTarget> frame_rt_;
|
Image saved_frame_;
|
||||||
|
ImageRenderTarget frame_rt_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace kiwano
|
||||||
: fill_color_(Color::White)
|
: fill_color_(Color::White)
|
||||||
, stroke_color_(Color(Color::Black, 0))
|
, stroke_color_(Color(Color::Black, 0))
|
||||||
, stroke_width_(1.f)
|
, stroke_width_(1.f)
|
||||||
, outline_join_(StrokeStyle::Miter)
|
, stroke_style_(StrokeStyle::Miter)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,9 +73,9 @@ namespace kiwano
|
||||||
stroke_width_ = std::max(width, 0.f);
|
stroke_width_ = std::max(width, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeActor::SetOutlineJoinStyle(StrokeStyle outline_join)
|
void ShapeActor::SetStrokeStyle(StrokeStyle stroke_style)
|
||||||
{
|
{
|
||||||
outline_join_ = outline_join;
|
stroke_style_ = stroke_style;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShapeActor::OnRender(Renderer* renderer)
|
void ShapeActor::OnRender(Renderer* renderer)
|
||||||
|
|
@ -93,7 +93,7 @@ namespace kiwano
|
||||||
geo_,
|
geo_,
|
||||||
stroke_color_,
|
stroke_color_,
|
||||||
stroke_width_,
|
stroke_width_,
|
||||||
outline_join_
|
stroke_style_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,8 @@ namespace kiwano
|
||||||
// ťńČĄĎßĚőżíśČ
|
// ťńČĄĎßĚőżíśČ
|
||||||
float GetStrokeWidth() const { return stroke_width_; }
|
float GetStrokeWidth() const { return stroke_width_; }
|
||||||
|
|
||||||
// ťńČĄĎßĚőĎཝŃůĘ˝
|
// »ñÈ¡ÏßÌõÑùʽ
|
||||||
StrokeStyle SetOutlineJoinStyle() const { return outline_join_; }
|
StrokeStyle SetStrokeStyle() const { return stroke_style_; }
|
||||||
|
|
||||||
// ťńČĄąß˝ç
|
// ťńČĄąß˝ç
|
||||||
Rect GetBounds() const override;
|
Rect GetBounds() const override;
|
||||||
|
|
@ -70,9 +70,9 @@ namespace kiwano
|
||||||
float width
|
float width
|
||||||
);
|
);
|
||||||
|
|
||||||
// ÉčÖĂĎßĚőĎཝŃůĘ˝
|
// ÉèÖÃÏßÌõÑùʽ
|
||||||
void SetOutlineJoinStyle(
|
void SetStrokeStyle(
|
||||||
StrokeStyle outline_join
|
StrokeStyle stroke_style
|
||||||
);
|
);
|
||||||
|
|
||||||
// ÉčÖĂĐÎ×´
|
// ÉčÖĂĐÎ×´
|
||||||
|
|
@ -87,7 +87,7 @@ namespace kiwano
|
||||||
Color fill_color_;
|
Color fill_color_;
|
||||||
Color stroke_color_;
|
Color stroke_color_;
|
||||||
float stroke_width_;
|
float stroke_width_;
|
||||||
StrokeStyle outline_join_;
|
StrokeStyle stroke_style_;
|
||||||
Geometry geo_;
|
Geometry geo_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,21 +24,29 @@
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
Sprite::Sprite()
|
Sprite::Sprite()
|
||||||
: frame_(nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sprite::Sprite(String const& file_path)
|
||||||
|
{
|
||||||
|
Load(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sprite::Sprite(String const& file_path, Rect const& crop_rect)
|
||||||
|
{
|
||||||
|
Load(file_path);
|
||||||
|
SetCropRect(crop_rect);
|
||||||
|
}
|
||||||
|
|
||||||
Sprite::Sprite(Resource const& res)
|
Sprite::Sprite(Resource const& res)
|
||||||
: frame_(nullptr)
|
|
||||||
{
|
{
|
||||||
Load(res);
|
Load(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite::Sprite(Resource const& res, const Rect& crop_rect)
|
Sprite::Sprite(Resource const& res, const Rect& crop_rect)
|
||||||
: frame_(nullptr)
|
|
||||||
{
|
{
|
||||||
Load(res);
|
Load(res);
|
||||||
Crop(crop_rect);
|
SetCropRect(crop_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite::Sprite(FramePtr frame)
|
Sprite::Sprite(FramePtr frame)
|
||||||
|
|
@ -51,6 +59,17 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Sprite::Load(String const& file_path)
|
||||||
|
{
|
||||||
|
FramePtr frame = new (std::nothrow) Frame;
|
||||||
|
if (frame->Load(file_path))
|
||||||
|
{
|
||||||
|
SetFrame(frame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool Sprite::Load(Resource const& res)
|
bool Sprite::Load(Resource const& res)
|
||||||
{
|
{
|
||||||
FramePtr frame = new (std::nothrow) Frame;
|
FramePtr frame = new (std::nothrow) Frame;
|
||||||
|
|
@ -62,11 +81,11 @@ namespace kiwano
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sprite::Crop(const Rect& crop_rect)
|
void Sprite::SetCropRect(const Rect& crop_rect)
|
||||||
{
|
{
|
||||||
if (frame_)
|
if (frame_)
|
||||||
{
|
{
|
||||||
frame_->Crop(crop_rect);
|
frame_->SetCropRect(crop_rect);
|
||||||
SetSize(frame_->GetWidth(), frame_->GetHeight());
|
SetSize(frame_->GetWidth(), frame_->GetHeight());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -89,7 +108,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
PrepareRender(renderer);
|
PrepareRender(renderer);
|
||||||
|
|
||||||
renderer->DrawBitmap(frame_->GetImage()->GetBitmap(), frame_->GetCropRect(), GetBounds());
|
renderer->DrawImage(frame_->GetImage(), &frame_->GetCropRect(), nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,19 @@ namespace kiwano
|
||||||
Sprite();
|
Sprite();
|
||||||
|
|
||||||
explicit Sprite(
|
explicit Sprite(
|
||||||
Resource const& res
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
|
Sprite(
|
||||||
|
String const& file_path,
|
||||||
|
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
|
||||||
);
|
);
|
||||||
|
|
||||||
explicit Sprite(
|
explicit Sprite(
|
||||||
|
Resource const& res
|
||||||
|
);
|
||||||
|
|
||||||
|
Sprite(
|
||||||
Resource const& res,
|
Resource const& res,
|
||||||
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
|
Rect const& crop_rect /* ²Ã¼ô¾ØÐÎ */
|
||||||
);
|
);
|
||||||
|
|
@ -46,13 +55,18 @@ namespace kiwano
|
||||||
|
|
||||||
virtual ~Sprite();
|
virtual ~Sprite();
|
||||||
|
|
||||||
|
// ¼ÓÔØÍ¼Ïñ
|
||||||
|
bool Load(
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
// ¼ÓÔØÍ¼Ïñ×ÊÔ´
|
// ¼ÓÔØÍ¼Ïñ×ÊÔ´
|
||||||
bool Load(
|
bool Load(
|
||||||
Resource const& res
|
Resource const& res
|
||||||
);
|
);
|
||||||
|
|
||||||
// ²Ã¼ô¾ØÐÎ
|
// ²Ã¼ô¾ØÐÎ
|
||||||
void Crop(
|
void SetCropRect(
|
||||||
const Rect& crop_rect
|
const Rect& crop_rect
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ namespace kiwano
|
||||||
: font_(text_default_font)
|
: font_(text_default_font)
|
||||||
, style_(text_default_style)
|
, style_(text_default_style)
|
||||||
, layout_dirty_(false)
|
, layout_dirty_(false)
|
||||||
|
, format_dirty_(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,96 +75,6 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
String const& Text::GetText() const
|
|
||||||
{
|
|
||||||
return text_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Font& Text::GetFont() const
|
|
||||||
{
|
|
||||||
return font_;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TextStyle& Text::GetStyle() const
|
|
||||||
{
|
|
||||||
return style_;
|
|
||||||
}
|
|
||||||
|
|
||||||
String const& Text::GetFontFamily() const
|
|
||||||
{
|
|
||||||
return font_.family;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Text::GetFontSize() const
|
|
||||||
{
|
|
||||||
return font_.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int Text::GetFontWeight() const
|
|
||||||
{
|
|
||||||
return font_.weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Color& Text::GetColor() const
|
|
||||||
{
|
|
||||||
return style_.color;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Color& Text::GetOutlineColor() const
|
|
||||||
{
|
|
||||||
return style_.outline_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Text::GetOutlineWidth() const
|
|
||||||
{
|
|
||||||
return style_.outline_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
StrokeStyle Text::GetOutlineStroke() const
|
|
||||||
{
|
|
||||||
return style_.outline_stroke;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Text::GetLineCount()
|
|
||||||
{
|
|
||||||
UpdateLayout();
|
|
||||||
if (text_layout_)
|
|
||||||
{
|
|
||||||
DWRITE_TEXT_METRICS metrics;
|
|
||||||
if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
|
|
||||||
{
|
|
||||||
return static_cast<int>(metrics.lineCount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Size const& Text::GetLayoutSize() const
|
|
||||||
{
|
|
||||||
UpdateLayout();
|
|
||||||
return layout_size_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Text::IsItalic() const
|
|
||||||
{
|
|
||||||
return font_.italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Text::HasStrikethrough() const
|
|
||||||
{
|
|
||||||
return style_.strikethrough;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Text::HasUnderline() const
|
|
||||||
{
|
|
||||||
return style_.underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Text::HasOutline() const
|
|
||||||
{
|
|
||||||
return style_.outline;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::SetText(String const& text)
|
void Text::SetText(String const& text)
|
||||||
{
|
{
|
||||||
text_ = text;
|
text_ = text;
|
||||||
|
|
@ -179,7 +90,7 @@ namespace kiwano
|
||||||
void Text::SetFont(const Font & font)
|
void Text::SetFont(const Font & font)
|
||||||
{
|
{
|
||||||
font_ = font;
|
font_ = font;
|
||||||
layout_dirty_ = true;
|
format_dirty_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::SetFontFamily(String const& family)
|
void Text::SetFontFamily(String const& family)
|
||||||
|
|
@ -187,7 +98,7 @@ namespace kiwano
|
||||||
if (font_.family != family)
|
if (font_.family != family)
|
||||||
{
|
{
|
||||||
font_.family = family;
|
font_.family = family;
|
||||||
layout_dirty_ = true;
|
format_dirty_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -196,7 +107,7 @@ namespace kiwano
|
||||||
if (font_.size != size)
|
if (font_.size != size)
|
||||||
{
|
{
|
||||||
font_.size = size;
|
font_.size = size;
|
||||||
layout_dirty_ = true;
|
format_dirty_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -205,7 +116,7 @@ namespace kiwano
|
||||||
if (font_.weight != weight)
|
if (font_.weight != weight)
|
||||||
{
|
{
|
||||||
font_.weight = weight;
|
font_.weight = weight;
|
||||||
layout_dirty_ = true;
|
format_dirty_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,16 +130,7 @@ namespace kiwano
|
||||||
if (font_.italic != val)
|
if (font_.italic != val)
|
||||||
{
|
{
|
||||||
font_.italic = val;
|
font_.italic = val;
|
||||||
layout_dirty_ = true;
|
format_dirty_ = true;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Text::SetWrapEnabled(bool wrap)
|
|
||||||
{
|
|
||||||
if (style_.wrap != wrap)
|
|
||||||
{
|
|
||||||
style_.wrap = wrap;
|
|
||||||
layout_dirty_ = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -236,12 +138,12 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
if (style_.wrap_width != wrap_width)
|
if (style_.wrap_width != wrap_width)
|
||||||
{
|
{
|
||||||
style_.wrap_width = std::max(wrap_width, 0.f);
|
style_.wrap_width = wrap_width;
|
||||||
layout_dirty_ = true;
|
layout_dirty_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::SetLineacingPtr(float line_spacing)
|
void Text::SetLineSpacing(float line_spacing)
|
||||||
{
|
{
|
||||||
if (style_.line_spacing != line_spacing)
|
if (style_.line_spacing != line_spacing)
|
||||||
{
|
{
|
||||||
|
|
@ -301,51 +203,26 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
UpdateLayout();
|
UpdateLayout();
|
||||||
|
|
||||||
if (text_layout_ && renderer->CheckVisibility(layout_size_, transform_matrix_))
|
if (text_layout_ && renderer->CheckVisibility(size_, transform_matrix_))
|
||||||
{
|
{
|
||||||
PrepareRender(renderer);
|
PrepareRender(renderer);
|
||||||
renderer->SetTextStyle(
|
|
||||||
GetDisplayedOpacity(),
|
|
||||||
style_.color,
|
|
||||||
style_.outline,
|
|
||||||
style_.outline_color,
|
|
||||||
style_.outline_width,
|
|
||||||
style_.outline_stroke
|
|
||||||
);
|
|
||||||
renderer->DrawTextLayout(text_layout_);
|
renderer->DrawTextLayout(text_layout_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Text::UpdateLayout() const
|
void Text::UpdateLayout()
|
||||||
{
|
{
|
||||||
if (!layout_dirty_)
|
if (format_dirty_)
|
||||||
return;
|
{
|
||||||
|
format_dirty_ = false;
|
||||||
|
text_layout_.Update(font_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (layout_dirty_)
|
||||||
|
{
|
||||||
layout_dirty_ = false;
|
layout_dirty_ = false;
|
||||||
text_format_ = nullptr;
|
text_layout_.Update(text_, style_);
|
||||||
text_layout_ = nullptr;
|
SetSize(text_layout_.GetLayoutSize());
|
||||||
|
}
|
||||||
if (text_.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto renderer = Renderer::GetInstance();
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
renderer->GetD2DDeviceResources()->CreateTextFormat(
|
|
||||||
text_format_,
|
|
||||||
font_,
|
|
||||||
style_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
|
||||||
renderer->GetD2DDeviceResources()->CreateTextLayout(
|
|
||||||
text_layout_,
|
|
||||||
layout_size_,
|
|
||||||
text_,
|
|
||||||
text_format_,
|
|
||||||
style_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Font.hpp"
|
#include "../renderer/TextLayout.h"
|
||||||
#include "TextStyle.hpp"
|
|
||||||
#include <dwrite.h>
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -56,52 +54,16 @@ namespace kiwano
|
||||||
virtual ~Text();
|
virtual ~Text();
|
||||||
|
|
||||||
// 获取文本
|
// 获取文本
|
||||||
String const& GetText() const;
|
inline String const& GetText() const { return text_; }
|
||||||
|
|
||||||
// 获取字体
|
// 获取字体
|
||||||
const Font& GetFont() const;
|
inline Font GetFont() const { return font_; }
|
||||||
|
|
||||||
// 获取文本样式
|
// 获取文本样式
|
||||||
const TextStyle& GetStyle() const;
|
inline TextStyle GetStyle() const { return style_; }
|
||||||
|
|
||||||
// 获取字体族
|
// 获取文本布局
|
||||||
String const& GetFontFamily() const;
|
inline TextLayout GetLayout() const { return text_layout_; }
|
||||||
|
|
||||||
// 获取当前字号
|
|
||||||
float GetFontSize() const;
|
|
||||||
|
|
||||||
// 获取当前字体粗细值
|
|
||||||
unsigned int GetFontWeight() const;
|
|
||||||
|
|
||||||
// 获取文字颜色
|
|
||||||
const Color& GetColor() const;
|
|
||||||
|
|
||||||
// 获取描边颜色
|
|
||||||
const Color& GetOutlineColor() const;
|
|
||||||
|
|
||||||
// 获取描边线宽
|
|
||||||
float GetOutlineWidth() const;
|
|
||||||
|
|
||||||
// 获取描边线相交样式
|
|
||||||
StrokeStyle GetOutlineStroke() const;
|
|
||||||
|
|
||||||
// 获取文本显示行数
|
|
||||||
int GetLineCount();
|
|
||||||
|
|
||||||
// 获取文字布局大小
|
|
||||||
Size const& GetLayoutSize() const;
|
|
||||||
|
|
||||||
// 是否是斜体
|
|
||||||
bool IsItalic() const;
|
|
||||||
|
|
||||||
// 是否显示删除线
|
|
||||||
bool HasStrikethrough() const;
|
|
||||||
|
|
||||||
// 是否显示下划线
|
|
||||||
bool HasUnderline() const;
|
|
||||||
|
|
||||||
// 是否显示描边
|
|
||||||
bool HasOutline() const;
|
|
||||||
|
|
||||||
// 设置文本
|
// 设置文本
|
||||||
void SetText(
|
void SetText(
|
||||||
|
|
@ -143,18 +105,13 @@ namespace kiwano
|
||||||
bool val
|
bool val
|
||||||
);
|
);
|
||||||
|
|
||||||
// 打开或关闭文本自动换行(默认为关闭)
|
|
||||||
void SetWrapEnabled(
|
|
||||||
bool wrap
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置文本自动换行的宽度(默认为 0)
|
// 设置文本自动换行的宽度(默认为 0)
|
||||||
void SetWrapWidth(
|
void SetWrapWidth(
|
||||||
float wrap_width
|
float wrap_width
|
||||||
);
|
);
|
||||||
|
|
||||||
// 设置行间距(默认为 0)
|
// 设置行间距(默认为 0)
|
||||||
void SetLineacingPtr(
|
void SetLineSpacing(
|
||||||
float line_spacing
|
float line_spacing
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -206,16 +163,14 @@ namespace kiwano
|
||||||
void OnRender(Renderer* renderer) override;
|
void OnRender(Renderer* renderer) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateLayout() const;
|
void UpdateLayout();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
bool format_dirty_;
|
||||||
|
bool layout_dirty_;
|
||||||
|
TextLayout text_layout_;
|
||||||
String text_;
|
String text_;
|
||||||
Font font_;
|
Font font_;
|
||||||
TextStyle style_;
|
TextStyle style_;
|
||||||
|
|
||||||
mutable bool layout_dirty_;
|
|
||||||
mutable Size layout_size_;
|
|
||||||
mutable ComPtr<IDWriteTextFormat> text_format_;
|
|
||||||
mutable ComPtr<IDWriteTextLayout> text_layout_;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ namespace kiwano
|
||||||
public:
|
public:
|
||||||
Color color; // 颜色
|
Color color; // 颜色
|
||||||
TextAlign alignment; // 对齐方式
|
TextAlign alignment; // 对齐方式
|
||||||
bool wrap; // 打开自动换行
|
|
||||||
float wrap_width; // 自动换行宽度
|
float wrap_width; // 自动换行宽度
|
||||||
float line_spacing; // 行间距
|
float line_spacing; // 行间距
|
||||||
bool underline; // 下划线
|
bool underline; // 下划线
|
||||||
|
|
@ -51,7 +50,6 @@ namespace kiwano
|
||||||
TextStyle()
|
TextStyle()
|
||||||
: color(Color::White)
|
: color(Color::White)
|
||||||
, alignment(TextAlign::Left)
|
, alignment(TextAlign::Left)
|
||||||
, wrap(false)
|
|
||||||
, wrap_width(0.f)
|
, wrap_width(0.f)
|
||||||
, line_spacing(0.f)
|
, line_spacing(0.f)
|
||||||
, underline(false)
|
, underline(false)
|
||||||
|
|
@ -65,7 +63,6 @@ namespace kiwano
|
||||||
TextStyle(
|
TextStyle(
|
||||||
Color color,
|
Color color,
|
||||||
TextAlign alignment = TextAlign::Left,
|
TextAlign alignment = TextAlign::Left,
|
||||||
bool wrap = false,
|
|
||||||
float wrap_width = 0.f,
|
float wrap_width = 0.f,
|
||||||
float line_spacing = 0.f,
|
float line_spacing = 0.f,
|
||||||
bool underline = false,
|
bool underline = false,
|
||||||
|
|
@ -77,7 +74,6 @@ namespace kiwano
|
||||||
)
|
)
|
||||||
: color(color)
|
: color(color)
|
||||||
, alignment(alignment)
|
, alignment(alignment)
|
||||||
, wrap(wrap)
|
|
||||||
, wrap_width(wrap_width)
|
, wrap_width(wrap_width)
|
||||||
, line_spacing(line_spacing)
|
, line_spacing(line_spacing)
|
||||||
, underline(underline)
|
, underline(underline)
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,8 @@ namespace kiwano
|
||||||
, window_size_()
|
, window_size_()
|
||||||
, out_scene_(nullptr)
|
, out_scene_(nullptr)
|
||||||
, in_scene_(nullptr)
|
, in_scene_(nullptr)
|
||||||
, out_layer_(nullptr)
|
, out_layer_()
|
||||||
, in_layer_(nullptr)
|
, in_layer_()
|
||||||
, out_layer_prop_()
|
|
||||||
, in_layer_prop_()
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,7 +72,8 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
|
|
||||||
window_size_ = Renderer::GetInstance()->GetOutputSize();
|
window_size_ = Renderer::GetInstance()->GetOutputSize();
|
||||||
out_layer_prop_ = in_layer_prop_ = LayerProperties{ Rect(Point(), window_size_),1.f };
|
out_layer_.SetAreaRect(Rect{ Point(), window_size_ });
|
||||||
|
in_layer_.SetAreaRect(Rect{ Point(), window_size_ });
|
||||||
}
|
}
|
||||||
|
|
||||||
void Transition::Update(Duration dt)
|
void Transition::Update(Duration dt)
|
||||||
|
|
@ -99,30 +98,26 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
if (out_scene_)
|
if (out_scene_)
|
||||||
{
|
{
|
||||||
renderer->PushClip(
|
renderer->SetTransform(out_scene_->GetTransformMatrix());
|
||||||
out_scene_->GetTransformMatrix(),
|
renderer->PushClipRect(Rect{ Point{}, window_size_ });
|
||||||
window_size_
|
renderer->PushLayer(out_layer_);
|
||||||
);
|
|
||||||
renderer->PushLayer(out_layer_, out_layer_prop_);
|
|
||||||
|
|
||||||
out_scene_->Render(renderer);
|
out_scene_->Render(renderer);
|
||||||
|
|
||||||
renderer->PopLayer();
|
renderer->PopLayer();
|
||||||
renderer->PopClip();
|
renderer->PopClipRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_scene_)
|
if (in_scene_)
|
||||||
{
|
{
|
||||||
renderer->PushClip(
|
renderer->SetTransform(in_scene_->GetTransformMatrix());
|
||||||
in_scene_->GetTransformMatrix(),
|
renderer->PushClipRect(Rect{ Point{}, window_size_ });
|
||||||
window_size_
|
renderer->PushLayer(in_layer_);
|
||||||
);
|
|
||||||
renderer->PushLayer(in_layer_, in_layer_prop_);
|
|
||||||
|
|
||||||
in_scene_->Render(renderer);
|
in_scene_->Render(renderer);
|
||||||
|
|
||||||
renderer->PopLayer();
|
renderer->PopLayer();
|
||||||
renderer->PopClip();
|
renderer->PopClipRect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,7 +140,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
Transition::Init(prev, next);
|
Transition::Init(prev, next);
|
||||||
|
|
||||||
in_layer_prop_.opacity = 0;
|
in_layer_.SetOpacity(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoxTransition::Update(Duration dt)
|
void BoxTransition::Update(Duration dt)
|
||||||
|
|
@ -154,22 +149,26 @@ namespace kiwano
|
||||||
|
|
||||||
if (process_ < .5f)
|
if (process_ < .5f)
|
||||||
{
|
{
|
||||||
out_layer_prop_.area = Rect(
|
out_layer_.SetAreaRect(
|
||||||
|
Rect(
|
||||||
window_size_.x * process_,
|
window_size_.x * process_,
|
||||||
window_size_.y * process_,
|
window_size_.y * process_,
|
||||||
window_size_.x * (1 - process_ * 2),
|
window_size_.x * (1 - process_ * 2),
|
||||||
window_size_.y * (1 - process_ * 2)
|
window_size_.y * (1 - process_ * 2)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out_layer_prop_.opacity = 0;
|
out_layer_.SetOpacity(0.f);
|
||||||
in_layer_prop_.opacity = 1;
|
in_layer_.SetOpacity(1.f);
|
||||||
in_layer_prop_.area = Rect(
|
in_layer_.SetAreaRect(
|
||||||
|
Rect(
|
||||||
window_size_.x * (1 - process_),
|
window_size_.x * (1 - process_),
|
||||||
window_size_.y * (1 - process_),
|
window_size_.y * (1 - process_),
|
||||||
window_size_.x * (2 * process_ - 1),
|
window_size_.x * (2 * process_ - 1),
|
||||||
window_size_.y * (2 * process_ - 1)
|
window_size_.y * (2 * process_ - 1)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -187,16 +186,16 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
Transition::Init(prev, next);
|
Transition::Init(prev, next);
|
||||||
|
|
||||||
out_layer_prop_.opacity = 1;
|
out_layer_.SetOpacity(1.f);
|
||||||
in_layer_prop_.opacity = 0;
|
in_layer_.SetOpacity(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmergeTransition::Update(Duration dt)
|
void EmergeTransition::Update(Duration dt)
|
||||||
{
|
{
|
||||||
Transition::Update(dt);
|
Transition::Update(dt);
|
||||||
|
|
||||||
out_layer_prop_.opacity = 1 - process_;
|
out_layer_.SetOpacity(1 - process_);
|
||||||
in_layer_prop_.opacity = process_;
|
in_layer_.SetOpacity(process_);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------
|
//-------------------------------------------------------
|
||||||
|
|
@ -212,8 +211,8 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
Transition::Init(prev, next);
|
Transition::Init(prev, next);
|
||||||
|
|
||||||
out_layer_prop_.opacity = 1;
|
out_layer_.SetOpacity(1.f);
|
||||||
in_layer_prop_.opacity = 0;
|
in_layer_.SetOpacity(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FadeTransition::Update(Duration dt)
|
void FadeTransition::Update(Duration dt)
|
||||||
|
|
@ -222,13 +221,13 @@ namespace kiwano
|
||||||
|
|
||||||
if (process_ < 0.5)
|
if (process_ < 0.5)
|
||||||
{
|
{
|
||||||
out_layer_prop_.opacity = 1 - process_ * 2;
|
out_layer_.SetOpacity(1 - process_ * 2);
|
||||||
in_layer_prop_.opacity = 0;
|
in_layer_.SetOpacity(0.f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out_layer_prop_.opacity = 0;
|
out_layer_.SetOpacity(0.f);
|
||||||
in_layer_prop_.opacity = (process_ - 0.5f) * 2;
|
in_layer_.SetOpacity((process_ - 0.5f) * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,7 +339,7 @@ namespace kiwano
|
||||||
in_scene_->SetAnchor(0.5f, 0.5f);
|
in_scene_->SetAnchor(0.5f, 0.5f);
|
||||||
}
|
}
|
||||||
|
|
||||||
in_layer_prop_.opacity = 0;
|
in_layer_.SetOpacity(0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotationTransition::Update(Duration dt)
|
void RotationTransition::Update(Duration dt)
|
||||||
|
|
@ -361,8 +360,8 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
if (in_scene_)
|
if (in_scene_)
|
||||||
{
|
{
|
||||||
out_layer_prop_.opacity = 0;
|
out_layer_.SetOpacity(0.f);
|
||||||
in_layer_prop_.opacity = 1;
|
in_layer_.SetOpacity(1.f);
|
||||||
|
|
||||||
auto transform = in_scene_->GetTransform();
|
auto transform = in_scene_->GetTransform();
|
||||||
transform.scale = Point{ (process_ - .5f) * 2, (process_ - .5f) * 2 };
|
transform.scale = Point{ (process_ - .5f) * 2, (process_ - .5f) * 2 };
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "include-forwards.h"
|
#include "include-forwards.h"
|
||||||
#include <d2d1.h>
|
#include "../renderer/LayerArea.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -29,7 +29,7 @@ namespace kiwano
|
||||||
|
|
||||||
// 舞台过渡
|
// 舞台过渡
|
||||||
class KGE_API Transition
|
class KGE_API Transition
|
||||||
: public Object
|
: public ObjectBase
|
||||||
{
|
{
|
||||||
friend class Director;
|
friend class Director;
|
||||||
|
|
||||||
|
|
@ -64,10 +64,8 @@ namespace kiwano
|
||||||
Size window_size_;
|
Size window_size_;
|
||||||
StagePtr out_scene_;
|
StagePtr out_scene_;
|
||||||
StagePtr in_scene_;
|
StagePtr in_scene_;
|
||||||
ComPtr<ID2D1Layer> out_layer_;
|
LayerArea out_layer_;
|
||||||
ComPtr<ID2D1Layer> in_layer_;
|
LayerArea in_layer_;
|
||||||
LayerProperties out_layer_prop_;
|
|
||||||
LayerProperties in_layer_prop_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace kiwano
|
||||||
class ActionManager;
|
class ActionManager;
|
||||||
|
|
||||||
class KGE_API Action
|
class KGE_API Action
|
||||||
: public Object
|
: public ObjectBase
|
||||||
, protected intrusive_list_item<ActionPtr>
|
, protected intrusive_list_item<ActionPtr>
|
||||||
{
|
{
|
||||||
friend class ActionManager;
|
friend class ActionManager;
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ namespace kiwano
|
||||||
|
|
||||||
void ActionGroup::Init(ActorPtr target)
|
void ActionGroup::Init(ActorPtr target)
|
||||||
{
|
{
|
||||||
if (actions_.is_empty())
|
if (actions_.item_empty())
|
||||||
{
|
{
|
||||||
Done();
|
Done();
|
||||||
return;
|
return;
|
||||||
|
|
@ -135,7 +135,7 @@ namespace kiwano
|
||||||
ActionPtr ActionGroup::Reverse() const
|
ActionPtr ActionGroup::Reverse() const
|
||||||
{
|
{
|
||||||
auto group = new (std::nothrow) ActionGroup();
|
auto group = new (std::nothrow) ActionGroup();
|
||||||
if (group && !actions_.is_empty())
|
if (group && !actions_.item_empty())
|
||||||
{
|
{
|
||||||
for (auto action = actions_.last_item(); action; action = action->prev_item())
|
for (auto action = actions_.last_item(); action; action = action->prev_item())
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
void ActionManager::UpdateActions(ActorPtr target, Duration dt)
|
void ActionManager::UpdateActions(ActorPtr target, Duration dt)
|
||||||
{
|
{
|
||||||
if (actions_.is_empty() || !target)
|
if (actions_.item_empty() || !target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ActionPtr next;
|
ActionPtr next;
|
||||||
|
|
@ -55,7 +55,7 @@ namespace kiwano
|
||||||
|
|
||||||
ActionPtr ActionManager::GetAction(String const & name)
|
ActionPtr ActionManager::GetAction(String const & name)
|
||||||
{
|
{
|
||||||
if (actions_.is_empty())
|
if (actions_.item_empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
|
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
|
||||||
|
|
@ -66,7 +66,7 @@ namespace kiwano
|
||||||
|
|
||||||
void ActionManager::ResumeAllActions()
|
void ActionManager::ResumeAllActions()
|
||||||
{
|
{
|
||||||
if (actions_.is_empty())
|
if (actions_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
|
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
|
||||||
|
|
@ -77,7 +77,7 @@ namespace kiwano
|
||||||
|
|
||||||
void ActionManager::PauseAllActions()
|
void ActionManager::PauseAllActions()
|
||||||
{
|
{
|
||||||
if (actions_.is_empty())
|
if (actions_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
|
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
|
||||||
|
|
@ -88,7 +88,7 @@ namespace kiwano
|
||||||
|
|
||||||
void ActionManager::StopAllActions()
|
void ActionManager::StopAllActions()
|
||||||
{
|
{
|
||||||
if (actions_.is_empty())
|
if (actions_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
|
for (auto action = actions_.first_item().get(); action; action = action->next_item().get())
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,14 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Color.h"
|
|
||||||
#include "../core/core.h"
|
#include "../core/core.h"
|
||||||
#include "../base/time.h"
|
#include "../base/time.h"
|
||||||
#include "../base/RefCounter.hpp"
|
#include "../base/RefCounter.hpp"
|
||||||
#include "../base/SmartPtr.hpp"
|
#include "../base/SmartPtr.hpp"
|
||||||
#include "../base/ComPtr.hpp"
|
#include "../base/ObjectBase.h"
|
||||||
#include "../base/Object.h"
|
|
||||||
#include "../math/helper.h"
|
|
||||||
#include "../base/types.h"
|
#include "../base/types.h"
|
||||||
|
#include "../math/math.h"
|
||||||
|
#include "../renderer/Color.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Object.h"
|
#include "ObjectBase.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace kiwano
|
||||||
typedef Function<void()> AsyncTaskCallback;
|
typedef Function<void()> AsyncTaskCallback;
|
||||||
|
|
||||||
class AsyncTask
|
class AsyncTask
|
||||||
: public Object
|
: public ObjectBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AsyncTask();
|
AsyncTask();
|
||||||
|
|
|
||||||
|
|
@ -146,9 +146,11 @@ namespace kiwano
|
||||||
if (render_border_enabled_)
|
if (render_border_enabled_)
|
||||||
{
|
{
|
||||||
if (curr_scene_)
|
if (curr_scene_)
|
||||||
|
{
|
||||||
curr_scene_->RenderBorder();
|
curr_scene_->RenderBorder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Director::HandleEvent(Event& evt)
|
void Director::HandleEvent(Event& evt)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
void EventDispatcher::Dispatch(Event& evt)
|
void EventDispatcher::Dispatch(Event& evt)
|
||||||
{
|
{
|
||||||
if (listeners_.is_empty())
|
if (listeners_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
EventListenerPtr next;
|
EventListenerPtr next;
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../core/core.h"
|
#include "../core/core.h"
|
||||||
#include "../base/SmartPtr.hpp"
|
#include "../base/SmartPtr.hpp"
|
||||||
#include "Object.h"
|
#include "ObjectBase.h"
|
||||||
#include "Event.hpp"
|
#include "Event.hpp"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
|
|
@ -34,7 +34,7 @@ namespace kiwano
|
||||||
|
|
||||||
// 事件监听器
|
// 事件监听器
|
||||||
class KGE_API EventListener
|
class KGE_API EventListener
|
||||||
: public Object
|
: public ObjectBase
|
||||||
, protected intrusive_list_item<EventListenerPtr>
|
, protected intrusive_list_item<EventListenerPtr>
|
||||||
{
|
{
|
||||||
friend class EventDispatcher;
|
friend class EventDispatcher;
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../macros.h"
|
#include "../macros.h"
|
||||||
#include "../core/core.h"
|
#include "../core/core.h"
|
||||||
#include "../math/helper.h"
|
#include "../math/math.h"
|
||||||
#include "keys.hpp"
|
#include "keys.hpp"
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include "Object.h"
|
#include "ObjectBase.h"
|
||||||
#include "Logger.h"
|
#include "Logger.h"
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
|
||||||
|
|
@ -27,12 +27,12 @@ namespace kiwano
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
bool tracing_leaks = false;
|
bool tracing_leaks = false;
|
||||||
Vector<Object*> tracing_objects;
|
Vector<ObjectBase*> tracing_objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Object::last_object_id = 0;
|
unsigned int ObjectBase::last_object_id = 0;
|
||||||
|
|
||||||
Object::Object()
|
ObjectBase::ObjectBase()
|
||||||
: tracing_leak_(false)
|
: tracing_leak_(false)
|
||||||
, user_data_(nullptr)
|
, user_data_(nullptr)
|
||||||
, name_(nullptr)
|
, name_(nullptr)
|
||||||
|
|
@ -40,34 +40,34 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
#ifdef KGE_DEBUG
|
#ifdef KGE_DEBUG
|
||||||
|
|
||||||
Object::__AddObjectToTracingList(this);
|
ObjectBase::__AddObjectToTracingList(this);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::~Object()
|
ObjectBase::~ObjectBase()
|
||||||
{
|
{
|
||||||
if (name_)
|
if (name_)
|
||||||
delete name_;
|
delete name_;
|
||||||
|
|
||||||
#ifdef KGE_DEBUG
|
#ifdef KGE_DEBUG
|
||||||
|
|
||||||
Object::__RemoveObjectFromTracingList(this);
|
ObjectBase::__RemoveObjectFromTracingList(this);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void * Object::GetUserData() const
|
void * ObjectBase::GetUserData() const
|
||||||
{
|
{
|
||||||
return user_data_;
|
return user_data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::SetUserData(void * data)
|
void ObjectBase::SetUserData(void * data)
|
||||||
{
|
{
|
||||||
user_data_ = data;
|
user_data_ = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::SetName(String const & name)
|
void ObjectBase::SetName(String const & name)
|
||||||
{
|
{
|
||||||
if (IsName(name))
|
if (IsName(name))
|
||||||
return;
|
return;
|
||||||
|
|
@ -88,29 +88,29 @@ namespace kiwano
|
||||||
*name_ = name;
|
*name_ = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Object::DumpObject()
|
String ObjectBase::DumpObject()
|
||||||
{
|
{
|
||||||
String name = kiwano::string_to_wide(typeid(*this).name());
|
String name = kiwano::string_to_wide(typeid(*this).name());
|
||||||
return String::format(L"{ class=\"%s\" id=%d refcount=%d name=\"%s\" }",
|
return String::format(L"{ class=\"%s\" id=%d refcount=%d name=\"%s\" }",
|
||||||
name.c_str(), GetObjectID(), GetRefCount(), GetName().c_str());
|
name.c_str(), GetObjectID(), GetRefCount(), GetName().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Object::IsTracingLeaks()
|
bool ObjectBase::IsTracingLeaks()
|
||||||
{
|
{
|
||||||
return tracing_leaks;
|
return tracing_leaks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::StartTracingLeaks()
|
void ObjectBase::StartTracingLeaks()
|
||||||
{
|
{
|
||||||
tracing_leaks = true;
|
tracing_leaks = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::StopTracingLeaks()
|
void ObjectBase::StopTracingLeaks()
|
||||||
{
|
{
|
||||||
tracing_leaks = false;
|
tracing_leaks = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::DumpTracingObjects()
|
void ObjectBase::DumpTracingObjects()
|
||||||
{
|
{
|
||||||
KGE_LOG(L"-------------------------- All Objects --------------------------");
|
KGE_LOG(L"-------------------------- All Objects --------------------------");
|
||||||
for (const auto object : tracing_objects)
|
for (const auto object : tracing_objects)
|
||||||
|
|
@ -120,12 +120,12 @@ namespace kiwano
|
||||||
KGE_LOG(L"------------------------- Total size: %d -------------------------", tracing_objects.size());
|
KGE_LOG(L"------------------------- Total size: %d -------------------------", tracing_objects.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Object*>& kiwano::Object::__GetTracingObjects()
|
Vector<ObjectBase*>& kiwano::ObjectBase::__GetTracingObjects()
|
||||||
{
|
{
|
||||||
return tracing_objects;
|
return tracing_objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::__AddObjectToTracingList(Object * obj)
|
void ObjectBase::__AddObjectToTracingList(ObjectBase * obj)
|
||||||
{
|
{
|
||||||
#ifdef KGE_DEBUG
|
#ifdef KGE_DEBUG
|
||||||
|
|
||||||
|
|
@ -138,7 +138,7 @@ namespace kiwano
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::__RemoveObjectFromTracingList(Object * obj)
|
void ObjectBase::__RemoveObjectFromTracingList(ObjectBase * obj)
|
||||||
{
|
{
|
||||||
#ifdef KGE_DEBUG
|
#ifdef KGE_DEBUG
|
||||||
|
|
||||||
|
|
@ -26,15 +26,15 @@
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
KGE_DECLARE_SMART_PTR(Object);
|
KGE_DECLARE_SMART_PTR(ObjectBase);
|
||||||
|
|
||||||
class KGE_API Object
|
class KGE_API ObjectBase
|
||||||
: public RefCounter
|
: public RefCounter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Object();
|
ObjectBase();
|
||||||
|
|
||||||
virtual ~Object();
|
virtual ~ObjectBase();
|
||||||
|
|
||||||
void* GetUserData() const;
|
void* GetUserData() const;
|
||||||
|
|
||||||
|
|
@ -60,11 +60,11 @@ namespace kiwano
|
||||||
static void DumpTracingObjects();
|
static void DumpTracingObjects();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Vector<Object*>& __GetTracingObjects();
|
static Vector<ObjectBase*>& __GetTracingObjects();
|
||||||
|
|
||||||
static void __AddObjectToTracingList(Object*);
|
static void __AddObjectToTracingList(ObjectBase*);
|
||||||
|
|
||||||
static void __RemoveObjectFromTracingList(Object*);
|
static void __RemoveObjectFromTracingList(ObjectBase*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool tracing_leak_;
|
bool tracing_leak_;
|
||||||
|
|
@ -21,116 +21,63 @@
|
||||||
#include "Resource.h"
|
#include "Resource.h"
|
||||||
#include "../base/Logger.h"
|
#include "../base/Logger.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
Resource::Resource(LPCWSTR file_name)
|
Resource::Resource()
|
||||||
: type_(Type::File)
|
: id_(0)
|
||||||
, bin_name_(nullptr)
|
, type_(nullptr)
|
||||||
, bin_type_(nullptr)
|
|
||||||
{
|
{
|
||||||
if (file_name)
|
|
||||||
file_name_ = new (std::nothrow) String(file_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource::Resource(String const& file_name)
|
Resource::Resource(UINT id, LPCWSTR type)
|
||||||
: type_(Type::File)
|
: id_(id)
|
||||||
, bin_name_(nullptr)
|
, type_(type)
|
||||||
, bin_type_(nullptr)
|
|
||||||
{
|
|
||||||
if (!file_name.empty())
|
|
||||||
file_name_ = new (std::nothrow) String(file_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Resource::Resource(LPCWSTR name, LPCWSTR type)
|
|
||||||
: type_(Type::Binary)
|
|
||||||
, bin_name_(name)
|
|
||||||
, bin_type_(type)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource::Resource(Resource const & rhs)
|
Resource::Data Resource::GetData() const
|
||||||
{
|
{
|
||||||
operator=(rhs);
|
do
|
||||||
|
{
|
||||||
|
if (data_.buffer && data_.size)
|
||||||
|
{
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Resource::~Resource()
|
HRSRC res_info = FindResourceW(nullptr, MAKEINTRESOURCE(id_), type_);
|
||||||
{
|
|
||||||
if (IsFileType() && file_name_)
|
|
||||||
delete file_name_;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t Resource::GetHashCode() const
|
|
||||||
{
|
|
||||||
if (type_ == Type::File)
|
|
||||||
return GetFileName().hash();
|
|
||||||
return std::hash<LPCWSTR>{}(bin_name_);
|
|
||||||
}
|
|
||||||
|
|
||||||
Resource & Resource::operator=(Resource const & rhs)
|
|
||||||
{
|
|
||||||
if (&rhs != this)
|
|
||||||
{
|
|
||||||
if (IsFileType() && file_name_)
|
|
||||||
{
|
|
||||||
delete file_name_;
|
|
||||||
file_name_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
type_ = rhs.type_;
|
|
||||||
if (IsFileType())
|
|
||||||
{
|
|
||||||
if (rhs.file_name_)
|
|
||||||
{
|
|
||||||
file_name_ = new (std::nothrow) String(*rhs.file_name_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bin_name_ = rhs.bin_name_;
|
|
||||||
bin_type_ = rhs.bin_type_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Resource::Load(LPVOID& buffer, DWORD& buffer_size) const
|
|
||||||
{
|
|
||||||
if (type_ != Type::Binary)
|
|
||||||
{
|
|
||||||
KGE_ERROR_LOG(L"Only binary resource can be loaded");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
HGLOBAL res_data;
|
|
||||||
HRSRC res_info;
|
|
||||||
|
|
||||||
res_info = FindResourceW(nullptr, bin_name_, bin_type_);
|
|
||||||
if (res_info == nullptr)
|
if (res_info == nullptr)
|
||||||
{
|
{
|
||||||
KGE_ERROR_LOG(L"FindResource failed");
|
KGE_ERROR_LOG(L"FindResource failed");
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
res_data = LoadResource(nullptr, res_info);
|
HGLOBAL res_data = LoadResource(nullptr, res_info);
|
||||||
if (res_data == nullptr)
|
if (res_data == nullptr)
|
||||||
{
|
{
|
||||||
KGE_ERROR_LOG(L"LoadResource failed");
|
KGE_ERROR_LOG(L"LoadResource failed");
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_size = SizeofResource(nullptr, res_info);
|
DWORD size = SizeofResource(nullptr, res_info);
|
||||||
if (buffer_size == 0)
|
if (size == 0)
|
||||||
{
|
{
|
||||||
KGE_ERROR_LOG(L"SizeofResource failed");
|
KGE_ERROR_LOG(L"SizeofResource failed");
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = LockResource(res_data);
|
LPVOID buffer = LockResource(res_data);
|
||||||
if (buffer == nullptr)
|
if (buffer == nullptr)
|
||||||
{
|
{
|
||||||
KGE_ERROR_LOG(L"LockResource failed");
|
KGE_ERROR_LOG(L"LockResource failed");
|
||||||
return false;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
data_.buffer = static_cast<void*>(buffer);
|
||||||
|
data_.size = static_cast<UINT32>(size);
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
return data_;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,63 +26,43 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
// 资源
|
// 资源
|
||||||
//
|
//
|
||||||
// 资源可以是文件类型,也可以是保存在 exe 中的二进制资源
|
// 资源是保存在 exe 中的二进制数据
|
||||||
// 例如, 一份音频资源的类型为 L"WAVE", 名称标识符为 IDR_WAVE_1,
|
// 例如, 一份音频资源的类型为 L"WAVE", 名称标识符为 IDR_WAVE_1,
|
||||||
// 那么可以这样指定该资源: Resource res(MAKEINTRESOURCE(IDR_WAVE_1), L"WAVE");
|
// 那么可以这样指定该资源: Resource(IDR_WAVE_1, L"WAVE");
|
||||||
//
|
//
|
||||||
// 了解资源的更多信息: https://docs.microsoft.com/en-us/windows/desktop/menurc/resources
|
// 了解资源的更多信息: https://docs.microsoft.com/en-us/windows/desktop/menurc/resources
|
||||||
//
|
//
|
||||||
class KGE_API Resource
|
class KGE_API Resource
|
||||||
{
|
{
|
||||||
enum class Type { File, Binary };
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Resource(
|
// 二进制数据
|
||||||
LPCWSTR file_name /* 文件路径 */
|
struct Data
|
||||||
);
|
{
|
||||||
|
void* buffer;
|
||||||
|
UINT32 size;
|
||||||
|
|
||||||
|
inline Data() : buffer(nullptr), size(0) {}
|
||||||
|
|
||||||
|
inline operator bool() const { return buffer && size; }
|
||||||
|
};
|
||||||
|
|
||||||
|
Resource();
|
||||||
|
|
||||||
Resource(
|
Resource(
|
||||||
String const& file_name /* 文件路径 */
|
UINT id, /* 资源名称 */
|
||||||
);
|
|
||||||
|
|
||||||
Resource(
|
|
||||||
LPCWSTR name, /* 资源名称 */
|
|
||||||
LPCWSTR type /* 资源类型 */
|
LPCWSTR type /* 资源类型 */
|
||||||
);
|
);
|
||||||
|
|
||||||
Resource(
|
// 获取二进制数据
|
||||||
Resource const& rhs
|
Resource::Data GetData() const;
|
||||||
);
|
|
||||||
|
|
||||||
virtual ~Resource();
|
inline UINT GetId() const { return id_; }
|
||||||
|
|
||||||
inline bool IsFileType() const { return type_ == Type::File; }
|
inline LPCWSTR GetType() const { return type_; }
|
||||||
|
|
||||||
inline String GetFileName() const { if (file_name_) return *file_name_; return String(); }
|
|
||||||
|
|
||||||
bool Load(
|
|
||||||
LPVOID& buffer,
|
|
||||||
DWORD& buffer_size
|
|
||||||
) const;
|
|
||||||
|
|
||||||
size_t GetHashCode() const;
|
|
||||||
|
|
||||||
Resource& operator= (Resource const& rhs);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
UINT id_;
|
||||||
union
|
LPCWSTR type_;
|
||||||
{
|
mutable Resource::Data data_;
|
||||||
struct
|
|
||||||
{
|
|
||||||
String* file_name_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
LPCWSTR bin_name_;
|
|
||||||
LPCWSTR bin_type_;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Object.h"
|
#include "ObjectBase.h"
|
||||||
#include "time.h"
|
#include "time.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace kiwano
|
||||||
|
|
||||||
// 定时任务
|
// 定时任务
|
||||||
class KGE_API Timer
|
class KGE_API Timer
|
||||||
: public Object
|
: public ObjectBase
|
||||||
, protected intrusive_list_item<TimerPtr>
|
, protected intrusive_list_item<TimerPtr>
|
||||||
{
|
{
|
||||||
friend class TimerManager;
|
friend class TimerManager;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
void TimerManager::UpdateTimers(Duration dt)
|
void TimerManager::UpdateTimers(Duration dt)
|
||||||
{
|
{
|
||||||
if (timers_.is_empty())
|
if (timers_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TimerPtr next;
|
TimerPtr next;
|
||||||
|
|
@ -54,7 +54,7 @@ namespace kiwano
|
||||||
|
|
||||||
void TimerManager::StopTimers(String const& name)
|
void TimerManager::StopTimers(String const& name)
|
||||||
{
|
{
|
||||||
if (timers_.is_empty())
|
if (timers_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get())
|
for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get())
|
||||||
|
|
@ -68,7 +68,7 @@ namespace kiwano
|
||||||
|
|
||||||
void TimerManager::StartTimers(String const& name)
|
void TimerManager::StartTimers(String const& name)
|
||||||
{
|
{
|
||||||
if (timers_.is_empty())
|
if (timers_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get())
|
for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get())
|
||||||
|
|
@ -82,7 +82,7 @@ namespace kiwano
|
||||||
|
|
||||||
void TimerManager::RemoveTimers(String const& name)
|
void TimerManager::RemoveTimers(String const& name)
|
||||||
{
|
{
|
||||||
if (timers_.is_empty())
|
if (timers_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TimerPtr next;
|
TimerPtr next;
|
||||||
|
|
@ -98,7 +98,7 @@ namespace kiwano
|
||||||
|
|
||||||
void TimerManager::StopAllTimers()
|
void TimerManager::StopAllTimers()
|
||||||
{
|
{
|
||||||
if (timers_.is_empty())
|
if (timers_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get())
|
for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get())
|
||||||
|
|
@ -109,7 +109,7 @@ namespace kiwano
|
||||||
|
|
||||||
void TimerManager::StartAllTimers()
|
void TimerManager::StartAllTimers()
|
||||||
{
|
{
|
||||||
if (timers_.is_empty())
|
if (timers_.item_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get())
|
for (auto timer = timers_.first_item().get(); timer; timer = timer->next_item().get())
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Window::Create(String const& title, int width, int height, LPCWSTR icon, bool fullscreen, WNDPROC proc)
|
void Window::Init(String const& title, int width, int height, LPCWSTR icon, bool fullscreen, WNDPROC proc)
|
||||||
{
|
{
|
||||||
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
||||||
WNDCLASSEX wcex = { 0 };
|
WNDCLASSEX wcex = { 0 };
|
||||||
|
|
@ -157,16 +157,17 @@ namespace kiwano
|
||||||
if (handle_ == nullptr)
|
if (handle_ == nullptr)
|
||||||
{
|
{
|
||||||
::UnregisterClass(KGE_WND_CLASS_NAME, hinst);
|
::UnregisterClass(KGE_WND_CLASS_NAME, hinst);
|
||||||
return HRESULT_FROM_WIN32(GetLastError());
|
ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetClientRect(handle_, &rc);
|
GetClientRect(handle_, &rc);
|
||||||
width_ = rc.right - rc.left;
|
width_ = rc.right - rc.left;
|
||||||
height_ = rc.bottom - rc.top;
|
height_ = rc.bottom - rc.top;
|
||||||
|
|
||||||
SetMouseCursor(MouseCursor::Arrow);
|
SetMouseCursor(MouseCursor::Arrow);
|
||||||
return S_OK;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::Prepare()
|
void Window::Prepare()
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../macros.h"
|
#include "../macros.h"
|
||||||
#include "../core/core.h"
|
#include "../core/core.h"
|
||||||
#include "../math/helper.h"
|
#include "../math/math.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
|
|
@ -60,7 +60,7 @@ namespace kiwano
|
||||||
void SetMouseCursor(MouseCursor cursor);
|
void SetMouseCursor(MouseCursor cursor);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HRESULT Create(
|
void Init(
|
||||||
String const& title,
|
String const& title,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
// 画笔样式
|
// マ゚フ<EFBFBD><EFBFBD>ス
|
||||||
enum class StrokeStyle : int
|
enum class StrokeStyle : int
|
||||||
{
|
{
|
||||||
Miter = 0, /* 斜切 */
|
Miter = 0, /* 斜切 */
|
||||||
|
|
@ -61,11 +61,4 @@ namespace kiwano
|
||||||
GrayScale, // 灰度抗锯齿
|
GrayScale, // 灰度抗锯齿
|
||||||
None // 不启用抗锯齿
|
None // 不启用抗锯齿
|
||||||
};
|
};
|
||||||
|
|
||||||
// 图层属性
|
|
||||||
struct LayerProperties
|
|
||||||
{
|
|
||||||
Rect area;
|
|
||||||
float opacity;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,418 +0,0 @@
|
||||||
// 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 "Window.h"
|
|
||||||
#include "Logger.h"
|
|
||||||
|
|
||||||
#define WINDOW_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
|
|
||||||
#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP
|
|
||||||
#define KGE_WND_CLASS_NAME L"KiwanoAppWnd"
|
|
||||||
|
|
||||||
namespace kiwano
|
|
||||||
{
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
MONITORINFOEX GetMoniterInfoEx(HWND hwnd);
|
|
||||||
|
|
||||||
void AdjustWindow(UINT width, UINT height, DWORD style, UINT* win_width, UINT* win_height);
|
|
||||||
|
|
||||||
void ChangeFullScreenResolution(int width, int height, WCHAR* device_name);
|
|
||||||
|
|
||||||
void RestoreResolution(WCHAR* device_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::Window()
|
|
||||||
: handle_(nullptr)
|
|
||||||
, width_(0)
|
|
||||||
, height_(0)
|
|
||||||
, device_name_(nullptr)
|
|
||||||
, is_fullscreen_(false)
|
|
||||||
, mouse_cursor_(MouseCursor(-1))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Window::~Window()
|
|
||||||
{
|
|
||||||
if (is_fullscreen_)
|
|
||||||
RestoreResolution(device_name_);
|
|
||||||
|
|
||||||
if (device_name_)
|
|
||||||
{
|
|
||||||
delete[] device_name_;
|
|
||||||
device_name_ = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle_)
|
|
||||||
{
|
|
||||||
::DestroyWindow(handle_);
|
|
||||||
handle_ = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT Window::Create(String const& title, int width, int height, LPCWSTR icon, bool fullscreen, WNDPROC proc)
|
|
||||||
{
|
|
||||||
HINSTANCE hinst = GetModuleHandleW(nullptr);
|
|
||||||
WNDCLASSEX wcex = { 0 };
|
|
||||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
|
||||||
wcex.lpszClassName = KGE_WND_CLASS_NAME;
|
|
||||||
wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */;
|
|
||||||
wcex.lpfnWndProc = proc;
|
|
||||||
wcex.hIcon = nullptr;
|
|
||||||
wcex.cbClsExtra = 0;
|
|
||||||
wcex.cbWndExtra = sizeof(LONG_PTR);
|
|
||||||
wcex.hInstance = hinst;
|
|
||||||
wcex.hbrBackground = nullptr;
|
|
||||||
wcex.lpszMenuName = nullptr;
|
|
||||||
wcex.hCursor = nullptr;
|
|
||||||
|
|
||||||
if (icon)
|
|
||||||
{
|
|
||||||
wcex.hIcon = (HICON)::LoadImageW(hinst, icon, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
::RegisterClassExW(&wcex);
|
|
||||||
|
|
||||||
// Get the nearest monitor to this window
|
|
||||||
HMONITOR monitor = ::MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
|
||||||
|
|
||||||
// Get the target monitor info
|
|
||||||
MONITORINFOEX monitor_info_ex;
|
|
||||||
memset(&monitor_info_ex, 0, sizeof(MONITORINFOEX));
|
|
||||||
monitor_info_ex.cbSize = sizeof(MONITORINFOEX);
|
|
||||||
::GetMonitorInfoW(monitor, &monitor_info_ex);
|
|
||||||
|
|
||||||
// Save the device name
|
|
||||||
int len = lstrlenW(monitor_info_ex.szDevice);
|
|
||||||
device_name_ = new WCHAR[len + 1];
|
|
||||||
lstrcpyW(device_name_, monitor_info_ex.szDevice);
|
|
||||||
|
|
||||||
int left = -1;
|
|
||||||
int top = -1;
|
|
||||||
|
|
||||||
is_fullscreen_ = fullscreen;
|
|
||||||
|
|
||||||
if (is_fullscreen_)
|
|
||||||
{
|
|
||||||
top = monitor_info_ex.rcMonitor.top;
|
|
||||||
left = monitor_info_ex.rcMonitor.left;
|
|
||||||
|
|
||||||
if (width > monitor_info_ex.rcWork.right - left)
|
|
||||||
width = monitor_info_ex.rcWork.right - left;
|
|
||||||
|
|
||||||
if (height > monitor_info_ex.rcWork.bottom - top)
|
|
||||||
height = monitor_info_ex.rcWork.bottom - top;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UINT screenw = monitor_info_ex.rcWork.right - monitor_info_ex.rcWork.left;
|
|
||||||
UINT screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top;
|
|
||||||
|
|
||||||
UINT win_width, win_height;
|
|
||||||
AdjustWindow(
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
GetWindowStyle(),
|
|
||||||
&win_width,
|
|
||||||
&win_height
|
|
||||||
);
|
|
||||||
|
|
||||||
left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2;
|
|
||||||
top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2;
|
|
||||||
width = win_width;
|
|
||||||
height = win_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_ = ::CreateWindowExW(
|
|
||||||
is_fullscreen_ ? WS_EX_TOPMOST : 0,
|
|
||||||
KGE_WND_CLASS_NAME,
|
|
||||||
title.c_str(),
|
|
||||||
GetWindowStyle(),
|
|
||||||
left,
|
|
||||||
top,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
nullptr,
|
|
||||||
nullptr,
|
|
||||||
hinst,
|
|
||||||
nullptr
|
|
||||||
);
|
|
||||||
|
|
||||||
if (handle_ == nullptr)
|
|
||||||
{
|
|
||||||
::UnregisterClass(KGE_WND_CLASS_NAME, hinst);
|
|
||||||
return HRESULT_FROM_WIN32(GetLastError());
|
|
||||||
}
|
|
||||||
|
|
||||||
RECT rc;
|
|
||||||
GetClientRect(handle_, &rc);
|
|
||||||
width_ = rc.right - rc.left;
|
|
||||||
height_ = rc.bottom - rc.top;
|
|
||||||
|
|
||||||
SetMouseCursor(MouseCursor::Arrow);
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::Prepare()
|
|
||||||
{
|
|
||||||
::ShowWindow(handle_, SW_SHOWNORMAL);
|
|
||||||
::UpdateWindow(handle_);
|
|
||||||
|
|
||||||
if (is_fullscreen_)
|
|
||||||
{
|
|
||||||
ChangeFullScreenResolution(width_, height_, device_name_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String Window::GetTitle() const
|
|
||||||
{
|
|
||||||
if (handle_)
|
|
||||||
{
|
|
||||||
wchar_t title[256];
|
|
||||||
::GetWindowTextW(handle_, title, 256);
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
return String();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetTitle(String const& title)
|
|
||||||
{
|
|
||||||
if (handle_)
|
|
||||||
::SetWindowTextW(handle_, title.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Size Window::GetSize() const
|
|
||||||
{
|
|
||||||
return Size{
|
|
||||||
static_cast<float>(width_),
|
|
||||||
static_cast<float>(height_)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
float Window::GetWidth() const
|
|
||||||
{
|
|
||||||
return static_cast<float>(width_);
|
|
||||||
}
|
|
||||||
|
|
||||||
float Window::GetHeight() const
|
|
||||||
{
|
|
||||||
return static_cast<float>(height_);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetIcon(LPCWSTR icon_resource)
|
|
||||||
{
|
|
||||||
if (handle_)
|
|
||||||
{
|
|
||||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
|
||||||
HICON icon = (HICON)::LoadImage(
|
|
||||||
hinstance,
|
|
||||||
icon_resource,
|
|
||||||
IMAGE_ICON,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
|
||||||
);
|
|
||||||
|
|
||||||
::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
|
||||||
::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::Resize(int width, int height)
|
|
||||||
{
|
|
||||||
if (handle_ && !is_fullscreen_)
|
|
||||||
{
|
|
||||||
RECT rc = { 0, 0, int(width), int(height) };
|
|
||||||
::AdjustWindowRect(&rc, GetWindowStyle(), false);
|
|
||||||
|
|
||||||
width = rc.right - rc.left;
|
|
||||||
height = rc.bottom - rc.top;
|
|
||||||
::SetWindowPos(handle_, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetFullscreen(bool fullscreen, int width, int height)
|
|
||||||
{
|
|
||||||
if (is_fullscreen_ != fullscreen || width != width_ || height != height_)
|
|
||||||
{
|
|
||||||
is_fullscreen_ = fullscreen;
|
|
||||||
|
|
||||||
if (is_fullscreen_)
|
|
||||||
{
|
|
||||||
// move window to (0, 0) before display switch
|
|
||||||
::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width_, height_, SWP_NOACTIVATE);
|
|
||||||
|
|
||||||
ChangeFullScreenResolution(width, height, device_name_);
|
|
||||||
|
|
||||||
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
|
||||||
|
|
||||||
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
|
|
||||||
::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, SWP_NOACTIVATE);
|
|
||||||
|
|
||||||
width_ = width;
|
|
||||||
height_ = height;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RestoreResolution(device_name_);
|
|
||||||
|
|
||||||
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
|
||||||
|
|
||||||
UINT screenw = info.rcWork.right - info.rcWork.left;
|
|
||||||
UINT screenh = info.rcWork.bottom - info.rcWork.top;
|
|
||||||
|
|
||||||
UINT win_width, win_height;
|
|
||||||
AdjustWindow(width, height, GetWindowStyle(), &win_width, &win_height);
|
|
||||||
|
|
||||||
int left = screenw > win_width ? ((screenw - win_width) / 2) : 0;
|
|
||||||
int top = screenh > win_height ? ((screenh - win_height) / 2) : 0;
|
|
||||||
|
|
||||||
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
|
|
||||||
::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, win_width, win_height, SWP_DRAWFRAME | SWP_FRAMECHANGED);
|
|
||||||
|
|
||||||
UpdateWindowRect();
|
|
||||||
}
|
|
||||||
|
|
||||||
::ShowWindow(handle_, SW_SHOWNORMAL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetMouseCursor(MouseCursor cursor)
|
|
||||||
{
|
|
||||||
if (mouse_cursor_ != cursor)
|
|
||||||
{
|
|
||||||
mouse_cursor_ = cursor;
|
|
||||||
|
|
||||||
LPTSTR win32_cursor = IDC_ARROW;
|
|
||||||
switch (cursor)
|
|
||||||
{
|
|
||||||
case MouseCursor::Arrow: win32_cursor = IDC_ARROW; break;
|
|
||||||
case MouseCursor::TextInput: win32_cursor = IDC_IBEAM; break;
|
|
||||||
case MouseCursor::SizeAll: win32_cursor = IDC_SIZEALL; break;
|
|
||||||
case MouseCursor::SizeWE: win32_cursor = IDC_SIZEWE; break;
|
|
||||||
case MouseCursor::SizeNS: win32_cursor = IDC_SIZENS; break;
|
|
||||||
case MouseCursor::SizeNESW: win32_cursor = IDC_SIZENESW; break;
|
|
||||||
case MouseCursor::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
|
|
||||||
case MouseCursor::Hand: win32_cursor = IDC_HAND; break;
|
|
||||||
}
|
|
||||||
::SetCursor(::LoadCursorW(nullptr, win32_cursor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HWND Window::GetHandle() const
|
|
||||||
{
|
|
||||||
return handle_;
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD Window::GetWindowStyle() const
|
|
||||||
{
|
|
||||||
return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::UpdateWindowRect()
|
|
||||||
{
|
|
||||||
if (!handle_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RECT rc;
|
|
||||||
::GetClientRect(handle_, &rc);
|
|
||||||
|
|
||||||
width_ = rc.right - rc.left;
|
|
||||||
height_ = rc.bottom - rc.top;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::SetActive(bool actived)
|
|
||||||
{
|
|
||||||
if (!handle_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (is_fullscreen_)
|
|
||||||
{
|
|
||||||
if (actived)
|
|
||||||
{
|
|
||||||
ChangeFullScreenResolution(width_, height_, device_name_);
|
|
||||||
|
|
||||||
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
|
||||||
::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width_, height_, SWP_NOACTIVATE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RestoreResolution(device_name_);
|
|
||||||
|
|
||||||
::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
||||||
::ShowWindow(handle_, SW_MINIMIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
MONITORINFOEX GetMoniterInfoEx(HWND hwnd)
|
|
||||||
{
|
|
||||||
HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
|
||||||
MONITORINFOEX monitor_info;
|
|
||||||
|
|
||||||
memset(&monitor_info, 0, sizeof(MONITORINFOEX));
|
|
||||||
monitor_info.cbSize = sizeof(MONITORINFOEX);
|
|
||||||
::GetMonitorInfoW(monitor, &monitor_info);
|
|
||||||
|
|
||||||
return monitor_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdjustWindow(UINT width, UINT height, DWORD style, UINT* win_width, UINT* win_height)
|
|
||||||
{
|
|
||||||
RECT rc;
|
|
||||||
::SetRect(&rc, 0, 0, (int)width, (int)height);
|
|
||||||
::AdjustWindowRect(&rc, style, false);
|
|
||||||
|
|
||||||
*win_width = rc.right - rc.left;
|
|
||||||
*win_height = rc.bottom - rc.top;
|
|
||||||
|
|
||||||
MONITORINFOEX info = GetMoniterInfoEx(NULL);
|
|
||||||
|
|
||||||
UINT screenw = info.rcWork.right - info.rcWork.left;
|
|
||||||
UINT screenh = info.rcWork.bottom - info.rcWork.top;
|
|
||||||
|
|
||||||
if (*win_width > screenw)
|
|
||||||
*win_width = screenw;
|
|
||||||
if (*win_height > screenh)
|
|
||||||
*win_height = screenh;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChangeFullScreenResolution(int width, int height, WCHAR* device_name)
|
|
||||||
{
|
|
||||||
DEVMODE mode;
|
|
||||||
|
|
||||||
memset(&mode, 0, sizeof(mode));
|
|
||||||
mode.dmSize = sizeof(DEVMODE);
|
|
||||||
mode.dmBitsPerPel = ::GetDeviceCaps(::GetDC(0), BITSPIXEL);;
|
|
||||||
mode.dmPelsWidth = width;
|
|
||||||
mode.dmPelsHeight = height;
|
|
||||||
mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
||||||
|
|
||||||
if (::ChangeDisplaySettingsExW(device_name, &mode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
|
|
||||||
KGE_ERROR_LOG(L"ChangeDisplaySettings failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
void RestoreResolution(WCHAR* device_name)
|
|
||||||
{
|
|
||||||
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -82,7 +82,7 @@ public:
|
||||||
|
|
||||||
T& last_item() { return last_; }
|
T& last_item() { return last_; }
|
||||||
|
|
||||||
bool is_empty() const { return !first_; }
|
bool item_empty() const { return !first_; }
|
||||||
|
|
||||||
void push_back_item(T const& child)
|
void push_back_item(T const& child)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -56,23 +56,31 @@
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// base
|
// renderer
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "renderer/Renderer.h"
|
#include "renderer/Color.h"
|
||||||
|
#include "renderer/Font.h"
|
||||||
#include "renderer/Image.h"
|
#include "renderer/Image.h"
|
||||||
#include "renderer/GifImage.h"
|
#include "renderer/GifImage.h"
|
||||||
|
#include "renderer/TextLayout.h"
|
||||||
|
#include "renderer/Geometry.h"
|
||||||
|
#include "renderer/LayerArea.h"
|
||||||
|
#include "renderer/ImageCache.h"
|
||||||
|
#include "renderer/Renderer.h"
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// base
|
||||||
|
//
|
||||||
|
|
||||||
#include "base/time.h"
|
#include "base/time.h"
|
||||||
#include "base/Window.h"
|
#include "base/Window.h"
|
||||||
#include "base/input.h"
|
#include "base/input.h"
|
||||||
#include "base/Director.h"
|
#include "base/Director.h"
|
||||||
#include "base/Logger.h"
|
#include "base/Logger.h"
|
||||||
|
|
||||||
#include "base/SmartPtr.hpp"
|
#include "base/SmartPtr.hpp"
|
||||||
#include "base/ComPtr.hpp"
|
#include "base/ObjectBase.h"
|
||||||
|
|
||||||
#include "base/Object.h"
|
|
||||||
#include "base/Event.hpp"
|
#include "base/Event.hpp"
|
||||||
#include "base/EventListener.h"
|
#include "base/EventListener.h"
|
||||||
#include "base/EventDispatcher.h"
|
#include "base/EventDispatcher.h"
|
||||||
|
|
@ -81,8 +89,12 @@
|
||||||
#include "base/AsyncTask.h"
|
#include "base/AsyncTask.h"
|
||||||
#include "base/Resource.h"
|
#include "base/Resource.h"
|
||||||
|
|
||||||
#include "2d/Font.hpp"
|
|
||||||
#include "2d/Color.h"
|
//
|
||||||
|
// 2d
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
#include "2d/Transform.hpp"
|
#include "2d/Transform.hpp"
|
||||||
#include "2d/TextStyle.hpp"
|
#include "2d/TextStyle.hpp"
|
||||||
|
|
||||||
|
|
@ -110,9 +122,15 @@
|
||||||
#include "2d/ShapeActor.h"
|
#include "2d/ShapeActor.h"
|
||||||
#include "2d/DebugActor.h"
|
#include "2d/DebugActor.h"
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// platform
|
||||||
|
//
|
||||||
|
|
||||||
#include "platform/modules.h"
|
#include "platform/modules.h"
|
||||||
#include "platform/Application.h"
|
#include "platform/Application.h"
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// utils
|
// utils
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@
|
||||||
|
|
||||||
#ifndef KGE_ASSERT
|
#ifndef KGE_ASSERT
|
||||||
# ifdef KGE_DEBUG
|
# ifdef KGE_DEBUG
|
||||||
# define KGE_ASSERT(EXPR) assert(EXPR)
|
# define KGE_ASSERT(EXPR) do { (void)((!!(EXPR)) || (_wassert(_CRT_WIDE(#EXPR), _CRT_WIDE(__FUNCTION__), (unsigned)(__LINE__)), 0)); } while(0)
|
||||||
# else
|
# else
|
||||||
# define KGE_ASSERT __noop
|
# define KGE_ASSERT __noop
|
||||||
# endif
|
# endif
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ namespace kiwano
|
||||||
|
|
||||||
inline value_type GetBottom() const { return origin.y + size.y; }
|
inline value_type GetBottom() const { return origin.y + size.y; }
|
||||||
|
|
||||||
inline bool is_empty() const { return origin.IsOrigin() && size.IsOrigin(); }
|
inline bool IsEmpty() const { return origin.IsOrigin() && size.IsOrigin(); }
|
||||||
|
|
||||||
inline bool ContainsPoint(const Vec2T<value_type>& point) const
|
inline bool ContainsPoint(const Vec2T<value_type>& point) const
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "../base/Logger.h"
|
#include "../base/Logger.h"
|
||||||
#include "../base/input.h"
|
#include "../base/input.h"
|
||||||
#include "../base/Director.h"
|
#include "../base/Director.h"
|
||||||
|
#include "../renderer/ImageCache.h"
|
||||||
#include "../renderer/Renderer.h"
|
#include "../renderer/Renderer.h"
|
||||||
#include "../utils/ResourceCache.h"
|
#include "../utils/ResourceCache.h"
|
||||||
#include <windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
|
#include <windowsx.h> // GET_X_LPARAM, GET_Y_LPARAM
|
||||||
|
|
@ -79,15 +80,13 @@ namespace kiwano
|
||||||
|
|
||||||
void Application::Init(const Options& options)
|
void Application::Init(const Options& options)
|
||||||
{
|
{
|
||||||
ThrowIfFailed(
|
Window::GetInstance()->Init(
|
||||||
Window::GetInstance()->Create(
|
|
||||||
options.title,
|
options.title,
|
||||||
options.width,
|
options.width,
|
||||||
options.height,
|
options.height,
|
||||||
options.icon,
|
options.icon,
|
||||||
options.fullscreen,
|
options.fullscreen,
|
||||||
Application::WndProc
|
Application::WndProc
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Renderer::GetInstance()->SetClearColor(options.clear_color);
|
Renderer::GetInstance()->SetClearColor(options.clear_color);
|
||||||
|
|
@ -121,10 +120,9 @@ namespace kiwano
|
||||||
|
|
||||||
void Application::Run()
|
void Application::Run()
|
||||||
{
|
{
|
||||||
HWND hwnd = Window::GetInstance()->GetHandle();
|
KGE_ASSERT(inited_ && "Calling Application::Run before Application::Init");
|
||||||
|
|
||||||
if (!inited_)
|
HWND hwnd = Window::GetInstance()->GetHandle();
|
||||||
throw std::exception("Calling Application::Run before Application::Init");
|
|
||||||
|
|
||||||
if (hwnd)
|
if (hwnd)
|
||||||
{
|
{
|
||||||
|
|
@ -147,8 +145,10 @@ namespace kiwano
|
||||||
|
|
||||||
void Application::Destroy()
|
void Application::Destroy()
|
||||||
{
|
{
|
||||||
// Clear all stages
|
// Clear all resources
|
||||||
Director::GetInstance()->ClearStages();
|
Director::GetInstance()->ClearStages();
|
||||||
|
ResourceCache::GetInstance()->Clear();
|
||||||
|
ImageCache::GetInstance()->Clear();
|
||||||
|
|
||||||
if (inited_)
|
if (inited_)
|
||||||
{
|
{
|
||||||
|
|
@ -164,6 +164,7 @@ namespace kiwano
|
||||||
// Destroy all instances
|
// Destroy all instances
|
||||||
Director::DestroyInstance();
|
Director::DestroyInstance();
|
||||||
ResourceCache::DestroyInstance();
|
ResourceCache::DestroyInstance();
|
||||||
|
ImageCache::DestroyInstance();
|
||||||
Input::DestroyInstance();
|
Input::DestroyInstance();
|
||||||
Renderer::DestroyInstance();
|
Renderer::DestroyInstance();
|
||||||
Window::DestroyInstance();
|
Window::DestroyInstance();
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
#include "../base/time.h"
|
#include "../base/time.h"
|
||||||
#include "../base/Component.h"
|
#include "../base/Component.h"
|
||||||
#include "../base/Event.hpp"
|
#include "../base/Event.hpp"
|
||||||
#include "../2d/Color.h"
|
#include "../renderer/Color.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
// 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 "helper.hpp"
|
|
||||||
#include "../base/Resource.h"
|
|
||||||
#include "../2d/Font.hpp"
|
|
||||||
#include "../2d/TextStyle.hpp"
|
|
||||||
#include <dwrite.h>
|
|
||||||
#include <d2d1.h>
|
|
||||||
#include <d2d1_1.h>
|
|
||||||
|
|
||||||
namespace kiwano
|
|
||||||
{
|
|
||||||
MIDL_INTERFACE("5706684a-bf6d-4b03-b627-094758a33032")
|
|
||||||
KGE_API ID2DDeviceResources
|
|
||||||
: public IUnknown
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static HRESULT Create(ID2DDeviceResources** device_resources);
|
|
||||||
|
|
||||||
virtual HRESULT CreateBitmapFromFile(
|
|
||||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
|
||||||
_In_ String const& file_path
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual HRESULT CreateBitmapFromResource(
|
|
||||||
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
|
||||||
_In_ Resource const& res
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual HRESULT CreateTextFormat(
|
|
||||||
_Out_ ComPtr<IDWriteTextFormat>& text_format,
|
|
||||||
_In_ Font const& font,
|
|
||||||
_In_ TextStyle const& text_style
|
|
||||||
) const = 0;
|
|
||||||
|
|
||||||
virtual HRESULT CreateTextLayout(
|
|
||||||
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
|
|
||||||
_Out_ Size& layout_size,
|
|
||||||
_In_ String const& text,
|
|
||||||
_In_ ComPtr<IDWriteTextFormat> const& text_format,
|
|
||||||
_In_ TextStyle const& text_style
|
|
||||||
) const = 0;
|
|
||||||
|
|
||||||
virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0;
|
|
||||||
|
|
||||||
virtual HRESULT SetD2DDevice(
|
|
||||||
_In_ ComPtr<ID2D1Device> const& device
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual void SetTargetBitmap(
|
|
||||||
_In_ ComPtr<ID2D1Bitmap1> const& target
|
|
||||||
) = 0;
|
|
||||||
|
|
||||||
virtual void DiscardResources() = 0;
|
|
||||||
|
|
||||||
inline ID2D1Factory1* GetFactory() const { KGE_ASSERT(factory_); return factory_.get(); }
|
|
||||||
inline IWICImagingFactory* GetWICImagingFactory() const { KGE_ASSERT(imaging_factory_); return imaging_factory_.get(); }
|
|
||||||
inline IDWriteFactory* GetDWriteFactory() const { KGE_ASSERT(dwrite_factory_); return dwrite_factory_.get(); }
|
|
||||||
inline ID2D1Device* GetDevice() const { KGE_ASSERT(device_); return device_.get(); }
|
|
||||||
inline ID2D1DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.get(); }
|
|
||||||
inline ID2D1Bitmap1* GetTargetBitmap() const { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ComPtr<ID2D1Factory1> factory_;
|
|
||||||
ComPtr<ID2D1Device> device_;
|
|
||||||
ComPtr<ID2D1DeviceContext> device_context_;
|
|
||||||
ComPtr<ID2D1Bitmap1> target_bitmap_;
|
|
||||||
|
|
||||||
ComPtr<IWICImagingFactory> imaging_factory_;
|
|
||||||
ComPtr<IDWriteFactory> dwrite_factory_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
// 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 "Font.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
Font::Font(const String& family, float size, unsigned int weight, bool italic, FontCollection collection)
|
||||||
|
: family(family)
|
||||||
|
, size(size)
|
||||||
|
, weight(weight)
|
||||||
|
, italic(italic)
|
||||||
|
, collection(collection)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include "FontCollection.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -45,19 +45,15 @@ namespace kiwano
|
||||||
float size; // 字号
|
float size; // 字号
|
||||||
unsigned int weight; // 粗细值
|
unsigned int weight; // 粗细值
|
||||||
bool italic; // 是否斜体
|
bool italic; // 是否斜体
|
||||||
|
FontCollection collection; // ×ÖÌ弯
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Font(
|
Font(
|
||||||
const String& family = L"",
|
const String& family = L"",
|
||||||
float size = 18,
|
float size = 18,
|
||||||
unsigned int weight = FontWeight::Normal,
|
unsigned int weight = FontWeight::Normal,
|
||||||
bool italic = false
|
bool italic = false,
|
||||||
)
|
FontCollection collection = FontCollection()
|
||||||
: family(family)
|
);
|
||||||
, size(size)
|
|
||||||
, weight(weight)
|
|
||||||
, italic(italic)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
// 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 "FontCollection.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
FontCollection::FontCollection()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FontCollection::FontCollection(String const& file)
|
||||||
|
{
|
||||||
|
Load(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
FontCollection::FontCollection(Vector<String> const& files)
|
||||||
|
{
|
||||||
|
Load(files);
|
||||||
|
}
|
||||||
|
|
||||||
|
FontCollection::FontCollection(Resource const& res)
|
||||||
|
{
|
||||||
|
Load(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
FontCollection::FontCollection(Vector<Resource> const& res_arr)
|
||||||
|
{
|
||||||
|
Load(res_arr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontCollection::Load(String const& file)
|
||||||
|
{
|
||||||
|
Renderer::GetInstance()->CreateFontCollection(*this, { file });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontCollection::Load(Vector<String> const& files)
|
||||||
|
{
|
||||||
|
Renderer::GetInstance()->CreateFontCollection(*this, files);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontCollection::Load(Resource const& res)
|
||||||
|
{
|
||||||
|
Renderer::GetInstance()->CreateFontCollection(*this, { res });
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FontCollection::Load(Vector<Resource> const& res_arr)
|
||||||
|
{
|
||||||
|
Renderer::GetInstance()->CreateFontCollection(*this, res_arr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,77 +19,44 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../macros.h"
|
#include "../base/Resource.h"
|
||||||
#include "../core/core.h"
|
#include "win32/ComPtr.hpp"
|
||||||
#include "../math/helper.h"
|
#include <dwrite.h>
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
class KGE_API Window
|
// 字体集
|
||||||
: public Singleton<Window>
|
class FontCollection
|
||||||
{
|
{
|
||||||
KGE_DECLARE_SINGLETON(Window);
|
public:
|
||||||
|
FontCollection();
|
||||||
|
|
||||||
|
FontCollection(String const& file);
|
||||||
|
|
||||||
|
FontCollection(Vector<String> const& files);
|
||||||
|
|
||||||
|
FontCollection(Resource const& res);
|
||||||
|
|
||||||
|
FontCollection(Vector<Resource> const& res_arr);
|
||||||
|
|
||||||
|
// 从本地文件加载字体
|
||||||
|
bool Load(String const& file);
|
||||||
|
|
||||||
|
// 从多个本地文件加载字体
|
||||||
|
bool Load(Vector<String> const& files);
|
||||||
|
|
||||||
|
// 从资源加载字体
|
||||||
|
bool Load(Resource const& res);
|
||||||
|
|
||||||
|
// 从多个资源加载字体
|
||||||
|
bool Load(Vector<Resource> const& res_arr);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 获取标题
|
inline ComPtr<IDWriteFontCollection> GetFontCollection() const { return collection_; }
|
||||||
String GetTitle() const;
|
|
||||||
|
|
||||||
// 获取窗口大小
|
inline void SetFontCollection(ComPtr<IDWriteFontCollection> collection) { collection_ = collection; }
|
||||||
Size GetSize() const;
|
|
||||||
|
|
||||||
// 获取窗口宽度
|
|
||||||
float GetWidth() const;
|
|
||||||
|
|
||||||
// 获取窗口高度
|
|
||||||
float GetHeight() const;
|
|
||||||
|
|
||||||
// 设置标题
|
|
||||||
void SetTitle(String const& title);
|
|
||||||
|
|
||||||
// 设置窗口图标
|
|
||||||
void SetIcon(LPCWSTR icon_resource);
|
|
||||||
|
|
||||||
// 重设窗口大小
|
|
||||||
void Resize(int width, int height);
|
|
||||||
|
|
||||||
// 设置全屏模式
|
|
||||||
void SetFullscreen(bool fullscreen, int width, int height);
|
|
||||||
|
|
||||||
// 设置鼠标指针
|
|
||||||
void SetMouseCursor(MouseCursor cursor);
|
|
||||||
|
|
||||||
public:
|
|
||||||
HRESULT Create(
|
|
||||||
String const& title,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
LPCWSTR icon,
|
|
||||||
bool fullscreen,
|
|
||||||
WNDPROC proc
|
|
||||||
);
|
|
||||||
|
|
||||||
void Prepare();
|
|
||||||
|
|
||||||
HWND GetHandle() const;
|
|
||||||
|
|
||||||
DWORD GetWindowStyle() const;
|
|
||||||
|
|
||||||
void UpdateWindowRect();
|
|
||||||
|
|
||||||
void SetActive(bool actived);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Window();
|
ComPtr<IDWriteFontCollection> collection_;
|
||||||
|
|
||||||
~Window();
|
|
||||||
|
|
||||||
private:
|
|
||||||
HWND handle_;
|
|
||||||
bool is_fullscreen_;
|
|
||||||
int width_;
|
|
||||||
int height_;
|
|
||||||
WCHAR* device_name_;
|
|
||||||
MouseCursor mouse_cursor_;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -19,8 +19,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../base/SmartPtr.hpp"
|
#include "win32/D2DDeviceResources.h"
|
||||||
#include "D2DDeviceResources.h"
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,258 +19,65 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include "GifImage.h"
|
#include "GifImage.h"
|
||||||
|
#include "Renderer.h"
|
||||||
#include "../base/Logger.h"
|
#include "../base/Logger.h"
|
||||||
#include "../utils/FileUtil.h"
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
GifImage::GifImage()
|
GifImage::GifImage()
|
||||||
: frames_count_(0)
|
: frames_count_(0)
|
||||||
, disposal_type_(DisposalType::Unknown)
|
|
||||||
, width_in_pixels_(0)
|
, width_in_pixels_(0)
|
||||||
, height_in_pixels_(0)
|
, height_in_pixels_(0)
|
||||||
, frame_delay_(0)
|
|
||||||
, frame_position_{}
|
|
||||||
, bg_color_{}
|
, bg_color_{}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GifImage::GifImage(String const& file_path)
|
||||||
|
{
|
||||||
|
Load(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
GifImage::GifImage(Resource const& res)
|
GifImage::GifImage(Resource const& res)
|
||||||
: GifImage()
|
: GifImage()
|
||||||
{
|
{
|
||||||
Load(res);
|
Load(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GifImage::Load(Resource const& res)
|
bool GifImage::Load(String const& file_path)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
Renderer::GetInstance()->CreateGifImage(*this, file_path);
|
||||||
|
|
||||||
frames_count_ = 0;
|
if (IsValid())
|
||||||
disposal_type_ = DisposalType::None;
|
|
||||||
|
|
||||||
saved_frame_.reset();
|
|
||||||
decoder_.reset();
|
|
||||||
|
|
||||||
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
|
|
||||||
|
|
||||||
if (res.IsFileType())
|
|
||||||
{
|
{
|
||||||
#ifdef KGE_DEBUG
|
if (FAILED(GetGlobalMetadata()))
|
||||||
if (!FileUtil::ExistsFile(res.GetFileName().c_str()))
|
|
||||||
{
|
{
|
||||||
KGE_WARNING_LOG(L"Gif file '%s' not found!", res.GetFileName().c_str());
|
SetDecoder(nullptr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
return true;
|
||||||
|
|
||||||
hr = factory->CreateDecoderFromFilename(
|
|
||||||
res.GetFileName().c_str(),
|
|
||||||
nullptr,
|
|
||||||
GENERIC_READ,
|
|
||||||
WICDecodeMetadataCacheOnLoad,
|
|
||||||
&decoder_);
|
|
||||||
}
|
}
|
||||||
else
|
return false;
|
||||||
{
|
|
||||||
LPVOID buffer;
|
|
||||||
DWORD buffer_size;
|
|
||||||
HRESULT hr = res.Load(buffer, buffer_size) ? S_OK : E_FAIL;
|
|
||||||
|
|
||||||
ComPtr<IWICStream> stream;
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = factory->CreateStream(&stream);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
bool GifImage::Load(Resource const& res)
|
||||||
{
|
{
|
||||||
hr = stream->InitializeFromMemory(
|
Renderer::GetInstance()->CreateGifImage(*this, res);
|
||||||
static_cast<WICInProcPointer>(buffer),
|
|
||||||
buffer_size
|
if (IsValid())
|
||||||
);
|
{
|
||||||
|
if (FAILED(GetGlobalMetadata()))
|
||||||
|
{
|
||||||
|
SetDecoder(nullptr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
bool GifImage::IsValid() const
|
||||||
{
|
{
|
||||||
hr = factory->CreateDecoderFromStream(
|
return decoder_ != nullptr;
|
||||||
stream.get(),
|
|
||||||
nullptr,
|
|
||||||
WICDecodeMetadataCacheOnLoad,
|
|
||||||
&decoder_
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = GetGlobalMetadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCEEDED(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GifImage::GetRawFrame(UINT frame_index)
|
|
||||||
{
|
|
||||||
ComPtr<IWICFormatConverter> converter;
|
|
||||||
ComPtr<IWICBitmapFrameDecode> wic_frame;
|
|
||||||
ComPtr<IWICMetadataQueryReader> metadata_reader;
|
|
||||||
|
|
||||||
PROPVARIANT prop_val;
|
|
||||||
PropVariantInit(&prop_val);
|
|
||||||
|
|
||||||
// Retrieve the current frame
|
|
||||||
HRESULT hr = decoder_->GetFrame(frame_index, &wic_frame);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
// Format convert to 32bppPBGRA which D2D expects
|
|
||||||
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
|
|
||||||
hr = factory->CreateFormatConverter(&converter);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = converter->Initialize(
|
|
||||||
wic_frame.get(),
|
|
||||||
GUID_WICPixelFormat32bppPBGRA,
|
|
||||||
WICBitmapDitherTypeNone,
|
|
||||||
nullptr,
|
|
||||||
0.f,
|
|
||||||
WICBitmapPaletteTypeCustom);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
|
|
||||||
|
|
||||||
// Create a D2DBitmap from IWICBitmapSource
|
|
||||||
raw_frame_.reset();
|
|
||||||
hr = ctx->CreateBitmapFromWicBitmap(
|
|
||||||
converter.get(),
|
|
||||||
nullptr,
|
|
||||||
&raw_frame_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
// Get Metadata Query Reader from the frame
|
|
||||||
hr = wic_frame->GetMetadataQueryReader(&metadata_reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the Metadata for the current frame
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
frame_position_.left = static_cast<float>(prop_val.uiVal);
|
|
||||||
}
|
|
||||||
PropVariantClear(&prop_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
frame_position_.top = static_cast<float>(prop_val.uiVal);
|
|
||||||
}
|
|
||||||
PropVariantClear(&prop_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
frame_position_.right = static_cast<float>(prop_val.uiVal)
|
|
||||||
+ frame_position_.left;
|
|
||||||
}
|
|
||||||
PropVariantClear(&prop_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
frame_position_.bottom = static_cast<float>(prop_val.uiVal)
|
|
||||||
+ frame_position_.top;
|
|
||||||
}
|
|
||||||
PropVariantClear(&prop_val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
frame_delay_ = 0;
|
|
||||||
|
|
||||||
hr = metadata_reader->GetMetadataByName(
|
|
||||||
L"/grctlext/Delay",
|
|
||||||
&prop_val);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = UIntMult(prop_val.uiVal, 10, &frame_delay_);
|
|
||||||
}
|
|
||||||
PropVariantClear(&prop_val);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
frame_delay_ = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
// 插入一个强制延迟
|
|
||||||
if (frame_delay_ < 90)
|
|
||||||
{
|
|
||||||
frame_delay_ = 90;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = metadata_reader->GetMetadataByName(
|
|
||||||
L"/grctlext/Disposal",
|
|
||||||
&prop_val);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL;
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
disposal_type_ = DisposalType(prop_val.bVal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 获取 DisposalType 失败,可能图片是只有一帧的图片
|
|
||||||
disposal_type_ = DisposalType::Unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
::PropVariantClear(&prop_val);
|
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT GifImage::GetGlobalMetadata()
|
HRESULT GifImage::GetGlobalMetadata()
|
||||||
|
|
@ -284,7 +91,12 @@ namespace kiwano
|
||||||
ComPtr<IWICMetadataQueryReader> metadata_reader;
|
ComPtr<IWICMetadataQueryReader> metadata_reader;
|
||||||
|
|
||||||
// 获取帧数量
|
// 获取帧数量
|
||||||
HRESULT hr = decoder_->GetFrameCount(&frames_count_);
|
HRESULT hr = decoder_ ? S_OK : E_FAIL;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = decoder_->GetFrameCount(&frames_count_);
|
||||||
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -297,7 +109,7 @@ namespace kiwano
|
||||||
if (FAILED(GetBackgroundColor(metadata_reader.get())))
|
if (FAILED(GetBackgroundColor(metadata_reader.get())))
|
||||||
{
|
{
|
||||||
// 如果未能获得颜色,则默认为透明
|
// 如果未能获得颜色,则默认为透明
|
||||||
bg_color_ = D2D1::ColorF(0, 0.f);
|
bg_color_ = Color(0, 0.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,9 +117,7 @@ namespace kiwano
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// 获取宽度
|
// 获取宽度
|
||||||
hr = metadata_reader->GetMetadataByName(
|
hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Width", &prop_val);
|
||||||
L"/logscrdesc/Width",
|
|
||||||
&prop_val);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -323,9 +133,7 @@ namespace kiwano
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// 获取高度
|
// 获取高度
|
||||||
hr = metadata_reader->GetMetadataByName(
|
hr = metadata_reader->GetMetadataByName(L"/logscrdesc/Height", &prop_val);
|
||||||
L"/logscrdesc/Height",
|
|
||||||
&prop_val);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -341,9 +149,7 @@ namespace kiwano
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// 获得像素纵横比
|
// 获得像素纵横比
|
||||||
hr = metadata_reader->GetMetadataByName(
|
hr = metadata_reader->GetMetadataByName(L"/logscrdesc/PixelAspectRatio", &prop_val);
|
||||||
L"/logscrdesc/PixelAspectRatio",
|
|
||||||
&prop_val);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -383,101 +189,17 @@ namespace kiwano
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT GifImage::DisposeCurrentFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt)
|
HRESULT GifImage::GetBackgroundColor(ComPtr<IWICMetadataQueryReader> metadata_reader)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
switch (disposal_type_)
|
|
||||||
{
|
|
||||||
case DisposalType::Unknown:
|
|
||||||
case DisposalType::None:
|
|
||||||
break;
|
|
||||||
case DisposalType::Background:
|
|
||||||
// 用背景颜色清除当前原始帧覆盖的区域
|
|
||||||
hr = ClearCurrentFrameArea(frame_rt);
|
|
||||||
break;
|
|
||||||
case DisposalType::Previous:
|
|
||||||
// 恢复先前构图的帧
|
|
||||||
hr = RestoreSavedFrame(frame_rt);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
hr = E_FAIL;
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GifImage::SaveComposedFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
ComPtr<ID2D1Bitmap> frame_to_be_saved;
|
|
||||||
|
|
||||||
hr = frame_rt->GetBitmap(&frame_to_be_saved);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
if (saved_frame_ == nullptr)
|
|
||||||
{
|
|
||||||
auto size = frame_to_be_saved->GetPixelSize();
|
|
||||||
auto prop = D2D1::BitmapProperties(frame_to_be_saved->GetPixelFormat());
|
|
||||||
|
|
||||||
hr = frame_rt->CreateBitmap(size, prop, &saved_frame_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = saved_frame_->CopyFromBitmap(nullptr, frame_to_be_saved.get(), nullptr);
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GifImage::RestoreSavedFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
|
|
||||||
ComPtr<ID2D1Bitmap> frame_to_copy_to;
|
|
||||||
|
|
||||||
hr = saved_frame_ ? S_OK : E_FAIL;
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = frame_rt->GetBitmap(&frame_to_copy_to);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = frame_to_copy_to->CopyFromBitmap(nullptr, saved_frame_.get(), nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GifImage::ClearCurrentFrameArea(ComPtr<ID2D1BitmapRenderTarget> frame_rt)
|
|
||||||
{
|
|
||||||
frame_rt->BeginDraw();
|
|
||||||
|
|
||||||
frame_rt->PushAxisAlignedClip(&frame_position_, D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
|
|
||||||
frame_rt->Clear(bg_color_);
|
|
||||||
frame_rt->PopAxisAlignedClip();
|
|
||||||
|
|
||||||
return frame_rt->EndDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT GifImage::GetBackgroundColor(IWICMetadataQueryReader* metadata_reader)
|
|
||||||
{
|
|
||||||
DWORD bgcolor = 0;
|
|
||||||
BYTE bg_index = 0;
|
BYTE bg_index = 0;
|
||||||
WICColor bgcolors[256];
|
WICColor bgcolors[256];
|
||||||
UINT colors_copied = 0;
|
UINT colors_copied = 0;
|
||||||
|
ComPtr<IWICPalette> wic_palette;
|
||||||
|
|
||||||
PROPVARIANT prop_val;
|
PROPVARIANT prop_val;
|
||||||
PropVariantInit(&prop_val);
|
PropVariantInit(&prop_val);
|
||||||
|
|
||||||
ComPtr<IWICPalette> wic_palette;
|
HRESULT hr = metadata_reader->GetMetadataByName(L"/logscrdesc/GlobalColorTableFlag", &prop_val);
|
||||||
|
|
||||||
HRESULT hr = metadata_reader->GetMetadataByName(
|
|
||||||
L"/logscrdesc/GlobalColorTableFlag",
|
|
||||||
&prop_val);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -487,9 +209,7 @@ namespace kiwano
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = metadata_reader->GetMetadataByName(
|
hr = metadata_reader->GetMetadataByName(L"/logscrdesc/BackgroundColorIndex", &prop_val);
|
||||||
L"/logscrdesc/BackgroundColorIndex",
|
|
||||||
&prop_val);
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -523,19 +243,175 @@ namespace kiwano
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// 检查下标
|
|
||||||
hr = (bg_index >= colors_copied) ? E_FAIL : S_OK;
|
hr = (bg_index >= colors_copied) ? E_FAIL : S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
bgcolor = bgcolors[bg_index];
|
|
||||||
|
|
||||||
// 转换为 ARGB 格式
|
// 转换为 ARGB 格式
|
||||||
float alpha = (bgcolor >> 24) / 255.f;
|
float alpha = (bgcolors[bg_index] >> 24) / 255.f;
|
||||||
bg_color_ = D2D1::ColorF(bgcolor, alpha);
|
bg_color_ = Color(bgcolors[bg_index], alpha);
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT GifImage::GetRawFrame(UINT frame_index, Image& raw_frame, Rect& frame_rect, Duration& delay, DisposalType& disposal_type)
|
||||||
|
{
|
||||||
|
ComPtr<IWICFormatConverter> converter;
|
||||||
|
ComPtr<IWICBitmapFrameDecode> wic_frame;
|
||||||
|
ComPtr<IWICMetadataQueryReader> metadata_reader;
|
||||||
|
|
||||||
|
PROPVARIANT prop_val;
|
||||||
|
PropVariantInit(&prop_val);
|
||||||
|
|
||||||
|
// Retrieve the current frame
|
||||||
|
HRESULT hr = decoder_->GetFrame(frame_index, &wic_frame);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// Format convert to 32bppPBGRA which D2D expects
|
||||||
|
auto factory = Renderer::GetInstance()->GetD2DDeviceResources()->GetWICImagingFactory();
|
||||||
|
hr = factory->CreateFormatConverter(&converter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = converter->Initialize(
|
||||||
|
wic_frame.get(),
|
||||||
|
GUID_WICPixelFormat32bppPBGRA,
|
||||||
|
WICBitmapDitherTypeNone,
|
||||||
|
nullptr,
|
||||||
|
0.f,
|
||||||
|
WICBitmapPaletteTypeCustom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
auto ctx = Renderer::GetInstance()->GetD2DDeviceResources()->GetDeviceContext();
|
||||||
|
|
||||||
|
// Create a D2DBitmap from IWICBitmapSource
|
||||||
|
ComPtr<ID2D1Bitmap> raw_bitmap;
|
||||||
|
hr = ctx->CreateBitmapFromWicBitmap(
|
||||||
|
converter.get(),
|
||||||
|
nullptr,
|
||||||
|
&raw_bitmap
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
raw_frame.SetBitmap(raw_bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// Get Metadata Query Reader from the frame
|
||||||
|
hr = wic_frame->GetMetadataQueryReader(&metadata_reader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Metadata for the current frame
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Left", &prop_val);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
frame_rect.origin.x = static_cast<float>(prop_val.uiVal);
|
||||||
|
}
|
||||||
|
PropVariantClear(&prop_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Top", &prop_val);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
frame_rect.origin.y = static_cast<float>(prop_val.uiVal);
|
||||||
|
}
|
||||||
|
PropVariantClear(&prop_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Width", &prop_val);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
frame_rect.size.x = static_cast<float>(prop_val.uiVal);
|
||||||
|
}
|
||||||
|
PropVariantClear(&prop_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = metadata_reader->GetMetadataByName(L"/imgdesc/Height", &prop_val);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
frame_rect.size.y = static_cast<float>(prop_val.uiVal);
|
||||||
|
}
|
||||||
|
PropVariantClear(&prop_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = metadata_reader->GetMetadataByName(L"/grctlext/Delay", &prop_val);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = (prop_val.vt == VT_UI2 ? S_OK : E_FAIL);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
UINT udelay = 0;
|
||||||
|
hr = UIntMult(prop_val.uiVal, 10, &udelay);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
delay.SetMilliseconds(static_cast<long>(udelay));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropVariantClear(&prop_val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delay = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = metadata_reader->GetMetadataByName(L"/grctlext/Disposal", &prop_val);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = (prop_val.vt == VT_UI1) ? S_OK : E_FAIL;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
disposal_type = DisposalType(prop_val.bVal);
|
||||||
|
}
|
||||||
|
::PropVariantClear(&prop_val);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 获取 DisposalType 失败,可能图片是只有一帧的图片
|
||||||
|
disposal_type = DisposalType::Unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::PropVariantClear(&prop_val);
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,34 +19,33 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../base/Resource.h"
|
#include "Image.h"
|
||||||
#include "Renderer.h"
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
// GIF ͼÏñ
|
// GIF ͼÏñ
|
||||||
KGE_DECLARE_SMART_PTR(GifImage);
|
|
||||||
class KGE_API GifImage
|
class KGE_API GifImage
|
||||||
: public Object
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GifImage();
|
GifImage();
|
||||||
|
|
||||||
GifImage(
|
GifImage(String const& file_path);
|
||||||
Resource const& res
|
|
||||||
);
|
|
||||||
|
|
||||||
bool Load(
|
GifImage(Resource const& res);
|
||||||
Resource const& res
|
|
||||||
);
|
|
||||||
|
|
||||||
inline unsigned int GetWidthInPixels() const { return width_in_pixels_; }
|
bool Load(String const& file_path);
|
||||||
|
|
||||||
inline unsigned int GetHeightInPixels() const { return height_in_pixels_; }
|
bool Load(Resource const& res);
|
||||||
|
|
||||||
inline unsigned int GetFrameDelay() const { return frame_delay_; }
|
bool IsValid() const;
|
||||||
|
|
||||||
inline unsigned int GetFramesCount() const { return frames_count_; }
|
inline UINT GetWidthInPixels() const { return width_in_pixels_; }
|
||||||
|
|
||||||
|
inline UINT GetHeightInPixels() const { return height_in_pixels_; }
|
||||||
|
|
||||||
|
inline UINT GetFramesCount() const { return frames_count_; }
|
||||||
|
|
||||||
|
inline Color GetBackgroundColor() const { return bg_color_; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class DisposalType
|
enum class DisposalType
|
||||||
|
|
@ -57,37 +56,31 @@ namespace kiwano
|
||||||
Previous
|
Previous
|
||||||
};
|
};
|
||||||
|
|
||||||
inline DisposalType GetDisposalType() const { return disposal_type_; }
|
HRESULT GetRawFrame(
|
||||||
|
UINT frame_index,
|
||||||
|
Image& raw_frame,
|
||||||
|
Rect& frame_rect,
|
||||||
|
Duration& delay,
|
||||||
|
DisposalType& disposal_type
|
||||||
|
);
|
||||||
|
|
||||||
inline D2D1_COLOR_F GetBackgroundColor() const { return bg_color_; }
|
inline ComPtr<IWICBitmapDecoder> GetDecoder() const { return decoder_; }
|
||||||
|
|
||||||
inline D2D1_RECT_F const& GetFramePosition() const { return frame_position_; }
|
inline void SetDecoder(ComPtr<IWICBitmapDecoder> decoder) { decoder_ = decoder; }
|
||||||
|
|
||||||
inline ComPtr<ID2D1Bitmap> GetRawFrame() const { return raw_frame_; }
|
|
||||||
|
|
||||||
inline void SetDisposalType(DisposalType type) { disposal_type_ = type; }
|
|
||||||
|
|
||||||
public:
|
|
||||||
HRESULT GetRawFrame(UINT frame_index);
|
|
||||||
HRESULT GetGlobalMetadata();
|
|
||||||
HRESULT GetBackgroundColor(IWICMetadataQueryReader* metadata_reader);
|
|
||||||
|
|
||||||
HRESULT DisposeCurrentFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt);
|
|
||||||
HRESULT SaveComposedFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt);
|
|
||||||
HRESULT RestoreSavedFrame(ComPtr<ID2D1BitmapRenderTarget> frame_rt);
|
|
||||||
HRESULT ClearCurrentFrameArea(ComPtr<ID2D1BitmapRenderTarget> frame_rt);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ComPtr<ID2D1Bitmap> raw_frame_;
|
HRESULT GetGlobalMetadata();
|
||||||
ComPtr<ID2D1Bitmap> saved_frame_;
|
|
||||||
ComPtr<IWICBitmapDecoder> decoder_;
|
|
||||||
|
|
||||||
unsigned int frames_count_;
|
HRESULT GetBackgroundColor(
|
||||||
unsigned int frame_delay_;
|
ComPtr<IWICMetadataQueryReader> metadata_reader
|
||||||
unsigned int width_in_pixels_;
|
);
|
||||||
unsigned int height_in_pixels_;
|
|
||||||
DisposalType disposal_type_;
|
protected:
|
||||||
D2D1_RECT_F frame_position_;
|
UINT frames_count_;
|
||||||
D2D1_COLOR_F bg_color_;
|
UINT width_in_pixels_;
|
||||||
|
UINT height_in_pixels_;
|
||||||
|
Color bg_color_;
|
||||||
|
|
||||||
|
ComPtr<IWICBitmapDecoder> decoder_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,18 +19,26 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include "Image.h"
|
#include "Image.h"
|
||||||
|
#include "Renderer.h"
|
||||||
#include "../base/Logger.h"
|
#include "../base/Logger.h"
|
||||||
#include "../platform/modules.h"
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
Image::Image()
|
Image::Image()
|
||||||
: bitmap_(nullptr)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Image::Image(String const& file_path)
|
||||||
|
{
|
||||||
|
Load(file_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
Image::Image(Resource const& res)
|
||||||
|
{
|
||||||
|
Load(res);
|
||||||
|
}
|
||||||
|
|
||||||
Image::Image(ComPtr<ID2D1Bitmap> const & bitmap)
|
Image::Image(ComPtr<ID2D1Bitmap> const & bitmap)
|
||||||
: Image()
|
|
||||||
{
|
{
|
||||||
SetBitmap(bitmap);
|
SetBitmap(bitmap);
|
||||||
}
|
}
|
||||||
|
|
@ -39,9 +47,21 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Image::Load(String const& file_path)
|
||||||
|
{
|
||||||
|
Renderer::GetInstance()->CreateImage(*this, file_path);
|
||||||
|
return IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Image::Load(Resource const& res)
|
||||||
|
{
|
||||||
|
Renderer::GetInstance()->CreateImage(*this, res);
|
||||||
|
return IsValid();
|
||||||
|
}
|
||||||
|
|
||||||
bool Image::IsValid() const
|
bool Image::IsValid() const
|
||||||
{
|
{
|
||||||
return !!bitmap_;
|
return bitmap_ != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Image::GetWidth() const
|
float Image::GetWidth() const
|
||||||
|
|
@ -100,6 +120,43 @@ namespace kiwano
|
||||||
return math::Vec2T<UINT32>{};
|
return math::Vec2T<UINT32>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Image::CopyFrom(Image const& copy_from)
|
||||||
|
{
|
||||||
|
if (IsValid() && copy_from.IsValid())
|
||||||
|
{
|
||||||
|
HRESULT hr = bitmap_->CopyFromBitmap(nullptr, copy_from.GetBitmap().get(), nullptr);
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Image::CopyFrom(Image const& copy_from, Rect const& src_rect, Point const& dest_point)
|
||||||
|
{
|
||||||
|
if (IsValid() && copy_from.IsValid())
|
||||||
|
{
|
||||||
|
HRESULT hr = bitmap_->CopyFromBitmap(
|
||||||
|
&D2D1::Point2U(UINT(dest_point.x), UINT(dest_point.y)),
|
||||||
|
copy_from.GetBitmap().get(),
|
||||||
|
&D2D1::RectU(
|
||||||
|
UINT(src_rect.GetLeft()),
|
||||||
|
UINT(src_rect.GetTop()),
|
||||||
|
UINT(src_rect.GetRight()),
|
||||||
|
UINT(src_rect.GetBottom()))
|
||||||
|
);
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
D2D1_PIXEL_FORMAT Image::GetPixelFormat() const
|
||||||
|
{
|
||||||
|
if (bitmap_)
|
||||||
|
{
|
||||||
|
return bitmap_->GetPixelFormat();
|
||||||
|
}
|
||||||
|
return D2D1_PIXEL_FORMAT();
|
||||||
|
}
|
||||||
|
|
||||||
ComPtr<ID2D1Bitmap> Image::GetBitmap() const
|
ComPtr<ID2D1Bitmap> Image::GetBitmap() const
|
||||||
{
|
{
|
||||||
return bitmap_;
|
return bitmap_;
|
||||||
|
|
|
||||||
|
|
@ -19,25 +19,40 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../base/Resource.h"
|
#include "win32/D2DDeviceResources.h"
|
||||||
#include "D2DDeviceResources.h" // ID2D1Bitmap
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
// 图像
|
// 图像
|
||||||
KGE_DECLARE_SMART_PTR(Image);
|
|
||||||
class KGE_API Image
|
class KGE_API Image
|
||||||
: public Object
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Image();
|
Image();
|
||||||
|
|
||||||
|
explicit Image(
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
|
explicit Image(
|
||||||
|
Resource const& res
|
||||||
|
);
|
||||||
|
|
||||||
explicit Image(
|
explicit Image(
|
||||||
ComPtr<ID2D1Bitmap> const& bitmap
|
ComPtr<ID2D1Bitmap> const& bitmap
|
||||||
);
|
);
|
||||||
|
|
||||||
virtual ~Image();
|
virtual ~Image();
|
||||||
|
|
||||||
|
// 加载本地文件
|
||||||
|
bool Load(
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
|
// 加载资源
|
||||||
|
bool Load(
|
||||||
|
Resource const& res
|
||||||
|
);
|
||||||
|
|
||||||
// 资源是否有效
|
// 资源是否有效
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
||||||
|
|
@ -59,12 +74,22 @@ namespace kiwano
|
||||||
// 获取位图像素大小
|
// 获取位图像素大小
|
||||||
math::Vec2T<UINT32> GetSizeInPixels() const;
|
math::Vec2T<UINT32> GetSizeInPixels() const;
|
||||||
|
|
||||||
|
// 拷贝位图内存
|
||||||
|
void CopyFrom(Image const& copy_from);
|
||||||
|
|
||||||
|
// 拷贝位图内存
|
||||||
|
void CopyFrom(Image const& copy_from, Rect const& src_rect, Point const& dest_point);
|
||||||
|
|
||||||
|
public:
|
||||||
// 获取源位图
|
// 获取源位图
|
||||||
ComPtr<ID2D1Bitmap> GetBitmap() const;
|
ComPtr<ID2D1Bitmap> GetBitmap() const;
|
||||||
|
|
||||||
// 设置源位图
|
// 设置源位图
|
||||||
void SetBitmap(ComPtr<ID2D1Bitmap> bitmap);
|
void SetBitmap(ComPtr<ID2D1Bitmap> bitmap);
|
||||||
|
|
||||||
|
// 获取像素格式
|
||||||
|
D2D1_PIXEL_FORMAT GetPixelFormat() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ComPtr<ID2D1Bitmap> bitmap_;
|
ComPtr<ID2D1Bitmap> bitmap_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,37 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include "ImageCache.h"
|
#include "ImageCache.h"
|
||||||
|
#include "Renderer.h"
|
||||||
#include "../base/Logger.h"
|
#include "../base/Logger.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
template <typename _Ty, typename _PathTy, typename _CacheTy>
|
||||||
|
_Ty CreateOrGetCache(_CacheTy& cache, _PathTy const& path, size_t hash)
|
||||||
|
{
|
||||||
|
auto iter = cache.find(hash);
|
||||||
|
if (iter != cache.end())
|
||||||
|
{
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Ty image;
|
||||||
|
if (image.Load(path))
|
||||||
|
{
|
||||||
|
cache.insert(std::make_pair(hash, image));
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _CacheTy>
|
||||||
|
void RemoveCache(_CacheTy& cache, size_t hash)
|
||||||
|
{
|
||||||
|
auto iter = cache.find(hash);
|
||||||
|
if (iter != cache.end())
|
||||||
|
{
|
||||||
|
cache.erase(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImageCache::ImageCache()
|
ImageCache::ImageCache()
|
||||||
{
|
{
|
||||||
|
|
@ -32,53 +59,50 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ImagePtr ImageCache::AddImage(Resource const& res)
|
Image ImageCache::AddOrGetImage(String const& file_path)
|
||||||
{
|
{
|
||||||
size_t hash_code = res.GetHashCode();
|
return CreateOrGetCache<Image>(image_cache_, file_path, file_path.hash());
|
||||||
auto iter = image_cache_.find(hash_code);
|
|
||||||
if (iter != image_cache_.end())
|
|
||||||
{
|
|
||||||
return iter->second;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT hr = S_OK;
|
Image ImageCache::AddOrGetImage(Resource const& res)
|
||||||
ComPtr<ID2D1Bitmap> bitmap;
|
|
||||||
|
|
||||||
if (res.IsFileType())
|
|
||||||
{
|
{
|
||||||
hr = Renderer::GetInstance()->GetD2DDeviceResources()->CreateBitmapFromFile(bitmap, res.GetFileName());
|
return CreateOrGetCache<Image>(image_cache_, res, res.GetId());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hr = Renderer::GetInstance()->GetD2DDeviceResources()->CreateBitmapFromResource(bitmap, res);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
GifImage ImageCache::AddOrGetGifImage(String const& file_path)
|
||||||
{
|
{
|
||||||
ImagePtr ptr = new Image(bitmap);
|
return CreateOrGetCache<GifImage>(gif_image_cache_, file_path, file_path.hash());
|
||||||
image_cache_.insert(std::make_pair(hash_code, ptr));
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
GifImage ImageCache::AddOrGetGifImage(Resource const& res)
|
||||||
{
|
{
|
||||||
KGE_ERROR_LOG(L"Load image file failed with HRESULT of %08X", hr);
|
return CreateOrGetCache<GifImage>(gif_image_cache_, res, res.GetId());
|
||||||
}
|
}
|
||||||
return nullptr;
|
|
||||||
|
void ImageCache::RemoveImage(String const& file_path)
|
||||||
|
{
|
||||||
|
RemoveCache(image_cache_, file_path.hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageCache::RemoveImage(Resource const& res)
|
void ImageCache::RemoveImage(Resource const& res)
|
||||||
{
|
{
|
||||||
size_t hash_code = res.GetHashCode();
|
RemoveCache(image_cache_, res.GetId());
|
||||||
auto iter = image_cache_.find(hash_code);
|
|
||||||
if (iter != image_cache_.end())
|
|
||||||
{
|
|
||||||
image_cache_.erase(iter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageCache::RemoveGifImage(String const& file_path)
|
||||||
|
{
|
||||||
|
RemoveCache(gif_image_cache_, file_path.hash());
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageCache::RemoveGifImage(Resource const& res)
|
||||||
|
{
|
||||||
|
RemoveCache(gif_image_cache_, res.GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageCache::Clear()
|
void ImageCache::Clear()
|
||||||
{
|
{
|
||||||
image_cache_.clear();
|
image_cache_.clear();
|
||||||
|
gif_image_cache_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,8 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../core/singleton.hpp"
|
#include "Image.h"
|
||||||
#include "Renderer.h"
|
#include "GifImage.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -30,9 +30,15 @@ namespace kiwano
|
||||||
KGE_DECLARE_SINGLETON(ImageCache);
|
KGE_DECLARE_SINGLETON(ImageCache);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ImagePtr AddImage(Resource const& res);
|
Image AddOrGetImage(String const& file_path);
|
||||||
|
Image AddOrGetImage(Resource const& res);
|
||||||
|
GifImage AddOrGetGifImage(String const& file_path);
|
||||||
|
GifImage AddOrGetGifImage(Resource const& res);
|
||||||
|
|
||||||
|
void RemoveImage(String const& file_path);
|
||||||
void RemoveImage(Resource const& res);
|
void RemoveImage(Resource const& res);
|
||||||
|
void RemoveGifImage(String const& file_path);
|
||||||
|
void RemoveGifImage(Resource const& res);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
|
@ -42,7 +48,10 @@ namespace kiwano
|
||||||
virtual ~ImageCache();
|
virtual ~ImageCache();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using ImageMap = UnorderedMap<size_t, ImagePtr>;
|
using ImageMap = UnorderedMap<size_t, Image>;
|
||||||
ImageMap image_cache_;
|
ImageMap image_cache_;
|
||||||
|
|
||||||
|
using GifImageMap = UnorderedMap<size_t, GifImage>;
|
||||||
|
GifImageMap gif_image_cache_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright (c) 2016-2019 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 "LayerArea.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
LayerArea::LayerArea()
|
||||||
|
: opacity_(1.f)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LayerArea::IsValid() const
|
||||||
|
{
|
||||||
|
return layer_ != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size LayerArea::GetSize() const
|
||||||
|
{
|
||||||
|
if (layer_)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<Size const&>(layer_->GetSize());
|
||||||
|
}
|
||||||
|
return Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (c) 2016-2019 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 "Geometry.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
// ͼ²ã
|
||||||
|
class KGE_API LayerArea
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LayerArea();
|
||||||
|
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
Size GetSize() const;
|
||||||
|
|
||||||
|
inline Rect const& GetAreaRect() const { return area_; }
|
||||||
|
|
||||||
|
inline void SetAreaRect(Rect const& area) { area_ = area; }
|
||||||
|
|
||||||
|
inline float GetOpacity() const { return opacity_; }
|
||||||
|
|
||||||
|
inline void SetOpacity(float opacity) { opacity_ = opacity; }
|
||||||
|
|
||||||
|
inline Geometry const& GetMaskGeometry() const { return mask_; }
|
||||||
|
|
||||||
|
inline void SetMaskGeometry(Geometry const& mask) { mask_ = mask; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline ComPtr<ID2D1Layer> GetLayer() const { return layer_; }
|
||||||
|
|
||||||
|
inline void SetLayer(ComPtr<ID2D1Layer> layer) { layer_ = layer; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Rect area_;
|
||||||
|
float opacity_;
|
||||||
|
Geometry mask_;
|
||||||
|
ComPtr<ID2D1Layer> layer_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,660 @@
|
||||||
|
// Copyright (c) 2016-2019 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 "RenderTarget.h"
|
||||||
|
#include "../base/Logger.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// RenderTarget
|
||||||
|
//
|
||||||
|
|
||||||
|
RenderTarget::RenderTarget()
|
||||||
|
: opacity_(1.f)
|
||||||
|
, collecting_status_(false)
|
||||||
|
, antialias_(true)
|
||||||
|
, text_antialias_(TextAntialias::GrayScale)
|
||||||
|
{
|
||||||
|
status_.primitives = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT RenderTarget::InitDeviceResources(ComPtr<ID2D1RenderTarget> rt, ComPtr<ID2DDeviceResources> dev_res)
|
||||||
|
{
|
||||||
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
|
if (rt && dev_res)
|
||||||
|
{
|
||||||
|
render_target_ = rt;
|
||||||
|
d2d_res_ = dev_res;
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
text_renderer_.reset();
|
||||||
|
hr = ITextRenderer::Create(
|
||||||
|
&text_renderer_,
|
||||||
|
render_target_.get()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
solid_color_brush_.reset();
|
||||||
|
hr = render_target_->CreateSolidColorBrush(
|
||||||
|
D2D1::ColorF(D2D1::ColorF::White),
|
||||||
|
D2D1::BrushProperties(),
|
||||||
|
&solid_color_brush_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RenderTarget::IsValid() const
|
||||||
|
{
|
||||||
|
return render_target_ && d2d_res_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::BeginDraw()
|
||||||
|
{
|
||||||
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
|
if (collecting_status_)
|
||||||
|
{
|
||||||
|
status_.start = Time::Now();
|
||||||
|
status_.primitives = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (render_target_)
|
||||||
|
{
|
||||||
|
render_target_->BeginDraw();
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::EndDraw()
|
||||||
|
{
|
||||||
|
ThrowIfFailed(render_target_->EndDraw());
|
||||||
|
|
||||||
|
if (collecting_status_)
|
||||||
|
{
|
||||||
|
status_.duration = Time::Now() - status_.start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::DrawGeometry(
|
||||||
|
Geometry const& geometry,
|
||||||
|
Color const& stroke_color,
|
||||||
|
float stroke_width,
|
||||||
|
StrokeStyle stroke
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && geometry.GetGeometry())
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
|
||||||
|
|
||||||
|
render_target_->DrawGeometry(
|
||||||
|
geometry.GetGeometry().get(),
|
||||||
|
solid_color_brush_.get(),
|
||||||
|
stroke_width,
|
||||||
|
d2d_res_->GetStrokeStyle(stroke)
|
||||||
|
);
|
||||||
|
|
||||||
|
IncreasePrimitivesCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::FillGeometry(Geometry const& geometry, Color const& fill_color) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && geometry.GetGeometry())
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
|
||||||
|
render_target_->FillGeometry(
|
||||||
|
geometry.GetGeometry().get(),
|
||||||
|
solid_color_brush_.get()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::DrawLine(Point const& point1, Point const& point2, Color const& stroke_color, float stroke_width, StrokeStyle stroke) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
|
||||||
|
|
||||||
|
render_target_->DrawLine(
|
||||||
|
DX::ConvertToPoint2F(point1),
|
||||||
|
DX::ConvertToPoint2F(point2),
|
||||||
|
solid_color_brush_.get(),
|
||||||
|
stroke_width,
|
||||||
|
d2d_res_->GetStrokeStyle(stroke)
|
||||||
|
);
|
||||||
|
|
||||||
|
IncreasePrimitivesCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::DrawRectangle(Rect const& rect, Color const& stroke_color, float stroke_width, StrokeStyle stroke) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
|
||||||
|
|
||||||
|
render_target_->DrawRectangle(
|
||||||
|
DX::ConvertToRectF(rect),
|
||||||
|
solid_color_brush_.get(),
|
||||||
|
stroke_width,
|
||||||
|
d2d_res_->GetStrokeStyle(stroke)
|
||||||
|
);
|
||||||
|
|
||||||
|
IncreasePrimitivesCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::FillRectangle(Rect const& rect, Color const& fill_color) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
|
||||||
|
render_target_->FillRectangle(
|
||||||
|
DX::ConvertToRectF(rect),
|
||||||
|
solid_color_brush_.get()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::DrawRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& stroke_color, float stroke_width, StrokeStyle stroke) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
|
||||||
|
|
||||||
|
render_target_->DrawRoundedRectangle(
|
||||||
|
D2D1::RoundedRect(
|
||||||
|
DX::ConvertToRectF(rect),
|
||||||
|
radius.x,
|
||||||
|
radius.y
|
||||||
|
),
|
||||||
|
solid_color_brush_.get(),
|
||||||
|
stroke_width,
|
||||||
|
d2d_res_->GetStrokeStyle(stroke)
|
||||||
|
);
|
||||||
|
|
||||||
|
IncreasePrimitivesCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::FillRoundedRectangle(Rect const& rect, Vec2 const& radius, Color const& fill_color) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
|
||||||
|
render_target_->FillRoundedRectangle(
|
||||||
|
D2D1::RoundedRect(
|
||||||
|
DX::ConvertToRectF(rect),
|
||||||
|
radius.x,
|
||||||
|
radius.y
|
||||||
|
),
|
||||||
|
solid_color_brush_.get()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::DrawEllipse(Point const& center, Vec2 const& radius, Color const& stroke_color, float stroke_width, StrokeStyle stroke) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
|
||||||
|
|
||||||
|
render_target_->DrawEllipse(
|
||||||
|
D2D1::Ellipse(
|
||||||
|
DX::ConvertToPoint2F(center),
|
||||||
|
radius.x,
|
||||||
|
radius.y
|
||||||
|
),
|
||||||
|
solid_color_brush_.get(),
|
||||||
|
stroke_width,
|
||||||
|
d2d_res_->GetStrokeStyle(stroke)
|
||||||
|
);
|
||||||
|
|
||||||
|
IncreasePrimitivesCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::FillEllipse(Point const& center, Vec2 const& radius, Color const& fill_color) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_ || !render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
|
||||||
|
render_target_->FillEllipse(
|
||||||
|
D2D1::Ellipse(
|
||||||
|
DX::ConvertToPoint2F(center),
|
||||||
|
radius.x,
|
||||||
|
radius.y
|
||||||
|
),
|
||||||
|
solid_color_brush_.get()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::DrawImage(Image const& image, Rect const& src_rect, Rect const& dest_rect) const
|
||||||
|
{
|
||||||
|
DrawImage(image, &src_rect, &dest_rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::DrawImage(Image const& image, const Rect* src_rect, const Rect* dest_rect) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && image.IsValid())
|
||||||
|
{
|
||||||
|
render_target_->DrawBitmap(
|
||||||
|
image.GetBitmap().get(),
|
||||||
|
dest_rect ? &DX::ConvertToRectF(*dest_rect) : nullptr,
|
||||||
|
opacity_,
|
||||||
|
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
||||||
|
src_rect ? &DX::ConvertToRectF(*src_rect) : nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
IncreasePrimitivesCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::DrawTextLayout(TextLayout const& layout, Point const& offset) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!text_renderer_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
text_renderer_->SetTextStyle(
|
||||||
|
opacity_,
|
||||||
|
DX::ConvertToColorF(layout.GetTextStyle().color),
|
||||||
|
layout.GetTextStyle().outline,
|
||||||
|
DX::ConvertToColorF(layout.GetTextStyle().outline_color),
|
||||||
|
layout.GetTextStyle().outline_width,
|
||||||
|
d2d_res_->GetStrokeStyle(layout.GetTextStyle().outline_stroke)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = layout.GetTextLayout()->Draw(nullptr, text_renderer_.get(), offset.x, offset.y);
|
||||||
|
|
||||||
|
IncreasePrimitivesCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::CreateLayer(LayerArea& layer) const
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (!render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<ID2D1Layer> output;
|
||||||
|
hr = render_target_->CreateLayer(&output);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
layer.SetLayer(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::PushClipRect(Rect const& clip_rect)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
render_target_->PushAxisAlignedClip(
|
||||||
|
DX::ConvertToRectF(clip_rect),
|
||||||
|
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::PopClipRect()
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
render_target_->PopAxisAlignedClip();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::PushLayer(LayerArea const& layer)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!render_target_ || !solid_color_brush_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr) && layer.IsValid())
|
||||||
|
{
|
||||||
|
render_target_->PushLayer(
|
||||||
|
D2D1::LayerParameters(
|
||||||
|
DX::ConvertToRectF(layer.GetAreaRect()),
|
||||||
|
layer.GetMaskGeometry().GetGeometry().get(),
|
||||||
|
antialias_ ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED,
|
||||||
|
D2D1::Matrix3x2F::Identity(),
|
||||||
|
layer.GetOpacity(),
|
||||||
|
nullptr,
|
||||||
|
D2D1_LAYER_OPTIONS_NONE
|
||||||
|
),
|
||||||
|
layer.GetLayer().get()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::PopLayer()
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
render_target_->PopLayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::Clear()
|
||||||
|
{
|
||||||
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
|
if (render_target_)
|
||||||
|
{
|
||||||
|
render_target_->Clear();
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::Clear(Color const& clear_color)
|
||||||
|
{
|
||||||
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
|
if (render_target_)
|
||||||
|
{
|
||||||
|
render_target_->Clear(DX::ConvertToColorF(clear_color));
|
||||||
|
hr = S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
float RenderTarget::GetOpacity() const
|
||||||
|
{
|
||||||
|
return opacity_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::SetTransform(const Matrix3x2& matrix)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
render_target_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::SetOpacity(float opacity)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!solid_color_brush_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (opacity_ != opacity)
|
||||||
|
{
|
||||||
|
opacity_ = opacity;
|
||||||
|
solid_color_brush_->SetOpacity(opacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::SetAntialiasMode(bool enabled)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
render_target_->SetAntialiasMode(
|
||||||
|
enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
|
||||||
|
);
|
||||||
|
antialias_ = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::SetTextAntialiasMode(TextAntialias mode)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!render_target_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
text_antialias_ = mode;
|
||||||
|
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||||
|
switch (text_antialias_)
|
||||||
|
{
|
||||||
|
case TextAntialias::Default:
|
||||||
|
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
|
||||||
|
break;
|
||||||
|
case TextAntialias::ClearType:
|
||||||
|
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
||||||
|
break;
|
||||||
|
case TextAntialias::GrayScale:
|
||||||
|
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
||||||
|
break;
|
||||||
|
case TextAntialias::None:
|
||||||
|
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
render_target_->SetTextAntialiasMode(antialias_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::SetCollectingStatus(bool collecting)
|
||||||
|
{
|
||||||
|
collecting_status_ = collecting;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderTarget::IncreasePrimitivesCount() const
|
||||||
|
{
|
||||||
|
if (collecting_status_)
|
||||||
|
{
|
||||||
|
++status_.primitives;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// ImageRenderTarget
|
||||||
|
//
|
||||||
|
|
||||||
|
ImageRenderTarget::ImageRenderTarget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageRenderTarget::GetOutput(Image& output) const
|
||||||
|
{
|
||||||
|
HRESULT hr = E_FAIL;
|
||||||
|
|
||||||
|
ComPtr<ID2D1BitmapRenderTarget> bitmap_rt;
|
||||||
|
if (render_target_)
|
||||||
|
{
|
||||||
|
hr = render_target_->QueryInterface<ID2D1BitmapRenderTarget>(&bitmap_rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<ID2D1Bitmap> bitmap;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = bitmap_rt->GetBitmap(&bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
output.SetBitmap(bitmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,207 @@
|
||||||
|
// Copyright (c) 2016-2019 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 "../base/time.h"
|
||||||
|
#include "Image.h"
|
||||||
|
#include "Geometry.h"
|
||||||
|
#include "TextLayout.h"
|
||||||
|
#include "LayerArea.h"
|
||||||
|
#include "win32/TextRenderer.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
// äÖȾĿ±ê
|
||||||
|
class KGE_API RenderTarget
|
||||||
|
: public noncopyable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void BeginDraw();
|
||||||
|
|
||||||
|
void EndDraw();
|
||||||
|
|
||||||
|
void CreateLayer(
|
||||||
|
LayerArea& layer
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void DrawGeometry(
|
||||||
|
Geometry const& geometry,
|
||||||
|
Color const& stroke_color,
|
||||||
|
float stroke_width,
|
||||||
|
StrokeStyle stroke = StrokeStyle::Miter
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void FillGeometry(
|
||||||
|
Geometry const& geometry,
|
||||||
|
Color const& fill_color
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void DrawLine(
|
||||||
|
Point const& point1,
|
||||||
|
Point const& point2,
|
||||||
|
Color const& stroke_color,
|
||||||
|
float stroke_width,
|
||||||
|
StrokeStyle stroke = StrokeStyle::Miter
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void DrawRectangle(
|
||||||
|
Rect const& rect,
|
||||||
|
Color const& stroke_color,
|
||||||
|
float stroke_width,
|
||||||
|
StrokeStyle stroke = StrokeStyle::Miter
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void FillRectangle(
|
||||||
|
Rect const& rect,
|
||||||
|
Color const& fill_color
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void DrawRoundedRectangle(
|
||||||
|
Rect const& rect,
|
||||||
|
Vec2 const& radius,
|
||||||
|
Color const& stroke_color,
|
||||||
|
float stroke_width,
|
||||||
|
StrokeStyle stroke = StrokeStyle::Miter
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void FillRoundedRectangle(
|
||||||
|
Rect const& rect,
|
||||||
|
Vec2 const& radius,
|
||||||
|
Color const& fill_color
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void DrawEllipse(
|
||||||
|
Point const& center,
|
||||||
|
Vec2 const& radius,
|
||||||
|
Color const& stroke_color,
|
||||||
|
float stroke_width,
|
||||||
|
StrokeStyle stroke = StrokeStyle::Miter
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void FillEllipse(
|
||||||
|
Point const& center,
|
||||||
|
Vec2 const& radius,
|
||||||
|
Color const& fill_color
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void DrawImage(
|
||||||
|
Image const& image,
|
||||||
|
Rect const& src_rect,
|
||||||
|
Rect const& dest_rect
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void DrawImage(
|
||||||
|
Image const& image,
|
||||||
|
const Rect* src_rect = nullptr,
|
||||||
|
const Rect* dest_rect = nullptr
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void DrawTextLayout(
|
||||||
|
TextLayout const& layout,
|
||||||
|
Point const& offset = Point{}
|
||||||
|
) const;
|
||||||
|
|
||||||
|
void PushClipRect(
|
||||||
|
Rect const& clip_rect
|
||||||
|
);
|
||||||
|
|
||||||
|
void PopClipRect();
|
||||||
|
|
||||||
|
void PushLayer(
|
||||||
|
LayerArea const& layer
|
||||||
|
);
|
||||||
|
|
||||||
|
void PopLayer();
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
void Clear(
|
||||||
|
Color const& clear_color
|
||||||
|
);
|
||||||
|
|
||||||
|
float GetOpacity() const;
|
||||||
|
|
||||||
|
void SetOpacity(
|
||||||
|
float opacity
|
||||||
|
);
|
||||||
|
|
||||||
|
void SetTransform(
|
||||||
|
const Matrix3x2& matrix
|
||||||
|
);
|
||||||
|
|
||||||
|
// ÉèÖÿ¹¾â³Ýģʽ
|
||||||
|
void SetAntialiasMode(
|
||||||
|
bool enabled
|
||||||
|
);
|
||||||
|
|
||||||
|
// ÉèÖÃÎÄ×Ö¿¹¾â³Ýģʽ
|
||||||
|
void SetTextAntialiasMode(
|
||||||
|
TextAntialias mode
|
||||||
|
);
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct Status
|
||||||
|
{
|
||||||
|
int primitives;
|
||||||
|
Time start;
|
||||||
|
Duration duration;
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetCollectingStatus(bool collecting);
|
||||||
|
|
||||||
|
void IncreasePrimitivesCount() const;
|
||||||
|
|
||||||
|
inline Status const& GetStatus() const { return status_; }
|
||||||
|
|
||||||
|
inline ComPtr<ID2D1RenderTarget> GetRenderTarget() const { return render_target_; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
RenderTarget();
|
||||||
|
|
||||||
|
HRESULT InitDeviceResources(
|
||||||
|
ComPtr<ID2D1RenderTarget> rt,
|
||||||
|
ComPtr<ID2DDeviceResources> dev_res
|
||||||
|
);
|
||||||
|
|
||||||
|
bool IsValid() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float opacity_;
|
||||||
|
bool antialias_;
|
||||||
|
mutable bool collecting_status_;
|
||||||
|
mutable Status status_;
|
||||||
|
TextAntialias text_antialias_;
|
||||||
|
ComPtr<ID2D1RenderTarget> render_target_;
|
||||||
|
ComPtr<ITextRenderer> text_renderer_;
|
||||||
|
ComPtr<ID2D1SolidColorBrush> solid_color_brush_;
|
||||||
|
ComPtr<ID2DDeviceResources> d2d_res_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// λͼäÖȾĿ±ê
|
||||||
|
class KGE_API ImageRenderTarget
|
||||||
|
: public RenderTarget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ImageRenderTarget();
|
||||||
|
|
||||||
|
void GetOutput(Image& output) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -21,19 +21,15 @@
|
||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "../base/Logger.h"
|
#include "../base/Logger.h"
|
||||||
#include "../base/Window.h"
|
#include "../base/Window.h"
|
||||||
|
#include "../utils/FileUtil.h"
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
Renderer::Renderer()
|
Renderer::Renderer()
|
||||||
: hwnd_(nullptr)
|
: hwnd_(nullptr)
|
||||||
, antialias_(true)
|
|
||||||
, vsync_(true)
|
, vsync_(true)
|
||||||
, text_antialias_(TextAntialias::GrayScale)
|
|
||||||
, clear_color_(Color::Black)
|
, clear_color_(Color::Black)
|
||||||
, opacity_(1.f)
|
|
||||||
, collecting_status_(false)
|
|
||||||
{
|
{
|
||||||
status_.primitives = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Renderer::~Renderer()
|
Renderer::~Renderer()
|
||||||
|
|
@ -45,54 +41,97 @@ namespace kiwano
|
||||||
KGE_LOG(L"Creating device resources");
|
KGE_LOG(L"Creating device resources");
|
||||||
|
|
||||||
hwnd_ = Window::GetInstance()->GetHandle();
|
hwnd_ = Window::GetInstance()->GetHandle();
|
||||||
|
output_size_ = Window::GetInstance()->GetSize();
|
||||||
ThrowIfFailed(hwnd_ ? S_OK : E_FAIL);
|
|
||||||
|
|
||||||
d2d_res_ = nullptr;
|
d2d_res_ = nullptr;
|
||||||
d3d_res_ = nullptr;
|
d3d_res_ = nullptr;
|
||||||
drawing_state_block_ = nullptr;
|
drawing_state_block_ = nullptr;
|
||||||
|
|
||||||
ThrowIfFailed(
|
HRESULT hr = hwnd_ ? S_OK : E_FAIL;
|
||||||
ID2DDeviceResources::Create(
|
|
||||||
&d2d_res_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
ThrowIfFailed(
|
// Direct2D device resources
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = ID2DDeviceResources::Create(&d2d_res_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Direct3D device resources
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
#if defined(KGE_USE_DIRECTX10)
|
#if defined(KGE_USE_DIRECTX10)
|
||||||
ID3D10DeviceResources::Create(
|
hr = ID3D10DeviceResources::Create(
|
||||||
&d3d_res_,
|
&d3d_res_,
|
||||||
d2d_res_.get(),
|
d2d_res_.get(),
|
||||||
hwnd_
|
hwnd_
|
||||||
)
|
);
|
||||||
#else
|
#else
|
||||||
ID3D11DeviceResources::Create(
|
hr = ID3D11DeviceResources::Create(
|
||||||
&d3d_res_,
|
&d3d_res_,
|
||||||
d2d_res_.get(),
|
d2d_res_.get(),
|
||||||
hwnd_
|
hwnd_
|
||||||
)
|
);
|
||||||
#endif
|
#endif
|
||||||
);
|
}
|
||||||
|
|
||||||
device_context_ = d2d_res_->GetDeviceContext();
|
// DrawingStateBlock
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
ThrowIfFailed(
|
{
|
||||||
d2d_res_->GetFactory()->CreateDrawingStateBlock(
|
hr = d2d_res_->GetFactory()->CreateDrawingStateBlock(
|
||||||
&drawing_state_block_
|
&drawing_state_block_
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ThrowIfFailed(
|
// Other device resources
|
||||||
CreateDeviceResources()
|
if (SUCCEEDED(hr))
|
||||||
);
|
{
|
||||||
|
hr = CreateDeviceResources();
|
||||||
|
}
|
||||||
|
|
||||||
output_size_ = Window::GetInstance()->GetSize();
|
// FontFileLoader and FontCollectionLoader
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IFontCollectionLoader::Create(&font_collection_loader_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(font_collection_loader_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResourceFontFileLoader and ResourceFontCollectionLoader
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IResourceFontFileLoader::Create(&res_font_file_loader_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = d2d_res_->GetDWriteFactory()->RegisterFontFileLoader(res_font_file_loader_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = IResourceFontCollectionLoader::Create(&res_font_collection_loader_, res_font_file_loader_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = d2d_res_->GetDWriteFactory()->RegisterFontCollectionLoader(res_font_collection_loader_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DestroyComponent()
|
void Renderer::DestroyComponent()
|
||||||
{
|
{
|
||||||
KGE_LOG(L"Destroying device resources");
|
KGE_LOG(L"Destroying device resources");
|
||||||
|
|
||||||
|
d2d_res_->GetDWriteFactory()->UnregisterFontFileLoader(res_font_file_loader_.get());
|
||||||
|
res_font_file_loader_.reset();
|
||||||
|
|
||||||
|
d2d_res_->GetDWriteFactory()->UnregisterFontCollectionLoader(res_font_collection_loader_.get());
|
||||||
|
res_font_collection_loader_.reset();
|
||||||
|
|
||||||
drawing_state_block_.reset();
|
drawing_state_block_.reset();
|
||||||
solid_color_brush_.reset();
|
solid_color_brush_.reset();
|
||||||
d2d_res_.reset();
|
d2d_res_.reset();
|
||||||
|
|
@ -101,16 +140,55 @@ namespace kiwano
|
||||||
|
|
||||||
void Renderer::BeforeRender()
|
void Renderer::BeforeRender()
|
||||||
{
|
{
|
||||||
ThrowIfFailed(
|
HRESULT hr = S_OK;
|
||||||
BeginDraw()
|
|
||||||
);
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
render_target_->SaveDrawingState(drawing_state_block_.get());
|
||||||
|
BeginDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = d3d_res_->ClearRenderTarget(clear_color_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::AfterRender()
|
void Renderer::AfterRender()
|
||||||
{
|
{
|
||||||
ThrowIfFailed(
|
HRESULT hr = S_OK;
|
||||||
EndDraw()
|
|
||||||
);
|
if (!IsValid())
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
EndDraw();
|
||||||
|
|
||||||
|
render_target_->RestoreDrawingState(drawing_state_block_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = d3d_res_->Present(vsync_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
||||||
|
{
|
||||||
|
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
|
||||||
|
hr = HandleDeviceLost();
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
void Renderer::HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
|
@ -130,24 +208,11 @@ namespace kiwano
|
||||||
|
|
||||||
HRESULT Renderer::CreateDeviceResources()
|
HRESULT Renderer::CreateDeviceResources()
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = InitDeviceResources(
|
||||||
|
d2d_res_->GetDeviceContext(),
|
||||||
solid_color_brush_.reset();
|
d2d_res_
|
||||||
hr = device_context_->CreateSolidColorBrush(
|
|
||||||
D2D1::ColorF(D2D1::ColorF::White),
|
|
||||||
D2D1::BrushProperties(),
|
|
||||||
&solid_color_brush_
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
text_renderer_.reset();
|
|
||||||
hr = ITextRenderer::Create(
|
|
||||||
&text_renderer_,
|
|
||||||
device_context_.get()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
SetAntialiasMode(antialias_);
|
SetAntialiasMode(antialias_);
|
||||||
|
|
@ -167,79 +232,273 @@ namespace kiwano
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Renderer::BeginDraw()
|
void Renderer::CreateImage(Image& image, String const& file_path)
|
||||||
{
|
|
||||||
if (!device_context_)
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
|
|
||||||
if (collecting_status_)
|
|
||||||
{
|
|
||||||
status_.start = Time::Now();
|
|
||||||
status_.primitives = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
device_context_->SaveDrawingState(drawing_state_block_.get());
|
|
||||||
|
|
||||||
device_context_->BeginDraw();
|
|
||||||
|
|
||||||
HRESULT hr = d3d_res_->ClearRenderTarget(clear_color_);
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
HRESULT Renderer::EndDraw()
|
|
||||||
{
|
|
||||||
if (!device_context_)
|
|
||||||
return E_UNEXPECTED;
|
|
||||||
|
|
||||||
HRESULT hr = device_context_->EndDraw();
|
|
||||||
|
|
||||||
device_context_->RestoreDrawingState(drawing_state_block_.get());
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = d3d_res_->Present(vsync_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
|
||||||
{
|
|
||||||
// 如果 Direct3D 设备在执行过程中消失,将丢弃当前的设备相关资源
|
|
||||||
hr = HandleDeviceLost();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collecting_status_)
|
|
||||||
{
|
|
||||||
status_.duration = Time::Now() - status_.start;
|
|
||||||
}
|
|
||||||
return hr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::IncreasePrimitivesCount()
|
|
||||||
{
|
|
||||||
if (collecting_status_)
|
|
||||||
{
|
|
||||||
++status_.primitives;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::CreateLayer(ComPtr<ID2D1Layer>& layer)
|
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
ComPtr<ID2D1Layer> new_layer;
|
if (!d2d_res_)
|
||||||
|
|
||||||
if (!device_context_)
|
|
||||||
{
|
{
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = device_context_->CreateLayer(&new_layer);
|
ComPtr<ID2D1Bitmap> bitmap;
|
||||||
|
hr = d2d_res_->CreateBitmapFromFile(bitmap, file_path);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
image.SetBitmap(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CreateImage(Image& image, Resource const& res)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!d2d_res_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
layer = new_layer;
|
ComPtr<ID2D1Bitmap> bitmap;
|
||||||
|
hr = d2d_res_->CreateBitmapFromResource(bitmap, res);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
image.SetBitmap(bitmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Load image failed with HRESULT of %08X!", hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CreateGifImage(GifImage& image, String const& file_path)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!d2d_res_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileUtil::ExistsFile(file_path))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Gif image file '%s' not found!", file_path.c_str());
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IWICBitmapDecoder> decoder;
|
||||||
|
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromFilename(
|
||||||
|
file_path.c_str(),
|
||||||
|
nullptr,
|
||||||
|
GENERIC_READ,
|
||||||
|
WICDecodeMetadataCacheOnLoad,
|
||||||
|
&decoder
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
image.SetDecoder(decoder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CreateGifImage(GifImage& image, Resource const& res)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!d2d_res_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Resource::Data res_data = res.GetData();
|
||||||
|
|
||||||
|
hr = res_data ? S_OK : E_FAIL;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IWICStream> stream;
|
||||||
|
hr = d2d_res_->GetWICImagingFactory()->CreateStream(&stream);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = stream->InitializeFromMemory(
|
||||||
|
static_cast<WICInProcPointer>(res_data.buffer),
|
||||||
|
res_data.size
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IWICBitmapDecoder> decoder;
|
||||||
|
hr = d2d_res_->GetWICImagingFactory()->CreateDecoderFromStream(
|
||||||
|
stream.get(),
|
||||||
|
nullptr,
|
||||||
|
WICDecodeMetadataCacheOnLoad,
|
||||||
|
&decoder
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
image.SetDecoder(decoder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Load GIF image failed with HRESULT of %08X!", hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CreateFontCollection(FontCollection& collection, Vector<String> const& file_paths)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!d2d_res_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
for (const auto& file_path : file_paths)
|
||||||
|
{
|
||||||
|
if (!FileUtil::ExistsFile(file_path))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Font file '%s' not found!", file_path.c_str());
|
||||||
|
hr = E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
LPVOID collection_key = nullptr;
|
||||||
|
UINT32 collection_key_size = 0;
|
||||||
|
|
||||||
|
hr = font_collection_loader_->AddFilePaths(file_paths, &collection_key, &collection_key_size);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IDWriteFontCollection> font_collection;
|
||||||
|
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(
|
||||||
|
font_collection_loader_.get(),
|
||||||
|
collection_key,
|
||||||
|
collection_key_size,
|
||||||
|
&font_collection
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
collection.SetFontCollection(font_collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Load font failed with HRESULT of %08X!", hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CreateFontCollection(FontCollection& collection, Vector<Resource> const& res_arr)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!d2d_res_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
LPVOID collection_key = nullptr;
|
||||||
|
UINT32 collection_key_size = 0;
|
||||||
|
|
||||||
|
hr = res_font_collection_loader_->AddResources(res_arr, &collection_key, &collection_key_size);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ComPtr<IDWriteFontCollection> font_collection;
|
||||||
|
hr = d2d_res_->GetDWriteFactory()->CreateCustomFontCollection(
|
||||||
|
res_font_collection_loader_.get(),
|
||||||
|
collection_key,
|
||||||
|
collection_key_size,
|
||||||
|
&font_collection
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
collection.SetFontCollection(font_collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
KGE_WARNING_LOG(L"Load font failed with HRESULT of %08X!", hr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CreateTextFormat(TextFormat& format, Font const& font)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!d2d_res_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<IDWriteTextFormat> output;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = d2d_res_->CreateTextFormat(output, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
format.SetTextFormat(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThrowIfFailed(hr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Renderer::CreateTextLayout(TextLayout& layout, String const& text, TextStyle const& style, TextFormat const& format)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
if (!d2d_res_)
|
||||||
|
{
|
||||||
|
hr = E_UNEXPECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ComPtr<IDWriteTextLayout> output;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = d2d_res_->CreateTextLayout(
|
||||||
|
output,
|
||||||
|
text,
|
||||||
|
style,
|
||||||
|
format.GetTextFormat()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
layout.SetTextLayout(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
ThrowIfFailed(hr);
|
||||||
|
|
@ -248,7 +507,7 @@ namespace kiwano
|
||||||
void Renderer::CreateLineGeometry(Geometry& geo, Point const& begin_pos, Point const& end_pos)
|
void Renderer::CreateLineGeometry(Geometry& geo, Point const& begin_pos, Point const& end_pos)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!device_context_ || !d2d_res_)
|
if (!d2d_res_)
|
||||||
{
|
{
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
@ -284,7 +543,7 @@ namespace kiwano
|
||||||
void Renderer::CreateRectGeometry(Geometry& geo, Rect const& rect)
|
void Renderer::CreateRectGeometry(Geometry& geo, Rect const& rect)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!device_context_ || !d2d_res_)
|
if (!d2d_res_)
|
||||||
{
|
{
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
@ -306,7 +565,7 @@ namespace kiwano
|
||||||
void Renderer::CreateRoundedRectGeometry(Geometry& geo, Rect const& rect, Vec2 const& radius)
|
void Renderer::CreateRoundedRectGeometry(Geometry& geo, Rect const& rect, Vec2 const& radius)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!device_context_ || !d2d_res_)
|
if (!d2d_res_)
|
||||||
{
|
{
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
@ -334,7 +593,7 @@ namespace kiwano
|
||||||
void Renderer::CreateEllipseGeometry(Geometry& geo, Point const& center, Vec2 const& radius)
|
void Renderer::CreateEllipseGeometry(Geometry& geo, Point const& center, Vec2 const& radius)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!device_context_ || !d2d_res_)
|
if (!d2d_res_)
|
||||||
{
|
{
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
@ -362,7 +621,7 @@ namespace kiwano
|
||||||
void Renderer::CreatePathGeometrySink(GeometrySink& sink)
|
void Renderer::CreatePathGeometrySink(GeometrySink& sink)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!device_context_ || !d2d_res_)
|
if (!d2d_res_)
|
||||||
{
|
{
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
@ -381,138 +640,23 @@ namespace kiwano
|
||||||
ThrowIfFailed(hr);
|
ThrowIfFailed(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DrawGeometry(
|
void Renderer::CreateImageRenderTarget(ImageRenderTarget& render_target)
|
||||||
Geometry const& geometry,
|
|
||||||
Color const& stroke_color,
|
|
||||||
float stroke_width,
|
|
||||||
StrokeStyle stroke
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
if (!solid_color_brush_ || !device_context_)
|
if (!d2d_res_)
|
||||||
{
|
{
|
||||||
hr = E_UNEXPECTED;
|
hr = E_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr) && geometry.GetGeometry())
|
ComPtr<ID2D1BitmapRenderTarget> output;
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
|
hr = d2d_res_->GetDeviceContext()->CreateCompatibleRenderTarget(&output);
|
||||||
|
|
||||||
device_context_->DrawGeometry(
|
|
||||||
geometry.GetGeometry().get(),
|
|
||||||
solid_color_brush_.get(),
|
|
||||||
stroke_width,
|
|
||||||
d2d_res_->GetStrokeStyle(stroke)
|
|
||||||
);
|
|
||||||
|
|
||||||
IncreasePrimitivesCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::FillGeometry(Geometry const & geometry, Color const& fill_color)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!solid_color_brush_ || !device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr) && geometry.GetGeometry())
|
|
||||||
{
|
|
||||||
solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
|
|
||||||
device_context_->FillGeometry(
|
|
||||||
geometry.GetGeometry().get(),
|
|
||||||
solid_color_brush_.get()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::DrawRectangle(Rect const& rect, Color const& stroke_color, float stroke_width, StrokeStyle stroke)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!solid_color_brush_ || !device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
solid_color_brush_->SetColor(DX::ConvertToColorF(stroke_color));
|
hr = render_target.InitDeviceResources(output, d2d_res_);
|
||||||
|
|
||||||
device_context_->DrawRectangle(
|
|
||||||
DX::ConvertToRectF(rect),
|
|
||||||
solid_color_brush_.get(),
|
|
||||||
stroke_width,
|
|
||||||
d2d_res_->GetStrokeStyle(stroke)
|
|
||||||
);
|
|
||||||
|
|
||||||
IncreasePrimitivesCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::FillRectangle(Rect const& rect, Color const& fill_color)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!solid_color_brush_ || !device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
solid_color_brush_->SetColor(DX::ConvertToColorF(fill_color));
|
|
||||||
device_context_->FillRectangle(
|
|
||||||
DX::ConvertToRectF(rect),
|
|
||||||
solid_color_brush_.get()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::DrawBitmap(ComPtr<ID2D1Bitmap> const & bitmap, Rect const& src_rect, Rect const& dest_rect)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr) && bitmap)
|
|
||||||
{
|
|
||||||
device_context_->DrawBitmap(
|
|
||||||
bitmap.get(),
|
|
||||||
DX::ConvertToRectF(dest_rect),
|
|
||||||
opacity_,
|
|
||||||
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
|
|
||||||
DX::ConvertToRectF(src_rect)
|
|
||||||
);
|
|
||||||
|
|
||||||
IncreasePrimitivesCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::DrawTextLayout(ComPtr<IDWriteTextLayout> const& text_layout)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!text_renderer_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = text_layout->Draw(nullptr, text_renderer_.get(), 0, 0);
|
|
||||||
|
|
||||||
IncreasePrimitivesCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
ThrowIfFailed(hr);
|
||||||
|
|
@ -523,85 +667,6 @@ namespace kiwano
|
||||||
vsync_ = enabled;
|
vsync_ = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::PushClip(const Matrix3x2 & clip_matrix, const Size & clip_size)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
device_context_->SetTransform(DX::ConvertToMatrix3x2F(clip_matrix));
|
|
||||||
device_context_->PushAxisAlignedClip(
|
|
||||||
D2D1::RectF(0, 0, clip_size.x, clip_size.y),
|
|
||||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::PopClip()
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
device_context_->PopAxisAlignedClip();
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::PushLayer(ComPtr<ID2D1Layer> const& layer, LayerProperties const& properties)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!device_context_ || !solid_color_brush_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
device_context_->PushLayer(
|
|
||||||
D2D1::LayerParameters(
|
|
||||||
DX::ConvertToRectF(properties.area),
|
|
||||||
nullptr,
|
|
||||||
D2D1_ANTIALIAS_MODE_PER_PRIMITIVE,
|
|
||||||
D2D1::Matrix3x2F::Identity(),
|
|
||||||
properties.opacity,
|
|
||||||
nullptr,
|
|
||||||
D2D1_LAYER_OPTIONS_NONE
|
|
||||||
),
|
|
||||||
layer.get()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::PopLayer()
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
device_context_->PopLayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::Resize(UINT width, UINT height)
|
void Renderer::Resize(UINT width, UINT height)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
@ -620,136 +685,11 @@ namespace kiwano
|
||||||
ThrowIfFailed(hr);
|
ThrowIfFailed(hr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetCollectingStatus(bool collecting)
|
void Renderer::SetClearColor(const Color& color)
|
||||||
{
|
|
||||||
collecting_status_ = collecting;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetClearColor(const Color & color)
|
|
||||||
{
|
{
|
||||||
clear_color_ = color;
|
clear_color_ = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::SetTransform(const Matrix3x2 & matrix)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
device_context_->SetTransform(DX::ConvertToMatrix3x2F(&matrix));
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetOpacity(float opacity)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!solid_color_brush_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
if (opacity_ != opacity)
|
|
||||||
{
|
|
||||||
opacity_ = opacity;
|
|
||||||
solid_color_brush_->SetOpacity(opacity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetTextStyle(
|
|
||||||
float opacity,
|
|
||||||
Color const& color,
|
|
||||||
bool has_outline,
|
|
||||||
Color const& outline_color,
|
|
||||||
float outline_width,
|
|
||||||
StrokeStyle outline_stroke
|
|
||||||
)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!text_renderer_ || !d3d_res_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
text_renderer_->SetTextStyle(
|
|
||||||
opacity,
|
|
||||||
DX::ConvertToColorF(color),
|
|
||||||
has_outline,
|
|
||||||
DX::ConvertToColorF(outline_color),
|
|
||||||
outline_width,
|
|
||||||
d2d_res_->GetStrokeStyle(outline_stroke)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetAntialiasMode(bool enabled)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
device_context_->SetAntialiasMode(
|
|
||||||
enabled ? D2D1_ANTIALIAS_MODE_PER_PRIMITIVE : D2D1_ANTIALIAS_MODE_ALIASED
|
|
||||||
);
|
|
||||||
antialias_ = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::SetTextAntialiasMode(TextAntialias mode)
|
|
||||||
{
|
|
||||||
HRESULT hr = S_OK;
|
|
||||||
if (!device_context_)
|
|
||||||
{
|
|
||||||
hr = E_UNEXPECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
text_antialias_ = mode;
|
|
||||||
D2D1_TEXT_ANTIALIAS_MODE antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
|
||||||
switch (text_antialias_)
|
|
||||||
{
|
|
||||||
case TextAntialias::Default:
|
|
||||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
|
|
||||||
break;
|
|
||||||
case TextAntialias::ClearType:
|
|
||||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
|
|
||||||
break;
|
|
||||||
case TextAntialias::GrayScale:
|
|
||||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
|
|
||||||
break;
|
|
||||||
case TextAntialias::None:
|
|
||||||
antialias_mode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
device_context_->SetTextAntialiasMode(antialias_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThrowIfFailed(hr);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Renderer::CheckVisibility(Size const& content_size, Matrix3x2 const& transform)
|
bool Renderer::CheckVisibility(Size const& content_size, Matrix3x2 const& transform)
|
||||||
{
|
{
|
||||||
return Rect{ Point{}, output_size_ }.Intersects(
|
return Rect{ Point{}, output_size_ }.Intersects(
|
||||||
|
|
|
||||||
|
|
@ -19,21 +19,15 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../base/time.h"
|
|
||||||
#include "../base/Component.h"
|
#include "../base/Component.h"
|
||||||
#include "../base/Resource.h"
|
#include "win32/FontCollectionLoader.h"
|
||||||
#include "../2d/include-forwards.h"
|
#include "RenderTarget.h"
|
||||||
#include "../2d/Font.hpp"
|
#include "GifImage.h"
|
||||||
#include "../2d/TextStyle.hpp"
|
|
||||||
#include "helper.hpp"
|
|
||||||
#include "Image.h"
|
|
||||||
#include "Geometry.h"
|
|
||||||
#include "TextRenderer.h"
|
|
||||||
|
|
||||||
#if defined(KGE_USE_DIRECTX10)
|
#if defined(KGE_USE_DIRECTX10)
|
||||||
# include "D3D10DeviceResources.h"
|
# include "D3D10DeviceResources.h"
|
||||||
#else
|
#else
|
||||||
# include "D3D11DeviceResources.h"
|
# include "win32/D3D11DeviceResources.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
|
|
@ -48,12 +42,62 @@ namespace kiwano
|
||||||
class KGE_API Renderer
|
class KGE_API Renderer
|
||||||
: public Singleton<Renderer>
|
: public Singleton<Renderer>
|
||||||
, public Component
|
, public Component
|
||||||
|
, public RenderTarget
|
||||||
{
|
{
|
||||||
KGE_DECLARE_SINGLETON(Renderer);
|
KGE_DECLARE_SINGLETON(Renderer);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void CreateLayer(
|
// 设置清屏颜色
|
||||||
ComPtr<ID2D1Layer>& layer
|
void SetClearColor(
|
||||||
|
Color const& clear_color
|
||||||
|
);
|
||||||
|
|
||||||
|
// 开启或关闭垂直同步
|
||||||
|
void SetVSyncEnabled(
|
||||||
|
bool enabled
|
||||||
|
);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void CreateImage(
|
||||||
|
Image& image,
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
|
void CreateImage(
|
||||||
|
Image& image,
|
||||||
|
Resource const& res
|
||||||
|
);
|
||||||
|
|
||||||
|
void CreateGifImage(
|
||||||
|
GifImage& image,
|
||||||
|
String const& file_path
|
||||||
|
);
|
||||||
|
|
||||||
|
void CreateGifImage(
|
||||||
|
GifImage& image,
|
||||||
|
Resource const& res
|
||||||
|
);
|
||||||
|
|
||||||
|
void CreateFontCollection(
|
||||||
|
FontCollection& collection,
|
||||||
|
Vector<String> const& file_paths
|
||||||
|
);
|
||||||
|
|
||||||
|
void CreateFontCollection(
|
||||||
|
FontCollection& collection,
|
||||||
|
Vector<Resource> const& res_arr
|
||||||
|
);
|
||||||
|
|
||||||
|
void CreateTextFormat(
|
||||||
|
TextFormat& format,
|
||||||
|
Font const& font
|
||||||
|
);
|
||||||
|
|
||||||
|
void CreateTextLayout(
|
||||||
|
TextLayout& layout,
|
||||||
|
String const& text,
|
||||||
|
TextStyle const& style,
|
||||||
|
TextFormat const& format
|
||||||
);
|
);
|
||||||
|
|
||||||
void CreateLineGeometry(
|
void CreateLineGeometry(
|
||||||
|
|
@ -83,92 +127,10 @@ namespace kiwano
|
||||||
GeometrySink& sink
|
GeometrySink& sink
|
||||||
);
|
);
|
||||||
|
|
||||||
void DrawGeometry(
|
void CreateImageRenderTarget(
|
||||||
Geometry const& geometry,
|
ImageRenderTarget& render_target
|
||||||
const Color& stroke_color,
|
|
||||||
float stroke_width,
|
|
||||||
StrokeStyle stroke = StrokeStyle::Miter
|
|
||||||
);
|
);
|
||||||
|
|
||||||
void FillGeometry(
|
|
||||||
Geometry const& geometry,
|
|
||||||
Color const& fill_color
|
|
||||||
);
|
|
||||||
|
|
||||||
void DrawRectangle(
|
|
||||||
Rect const& rect,
|
|
||||||
Color const& stroke_color,
|
|
||||||
float stroke_width,
|
|
||||||
StrokeStyle stroke = StrokeStyle::Miter
|
|
||||||
);
|
|
||||||
|
|
||||||
void FillRectangle(
|
|
||||||
Rect const& rect,
|
|
||||||
Color const& fill_color
|
|
||||||
);
|
|
||||||
|
|
||||||
void DrawBitmap(
|
|
||||||
ComPtr<ID2D1Bitmap> const& bitmap,
|
|
||||||
Rect const& src_rect,
|
|
||||||
Rect const& dest_rect
|
|
||||||
);
|
|
||||||
|
|
||||||
void DrawTextLayout(
|
|
||||||
ComPtr<IDWriteTextLayout> const& text_layout
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置清屏颜色
|
|
||||||
void SetClearColor(
|
|
||||||
Color const& clear_color
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置抗锯齿模式
|
|
||||||
void SetAntialiasMode(
|
|
||||||
bool enabled
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置文字抗锯齿模式
|
|
||||||
void SetTextAntialiasMode(
|
|
||||||
TextAntialias mode
|
|
||||||
);
|
|
||||||
|
|
||||||
// 开启或关闭垂直同步
|
|
||||||
void SetVSyncEnabled(
|
|
||||||
bool enabled
|
|
||||||
);
|
|
||||||
|
|
||||||
// 设置画笔透明度
|
|
||||||
void SetOpacity(
|
|
||||||
float opacity
|
|
||||||
);
|
|
||||||
|
|
||||||
void SetTransform(
|
|
||||||
const Matrix3x2& matrix
|
|
||||||
);
|
|
||||||
|
|
||||||
void SetTextStyle(
|
|
||||||
float opacity,
|
|
||||||
const Color& color,
|
|
||||||
bool has_outline,
|
|
||||||
const Color& outline_color,
|
|
||||||
float outline_width,
|
|
||||||
StrokeStyle outline_stroke
|
|
||||||
);
|
|
||||||
|
|
||||||
void PushClip(
|
|
||||||
const Matrix3x2& clip_matrix,
|
|
||||||
const Size& clip_size
|
|
||||||
);
|
|
||||||
|
|
||||||
void PopClip();
|
|
||||||
|
|
||||||
void PushLayer(
|
|
||||||
ComPtr<ID2D1Layer> const& layer,
|
|
||||||
LayerProperties const& properties
|
|
||||||
);
|
|
||||||
|
|
||||||
void PopLayer();
|
|
||||||
|
|
||||||
void Resize(
|
void Resize(
|
||||||
UINT width,
|
UINT width,
|
||||||
UINT height
|
UINT height
|
||||||
|
|
@ -190,20 +152,9 @@ namespace kiwano
|
||||||
|
|
||||||
void HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override;
|
void HandleMessage(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) override;
|
||||||
|
|
||||||
void SetCollectingStatus(bool collecting);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Status
|
|
||||||
{
|
|
||||||
Time start;
|
|
||||||
Duration duration;
|
|
||||||
int primitives;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline HWND GetTargetWindow() const { return hwnd_; }
|
inline HWND GetTargetWindow() const { return hwnd_; }
|
||||||
|
|
||||||
inline Status const& GetStatus() const { return status_; }
|
|
||||||
|
|
||||||
inline Size const& GetOutputSize() const { return output_size_; }
|
inline Size const& GetOutputSize() const { return output_size_; }
|
||||||
|
|
||||||
inline ID2DDeviceResources* GetD2DDeviceResources() const { KGE_ASSERT(d2d_res_); return d2d_res_.get(); }
|
inline ID2DDeviceResources* GetD2DDeviceResources() const { KGE_ASSERT(d2d_res_); return d2d_res_.get(); }
|
||||||
|
|
@ -223,28 +174,18 @@ namespace kiwano
|
||||||
|
|
||||||
HRESULT HandleDeviceLost();
|
HRESULT HandleDeviceLost();
|
||||||
|
|
||||||
HRESULT BeginDraw();
|
|
||||||
|
|
||||||
HRESULT EndDraw();
|
|
||||||
|
|
||||||
void IncreasePrimitivesCount();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool vsync_;
|
bool vsync_;
|
||||||
bool antialias_;
|
|
||||||
bool collecting_status_;
|
|
||||||
float opacity_;
|
|
||||||
HWND hwnd_;
|
HWND hwnd_;
|
||||||
Size output_size_;
|
Size output_size_;
|
||||||
Color clear_color_;
|
Color clear_color_;
|
||||||
TextAntialias text_antialias_;
|
|
||||||
Status status_;
|
|
||||||
|
|
||||||
ComPtr<ID2DDeviceResources> d2d_res_;
|
ComPtr<ID2DDeviceResources> d2d_res_;
|
||||||
ComPtr<ID3DDeviceResources> d3d_res_;
|
ComPtr<ID3DDeviceResources> d3d_res_;
|
||||||
ComPtr<ID2D1DeviceContext> device_context_;
|
|
||||||
ComPtr<ID2D1DrawingStateBlock> drawing_state_block_;
|
ComPtr<ID2D1DrawingStateBlock> drawing_state_block_;
|
||||||
ComPtr<ITextRenderer> text_renderer_;
|
|
||||||
ComPtr<ID2D1SolidColorBrush> solid_color_brush_;
|
ComPtr<IFontCollectionLoader> font_collection_loader_;
|
||||||
|
ComPtr<IResourceFontFileLoader> res_font_file_loader_;
|
||||||
|
ComPtr<IResourceFontCollectionLoader> res_font_collection_loader_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
// 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 "TextLayout.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "../base/Logger.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// TextFormat
|
||||||
|
//
|
||||||
|
|
||||||
|
TextFormat::TextFormat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TextFormat::TextFormat(Font const& font)
|
||||||
|
{
|
||||||
|
Update(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextFormat::Update(Font const& font)
|
||||||
|
{
|
||||||
|
Renderer::GetInstance()->CreateTextFormat(*this, font);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// TextLayout
|
||||||
|
//
|
||||||
|
|
||||||
|
TextLayout::TextLayout()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TextLayout::TextLayout(String const& text, Font const& font, TextStyle const& style)
|
||||||
|
{
|
||||||
|
Update(font);
|
||||||
|
Update(text, style);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextLayout::Update(Font const& font)
|
||||||
|
{
|
||||||
|
text_format_.Update(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextLayout::Update(String const& text, TextStyle const& style)
|
||||||
|
{
|
||||||
|
style_ = style;
|
||||||
|
|
||||||
|
if (text.empty())
|
||||||
|
{
|
||||||
|
text_format_.SetTextFormat(nullptr);
|
||||||
|
SetTextLayout(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Renderer::GetInstance()->CreateTextLayout(
|
||||||
|
*this,
|
||||||
|
text,
|
||||||
|
style,
|
||||||
|
text_format_
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 TextLayout::GetLineCount()
|
||||||
|
{
|
||||||
|
if (text_layout_)
|
||||||
|
{
|
||||||
|
DWRITE_TEXT_METRICS metrics;
|
||||||
|
if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
|
||||||
|
{
|
||||||
|
return metrics.lineCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size TextLayout::GetLayoutSize() const
|
||||||
|
{
|
||||||
|
if (text_layout_)
|
||||||
|
{
|
||||||
|
DWRITE_TEXT_METRICS metrics;
|
||||||
|
if (SUCCEEDED(text_layout_->GetMetrics(&metrics)))
|
||||||
|
{
|
||||||
|
return (metrics.layoutWidth > 0) ? Size(metrics.layoutWidth, metrics.height) : Size(metrics.width, metrics.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
// 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 "Font.h"
|
||||||
|
#include "../2d/TextStyle.hpp"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
// Îı¾¸ñʽ»¯
|
||||||
|
class KGE_API TextFormat
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextFormat();
|
||||||
|
|
||||||
|
TextFormat(Font const& font);
|
||||||
|
|
||||||
|
void Update(Font const& font);
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline ComPtr<IDWriteTextFormat> GetTextFormat() const { return text_format_; }
|
||||||
|
|
||||||
|
inline void SetTextFormat(ComPtr<IDWriteTextFormat> format) { text_format_ = format; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ComPtr<IDWriteTextFormat> text_format_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Îı¾²¼¾Ö
|
||||||
|
class KGE_API TextLayout
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextLayout();
|
||||||
|
|
||||||
|
TextLayout(String const& text, Font const& font, TextStyle const& style);
|
||||||
|
|
||||||
|
void Update(Font const& font);
|
||||||
|
|
||||||
|
void Update(String const& text, TextStyle const& style);
|
||||||
|
|
||||||
|
UINT32 GetLineCount();
|
||||||
|
|
||||||
|
Size GetLayoutSize() const;
|
||||||
|
|
||||||
|
inline TextStyle const& GetTextStyle() const { return style_; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
inline TextFormat GetTextFormat() const { return text_format_; }
|
||||||
|
|
||||||
|
inline ComPtr<IDWriteTextLayout> GetTextLayout() const { return text_layout_; }
|
||||||
|
|
||||||
|
inline void SetTextLayout(ComPtr<IDWriteTextLayout> layout) { text_layout_ = layout; }
|
||||||
|
|
||||||
|
inline operator bool() const { return static_cast<bool>(text_layout_); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
TextStyle style_;
|
||||||
|
TextFormat text_format_;
|
||||||
|
ComPtr<IDWriteTextLayout> text_layout_;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../core/intrusive_ptr.hpp"
|
#include "../../core/intrusive_ptr.hpp"
|
||||||
#include <Unknwnbase.h>
|
#include <Unknwnbase.h>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
|
@ -19,9 +19,8 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include "D2DDeviceResources.h"
|
#include "D2DDeviceResources.h"
|
||||||
#include "ImageCache.h"
|
#include "../../base/Logger.h"
|
||||||
#include "../base/Logger.h"
|
#include "../../utils/FileUtil.h"
|
||||||
#include "../utils/FileUtil.h"
|
|
||||||
|
|
||||||
#pragma comment(lib, "d2d1.lib")
|
#pragma comment(lib, "d2d1.lib")
|
||||||
#pragma comment(lib, "dwrite.lib")
|
#pragma comment(lib, "dwrite.lib")
|
||||||
|
|
@ -51,16 +50,14 @@ namespace kiwano
|
||||||
|
|
||||||
HRESULT CreateTextFormat(
|
HRESULT CreateTextFormat(
|
||||||
_Out_ ComPtr<IDWriteTextFormat>& text_format,
|
_Out_ ComPtr<IDWriteTextFormat>& text_format,
|
||||||
_In_ Font const& font,
|
_In_ Font const& font
|
||||||
_In_ TextStyle const& text_style
|
|
||||||
) const override;
|
) const override;
|
||||||
|
|
||||||
HRESULT CreateTextLayout(
|
HRESULT CreateTextLayout(
|
||||||
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
|
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
|
||||||
_Out_ Size& layout_size,
|
|
||||||
_In_ String const& text,
|
_In_ String const& text,
|
||||||
_In_ ComPtr<IDWriteTextFormat> const& text_format,
|
_In_ TextStyle const& text_style,
|
||||||
_In_ TextStyle const& text_style
|
_In_ ComPtr<IDWriteTextFormat> const& text_format
|
||||||
) const override;
|
) const override;
|
||||||
|
|
||||||
HRESULT SetD2DDevice(
|
HRESULT SetD2DDevice(
|
||||||
|
|
@ -110,7 +107,10 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
res->AddRef();
|
res->AddRef();
|
||||||
|
|
||||||
DX::SafeRelease(*device_resources);
|
if (*device_resources)
|
||||||
|
{
|
||||||
|
(*device_resources)->Release();
|
||||||
|
}
|
||||||
(*device_resources) = res;
|
(*device_resources) = res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -174,8 +174,6 @@ namespace kiwano
|
||||||
|
|
||||||
void D2DDeviceResources::DiscardResources()
|
void D2DDeviceResources::DiscardResources()
|
||||||
{
|
{
|
||||||
ImageCache::GetInstance()->Clear();
|
|
||||||
|
|
||||||
factory_.reset();
|
factory_.reset();
|
||||||
device_.reset();
|
device_.reset();
|
||||||
device_context_.reset();
|
device_context_.reset();
|
||||||
|
|
@ -394,9 +392,8 @@ namespace kiwano
|
||||||
ComPtr<ID2D1Bitmap> bitmap_tmp;
|
ComPtr<ID2D1Bitmap> bitmap_tmp;
|
||||||
|
|
||||||
// ¼ÓÔØ×ÊÔ´
|
// ¼ÓÔØ×ÊÔ´
|
||||||
LPVOID buffer;
|
Resource::Data res_data = res.GetData();
|
||||||
DWORD buffer_size;
|
HRESULT hr = res_data ? S_OK : E_FAIL;
|
||||||
HRESULT hr = res.Load(buffer, buffer_size) ? S_OK : E_FAIL;
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
@ -406,8 +403,8 @@ namespace kiwano
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = stream->InitializeFromMemory(
|
hr = stream->InitializeFromMemory(
|
||||||
static_cast<WICInProcPointer>(buffer),
|
static_cast<WICInProcPointer>(res_data.buffer),
|
||||||
buffer_size
|
res_data.size
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -460,59 +457,41 @@ namespace kiwano
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat> & text_format,
|
HRESULT D2DDeviceResources::CreateTextFormat(_Out_ ComPtr<IDWriteTextFormat> & text_format, _In_ Font const & font) const
|
||||||
_In_ Font const & font, _In_ TextStyle const & text_style) const
|
|
||||||
{
|
{
|
||||||
if (!dwrite_factory_)
|
if (!dwrite_factory_)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
ComPtr<IDWriteTextFormat> text_format_tmp;
|
ComPtr<IDWriteTextFormat> output;
|
||||||
HRESULT hr = dwrite_factory_->CreateTextFormat(
|
HRESULT hr = dwrite_factory_->CreateTextFormat(
|
||||||
font.family.c_str(),
|
font.family.c_str(),
|
||||||
nullptr,
|
font.collection.GetFontCollection().get(),
|
||||||
DWRITE_FONT_WEIGHT(font.weight),
|
DWRITE_FONT_WEIGHT(font.weight),
|
||||||
font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
|
font.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL,
|
||||||
DWRITE_FONT_STRETCH_NORMAL,
|
DWRITE_FONT_STRETCH_NORMAL,
|
||||||
font.size,
|
font.size,
|
||||||
L"",
|
L"en-us",
|
||||||
&text_format_tmp
|
&output
|
||||||
);
|
);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
if (text_style.line_spacing == 0.f)
|
text_format = output;
|
||||||
{
|
|
||||||
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;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout,
|
HRESULT D2DDeviceResources::CreateTextLayout(_Out_ ComPtr<IDWriteTextLayout> & text_layout, _In_ String const & text,
|
||||||
_Out_ Size& layout_size, _In_ String const & text, _In_ ComPtr<IDWriteTextFormat> const& text_format,
|
_In_ TextStyle const & text_style, _In_ ComPtr<IDWriteTextFormat> const& text_format) const
|
||||||
_In_ TextStyle const & text_style) const
|
|
||||||
{
|
{
|
||||||
if (!dwrite_factory_)
|
if (!dwrite_factory_)
|
||||||
return E_UNEXPECTED;
|
return E_UNEXPECTED;
|
||||||
|
|
||||||
text_layout = nullptr;
|
|
||||||
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
ComPtr<IDWriteTextLayout> text_layout_tmp;
|
ComPtr<IDWriteTextLayout> output;
|
||||||
UINT32 length = static_cast<UINT32>(text.length());
|
UINT32 length = static_cast<UINT32>(text.length());
|
||||||
|
|
||||||
if (text_style.wrap)
|
if (text_style.wrap_width > 0)
|
||||||
{
|
{
|
||||||
hr = dwrite_factory_->CreateTextLayout(
|
hr = dwrite_factory_->CreateTextLayout(
|
||||||
text.c_str(),
|
text.c_str(),
|
||||||
|
|
@ -520,7 +499,7 @@ namespace kiwano
|
||||||
text_format.get(),
|
text_format.get(),
|
||||||
text_style.wrap_width,
|
text_style.wrap_width,
|
||||||
0,
|
0,
|
||||||
&text_layout_tmp
|
&output
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -531,53 +510,70 @@ namespace kiwano
|
||||||
text_format.get(),
|
text_format.get(),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
&text_layout_tmp
|
&output
|
||||||
);
|
|
||||||
|
|
||||||
DWRITE_TEXT_METRICS metrics;
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
hr = text_layout_tmp->GetMetrics(&metrics);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
text_layout_tmp = nullptr;
|
|
||||||
hr = dwrite_factory_->CreateTextLayout(
|
|
||||||
text.c_str(),
|
|
||||||
length,
|
|
||||||
text_format.get(),
|
|
||||||
metrics.width,
|
|
||||||
0,
|
|
||||||
&text_layout_tmp
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
DWRITE_TEXT_METRICS metrics;
|
if (text_style.line_spacing == 0.f)
|
||||||
text_layout_tmp->GetMetrics(&metrics);
|
|
||||||
|
|
||||||
if (text_style.wrap)
|
|
||||||
{
|
{
|
||||||
layout_size = Size(metrics.layoutWidth, metrics.height);
|
hr = output->SetLineSpacing(DWRITE_LINE_SPACING_METHOD_DEFAULT, 0, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
layout_size = Size(metrics.width, metrics.height);
|
hr = output->SetLineSpacing(
|
||||||
|
DWRITE_LINE_SPACING_METHOD_UNIFORM,
|
||||||
|
text_style.line_spacing,
|
||||||
|
text_style.line_spacing * 0.8f
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWRITE_TEXT_RANGE range = { 0, length };
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = output->SetTextAlignment(DWRITE_TEXT_ALIGNMENT(text_style.alignment));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = output->SetWordWrapping((text_style.wrap_width > 0) ? DWRITE_WORD_WRAPPING_WRAP : DWRITE_WORD_WRAPPING_NO_WRAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
if (text_style.underline)
|
if (text_style.underline)
|
||||||
{
|
{
|
||||||
text_layout_tmp->SetUnderline(true, range);
|
hr = output->SetUnderline(true, { 0, length });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
if (text_style.strikethrough)
|
if (text_style.strikethrough)
|
||||||
{
|
{
|
||||||
text_layout_tmp->SetStrikethrough(true, range);
|
output->SetStrikethrough(true, { 0, length });
|
||||||
}
|
}
|
||||||
text_layout = text_layout_tmp;
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// Fix the layout width when the text does not wrap
|
||||||
|
if (!(text_style.wrap_width > 0))
|
||||||
|
{
|
||||||
|
DWRITE_TEXT_METRICS metrics;
|
||||||
|
hr = output->GetMetrics(&metrics);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = output->SetMaxWidth(metrics.width);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
text_layout = output;
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
@ -19,10 +19,14 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../base/ComPtr.hpp"
|
#include "../Font.h"
|
||||||
#include "../math/helper.h"
|
#include "../Color.h"
|
||||||
#include "../2d/Color.h"
|
#include "../../math/math.h"
|
||||||
|
#include "../../base/Resource.h"
|
||||||
|
#include "../../2d/TextStyle.hpp"
|
||||||
|
#include <dwrite.h>
|
||||||
#include <d2d1.h>
|
#include <d2d1.h>
|
||||||
|
#include <d2d1_1.h>
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -38,6 +42,16 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline T* SafeAcquire(T* ptr)
|
||||||
|
{
|
||||||
|
if (ptr != nullptr)
|
||||||
|
{
|
||||||
|
ptr->AddRef();
|
||||||
|
}
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Point2F
|
// Point2F
|
||||||
//
|
//
|
||||||
|
|
@ -150,3 +164,65 @@ namespace kiwano
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
MIDL_INTERFACE("5706684a-bf6d-4b03-b627-094758a33032")
|
||||||
|
KGE_API ID2DDeviceResources
|
||||||
|
: public IUnknown
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static HRESULT Create(ID2DDeviceResources** device_resources);
|
||||||
|
|
||||||
|
virtual HRESULT CreateBitmapFromFile(
|
||||||
|
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
||||||
|
_In_ String const& file_path
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual HRESULT CreateBitmapFromResource(
|
||||||
|
_Out_ ComPtr<ID2D1Bitmap>& bitmap,
|
||||||
|
_In_ Resource const& res
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual HRESULT CreateTextFormat(
|
||||||
|
_Out_ ComPtr<IDWriteTextFormat>& text_format,
|
||||||
|
_In_ Font const& font
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual HRESULT CreateTextLayout(
|
||||||
|
_Out_ ComPtr<IDWriteTextLayout>& text_layout,
|
||||||
|
_In_ String const& text,
|
||||||
|
_In_ TextStyle const& text_style,
|
||||||
|
_In_ ComPtr<IDWriteTextFormat> const& text_format
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
virtual ID2D1StrokeStyle* GetStrokeStyle(StrokeStyle stroke) const = 0;
|
||||||
|
|
||||||
|
virtual HRESULT SetD2DDevice(
|
||||||
|
_In_ ComPtr<ID2D1Device> const& device
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual void SetTargetBitmap(
|
||||||
|
_In_ ComPtr<ID2D1Bitmap1> const& target
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
virtual void DiscardResources() = 0;
|
||||||
|
|
||||||
|
inline ID2D1Factory1* GetFactory() const { KGE_ASSERT(factory_); return factory_.get(); }
|
||||||
|
inline IWICImagingFactory* GetWICImagingFactory() const { KGE_ASSERT(imaging_factory_); return imaging_factory_.get(); }
|
||||||
|
inline IDWriteFactory* GetDWriteFactory() const { KGE_ASSERT(dwrite_factory_); return dwrite_factory_.get(); }
|
||||||
|
inline ID2D1Device* GetDevice() const { KGE_ASSERT(device_); return device_.get(); }
|
||||||
|
inline ID2D1DeviceContext* GetDeviceContext() const { KGE_ASSERT(device_context_); return device_context_.get(); }
|
||||||
|
inline ID2D1Bitmap1* GetTargetBitmap() const { KGE_ASSERT(target_bitmap_); return target_bitmap_.get(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ComPtr<ID2D1Factory1> factory_;
|
||||||
|
ComPtr<ID2D1Device> device_;
|
||||||
|
ComPtr<ID2D1DeviceContext> device_context_;
|
||||||
|
ComPtr<ID2D1Bitmap1> target_bitmap_;
|
||||||
|
|
||||||
|
ComPtr<IWICImagingFactory> imaging_factory_;
|
||||||
|
ComPtr<IDWriteFactory> dwrite_factory_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include "D3D10DeviceResources.h"
|
#include "D3D10DeviceResources.h"
|
||||||
|
|
||||||
#include "../base/Logger.h"
|
#include "../../base/Logger.h"
|
||||||
|
|
||||||
#pragma comment(lib, "d3d10_1.lib")
|
#pragma comment(lib, "d3d10_1.lib")
|
||||||
|
|
||||||
|
|
@ -163,7 +163,10 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
res->AddRef();
|
res->AddRef();
|
||||||
|
|
||||||
DX::SafeRelease(*device_resources);
|
if (*device_resources)
|
||||||
|
{
|
||||||
|
(*device_resources)->Release();
|
||||||
|
}
|
||||||
(*device_resources) = res;
|
(*device_resources) = res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../macros.h"
|
#include "../../macros.h"
|
||||||
|
|
||||||
#include "D2DDeviceResources.h"
|
#include "D2DDeviceResources.h"
|
||||||
#include "D3DDeviceResourcesBase.h"
|
#include "D3DDeviceResourcesBase.h"
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include "D3D11DeviceResources.h"
|
#include "D3D11DeviceResources.h"
|
||||||
|
|
||||||
#include "../base/Logger.h"
|
#include "../../base/Logger.h"
|
||||||
#include <versionhelpers.h> // IsWindows10OrGreater
|
#include <versionhelpers.h> // IsWindows10OrGreater
|
||||||
|
|
||||||
#pragma comment(lib, "d3d11.lib")
|
#pragma comment(lib, "d3d11.lib")
|
||||||
|
|
@ -140,7 +140,10 @@ namespace kiwano
|
||||||
{
|
{
|
||||||
res->AddRef();
|
res->AddRef();
|
||||||
|
|
||||||
DX::SafeRelease(*device_resources);
|
if (*device_resources)
|
||||||
|
{
|
||||||
|
(*device_resources)->Release();
|
||||||
|
}
|
||||||
(*device_resources) = res;
|
(*device_resources) = res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../macros.h"
|
#include "../../macros.h"
|
||||||
|
|
||||||
#include "D2DDeviceResources.h"
|
#include "D2DDeviceResources.h"
|
||||||
#include "D3DDeviceResourcesBase.h"
|
#include "D3DDeviceResourcesBase.h"
|
||||||
|
|
@ -19,16 +19,12 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../macros.h"
|
|
||||||
#include "../math/helper.h"
|
|
||||||
#include "../2d/Color.h"
|
|
||||||
#include <Unknwnbase.h>
|
#include <Unknwnbase.h>
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
||||||
MIDL_INTERFACE("fb99fa64-d9cf-4e0e-9c75-90514797b01d")
|
MIDL_INTERFACE("fb99fa64-d9cf-4e0e-9c75-90514797b01d")
|
||||||
KGE_API ID3DDeviceResourcesBase : public IUnknown
|
ID3DDeviceResourcesBase : public IUnknown
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual HRESULT Present(bool vsync) = 0;
|
virtual HRESULT Present(bool vsync) = 0;
|
||||||
|
|
@ -0,0 +1,985 @@
|
||||||
|
// 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 "FontCollectionLoader.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// FontCollectionLoader
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FontCollectionLoader
|
||||||
|
: public IFontCollectionLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FontCollectionLoader()
|
||||||
|
: refCount_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHOD(AddFilePaths)(
|
||||||
|
Vector<String> const& filePaths,
|
||||||
|
_Out_ LPVOID* pCollectionKey,
|
||||||
|
_Out_ UINT32* pCollectionKeySize
|
||||||
|
);
|
||||||
|
|
||||||
|
// IUnknown methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
|
||||||
|
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
virtual ULONG STDMETHODCALLTYPE Release();
|
||||||
|
|
||||||
|
// IDWriteFontCollectionLoader methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
|
||||||
|
IDWriteFactory* pFactory,
|
||||||
|
void const* collectionKey,
|
||||||
|
UINT32 collectionKeySize,
|
||||||
|
_Out_ IDWriteFontFileEnumerator** fontFileEnumerator
|
||||||
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ULONG refCount_;
|
||||||
|
|
||||||
|
typedef Vector<String> FileCollection;
|
||||||
|
Vector<FileCollection> filePaths_;
|
||||||
|
Vector<UINT32> collectionKeys_;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT IFontCollectionLoader::Create(_Out_ IFontCollectionLoader** ppCollectionLoader)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (!ppCollectionLoader)
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
FontCollectionLoader* pCollectionLoader = new (std::nothrow) FontCollectionLoader;
|
||||||
|
hr = pCollectionLoader ? S_OK : E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DX::SafeRelease(*ppCollectionLoader);
|
||||||
|
(*ppCollectionLoader) = DX::SafeAcquire(pCollectionLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP FontCollectionLoader::AddFilePaths(
|
||||||
|
Vector<String> const& filePaths,
|
||||||
|
_Out_ LPVOID* pCollectionKey,
|
||||||
|
_Out_ UINT32* pCollectionKeySize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!pCollectionKey || !pCollectionKeySize)
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UINT32 collectionKey = filePaths_.size();
|
||||||
|
collectionKeys_.push_back(collectionKey);
|
||||||
|
filePaths_.push_back(filePaths);
|
||||||
|
|
||||||
|
*pCollectionKey = reinterpret_cast<LPVOID>(&collectionKeys_.back());
|
||||||
|
*pCollectionKeySize = sizeof(collectionKey);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE FontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject)
|
||||||
|
{
|
||||||
|
if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader))
|
||||||
|
{
|
||||||
|
*ppvObject = this;
|
||||||
|
AddRef();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppvObject = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE FontCollectionLoader::AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&refCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE FontCollectionLoader::Release()
|
||||||
|
{
|
||||||
|
ULONG newCount = InterlockedDecrement(&refCount_);
|
||||||
|
if (newCount == 0)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
return newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey(
|
||||||
|
IDWriteFactory* pFactory,
|
||||||
|
void const* collectionKey,
|
||||||
|
UINT32 collectionKeySize,
|
||||||
|
_Out_ IDWriteFontFileEnumerator** fontFileEnumerator
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (collectionKey == NULL || collectionKeySize % sizeof(UINT32) != 0)
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
IFontFileEnumerator* pEnumerator = NULL;
|
||||||
|
hr = IFontFileEnumerator::Create(&pEnumerator, pFactory);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
const UINT32 fileIndex = *static_cast<UINT32 const*>(collectionKey);
|
||||||
|
hr = pEnumerator->SetFilePaths(filePaths_[fileIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
*fontFileEnumerator = DX::SafeAcquire(pEnumerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// FontFileEnumerator
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class FontFileEnumerator
|
||||||
|
: public IFontFileEnumerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FontFileEnumerator();
|
||||||
|
|
||||||
|
STDMETHOD(Initialize)(
|
||||||
|
IDWriteFactory* pFactory
|
||||||
|
);
|
||||||
|
|
||||||
|
STDMETHOD(SetFilePaths)(
|
||||||
|
Vector<String> const& filePaths
|
||||||
|
);
|
||||||
|
|
||||||
|
~FontFileEnumerator()
|
||||||
|
{
|
||||||
|
DX::SafeRelease(currentFile_);
|
||||||
|
DX::SafeRelease(pFactory_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IUnknown methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, _Out_ void** ppvObject);
|
||||||
|
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
virtual ULONG STDMETHODCALLTYPE Release();
|
||||||
|
|
||||||
|
// IDWriteFontFileEnumerator methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ BOOL* hasCurrentFile);
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ULONG refCount_;
|
||||||
|
|
||||||
|
IDWriteFactory* pFactory_;
|
||||||
|
IDWriteFontFile* currentFile_;
|
||||||
|
Vector<String> filePaths_;
|
||||||
|
size_t nextIndex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT IFontFileEnumerator::Create(_Out_ IFontFileEnumerator** ppEnumerator, IDWriteFactory* pFactory)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (!ppEnumerator)
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
FontFileEnumerator* pEnumerator = new (std::nothrow) FontFileEnumerator;
|
||||||
|
hr = pEnumerator ? S_OK : E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pEnumerator->Initialize(pFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DX::SafeRelease(*ppEnumerator);
|
||||||
|
(*ppEnumerator) = DX::SafeAcquire(pEnumerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FontFileEnumerator::FontFileEnumerator()
|
||||||
|
: refCount_(0)
|
||||||
|
, pFactory_(NULL)
|
||||||
|
, currentFile_(NULL)
|
||||||
|
, nextIndex_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP FontFileEnumerator::Initialize(
|
||||||
|
IDWriteFactory* pFactory
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (pFactory)
|
||||||
|
{
|
||||||
|
pFactory_ = DX::SafeAcquire(pFactory);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP FontFileEnumerator::SetFilePaths(
|
||||||
|
Vector<String> const& filePaths
|
||||||
|
)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
filePaths_.assign(filePaths);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE FontFileEnumerator::QueryInterface(REFIID iid, _Out_ void** ppvObject)
|
||||||
|
{
|
||||||
|
if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator))
|
||||||
|
{
|
||||||
|
*ppvObject = this;
|
||||||
|
AddRef();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppvObject = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE FontFileEnumerator::AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&refCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE FontFileEnumerator::Release()
|
||||||
|
{
|
||||||
|
ULONG newCount = InterlockedDecrement(&refCount_);
|
||||||
|
if (newCount == 0)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
return newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE FontFileEnumerator::MoveNext(_Out_ BOOL* hasCurrentFile)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
*hasCurrentFile = FALSE;
|
||||||
|
DX::SafeRelease(currentFile_);
|
||||||
|
|
||||||
|
if (nextIndex_ < filePaths_.size())
|
||||||
|
{
|
||||||
|
hr = pFactory_->CreateFontFileReference(
|
||||||
|
filePaths_[nextIndex_].c_str(),
|
||||||
|
NULL,
|
||||||
|
¤tFile_
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
*hasCurrentFile = TRUE;
|
||||||
|
|
||||||
|
++nextIndex_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE FontFileEnumerator::GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile)
|
||||||
|
{
|
||||||
|
*fontFile = DX::SafeAcquire(currentFile_);
|
||||||
|
|
||||||
|
return (currentFile_ != NULL) ? S_OK : E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ResourceFontCollectionLoader
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class ResourceFontCollectionLoader
|
||||||
|
: public IResourceFontCollectionLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ResourceFontCollectionLoader(IDWriteFontFileLoader* pFileLoader)
|
||||||
|
: refCount_(0)
|
||||||
|
, pFileLoader_(pFileLoader)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHOD(AddResources)(
|
||||||
|
Vector<Resource> const& resources,
|
||||||
|
_Out_ LPVOID* pCollectionKey,
|
||||||
|
_Out_ UINT32* pCollectionKeySize
|
||||||
|
);
|
||||||
|
|
||||||
|
// IUnknown methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
|
||||||
|
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
virtual ULONG STDMETHODCALLTYPE Release();
|
||||||
|
|
||||||
|
// IDWriteFontCollectionLoader methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
|
||||||
|
IDWriteFactory* pFactory,
|
||||||
|
void const* collectionKey,
|
||||||
|
UINT32 collectionKeySize,
|
||||||
|
_Out_ IDWriteFontFileEnumerator** fontFileEnumerator
|
||||||
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ULONG refCount_;
|
||||||
|
IDWriteFontFileLoader* pFileLoader_;
|
||||||
|
|
||||||
|
typedef Vector<Resource> ResourceCollection;
|
||||||
|
Vector<ResourceCollection> resources_;
|
||||||
|
Vector<UINT32> collectionKeys_;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT IResourceFontCollectionLoader::Create(_Out_ IResourceFontCollectionLoader** ppCollectionLoader, IDWriteFontFileLoader* pFileLoader)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (!ppCollectionLoader)
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ResourceFontCollectionLoader* pCollectionLoader = new (std::nothrow) ResourceFontCollectionLoader(pFileLoader);
|
||||||
|
hr = pCollectionLoader ? S_OK : E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DX::SafeRelease(*ppCollectionLoader);
|
||||||
|
(*ppCollectionLoader) = DX::SafeAcquire(pCollectionLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP ResourceFontCollectionLoader::AddResources(
|
||||||
|
Vector<Resource> const& resources,
|
||||||
|
_Out_ LPVOID* pCollectionKey,
|
||||||
|
_Out_ UINT32* pCollectionKeySize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!pCollectionKey || !pCollectionKeySize)
|
||||||
|
{
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
UINT32 collectionKey = resources_.size();
|
||||||
|
collectionKeys_.push_back(collectionKey);
|
||||||
|
resources_.push_back(resources);
|
||||||
|
|
||||||
|
*pCollectionKey = reinterpret_cast<LPVOID>(&collectionKeys_.back());
|
||||||
|
*pCollectionKeySize = sizeof(collectionKey);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject)
|
||||||
|
{
|
||||||
|
if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader))
|
||||||
|
{
|
||||||
|
*ppvObject = this;
|
||||||
|
AddRef();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppvObject = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE ResourceFontCollectionLoader::AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&refCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE ResourceFontCollectionLoader::Release()
|
||||||
|
{
|
||||||
|
ULONG newCount = InterlockedDecrement(&refCount_);
|
||||||
|
if (newCount == 0)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
return newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontCollectionLoader::CreateEnumeratorFromKey(
|
||||||
|
IDWriteFactory* pFactory,
|
||||||
|
void const* collectionKey,
|
||||||
|
UINT32 collectionKeySize,
|
||||||
|
_Out_ IDWriteFontFileEnumerator** fontFileEnumerator
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (collectionKey == NULL || collectionKeySize % sizeof(Resource*) != 0)
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
IResourceFontFileEnumerator* pEnumerator = NULL;
|
||||||
|
hr = IResourceFontFileEnumerator::Create(&pEnumerator, pFactory, pFileLoader_);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
const UINT32 resourceIndex = *static_cast<const UINT32*>(collectionKey);
|
||||||
|
|
||||||
|
hr = pEnumerator->SetResources(resources_[resourceIndex]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
*fontFileEnumerator = DX::SafeAcquire(pEnumerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ResourceFontFileLoader
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class ResourceFontFileLoader
|
||||||
|
: public IResourceFontFileLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ResourceFontFileLoader()
|
||||||
|
: refCount_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// IUnknown methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
|
||||||
|
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
virtual ULONG STDMETHODCALLTYPE Release();
|
||||||
|
|
||||||
|
// IDWriteFontFileLoader methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
|
||||||
|
void const* fontFileReferenceKey,
|
||||||
|
UINT32 fontFileReferenceKeySize,
|
||||||
|
_Out_ IDWriteFontFileStream** fontFileStream
|
||||||
|
);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ULONG refCount_;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT IResourceFontFileLoader::Create(_Out_ IResourceFontFileLoader** ppFileLoader)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (!ppFileLoader)
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ResourceFontFileLoader* pFileLoader = new (std::nothrow) ResourceFontFileLoader;
|
||||||
|
hr = pFileLoader ? S_OK : E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
(*ppFileLoader) = DX::SafeAcquire(pFileLoader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::QueryInterface(REFIID iid, void** ppvObject)
|
||||||
|
{
|
||||||
|
if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader))
|
||||||
|
{
|
||||||
|
*ppvObject = this;
|
||||||
|
AddRef();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppvObject = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE ResourceFontFileLoader::AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&refCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE ResourceFontFileLoader::Release()
|
||||||
|
{
|
||||||
|
ULONG newCount = InterlockedDecrement(&refCount_);
|
||||||
|
if (newCount == 0)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
return newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileLoader::CreateStreamFromKey(
|
||||||
|
void const* fontFileReferenceKey,
|
||||||
|
UINT32 fontFileReferenceKeySize,
|
||||||
|
_Out_ IDWriteFontFileStream** fontFileStream
|
||||||
|
)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
// Make sure the key is the right size.
|
||||||
|
if (fontFileReferenceKeySize != sizeof(Resource))
|
||||||
|
hr = E_INVALIDARG;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
// Create the pFileStream object.
|
||||||
|
IResourceFontFileStream* pFileStream = NULL;
|
||||||
|
Resource resource = *static_cast<Resource const*>(fontFileReferenceKey);
|
||||||
|
|
||||||
|
hr = IResourceFontFileStream::Create(&pFileStream, resource);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DX::SafeRelease(*fontFileStream);
|
||||||
|
*fontFileStream = DX::SafeAcquire(pFileStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ResourceFontFileEnumerator
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class ResourceFontFileEnumerator
|
||||||
|
: public IResourceFontFileEnumerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ResourceFontFileEnumerator();
|
||||||
|
|
||||||
|
STDMETHOD(Initialize)(
|
||||||
|
IDWriteFactory* pFactory,
|
||||||
|
IDWriteFontFileLoader* pLoader
|
||||||
|
);
|
||||||
|
|
||||||
|
STDMETHOD(SetResources)(
|
||||||
|
Vector<Resource> const& resources
|
||||||
|
);
|
||||||
|
|
||||||
|
~ResourceFontFileEnumerator()
|
||||||
|
{
|
||||||
|
DX::SafeRelease(currentFile_);
|
||||||
|
DX::SafeRelease(pFactory_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IUnknown methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, _Out_ void** ppvObject);
|
||||||
|
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
virtual ULONG STDMETHODCALLTYPE Release();
|
||||||
|
|
||||||
|
// IDWriteFontFileEnumerator methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE MoveNext(_Out_ BOOL* hasCurrentFile);
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ULONG refCount_;
|
||||||
|
|
||||||
|
IDWriteFactory* pFactory_;
|
||||||
|
IDWriteFontFile* currentFile_;
|
||||||
|
IDWriteFontFileLoader* pLoader_;
|
||||||
|
Vector<Resource> resources_;
|
||||||
|
size_t nextIndex_;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT IResourceFontFileEnumerator::Create(_Out_ IResourceFontFileEnumerator** ppEnumerator, IDWriteFactory* pFactory, IDWriteFontFileLoader* pFileLoader)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (!ppEnumerator)
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ResourceFontFileEnumerator* pEnumerator = new (std::nothrow) ResourceFontFileEnumerator;
|
||||||
|
hr = pEnumerator ? S_OK : E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pEnumerator->Initialize(pFactory, pFileLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DX::SafeRelease(*ppEnumerator);
|
||||||
|
(*ppEnumerator) = DX::SafeAcquire(pEnumerator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceFontFileEnumerator::ResourceFontFileEnumerator()
|
||||||
|
: refCount_(0)
|
||||||
|
, pFactory_(NULL)
|
||||||
|
, currentFile_(NULL)
|
||||||
|
, nextIndex_(0)
|
||||||
|
, pLoader_(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP ResourceFontFileEnumerator::Initialize(
|
||||||
|
IDWriteFactory* pFactory,
|
||||||
|
IDWriteFontFileLoader* pLoader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (pFactory && pLoader)
|
||||||
|
{
|
||||||
|
pFactory_ = DX::SafeAcquire(pFactory);
|
||||||
|
pLoader_ = DX::SafeAcquire(pLoader);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP ResourceFontFileEnumerator::SetResources(
|
||||||
|
Vector<Resource> const& resources
|
||||||
|
)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
resources_.assign(resources);
|
||||||
|
}
|
||||||
|
catch (std::bad_alloc&)
|
||||||
|
{
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::QueryInterface(REFIID iid, _Out_ void** ppvObject)
|
||||||
|
{
|
||||||
|
if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator))
|
||||||
|
{
|
||||||
|
*ppvObject = this;
|
||||||
|
AddRef();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppvObject = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE ResourceFontFileEnumerator::AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&refCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE ResourceFontFileEnumerator::Release()
|
||||||
|
{
|
||||||
|
ULONG newCount = InterlockedDecrement(&refCount_);
|
||||||
|
if (newCount == 0)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
return newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::MoveNext(_Out_ BOOL* hasCurrentFile)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
*hasCurrentFile = FALSE;
|
||||||
|
DX::SafeRelease(currentFile_);
|
||||||
|
|
||||||
|
if (nextIndex_ < resources_.size())
|
||||||
|
{
|
||||||
|
hr = pFactory_->CreateCustomFontFileReference(
|
||||||
|
&resources_[nextIndex_],
|
||||||
|
sizeof(Resource),
|
||||||
|
pLoader_,
|
||||||
|
¤tFile_
|
||||||
|
);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
*hasCurrentFile = TRUE;
|
||||||
|
|
||||||
|
++nextIndex_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileEnumerator::GetCurrentFontFile(_Out_ IDWriteFontFile** fontFile)
|
||||||
|
{
|
||||||
|
*fontFile = DX::SafeAcquire(currentFile_);
|
||||||
|
|
||||||
|
return (currentFile_ != NULL) ? S_OK : E_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// ResourceFontFileStream
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class ResourceFontFileStream
|
||||||
|
: public IResourceFontFileStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ResourceFontFileStream();
|
||||||
|
|
||||||
|
STDMETHOD(Initialize)(
|
||||||
|
Resource const resources
|
||||||
|
);
|
||||||
|
|
||||||
|
// IUnknown methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
|
||||||
|
virtual ULONG STDMETHODCALLTYPE AddRef();
|
||||||
|
virtual ULONG STDMETHODCALLTYPE Release();
|
||||||
|
|
||||||
|
// IDWriteFontFileStream methods
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE ReadFileFragment(
|
||||||
|
void const** fragmentStart,
|
||||||
|
UINT64 fileOffset,
|
||||||
|
UINT64 fragmentSize,
|
||||||
|
_Out_ void** fragmentContext
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual void STDMETHODCALLTYPE ReleaseFileFragment(
|
||||||
|
void* fragmentContext
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetFileSize(
|
||||||
|
_Out_ UINT64* fileSize
|
||||||
|
);
|
||||||
|
|
||||||
|
virtual HRESULT STDMETHODCALLTYPE GetLastWriteTime(
|
||||||
|
_Out_ UINT64* lastWriteTime
|
||||||
|
);
|
||||||
|
|
||||||
|
bool IsInitialized()
|
||||||
|
{
|
||||||
|
return resourcePtr_ != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ULONG refCount_;
|
||||||
|
LPVOID resourcePtr_;
|
||||||
|
DWORD resourceSize_;
|
||||||
|
};
|
||||||
|
|
||||||
|
HRESULT IResourceFontFileStream::Create(_Out_ IResourceFontFileStream** ppStream, const Resource resource)
|
||||||
|
{
|
||||||
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
if (!ppStream)
|
||||||
|
{
|
||||||
|
hr = E_POINTER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
ResourceFontFileStream* pFileStream = new (std::nothrow) ResourceFontFileStream;
|
||||||
|
hr = pFileStream ? S_OK : E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = pFileStream->Initialize(resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
DX::SafeRelease(*ppStream);
|
||||||
|
(*ppStream) = DX::SafeAcquire(pFileStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceFontFileStream::ResourceFontFileStream()
|
||||||
|
: refCount_(0)
|
||||||
|
, resourcePtr_(NULL)
|
||||||
|
, resourceSize_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP ResourceFontFileStream::Initialize(
|
||||||
|
const Resource resource
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Resource::Data data = resource.GetData();
|
||||||
|
HRESULT hr = data ? S_OK : E_FAIL;
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
resourcePtr_ = data.buffer;
|
||||||
|
resourceSize_ = data.size;
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IUnknown methods
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileStream::QueryInterface(REFIID iid, void** ppvObject)
|
||||||
|
{
|
||||||
|
if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream))
|
||||||
|
{
|
||||||
|
*ppvObject = this;
|
||||||
|
AddRef();
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*ppvObject = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE ResourceFontFileStream::AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&refCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG STDMETHODCALLTYPE ResourceFontFileStream::Release()
|
||||||
|
{
|
||||||
|
ULONG newCount = InterlockedDecrement(&refCount_);
|
||||||
|
if (newCount == 0)
|
||||||
|
delete this;
|
||||||
|
|
||||||
|
return newCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileStream::ReadFileFragment(
|
||||||
|
void const** fragmentStart,
|
||||||
|
UINT64 fileOffset,
|
||||||
|
UINT64 fragmentSize,
|
||||||
|
_Out_ void** fragmentContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// The pLoader is responsible for doing a bounds check.
|
||||||
|
if (fileOffset <= resourceSize_ &&
|
||||||
|
fragmentSize <= resourceSize_ - fileOffset)
|
||||||
|
{
|
||||||
|
*fragmentStart = static_cast<BYTE const*>(resourcePtr_) + static_cast<size_t>(fileOffset);
|
||||||
|
*fragmentContext = NULL;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*fragmentStart = NULL;
|
||||||
|
*fragmentContext = NULL;
|
||||||
|
return E_FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void STDMETHODCALLTYPE ResourceFontFileStream::ReleaseFileFragment(
|
||||||
|
void* fragmentContext
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileStream::GetFileSize(
|
||||||
|
_Out_ UINT64* fileSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
*fileSize = resourceSize_;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
HRESULT STDMETHODCALLTYPE ResourceFontFileStream::GetLastWriteTime(
|
||||||
|
_Out_ UINT64* lastWriteTime
|
||||||
|
)
|
||||||
|
{
|
||||||
|
*lastWriteTime = 0;
|
||||||
|
return E_NOTIMPL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
// 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", WITH_Out_ 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 "D2DDeviceResources.h"
|
||||||
|
|
||||||
|
namespace kiwano
|
||||||
|
{
|
||||||
|
interface DWRITE_DECLARE_INTERFACE("7EC7A55A-1964-4098-83E0-EFA7C12C6EF7")
|
||||||
|
IFontCollectionLoader : public IDWriteFontCollectionLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static HRESULT Create(
|
||||||
|
_Out_ IFontCollectionLoader** ppCollectionLoader
|
||||||
|
);
|
||||||
|
|
||||||
|
STDMETHOD(AddFilePaths)(
|
||||||
|
Vector<String> const& filePaths,
|
||||||
|
_Out_ LPVOID * pCollectionKey,
|
||||||
|
_Out_ UINT32 * pCollectionKeySize
|
||||||
|
) PURE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
interface DWRITE_DECLARE_INTERFACE("0A1A3F2A-85F2-41BB-80FD-EC01271740C4")
|
||||||
|
IFontFileEnumerator : public IDWriteFontFileEnumerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static HRESULT Create(
|
||||||
|
_Out_ IFontFileEnumerator** ppEnumerator,
|
||||||
|
IDWriteFactory* pFactory
|
||||||
|
);
|
||||||
|
|
||||||
|
STDMETHOD(SetFilePaths)(
|
||||||
|
Vector<String> const& filePaths
|
||||||
|
) PURE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
interface DWRITE_DECLARE_INTERFACE("F2C411F0-2FB0-4D0E-8C73-D2B8F30137A4")
|
||||||
|
IResourceFontCollectionLoader : public IDWriteFontCollectionLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static HRESULT Create(
|
||||||
|
_Out_ IResourceFontCollectionLoader** ppCollectionLoader,
|
||||||
|
IDWriteFontFileLoader * pFileLoader
|
||||||
|
);
|
||||||
|
|
||||||
|
STDMETHOD(AddResources)(
|
||||||
|
Vector<Resource> const& resources,
|
||||||
|
_Out_ LPVOID * pCollectionKey,
|
||||||
|
_Out_ UINT32 * pCollectionKeySize
|
||||||
|
) PURE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
interface DWRITE_DECLARE_INTERFACE("08D21408-6FC1-4E36-A4EB-4DA16BE3399E")
|
||||||
|
IResourceFontFileLoader : public IDWriteFontFileLoader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static HRESULT Create(
|
||||||
|
_Out_ IResourceFontFileLoader** ppFileLoader
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
interface DWRITE_DECLARE_INTERFACE("0AD0EC74-7503-46E8-8899-520175ECCB4A")
|
||||||
|
IResourceFontFileEnumerator : public IDWriteFontFileEnumerator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static HRESULT Create(
|
||||||
|
_Out_ IResourceFontFileEnumerator** ppEnumerator,
|
||||||
|
IDWriteFactory* pFactory,
|
||||||
|
IDWriteFontFileLoader* pFileLoader
|
||||||
|
);
|
||||||
|
|
||||||
|
STDMETHOD(SetResources)(
|
||||||
|
Vector<Resource> const& resources
|
||||||
|
) PURE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
interface DWRITE_DECLARE_INTERFACE("A6267450-27F3-4948-995F-FF8345A72F88")
|
||||||
|
IResourceFontFileStream : public IDWriteFontFileStream
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static HRESULT Create(
|
||||||
|
_Out_ IResourceFontFileStream** ppStream,
|
||||||
|
const Resource resource
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -98,7 +98,7 @@ namespace kiwano
|
||||||
unsigned long STDMETHODCALLTYPE AddRef();
|
unsigned long STDMETHODCALLTYPE AddRef();
|
||||||
unsigned long STDMETHODCALLTYPE Release();
|
unsigned long STDMETHODCALLTYPE Release();
|
||||||
HRESULT STDMETHODCALLTYPE QueryInterface(
|
HRESULT STDMETHODCALLTYPE QueryInterface(
|
||||||
IID const& riid,
|
REFIID riid,
|
||||||
void** ppvObject
|
void** ppvObject
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -454,24 +454,6 @@ namespace kiwano
|
||||||
return E_NOTIMPL;
|
return E_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
|
||||||
STDMETHODIMP_(unsigned long) TextRenderer::AddRef()
|
|
||||||
{
|
|
||||||
return InterlockedIncrement(&cRefCount_);
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP_(unsigned long) TextRenderer::Release()
|
|
||||||
{
|
|
||||||
unsigned long newCount = InterlockedDecrement(&cRefCount_);
|
|
||||||
|
|
||||||
if (newCount == 0)
|
|
||||||
{
|
|
||||||
delete this;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
STDMETHODIMP TextRenderer::IsPixelSnappingDisabled(
|
STDMETHODIMP TextRenderer::IsPixelSnappingDisabled(
|
||||||
__maybenull void* clientDrawingContext,
|
__maybenull void* clientDrawingContext,
|
||||||
__out BOOL* isDisabled)
|
__out BOOL* isDisabled)
|
||||||
|
|
@ -506,8 +488,26 @@ namespace kiwano
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP_(unsigned long) TextRenderer::AddRef()
|
||||||
|
{
|
||||||
|
return InterlockedIncrement(&cRefCount_);
|
||||||
|
}
|
||||||
|
|
||||||
|
STDMETHODIMP_(unsigned long) TextRenderer::Release()
|
||||||
|
{
|
||||||
|
unsigned long newCount = InterlockedDecrement(&cRefCount_);
|
||||||
|
|
||||||
|
if (newCount == 0)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newCount;
|
||||||
|
}
|
||||||
|
|
||||||
STDMETHODIMP TextRenderer::QueryInterface(
|
STDMETHODIMP TextRenderer::QueryInterface(
|
||||||
IID const& riid,
|
REFIID riid,
|
||||||
void** ppvObject)
|
void** ppvObject)
|
||||||
{
|
{
|
||||||
if (__uuidof(ITextRenderer) == riid)
|
if (__uuidof(ITextRenderer) == riid)
|
||||||
|
|
@ -19,13 +19,12 @@
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "helper.hpp"
|
#include "D2DDeviceResources.h"
|
||||||
#include <dwrite.h>
|
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
interface DWRITE_DECLARE_INTERFACE("b293e798-9916-4096-a3c1-e5d4039dfa64") ITextRenderer
|
interface DWRITE_DECLARE_INTERFACE("b293e798-9916-4096-a3c1-e5d4039dfa64")
|
||||||
: public IDWriteTextRenderer
|
ITextRenderer : public IDWriteTextRenderer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static KGE_API HRESULT Create(
|
static KGE_API HRESULT Create(
|
||||||
|
|
@ -46,12 +46,11 @@ namespace kiwano
|
||||||
if (file_handle == INVALID_HANDLE_VALUE)
|
if (file_handle == INVALID_HANDLE_VALUE)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
LPVOID buffer;
|
Resource::Data data = res.GetData();
|
||||||
DWORD buffer_size;
|
if (data)
|
||||||
if (res.Load(buffer, buffer_size))
|
|
||||||
{
|
{
|
||||||
DWORD written_bytes = 0;
|
DWORD written_bytes = 0;
|
||||||
::WriteFile(file_handle, buffer, buffer_size, &written_bytes, NULL);
|
::WriteFile(file_handle, data.buffer, data.size, &written_bytes, NULL);
|
||||||
::CloseHandle(file_handle);
|
::CloseHandle(file_handle);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -173,12 +173,12 @@ namespace kiwano
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceCache::AddFrame(String const& id, Resource const& res)
|
bool ResourceCache::AddFrame(String const& id, String const& file_path)
|
||||||
{
|
{
|
||||||
FramePtr ptr = new (std::nothrow) Frame;
|
FramePtr ptr = new (std::nothrow) Frame;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
if (ptr->Load(res))
|
if (ptr->Load(file_path))
|
||||||
{
|
{
|
||||||
return AddFrame(id, ptr);
|
return AddFrame(id, ptr);
|
||||||
}
|
}
|
||||||
|
|
@ -196,43 +196,20 @@ namespace kiwano
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceCache::AddGifImage(String const& id, Resource const& res)
|
size_t ResourceCache::AddFrameSequence(String const& id, Vector<String> const& files)
|
||||||
{
|
{
|
||||||
GifImagePtr ptr = new (std::nothrow) GifImage;
|
if (files.empty())
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
if (ptr->Load(res))
|
|
||||||
{
|
|
||||||
return AddGifImage(id, ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ResourceCache::AddGifImage(String const& id, GifImagePtr image)
|
|
||||||
{
|
|
||||||
if (image)
|
|
||||||
{
|
|
||||||
cache_.insert(std::make_pair(id, image));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ResourceCache::AddFrameSequence(String const& id, Vector<Resource> const& images)
|
|
||||||
{
|
|
||||||
if (images.empty())
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
Vector<FramePtr> image_arr;
|
Vector<FramePtr> image_arr;
|
||||||
image_arr.reserve(images.size());
|
image_arr.reserve(files.size());
|
||||||
|
|
||||||
for (const auto& image : images)
|
for (const auto& file : files)
|
||||||
{
|
{
|
||||||
FramePtr ptr = new (std::nothrow) Frame;
|
FramePtr ptr = new (std::nothrow) Frame;
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
if (ptr->Load(image))
|
if (ptr->Load(file))
|
||||||
{
|
{
|
||||||
image_arr.push_back(ptr);
|
image_arr.push_back(ptr);
|
||||||
}
|
}
|
||||||
|
|
@ -247,22 +224,13 @@ namespace kiwano
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ResourceCache::AddFrameSequence(String const& id, Vector<FramePtr> const& images)
|
size_t ResourceCache::AddFrameSequence(String const & id, String const& file_path, int cols, int rows)
|
||||||
{
|
|
||||||
if (images.empty())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
FrameSequencePtr frames = new (std::nothrow) FrameSequence(images);
|
|
||||||
return AddFrameSequence(id, frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ResourceCache::AddFrameSequence(String const & id, Resource const & image, int cols, int rows)
|
|
||||||
{
|
{
|
||||||
if (cols <= 0 || rows <= 0)
|
if (cols <= 0 || rows <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
FramePtr raw = new (std::nothrow) Frame;
|
FramePtr raw = new (std::nothrow) Frame;
|
||||||
if (!raw || !raw->Load(image))
|
if (!raw || !raw->Load(file_path))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float raw_width = raw->GetWidth();
|
float raw_width = raw->GetWidth();
|
||||||
|
|
@ -280,7 +248,7 @@ namespace kiwano
|
||||||
FramePtr ptr = new (std::nothrow) Frame(raw->GetImage());
|
FramePtr ptr = new (std::nothrow) Frame(raw->GetImage());
|
||||||
if (ptr)
|
if (ptr)
|
||||||
{
|
{
|
||||||
ptr->Crop(Rect{ j * width, i * height, width, height });
|
ptr->SetCropRect(Rect{ j * width, i * height, width, height });
|
||||||
image_arr.push_back(ptr);
|
image_arr.push_back(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -290,29 +258,6 @@ namespace kiwano
|
||||||
return AddFrameSequence(id, frames);
|
return AddFrameSequence(id, frames);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ResourceCache::AddFrameSequence(String const & id, Resource const & image, Vector<Rect> const & crop_rects)
|
|
||||||
{
|
|
||||||
FramePtr raw = new (std::nothrow) Frame;
|
|
||||||
if (!raw || !raw->Load(image))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
Vector<FramePtr> image_arr;
|
|
||||||
image_arr.reserve(crop_rects.size());
|
|
||||||
|
|
||||||
for (const auto& rect : crop_rects)
|
|
||||||
{
|
|
||||||
FramePtr ptr = new (std::nothrow) Frame(raw->GetImage());
|
|
||||||
if (ptr)
|
|
||||||
{
|
|
||||||
ptr->Crop(rect);
|
|
||||||
image_arr.push_back(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameSequencePtr frames = new (std::nothrow) FrameSequence(image_arr);
|
|
||||||
return AddFrameSequence(id, frames);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t ResourceCache::AddFrameSequence(String const & id, FrameSequencePtr frames)
|
size_t ResourceCache::AddFrameSequence(String const & id, FrameSequencePtr frames)
|
||||||
{
|
{
|
||||||
if (frames)
|
if (frames)
|
||||||
|
|
@ -323,7 +268,7 @@ namespace kiwano
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResourceCache::AddObj(String const& id, ObjectPtr obj)
|
bool ResourceCache::AddObjectBase(String const& id, ObjectBasePtr obj)
|
||||||
{
|
{
|
||||||
if (obj)
|
if (obj)
|
||||||
{
|
{
|
||||||
|
|
@ -338,11 +283,6 @@ namespace kiwano
|
||||||
return Get<Frame>(id);
|
return Get<Frame>(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
GifImagePtr ResourceCache::GetGifImage(String const& id) const
|
|
||||||
{
|
|
||||||
return Get<GifImage>(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
FrameSequencePtr ResourceCache::GetFrameSequence(String const & id) const
|
FrameSequencePtr ResourceCache::GetFrameSequence(String const & id) const
|
||||||
{
|
{
|
||||||
return Get<FrameSequence>(id);
|
return Get<FrameSequence>(id);
|
||||||
|
|
@ -376,23 +316,17 @@ namespace kiwano
|
||||||
|
|
||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
// Gif image
|
|
||||||
if (type && (*type) == L"gif")
|
|
||||||
{
|
|
||||||
return loader->AddGifImage(*id, Resource(gdata->path + (*file)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(*file).empty())
|
if (!(*file).empty())
|
||||||
{
|
{
|
||||||
if (rows || cols)
|
if (rows || cols)
|
||||||
{
|
{
|
||||||
// Frame slices
|
// Frame slices
|
||||||
return !!loader->AddFrameSequence(*id, Resource(gdata->path + (*file)), std::max(cols, 1), std::max(rows, 1));
|
return !!loader->AddFrameSequence(*id, gdata->path + (*file), std::max(cols, 1), std::max(rows, 1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Simple image
|
// Simple image
|
||||||
return loader->AddFrame(*id, Resource(gdata->path + (*file)));
|
return loader->AddFrame(*id, gdata->path + (*file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -410,7 +344,8 @@ namespace kiwano
|
||||||
frames.push_back(frame);
|
frames.push_back(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return !!loader->AddFrameSequence(*id, frames);
|
FrameSequencePtr frame_seq = new FrameSequence(frames);
|
||||||
|
return !!loader->AddFrameSequence(*id, frame_seq);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,44 +46,28 @@ namespace kiwano
|
||||||
// 从 XML 文档对象加载资源信息
|
// 从 XML 文档对象加载资源信息
|
||||||
bool LoadFromXml(tinyxml2::XMLDocument* doc);
|
bool LoadFromXml(tinyxml2::XMLDocument* doc);
|
||||||
|
|
||||||
// Ìí¼ÓͼƬ
|
// Ìí¼Ó֡ͼÏñ
|
||||||
bool AddFrame(String const& id, Resource const& res);
|
bool AddFrame(String const& id, String const& file_path);
|
||||||
|
|
||||||
// Ìí¼ÓͼƬ
|
// Ìí¼Ó֡ͼÏñ
|
||||||
bool AddFrame(String const& id, FramePtr frame);
|
bool AddFrame(String const& id, FramePtr frame);
|
||||||
|
|
||||||
// Ìí¼Ó GIF ͼƬ
|
|
||||||
bool AddGifImage(String const& id, Resource const& res);
|
|
||||||
|
|
||||||
// Ìí¼Ó GIF ͼƬ
|
|
||||||
bool AddGifImage(String const& id, GifImagePtr image);
|
|
||||||
|
|
||||||
// 添加序列帧
|
// 添加序列帧
|
||||||
size_t AddFrameSequence(String const& id, Vector<Resource> const& frames);
|
size_t AddFrameSequence(String const& id, Vector<String> const& files);
|
||||||
|
|
||||||
// Ìí¼ÓÐòÁÐÖ¡
|
|
||||||
size_t AddFrameSequence(String const& id, Vector<FramePtr> const& frames);
|
|
||||||
|
|
||||||
// 添加序列帧
|
// 添加序列帧
|
||||||
// 按行列数裁剪图片
|
// 按行列数裁剪图片
|
||||||
size_t AddFrameSequence(String const& id, Resource const& frame, int cols, int rows = 1);
|
size_t AddFrameSequence(String const& id, String const& file_path, int cols, int rows = 1);
|
||||||
|
|
||||||
// Ìí¼ÓÐòÁÐÖ¡
|
|
||||||
// °´Ö¸¶¨²Ã¼ô¾ØÐβüôͼƬ
|
|
||||||
size_t AddFrameSequence(String const& id, Resource const& frame, Vector<Rect> const& crop_rects);
|
|
||||||
|
|
||||||
// 添加序列帧
|
// 添加序列帧
|
||||||
size_t AddFrameSequence(String const& id, FrameSequencePtr frames);
|
size_t AddFrameSequence(String const& id, FrameSequencePtr frames);
|
||||||
|
|
||||||
// 添加对象
|
// 添加对象
|
||||||
bool AddObj(String const& id, ObjectPtr obj);
|
bool AddObjectBase(String const& id, ObjectBasePtr obj);
|
||||||
|
|
||||||
// »ñȡͼƬ×ÊÔ´
|
// »ñȡ֡ͼÏñ
|
||||||
FramePtr GetFrame(String const& id) const;
|
FramePtr GetFrame(String const& id) const;
|
||||||
|
|
||||||
// »ñÈ¡ GIF ͼƬ×ÊÔ´
|
|
||||||
GifImagePtr GetGifImage(String const& id) const;
|
|
||||||
|
|
||||||
// 获取序列帧
|
// 获取序列帧
|
||||||
FrameSequencePtr GetFrameSequence(String const& id) const;
|
FrameSequencePtr GetFrameSequence(String const& id) const;
|
||||||
|
|
||||||
|
|
@ -108,6 +92,6 @@ namespace kiwano
|
||||||
virtual ~ResourceCache();
|
virtual ~ResourceCache();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
UnorderedMap<String, ObjectPtr> cache_;
|
UnorderedMap<String, ObjectBasePtr> cache_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue