├── .gitattributes
├── .github
├── FUNDING.yml
└── workflows
│ ├── build-and-publish-beta.yml
│ ├── build-and-publish-release.yml
│ └── validate-pull-request.yml
├── .gitignore
├── .gitmodules
├── Directory.Build.props
├── LICENSE.txt
├── README.md
├── build
├── NvgSharp.FNA.Core.sln
├── NvgSharp.FNA.sln
├── NvgSharp.MonoGame.sln
└── NvgSharp.sln
├── images
└── screenshot.png
├── samples
├── Assets
│ ├── Roboto-Bold.ttf
│ ├── Roboto-Light.ttf
│ ├── Roboto-Regular.ttf
│ ├── entypo.ttf
│ ├── images.txt
│ └── images
│ │ ├── image1.jpg
│ │ ├── image10.jpg
│ │ ├── image11.jpg
│ │ ├── image12.jpg
│ │ ├── image2.jpg
│ │ ├── image3.jpg
│ │ ├── image4.jpg
│ │ ├── image5.jpg
│ │ ├── image6.jpg
│ │ ├── image7.jpg
│ │ ├── image8.jpg
│ │ └── image9.jpg
├── NvgSharp.Samples.Demo
│ ├── Demo.cs
│ ├── Game1.cs
│ ├── Icon.ico
│ ├── NvgExtensions.cs
│ ├── NvgSharp.Samples.Demo.FNA.Core.csproj
│ ├── NvgSharp.Samples.Demo.FNA.csproj
│ ├── NvgSharp.Samples.Demo.MonoGame.csproj
│ ├── PerfGraph.cs
│ ├── Program.cs
│ └── Utility.cs
├── NvgSharp.Samples.OpenTK
│ ├── BufferObject.cs
│ ├── GLUtility.cs
│ ├── NvgSharp.Samples.OpenTK.csproj
│ ├── Platform
│ │ └── Renderer.cs
│ ├── Program.cs
│ ├── Shader.cs
│ ├── Texture.cs
│ ├── VertexArrayObject.cs
│ ├── Window.cs
│ ├── shader.frag
│ └── shader.vert
└── NvgSharp.Samples.Silk.NET
│ ├── BufferObject.cs
│ ├── Env.cs
│ ├── GLUtility.cs
│ ├── NvgSharp.Samples.Silk.NET.csproj
│ ├── Platform
│ └── Renderer.cs
│ ├── Program.cs
│ ├── Shader.cs
│ ├── Texture.cs
│ ├── VertexArrayObject.cs
│ ├── shader.frag
│ └── shader.vert
└── src
├── NvgSharp.Text
├── NvgSharp.Text.FNA.Core.csproj
├── NvgSharp.Text.FNA.csproj
├── NvgSharp.Text.MonoGame.csproj
├── NvgSharp.Text.csproj
├── NvgText.cs
└── TextSource.cs
├── NvgSharp
├── ArrayBuffer.cs
├── AssemblyInfo.cs
├── Bounds.cs
├── Command.cs
├── Enums.cs
├── INvgRenderer.cs
├── NvgContext.cs
├── NvgContextState.cs
├── NvgPoint.cs
├── NvgSharp.csproj
├── NvgUtility.cs
├── Paint.cs
├── Path.cs
├── RenderCache.cs
├── Scissor.cs
├── Transform.cs
└── Vertex.cs
└── XNA
├── NvgSharp.FNA.Core.csproj
├── NvgSharp.FNA.csproj
├── NvgSharp.MonoGame.csproj
├── Resources.cs
├── Resources
├── Effect.dx11.mgfxo
├── Effect.fx
├── Effect.fxb
├── Effect.ogl.mgfxo
├── Effect_AA.dx11.mgfxo
├── Effect_AA.fxb
├── Effect_AA.ogl.mgfxo
├── Macros.fxh
└── build.bat
└── XNARenderer.cs
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | patreon: rds1983
2 | custom: https://boosty.to/rds1983
--------------------------------------------------------------------------------
/.github/workflows/build-and-publish-beta.yml:
--------------------------------------------------------------------------------
1 | name: Build & Publish Beta
2 |
3 | on:
4 | push:
5 | paths:
6 | - 'src/**'
7 | - 'build/**'
8 | - 'samples/**'
9 | workflow_dispatch:
10 |
11 | jobs:
12 | BuildAndPublish:
13 | runs-on: windows-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v2
17 | with:
18 | submodules: recursive
19 | - name: Setup .NET Core
20 | uses: actions/setup-dotnet@v1
21 | with:
22 | dotnet-version: '6.0.x'
23 | - name: Build NvgSharp
24 | run: dotnet build build\NvgSharp.sln --configuration Release
25 | - name: Build NvgSharp.MonoGame
26 | run: dotnet build build\NvgSharp.MonoGame.sln --configuration Release
27 | - name: Test
28 | run: dotnet test build\NvgSharp.MonoGame.sln
29 | - name: Install NuGet
30 | uses: NuGet/setup-nuget@v1
--------------------------------------------------------------------------------
/.github/workflows/build-and-publish-release.yml:
--------------------------------------------------------------------------------
1 | name: Build & Publish Release
2 |
3 | on: [workflow_dispatch]
4 |
5 | jobs:
6 | BuildAndPublish:
7 | runs-on: windows-latest
8 |
9 | steps:
10 | - uses: actions/checkout@v2
11 | with:
12 | submodules: recursive
13 | - name: Setup .NET Core
14 | uses: actions/setup-dotnet@v1
15 | with:
16 | dotnet-version: '6.0.x'
17 | - name: Build NvgSharp
18 | run: dotnet build build\NvgSharp.sln --configuration Release
19 | - name: Build NvgSharp.MonoGame
20 | run: dotnet build build\NvgSharp.MonoGame.sln --configuration Release
21 | - name: Test
22 | run: dotnet test build\NvgSharp.MonoGame.sln
23 | - name: Install NuGet
24 | uses: NuGet/setup-nuget@v1
25 | - name: Publish NvgSharp.Text.MonoGame to NuGet
26 | run: nuget.exe push src\NvgSharp.Text\bin\MonoGame\Release\NvgSharp.Text.MonoGame.*.nupkg ${{secrets.NUGET_APIKEY}} -Source https://api.nuget.org/v3/index.json
27 | - name: Publish NvgSharp.Text to NuGet
28 | run: nuget.exe push src\NvgSharp.Text\bin\Release\NvgSharp.Text.*.nupkg ${{secrets.NUGET_APIKEY}} -Source https://api.nuget.org/v3/index.json
29 | - name: Publish NvgSharp.MonoGame to NuGet
30 | run: nuget.exe push src\XNA\bin\MonoGame\Release\NvgSharp.MonoGame.*.nupkg ${{secrets.NUGET_APIKEY}} -Source https://api.nuget.org/v3/index.json
31 | - name: Publish NvgSharp to NuGet
32 | run: nuget.exe push src\NvgSharp\bin\Release\NvgSharp.*.nupkg ${{secrets.NUGET_APIKEY}} -Source https://api.nuget.org/v3/index.json
33 |
--------------------------------------------------------------------------------
/.github/workflows/validate-pull-request.yml:
--------------------------------------------------------------------------------
1 | name: Validate Pull Request
2 |
3 | on: [pull_request, workflow_dispatch]
4 |
5 | jobs:
6 | BuildAndPublish:
7 | runs-on: windows-latest
8 |
9 | steps:
10 | - uses: actions/checkout@v2
11 | with:
12 | submodules: recursive
13 | - name: Setup .NET Core
14 | uses: actions/setup-dotnet@v1
15 | with:
16 | dotnet-version: '6.0.x'
17 | - name: Build NvgSharp
18 | run: dotnet build build\NvgSharp.sln --configuration Release
19 | - name: Build NvgSharp.MonoGame
20 | run: dotnet build build\NvgSharp.MonoGame.sln --configuration Release
21 | - name: Test
22 | run: dotnet test build\NvgSharp.MonoGame.sln
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | bld/
21 | [Bb]in/
22 | [Oo]bj/
23 | [Ll]og/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | project.fragment.lock.json
46 | artifacts/
47 |
48 | *_i.c
49 | *_p.c
50 | *_i.h
51 | *.ilk
52 | *.meta
53 | *.obj
54 | *.pch
55 | *.pdb
56 | *.pgc
57 | *.pgd
58 | *.rsp
59 | *.sbr
60 | *.tlb
61 | *.tli
62 | *.tlh
63 | *.tmp
64 | *.tmp_proj
65 | *.log
66 | *.vspscc
67 | *.vssscc
68 | .builds
69 | *.pidb
70 | *.svclog
71 | *.scc
72 |
73 | # Chutzpah Test files
74 | _Chutzpah*
75 |
76 | # Visual C++ cache files
77 | ipch/
78 | *.aps
79 | *.ncb
80 | *.opendb
81 | *.opensdf
82 | *.sdf
83 | *.cachefile
84 | *.VC.db
85 | *.VC.VC.opendb
86 |
87 | # Visual Studio profiler
88 | *.psess
89 | *.vsp
90 | *.vspx
91 | *.sap
92 |
93 | # TFS 2012 Local Workspace
94 | $tf/
95 |
96 | # Guidance Automation Toolkit
97 | *.gpState
98 |
99 | # ReSharper is a .NET coding add-in
100 | _ReSharper*/
101 | *.[Rr]e[Ss]harper
102 | *.DotSettings.user
103 |
104 | # JustCode is a .NET coding add-in
105 | .JustCode
106 |
107 | # TeamCity is a build add-in
108 | _TeamCity*
109 |
110 | # DotCover is a Code Coverage Tool
111 | *.dotCover
112 |
113 | # NCrunch
114 | _NCrunch_*
115 | .*crunch*.local.xml
116 | nCrunchTemp_*
117 |
118 | # MightyMoose
119 | *.mm.*
120 | AutoTest.Net/
121 |
122 | # Web workbench (sass)
123 | .sass-cache/
124 |
125 | # Installshield output folder
126 | [Ee]xpress/
127 |
128 | # DocProject is a documentation generator add-in
129 | DocProject/buildhelp/
130 | DocProject/Help/*.HxT
131 | DocProject/Help/*.HxC
132 | DocProject/Help/*.hhc
133 | DocProject/Help/*.hhk
134 | DocProject/Help/*.hhp
135 | DocProject/Help/Html2
136 | DocProject/Help/html
137 |
138 | # Click-Once directory
139 | publish/
140 |
141 | # Publish Web Output
142 | *.[Pp]ublish.xml
143 | *.azurePubxml
144 | # TODO: Comment the next line if you want to checkin your web deploy settings
145 | # but database connection strings (with potential passwords) will be unencrypted
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
150 | # checkin your Azure Web App publish settings, but sensitive information contained
151 | # in these scripts will be unencrypted
152 | PublishScripts/
153 |
154 | # NuGet Packages
155 | *.nupkg
156 | # The packages folder can be ignored because of Package Restore
157 | **/packages/*
158 | # except build/, which is used as an MSBuild target.
159 | !**/packages/build/
160 | # Uncomment if necessary however generally it will be regenerated when needed
161 | #!**/packages/repositories.config
162 | # NuGet v3's project.json files produces more ignoreable files
163 | *.nuget.props
164 | *.nuget.targets
165 |
166 | # Microsoft Azure Build Output
167 | csx/
168 | *.build.csdef
169 |
170 | # Microsoft Azure Emulator
171 | ecf/
172 | rcf/
173 |
174 | # Windows Store app package directories and files
175 | AppPackages/
176 | BundleArtifacts/
177 | Package.StoreAssociation.xml
178 | _pkginfo.txt
179 |
180 | # Visual Studio cache files
181 | # files ending in .cache can be ignored
182 | *.[Cc]ache
183 | # but keep track of directories ending in .cache
184 | !*.[Cc]ache/
185 |
186 | # Others
187 | ClientBin/
188 | ~$*
189 | *~
190 | *.dbmdl
191 | *.dbproj.schemaview
192 | *.jfm
193 | *.pfx
194 | *.publishsettings
195 | node_modules/
196 | orleans.codegen.cs
197 |
198 | # Since there are multiple workflows, uncomment next line to ignore bower_components
199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
200 | #bower_components/
201 |
202 | # RIA/Silverlight projects
203 | Generated_Code/
204 |
205 | # Backup & report files from converting an old project file
206 | # to a newer Visual Studio version. Backup files are not needed,
207 | # because we have git ;-)
208 | _UpgradeReport_Files/
209 | Backup*/
210 | UpgradeLog*.XML
211 | UpgradeLog*.htm
212 |
213 | # SQL Server files
214 | *.mdf
215 | *.ldf
216 |
217 | # Business Intelligence projects
218 | *.rdl.data
219 | *.bim.layout
220 | *.bim_*.settings
221 |
222 | # Microsoft Fakes
223 | FakesAssemblies/
224 |
225 | # GhostDoc plugin setting file
226 | *.GhostDoc.xml
227 |
228 | # Node.js Tools for Visual Studio
229 | .ntvs_analysis.dat
230 |
231 | # Visual Studio 6 build log
232 | *.plg
233 |
234 | # Visual Studio 6 workspace options file
235 | *.opt
236 |
237 | # Visual Studio LightSwitch build output
238 | **/*.HTMLClient/GeneratedArtifacts
239 | **/*.DesktopClient/GeneratedArtifacts
240 | **/*.DesktopClient/ModelManifest.xml
241 | **/*.Server/GeneratedArtifacts
242 | **/*.Server/ModelManifest.xml
243 | _Pvt_Extensions
244 |
245 | # Paket dependency manager
246 | .paket/paket.exe
247 | paket-files/
248 |
249 | # FAKE - F# Make
250 | .fake/
251 |
252 | # JetBrains Rider
253 | .idea/
254 | *.sln.iml
255 |
256 | # CodeRush
257 | .cr/
258 |
259 | # Python Tools for Visual Studio (PTVS)
260 | __pycache__/
261 | *.pyc
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/.gitmodules
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | NvgSharpTeam
4 | NvgSharp
5 | Zlib
6 | https://github.com/rds1983/NvgSharp
7 | NvgSharp
8 | 0.6.3
9 | 1.2.8
10 |
11 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013 Mikko Mononen memon@inside.org
2 |
3 | This software is provided 'as-is', without any express or implied
4 | warranty. In no event will the authors be held liable for any damages
5 | arising from the use of this software.
6 |
7 | Permission is granted to anyone to use this software for any purpose,
8 | including commercial applications, and to alter it and redistribute it
9 | freely, subject to the following restrictions:
10 |
11 | 1. The origin of this software must not be misrepresented; you must not
12 | claim that you wrote the original software. If you use this software
13 | in a product, an acknowledgment in the product documentation would be
14 | appreciated but is not required.
15 | 2. Altered source versions must be plainly marked as such, and must not be
16 | misrepresented as being the original software.
17 | 3. This notice may not be removed or altered from any source distribution.
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NvgSharp
2 | [](https://www.nuget.org/packages/NvgSharp.MonoGame/) [](https://ci.appveyor.com/project/RomanShapiro/nvgsharp)
3 | [](https://discord.gg/ZeHxhCY)
4 |
5 | NvgSharp is 2D vector graphics library in pure C#.
6 |
7 | # Usage
8 | [Using NvgSharp in MonoGame or FNA](https://github.com/rds1983/NvgSharp/wiki/Using-NvgSharp-in-MonoGame-or-FNA)
9 |
10 | [Using NvgSharp in Generic Game Engine](https://github.com/rds1983/NvgSharp/wiki/Using-NvgSharp-in-Generic-Game-Engine)
11 |
12 | [Text Rendering](https://github.com/rds1983/NvgSharp/wiki/Text-Rendering)
13 |
14 | ## Support
15 | [Discord](https://discord.gg/ZeHxhCY)
16 |
17 | ## Building From Source Code
18 | 1. Clone this repo.
19 | 2. Open a solution from the "build" folder.
20 |
21 | ## Sponsor
22 | https://www.patreon.com/rds1983
23 |
24 | https://boosty.to/rds1983
25 |
26 | bitcoin: 3GeKFcv8X1cn8WqH1mr8i7jgPBkQjQuyN1
27 |
28 | # Screenshot
29 | 
30 |
31 | ## Credits
32 | * [nanovg](https://github.com/memononen/nanovg)
33 | * [MonoGame](http://www.monogame.net/)
34 | * [FNA](https://github.com/FNA-XNA/FNA)
35 | * [OpenTK](https://github.com/opentk/opentk)
36 | * [Silk.NET](https://github.com/dotnet/Silk.NET)
37 | * [stb](https://github.com/nothings/stb)
38 |
--------------------------------------------------------------------------------
/build/NvgSharp.FNA.Core.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32328.378
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{578F4E7E-3DB4-4111-B6FD-831713726E4E}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FNA.Core", "..\..\FNA\FNA.Core.csproj", "{F724B17F-09FB-46C2-A8E3-407FC7B0591F}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FontStashSharp.FNA.Core", "..\..\FontStashSharp\src\XNA\FontStashSharp.FNA.Core.csproj", "{30A915B3-D36B-42DE-8F1A-96808C5F9948}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.FNA.Core", "..\src\XNA\NvgSharp.FNA.Core.csproj", "{267F26C4-E68A-443D-9794-689619F640AD}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Text.FNA.Core", "..\src\NvgSharp.Text\NvgSharp.Text.FNA.Core.csproj", "{F81AF955-0126-4B2F-9120-D011B53B5F49}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Samples.Demo.FNA.Core", "..\samples\NvgSharp.Samples.Demo\NvgSharp.Samples.Demo.FNA.Core.csproj", "{A213D290-ED16-4E5F-9181-8B5DD453E558}"
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|Any CPU = Debug|Any CPU
21 | Release|Any CPU = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {F724B17F-09FB-46C2-A8E3-407FC7B0591F}.Debug|Any CPU.ActiveCfg = Debug|x64
25 | {F724B17F-09FB-46C2-A8E3-407FC7B0591F}.Debug|Any CPU.Build.0 = Debug|x64
26 | {F724B17F-09FB-46C2-A8E3-407FC7B0591F}.Release|Any CPU.ActiveCfg = Release|x64
27 | {F724B17F-09FB-46C2-A8E3-407FC7B0591F}.Release|Any CPU.Build.0 = Release|x64
28 | {30A915B3-D36B-42DE-8F1A-96808C5F9948}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {30A915B3-D36B-42DE-8F1A-96808C5F9948}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {30A915B3-D36B-42DE-8F1A-96808C5F9948}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {30A915B3-D36B-42DE-8F1A-96808C5F9948}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {267F26C4-E68A-443D-9794-689619F640AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {267F26C4-E68A-443D-9794-689619F640AD}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {267F26C4-E68A-443D-9794-689619F640AD}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {267F26C4-E68A-443D-9794-689619F640AD}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {F81AF955-0126-4B2F-9120-D011B53B5F49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {F81AF955-0126-4B2F-9120-D011B53B5F49}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {F81AF955-0126-4B2F-9120-D011B53B5F49}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {F81AF955-0126-4B2F-9120-D011B53B5F49}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {A213D290-ED16-4E5F-9181-8B5DD453E558}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {A213D290-ED16-4E5F-9181-8B5DD453E558}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {A213D290-ED16-4E5F-9181-8B5DD453E558}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {A213D290-ED16-4E5F-9181-8B5DD453E558}.Release|Any CPU.Build.0 = Release|Any CPU
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(NestedProjects) = preSolution
49 | {A213D290-ED16-4E5F-9181-8B5DD453E558} = {578F4E7E-3DB4-4111-B6FD-831713726E4E}
50 | EndGlobalSection
51 | GlobalSection(ExtensibilityGlobals) = postSolution
52 | SolutionGuid = {A9C9D369-EE58-4E9D-B9FE-63023B644741}
53 | EndGlobalSection
54 | GlobalSection(MonoDevelopProperties) = preSolution
55 | StartupItem = Myra.UIEditor\Myra.UIEditor.csproj
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/build/NvgSharp.FNA.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32328.378
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FNA", "..\..\FNA\FNA.csproj", "{35253CE1-C864-4CD3-8249-4D1319748E8F}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{ADFCD11E-96DF-4C72-A428-D96BA161223E}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Samples.Demo.FNA", "..\samples\NvgSharp.Samples.Demo\NvgSharp.Samples.Demo.FNA.csproj", "{63C60C7F-3E6F-4026-A801-8E3AD2CEE9C3}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FontStashSharp.FNA", "..\..\FontStashSharp\src\XNA\FontStashSharp.FNA.csproj", "{4200A37F-4272-48EA-8CA7-BA5FE0BD6790}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Text.FNA", "..\src\NvgSharp.Text\NvgSharp.Text.FNA.csproj", "{A62DFB9E-0A89-4347-AA7A-2891C1C3D206}"
15 | EndProject
16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.FNA", "..\src\XNA\NvgSharp.FNA.csproj", "{94601022-412B-46BD-BA20-44A8A91E2022}"
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|Any CPU = Debug|Any CPU
21 | Release|Any CPU = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {35253CE1-C864-4CD3-8249-4D1319748E8F}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {35253CE1-C864-4CD3-8249-4D1319748E8F}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {63C60C7F-3E6F-4026-A801-8E3AD2CEE9C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {63C60C7F-3E6F-4026-A801-8E3AD2CEE9C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {63C60C7F-3E6F-4026-A801-8E3AD2CEE9C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {63C60C7F-3E6F-4026-A801-8E3AD2CEE9C3}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {4200A37F-4272-48EA-8CA7-BA5FE0BD6790}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {4200A37F-4272-48EA-8CA7-BA5FE0BD6790}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {4200A37F-4272-48EA-8CA7-BA5FE0BD6790}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {4200A37F-4272-48EA-8CA7-BA5FE0BD6790}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {A62DFB9E-0A89-4347-AA7A-2891C1C3D206}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {A62DFB9E-0A89-4347-AA7A-2891C1C3D206}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {A62DFB9E-0A89-4347-AA7A-2891C1C3D206}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {A62DFB9E-0A89-4347-AA7A-2891C1C3D206}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {94601022-412B-46BD-BA20-44A8A91E2022}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {94601022-412B-46BD-BA20-44A8A91E2022}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {94601022-412B-46BD-BA20-44A8A91E2022}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {94601022-412B-46BD-BA20-44A8A91E2022}.Release|Any CPU.Build.0 = Release|Any CPU
44 | EndGlobalSection
45 | GlobalSection(SolutionProperties) = preSolution
46 | HideSolutionNode = FALSE
47 | EndGlobalSection
48 | GlobalSection(NestedProjects) = preSolution
49 | {63C60C7F-3E6F-4026-A801-8E3AD2CEE9C3} = {ADFCD11E-96DF-4C72-A428-D96BA161223E}
50 | EndGlobalSection
51 | GlobalSection(ExtensibilityGlobals) = postSolution
52 | SolutionGuid = {A9C9D369-EE58-4E9D-B9FE-63023B644741}
53 | EndGlobalSection
54 | GlobalSection(MonoDevelopProperties) = preSolution
55 | StartupItem = Myra.UIEditor\Myra.UIEditor.csproj
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/build/NvgSharp.MonoGame.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32328.378
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{ADFCD11E-96DF-4C72-A428-D96BA161223E}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.MonoGame", "..\src\XNA\NvgSharp.MonoGame.csproj", "{6AFF5FD8-43AE-4144-918B-6D37C570BFA4}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Samples.Demo.MonoGame", "..\samples\NvgSharp.Samples.Demo\NvgSharp.Samples.Demo.MonoGame.csproj", "{7D2336D8-D4A4-4CF0-A86C-4B904B3EF428}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Text.MonoGame", "..\src\NvgSharp.Text\NvgSharp.Text.MonoGame.csproj", "{29F04FB2-43D8-4BC8-A92F-07E62F4934E1}"
13 | EndProject
14 | Global
15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 | Debug|Any CPU = Debug|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
20 | {6AFF5FD8-43AE-4144-918B-6D37C570BFA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {6AFF5FD8-43AE-4144-918B-6D37C570BFA4}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {6AFF5FD8-43AE-4144-918B-6D37C570BFA4}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {6AFF5FD8-43AE-4144-918B-6D37C570BFA4}.Release|Any CPU.Build.0 = Release|Any CPU
24 | {7D2336D8-D4A4-4CF0-A86C-4B904B3EF428}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {7D2336D8-D4A4-4CF0-A86C-4B904B3EF428}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {7D2336D8-D4A4-4CF0-A86C-4B904B3EF428}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {7D2336D8-D4A4-4CF0-A86C-4B904B3EF428}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {29F04FB2-43D8-4BC8-A92F-07E62F4934E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {29F04FB2-43D8-4BC8-A92F-07E62F4934E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {29F04FB2-43D8-4BC8-A92F-07E62F4934E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {29F04FB2-43D8-4BC8-A92F-07E62F4934E1}.Release|Any CPU.Build.0 = Release|Any CPU
32 | EndGlobalSection
33 | GlobalSection(SolutionProperties) = preSolution
34 | HideSolutionNode = FALSE
35 | EndGlobalSection
36 | GlobalSection(NestedProjects) = preSolution
37 | {7D2336D8-D4A4-4CF0-A86C-4B904B3EF428} = {ADFCD11E-96DF-4C72-A428-D96BA161223E}
38 | EndGlobalSection
39 | GlobalSection(ExtensibilityGlobals) = postSolution
40 | SolutionGuid = {A9C9D369-EE58-4E9D-B9FE-63023B644741}
41 | EndGlobalSection
42 | GlobalSection(MonoDevelopProperties) = preSolution
43 | StartupItem = Myra.UIEditor\Myra.UIEditor.csproj
44 | EndGlobalSection
45 | EndGlobal
46 |
--------------------------------------------------------------------------------
/build/NvgSharp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32328.378
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{ADFCD11E-96DF-4C72-A428-D96BA161223E}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp", "..\src\NvgSharp\NvgSharp.csproj", "{E7D9D1C9-51C6-4EDC-B21A-5B4C7E87B663}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Samples.Silk.NET", "..\samples\NvgSharp.Samples.Silk.NET\NvgSharp.Samples.Silk.NET.csproj", "{48B8A551-6457-4E8A-9725-EE481FEC659C}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Samples.OpenTK", "..\samples\NvgSharp.Samples.OpenTK\NvgSharp.Samples.OpenTK.csproj", "{9D43A56B-7AFB-434F-83A5-335848FCA1D9}"
13 | EndProject
14 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NvgSharp.Text", "..\src\NvgSharp.Text\NvgSharp.Text.csproj", "{2CD25B57-790B-413D-9005-FF4DA59F4D13}"
15 | EndProject
16 | Global
17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
18 | Debug|Any CPU = Debug|Any CPU
19 | Release|Any CPU = Release|Any CPU
20 | EndGlobalSection
21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
22 | {E7D9D1C9-51C6-4EDC-B21A-5B4C7E87B663}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {E7D9D1C9-51C6-4EDC-B21A-5B4C7E87B663}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {E7D9D1C9-51C6-4EDC-B21A-5B4C7E87B663}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {E7D9D1C9-51C6-4EDC-B21A-5B4C7E87B663}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {48B8A551-6457-4E8A-9725-EE481FEC659C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {48B8A551-6457-4E8A-9725-EE481FEC659C}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {48B8A551-6457-4E8A-9725-EE481FEC659C}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {48B8A551-6457-4E8A-9725-EE481FEC659C}.Release|Any CPU.Build.0 = Release|Any CPU
30 | {9D43A56B-7AFB-434F-83A5-335848FCA1D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {9D43A56B-7AFB-434F-83A5-335848FCA1D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {9D43A56B-7AFB-434F-83A5-335848FCA1D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {9D43A56B-7AFB-434F-83A5-335848FCA1D9}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {2CD25B57-790B-413D-9005-FF4DA59F4D13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {2CD25B57-790B-413D-9005-FF4DA59F4D13}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {2CD25B57-790B-413D-9005-FF4DA59F4D13}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {2CD25B57-790B-413D-9005-FF4DA59F4D13}.Release|Any CPU.Build.0 = Release|Any CPU
38 | EndGlobalSection
39 | GlobalSection(SolutionProperties) = preSolution
40 | HideSolutionNode = FALSE
41 | EndGlobalSection
42 | GlobalSection(NestedProjects) = preSolution
43 | {48B8A551-6457-4E8A-9725-EE481FEC659C} = {ADFCD11E-96DF-4C72-A428-D96BA161223E}
44 | {9D43A56B-7AFB-434F-83A5-335848FCA1D9} = {ADFCD11E-96DF-4C72-A428-D96BA161223E}
45 | EndGlobalSection
46 | GlobalSection(ExtensibilityGlobals) = postSolution
47 | SolutionGuid = {A9C9D369-EE58-4E9D-B9FE-63023B644741}
48 | EndGlobalSection
49 | GlobalSection(MonoDevelopProperties) = preSolution
50 | StartupItem = Myra.UIEditor\Myra.UIEditor.csproj
51 | EndGlobalSection
52 | EndGlobal
53 |
--------------------------------------------------------------------------------
/images/screenshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/images/screenshot.png
--------------------------------------------------------------------------------
/samples/Assets/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/samples/Assets/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/Roboto-Light.ttf
--------------------------------------------------------------------------------
/samples/Assets/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/samples/Assets/entypo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/entypo.ttf
--------------------------------------------------------------------------------
/samples/Assets/images.txt:
--------------------------------------------------------------------------------
1 | Image credits
2 | http://cuteoverload.com/2013/11/05/mom-taxi-xvi-birthday-party/
3 | http://cuteoverload.com/2013/11/05/benson-hedges-private-eye-in-the-case-of-the-crafty-craftsman/
4 | http://cuteoverload.com/2013/11/05/no-underwater-ballets/
5 | http://cuteoverload.com/2013/11/05/every-nose-has-a-story/
6 | http://cuteoverload.com/2013/11/04/nosevember-nozzle-nose/
7 | http://cuteoverload.com/2013/11/04/this-just-in-super-strength-cute/
8 | http://cuteoverload.com/2013/11/03/have-a-bunderful-sunday/
9 | http://cuteoverload.com/2013/11/02/caturday-sense-a-common-theme-here/
10 | http://cuteoverload.com/2013/11/01/nosevember-1st-24-hours-of-noses-1148pm-pt/
11 | http://cuteoverload.com/2013/04/02/there-might-be-something-cuter-than-this/
12 | http://cuteoverload.com/2013/07/17/snorting-micro-peeg-gets-belleh-rubs-interwebs-explode/
13 | http://cuteoverload.com/2013/08/07/bark-in-the-park-v3-0/
--------------------------------------------------------------------------------
/samples/Assets/images/image1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image1.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image10.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image11.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image12.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image2.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image3.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image4.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image5.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image6.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image7.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image8.jpg
--------------------------------------------------------------------------------
/samples/Assets/images/image9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/Assets/images/image9.jpg
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/Demo.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using FontStashSharp;
4 |
5 | #if MONOGAME || FNA
6 | using Microsoft.Xna.Framework;
7 | using Microsoft.Xna.Framework.Graphics;
8 | #elif STRIDE
9 | using Stride.Core.Mathematics;
10 | #else
11 | using StbImageSharp;
12 | using System.Drawing;
13 | using Texture2D = NvgSharp.Samples.Texture;
14 | #endif
15 |
16 | namespace NvgSharp.Samples
17 | {
18 | public class Demo
19 | {
20 | private static readonly string ICON_SEARCH = char.ConvertFromUtf32(0x1F50D);
21 | private static readonly string ICON_CIRCLED_CROSS = char.ConvertFromUtf32(0x2716);
22 | private static readonly string ICON_CHEVRON_RIGHT = char.ConvertFromUtf32(0xE75E);
23 | private static readonly string ICON_CHECK = char.ConvertFromUtf32(0x2713);
24 | private static readonly string ICON_LOGIN = char.ConvertFromUtf32(0xE740);
25 | private static readonly string ICON_TRASH = char.ConvertFromUtf32(0xE729);
26 |
27 | public FontSystem fontSystemNormal, fontSystemBold, fontSystemIcons;
28 | SpriteFontBase fontSans18, fontSans20, fontBold18, fontBold20;
29 | Texture2D[] images = new Texture2D[12];
30 |
31 | static float clampf(float a, float mn, float mx)
32 | {
33 | return a < mn ? mn : (a > mx ? mx : a);
34 | }
35 |
36 | // Returns 1 if col.rgba is 0.0f,0.0f,0.0f,0.0f, 0 otherwise
37 | public static bool isBlack(Color col)
38 | {
39 | return col == Color.Transparent;
40 | }
41 |
42 | public Demo(NvgContext vg)
43 | {
44 | for (var i = 0; i < images.Length; i++)
45 | {
46 | var path = "Assets/images/image" + (i + 1).ToString() + ".jpg";
47 |
48 | #if MONOGAME || FNA || STRIDE
49 | using (var stream = File.OpenRead(path))
50 | {
51 | images[i] = Texture2D.FromStream(vg.GraphicsDevice, stream);
52 | }
53 | #else
54 | ImageResult imageResult;
55 | using (var stream = File.OpenRead(path))
56 | {
57 | imageResult = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
58 | }
59 |
60 | var texture = new Texture(imageResult.Width, imageResult.Height);
61 | texture.SetData(new Rectangle(0, 0, imageResult.Width, imageResult.Height), imageResult.Data);
62 | images[i] = texture;
63 | #endif
64 | }
65 |
66 | fontSystemIcons = LoadFont("Assets/entypo.ttf");
67 | fontSystemNormal = LoadFont("Assets/Roboto-Regular.ttf");
68 | fontSystemBold = LoadFont("Assets/Roboto-Bold.ttf");
69 |
70 | fontSans18 = fontSystemNormal.GetFont(18);
71 | fontSans20 = fontSystemNormal.GetFont(20);
72 |
73 | fontBold18 = fontSystemBold.GetFont(18);
74 | fontBold20 = fontSystemBold.GetFont(20);
75 | }
76 |
77 | public void drawWindow(NvgContext vg, string title, float x, float y, float w, float h)
78 | {
79 | float cornerRadius = 3.0f;
80 | Paint shadowPaint;
81 | Paint headerPaint;
82 |
83 | vg.SaveState();
84 |
85 | // Window
86 | vg.BeginPath();
87 | vg.RoundedRect(x, y, w, h, cornerRadius);
88 | vg.FillColor(Utility.FromRGBA(28, 30, 34, 192));
89 | // vg.FillColor(GLUtility.FromRGBA(0,0,0,128));
90 | vg.Fill();
91 |
92 | // Drop shadow
93 | shadowPaint = vg.BoxGradient(x, y + 2, w, h, cornerRadius * 2, 10, Utility.FromRGBA(0, 0, 0, 128), Utility.FromRGBA(0, 0, 0, 0));
94 | vg.BeginPath();
95 | vg.Rect(x - 10, y - 10, w + 20, h + 30);
96 | vg.RoundedRect(x, y, w, h, cornerRadius);
97 | vg.PathWinding(Solidity.Hole);
98 | vg.FillPaint(shadowPaint);
99 | vg.Fill();
100 |
101 | // Header
102 | headerPaint = vg.LinearGradient(x, y, x, y + 15, Utility.FromRGBA(255, 255, 255, 8), Utility.FromRGBA(0, 0, 0, 16));
103 | vg.BeginPath();
104 | vg.RoundedRect(x + 1, y + 1, w - 2, 30, cornerRadius - 1);
105 | vg.FillPaint(headerPaint);
106 | vg.Fill();
107 | vg.BeginPath();
108 | vg.MoveTo(x + 0.5f, y + 0.5f + 30);
109 | vg.LineTo(x + 0.5f + w - 1, y + 0.5f + 30);
110 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 32));
111 | vg.Stroke();
112 |
113 | vg.FillColor(Utility.FromRGBA(0, 0, 0, 128));
114 | vg.TextAligned(fontBold18, title, x + w / 2, y + 16 + 1, TextHorizontalAlignment.Center, TextVerticalAlignment.Center);
115 |
116 | vg.FillColor(Utility.FromRGBA(220, 220, 220, 160));
117 | vg.TextAligned(fontBold18, title, x + w / 2, y + 16, TextHorizontalAlignment.Center, TextVerticalAlignment.Center);
118 |
119 | vg.RestoreState();
120 | }
121 |
122 | public void drawSearchBox(NvgContext vg, string text, float x, float y, float w, float h)
123 | {
124 | Paint bg;
125 | float cornerRadius = h / 2 - 1;
126 |
127 | // Edit
128 | bg = vg.BoxGradient(x, y + 1.5f, w, h, h / 2, 5, Utility.FromRGBA(0, 0, 0, 16), Utility.FromRGBA(0, 0, 0, 92));
129 | vg.BeginPath();
130 | vg.RoundedRect(x, y, w, h, cornerRadius);
131 | vg.FillPaint(bg);
132 | vg.Fill();
133 |
134 | var fontIcons = fontSystemIcons.GetFont((int)(h * 1.3f));
135 |
136 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 64));
137 | vg.TextAligned(fontIcons, ICON_SEARCH, x + h * 0.55f, y + h * 0.55f, TextHorizontalAlignment.Center, TextVerticalAlignment.Center);
138 |
139 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 32));
140 | vg.TextAligned(fontSans20, text, x + h * 1.05f, y + h * 0.5f, TextHorizontalAlignment.Left, TextVerticalAlignment.Center);
141 |
142 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 32));
143 | vg.TextAligned(fontIcons, ICON_CIRCLED_CROSS, x + w - h * 0.55f, y + h * 0.55f, TextHorizontalAlignment.Center, TextVerticalAlignment.Center);
144 | }
145 |
146 | public void drawDropDown(NvgContext vg, string text, float x, float y, float w, float h)
147 | {
148 | Paint bg;
149 | float cornerRadius = 4.0f;
150 |
151 | bg = vg.LinearGradient(x, y, x, y + h, Utility.FromRGBA(255, 255, 255, 16), Utility.FromRGBA(0, 0, 0, 16));
152 | vg.BeginPath();
153 | vg.RoundedRect(x + 1, y + 1, w - 2, h - 2, cornerRadius - 1);
154 | vg.FillPaint(bg);
155 | vg.Fill();
156 |
157 | vg.BeginPath();
158 | vg.RoundedRect(x + 0.5f, y + 0.5f, w - 1, h - 1, cornerRadius - 0.5f);
159 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 48));
160 | vg.Stroke();
161 |
162 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 160));
163 | vg.TextAligned(fontSans20, text, x + h * 0.3f, y + h * 0.5f, TextHorizontalAlignment.Left, TextVerticalAlignment.Center);
164 |
165 | var fontIcons = fontSystemIcons.GetFont((int)(h * 1.3f));
166 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 64));
167 | vg.TextAligned(fontIcons, ICON_CHEVRON_RIGHT, x + w - h * 0.5f, y + h * 0.5f, TextHorizontalAlignment.Center, TextVerticalAlignment.Center);
168 | }
169 |
170 | public void drawLabel(NvgContext vg, string text, float x, float y, float w, float h)
171 | {
172 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 128));
173 | vg.TextAligned(fontSans18, text, x, y + h * 0.5f, TextHorizontalAlignment.Left, TextVerticalAlignment.Center);
174 | }
175 |
176 | public static void drawEditBoxBase(NvgContext vg, float x, float y, float w, float h)
177 | {
178 | Paint bg;
179 | // Edit
180 | bg = vg.BoxGradient(x + 1, y + 1 + 1.5f, w - 2, h - 2, 3, 4, Utility.FromRGBA(255, 255, 255, 32), Utility.FromRGBA(32, 32, 32, 32));
181 | vg.BeginPath();
182 | vg.RoundedRect(x + 1, y + 1, w - 2, h - 2, 4 - 1);
183 | vg.FillPaint(bg);
184 | vg.Fill();
185 |
186 | vg.BeginPath();
187 | vg.RoundedRect(x + 0.5f, y + 0.5f, w - 1, h - 1, 4 - 0.5f);
188 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 48));
189 | vg.Stroke();
190 | }
191 |
192 | public void drawEditBox(NvgContext vg, string text, float x, float y, float w, float h)
193 | {
194 | drawEditBoxBase(vg, x, y, w, h);
195 |
196 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 64));
197 | vg.TextAligned(fontSans20, text, x + h * 0.3f, y + h * 0.5f, TextHorizontalAlignment.Left, TextVerticalAlignment.Center);
198 | }
199 |
200 | public void drawEditBoxNum(NvgContext vg, string text, string units, float x, float y, float w, float h)
201 | {
202 | drawEditBoxBase(vg, x, y, w, h);
203 |
204 | var sz = fontSans18.MeasureString(units);
205 |
206 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 64));
207 | vg.TextAligned(fontSans18, units, x + w - h * 0.3f, y + h * 0.5f, TextHorizontalAlignment.Right, TextVerticalAlignment.Center);
208 |
209 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 128));
210 | vg.TextAligned(fontSans20, text, x + w - sz.X - h * 0.5f, y + h * 0.5f, TextHorizontalAlignment.Right, TextVerticalAlignment.Center);
211 | }
212 |
213 | public void drawCheckBox(NvgContext vg, string text, float x, float y, float w, float h)
214 | {
215 | Paint bg;
216 |
217 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 160));
218 | vg.TextAligned(fontSans18, text, x + 28, y + h * 0.5f, TextHorizontalAlignment.Left, TextVerticalAlignment.Center);
219 |
220 | bg = vg.BoxGradient(x + 1, y + (int)(h * 0.5f) - 9 + 1, 18, 18, 3, 3, Utility.FromRGBA(0, 0, 0, 32), Utility.FromRGBA(0, 0, 0, 92));
221 | vg.BeginPath();
222 | vg.RoundedRect(x + 1, y + (int)(h * 0.5f) - 9, 18, 18, 3);
223 | vg.FillPaint(bg);
224 | vg.Fill();
225 |
226 | var fontIcons = fontSystemIcons.GetFont(40);
227 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 128));
228 | vg.TextAligned(fontIcons, ICON_CHECK, x + 9 + 2, y + h * 0.5f, TextHorizontalAlignment.Center, TextVerticalAlignment.Center);
229 | }
230 |
231 | public void drawButton(NvgContext vg, string preicon, string text, float x, float y, float w, float h, Color col)
232 | {
233 | Paint bg;
234 | float cornerRadius = 4.0f;
235 | float tw = 0, iw = 0;
236 |
237 | bg = vg.LinearGradient(x, y, x, y + h, Utility.FromRGBA(255, 255, 255, isBlack(col) ? (byte)16 : (byte)32),
238 | Utility.FromRGBA(0, 0, 0, isBlack(col) ? (byte)16 : (byte)32));
239 | vg.BeginPath();
240 | vg.RoundedRect(x + 1, y + 1, w - 2, h - 2, cornerRadius - 1);
241 | if (!isBlack(col))
242 | {
243 | vg.FillColor(col);
244 | vg.Fill();
245 | }
246 | vg.FillPaint(bg);
247 | vg.Fill();
248 |
249 | vg.BeginPath();
250 | vg.RoundedRect(x + 0.5f, y + 0.5f, w - 1, h - 1, cornerRadius - 0.5f);
251 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 48));
252 | vg.Stroke();
253 |
254 | var sz = fontBold20.MeasureString(text);
255 | tw = sz.X;
256 | if (!string.IsNullOrEmpty(preicon))
257 | {
258 | var fontIcons = fontSystemIcons.GetFont((int)(h * 1.3f));
259 | sz = fontIcons.MeasureString(preicon);
260 | iw = sz.X;
261 | iw += h * 0.15f;
262 |
263 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 96));
264 | vg.TextAligned(fontIcons, preicon, x + w * 0.5f - tw * 0.5f - iw * 0.75f, y + h * 0.5f, TextHorizontalAlignment.Left, TextVerticalAlignment.Center);
265 | }
266 |
267 | vg.FillColor(Utility.FromRGBA(0, 0, 0, 160));
268 | vg.TextAligned(fontBold20, text, x + w * 0.5f - tw * 0.5f + iw * 0.25f, y + h * 0.5f - 1, TextHorizontalAlignment.Left, TextVerticalAlignment.Center);
269 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 160));
270 | vg.TextAligned(fontBold20, text, x + w * 0.5f - tw * 0.5f + iw * 0.25f, y + h * 0.5f, TextHorizontalAlignment.Left, TextVerticalAlignment.Center);
271 | }
272 |
273 | public static void drawSlider(NvgContext vg, float pos, float x, float y, float w, float h)
274 | {
275 | Paint bg, knob;
276 | float cy = y + (int)(h * 0.5f);
277 | float kr = (int)(h * 0.25f);
278 |
279 | vg.SaveState();
280 | // ClearState(vg);
281 |
282 | // Slot
283 | bg = vg.BoxGradient(x, cy - 2 + 1, w, 4, 2, 2, Utility.FromRGBA(0, 0, 0, 32), Utility.FromRGBA(0, 0, 0, 128));
284 | vg.BeginPath();
285 | vg.RoundedRect(x, cy - 2, w, 4, 2);
286 | vg.FillPaint(bg);
287 | vg.Fill();
288 |
289 | // Knob Shadow
290 | bg = vg.RadialGradient(x + (int)(pos * w), cy + 1, kr - 3, kr + 3, Utility.FromRGBA(0, 0, 0, 64), Utility.FromRGBA(0, 0, 0, 0));
291 | vg.BeginPath();
292 | vg.Rect(x + (int)(pos * w) - kr - 5, cy - kr - 5, kr * 2 + 5 + 5, kr * 2 + 5 + 5 + 3);
293 | vg.Circle(x + (int)(pos * w), cy, kr);
294 | vg.PathWinding(Solidity.Hole);
295 | vg.FillPaint(bg);
296 | vg.Fill();
297 |
298 | // Knob
299 | knob = vg.LinearGradient(x, cy - kr, x, cy + kr, Utility.FromRGBA(255, 255, 255, 16), Utility.FromRGBA(0, 0, 0, 16));
300 | vg.BeginPath();
301 | vg.Circle(x + (int)(pos * w), cy, kr - 1);
302 | vg.FillColor(Utility.FromRGBA(40, 43, 48, 255));
303 | vg.Fill();
304 | vg.FillPaint(knob);
305 | vg.Fill();
306 |
307 | vg.BeginPath();
308 | vg.Circle(x + (int)(pos * w), cy, kr - 0.5f);
309 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 92));
310 | vg.Stroke();
311 |
312 | vg.RestoreState();
313 | }
314 |
315 | public static void drawEyes(NvgContext vg, float x, float y, float w, float h, float mx, float my, float t)
316 | {
317 | Paint gloss, bg;
318 | float ex = w * 0.23f;
319 | float ey = h * 0.5f;
320 | float lx = x + ex;
321 | float ly = y + ey;
322 | float rx = x + w - ex;
323 | float ry = y + ey;
324 | float dx, dy, d;
325 | float br = (ex < ey ? ex : ey) * 0.5f;
326 | float blink = 1 - (float)(Math.Pow(Math.Sin(t * 0.5f), 200) * 0.8f);
327 |
328 | bg = vg.LinearGradient(x, y + h * 0.5f, x + w * 0.1f, y + h, Utility.FromRGBA(0, 0, 0, 32), Utility.FromRGBA(0, 0, 0, 16));
329 | vg.BeginPath();
330 | vg.Ellipse(lx + 3.0f, ly + 16.0f, ex, ey);
331 | vg.Ellipse(rx + 3.0f, ry + 16.0f, ex, ey);
332 | vg.FillPaint(bg);
333 | vg.Fill();
334 |
335 | bg = vg.LinearGradient(x, y + h * 0.25f, x + w * 0.1f, y + h, Utility.FromRGBA(220, 220, 220, 255), Utility.FromRGBA(128, 128, 128, 255));
336 | vg.BeginPath();
337 | vg.Ellipse(lx, ly, ex, ey);
338 | vg.Ellipse(rx, ry, ex, ey);
339 | vg.FillPaint(bg);
340 | vg.Fill();
341 |
342 | dx = (mx - rx) / (ex * 10);
343 | dy = (my - ry) / (ey * 10);
344 | d = (float)Math.Sqrt(dx * dx + dy * dy);
345 | if (d > 1.0f)
346 | {
347 | dx /= d;
348 | dy /= d;
349 | }
350 | dx *= ex * 0.4f;
351 | dy *= ey * 0.5f;
352 | vg.BeginPath();
353 | vg.Ellipse(lx + dx, ly + dy + ey * 0.25f * (1 - blink), br, br * blink);
354 | vg.FillColor(Utility.FromRGBA(32, 32, 32, 255));
355 | vg.Fill();
356 |
357 | dx = (mx - rx) / (ex * 10);
358 | dy = (my - ry) / (ey * 10);
359 | d = (float)Math.Sqrt(dx * dx + dy * dy);
360 | if (d > 1.0f)
361 | {
362 | dx /= d;
363 | dy /= d;
364 | }
365 | dx *= ex * 0.4f;
366 | dy *= ey * 0.5f;
367 | vg.BeginPath();
368 | vg.Ellipse(rx + dx, ry + dy + ey * 0.25f * (1 - blink), br, br * blink);
369 | vg.FillColor(Utility.FromRGBA(32, 32, 32, 255));
370 | vg.Fill();
371 |
372 | gloss = vg.RadialGradient(lx - ex * 0.25f, ly - ey * 0.5f, ex * 0.1f, ex * 0.75f, Utility.FromRGBA(255, 255, 255, 128), Utility.FromRGBA(255, 255, 255, 0));
373 | vg.BeginPath();
374 | vg.Ellipse(lx, ly, ex, ey);
375 | vg.FillPaint(gloss);
376 | vg.Fill();
377 |
378 | gloss = vg.RadialGradient(rx - ex * 0.25f, ry - ey * 0.5f, ex * 0.1f, ex * 0.75f, Utility.FromRGBA(255, 255, 255, 128), Utility.FromRGBA(255, 255, 255, 0));
379 | vg.BeginPath();
380 | vg.Ellipse(rx, ry, ex, ey);
381 | vg.FillPaint(gloss);
382 | vg.Fill();
383 | }
384 |
385 | public static void drawGraph(NvgContext vg, float x, float y, float w, float h, float t)
386 | {
387 | Paint bg;
388 | float[] samples = new float[6];
389 | float[] sx = new float[6], sy = new float[6];
390 | float dx = w / 5.0f;
391 | int i;
392 |
393 | samples[0] = (1 + (float)Math.Sin(t * 1.2345f + (float)Math.Cos(t * 0.33457f) * 0.44f)) * 0.5f;
394 | samples[1] = (1 + (float)Math.Sin(t * 0.68363f + (float)Math.Cos(t * 1.3f) * 1.55f)) * 0.5f;
395 | samples[2] = (1 + (float)Math.Sin(t * 1.1642f + (float)Math.Cos(t * 0.33457) * 1.24f)) * 0.5f;
396 | samples[3] = (1 + (float)Math.Sin(t * 0.56345f + (float)Math.Cos(t * 1.63f) * 0.14f)) * 0.5f;
397 | samples[4] = (1 + (float)Math.Sin(t * 1.6245f + (float)Math.Cos(t * 0.254f) * 0.3f)) * 0.5f;
398 | samples[5] = (1 + (float)Math.Sin(t * 0.345f + (float)Math.Cos(t * 0.03f) * 0.6f)) * 0.5f;
399 |
400 | for (i = 0; i < 6; i++)
401 | {
402 | sx[i] = x + i * dx;
403 | sy[i] = y + h * samples[i] * 0.8f;
404 | }
405 |
406 | // Graph background
407 | bg = vg.LinearGradient(x, y, x, y + h, Utility.FromRGBA(0, 160, 192, 0), Utility.FromRGBA(0, 160, 192, 64));
408 | vg.BeginPath();
409 | vg.MoveTo(sx[0], sy[0]);
410 | for (i = 1; i < 6; i++)
411 | vg.BezierTo(sx[i - 1] + dx * 0.5f, sy[i - 1], sx[i] - dx * 0.5f, sy[i], sx[i], sy[i]);
412 | vg.LineTo(x + w, y + h);
413 | vg.LineTo(x, y + h);
414 | vg.FillPaint(bg);
415 | vg.Fill();
416 |
417 | // Graph line
418 | vg.BeginPath();
419 | vg.MoveTo(sx[0], sy[0] + 2);
420 | for (i = 1; i < 6; i++)
421 | vg.BezierTo(sx[i - 1] + dx * 0.5f, sy[i - 1] + 2, sx[i] - dx * 0.5f, sy[i] + 2, sx[i], sy[i] + 2);
422 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 32));
423 | vg.StrokeWidth(3.0f);
424 | vg.Stroke();
425 |
426 | vg.BeginPath();
427 | vg.MoveTo(sx[0], sy[0]);
428 | for (i = 1; i < 6; i++)
429 | vg.BezierTo(sx[i - 1] + dx * 0.5f, sy[i - 1], sx[i] - dx * 0.5f, sy[i], sx[i], sy[i]);
430 | vg.StrokeColor(Utility.FromRGBA(0, 160, 192, 255));
431 | vg.StrokeWidth(3.0f);
432 | vg.Stroke();
433 |
434 | // Graph sample pos
435 | for (i = 0; i < 6; i++)
436 | {
437 | bg = vg.RadialGradient(sx[i], sy[i] + 2, 3.0f, 8.0f, Utility.FromRGBA(0, 0, 0, 32), Utility.FromRGBA(0, 0, 0, 0));
438 | vg.BeginPath();
439 | vg.Rect(sx[i] - 10, sy[i] - 10 + 2, 20, 20);
440 | vg.FillPaint(bg);
441 | vg.Fill();
442 | }
443 |
444 | vg.BeginPath();
445 | for (i = 0; i < 6; i++)
446 | vg.Circle(sx[i], sy[i], 4.0f);
447 | vg.FillColor(Utility.FromRGBA(0, 160, 192, 255));
448 | vg.Fill();
449 | vg.BeginPath();
450 | for (i = 0; i < 6; i++)
451 | vg.Circle(sx[i], sy[i], 2.0f);
452 | vg.FillColor(Utility.FromRGBA(220, 220, 220, 255));
453 | vg.Fill();
454 |
455 | vg.StrokeWidth(1.0f);
456 | }
457 |
458 | public static void drawSpinner(NvgContext vg, float cx, float cy, float r, float t)
459 | {
460 | float a0 = 0.0f + t * 6;
461 | float a1 = (float)Math.PI + t * 6;
462 | float r0 = r;
463 | float r1 = r * 0.75f;
464 | float ax, ay, bx, by;
465 | Paint paint;
466 |
467 | vg.SaveState();
468 |
469 | vg.BeginPath();
470 | vg.Arc(cx, cy, r0, a0, a1, Winding.ClockWise);
471 | vg.Arc(cx, cy, r1, a1, a0, Winding.CounterClockWise);
472 | vg.ClosePath();
473 | ax = cx + (float)Math.Cos(a0) * (r0 + r1) * 0.5f;
474 | ay = cy + (float)Math.Sin(a0) * (r0 + r1) * 0.5f;
475 | bx = cx + (float)Math.Cos(a1) * (r0 + r1) * 0.5f;
476 | by = cy + (float)Math.Sin(a1) * (r0 + r1) * 0.5f;
477 | paint = vg.LinearGradient(ax, ay, bx, by, Utility.FromRGBA(0, 0, 0, 0), Utility.FromRGBA(0, 0, 0, 128));
478 | vg.FillPaint(paint);
479 | vg.Fill();
480 |
481 | vg.RestoreState();
482 | }
483 |
484 | public static void drawThumbnails(NvgContext vg, float x, float y, float w, float h, Texture2D[] images, float t)
485 | {
486 | float cornerRadius = 3.0f;
487 | Paint shadowPaint, imgPaint, fadePaint;
488 | float ix, iy, iw, ih;
489 | float thumb = 60.0f;
490 | float arry = 30.5f;
491 | int imgw, imgh;
492 | float stackh = (images.Length / 2) * (thumb + 10) + 10;
493 | int i;
494 | float u = (1 + (float)Math.Cos(t * 0.5f)) * 0.5f;
495 | float u2 = (1 - (float)Math.Cos(t * 0.2f)) * 0.5f;
496 | float scrollh, dv;
497 |
498 | vg.SaveState();
499 | // ClearState(vg);
500 |
501 | // Drop shadow
502 | shadowPaint = vg.BoxGradient(x, y + 4, w, h, cornerRadius * 2, 20, Utility.FromRGBA(0, 0, 0, 128), Utility.FromRGBA(0, 0, 0, 0));
503 | vg.BeginPath();
504 | vg.Rect(x - 10, y - 10, w + 20, h + 30);
505 | vg.RoundedRect(x, y, w, h, cornerRadius);
506 | vg.PathWinding(Solidity.Hole);
507 | vg.FillPaint(shadowPaint);
508 | vg.Fill();
509 |
510 | // Window
511 | vg.BeginPath();
512 | vg.RoundedRect(x, y, w, h, cornerRadius);
513 | vg.MoveTo(x - 10, y + arry);
514 | vg.LineTo(x + 1, y + arry - 11);
515 | vg.LineTo(x + 1, y + arry + 11);
516 | vg.FillColor(Utility.FromRGBA(200, 200, 200, 255));
517 | vg.Fill();
518 |
519 | vg.SaveState();
520 | vg.Scissor(x, y, w, h);
521 | vg.Translate(0, -(stackh - h) * u);
522 |
523 | dv = 1.0f / (images.Length - 1);
524 |
525 | for (i = 0; i < images.Length; i++)
526 | {
527 | float tx, ty, v, a;
528 | tx = x + 10;
529 | ty = y + 10;
530 | tx += (i % 2) * (thumb + 10);
531 | ty += (i / 2) * (thumb + 10);
532 |
533 | imgw = images[i].Width;
534 | imgh = images[i].Height;
535 |
536 | if (imgw < imgh)
537 | {
538 | iw = thumb;
539 | ih = iw * imgh / imgw;
540 | ix = 0;
541 | iy = -(ih - thumb) * 0.5f;
542 | }
543 | else
544 | {
545 | ih = thumb;
546 | iw = ih * imgw / imgh;
547 | ix = -(iw - thumb) * 0.5f;
548 | iy = 0;
549 | }
550 |
551 | v = i * dv;
552 | a = clampf((u2 - v) / dv, 0, 1);
553 |
554 | if (a < 1.0f)
555 | drawSpinner(vg, tx + thumb / 2, ty + thumb / 2, thumb * 0.25f, t);
556 |
557 | imgPaint = vg.ImagePattern(tx + ix, ty + iy, iw, ih, 0.0f / 180.0f * (float)Math.PI, images[i], a);
558 | vg.BeginPath();
559 | vg.RoundedRect(tx, ty, thumb, thumb, 5);
560 | vg.FillPaint(imgPaint);
561 | vg.Fill();
562 |
563 | shadowPaint = vg.BoxGradient(tx - 1, ty, thumb + 2, thumb + 2, 5, 3, Utility.FromRGBA(0, 0, 0, 128), Utility.FromRGBA(0, 0, 0, 0));
564 | vg.BeginPath();
565 | vg.Rect(tx - 5, ty - 5, thumb + 10, thumb + 10);
566 | vg.RoundedRect(tx, ty, thumb, thumb, 6);
567 | vg.PathWinding(Solidity.Hole);
568 | vg.FillPaint(shadowPaint);
569 | vg.Fill();
570 |
571 | vg.BeginPath();
572 | vg.RoundedRect(tx + 0.5f, ty + 0.5f, thumb - 1, thumb - 1, 4 - 0.5f);
573 | vg.StrokeWidth(1.0f);
574 | vg.StrokeColor(Utility.FromRGBA(255, 255, 255, 192));
575 | vg.Stroke();
576 | }
577 | vg.RestoreState();
578 |
579 | // Hide fades
580 | fadePaint = vg.LinearGradient(x, y, x, y + 6, Utility.FromRGBA(200, 200, 200, 255), Utility.FromRGBA(200, 200, 200, 0));
581 | vg.BeginPath();
582 | vg.Rect(x + 4, y, w - 8, 6);
583 | vg.FillPaint(fadePaint);
584 | vg.Fill();
585 |
586 | fadePaint = vg.LinearGradient(x, y + h, x, y + h - 6, Utility.FromRGBA(200, 200, 200, 255), Utility.FromRGBA(200, 200, 200, 0));
587 | vg.BeginPath();
588 | vg.Rect(x + 4, y + h - 6, w - 8, 6);
589 | vg.FillPaint(fadePaint);
590 | vg.Fill();
591 |
592 | // Scroll bar
593 | shadowPaint = vg.BoxGradient(x + w - 12 + 1, y + 4 + 1, 8, h - 8, 3, 4, Utility.FromRGBA(0, 0, 0, 32), Utility.FromRGBA(0, 0, 0, 92));
594 | vg.BeginPath();
595 | vg.RoundedRect(x + w - 12, y + 4, 8, h - 8, 3);
596 | vg.FillPaint(shadowPaint);
597 | // vg.FillColor(GLUtility.FromRGBA(255,0,0,128));
598 | vg.Fill();
599 |
600 | scrollh = (h / stackh) * (h - 8);
601 | shadowPaint = vg.BoxGradient(x + w - 12 - 1, y + 4 + (h - 8 - scrollh) * u - 1, 8, scrollh, 3, 4, Utility.FromRGBA(220, 220, 220, 255), Utility.FromRGBA(128, 128, 128, 255));
602 | vg.BeginPath();
603 | vg.RoundedRect(x + w - 12 + 1, y + 4 + 1 + (h - 8 - scrollh) * u, 8 - 2, scrollh - 2, 2);
604 | vg.FillPaint(shadowPaint);
605 | // vg.FillColor(GLUtility.FromRGBA(0,0,0,128));
606 | vg.Fill();
607 |
608 | vg.RestoreState();
609 | }
610 |
611 | public static void drawColorwheel(NvgContext vg, float x, float y, float w, float h, float t)
612 | {
613 | int i;
614 | float r0, r1, ax, ay, bx, by, cx, cy, aeps, r;
615 | float hue = (float)Math.Sin(t * 0.12f);
616 | Paint paint;
617 |
618 | vg.SaveState();
619 |
620 | /* vg.BeginPath();
621 | vg.Rect(x,y,w,h);
622 | vg.FillColor(GLUtility.FromRGBA(255,0,0,128));
623 | vg.Fill();*/
624 |
625 | cx = x + w * 0.5f;
626 | cy = y + h * 0.5f;
627 | r1 = (w < h ? w : h) * 0.5f - 5.0f;
628 | r0 = r1 - 20.0f;
629 | aeps = 0.5f / r1; // half a pixel arc length in radians (2pi cancels out).
630 |
631 | for (i = 0; i < 6; i++)
632 | {
633 | float a0 = (float)i / 6.0f * (float)Math.PI * 2.0f - aeps;
634 | float a1 = (float)(i + 1.0f) / 6.0f * (float)Math.PI * 2.0f + aeps;
635 | vg.BeginPath();
636 | vg.Arc(cx, cy, r0, a0, a1, Winding.ClockWise);
637 | vg.Arc(cx, cy, r1, a1, a0, Winding.CounterClockWise);
638 | vg.ClosePath();
639 | ax = cx + (float)Math.Cos(a0) * (r0 + r1) * 0.5f;
640 | ay = cy + (float)Math.Sin(a0) * (r0 + r1) * 0.5f;
641 | bx = cx + (float)Math.Cos(a1) * (r0 + r1) * 0.5f;
642 | by = cy + (float)Math.Sin(a1) * (r0 + r1) * 0.5f;
643 | paint = vg.LinearGradient(ax, ay, bx, by, Utility.HSLA(a0 / ((float)Math.PI * 2), 1.0f, 0.55f, 255), Utility.HSLA(a1 / ((float)Math.PI * 2), 1.0f, 0.55f, 255));
644 | vg.FillPaint(paint);
645 | vg.Fill();
646 | }
647 |
648 | vg.BeginPath();
649 | vg.Circle(cx, cy, r0 - 0.5f);
650 | vg.Circle(cx, cy, r1 + 0.5f);
651 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 64));
652 | vg.StrokeWidth(1.0f);
653 | vg.Stroke();
654 |
655 | // Selector
656 | vg.SaveState();
657 | vg.Translate(cx, cy);
658 | vg.Rotate(hue * (float)Math.PI * 2);
659 |
660 | // Marker on
661 | vg.StrokeWidth(2.0f);
662 | vg.BeginPath();
663 | vg.Rect(r0 - 1, -3, r1 - r0 + 2, 6);
664 | vg.StrokeColor(Utility.FromRGBA(255, 255, 255, 192));
665 | vg.Stroke();
666 |
667 | paint = vg.BoxGradient(r0 - 3, -5, r1 - r0 + 6, 10, 2, 4, Utility.FromRGBA(0, 0, 0, 128), Utility.FromRGBA(0, 0, 0, 0));
668 | vg.BeginPath();
669 | vg.Rect(r0 - 2 - 10, -4 - 10, r1 - r0 + 4 + 20, 8 + 20);
670 | vg.Rect(r0 - 2, -4, r1 - r0 + 4, 8);
671 | vg.PathWinding(Solidity.Hole);
672 | vg.FillPaint(paint);
673 | vg.Fill();
674 |
675 | // Center triangle
676 | r = r0 - 6;
677 | ax = (float)Math.Cos(120.0f / 180.0f * (float)Math.PI) * r;
678 | ay = (float)Math.Sin(120.0f / 180.0f * (float)Math.PI) * r;
679 | bx = (float)Math.Cos(-120.0f / 180.0f * (float)Math.PI) * r;
680 | by = (float)Math.Sin(-120.0f / 180.0f * (float)Math.PI) * r;
681 | vg.BeginPath();
682 | vg.MoveTo(r, 0);
683 | vg.LineTo(ax, ay);
684 | vg.LineTo(bx, by);
685 | vg.ClosePath();
686 | paint = vg.LinearGradient(r, 0, ax, ay, Utility.HSLA(hue, 1.0f, 0.5f, 255), Utility.FromRGBA(255, 255, 255, 255));
687 | vg.FillPaint(paint);
688 | vg.Fill();
689 | paint = vg.LinearGradient((r + ax) * 0.5f, (0 + ay) * 0.5f, bx, by, Utility.FromRGBA(0, 0, 0, 0), Utility.FromRGBA(0, 0, 0, 255));
690 | vg.FillPaint(paint);
691 | vg.Fill();
692 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 64));
693 | vg.Stroke();
694 |
695 | // Select circle on triangle
696 | ax = (float)Math.Cos(120.0f / 180.0f * (float)Math.PI) * r * 0.3f;
697 | ay = (float)Math.Sin(120.0f / 180.0f * (float)Math.PI) * r * 0.4f;
698 | vg.StrokeWidth(2.0f);
699 | vg.BeginPath();
700 | vg.Circle(ax, ay, 5);
701 | vg.StrokeColor(Utility.FromRGBA(255, 255, 255, 192));
702 | vg.Stroke();
703 |
704 | paint = vg.RadialGradient(ax, ay, 7, 9, Utility.FromRGBA(0, 0, 0, 64), Utility.FromRGBA(0, 0, 0, 0));
705 | vg.BeginPath();
706 | vg.Rect(ax - 20, ay - 20, 40, 40);
707 | vg.Circle(ax, ay, 7);
708 | vg.PathWinding(Solidity.Hole);
709 | vg.FillPaint(paint);
710 | vg.Fill();
711 |
712 | vg.RestoreState();
713 |
714 | vg.RestoreState();
715 | }
716 |
717 | public static void drawLines(NvgContext vg, float x, float y, float w, float h, float t)
718 | {
719 | int i, j;
720 | float pad = 5.0f, s = w / 9.0f - pad * 2;
721 | float[] pts = new float[4 * 2];
722 | float fx, fy;
723 | LineCap[] joins = new LineCap[] { LineCap.Miter, LineCap.Round, LineCap.Bevel };
724 | LineCap[] caps = new LineCap[] { LineCap.Butt, LineCap.Round, LineCap.Square };
725 |
726 | vg.SaveState();
727 | pts[0] = -s * 0.25f + (float)Math.Cos(t * 0.3f) * s * 0.5f;
728 | pts[1] = (float)Math.Sin(t * 0.3f) * s * 0.5f;
729 | pts[2] = -s * 0.25f;
730 | pts[3] = 0;
731 | pts[4] = s * 0.25f;
732 | pts[5] = 0;
733 | pts[6] = s * 0.25f + (float)Math.Cos(-t * 0.3f) * s * 0.5f;
734 | pts[7] = (float)Math.Sin(-t * 0.3f) * s * 0.5f;
735 |
736 | for (i = 0; i < 3; i++)
737 | {
738 | for (j = 0; j < 3; j++)
739 | {
740 | fx = x + s * 0.5f + (i * 3 + j) / 9.0f * w + pad;
741 | fy = y - s * 0.5f + pad;
742 |
743 | vg.LineCap(caps[i]);
744 | vg.LineJoin(joins[j]);
745 |
746 | vg.StrokeWidth(s * 0.3f);
747 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 160));
748 | vg.BeginPath();
749 | vg.MoveTo(fx + pts[0], fy + pts[1]);
750 | vg.LineTo(fx + pts[2], fy + pts[3]);
751 | vg.LineTo(fx + pts[4], fy + pts[5]);
752 | vg.LineTo(fx + pts[6], fy + pts[7]);
753 | vg.Stroke();
754 |
755 | vg.LineCap(LineCap.Butt);
756 | vg.LineJoin(LineCap.Bevel);
757 |
758 | vg.StrokeWidth(1.0f);
759 | vg.StrokeColor(Utility.FromRGBA(0, 192, 255, 255));
760 | vg.BeginPath();
761 | vg.MoveTo(fx + pts[0], fy + pts[1]);
762 | vg.LineTo(fx + pts[2], fy + pts[3]);
763 | vg.LineTo(fx + pts[4], fy + pts[5]);
764 | vg.LineTo(fx + pts[6], fy + pts[7]);
765 | vg.Stroke();
766 | }
767 | }
768 |
769 | vg.RestoreState();
770 | }
771 |
772 | private static FontSystem LoadFont(string path)
773 | {
774 | var result = new FontSystem();
775 | using (var stream = File.OpenRead(path))
776 | {
777 | result.AddFont(stream);
778 | }
779 |
780 | return result;
781 | }
782 |
783 | public static void drawWidths(NvgContext vg, float x, float y, float width)
784 | {
785 | int i;
786 |
787 | vg.SaveState();
788 |
789 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 255));
790 |
791 | for (i = 0; i < 20; i++)
792 | {
793 | float w = (i + 0.5f) * 0.1f;
794 | vg.StrokeWidth(w);
795 | vg.BeginPath();
796 | vg.MoveTo(x, y);
797 | vg.LineTo(x + width, y + width * 0.3f);
798 | vg.Stroke();
799 | y += 10;
800 | }
801 |
802 | vg.RestoreState();
803 | }
804 |
805 | public static void drawCaps(NvgContext vg, float x, float y, float width)
806 | {
807 | int i;
808 | LineCap[] caps = new[] { LineCap.Butt, LineCap.Round, LineCap.Square };
809 | float lineWidth = 8.0f;
810 |
811 | vg.SaveState();
812 |
813 | vg.BeginPath();
814 | vg.Rect(x - lineWidth / 2, y, width + lineWidth, 40);
815 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 32));
816 | vg.Fill();
817 |
818 | vg.BeginPath();
819 | vg.Rect(x, y, width, 40);
820 | vg.FillColor(Utility.FromRGBA(255, 255, 255, 32));
821 | vg.Fill();
822 |
823 | vg.StrokeWidth(lineWidth);
824 | for (i = 0; i < 3; i++)
825 | {
826 | vg.LineCap(caps[i]);
827 | vg.StrokeColor(Utility.FromRGBA(0, 0, 0, 255));
828 | vg.BeginPath();
829 | vg.MoveTo(x, y + i * 10 + 5);
830 | vg.LineTo(x + width, y + i * 10 + 5);
831 | vg.Stroke();
832 | }
833 |
834 | vg.RestoreState();
835 | }
836 |
837 | public static void drawScissor(NvgContext vg, float x, float y, float t)
838 | {
839 | vg.SaveState();
840 |
841 | // Draw first rect and set scissor to it's area.
842 | vg.Translate(x, y);
843 | vg.Rotate(Utility.DegToRad(5));
844 | vg.BeginPath();
845 | vg.Rect(-20, -20, 60, 40);
846 | vg.FillColor(Utility.FromRGBA(255, 0, 0, 255));
847 | vg.Fill();
848 | vg.Scissor(-20, -20, 60, 40);
849 |
850 | // Draw second rectangle with offset and rotation.
851 | vg.Translate(40, 0);
852 | vg.Rotate(t);
853 |
854 | // Draw the intended second rectangle without any scissoring.
855 | vg.SaveState();
856 | vg.ResetScissor();
857 | vg.BeginPath();
858 | vg.Rect(-20, -10, 60, 30);
859 | vg.FillColor(Utility.FromRGBA(255, 128, 0, 64));
860 | vg.Fill();
861 | vg.RestoreState();
862 |
863 | // Draw second rectangle with combined scissoring.
864 | vg.IntersectScissor(-20, -10, 60, 30);
865 | vg.BeginPath();
866 | vg.Rect(-20, -10, 60, 30);
867 | vg.FillColor(Utility.FromRGBA(255, 128, 0, 255));
868 | vg.Fill();
869 |
870 | vg.RestoreState();
871 | }
872 |
873 | public void renderDemo(NvgContext vg, float mx, float my, float width, float height,
874 | float t, bool blowup)
875 | {
876 | float x, y, popy;
877 |
878 | drawEyes(vg, width - 250, 50, 150, 100, mx, my, t);
879 | drawGraph(vg, 0, height / 2, width, height / 2, t);
880 | drawColorwheel(vg, width - 300, height - 300, 250.0f, 250.0f, t);
881 |
882 | // Line joints
883 | drawLines(vg, 120, height - 50, 600, 50, t);
884 |
885 | // Line caps
886 | drawWidths(vg, 10, 50, 30);
887 |
888 | // Line caps
889 | drawCaps(vg, 10, 300, 30);
890 |
891 | drawScissor(vg, 50, height - 80, t);
892 |
893 | vg.SaveState();
894 | if (blowup)
895 | {
896 | vg.Rotate((float)Math.Sin(t * 0.3f) * 5.0f / 180.0f * (float)Math.PI);
897 | vg.Scale(2.0f, 2.0f);
898 | }
899 |
900 | // Widgets
901 | drawWindow(vg, "Widgets `n Stuff", 50, 50, 300, 400);
902 | x = 60;
903 | y = 95;
904 | drawSearchBox(vg, "Search", x, y, 280, 25);
905 | y += 40;
906 | drawDropDown(vg, "Effects", x, y, 280, 28);
907 | popy = y + 14;
908 | y += 45;
909 |
910 | // Form
911 | drawLabel(vg, "Login", x, y, 280, 20);
912 | y += 25;
913 | drawEditBox(vg, "Email", x, y, 280, 28);
914 | y += 35;
915 | drawEditBox(vg, "Password", x, y, 280, 28);
916 | y += 38;
917 | drawCheckBox(vg, "Remember me", x, y, 140, 28);
918 | drawButton(vg, ICON_LOGIN, "Sign in", x + 138, y, 140, 28, Utility.FromRGBA(0, 96, 128, 255));
919 | y += 45;
920 |
921 | // Slider
922 | drawLabel(vg, "Diameter", x, y, 280, 20);
923 | y += 25;
924 | drawEditBoxNum(vg, "123.00", "px", x + 180, y, 100, 28);
925 | drawSlider(vg, 0.4f, x, y, 170, 28);
926 | y += 55;
927 |
928 | drawButton(vg, ICON_TRASH, "Delete", x, y, 160, 28, Utility.FromRGBA(128, 16, 8, 255));
929 | drawButton(vg, null, "Cancel", x + 170, y, 110, 28, Utility.FromRGBA(0, 0, 0, 0));
930 |
931 | // Thumbnails box
932 | drawThumbnails(vg, 365, popy - 30, 160, 300, images, t);
933 |
934 | vg.RestoreState();
935 | }
936 | }
937 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/Game1.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using Microsoft.Xna.Framework.Input;
4 | using System;
5 | using System.Diagnostics;
6 |
7 | namespace NvgSharp.Samples.XNA
8 | {
9 | ///
10 | /// This is the main type for your game.
11 | ///
12 | public class Game1 : Game
13 | {
14 | GraphicsDeviceManager _graphics;
15 |
16 | private NvgContext _context;
17 | private SpriteBatch _spriteBatch;
18 | private Demo _demo;
19 | private PerfGraph _perfGraph;
20 |
21 | public Game1()
22 | {
23 | _graphics = new GraphicsDeviceManager(this)
24 | {
25 | PreferredBackBufferWidth = 1200,
26 | PreferredBackBufferHeight = 800,
27 | PreferredDepthStencilFormat = DepthFormat.Depth24Stencil8
28 | };
29 |
30 | Content.RootDirectory = "Content";
31 | IsMouseVisible = true;
32 | Window.AllowUserResizing = true;
33 | IsFixedTimeStep = false;
34 | _graphics.SynchronizeWithVerticalRetrace = false;
35 | }
36 |
37 | ///
38 | /// LoadContent will be called once per game and is the place to load
39 | /// all of your content.
40 | ///
41 | protected override void LoadContent()
42 | {
43 | _context = new NvgContext(GraphicsDevice, true);
44 |
45 | _demo = new Demo(_context);
46 |
47 | _spriteBatch = new SpriteBatch(GraphicsDevice);
48 | _perfGraph = new PerfGraph(PerfGraph.Style.GRAPH_RENDER_FPS, "Frame Time", _demo.fontSystemNormal);
49 | }
50 |
51 | ///
52 | /// UnloadContent will be called once per game and is the place to unload
53 | /// game-specific content.
54 | ///
55 | protected override void UnloadContent()
56 | {
57 | // TODO: Unload any non ContentManager content here
58 | }
59 |
60 | protected override void Update(GameTime gameTime)
61 | {
62 | base.Update(gameTime);
63 |
64 | _perfGraph.Update((float)gameTime.ElapsedGameTime.TotalSeconds);
65 |
66 | if (dt == null)
67 | {
68 | dt = DateTime.Now;
69 | }
70 | else if ((DateTime.Now - dt.Value).TotalSeconds >= 1)
71 | {
72 | Trace.WriteLine("FPS: " + 1.0f / _perfGraph.GetAverage());
73 | dt = DateTime.Now;
74 | }
75 | }
76 |
77 | DateTime? dt;
78 |
79 | ///
80 | /// This is called when the game should draw itself.
81 | ///
82 | /// Provides a snapshot of timing values.
83 | protected override void Draw(GameTime gameTime)
84 | {
85 | GraphicsDevice.Clear(new Color(0.3f, 0.3f, 0.3f));
86 |
87 | if (_graphics.PreferredBackBufferWidth != Window.ClientBounds.Width ||
88 | _graphics.PreferredBackBufferHeight != Window.ClientBounds.Height)
89 | {
90 | _graphics.PreferredBackBufferWidth = Window.ClientBounds.Width;
91 | _graphics.PreferredBackBufferHeight = Window.ClientBounds.Height;
92 | _graphics.ApplyChanges();
93 | }
94 |
95 | // TODO: Add your drawing code here
96 |
97 | var mouseState = Mouse.GetState();
98 |
99 | _context.ResetState();
100 |
101 | var t = (float)gameTime.TotalGameTime.TotalSeconds;
102 | _demo.renderDemo(_context,
103 | mouseState.X,
104 | mouseState.Y,
105 | _graphics.PreferredBackBufferWidth,
106 | _graphics.PreferredBackBufferHeight,
107 | t,
108 | false);
109 |
110 | _perfGraph.Render(_context, 5, 5);
111 |
112 | _context.Flush();
113 |
114 | /* var texture = ((XNARenderer)_context._renderer)._textures[8];
115 |
116 | _spriteBatch.Begin();
117 | _spriteBatch.Draw(texture, Vector2.Zero, Color.White);
118 | _spriteBatch.End();*/
119 |
120 | base.Draw(gameTime);
121 | }
122 | }
123 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/Icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/samples/NvgSharp.Samples.Demo/Icon.ico
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/NvgExtensions.cs:
--------------------------------------------------------------------------------
1 | using FontStashSharp;
2 | using System.Text;
3 |
4 | namespace NvgSharp
5 | {
6 | public enum TextHorizontalAlignment
7 | {
8 | ///
9 | /// Default, align text horizontally to left
10 | ///
11 | Left,
12 |
13 | ///
14 | /// Align text horizontally to center
15 | ///
16 | Center,
17 |
18 | ///
19 | /// Align text horizontally to right
20 | ///
21 | Right
22 | }
23 |
24 | public enum TextVerticalAlignment
25 | {
26 | ///
27 | /// Default, Align text vertically to top
28 | ///
29 | Top,
30 |
31 | ///
32 | /// Align text vertically to middle
33 | ///
34 | Center,
35 |
36 | ///
37 | /// Align text vertically to bottom
38 | ///
39 | Bottom
40 | }
41 |
42 | internal static class NvgExtensions
43 | {
44 | public static void TextAligned(this NvgContext context, SpriteFontBase font, string text, float x, float y,
45 | TextHorizontalAlignment horizontalAlignment = TextHorizontalAlignment.Left, TextVerticalAlignment verticalAlignment = TextVerticalAlignment.Top,
46 | float layerDepth = 0.0f, float characterSpacing = 0.0f, float lineSpacing = 0.0f)
47 | {
48 | if (string.IsNullOrEmpty(text))
49 | {
50 | return;
51 | }
52 |
53 | if (horizontalAlignment != TextHorizontalAlignment.Left)
54 | {
55 | var sz = font.MeasureString(text);
56 | if (horizontalAlignment == TextHorizontalAlignment.Center)
57 | {
58 | x -= sz.X / 2.0f;
59 | }
60 | else if (horizontalAlignment == TextHorizontalAlignment.Right)
61 | {
62 | x -= sz.X;
63 | }
64 | }
65 |
66 | if (verticalAlignment == TextVerticalAlignment.Center)
67 | {
68 | y -= font.LineHeight / 2.0f;
69 | }
70 | else if (verticalAlignment == TextVerticalAlignment.Bottom)
71 | {
72 | y -= font.LineHeight;
73 | }
74 |
75 | context.Text(font, text, x, y, layerDepth, characterSpacing, lineSpacing);
76 | }
77 |
78 | public static void TextAligned(this NvgContext context, SpriteFontBase font, StringBuilder text, float x, float y,
79 | TextHorizontalAlignment horizontalAlignment = TextHorizontalAlignment.Left, TextVerticalAlignment verticalAlignment = TextVerticalAlignment.Top,
80 | float layerDepth = 0.0f, float characterSpacing = 0.0f, float lineSpacing = 0.0f)
81 | {
82 | if (text == null || text.Length == 0)
83 | {
84 | return;
85 | }
86 |
87 | if (horizontalAlignment != TextHorizontalAlignment.Left)
88 | {
89 | var sz = font.MeasureString(text);
90 | if (horizontalAlignment == TextHorizontalAlignment.Center)
91 | {
92 | x -= sz.X / 2.0f;
93 | }
94 | else if (horizontalAlignment == TextHorizontalAlignment.Right)
95 | {
96 | x -= sz.X;
97 | }
98 | }
99 |
100 | if (verticalAlignment == TextVerticalAlignment.Center)
101 | {
102 | y -= font.LineHeight / 2.0f;
103 | }
104 | else if (verticalAlignment == TextVerticalAlignment.Bottom)
105 | {
106 | y -= font.LineHeight;
107 | }
108 |
109 | context.Text(font, text, x, y, layerDepth, characterSpacing, lineSpacing);
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/NvgSharp.Samples.Demo.FNA.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net6.0
5 | bin\FNA.Core\$(Configuration)
6 | $(DefineConstants);FNA
7 |
8 |
9 |
10 | PreserveNewest
11 |
12 |
13 | PreserveNewest
14 |
15 |
16 | PreserveNewest
17 |
18 |
19 | PreserveNewest
20 |
21 |
22 | PreserveNewest
23 |
24 |
25 | PreserveNewest
26 |
27 |
28 | PreserveNewest
29 |
30 |
31 | PreserveNewest
32 |
33 |
34 | PreserveNewest
35 |
36 |
37 | PreserveNewest
38 |
39 |
40 | PreserveNewest
41 |
42 |
43 | PreserveNewest
44 |
45 |
46 |
47 |
48 |
49 | PreserveNewest
50 |
51 |
52 | PreserveNewest
53 |
54 |
55 | PreserveNewest
56 |
57 |
58 | PreserveNewest
59 |
60 |
61 | PreserveNewest
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/NvgSharp.Samples.Demo.FNA.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | net461
5 | bin\FNA\$(Configuration)
6 | $(DefineConstants);FNA
7 |
8 |
9 |
10 | PreserveNewest
11 |
12 |
13 | PreserveNewest
14 |
15 |
16 | PreserveNewest
17 |
18 |
19 | PreserveNewest
20 |
21 |
22 | PreserveNewest
23 |
24 |
25 | PreserveNewest
26 |
27 |
28 | PreserveNewest
29 |
30 |
31 | PreserveNewest
32 |
33 |
34 | PreserveNewest
35 |
36 |
37 | PreserveNewest
38 |
39 |
40 | PreserveNewest
41 |
42 |
43 | PreserveNewest
44 |
45 |
46 |
47 |
48 |
49 | PreserveNewest
50 |
51 |
52 | PreserveNewest
53 |
54 |
55 | PreserveNewest
56 |
57 |
58 | PreserveNewest
59 |
60 |
61 | PreserveNewest
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/NvgSharp.Samples.Demo.MonoGame.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | net6.0
5 | bin\MonoGame\$(Configuration)
6 | $(DefineConstants);MONOGAME
7 |
8 |
9 |
10 | PreserveNewest
11 |
12 |
13 | PreserveNewest
14 |
15 |
16 | PreserveNewest
17 |
18 |
19 | PreserveNewest
20 |
21 |
22 | PreserveNewest
23 |
24 |
25 | PreserveNewest
26 |
27 |
28 | PreserveNewest
29 |
30 |
31 | PreserveNewest
32 |
33 |
34 | PreserveNewest
35 |
36 |
37 | PreserveNewest
38 |
39 |
40 | PreserveNewest
41 |
42 |
43 | PreserveNewest
44 |
45 |
46 |
47 |
48 |
49 | PreserveNewest
50 |
51 |
52 | PreserveNewest
53 |
54 |
55 | PreserveNewest
56 |
57 |
58 | PreserveNewest
59 |
60 |
61 | PreserveNewest
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/PerfGraph.cs:
--------------------------------------------------------------------------------
1 | using FontStashSharp;
2 |
3 | #if MONOGAME || FNA
4 | using Microsoft.Xna.Framework;
5 | #elif STRIDE
6 | using Stride.Core.Mathematics;
7 | #else
8 | using System.Drawing;
9 | using Texture2D = System.Object;
10 | #endif
11 |
12 | namespace NvgSharp.Samples
13 | {
14 | public class PerfGraph
15 | {
16 | public enum Style
17 | {
18 | GRAPH_RENDER_FPS,
19 | GRAPH_RENDER_MS,
20 | GRAPH_RENDER_PERCENT,
21 | };
22 |
23 | private Style _style;
24 | private string _name;
25 | private float[] _values = new float[100];
26 | private int _head;
27 | private readonly FontSystem _fontSystem;
28 |
29 | public PerfGraph(Style style, string name, FontSystem fontSystem)
30 | {
31 | _style = style;
32 | _name = name;
33 | _fontSystem = fontSystem;
34 | }
35 |
36 | public void Update(float frameTime)
37 | {
38 | _head = (_head + 1) % _values.Length;
39 | _values[_head] = frameTime;
40 | }
41 |
42 | public float GetAverage()
43 | {
44 | float avg = 0;
45 | for (var i = 0; i < _values.Length; i++)
46 | {
47 | avg += _values[i];
48 | }
49 | return avg / _values.Length;
50 | }
51 |
52 | public void Render(NvgContext vg, float x, float y)
53 | {
54 | int i;
55 | float avg, w, h;
56 | string str;
57 |
58 | avg = GetAverage();
59 |
60 | w = 200;
61 | h = 35;
62 |
63 | vg.BeginPath();
64 | vg.Rect(x, y, w, h);
65 | vg.FillColor(Utility.FromRGBA(0, 0, 0, 128));
66 | vg.Fill();
67 |
68 | vg.BeginPath();
69 | vg.MoveTo(x, y + h);
70 | if (_style == Style.GRAPH_RENDER_FPS)
71 | {
72 | for (i = 0; i < _values.Length; i++)
73 | {
74 | float v = 1.0f / (0.00001f + _values[(_head + i) % _values.Length]);
75 | float vx, vy;
76 | if (v > 80.0f)
77 | v = 80.0f;
78 | vx = x + ((float)i / (_values.Length - 1)) * w;
79 | vy = y + h - ((v / 80.0f) * h);
80 | vg.LineTo(vx, vy);
81 | }
82 | }
83 | else if (_style == Style.GRAPH_RENDER_PERCENT)
84 | {
85 | for (i = 0; i < _values.Length; i++)
86 | {
87 | float v = _values[(_head + i) % _values.Length] * 1.0f;
88 | float vx, vy;
89 | if (v > 100.0f)
90 | v = 100.0f;
91 | vx = x + ((float)i / (_values.Length - 1)) * w;
92 | vy = y + h - ((v / 100.0f) * h);
93 | vg.LineTo(vx, vy);
94 | }
95 | }
96 | else
97 | {
98 | for (i = 0; i < _values.Length; i++)
99 | {
100 | float v = _values[(_head + i) % _values.Length] * 1000.0f;
101 | float vx, vy;
102 | if (v > 20.0f)
103 | v = 20.0f;
104 | vx = x + ((float)i / (_values.Length - 1)) * w;
105 | vy = y + h - ((v / 20.0f) * h);
106 | vg.LineTo(vx, vy);
107 | }
108 | }
109 | vg.LineTo(x + w, y + h);
110 | vg.FillColor(Utility.FromRGBA(255, 192, 0, 128));
111 | vg.Fill();
112 |
113 | if (!string.IsNullOrEmpty(_name))
114 | {
115 | var font = _fontSystem.GetFont(14);
116 | vg.FillColor(Utility.FromRGBA(240, 240, 240, 192));
117 | vg.TextAligned(font, _name, x + 3, y + 1, TextHorizontalAlignment.Left, TextVerticalAlignment.Top);
118 | }
119 |
120 | if (_style == Style.GRAPH_RENDER_FPS)
121 | {
122 | var font = _fontSystem.GetFont(18);
123 | vg.FillColor(Utility.FromRGBA(240, 240, 240, 255));
124 | str = string.Format("{0:0.00} FPS", 1.0f / avg);
125 | vg.TextAligned(font, str, x + w - 3, y + 1, TextHorizontalAlignment.Right, TextVerticalAlignment.Top);
126 |
127 | font = _fontSystem.GetFont(15);
128 | vg.FillColor(Utility.FromRGBA(240, 240, 240, 160));
129 | str = string.Format("{0:0.00} ms", avg * 1000.0f);
130 | vg.TextAligned(font, str, x + w - 3, y + h - 1, TextHorizontalAlignment.Right, TextVerticalAlignment.Bottom);
131 | }
132 | else if (_style == Style.GRAPH_RENDER_PERCENT)
133 | {
134 | var font = _fontSystem.GetFont(18);
135 | vg.FillColor(Utility.FromRGBA(240, 240, 240, 255));
136 | str = string.Format("{0:0.00} %%", avg);
137 | vg.TextAligned(font, str, x + w - 3, y + 1, TextHorizontalAlignment.Right, TextVerticalAlignment.Top);
138 | }
139 | else
140 | {
141 | var font = _fontSystem.GetFont(18);
142 | vg.FillColor(Utility.FromRGBA(240, 240, 240, 255));
143 | str = string.Format("{0:0.00} ms", avg * 1000.0f);
144 | vg.TextAligned(font, str, x + w - 3, y + 1, TextHorizontalAlignment.Right, TextVerticalAlignment.Top);
145 | }
146 | }
147 |
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NvgSharp.Samples.XNA
4 | {
5 | ///
6 | /// The main class.
7 | ///
8 | public static class Program
9 | {
10 | ///
11 | /// The main entry point for the application.
12 | ///
13 | [STAThread]
14 | static void Main()
15 | {
16 | using (var game = new Game1())
17 | game.Run();
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Demo/Utility.cs:
--------------------------------------------------------------------------------
1 | #if MONOGAME || FNA
2 | using Microsoft.Xna.Framework;
3 | #elif STRIDE
4 | using Stride.Core.Mathematics;
5 | #else
6 | using System.Drawing;
7 | #endif
8 |
9 | namespace NvgSharp.Samples
10 | {
11 | internal static class Utility
12 | {
13 | public static float Mod(float a, float b)
14 | {
15 | return (float)(a % b);
16 | }
17 |
18 | public static float Clamp(float a, float mn, float mx)
19 | {
20 | return (float)((a) < (mn) ? mn : ((a) > (mx) ? mx : a));
21 | }
22 |
23 | public static float Hue(float h, float m1, float m2)
24 | {
25 | if ((h) < (0))
26 | h += (float)(1);
27 | if ((h) > (1))
28 | h -= (float)(1);
29 | if ((h) < (1.0f / 6.0f))
30 | return (float)(m1 + (m2 - m1) * h * 6.0f);
31 | else if ((h) < (3.0f / 6.0f))
32 | return (float)(m2);
33 | else if ((h) < (4.0f / 6.0f))
34 | return (float)(m1 + (m2 - m1) * (2.0f / 3.0f - h) * 6.0f);
35 | return (float)(m1);
36 | }
37 |
38 | public static Color HSLA(float h, float s, float l, byte a)
39 | {
40 | h = (float)(Mod((float)(h), (float)(1.0f)));
41 | if ((h) < (0.0f))
42 | h += (float)(1.0f);
43 | s = (float)(Clamp((float)(s), (float)(0.0f), (float)(1.0f)));
44 | l = (float)(Clamp((float)(l), (float)(0.0f), (float)(1.0f)));
45 | var m2 = (float)(l <= 0.5f ? (l * (1 + s)) : (l + s - l * s));
46 | var m1 = (float)(2 * l - m2);
47 |
48 | float fr = (float)(Clamp((float)(Hue((float)(h + 1.0f / 3.0f), (float)(m1), (float)(m2))), (float)(0.0f), (float)(1.0f)));
49 | float fg = (float)(Clamp((float)(Hue((float)(h), (float)(m1), (float)(m2))), (float)(0.0f), (float)(1.0f)));
50 | float fb = (float)(Clamp((float)(Hue((float)(h - 1.0f / 3.0f), (float)(m1), (float)(m2))), (float)(0.0f), (float)(1.0f)));
51 | float fa = (float)(a / 255.0f);
52 |
53 | return FromRGBA((byte)(int)(fr * 255), (byte)(int)(fg * 255), (byte)(int)(fb * 255), (byte)(int)(fa * 255));
54 | }
55 |
56 | public static float DegToRad(float deg)
57 | {
58 | return (float)(deg / 180.0f * 3.14159274);
59 | }
60 |
61 | public static float RadToDeg(float rad)
62 | {
63 | return (float)(rad / 3.14159274 * 180.0f);
64 | }
65 |
66 | public static Color FromRGBA(byte r, byte g, byte b, byte a)
67 | {
68 | #if MONOGAME || FNA || STRIDE
69 | return new Color(r, g, b, a);
70 | #else
71 | return Color.FromArgb(a, r, g, b);
72 | #endif
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/BufferObject.cs:
--------------------------------------------------------------------------------
1 | using OpenTK.Graphics.OpenGL4;
2 | using System;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace NvgSharp.Samples
6 | {
7 | public class BufferObject : IDisposable where T : unmanaged
8 | {
9 | private readonly int _handle;
10 | private readonly BufferTarget _bufferType;
11 | private readonly int _size;
12 |
13 | public int Size => _size;
14 |
15 | public unsafe BufferObject(int size, BufferTarget bufferType, bool isDynamic)
16 | {
17 | _bufferType = bufferType;
18 | _size = size;
19 |
20 | _handle = GL.GenBuffer();
21 | GLUtility.CheckError();
22 |
23 | Bind();
24 |
25 | var elementSizeInBytes = Marshal.SizeOf();
26 | GL.BufferData(bufferType, size * elementSizeInBytes, IntPtr.Zero, isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw);
27 | GLUtility.CheckError();
28 | }
29 |
30 | public void Bind()
31 | {
32 | GL.BindBuffer(_bufferType, _handle);
33 | GLUtility.CheckError();
34 | }
35 |
36 | public void Dispose()
37 | {
38 | GL.DeleteBuffer(_handle);
39 | GLUtility.CheckError();
40 | }
41 |
42 | public unsafe void SetData(T[] data, int startIndex, int elementCount)
43 | {
44 | Bind();
45 |
46 | fixed(T* dataPtr = &data[startIndex])
47 | {
48 | var elementSizeInBytes = sizeof(T);
49 |
50 | GL.BufferSubData(_bufferType, IntPtr.Zero, elementCount * elementSizeInBytes, new IntPtr(dataPtr));
51 | GLUtility.CheckError();
52 | }
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/GLUtility.cs:
--------------------------------------------------------------------------------
1 | using OpenTK.Graphics.OpenGL4;
2 | using System;
3 |
4 |
5 | namespace NvgSharp.Samples
6 | {
7 | internal static class GLUtility
8 | {
9 | public static void CheckError()
10 | {
11 | var error = GL.GetError();
12 | if (error != ErrorCode.NoError)
13 | throw new Exception("GL.GetError() returned " + error.ToString());
14 | }
15 |
16 | public static void DrawStroke(this FillStrokeInfo fillStrokeInfo, PrimitiveType primitiveType)
17 | {
18 | if (fillStrokeInfo.StrokeCount <= 0)
19 | {
20 | return;
21 | }
22 |
23 | GL.DrawArrays(primitiveType, fillStrokeInfo.StrokeOffset, fillStrokeInfo.StrokeCount);
24 | CheckError();
25 | }
26 |
27 | public static void DrawFill(this FillStrokeInfo fillStrokeInfo, PrimitiveType primitiveType)
28 | {
29 | if (fillStrokeInfo.FillCount <= 0)
30 | {
31 | return;
32 | }
33 |
34 | GL.DrawArrays(primitiveType, fillStrokeInfo.FillOffset, fillStrokeInfo.FillCount);
35 | CheckError();
36 | }
37 |
38 | public static void DrawTriangles(this CallInfo callInfo, PrimitiveType primitiveType)
39 | {
40 | if (callInfo.TriangleCount <= 0)
41 | {
42 | return;
43 | }
44 |
45 | GL.DrawArrays(primitiveType, callInfo.TriangleOffset, callInfo.TriangleCount);
46 | CheckError();
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/NvgSharp.Samples.OpenTK.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | PreserveNewest
19 |
20 |
21 | PreserveNewest
22 |
23 |
24 | PreserveNewest
25 |
26 |
27 | PreserveNewest
28 |
29 |
30 | PreserveNewest
31 |
32 |
33 | PreserveNewest
34 |
35 |
36 | PreserveNewest
37 |
38 |
39 | PreserveNewest
40 |
41 |
42 | PreserveNewest
43 |
44 |
45 | PreserveNewest
46 |
47 |
48 | PreserveNewest
49 |
50 |
51 | PreserveNewest
52 |
53 |
54 |
55 |
56 |
57 | PreserveNewest
58 |
59 |
60 | PreserveNewest
61 |
62 |
63 | PreserveNewest
64 |
65 |
66 | PreserveNewest
67 |
68 |
69 | PreserveNewest
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | PreserveNewest
82 |
83 |
84 | PreserveNewest
85 |
86 |
87 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/Platform/Renderer.cs:
--------------------------------------------------------------------------------
1 | using OpenTK.Graphics.OpenGL4;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Numerics;
5 |
6 | namespace NvgSharp.Samples
7 | {
8 | internal class Renderer : INvgRenderer
9 | {
10 | private const int MAX_VERTICES = 8192;
11 |
12 | private readonly Shader _shader;
13 | private BufferObject _vertexBuffer;
14 | private readonly VertexArrayObject _vao;
15 | private readonly bool _edgeAntiAlias, _stencilStrokes;
16 | private readonly int[] _viewPortValues = new int[4];
17 |
18 | public bool EdgeAntiAlias => _edgeAntiAlias;
19 |
20 | public unsafe Renderer(bool edgeAntiAlias = true, bool stencilStrokes = true)
21 | {
22 | _edgeAntiAlias = edgeAntiAlias;
23 | _stencilStrokes = stencilStrokes;
24 |
25 | var defines = new Dictionary();
26 | if (edgeAntiAlias)
27 | {
28 | defines["EDGE_AA"] = "1";
29 | }
30 |
31 | _shader = new Shader("shader.vert", "shader.frag", defines);
32 | _vertexBuffer = new BufferObject(MAX_VERTICES, BufferTarget.ArrayBuffer, true);
33 | _vao = new VertexArrayObject(sizeof(Vertex));
34 | }
35 |
36 | ~Renderer() => Dispose(false);
37 |
38 | public void Dispose() => Dispose(true);
39 |
40 | protected virtual void Dispose(bool disposing)
41 | {
42 | if (!disposing)
43 | {
44 | return;
45 | }
46 |
47 | _vao.Dispose();
48 | _vertexBuffer.Dispose();
49 | _shader.Dispose();
50 | }
51 |
52 | public object CreateTexture(int width, int height) => new Texture(width, height);
53 |
54 | public Point GetTextureSize(object texture)
55 | {
56 | var t = (Texture)texture;
57 | return new Point(t.Width, t.Height);
58 | }
59 |
60 | public void SetTextureData(object texture, Rectangle bounds, byte[] data)
61 | {
62 | var t = (Texture)texture;
63 | t.SetData(bounds, data);
64 | }
65 |
66 | private void SetUniform(ref UniformInfo uniform)
67 | {
68 | _shader.SetUniform("scissorMat", uniform.scissorMat);
69 | _shader.SetUniform("paintMat", uniform.paintMat);
70 | _shader.SetUniform("innerCol", uniform.innerCol);
71 | _shader.SetUniform("outerCol", uniform.outerCol);
72 | _shader.SetUniform("scissorExt", uniform.scissorExt);
73 | _shader.SetUniform("scissorScale", uniform.scissorScale);
74 | _shader.SetUniform("extent", uniform.extent);
75 | _shader.SetUniform("radius", uniform.radius);
76 | _shader.SetUniform("feather", uniform.feather);
77 | _shader.SetUniform("type", (int)uniform.type);
78 |
79 | if (uniform.Image != null)
80 | {
81 | var texture = (Texture)uniform.Image;
82 | texture.Bind();
83 | }
84 | else
85 | {
86 | GL.BindTexture(TextureTarget.Texture2D, 0);
87 | GLUtility.CheckError();
88 | }
89 |
90 | if (_edgeAntiAlias)
91 | {
92 | _shader.SetUniform("strokeMult", uniform.strokeMult);
93 | _shader.SetUniform("strokeThr", uniform.strokeThr);
94 | }
95 | }
96 |
97 | private void ProcessFill(CallInfo call)
98 | {
99 | // Draw shapes
100 | GL.Enable(EnableCap.StencilTest);
101 | GLUtility.CheckError();
102 | GL.StencilMask(0xff);
103 | GLUtility.CheckError();
104 | GL.StencilFunc(StencilFunction.Always, 0, 0xff);
105 | GLUtility.CheckError();
106 | GL.ColorMask(false, false, false, false);
107 | GLUtility.CheckError();
108 |
109 | SetUniform(ref call.UniformInfo);
110 |
111 | // set bindpoint for solid loc
112 | GL.StencilOpSeparate(StencilFace.Front, StencilOp.Keep, StencilOp.Keep, StencilOp.IncrWrap);
113 | GLUtility.CheckError();
114 | GL.StencilOpSeparate(StencilFace.Back, StencilOp.Keep, StencilOp.Keep, StencilOp.DecrWrap);
115 | GLUtility.CheckError();
116 |
117 | GL.Disable(EnableCap.CullFace);
118 | GLUtility.CheckError();
119 |
120 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
121 | {
122 | call.FillStrokeInfos[i].DrawFill(PrimitiveType.TriangleFan);
123 | }
124 |
125 | GL.Enable(EnableCap.CullFace);
126 | GLUtility.CheckError();
127 |
128 | // Draw anti-aliased pixels
129 | GL.ColorMask(true, true, true, true);
130 | GLUtility.CheckError();
131 |
132 | SetUniform(ref call.UniformInfo2);
133 |
134 | if (_edgeAntiAlias)
135 | {
136 | GL.StencilFunc(StencilFunction.Equal, 0, 0xff);
137 | GLUtility.CheckError();
138 | GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);
139 | GLUtility.CheckError();
140 |
141 | // Draw fringes
142 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
143 | {
144 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
145 | }
146 | }
147 |
148 | // Draw fill
149 | GL.StencilFunc(StencilFunction.Notequal, 0, 0xff);
150 | GLUtility.CheckError();
151 | GL.StencilOp(StencilOp.Zero, StencilOp.Zero, StencilOp.Zero);
152 | GLUtility.CheckError();
153 |
154 | call.DrawTriangles(PrimitiveType.TriangleStrip);
155 |
156 | GL.Disable(EnableCap.StencilTest);
157 | GLUtility.CheckError();
158 | }
159 |
160 | private void ProcessConvexFill(CallInfo call)
161 | {
162 | SetUniform(ref call.UniformInfo);
163 |
164 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
165 | {
166 | var fillStrokeInfo = call.FillStrokeInfos[i];
167 |
168 | fillStrokeInfo.DrawFill(PrimitiveType.TriangleFan);
169 | fillStrokeInfo.DrawStroke(PrimitiveType.TriangleStrip);
170 | }
171 | }
172 |
173 | private void ProcessStroke(CallInfo call)
174 | {
175 | if (_stencilStrokes)
176 | {
177 | // Fill the stroke base without overlap
178 | GL.Enable(EnableCap.StencilTest);
179 | GLUtility.CheckError();
180 | GL.StencilMask(0xff);
181 | GLUtility.CheckError();
182 | GL.StencilFunc(StencilFunction.Equal, 0, 0xff);
183 | GLUtility.CheckError();
184 | GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Incr);
185 | GLUtility.CheckError();
186 |
187 | SetUniform(ref call.UniformInfo2);
188 |
189 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
190 | {
191 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
192 | }
193 |
194 | // Draw anti-aliased pixels.
195 | SetUniform(ref call.UniformInfo);
196 |
197 | GL.StencilFunc(StencilFunction.Equal, 0, 0xff);
198 | GLUtility.CheckError();
199 | GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);
200 | GLUtility.CheckError();
201 |
202 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
203 | {
204 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
205 | }
206 |
207 | // Clear stencil buffer.
208 | GL.ColorMask(false, false, false, false);
209 | GLUtility.CheckError();
210 |
211 | GL.StencilFunc(StencilFunction.Always, 0, 0xff);
212 | GLUtility.CheckError();
213 | GL.StencilOp(StencilOp.Zero, StencilOp.Zero, StencilOp.Zero);
214 | GLUtility.CheckError();
215 |
216 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
217 | {
218 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
219 | }
220 |
221 | GL.ColorMask(true, true, true, true);
222 | GLUtility.CheckError();
223 |
224 | GL.Disable(EnableCap.StencilTest);
225 | GLUtility.CheckError();
226 | }
227 | else
228 | {
229 | SetUniform(ref call.UniformInfo);
230 |
231 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
232 | {
233 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
234 | }
235 | }
236 | }
237 |
238 | private void ProcessTriangles(CallInfo call)
239 | {
240 | SetUniform(ref call.UniformInfo);
241 |
242 | call.DrawTriangles(PrimitiveType.Triangles);
243 | }
244 |
245 | public void Draw(float devicePixelRatio, IEnumerable calls, Vertex[] vertexes)
246 | {
247 | // Setup required GL state
248 | GL.Enable(EnableCap.CullFace);
249 | GLUtility.CheckError();
250 | GL.CullFace(CullFaceMode.Back);
251 | GLUtility.CheckError();
252 | GL.FrontFace(FrontFaceDirection.Ccw);
253 | GLUtility.CheckError();
254 | GL.Enable(EnableCap.Blend);
255 | GLUtility.CheckError();
256 | GL.Disable(EnableCap.DepthTest);
257 | GLUtility.CheckError();
258 | GL.Disable(EnableCap.ScissorTest);
259 | GLUtility.CheckError();
260 | GL.ColorMask(true, true, true, true);
261 | GLUtility.CheckError();
262 | GL.StencilMask(0xffffffff);
263 | GLUtility.CheckError();
264 | GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);
265 | GLUtility.CheckError();
266 | GL.StencilFunc(StencilFunction.Always, 0, 0xffffffff);
267 | GLUtility.CheckError();
268 | GL.ActiveTexture(TextureUnit.Texture0);
269 | GLUtility.CheckError();
270 | GL.BindTexture(TextureTarget.Texture2D, 0);
271 | GLUtility.CheckError();
272 |
273 | // Bind and update vertex buffer
274 | if (_vertexBuffer.Size < vertexes.Length)
275 | {
276 | _vertexBuffer = new BufferObject(vertexes.Length, BufferTarget.ArrayBuffer, true);
277 | }
278 |
279 | _vertexBuffer.Bind();
280 | _vertexBuffer.SetData(vertexes, 0, vertexes.Length);
281 |
282 | // Setup vao
283 | _vao.Bind();
284 | var location = _shader.GetAttribLocation("vertex");
285 | _vao.VertexAttribPointer(location, 2, VertexAttribPointerType.Float, false, 0);
286 |
287 | location = _shader.GetAttribLocation("tcoord");
288 | _vao.VertexAttribPointer(location, 2, VertexAttribPointerType.Float, false, 8);
289 |
290 | // Setup shader
291 | _shader.Use();
292 | _shader.SetUniform("tex", 0);
293 |
294 | GL.GetInteger(GetPName.Viewport, _viewPortValues);
295 | GLUtility.CheckError();
296 |
297 | var transform = Matrix4x4.CreateOrthographicOffCenter(0, _viewPortValues[2], _viewPortValues[3], 0, 0, -1);
298 | _shader.SetUniform("transformMat", transform);
299 |
300 | GL.BlendFunc(BlendingFactor.One, BlendingFactor.OneMinusSrcAlpha);
301 | GLUtility.CheckError();
302 |
303 | // Process calls
304 | foreach (var call in calls)
305 | {
306 | switch (call.Type)
307 | {
308 | case CallType.Fill:
309 | ProcessFill(call);
310 | break;
311 | case CallType.ConvexFill:
312 | ProcessConvexFill(call);
313 | break;
314 | case CallType.Stroke:
315 | ProcessStroke(call);
316 | break;
317 | case CallType.Triangles:
318 | ProcessTriangles(call);
319 | break;
320 | }
321 | }
322 | }
323 | }
324 | }
325 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/Program.cs:
--------------------------------------------------------------------------------
1 | using OpenTK.Mathematics;
2 | using OpenTK.Windowing.Common;
3 | using OpenTK.Windowing.Desktop;
4 |
5 | namespace NvgSharp.Samples
6 | {
7 | class Program
8 | {
9 | private static void Main(string[] args)
10 | {
11 | var nativeWindowSettings = new NativeWindowSettings()
12 | {
13 | Size = new Vector2i(1200, 800),
14 | Title = "NvgSharp.Samples.OpenTK",
15 | // This is needed to run on macos
16 | Flags = ContextFlags.ForwardCompatible,
17 | };
18 |
19 | using (var window = new Window(GameWindowSettings.Default, nativeWindowSettings))
20 | {
21 | window.Run();
22 | }
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/Shader.cs:
--------------------------------------------------------------------------------
1 | using OpenTK.Graphics.OpenGL4;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Numerics;
6 | using System.Text;
7 |
8 | namespace NvgSharp.Samples
9 | {
10 | public class Shader : IDisposable
11 | {
12 | private int _handle;
13 |
14 | public Shader(string vertexPath, string fragmentPath, Dictionary defines)
15 | {
16 | int vertex = LoadShader(ShaderType.VertexShader, vertexPath, defines);
17 | int fragment = LoadShader(ShaderType.FragmentShader, fragmentPath, defines);
18 | _handle = GL.CreateProgram();
19 | GLUtility.CheckError();
20 |
21 | GL.AttachShader(_handle, vertex);
22 | GLUtility.CheckError();
23 |
24 | GL.AttachShader(_handle, fragment);
25 | GLUtility.CheckError();
26 |
27 | GL.LinkProgram(_handle);
28 | GL.GetProgram(_handle, GetProgramParameterName.LinkStatus, out var status);
29 | if (status == 0)
30 | {
31 | throw new Exception($"Program failed to link with error: {GL.GetProgramInfoLog(_handle)}");
32 | }
33 |
34 | GL.DetachShader(_handle, vertex);
35 | GL.DetachShader(_handle, fragment);
36 |
37 | GL.DeleteShader(vertex);
38 | GL.DeleteShader(fragment);
39 | }
40 |
41 | public void Use()
42 | {
43 | GL.UseProgram(_handle);
44 | GLUtility.CheckError();
45 | }
46 |
47 | public void SetUniform(string name, int value)
48 | {
49 | int location = GL.GetUniformLocation(_handle, name);
50 | if (location == -1)
51 | {
52 | throw new Exception($"{name} uniform not found on shader.");
53 | }
54 | GL.Uniform1(location, value);
55 | GLUtility.CheckError();
56 | }
57 |
58 | public void SetUniform(string name, float value)
59 | {
60 | int location = GL.GetUniformLocation(_handle, name);
61 | if (location == -1)
62 | {
63 | throw new Exception($"{name} uniform not found on shader.");
64 | }
65 | GL.Uniform1(location, value);
66 | GLUtility.CheckError();
67 | }
68 |
69 | public void SetUniform(string name, Vector2 value)
70 | {
71 | int location = GL.GetUniformLocation(_handle, name);
72 | if (location == -1)
73 | {
74 | throw new Exception($"{name} uniform not found on shader.");
75 | }
76 | GL.Uniform2(location, value.X, value.Y);
77 | GLUtility.CheckError();
78 | }
79 |
80 | public void SetUniform(string name, Vector4 value)
81 | {
82 | int location = GL.GetUniformLocation(_handle, name);
83 | if (location == -1)
84 | {
85 | throw new Exception($"{name} uniform not found on shader.");
86 | }
87 | GL.Uniform4(location, value.X, value.Y, value.Z, value.W);
88 | GLUtility.CheckError();
89 | }
90 |
91 | public unsafe void SetUniform(string name, Matrix4x4 value)
92 | {
93 | int location = GL.GetUniformLocation(_handle, name);
94 | if (location == -1)
95 | {
96 | throw new Exception($"{name} uniform not found on shader.");
97 | }
98 |
99 | GL.UniformMatrix4(location, 1, false, (float*)&value);
100 | GLUtility.CheckError();
101 | }
102 |
103 | public void Dispose()
104 | {
105 | GL.DeleteProgram(_handle);
106 | }
107 |
108 | private int LoadShader(ShaderType type, string path, Dictionary defines)
109 | {
110 | var sb = new StringBuilder();
111 |
112 | if (defines != null)
113 | {
114 | foreach(var pair in defines)
115 | {
116 | sb.Append("#define " + pair.Key + " " + pair.Value + "\n");
117 | }
118 | }
119 |
120 | string src = File.ReadAllText(path);
121 | sb.Append(src);
122 |
123 | int handle = GL.CreateShader(type);
124 | GLUtility.CheckError();
125 |
126 | GL.ShaderSource(handle, sb.ToString());
127 | GLUtility.CheckError();
128 |
129 | GL.CompileShader(handle);
130 | string infoLog = GL.GetShaderInfoLog(handle);
131 | if (!string.IsNullOrWhiteSpace(infoLog))
132 | {
133 | throw new Exception($"Error compiling shader of type {type}, failed with error {infoLog}");
134 | }
135 |
136 | return handle;
137 | }
138 |
139 | public int GetAttribLocation(string attribName)
140 | {
141 | var result = GL.GetAttribLocation(_handle, attribName);
142 | GLUtility.CheckError();
143 | return result;
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/Texture.cs:
--------------------------------------------------------------------------------
1 | using OpenTK.Graphics.OpenGL4;
2 | using System;
3 | using System.Drawing;
4 |
5 | namespace NvgSharp.Samples
6 | {
7 | public unsafe class Texture : IDisposable
8 | {
9 | private readonly int _handle;
10 |
11 | public readonly int Width;
12 | public readonly int Height;
13 |
14 | public Texture(int width, int height)
15 | {
16 | Width = width;
17 | Height = height;
18 |
19 | _handle = GL.GenTexture();
20 | GLUtility.CheckError();
21 | Bind();
22 |
23 | //Reserve enough memory from the gpu for the whole image
24 | GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, width, height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
25 | GLUtility.CheckError();
26 |
27 | SetParameters();
28 | }
29 |
30 | private void SetParameters()
31 | {
32 | //Setting some texture perameters so the texture behaves as expected.
33 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
34 | GLUtility.CheckError();
35 |
36 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
37 | GLUtility.CheckError();
38 |
39 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
40 | GLUtility.CheckError();
41 |
42 | GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMinFilter.Linear);
43 | GLUtility.CheckError();
44 |
45 | //Generating mipmaps.
46 | GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
47 | GLUtility.CheckError();
48 | }
49 |
50 | public void Bind(TextureUnit textureSlot = TextureUnit.Texture0)
51 | {
52 | //When we bind a texture we can choose which textureslot we can bind it to.
53 | GL.ActiveTexture(textureSlot);
54 | GLUtility.CheckError();
55 |
56 | GL.BindTexture(TextureTarget.Texture2D, _handle);
57 | GLUtility.CheckError();
58 | }
59 |
60 | public void Dispose()
61 | {
62 | //In order to dispose we need to delete the opengl handle for the texure.
63 | GL.DeleteTexture(_handle);
64 | GLUtility.CheckError();
65 | }
66 |
67 | public void SetData(Rectangle bounds, byte[] data)
68 | {
69 | Bind();
70 | fixed (byte* ptr = data)
71 | {
72 | GL.TexSubImage2D(
73 | target: TextureTarget.Texture2D,
74 | level: 0,
75 | xoffset: bounds.Left,
76 | yoffset: bounds.Top,
77 | width: bounds.Width,
78 | height: bounds.Height,
79 | format: PixelFormat.Rgba,
80 | type: PixelType.UnsignedByte,
81 | pixels: new IntPtr(ptr)
82 | );
83 | GLUtility.CheckError();
84 | }
85 | }
86 | }
87 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/VertexArrayObject.cs:
--------------------------------------------------------------------------------
1 | using OpenTK.Graphics.OpenGL4;
2 | using System;
3 |
4 | namespace NvgSharp.Samples
5 | {
6 | public class VertexArrayObject: IDisposable
7 | {
8 | private readonly uint _handle;
9 | private readonly int _stride;
10 |
11 | public VertexArrayObject(int stride)
12 | {
13 | if (stride <= 0)
14 | {
15 | throw new ArgumentOutOfRangeException(nameof(stride));
16 | }
17 |
18 | _stride = stride;
19 |
20 | GL.GenVertexArrays(1, out _handle);
21 | GLUtility.CheckError();
22 | }
23 |
24 | public void Dispose()
25 | {
26 | GL.DeleteVertexArray(_handle);
27 | GLUtility.CheckError();
28 | }
29 |
30 | public void Bind()
31 | {
32 | GL.BindVertexArray(_handle);
33 | GLUtility.CheckError();
34 | }
35 |
36 | public unsafe void VertexAttribPointer(int location, int size, VertexAttribPointerType type, bool normalized, int offset)
37 | {
38 | GL.EnableVertexAttribArray(location);
39 | GLUtility.CheckError();
40 | GL.VertexAttribPointer(location, size, type, normalized, _stride, new IntPtr(offset));
41 | GLUtility.CheckError();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/Window.cs:
--------------------------------------------------------------------------------
1 | using OpenTK.Graphics.OpenGL4;
2 | using OpenTK.Windowing.Common;
3 | using OpenTK.Windowing.Desktop;
4 | using System;
5 | using System.Diagnostics;
6 |
7 | namespace NvgSharp.Samples
8 | {
9 | internal class Window : GameWindow
10 | {
11 | private Renderer _renderer;
12 | private NvgContext nvgContext;
13 | private PerfGraph _perfGraph;
14 | private Demo demo;
15 | private Stopwatch gameTimer;
16 | private long startTicks;
17 | private long previousTicks;
18 |
19 | public Window(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings)
20 | : base(gameWindowSettings, nativeWindowSettings)
21 | {
22 | gameTimer = Stopwatch.StartNew();
23 | startTicks = gameTimer.Elapsed.Ticks;
24 | }
25 |
26 | protected override void OnLoad()
27 | {
28 | base.OnLoad();
29 |
30 | var renderer = new Renderer(true, true);
31 | nvgContext = new NvgContext(renderer, renderer.EdgeAntiAlias);
32 |
33 | demo = new Demo(nvgContext);
34 | _perfGraph = new PerfGraph(PerfGraph.Style.GRAPH_RENDER_FPS, "Frame Time", demo.fontSystemNormal);
35 | }
36 |
37 | protected override void OnRenderFrame(FrameEventArgs args)
38 | {
39 | base.OnRenderFrame(args);
40 |
41 | GL.ClearColor(0.3f, 0.3f, 0.32f, 1.0f);
42 | GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);
43 |
44 |
45 | nvgContext.ResetState();
46 |
47 | long currentTicks = gameTimer.Elapsed.Ticks;
48 |
49 | var elapsedTime = (float)TimeSpan.FromTicks(currentTicks - previousTicks).TotalSeconds;
50 | _perfGraph.Update(elapsedTime);
51 |
52 | previousTicks = currentTicks;
53 |
54 | var totalElapsedTime = (float)TimeSpan.FromTicks(currentTicks - startTicks).TotalSeconds;
55 |
56 | demo.renderDemo(nvgContext, MousePosition.X, MousePosition.Y, Size.X, Size.Y, totalElapsedTime, false);
57 | _perfGraph.Render(nvgContext, 5, 5);
58 |
59 | nvgContext.Flush();
60 |
61 | SwapBuffers();
62 | }
63 |
64 | protected override void OnResize(ResizeEventArgs e)
65 | {
66 | base.OnResize(e);
67 |
68 | GL.Viewport(0, 0, Size.X, Size.Y);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/shader.frag:
--------------------------------------------------------------------------------
1 | #ifdef GL_ES
2 | #define LOWP lowp
3 | precision mediump float;
4 | #else
5 | #define LOWP
6 | #endif
7 |
8 | // Uniforms
9 | uniform sampler2D tex;
10 | uniform mat4 scissorMat;
11 | uniform mat4 paintMat;
12 | uniform vec4 innerCol;
13 | uniform vec4 outerCol;
14 | uniform vec2 scissorExt;
15 | uniform vec2 scissorScale;
16 | uniform vec2 extent;
17 | uniform float radius;
18 | uniform float feather;
19 | uniform float strokeMult;
20 | uniform float strokeThr;
21 | uniform int type;
22 |
23 | // Varyings
24 | varying vec2 fpos;
25 | varying vec2 ftcoord;
26 |
27 | float sdroundrect(vec2 pt, vec2 ext, float rad) {
28 | vec2 ext2 = ext - vec2(rad,rad);
29 | vec2 d = abs(pt) - ext2;
30 | return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;
31 | }
32 |
33 | // Scissoring
34 | float scissorMask(vec2 p) {
35 | vec2 sc = (abs((scissorMat * vec4(p,0,1)).xy) - scissorExt);
36 | sc = vec2(0.5,0.5) - sc * scissorScale;
37 | return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);
38 | }
39 | #ifdef EDGE_AA
40 | // Stroke - from [0..1] to clipped pyramid, where the slope is 1px.
41 | float strokeMask() {
42 | return min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * min(1.0, ftcoord.y);
43 | }
44 | #endif
45 |
46 | void main(void) {
47 | vec4 result;
48 | float scissor = scissorMask(fpos);
49 | #ifdef EDGE_AA
50 | float strokeAlpha = strokeMask();
51 | if (strokeAlpha < strokeThr) discard;
52 | #else
53 | float strokeAlpha = 1.0;
54 | #endif
55 | if (type == 0) {
56 | // Gradient
57 | // Calculate gradient color using box gradient
58 | vec2 pt = (paintMat * vec4(fpos,0,1)).xy;
59 | float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);
60 | vec4 color = mix(innerCol,outerCol,d);
61 |
62 | // Combine alpha
63 | color *= strokeAlpha * scissor;
64 | result = color;
65 | } else if (type == 1) {
66 | // Image
67 | // Calculate color fron texture
68 | vec2 pt = (paintMat * vec4(fpos,0,1)).xy / extent;
69 | vec4 color = texture2D(tex, pt);
70 | color = vec4(color.xyz*color.w,color.w);
71 |
72 | // Apply color tint and alpha.
73 | color *= innerCol;
74 | // Combine alpha
75 | color *= strokeAlpha * scissor;
76 | result = color;
77 | } else if (type == 2) {
78 | // Stencil fill
79 | result = vec4(1,1,1,1);
80 | } else if (type == 3) {
81 | // Textured tris
82 | vec4 color = texture2D(tex, ftcoord);
83 | color *= scissor;
84 | result = color * innerCol;
85 | }
86 |
87 | gl_FragColor = result;
88 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.OpenTK/shader.vert:
--------------------------------------------------------------------------------
1 | // Attributes
2 | attribute vec2 vertex;
3 | attribute vec2 tcoord;
4 |
5 | // Uniforms
6 | uniform mat4 transformMat;
7 |
8 | // Varyings
9 | varying vec2 fpos;
10 | varying vec2 ftcoord;
11 |
12 | void main()
13 | {
14 | ftcoord = tcoord;
15 | fpos = vertex;
16 | gl_Position = transformMat * vec4(vertex, 0, 1);
17 | }
18 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/BufferObject.cs:
--------------------------------------------------------------------------------
1 | using Silk.NET.OpenGL;
2 | using System;
3 | using System.Runtime.InteropServices;
4 |
5 | namespace NvgSharp.Samples
6 | {
7 | public class BufferObject : IDisposable where T : unmanaged
8 | {
9 | private readonly uint _handle;
10 | private readonly BufferTargetARB _bufferType;
11 | private readonly int _size;
12 |
13 | public int Size => _size;
14 |
15 | public unsafe BufferObject(int size, BufferTargetARB bufferType, bool isDynamic)
16 | {
17 | _bufferType = bufferType;
18 | _size = size;
19 |
20 | _handle = Env.Gl.GenBuffer();
21 | GLUtility.CheckError();
22 |
23 | Bind();
24 |
25 | var elementSizeInBytes = Marshal.SizeOf();
26 | Env.Gl.BufferData(bufferType, (nuint)(size * elementSizeInBytes), null, isDynamic ? BufferUsageARB.StreamDraw : BufferUsageARB.StaticDraw);
27 | GLUtility.CheckError();
28 | }
29 |
30 | public void Bind()
31 | {
32 | Env.Gl.BindBuffer(_bufferType, _handle);
33 | GLUtility.CheckError();
34 | }
35 |
36 | public void Dispose()
37 | {
38 | Env.Gl.DeleteBuffer(_handle);
39 | GLUtility.CheckError();
40 | }
41 |
42 | public unsafe void SetData(T[] data, int startIndex, int elementCount)
43 | {
44 | Bind();
45 |
46 | fixed(T* dataPtr = &data[startIndex])
47 | {
48 | var elementSizeInBytes = sizeof(T);
49 |
50 | Env.Gl.BufferSubData(_bufferType, 0, (nuint)(elementCount * elementSizeInBytes), dataPtr);
51 | GLUtility.CheckError();
52 | }
53 | }
54 | }
55 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/Env.cs:
--------------------------------------------------------------------------------
1 | using Silk.NET.OpenGL;
2 |
3 | namespace NvgSharp.Samples
4 | {
5 | internal static class Env
6 | {
7 | public static GL Gl;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/GLUtility.cs:
--------------------------------------------------------------------------------
1 | using Silk.NET.OpenGL;
2 | using System;
3 | using System.Drawing;
4 | using System.Numerics;
5 |
6 |
7 | namespace NvgSharp.Samples
8 | {
9 | internal static class GLUtility
10 | {
11 | public static void CheckError()
12 | {
13 | var error = (ErrorCode)Env.Gl.GetError();
14 | if (error != ErrorCode.NoError)
15 | throw new Exception("GL.GetError() returned " + error.ToString());
16 | }
17 |
18 | public static Matrix4x4 ToMatrix4x4(this Transform t)
19 | {
20 | var result = Matrix4x4.Identity;
21 |
22 | result.M11 = t.T1;
23 | result.M12 = t.T2;
24 | result.M13 = 0f;
25 | result.M14 = 0f;
26 | result.M21 = t.T3;
27 | result.M22 = t.T4;
28 | result.M23 = 0f;
29 | result.M24 = 0f;
30 | result.M31 = 0f;
31 | result.M32 = 0f;
32 | result.M33 = 1f;
33 | result.M34 = 0f;
34 | result.M41 = t.T5;
35 | result.M42 = t.T6;
36 | result.M43 = 0f;
37 | result.M44 = 1f;
38 |
39 | return result;
40 | }
41 |
42 | public static void MakeZero(this Matrix4x4 m)
43 | {
44 | m.M11 = m.M12 = m.M13 = m.M14 = 0;
45 | m.M21 = m.M22 = m.M23 = m.M24 = 0;
46 | m.M31 = m.M32 = m.M33 = m.M34 = 0;
47 | m.M41 = m.M42 = m.M43 = m.M44 = 0;
48 | }
49 |
50 |
51 | public static void DrawStroke(this FillStrokeInfo fillStrokeInfo, PrimitiveType primitiveType)
52 | {
53 | if (fillStrokeInfo.StrokeCount <= 0)
54 | {
55 | return;
56 | }
57 |
58 | Env.Gl.DrawArrays(primitiveType, fillStrokeInfo.StrokeOffset, (uint)fillStrokeInfo.StrokeCount);
59 | CheckError();
60 | }
61 |
62 | public static void DrawFill(this FillStrokeInfo fillStrokeInfo, PrimitiveType primitiveType)
63 | {
64 | if (fillStrokeInfo.FillCount <= 0)
65 | {
66 | return;
67 | }
68 |
69 | Env.Gl.DrawArrays(primitiveType, fillStrokeInfo.FillOffset, (uint)fillStrokeInfo.FillCount);
70 | CheckError();
71 | }
72 |
73 | public static void DrawTriangles(this CallInfo callInfo, PrimitiveType primitiveType)
74 | {
75 | if (callInfo.TriangleCount <= 0)
76 | {
77 | return;
78 | }
79 |
80 | Env.Gl.DrawArrays(primitiveType, callInfo.TriangleOffset, (uint)callInfo.TriangleCount);
81 | CheckError();
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/NvgSharp.Samples.Silk.NET.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | PreserveNewest
19 |
20 |
21 | PreserveNewest
22 |
23 |
24 | PreserveNewest
25 |
26 |
27 | PreserveNewest
28 |
29 |
30 | PreserveNewest
31 |
32 |
33 | PreserveNewest
34 |
35 |
36 | PreserveNewest
37 |
38 |
39 | PreserveNewest
40 |
41 |
42 | PreserveNewest
43 |
44 |
45 | PreserveNewest
46 |
47 |
48 | PreserveNewest
49 |
50 |
51 | PreserveNewest
52 |
53 |
54 |
55 |
56 |
57 | PreserveNewest
58 |
59 |
60 | PreserveNewest
61 |
62 |
63 | PreserveNewest
64 |
65 |
66 | PreserveNewest
67 |
68 |
69 | PreserveNewest
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 | PreserveNewest
84 |
85 |
86 | PreserveNewest
87 |
88 |
89 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/Platform/Renderer.cs:
--------------------------------------------------------------------------------
1 | using Silk.NET.OpenGL;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.Numerics;
5 |
6 | namespace NvgSharp.Samples
7 | {
8 | internal class Renderer : INvgRenderer
9 | {
10 | private const int MAX_VERTICES = 8192;
11 |
12 | private readonly Shader _shader;
13 | private BufferObject _vertexBuffer;
14 | private readonly VertexArrayObject _vao;
15 | private readonly bool _edgeAntiAlias, _stencilStrokes;
16 | private readonly int[] _viewPortValues = new int[4];
17 |
18 | public bool EdgeAntiAlias => _edgeAntiAlias;
19 |
20 | public unsafe Renderer(bool edgeAntiAlias = true, bool stencilStrokes = true)
21 | {
22 | _edgeAntiAlias = edgeAntiAlias;
23 | _stencilStrokes = stencilStrokes;
24 |
25 | var defines = new Dictionary();
26 | if (edgeAntiAlias)
27 | {
28 | defines["EDGE_AA"] = "1";
29 | }
30 |
31 | _shader = new Shader("shader.vert", "shader.frag", defines);
32 | _vertexBuffer = new BufferObject(MAX_VERTICES, BufferTargetARB.ArrayBuffer, true);
33 | _vao = new VertexArrayObject(sizeof(Vertex));
34 | }
35 |
36 | ~Renderer() => Dispose(false);
37 |
38 | public void Dispose() => Dispose(true);
39 |
40 | protected virtual void Dispose(bool disposing)
41 | {
42 | if (!disposing)
43 | {
44 | return;
45 | }
46 |
47 | _vao.Dispose();
48 | _vertexBuffer.Dispose();
49 | _shader.Dispose();
50 | }
51 |
52 | public object CreateTexture(int width, int height) => new Texture(width, height);
53 |
54 | public Point GetTextureSize(object texture)
55 | {
56 | var t = (Texture)texture;
57 | return new Point(t.Width, t.Height);
58 | }
59 |
60 | public void SetTextureData(object texture, Rectangle bounds, byte[] data)
61 | {
62 | var t = (Texture)texture;
63 | t.SetData(bounds, data);
64 | }
65 |
66 | private void SetUniform(ref UniformInfo uniform)
67 | {
68 | _shader.SetUniform("scissorMat", uniform.scissorMat);
69 | _shader.SetUniform("paintMat", uniform.paintMat);
70 | _shader.SetUniform("innerCol", uniform.innerCol);
71 | _shader.SetUniform("outerCol", uniform.outerCol);
72 | _shader.SetUniform("scissorExt", uniform.scissorExt);
73 | _shader.SetUniform("scissorScale", uniform.scissorScale);
74 | _shader.SetUniform("extent", uniform.extent);
75 | _shader.SetUniform("radius", uniform.radius);
76 | _shader.SetUniform("feather", uniform.feather);
77 | _shader.SetUniform("type", (int)uniform.type);
78 |
79 | if (uniform.Image != null)
80 | {
81 | var texture = (Texture)uniform.Image;
82 | texture.Bind();
83 | }
84 | else
85 | {
86 | Env.Gl.BindTexture(TextureTarget.Texture2D, 0);
87 | GLUtility.CheckError();
88 | }
89 |
90 | if (_edgeAntiAlias)
91 | {
92 | _shader.SetUniform("strokeMult", uniform.strokeMult);
93 | _shader.SetUniform("strokeThr", uniform.strokeThr);
94 | }
95 | }
96 |
97 | private void ProcessFill(CallInfo call)
98 | {
99 | // Draw shapes
100 | Env.Gl.Enable(EnableCap.StencilTest);
101 | GLUtility.CheckError();
102 | Env.Gl.StencilMask(0xff);
103 | GLUtility.CheckError();
104 | Env.Gl.StencilFunc(StencilFunction.Always, 0, 0xff);
105 | GLUtility.CheckError();
106 | Env.Gl.ColorMask(false, false, false, false);
107 | GLUtility.CheckError();
108 |
109 | SetUniform(ref call.UniformInfo);
110 |
111 | // set bindpoint for solid loc
112 | Env.Gl.StencilOpSeparate(StencilFaceDirection.Front, StencilOp.Keep, StencilOp.Keep, StencilOp.IncrWrap);
113 | GLUtility.CheckError();
114 | Env.Gl.StencilOpSeparate(StencilFaceDirection.Back, StencilOp.Keep, StencilOp.Keep, StencilOp.DecrWrap);
115 | GLUtility.CheckError();
116 |
117 | Env.Gl.Disable(EnableCap.CullFace);
118 | GLUtility.CheckError();
119 |
120 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
121 | {
122 | call.FillStrokeInfos[i].DrawFill(PrimitiveType.TriangleFan);
123 | }
124 |
125 | Env.Gl.Enable(EnableCap.CullFace);
126 | GLUtility.CheckError();
127 |
128 | // Draw anti-aliased pixels
129 | Env.Gl.ColorMask(true, true, true, true);
130 | GLUtility.CheckError();
131 |
132 | SetUniform(ref call.UniformInfo2);
133 |
134 | if (_edgeAntiAlias)
135 | {
136 | Env.Gl.StencilFunc(StencilFunction.Equal, 0, 0xff);
137 | GLUtility.CheckError();
138 | Env.Gl.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);
139 | GLUtility.CheckError();
140 |
141 | // Draw fringes
142 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
143 | {
144 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
145 | }
146 | }
147 |
148 | // Draw fill
149 | Env.Gl.StencilFunc(StencilFunction.Notequal, 0, 0xff);
150 | GLUtility.CheckError();
151 | Env.Gl.StencilOp(StencilOp.Zero, StencilOp.Zero, StencilOp.Zero);
152 | GLUtility.CheckError();
153 |
154 | call.DrawTriangles(PrimitiveType.TriangleStrip);
155 |
156 | Env.Gl.Disable(EnableCap.StencilTest);
157 | GLUtility.CheckError();
158 | }
159 |
160 | private void ProcessConvexFill(CallInfo call)
161 | {
162 | SetUniform(ref call.UniformInfo);
163 |
164 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
165 | {
166 | var fillStrokeInfo = call.FillStrokeInfos[i];
167 |
168 | fillStrokeInfo.DrawFill(PrimitiveType.TriangleFan);
169 | fillStrokeInfo.DrawStroke(PrimitiveType.TriangleStrip);
170 | }
171 | }
172 |
173 | private void ProcessStroke(CallInfo call)
174 | {
175 | if (_stencilStrokes)
176 | {
177 | // Fill the stroke base without overlap
178 | Env.Gl.Enable(EnableCap.StencilTest);
179 | GLUtility.CheckError();
180 | Env.Gl.StencilMask(0xff);
181 | GLUtility.CheckError();
182 | Env.Gl.StencilFunc(StencilFunction.Equal, 0, 0xff);
183 | GLUtility.CheckError();
184 | Env.Gl.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Incr);
185 | GLUtility.CheckError();
186 |
187 | SetUniform(ref call.UniformInfo2);
188 |
189 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
190 | {
191 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
192 | }
193 |
194 | // Draw anti-aliased pixels.
195 | SetUniform(ref call.UniformInfo);
196 |
197 | Env.Gl.StencilFunc(StencilFunction.Equal, 0, 0xff);
198 | GLUtility.CheckError();
199 | Env.Gl.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);
200 | GLUtility.CheckError();
201 |
202 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
203 | {
204 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
205 | }
206 |
207 | // Clear stencil buffer.
208 | Env.Gl.ColorMask(false, false, false, false);
209 | GLUtility.CheckError();
210 |
211 | Env.Gl.StencilFunc(StencilFunction.Always, 0, 0xff);
212 | GLUtility.CheckError();
213 | Env.Gl.StencilOp(StencilOp.Zero, StencilOp.Zero, StencilOp.Zero);
214 | GLUtility.CheckError();
215 |
216 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
217 | {
218 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
219 | }
220 |
221 | Env.Gl.ColorMask(true, true, true, true);
222 | GLUtility.CheckError();
223 |
224 | Env.Gl.Disable(EnableCap.StencilTest);
225 | GLUtility.CheckError();
226 | }
227 | else
228 | {
229 | SetUniform(ref call.UniformInfo);
230 |
231 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
232 | {
233 | call.FillStrokeInfos[i].DrawStroke(PrimitiveType.TriangleStrip);
234 | }
235 | }
236 | }
237 |
238 | private void ProcessTriangles(CallInfo call)
239 | {
240 | SetUniform(ref call.UniformInfo);
241 |
242 | call.DrawTriangles(PrimitiveType.Triangles);
243 | }
244 |
245 | public void Draw(float devicePixelRatio, IEnumerable calls, Vertex[] vertexes)
246 | {
247 | // Setup required GL state
248 | Env.Gl.Enable(EnableCap.CullFace);
249 | GLUtility.CheckError();
250 | Env.Gl.CullFace(CullFaceMode.Back);
251 | GLUtility.CheckError();
252 | Env.Gl.FrontFace(FrontFaceDirection.Ccw);
253 | GLUtility.CheckError();
254 | Env.Gl.Enable(EnableCap.Blend);
255 | GLUtility.CheckError();
256 | Env.Gl.Disable(EnableCap.DepthTest);
257 | GLUtility.CheckError();
258 | Env.Gl.Disable(EnableCap.ScissorTest);
259 | GLUtility.CheckError();
260 | Env.Gl.ColorMask(true, true, true, true);
261 | GLUtility.CheckError();
262 | Env.Gl.StencilMask(0xffffffff);
263 | GLUtility.CheckError();
264 | Env.Gl.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);
265 | GLUtility.CheckError();
266 | Env.Gl.StencilFunc(StencilFunction.Always, 0, 0xffffffff);
267 | GLUtility.CheckError();
268 | Env.Gl.ActiveTexture(TextureUnit.Texture0);
269 | GLUtility.CheckError();
270 | Env.Gl.BindTexture(TextureTarget.Texture2D, 0);
271 | GLUtility.CheckError();
272 |
273 | // Bind and update vertex buffer
274 | if (_vertexBuffer.Size < vertexes.Length)
275 | {
276 | _vertexBuffer = new BufferObject(vertexes.Length, BufferTargetARB.ArrayBuffer, true);
277 | }
278 |
279 | _vertexBuffer.Bind();
280 | _vertexBuffer.SetData(vertexes, 0, vertexes.Length);
281 |
282 | // Setup vao
283 | _vao.Bind();
284 | var location = _shader.GetAttribLocation("vertex");
285 | _vao.VertexAttribPointer(location, 2, VertexAttribPointerType.Float, false, 0);
286 |
287 | location = _shader.GetAttribLocation("tcoord");
288 | _vao.VertexAttribPointer(location, 2, VertexAttribPointerType.Float, false, 8);
289 |
290 | // Setup shader
291 | _shader.Use();
292 | _shader.SetUniform("tex", 0);
293 |
294 | unsafe
295 | {
296 | fixed (int* ptr = _viewPortValues)
297 | {
298 | Env.Gl.GetInteger(GLEnum.Viewport, 0, ptr);
299 | }
300 | }
301 | GLUtility.CheckError();
302 |
303 | var transform = Matrix4x4.CreateOrthographicOffCenter(0, _viewPortValues[2], _viewPortValues[3], 0, 0, -1);
304 | _shader.SetUniform("transformMat", transform);
305 |
306 | Env.Gl.BlendFunc(BlendingFactor.One, BlendingFactor.OneMinusSrcAlpha);
307 | GLUtility.CheckError();
308 |
309 | // Process calls
310 | foreach (var call in calls)
311 | {
312 | switch (call.Type)
313 | {
314 | case CallType.Fill:
315 | ProcessFill(call);
316 | break;
317 | case CallType.ConvexFill:
318 | ProcessConvexFill(call);
319 | break;
320 | case CallType.Stroke:
321 | ProcessStroke(call);
322 | break;
323 | case CallType.Triangles:
324 | ProcessTriangles(call);
325 | break;
326 | }
327 | }
328 | }
329 | }
330 | }
331 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/Program.cs:
--------------------------------------------------------------------------------
1 | using Silk.NET.Input;
2 | using Silk.NET.OpenGL;
3 | using Silk.NET.Windowing;
4 | using Silk.NET.Maths;
5 | using System;
6 | using System.Diagnostics;
7 |
8 | namespace NvgSharp.Samples
9 | {
10 | class Program
11 | {
12 | private static IWindow window;
13 | private static IInputContext input;
14 | private static NvgContext nvgContext;
15 | private static PerfGraph _perfGraph;
16 | private static Demo demo;
17 | private static Stopwatch gameTimer;
18 | private static long startTicks;
19 | private static long previousTicks;
20 |
21 | private static void Main(string[] args)
22 | {
23 | gameTimer = Stopwatch.StartNew();
24 | startTicks = gameTimer.Elapsed.Ticks;
25 |
26 | var options = WindowOptions.Default;
27 | options.Size = new Vector2D(1200, 800);
28 | options.PreferredDepthBufferBits = 24;
29 | options.PreferredStencilBufferBits = 8;
30 | options.Title = "FontStashSharp.Silk.NET";
31 | window = Window.Create(options);
32 |
33 | window.Load += OnLoad;
34 | window.Render += OnRender;
35 | window.Closing += OnClose;
36 |
37 | window.Run();
38 | }
39 |
40 | private static void OnLoad()
41 | {
42 | input = window.CreateInput();
43 | for (int i = 0; i < input.Keyboards.Count; i++)
44 | {
45 | input.Keyboards[i].KeyDown += KeyDown;
46 | }
47 |
48 | Env.Gl = GL.GetApi(window);
49 | var renderer = new Renderer(true, true);
50 | nvgContext = new NvgContext(renderer, renderer.EdgeAntiAlias);
51 |
52 | demo = new Demo(nvgContext);
53 | _perfGraph = new PerfGraph(PerfGraph.Style.GRAPH_RENDER_FPS, "Frame Time", demo.fontSystemNormal);
54 | }
55 |
56 | private static unsafe void OnRender(double obj)
57 | {
58 | Env.Gl.ClearColor(0.3f, 0.3f, 0.32f, 1.0f);
59 | Env.Gl.Clear((uint)(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit));
60 |
61 | nvgContext.ResetState();
62 |
63 | long currentTicks = gameTimer.Elapsed.Ticks;
64 |
65 | var elapsedTime = (float)TimeSpan.FromTicks(currentTicks - previousTicks).TotalSeconds;
66 | _perfGraph.Update(elapsedTime);
67 |
68 | previousTicks = currentTicks;
69 |
70 | var totalElapsedTime = (float)TimeSpan.FromTicks(currentTicks - startTicks).TotalSeconds;
71 |
72 | var mousePos = input.Mice[0].Position;
73 | demo.renderDemo(nvgContext, mousePos.X, mousePos.Y, window.Size.X, window.Size.Y, totalElapsedTime, false);
74 | _perfGraph.Render(nvgContext, 5, 5);
75 |
76 | nvgContext.Flush();
77 | }
78 |
79 | private static void OnClose()
80 | {
81 | }
82 |
83 | private static void KeyDown(IKeyboard arg1, Key arg2, int arg3)
84 | {
85 | if (arg2 == Key.Escape)
86 | {
87 | window.Close();
88 | }
89 | }
90 | }
91 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/Shader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Numerics;
5 | using System.Text;
6 | using Silk.NET.OpenGL;
7 |
8 | namespace NvgSharp.Samples
9 | {
10 | public class Shader : IDisposable
11 | {
12 | private uint _handle;
13 |
14 | public Shader(string vertexPath, string fragmentPath, Dictionary defines)
15 | {
16 | uint vertex = LoadShader(ShaderType.VertexShader, vertexPath, defines);
17 | uint fragment = LoadShader(ShaderType.FragmentShader, fragmentPath, defines);
18 | _handle = Env.Gl.CreateProgram();
19 | GLUtility.CheckError();
20 |
21 | Env.Gl.AttachShader(_handle, vertex);
22 | GLUtility.CheckError();
23 |
24 | Env.Gl.AttachShader(_handle, fragment);
25 | GLUtility.CheckError();
26 |
27 | Env.Gl.LinkProgram(_handle);
28 | Env.Gl.GetProgram(_handle, GLEnum.LinkStatus, out var status);
29 | if (status == 0)
30 | {
31 | throw new Exception($"Program failed to link with error: {Env.Gl.GetProgramInfoLog(_handle)}");
32 | }
33 |
34 | Env.Gl.DetachShader(_handle, vertex);
35 | Env.Gl.DetachShader(_handle, fragment);
36 |
37 | Env.Gl.DeleteShader(vertex);
38 | Env.Gl.DeleteShader(fragment);
39 | }
40 |
41 | public void Use()
42 | {
43 | Env.Gl.UseProgram(_handle);
44 | GLUtility.CheckError();
45 | }
46 |
47 | public void SetUniform(string name, int value)
48 | {
49 | int location = Env.Gl.GetUniformLocation(_handle, name);
50 | if (location == -1)
51 | {
52 | throw new Exception($"{name} uniform not found on shader.");
53 | }
54 | Env.Gl.Uniform1(location, value);
55 | GLUtility.CheckError();
56 | }
57 |
58 | public void SetUniform(string name, float value)
59 | {
60 | int location = Env.Gl.GetUniformLocation(_handle, name);
61 | if (location == -1)
62 | {
63 | throw new Exception($"{name} uniform not found on shader.");
64 | }
65 | Env.Gl.Uniform1(location, value);
66 | GLUtility.CheckError();
67 | }
68 |
69 | public void SetUniform(string name, Vector2 value)
70 | {
71 | int location = Env.Gl.GetUniformLocation(_handle, name);
72 | if (location == -1)
73 | {
74 | throw new Exception($"{name} uniform not found on shader.");
75 | }
76 | Env.Gl.Uniform2(location, ref value);
77 | GLUtility.CheckError();
78 | }
79 |
80 | public void SetUniform(string name, Vector4 value)
81 | {
82 | int location = Env.Gl.GetUniformLocation(_handle, name);
83 | if (location == -1)
84 | {
85 | throw new Exception($"{name} uniform not found on shader.");
86 | }
87 | Env.Gl.Uniform4(location, ref value);
88 | GLUtility.CheckError();
89 | }
90 |
91 | public unsafe void SetUniform(string name, Matrix4x4 value)
92 | {
93 | int location = Env.Gl.GetUniformLocation(_handle, name);
94 | if (location == -1)
95 | {
96 | throw new Exception($"{name} uniform not found on shader.");
97 | }
98 |
99 | Env.Gl.UniformMatrix4(location, 1, false, (float*)&value);
100 | GLUtility.CheckError();
101 | }
102 |
103 | public void Dispose()
104 | {
105 | Env.Gl.DeleteProgram(_handle);
106 | }
107 |
108 | private uint LoadShader(ShaderType type, string path, Dictionary defines)
109 | {
110 | var sb = new StringBuilder();
111 |
112 | if (defines != null)
113 | {
114 | foreach(var pair in defines)
115 | {
116 | sb.Append("#define " + pair.Key + " " + pair.Value + "\n");
117 | }
118 | }
119 |
120 | string src = File.ReadAllText(path);
121 | sb.Append(src);
122 |
123 | uint handle = Env.Gl.CreateShader(type);
124 | GLUtility.CheckError();
125 |
126 | Env.Gl.ShaderSource(handle, sb.ToString());
127 | GLUtility.CheckError();
128 |
129 | Env.Gl.CompileShader(handle);
130 | string infoLog = Env.Gl.GetShaderInfoLog(handle);
131 | if (!string.IsNullOrWhiteSpace(infoLog))
132 | {
133 | throw new Exception($"Error compiling shader of type {type}, failed with error {infoLog}");
134 | }
135 |
136 | return handle;
137 | }
138 |
139 | public int GetAttribLocation(string attribName)
140 | {
141 | var result = Env.Gl.GetAttribLocation(_handle, attribName);
142 | GLUtility.CheckError();
143 | return result;
144 | }
145 | }
146 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/Texture.cs:
--------------------------------------------------------------------------------
1 | using Silk.NET.OpenGL;
2 | using StbImageSharp;
3 | using System;
4 | using System.Drawing;
5 |
6 | namespace NvgSharp.Samples
7 | {
8 | public unsafe class Texture : IDisposable
9 | {
10 | private readonly uint _handle;
11 |
12 | public readonly int Width;
13 | public readonly int Height;
14 |
15 | public uint Handle => _handle;
16 |
17 | public Texture(int width, int height)
18 | {
19 | Width = width;
20 | Height = height;
21 |
22 | _handle = Env.Gl.GenTexture();
23 | GLUtility.CheckError();
24 | Bind();
25 |
26 | //Reserve enough memory from the gpu for the whole image
27 | Env.Gl.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgba8, (uint)width, (uint)height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, null);
28 | GLUtility.CheckError();
29 |
30 | SetParameters();
31 | }
32 |
33 | private void SetParameters()
34 | {
35 | //Setting some texture perameters so the texture behaves as expected.
36 | Env.Gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)GLEnum.ClampToEdge);
37 | GLUtility.CheckError();
38 |
39 | Env.Gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)GLEnum.ClampToEdge);
40 | GLUtility.CheckError();
41 |
42 | Env.Gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)GLEnum.Linear);
43 | GLUtility.CheckError();
44 |
45 | Env.Gl.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)GLEnum.Linear);
46 | GLUtility.CheckError();
47 |
48 | //Generating mipmaps.
49 | Env.Gl.GenerateMipmap(TextureTarget.Texture2D);
50 | GLUtility.CheckError();
51 | }
52 |
53 | public void Bind(TextureUnit textureSlot = TextureUnit.Texture0)
54 | {
55 | //When we bind a texture we can choose which textureslot we can bind it to.
56 | Env.Gl.ActiveTexture(textureSlot);
57 | GLUtility.CheckError();
58 |
59 | Env.Gl.BindTexture(TextureTarget.Texture2D, _handle);
60 | GLUtility.CheckError();
61 | }
62 |
63 | public void Dispose()
64 | {
65 | //In order to dispose we need to delete the opengl handle for the texure.
66 | Env.Gl.DeleteTexture(_handle);
67 | GLUtility.CheckError();
68 | }
69 |
70 | public void SetData(Rectangle bounds, byte[] data)
71 | {
72 | Bind();
73 | fixed (byte* ptr = data)
74 | {
75 | Env.Gl.TexSubImage2D(
76 | target: TextureTarget.Texture2D,
77 | level: 0,
78 | xoffset: bounds.Left,
79 | yoffset: bounds.Top,
80 | width: (uint)bounds.Width,
81 | height: (uint)bounds.Height,
82 | format: PixelFormat.Rgba,
83 | type: PixelType.UnsignedByte,
84 | pixels: ptr
85 | );
86 | GLUtility.CheckError();
87 | }
88 | }
89 |
90 | public ImageResult GetData()
91 | {
92 | var result = new ImageResult
93 | {
94 | Width = Width,
95 | Height = Height,
96 | Data = new byte[Width * Height * 4]
97 | };
98 |
99 | fixed (byte* ptr = result.Data)
100 | {
101 | Env.Gl.GetTexImage(
102 | target: TextureTarget.Texture2D,
103 | level: 0,
104 | format: PixelFormat.Rgba,
105 | type: PixelType.UnsignedByte,
106 | ptr);
107 | }
108 |
109 | return result;
110 | }
111 | }
112 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/VertexArrayObject.cs:
--------------------------------------------------------------------------------
1 | using Silk.NET.OpenGL;
2 | using System;
3 |
4 | namespace NvgSharp.Samples
5 | {
6 | public class VertexArrayObject: IDisposable
7 | {
8 | private readonly uint _handle;
9 | private readonly int _stride;
10 |
11 | public VertexArrayObject(int stride)
12 | {
13 | if (stride <= 0)
14 | {
15 | throw new ArgumentOutOfRangeException(nameof(stride));
16 | }
17 |
18 | _stride = stride;
19 |
20 | Env.Gl.GenVertexArrays(1, out _handle);
21 | GLUtility.CheckError();
22 | }
23 |
24 | public void Dispose()
25 | {
26 | Env.Gl.DeleteVertexArray(_handle);
27 | GLUtility.CheckError();
28 | }
29 |
30 | public void Bind()
31 | {
32 | Env.Gl.BindVertexArray(_handle);
33 | GLUtility.CheckError();
34 | }
35 |
36 | public unsafe void VertexAttribPointer(int location, int size, VertexAttribPointerType type, bool normalized, int offset)
37 | {
38 | Env.Gl.EnableVertexAttribArray((uint)location);
39 | GLUtility.CheckError();
40 | Env.Gl.VertexAttribPointer((uint)location, size, type, normalized, (uint)_stride, (void*)offset);
41 | GLUtility.CheckError();
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/shader.frag:
--------------------------------------------------------------------------------
1 | #ifdef GL_ES
2 | #define LOWP lowp
3 | precision mediump float;
4 | #else
5 | #define LOWP
6 | #endif
7 |
8 | // Uniforms
9 | uniform sampler2D tex;
10 | uniform mat4 scissorMat;
11 | uniform mat4 paintMat;
12 | uniform vec4 innerCol;
13 | uniform vec4 outerCol;
14 | uniform vec2 scissorExt;
15 | uniform vec2 scissorScale;
16 | uniform vec2 extent;
17 | uniform float radius;
18 | uniform float feather;
19 | uniform float strokeMult;
20 | uniform float strokeThr;
21 | uniform int type;
22 |
23 | // Varyings
24 | varying vec2 fpos;
25 | varying vec2 ftcoord;
26 |
27 | float sdroundrect(vec2 pt, vec2 ext, float rad) {
28 | vec2 ext2 = ext - vec2(rad,rad);
29 | vec2 d = abs(pt) - ext2;
30 | return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;
31 | }
32 |
33 | // Scissoring
34 | float scissorMask(vec2 p) {
35 | vec2 sc = (abs((scissorMat * vec4(p,0,1)).xy) - scissorExt);
36 | sc = vec2(0.5,0.5) - sc * scissorScale;
37 | return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);
38 | }
39 | #ifdef EDGE_AA
40 | // Stroke - from [0..1] to clipped pyramid, where the slope is 1px.
41 | float strokeMask() {
42 | return min(1.0, (1.0-abs(ftcoord.x*2.0-1.0))*strokeMult) * min(1.0, ftcoord.y);
43 | }
44 | #endif
45 |
46 | void main(void) {
47 | vec4 result;
48 | float scissor = scissorMask(fpos);
49 | #ifdef EDGE_AA
50 | float strokeAlpha = strokeMask();
51 | if (strokeAlpha < strokeThr) discard;
52 | #else
53 | float strokeAlpha = 1.0;
54 | #endif
55 | if (type == 0) {
56 | // Gradient
57 | // Calculate gradient color using box gradient
58 | vec2 pt = (paintMat * vec4(fpos,0,1)).xy;
59 | float d = clamp((sdroundrect(pt, extent, radius) + feather*0.5) / feather, 0.0, 1.0);
60 | vec4 color = mix(innerCol,outerCol,d);
61 |
62 | // Combine alpha
63 | color *= strokeAlpha * scissor;
64 | result = color;
65 | } else if (type == 1) {
66 | // Image
67 | // Calculate color fron texture
68 | vec2 pt = (paintMat * vec4(fpos,0,1)).xy / extent;
69 | vec4 color = texture2D(tex, pt);
70 | color = vec4(color.xyz*color.w,color.w);
71 |
72 | // Apply color tint and alpha.
73 | color *= innerCol;
74 | // Combine alpha
75 | color *= strokeAlpha * scissor;
76 | result = color;
77 | } else if (type == 2) {
78 | // Stencil fill
79 | result = vec4(1,1,1,1);
80 | } else if (type == 3) {
81 | // Textured tris
82 | vec4 color = texture2D(tex, ftcoord);
83 | color *= scissor;
84 | result = color * innerCol;
85 | }
86 |
87 | gl_FragColor = result;
88 | }
--------------------------------------------------------------------------------
/samples/NvgSharp.Samples.Silk.NET/shader.vert:
--------------------------------------------------------------------------------
1 | // Attributes
2 | attribute vec2 vertex;
3 | attribute vec2 tcoord;
4 |
5 | // Uniforms
6 | uniform mat4 transformMat;
7 |
8 | // Varyings
9 | varying vec2 fpos;
10 | varying vec2 ftcoord;
11 |
12 | void main()
13 | {
14 | ftcoord = tcoord;
15 | fpos = vertex;
16 | gl_Position = transformMat * vec4(vertex, 0, 1);
17 | }
18 |
--------------------------------------------------------------------------------
/src/NvgSharp.Text/NvgSharp.Text.FNA.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | NvgSharp.Text.FNA
5 | NvgSharp.Text.FNA
6 | NvgSharp.Text for FNA.Core
7 | $(DefineConstants);FNA
8 | bin\FNA.Core\$(Configuration)
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/NvgSharp.Text/NvgSharp.Text.FNA.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net461
4 | NvgSharp.Text.FNA
5 | NvgSharp.Text.FNA
6 | NvgSharp.Text for FNA
7 | $(DefineConstants);FNA
8 | bin\FNA\$(Configuration)
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/NvgSharp.Text/NvgSharp.Text.MonoGame.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | NvgSharp.Text for MonoGame
5 | $(DefineConstants);MONOGAME
6 | bin\MonoGame\$(Configuration)
7 |
8 |
9 |
10 | true
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/NvgSharp.Text/NvgSharp.Text.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | Platform-Agnostic Version of NvgSharp.Text
5 | $(DefineConstants);PLATFORM_AGNOSTIC
6 |
7 |
8 |
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/NvgSharp.Text/NvgText.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using FontStashSharp;
3 | using FontStashSharp.Interfaces;
4 |
5 | #if MONOGAME || FNA
6 | using Microsoft.Xna.Framework;
7 | using Microsoft.Xna.Framework.Graphics;
8 | #elif STRIDE
9 | using Stride.Core.Mathematics;
10 | #else
11 | using System.Numerics;
12 | using System.Drawing;
13 | using Texture2D = System.Object;
14 | using Color = FontStashSharp.FSColor;
15 | #endif
16 |
17 | namespace NvgSharp
18 | {
19 | public static class NvgText
20 | {
21 | private class TextRenderer : IFontStashRenderer2
22 | #if PLATFORM_AGNOSTIC
23 | , ITexture2DManager
24 | #endif
25 | {
26 | private readonly NvgContext _context;
27 | internal int _lastVertexOffset;
28 | internal Texture2D _lastTextTexture = null;
29 |
30 | #if MONOGAME || FNA || STRIDE
31 | public GraphicsDevice GraphicsDevice => _context.GraphicsDevice;
32 | #else
33 |
34 | public ITexture2DManager TextureManager => this;
35 |
36 | public object CreateTexture(int width, int height) => _context._renderer.CreateTexture(width, height);
37 |
38 | public Point GetTextureSize(object texture) => _context._renderer.GetTextureSize(texture);
39 |
40 | public void SetTextureData(object texture, Rectangle bounds, byte[] data) => _context._renderer.SetTextureData(texture, bounds, data);
41 |
42 | #endif
43 |
44 | public TextRenderer(NvgContext context)
45 | {
46 | _context = context;
47 | }
48 |
49 | public void DrawQuad(Texture2D texture, ref VertexPositionColorTexture topLeft, ref VertexPositionColorTexture topRight,
50 | ref VertexPositionColorTexture bottomLeft, ref VertexPositionColorTexture bottomRight)
51 | {
52 | if (_lastTextTexture != null && _lastTextTexture != texture)
53 | {
54 | FlushText();
55 | }
56 |
57 | var state = _context._currentState;
58 |
59 | float px, py;
60 | state.Transform.TransformPoint(out px, out py, topLeft.Position.X, topLeft.Position.Y);
61 | px = (int)px;
62 | py = (int)py;
63 | var newTopLeft = new Vertex(px, py, topLeft.TextureCoordinate.X, topLeft.TextureCoordinate.Y);
64 |
65 | state.Transform.TransformPoint(out px, out py, topRight.Position.X, topRight.Position.Y);
66 | px = (int)px;
67 | py = (int)py;
68 | var newTopRight = new Vertex(px, py, topRight.TextureCoordinate.X, topRight.TextureCoordinate.Y);
69 |
70 | state.Transform.TransformPoint(out px, out py, bottomRight.Position.X, bottomRight.Position.Y);
71 | px = (int)px;
72 | py = (int)py;
73 | var newBottomRight = new Vertex(px, py, bottomRight.TextureCoordinate.X, bottomRight.TextureCoordinate.Y);
74 |
75 | state.Transform.TransformPoint(out px, out py, bottomLeft.Position.X, bottomLeft.Position.Y);
76 | px = (int)px;
77 | py = (int)py;
78 | var newBottomLeft = new Vertex(px, py, bottomLeft.TextureCoordinate.X, bottomLeft.TextureCoordinate.Y);
79 |
80 | var renderCache = _context._renderCache;
81 | renderCache.AddVertex(newTopLeft);
82 | renderCache.AddVertex(newBottomRight);
83 | renderCache.AddVertex(newTopRight);
84 | renderCache.AddVertex(newTopLeft);
85 | renderCache.AddVertex(newBottomLeft);
86 | renderCache.AddVertex(newBottomRight);
87 |
88 | _lastTextTexture = texture;
89 | }
90 |
91 | private void FlushText()
92 | {
93 | var renderCache = _context._renderCache;
94 | if (_lastTextTexture == null || _lastVertexOffset == renderCache.VertexCount)
95 | {
96 | return;
97 | }
98 |
99 | var state = _context._currentState;
100 | var paint = state.Fill;
101 | paint.Image = _lastTextTexture;
102 |
103 | NvgContext.MultiplyAlpha(ref paint.InnerColor, state.Alpha);
104 | NvgContext.MultiplyAlpha(ref paint.OuterColor, state.Alpha);
105 |
106 | renderCache.RenderTriangles(ref paint, ref state.Scissor, _context._fringeWidth, _lastVertexOffset, renderCache.VertexCount - _lastVertexOffset);
107 |
108 | _lastVertexOffset = renderCache.VertexCount;
109 | _lastTextTexture = null;
110 | }
111 |
112 | public void Text(SpriteFontBase font, TextSource text, float x, float y, float layerDepth, float characterSpacing, float lineSpacing)
113 | {
114 | if (text.IsNull)
115 | {
116 | return;
117 | }
118 |
119 | _lastVertexOffset = _context._renderCache.VertexCount;
120 |
121 | if (text.StringText != null)
122 | {
123 | font.DrawText(this, text.StringText, new Vector2(x, y), Color.White,
124 | layerDepth: layerDepth, characterSpacing: characterSpacing, lineSpacing: lineSpacing);
125 | }
126 | else
127 | {
128 | font.DrawText(this, text.StringBuilderText, new Vector2(x, y), Color.White,
129 | layerDepth: layerDepth, characterSpacing: characterSpacing, lineSpacing: lineSpacing);
130 | }
131 |
132 | FlushText();
133 | }
134 | }
135 | private static void Text(this NvgContext context, SpriteFontBase font, TextSource text, float x, float y,
136 | float layerDepth, float characterSpacing, float lineSpacing)
137 | {
138 | TextRenderer textRenderer;
139 | if (context._textRenderer == null)
140 | {
141 | textRenderer = new TextRenderer(context);
142 | context._textRenderer = textRenderer;
143 | } else {
144 | textRenderer = (TextRenderer)context._textRenderer;
145 | }
146 |
147 | textRenderer.Text(font, text, x, y, layerDepth, characterSpacing, lineSpacing);
148 | }
149 |
150 | public static void Text(this NvgContext context, SpriteFontBase font, string text, float x, float y,
151 | float layerDepth = 0.0f, float characterSpacing = 0.0f, float lineSpacing = 0.0f) =>
152 | Text(context, font, new TextSource(text), x, y, layerDepth, characterSpacing, lineSpacing);
153 |
154 | public static void Text(this NvgContext context, SpriteFontBase font, StringBuilder text, float x, float y,
155 | float layerDepth = 0.0f, float characterSpacing = 0.0f, float lineSpacing = 0.0f) =>
156 | Text(context, font, new TextSource(text), x, y, layerDepth, characterSpacing, lineSpacing);
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/NvgSharp.Text/TextSource.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 |
3 | namespace NvgSharp
4 | {
5 | internal struct TextSource
6 | {
7 | public string StringText;
8 | public StringBuilder StringBuilderText;
9 | private int Position;
10 |
11 | public TextSource(string text)
12 | {
13 | StringText = text;
14 | StringBuilderText = null;
15 | Position = 0;
16 | }
17 |
18 | public TextSource(StringBuilder text)
19 | {
20 | StringText = null;
21 | StringBuilderText = text;
22 | Position = 0;
23 | }
24 |
25 | public bool IsNull => StringText == null && StringBuilderText == null;
26 |
27 | public int Length
28 | {
29 | get
30 | {
31 | if (StringText != null)
32 | {
33 | return StringText.Length;
34 | }
35 |
36 | if (StringBuilderText != null)
37 | {
38 | return StringBuilderText.Length;
39 | }
40 |
41 | return 0;
42 | }
43 | }
44 |
45 | public bool GetNextCodepoint(out int result)
46 | {
47 | result = 0;
48 |
49 | if (StringText != null)
50 | {
51 | if (Position >= StringText.Length)
52 | {
53 | return false;
54 | }
55 |
56 | result = char.ConvertToUtf32(StringText, Position);
57 | Position += char.IsSurrogatePair(StringText, Position) ? 2 : 1;
58 | return true;
59 | }
60 |
61 | if (StringBuilderText != null)
62 | {
63 | if (Position >= StringBuilderText.Length)
64 | {
65 | return false;
66 | }
67 |
68 | result = StringBuilderConvertToUtf32(StringBuilderText, Position);
69 | Position += StringBuilderIsSurrogatePair(StringBuilderText, Position) ? 2 : 1;
70 | return true;
71 | }
72 |
73 | return false;
74 | }
75 |
76 | public void Reset()
77 | {
78 | Position = 0;
79 | }
80 |
81 | private static bool StringBuilderIsSurrogatePair(StringBuilder sb, int index)
82 | {
83 | if (index + 1 < sb.Length)
84 | return char.IsSurrogatePair(sb[index], sb[index + 1]);
85 | return false;
86 | }
87 |
88 | private static int StringBuilderConvertToUtf32(StringBuilder sb, int index)
89 | {
90 | if (!char.IsHighSurrogate(sb[index]))
91 | return sb[index];
92 |
93 | return char.ConvertToUtf32(sb[index], sb[index + 1]);
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/NvgSharp/ArrayBuffer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace NvgSharp
4 | {
5 | internal class ArrayBuffer
6 | {
7 | private T[] _array;
8 | private int _count = 0;
9 |
10 | public T[] Array => _array;
11 |
12 | public int Count => _count;
13 |
14 | public int Capacity => _array.Length;
15 |
16 | public T this[int index]
17 | {
18 | get => _array[index];
19 | set => _array[index] = value;
20 | }
21 |
22 | public T this[ulong index]
23 | {
24 | get => _array[index];
25 | set => _array[index] = value;
26 | }
27 |
28 | public ArrayBuffer(int capacity)
29 | {
30 | _array = new T[capacity];
31 | }
32 |
33 | public void Clear()
34 | {
35 | _count = 0;
36 | }
37 |
38 | public void EnsureSize(int required)
39 | {
40 | if (_array.Length >= required) return;
41 |
42 | // Realloc
43 | var oldData = _array;
44 |
45 | var newSize = _array.Length;
46 | while (newSize < required)
47 | {
48 | newSize *= 2;
49 | }
50 |
51 | _array = new T[newSize];
52 |
53 | System.Array.Copy(oldData, _array, oldData.Length);
54 | }
55 |
56 | public void Add(T item)
57 | {
58 | EnsureSize(_count + 1);
59 |
60 | _array[_count] = item;
61 | ++_count;
62 | }
63 |
64 | public void Add(ArraySegment data)
65 | {
66 | if (data.Count == 0)
67 | {
68 | return;
69 | }
70 |
71 | EnsureSize(_count + data.Count);
72 | System.Array.Copy(data.Array, data.Offset, _array, _count, data.Count);
73 | _count += data.Count;
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/NvgSharp/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | #if MONOGAME
4 | [assembly: InternalsVisibleTo("NvgSharp.Text.MonoGame", AllInternalsVisible = true)]
5 | #elif FNA
6 | [assembly: InternalsVisibleTo("NvgSharp.Text.FNA", AllInternalsVisible = true)]
7 | #else
8 | [assembly: InternalsVisibleTo("NvgSharp.Text", AllInternalsVisible = true)]
9 | #endif
10 |
--------------------------------------------------------------------------------
/src/NvgSharp/Bounds.cs:
--------------------------------------------------------------------------------
1 | #if MONOGAME || FNA
2 | using Microsoft.Xna.Framework;
3 | #elif STRIDE
4 | using Stride.Core.Mathematics;
5 | #else
6 | using System.Numerics;
7 | #endif
8 |
9 | namespace NvgSharp
10 | {
11 | internal struct Bounds
12 | {
13 | public static readonly Bounds Empty = new Bounds
14 | {
15 | X = 0,
16 | Y = 0,
17 | X2 = 0,
18 | Y2 = 0,
19 | };
20 |
21 | public float X, Y, X2, Y2;
22 |
23 | public Bounds(float x, float y, float x2, float y2)
24 | {
25 | X = x;
26 | Y = y;
27 | X2 = x2;
28 | Y2 = y2;
29 | }
30 |
31 | public void ApplyScale(Vector2 scale)
32 | {
33 | X *= scale.X;
34 | Y *= scale.Y;
35 | X2 *= scale.X;
36 | Y2 *= scale.Y;
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/NvgSharp/Command.cs:
--------------------------------------------------------------------------------
1 | namespace NvgSharp
2 | {
3 | internal struct Command
4 | {
5 | public CommandType Type;
6 | public float P1, P2, P3, P4, P5, P6;
7 |
8 | public Command(CommandType type)
9 | {
10 | Type = type;
11 | P1 = P2 = P3 = P4 = P5 = P6 = 0;
12 | }
13 |
14 | public Command(Solidity solidity)
15 | {
16 | Type = CommandType.Winding;
17 | P1 = (int)solidity;
18 | P2 = P3 = P4 = P5 = P6 = 0;
19 | }
20 |
21 | public Command(CommandType type, float p1, float p2)
22 | {
23 | Type = type;
24 | P1 = p1;
25 | P2 = p2;
26 | P3 = P4 = P5 = P6 = 0;
27 | }
28 |
29 | public Command(float p1, float p2, float p3, float p4, float p5, float p6)
30 | {
31 | Type = CommandType.BezierTo;
32 | P1 = p1;
33 | P2 = p2;
34 | P3 = p3;
35 | P4 = p4;
36 | P5 = p5;
37 | P6 = p6;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/NvgSharp/Enums.cs:
--------------------------------------------------------------------------------
1 | namespace NvgSharp
2 | {
3 | public enum Winding
4 | {
5 | ///
6 | /// Winding for solid shapes
7 | ///
8 | CounterClockWise = 1,
9 |
10 | ///
11 | /// Winding for holes
12 | ///
13 | ClockWise = 2,
14 | };
15 |
16 | public enum Solidity
17 | {
18 | ///
19 | /// CCW
20 | ///
21 | Solid = 1,
22 |
23 | ///
24 | /// CW
25 | ///
26 | Hole = 2,
27 | };
28 |
29 | public enum LineCap
30 | {
31 | Butt,
32 | Round,
33 | Square,
34 | Bevel,
35 | Miter,
36 | };
37 |
38 | public enum ImageFlags
39 | {
40 | ///
41 | /// Generate mipmaps during creation of the image
42 | ///
43 | GenerateMipMaps = 1 << 0,
44 |
45 | ///
46 | /// Repeat image in X direction
47 | ///
48 | RepeatX = 1 << 1,
49 |
50 | ///
51 | /// Repeat image in Y direction
52 | ///
53 | RepeatY = 1 << 2,
54 |
55 | ///
56 | /// Flips (inverses) image in Y direction when rendered
57 | ///
58 | FlipY = 1 << 3,
59 |
60 | ///
61 | /// Image data has premultiplied alpha
62 | ///
63 | Premultiplied = 1 << 4,
64 |
65 | ///
66 | /// Image interpolation is Nearest instead Linear
67 | ///
68 | Nearest = 1 << 5,
69 | };
70 |
71 | internal enum CommandType
72 | {
73 | MoveTo = 0,
74 | LineTo = 1,
75 | BezierTo = 2,
76 | Close = 3,
77 | Winding = 4,
78 | };
79 |
80 | internal enum PointFlags
81 | {
82 | Corner = 0x01,
83 | Left = 0x02,
84 | Bevel = 0x04,
85 | InnerBevel = 0x08,
86 | };
87 |
88 | internal enum CodepointType
89 | {
90 | Space,
91 | Newline,
92 | Char,
93 | CjkChar,
94 | };
95 | }
--------------------------------------------------------------------------------
/src/NvgSharp/INvgRenderer.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | #if MONOGAME || FNA
4 | using Microsoft.Xna.Framework;
5 | using Microsoft.Xna.Framework.Graphics;
6 | #elif STRIDE
7 | using Stride.Graphics;
8 | #else
9 | using System.Drawing;
10 | using System.Numerics;
11 | using Matrix = System.Numerics.Matrix4x4;
12 | using Texture2D = System.Object;
13 | #endif
14 |
15 | namespace NvgSharp
16 | {
17 | public enum CallType
18 | {
19 | Fill,
20 | ConvexFill,
21 | Stroke,
22 | Triangles
23 | }
24 |
25 | public enum RenderType
26 | {
27 | FillGradient,
28 | FillImage,
29 | Simple,
30 | Image
31 | };
32 |
33 | public struct UniformInfo
34 | {
35 | public Matrix scissorMat;
36 | public Matrix paintMat;
37 | public Vector4 innerCol;
38 | public Vector4 outerCol;
39 | public Vector2 scissorExt;
40 | public Vector2 scissorScale;
41 | public Vector2 extent;
42 | public float radius;
43 | public float feather;
44 | public float strokeMult;
45 | public float strokeThr;
46 | public Texture2D Image;
47 | public RenderType type;
48 | }
49 |
50 | public struct FillStrokeInfo
51 | {
52 | public int FillOffset;
53 | public int FillCount;
54 | public int StrokeOffset;
55 | public int StrokeCount;
56 | }
57 |
58 | public class CallInfo
59 | {
60 | public CallType Type;
61 | public UniformInfo UniformInfo, UniformInfo2;
62 | public readonly List FillStrokeInfos = new List();
63 | public int TriangleOffset;
64 | public int TriangleCount;
65 | }
66 |
67 | public interface INvgRenderer
68 | {
69 | #if MONOGAME || FNA || STRIDE
70 | GraphicsDevice GraphicsDevice { get; }
71 | #else
72 | ///
73 | /// Creates a texture of the specified size
74 | ///
75 | ///
76 | ///
77 | ///
78 | object CreateTexture(int width, int height);
79 |
80 | ///
81 | /// Returns size of the specified texture
82 | ///
83 | ///
84 | ///
85 | Point GetTextureSize(object texture);
86 |
87 | ///
88 | /// Sets RGBA data at the specified bounds
89 | ///
90 | ///
91 | ///
92 | void SetTextureData(object texture, Rectangle bounds, byte[] data);
93 | #endif
94 |
95 | void Draw(float devicePixelRatio, IEnumerable calls, Vertex[] vertexes);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/NvgSharp/NvgContextState.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | namespace NvgSharp
4 | {
5 | [StructLayout(LayoutKind.Sequential)]
6 | internal class NvgContextState
7 | {
8 | public int ShapeAntiAlias;
9 | public Paint Fill;
10 | public Paint Stroke;
11 | public float StrokeWidth;
12 | public float MiterLimit;
13 | public LineCap LineJoin;
14 | public LineCap LineCap;
15 | public float Alpha;
16 | public Transform Transform = new Transform();
17 | public Scissor Scissor;
18 |
19 | public NvgContextState Clone()
20 | {
21 | return new NvgContextState
22 | {
23 | ShapeAntiAlias = ShapeAntiAlias,
24 | Fill = Fill,
25 | Stroke = Stroke,
26 | StrokeWidth = StrokeWidth,
27 | MiterLimit = MiterLimit,
28 | LineJoin = LineJoin,
29 | LineCap = LineCap,
30 | Alpha = Alpha,
31 | Transform = Transform,
32 | Scissor = Scissor,
33 | };
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/NvgSharp/NvgPoint.cs:
--------------------------------------------------------------------------------
1 | namespace NvgSharp
2 | {
3 | internal class NvgPoint
4 | {
5 | public float X;
6 | public float Y;
7 | public float DeltaX;
8 | public float DeltaY;
9 | public float Length;
10 | public float dmx;
11 | public float dmy;
12 | public byte flags;
13 |
14 | public void Reset()
15 | {
16 | X = Y = DeltaX = DeltaY = Length = dmx = dmy = 0;
17 | flags = 0;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/NvgSharp/NvgSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | Platform-Agnostic Version of NvgSharp
5 | $(DefineConstants);PLATFORM_AGNOSTIC
6 |
7 |
8 |
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/src/NvgSharp/NvgUtility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | #if MONOGAME || FNA
4 | using Microsoft.Xna.Framework;
5 | #elif STRIDE
6 | using Stride.Core.Mathematics;
7 | #else
8 | using System.Drawing;
9 | using System.Numerics;
10 | using Matrix = System.Numerics.Matrix4x4;
11 | #endif
12 |
13 | namespace NvgSharp
14 | {
15 | internal static class NvgUtility
16 | {
17 | ///
18 | /// Length proportional to radius of a cubic bezier handle for 90deg arcs
19 | ///
20 | public const float NVG_KAPPA90 = 0.5522847493f;
21 |
22 | ///
23 | /// PI
24 | ///
25 | public const float PI = (float)Math.PI;
26 |
27 | public static float SqrtF(float a) => (float)Math.Sqrt(a);
28 |
29 | public static float SinF(float a) => (float)Math.Sin(a);
30 |
31 | public static float TanF(float a) => (float)Math.Tan(a);
32 |
33 | public static float Atan2F(float a, float b) => (float)Math.Atan2(a, b);
34 |
35 | public static float CosF(float a) => (float)Math.Cos(a);
36 |
37 | public static float AcosF(float a) => (float)Math.Acos(a);
38 |
39 | public static float CeilingF(float a) => (float)Math.Ceiling(a);
40 |
41 | public static int ClampI(int a, int mn, int mx)
42 | {
43 | if (a < mn) return a;
44 | if (a > mx) return mx;
45 |
46 | return a;
47 | }
48 |
49 | public static float ClampF(float a, float mn, float mx)
50 | {
51 | if (a < mn) return a;
52 | if (a > mx) return mx;
53 |
54 | return a;
55 | }
56 |
57 | public static float Cross(float dx0, float dy0, float dx1, float dy1) => dx1 * dy0 - dx0 * dy1;
58 |
59 | public static float Normalize(ref float x, ref float y)
60 | {
61 | var d = SqrtF((x * x) + (y * y));
62 | if (d > 1e-6f)
63 | {
64 | float id = (float)(1.0f / d);
65 | x *= id;
66 | y *= id;
67 | }
68 |
69 | return d;
70 | }
71 |
72 | public static void MakeZero(this Matrix m)
73 | {
74 | m.M11 = m.M12 = m.M13 = m.M14 = 0;
75 | m.M21 = m.M22 = m.M23 = m.M24 = 0;
76 | m.M31 = m.M32 = m.M33 = m.M34 = 0;
77 | m.M41 = m.M42 = m.M43 = m.M44 = 0;
78 | }
79 |
80 | public static Color FromRGBA(byte r, byte g, byte b, byte a)
81 | {
82 | #if MONOGAME || FNA || STRIDE
83 | return new Color(r, g, b, a);
84 | #else
85 | return Color.FromArgb(a, r, g, b);
86 | #endif
87 | }
88 |
89 | public static Vector4 ToVector4(this Color c, bool premultiply)
90 | {
91 | var result = new Vector4(c.R / 255.0f, c.G / 255.0f, c.B / 255.0f, c.A / 255.0f);
92 |
93 | if (premultiply)
94 | {
95 | result.X *= result.W;
96 | result.Y *= result.W;
97 | result.Z *= result.W;
98 | }
99 |
100 | return result;
101 | }
102 | }
103 | }
--------------------------------------------------------------------------------
/src/NvgSharp/Paint.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #if MONOGAME || FNA
4 | using Microsoft.Xna.Framework;
5 | using Microsoft.Xna.Framework.Graphics;
6 | #elif STRIDE
7 | using Stride.Core.Mathematics;
8 | #else
9 | using System.Numerics;
10 | using System.Drawing;
11 | using Texture2D = System.Object;
12 | #endif
13 |
14 | namespace NvgSharp
15 | {
16 | [StructLayout(LayoutKind.Sequential)]
17 | public struct Paint
18 | {
19 | public Transform Transform;
20 | public Vector2 Extent;
21 | public float Radius;
22 | public float Feather;
23 | public Color InnerColor;
24 | public Color OuterColor;
25 | public Texture2D Image;
26 |
27 | public Paint(Color color)
28 | {
29 | Transform = new Transform();
30 | Extent = new Vector2();
31 | Transform.SetIdentity();
32 | Radius = 0.0f;
33 | Feather = 1.0f;
34 | InnerColor = color;
35 | OuterColor = color;
36 | Image = null;
37 | }
38 |
39 | public void Zero()
40 | {
41 | Transform.Zero();
42 | Extent = Vector2.Zero;
43 | Radius = 0;
44 | Feather = 0;
45 | InnerColor = Color.Transparent;
46 | OuterColor = Color.Transparent;
47 | Image = null;
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/src/NvgSharp/Path.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace NvgSharp
4 | {
5 | internal class Path
6 | {
7 | public bool Closed;
8 | public int BevelCount;
9 | public int FillOffset, FillCount;
10 | public int StrokeOffset, StrokeCount;
11 | public Winding Winding;
12 | public bool Convex;
13 | public readonly List Points = new List();
14 |
15 | public NvgPoint this[int index]
16 | {
17 | get => Points[index];
18 | set => Points[index] = value;
19 | }
20 |
21 | public int Count => Points.Count;
22 |
23 | public NvgPoint FirstPoint => Points[0];
24 | public NvgPoint LastPoint => Points[Points.Count - 1];
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/NvgSharp/RenderCache.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | #if MONOGAME || FNA
5 | using Microsoft.Xna.Framework;
6 | #elif STRIDE
7 | using Stride.Core.Mathematics;
8 | #else
9 | using System.Numerics;
10 | #endif
11 |
12 | namespace NvgSharp
13 | {
14 | internal class RenderCache
15 | {
16 | private const int MAX_VERTICES = 8192;
17 |
18 | private readonly bool _stencilStrokes;
19 |
20 | public readonly ArrayBuffer VertexArray = new ArrayBuffer(MAX_VERTICES);
21 | public readonly List Calls = new List();
22 | public float DevicePixelRatio;
23 |
24 | public int VertexCount => VertexArray.Count;
25 |
26 | public bool StencilStrokes => _stencilStrokes;
27 |
28 | public RenderCache(bool stencilStrokes)
29 | {
30 | _stencilStrokes = stencilStrokes;
31 | }
32 |
33 | public void Reset()
34 | {
35 | VertexArray.Clear();
36 | Calls.Clear();
37 | }
38 |
39 | public void AddVertex(float x, float y, float u, float v)
40 | {
41 | VertexArray.Add(new Vertex(x, y, u, v));
42 | }
43 |
44 | public void AddVertex(Vertex v)
45 | {
46 | VertexArray.Add(v);
47 | }
48 |
49 | private static void BuildUniform(ref Paint paint, ref Scissor scissor, float width, float fringe,
50 | float strokeThr, ref UniformInfo uniform)
51 | {
52 | uniform.innerCol = paint.InnerColor.ToVector4(true);
53 | uniform.outerCol = paint.OuterColor.ToVector4(true);
54 |
55 | if (scissor.Extent.X < -0.5f || scissor.Extent.Y < -0.5f)
56 | {
57 | uniform.scissorMat.MakeZero();
58 | uniform.scissorExt.X = 1.0f;
59 | uniform.scissorExt.Y = 1.0f;
60 | uniform.scissorScale.X = 1.0f;
61 | uniform.scissorScale.Y = 1.0f;
62 | }
63 | else
64 | {
65 | uniform.scissorMat = scissor.Transform.BuildInverse().ToMatrix();
66 | uniform.scissorExt.X = scissor.Extent.X;
67 | uniform.scissorExt.Y = scissor.Extent.Y;
68 | uniform.scissorScale.X = (float)Math.Sqrt(scissor.Transform.T1 * scissor.Transform.T1 + scissor.Transform.T3 * scissor.Transform.T3) / fringe;
69 | uniform.scissorScale.Y = (float)Math.Sqrt(scissor.Transform.T2 * scissor.Transform.T2 + scissor.Transform.T4 * scissor.Transform.T4) / fringe;
70 | }
71 |
72 | uniform.extent = paint.Extent;
73 | uniform.strokeMult = (width * 0.5f + fringe * 0.5f) / fringe;
74 | uniform.strokeThr = strokeThr;
75 |
76 | uniform.Image = paint.Image;
77 |
78 | if (paint.Image != null)
79 | {
80 | uniform.type = RenderType.FillImage;
81 | }
82 | else
83 | {
84 | uniform.type = (int)RenderType.FillGradient;
85 | uniform.radius = paint.Radius;
86 | uniform.feather = paint.Feather;
87 | }
88 |
89 | uniform.paintMat = paint.Transform.BuildInverse().ToMatrix();
90 | }
91 |
92 | public void RenderFill(ref Paint paint, ref Scissor scissor, float fringe, Bounds bounds, IReadOnlyList paths)
93 | {
94 | var call = new CallInfo
95 | {
96 | Type = CallType.Fill
97 | };
98 |
99 | if (paths.Count == 1 && paths[0].Convex)
100 | {
101 | call.Type = CallType.ConvexFill;
102 | }
103 |
104 | for (var i = 0; i < paths.Count; i++)
105 | {
106 | var path = paths[i];
107 |
108 | var drawCallInfo = new FillStrokeInfo
109 | {
110 | FillOffset = path.FillOffset,
111 | FillCount = path.FillCount,
112 | StrokeOffset = path.StrokeOffset,
113 | StrokeCount = path.StrokeCount,
114 | };
115 |
116 | call.FillStrokeInfos.Add(drawCallInfo);
117 | }
118 |
119 | // Setup uniforms for draw calls
120 | if (call.Type == CallType.Fill)
121 | {
122 | // Quad
123 | call.TriangleOffset = VertexArray.Count;
124 | call.TriangleCount = 4;
125 | VertexArray.Add(new Vertex(bounds.X2, bounds.Y2, 0.5f, 1.0f));
126 | VertexArray.Add(new Vertex(bounds.X2, bounds.Y, 0.5f, 1.0f));
127 | VertexArray.Add(new Vertex(bounds.X, bounds.Y2, 0.5f, 1.0f));
128 | VertexArray.Add(new Vertex(bounds.X, bounds.Y, 0.5f, 1.0f));
129 |
130 | // Simple shader for stencil
131 | call.UniformInfo.strokeThr = -1.0f;
132 | call.UniformInfo.type = RenderType.Simple;
133 |
134 | // Fill shader
135 | BuildUniform(ref paint, ref scissor, fringe, fringe, -1.0f, ref call.UniformInfo2);
136 | }
137 | else
138 | {
139 | // Fill shader
140 | BuildUniform(ref paint, ref scissor, fringe, fringe, -1.0f, ref call.UniformInfo);
141 | }
142 |
143 | Calls.Add(call);
144 | }
145 |
146 | public void RenderStroke(ref Paint paint, ref Scissor scissor, float fringe, float strokeWidth, IReadOnlyList paths)
147 | {
148 | var call = new CallInfo
149 | {
150 | Type = CallType.Stroke,
151 | };
152 |
153 | for (var i = 0; i < paths.Count; i++)
154 | {
155 | var path = paths[i];
156 |
157 | var drawCallInfo = new FillStrokeInfo
158 | {
159 | StrokeOffset = path.StrokeOffset,
160 | StrokeCount = path.StrokeCount,
161 | };
162 |
163 | call.FillStrokeInfos.Add(drawCallInfo);
164 | }
165 |
166 | // Setup uniforms for draw calls
167 | if (_stencilStrokes)
168 | {
169 | // Fill shader
170 | BuildUniform(ref paint, ref scissor, strokeWidth, fringe, -1.0f, ref call.UniformInfo);
171 | BuildUniform(ref paint, ref scissor, strokeWidth, fringe, 1.0f - 0.5f / 255.0f, ref call.UniformInfo2);
172 | }
173 | else
174 | {
175 | // Fill shader
176 | BuildUniform(ref paint, ref scissor, strokeWidth, fringe, -1.0f, ref call.UniformInfo);
177 | }
178 |
179 | Calls.Add(call);
180 | }
181 |
182 | public void RenderTriangles(ref Paint paint, ref Scissor scissor, float fringe, int triangleOffset, int triangleCount)
183 | {
184 | var call = new CallInfo
185 | {
186 | Type = CallType.Triangles,
187 | TriangleOffset = triangleOffset,
188 | TriangleCount = triangleCount
189 | };
190 |
191 | // Fill shader
192 | BuildUniform(ref paint, ref scissor, 1.0f, fringe, -1.0f, ref call.UniformInfo);
193 | call.UniformInfo.type = RenderType.Image;
194 |
195 | Calls.Add(call);
196 | }
197 | }
198 | }
--------------------------------------------------------------------------------
/src/NvgSharp/Scissor.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #if MONOGAME || FNA
4 | using Microsoft.Xna.Framework;
5 | #elif STRIDE
6 | using Stride.Core.Mathematics;
7 | #else
8 | using System.Numerics;
9 | #endif
10 |
11 | namespace NvgSharp
12 | {
13 | [StructLayout(LayoutKind.Sequential)]
14 | internal struct Scissor
15 | {
16 | public Transform Transform;
17 | public Vector2 Extent;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/NvgSharp/Transform.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #if MONOGAME || FNA
4 | using Microsoft.Xna.Framework;
5 | #elif STRIDE
6 | using Stride.Core.Mathematics;
7 | #else
8 | using System.Numerics;
9 | #endif
10 |
11 | namespace NvgSharp
12 | {
13 | [StructLayout(LayoutKind.Sequential)]
14 | public struct Transform
15 | {
16 | public float T1, T2, T3, T4, T5, T6;
17 |
18 | public void Zero()
19 | {
20 | T1 = T2 = T3 = T4 = T5 = T6 = 0;
21 | }
22 |
23 | public void Set(Transform src)
24 | {
25 | T1 = src.T1;
26 | T2 = src.T2;
27 | T3 = src.T3;
28 | T4 = src.T4;
29 | T5 = src.T5;
30 | T6 = src.T6;
31 | }
32 |
33 | public void SetIdentity()
34 | {
35 | T1 = 1.0f;
36 | T2 = 0.0f;
37 | T3 = 0.0f;
38 | T4 = 1.0f;
39 | T5 = 0.0f;
40 | T6 = 0.0f;
41 | }
42 |
43 | public void SetTranslate(float tx, float ty)
44 | {
45 | T1 = 1.0f;
46 | T2 = 0.0f;
47 | T3 = 0.0f;
48 | T4 = 1.0f;
49 | T5 = tx;
50 | T6 = ty;
51 | }
52 |
53 | public void SetScale(float sx, float sy)
54 | {
55 | T1 = sx;
56 | T2 = 0.0f;
57 | T3 = 0.0f;
58 | T4 = sy;
59 | T5 = 0.0f;
60 | T6 = 0.0f;
61 | }
62 |
63 | public void SetRotate(float a)
64 | {
65 | var cs = NvgUtility.CosF(a);
66 | var sn = NvgUtility.SinF(a);
67 | T1 = cs;
68 | T2 = sn;
69 | T3 = -sn;
70 | T4 = cs;
71 | T5 = 0.0f;
72 | T6 = 0.0f;
73 | }
74 |
75 | public void SetSkewX(float a)
76 | {
77 | T1 = 1.0f;
78 | T2 = 0.0f;
79 | T3 = NvgUtility.TanF(a);
80 | T4 = 1.0f;
81 | T5 = 0.0f;
82 | T6 = 0.0f;
83 | }
84 |
85 | public void SetSkewY(float a)
86 | {
87 | T1 = 1.0f;
88 | T2 = NvgUtility.TanF(a);
89 | T3 = 0.0f;
90 | T4 = 1.0f;
91 | T5 = 0.0f;
92 | T6 = 0.0f;
93 | }
94 |
95 | public void Multiply(ref Transform s)
96 | {
97 | var t0 = T1 * s.T1 + T2 * s.T3;
98 | var t2 = T3 * s.T1 + T4 * s.T3;
99 | var t4 = T5 * s.T1 + T6 * s.T3 + s.T5;
100 | T2 = T1 * s.T2 + T2 * s.T4;
101 | T4 = T3 * s.T2 + T4 * s.T4;
102 | T6 = T5 * s.T2 + T6 * s.T4 + s.T6;
103 | T1 = t0;
104 | T3 = t2;
105 | T5 = t4;
106 | }
107 |
108 | public void Premultiply(ref Transform s)
109 | {
110 | var s2 = s;
111 | s2.Multiply(ref this);
112 | Set(s2);
113 | }
114 |
115 | public Transform BuildInverse()
116 | {
117 | var det = T1 * T4 - T3 * T2;
118 | var inv = new Transform();
119 | if (det > -1e-6 && det < 1e-6)
120 | {
121 | inv.SetIdentity();
122 | return inv;
123 | }
124 |
125 | var inverseDeterminant = 1.0f / det;
126 | inv.T1 = T4 * inverseDeterminant;
127 | inv.T3 = -T3 * inverseDeterminant;
128 | inv.T5 = (T3 * T6 - T4 * T5) * inverseDeterminant;
129 | inv.T2 = -T2 * inverseDeterminant;
130 | inv.T4 = T1 * inverseDeterminant;
131 | inv.T6 = (T2 * T5 - T1 * T6) * inverseDeterminant;
132 |
133 | return inv;
134 | }
135 |
136 | public void TransformPoint(out float dx, out float dy, float sx, float sy)
137 | {
138 | dx = sx * T1 + sy * T3 + T5;
139 | dy = sx * T2 + sy * T4 + T6;
140 | }
141 |
142 | public void TransformVector(out Vector2 v, Vector2 s)
143 | {
144 | TransformPoint(out v.X, out v.Y, s.X, s.Y);
145 | }
146 |
147 | #if MONOGAME || FNA || STRIDE
148 | public Matrix ToMatrix()
149 | {
150 | var m3 = Matrix.Identity;
151 |
152 | m3.M11 = T1;
153 | m3.M21 = T2;
154 | m3.M31 = 0.0f;
155 | m3.M41 = 0.0f;
156 | m3.M12 = T3;
157 | m3.M22 = T4;
158 | m3.M32 = 0.0f;
159 | m3.M42 = 0.0f;
160 | m3.M13 = T5;
161 | m3.M23 = T6;
162 | m3.M33 = 1.0f;
163 | m3.M43 = 0.0f;
164 |
165 | return m3;
166 | }
167 | #else
168 | public Matrix4x4 ToMatrix()
169 | {
170 | var result = Matrix4x4.Identity;
171 |
172 | result.M11 = T1;
173 | result.M12 = T2;
174 | result.M13 = 0f;
175 | result.M14 = 0f;
176 | result.M21 = T3;
177 | result.M22 = T4;
178 | result.M23 = 0f;
179 | result.M24 = 0f;
180 | result.M31 = 0f;
181 | result.M32 = 0f;
182 | result.M33 = 1f;
183 | result.M34 = 0f;
184 | result.M41 = T5;
185 | result.M42 = T6;
186 | result.M43 = 0f;
187 | result.M44 = 1f;
188 |
189 | return result;
190 | }
191 | #endif
192 | }
193 | }
--------------------------------------------------------------------------------
/src/NvgSharp/Vertex.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | #if MONOGAME || FNA
4 | using Microsoft.Xna.Framework;
5 | using Microsoft.Xna.Framework.Graphics;
6 | #elif STRIDE
7 | using Stride.Core.Mathematics;
8 | #else
9 | using System.Numerics;
10 | #endif
11 |
12 | namespace NvgSharp
13 | {
14 | [StructLayout(LayoutKind.Sequential, Pack = 1)]
15 | public struct Vertex
16 | #if MONOGAME || FNA || STRIDE
17 | : IVertexType
18 | #endif
19 | {
20 | public Vector2 Position;
21 | public Vector2 TextureCoordinate;
22 |
23 | public Vertex(float x, float y, float u, float v)
24 | {
25 | Position.X = x;
26 | Position.Y = y;
27 | TextureCoordinate.X = u;
28 | TextureCoordinate.Y = v;
29 | }
30 |
31 | #if MONOGAME || FNA || STRIDE
32 |
33 | public static readonly VertexDeclaration VertexDeclaration;
34 |
35 | VertexDeclaration IVertexType.VertexDeclaration
36 | {
37 | get
38 | {
39 | return VertexDeclaration;
40 | }
41 | }
42 |
43 | static Vertex()
44 | {
45 | VertexElement[] elements = new VertexElement[] {
46 | new VertexElement(0, VertexElementFormat.Vector2, VertexElementUsage.Position, 0),
47 | new VertexElement(8, VertexElementFormat.Vector2, VertexElementUsage.TextureCoordinate, 0)
48 | };
49 | VertexDeclaration declaration = new VertexDeclaration(elements);
50 | VertexDeclaration = declaration;
51 | }
52 | #endif
53 | }
54 | }
--------------------------------------------------------------------------------
/src/XNA/NvgSharp.FNA.Core.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | NvgSharp.FNA
5 | NvgSharp.FNA
6 | NvgSharp for FNA.Core
7 | $(DefineConstants);FNA
8 | bin\FNA.Core\$(Configuration)
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/XNA/NvgSharp.FNA.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net461
4 | NvgSharp.FNA
5 | NvgSharp.FNA
6 | NvgSharp for FNA
7 | $(DefineConstants);FNA
8 | bin\FNA\$(Configuration)
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/XNA/NvgSharp.MonoGame.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | NvgSharp for MonoGame
5 | $(DefineConstants);MONOGAME
6 | bin\MonoGame\$(Configuration)
7 |
8 |
9 |
10 | true
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/XNA/Resources.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Linq;
3 | using System.Reflection;
4 | using Microsoft.Xna.Framework.Graphics;
5 |
6 | namespace NvgSharp
7 | {
8 | internal static class Resources
9 | {
10 | private static byte[] _effectSource = null, _effectWithAASource = null;
11 |
12 | #if MONOGAME
13 | private static bool? _isOpenGL;
14 | #endif
15 |
16 | public static byte[] GetNvgEffectSource(bool edgeAntiAlias)
17 | {
18 | if (_effectSource != null && !edgeAntiAlias)
19 | {
20 | return _effectSource;
21 | }
22 |
23 | if (_effectWithAASource != null && edgeAntiAlias)
24 | {
25 | return _effectWithAASource;
26 | }
27 |
28 | var assembly = typeof(Resources).Assembly;
29 |
30 | var name = "Effect";
31 | if (edgeAntiAlias)
32 | {
33 | name += "_AA";
34 | }
35 |
36 | #if MONOGAME
37 | var path = IsOpenGL?"NvgSharp.Resources." + name + ".ogl.mgfxo":"NvgSharp.Resources." + name + ".dx11.mgfxo";
38 | #elif FNA
39 | var path = "NvgSharp.Resources." + name + ".fxb";
40 | #endif
41 |
42 | byte[] result;
43 |
44 | var ms = new MemoryStream();
45 | using (var stream = assembly.GetManifestResourceStream(path))
46 | {
47 | stream.CopyTo(ms);
48 | result = ms.ToArray();
49 | }
50 |
51 | if (edgeAntiAlias)
52 | {
53 | _effectWithAASource = result;
54 | }
55 | else
56 | {
57 | _effectSource = result;
58 | }
59 |
60 | return result;
61 | }
62 |
63 | #if MONOGAME
64 | public static bool IsOpenGL
65 | {
66 | get
67 | {
68 | if (_isOpenGL == null)
69 | {
70 | _isOpenGL = (from f in typeof(GraphicsDevice).GetFields(BindingFlags.NonPublic |
71 | BindingFlags.Instance)
72 | where f.Name == "glFramebuffer"
73 | select f).FirstOrDefault() != null;
74 | }
75 |
76 | return _isOpenGL.Value;
77 | }
78 | }
79 | #endif
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/XNA/Resources/Effect.dx11.mgfxo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/src/XNA/Resources/Effect.dx11.mgfxo
--------------------------------------------------------------------------------
/src/XNA/Resources/Effect.fx:
--------------------------------------------------------------------------------
1 | #include "Macros.fxh"
2 |
3 | DECLARE_TEXTURE(g_texture, 0);
4 |
5 | BEGIN_CONSTANTS
6 |
7 | float4 innerCol;
8 | float4 outerCol;
9 | float2 scissorExt;
10 | float2 scissorScale;
11 | float2 extent;
12 | float radius;
13 | float feather;
14 | float strokeMult;
15 | float strokeThr;
16 |
17 | MATRIX_CONSTANTS
18 |
19 | float4x4 dummy;
20 | float4x4 scissorMat;
21 | float4x4 paintMat;
22 | float4x4 transformMat;
23 |
24 | END_CONSTANTS
25 |
26 |
27 | struct VS_OUTPUT
28 | {
29 | float4 position : SV_Position; // vertex position
30 | float2 ftcoord : TEXCOORD0; // float 2 tex coord
31 | float2 fpos : TEXCOORD1; // float 2 position
32 | };
33 |
34 | struct PS_INPUT
35 | {
36 | float4 position : SV_Position; // vertex position
37 | float2 ftcoord : TEXCOORD0; // float 2 tex coord
38 | float2 fpos : TEXCOORD1; // float 2 position
39 | };
40 |
41 | VS_OUTPUT VSMain(float2 pt : POSITION, float2 tex : TEXCOORD0)
42 | {
43 | VS_OUTPUT Output;
44 | Output.ftcoord = tex;
45 | Output.fpos = pt;
46 | Output.position = mul(float4(pt.x, pt.y, 0, 1), transformMat);
47 |
48 | return Output;
49 | }
50 |
51 | float sdroundrect(float2 pt, float2 ext, float rad)
52 | {
53 | float2 ext2 = ext - float2(rad,rad);
54 | float2 d = abs(pt) - ext2;
55 | return min(max(d.x,d.y),0.0) + length(max(d,0.0)) - rad;
56 | }
57 |
58 | // Scissoring
59 | float scissorMask(float2 p)
60 | {
61 | float2 sc = (abs((mul((float3x3)scissorMat, float3(p.x, p.y, 1.0))).xy) - scissorExt.xy);
62 | sc = float2(0.5,0.5) - sc * scissorScale.xy;
63 | return clamp(sc.x,0.0,1.0) * clamp(sc.y,0.0,1.0);
64 | }
65 |
66 | #ifdef EDGE_AA
67 | // Stroke - from [0..1] to clipped pyramid, where the slope is 1px.
68 | float strokeMask(float2 ftcoord)
69 | {
70 | return min(1.0, (1.0 - abs(ftcoord.x*2.0 - 1.0))*strokeMult.x) * min(1.0f, ftcoord.y);
71 | }
72 | #endif
73 |
74 | float4 PSMainFillGradient(PS_INPUT input) : SV_TARGET
75 | {
76 | float4 result;
77 | float scissor = scissorMask(input.fpos);
78 | #ifdef EDGE_AA
79 | float strokeAlpha = strokeMask(input.ftcoord);
80 | if (strokeAlpha < strokeThr) discard;
81 | #else
82 | float strokeAlpha = 1.0;
83 | #endif
84 | // Calculate gradient color using box gradient
85 | float2 pt = (mul((float3x3)paintMat, float3(input.fpos,1.0))).xy;
86 | float d = clamp((sdroundrect(pt, extent.xy, radius.x) + feather.x*0.5) / feather.x, 0.0, 1.0);
87 | float4 color = lerp(innerCol, outerCol, d);
88 |
89 | // Combine alpha
90 | color *= strokeAlpha * scissor;
91 | result = color;
92 |
93 | return result;
94 | }
95 |
96 | float4 PSMainFillImage(PS_INPUT input) : SV_TARGET
97 | {
98 | float4 result;
99 | float scissor = scissorMask(input.fpos);
100 | #ifdef EDGE_AA
101 | float strokeAlpha = strokeMask(input.ftcoord);
102 | if (strokeAlpha < strokeThr) discard;
103 | #else
104 | float strokeAlpha = 1.0;
105 | #endif
106 | // Calculate color fron texture
107 | float2 pt = (mul((float3x3)paintMat, float3(input.fpos,1.0))).xy / extent.xy;
108 | float4 color = SAMPLE_TEXTURE(g_texture, pt);
109 | color = float4(color.xyz*color.w,color.w);
110 |
111 | // Apply color tint and alpha.
112 | color *= innerCol;
113 | // Combine alpha
114 | color *= strokeAlpha * scissor;
115 | result = color;
116 |
117 | return result;
118 | }
119 |
120 | float4 PSMainSimple(PS_INPUT input) : SV_TARGET
121 | {
122 | float4 result;
123 | float scissor = scissorMask(input.fpos);
124 | #ifdef EDGE_AA
125 | float strokeAlpha = strokeMask(input.ftcoord);
126 | if (strokeAlpha < strokeThr) discard;
127 | #else
128 | float strokeAlpha = 1.0;
129 | #endif
130 | // Stencil fill
131 | result = float4(1,1,1,1);
132 |
133 | return result;
134 | }
135 |
136 | float4 PSMainTriangles(PS_INPUT input) : SV_TARGET
137 | {
138 | float4 result;
139 | float scissor = scissorMask(input.fpos);
140 | #ifdef EDGE_AA
141 | float strokeAlpha = strokeMask(input.ftcoord);
142 | if (strokeAlpha < strokeThr) discard;
143 | #else
144 | float strokeAlpha = 1.0;
145 | #endif
146 | // Textured tris
147 | float4 color = SAMPLE_TEXTURE(g_texture, input.ftcoord);
148 | color *= scissor;
149 | result = (color * innerCol);
150 |
151 | return result;
152 | }
153 |
154 | TECHNIQUE(FillGradient, VSMain, PSMainFillGradient);
155 | TECHNIQUE(FillImage, VSMain, PSMainFillImage);
156 | TECHNIQUE(Simple, VSMain, PSMainSimple);
157 | TECHNIQUE(Triangles, VSMain, PSMainTriangles);
--------------------------------------------------------------------------------
/src/XNA/Resources/Effect.fxb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/src/XNA/Resources/Effect.fxb
--------------------------------------------------------------------------------
/src/XNA/Resources/Effect.ogl.mgfxo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/src/XNA/Resources/Effect.ogl.mgfxo
--------------------------------------------------------------------------------
/src/XNA/Resources/Effect_AA.dx11.mgfxo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/src/XNA/Resources/Effect_AA.dx11.mgfxo
--------------------------------------------------------------------------------
/src/XNA/Resources/Effect_AA.fxb:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/src/XNA/Resources/Effect_AA.fxb
--------------------------------------------------------------------------------
/src/XNA/Resources/Effect_AA.ogl.mgfxo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rds1983/NvgSharp/b6e8b7ed50b8fe6b550406f45a077d7138033fb6/src/XNA/Resources/Effect_AA.ogl.mgfxo
--------------------------------------------------------------------------------
/src/XNA/Resources/Macros.fxh:
--------------------------------------------------------------------------------
1 | //-----------------------------------------------------------------------------
2 | // Macros.fxh
3 | //
4 | // Microsoft XNA Community Game Platform
5 | // Copyright (C) Microsoft Corporation. All rights reserved.
6 | //-----------------------------------------------------------------------------
7 |
8 | #ifdef SM4
9 |
10 | // Macros for targetting shader model 4.0 (DX11)
11 |
12 | #define TECHNIQUE(name, vsname, psname ) \
13 | technique name { pass { VertexShader = compile vs_4_0_level_9_1 vsname (); PixelShader = compile ps_4_0_level_9_1 psname(); } }
14 |
15 | #define BEGIN_CONSTANTS cbuffer Parameters : register(b0) {
16 | #define MATRIX_CONSTANTS
17 | #define END_CONSTANTS };
18 |
19 | #define _vs(r)
20 | #define _ps(r)
21 | #define _cb(r)
22 |
23 | #define DECLARE_TEXTURE(Name, index) \
24 | Texture2D Name : register(t##index); \
25 | sampler Name##Sampler : register(s##index)
26 |
27 | #define DECLARE_CUBEMAP(Name, index) \
28 | TextureCube Name : register(t##index); \
29 | sampler Name##Sampler : register(s##index)
30 |
31 | #define SAMPLE_TEXTURE(Name, texCoord) Name.Sample(Name##Sampler, texCoord)
32 | #define SAMPLE_CUBEMAP(Name, texCoord) Name.Sample(Name##Sampler, texCoord)
33 |
34 |
35 | #else
36 |
37 |
38 | // Macros for targetting shader model 2.0 (DX9)
39 |
40 | #define TECHNIQUE(name, vsname, psname ) \
41 | technique name { pass { VertexShader = compile vs_2_0 vsname (); PixelShader = compile ps_2_0 psname(); } }
42 |
43 | #define BEGIN_CONSTANTS
44 | #define MATRIX_CONSTANTS
45 | #define END_CONSTANTS
46 |
47 | #define _vs(r) : register(vs, r)
48 | #define _ps(r) : register(ps, r)
49 | #define _cb(r)
50 |
51 | #define DECLARE_TEXTURE(Name, index) \
52 | texture2D Name; \
53 | sampler Name##Sampler : register(s##index) = sampler_state { Texture = (Name); };
54 |
55 | #define DECLARE_CUBEMAP(Name, index) \
56 | textureCUBE Name; \
57 | sampler Name##Sampler : register(s##index) = sampler_state { Texture = (Name); };
58 |
59 | #define SAMPLE_TEXTURE(Name, texCoord) tex2D(Name##Sampler, texCoord)
60 | #define SAMPLE_CUBEMAP(Name, texCoord) texCUBE(Name##Sampler, texCoord)
61 |
62 | #endif
63 |
--------------------------------------------------------------------------------
/src/XNA/Resources/build.bat:
--------------------------------------------------------------------------------
1 | mgfxc Effect.fx Effect.dx11.mgfxo /Profile:DirectX_11
2 | mgfxc Effect.fx Effect_AA.ogl.mgfxo /Profile:OpenGL /defines:EDGE_AA=1
3 | mgfxc Effect.fx Effect.dx11.mgfxo /Profile:DirectX_11
4 | mgfxc Effect.fx Effect_AA.dx11.mgfxo /Profile:DirectX_11 /defines:EDGE_AA=1
5 |
6 | "D:\Windows Kits\10\bin\10.0.19041.0\x64\fxc.exe" /T fx_2_0 /Fo Effect.fxb Effect.fx
7 | "D:\Windows Kits\10\bin\10.0.19041.0\x64\fxc.exe" /T fx_2_0 /Fo Effect_AA.fxb Effect.fx /D EDGE_AA=1
--------------------------------------------------------------------------------
/src/XNA/XNARenderer.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using Microsoft.Xna.Framework;
5 | using Microsoft.Xna.Framework.Graphics;
6 |
7 | namespace NvgSharp
8 | {
9 | internal class XNARenderer : INvgRenderer
10 | {
11 | private readonly BlendState _blendStateNoDraw = new BlendState
12 | {
13 | ColorWriteChannels = ColorWriteChannels.None
14 | };
15 |
16 | private readonly GraphicsDevice _device;
17 | private readonly Effect _effect;
18 |
19 | private readonly DepthStencilState _stencilStateFill1 = new DepthStencilState
20 | {
21 | StencilEnable = true,
22 | TwoSidedStencilMode = true,
23 | StencilWriteMask = 0xff,
24 | ReferenceStencil = 0,
25 | StencilMask = 0xff,
26 | StencilFunction = CompareFunction.Always,
27 | StencilFail = StencilOperation.Keep,
28 | StencilDepthBufferFail = StencilOperation.Keep,
29 | StencilPass = StencilOperation.Increment,
30 | CounterClockwiseStencilFunction = CompareFunction.Always,
31 | CounterClockwiseStencilFail = StencilOperation.Keep,
32 | CounterClockwiseStencilDepthBufferFail = StencilOperation.Keep,
33 | CounterClockwiseStencilPass = StencilOperation.Decrement
34 | };
35 |
36 | private readonly DepthStencilState _stencilStateFill2 = new DepthStencilState
37 | {
38 | StencilEnable = true,
39 | TwoSidedStencilMode = false,
40 | StencilWriteMask = 0xff,
41 | ReferenceStencil = 0,
42 | StencilMask = 0xff,
43 | StencilFunction = CompareFunction.Equal,
44 | StencilFail = StencilOperation.Keep,
45 | StencilDepthBufferFail = StencilOperation.Keep,
46 | StencilPass = StencilOperation.Keep,
47 | };
48 |
49 | private readonly DepthStencilState _stencilStateFill3 = new DepthStencilState
50 | {
51 | StencilEnable = true,
52 | TwoSidedStencilMode = false,
53 | StencilWriteMask = 0xff,
54 | ReferenceStencil = 0,
55 | StencilMask = 0xff,
56 | StencilFunction = CompareFunction.NotEqual,
57 | StencilFail = StencilOperation.Zero,
58 | StencilDepthBufferFail = StencilOperation.Zero,
59 | StencilPass = StencilOperation.Zero
60 | };
61 |
62 | private readonly EffectTechnique[] _techniques = new EffectTechnique[4];
63 | private readonly EffectParameter _extentParam;
64 | private readonly EffectParameter _radiusParam;
65 | private readonly EffectParameter _featherParam;
66 | private readonly EffectParameter _innerColParam;
67 | private readonly EffectParameter _outerColParam;
68 | private readonly EffectParameter _textureParam;
69 | private short[] _indexes = BuildTriangleFanIndexBuffer(2048 * 6);
70 | private BlendState _oldBlendState;
71 | private DepthStencilState _oldDepthStencilState;
72 | private RasterizerState _oldRasterizerState;
73 | private SamplerState _oldSamplerState;
74 | private readonly bool _edgeAntiAlias;
75 | private Vertex[] _vertexArray;
76 |
77 | private readonly EffectParameter _transformMatParam;
78 | private readonly EffectParameter _scissorMatParam;
79 | private readonly EffectParameter _scissorExtParam;
80 | private readonly EffectParameter _scissorScaleParam;
81 | private readonly EffectParameter _paintMatParam;
82 | private readonly EffectParameter _strokeMultParam, _strokeThrParam;
83 |
84 | public GraphicsDevice GraphicsDevice => _device;
85 |
86 | public XNARenderer(GraphicsDevice device, bool edgeAntiAlias)
87 | {
88 | if (device == null)
89 | throw new ArgumentNullException("device");
90 |
91 | _device = device;
92 | _edgeAntiAlias = edgeAntiAlias;
93 | _effect = new Effect(device, Resources.GetNvgEffectSource(edgeAntiAlias));
94 |
95 | _transformMatParam = _effect.Parameters["transformMat"];
96 | _scissorMatParam = _effect.Parameters["scissorMat"];
97 | _scissorExtParam = _effect.Parameters["scissorExt"];
98 | _scissorScaleParam = _effect.Parameters["scissorScale"];
99 | _paintMatParam = _effect.Parameters["paintMat"];
100 | _extentParam = _effect.Parameters["extent"];
101 | _radiusParam = _effect.Parameters["radius"];
102 | _featherParam = _effect.Parameters["feather"];
103 | _innerColParam = _effect.Parameters["innerCol"];
104 | _outerColParam = _effect.Parameters["outerCol"];
105 | _textureParam = _effect.Parameters["g_texture"];
106 |
107 | if (_edgeAntiAlias)
108 | {
109 | _strokeThrParam = _effect.Parameters["strokeThr"];
110 | _strokeMultParam = _effect.Parameters["strokeMult"];
111 | }
112 |
113 | foreach (RenderingType param in Enum.GetValues(typeof(RenderingType)))
114 | _techniques[(int)param] = _effect.Techniques[param.ToString()];
115 | }
116 |
117 | public void Draw(float devicePixelRatio, IEnumerable calls, Vertex[] vertexes)
118 | {
119 | try
120 | {
121 | _oldSamplerState = _device.SamplerStates[0];
122 | _oldBlendState = _device.BlendState;
123 | _oldDepthStencilState = _device.DepthStencilState;
124 | _oldRasterizerState = _device.RasterizerState;
125 |
126 | _device.BlendState = BlendState.AlphaBlend;
127 | _device.DepthStencilState = DepthStencilState.None;
128 | _device.RasterizerState = RasterizerState.CullNone;
129 | _device.SamplerStates[0] = SamplerState.PointClamp;
130 |
131 | _vertexArray = vertexes;
132 |
133 | var transform = Matrix.CreateOrthographicOffCenter(0, _device.Viewport.Width, _device.Viewport.Height, 0, 0, -1);
134 | _transformMatParam.SetValue(transform);
135 |
136 | foreach (var call in calls)
137 | {
138 | switch (call.Type)
139 | {
140 | case CallType.Fill:
141 | RenderFill(call);
142 | break;
143 | case CallType.ConvexFill:
144 | RenderConvexFill(call);
145 | break;
146 | case CallType.Stroke:
147 | RenderStroke(call);
148 | break;
149 | case CallType.Triangles:
150 | RenderTriangles(call);
151 | break;
152 | }
153 | }
154 | }
155 | finally
156 | {
157 | _device.SamplerStates[0] = _oldSamplerState;
158 | _device.BlendState = _oldBlendState;
159 | _device.DepthStencilState = _oldDepthStencilState;
160 | _device.RasterizerState = _oldRasterizerState;
161 | _vertexArray = null;
162 | }
163 | }
164 |
165 | private void SetUniform(ref UniformInfo uniform)
166 | {
167 | _scissorMatParam.SetValue(uniform.scissorMat);
168 | _paintMatParam.SetValue(uniform.paintMat);
169 | _innerColParam.SetValue(uniform.innerCol);
170 | _outerColParam.SetValue(uniform.outerCol);
171 | _scissorExtParam.SetValue(uniform.scissorExt);
172 | _scissorScaleParam.SetValue(uniform.scissorScale);
173 | _extentParam.SetValue(uniform.extent);
174 | _radiusParam.SetValue(uniform.radius);
175 | _featherParam.SetValue(uniform.feather);
176 | _textureParam.SetValue(uniform.Image);
177 |
178 | if (_edgeAntiAlias)
179 | {
180 | _strokeMultParam.SetValue(uniform.strokeMult);
181 | _strokeThrParam.SetValue(uniform.strokeThr);
182 | }
183 | }
184 |
185 | private void DrawVertexes(RenderingType renderingType, PrimitiveType primitiveType, int vertexOffset, int vertexCount, bool indexed)
186 | {
187 | if (vertexCount == 0)
188 | {
189 | return;
190 | }
191 |
192 | var technique = _techniques[(int)renderingType];
193 | _effect.CurrentTechnique = technique;
194 | foreach (var pass in _effect.CurrentTechnique.Passes)
195 | {
196 | pass.Apply();
197 |
198 | if (indexed)
199 | {
200 | var primitiveCount = vertexCount - 2;
201 | _device.DrawUserIndexedPrimitives(primitiveType, _vertexArray, vertexOffset, vertexCount, _indexes, 0, primitiveCount);
202 | }
203 | else
204 | {
205 | var primitiveCount =
206 | primitiveType == PrimitiveType.TriangleList ? vertexCount / 3 : vertexCount - 2;
207 | _device.DrawUserPrimitives(primitiveType, _vertexArray, vertexOffset, primitiveCount);
208 | }
209 | }
210 | }
211 |
212 | private void RenderConvexFill(CallInfo call)
213 | {
214 | // Convex Fill
215 | SetUniform(ref call.UniformInfo);
216 |
217 | var renderingType = call.UniformInfo.Image != null ? RenderingType.FillImage : RenderingType.FillGradient;
218 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
219 | {
220 | var fillStrokeInfo = call.FillStrokeInfos[i];
221 |
222 | DrawVertexes(renderingType, PrimitiveType.TriangleList, fillStrokeInfo.FillOffset, fillStrokeInfo.FillCount, true);
223 | DrawVertexes(renderingType, PrimitiveType.TriangleStrip, fillStrokeInfo.StrokeOffset, fillStrokeInfo.StrokeCount, false);
224 | }
225 | }
226 |
227 | private void RenderFill(CallInfo call)
228 | {
229 | _device.BlendState = _blendStateNoDraw;
230 | _device.DepthStencilState = _stencilStateFill1;
231 | var renderingType = RenderingType.Simple;
232 |
233 | SetUniform(ref call.UniformInfo);
234 |
235 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
236 | {
237 | var fillStrokeInfo = call.FillStrokeInfos[i];
238 |
239 | DrawVertexes(renderingType, PrimitiveType.TriangleList, fillStrokeInfo.FillOffset, fillStrokeInfo.FillCount, true);
240 | }
241 |
242 | // Draw anti-aliased pixels
243 | _device.BlendState = BlendState.AlphaBlend;
244 |
245 | SetUniform(ref call.UniformInfo2);
246 |
247 | if (_edgeAntiAlias)
248 | {
249 | _device.DepthStencilState = _stencilStateFill2;
250 | renderingType = call.UniformInfo2.Image != null ? RenderingType.FillImage : RenderingType.FillGradient;
251 |
252 | // Draw fringes
253 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
254 | {
255 | var fillStrokeInfo = call.FillStrokeInfos[i];
256 |
257 | DrawVertexes(renderingType, PrimitiveType.TriangleStrip, fillStrokeInfo.StrokeOffset, fillStrokeInfo.StrokeCount, false);
258 | }
259 | }
260 |
261 | _device.DepthStencilState = _stencilStateFill3;
262 |
263 | renderingType = RenderingType.FillGradient;
264 | DrawVertexes(renderingType, PrimitiveType.TriangleStrip, call.TriangleOffset, call.TriangleCount, false);
265 |
266 | _device.DepthStencilState = DepthStencilState.None;
267 | }
268 |
269 | private void RenderStroke(CallInfo call)
270 | {
271 | SetUniform(ref call.UniformInfo);
272 | var renderingType = call.UniformInfo.Image != null ? RenderingType.FillImage : RenderingType.FillGradient;
273 |
274 | for (var i = 0; i < call.FillStrokeInfos.Count; i++)
275 | {
276 | var fillStrokeInfo = call.FillStrokeInfos[i];
277 |
278 | DrawVertexes(renderingType, PrimitiveType.TriangleStrip, fillStrokeInfo.StrokeOffset, fillStrokeInfo.StrokeCount, false);
279 | }
280 | }
281 |
282 | private void RenderTriangles(CallInfo call)
283 | {
284 | SetUniform(ref call.UniformInfo);
285 |
286 | DrawVertexes(RenderingType.Triangles, PrimitiveType.TriangleList, call.TriangleOffset, call.TriangleCount, false);
287 | }
288 |
289 | private static short[] BuildTriangleFanIndexBuffer(int indexesCount)
290 | {
291 | var result = new List();
292 | for (var j = 2; j < indexesCount; ++j)
293 | {
294 | result.Add(0);
295 | result.Add((short)(j - 1));
296 | result.Add((short)j);
297 | }
298 |
299 | return result.ToArray();
300 | }
301 |
302 | private enum RenderingType
303 | {
304 | FillGradient,
305 | FillImage,
306 | Simple,
307 | Triangles
308 | }
309 | }
310 | }
--------------------------------------------------------------------------------