mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-05 22:56:11 +00:00
Add Windows support (#1632)
Adds Windows support. Co-authored-by: Adam Gleitman <adam.gleitman@gmail.com> Co-authored-by: REDMOND\agnel <agnel@microsoft.com>
This commit is contained in:
committed by
Wojciech Lewicki
parent
4d3c521a22
commit
28d51bdf06
@@ -3,7 +3,7 @@
|
|||||||
[](https://www.npmjs.com/package/react-native-svg)
|
[](https://www.npmjs.com/package/react-native-svg)
|
||||||
[](https://www.npmjs.com/package/react-native-svg)
|
[](https://www.npmjs.com/package/react-native-svg)
|
||||||
|
|
||||||
`react-native-svg` provides SVG support to React Native on iOS and Android, and a compatibility layer for the web.
|
`react-native-svg` provides SVG support to React Native on iOS, Android, macOS, Windows, and a compatibility layer for the web.
|
||||||
|
|
||||||
[Check out the demo](https://snack.expo.io/@msand/react-native-svg-example)
|
[Check out the demo](https://snack.expo.io/@msand/react-native-svg-example)
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,8 @@
|
|||||||
"lib",
|
"lib",
|
||||||
"src",
|
"src",
|
||||||
"RNSVG.podspec",
|
"RNSVG.podspec",
|
||||||
"!android/build"
|
"!android/build",
|
||||||
|
"windows"
|
||||||
],
|
],
|
||||||
"@react-native-community/bob": {
|
"@react-native-community/bob": {
|
||||||
"source": "src",
|
"source": "src",
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
"react-native",
|
"react-native",
|
||||||
"ios",
|
"ios",
|
||||||
"android",
|
"android",
|
||||||
|
"windows",
|
||||||
"SVG",
|
"SVG",
|
||||||
"ART",
|
"ART",
|
||||||
"VML",
|
"VML",
|
||||||
@@ -87,8 +89,9 @@
|
|||||||
"jest": "^28.1.0",
|
"jest": "^28.1.0",
|
||||||
"pegjs": "^0.10.0",
|
"pegjs": "^0.10.0",
|
||||||
"prettier": "^2.6.2",
|
"prettier": "^2.6.2",
|
||||||
"react": "^16.13.0",
|
"react": "^17.0.1",
|
||||||
"react-native": "^0.62.3",
|
"react-native": "^0.64.0",
|
||||||
|
"react-native-windows": "^0.64.0",
|
||||||
"react-test-renderer": "^16.13.0",
|
"react-test-renderer": "^16.13.0",
|
||||||
"release-it": "^14.12.5",
|
"release-it": "^14.12.5",
|
||||||
"ts-node": "^10.8.0",
|
"ts-node": "^10.8.0",
|
||||||
|
|||||||
91
windows/.clang-format
Normal file
91
windows/.clang-format
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
AccessModifierOffset: -1
|
||||||
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlinesLeft: true
|
||||||
|
AlignOperands: false
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: true
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: false
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: false
|
||||||
|
AfterFunction: false
|
||||||
|
AfterNamespace: false
|
||||||
|
AfterObjCDeclaration: false
|
||||||
|
AfterStruct: false
|
||||||
|
AfterUnion: false
|
||||||
|
BeforeCatch: false
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: false
|
||||||
|
ColumnLimit: 120
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ForEachMacros: [ FOR_EACH_RANGE, FOR_EACH, TEST_CLASS, TEST_CLASS_EX ]
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: 'pch.h'
|
||||||
|
Priority: -1
|
||||||
|
- Regex: '.*\.g\..*'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^<.*\.h(pp)?>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 3
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 4
|
||||||
|
IndentCaseLabels: true
|
||||||
|
IndentWidth: 2
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: true
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 1
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 200
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: true
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: Never
|
||||||
92
windows/.gitignore
vendored
Normal file
92
windows/.gitignore
vendored
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
*AppPackages*
|
||||||
|
*BundleArtifacts*
|
||||||
|
|
||||||
|
#OS junk files
|
||||||
|
[Tt]humbs.db
|
||||||
|
*.DS_Store
|
||||||
|
|
||||||
|
#Visual Studio files
|
||||||
|
*.[Oo]bj
|
||||||
|
*.user
|
||||||
|
*.aps
|
||||||
|
*.pch
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*.ncb
|
||||||
|
*.suo
|
||||||
|
*.tlb
|
||||||
|
*.tlh
|
||||||
|
*.bak
|
||||||
|
*.[Cc]ache
|
||||||
|
*.ilk
|
||||||
|
*.log
|
||||||
|
*.lib
|
||||||
|
*.sbr
|
||||||
|
*.sdf
|
||||||
|
*.opensdf
|
||||||
|
*.opendb
|
||||||
|
*.unsuccessfulbuild
|
||||||
|
ipch/
|
||||||
|
[Oo]bj/
|
||||||
|
[Bb]in
|
||||||
|
[Dd]ebug*/
|
||||||
|
[Rr]elease*/
|
||||||
|
Ankh.NoLoad
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
#MonoDevelop
|
||||||
|
*.pidb
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
#Tooling
|
||||||
|
_ReSharper*/
|
||||||
|
*.resharper
|
||||||
|
[Tt]est[Rr]esult*
|
||||||
|
*.sass-cache
|
||||||
|
|
||||||
|
#Project files
|
||||||
|
[Bb]uild/
|
||||||
|
|
||||||
|
#Subversion files
|
||||||
|
.svn
|
||||||
|
|
||||||
|
# Office Temp Files
|
||||||
|
~$*
|
||||||
|
|
||||||
|
# vim Temp Files
|
||||||
|
*~
|
||||||
|
|
||||||
|
#NuGet
|
||||||
|
packages/
|
||||||
|
*.nupkg
|
||||||
|
|
||||||
|
#ncrunch
|
||||||
|
*ncrunch*
|
||||||
|
*crunch*.local.xml
|
||||||
|
|
||||||
|
# visual studio database projects
|
||||||
|
*.dbmdl
|
||||||
|
|
||||||
|
#Test files
|
||||||
|
*.testsettings
|
||||||
|
|
||||||
|
#Other files
|
||||||
|
*.DotSettings
|
||||||
|
.vs/
|
||||||
|
*project.lock.json
|
||||||
|
|
||||||
|
#Files generated by the VS build
|
||||||
|
**/Generated Files/**
|
||||||
|
|
||||||
187
windows/RNSVG.sln
Normal file
187
windows/RNSVG.sln
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio Version 16
|
||||||
|
VisualStudioVersion = 16.0.29215.179
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RNSVG", "RNSVG\RNSVG.vcxproj", "{7ACF84EC-EFBA-4043-8E14-40B159508902}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {F7D32BD0-2749-483E-9A0D-1635EF7E3136}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Folly", "..\node_modules\react-native-windows\Folly\Folly.vcxproj", "{A990658C-CE31-4BCC-976F-0FC6B1AF693D}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "..\node_modules\react-native-windows\ReactCommon\ReactCommon.vcxproj", "{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}"
|
||||||
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D}
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Chakra", "..\node_modules\react-native-windows\Chakra\Chakra.vcxitems", "{C38970C0-5FBF-4D69-90D8-CBAC225AE895}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative", "..\node_modules\react-native-windows\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj", "{F7D32BD0-2749-483E-9A0D-1635EF7E3136}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Shared", "..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems", "{0CC28589-39E4-4288-B162-97B959F8B843}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Universal", "..\node_modules\react-native-windows\JSI\Universal\JSI.Universal.vcxproj", "{A62D504A-16B8-41D2-9F19-E2E86019E5E4}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\node_modules\react-native-windows\Common\Common.vcxproj", "{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative", "{5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Shared", "..\node_modules\react-native-windows\Shared\Shared.vcxitems", "{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\node_modules\react-native-windows\Mso\Mso.vcxitems", "{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Include", "..\node_modules\react-native-windows\include\Include.vcxitems", "{EF074BA1-2D54-4D49-A28E-5E040B47CD2E}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||||
|
..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9
|
||||||
|
..\node_modules\react-native-windows\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9
|
||||||
|
..\node_modules\react-native-windows\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9
|
||||||
|
..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4
|
||||||
|
..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9
|
||||||
|
..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9
|
||||||
|
..\node_modules\react-native-windows\include\Include.vcxitems*{ef074ba1-2d54-4d49-a28e-5e040b47cd2e}*SharedItemsImports = 9
|
||||||
|
..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||||
|
..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||||
|
..\node_modules\react-native-windows\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||||
|
..\node_modules\react-native-windows\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|ARM = Debug|ARM
|
||||||
|
Debug|ARM64 = Debug|ARM64
|
||||||
|
Debug|x64 = Debug|x64
|
||||||
|
Debug|x86 = Debug|x86
|
||||||
|
Release|ARM = Release|ARM
|
||||||
|
Release|ARM64 = Release|ARM64
|
||||||
|
Release|x64 = Release|x64
|
||||||
|
Release|x86 = Release|x86
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|ARM64.Deploy.0 = Debug|ARM64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|x64.Deploy.0 = Debug|x64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Debug|x86.Deploy.0 = Debug|Win32
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|ARM.Deploy.0 = Release|ARM
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|ARM64.Deploy.0 = Release|ARM64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|x64.Build.0 = Release|x64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|x64.Deploy.0 = Release|x64
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{7ACF84EC-EFBA-4043-8E14-40B159508902}.Release|x86.Deploy.0 = Release|Win32
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.Build.0 = Release|x64
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.Build.0 = Release|x64
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.Build.0 = Release|x64
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.Build.0 = Release|x64
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.Build.0 = Debug|ARM
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM.ActiveCfg = Release|ARM
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM.Build.0 = Release|ARM
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.Build.0 = Release|ARM64
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.Build.0 = Release|x64
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.Build.0 = Release|Win32
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(NestedProjects) = preSolution
|
||||||
|
{A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{C38970C0-5FBF-4D69-90D8-CBAC225AE895} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{0CC28589-39E4-4288-B162-97B959F8B843} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{A62D504A-16B8-41D2-9F19-E2E86019E5E4} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
{EF074BA1-2D54-4D49-A28E-5E040B47CD2E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {D43FAD39-F619-437D-BB40-04A3982ACB6A}
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
24
windows/RNSVG/BrushView.cpp
Normal file
24
windows/RNSVG/BrushView.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "BrushView.h"
|
||||||
|
#include "BrushView.g.cpp"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void BrushView::SaveDefinition() {
|
||||||
|
if (auto const &root{SvgRoot()}) {
|
||||||
|
CreateBrush();
|
||||||
|
root.Brushes().Insert(Id(), *this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrushView::SetBounds(Windows::Foundation::Rect const &rect) {
|
||||||
|
m_bounds = rect;
|
||||||
|
UpdateBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrushView::Unload() {
|
||||||
|
m_brush.Close();
|
||||||
|
m_brush = nullptr;
|
||||||
|
|
||||||
|
__super::Unload();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
28
windows/RNSVG/BrushView.h
Normal file
28
windows/RNSVG/BrushView.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "BrushView.g.h"
|
||||||
|
#include "GroupView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct BrushView : BrushViewT<BrushView, RNSVG::implementation::GroupView> {
|
||||||
|
public:
|
||||||
|
BrushView() = default;
|
||||||
|
|
||||||
|
void SaveDefinition();
|
||||||
|
|
||||||
|
Microsoft::Graphics::Canvas::Brushes::ICanvasBrush Brush() { return m_brush; }
|
||||||
|
virtual void CreateBrush() {}
|
||||||
|
virtual void Unload();
|
||||||
|
void SetBounds(Windows::Foundation::Rect const &rect);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Microsoft::Graphics::Canvas::Brushes::ICanvasBrush m_brush{nullptr};
|
||||||
|
Windows::Foundation::Rect m_bounds{};
|
||||||
|
|
||||||
|
virtual void UpdateBounds() {}
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct BrushView : BrushViewT<BrushView, implementation::BrushView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
41
windows/RNSVG/CircleView.cpp
Normal file
41
windows/RNSVG/CircleView.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "CircleView.h"
|
||||||
|
#include "CircleView.g.cpp"
|
||||||
|
|
||||||
|
#include "JSValueXaml.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void CircleView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "r") {
|
||||||
|
m_r = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "cx") {
|
||||||
|
m_cx = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "cy") {
|
||||||
|
m_cy = SVGLength::From(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CircleView::CreateGeometry(UI::Xaml::CanvasControl const &canvas) {
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
|
||||||
|
float cx{Utils::GetAbsoluteLength(m_cx, canvas.Size().Width)};
|
||||||
|
float cy{Utils::GetAbsoluteLength(m_cy, canvas.Size().Height)};
|
||||||
|
float r{Utils::GetAbsoluteLength(m_r, Utils::GetCanvasDiagonal(canvas.Size()))};
|
||||||
|
|
||||||
|
Geometry(Geometry::CanvasGeometry::CreateCircle(resourceCreator, cx, cy, r));
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
20
windows/RNSVG/CircleView.h
Normal file
20
windows/RNSVG/CircleView.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CircleView.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct CircleView : CircleViewT<CircleView, RNSVG::implementation::RenderableView> {
|
||||||
|
public:
|
||||||
|
CircleView() = default;
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void CreateGeometry(Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RNSVG::SVGLength m_r{};
|
||||||
|
RNSVG::SVGLength m_cx{};
|
||||||
|
RNSVG::SVGLength m_cy{};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct CircleView : CircleViewT<CircleView, implementation::CircleView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
28
windows/RNSVG/CircleViewManager.cpp
Normal file
28
windows/RNSVG/CircleViewManager.cpp
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "CircleViewManager.h"
|
||||||
|
#include "CircleViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
CircleViewManager::CircleViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGCircle;
|
||||||
|
m_name = L"RNSVGCircle";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> CircleViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"cx", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"cy", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"r", ViewManagerPropertyType::String);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
15
windows/RNSVG/CircleViewManager.h
Normal file
15
windows/RNSVG/CircleViewManager.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "CircleViewManager.g.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct CircleViewManager : CircleViewManagerT<CircleViewManager, RNSVG::implementation::RenderableViewManager> {
|
||||||
|
CircleViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct CircleViewManager : CircleViewManagerT<CircleViewManager, implementation::CircleViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
10
windows/RNSVG/DefsView.cpp
Normal file
10
windows/RNSVG/DefsView.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "DefsView.h"
|
||||||
|
#include "DefsView.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void DefsView::Render(UI::Xaml::CanvasControl const &/*canvas*/, CanvasDrawingSession const &/*session*/) {}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
17
windows/RNSVG/DefsView.h
Normal file
17
windows/RNSVG/DefsView.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "DefsView.g.h"
|
||||||
|
#include "GroupView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct DefsView : DefsViewT<DefsView, RNSVG::implementation::GroupView> {
|
||||||
|
DefsView() = default;
|
||||||
|
|
||||||
|
void Render(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct DefsView : DefsViewT<DefsView, implementation::DefsView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
10
windows/RNSVG/DefsViewManager.cpp
Normal file
10
windows/RNSVG/DefsViewManager.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "DefsViewManager.h"
|
||||||
|
#include "DefsViewManager.g.cpp"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
DefsViewManager::DefsViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGDefs;
|
||||||
|
m_name = L"RNSVGDefs";
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
12
windows/RNSVG/DefsViewManager.h
Normal file
12
windows/RNSVG/DefsViewManager.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "DefsViewManager.g.h"
|
||||||
|
#include "GroupViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct DefsViewManager : DefsViewManagerT<DefsViewManager, RNSVG::implementation::GroupViewManager> {
|
||||||
|
DefsViewManager();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct DefsViewManager : DefsViewManagerT<DefsViewManager, implementation::DefsViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
44
windows/RNSVG/EllipseView.cpp
Normal file
44
windows/RNSVG/EllipseView.cpp
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "EllipseView.h"
|
||||||
|
#include "EllipseView.g.cpp"
|
||||||
|
|
||||||
|
#include "JSValueXaml.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void EllipseView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "cx") {
|
||||||
|
m_cx = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "cy") {
|
||||||
|
m_cy = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "rx") {
|
||||||
|
m_rx = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "ry") {
|
||||||
|
m_ry = SVGLength::From(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EllipseView::CreateGeometry(UI::Xaml::CanvasControl const &canvas) {
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
|
||||||
|
float cx{Utils::GetAbsoluteLength(m_cx, canvas.Size().Width)};
|
||||||
|
float cy{Utils::GetAbsoluteLength(m_cy, canvas.Size().Height)};
|
||||||
|
float rx{Utils::GetAbsoluteLength(m_rx, canvas.Size().Width)};
|
||||||
|
float ry{Utils::GetAbsoluteLength(m_ry, canvas.Size().Height)};
|
||||||
|
|
||||||
|
Geometry(Geometry::CanvasGeometry::CreateEllipse(resourceCreator, cx, cy, rx, ry));
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
21
windows/RNSVG/EllipseView.h
Normal file
21
windows/RNSVG/EllipseView.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "EllipseView.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct EllipseView : EllipseViewT<EllipseView, RNSVG::implementation::RenderableView> {
|
||||||
|
public:
|
||||||
|
EllipseView() = default;
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void CreateGeometry(Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RNSVG::SVGLength m_cx{};
|
||||||
|
RNSVG::SVGLength m_cy{};
|
||||||
|
RNSVG::SVGLength m_rx{};
|
||||||
|
RNSVG::SVGLength m_ry{};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct EllipseView : EllipseViewT<EllipseView, implementation::EllipseView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
29
windows/RNSVG/EllipseViewManager.cpp
Normal file
29
windows/RNSVG/EllipseViewManager.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "EllipseViewManager.h"
|
||||||
|
#include "EllipseViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
EllipseViewManager::EllipseViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGEllipse;
|
||||||
|
m_name = L"RNSVGEllipse";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> EllipseViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"cx", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"cy", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"rx", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"ry", ViewManagerPropertyType::String);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
15
windows/RNSVG/EllipseViewManager.h
Normal file
15
windows/RNSVG/EllipseViewManager.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "EllipseViewManager.g.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct EllipseViewManager : EllipseViewManagerT<EllipseViewManager, RNSVG::implementation::RenderableViewManager> {
|
||||||
|
EllipseViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct EllipseViewManager : EllipseViewManagerT<EllipseViewManager, implementation::EllipseViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
172
windows/RNSVG/GroupView.cpp
Normal file
172
windows/RNSVG/GroupView.cpp
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "JSValueXaml.h"
|
||||||
|
|
||||||
|
#include "GroupView.h"
|
||||||
|
#if __has_include("GroupView.g.cpp")
|
||||||
|
#include "GroupView.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "SVGLength.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void GroupView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
auto const &parent{SvgParent().try_as<RNSVG::GroupView>()};
|
||||||
|
auto fontProp{RNSVG::FontProp::Unknown};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "font") {
|
||||||
|
auto const &font{propertyValue.AsObject()};
|
||||||
|
|
||||||
|
// When any of the font props update, you don't get individual updates.
|
||||||
|
// Instead, you get a new JSValueObject with all font props set on the element.
|
||||||
|
// If a prop was removed, you will not get a null type - it just won't
|
||||||
|
// be part of the new prop object, so we will reset all font values.
|
||||||
|
if (forceUpdate) {
|
||||||
|
m_fontPropMap[RNSVG::FontProp::FontSize] = false;
|
||||||
|
m_fontPropMap[RNSVG::FontProp::FontFamily] = false;
|
||||||
|
m_fontPropMap[RNSVG::FontProp::FontWeight] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const &item : m_fontPropMap) {
|
||||||
|
if (!item.second) {
|
||||||
|
switch (item.first) {
|
||||||
|
case RNSVG::FontProp::FontSize:
|
||||||
|
m_fontSize = parent ? parent.FontSize() : 12.0f;
|
||||||
|
break;
|
||||||
|
case RNSVG::FontProp::FontFamily:
|
||||||
|
m_fontFamily = parent ? parent.FontFamily() : L"Segoe UI";
|
||||||
|
break;
|
||||||
|
case RNSVG::FontProp::FontWeight:
|
||||||
|
m_fontWeight = L"auto";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw hresult_error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const &prop : font) {
|
||||||
|
auto const &key{prop.first};
|
||||||
|
auto const &value{prop.second};
|
||||||
|
|
||||||
|
if (key == "fontSize") {
|
||||||
|
fontProp = RNSVG::FontProp::FontSize;
|
||||||
|
if (forceUpdate || !m_fontPropMap[fontProp]) {
|
||||||
|
m_fontSize = value.AsSingle();
|
||||||
|
}
|
||||||
|
} else if (key == "fontFamily") {
|
||||||
|
fontProp = RNSVG::FontProp::FontFamily;
|
||||||
|
if (forceUpdate || !m_fontPropMap[fontProp]) {
|
||||||
|
m_fontFamily = to_hstring(value.AsString());
|
||||||
|
}
|
||||||
|
} else if (key == "fontWeight") {
|
||||||
|
fontProp = RNSVG::FontProp::FontWeight;
|
||||||
|
auto fontWeight{to_hstring(value.AsString())};
|
||||||
|
if (forceUpdate) {
|
||||||
|
m_fontWeight = fontWeight;
|
||||||
|
} else if (!m_fontPropMap[fontProp]) {
|
||||||
|
m_fontWeight = L"auto";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// forceUpdate = true means the property is being set on an element
|
||||||
|
// instead of being inherited from the parent.
|
||||||
|
if (forceUpdate && (fontProp != RNSVG::FontProp::Unknown)) {
|
||||||
|
// If the propertyValue is null, that means we reset the property
|
||||||
|
m_fontPropMap[fontProp] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, false);
|
||||||
|
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.UpdateProperties(reader, false, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invalidate && SvgParent()) {
|
||||||
|
SvgRoot().InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupView::CreateGeometry(UI::Xaml::CanvasControl const &canvas) {
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
std::vector<Geometry::CanvasGeometry> geometries;
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
geometries.push_back(child.Geometry());
|
||||||
|
}
|
||||||
|
|
||||||
|
Geometry(Geometry::CanvasGeometry::CreateGroup(resourceCreator, geometries, FillRule()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupView::SaveDefinition() {
|
||||||
|
__super::SaveDefinition();
|
||||||
|
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.SaveDefinition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupView::MergeProperties(RNSVG::RenderableView const &other) {
|
||||||
|
__super::MergeProperties(other);
|
||||||
|
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.MergeProperties(*this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupView::Render(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
||||||
|
auto const &transform{session.Transform()};
|
||||||
|
|
||||||
|
if (m_propSetMap[RNSVG::BaseProp::Matrix]) {
|
||||||
|
session.Transform(transform * SvgTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto const &opacityLayer{session.CreateLayer(m_opacity)}) {
|
||||||
|
if (Children().Size() == 0) {
|
||||||
|
__super::Render(canvas, session);
|
||||||
|
} else {
|
||||||
|
RenderGroup(canvas, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
opacityLayer.Close();
|
||||||
|
}
|
||||||
|
session.Transform(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupView::RenderGroup(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.Render(canvas, session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupView::CreateResources(ICanvasResourceCreator const &resourceCreator, UI::CanvasCreateResourcesEventArgs const &args) {
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.CreateResources(resourceCreator, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupView::Unload() {
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_reactContext = nullptr;
|
||||||
|
m_fontPropMap.clear();
|
||||||
|
m_children.Clear();
|
||||||
|
|
||||||
|
__super::Unload();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
62
windows/RNSVG/GroupView.h
Normal file
62
windows/RNSVG/GroupView.h
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "GroupView.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct GroupView : GroupViewT<GroupView, RNSVG::implementation::RenderableView> {
|
||||||
|
public:
|
||||||
|
GroupView() = default;
|
||||||
|
GroupView(Microsoft::ReactNative::IReactContext const &context) : m_reactContext(context) {}
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::IRenderable> Children() { return m_children; }
|
||||||
|
|
||||||
|
hstring FontFamily() { return m_fontFamily; }
|
||||||
|
void FontFamily(hstring const &value) { m_fontFamily = value; }
|
||||||
|
|
||||||
|
float FontSize() { return m_fontSize; }
|
||||||
|
void FontSize(float value) { m_fontSize = value; }
|
||||||
|
|
||||||
|
hstring FontWeight(){ return m_fontWeight; }
|
||||||
|
void FontWeight(hstring const &value) { m_fontWeight = value; }
|
||||||
|
|
||||||
|
virtual void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
virtual void CreateGeometry(Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas);
|
||||||
|
|
||||||
|
virtual void SaveDefinition();
|
||||||
|
|
||||||
|
virtual void MergeProperties(RNSVG::RenderableView const &other);
|
||||||
|
|
||||||
|
virtual void Render(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
|
||||||
|
virtual void RenderGroup(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
|
||||||
|
virtual void CreateResources(
|
||||||
|
Microsoft::Graphics::Canvas::ICanvasResourceCreator const &resourceCreator,
|
||||||
|
Microsoft::Graphics::Canvas::UI::CanvasCreateResourcesEventArgs const &args);
|
||||||
|
|
||||||
|
virtual void Unload();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Microsoft::ReactNative::IReactContext m_reactContext{nullptr};
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::IRenderable> m_children{
|
||||||
|
winrt::single_threaded_vector<RNSVG::IRenderable>()};
|
||||||
|
|
||||||
|
float m_fontSize{12.0f};
|
||||||
|
hstring m_fontFamily{L"Segoe UI"};
|
||||||
|
hstring m_fontWeight{L"auto"};
|
||||||
|
|
||||||
|
std::map<RNSVG::FontProp, bool> m_fontPropMap{
|
||||||
|
{RNSVG::FontProp::FontSize, false},
|
||||||
|
{RNSVG::FontProp::FontWeight, false},
|
||||||
|
{RNSVG::FontProp::FontFamily, false},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct GroupView : GroupViewT<GroupView, implementation::GroupView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
107
windows/RNSVG/GroupViewManager.cpp
Normal file
107
windows/RNSVG/GroupViewManager.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "GroupViewManager.h"
|
||||||
|
#if __has_include("GroupViewManager.g.cpp")
|
||||||
|
#include "GroupViewManager.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "GroupView.h"
|
||||||
|
|
||||||
|
#include <winrt/Windows.UI.Xaml.Shapes.h>
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
using namespace Windows::Foundation;
|
||||||
|
using namespace Windows::Foundation::Collections;
|
||||||
|
using namespace Windows::UI::Xaml;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
GroupViewManager::GroupViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGGroup;
|
||||||
|
m_name = L"RNSVGGroup";
|
||||||
|
}
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> GroupViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"font", ViewManagerPropertyType::Map);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
|
||||||
|
// IViewManagerWithChildren
|
||||||
|
void GroupViewManager::AddView(FrameworkElement const &parent, UIElement const &child, int64_t /*index*/) {
|
||||||
|
if (auto const &groupView{parent.try_as<RNSVG::GroupView>()}) {
|
||||||
|
if (auto const &childView{child.try_as<IRenderable>()}) {
|
||||||
|
childView.SvgParent(parent);
|
||||||
|
groupView.Children().Append(childView);
|
||||||
|
childView.MergeProperties(groupView);
|
||||||
|
|
||||||
|
if (auto const &root{groupView.SvgRoot()}) {
|
||||||
|
root.InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupViewManager::RemoveAllChildren(FrameworkElement const &parent) {
|
||||||
|
if (auto const &groupView{parent.try_as<RNSVG::GroupView>()}) {
|
||||||
|
for (auto const &child : groupView.Children()) {
|
||||||
|
child.Unload();
|
||||||
|
child.SvgParent(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
groupView.Children().Clear();
|
||||||
|
|
||||||
|
if (auto const &root{groupView.SvgRoot()}) {
|
||||||
|
root.InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupViewManager::RemoveChildAt(FrameworkElement const &parent, int64_t index) {
|
||||||
|
if (auto const &groupView{parent.try_as<RNSVG::GroupView>()}) {
|
||||||
|
auto const &child{groupView.Children().GetAt(static_cast<uint32_t>(index))};
|
||||||
|
child.Unload();
|
||||||
|
child.SvgParent(nullptr);
|
||||||
|
|
||||||
|
groupView.Children().RemoveAt(static_cast<uint32_t>(index));
|
||||||
|
|
||||||
|
if (auto const &root{groupView.SvgRoot()}) {
|
||||||
|
root.InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupViewManager::ReplaceChild(
|
||||||
|
FrameworkElement const &parent,
|
||||||
|
UIElement const &oldChild,
|
||||||
|
UIElement const &newChild) {
|
||||||
|
auto const &groupView{parent.try_as<RNSVG::GroupView>()};
|
||||||
|
auto const &oldChildView{oldChild.try_as<IRenderable>()};
|
||||||
|
auto const &newChildView{newChild.try_as<IRenderable>()};
|
||||||
|
|
||||||
|
if (groupView && oldChildView && newChildView) {
|
||||||
|
uint32_t index;
|
||||||
|
|
||||||
|
if (groupView.Children().IndexOf(oldChildView, index)) {
|
||||||
|
groupView.Children().RemoveAt(index);
|
||||||
|
oldChildView.Unload();
|
||||||
|
oldChildView.SvgParent(nullptr);
|
||||||
|
newChildView.SvgParent(parent);
|
||||||
|
groupView.Children().Append(newChildView);
|
||||||
|
newChildView.MergeProperties(groupView);
|
||||||
|
|
||||||
|
if (auto const &root{groupView.SvgRoot()}) {
|
||||||
|
root.InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
28
windows/RNSVG/GroupViewManager.h
Normal file
28
windows/RNSVG/GroupViewManager.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "GroupViewManager.g.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct GroupViewManager : GroupViewManagerT<GroupViewManager, RNSVG::implementation::RenderableViewManager> {
|
||||||
|
public:
|
||||||
|
GroupViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
|
||||||
|
// IViewManagerWithChildren
|
||||||
|
void
|
||||||
|
AddView(Windows::UI::Xaml::FrameworkElement const &parent, Windows::UI::Xaml::UIElement const &child, int64_t index);
|
||||||
|
void RemoveAllChildren(Windows::UI::Xaml::FrameworkElement const &parent);
|
||||||
|
void RemoveChildAt(Windows::UI::Xaml::FrameworkElement const &parent, int64_t index);
|
||||||
|
void ReplaceChild(
|
||||||
|
Windows::UI::Xaml::FrameworkElement const &parent,
|
||||||
|
Windows::UI::Xaml::UIElement const &oldChild,
|
||||||
|
Windows::UI::Xaml::UIElement const &newChild);
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct GroupViewManager : GroupViewManagerT<GroupViewManager, implementation::GroupViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
267
windows/RNSVG/ImageView.cpp
Normal file
267
windows/RNSVG/ImageView.cpp
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "ImageView.h"
|
||||||
|
#include "ImageView.g.cpp"
|
||||||
|
|
||||||
|
#include <winrt/Microsoft.Graphics.Canvas.Effects.h>
|
||||||
|
#include <winrt/Windows.Security.Cryptography.h>
|
||||||
|
#include <winrt/Windows.Storage.Streams.h>
|
||||||
|
#include <winrt/Windows.Web.Http.Headers.h>
|
||||||
|
#include <winrt/Windows.Web.Http.h>
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
using namespace Windows::Security::Cryptography;
|
||||||
|
using namespace Windows::Storage::Streams;
|
||||||
|
using namespace Windows::Web::Http;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void ImageView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "src") {
|
||||||
|
auto const &src{propertyValue.AsObject()};
|
||||||
|
|
||||||
|
for (auto const &item : src) {
|
||||||
|
auto const &key{item.first};
|
||||||
|
auto const &value{item.second};
|
||||||
|
|
||||||
|
if (key == "uri") {
|
||||||
|
m_source.uri = to_hstring(Utils::JSValueAsString(value));
|
||||||
|
m_source.type = ImageSourceType::Uri;
|
||||||
|
m_source.format = ImageSourceFormat::Bitmap;
|
||||||
|
m_source.width = 0;
|
||||||
|
m_source.height = 0;
|
||||||
|
|
||||||
|
if (SvgParent()) {
|
||||||
|
LoadImageSourceAsync(SvgRoot().Canvas(), true);
|
||||||
|
}
|
||||||
|
} else if (key == "width") {
|
||||||
|
m_source.width = Utils::JSValueAsFloat(value);
|
||||||
|
} else if (key == "height") {
|
||||||
|
m_source.height = Utils::JSValueAsFloat(value);
|
||||||
|
} else if (key == "scale") {
|
||||||
|
m_source.scale = Utils::JSValueAsFloat(value);
|
||||||
|
} else if (key == "method") {
|
||||||
|
m_source.method = to_hstring(Utils::JSValueAsString(value));
|
||||||
|
} else if (key == "headers") {
|
||||||
|
m_source.headers.clear();
|
||||||
|
for (auto const &header : value.AsObject()) {
|
||||||
|
m_source.headers.push_back(std::make_pair(to_hstring(header.first), to_hstring(Utils::JSValueAsString(header.second))));
|
||||||
|
}
|
||||||
|
} else if (key == "__packager_asset") {
|
||||||
|
m_source.packagerAsset = value.AsBoolean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (propertyName == "x") {
|
||||||
|
m_x = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "y") {
|
||||||
|
m_y = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "width") {
|
||||||
|
m_width = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "height") {
|
||||||
|
m_height = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "align") {
|
||||||
|
m_align = Utils::JSValueAsString(propertyValue);
|
||||||
|
} else if (propertyName == "meetOrSlice") {
|
||||||
|
m_meetOrSlice = Utils::GetMeetOrSlice(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageView::Render(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
||||||
|
if (m_source.width == 0 || m_source.height == 0) {
|
||||||
|
m_source.width = canvas.Size().Width;
|
||||||
|
m_source.height = canvas.Size().Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
float x{Utils::GetAbsoluteLength(m_x, canvas.Size().Width)};
|
||||||
|
float y{Utils::GetAbsoluteLength(m_y, canvas.Size().Height)};
|
||||||
|
float width{Utils::GetAbsoluteLength(m_width, canvas.Size().Width)};
|
||||||
|
float height{Utils::GetAbsoluteLength(m_height, canvas.Size().Height)};
|
||||||
|
|
||||||
|
if (width == 0) {
|
||||||
|
width = m_source.width * m_source.scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height == 0) {
|
||||||
|
height = m_source.height * m_source.scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
Effects::Transform2DEffect transformEffect{nullptr};
|
||||||
|
if (m_align != "") {
|
||||||
|
Rect elRect{x, y, width, height};
|
||||||
|
Rect vbRect{0, 0, m_source.width, m_source.height};
|
||||||
|
transformEffect = Effects::Transform2DEffect{};
|
||||||
|
transformEffect.TransformMatrix(Utils::GetViewBoxTransform(vbRect, elRect, m_align, m_meetOrSlice));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto const &opacityLayer{session.CreateLayer(m_opacity)}) {
|
||||||
|
if (m_source.format == ImageSourceFormat::Bitmap && m_bitmap) {
|
||||||
|
auto const &transform{session.Transform()};
|
||||||
|
if (m_propSetMap[RNSVG::BaseProp::Matrix]) {
|
||||||
|
session.Transform(SvgTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_align != "" && transformEffect) {
|
||||||
|
transformEffect.Source(m_bitmap);
|
||||||
|
Effects::CropEffect cropEffect{};
|
||||||
|
cropEffect.SourceRectangle({x, y, width, height});
|
||||||
|
cropEffect.Source(transformEffect);
|
||||||
|
session.DrawImage(cropEffect);
|
||||||
|
} else {
|
||||||
|
session.DrawImage(m_bitmap, {x, y, width, height});
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Transform(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
opacityLayer.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageView::CreateResources(ICanvasResourceCreator const &resourceCreator, UI::CanvasCreateResourcesEventArgs const &args) {
|
||||||
|
args.TrackAsyncAction(LoadImageSourceAsync(resourceCreator, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageView::Unload() {
|
||||||
|
if (m_bitmap) {
|
||||||
|
m_bitmap.Close();
|
||||||
|
m_bitmap = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IAsyncAction ImageView::LoadImageSourceAsync(ICanvasResourceCreator resourceCreator, bool invalidate) {
|
||||||
|
Uri uri{m_source.uri};
|
||||||
|
hstring scheme{uri ? uri.SchemeName() : L""};
|
||||||
|
hstring ext{uri ? uri.Extension() : L""};
|
||||||
|
|
||||||
|
if (ext == L".svg" || ext == L".svgz") {
|
||||||
|
m_source.format = ImageSourceFormat::Svg;
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scheme == L"http" || scheme == L"https") {
|
||||||
|
m_source.type = ImageSourceType::Download;
|
||||||
|
} else if (scheme == L"data") {
|
||||||
|
m_source.type = ImageSourceType::InlineData;
|
||||||
|
if (to_string(m_source.uri).find("image/svg+xml") != std::string::npos) {
|
||||||
|
m_source.format = ImageSourceFormat::Svg;
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool fromStream{m_source.type == ImageSourceType::Download || m_source.type == ImageSourceType::InlineData};
|
||||||
|
|
||||||
|
InMemoryRandomAccessStream stream{nullptr};
|
||||||
|
|
||||||
|
// get weak reference before any co_await calls
|
||||||
|
auto weak_this{get_weak()};
|
||||||
|
|
||||||
|
try {
|
||||||
|
stream = co_await GetImageMemoryStreamAsync(m_source);
|
||||||
|
|
||||||
|
if (fromStream && !stream) {
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
} catch (winrt::hresult_error const &) {
|
||||||
|
co_return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stream) {
|
||||||
|
m_bitmap = co_await CanvasBitmap::LoadAsync(resourceCreator, stream);
|
||||||
|
} else {
|
||||||
|
m_bitmap = co_await CanvasBitmap::LoadAsync(resourceCreator, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_source.width = m_bitmap.Size().Width;
|
||||||
|
m_source.height = m_bitmap.Size().Height;
|
||||||
|
|
||||||
|
if (invalidate) {
|
||||||
|
if (auto strong_this{weak_this.get()}) {
|
||||||
|
strong_this->SvgRoot().InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IAsyncOperation<InMemoryRandomAccessStream> ImageView::GetImageMemoryStreamAsync(ImageSource source) {
|
||||||
|
switch (source.type) {
|
||||||
|
case ImageSourceType::Download:
|
||||||
|
co_return co_await GetImageStreamAsync(source);
|
||||||
|
case ImageSourceType::InlineData:
|
||||||
|
co_return co_await GetImageInlineDataAsync(source);
|
||||||
|
default: // ImageSourceType::Uri
|
||||||
|
co_return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IAsyncOperation<InMemoryRandomAccessStream> ImageView::GetImageStreamAsync(ImageSource source) {
|
||||||
|
try {
|
||||||
|
co_await resume_background();
|
||||||
|
|
||||||
|
auto httpMethod{source.method.empty() ? HttpMethod::Get() : HttpMethod{source.method}};
|
||||||
|
|
||||||
|
Uri uri{source.uri};
|
||||||
|
HttpRequestMessage request{httpMethod, uri};
|
||||||
|
|
||||||
|
if (!source.headers.empty()) {
|
||||||
|
for (auto const &header : source.headers) {
|
||||||
|
if (_stricmp(to_string(header.first).c_str(), "authorization") == 0) {
|
||||||
|
request.Headers().TryAppendWithoutValidation(header.first, header.second);
|
||||||
|
} else {
|
||||||
|
request.Headers().Append(header.first, header.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpClient httpClient;
|
||||||
|
HttpResponseMessage response{co_await httpClient.SendRequestAsync(request)};
|
||||||
|
|
||||||
|
if (response && response.StatusCode() == HttpStatusCode::Ok) {
|
||||||
|
IInputStream inputStream{co_await response.Content().ReadAsInputStreamAsync()};
|
||||||
|
InMemoryRandomAccessStream memoryStream;
|
||||||
|
co_await RandomAccessStream::CopyAsync(inputStream, memoryStream);
|
||||||
|
memoryStream.Seek(0);
|
||||||
|
|
||||||
|
co_return memoryStream;
|
||||||
|
}
|
||||||
|
} catch (hresult_error const &) {
|
||||||
|
}
|
||||||
|
|
||||||
|
co_return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
IAsyncOperation<InMemoryRandomAccessStream> ImageView::GetImageInlineDataAsync(ImageSource source) {
|
||||||
|
std::string uri{to_string(source.uri)};
|
||||||
|
|
||||||
|
size_t start = uri.find(',');
|
||||||
|
if (start == std::string::npos || start + 1 > uri.length()) {
|
||||||
|
co_return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
co_await winrt::resume_background();
|
||||||
|
|
||||||
|
std::string_view base64String{uri.c_str() + start + 1, uri.length() - start - 1};
|
||||||
|
auto const &buffer{CryptographicBuffer::DecodeFromBase64String(to_hstring(base64String))};
|
||||||
|
|
||||||
|
InMemoryRandomAccessStream memoryStream;
|
||||||
|
co_await memoryStream.WriteAsync(buffer);
|
||||||
|
memoryStream.Seek(0);
|
||||||
|
|
||||||
|
co_return memoryStream;
|
||||||
|
} catch (winrt::hresult_error const &) {
|
||||||
|
// Base64 decode failed
|
||||||
|
}
|
||||||
|
|
||||||
|
co_return nullptr;
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
58
windows/RNSVG/ImageView.h
Normal file
58
windows/RNSVG/ImageView.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ImageView.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
enum class ImageSourceType { Uri = 0, Download = 1, InlineData = 2 };
|
||||||
|
enum class ImageSourceFormat { Bitmap = 0, Svg = 1 };
|
||||||
|
struct ImageSource {
|
||||||
|
hstring uri{L""};
|
||||||
|
hstring method{L""};
|
||||||
|
std::vector<std::pair<hstring, hstring>> headers{};
|
||||||
|
float width{0.0f};
|
||||||
|
float height{0.0f};
|
||||||
|
float scale{1.0f};
|
||||||
|
bool packagerAsset{false};
|
||||||
|
ImageSourceType type{ImageSourceType::Uri};
|
||||||
|
ImageSourceFormat format{ImageSourceFormat::Bitmap};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ImageView : ImageViewT<ImageView, RNSVG::implementation::RenderableView> {
|
||||||
|
public:
|
||||||
|
ImageView() = default;
|
||||||
|
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void Render(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
void CreateResources(
|
||||||
|
Microsoft::Graphics::Canvas::ICanvasResourceCreator const &resourceCreator,
|
||||||
|
Microsoft::Graphics::Canvas::UI::CanvasCreateResourcesEventArgs const &args);
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
private:
|
||||||
|
RNSVG::SVGLength m_x{};
|
||||||
|
RNSVG::SVGLength m_y{};
|
||||||
|
RNSVG::SVGLength m_width{};
|
||||||
|
RNSVG::SVGLength m_height{};
|
||||||
|
|
||||||
|
// preserveAspectRatio
|
||||||
|
std::string m_align{""};
|
||||||
|
RNSVG::MeetOrSlice m_meetOrSlice{RNSVG::MeetOrSlice::Meet};
|
||||||
|
|
||||||
|
ImageSource m_source{};
|
||||||
|
Microsoft::Graphics::Canvas::CanvasBitmap m_bitmap{nullptr};
|
||||||
|
|
||||||
|
Windows::Foundation::IAsyncAction LoadImageSourceAsync(Microsoft::Graphics::Canvas::ICanvasResourceCreator resourceCreator, bool invalidate);
|
||||||
|
winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::InMemoryRandomAccessStream>
|
||||||
|
GetImageMemoryStreamAsync(ImageSource source);
|
||||||
|
Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::InMemoryRandomAccessStream>
|
||||||
|
GetImageStreamAsync(ImageSource source);
|
||||||
|
Windows::Foundation::IAsyncOperation<winrt::Windows::Storage::Streams::InMemoryRandomAccessStream>
|
||||||
|
GetImageInlineDataAsync(ImageSource source);
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct ImageView : ImageViewT<ImageView, implementation::ImageView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
34
windows/RNSVG/ImageViewManager.cpp
Normal file
34
windows/RNSVG/ImageViewManager.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "ImageViewManager.h"
|
||||||
|
#include "ImageViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
ImageViewManager::ImageViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGImage;
|
||||||
|
m_name = L"RNSVGImage";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> ImageViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"x", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"y", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"height", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"width", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"src", ViewManagerPropertyType::String);
|
||||||
|
|
||||||
|
// preserveAspectRatio
|
||||||
|
nativeProps.Insert(L"align", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"meetOrSlice", ViewManagerPropertyType::Number);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
windows/RNSVG/ImageViewManager.h
Normal file
16
windows/RNSVG/ImageViewManager.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ImageViewManager.g.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct ImageViewManager : ImageViewManagerT<ImageViewManager, RNSVG::implementation::RenderableViewManager> {
|
||||||
|
ImageViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct ImageViewManager : ImageViewManagerT<ImageViewManager, implementation::ImageViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
47
windows/RNSVG/LineView.cpp
Normal file
47
windows/RNSVG/LineView.cpp
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "LineView.h"
|
||||||
|
#include "LineView.g.cpp"
|
||||||
|
|
||||||
|
#include "JSValueXaml.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void LineView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "x1") {
|
||||||
|
m_x1 = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "y1") {
|
||||||
|
m_y1 = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "x2") {
|
||||||
|
m_x2 = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "y2") {
|
||||||
|
m_y2 = SVGLength::From(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
void LineView::CreateGeometry(UI::Xaml::CanvasControl const &canvas) {
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
|
||||||
|
float x1{Utils::GetAbsoluteLength(m_x1, canvas.Size().Width)};
|
||||||
|
float y1{Utils::GetAbsoluteLength(m_y1, canvas.Size().Height)};
|
||||||
|
float x2{Utils::GetAbsoluteLength(m_x2, canvas.Size().Width)};
|
||||||
|
float y2{Utils::GetAbsoluteLength(m_y2, canvas.Size().Height)};
|
||||||
|
|
||||||
|
auto const &pathBuilder{Geometry::CanvasPathBuilder(resourceCreator)};
|
||||||
|
pathBuilder.BeginFigure(x1, y1);
|
||||||
|
pathBuilder.AddLine (x2, y2);
|
||||||
|
pathBuilder.EndFigure(Geometry::CanvasFigureLoop::Open);
|
||||||
|
Geometry(Geometry::CanvasGeometry::CreatePath(pathBuilder));
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
21
windows/RNSVG/LineView.h
Normal file
21
windows/RNSVG/LineView.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "LineView.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct LineView : LineViewT<LineView, RNSVG::implementation::RenderableView> {
|
||||||
|
public:
|
||||||
|
LineView() = default;
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void CreateGeometry(Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RNSVG::SVGLength m_x1{};
|
||||||
|
RNSVG::SVGLength m_y1{};
|
||||||
|
RNSVG::SVGLength m_x2{};
|
||||||
|
RNSVG::SVGLength m_y2{};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct LineView : LineViewT<LineView, implementation::LineView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
29
windows/RNSVG/LineViewManager.cpp
Normal file
29
windows/RNSVG/LineViewManager.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "LineViewManager.h"
|
||||||
|
#include "LineViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
LineViewManager::LineViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGLine;
|
||||||
|
m_name = L"RNSVGLine";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> LineViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"x1", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"y1", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"x2", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"y2", ViewManagerPropertyType::String);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
15
windows/RNSVG/LineViewManager.h
Normal file
15
windows/RNSVG/LineViewManager.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "LineViewManager.g.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct LineViewManager : LineViewManagerT<LineViewManager, RNSVG::implementation::RenderableViewManager> {
|
||||||
|
LineViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct LineViewManager : LineViewManagerT<LineViewManager, implementation::LineViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
81
windows/RNSVG/LinearGradientView.cpp
Normal file
81
windows/RNSVG/LinearGradientView.cpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "LinearGradientView.h"
|
||||||
|
#include "LinearGradientView.g.cpp"
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void LinearGradientView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "x1") {
|
||||||
|
m_x1 = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "y1") {
|
||||||
|
m_y1 = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "x2") {
|
||||||
|
m_x2 = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "y2") {
|
||||||
|
m_y2 = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "gradient") {
|
||||||
|
m_stops = Utils::JSValueAsStops(propertyValue);
|
||||||
|
} else if (propertyName == "gradientUnits") {
|
||||||
|
m_gradientUnits = Utils::JSValueAsBrushUnits(propertyValue);
|
||||||
|
} else if (propertyName == "gradientTransform") {
|
||||||
|
m_transformSet = true;
|
||||||
|
m_transform = Utils::JSValueAsTransform(propertyValue);
|
||||||
|
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
m_transformSet = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
|
||||||
|
SaveDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearGradientView::Unload() {
|
||||||
|
m_stops.clear();
|
||||||
|
__super::Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearGradientView::CreateBrush() {
|
||||||
|
auto const &canvas{SvgRoot().Canvas()};
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
Brushes::CanvasLinearGradientBrush brush{resourceCreator, m_stops};
|
||||||
|
|
||||||
|
SetPoints(brush, {0, 0, canvas.Size().Width, canvas.Size().Height});
|
||||||
|
|
||||||
|
if (m_transformSet) {
|
||||||
|
brush.Transform(m_transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_brush = brush;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearGradientView::UpdateBounds() {
|
||||||
|
if (m_gradientUnits == "objectBoundingBox") {
|
||||||
|
SetPoints(m_brush.as<Brushes::CanvasLinearGradientBrush>(), m_bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LinearGradientView::SetPoints(Brushes::CanvasLinearGradientBrush brush, Windows::Foundation::Rect const &bounds) {
|
||||||
|
float x1{Utils::GetAbsoluteLength(m_x1, bounds.Width) + bounds.X};
|
||||||
|
float y1{Utils::GetAbsoluteLength(m_y1, bounds.Height) + bounds.Y};
|
||||||
|
float x2{Utils::GetAbsoluteLength(m_x2, bounds.Width) + bounds.X};
|
||||||
|
float y2{Utils::GetAbsoluteLength(m_y2, bounds.Height) + bounds.Y};
|
||||||
|
|
||||||
|
brush.StartPoint({x1, y1});
|
||||||
|
brush.EndPoint({x2, y2});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
32
windows/RNSVG/LinearGradientView.h
Normal file
32
windows/RNSVG/LinearGradientView.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "LinearGradientView.g.h"
|
||||||
|
#include "BrushView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct LinearGradientView : LinearGradientViewT<LinearGradientView, RNSVG::implementation::BrushView> {
|
||||||
|
public:
|
||||||
|
LinearGradientView() = default;
|
||||||
|
|
||||||
|
// RenderableView
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
private:
|
||||||
|
RNSVG::SVGLength m_x1{};
|
||||||
|
RNSVG::SVGLength m_y1{};
|
||||||
|
RNSVG::SVGLength m_x2{};
|
||||||
|
RNSVG::SVGLength m_y2{};
|
||||||
|
std::vector<Microsoft::Graphics::Canvas::Brushes::CanvasGradientStop> m_stops{};
|
||||||
|
std::string m_gradientUnits{"objectBoundingBox"};
|
||||||
|
bool m_transformSet{false};
|
||||||
|
Numerics::float3x2 m_transform{Numerics::make_float3x2_scale(1)};
|
||||||
|
|
||||||
|
void CreateBrush();
|
||||||
|
void UpdateBounds();
|
||||||
|
void SetPoints(Microsoft::Graphics::Canvas::Brushes::CanvasLinearGradientBrush brush, Windows::Foundation::Rect const &bounds);
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct LinearGradientView : LinearGradientViewT<LinearGradientView, implementation::LinearGradientView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
32
windows/RNSVG/LinearGradientViewManager.cpp
Normal file
32
windows/RNSVG/LinearGradientViewManager.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "LinearGradientViewManager.h"
|
||||||
|
#include "LinearGradientViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
LinearGradientViewManager::LinearGradientViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGLinearGradient;
|
||||||
|
m_name = L"RNSVGLinearGradient";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> LinearGradientViewManager::NativeProps() {
|
||||||
|
auto const& parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"x1", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"y1", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"x2", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"y2", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"gradient", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"gradientUnits", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"gradientTransform", ViewManagerPropertyType::Array);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
18
windows/RNSVG/LinearGradientViewManager.h
Normal file
18
windows/RNSVG/LinearGradientViewManager.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "LinearGradientViewManager.g.h"
|
||||||
|
#include "GroupViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct LinearGradientViewManager
|
||||||
|
: LinearGradientViewManagerT<LinearGradientViewManager, RNSVG::implementation::GroupViewManager> {
|
||||||
|
LinearGradientViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct LinearGradientViewManager
|
||||||
|
: LinearGradientViewManagerT<LinearGradientViewManager, implementation::LinearGradientViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
295
windows/RNSVG/PathView.cpp
Normal file
295
windows/RNSVG/PathView.cpp
Normal file
@@ -0,0 +1,295 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "PathView.h"
|
||||||
|
#if __has_include("PathView.g.cpp")
|
||||||
|
#include "PathView.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <winrt/Microsoft.Graphics.Canvas.Svg.h>
|
||||||
|
|
||||||
|
#include "JSValueXaml.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void PathView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "d") {
|
||||||
|
m_commands.clear();
|
||||||
|
m_segmentData.clear();
|
||||||
|
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
m_d.clear();
|
||||||
|
} else {
|
||||||
|
m_d = propertyValue.AsString();
|
||||||
|
ParsePath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathView::CreateGeometry(UI::Xaml::CanvasControl const &canvas) {
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
Svg::CanvasSvgDocument doc{resourceCreator};
|
||||||
|
auto const &path{doc.CreatePathAttribute(m_segmentData, m_commands)};
|
||||||
|
Geometry(path.CreatePathGeometry());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathView::ParsePath() {
|
||||||
|
char prev_cmd = ' ';
|
||||||
|
|
||||||
|
size_t i{0};
|
||||||
|
auto length{m_d.length()};
|
||||||
|
while (i < length) {
|
||||||
|
SkipSpaces(i);
|
||||||
|
|
||||||
|
if (i > length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has_prev_cmd{prev_cmd != ' '};
|
||||||
|
char first_char = m_d.at(i);
|
||||||
|
|
||||||
|
if (!has_prev_cmd && first_char != 'M' && first_char != 'm') {
|
||||||
|
throw hresult_invalid_argument(L"First segment must be a MoveTo.");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_implicit_move_to{false};
|
||||||
|
char cmd = ' ';
|
||||||
|
|
||||||
|
if (IsCommand(first_char)) {
|
||||||
|
cmd = first_char;
|
||||||
|
m_commands.push_back(m_cmds[cmd]);
|
||||||
|
++i;
|
||||||
|
} else if (has_prev_cmd && IsNumberStart(first_char)) {
|
||||||
|
if (prev_cmd == 'Z' || prev_cmd == 'z') {
|
||||||
|
throw hresult_invalid_argument(L"ClosePath cannot be followed by a number.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prev_cmd == 'M' || prev_cmd == 'm') {
|
||||||
|
// If a MoveTo is followed by multiple pairs of coordinates,
|
||||||
|
// the subsequent pairs are treated as implicit LineTo commands.
|
||||||
|
is_implicit_move_to = true;
|
||||||
|
if (IsUpper(prev_cmd)) {
|
||||||
|
cmd = 'L';
|
||||||
|
m_commands.push_back(m_cmds[cmd]);
|
||||||
|
} else {
|
||||||
|
cmd = 'l';
|
||||||
|
m_commands.push_back(m_cmds[cmd]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cmd = prev_cmd;
|
||||||
|
m_commands.push_back(m_cmds[cmd]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw hresult_invalid_argument(L"Unexpected character: " + first_char);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool absolute{IsUpper(cmd)};
|
||||||
|
switch (cmd) {
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
case 'l':
|
||||||
|
case 'L':
|
||||||
|
case 't':
|
||||||
|
case 'T':
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
case 'v':
|
||||||
|
case 'V':
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
case 'C':
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
case 'A':
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseFlag(i));
|
||||||
|
m_segmentData.push_back(ParseFlag(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
m_segmentData.push_back(ParseListNumber(i));
|
||||||
|
break;
|
||||||
|
case 'z':
|
||||||
|
case 'Z':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw hresult_invalid_argument(L"Unexpected command.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_implicit_move_to) {
|
||||||
|
if (absolute) {
|
||||||
|
prev_cmd = 'M';
|
||||||
|
} else {
|
||||||
|
prev_cmd = 'm';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
prev_cmd = cmd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathView::SkipSpaces(size_t &index) {
|
||||||
|
while (index < m_d.length() && IsSpace(m_d.at(index))) {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathView::SkipDigits(size_t& index) {
|
||||||
|
while (index < m_d.length() && IsDigit(m_d.at(index))) {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PathView::SkipListSeparator(size_t& index) {
|
||||||
|
if (index < m_d.length() && m_d.at(index) == ',') {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathView::IsCommand(char const &cmd) {
|
||||||
|
return m_cmds.find(cmd) != m_cmds.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathView::IsNumberStart(char const& c) {
|
||||||
|
return IsDigit(c) || c == '.' || c == '-' || c == '+';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathView::IsDigit(char const &c) {
|
||||||
|
return std::isdigit(static_cast<unsigned char>(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathView::IsUpper(char const &c) {
|
||||||
|
return std::isupper(static_cast<unsigned char>(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathView::IsSpace(char const& c) {
|
||||||
|
return std::isspace(static_cast<unsigned char>(c));
|
||||||
|
}
|
||||||
|
|
||||||
|
float PathView::ParseListNumber(size_t &index) {
|
||||||
|
if (index == m_d.length()) {
|
||||||
|
throw hresult_invalid_argument(L"Unexpected end.");
|
||||||
|
}
|
||||||
|
|
||||||
|
float result{ParseNumber(index)};
|
||||||
|
SkipSpaces(index);
|
||||||
|
SkipListSeparator(index);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PathView::ParseNumber(size_t &index) {
|
||||||
|
SkipSpaces(index);
|
||||||
|
|
||||||
|
if (index == m_d.length()) {
|
||||||
|
throw hresult_invalid_argument(L"Unexpected end.");
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t start = index;
|
||||||
|
char c = m_d.at(start);
|
||||||
|
|
||||||
|
// Consume sign.
|
||||||
|
if (c == '-' || c == '+') {
|
||||||
|
++index;
|
||||||
|
c = m_d.at(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume integer.
|
||||||
|
if (IsDigit(c)) {
|
||||||
|
SkipDigits(index);
|
||||||
|
if (index < m_d.length()) {
|
||||||
|
c = m_d.at(index);
|
||||||
|
}
|
||||||
|
} else if (c != '.') {
|
||||||
|
throw hresult_invalid_argument(L"Invalid number formating character.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consume fraction.
|
||||||
|
if (c == '.') {
|
||||||
|
++index;
|
||||||
|
SkipDigits(index);
|
||||||
|
if (index < m_d.length()) {
|
||||||
|
c = m_d.at(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((c == 'e' || c == 'E') && ((index + 1) < m_d.length())) {
|
||||||
|
char c2 = m_d.at(index + 1);
|
||||||
|
// Check for 'em'/'ex'
|
||||||
|
if (c2 != 'm' && c2 != 'x') {
|
||||||
|
++index;
|
||||||
|
c = m_d.at(index);
|
||||||
|
|
||||||
|
if (c == '+' || c == '-') {
|
||||||
|
++index;
|
||||||
|
SkipDigits(index);
|
||||||
|
} else if (IsDigit(c)) {
|
||||||
|
SkipDigits(index);
|
||||||
|
} else {
|
||||||
|
throw hresult_invalid_argument(L"Invalid number formating character.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto num{m_d.substr(start, index)};
|
||||||
|
auto result{std::stof(num, nullptr)};
|
||||||
|
|
||||||
|
if (std::isinf(result) || std::isnan(result)) {
|
||||||
|
throw hresult_invalid_argument(L"Invalid number.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PathView::ParseFlag(size_t& index) {
|
||||||
|
SkipSpaces(index);
|
||||||
|
|
||||||
|
char c = m_d.at(index);
|
||||||
|
switch (c) {
|
||||||
|
case '0':
|
||||||
|
case '1': {
|
||||||
|
++index;
|
||||||
|
if (index < m_d.length() && m_d.at(index) == ',') {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
SkipSpaces(index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw hresult_invalid_argument(L"Unexpected flag.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<float>(c - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
61
windows/RNSVG/PathView.h
Normal file
61
windows/RNSVG/PathView.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "PathView.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct PathView : PathViewT<PathView, RNSVG::implementation::RenderableView> {
|
||||||
|
public:
|
||||||
|
PathView() = default;
|
||||||
|
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void CreateGeometry(Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_d;
|
||||||
|
std::vector<float> m_segmentData;
|
||||||
|
std::vector<Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand> m_commands;
|
||||||
|
|
||||||
|
std::map<char, Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand> m_cmds{
|
||||||
|
{'M', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::MoveAbsolute},
|
||||||
|
{'m', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::MoveRelative},
|
||||||
|
{'Z', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::ClosePath},
|
||||||
|
{'z', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::ClosePath},
|
||||||
|
{'L', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::LineAbsolute},
|
||||||
|
{'l', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::LineRelative},
|
||||||
|
{'H', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::HorizontalAbsolute},
|
||||||
|
{'h', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::HorizontalRelative},
|
||||||
|
{'V', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::VerticalAbsolute},
|
||||||
|
{'v', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::VerticalRelative},
|
||||||
|
{'C', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::CubicAbsolute},
|
||||||
|
{'c', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::CubicRelative},
|
||||||
|
{'S', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::CubicSmoothAbsolute},
|
||||||
|
{'s', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::CubicSmoothRelative},
|
||||||
|
{'Q', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::QuadraticAbsolute},
|
||||||
|
{'q', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::QuadraticRelative},
|
||||||
|
{'T', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::QuadraticSmoothAbsolute},
|
||||||
|
{'t', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::QuadraticSmoothRelative},
|
||||||
|
{'A', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::ArcAbsolute},
|
||||||
|
{'a', Microsoft::Graphics::Canvas::Svg::CanvasSvgPathCommand::ArcRelative},
|
||||||
|
};
|
||||||
|
|
||||||
|
void ParsePath();
|
||||||
|
|
||||||
|
// Parser helpers
|
||||||
|
void SkipSpaces(size_t &index);
|
||||||
|
void SkipDigits(size_t &index);
|
||||||
|
void SkipListSeparator(size_t &index);
|
||||||
|
bool IsCommand(char const &cmd);
|
||||||
|
bool IsNumberStart(char const &c);
|
||||||
|
bool IsDigit(char const &c);
|
||||||
|
bool IsUpper(char const &c);
|
||||||
|
bool IsSpace(char const &c);
|
||||||
|
float ParseListNumber(size_t &index);
|
||||||
|
float ParseNumber(size_t &index);
|
||||||
|
float ParseFlag(size_t &index);
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct PathView : PathViewT<PathView, implementation::PathView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
31
windows/RNSVG/PathViewManager.cpp
Normal file
31
windows/RNSVG/PathViewManager.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "PathViewManager.h"
|
||||||
|
#if __has_include("PathViewManager.g.cpp")
|
||||||
|
#include "PathViewManager.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "PathViewManager.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
PathViewManager::PathViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGPath;
|
||||||
|
m_name = L"RNSVGPath";
|
||||||
|
}
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> PathViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"d", ViewManagerPropertyType::String);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
17
windows/RNSVG/PathViewManager.h
Normal file
17
windows/RNSVG/PathViewManager.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "PathViewManager.g.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct PathViewManager : PathViewManagerT<PathViewManager, RNSVG::implementation::RenderableViewManager> {
|
||||||
|
PathViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct PathViewManager : PathViewManagerT<PathViewManager, implementation::PathViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
134
windows/RNSVG/PatternView.cpp
Normal file
134
windows/RNSVG/PatternView.cpp
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "PatternView.h"
|
||||||
|
#include "PatternView.g.cpp"
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void PatternView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "x") {
|
||||||
|
m_x = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "y") {
|
||||||
|
m_y = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "width") {
|
||||||
|
m_width = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "height") {
|
||||||
|
m_height = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "patternUnits") {
|
||||||
|
m_patternUnits = Utils::JSValueAsBrushUnits(propertyValue);
|
||||||
|
} else if (propertyName == "patternContentUnits") {
|
||||||
|
m_patternContentUnits = Utils::JSValueAsBrushUnits(propertyValue, "userSpaceOnUse");
|
||||||
|
} else if (propertyName == "patternTransform") {
|
||||||
|
m_transformSet = true;
|
||||||
|
m_transform = Utils::JSValueAsTransform(propertyValue);
|
||||||
|
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
m_transformSet = false;
|
||||||
|
}
|
||||||
|
} else if (propertyName == "vbWidth") {
|
||||||
|
m_vbWidth = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "vbHeight") {
|
||||||
|
m_vbHeight = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "minX") {
|
||||||
|
m_minX = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "minY") {
|
||||||
|
m_minY = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "align") {
|
||||||
|
m_align = Utils::JSValueAsString(propertyValue);
|
||||||
|
} else if (propertyName == "meetOrSlice") {
|
||||||
|
m_meetOrSlice = Utils::GetMeetOrSlice(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
|
||||||
|
SaveDefinition();
|
||||||
|
|
||||||
|
if (auto const &root{SvgRoot()}) {
|
||||||
|
root.InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PatternView::UpdateBounds() {
|
||||||
|
if (m_patternUnits == "objectBoundingBox") {
|
||||||
|
Rect rect{GetAdjustedRect(m_bounds)};
|
||||||
|
CreateBrush(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PatternView::CreateBrush() {
|
||||||
|
auto const &canvas{SvgRoot().Canvas()};
|
||||||
|
|
||||||
|
Rect elRect{GetAdjustedRect({0, 0, canvas.Size().Width, canvas.Size().Height})};
|
||||||
|
CreateBrush(elRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PatternView::CreateBrush(Windows::Foundation::Rect const &rect) {
|
||||||
|
auto const &canvas{SvgRoot().Canvas()};
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
|
||||||
|
if (auto const &cmdList{GetCommandList(rect)}) {
|
||||||
|
Brushes::CanvasImageBrush brush{resourceCreator, cmdList};
|
||||||
|
|
||||||
|
brush.SourceRectangle(rect);
|
||||||
|
brush.ExtendX(Microsoft::Graphics::Canvas::CanvasEdgeBehavior::Wrap);
|
||||||
|
brush.ExtendY(Microsoft::Graphics::Canvas::CanvasEdgeBehavior::Wrap);
|
||||||
|
|
||||||
|
cmdList.Close();
|
||||||
|
|
||||||
|
m_brush = brush;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows::Foundation::Rect PatternView::GetAdjustedRect(Windows::Foundation::Rect const &bounds) {
|
||||||
|
float x{Utils::GetAbsoluteLength(m_x, bounds.Width) + bounds.X};
|
||||||
|
float y{Utils::GetAbsoluteLength(m_y, bounds.Height) + bounds.Y};
|
||||||
|
float width{Utils::GetAbsoluteLength(m_width, bounds.Width)};
|
||||||
|
float height{Utils::GetAbsoluteLength(m_height, bounds.Height)};
|
||||||
|
|
||||||
|
return {x, y, width, height};
|
||||||
|
}
|
||||||
|
|
||||||
|
Microsoft::Graphics::Canvas::CanvasCommandList PatternView::GetCommandList(Windows::Foundation::Rect const &rect) {
|
||||||
|
auto const &root{SvgRoot()};
|
||||||
|
auto const &canvas{root.Canvas()};
|
||||||
|
auto const &cmdList{CanvasCommandList(canvas)};
|
||||||
|
auto const &session{cmdList.CreateDrawingSession()};
|
||||||
|
|
||||||
|
if (m_align != "") {
|
||||||
|
Rect vbRect{
|
||||||
|
m_minX * root.SvgScale(),
|
||||||
|
m_minY * root.SvgScale(),
|
||||||
|
(m_vbWidth + m_minX) * root.SvgScale(),
|
||||||
|
(m_vbHeight + m_minY) * root.SvgScale()};
|
||||||
|
|
||||||
|
auto transform{Utils::GetViewBoxTransform(vbRect, rect, m_align, m_meetOrSlice)};
|
||||||
|
|
||||||
|
if (m_transformSet) {
|
||||||
|
transform = transform * m_transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Transform(transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.Render(canvas, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Close();
|
||||||
|
return cmdList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
44
windows/RNSVG/PatternView.h
Normal file
44
windows/RNSVG/PatternView.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "PatternView.g.h"
|
||||||
|
#include "BrushView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct PatternView : PatternViewT<PatternView, RNSVG::implementation::BrushView> {
|
||||||
|
public:
|
||||||
|
PatternView() = default;
|
||||||
|
|
||||||
|
// RenderableView
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RNSVG::SVGLength m_x{};
|
||||||
|
RNSVG::SVGLength m_y{};
|
||||||
|
RNSVG::SVGLength m_width{};
|
||||||
|
RNSVG::SVGLength m_height{};
|
||||||
|
std::string m_patternUnits{"objectBoundingBox"};
|
||||||
|
std::string m_patternContentUnits{"userSpaceOnUse"};
|
||||||
|
bool m_transformSet{false};
|
||||||
|
Numerics::float3x2 m_transform{Numerics::make_float3x2_scale(1)};
|
||||||
|
|
||||||
|
// ViewBox
|
||||||
|
float m_minX{0.0f};
|
||||||
|
float m_minY{0.0f};
|
||||||
|
float m_vbWidth{0.0f};
|
||||||
|
float m_vbHeight{0.0f};
|
||||||
|
std::string m_align{""};
|
||||||
|
RNSVG::MeetOrSlice m_meetOrSlice{RNSVG::MeetOrSlice::Meet};
|
||||||
|
|
||||||
|
// BrushView
|
||||||
|
void CreateBrush();
|
||||||
|
void UpdateBounds();
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
void CreateBrush(Windows::Foundation::Rect const &rect);
|
||||||
|
Windows::Foundation::Rect GetAdjustedRect(Windows::Foundation::Rect const &bounds);
|
||||||
|
Microsoft::Graphics::Canvas::CanvasCommandList GetCommandList(Windows::Foundation::Rect const &elRect);
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct PatternView : PatternViewT<PatternView, implementation::PatternView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
38
windows/RNSVG/PatternViewManager.cpp
Normal file
38
windows/RNSVG/PatternViewManager.cpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "PatternViewManager.h"
|
||||||
|
#include "PatternViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
PatternViewManager::PatternViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGPattern;
|
||||||
|
m_name = L"RNSVGPattern";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> PatternViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"x", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"y", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"width", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"height", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"patternUnits", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"patternContentUnits", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"patternTransform", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"minX", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"minY", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"vbWidth", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"vbHeight", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"align", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"meetOrSlice", ViewManagerPropertyType::Number);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
16
windows/RNSVG/PatternViewManager.h
Normal file
16
windows/RNSVG/PatternViewManager.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "PatternViewManager.g.h"
|
||||||
|
#include "GroupViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct PatternViewManager : PatternViewManagerT<PatternViewManager, RNSVG::implementation::GroupViewManager> {
|
||||||
|
PatternViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct PatternViewManager : PatternViewManagerT<PatternViewManager, implementation::PatternViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
16
windows/RNSVG/PropertySheet.props
Normal file
16
windows/RNSVG/PropertySheet.props
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ImportGroup Label="PropertySheets" />
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<!--
|
||||||
|
To customize common C++/WinRT project properties:
|
||||||
|
* right-click the project node
|
||||||
|
* expand the Common Properties item
|
||||||
|
* select the C++/WinRT property page
|
||||||
|
|
||||||
|
For more advanced scenarios, and complete documentation, please see:
|
||||||
|
https://github.com/Microsoft/xlang/tree/master/src/package/cppwinrt/nuget
|
||||||
|
-->
|
||||||
|
<PropertyGroup />
|
||||||
|
<ItemDefinitionGroup />
|
||||||
|
</Project>
|
||||||
3
windows/RNSVG/RNSVG.def
Normal file
3
windows/RNSVG/RNSVG.def
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
EXPORTS
|
||||||
|
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
|
||||||
|
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE
|
||||||
240
windows/RNSVG/RNSVG.vcxproj
Normal file
240
windows/RNSVG/RNSVG.vcxproj
Normal file
@@ -0,0 +1,240 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="16.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||||
|
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
|
||||||
|
<MinimalCoreWin>true</MinimalCoreWin>
|
||||||
|
<ProjectGuid>{7acf84ec-efba-4043-8e14-40b159508902}</ProjectGuid>
|
||||||
|
<ProjectName>RNSVG</ProjectName>
|
||||||
|
<RootNamespace>RNSVG</RootNamespace>
|
||||||
|
<DefaultLanguage>en-US</DefaultLanguage>
|
||||||
|
<MinimumVisualStudioVersion>16.0</MinimumVisualStudioVersion>
|
||||||
|
<AppContainerApplication>true</AppContainerApplication>
|
||||||
|
<ApplicationType>Windows Store</ApplicationType>
|
||||||
|
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||||
|
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.18362.0</WindowsTargetPlatformVersion>
|
||||||
|
<WindowsTargetPlatformMinVersion>10.0.16299.0</WindowsTargetPlatformMinVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Label="ReactNativeWindowsProps">
|
||||||
|
<ReactNativeWindowsDir Condition="'$(ReactNativeWindowsDir)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(SolutionDir), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\</ReactNativeWindowsDir>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|ARM">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>ARM</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|ARM64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>ARM64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|ARM">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>ARM</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|ARM64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>ARM64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Configuration">
|
||||||
|
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||||
|
<CharacterSet>Unicode</CharacterSet>
|
||||||
|
<GenerateManifest>false</GenerateManifest>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<LinkIncremental>true</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<LinkIncremental>false</LinkIncremental>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets">
|
||||||
|
<Import Project="PropertySheet.props" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="ReactNativeWindowsPropertySheets">
|
||||||
|
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\external\Microsoft.ReactNative.Uwp.CppLib.props" Condition="Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.Uwp.CppLib.props')" />
|
||||||
|
<Import Project="$(SolutionDir)\packages\$(WinUIPackageProps)" Condition="'$(WinUIPackageProps)'!='' And Exists('$(SolutionDir)\packages\$(WinUIPackageProps)')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<ClCompile>
|
||||||
|
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||||
|
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
|
||||||
|
<PrecompiledHeaderOutputFile>$(IntDir)pch.pch</PrecompiledHeaderOutputFile>
|
||||||
|
<WarningLevel>Level4</WarningLevel>
|
||||||
|
<AdditionalOptions>%(AdditionalOptions) /bigobj</AdditionalOptions>
|
||||||
|
<DisableSpecificWarnings>4453;28204</DisableSpecificWarnings>
|
||||||
|
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<SubSystem>Console</SubSystem>
|
||||||
|
<GenerateWindowsMetadata>true</GenerateWindowsMetadata>
|
||||||
|
<ModuleDefinitionFile>RNSVG.def</ModuleDefinitionFile>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||||
|
<ClCompile>
|
||||||
|
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="BrushView.h" />
|
||||||
|
<ClInclude Include="CircleView.h" />
|
||||||
|
<ClInclude Include="CircleViewManager.h" />
|
||||||
|
<ClInclude Include="DefsView.h" />
|
||||||
|
<ClInclude Include="DefsViewManager.h" />
|
||||||
|
<ClInclude Include="EllipseView.h" />
|
||||||
|
<ClInclude Include="EllipseViewManager.h" />
|
||||||
|
<ClInclude Include="GroupView.h" />
|
||||||
|
<ClInclude Include="GroupViewManager.h" />
|
||||||
|
<ClInclude Include="ImageView.h" />
|
||||||
|
<ClInclude Include="ImageViewManager.h" />
|
||||||
|
<ClInclude Include="LinearGradientView.h" />
|
||||||
|
<ClInclude Include="LinearGradientViewManager.h" />
|
||||||
|
<ClInclude Include="LineView.h" />
|
||||||
|
<ClInclude Include="LineViewManager.h" />
|
||||||
|
<ClInclude Include="PathView.h" />
|
||||||
|
<ClInclude Include="PathViewManager.h" />
|
||||||
|
<ClInclude Include="PatternView.h" />
|
||||||
|
<ClInclude Include="PatternViewManager.h" />
|
||||||
|
<ClInclude Include="RadialGradientView.h" />
|
||||||
|
<ClInclude Include="RadialGradientViewManager.h" />
|
||||||
|
<ClInclude Include="RectView.h" />
|
||||||
|
<ClInclude Include="RectViewManager.h" />
|
||||||
|
<ClInclude Include="RenderableView.h" />
|
||||||
|
<ClInclude Include="RenderableViewManager.h" />
|
||||||
|
<ClInclude Include="SVGLength.h" />
|
||||||
|
<ClInclude Include="SvgView.h" />
|
||||||
|
<ClInclude Include="SvgViewManager.h" />
|
||||||
|
<ClInclude Include="SymbolView.h" />
|
||||||
|
<ClInclude Include="SymbolViewManager.h" />
|
||||||
|
<ClInclude Include="TextView.h" />
|
||||||
|
<ClInclude Include="TextViewManager.h" />
|
||||||
|
<ClInclude Include="TSpanView.h" />
|
||||||
|
<ClInclude Include="TSpanViewManager.h" />
|
||||||
|
<ClInclude Include="UseView.h" />
|
||||||
|
<ClInclude Include="UseViewManager.h" />
|
||||||
|
<ClInclude Include="Utils.h" />
|
||||||
|
<ClInclude Include="ReactPackageProvider.h">
|
||||||
|
<DependentUpon>ReactPackageProvider.idl</DependentUpon>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="RNSVGModule.h" />
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="BrushView.cpp" />
|
||||||
|
<ClCompile Include="CircleView.cpp" />
|
||||||
|
<ClCompile Include="CircleViewManager.cpp" />
|
||||||
|
<ClCompile Include="DefsView.cpp" />
|
||||||
|
<ClCompile Include="DefsViewManager.cpp" />
|
||||||
|
<ClCompile Include="EllipseView.cpp" />
|
||||||
|
<ClCompile Include="EllipseViewManager.cpp" />
|
||||||
|
<ClCompile Include="GroupView.cpp" />
|
||||||
|
<ClCompile Include="GroupViewManager.cpp" />
|
||||||
|
<ClCompile Include="ImageView.cpp" />
|
||||||
|
<ClCompile Include="ImageViewManager.cpp" />
|
||||||
|
<ClCompile Include="LinearGradientView.cpp" />
|
||||||
|
<ClCompile Include="LinearGradientViewManager.cpp" />
|
||||||
|
<ClCompile Include="LineView.cpp" />
|
||||||
|
<ClCompile Include="LineViewManager.cpp" />
|
||||||
|
<ClCompile Include="PathView.cpp" />
|
||||||
|
<ClCompile Include="PatternView.cpp" />
|
||||||
|
<ClCompile Include="PatternViewManager.cpp" />
|
||||||
|
<ClCompile Include="pch.cpp">
|
||||||
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PathViewManager.cpp" />
|
||||||
|
<ClCompile Include="RadialGradientView.cpp" />
|
||||||
|
<ClCompile Include="RadialGradientViewManager.cpp" />
|
||||||
|
<ClCompile Include="ReactPackageProvider.cpp">
|
||||||
|
<DependentUpon>ReactPackageProvider.idl</DependentUpon>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||||
|
<ClCompile Include="RectView.cpp" />
|
||||||
|
<ClCompile Include="RectViewManager.cpp" />
|
||||||
|
<ClCompile Include="RenderableView.cpp" />
|
||||||
|
<ClCompile Include="RenderableViewManager.cpp" />
|
||||||
|
<ClCompile Include="SVGLength.cpp" />
|
||||||
|
<ClCompile Include="SvgView.cpp" />
|
||||||
|
<ClCompile Include="SvgViewManager.cpp" />
|
||||||
|
<ClCompile Include="SymbolView.cpp" />
|
||||||
|
<ClCompile Include="SymbolViewManager.cpp" />
|
||||||
|
<ClCompile Include="TextView.cpp" />
|
||||||
|
<ClCompile Include="TextViewManager.cpp" />
|
||||||
|
<ClCompile Include="TSpanView.cpp" />
|
||||||
|
<ClCompile Include="TSpanViewManager.cpp" />
|
||||||
|
<ClCompile Include="UseView.cpp" />
|
||||||
|
<ClCompile Include="UseViewManager.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Midl Include="ReactPackageProvider.idl" />
|
||||||
|
<Midl Include="Types.idl" />
|
||||||
|
<Midl Include="Views.idl">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Midl>
|
||||||
|
<Midl Include="ViewManagers.idl">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Midl>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="packages.config" />
|
||||||
|
<None Include="PropertySheet.props" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ReactNativeWindowsTargets">
|
||||||
|
<Import Project="$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.Uwp.CppLib.targets" Condition="Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.Uwp.CppLib.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="EnsureReactNativeWindowsTargets" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references targets in your node_modules\react-native-windows folder that are missing. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.Uwp.CppLib.props')" Text="$([System.String]::Format('$(ErrorText)', '$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.Uwp.CppLib.props'))" />
|
||||||
|
<Error Condition="!Exists('$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.Uwp.CppLib.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(ReactNativeWindowsDir)\PropertySheets\External\Microsoft.ReactNative.Uwp.CppLib.targets'))" />
|
||||||
|
</Target>
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
<Import Project="$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||||
|
<Import Project="$(SolutionDir)\packages\$(WinUIPackageName).$(WinUIPackageVersion)\build\native\$(WinUIPackageName).targets" Condition="Exists('$(SolutionDir)\packages\$(WinUIPackageName).$(WinUIPackageVersion)\build\native\$(WinUIPackageName).targets')" />
|
||||||
|
<Import Project="$(SolutionDir)\packages\Win2D.uwp.1.25.0\build\native\Win2D.uwp.targets" Condition="Exists('$(SolutionDir)\packages\Win2D.uwp.1.25.0\build\native\Win2D.uwp.targets')" />
|
||||||
|
</ImportGroup>
|
||||||
|
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||||
|
<PropertyGroup>
|
||||||
|
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||||
|
<Error Condition="!Exists('$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Microsoft.Windows.CppWinRT.2.0.200615.7\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||||
|
<Error Condition="!Exists('$(SolutionDir)\packages\$(WinUIPackageName).$(WinUIPackageVersion)\build\native\$(WinUIPackageName).targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\$(WinUIPackageName).$(WinUIPackageVersion)\build\native\$(WinUIPackageName).targets'))" />
|
||||||
|
<Error Condition="!Exists('$(SolutionDir)\packages\Win2D.uwp.1.25.0\build\native\Win2D.uwp.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\packages\Win2D.uwp.1.25.0\build\native\Win2D.uwp.targets'))" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
268
windows/RNSVG/RNSVG.vcxproj.filters
Normal file
268
windows/RNSVG/RNSVG.vcxproj.filters
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Midl Include="ReactPackageProvider.idl" />
|
||||||
|
<Midl Include="Views.idl">
|
||||||
|
<Filter>IDLs</Filter>
|
||||||
|
</Midl>
|
||||||
|
<Midl Include="ViewManagers.idl">
|
||||||
|
<Filter>IDLs</Filter>
|
||||||
|
</Midl>
|
||||||
|
<Midl Include="Types.idl">
|
||||||
|
<Filter>IDLs</Filter>
|
||||||
|
</Midl>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="pch.cpp" />
|
||||||
|
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
|
||||||
|
<ClCompile Include="ReactPackageProvider.cpp" />
|
||||||
|
<ClCompile Include="RectView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="SVGLength.cpp">
|
||||||
|
<Filter>Utils</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="RectViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PathViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PathView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="GroupView.cpp">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="TextView.cpp">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="TSpanView.cpp">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="CircleView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="CircleViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="EllipseViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="EllipseView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="LineViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="LineView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="RenderableView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="SvgView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="SymbolView.cpp">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="SvgViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="RenderableViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="GroupViewManager.cpp">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="TextViewManager.cpp">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="TSpanViewManager.cpp">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="UseView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="SymbolViewManager.cpp">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="UseViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="DefsViewManager.cpp">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="LinearGradientViewManager.cpp">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="DefsView.cpp">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="LinearGradientView.cpp">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="BrushView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PatternViewManager.cpp">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="PatternView.cpp">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="ImageView.cpp">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="ImageViewManager.cpp">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="RadialGradientView.cpp">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="RadialGradientViewManager.cpp">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="pch.h" />
|
||||||
|
<ClInclude Include="ReactPackageProvider.h" />
|
||||||
|
<ClInclude Include="RNSVGModule.h" />
|
||||||
|
<ClInclude Include="RectView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Utils.h">
|
||||||
|
<Filter>Utils</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SVGLength.h">
|
||||||
|
<Filter>Utils</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="RectViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PathViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PathView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="GroupView.h">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="TextView.h">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="TSpanView.h">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="CircleView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="CircleViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="EllipseViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="EllipseView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="LineViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="LineView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="RenderableView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SvgView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SymbolView.h">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SvgViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="RenderableViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="GroupViewManager.h">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="TextViewManager.h">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="TSpanViewManager.h">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="UseView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="SymbolViewManager.h">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="UseViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="DefsViewManager.h">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="LinearGradientViewManager.h">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="DefsView.h">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="LinearGradientView.h">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="BrushView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PatternViewManager.h">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="PatternView.h">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ImageView.h">
|
||||||
|
<Filter>Views</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ImageViewManager.h">
|
||||||
|
<Filter>ViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="RadialGradientView.h">
|
||||||
|
<Filter>Views\GroupViews</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="RadialGradientViewManager.h">
|
||||||
|
<Filter>ViewManagers\GroupViewManagers</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="PropertySheet.props" />
|
||||||
|
<None Include="packages.config" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Views">
|
||||||
|
<UniqueIdentifier>{e902587e-fe1d-4643-875b-d58996b40d98}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="ViewManagers">
|
||||||
|
<UniqueIdentifier>{cb3ce7b2-9fdf-4578-8e0d-4d6853b727bc}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Utils">
|
||||||
|
<UniqueIdentifier>{8a4e0664-0d52-46ca-b476-a1ad90239a09}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Views\GroupViews">
|
||||||
|
<UniqueIdentifier>{96f26034-8559-4794-a806-4ecac541e02b}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="ViewManagers\GroupViewManagers">
|
||||||
|
<UniqueIdentifier>{5942afc3-8b5d-4d8c-bb09-e82581f606b7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="IDLs">
|
||||||
|
<UniqueIdentifier>{50f81ae3-d543-477a-a60c-a0f310289f29}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
33
windows/RNSVG/RNSVGModule.h
Normal file
33
windows/RNSVG/RNSVGModule.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "JSValue.h"
|
||||||
|
#include "NativeModules.h"
|
||||||
|
|
||||||
|
using namespace winrt::Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG
|
||||||
|
{
|
||||||
|
REACT_MODULE(RNSVGModule, L"RNSVG")
|
||||||
|
struct RNSVGModule
|
||||||
|
{
|
||||||
|
// See https://microsoft.github.io/react-native-windows/docs/native-modules for details on writing native modules
|
||||||
|
|
||||||
|
REACT_INIT(Initialize)
|
||||||
|
void Initialize(ReactContext const &reactContext) noexcept
|
||||||
|
{
|
||||||
|
m_reactContext = reactContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
REACT_METHOD(sampleMethod)
|
||||||
|
void
|
||||||
|
sampleMethod(std::string stringArgument, int numberArgument, std::function<void(std::string)> &&callback) noexcept
|
||||||
|
{
|
||||||
|
// TODO: Implement some actually useful functionality
|
||||||
|
callback("Received numberArgument: " + std::to_string(numberArgument) + " stringArgument: " + stringArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ReactContext m_reactContext{nullptr};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace winrt::RNSVG
|
||||||
92
windows/RNSVG/RadialGradientView.cpp
Normal file
92
windows/RNSVG/RadialGradientView.cpp
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "RadialGradientView.h"
|
||||||
|
#include "RadialGradientView.g.cpp"
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void RadialGradientView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "fx") {
|
||||||
|
m_fx = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "fy") {
|
||||||
|
m_fy = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "rx") {
|
||||||
|
m_rx = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "ry") {
|
||||||
|
m_ry = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "cx") {
|
||||||
|
m_cx = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "cy") {
|
||||||
|
m_cy = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "gradient") {
|
||||||
|
m_stops = Utils::JSValueAsStops(propertyValue);
|
||||||
|
} else if (propertyName == "gradientUnits") {
|
||||||
|
m_gradientUnits = Utils::JSValueAsBrushUnits(propertyValue);
|
||||||
|
} else if (propertyName == "gradientTransform") {
|
||||||
|
m_transformSet = true;
|
||||||
|
m_transform = Utils::JSValueAsTransform(propertyValue);
|
||||||
|
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
m_transformSet = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
|
||||||
|
SaveDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadialGradientView::Unload() {
|
||||||
|
m_stops.clear();
|
||||||
|
__super::Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadialGradientView::CreateBrush() {
|
||||||
|
auto const &canvas{SvgRoot().Canvas()};
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
Brushes::CanvasRadialGradientBrush brush{resourceCreator, m_stops};
|
||||||
|
|
||||||
|
SetPoints(brush, {0, 0, canvas.Size().Width, canvas.Size().Height});
|
||||||
|
|
||||||
|
if (m_transformSet) {
|
||||||
|
brush.Transform(m_transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_brush = brush;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadialGradientView::UpdateBounds() {
|
||||||
|
if (m_gradientUnits == "objectBoundingBox") {
|
||||||
|
SetPoints(m_brush.as<Brushes::CanvasRadialGradientBrush>(), m_bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RadialGradientView::SetPoints(Brushes::CanvasRadialGradientBrush brush, Windows::Foundation::Rect const &bounds) {
|
||||||
|
float rx{Utils::GetAbsoluteLength(m_rx, bounds.Width)};
|
||||||
|
float ry{Utils::GetAbsoluteLength(m_ry, bounds.Height)};
|
||||||
|
|
||||||
|
float fx{Utils::GetAbsoluteLength(m_fx, bounds.Width) + bounds.X};
|
||||||
|
float fy{Utils::GetAbsoluteLength(m_fy, bounds.Height) + bounds.Y};
|
||||||
|
|
||||||
|
float cx{Utils::GetAbsoluteLength(m_cx, bounds.Width) + bounds.X};
|
||||||
|
float cy{Utils::GetAbsoluteLength(m_cy, bounds.Height) + bounds.Y};
|
||||||
|
|
||||||
|
brush.RadiusX(rx);
|
||||||
|
brush.RadiusY(ry);
|
||||||
|
|
||||||
|
brush.Center({cx, cy});
|
||||||
|
brush.OriginOffset({(fx - cx), (fy - cy)});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
34
windows/RNSVG/RadialGradientView.h
Normal file
34
windows/RNSVG/RadialGradientView.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "RadialGradientView.g.h"
|
||||||
|
#include "BrushView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct RadialGradientView : RadialGradientViewT<RadialGradientView, RNSVG::implementation::BrushView> {
|
||||||
|
public:
|
||||||
|
RadialGradientView() = default;
|
||||||
|
|
||||||
|
// RenderableView
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
private:
|
||||||
|
RNSVG::SVGLength m_fx{};
|
||||||
|
RNSVG::SVGLength m_fy{};
|
||||||
|
RNSVG::SVGLength m_rx{};
|
||||||
|
RNSVG::SVGLength m_ry{};
|
||||||
|
RNSVG::SVGLength m_cx{};
|
||||||
|
RNSVG::SVGLength m_cy{};
|
||||||
|
std::vector<Microsoft::Graphics::Canvas::Brushes::CanvasGradientStop> m_stops{};
|
||||||
|
std::string m_gradientUnits{"objectBoundingBox"};
|
||||||
|
bool m_transformSet{false};
|
||||||
|
Numerics::float3x2 m_transform{Numerics::make_float3x2_scale(1)};
|
||||||
|
|
||||||
|
void CreateBrush();
|
||||||
|
void UpdateBounds();
|
||||||
|
void SetPoints(Microsoft::Graphics::Canvas::Brushes::CanvasRadialGradientBrush brush, Windows::Foundation::Rect const &bounds);
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct RadialGradientView : RadialGradientViewT<RadialGradientView, implementation::RadialGradientView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
34
windows/RNSVG/RadialGradientViewManager.cpp
Normal file
34
windows/RNSVG/RadialGradientViewManager.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "RadialGradientViewManager.h"
|
||||||
|
#include "RadialGradientViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
RadialGradientViewManager::RadialGradientViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGRadialGradient;
|
||||||
|
m_name = L"RNSVGRadialGradient";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> RadialGradientViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"fx", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"fy", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"rx", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"ry", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"cx", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"cy", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"gradient", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"gradientUnits", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"gradientTransform", ViewManagerPropertyType::Array);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
18
windows/RNSVG/RadialGradientViewManager.h
Normal file
18
windows/RNSVG/RadialGradientViewManager.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "RadialGradientViewManager.g.h"
|
||||||
|
#include "GroupViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct RadialGradientViewManager
|
||||||
|
: RadialGradientViewManagerT<RadialGradientViewManager, RNSVG::implementation::GroupViewManager> {
|
||||||
|
RadialGradientViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct RadialGradientViewManager
|
||||||
|
: RadialGradientViewManagerT<RadialGradientViewManager, implementation::RadialGradientViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
50
windows/RNSVG/ReactPackageProvider.cpp
Normal file
50
windows/RNSVG/ReactPackageProvider.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "ReactPackageProvider.h"
|
||||||
|
#if __has_include("ReactPackageProvider.g.cpp")
|
||||||
|
#include "ReactPackageProvider.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "RNSVGModule.h"
|
||||||
|
#include "SvgViewManager.h"
|
||||||
|
#include "GroupViewManager.h"
|
||||||
|
#include "PathViewManager.h"
|
||||||
|
#include "RectViewManager.h"
|
||||||
|
#include "CircleViewManager.h"
|
||||||
|
#include "EllipseViewManager.h"
|
||||||
|
#include "LineViewManager.h"
|
||||||
|
#include "UseViewManager.h"
|
||||||
|
#include "ImageViewManager.h"
|
||||||
|
#include "TextViewManager.h"
|
||||||
|
#include "TSpanViewManager.h"
|
||||||
|
#include "SymbolViewManager.h"
|
||||||
|
#include "DefsViewManager.h"
|
||||||
|
#include "LinearGradientViewManager.h"
|
||||||
|
#include "RadialGradientViewManager.h"
|
||||||
|
#include "PatternViewManager.h"
|
||||||
|
|
||||||
|
using namespace winrt::Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation
|
||||||
|
{
|
||||||
|
void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept
|
||||||
|
{
|
||||||
|
AddAttributedModules(packageBuilder);
|
||||||
|
packageBuilder.AddViewManager(L"SvgViewManager", []() { return winrt::make<SvgViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"GroupViewManager", []() { return winrt::make<GroupViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"PathViewManager", []() { return winrt::make<PathViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"RectViewManager", []() { return winrt::make<RectViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"CircleViewManager", []() { return winrt::make<CircleViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"EllipseViewManager", []() { return winrt::make<EllipseViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"LineViewManager", []() { return winrt::make<LineViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"UseViewManager", []() { return winrt::make<UseViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"ImageViewManager", []() { return winrt::make<ImageViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"TextViewManager", []() { return winrt::make<TextViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"TSpanViewManager", []() { return winrt::make<TSpanViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"SymbolViewManager", []() { return winrt::make<SymbolViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"DefsViewManager", []() { return winrt::make<DefsViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"LinearGradientViewManager", []() { return winrt::make<LinearGradientViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"RadialGradientViewManager", []() { return winrt::make<RadialGradientViewManager>(); });
|
||||||
|
packageBuilder.AddViewManager(L"PatternViewManager", []() { return winrt::make<PatternViewManager>(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
21
windows/RNSVG/ReactPackageProvider.h
Normal file
21
windows/RNSVG/ReactPackageProvider.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "ReactPackageProvider.g.h"
|
||||||
|
|
||||||
|
using namespace winrt::Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation
|
||||||
|
{
|
||||||
|
struct ReactPackageProvider : ReactPackageProviderT<ReactPackageProvider>
|
||||||
|
{
|
||||||
|
ReactPackageProvider() = default;
|
||||||
|
|
||||||
|
void CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept;
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation
|
||||||
|
{
|
||||||
|
|
||||||
|
struct ReactPackageProvider : ReactPackageProviderT<ReactPackageProvider, implementation::ReactPackageProvider> {};
|
||||||
|
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
9
windows/RNSVG/ReactPackageProvider.idl
Normal file
9
windows/RNSVG/ReactPackageProvider.idl
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace RNSVG
|
||||||
|
{
|
||||||
|
[webhosthidden]
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass ReactPackageProvider : Microsoft.ReactNative.IReactPackageProvider
|
||||||
|
{
|
||||||
|
ReactPackageProvider();
|
||||||
|
};
|
||||||
|
}
|
||||||
55
windows/RNSVG/RectView.cpp
Normal file
55
windows/RNSVG/RectView.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "RectView.h"
|
||||||
|
#if __has_include("RectView.g.cpp")
|
||||||
|
#include "RectView.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "JSValueXaml.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void RectView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "width") {
|
||||||
|
m_width = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "height") {
|
||||||
|
m_height = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "x") {
|
||||||
|
m_x = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "y") {
|
||||||
|
m_y = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "rx") {
|
||||||
|
m_rx = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "ry") {
|
||||||
|
m_ry = SVGLength::From(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RectView::CreateGeometry(UI::Xaml::CanvasControl const &canvas) {
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
|
||||||
|
float x{Utils::GetAbsoluteLength(m_x, canvas.Size().Width)};
|
||||||
|
float y{Utils::GetAbsoluteLength(m_y, canvas.Size().Height)};
|
||||||
|
float width{Utils::GetAbsoluteLength(m_width, canvas.Size().Width)};
|
||||||
|
float height{Utils::GetAbsoluteLength(m_height, canvas.Size().Height)};
|
||||||
|
|
||||||
|
auto const &rxLength{m_rx.Unit() == RNSVG::LengthType::Unknown ? m_ry : m_rx};
|
||||||
|
auto const &ryLength{m_ry.Unit() == RNSVG::LengthType::Unknown ? m_rx : m_ry};
|
||||||
|
float rx{Utils::GetAbsoluteLength(rxLength, canvas.Size().Width)};
|
||||||
|
float ry{Utils::GetAbsoluteLength(ryLength, canvas.Size().Height)};
|
||||||
|
|
||||||
|
Geometry(Geometry::CanvasGeometry::CreateRoundedRectangle(resourceCreator, x, y, width, height, rx, ry));
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
26
windows/RNSVG/RectView.h
Normal file
26
windows/RNSVG/RectView.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RectView.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct RectView : RectViewT<RectView, RNSVG::implementation::RenderableView> {
|
||||||
|
public:
|
||||||
|
RectView() = default;
|
||||||
|
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void CreateGeometry(Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas);
|
||||||
|
|
||||||
|
private:
|
||||||
|
RNSVG::SVGLength m_width{};
|
||||||
|
RNSVG::SVGLength m_height{};
|
||||||
|
RNSVG::SVGLength m_x{};
|
||||||
|
RNSVG::SVGLength m_y{};
|
||||||
|
RNSVG::SVGLength m_rx{};
|
||||||
|
RNSVG::SVGLength m_ry{};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct RectView : RectViewT<RectView, implementation::RectView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
36
windows/RNSVG/RectViewManager.cpp
Normal file
36
windows/RNSVG/RectViewManager.cpp
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "RectViewManager.h"
|
||||||
|
#if __has_include("RectViewManager.g.cpp")
|
||||||
|
#include "RectViewManager.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "RectView.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
RectViewManager::RectViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGRect;
|
||||||
|
m_name = L"RNSVGRect";
|
||||||
|
}
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> RectViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"height", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"width", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"x", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"y", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"rx", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"ry", ViewManagerPropertyType::String);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
17
windows/RNSVG/RectViewManager.h
Normal file
17
windows/RNSVG/RectViewManager.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RectViewManager.g.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct RectViewManager : RectViewManagerT<RectViewManager, RNSVG::implementation::RenderableViewManager> {
|
||||||
|
RectViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct RectViewManager : RectViewManagerT<RectViewManager, implementation::RectViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
341
windows/RNSVG/RenderableView.cpp
Normal file
341
windows/RNSVG/RenderableView.cpp
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
#if __has_include("RenderableView.g.cpp")
|
||||||
|
#include "RenderableView.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "JSValueXaml.h"
|
||||||
|
#include "SvgView.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void RenderableView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
auto const &parent{SvgParent().try_as<RNSVG::RenderableView>()};
|
||||||
|
|
||||||
|
auto const &propList{propertyMap.find("propList")};
|
||||||
|
if (propList != propertyMap.end()) {
|
||||||
|
m_propList.clear();
|
||||||
|
auto const &propValue{(*propList).second};
|
||||||
|
for (auto const &item : propValue.AsArray()) {
|
||||||
|
m_propList.push_back(Utils::JSValueAsString(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fillSet{std::find(m_propList.begin(), m_propList.end(), "fill") != m_propList.end()};
|
||||||
|
bool strokeSet{std::find(m_propList.begin(), m_propList.end(), "stroke") != m_propList.end()};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
auto prop{RNSVG::BaseProp::Unknown};
|
||||||
|
|
||||||
|
// name is not a prop we want to propagate to child elements
|
||||||
|
// so we only set it when forceUpdate = true
|
||||||
|
if (propertyName == "name" && forceUpdate) {
|
||||||
|
if (parent) {
|
||||||
|
SvgRoot().Templates().Remove(m_id);
|
||||||
|
}
|
||||||
|
m_id = to_hstring(Utils::JSValueAsString(propertyValue));
|
||||||
|
if (parent) {
|
||||||
|
SaveDefinition();
|
||||||
|
}
|
||||||
|
} else if (propertyName == "strokeWidth") {
|
||||||
|
prop = RNSVG::BaseProp::StrokeWidth;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
auto const &fallbackValue{parent ? parent.StrokeWidth() : RNSVG::SVGLength(1.0f, RNSVG::LengthType::Pixel)};
|
||||||
|
m_strokeWidth = Utils::JSValueAsSVGLength(propertyValue, fallbackValue);
|
||||||
|
}
|
||||||
|
} else if (propertyName == "strokeOpacity") {
|
||||||
|
prop = RNSVG::BaseProp::StrokeOpacity;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
float fallbackValue{parent ? parent.StrokeOpacity() : 1.0f};
|
||||||
|
m_strokeOpacity = Utils::JSValueAsFloat(propertyValue, fallbackValue);
|
||||||
|
}
|
||||||
|
} else if (propertyName == "fillOpacity") {
|
||||||
|
prop = RNSVG::BaseProp::FillOpacity;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
float fallbackValue{parent ? parent.FillOpacity() : 1.0f};
|
||||||
|
m_fillOpacity = Utils::JSValueAsFloat(propertyValue, fallbackValue);
|
||||||
|
}
|
||||||
|
} else if (propertyName == "stroke") {
|
||||||
|
prop = RNSVG::BaseProp::Stroke;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
if (propertyValue.Type() == JSValueType::Array) {
|
||||||
|
auto const &brush{propertyValue.AsArray()};
|
||||||
|
m_strokeBrushId = to_hstring(Utils::JSValueAsString(brush.at(1)));
|
||||||
|
} else {
|
||||||
|
Windows::UI::Color fallbackColor{(parent && !strokeSet) ? parent.Stroke() : Windows::UI::Colors::Transparent()};
|
||||||
|
m_stroke = Utils::JSValueAsColor(propertyValue, fallbackColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (propertyName == "fill") {
|
||||||
|
prop = RNSVG::BaseProp::Fill;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
if (propertyValue.Type() == JSValueType::Array) {
|
||||||
|
auto const &brush{propertyValue.AsArray()};
|
||||||
|
m_fillBrushId = to_hstring(Utils::JSValueAsString(brush.at(1)));
|
||||||
|
} else {
|
||||||
|
Windows::UI::Color fallbackColor{Windows::UI::Colors::Black()};
|
||||||
|
if (propertyValue.IsNull() && fillSet) {
|
||||||
|
fallbackColor = Windows::UI::Colors::Transparent();
|
||||||
|
} else if (parent) {
|
||||||
|
fallbackColor = parent.Fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_fill = Utils::JSValueAsColor(propertyValue, fallbackColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (propertyName == "strokeLinecap") {
|
||||||
|
prop = RNSVG::BaseProp::StrokeLineCap;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
m_strokeLineCap = parent.StrokeLineCap();
|
||||||
|
} else {
|
||||||
|
auto const &strokeLineCap{propertyValue.AsInt32()};
|
||||||
|
switch (strokeLineCap) {
|
||||||
|
case 2:
|
||||||
|
m_strokeLineCap = Geometry::CanvasCapStyle::Square;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
m_strokeLineCap = Geometry::CanvasCapStyle::Round;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
m_strokeLineCap = Geometry::CanvasCapStyle::Flat;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (propertyName == "strokeLinejoin") {
|
||||||
|
prop = RNSVG::BaseProp::StrokeLineJoin;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
m_strokeLineCap = parent.StrokeLineCap();
|
||||||
|
} else {
|
||||||
|
auto const &strokeLineJoin{propertyValue.AsInt32()};
|
||||||
|
switch (strokeLineJoin) {
|
||||||
|
case 2:
|
||||||
|
m_strokeLineJoin = Geometry::CanvasLineJoin::Bevel;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
m_strokeLineJoin = Geometry::CanvasLineJoin::Round;
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
m_strokeLineJoin = Geometry::CanvasLineJoin::Miter;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (propertyName == "fillRule") {
|
||||||
|
prop = RNSVG::BaseProp::FillRule;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
m_fillRule = parent.FillRule();
|
||||||
|
} else {
|
||||||
|
auto const &fillRule{propertyValue.AsInt32()};
|
||||||
|
switch (fillRule) {
|
||||||
|
case 0:
|
||||||
|
m_fillRule = Geometry::CanvasFilledRegionDetermination::Alternate;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
m_fillRule = Geometry::CanvasFilledRegionDetermination::Winding;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (propertyName == "strokeDashoffset") {
|
||||||
|
prop = RNSVG::BaseProp::StrokeDashOffset;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
float fallbackValue{parent ? parent.StrokeDashOffset() : 0.0f};
|
||||||
|
m_strokeDashOffset = Utils::JSValueAsFloat(propertyValue, fallbackValue);
|
||||||
|
}
|
||||||
|
} else if (propertyName == "strokeMiterlimit") {
|
||||||
|
prop = RNSVG::BaseProp::StrokeMiterLimit;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
float fallbackValue{parent ? parent.StrokeMiterLimit() : 0.0f};
|
||||||
|
m_strokeMiterLimit = Utils::JSValueAsFloat(propertyValue, fallbackValue);
|
||||||
|
}
|
||||||
|
} else if (propertyName == "strokeDasharray") {
|
||||||
|
prop = RNSVG::BaseProp::StrokeDashArray;
|
||||||
|
if (forceUpdate || !m_propSetMap[prop]) {
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
m_strokeDashArray = parent.StrokeDashArray();
|
||||||
|
} else {
|
||||||
|
auto const &asArray = propertyValue.AsArray();
|
||||||
|
|
||||||
|
if (!asArray.empty() && (asArray.size() % 2 == 0)) {
|
||||||
|
m_strokeDashArray.Clear();
|
||||||
|
|
||||||
|
for (auto const &item : asArray) {
|
||||||
|
m_strokeDashArray.Append(SVGLength::From(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (propertyName == "matrix") {
|
||||||
|
prop = RNSVG::BaseProp::Matrix;
|
||||||
|
if (forceUpdate) {
|
||||||
|
Numerics::float3x2 fallbackValue{parent ? parent.SvgTransform() : Numerics::make_float3x2_rotation(0)};
|
||||||
|
m_transformMatrix = Utils::JSValueAsTransform(propertyValue, fallbackValue);
|
||||||
|
}
|
||||||
|
} else if (propertyName == "opacity" && forceUpdate) {
|
||||||
|
m_opacity = Utils::JSValueAsFloat(propertyValue, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// forceUpdate = true means the property is being set on an element
|
||||||
|
// instead of being inherited from the parent.
|
||||||
|
if (forceUpdate && (prop != RNSVG::BaseProp::Unknown)) {
|
||||||
|
// If the propertyValue is null, that generally means the prop was deleted
|
||||||
|
bool propSet{!propertyValue.IsNull()};
|
||||||
|
|
||||||
|
// The exception being Fill and Stroke due to 'none' coming through as null
|
||||||
|
if (prop == RNSVG::BaseProp::Fill) {
|
||||||
|
propSet = fillSet;
|
||||||
|
} else if (prop == RNSVG::BaseProp::Stroke) {
|
||||||
|
propSet = strokeSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_propSetMap[prop] = propSet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_recreateResources = true;
|
||||||
|
|
||||||
|
if (invalidate && SvgParent()) {
|
||||||
|
SvgRoot().InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableView::SaveDefinition() {
|
||||||
|
if (m_id != L"") {
|
||||||
|
SvgRoot().Templates().Insert(m_id, *this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableView::Render(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
if (m_recreateResources) {
|
||||||
|
CreateGeometry(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto geometry{Geometry()};
|
||||||
|
if (m_propSetMap[RNSVG::BaseProp::Matrix]) {
|
||||||
|
geometry = geometry.Transform(SvgTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
geometry = Geometry::CanvasGeometry::CreateGroup(resourceCreator, {geometry}, FillRule());
|
||||||
|
|
||||||
|
if (auto const &opacityLayer{session.CreateLayer(m_opacity)}) {
|
||||||
|
if (auto const &fillLayer{session.CreateLayer(FillOpacity())}) {
|
||||||
|
auto const &fill{Utils::GetCanvasBrush(FillBrushId(), Fill(), SvgRoot(), geometry, resourceCreator)};
|
||||||
|
session.FillGeometry(geometry, fill);
|
||||||
|
fillLayer.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto const &strokeLayer{session.CreateLayer(StrokeOpacity())}) {
|
||||||
|
Geometry::CanvasStrokeStyle strokeStyle{};
|
||||||
|
strokeStyle.StartCap(StrokeLineCap());
|
||||||
|
strokeStyle.EndCap(StrokeLineCap());
|
||||||
|
strokeStyle.LineJoin(StrokeLineJoin());
|
||||||
|
strokeStyle.DashOffset(StrokeDashOffset());
|
||||||
|
strokeStyle.MiterLimit(StrokeMiterLimit());
|
||||||
|
|
||||||
|
float canvasDiagonal{Utils::GetCanvasDiagonal(canvas.Size())};
|
||||||
|
float strokeWidth{Utils::GetAbsoluteLength(StrokeWidth(), canvasDiagonal)};
|
||||||
|
strokeStyle.CustomDashStyle(Utils::GetAdjustedStrokeArray(StrokeDashArray(), strokeWidth, canvasDiagonal));
|
||||||
|
|
||||||
|
auto const &stroke{Utils::GetCanvasBrush(StrokeBrushId(), Stroke(), SvgRoot(), geometry, resourceCreator)};
|
||||||
|
session.DrawGeometry(geometry, stroke, strokeWidth, strokeStyle);
|
||||||
|
strokeLayer.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
opacityLayer.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableView::MergeProperties(RNSVG::RenderableView const &other) {
|
||||||
|
for (auto const &prop : m_propSetMap) {
|
||||||
|
if (!prop.second) {
|
||||||
|
switch (prop.first) {
|
||||||
|
case RNSVG::BaseProp::Fill:
|
||||||
|
m_fill = other.Fill();
|
||||||
|
m_fillBrushId = other.FillBrushId();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::FillOpacity:
|
||||||
|
m_fillOpacity = other.FillOpacity();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::FillRule:
|
||||||
|
m_fillRule = other.FillRule();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::Stroke:
|
||||||
|
m_stroke = other.Stroke();
|
||||||
|
m_strokeBrushId = other.StrokeBrushId();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::StrokeOpacity:
|
||||||
|
m_strokeOpacity = other.StrokeOpacity();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::StrokeWidth:
|
||||||
|
m_strokeWidth = other.StrokeWidth();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::StrokeMiterLimit:
|
||||||
|
m_strokeMiterLimit = other.StrokeMiterLimit();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::StrokeDashOffset:
|
||||||
|
m_strokeDashOffset = other.StrokeDashOffset();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::StrokeDashArray:
|
||||||
|
m_strokeDashArray = other.StrokeDashArray();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::StrokeLineCap:
|
||||||
|
m_strokeLineCap = other.StrokeLineCap();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::StrokeLineJoin:
|
||||||
|
m_strokeLineJoin = other.StrokeLineJoin();
|
||||||
|
break;
|
||||||
|
case RNSVG::BaseProp::Unknown:
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RNSVG::SvgView RenderableView::SvgRoot() {
|
||||||
|
if (SvgParent()) {
|
||||||
|
if (auto const &svgView{SvgParent().try_as<RNSVG::SvgView>()}) {
|
||||||
|
if (svgView.SvgParent()) {
|
||||||
|
if (auto const &parent{svgView.SvgParent().try_as<RNSVG::RenderableView>()}) {
|
||||||
|
return parent.SvgRoot();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return svgView;
|
||||||
|
}
|
||||||
|
} else if (auto const &renderable{SvgParent().try_as<RNSVG::RenderableView>()}) {
|
||||||
|
return renderable.SvgRoot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableView::Unload() {
|
||||||
|
if (m_geometry) {
|
||||||
|
m_geometry.Close();
|
||||||
|
m_geometry = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_parent = nullptr;
|
||||||
|
m_reactContext = nullptr;
|
||||||
|
m_propList.clear();
|
||||||
|
m_propSetMap.clear();
|
||||||
|
m_strokeDashArray.Clear();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
97
windows/RNSVG/RenderableView.h
Normal file
97
windows/RNSVG/RenderableView.h
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RenderableView.g.h"
|
||||||
|
#include "SVGLength.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct RenderableView : RenderableViewT<RenderableView> {
|
||||||
|
public:
|
||||||
|
RenderableView() = default;
|
||||||
|
RenderableView(Microsoft::ReactNative::IReactContext const &context) : m_reactContext(context) {}
|
||||||
|
|
||||||
|
RNSVG::SvgView SvgRoot();
|
||||||
|
|
||||||
|
Windows::UI::Xaml::FrameworkElement SvgParent() { return m_parent; }
|
||||||
|
void SvgParent(Windows::UI::Xaml::FrameworkElement const &value) { m_parent = value; }
|
||||||
|
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasGeometry Geometry() { return m_geometry; }
|
||||||
|
void Geometry(Microsoft::Graphics::Canvas::Geometry::CanvasGeometry value) { m_geometry = value; }
|
||||||
|
|
||||||
|
hstring Id() { return m_id; }
|
||||||
|
Numerics::float3x2 SvgTransform() { return m_transformMatrix; }
|
||||||
|
|
||||||
|
hstring FillBrushId() { return m_fillBrushId; }
|
||||||
|
Windows::UI::Color Fill() { return m_fill; }
|
||||||
|
float FillOpacity() { return m_fillOpacity; }
|
||||||
|
hstring StrokeBrushId() { return m_strokeBrushId; }
|
||||||
|
Windows::UI::Color Stroke() { return m_stroke; }
|
||||||
|
float StrokeOpacity() { return m_strokeOpacity; }
|
||||||
|
float StrokeMiterLimit() { return m_strokeMiterLimit; }
|
||||||
|
float StrokeDashOffset() { return m_strokeDashOffset; }
|
||||||
|
RNSVG::SVGLength StrokeWidth() { return m_strokeWidth; }
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> StrokeDashArray() { return m_strokeDashArray; }
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasCapStyle StrokeLineCap() { return m_strokeLineCap; }
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasLineJoin StrokeLineJoin() { return m_strokeLineJoin; }
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasFilledRegionDetermination FillRule() { return m_fillRule; }
|
||||||
|
|
||||||
|
virtual void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate = true, bool invalidate = true);
|
||||||
|
virtual void CreateGeometry(Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const & /*canvas*/) {}
|
||||||
|
virtual void MergeProperties(RNSVG::RenderableView const &other);
|
||||||
|
virtual void SaveDefinition();
|
||||||
|
virtual void Unload();
|
||||||
|
virtual void Render(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
virtual void CreateResources(
|
||||||
|
Microsoft::Graphics::Canvas::ICanvasResourceCreator const & /*resourceCreator*/,
|
||||||
|
Microsoft::Graphics::Canvas::UI::CanvasCreateResourcesEventArgs const & /*args*/) { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
float m_opacity{1.0f};
|
||||||
|
std::vector<std::string> m_propList{};
|
||||||
|
std::map<RNSVG::BaseProp, bool> m_propSetMap{
|
||||||
|
{RNSVG::BaseProp::Matrix, false},
|
||||||
|
{RNSVG::BaseProp::Fill, false},
|
||||||
|
{RNSVG::BaseProp::FillOpacity, false},
|
||||||
|
{RNSVG::BaseProp::FillRule, false},
|
||||||
|
{RNSVG::BaseProp::Stroke, false},
|
||||||
|
{RNSVG::BaseProp::StrokeOpacity, false},
|
||||||
|
{RNSVG::BaseProp::StrokeWidth, false},
|
||||||
|
{RNSVG::BaseProp::StrokeMiterLimit, false},
|
||||||
|
{RNSVG::BaseProp::StrokeDashOffset, false},
|
||||||
|
{RNSVG::BaseProp::StrokeDashArray, false},
|
||||||
|
{RNSVG::BaseProp::StrokeLineCap, false},
|
||||||
|
{RNSVG::BaseProp::StrokeLineJoin, false},
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
Microsoft::ReactNative::IReactContext m_reactContext{nullptr};
|
||||||
|
Windows::UI::Xaml::FrameworkElement m_parent{nullptr};
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasGeometry m_geometry{nullptr};
|
||||||
|
bool m_recreateResources{true};
|
||||||
|
|
||||||
|
hstring m_id{L""};
|
||||||
|
Numerics::float3x2 m_transformMatrix{Numerics::make_float3x2_rotation(0)};
|
||||||
|
Windows::UI::Color m_fill{Windows::UI::Colors::Black()};
|
||||||
|
Windows::UI::Color m_stroke{Windows::UI::Colors::Transparent()};
|
||||||
|
hstring m_fillBrushId{L""};
|
||||||
|
hstring m_strokeBrushId{L""};
|
||||||
|
float m_fillOpacity{1.0f};
|
||||||
|
float m_strokeOpacity{1.0f};
|
||||||
|
float m_strokeMiterLimit{0.0f};
|
||||||
|
float m_strokeDashOffset{0.0f};
|
||||||
|
RNSVG::SVGLength m_strokeWidth{1.0f, RNSVG::LengthType::Pixel};
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> m_strokeDashArray{
|
||||||
|
winrt::single_threaded_vector<RNSVG::SVGLength>()};
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasCapStyle m_strokeLineCap{
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasCapStyle::Flat};
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasLineJoin m_strokeLineJoin{
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasLineJoin::Miter};
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasFilledRegionDetermination m_fillRule{
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasFilledRegionDetermination::Winding};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct RenderableView : RenderableViewT<RenderableView, implementation::RenderableView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
78
windows/RNSVG/RenderableViewManager.cpp
Normal file
78
windows/RNSVG/RenderableViewManager.cpp
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
#if __has_include("RenderableViewManager.g.cpp")
|
||||||
|
#include "RenderableViewManager.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
Windows::UI::Xaml::FrameworkElement RenderableViewManager::CreateView() {
|
||||||
|
switch (m_class) {
|
||||||
|
case RNSVG::SVGClass::RNSVGGroup:
|
||||||
|
return winrt::RNSVG::GroupView(m_reactContext);
|
||||||
|
case RNSVG::SVGClass::RNSVGPath:
|
||||||
|
return winrt::RNSVG::PathView();
|
||||||
|
case RNSVG::SVGClass::RNSVGRect:
|
||||||
|
return winrt::RNSVG::RectView();
|
||||||
|
case RNSVG::SVGClass::RNSVGCircle:
|
||||||
|
return winrt::RNSVG::CircleView();
|
||||||
|
case RNSVG::SVGClass::RNSVGEllipse:
|
||||||
|
return winrt::RNSVG::EllipseView();
|
||||||
|
case RNSVG::SVGClass::RNSVGLine:
|
||||||
|
return winrt::RNSVG::LineView();
|
||||||
|
case RNSVG::SVGClass::RNSVGUse:
|
||||||
|
return winrt::RNSVG::UseView();
|
||||||
|
case RNSVG::SVGClass::RNSVGImage:
|
||||||
|
return winrt::RNSVG::ImageView();
|
||||||
|
case RNSVG::SVGClass::RNSVGText:
|
||||||
|
return winrt::RNSVG::TextView();
|
||||||
|
case RNSVG::SVGClass::RNSVGTSpan:
|
||||||
|
return winrt::RNSVG::TSpanView();
|
||||||
|
case RNSVG::SVGClass::RNSVGSymbol:
|
||||||
|
return winrt::RNSVG::SymbolView();
|
||||||
|
case RNSVG::SVGClass::RNSVGDefs:
|
||||||
|
return winrt::RNSVG::DefsView();
|
||||||
|
case RNSVG::SVGClass::RNSVGLinearGradient:
|
||||||
|
return winrt::RNSVG::LinearGradientView();
|
||||||
|
case RNSVG::SVGClass::RNSVGRadialGradient:
|
||||||
|
return winrt::RNSVG::RadialGradientView();
|
||||||
|
case RNSVG::SVGClass::RNSVGPattern:
|
||||||
|
return winrt::RNSVG::PatternView();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw hresult_not_implemented();
|
||||||
|
}
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> RenderableViewManager::NativeProps() {
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
nativeProps.Insert(L"name", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"fill", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"fillRule", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"fillOpacity", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"stroke", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"strokeOpacity", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"strokeWidth", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"strokeLinecap", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"strokeLinejoin", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"strokeMiterlimit", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"strokeDashoffset", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"strokeDasharray", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"matrix", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"opacity", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"propList", ViewManagerPropertyType::Array);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderableViewManager::UpdateProperties(
|
||||||
|
Windows::UI::Xaml::FrameworkElement const &view,
|
||||||
|
Microsoft::ReactNative::IJSValueReader const &propertyMapReader) {
|
||||||
|
if (auto const &renderable{view.try_as<RenderableView>()}) {
|
||||||
|
renderable->UpdateProperties(propertyMapReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
35
windows/RNSVG/RenderableViewManager.h
Normal file
35
windows/RNSVG/RenderableViewManager.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "RenderableViewManager.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct RenderableViewManager : RenderableViewManagerT<RenderableViewManager> {
|
||||||
|
public:
|
||||||
|
RenderableViewManager() = default;
|
||||||
|
|
||||||
|
// IViewManager
|
||||||
|
hstring Name() { return m_name; }
|
||||||
|
Windows::UI::Xaml::FrameworkElement CreateView();
|
||||||
|
|
||||||
|
// IViewManagerWithReactContext
|
||||||
|
Microsoft::ReactNative::IReactContext ReactContext() { return m_reactContext; }
|
||||||
|
void ReactContext(Microsoft::ReactNative::IReactContext const &value) { m_reactContext = value; }
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
void UpdateProperties(
|
||||||
|
Windows::UI::Xaml::FrameworkElement const &view,
|
||||||
|
Microsoft::ReactNative::IJSValueReader const &propertyMapReader);
|
||||||
|
virtual
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Microsoft::ReactNative::IReactContext m_reactContext{nullptr};
|
||||||
|
RNSVG::SVGClass m_class{RNSVG::SVGClass::Unknown};
|
||||||
|
hstring m_name{};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct RenderableViewManager : RenderableViewManagerT<RenderableViewManager, implementation::RenderableViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
59
windows/RNSVG/SVGLength.cpp
Normal file
59
windows/RNSVG/SVGLength.cpp
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "SVGLength.h"
|
||||||
|
#if __has_include("SVGLength.g.cpp")
|
||||||
|
#include "SVGLength.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
SVGLength::SVGLength(float value) : m_value(value), m_unit(RNSVG::LengthType::Number) {}
|
||||||
|
|
||||||
|
SVGLength::SVGLength(float value, RNSVG::LengthType type) : m_value(value), m_unit(type) {}
|
||||||
|
|
||||||
|
RNSVG::SVGLength SVGLength::From(std::string value) {
|
||||||
|
auto strLength{value.size()};
|
||||||
|
if (strLength == 0 || value == "normal") {
|
||||||
|
return {0.0, RNSVG::LengthType::Unknown};
|
||||||
|
} else if (value.back() == '%') {
|
||||||
|
return {std::stof(value.substr(0, strLength - 1), nullptr), RNSVG::LengthType::Percentage};
|
||||||
|
} else if (strLength > 2) {
|
||||||
|
auto end{strLength - 2};
|
||||||
|
auto lastTwo{value.substr(end)};
|
||||||
|
|
||||||
|
auto unit{RNSVG::LengthType::Unknown};
|
||||||
|
if (lastTwo == "px") {
|
||||||
|
unit = RNSVG::LengthType::Number;
|
||||||
|
} else if (lastTwo == "em") {
|
||||||
|
unit = RNSVG::LengthType::EMS;
|
||||||
|
} else if (lastTwo == "ex") {
|
||||||
|
unit = RNSVG::LengthType::EXS;
|
||||||
|
} else if (lastTwo == "cm") {
|
||||||
|
unit = RNSVG::LengthType::Centimeter;
|
||||||
|
} else if (lastTwo == "mm") {
|
||||||
|
unit = RNSVG::LengthType::Millimeter;
|
||||||
|
} else if (lastTwo == "in") {
|
||||||
|
unit = RNSVG::LengthType::Inch;
|
||||||
|
} else if (lastTwo == "pt") {
|
||||||
|
unit = RNSVG::LengthType::Point;
|
||||||
|
} else if (lastTwo == "pc") {
|
||||||
|
unit = RNSVG::LengthType::Pica;
|
||||||
|
} else {
|
||||||
|
unit = RNSVG::LengthType::Number;
|
||||||
|
end = strLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {std::stof(value.substr(0, end), nullptr), unit};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {std::stof(value, nullptr), RNSVG::LengthType::Number};
|
||||||
|
}
|
||||||
|
|
||||||
|
RNSVG::SVGLength SVGLength::From(Microsoft::ReactNative::JSValue const &propertyValue) {
|
||||||
|
if (propertyValue.IsNull()) {
|
||||||
|
return {0.0f, RNSVG::LengthType::Unknown};
|
||||||
|
} else if (propertyValue.Type() == Microsoft::ReactNative::JSValueType::String) {
|
||||||
|
return SVGLength::From(propertyValue.AsString());
|
||||||
|
} else {
|
||||||
|
return RNSVG::SVGLength(propertyValue.AsSingle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
28
windows/RNSVG/SVGLength.h
Normal file
28
windows/RNSVG/SVGLength.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SVGLength.g.h"
|
||||||
|
|
||||||
|
#include "JSValueXaml.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct SVGLength : SVGLengthT<SVGLength> {
|
||||||
|
public:
|
||||||
|
SVGLength() = default;
|
||||||
|
SVGLength(float value);
|
||||||
|
SVGLength(float value, RNSVG::LengthType type);
|
||||||
|
|
||||||
|
float Value() { return m_value; }
|
||||||
|
RNSVG::LengthType Unit() { return m_unit; }
|
||||||
|
|
||||||
|
static RNSVG::SVGLength From(std::string value);
|
||||||
|
static RNSVG::SVGLength From(Microsoft::ReactNative::JSValue const &value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_value{0.0f};
|
||||||
|
RNSVG::LengthType m_unit{RNSVG::LengthType::Unknown};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct SVGLength : SVGLengthT<SVGLength, implementation::SVGLength> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
194
windows/RNSVG/SvgView.cpp
Normal file
194
windows/RNSVG/SvgView.cpp
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "SvgView.h"
|
||||||
|
#if __has_include("SvgView.g.cpp")
|
||||||
|
#include "SvgView.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <winrt/Windows.Graphics.Display.h>
|
||||||
|
|
||||||
|
#include "GroupView.h"
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
using namespace Windows::Graphics::Display;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
SvgView::SvgView(IReactContext const &context) : m_reactContext(context) {
|
||||||
|
m_scale = static_cast<float>(DisplayInformation::GetForCurrentView().ResolutionScale()) / 100;
|
||||||
|
|
||||||
|
m_canvasDrawRevoker = m_canvas.Draw(winrt::auto_revoke, {get_weak(), &SvgView::Canvas_Draw});
|
||||||
|
m_canvasCreateResourcesRevoker = m_canvas.CreateResources(winrt::auto_revoke, {get_weak(), &SvgView::Canvas_CreateResources});
|
||||||
|
m_canvasSizeChangedRevoker = m_canvas.SizeChanged(winrt::auto_revoke, {get_weak(), &SvgView::Canvas_SizeChanged});
|
||||||
|
m_panelUnloadedRevoker = Unloaded(winrt::auto_revoke, {get_weak(), &SvgView::Panel_Unloaded});
|
||||||
|
|
||||||
|
Children().Append(m_canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::SvgParent(Windows::UI::Xaml::FrameworkElement const &value) {
|
||||||
|
if (value) {
|
||||||
|
m_canvasDrawRevoker.revoke();
|
||||||
|
m_canvasCreateResourcesRevoker.revoke();
|
||||||
|
m_canvasSizeChangedRevoker.revoke();
|
||||||
|
m_panelUnloadedRevoker.revoke();
|
||||||
|
m_canvas.RemoveFromVisualTree();
|
||||||
|
m_canvas = nullptr;
|
||||||
|
m_parent = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
// If forceUpdate is false, that means this is a nested Svg
|
||||||
|
// and we're inheriting props. Pass those along to the group.
|
||||||
|
if (!forceUpdate && m_group) {
|
||||||
|
m_group.UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
} else {
|
||||||
|
auto const &propertyMap{JSValueObject::ReadFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "name") {
|
||||||
|
if (m_parent && m_group) {
|
||||||
|
m_group.SvgRoot().Templates().Remove(m_id);
|
||||||
|
}
|
||||||
|
m_id = to_hstring(Utils::JSValueAsString(propertyValue));
|
||||||
|
if (m_parent) {
|
||||||
|
SaveDefinition();
|
||||||
|
}
|
||||||
|
} else if (propertyName == "width") {
|
||||||
|
m_width = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "height") {
|
||||||
|
m_height = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "bbWidth") {
|
||||||
|
m_bbWidth = SVGLength::From(propertyValue);
|
||||||
|
Width(m_bbWidth.Value());
|
||||||
|
} else if (propertyName == "bbHeight") {
|
||||||
|
m_bbHeight = SVGLength::From(propertyValue);
|
||||||
|
Height(m_bbHeight.Value());
|
||||||
|
} else if (propertyName == "vbWidth") {
|
||||||
|
m_vbWidth = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "vbHeight") {
|
||||||
|
m_vbHeight = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "minX") {
|
||||||
|
m_minX = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "minY") {
|
||||||
|
m_minY = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "align") {
|
||||||
|
m_align = Utils::JSValueAsString(propertyValue);
|
||||||
|
} else if (propertyName == "meetOrSlice") {
|
||||||
|
m_meetOrSlice = Utils::GetMeetOrSlice(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InvalidateCanvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::SaveDefinition() {
|
||||||
|
if (m_id != L"" && m_group) {
|
||||||
|
m_group.SvgRoot().Templates().Insert(m_id, *this);
|
||||||
|
m_group.SaveDefinition();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::MergeProperties(RNSVG::RenderableView const &other) {
|
||||||
|
if (m_group) {
|
||||||
|
m_group.MergeProperties(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Size SvgView::MeasureOverride(Size availableSize) {
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.Measure(availableSize);
|
||||||
|
}
|
||||||
|
return availableSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
Size SvgView::ArrangeOverride(Size finalSize) {
|
||||||
|
for (auto const &child : Children()) {
|
||||||
|
child.Arrange({0, 0, finalSize.Width, finalSize.Height});
|
||||||
|
}
|
||||||
|
return finalSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::Render(UI::Xaml::CanvasControl const & canvas, CanvasDrawingSession const & session) {
|
||||||
|
if (m_align != "") {
|
||||||
|
Rect vbRect{m_minX * m_scale, m_minY * m_scale, m_vbWidth * m_scale, m_vbHeight * m_scale};
|
||||||
|
float width{static_cast<float>(canvas.ActualWidth())};
|
||||||
|
float height{static_cast<float>(canvas.ActualHeight())};
|
||||||
|
bool nested{m_parent};
|
||||||
|
|
||||||
|
if (nested) {
|
||||||
|
width = Utils::GetAbsoluteLength(m_bbWidth, width);
|
||||||
|
height = Utils::GetAbsoluteLength(m_bbHeight, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect elRect{0, 0, width, height};
|
||||||
|
|
||||||
|
session.Transform(Utils::GetViewBoxTransform(vbRect, elRect, m_align, m_meetOrSlice));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_group) {
|
||||||
|
m_group.SaveDefinition();
|
||||||
|
m_group.Render(canvas, session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::Canvas_Draw(UI::Xaml::CanvasControl const &sender, UI::Xaml::CanvasDrawEventArgs const &args) {
|
||||||
|
if (!m_hasRendered) {
|
||||||
|
m_hasRendered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_brushes.Clear();
|
||||||
|
m_templates.Clear();
|
||||||
|
|
||||||
|
Render(sender, args.DrawingSession());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::CreateResources(ICanvasResourceCreator const &resourceCreator, UI::CanvasCreateResourcesEventArgs const &args) {
|
||||||
|
if (m_group) {
|
||||||
|
m_group.CreateResources(resourceCreator, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::Canvas_CreateResources(UI::Xaml::CanvasControl const &sender, UI::CanvasCreateResourcesEventArgs const &args) {
|
||||||
|
CreateResources(sender, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::Canvas_SizeChanged(
|
||||||
|
IInspectable const & /*sender*/,
|
||||||
|
Windows::UI::Xaml::SizeChangedEventArgs const & /*args*/) {
|
||||||
|
// sender.Invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::Panel_Unloaded(IInspectable const &sender, Windows::UI::Xaml::RoutedEventArgs const & /*args*/) {
|
||||||
|
if (auto const &svgView{sender.try_as<RNSVG::SvgView>()}) {
|
||||||
|
svgView.Unload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::Unload() {
|
||||||
|
m_reactContext = nullptr;
|
||||||
|
m_templates.Clear();
|
||||||
|
m_brushes.Clear();
|
||||||
|
|
||||||
|
if (m_group) {
|
||||||
|
m_group.Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_canvas) {
|
||||||
|
m_canvas.RemoveFromVisualTree();
|
||||||
|
m_canvas = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgView::InvalidateCanvas() {
|
||||||
|
if (m_hasRendered) {
|
||||||
|
m_canvas.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
95
windows/RNSVG/SvgView.h
Normal file
95
windows/RNSVG/SvgView.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SvgView.g.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct SvgView : SvgViewT<SvgView> {
|
||||||
|
public:
|
||||||
|
SvgView() = default;
|
||||||
|
|
||||||
|
SvgView(Microsoft::ReactNative::IReactContext const &context);
|
||||||
|
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl Canvas() { return m_canvas; }
|
||||||
|
|
||||||
|
Windows::UI::Xaml::FrameworkElement SvgParent() { return m_parent; }
|
||||||
|
void SvgParent(Windows::UI::Xaml::FrameworkElement const &value);
|
||||||
|
|
||||||
|
RNSVG::GroupView Group() { return m_group; }
|
||||||
|
void Group(RNSVG::GroupView const &value) { m_group = value; }
|
||||||
|
|
||||||
|
Microsoft::Graphics::Canvas::Geometry::CanvasGeometry Geometry() { return m_group ? m_group.Geometry() : nullptr; }
|
||||||
|
void Geometry(Microsoft::Graphics::Canvas::Geometry::CanvasGeometry /*value*/) { }
|
||||||
|
|
||||||
|
float SvgScale() { return m_scale; }
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IMap<hstring, RNSVG::IRenderable> Templates() {
|
||||||
|
return m_templates;
|
||||||
|
}
|
||||||
|
Windows::Foundation::Collections::IMap<hstring, RNSVG::BrushView> Brushes() {
|
||||||
|
return m_brushes;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IRenderable
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate = true, bool invalidate = true);
|
||||||
|
void MergeProperties(RNSVG::RenderableView const &other);
|
||||||
|
void SaveDefinition();
|
||||||
|
void Unload();
|
||||||
|
void Render(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
void CreateResources(
|
||||||
|
Microsoft::Graphics::Canvas::ICanvasResourceCreator const &resourceCreator,
|
||||||
|
Microsoft::Graphics::Canvas::UI::CanvasCreateResourcesEventArgs const &args);
|
||||||
|
|
||||||
|
// Overrides
|
||||||
|
Windows::Foundation::Size MeasureOverride(Windows::Foundation::Size availableSize);
|
||||||
|
Windows::Foundation::Size ArrangeOverride(Windows::Foundation::Size finalSize);
|
||||||
|
|
||||||
|
// CanvasControl
|
||||||
|
void Canvas_Draw(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &sender,
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasDrawEventArgs const &args);
|
||||||
|
void Canvas_CreateResources(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &sender,
|
||||||
|
Microsoft::Graphics::Canvas::UI::CanvasCreateResourcesEventArgs const &args);
|
||||||
|
void Canvas_SizeChanged(
|
||||||
|
Windows::Foundation::IInspectable const &sender,
|
||||||
|
Windows::UI::Xaml::SizeChangedEventArgs const &args);
|
||||||
|
|
||||||
|
void Panel_Unloaded(Windows::Foundation::IInspectable const &sender, Windows::UI::Xaml::RoutedEventArgs const &args);
|
||||||
|
|
||||||
|
void InvalidateCanvas();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_hasRendered{false};
|
||||||
|
Microsoft::ReactNative::IReactContext m_reactContext{nullptr};
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl m_canvas{};
|
||||||
|
Windows::UI::Xaml::FrameworkElement m_parent{nullptr};
|
||||||
|
RNSVG::GroupView m_group{nullptr};
|
||||||
|
hstring m_id{L""};
|
||||||
|
float m_scale{0.0f};
|
||||||
|
float m_minX{0.0f};
|
||||||
|
float m_minY{0.0f};
|
||||||
|
float m_vbWidth{0.0f};
|
||||||
|
float m_vbHeight{0.0f};
|
||||||
|
RNSVG::SVGLength m_bbWidth{};
|
||||||
|
RNSVG::SVGLength m_bbHeight{};
|
||||||
|
RNSVG::SVGLength m_width{};
|
||||||
|
RNSVG::SVGLength m_height{};
|
||||||
|
std::string m_align{""};
|
||||||
|
RNSVG::MeetOrSlice m_meetOrSlice{RNSVG::MeetOrSlice::Meet};
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IMap<hstring, RNSVG::IRenderable> m_templates{
|
||||||
|
winrt::single_threaded_map<hstring, RNSVG::IRenderable>()};
|
||||||
|
Windows::Foundation::Collections::IMap<hstring, RNSVG::BrushView> m_brushes{
|
||||||
|
winrt::single_threaded_map<hstring, RNSVG::BrushView>()};
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl::Draw_revoker m_canvasDrawRevoker{};
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl::CreateResources_revoker m_canvasCreateResourcesRevoker{};
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl::SizeChanged_revoker m_canvasSizeChangedRevoker{};
|
||||||
|
Windows::UI::Xaml::FrameworkElement::Unloaded_revoker m_panelUnloadedRevoker{};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct SvgView : SvgViewT<SvgView, implementation::SvgView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
108
windows/RNSVG/SvgViewManager.cpp
Normal file
108
windows/RNSVG/SvgViewManager.cpp
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "SvgViewManager.h"
|
||||||
|
#if __has_include("SvgViewManager.g.cpp")
|
||||||
|
#include "SvgViewManager.g.cpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <winrt/Windows.UI.Xaml.Media.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.Shapes.h>
|
||||||
|
|
||||||
|
#include "RenderableView.h"
|
||||||
|
#include "SvgView.h"
|
||||||
|
|
||||||
|
namespace winrt {
|
||||||
|
using namespace Windows::Foundation::Collections;
|
||||||
|
using namespace Microsoft::Graphics::Canvas::UI::Xaml;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
using namespace Windows::UI::Xaml;
|
||||||
|
using namespace Windows::UI::Xaml::Controls;
|
||||||
|
} // namespace winrt
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
// IViewManager
|
||||||
|
hstring SvgViewManager::Name() {
|
||||||
|
return L"RNSVGSvgView";
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameworkElement SvgViewManager::CreateView() {
|
||||||
|
return winrt::RNSVG::SvgView(m_reactContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// IViewManagerWithContext
|
||||||
|
IReactContext SvgViewManager::ReactContext() {
|
||||||
|
return m_reactContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgViewManager::ReactContext(IReactContext const &reactContext) {
|
||||||
|
m_reactContext = reactContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> SvgViewManager::NativeProps() {
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
nativeProps.Insert(L"height", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"width", ViewManagerPropertyType::Number);
|
||||||
|
|
||||||
|
// viewBox
|
||||||
|
nativeProps.Insert(L"minX", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"minY", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"vbWidth", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"vbHeight", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"bbWidth", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"bbHeight", ViewManagerPropertyType::Number);
|
||||||
|
|
||||||
|
// preserveAspectRatio
|
||||||
|
nativeProps.Insert(L"align", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"meetOrSlice", ViewManagerPropertyType::Number);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgViewManager::UpdateProperties(FrameworkElement const &view, IJSValueReader const &propertyMapReader) {
|
||||||
|
if (auto const &svgView{view.try_as<SvgView>()}) {
|
||||||
|
svgView->UpdateProperties(propertyMapReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IViewManagerWithChildren
|
||||||
|
void SvgViewManager::AddView(FrameworkElement const &parent, UIElement const &child, int64_t /*index*/) {
|
||||||
|
auto const &svgView{parent.try_as<RNSVG::SvgView>()};
|
||||||
|
auto const &group{child.try_as<RNSVG::GroupView>()};
|
||||||
|
|
||||||
|
if (svgView && group) {
|
||||||
|
// Every SvgView has exactly one child - a Group that gets
|
||||||
|
// all of Svg's children piped through.
|
||||||
|
group.SvgParent(parent);
|
||||||
|
svgView.Group(group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgViewManager::RemoveAllChildren(FrameworkElement const &parent) {
|
||||||
|
auto const &svgView{parent.try_as<RNSVG::SvgView>()};
|
||||||
|
if (svgView && svgView.Group()) {
|
||||||
|
svgView.Group().Unload();
|
||||||
|
}
|
||||||
|
svgView.Group(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgViewManager::RemoveChildAt(FrameworkElement const &parent, int64_t /*index*/) {
|
||||||
|
RemoveAllChildren(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SvgViewManager::ReplaceChild(
|
||||||
|
FrameworkElement const &parent,
|
||||||
|
UIElement const &oldChild,
|
||||||
|
UIElement const &newChild) {
|
||||||
|
auto const &svgView{parent.try_as<RNSVG::SvgView>()};
|
||||||
|
auto const &oldGroup{oldChild.try_as<RNSVG::GroupView>()};
|
||||||
|
auto const &newGroup{newChild.try_as<RNSVG::GroupView>()};
|
||||||
|
|
||||||
|
if (svgView && oldGroup && newGroup) {
|
||||||
|
newGroup.MergeProperties(oldGroup);
|
||||||
|
oldGroup.Unload();
|
||||||
|
newGroup.SvgParent(parent);
|
||||||
|
svgView.Group(newGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
40
windows/RNSVG/SvgViewManager.h
Normal file
40
windows/RNSVG/SvgViewManager.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SvgViewManager.g.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct SvgViewManager : SvgViewManagerT<SvgViewManager> {
|
||||||
|
SvgViewManager() = default;
|
||||||
|
|
||||||
|
// IViewManager
|
||||||
|
hstring Name();
|
||||||
|
Windows::UI::Xaml::FrameworkElement CreateView();
|
||||||
|
|
||||||
|
// IViewManagerWithReactContext
|
||||||
|
Microsoft::ReactNative::IReactContext ReactContext();
|
||||||
|
void ReactContext(Microsoft::ReactNative::IReactContext const &value);
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
void UpdateProperties(
|
||||||
|
Windows::UI::Xaml::FrameworkElement const &view,
|
||||||
|
Microsoft::ReactNative::IJSValueReader const &propertyMapReader);
|
||||||
|
|
||||||
|
// IViewManagerWithChildren
|
||||||
|
void
|
||||||
|
AddView(Windows::UI::Xaml::FrameworkElement const &parent, Windows::UI::Xaml::UIElement const &child, int64_t index);
|
||||||
|
void RemoveAllChildren(Windows::UI::Xaml::FrameworkElement const &parent);
|
||||||
|
void RemoveChildAt(Windows::UI::Xaml::FrameworkElement const &parent, int64_t index);
|
||||||
|
void ReplaceChild(
|
||||||
|
Windows::UI::Xaml::FrameworkElement const &parent,
|
||||||
|
Windows::UI::Xaml::UIElement const &oldChild,
|
||||||
|
Windows::UI::Xaml::UIElement const &newChild);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Microsoft::ReactNative::IReactContext m_reactContext{nullptr};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct SvgViewManager : SvgViewManagerT<SvgViewManager, implementation::SvgViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
37
windows/RNSVG/SymbolView.cpp
Normal file
37
windows/RNSVG/SymbolView.cpp
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "SymbolView.h"
|
||||||
|
#include "SymbolView.g.cpp"
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void SymbolView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "vbWidth") {
|
||||||
|
m_vbWidth = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "vbHeight") {
|
||||||
|
m_vbHeight = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "minX") {
|
||||||
|
m_minX = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "minY") {
|
||||||
|
m_minY = Utils::JSValueAsFloat(propertyValue);
|
||||||
|
} else if (propertyName == "align") {
|
||||||
|
m_align = Utils::JSValueAsString(propertyValue);
|
||||||
|
} else if (propertyName == "meetOrSlice") {
|
||||||
|
m_meetOrSlice = Utils::GetMeetOrSlice(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
35
windows/RNSVG/SymbolView.h
Normal file
35
windows/RNSVG/SymbolView.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "SymbolView.g.h"
|
||||||
|
#include "GroupView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct SymbolView : SymbolViewT<SymbolView, RNSVG::implementation::GroupView> {
|
||||||
|
public:
|
||||||
|
SymbolView() = default;
|
||||||
|
|
||||||
|
float MinX() { return m_minX; }
|
||||||
|
float MinY() { return m_minY; }
|
||||||
|
float VbWidth() { return m_vbWidth; }
|
||||||
|
float VbHeight() { return m_vbHeight; }
|
||||||
|
hstring Align() { return to_hstring(m_align); }
|
||||||
|
RNSVG::MeetOrSlice MeetOrSlice() { return m_meetOrSlice; }
|
||||||
|
|
||||||
|
// RenderableView
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void Render(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &/*canvas*/,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &/*session*/){};
|
||||||
|
|
||||||
|
private:
|
||||||
|
float m_minX{0.0f};
|
||||||
|
float m_minY{0.0f};
|
||||||
|
float m_vbWidth{0.0f};
|
||||||
|
float m_vbHeight{0.0f};
|
||||||
|
std::string m_align{""};
|
||||||
|
RNSVG::MeetOrSlice m_meetOrSlice{RNSVG::MeetOrSlice::Meet};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct SymbolView : SymbolViewT<SymbolView, implementation::SymbolView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
32
windows/RNSVG/SymbolViewManager.cpp
Normal file
32
windows/RNSVG/SymbolViewManager.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "SymbolViewManager.h"
|
||||||
|
#include "SymbolViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation
|
||||||
|
{
|
||||||
|
SymbolViewManager::SymbolViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGSymbol;
|
||||||
|
m_name = L"RNSVGSymbol";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> SymbolViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"minX", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"minY", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"vbWidth", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"vbHeight", ViewManagerPropertyType::Number);
|
||||||
|
nativeProps.Insert(L"align", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"meetOrSlice", ViewManagerPropertyType::Number);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
windows/RNSVG/SymbolViewManager.h
Normal file
16
windows/RNSVG/SymbolViewManager.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "SymbolViewManager.g.h"
|
||||||
|
#include "GroupViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct SymbolViewManager : SymbolViewManagerT<SymbolViewManager, RNSVG::implementation::GroupViewManager> {
|
||||||
|
SymbolViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct SymbolViewManager : SymbolViewManagerT<SymbolViewManager, implementation::SymbolViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
52
windows/RNSVG/TSpanView.cpp
Normal file
52
windows/RNSVG/TSpanView.cpp
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "TSpanView.h"
|
||||||
|
#include "TSpanView.g.cpp"
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
#include <winrt/Microsoft.Graphics.Canvas.Text.h>
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void TSpanView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "content") {
|
||||||
|
m_content = propertyValue.AsString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSpanView::CreateGeometry(UI::Xaml::CanvasControl const &canvas) {
|
||||||
|
auto const &resourceCreator{canvas.try_as<ICanvasResourceCreator>()};
|
||||||
|
Microsoft::Graphics::Canvas::Text::CanvasTextFormat const& textFormat{};
|
||||||
|
textFormat.FontSize(FontSize());
|
||||||
|
textFormat.FontFamily(FontFamily());
|
||||||
|
textFormat.FontWeight(Utils::FontWeightFrom(FontWeight(), SvgParent()));
|
||||||
|
|
||||||
|
Geometry(Geometry::CanvasGeometry::CreateText({resourceCreator, to_hstring(m_content), textFormat, canvas.Size().Width, canvas.Size().Height}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void TSpanView::Render(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
||||||
|
auto const &transform{session.Transform()};
|
||||||
|
bool translateXY{X().Size() > 0 || Y().Size() > 0};
|
||||||
|
|
||||||
|
if (translateXY) {
|
||||||
|
float x{X().Size() > 0 ? X().GetAt(0).Value() : 0};
|
||||||
|
float y{Y().Size() > 0 ? Y().GetAt(0).Value() : 0};
|
||||||
|
session.Transform(transform * Numerics::make_float3x2_translation(x, y));
|
||||||
|
}
|
||||||
|
__super::Render(canvas, session);
|
||||||
|
if (translateXY) {
|
||||||
|
session.Transform(transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
23
windows/RNSVG/TSpanView.h
Normal file
23
windows/RNSVG/TSpanView.h
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TSpanView.g.h"
|
||||||
|
#include "TextView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct TSpanView : TSpanViewT<TSpanView, RNSVG::implementation::TextView> {
|
||||||
|
public:
|
||||||
|
TSpanView() = default;
|
||||||
|
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void CreateGeometry(Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas);
|
||||||
|
virtual void Render(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string m_content;
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct TSpanView : TSpanViewT<TSpanView, implementation::TSpanView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
26
windows/RNSVG/TSpanViewManager.cpp
Normal file
26
windows/RNSVG/TSpanViewManager.cpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "TSpanViewManager.h"
|
||||||
|
#include "TSpanViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
TSpanViewManager::TSpanViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGTSpan;
|
||||||
|
m_name = L"RNSVGTSpan";
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, ViewManagerPropertyType> TSpanViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"content", ViewManagerPropertyType::String);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
windows/RNSVG/TSpanViewManager.h
Normal file
15
windows/RNSVG/TSpanViewManager.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TSpanViewManager.g.h"
|
||||||
|
#include "TextViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct TSpanViewManager : TSpanViewManagerT<TSpanViewManager, RNSVG::implementation::TextViewManager> {
|
||||||
|
TSpanViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct TSpanViewManager : TSpanViewManagerT<TSpanViewManager, implementation::TSpanViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
61
windows/RNSVG/TextView.cpp
Normal file
61
windows/RNSVG/TextView.cpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "TextView.h"
|
||||||
|
#include "TextView.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void TextView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "x") {
|
||||||
|
m_x.Clear();
|
||||||
|
for (auto const &item : propertyValue.AsArray()) {
|
||||||
|
m_x.Append(SVGLength::From(item));
|
||||||
|
}
|
||||||
|
} else if (propertyName == "y") {
|
||||||
|
m_y.Clear();
|
||||||
|
for (auto const &item : propertyValue.AsArray()) {
|
||||||
|
m_y.Append(SVGLength::From(item));
|
||||||
|
}
|
||||||
|
} else if (propertyName == "dx") {
|
||||||
|
m_dx.Clear();
|
||||||
|
for (auto const &item : propertyValue.AsArray()) {
|
||||||
|
m_dx.Append(SVGLength::From(item));
|
||||||
|
}
|
||||||
|
} else if (propertyName == "dy") {
|
||||||
|
m_dy.Clear();
|
||||||
|
for (auto const &item : propertyValue.AsArray()) {
|
||||||
|
m_dy.Append(SVGLength::From(item));
|
||||||
|
}
|
||||||
|
} else if (propertyName == "rotate") {
|
||||||
|
m_rotate.Clear();
|
||||||
|
for (auto const &item : propertyValue.AsArray()) {
|
||||||
|
m_rotate.Append(SVGLength::From(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextView::RenderGroup(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
||||||
|
auto const &transform{session.Transform()};
|
||||||
|
bool translateXY{X().Size() > 0 || Y().Size() > 0};
|
||||||
|
if (translateXY) {
|
||||||
|
float x{X().Size() > 0 ? X().GetAt(0).Value() : 0};
|
||||||
|
float y{Y().Size() > 0 ? Y().GetAt(0).Value() : 0};
|
||||||
|
session.Transform(transform * Numerics::make_float3x2_translation(x, y));
|
||||||
|
}
|
||||||
|
__super::RenderGroup(canvas, session);
|
||||||
|
if (translateXY) {
|
||||||
|
session.Transform(transform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
31
windows/RNSVG/TextView.h
Normal file
31
windows/RNSVG/TextView.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TextView.g.h"
|
||||||
|
#include "GroupView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct TextView : TextViewT<TextView, RNSVG::implementation::GroupView> {
|
||||||
|
public:
|
||||||
|
TextView() = default;
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> X() { return m_x; }
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> Y() { return m_y; }
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> DX() { return m_dx; }
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> DY() { return m_dy; }
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> Rotate() { return m_rotate; }
|
||||||
|
|
||||||
|
virtual void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
virtual void RenderGroup(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> m_x{winrt::single_threaded_vector<RNSVG::SVGLength>()};
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> m_y{winrt::single_threaded_vector<RNSVG::SVGLength>()};
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> m_dx{winrt::single_threaded_vector<RNSVG::SVGLength>()};
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> m_dy{winrt::single_threaded_vector<RNSVG::SVGLength>()};
|
||||||
|
Windows::Foundation::Collections::IVector<RNSVG::SVGLength> m_rotate{winrt::single_threaded_vector<RNSVG::SVGLength>()};
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct TextView : TextViewT<TextView, implementation::TextView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
30
windows/RNSVG/TextViewManager.cpp
Normal file
30
windows/RNSVG/TextViewManager.cpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "TextViewManager.h"
|
||||||
|
#include "TextViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
TextViewManager::TextViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGText;
|
||||||
|
m_name = L"RNSVGText";
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, ViewManagerPropertyType> TextViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"x", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"y", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"dx", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"dy", ViewManagerPropertyType::Array);
|
||||||
|
nativeProps.Insert(L"rotate", ViewManagerPropertyType::Array);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
15
windows/RNSVG/TextViewManager.h
Normal file
15
windows/RNSVG/TextViewManager.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "TextViewManager.g.h"
|
||||||
|
#include "GroupViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct TextViewManager : TextViewManagerT<TextViewManager, RNSVG::implementation::GroupViewManager> {
|
||||||
|
TextViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct TextViewManager : TextViewManagerT<TextViewManager, implementation::TextViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
79
windows/RNSVG/Types.idl
Normal file
79
windows/RNSVG/Types.idl
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
namespace RNSVG {
|
||||||
|
enum SVGClass {
|
||||||
|
RNSVGGroup,
|
||||||
|
RNSVGPath,
|
||||||
|
RNSVGText,
|
||||||
|
RNSVGTSpan,
|
||||||
|
RNSVGTextPath,
|
||||||
|
RNSVGImage,
|
||||||
|
RNSVGCircle,
|
||||||
|
RNSVGEllipse,
|
||||||
|
RNSVGLine,
|
||||||
|
RNSVGRect,
|
||||||
|
RNSVGClipPath,
|
||||||
|
RNSVGDefs,
|
||||||
|
RNSVGUse,
|
||||||
|
RNSVGSymbol,
|
||||||
|
RNSVGLinearGradient,
|
||||||
|
RNSVGRadialGradient,
|
||||||
|
RNSVGPattern,
|
||||||
|
RNSVGMask,
|
||||||
|
RNSVGMarker,
|
||||||
|
RNSVGForeignObject,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum MeetOrSlice {
|
||||||
|
Meet,
|
||||||
|
Slice,
|
||||||
|
None,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BaseProp {
|
||||||
|
Matrix,
|
||||||
|
Fill,
|
||||||
|
FillOpacity,
|
||||||
|
FillRule,
|
||||||
|
Stroke,
|
||||||
|
StrokeOpacity,
|
||||||
|
StrokeWidth,
|
||||||
|
StrokeMiterLimit,
|
||||||
|
StrokeDashOffset,
|
||||||
|
StrokeDashArray,
|
||||||
|
StrokeLineCap,
|
||||||
|
StrokeLineJoin,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FontProp {
|
||||||
|
FontSize,
|
||||||
|
FontWeight,
|
||||||
|
FontFamily,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum LengthType
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Number,
|
||||||
|
Percentage,
|
||||||
|
EMS,
|
||||||
|
EXS,
|
||||||
|
Pixel,
|
||||||
|
Centimeter,
|
||||||
|
Millimeter,
|
||||||
|
Inch,
|
||||||
|
Point,
|
||||||
|
Pica,
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass SVGLength {
|
||||||
|
SVGLength();
|
||||||
|
SVGLength(Single param);
|
||||||
|
SVGLength(Single param, LengthType type);
|
||||||
|
|
||||||
|
Single Value{ get; };
|
||||||
|
LengthType Unit{ get; };
|
||||||
|
};
|
||||||
|
}
|
||||||
105
windows/RNSVG/UseView.cpp
Normal file
105
windows/RNSVG/UseView.cpp
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "UseView.h"
|
||||||
|
#include "UseView.g.cpp"
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
void UseView::UpdateProperties(IJSValueReader const &reader, bool forceUpdate, bool invalidate) {
|
||||||
|
const JSValueObject &propertyMap{JSValue::ReadObjectFrom(reader)};
|
||||||
|
|
||||||
|
for (auto const &pair : propertyMap) {
|
||||||
|
auto const &propertyName{pair.first};
|
||||||
|
auto const &propertyValue{pair.second};
|
||||||
|
|
||||||
|
if (propertyName == "href") {
|
||||||
|
m_href = to_hstring(Utils::JSValueAsString(propertyValue));
|
||||||
|
} else if (propertyName == "x") {
|
||||||
|
m_x = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "y") {
|
||||||
|
m_y = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "width") {
|
||||||
|
m_width = SVGLength::From(propertyValue);
|
||||||
|
} else if (propertyName == "height") {
|
||||||
|
m_height = SVGLength::From(propertyValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__super::UpdateProperties(reader, forceUpdate, invalidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UseView::Render(UI::Xaml::CanvasControl const &canvas, CanvasDrawingSession const &session) {
|
||||||
|
if (auto const &view{GetRenderableTemplate()}) {
|
||||||
|
auto const &originalTransform{session.Transform()};
|
||||||
|
auto transform{Numerics::make_float3x2_scale(1)};
|
||||||
|
|
||||||
|
// Figure out any necessary transforms
|
||||||
|
if (auto const &symbol{view.try_as<RNSVG::SymbolView>()}) {
|
||||||
|
if (symbol.Align() != L"") {
|
||||||
|
if (auto const &root{SvgRoot()}) {
|
||||||
|
Rect vbRect{
|
||||||
|
symbol.MinX() * root.SvgScale(),
|
||||||
|
symbol.MinY() * root.SvgScale(),
|
||||||
|
(symbol.MinX() + symbol.VbWidth()) * root.SvgScale(),
|
||||||
|
(symbol.MinY() + symbol.VbHeight()) * root.SvgScale()};
|
||||||
|
|
||||||
|
float elX{Utils::GetAbsoluteLength(m_x, canvas.Size().Width)};
|
||||||
|
float elY{Utils::GetAbsoluteLength(m_y, canvas.Size().Height)};
|
||||||
|
float elWidth{Utils::GetAbsoluteLength(m_width, canvas.Size().Width)};
|
||||||
|
float elHeight{Utils::GetAbsoluteLength(m_height, canvas.Size().Height)};
|
||||||
|
Rect elRect{elX, elY, elWidth, elHeight};
|
||||||
|
|
||||||
|
transform = Utils::GetViewBoxTransform(vbRect, elRect, to_string(symbol.Align()), symbol.MeetOrSlice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
float x{Utils::GetAbsoluteLength(m_x, canvas.Size().Width)};
|
||||||
|
float y{Utils::GetAbsoluteLength(m_y, canvas.Size().Height)};
|
||||||
|
transform = Numerics::make_float3x2_translation({x, y});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine new transform with existing one if it's set
|
||||||
|
if (m_propSetMap[RNSVG::BaseProp::Matrix]) {
|
||||||
|
transform = transform * SvgTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
session.Transform(transform);
|
||||||
|
|
||||||
|
// Propagate props to template
|
||||||
|
view.MergeProperties(*this);
|
||||||
|
|
||||||
|
// Set opacity and render
|
||||||
|
if (auto const &opacityLayer{session.CreateLayer(m_opacity)}) {
|
||||||
|
if (auto const &symbol{view.try_as<RNSVG::SymbolView>()}) {
|
||||||
|
symbol.RenderGroup(canvas, session);
|
||||||
|
} else {
|
||||||
|
view.Render(canvas, session);
|
||||||
|
}
|
||||||
|
opacityLayer.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore original template props
|
||||||
|
if (auto const &parent{view.SvgParent().try_as<RNSVG::RenderableView>()}) {
|
||||||
|
view.MergeProperties(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore session transform
|
||||||
|
session.Transform(originalTransform);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw hresult_not_implemented(L"'Use' element expected a pre-defined svg template as 'href' prop. Template named: " + m_href + L" is not defined");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RNSVG::IRenderable UseView::GetRenderableTemplate() {
|
||||||
|
if (auto const &root{SvgRoot()}) {
|
||||||
|
return root.Templates().TryLookup(m_href);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
28
windows/RNSVG/UseView.h
Normal file
28
windows/RNSVG/UseView.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "UseView.g.h"
|
||||||
|
#include "RenderableView.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct UseView : UseViewT<UseView, RNSVG::implementation::RenderableView> {
|
||||||
|
public:
|
||||||
|
UseView() = default;
|
||||||
|
|
||||||
|
void UpdateProperties(Microsoft::ReactNative::IJSValueReader const &reader, bool forceUpdate, bool invalidate);
|
||||||
|
void Render(
|
||||||
|
Microsoft::Graphics::Canvas::UI::Xaml::CanvasControl const &canvas,
|
||||||
|
Microsoft::Graphics::Canvas::CanvasDrawingSession const &session);
|
||||||
|
|
||||||
|
private:
|
||||||
|
hstring m_href{L""};
|
||||||
|
RNSVG::SVGLength m_x{};
|
||||||
|
RNSVG::SVGLength m_y{};
|
||||||
|
RNSVG::SVGLength m_width{};
|
||||||
|
RNSVG::SVGLength m_height{};
|
||||||
|
|
||||||
|
RNSVG::IRenderable GetRenderableTemplate();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct UseView : UseViewT<UseView, implementation::UseView> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
30
windows/RNSVG/UseViewManager.cpp
Normal file
30
windows/RNSVG/UseViewManager.cpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#include "pch.h"
|
||||||
|
#include "UseViewManager.h"
|
||||||
|
#include "UseViewManager.g.cpp"
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
UseViewManager::UseViewManager() {
|
||||||
|
m_class = RNSVG::SVGClass::RNSVGUse;
|
||||||
|
m_name = L"RNSVGUse";
|
||||||
|
}
|
||||||
|
|
||||||
|
IMapView<hstring, ViewManagerPropertyType> UseViewManager::NativeProps() {
|
||||||
|
auto const &parentProps{__super::NativeProps()};
|
||||||
|
auto const &nativeProps{winrt::single_threaded_map<hstring, ViewManagerPropertyType>()};
|
||||||
|
|
||||||
|
for (auto const &prop : parentProps) {
|
||||||
|
nativeProps.Insert(prop.Key(), prop.Value());
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeProps.Insert(L"href", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"x", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"y", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"width", ViewManagerPropertyType::String);
|
||||||
|
nativeProps.Insert(L"height", ViewManagerPropertyType::String);
|
||||||
|
|
||||||
|
return nativeProps.GetView();
|
||||||
|
}
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
16
windows/RNSVG/UseViewManager.h
Normal file
16
windows/RNSVG/UseViewManager.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "UseViewManager.g.h"
|
||||||
|
#include "RenderableViewManager.h"
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::implementation {
|
||||||
|
struct UseViewManager : UseViewManagerT<UseViewManager, RNSVG::implementation::RenderableViewManager> {
|
||||||
|
UseViewManager();
|
||||||
|
|
||||||
|
// IViewManagerWithNativeProperties
|
||||||
|
Windows::Foundation::Collections::IMapView<hstring, Microsoft::ReactNative::ViewManagerPropertyType> NativeProps();
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG::implementation
|
||||||
|
|
||||||
|
namespace winrt::RNSVG::factory_implementation {
|
||||||
|
struct UseViewManager : UseViewManagerT<UseViewManager, implementation::UseViewManager> {};
|
||||||
|
} // namespace winrt::RNSVG::factory_implementation
|
||||||
341
windows/RNSVG/Utils.h
Normal file
341
windows/RNSVG/Utils.h
Normal file
@@ -0,0 +1,341 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include <winrt/Microsoft.Graphics.Canvas.Brushes.h>
|
||||||
|
#include <winrt/Windows.Foundation.Numerics.h>
|
||||||
|
#include <winrt/Windows.UI.Text.h>
|
||||||
|
#include "JSValueReader.h"
|
||||||
|
|
||||||
|
#define _USE_MATH_DEFINES
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
using namespace winrt;
|
||||||
|
using namespace Microsoft::Graphics::Canvas;
|
||||||
|
using namespace Microsoft::ReactNative;
|
||||||
|
using namespace Windows::UI;
|
||||||
|
using namespace Windows::UI::Text;
|
||||||
|
|
||||||
|
namespace winrt::RNSVG {
|
||||||
|
struct Utils {
|
||||||
|
public:
|
||||||
|
static std::vector<float> GetAdjustedStrokeArray(IVector<SVGLength> const &value, float strokeWidth, float canvasDiagonal) {
|
||||||
|
std::vector<float> result;
|
||||||
|
|
||||||
|
for (auto const &item : value) {
|
||||||
|
float absValue{GetAbsoluteLength(item, canvasDiagonal)};
|
||||||
|
|
||||||
|
// Win2D sets the length of each dash as the product of the element value in array and stroke width,
|
||||||
|
// we divide each value in the dashArray by StrokeWidth to account for this.
|
||||||
|
// http://microsoft.github.io/Win2D/WinUI2/html/P_Microsoft_Graphics_Canvas_Geometry_CanvasStrokeStyle_CustomDashStyle.htm
|
||||||
|
result.push_back(absValue / (strokeWidth == 0.0f ? 1.0f : strokeWidth));
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float GetCanvasDiagonal(Windows::Foundation::Size const &size) {
|
||||||
|
float powX{std::powf(size.Width, 2)};
|
||||||
|
float powY{std::powf(size.Height, 2)};
|
||||||
|
|
||||||
|
return std::sqrtf(powX + powY) * static_cast<float>(M_SQRT1_2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float GetAbsoluteLength(SVGLength const &length, float relativeTo) {
|
||||||
|
auto value{length.Value()};
|
||||||
|
|
||||||
|
// 1in = 2.54cm = 96px
|
||||||
|
auto inch{96.0f};
|
||||||
|
auto cm{inch / 2.54f};
|
||||||
|
|
||||||
|
switch (length.Unit()) {
|
||||||
|
case RNSVG::LengthType::Percentage:
|
||||||
|
return value / 100.0f * relativeTo;
|
||||||
|
case RNSVG::LengthType::Centimeter:
|
||||||
|
// 1cm = 96px/2.54
|
||||||
|
return value * cm;
|
||||||
|
case RNSVG::LengthType::Millimeter:
|
||||||
|
// 1mm = 1/10th of 1cm
|
||||||
|
return value * cm / 10.0f;
|
||||||
|
case RNSVG::LengthType::Inch:
|
||||||
|
// 1in = 2.54cm = 96px
|
||||||
|
return value * inch;
|
||||||
|
case RNSVG::LengthType::Point:
|
||||||
|
// 1pt = 1/72th of 1in
|
||||||
|
return value * inch / 72.0f;
|
||||||
|
case RNSVG::LengthType::Pica:
|
||||||
|
// 1pc = 1/6th of 1in
|
||||||
|
return value * inch / 6.0f;
|
||||||
|
case RNSVG::LengthType::Pixel:
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Numerics::float3x2 GetRotationMatrix(float degrees) {
|
||||||
|
// convert to radians
|
||||||
|
auto radians{degrees * static_cast<float>(M_PI) / 100.0f};
|
||||||
|
return Numerics::make_float3x2_rotation(radians);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FontWeight FontWeightFrom(hstring const& weight, Xaml::FrameworkElement const& parent) {
|
||||||
|
if (weight == L"normal") {
|
||||||
|
return FontWeights::Normal();
|
||||||
|
} else if (weight == L"bold") {
|
||||||
|
return FontWeights::Bold();
|
||||||
|
} else if (weight == L"bolder" || weight == L"lighter" || weight == L"auto") {
|
||||||
|
auto const &groupView{parent.try_as<RNSVG::GroupView>()};
|
||||||
|
FontWeight parentWeight{
|
||||||
|
groupView ? FontWeightFrom(groupView.FontWeight(), groupView.SvgParent()) : FontWeights::Normal()};
|
||||||
|
|
||||||
|
if (weight == L"bolder") {
|
||||||
|
return Bolder(parentWeight.Weight);
|
||||||
|
} else if (weight == L"lighter") {
|
||||||
|
return Lighter(parentWeight.Weight);
|
||||||
|
} else if (weight == L"auto") {
|
||||||
|
return parentWeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetClosestFontWeight(std::stof(weight.c_str(), nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
static FontWeight GetClosestFontWeight(float weight) {
|
||||||
|
if (weight > 325 && weight < 375) {
|
||||||
|
return FontWeights::SemiLight();
|
||||||
|
} else if (weight > 925) {
|
||||||
|
return FontWeights::ExtraBlack();
|
||||||
|
} else {
|
||||||
|
switch (static_cast<uint16_t>(std::round(weight / 100.0f))) {
|
||||||
|
case 1:
|
||||||
|
return FontWeights::Thin();
|
||||||
|
case 2:
|
||||||
|
return FontWeights::ExtraLight();
|
||||||
|
case 3:
|
||||||
|
return FontWeights::Light();
|
||||||
|
case 4:
|
||||||
|
return FontWeights::Normal();
|
||||||
|
case 5:
|
||||||
|
return FontWeights::Medium();
|
||||||
|
case 6:
|
||||||
|
return FontWeights::SemiBold();
|
||||||
|
case 7:
|
||||||
|
return FontWeights::Bold();
|
||||||
|
case 8:
|
||||||
|
return FontWeights::ExtraBold();
|
||||||
|
case 9:
|
||||||
|
default:
|
||||||
|
return FontWeights::ExtraBlack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static FontWeight Bolder(uint16_t weight) {
|
||||||
|
if (weight < 350) {
|
||||||
|
return FontWeights::Normal();
|
||||||
|
} else if (weight < 550) {
|
||||||
|
return FontWeights::Bold();
|
||||||
|
} else if (weight < 900) {
|
||||||
|
return FontWeights::Black();
|
||||||
|
} else {
|
||||||
|
return FontWeights::ExtraBlack();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static FontWeight Lighter(uint16_t weight) {
|
||||||
|
if (weight < 550) {
|
||||||
|
return FontWeights::Thin();
|
||||||
|
} else if (weight < 750) {
|
||||||
|
return FontWeights::Normal();
|
||||||
|
} else {
|
||||||
|
return FontWeights::Bold();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Numerics::float3x2 GetViewBoxTransform(Rect vbRect, Rect elRect, std::string align, RNSVG::MeetOrSlice meetOrSlice) {
|
||||||
|
// based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform
|
||||||
|
|
||||||
|
// Let vb-x, vb-y, vb-width, vb-height be the min-x, min-y, width and height values of the viewBox attribute
|
||||||
|
// respectively.
|
||||||
|
float vbX = vbRect.X;
|
||||||
|
float vbY = vbRect.Y;
|
||||||
|
float vbWidth = vbRect.Width;
|
||||||
|
float vbHeight = vbRect.Height;
|
||||||
|
|
||||||
|
// Let e-x, e-y, e-width, e-height be the position and size of the element respectively.
|
||||||
|
float eX = elRect.X;
|
||||||
|
float eY = elRect.Y;
|
||||||
|
float eWidth = elRect.Width;
|
||||||
|
float eHeight = elRect.Height;
|
||||||
|
|
||||||
|
// Initialize scale-x to e-width/vb-width.
|
||||||
|
float scaleX = eWidth / vbWidth;
|
||||||
|
|
||||||
|
// Initialize scale-y to e-height/vb-height.
|
||||||
|
float scaleY = eHeight / vbHeight;
|
||||||
|
|
||||||
|
// If align is not 'none' and meetOrSlice is 'meet', set the larger of scale-x and scale-y to the smaller.
|
||||||
|
// Otherwise, if align is not 'none' and meetOrSlice is 'slice', set the smaller of scale-x and scale-y to the
|
||||||
|
// larger.
|
||||||
|
if (align != "none" && meetOrSlice == RNSVG::MeetOrSlice::Meet) {
|
||||||
|
scaleX = scaleY = std::min(scaleX, scaleY);
|
||||||
|
} else if (align != "none" && meetOrSlice == RNSVG::MeetOrSlice::Slice) {
|
||||||
|
scaleX = scaleY = std::max(scaleX, scaleY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize translate-x to e-x - (vb-x * scale-x).
|
||||||
|
float translateX = eX - (vbX * scaleX);
|
||||||
|
|
||||||
|
// Initialize translate-y to e-y - (vb-y * scale-y).
|
||||||
|
float translateY = eY - (vbY * scaleY);
|
||||||
|
|
||||||
|
// If align contains 'xMid', add (e-width - vb-width * scale-x) / 2 to translate-x.
|
||||||
|
if (align.find("xMid") != std::string::npos) {
|
||||||
|
translateX += (eWidth - vbWidth * scaleX) / 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If align contains 'xMax', add (e-width - vb-width * scale-x) to translate-x.
|
||||||
|
if (align.find("xMax") != std::string::npos) {
|
||||||
|
translateX += (eWidth - vbWidth * scaleX);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If align contains 'yMid', add (e-height - vb-height * scale-y) / 2 to translate-y.
|
||||||
|
if (align.find("YMid") != std::string::npos) {
|
||||||
|
translateY += (eHeight - vbHeight * scaleY) / 2.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If align contains 'yMax', add (e-height - vb-height * scale-y) to translate-y.
|
||||||
|
if (align.find("YMax") != std::string::npos) {
|
||||||
|
translateY += (eHeight - vbHeight * scaleY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The transform applied to content contained by the element is given by
|
||||||
|
// translate(translate-x, translate-y) scale(scale-x, scale-y).
|
||||||
|
auto const &translate{Numerics::make_float3x2_translation(translateX, translateY)};
|
||||||
|
auto const &scale{Numerics::make_float3x2_scale(scaleX, scaleY)};
|
||||||
|
|
||||||
|
return scale * translate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static RNSVG::MeetOrSlice GetMeetOrSlice(JSValue const &value) {
|
||||||
|
if (value.IsNull()) {
|
||||||
|
return RNSVG::MeetOrSlice::Meet;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (value.AsInt8()) {
|
||||||
|
case 2:
|
||||||
|
return RNSVG::MeetOrSlice::None;
|
||||||
|
case 1:
|
||||||
|
return RNSVG::MeetOrSlice::Slice;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
return RNSVG::MeetOrSlice::Meet;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string JSValueAsBrushUnits(JSValue const &value, std::string defaultValue = "objectBoundingBox") {
|
||||||
|
if (value.IsNull()) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
switch (value.AsInt32()) {
|
||||||
|
case 1:
|
||||||
|
return "userSpaceOnUse";
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
return "objectBoundingBox";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static float JSValueAsFloat(JSValue const &value, float defaultValue = 0.0f) {
|
||||||
|
if (value.IsNull()) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
return value.AsSingle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string JSValueAsString(JSValue const &value, std::string defaultValue = "") {
|
||||||
|
if (value.IsNull()) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
return value.AsString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Color JSValueAsColor(JSValue const &value, Color defaultValue = Colors::Transparent()) {
|
||||||
|
if (value.IsNull()) {
|
||||||
|
return defaultValue;
|
||||||
|
} else if (auto const &brush{value.To<Xaml::Media::Brush>()}) {
|
||||||
|
if (auto const &scb{brush.try_as<Xaml::Media::SolidColorBrush>()}) {
|
||||||
|
return scb.Color();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SVGLength JSValueAsSVGLength(JSValue const &value, SVGLength const &defaultValue = {}) {
|
||||||
|
if (value.IsNull()) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
return RNSVG::implementation::SVGLength::From(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Numerics::float3x2 JSValueAsTransform(JSValue const& value, Numerics::float3x2 defaultValue = {}) {
|
||||||
|
if (value.IsNull()) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
auto const &matrix{value.AsArray()};
|
||||||
|
|
||||||
|
return Numerics::float3x2(
|
||||||
|
matrix.at(0).AsSingle(),
|
||||||
|
matrix.at(1).AsSingle(),
|
||||||
|
matrix.at(2).AsSingle(),
|
||||||
|
matrix.at(3).AsSingle(),
|
||||||
|
matrix.at(4).AsSingle(),
|
||||||
|
matrix.at(5).AsSingle());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<Brushes::CanvasGradientStop> JSValueAsStops(JSValue const& value) {
|
||||||
|
if (value.IsNull()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto const &stops{value.AsArray()};
|
||||||
|
std::vector<Brushes::CanvasGradientStop> canvasStops{};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < stops.size(); ++i) {
|
||||||
|
Brushes::CanvasGradientStop stop{};
|
||||||
|
stop.Position = Utils::JSValueAsFloat(stops.at(i));
|
||||||
|
stop.Color = Utils::JSValueAsColor(stops.at(++i));
|
||||||
|
canvasStops.push_back(stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return canvasStops;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Brushes::ICanvasBrush GetCanvasBrush(
|
||||||
|
hstring const &brushId,
|
||||||
|
Color color,
|
||||||
|
RNSVG::SvgView const &root,
|
||||||
|
Geometry::CanvasGeometry const &geometry,
|
||||||
|
ICanvasResourceCreator const &resourceCreator) {
|
||||||
|
Brushes::ICanvasBrush brush{nullptr};
|
||||||
|
if (root && brushId != L"") {
|
||||||
|
if (auto const &brushView{root.Brushes().TryLookup(brushId)}) {
|
||||||
|
brushView.SetBounds(geometry.ComputeBounds());
|
||||||
|
brush = brushView.Brush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!brush) {
|
||||||
|
brush = Brushes::CanvasSolidColorBrush(resourceCreator, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
return brush;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace winrt::RNSVG
|
||||||
115
windows/RNSVG/ViewManagers.idl
Normal file
115
windows/RNSVG/ViewManagers.idl
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
import "Types.idl";
|
||||||
|
|
||||||
|
namespace RNSVG
|
||||||
|
{
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass SvgViewManager
|
||||||
|
: Microsoft.ReactNative.IViewManager
|
||||||
|
, Microsoft.ReactNative.IViewManagerWithReactContext
|
||||||
|
, Microsoft.ReactNative.IViewManagerWithNativeProperties
|
||||||
|
, Microsoft.ReactNative.IViewManagerWithChildren
|
||||||
|
{
|
||||||
|
SvgViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
unsealed runtimeclass RenderableViewManager
|
||||||
|
: Microsoft.ReactNative.IViewManager
|
||||||
|
, Microsoft.ReactNative.IViewManagerWithReactContext
|
||||||
|
, Microsoft.ReactNative.IViewManagerWithNativeProperties
|
||||||
|
{
|
||||||
|
RenderableViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass RectViewManager : RenderableViewManager
|
||||||
|
{
|
||||||
|
RectViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass CircleViewManager : RenderableViewManager
|
||||||
|
{
|
||||||
|
CircleViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass EllipseViewManager : RenderableViewManager
|
||||||
|
{
|
||||||
|
EllipseViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass LineViewManager : RenderableViewManager
|
||||||
|
{
|
||||||
|
LineViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass PathViewManager : RenderableViewManager
|
||||||
|
{
|
||||||
|
PathViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass UseViewManager : RenderableViewManager
|
||||||
|
{
|
||||||
|
UseViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass ImageViewManager : RenderableViewManager
|
||||||
|
{
|
||||||
|
ImageViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
unsealed runtimeclass GroupViewManager
|
||||||
|
: RenderableViewManager
|
||||||
|
, Microsoft.ReactNative.IViewManagerWithChildren
|
||||||
|
{
|
||||||
|
GroupViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass DefsViewManager : GroupViewManager
|
||||||
|
{
|
||||||
|
DefsViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass LinearGradientViewManager : GroupViewManager
|
||||||
|
{
|
||||||
|
LinearGradientViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass RadialGradientViewManager : GroupViewManager
|
||||||
|
{
|
||||||
|
RadialGradientViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass PatternViewManager : GroupViewManager
|
||||||
|
{
|
||||||
|
PatternViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass SymbolViewManager : GroupViewManager
|
||||||
|
{
|
||||||
|
SymbolViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
unsealed runtimeclass TextViewManager : GroupViewManager
|
||||||
|
{
|
||||||
|
TextViewManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass TSpanViewManager : TextViewManager
|
||||||
|
{
|
||||||
|
TSpanViewManager();
|
||||||
|
};
|
||||||
|
}
|
||||||
181
windows/RNSVG/Views.idl
Normal file
181
windows/RNSVG/Views.idl
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
import "Types.idl";
|
||||||
|
|
||||||
|
namespace RNSVG
|
||||||
|
{
|
||||||
|
interface IRenderable
|
||||||
|
{
|
||||||
|
Windows.UI.Xaml.FrameworkElement SvgParent;
|
||||||
|
Microsoft.Graphics.Canvas.Geometry.CanvasGeometry Geometry;
|
||||||
|
|
||||||
|
void CreateResources(
|
||||||
|
Microsoft.Graphics.Canvas.ICanvasResourceCreator resourceCreator,
|
||||||
|
Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args);
|
||||||
|
void Render(
|
||||||
|
Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl canvas,
|
||||||
|
Microsoft.Graphics.Canvas.CanvasDrawingSession session);
|
||||||
|
void UpdateProperties(Microsoft.ReactNative.IJSValueReader reader, Boolean forceUpdate, Boolean invalidate);
|
||||||
|
void MergeProperties(RenderableView other);
|
||||||
|
void SaveDefinition();
|
||||||
|
void Unload();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass SvgView : Windows.UI.Xaml.Controls.Panel, IRenderable
|
||||||
|
{
|
||||||
|
SvgView(Microsoft.ReactNative.IReactContext context);
|
||||||
|
|
||||||
|
Single SvgScale{ get; };
|
||||||
|
GroupView Group;
|
||||||
|
Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl Canvas{ get; };
|
||||||
|
Windows.Foundation.Collections.IMap<String, IRenderable> Templates{ get; };
|
||||||
|
Windows.Foundation.Collections.IMap<String, BrushView> Brushes{ get; };
|
||||||
|
|
||||||
|
void InvalidateCanvas();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
unsealed runtimeclass RenderableView : Windows.UI.Xaml.FrameworkElement, IRenderable
|
||||||
|
{
|
||||||
|
RenderableView(Microsoft.ReactNative.IReactContext context);
|
||||||
|
SvgView SvgRoot{ get; };
|
||||||
|
|
||||||
|
String Id{ get; };
|
||||||
|
Windows.Foundation.Numerics.Matrix3x2 SvgTransform{ get; };
|
||||||
|
Windows.UI.Color Fill{ get; };
|
||||||
|
Single FillOpacity{ get; };
|
||||||
|
String FillBrushId{ get; };
|
||||||
|
Windows.UI.Color Stroke{ get; };
|
||||||
|
Single StrokeOpacity{ get; };
|
||||||
|
String StrokeBrushId{ get; };
|
||||||
|
SVGLength StrokeWidth{ get; };
|
||||||
|
Single StrokeMiterLimit{ get; };
|
||||||
|
Single StrokeDashOffset{ get; };
|
||||||
|
Windows.Foundation.Collections.IVector<SVGLength> StrokeDashArray{ get; };
|
||||||
|
Microsoft.Graphics.Canvas.Geometry.CanvasCapStyle StrokeLineCap{ get; };
|
||||||
|
Microsoft.Graphics.Canvas.Geometry.CanvasLineJoin StrokeLineJoin{ get; };
|
||||||
|
Microsoft.Graphics.Canvas.Geometry.CanvasFilledRegionDetermination FillRule{ get; };
|
||||||
|
|
||||||
|
void CreateGeometry(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl canvas);
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass RectView : RenderableView
|
||||||
|
{
|
||||||
|
RectView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass CircleView : RenderableView
|
||||||
|
{
|
||||||
|
CircleView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass EllipseView : RenderableView
|
||||||
|
{
|
||||||
|
EllipseView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass LineView : RenderableView
|
||||||
|
{
|
||||||
|
LineView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass PathView : RenderableView
|
||||||
|
{
|
||||||
|
PathView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass UseView : RenderableView
|
||||||
|
{
|
||||||
|
UseView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass ImageView : RenderableView
|
||||||
|
{
|
||||||
|
ImageView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
unsealed runtimeclass GroupView : RenderableView
|
||||||
|
{
|
||||||
|
GroupView(Microsoft.ReactNative.IReactContext context);
|
||||||
|
Windows.Foundation.Collections.IVector<IRenderable> Children { get; };
|
||||||
|
|
||||||
|
Single FontSize;
|
||||||
|
String FontFamily;
|
||||||
|
String FontWeight;
|
||||||
|
|
||||||
|
void RenderGroup(
|
||||||
|
Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl canvas,
|
||||||
|
Microsoft.Graphics.Canvas.CanvasDrawingSession session);
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
unsealed runtimeclass TextView : GroupView
|
||||||
|
{
|
||||||
|
TextView();
|
||||||
|
Windows.Foundation.Collections.IVector<SVGLength> X{ get; };
|
||||||
|
Windows.Foundation.Collections.IVector<SVGLength> Y{ get; };
|
||||||
|
Windows.Foundation.Collections.IVector<SVGLength> DX{ get; };
|
||||||
|
Windows.Foundation.Collections.IVector<SVGLength> DY{ get; };
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass TSpanView : TextView
|
||||||
|
{
|
||||||
|
TSpanView();
|
||||||
|
|
||||||
|
Windows.Foundation.Collections.IVector<SVGLength> Rotate { get; };
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass DefsView : GroupView
|
||||||
|
{
|
||||||
|
DefsView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass SymbolView : GroupView
|
||||||
|
{
|
||||||
|
SymbolView();
|
||||||
|
Single MinX{ get; };
|
||||||
|
Single MinY{ get; };
|
||||||
|
Single VbWidth{ get; };
|
||||||
|
Single VbHeight{ get; };
|
||||||
|
String Align{ get; };
|
||||||
|
MeetOrSlice MeetOrSlice{ get; };
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
unsealed runtimeclass BrushView : GroupView
|
||||||
|
{
|
||||||
|
BrushView();
|
||||||
|
|
||||||
|
Microsoft.Graphics.Canvas.Brushes.ICanvasBrush Brush{ get; };
|
||||||
|
void CreateBrush();
|
||||||
|
void SetBounds(Windows.Foundation.Rect rect);
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass LinearGradientView : BrushView
|
||||||
|
{
|
||||||
|
LinearGradientView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass RadialGradientView : BrushView
|
||||||
|
{
|
||||||
|
RadialGradientView();
|
||||||
|
};
|
||||||
|
|
||||||
|
[default_interface]
|
||||||
|
runtimeclass PatternView : BrushView
|
||||||
|
{
|
||||||
|
PatternView();
|
||||||
|
};
|
||||||
|
}
|
||||||
6
windows/RNSVG/packages.config
Normal file
6
windows/RNSVG/packages.config
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<packages>
|
||||||
|
<package id="Microsoft.UI.Xaml" version="2.3.191129002" targetFramework="native" />
|
||||||
|
<package id="Microsoft.Windows.CppWinRT" version="2.0.200615.7" targetFramework="native" />
|
||||||
|
<package id="Win2D.uwp" version="1.25.0" targetFramework="native" />
|
||||||
|
</packages>
|
||||||
1
windows/RNSVG/pch.cpp
Normal file
1
windows/RNSVG/pch.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "pch.h"
|
||||||
31
windows/RNSVG/pch.h
Normal file
31
windows/RNSVG/pch.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
|
||||||
|
#include <hstring.h>
|
||||||
|
#include <restrictederrorinfo.h>
|
||||||
|
#include <unknwn.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winrt/Windows.Foundation.Collections.h>
|
||||||
|
#include <winrt/Windows.Foundation.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.Controls.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.Data.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.Interop.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.Markup.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.Media.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.Navigation.h>
|
||||||
|
#include <winrt/Windows.UI.Xaml.h>
|
||||||
|
|
||||||
|
#include <winrt/Microsoft.Graphics.Canvas.h>
|
||||||
|
#include <winrt/Microsoft.Graphics.Canvas.Geometry.h>
|
||||||
|
#include <winrt/Microsoft.Graphics.Canvas.UI.Xaml.h>
|
||||||
|
|
||||||
|
#include <winrt/Microsoft.ReactNative.h>
|
||||||
|
|
||||||
|
#include <winrt/Microsoft.UI.Xaml.Automation.Peers.h>
|
||||||
|
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
|
||||||
|
#include <winrt/Microsoft.UI.Xaml.Controls.h>
|
||||||
|
#include <winrt/Microsoft.UI.Xaml.Media.h>
|
||||||
|
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
||||||
|
using namespace winrt::Windows::Foundation;
|
||||||
Reference in New Issue
Block a user