├── .gitattributes ├── .gitignore ├── RLCompiler ├── RLCompiler.cpp ├── RLCompiler.vcxproj └── RLCompiler.vcxproj.filters ├── RLL.sln ├── RLL ├── Alias.h ├── Bitmap.cpp ├── Bitmap.h ├── BlockLayout.cpp ├── DescriptorHeap.cpp ├── DescriptorHeap.h ├── Font.h ├── FontStack.cpp ├── Interfaces.h ├── Metrics.h ├── Object.h ├── Painter.h ├── PathGeometry.h ├── RLL.vcxproj ├── RLL.vcxproj.filters ├── SharedImpl.cpp ├── StlImpl.cpp ├── TextInterfaces.h ├── TextLayout.cpp ├── TextProperty.h ├── ThirdParty.h ├── Win32impl.cpp ├── curve_tools.h ├── d3dx12.h ├── delegate.h ├── fi_ft.cpp ├── fi_ft.h ├── main.cpp ├── math3d │ └── Math3Df.h ├── meshutil.h ├── perf_util.cpp ├── perf_util.h ├── reactive.h ├── rlltest.h ├── shader │ ├── core.hlsl │ ├── core_anim.hlsl │ ├── core_vertex.hlsl │ ├── dbgWire.hlsl │ └── path.hlsli ├── test.cpp ├── test │ └── format.txt ├── win32acrylic.cpp ├── win32acrylic.h ├── win32core.cpp ├── win32core_mesh.cpp ├── win32core_mesh.h ├── win32impl.h ├── win32internal.h ├── win32paint_d12.cpp ├── win32paint_d12.h ├── win32paint_d12context.cpp ├── win32paint_d12device.cpp ├── win32paint_d12geometry.cpp ├── win32paint_d12svg.cpp └── win32whelper.h ├── readme.md └── readme ├── 1.png ├── 2.png ├── 3.png ├── 4.png └── 5.png /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Oo]ut/ 33 | [Ll]og/ 34 | [Ll]ogs/ 35 | 36 | # Visual Studio 2015/2017 cache/options directory 37 | .vs/ 38 | # Uncomment if you have tasks that create the project's static files in wwwroot 39 | #wwwroot/ 40 | 41 | # Visual Studio 2017 auto generated files 42 | Generated\ Files/ 43 | 44 | # MSTest test Results 45 | [Tt]est[Rr]esult*/ 46 | [Bb]uild[Ll]og.* 47 | 48 | # NUnit 49 | *.VisualState.xml 50 | TestResult.xml 51 | nunit-*.xml 52 | 53 | # Build Results of an ATL Project 54 | [Dd]ebugPS/ 55 | [Rr]eleasePS/ 56 | dlldata.c 57 | 58 | # Benchmark Results 59 | BenchmarkDotNet.Artifacts/ 60 | 61 | # .NET Core 62 | project.lock.json 63 | project.fragment.lock.json 64 | artifacts/ 65 | 66 | # ASP.NET Scaffolding 67 | ScaffoldingReadMe.txt 68 | 69 | # StyleCop 70 | StyleCopReport.xml 71 | 72 | # Files built by Visual Studio 73 | *_i.c 74 | *_p.c 75 | *_h.h 76 | *.ilk 77 | *.meta 78 | *.obj 79 | *.iobj 80 | *.pch 81 | *.pdb 82 | *.ipdb 83 | *.pgc 84 | *.pgd 85 | *.rsp 86 | *.sbr 87 | *.tlb 88 | *.tli 89 | *.tlh 90 | *.tmp 91 | *.tmp_proj 92 | *_wpftmp.csproj 93 | *.log 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio LightSwitch build output 298 | **/*.HTMLClient/GeneratedArtifacts 299 | **/*.DesktopClient/GeneratedArtifacts 300 | **/*.DesktopClient/ModelManifest.xml 301 | **/*.Server/GeneratedArtifacts 302 | **/*.Server/ModelManifest.xml 303 | _Pvt_Extensions 304 | 305 | # Paket dependency manager 306 | .paket/paket.exe 307 | paket-files/ 308 | 309 | # FAKE - F# Make 310 | .fake/ 311 | 312 | # CodeRush personal settings 313 | .cr/personal 314 | 315 | # Python Tools for Visual Studio (PTVS) 316 | __pycache__/ 317 | *.pyc 318 | 319 | # Cake - Uncomment if you are using it 320 | # tools/** 321 | # !tools/packages.config 322 | 323 | # Tabs Studio 324 | *.tss 325 | 326 | # Telerik's JustMock configuration file 327 | *.jmconfig 328 | 329 | # BizTalk build output 330 | *.btp.cs 331 | *.btm.cs 332 | *.odx.cs 333 | *.xsd.cs 334 | 335 | # OpenCover UI analysis results 336 | OpenCover/ 337 | 338 | # Azure Stream Analytics local run output 339 | ASALocalRun/ 340 | 341 | # MSBuild Binary and Structured Log 342 | *.binlog 343 | 344 | # NVidia Nsight GPU debugger configuration file 345 | *.nvuser 346 | 347 | # MFractors (Xamarin productivity tool) working folder 348 | .mfractor/ 349 | 350 | # Local History for Visual Studio 351 | .localhistory/ 352 | 353 | # BeatPulse healthcheck temp database 354 | healthchecksdb 355 | 356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 357 | MigrationBackup/ 358 | 359 | # Ionide (cross platform F# VS Code tools) working folder 360 | .ionide/ 361 | 362 | # Fody - auto-generated XML schema 363 | FodyWeavers.xsd 364 | 365 | #dll 366 | *.dll 367 | -------------------------------------------------------------------------------- /RLCompiler/RLCompiler.cpp: -------------------------------------------------------------------------------- 1 | // RLCompiler.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 2 | // 3 | 4 | #include 5 | 6 | int main() 7 | { 8 | std::cout << "Hello World!\n"; 9 | } 10 | 11 | // 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单 12 | // 调试程序: F5 或调试 >“开始调试”菜单 13 | 14 | // 入门使用技巧: 15 | // 1. 使用解决方案资源管理器窗口添加/管理文件 16 | // 2. 使用团队资源管理器窗口连接到源代码管理 17 | // 3. 使用输出窗口查看生成输出和其他消息 18 | // 4. 使用错误列表窗口查看错误 19 | // 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目 20 | // 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件 21 | -------------------------------------------------------------------------------- /RLCompiler/RLCompiler.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {75119a3c-07a6-4019-93a1-18d48d9a258c} 25 | RLCompiler 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Console 136 | true 137 | true 138 | true 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /RLCompiler/RLCompiler.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 10 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 11 | 12 | 13 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 14 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 15 | 16 | 17 | 18 | 19 | src 20 | 21 | 22 | -------------------------------------------------------------------------------- /RLL.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("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RLL", "RLL\RLL.vcxproj", "{ADB9F18C-C143-4CFA-830A-E50E4713BD75}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RLCompiler", "RLCompiler\RLCompiler.vcxproj", "{75119A3C-07A6-4019-93A1-18D48D9A258C}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {ADB9F18C-C143-4CFA-830A-E50E4713BD75}.Debug|x64.ActiveCfg = Debug|x64 19 | {ADB9F18C-C143-4CFA-830A-E50E4713BD75}.Debug|x64.Build.0 = Debug|x64 20 | {ADB9F18C-C143-4CFA-830A-E50E4713BD75}.Debug|x86.ActiveCfg = Debug|Win32 21 | {ADB9F18C-C143-4CFA-830A-E50E4713BD75}.Debug|x86.Build.0 = Debug|Win32 22 | {ADB9F18C-C143-4CFA-830A-E50E4713BD75}.Release|x64.ActiveCfg = Release|x64 23 | {ADB9F18C-C143-4CFA-830A-E50E4713BD75}.Release|x64.Build.0 = Release|x64 24 | {ADB9F18C-C143-4CFA-830A-E50E4713BD75}.Release|x86.ActiveCfg = Release|Win32 25 | {ADB9F18C-C143-4CFA-830A-E50E4713BD75}.Release|x86.Build.0 = Release|Win32 26 | {75119A3C-07A6-4019-93A1-18D48D9A258C}.Debug|x64.ActiveCfg = Debug|x64 27 | {75119A3C-07A6-4019-93A1-18D48D9A258C}.Debug|x64.Build.0 = Debug|x64 28 | {75119A3C-07A6-4019-93A1-18D48D9A258C}.Debug|x86.ActiveCfg = Debug|Win32 29 | {75119A3C-07A6-4019-93A1-18D48D9A258C}.Debug|x86.Build.0 = Debug|Win32 30 | {75119A3C-07A6-4019-93A1-18D48D9A258C}.Release|x64.ActiveCfg = Release|x64 31 | {75119A3C-07A6-4019-93A1-18D48D9A258C}.Release|x64.Build.0 = Release|x64 32 | {75119A3C-07A6-4019-93A1-18D48D9A258C}.Release|x86.ActiveCfg = Release|Win32 33 | {75119A3C-07A6-4019-93A1-18D48D9A258C}.Release|x86.Build.0 = Release|Win32 34 | EndGlobalSection 35 | GlobalSection(SolutionProperties) = preSolution 36 | HideSolutionNode = FALSE 37 | EndGlobalSection 38 | GlobalSection(ExtensibilityGlobals) = postSolution 39 | SolutionGuid = {80407084-EAAB-4CC4-92E5-5BF2F2A6A805} 40 | EndGlobalSection 41 | EndGlobal 42 | -------------------------------------------------------------------------------- /RLL/Alias.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #pragma disable 4305 7 | 8 | namespace Gz 9 | { 10 | template 11 | using Vector = std::vector<_T>; 12 | 13 | template 14 | using Atomic = std::atomic<_T>; 15 | 16 | using String = std::string; 17 | 18 | } -------------------------------------------------------------------------------- /RLL/Bitmap.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaazar/RLL/f82af45fa96038485a10bef3f6a514242f79e978/RLL/Bitmap.cpp -------------------------------------------------------------------------------- /RLL/Bitmap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Sharp.h" 3 | 4 | namespace Sharp 5 | { 6 | namespace Graphics { 7 | class Bitmap 8 | { 9 | Byte* buffer = nullptr; 10 | Int width; 11 | Int height; 12 | Int pitch; 13 | Int bits; 14 | public: 15 | Bitmap(); 16 | Bitmap(Sharp::Stream&); 17 | Int SaveTo(Sharp::Stream&); 18 | void CopyFrom(Byte* buffer, Int width, Int height, Int pitch = 0, Int bits = 24); 19 | }; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /RLL/BlockLayout.cpp: -------------------------------------------------------------------------------- 1 | #include "Interfaces.h" 2 | 3 | using namespace RLL; 4 | using namespace Math3D; 5 | using namespace std; 6 | 7 | 8 | 9 | 10 | //if parentProps.size == {0,0} then it means parent is not sized and should skip procedure, 11 | //if this element is dynamic; Then 12 | //set out_Size to its minimal size; 13 | bool BlockLayout::Flow(ElementProps& parentProps, RLL::FlowOut& out_Size) 14 | { 15 | properties.size = { 0,0 }; 16 | if (parentProps.size.SqurMagnitude() == 0 && properties.isDynamicSize) 17 | { 18 | out_Size.size = properties.minSize; 19 | return true; 20 | } 21 | for (auto& i : elements) 22 | { 23 | i.out = FlowOut(); 24 | if (i.element->Flow(properties, i.out)) 25 | { 26 | i.dynSize = true; 27 | } 28 | } 29 | lines.clear(); 30 | LinePart cLine; 31 | //horizontal only 32 | 33 | //calculate line metrics 34 | { 35 | for (auto& i : elements) 36 | { 37 | if (cLine.size.x + i.out.size.x > contentSize.x) 38 | { 39 | if (cLine.parts.size() > 0) 40 | { 41 | RLL::Size maxSize = { contentSize.x,cLine.size.y }; 42 | auto restSize = (maxSize - cLine.size) / cLine.dynSizeItgr; 43 | if (cLine.dynSizeItgr.x == 0) restSize.x = 0; 44 | if (cLine.dynSizeItgr.y == 0) restSize.y = 0; 45 | 46 | for (auto& i : cLine.parts) 47 | { 48 | i.finalSize = i.out.size + i.out.dynRation * restSize; 49 | } 50 | lines.push_back(cLine); 51 | cLine.parts.clear(); 52 | cLine.size = RLL::Size(0, 0); 53 | cLine.dynSizeItgr = { 0,0 }; 54 | //continue; 55 | } 56 | } 57 | i.direction = i.element->Direction(); 58 | cLine.parts.push_back(i); 59 | cLine.size.x += i.out.size.x; 60 | if (i.dynSize) 61 | cLine.dynSizeItgr += i.out.dynRation; 62 | 63 | if (i.out.size.y > cLine.size.y) 64 | { 65 | cLine.size.y = i.out.size.y; 66 | } 67 | } 68 | if (cLine.parts.size() > 0) 69 | { 70 | RLL::Size maxSize = { contentSize.x,cLine.size.y }; 71 | auto restSize = (maxSize - cLine.size) / cLine.dynSizeItgr; 72 | if (cLine.dynSizeItgr.x == 0) restSize.x = 0; 73 | if (cLine.dynSizeItgr.y == 0) restSize.y = 0; 74 | 75 | for (auto& i : cLine.parts) 76 | { 77 | i.finalSize = i.out.size + i.out.dynRation * restSize; 78 | } 79 | 80 | lines.push_back(cLine); 81 | } 82 | //adjust dynamic size element in line 83 | 84 | } 85 | 86 | //bidi lines 87 | { 88 | for (auto& l : lines) 89 | { 90 | LANG_DIRECTION prevDir = direction; 91 | //fix two terminal of the line's COMMON_SCRIPT bidi info 92 | for (auto k = 0; k < l.parts.size(); k++) 93 | { 94 | if (l.parts[k].element->Script() == USCRIPT_COMMON) 95 | { 96 | l.parts[k].direction = direction; 97 | } 98 | else break; 99 | } 100 | for (auto k = l.parts.size() - 1; k >= 0; k--) 101 | { 102 | if (l.parts[k].element->Script() == USCRIPT_COMMON) 103 | { 104 | l.parts[k].direction = direction; 105 | } 106 | else break; 107 | } 108 | //TODO: combine below two for, can it? 109 | BIDIPart bdp; 110 | for (auto i = 0; i < l.parts.size(); i++) 111 | { 112 | if (l.parts[i].direction != prevDir) 113 | { 114 | if (bdp.parts.size() > 0) 115 | { 116 | l.bidis.push_back(bdp); 117 | bdp.parts.clear(); 118 | } 119 | bdp.direction = l.parts[i].direction; 120 | } 121 | prevDir = l.parts[i].direction; 122 | bdp.parts.push_back(l.parts[i]); 123 | 124 | } 125 | if (bdp.parts.size() > 0) 126 | l.bidis.push_back(bdp); 127 | bdp.parts.clear(); 128 | l.parts.clear(); 129 | for (auto& i : l.bidis) 130 | { 131 | if (i.direction == LANG_DIRECTION_LR) 132 | { 133 | for (auto it = i.parts.begin(); it != i.parts.end(); ) 134 | { 135 | l.parts.push_back(*it); 136 | ++it; 137 | } 138 | 139 | } 140 | else if (i.direction == LANG_DIRECTION_RL) 141 | { 142 | for (auto it = i.parts.rbegin(); it != i.parts.rend(); ) 143 | { 144 | l.parts.push_back(*it); 145 | ++it; 146 | } 147 | } 148 | } 149 | } 150 | } 151 | 152 | return false; 153 | }; 154 | 155 | RLL::Size BlockLayout::Size(ElementProps* parentProps) 156 | { 157 | RLL::Size sz; 158 | 159 | return contentSize; 160 | } 161 | LANG_DIRECTION BlockLayout::Direction() 162 | { 163 | return direction; 164 | } 165 | ScriptCode BlockLayout::Script() 166 | { 167 | return USCRIPT_COMMON; 168 | } 169 | void BlockLayout::Place(Math3D::Matrix4x4* parentTransform, RenderList renderList) 170 | { 171 | Math3D::Vector2 cursor(0,0); 172 | for (int i = 0; i < lines.size(); i++) 173 | { 174 | cursor.y += lines[i].size.y * 1.2f; 175 | cursor.x = 0; 176 | for (auto& n : lines[i].parts) 177 | { 178 | //n.element->Place(sb, cursor); 179 | cursor.x += n.finalSize.x; 180 | } 181 | } 182 | 183 | } 184 | -------------------------------------------------------------------------------- /RLL/DescriptorHeap.cpp: -------------------------------------------------------------------------------- 1 | #include "DescriptorHeap.h" 2 | 3 | HRESULT DescriptorHeap::Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT numDescriptors, bool shaderVisible) 4 | { 5 | D3D12_DESCRIPTOR_HEAP_DESC heapDesc; 6 | heapDesc.Type = type; 7 | heapDesc.Flags = shaderVisible ? D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE : D3D12_DESCRIPTOR_HEAP_FLAG_NONE; 8 | heapDesc.NumDescriptors = numDescriptors; 9 | heapDesc.NodeMask = 0; 10 | auto hr = device->CreateDescriptorHeap(&heapDesc, IID_PPV_ARGS(&heap)); 11 | if (SUCCEEDED(hr)) 12 | { 13 | CPUHandle = heap->GetCPUDescriptorHandleForHeapStart(); 14 | GPUHandle = heap->GetGPUDescriptorHandleForHeapStart(); 15 | } 16 | incrementSize = device->GetDescriptorHandleIncrementSize(type); 17 | return hr; 18 | 19 | } -------------------------------------------------------------------------------- /RLL/DescriptorHeap.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "win32internal.h" 3 | using namespace Microsoft::WRL; 4 | 5 | class DescriptorHeap 6 | { 7 | 8 | D3D12_CPU_DESCRIPTOR_HANDLE CPUHandle; 9 | D3D12_GPU_DESCRIPTOR_HANDLE GPUHandle; 10 | UINT incrementSize; 11 | ComPtr heap; 12 | int refOffset = -1; 13 | 14 | public: 15 | HRESULT Create(ID3D12Device* device, D3D12_DESCRIPTOR_HEAP_TYPE type, UINT numDescriptors, bool shaderVisible = false); 16 | DescriptorHeap() = default; 17 | DescriptorHeap(const DescriptorHeap& d, int offsetIndex = 0) 18 | { 19 | heap = d.heap; 20 | CPUHandle = d.CPUHandle; 21 | GPUHandle = d.GPUHandle; 22 | incrementSize = d.incrementSize; 23 | CPUHandle = hCPU(offsetIndex); 24 | GPUHandle = hGPU(offsetIndex); 25 | refOffset = offsetIndex; 26 | } 27 | inline D3D12_CPU_DESCRIPTOR_HANDLE hCPU(int index = 0) 28 | { 29 | D3D12_CPU_DESCRIPTOR_HANDLE h; 30 | h.ptr = CPUHandle.ptr + index * incrementSize; 31 | return h; 32 | } 33 | inline D3D12_GPU_DESCRIPTOR_HANDLE hGPU(int index = 0) 34 | { 35 | D3D12_GPU_DESCRIPTOR_HANDLE h; 36 | h.ptr = GPUHandle.ptr + index * incrementSize; 37 | return h; 38 | } 39 | inline ID3D12DescriptorHeap* Get() 40 | { 41 | return heap.Get(); 42 | } 43 | inline ID3D12DescriptorHeap** Ptr() 44 | { 45 | return &heap; 46 | } 47 | inline void Reset() 48 | { 49 | heap.Reset(); 50 | } 51 | }; -------------------------------------------------------------------------------- /RLL/Font.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Sharp.h" 3 | #include 4 | #include 5 | class FontFamily; 6 | class FontFallbacks; 7 | class FontFace; 8 | struct _FontFace; 9 | 10 | enum FontStyle 11 | { 12 | None = 0, 13 | Italic = 1, 14 | }; 15 | enum FontWeight 16 | { 17 | Thin = 100, 18 | Lighter = 200, 19 | Light = 300, 20 | Regular = 400, 21 | Medium = 500, 22 | SemiBold = 600, 23 | Bold = 700, 24 | Bolder = 800, 25 | Black = 900 26 | }; 27 | class FontFormat 28 | { 29 | struct GlyphDetail 30 | { 31 | void* metrics; 32 | float uv[3]; //[0],[1] = u,v; [2] = vtex index. 33 | }; 34 | FontFace* face; 35 | float size; 36 | //textures that on gpu 37 | std::map glyphs; 38 | std::vector textures;//d3d12: tex descriptors, heap 39 | 40 | }; 41 | class FontFace 42 | { 43 | private: 44 | FontFamily* family; 45 | Sharp::String name; 46 | _FontFace* data; 47 | int style; 48 | int weight; 49 | float size = 16; 50 | 51 | void RenderGlyph(char32_t code,void* bitmap); 52 | 53 | }; 54 | 55 | class FontFamily 56 | { 57 | private: 58 | Sharp::String name; 59 | FontFace* fonts; 60 | public: 61 | FontFace* GetFace(FontStyle style = FontStyle::None, FontWeight weight = FontWeight::Regular, float size = 16); 62 | }; 63 | 64 | class FontFallbacks 65 | { 66 | std::vector families; 67 | 68 | }; 69 | 70 | -------------------------------------------------------------------------------- /RLL/FontStack.cpp: -------------------------------------------------------------------------------- 1 | #include "TextInterfaces.h" 2 | 3 | using namespace RLL; 4 | using namespace Math3D; 5 | 6 | ISVG* IFontStack::GetGlyph(char32_t unicode, RLL::GlyphMetrics* metrics ) 7 | { 8 | for (auto i = fonts.rbegin(); i != fonts.rend(); ++i) 9 | { 10 | auto code = (*i)->GetCodepoint(unicode); 11 | if (code != 0) 12 | { 13 | return (*i)->GetGlyph(code, metrics); 14 | } 15 | } 16 | return nullptr; 17 | } 18 | IGeometry* IFontStack::GetPlainGlyph(char32_t unicode, RLL::GlyphMetrics* metrics ) 19 | { 20 | for (auto i = fonts.rbegin(); i != fonts.rend(); ++i) 21 | { 22 | auto code = (*i)->GetCodepoint(unicode); 23 | if (code != 0) 24 | { 25 | return (*i)->GetPlainGlyph(code, metrics); 26 | } 27 | } 28 | return nullptr; 29 | 30 | } 31 | 32 | void IFontStack::Push(RLL::IFontFace* face) 33 | { 34 | if (!face) 35 | return; 36 | for (auto i = fonts.begin(); i != fonts.end(); i++) 37 | { 38 | if (*i == face) 39 | { 40 | fonts.erase(i); 41 | break; 42 | } 43 | } 44 | fonts.push_back(face); 45 | 46 | } 47 | RLL::IFontFace* IFontStack::GetFace(char32_t unicode) 48 | { 49 | if (fonts.size() == 0) return nullptr; 50 | for (auto i = fonts.rbegin(); i != fonts.rend(); ++i) 51 | { 52 | auto code = (*i)->GetCodepoint(unicode); 53 | if (code != 0) 54 | { 55 | return *i; 56 | } 57 | } 58 | return fonts[0]; 59 | 60 | } 61 | -------------------------------------------------------------------------------- /RLL/Interfaces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Metrics.h" 3 | #include "ThirdParty.h" 4 | 5 | #include 6 | #include 7 | #include 8 | namespace RLL 9 | { 10 | template 11 | using Vector = std::vector<_T>; 12 | 13 | template 14 | using Atomic = std::atomic<_T>; 15 | 16 | using String = std::string; 17 | 18 | enum EVENT_TYPE 19 | { 20 | EVENT_TYPE_MOUSE_MOVE, 21 | EVENT_TYPE_MOUSE_CLICK, 22 | EVENT_TYPE_SCROOL, 23 | EVENT_TYPE_TOUCH, 24 | EVENT_KEY, 25 | EVENT_CHAR, 26 | EVENT_INPUT, 27 | EVENT_FW_FRAME_SIZE_MOVE 28 | }; 29 | struct ControlKeys 30 | { 31 | int keys; 32 | bool IsControl() 33 | { 34 | return false; 35 | } 36 | bool IsShift() 37 | { 38 | return false; 39 | } 40 | bool IsAlt() 41 | { 42 | return false; 43 | } 44 | bool IsFn() 45 | { 46 | return false; 47 | } 48 | }; 49 | union EventArgs 50 | { 51 | struct MouseMove 52 | { 53 | Math3D::Vector2 pos; 54 | Math3D::Vector2 delta; 55 | } mouseMove; 56 | struct MouseClick 57 | { 58 | short button; 59 | float pressedTime; 60 | ControlKeys keys; 61 | } mouseClick; 62 | struct Scrool 63 | { 64 | float delta; 65 | bool direct; 66 | ControlKeys keys; 67 | }; 68 | struct Key 69 | { 70 | char code; 71 | bool down; 72 | bool IsKeyDown() 73 | { 74 | return down; 75 | } 76 | bool IsKeyUp() 77 | { 78 | return !down; 79 | } 80 | } key; 81 | wchar_t character; 82 | wchar_t* input; 83 | struct FrameMoveSize 84 | { 85 | int flag; 86 | Math3D::Vector2 pos; 87 | bool IsMoving() 88 | { 89 | return flag & 0x1; 90 | } 91 | bool IsMoved() 92 | { 93 | return flag & 0x2; 94 | } 95 | bool IsSizing() 96 | { 97 | return flag & 0x4; 98 | } 99 | bool IsSized() 100 | { 101 | return flag & 0x8; 102 | } 103 | bool IsFullscreen() 104 | { 105 | return flag & 0x16; 106 | } 107 | bool IsRestord() 108 | { 109 | return flag & 0x32; 110 | } 111 | bool IsMinized() 112 | { 113 | return flag & 0x64; 114 | } 115 | } frameMove; 116 | }; 117 | class IFrame; 118 | class IPaintDevice; 119 | class ISVGBuilder; 120 | class ISVG; 121 | void Initiate(int flag = 0); 122 | int GetFlags(); 123 | wchar_t* GetLocale(); 124 | Math3D::Vector2 GetScale(); 125 | IFrame* CreateFrame(IFrame* parent, Math3D::Vector2 size, Math3D::Vector2 pos); 126 | 127 | IPaintDevice* CreatePaintDevice(); 128 | 129 | 130 | class View 131 | { 132 | void* EventProcess(EVENT_TYPE, EventArgs) 133 | { 134 | return nullptr; 135 | } 136 | }; 137 | class IFrame 138 | { 139 | public: 140 | virtual void Show() = 0; 141 | virtual void Run() = 0; 142 | }; 143 | 144 | struct FlowOut 145 | { 146 | RLL::Size size; 147 | RLL::Size dynRation; 148 | }; 149 | class RenderList 150 | { 151 | public: 152 | void operator() (Math3D::Matrix4x4 globalTransform, RLL::ISVG* renderItem, int zIndex = 0) 153 | { 154 | join(globalTransform, renderItem, zIndex); 155 | }; 156 | void join(Math3D::Matrix4x4 globalTransform, RLL::ISVG* renderItem, int zIndex = 0) 157 | { 158 | } 159 | }; 160 | class IElement 161 | { 162 | public: 163 | //return true if its size is control by parent 164 | virtual bool Flow(ElementProps& parentProps, RLL::FlowOut& out_Size) { return false; }; 165 | //virtual RLL::Size Size(ElementProps* parentProps) = 0; 166 | virtual LANG_DIRECTION Direction() = 0; 167 | virtual UScriptCode Script() { return USCRIPT_COMMON; }; 168 | virtual void Place(Math3D::Matrix4x4* parentTransform, RenderList renderList) = 0; 169 | }; 170 | struct ElementData 171 | { 172 | IElement* element = nullptr; 173 | RLL::FlowOut out; 174 | RLL::Size finalSize; 175 | float dynSize = 0; 176 | LANG_DIRECTION direction; 177 | 178 | }; 179 | 180 | class BlockLayout //: public IElement 181 | { 182 | private: 183 | struct BIDIPart 184 | { 185 | std::vector parts; 186 | LANG_DIRECTION direction = LANG_DIRECTION_LR; 187 | }; 188 | struct LinePart 189 | { 190 | std::vector parts; 191 | std::vector bidis; 192 | RLL::Size size; 193 | RLL::Size dynSizeItgr; 194 | }; 195 | 196 | BlockProps properties; 197 | BlockMetrics metrics; 198 | 199 | RLL::Size contentSize; 200 | LANG_DIRECTION direction = LANG_DIRECTION_LR_TB; 201 | LINE_ALIGN lineAlign = LINE_ALIGN_START; 202 | PARA_ALIGN paraAlign = PARA_ALIGN_START; 203 | 204 | std::vector elements; 205 | std::vector lines; 206 | 207 | public: 208 | RLL::Size Size(ElementProps* parentProps); 209 | LANG_DIRECTION Direction(); 210 | ScriptCode Script(); 211 | void Place(Math3D::Matrix4x4* parentTransform, RenderList renderList); 212 | bool Flow(ElementProps& parentProps, RLL::FlowOut& out_Size); 213 | }; 214 | 215 | 216 | } -------------------------------------------------------------------------------- /RLL/Metrics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "math3d/Math3Df.h" 3 | 4 | #include "Object.h" 5 | 6 | #ifdef _DEBUG 7 | #define NOIMPL std::cout <<"[NOIMPL]\t"<< __FILE__ << "\tline:" << __LINE__ << "\t" << __FUNCTION__ << " not implemented yet." << std::endl; 8 | #else 9 | #define NOIMPL 10 | #endif 11 | 12 | #pragma warning(push) 13 | #pragma warning(disable:4244) 14 | namespace RLL 15 | { 16 | using namespace Gz; 17 | enum SIZE_MODE { 18 | SIZE_MODE_CONTENT, //size is calculated by inside content 19 | SIZE_MODE_FIXED, //by given metrics 20 | SIZE_MODE_DYNAMIC //by parent given 21 | }; 22 | //deprecated LANG_DIRECTION replaced. 23 | enum AXIS_DIR { 24 | AXIS_DIR_NORMAL, //left to right or top to bottom 25 | AXIS_DIR_REVERSE, 26 | AXIS_DIR_S2E, //start to end, text direction 27 | AXIS_DIR_E2S, //end to start 28 | }; 29 | //deprecated LANG_DIRECTION replaced. 30 | enum AXIS_MAJOR 31 | { 32 | AXIS_MAJOR_ROW, 33 | AXIS_MAJOR_COLUMN 34 | }; 35 | //deprecated, LINE_ALGIN PARA_ALIGN replaced. 36 | enum AXIS_SPACE 37 | { 38 | AXIS_SPACE_START, 39 | AXIS_SPACE_END, 40 | AXIS_SPACE_CENTER, 41 | AXIS_SPACE_BETWEEN, 42 | AXIS_SPACE_AROUND 43 | }; 44 | enum LANG_DIRECTION 45 | { 46 | LANG_DIRECTION_LR_TB = 0, 47 | LANG_DIRECTION_RL_TB = 1, 48 | LANG_DIRECTION_LR_BT = 2, 49 | LANG_DIRECTION_RL_BT = 3, 50 | LANG_DIRECTION_TB_LR, 51 | LANG_DIRECTION_BT_LR, 52 | LANG_DIRECTION_TB_RL, 53 | LANG_DIRECTION_BT_RL, 54 | 55 | LANG_DIRECTION_LR = LANG_DIRECTION_LR_TB, 56 | LANG_DIRECTION_RL = LANG_DIRECTION_RL_TB, 57 | }; 58 | enum LINE_ALIGN //define how to align a LINE in text direction 59 | { 60 | LINE_ALIGN_START, 61 | LINE_ALIGN_END, 62 | LINE_ALIGN_CENTER, 63 | LINE_ALIGN_STRETCH, 64 | LINE_ALIGN_AVERAGE, 65 | }; 66 | enum PARA_ALIGN //define how to align LINEs in vertical to text direction 67 | { 68 | PARA_ALIGN_START, 69 | PARA_ALIGN_END, 70 | PARA_ALIGN_CENTER, 71 | PARA_ALIGN_STRETCH, 72 | PARA_ALIGN_AVERAGE, 73 | }; 74 | 75 | enum UNIT 76 | { 77 | UNIT_PX, 78 | UNIT_EM, 79 | UNIT_PT, 80 | UNIT_VW, 81 | UNIT_VH, 82 | UNIT_PERCENTAGE, 83 | UNIT_FLEX, 84 | UNIT_PPX, 85 | 86 | }; 87 | struct Axis { 88 | AXIS_DIR direction; 89 | AXIS_SPACE space; 90 | 91 | }; 92 | struct AxisProps 93 | { 94 | AXIS_MAJOR majorAxis; 95 | 96 | Axis major; 97 | Axis bi; 98 | }; 99 | struct CharMetrics 100 | { 101 | Math3D::Vector2 offset; 102 | Math3D::Vector2 advance; 103 | float ascender, decender; 104 | }; 105 | struct PharaseMetrics 106 | { 107 | 108 | }; 109 | struct BlockMetrics 110 | { 111 | Math3D::float4 margin; 112 | Math3D::float4 border; 113 | Math3D::float4 padding; 114 | Math3D::float4 content; 115 | }; 116 | 117 | struct LineMetrics 118 | { 119 | Math3D::Vector2 size; 120 | Math3D::Vector2 baseline; 121 | float ascender, decender; 122 | }; 123 | struct ElementProps 124 | { 125 | Math3D::Vector2 minSize; 126 | Math3D::Vector2 maxSize; 127 | Math3D::Vector2 defaultSize; 128 | Math3D::Vector2 size; 129 | }; 130 | struct BlockProps : ElementProps 131 | { 132 | bool isDynamicSize; 133 | float lineGap; 134 | }; 135 | struct GlyphMetrics 136 | { 137 | Math3D::float2 size; 138 | struct SpecialMetrics 139 | { 140 | Math3D::float2 offset; 141 | float advance; 142 | }; 143 | SpecialMetrics vertical; 144 | SpecialMetrics horizontal; 145 | 146 | }; 147 | struct SizeI 148 | { 149 | int x = 0, y = 0; 150 | SizeI() = default; 151 | SizeI(int x,int y) 152 | { 153 | this->x = x; 154 | this->y = y; 155 | }; 156 | SizeI(Math3D::Vector2& v) 157 | { 158 | x = v.x; 159 | y = v.y; 160 | } 161 | }; 162 | 163 | struct Size :public Math3D::Vector2 164 | { 165 | Size() 166 | { 167 | x = 0; 168 | y = 0; 169 | } 170 | Size(float x, float y) 171 | { 172 | this->x = x; 173 | this->y = y; 174 | } 175 | Size(Math3D::Vector2& v) 176 | { 177 | this->x = v.x; 178 | this->y = v.y; 179 | } 180 | Size(SizeI& s) 181 | { 182 | x = s.x; 183 | y = s.y; 184 | } 185 | }; 186 | 187 | struct Color : private Math3D::Quaternion 188 | { 189 | void SetOpacity(float opacity) 190 | { 191 | w = 1.f - opacity; 192 | } 193 | void SetColor(float r, float g, float b, float a = 0) 194 | { 195 | x = r; 196 | y = g; 197 | z = b; 198 | w = a; 199 | } 200 | Color() 201 | {}; 202 | Color(float r, float g, float b, float a) 203 | { 204 | x = r; 205 | y = g; 206 | z = b; 207 | w = a; 208 | }; 209 | }; 210 | struct ColorGradient 211 | { 212 | Color colors[8]; 213 | float positions[8] = { 0.f,2.f }; 214 | ColorGradient() 215 | { 216 | for (int i = 1; i < 8; i++) 217 | { 218 | positions[i] = 2; 219 | } 220 | } 221 | }; 222 | struct RectangleI 223 | { 224 | int left = 0; 225 | int top = 0; 226 | int right = 0; 227 | int bottom = 0; 228 | int width() 229 | { 230 | return right - left; 231 | } 232 | int height() 233 | { 234 | return bottom - top; 235 | } 236 | RectangleI() 237 | { 238 | }; 239 | RectangleI(int l, int t, int r, int b) 240 | { 241 | left = l; 242 | top = t; 243 | right = r; 244 | bottom = b; 245 | } 246 | }; 247 | struct Rectangle : public Math3D::Quaternion 248 | { 249 | 250 | }; 251 | } 252 | #pragma warning(pop) -------------------------------------------------------------------------------- /RLL/Object.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Alias.h" 3 | 4 | #include 5 | 6 | namespace Gz 7 | { 8 | class Object 9 | { 10 | Atomic _ref_count = 1; 11 | Object* _parent = nullptr; 12 | Vector _children; 13 | String _name = "UnnamedObject"; 14 | String _error; 15 | public: 16 | Object(Object* parent = nullptr) 17 | { 18 | _parent = parent; 19 | if (parent) parent->_children.push_back(this); 20 | }; 21 | Object(String name, Object* parent = nullptr) : Object(parent) 22 | { 23 | _name = name; 24 | }; 25 | virtual ~Object() 26 | { 27 | if (_ref_count > 0) 28 | { 29 | std::cout << "Delete an Object whose reference count is not 0." << this << std::endl; 30 | } 31 | for (auto& child : _children) 32 | { 33 | child->_parent = nullptr; 34 | child->Release(); 35 | } 36 | _children.clear(); 37 | } 38 | void Aquire() { AddRef(); } 39 | void AddRef() 40 | { 41 | _ref_count++; 42 | } 43 | void Release() 44 | { 45 | _ref_count--; 46 | if (_ref_count <= 0) 47 | { 48 | //std::cout << "Counter Dispose:\t" << this << std::endl; 49 | delete this; 50 | } 51 | } 52 | String GetLastError() { return _error; }; 53 | protected: 54 | void SetError(String e) 55 | { 56 | _error = e; 57 | std::cout << this << ":\t" << _error << std::endl; 58 | }; 59 | 60 | public: 61 | Object* parent() { return _parent; }; 62 | String name() { return _name; }; 63 | void name(String name) { _name = name; }; 64 | 65 | }; 66 | 67 | } -------------------------------------------------------------------------------- /RLL/Painter.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Metrics.h" 3 | #include "Interfaces.h" 4 | namespace RLL 5 | { 6 | class ITexture : public Object 7 | { 8 | virtual SizeI GetSize() = 0; 9 | virtual void Dispose() = 0; 10 | 11 | }; 12 | class IRenderTarget : public ITexture 13 | { 14 | virtual ITexture* AsTexture() = 0; 15 | }; 16 | enum class JOINT_TYPE 17 | { 18 | FLAT = 0, 19 | MITER, 20 | BEVEL, 21 | ROUND 22 | }; 23 | enum class CAP_TYPE 24 | { 25 | NONE = 0, 26 | SQUARE, 27 | TRIANGLE, 28 | ROUND 29 | }; 30 | enum class ARC_TYPE 31 | { 32 | NEAREST, 33 | POSITIVE, 34 | NEGATIVE 35 | }; 36 | struct StrokeStyle 37 | { 38 | JOINT_TYPE joint = JOINT_TYPE::FLAT; 39 | CAP_TYPE cap = CAP_TYPE::NONE; 40 | float length = 10; 41 | }; 42 | class IBrush : public Object 43 | { 44 | public: 45 | virtual void Dispose() = 0; 46 | 47 | }; 48 | class IGeometry; 49 | class ISVG; 50 | class IBitmap :public RLL::Object 51 | { 52 | public: 53 | void Dispose() { NOIMPL; }; 54 | RLL::SizeI GetSize(); 55 | 56 | 57 | }; 58 | class IGeometryBuilder : public Object 59 | { 60 | public: 61 | virtual void Begin(Math3D::Vector2 p) = 0; 62 | virtual void End(bool close) = 0; 63 | virtual void LineTo(Math3D::Vector2 to) = 0; 64 | virtual void QuadraticTo(Math3D::Vector2 control, Math3D::Vector2 to) = 0; 65 | virtual void CubicTo(Math3D::Vector2 control0, Math3D::Vector2 control1, Math3D::Vector2 to) = 0; 66 | virtual void Ellipse(Math3D::Vector2 center, Math3D::Vector2 radius, bool inv = false) = 0; 67 | virtual void ArcTo(Math3D::Vector2 center, Math3D::Vector2 radius, float begin_rad, float end_rad, ARC_TYPE t = ARC_TYPE::NEAREST) = 0; 68 | virtual void Rectangle(Math3D::Vector2 lt, Math3D::Vector2 rb, bool inv = false) = 0; 69 | virtual void Triangle(Math3D::Vector2 p0, Math3D::Vector2 p1, Math3D::Vector2 p2, bool inv = false) = 0; 70 | virtual void RoundRectangle(Math3D::Vector2 lt, Math3D::Vector2 rb, Math3D::Vector2 radius, bool inv = false) = 0; 71 | virtual IGeometry* Fill(Math3D::Matrix4x4* bgTransform = nullptr) = 0; 72 | virtual IGeometry* Stroke(float stroke = 1, StrokeStyle* type = nullptr, Math3D::Matrix4x4* bgTransform = nullptr) = 0; 73 | virtual void Reset() = 0; 74 | virtual void Dispose() = 0; 75 | 76 | }; 77 | class ISVGBuilder : public Object 78 | { 79 | public: 80 | virtual void Push(IGeometry* geom, IBrush* brush = nullptr, Math3D::Matrix4x4* transform = nullptr) = 0; 81 | virtual void Push(ISVG* svg, Math3D::Matrix4x4* transform = nullptr) = 0; 82 | virtual void Reset() = 0; 83 | virtual ISVG* Commit() = 0; 84 | virtual void Dispose() = 0; 85 | }; 86 | class IGeometry : public Object 87 | { 88 | virtual void Dispose() = 0; 89 | 90 | }; 91 | class ISVG : public Object 92 | { 93 | virtual void Dispose() = 0; 94 | }; 95 | class IAVG : public Object 96 | { 97 | virtual void Dispose() = 0; 98 | }; 99 | class IPaintContext; 100 | class IPaintDevice :public RLL::Object 101 | { 102 | public: 103 | virtual IBrush* CreateSolidColorBrush(Color c) = 0; 104 | virtual IBrush* CreateDirectionalBrush(Math3D::Vector2 direction, ColorGradient* grad) = 0; 105 | virtual IBrush* CreateRadialBrush(Math3D::Vector2 center, float radius, ColorGradient* grad) = 0; 106 | virtual IBrush* CreateSweepBrush(Math3D::Vector2 center, float degree, ColorGradient* grad) = 0; 107 | virtual IBrush* CreateTexturedBrush(ITexture* tex, void* sampleMode) = 0; 108 | virtual ITexture* CreateTexture() = 0; 109 | virtual ITexture* CreateTexture(RLL::IBitmap* bitmap) = 0; 110 | virtual IRenderTarget* CreateRenderTarget() = 0; 111 | 112 | virtual IGeometryBuilder* CreateGeometryBuilder() = 0; 113 | virtual ISVGBuilder* CreateSVGBuilder() = 0; 114 | 115 | virtual IPaintContext* CreateContext(int flags) = 0; 116 | virtual RLL::IPaintContext* CreateContextForFrame(RLL::IFrame* f, int flags = 0) = 0; 117 | 118 | virtual void CopyTexture(ITexture* src, ITexture* dst) = 0; 119 | virtual void CopyTextureRegion(ITexture* src, ITexture* dst, RectangleI) = 0; 120 | 121 | //virtual void Flush() = 0; 122 | //virtual void ResizeView(SizeI& r) = 0; 123 | }; 124 | class IPaintContext : public Object 125 | { 126 | virtual void Dispose() = 0; 127 | public: 128 | virtual IPaintDevice* GetDevice() = 0; 129 | virtual void SetRenderTarget(IRenderTarget* rt) = 0; 130 | //virtual ITexture* GetRenderTarget() = 0; 131 | virtual void BeginDraw() = 0; 132 | virtual void Clear(Color clear = {}) = 0; 133 | virtual void PushClip(Rectangle clip) = 0; 134 | virtual void PopClip() = 0; 135 | virtual void EndDraw() = 0; 136 | virtual void SetTransform(Math3D::Matrix4x4& tfCache) = 0; 137 | virtual void DrawSVG(ISVG* svg) = 0; 138 | virtual void DrawMorph() = 0; 139 | virtual void Flush() = 0; 140 | //virtual void DrawGeometry(IGeometry* geom) = 0; 141 | 142 | }; 143 | } -------------------------------------------------------------------------------- /RLL/PathGeometry.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "math3d/Math3Df.h" 3 | #include "Painter.h" 4 | #include 5 | namespace RLL 6 | { 7 | } -------------------------------------------------------------------------------- /RLL/RLL.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {adb9f18c-c143-4cfa-830a-e50e4713bd75} 25 | RLL 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | F:\libs\include;$(IncludePath) 82 | $(ExternalIncludePath) 83 | $(LIBRARYD);$(LibraryPath) 84 | $(ExecutablePath) 85 | 86 | 87 | false 88 | $(INCLUDE);F:\libs\Sharp\include;$(IncludePath) 89 | $(LIBRARY);$(LibraryPath) 90 | F:\libs\Sharp\src;$(SourcePath) 91 | F:\libs\bin64;$(ExecutablePath) 92 | 93 | 94 | 95 | Level3 96 | true 97 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 98 | true 99 | 100 | 101 | Console 102 | true 103 | 104 | 105 | 106 | 107 | Level3 108 | true 109 | true 110 | true 111 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 112 | true 113 | 114 | 115 | Console 116 | true 117 | true 118 | true 119 | 120 | 121 | 122 | 123 | Level3 124 | true 125 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | false 127 | stdcpp20 128 | 129 | 130 | Console 131 | true 132 | F:\libs\debug;%(AdditionalLibraryDirectories) 133 | 134 | 135 | 136 | 137 | Level3 138 | true 139 | true 140 | true 141 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 142 | false 143 | stdcpp20 144 | 145 | 146 | Console 147 | true 148 | true 149 | true 150 | 151 | 152 | 153 | 154 | true 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | Document 202 | 203 | 204 | 205 | 206 | 207 | false 208 | Document 209 | 210 | 211 | Document 212 | 213 | 214 | Document 215 | 216 | 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /RLL/RLL.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 6 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 7 | 8 | 9 | {e525fde4-ca4c-45f5-8d39-362d33dae96e} 10 | 11 | 12 | {ab5d0693-fdf8-40d1-a930-a35112e61642} 13 | 14 | 15 | {9977944b-719a-45e0-8043-d703a7eae4d9} 16 | 17 | 18 | {5b79fdd3-b12e-4741-8f3e-aead13e111c7} 19 | 20 | 21 | {becbfa89-914f-47bd-b099-86832ff6c4d7} 22 | 23 | 24 | {317ef664-6b39-488b-8827-01e4e2484725} 25 | 26 | 27 | 28 | 29 | src 30 | 31 | 32 | src\win32impl 33 | 34 | 35 | src\win32impl 36 | 37 | 38 | src\win32impl 39 | 40 | 41 | src\win32impl 42 | 43 | 44 | src\win32impl 45 | 46 | 47 | src\shared 48 | 49 | 50 | src\shared 51 | 52 | 53 | src\win32impl 54 | 55 | 56 | src\win32impl 57 | 58 | 59 | src\win32impl 60 | 61 | 62 | src\win32impl 63 | 64 | 65 | src\win32impl 66 | 67 | 68 | src\shared 69 | 70 | 71 | src\shared 72 | 73 | 74 | src\shared 75 | 76 | 77 | src 78 | 79 | 80 | 81 | 82 | src\include 83 | 84 | 85 | src\include 86 | 87 | 88 | src\include 89 | 90 | 91 | src\include 92 | 93 | 94 | src\include 95 | 96 | 97 | src\include 98 | 99 | 100 | src\include 101 | 102 | 103 | src\win32impl\include 104 | 105 | 106 | src\win32impl\include 107 | 108 | 109 | src\win32impl\include 110 | 111 | 112 | src\win32impl\include 113 | 114 | 115 | src\win32impl\include 116 | 117 | 118 | src\win32impl\include 119 | 120 | 121 | src\win32impl\include 122 | 123 | 124 | src\win32impl\include 125 | 126 | 127 | src\include 128 | 129 | 130 | src\win32impl 131 | 132 | 133 | src\shared 134 | 135 | 136 | src\win32impl 137 | 138 | 139 | src\include 140 | 141 | 142 | src\include 143 | 144 | 145 | src\include 146 | 147 | 148 | src\include 149 | 150 | 151 | src\include 152 | 153 | 154 | 155 | 156 | src\shader 157 | 158 | 159 | src\shader 160 | 161 | 162 | src\shader 163 | 164 | 165 | src\shader 166 | 167 | 168 | src\shader 169 | 170 | 171 | -------------------------------------------------------------------------------- /RLL/SharedImpl.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaazar/RLL/f82af45fa96038485a10bef3f6a514242f79e978/RLL/SharedImpl.cpp -------------------------------------------------------------------------------- /RLL/StlImpl.cpp: -------------------------------------------------------------------------------- 1 | #include "Sharp.h" 2 | #include 3 | #include 4 | 5 | using namespace Sharp; 6 | 7 | FileStream::FileStream(String path, FileMode mode, FileAccess accs) 8 | { 9 | if (path.IsEmpty()) 10 | { 11 | throw Exception("Invalid argument: empty path"); 12 | } 13 | this->path = path; 14 | fmode = mode; 15 | faccs = accs; 16 | 17 | { 18 | DWORD m = 0, a = 0; 19 | switch (mode) 20 | { 21 | case FileMode::Create: 22 | m = OPEN_ALWAYS; 23 | break; 24 | case FileMode::CreateNew: 25 | m = CREATE_NEW; 26 | break; 27 | case FileMode::Open: 28 | m = OPEN_EXISTING; 29 | break; 30 | case FileMode::OpenCreate: 31 | m = CREATE_ALWAYS; 32 | break; 33 | case FileMode::Truncate: 34 | m = TRUNCATE_EXISTING; 35 | break; 36 | case FileMode::Append: 37 | m = OPEN_EXISTING; 38 | break; 39 | default: 40 | break; 41 | } 42 | switch (accs) 43 | { 44 | case FileAccess::Read: 45 | a = GENERIC_READ; 46 | break; 47 | case FileAccess::Write: 48 | a = GENERIC_WRITE; 49 | break; 50 | case FileAccess::ReadWrite: 51 | a = GENERIC_READ | GENERIC_WRITE; 52 | break; 53 | default: 54 | break; 55 | } 56 | auto h = CreateFile(path.CString(), a, 0, 0, m, FILE_ATTRIBUTE_NORMAL, 0); 57 | if (!h) throw Exception("Open|Create file failed."); 58 | CloseHandle(h); 59 | } 60 | 61 | handle = new std::fstream(); 62 | std::fstream& fs = *(std::fstream*)handle; 63 | auto m = std::ios::in | std::ios::out | std::ios::binary; 64 | switch (accs) 65 | { 66 | case FileAccess::Read: 67 | m = std::ios::in | std::ios::binary; 68 | break; 69 | case FileAccess::Write: 70 | m = std::ios::out | std::ios::binary; 71 | break; 72 | case FileAccess::ReadWrite: 73 | m = std::ios::in | std::ios::out | std::ios::binary; 74 | break; 75 | default: 76 | break; 77 | } 78 | fs.open(path.CString(), m); 79 | 80 | } 81 | bool FileStream::CanRead() 82 | { 83 | return handle && (faccs == FileAccess::Read || faccs == FileAccess::ReadWrite); 84 | } 85 | bool FileStream::CanWrite() 86 | { 87 | return handle && (faccs == FileAccess::Write || faccs == FileAccess::ReadWrite); 88 | 89 | } 90 | bool FileStream::CanSeek() 91 | { 92 | return true; 93 | } 94 | int64_t FileStream::Length() 95 | { 96 | throw Exception("No impelements."); 97 | return 0; 98 | } 99 | int64_t FileStream::Read(Byte* buffer, int64_t len) 100 | { 101 | std::fstream& fs = *(std::fstream*)handle; 102 | fs.read((char*)buffer, len); 103 | return !fs.eof(); 104 | } 105 | int64_t FileStream::Write(Byte* buffer, int64_t len) 106 | { 107 | std::fstream& fs = *(std::fstream*)handle; 108 | fs.write((char*)buffer, len); 109 | return !fs.eof(); 110 | } 111 | void FileStream::Seek(int64_t offset, SeekOrigin origin) 112 | { 113 | std::fstream& fs = *(std::fstream*)handle; 114 | std::ios_base::seekdir mm; 115 | switch (origin) 116 | { 117 | case SeekOrigin::Current: 118 | mm = std::ios::cur; 119 | break; 120 | case SeekOrigin::Start: 121 | mm = std::ios::beg; 122 | break; 123 | case SeekOrigin::End: 124 | mm = std::ios::end; 125 | break; 126 | default: 127 | break; 128 | } 129 | fs.seekg(offset, mm); 130 | fs.seekp(offset, mm); 131 | } 132 | void FileStream::Flush() 133 | { 134 | std::fstream& fs = *(std::fstream*)handle; 135 | fs.flush(); 136 | } 137 | int64_t FileStream::Position() 138 | { 139 | std::fstream& fs = *(std::fstream*)handle; 140 | return fs.showpos; 141 | } 142 | void FileStream::Position(int64_t pos) 143 | { 144 | Seek(pos, SeekOrigin::Start); 145 | } 146 | void FileStream::Close() 147 | { 148 | std::fstream& fs = *(std::fstream*)handle; 149 | fs.close(); 150 | } -------------------------------------------------------------------------------- /RLL/TextInterfaces.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Interfaces.h" 3 | #include "Painter.h" 4 | #include 5 | #include "unicode/utypes.h" 6 | #include "unicode/uscript.h" 7 | 8 | namespace RLL 9 | { 10 | void TextLayoutInit(); 11 | class IFontFace; 12 | class IFontFactory : public Object 13 | { 14 | public: 15 | virtual IFontFace* LoadFromFile(char*) = 0; 16 | virtual void Dispose() = 0; 17 | }; 18 | 19 | class IFontFace : public Object 20 | { 21 | public: 22 | virtual void SetLevel() { NOIMPL; }; 23 | virtual uint32_t GetCodepoint(char32_t unicode) = 0; 24 | virtual IGeometry* GetPlainGlyph(char32_t unicode, RLL::GlyphMetrics* metrics = nullptr) = 0; 25 | virtual RLL::IGeometry* GetPlainGlyph(uint32_t codepoint, RLL::GlyphMetrics* metrics = nullptr) = 0; 26 | 27 | virtual ISVG* GetGlyph(char32_t unicode, RLL::GlyphMetrics* metrics = nullptr) = 0; 28 | virtual RLL::ISVG* GetGlyph(uint32_t codepoint, RLL::GlyphMetrics* metrics = nullptr) = 0; 29 | 30 | virtual void Dispose() { NOIMPL; }; 31 | }; 32 | class IFontStack :public IFontFace 33 | { 34 | private: 35 | std::vector fonts; 36 | public: 37 | IFontStack() {}; 38 | virtual uint32_t GetCodepoint(char32_t unicode) { assert(0);/*no avaliable.*/ return 0; } 39 | 40 | virtual IGeometry* GetPlainGlyph(char32_t unicode, RLL::GlyphMetrics* metrics = nullptr); 41 | virtual RLL::IGeometry* GetPlainGlyph(uint32_t codepoint, RLL::GlyphMetrics* metrics = nullptr) { assert(0);/*no avaliable.*/ return nullptr; } 42 | 43 | virtual ISVG* GetGlyph(char32_t unicode, RLL::GlyphMetrics* metrics = nullptr); 44 | virtual RLL::ISVG* GetGlyph(uint32_t codepoint, RLL::GlyphMetrics* metrics = nullptr) { assert(0);/*no avaliable.*/ return nullptr; } 45 | virtual void Push(RLL::IFontFace* face); 46 | virtual RLL::IFontFace* GetFace(char32_t unicode); 47 | virtual void Dispose() { NOIMPL; }; 48 | 49 | }; 50 | 51 | IFontFactory* CreateFontFactory(IPaintDevice*); 52 | 53 | class ITextLayout :public Object 54 | { 55 | public: 56 | virtual void AppendText(char* text) = 0; 57 | virtual void InsertText(char* text, int pos) = 0; 58 | virtual RLL::ISVG* Commit() = 0; 59 | void Dispose() {}; 60 | 61 | }; 62 | 63 | class TextLayout :public Object 64 | { 65 | private: 66 | template 67 | struct Range 68 | { 69 | struct Pair 70 | { 71 | int32_t begin; 72 | int32_t end; 73 | T value; 74 | }; 75 | std::vector values; 76 | 77 | void Set(int32_t begin, int32_t end, T value) 78 | { 79 | Pair p = { begin,end,value }; 80 | for (auto i = values.begin(); i != values.end(); ++i) 81 | { 82 | if (i->end >= begin) 83 | { 84 | i->end = begin; 85 | auto ii = i + 1; 86 | if (ii != values.end()) 87 | { 88 | ii->begin = end; 89 | } 90 | values.insert(ii, p); 91 | break; 92 | } 93 | } 94 | values.push_back(p); 95 | } 96 | 97 | //std::vector> Intersect(INDEX begin, INDEX end) 98 | //{ 99 | // std::vector> res; 100 | // bool ena = false; 101 | // for (auto& i : values) 102 | // { 103 | // if (end >= i.begin && end < i.end) 104 | // { 105 | // res.push_back({ i.begin,end }); 106 | // ena = false; 107 | // break; 108 | // } 109 | // if (ena) 110 | // res.push_back({ i.begin,i.end }); 111 | // if (begin >= i.begin && begin < i.end) 112 | // { 113 | // res.push_back({ begin,i.end }); 114 | // ena = true; 115 | // } 116 | // } 117 | // return res; 118 | //} 119 | 120 | T operator[](int32_t index) 121 | { 122 | for (auto i = values.begin(); i != values.end(); ++i) 123 | { 124 | if (index >= i->begin && index < i->end) 125 | { 126 | return i->value; 127 | } 128 | } 129 | if (values.size() > 0) 130 | return values[0].value; 131 | assert(0); 132 | return T(); 133 | } 134 | 135 | }; 136 | struct BreakPart : public IElement 137 | { 138 | UChar* ucs; 139 | int32_t len; 140 | IFontFace* face; 141 | UScriptCode script; 142 | 143 | Math3D::Vector2 size; 144 | bool rtl = false; 145 | std::vector glyfOffset; 146 | std::vector glyfScale; 147 | std::vector glyfs; 148 | //int32_t charIndex; 149 | //int32_t charLength; 150 | BreakPart() 151 | { 152 | ucs = nullptr; 153 | len = 0; 154 | face = nullptr; 155 | script = USCRIPT_INVALID_CODE; 156 | size = { 0,0 }; 157 | } 158 | RLL::Size Size(ElementProps* parentProps) 159 | { 160 | return RLL::Size(size); 161 | } 162 | LANG_DIRECTION Direction() { return rtl ? LANG_DIRECTION_RL : LANG_DIRECTION_LR; } 163 | ScriptCode Script() { return script; }; 164 | void Place(Math3D::Matrix4x4* parentTransform, RenderList renderList) 165 | { 166 | NOIMPL; 167 | } 168 | }; 169 | ; 170 | void* text; 171 | int32_t textLen; 172 | RLL::Size contentSize; 173 | LANG_DIRECTION direction = LANG_DIRECTION_LR_TB; 174 | LINE_ALIGN lineAlign = LINE_ALIGN_START; 175 | PARA_ALIGN paraAlign = PARA_ALIGN_START; 176 | Range ffaces; 177 | Range fsizes; 178 | std::vector parts; 179 | 180 | public: 181 | void Metrics(); 182 | void Break(); 183 | void Place(RLL::ISVGBuilder*); 184 | public: 185 | TextLayout(wchar_t* text, RLL::Size size, RLL::IFontFace* fface); 186 | void SetParagraphAlign(PARA_ALIGN align); 187 | void SetLineAlign(LINE_ALIGN align); 188 | void SetFontFace(RLL::IFontFace* ff, int32_t begin, int32_t len); 189 | RLL::ISVG* Commit(RLL::IPaintDevice* dvc); 190 | void Dispose(); 191 | }; 192 | } -------------------------------------------------------------------------------- /RLL/TextLayout.cpp: -------------------------------------------------------------------------------- 1 | #include "TextInterfaces.h" 2 | #include "fi_ft.h" 3 | 4 | #include "unicode/ucnv.h" 5 | #include "unicode/ubidi.h" 6 | #include "unicode/ustring.h" 7 | #include "unicode/brkiter.h" 8 | 9 | #include "harfbuzz/hb.h" 10 | #include "harfbuzz/hb-ft.h" 11 | #include "harfbuzz/hb-icu.h" 12 | 13 | #pragma comment(lib, "harfbuzz.lib") 14 | #pragma comment(lib, "harfbuzz-icu.lib") 15 | 16 | #pragma comment(lib, "icuuc.lib") 17 | #pragma comment(lib, "icutu.lib") 18 | #pragma comment(lib, "icuio.lib") 19 | #pragma comment(lib, "icuin.lib") 20 | #pragma comment(lib, "icudt.lib") 21 | 22 | using namespace RLL; 23 | using namespace icu; 24 | using namespace Math3D; 25 | 26 | TextLayout::TextLayout(wchar_t* text, RLL::Size sz, IFontFace* fface) 27 | { 28 | UErrorCode uec = U_ZERO_ERROR; 29 | contentSize = sz; 30 | textLen = wcslen(text); 31 | this->text = new UChar[textLen + 1]; 32 | u_strFromWCS((UChar*)this->text, textLen + 1, &textLen, text, textLen, &uec); 33 | 34 | ffaces.Set(0, -1, fface); 35 | fsizes.Set(0, -1, 12); 36 | //fsizes.Set(2, 8, 16); 37 | 38 | } 39 | void TextLayout::SetFontFace(RLL::IFontFace* ff, int32_t begin, int32_t len) 40 | { 41 | 42 | } 43 | FTFace* GetFTFace(IFontFace* f, char16_t c) 44 | { 45 | FTFace* ftf = dynamic_cast(f); 46 | if (!ftf) 47 | { 48 | auto fs = dynamic_cast(f); 49 | ftf = (FTFace*)fs->GetFace(c); 50 | } 51 | return ftf; 52 | } 53 | bool bidi_ltr(LANG_DIRECTION d) 54 | { 55 | return (d == LANG_DIRECTION_BT_LR || LANG_DIRECTION_TB_LR || LANG_DIRECTION_LR_TB || LANG_DIRECTION_LR_BT); 56 | } 57 | void TextLayout::Break() 58 | { 59 | std::vector fs_bidi; 60 | std::vector fs_ucs; 61 | std::vector fs_script; 62 | //hb_font_t* hbf = hb_ft_font_create_referenced(ftf->face); 63 | BreakPart fs; 64 | UErrorCode uec = U_ZERO_ERROR; 65 | UChar* uTex = (UChar*)text; 66 | //break bidi 67 | { 68 | UBiDi* bidi = ubidi_open(); 69 | UBiDiLevel bidiReq = bidi_ltr(direction) ? UBIDI_DEFAULT_LTR : UBIDI_DEFAULT_RTL; 70 | ubidi_setPara(bidi, uTex, textLen, bidiReq, NULL, &uec); 71 | if (U_SUCCESS(uec)) { 72 | //int paraDir = ubidi_getParaLevel(bidi); 73 | size_t rc = ubidi_countRuns(bidi, &uec); 74 | for (size_t i = 0; i < size_t(rc); ++i) 75 | { 76 | int32_t startRun = -1; 77 | int32_t lengthRun = -1; 78 | UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun); 79 | fs.ucs = uTex + startRun; 80 | fs.len = lengthRun; 81 | fs.rtl = runDir == UBIDI_RTL; 82 | fs_bidi.push_back(fs); 83 | } 84 | } 85 | ubidi_close(bidi); 86 | } 87 | //break font styles 88 | for (auto& s : fs_bidi) 89 | { 90 | fs = s; 91 | auto j = s.ucs - uTex; 92 | int32_t b = 0; 93 | FTFace* ftf = GetFTFace(ffaces[j], ((char16_t*)s.ucs)[j]); 94 | for (int i = 0; i < s.len; i++) 95 | { 96 | auto n = j + i; 97 | if (ftf != GetFTFace(ffaces[n], ((char16_t*)s.ucs)[i])) 98 | { 99 | if (i - b > 0) 100 | { 101 | fs.ucs = &(s.ucs)[b]; 102 | fs.len = i - b; 103 | fs.face = ftf; 104 | fs_ucs.push_back(fs); 105 | } 106 | b = i; 107 | ftf = GetFTFace(ffaces[n], ((char16_t*)s.ucs)[i]); 108 | } 109 | } 110 | fs.ucs = &(s.ucs)[b]; 111 | fs.len = s.len - b; 112 | fs.face = ftf; 113 | fs_ucs.push_back(fs); 114 | } 115 | 116 | for (auto& i : fs_ucs) 117 | { 118 | fs = i; 119 | int b = 0; 120 | fs.script = USCRIPT_COMMON; 121 | UChar32* uc32 = new UChar32[i.len]; 122 | u_strToUTF32(uc32, i.len, nullptr, i.ucs, i.len, &uec); 123 | for (auto n = 0; n < i.len; n++) 124 | { 125 | //UChar32 c32 = 0; 126 | //u_strToUTF32(&c32, 1, nullptr, &i.ucs[n], 1, &uec); 127 | uec = U_ZERO_ERROR; 128 | auto sc = uscript_getScript(uc32[n], &uec); 129 | if (!U_SUCCESS(uec)) 130 | { 131 | sc = USCRIPT_COMMON; 132 | } 133 | uec = U_ZERO_ERROR; 134 | if (fs.script != sc) 135 | { 136 | if (n - b > 0) 137 | { 138 | fs.len = n - b; 139 | fs_script.push_back(fs); 140 | fs.ucs = i.ucs + n; 141 | b = n; 142 | } 143 | fs.script = sc; 144 | } 145 | } 146 | delete uc32; 147 | fs.ucs = &(i.ucs)[b]; 148 | fs.len = i.len - b; 149 | fs_script.push_back(fs); 150 | } 151 | 152 | 153 | 154 | UBiDi* bidi = ubidi_open(); 155 | UBiDiLevel bidiReq = UBIDI_DEFAULT_LTR; 156 | //std::vector brk_ucs; 157 | auto brki = icu::BreakIterator::createLineInstance(icu::Locale::getDefault(), uec); 158 | 159 | for (auto& i : fs_script) 160 | { 161 | fs = i; 162 | auto utx = utext_openUChars(nullptr, i.ucs, i.len, &uec); 163 | brki->setText(utx, uec); 164 | int32_t p = brki->first(); 165 | int32_t p_l = p; 166 | while (p != icu::BreakIterator::DONE) { 167 | //printf("Boundary at position %d\n", p); 168 | if (p_l != p) 169 | { 170 | int32_t wlen = p - p_l; 171 | //UChar* word = new UChar[p - p_l + 1]{ 0 }; 172 | //utext_extract(utx, p_l, p, word, p - p_l + 1, &uec); 173 | fs.face = i.face; 174 | fs.len = wlen; 175 | fs.ucs = &i.ucs[p_l]; 176 | fs.script = i.script; 177 | parts.push_back(fs); 178 | } 179 | p_l = p; 180 | p = brki->next(); 181 | } 182 | 183 | utext_close(utx); 184 | } 185 | delete brki; 186 | 187 | } 188 | void TextLayout::Metrics() 189 | { 190 | UErrorCode uec = U_ZERO_ERROR; 191 | auto dpi = RLL::GetScale() * 96; 192 | for (auto& p : parts) 193 | { 194 | uec = U_ZERO_ERROR; 195 | if (!U_SUCCESS(uec)) 196 | { 197 | assert(0); 198 | } 199 | auto f = dynamic_cast(p.face); 200 | FT_Set_Char_Size(f->face, 72 * 64, 0, 32, 32); 201 | Math3D::Vector2 scale( 202 | f->face->size->metrics.x_scale / 65536.f * f->face->units_per_EM, 203 | f->face->size->metrics.y_scale / 65536.f * f->face->units_per_EM); 204 | 205 | auto hbf = hb_ft_font_create_referenced(f->face); 206 | hb_buffer_t* buf = hb_buffer_create();; 207 | 208 | //u_charTo 209 | //UChar32 c32; 210 | //u_strToUTF32(&c32, 1, nullptr, &s.ucs[startRun], 1, &uec); 211 | //auto sc = uscript_getScript(c32, &uec); 212 | //printf("Processing Bidi Run = %d -- run-start = %d, run-len = %d, isRTL = %d\n", 213 | // i, startRun, lengthRun, isRTL); 214 | hb_buffer_add_utf16(buf, (uint16_t*)p.ucs, p.len, 0, -1); 215 | 216 | hb_buffer_set_script(buf, hb_icu_script_to_script(p.script)); 217 | hb_buffer_set_direction(buf, p.rtl ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); 218 | hb_buffer_set_language(buf, hb_language_from_string("en", -1)); 219 | 220 | hb_shape(hbf, buf, NULL, 0); 221 | 222 | unsigned int glyph_count; 223 | hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count); 224 | hb_glyph_position_t* glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count); 225 | //TimeCheck("Getglyf start"); 226 | float szMax = 0; float szMin = 0; 227 | Vector2 curs(0, 0); 228 | for (unsigned int i = 0; i < glyph_count; i++) { 229 | hb_codepoint_t glyphid = glyph_info[i].codepoint; 230 | hb_position_t x_offset = glyph_pos[i].x_offset; 231 | hb_position_t y_offset = glyph_pos[i].y_offset; 232 | hb_position_t x_advance = glyph_pos[i].x_advance; 233 | hb_position_t y_advance = glyph_pos[i].y_advance; 234 | /* draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset); */ 235 | //std::cout << x_advance / 64.f << "\t" << y_advance / 64.f << std::endl; 236 | //TODO: 237 | /* 238 | * make size, scale, every font size...; 239 | * 240 | */ 241 | auto fsz = fsizes[glyph_info[i].cluster]; 242 | GlyphMetrics gmet; 243 | auto sg = p.face->GetGlyph(glyphid, &gmet); 244 | Vector2 adv(x_advance, y_advance); 245 | auto gsc = Vector2(fsz * dpi.x / 72.f, fsz * dpi.y / 72.f); 246 | p.size.y = gsc.y; 247 | p.size.x += adv.x / scale.x * gsc.x; //horizontal layout only 248 | if (gmet.size.y * gsc.y > szMax) 249 | szMax = gmet.size.y * gsc.y; 250 | p.glyfs.push_back(sg); 251 | //bp.glyfAdvance.push_back({ xa, ya }); 252 | p.glyfOffset.push_back({ (curs.x + x_offset) / scale.x * gsc.x ,(curs.y + y_offset) / scale.y * gsc.y }); 253 | curs += adv; 254 | p.glyfScale.push_back(gsc); 255 | } 256 | hb_buffer_destroy(buf); 257 | p.size.y = szMax - szMin; 258 | 259 | hb_font_destroy(hbf); 260 | } 261 | //ubidi_close(bidi); 262 | } 263 | 264 | void TextLayout::Place(ISVGBuilder* sb) 265 | { 266 | struct BIDIPart 267 | { 268 | std::vector parts; 269 | bool rtl = false; 270 | }; 271 | struct LinePart 272 | { 273 | std::vector parts; 274 | std::vector bidis; 275 | Size size; 276 | }; 277 | std::vector lines; 278 | LinePart cLine; 279 | //horizontal only 280 | 281 | //calculate line metrics 282 | { 283 | for (auto& i : parts) 284 | { 285 | if (cLine.size.x + i.size.x > contentSize.x) 286 | { 287 | if (cLine.parts.size() > 0) 288 | { 289 | lines.push_back(cLine); 290 | cLine.parts.clear(); 291 | cLine.size = Size(0, 0); 292 | //continue; 293 | } 294 | } 295 | cLine.parts.push_back(i); 296 | cLine.size.x += i.size.x; 297 | 298 | if (i.size.y > cLine.size.y) 299 | { 300 | cLine.size.y = i.size.y; 301 | } 302 | } 303 | if (cLine.parts.size() > 0) 304 | { 305 | lines.push_back(cLine); 306 | } 307 | } 308 | 309 | //bidi lines 310 | { 311 | for (auto& l : lines) 312 | { 313 | bool inv = false; 314 | //fix two terminal of the line's COMMON_SCRIPT bidi info 315 | for (auto k = 0; k < l.parts.size(); k++) 316 | { 317 | if (l.parts[k].script == USCRIPT_COMMON) 318 | { 319 | l.parts[k].rtl = false; 320 | } 321 | else break; 322 | } 323 | for (auto k = l.parts.size() - 1; k >= 0; k--) 324 | { 325 | if (l.parts[k].script == USCRIPT_COMMON) 326 | { 327 | l.parts[k].rtl = false; 328 | } 329 | else break; 330 | } 331 | //TODO: combine below two for, can it? 332 | BIDIPart bdp; 333 | for (auto i = 0; i < l.parts.size(); i++) 334 | { 335 | if (l.parts[i].rtl != inv) 336 | { 337 | if (bdp.parts.size() > 0) 338 | { 339 | l.bidis.push_back(bdp); 340 | bdp.parts.clear(); 341 | } 342 | bdp.rtl = l.parts[i].rtl; 343 | } 344 | inv = l.parts[i].rtl; 345 | bdp.parts.push_back(l.parts[i]); 346 | 347 | } 348 | if (bdp.parts.size() > 0) 349 | l.bidis.push_back(bdp); 350 | bdp.parts.clear(); 351 | l.parts.clear(); 352 | for (auto& i : l.bidis) 353 | { 354 | if (i.rtl) 355 | { 356 | for (auto it = i.parts.rbegin(); it != i.parts.rend(); ) 357 | { 358 | l.parts.push_back(*it); 359 | ++it; 360 | } 361 | } 362 | else 363 | { 364 | for (auto it = i.parts.begin(); it != i.parts.end(); ) 365 | { 366 | l.parts.push_back(*it); 367 | ++it; 368 | } 369 | } 370 | } 371 | } 372 | } 373 | 374 | float2 cursor(0, 0); 375 | for (int i = 0; i < lines.size(); i++) 376 | { 377 | cursor.y += lines[i].size.y * 1.2f; 378 | cursor.x = 0; 379 | for (auto& n : lines[i].parts) 380 | { 381 | for (int j = 0; j < n.glyfs.size(); j++) 382 | { 383 | if (n.glyfs[j]) 384 | sb->Push(n.glyfs[j], &Matrix4x4::TRS( 385 | Vector3(cursor + n.glyfOffset[j]), Quaternion::identity(), 386 | Vector3(n.glyfScale[j].x, n.glyfScale[j].y, 1))); 387 | //auto o = cursor + n.glyfOffset[j]; 388 | //sb->Push(n.glyfs[j], 389 | // &(Matrix4x4::Scaling({ n.glyfScale[j].x, n.glyfScale[j].y, 1 }) * 390 | // Matrix4x4::Translation({ j * 16.f,i * 16.f,0 })) 391 | //); 392 | } 393 | cursor.x += n.size.x; 394 | } 395 | } 396 | } 397 | void TextLayout::SetParagraphAlign(PARA_ALIGN axis) 398 | { 399 | NOIMPL; 400 | } 401 | void TextLayout::SetLineAlign(LINE_ALIGN axis) 402 | { 403 | NOIMPL; 404 | } 405 | RLL::ISVG* TextLayout::Commit(RLL::IPaintDevice* dvc) 406 | { 407 | Break(); 408 | Metrics(); 409 | auto sb = dvc->CreateSVGBuilder(); 410 | Place(sb); 411 | auto svg = sb->Commit(); 412 | sb->Release(); 413 | NOIMPL; //TODO: Layout 414 | return svg; 415 | } 416 | void TextLayout::Dispose() 417 | { 418 | delete[] text; 419 | NOIMPL; 420 | } 421 | 422 | void RLL::TextLayoutInit() //abandoned 423 | { 424 | //return; 425 | hb_buffer_t* buf; 426 | buf = hb_buffer_create(); 427 | hb_buffer_add_utf16(buf, (uint16_t*)L"اللغة العربية", -1, 0, -1); 428 | hb_buffer_set_direction(buf, HB_DIRECTION_RTL); 429 | hb_buffer_set_script(buf, HB_SCRIPT_ARABIC); 430 | hb_buffer_set_language(buf, hb_language_from_string("en", -1)); 431 | 432 | hb_blob_t* blob = hb_blob_create_from_file("c:/windows/fonts/arial.ttf"); /* or hb_blob_create_from_file_or_fail() */ 433 | hb_face_t* face = hb_face_create(blob, 0); 434 | hb_font_t* font = hb_font_create(face); 435 | 436 | hb_shape(font, buf, NULL, 0); 437 | 438 | hb_buffer_destroy(buf); 439 | hb_font_destroy(font); 440 | hb_face_destroy(face); 441 | hb_blob_destroy(blob); 442 | } -------------------------------------------------------------------------------- /RLL/TextProperty.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Metrics.h" 3 | 4 | enum TEXT_RENDER_FLAG { 5 | NONE = 0, 6 | USE_HINT = 1 << 1, 7 | DYNAMIC_HINT = 1 << 2, 8 | }; 9 | inline TEXT_RENDER_FLAG operator|(TEXT_RENDER_FLAG a, TEXT_RENDER_FLAG b) 10 | { 11 | return static_cast(static_cast(a) | static_cast(b)); 12 | } -------------------------------------------------------------------------------- /RLL/ThirdParty.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "unicode/uscript.h" 3 | 4 | 5 | namespace RLL 6 | { 7 | typedef UScriptCode ScriptCode; 8 | } -------------------------------------------------------------------------------- /RLL/Win32impl.cpp: -------------------------------------------------------------------------------- 1 | #include "Sharp.h" 2 | #include "windows.h" 3 | using namespace Sharp; 4 | #ifdef NOSTL 5 | FileStream::FileStream(String path, FileMode mode, FileAccess accs) 6 | { 7 | if (path.IsEmpty()) 8 | { 9 | throw Exception("Invalid argument: empty path"); 10 | } 11 | this->path = path; 12 | fmode = mode; 13 | faccs = accs; 14 | DWORD m = 0, a = 0; 15 | switch (mode) 16 | { 17 | case FileMode::Create: 18 | m = OPEN_ALWAYS; 19 | break; 20 | case FileMode::CreateNew: 21 | m = CREATE_NEW; 22 | break; 23 | case FileMode::Open: 24 | m = OPEN_EXISTING; 25 | break; 26 | case FileMode::OpenCreate: 27 | m = CREATE_ALWAYS; 28 | break; 29 | case FileMode::Truncate: 30 | m = TRUNCATE_EXISTING; 31 | break; 32 | case FileMode::Append: 33 | m = OPEN_EXISTING; 34 | break; 35 | default: 36 | break; 37 | } 38 | switch (accs) 39 | { 40 | case FileAccess::Read: 41 | a = GENERIC_READ; 42 | break; 43 | case FileAccess::Write: 44 | a = GENERIC_WRITE; 45 | break; 46 | case FileAccess::ReadWrite: 47 | a = GENERIC_READ | GENERIC_WRITE; 48 | break; 49 | default: 50 | break; 51 | } 52 | handle = CreateFile(path.CString(), a, 0, 0, m, FILE_ATTRIBUTE_NORMAL, 0); 53 | if (handle == 0) throw Exception("Open|Create file failed."); 54 | if (mode == FileMode::Append) 55 | SetFilePointer(handle, 0, 0, FILE_END); 56 | } 57 | bool FileStream::CanRead() 58 | { 59 | return handle && (faccs == FileAccess::Read || faccs == FileAccess::ReadWrite); 60 | } 61 | bool FileStream::CanWrite() 62 | { 63 | return handle && (faccs == FileAccess::Write || faccs == FileAccess::ReadWrite); 64 | 65 | } 66 | bool FileStream::CanSeek() 67 | { 68 | return true; 69 | } 70 | int64_t FileStream::Length() 71 | { 72 | LARGE_INTEGER len; 73 | GetFileSizeEx(handle, &len); 74 | return len.QuadPart; 75 | } 76 | int64_t FileStream::Read(Byte* buffer, int64_t len) 77 | { 78 | DWORD rlen = 0; 79 | if (!ReadFile(handle, buffer, len, &rlen, NULL)) throw Exception("ReadFile failed."); 80 | return rlen; 81 | } 82 | int64_t FileStream::Write(Byte* buffer, int64_t len) 83 | { 84 | DWORD rlen = 0; 85 | if (!WriteFile(handle, buffer, len, &rlen, NULL)) throw Exception("WriteFile failed."); 86 | return rlen; 87 | } 88 | void FileStream::Seek(int64_t offset, SeekOrigin origin) 89 | { 90 | DWORD mm; 91 | switch (origin) 92 | { 93 | case SeekOrigin::Current: 94 | mm = FILE_CURRENT; 95 | break; 96 | case SeekOrigin::Start: 97 | mm = FILE_BEGIN; 98 | break; 99 | case SeekOrigin::End: 100 | mm = FILE_END; 101 | break; 102 | default: 103 | break; 104 | } 105 | LARGE_INTEGER li; 106 | li.QuadPart = offset; 107 | if (!SetFilePointerEx(handle, li, NULL, mm)) throw Exception("SeekFile failed."); 108 | } 109 | void FileStream::Flush() 110 | { 111 | FlushFileBuffers(handle); 112 | } 113 | int64_t FileStream::Position() 114 | { 115 | LARGE_INTEGER li; 116 | li.QuadPart = 0; 117 | LARGE_INTEGER rli; 118 | if (!SetFilePointerEx(handle, li, &rli, FILE_CURRENT)) throw Exception("Get file position failed."); 119 | return li.QuadPart; 120 | 121 | } 122 | void FileStream::Position(int64_t pos) 123 | { 124 | LARGE_INTEGER li; 125 | li.QuadPart = pos; 126 | if (!SetFilePointerEx(handle, li, NULL, FILE_BEGIN)) throw Exception("Get file position failed."); 127 | } 128 | void FileStream::Close() 129 | { 130 | CloseHandle(handle); 131 | } 132 | #endif -------------------------------------------------------------------------------- /RLL/curve_tools.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Metrics.h" 3 | #include 4 | #include 5 | 6 | namespace util 7 | { 8 | inline Math3D::Vector2 Lerp(float t, Math3D::Vector2 a, Math3D::Vector2 b) 9 | { 10 | return a + (b - a) * t; 11 | } 12 | inline Math3D::Vector2 QuadraticBezier(float t, Math3D::Vector2 b, Math3D::Vector2 c, Math3D::Vector2 e) 13 | { 14 | return Lerp(t, Lerp(t, b, c), Lerp(t, c, e)); 15 | // = b+(c-b)*t + c+(e-c)*t 16 | } 17 | inline Math3D::Vector2 QuadraticBezierTangent(float t, Math3D::Vector2 b, Math3D::Vector2 c, Math3D::Vector2 e) 18 | { 19 | return (Lerp(t, c, e) - Lerp(t, b, c)) * 2; 20 | //= c + (e - c) * t - ( b + (c - b) * t) 21 | //= c + e * t - c * t - b - c * t + b * t 22 | //= t*(e - 2c + b) + c - b 23 | //*2 = 2 * t(e - 2c + b) + 2c - 2b 24 | //' = 2(e - 2c + b) 25 | } 26 | inline Math3D::Vector2 dQBezierTangent(Math3D::Vector2 b, Math3D::Vector2 c, Math3D::Vector2 e) 27 | { 28 | return (e - c * 2 + b) * 2; 29 | } 30 | inline float CurvatureQBezier(float t, Math3D::Vector2 b, Math3D::Vector2 c, Math3D::Vector2 e) 31 | { 32 | auto dC = QuadraticBezierTangent(t, b, c, e); 33 | auto ddC = dQBezierTangent(b, c, e); 34 | float k = abs(dC.x * ddC.y - dC.y * ddC.x) / pow(dC.x * dC.x + dC.y * dC.y, 1.5f); 35 | return k; 36 | } 37 | inline Math3D::Vector2 CubicBezier(float t, Math3D::Vector2 b, Math3D::Vector2 c1, Math3D::Vector2 c2, Math3D::Vector2 e) 38 | { 39 | return Lerp(t, QuadraticBezier(t, b, c1, c2), QuadraticBezier(t, c1, c2, e)); 40 | } 41 | inline void TrianglePPTT( 42 | Math3D::Vector2 pb, Math3D::Vector2 pe, 43 | Math3D::Vector2 tb, Math3D::Vector2 te, 44 | Math3D::Vector2& c) 45 | { 46 | #define csconv(s) sqrtf(1 - (s)*(s)) 47 | auto be = pe - pb; 48 | auto cb = Math3D::Vector2::Dot(be, tb) / be.Magnitude() / tb.Magnitude(); 49 | auto ce = Math3D::Vector2::Dot(be, te) / be.Magnitude() / te.Magnitude(); 50 | auto b = acosf(cb); 51 | auto e = acosf(ce); 52 | auto sc = sinf(b + e); 53 | auto bc_l = sinf(e) * be.Magnitude() / sc; 54 | c = pb + tb.Normalized() * bc_l; 55 | } 56 | 57 | inline float MaximalResolve(std::function eq, float mi, float ma) 58 | { 59 | float ep = 0.0001f; 60 | float l = mi; float r = ma; 61 | while (abs(l - r) > ep) 62 | { 63 | float m = 0.5f * (l + r); 64 | float vl = eq(l); 65 | float vr = eq(r); 66 | if (vl > vr) 67 | r = m; 68 | else 69 | l = m; 70 | auto dbg = vl + vr; 71 | } 72 | return 0.5f * (l + r); 73 | } 74 | 75 | inline float dCurQB(float t, Math3D::Vector2 b, Math3D::Vector2 c, Math3D::Vector2 e) 76 | { 77 | auto dC = QuadraticBezierTangent(t, b, c, e); 78 | auto ddC = dQBezierTangent(b, c, e); 79 | float u = ((ddC.x * dC.x + ddC.y * dC.y) * -3.f); 80 | float v = powf(dC.x * dC.x + dC.y * dC.y, 2.5f); 81 | return u / v; 82 | } 83 | 84 | inline Math3D::Vector2 Ellipse(Math3D::Vector2 radius, float r) 85 | { 86 | return Math3D::Vector2(radius.x * cosf(r), radius.y * sinf(r)); 87 | } 88 | 89 | inline float EllipseDistance(Math3D::Vector2 radius, float rad) 90 | { 91 | return sqrtf(radius.x * cosf(rad) * radius.x * cosf(rad) + radius.y * radius.y * sinf(rad) * sinf(rad)); 92 | } 93 | 94 | inline Math3D::Vector2 EllipseTangent(Math3D::Vector2 radius, float rad) 95 | { 96 | return Math3D::Vector2(radius.x * -sinf(rad), radius.y * cosf(rad)); 97 | } 98 | inline Math3D::Vector2 Normal(Math3D::Vector2 v) 99 | { 100 | return ((v)*Math3D::Matrix4x4::Rotation(0, 0, -3.1415926f / 2)); 101 | } 102 | 103 | //return seg count 104 | inline int QBezierExpand(Math3D::Vector2 b, Math3D::Vector2 c, Math3D::Vector2 e, float s, 105 | Math3D::Vector2* o_b, Math3D::Vector2* o_c, Math3D::Vector2* o_e) 106 | { 107 | auto maxt = util::MaximalResolve([&](float t) {return util::CurvatureQBezier(t, b, c, e); }, 0, 1); 108 | auto maxc = util::CurvatureQBezier(maxt, b, c, e) * (e - b).Magnitude(); 109 | 110 | if (maxc > 3.f) 111 | { 112 | // 2 seg 113 | auto rb1 = b; 114 | auto rb2 = util::QuadraticBezier(maxt, b, c, e); 115 | auto rb3 = e; 116 | 117 | auto tb1 = (c - b).Normalized(); 118 | auto tb2 = util::QuadraticBezierTangent(maxt, b, c, e).Normalized(); 119 | auto tb3 = (e - c).Normalized(); 120 | 121 | auto nb1 = Normal(tb1).Normalized(); 122 | auto nb2 = Normal(tb2).Normalized(); 123 | auto nb3 = Normal(tb3).Normalized(); 124 | 125 | auto pb1 = rb1 + nb1 * s; 126 | auto pb2 = rb2 + nb2 * s; 127 | auto pb3 = rb3 + nb3 * s; 128 | 129 | Math3D::Vector2 c1, c2; 130 | util::TrianglePPTT(pb1, pb2, tb1, tb2, c1); 131 | util::TrianglePPTT(pb2, pb3, tb2, tb3, c2); 132 | o_b[0] = pb1; 133 | o_c[0] = c1; 134 | o_e[0] = pb2; 135 | 136 | o_b[1] = pb2; 137 | o_c[1] = c2; 138 | o_e[1] = pb3; 139 | return 2; 140 | } 141 | else if (maxc > 0.0001f) 142 | { 143 | //1 seg 144 | auto tb = c - b; 145 | auto te = e - c; 146 | auto nb = Normal(tb).Normalized(); 147 | auto ne = Normal(te).Normalized(); 148 | 149 | Math3D::Vector2 con; 150 | util::TrianglePPTT(b + nb * s, e + ne * s, 151 | tb, te, 152 | con 153 | ); 154 | o_b[0] = b + nb * s; 155 | o_c[0] = con; 156 | o_e[0] = e + ne * s; 157 | return 1; 158 | } 159 | else 160 | { 161 | auto tb = c - b; 162 | auto te = e - c; 163 | auto nb = Normal(tb).Normalized(); 164 | auto ne = Normal(te).Normalized(); 165 | 166 | o_b[0] = b + nb * s; 167 | o_e[0] = e + ne * s; 168 | o_c[0] = o_b[0] + tb; 169 | return 1; 170 | } 171 | return 0; 172 | } 173 | } 174 | 175 | // -------------------------------------------------------------------------------- /RLL/delegate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | template 6 | class _delegate_class_mem 7 | { 8 | public: 9 | typedef R(C::* class_func_type)(Args...); 10 | 11 | _delegate_class_mem(class_func_type fun, C* class_ptr) :_fun(fun), _class_ptr(class_ptr) {} 12 | 13 | R operator()(Args&&...args) 14 | { 15 | return (_class_ptr->*_fun)(args...); 16 | } 17 | 18 | 19 | bool operator== (const _delegate_class_mem& other) const 20 | { 21 | if (_class_ptr == other._class_ptr && _fun == other._fun) 22 | return true; 23 | return false; 24 | } 25 | 26 | template 27 | bool operator==(const T&&)const 28 | { 29 | return false; 30 | } 31 | 32 | private: 33 | C* _class_ptr; 34 | class_func_type _fun; 35 | 36 | }; 37 | 38 | 39 | template 40 | class delegate { }; 41 | 42 | 43 | template 44 | class delegate 45 | { 46 | public: 47 | typedef std::function dele_func; 48 | typedef std::list function_list; 49 | typedef R(*func_type)(Args...); 50 | typedef delegate this_type; 51 | 52 | 53 | delegate() 54 | { 55 | }; 56 | 57 | ~delegate() 58 | { 59 | func_list.clear(); 60 | } 61 | 62 | 63 | this_type& operator -=(func_type fun) 64 | { 65 | auto itr = std::find_if(func_list.begin(), func_list.end(), 66 | [&](dele_func& f)->bool 67 | { 68 | auto _fun = f.target(); 69 | if (_fun && *_fun == fun) 70 | { 71 | return true; 72 | } 73 | return false; 74 | }); 75 | 76 | if (itr != func_list.end()) 77 | func_list.erase(itr); 78 | 79 | return *this; 80 | } 81 | 82 | template 83 | this_type& operator -=(_delegate_class_mem&& class_mem_h) 84 | { 85 | auto itr = std::find_if(func_list.begin(), func_list.end(), 86 | [&](dele_func& f)->bool 87 | { 88 | auto _fun = f.target<_delegate_class_mem>(); 89 | if (_fun && *_fun == class_mem_h) 90 | { 91 | return true; 92 | } 93 | return false; 94 | }); 95 | 96 | 97 | if (itr != func_list.end()) 98 | { 99 | func_list.erase(itr); 100 | } 101 | return *this; 102 | } 103 | 104 | 105 | this_type& operator +=(func_type fun) 106 | { 107 | func_list.push_back(fun); 108 | return *this; 109 | } 110 | 111 | template 112 | this_type& operator +=(_delegate_class_mem&& class_mem_h) 113 | { 114 | func_list.push_back(class_mem_h); 115 | return *this; 116 | } 117 | 118 | void operator()(Args&&...args) 119 | { 120 | for (auto itr = func_list.begin(); itr != func_list.end(); itr++) 121 | { 122 | (*itr)(args...); 123 | 124 | //try 125 | //{ 126 | // (*itr)(args...); 127 | //} 128 | //catch (std::exception ex) 129 | //{ 130 | // //do something... 131 | //} 132 | } 133 | } 134 | 135 | 136 | private: 137 | function_list func_list; 138 | }; 139 | 140 | 141 | template 142 | auto makeDelegateClassHelper(R(C::* class_func_type)(Args...), C* class_ptr) -> _delegate_class_mem 143 | { 144 | return _delegate_class_mem(class_func_type, class_ptr); 145 | } 146 | -------------------------------------------------------------------------------- /RLL/fi_ft.cpp: -------------------------------------------------------------------------------- 1 | #include "fi_ft.h" 2 | #include "freetype/freetype.h" 3 | #include "freetype/ftoutln.h" 4 | #include "freetype/ftbbox.h" 5 | #include "freetype/ftbitmap.h" 6 | 7 | #define NO_TIMECHECKER 8 | #include "perf_util.h" 9 | 10 | #pragma comment(lib, "freetype.lib") 11 | using namespace RLL; 12 | using namespace Math3D; 13 | 14 | FT_Outline_Funcs dcomp_funcs; 15 | 16 | struct DecompParam 17 | { 18 | float scale; 19 | int index = 0; 20 | IGeometryBuilder* gb; 21 | }; 22 | int dcomp_qbezier(const FT_Vector* control, const FT_Vector* to, void* p) 23 | { 24 | DecompParam* bd = (DecompParam*)p; 25 | auto gb = bd->gb; 26 | auto s = bd->scale; 27 | if (bd->index == 0) 28 | { 29 | gb->Begin({ 0,0 }); 30 | } 31 | gb->QuadraticTo( 32 | { (float)control->x * s ,-(float)control->y * s }, 33 | { (float)to->x * s ,-(float)to->y * s }); 34 | bd->index++; 35 | //std::cout << "qb\t" << (float)control->x * s << "," << -(float)control->y * s << "; " << (float)to->x * s << "," << -(float)to->y * s << std::endl; 36 | return 0; 37 | } 38 | int dcomp_mvto(const FT_Vector* pos, void* p) 39 | { 40 | DecompParam* bd = (DecompParam*)p; 41 | auto gb = bd->gb; 42 | auto s = bd->scale; 43 | if (bd->index != 0) 44 | { 45 | gb->End(false); 46 | //bd->index = 0; 47 | } 48 | gb->Begin({ (float)pos->x * s, -(float)pos->y * s }); 49 | bd->index++; 50 | //std::cout << "mv\t" << (float)pos->x * s << "," << -(float)pos->y * s << std::endl; 51 | return 0; 52 | } 53 | int dcomp_lineto(const FT_Vector* to, void* p) 54 | { 55 | DecompParam* bd = (DecompParam*)p; 56 | auto gb = bd->gb; 57 | auto s = bd->scale; 58 | if (bd->index == 0) 59 | { 60 | gb->Begin({ 0,0 }); 61 | } 62 | gb->LineTo({ (float)to->x * s ,-(float)to->y * s }); 63 | bd->index++; 64 | //std::cout << "li\t" << (float)to->x * s << "," << -(float)to->y * s << std::endl; 65 | return 0; 66 | } 67 | int dcomp_cbezier(const FT_Vector* c1, const FT_Vector* c2, const FT_Vector* to, void* p) 68 | { 69 | DecompParam* bd = (DecompParam*)p; 70 | auto gb = bd->gb; 71 | auto s = bd->scale; 72 | if (bd->index == 0) 73 | { 74 | gb->Begin({ 0,0 }); 75 | } 76 | gb->CubicTo({ (float)c1->x * s ,-(float)c1->y * s }, 77 | { (float)c2->x * s ,-(float)c2->y * s }, 78 | { (float)to->x * s ,-(float)to->y * s } 79 | ); 80 | bd->index++; 81 | //std::cout << "cb\t" << (float)to->x * s << "," << -(float)to->y * s << std::endl; 82 | return 0; 83 | } 84 | 85 | IFontFactory* RLL::CreateFontFactory(IPaintDevice* device) 86 | { 87 | dcomp_funcs.conic_to = dcomp_qbezier; 88 | dcomp_funcs.cubic_to = dcomp_cbezier; 89 | dcomp_funcs.move_to = dcomp_mvto; 90 | dcomp_funcs.line_to = dcomp_lineto; 91 | dcomp_funcs.delta = 0; 92 | dcomp_funcs.shift = 0; 93 | 94 | 95 | 96 | return new FTFactory(device); 97 | } 98 | FTFactory::FTFactory(IPaintDevice* d) 99 | { 100 | FT_Init_FreeType(&lib); 101 | device = d; 102 | notdef = nullptr; 103 | //auto sb = d->CreateSVGBuilder(); 104 | //auto gb = d->CreateGeometryBuilder(); 105 | //gb->Rectangle({ 0,-1 }, { 1,0 }); 106 | //gb->Rectangle({ 0.1,-0.9 }, { 0.9,-0.1 }, true); 107 | //sb->Push(gb->Fill()); 108 | //notdef = sb->Commit(); 109 | //gb->Release(); 110 | //sb->Release(); 111 | } 112 | 113 | 114 | RLL::IFontFace* FTFactory::LoadFromFile(char* path) 115 | { 116 | auto fc = new FTFace(); 117 | fc->factory = this; 118 | if (FT_New_Face(lib, path, 0, &fc->face)) //seguiemj.ttf arial.ttf 119 | { 120 | delete fc; 121 | SetError("Load font file error."); 122 | std::cout << "Font file " << path << " no found." << std::endl; 123 | return nullptr; 124 | } 125 | fc->Load(); 126 | return fc; 127 | 128 | } 129 | void FTFace::Load() 130 | { 131 | FT_Palette_Data palinfo; 132 | FT_Palette_Data_Get(face, &palinfo); 133 | brushes = new IBrush * [palinfo.num_palette_entries]{ nullptr }; 134 | cache_svg = new ISVG * [face->num_glyphs]{ nullptr }; 135 | } 136 | uint32_t FTFace::GetCodepoint(char32_t unicode) 137 | { 138 | return FT_Get_Char_Index(face, unicode); 139 | } 140 | 141 | RLL::IGeometry* FTFace::GetPlainGlyph(char32_t unicode, RLL::GlyphMetrics* metrics) 142 | { 143 | auto glyph_index = FT_Get_Char_Index(face, unicode); 144 | if (glyph_index == 0) return nullptr; 145 | return GetPlainGlyph(glyph_index, metrics); 146 | } 147 | RLL::IGeometry* FTFace::GetPlainGlyph(uint32_t codepoint, RLL::GlyphMetrics* metrics) 148 | { 149 | auto hr = FT_Load_Glyph(face, codepoint, FT_LOAD_COLOR | FT_LOAD_NO_SCALE); 150 | auto& gol = face->glyph->outline; 151 | DecompParam dp; 152 | dp.gb = factory->device->CreateGeometryBuilder(); 153 | dp.scale = 1.f / face->units_per_EM; 154 | dp.index = 0; 155 | FT_Outline_Decompose(&gol, &dcomp_funcs, &dp); 156 | dp.gb->End(false); 157 | auto res = dp.gb->Fill(); 158 | dp.gb->Release(); 159 | GetMetrics(metrics); 160 | return res; 161 | 162 | } 163 | void FTFace::GetMetrics(RLL::GlyphMetrics* met) 164 | { 165 | if (met) 166 | { 167 | Math3D::Vector2 scale( 168 | face->units_per_EM, 169 | face->units_per_EM); 170 | 171 | auto& m = face->glyph->metrics; 172 | met->horizontal.offset.x = m.horiBearingX / scale.x; 173 | met->horizontal.offset.y = m.horiBearingY / scale.y; 174 | met->horizontal.advance = m.horiAdvance / scale.x; 175 | met->vertical.offset.x = m.vertBearingX / scale.x; 176 | met->vertical.offset.y = m.vertBearingY / scale.y; 177 | met->vertical.advance = m.vertAdvance / scale.y; 178 | 179 | met->size.x = m.width / scale.x; 180 | met->size.y = m.height / scale.y; 181 | } 182 | 183 | } 184 | RLL::ISVG* FTFace::GetGlyph(char32_t unicode, RLL::GlyphMetrics* metrics) 185 | { 186 | auto glyph_index = FT_Get_Char_Index(face, unicode); 187 | return GetGlyph(glyph_index, metrics); 188 | } 189 | RLL::ISVG* FTFace::GetGlyph(uint32_t codepoint, RLL::GlyphMetrics* metrics) 190 | { 191 | TimeCheck("GetGlyph Begin"); 192 | auto glyph_index = codepoint; 193 | if (cache_svg[glyph_index] != nullptr) 194 | { 195 | TimeCheck("GetGlyph done. Cache hit."); 196 | TimeCheckSum(); 197 | FT_Load_Glyph(face, codepoint, FT_LOAD_COLOR | FT_LOAD_NO_SCALE); 198 | GetMetrics(metrics); 199 | return cache_svg[glyph_index]; 200 | } 201 | DecompParam dp; 202 | ISVGBuilder* sb = factory->device->CreateSVGBuilder(); 203 | dp.gb = factory->device->CreateGeometryBuilder(); 204 | dp.scale = 1.f / face->units_per_EM; 205 | IBrush* br = nullptr; 206 | FT_Color* palcol; 207 | FT_LayerIterator itr; 208 | itr.p = nullptr; 209 | itr.num_layers = 0; 210 | FT_UInt glyf_i; 211 | FT_UInt glyf_c; 212 | FT_Palette_Select(face, 0, &palcol); 213 | ISVG* res = nullptr; 214 | while (FT_Get_Color_Glyph_Layer(face, glyph_index, &glyf_i, &glyf_c, &itr)) 215 | { 216 | FT_Load_Glyph(face, glyf_i, FT_LOAD_COLOR | FT_LOAD_DEFAULT | FT_LOAD_NO_SCALE); 217 | auto& gol = face->glyph->outline; 218 | dp.gb->Reset(); 219 | dp.index = 0; 220 | FT_Outline_Decompose(&gol, &dcomp_funcs, &dp); 221 | dp.gb->End(false); 222 | if (glyf_c != 0xff) 223 | { 224 | auto col = palcol[glyf_c]; 225 | if (brushes[glyf_c] == nullptr) 226 | { 227 | brushes[glyf_c] = factory->device->CreateSolidColorBrush({ col.red / 255.f,col.green / 255.f,col.blue / 255.f,0 }); 228 | } 229 | br = brushes[glyf_c]; 230 | } 231 | else 232 | { 233 | br = nullptr; 234 | } 235 | auto geo = dp.gb->Fill(); 236 | sb->Push(geo, br); 237 | } 238 | if (!itr.num_layers) 239 | { 240 | //TimeCheck("GetGlyph no layered entry."); 241 | auto hr = FT_Load_Glyph(face, glyph_index, FT_LOAD_COLOR | FT_LOAD_NO_SCALE); 242 | GetMetrics(metrics); 243 | auto& gol = face->glyph->outline; 244 | if (gol.n_contours == 0) 245 | { 246 | if (glyph_index == 0) 247 | res = factory->notdef; 248 | else 249 | res = nullptr; 250 | } 251 | else 252 | { 253 | TimeCheck("GetGlyph decompos."); 254 | dp.index = 0; 255 | dp.gb->Reset(); 256 | FT_Outline_Decompose(&gol, &dcomp_funcs, &dp); 257 | dp.gb->End(false); 258 | TimeCheck("GetGlyph decompos done. Geom build begn"); 259 | auto geo = dp.gb->Fill(); 260 | TimeCheck("GetGlyph geom built. push"); 261 | if (geo) 262 | sb->Push(geo, nullptr); 263 | TimeCheck("GetGlyph svg commit begin."); 264 | res = sb->Commit(); 265 | TimeCheck("GetGlyph svg commited."); 266 | } 267 | } 268 | else 269 | { 270 | res = sb->Commit(); 271 | //TimeCheck("GetGlyph layered svg commited."); 272 | FT_Load_Glyph(face, glyph_index, FT_LOAD_COLOR | FT_LOAD_NO_SCALE); 273 | GetMetrics(metrics); 274 | } 275 | dp.gb->Release(); 276 | sb->Release(); 277 | cache_svg[glyph_index] = res; 278 | 279 | 280 | TimeCheck("GetGlyph done."); 281 | TimeCheckSum(); 282 | return res; 283 | } 284 | 285 | -------------------------------------------------------------------------------- /RLL/fi_ft.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "TextInterfaces.h" 3 | #include "freetype/freetype.h" 4 | #include "freetype/ftbitmap.h" 5 | 6 | 7 | class FTFace; 8 | class FTFactory :public RLL::IFontFactory 9 | { 10 | friend class FTFace; 11 | RLL::IPaintDevice* device; 12 | FT_Library lib; 13 | RLL::ISVG* notdef; 14 | void Dispose() {}; 15 | public: 16 | FTFactory(RLL::IPaintDevice*); 17 | RLL::IFontFace* LoadFromFile(char*); 18 | 19 | }; 20 | class FTFace : public RLL::IFontFace 21 | { 22 | public: 23 | friend class FTFactory; 24 | FTFactory* factory; 25 | FT_Face face; 26 | FT_Palette_Data palinfo; 27 | RLL::IBrush** brushes; 28 | RLL::ISVG** cache_svg; 29 | 30 | void Load(); 31 | void Dispose() { NOIMPL; }; 32 | void GetMetrics(RLL::GlyphMetrics* met); 33 | 34 | public: 35 | void SetLevel() { NOIMPL; }; 36 | uint32_t GetCodepoint(char32_t unicode); 37 | RLL::IGeometry* GetPlainGlyph(char32_t unicode, RLL::GlyphMetrics* metrics = nullptr); 38 | RLL::IGeometry* GetPlainGlyph(uint32_t codepoint, RLL::GlyphMetrics* metrics = nullptr); 39 | RLL::ISVG* GetGlyph(char32_t unicode, RLL::GlyphMetrics* metrics); 40 | RLL::ISVG* GetGlyph(uint32_t codepoint, RLL::GlyphMetrics* metrics); 41 | }; 42 | -------------------------------------------------------------------------------- /RLL/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "win32impl.h" 3 | #include "stdio.h" 4 | #include 5 | #include "reactive.h" 6 | using namespace RLL; 7 | class TT 8 | { 9 | public: 10 | TT(int a, float b, double c) 11 | { 12 | } 13 | }; 14 | int main() 15 | { 16 | R test(1, 0.5f, 0.8); 17 | R tint(16); 18 | tint.listener() += ([](int o, int n) { 19 | printf("watch tint: %d -> %d\n", o, n); 20 | }); 21 | 22 | tint = 8; 23 | tint = 128; 24 | printf("final: %d\n", *(tint.value)); 25 | 26 | R tcstr("asdf"); 27 | tcstr.listener() += ([](const char* o, const char* n) { 28 | printf("watch tcstr: %s -> %s\n", o, n); 29 | }); 30 | 31 | tcstr = "8asdawf"; 32 | tcstr = "aaaaaaaaa"; 33 | printf("final: %s\n", tcstr.operator->()); 34 | 35 | std::cout << 36 | "TEST ReactiveLayoutProject" << std::endl; 37 | 38 | printf("%#5x: %#5x\r\n", unsigned char(56), unsigned char(78)); 39 | 40 | int c; 41 | #ifdef _DEBUG 42 | LoadLibrary(L"C:\\Program Files\\Microsoft PIX\\2405.15.002-OneBranch_release\\WinPixGpuCapturer.dll"); 43 | #endif 44 | RLL::Initiate(INIT_DIRECTX_DEBUG_LAYER); 45 | 46 | 47 | 48 | IFrame* f = RLL::CreateFrame(nullptr, { 800,600 }, { 1920 / 2 - 400,1080 / 2 - 300 }); 49 | f->Show(); 50 | f->Run(); 51 | 52 | return 0; 53 | } -------------------------------------------------------------------------------- /RLL/math3d/Math3Df.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | using namespace DirectX; 4 | 5 | namespace Math3D 6 | { 7 | static float RAD2DEG = 57.295780f; 8 | static float DEG2RAD = 0.0174533f; 9 | static float PI = 3.14159265358979323846f; 10 | inline float Deg2Rad(float deg) 11 | { 12 | return deg * DEG2RAD; 13 | } 14 | inline float Rad2Deg(float rad) 15 | { 16 | return rad * RAD2DEG; 17 | } 18 | inline float RadRangePNPi(float r) 19 | { 20 | auto t = fmodf(r, 2 * PI); 21 | if (t > PI) 22 | { 23 | return -2 * PI + t; 24 | } 25 | return t; 26 | } 27 | inline float RadRange2Pi(float r) 28 | { 29 | auto t = fmodf(r, 2 * PI); 30 | if (t < 0) return t + 2 * PI; 31 | return t; 32 | } 33 | inline float RadRangePNto2Pi(float r) 34 | { 35 | if (r < 0) return r + 2 * PI; 36 | return r; 37 | } 38 | struct Matrix4x4; 39 | typedef float Vector1; 40 | struct Vector2 41 | { 42 | public: 43 | union 44 | { 45 | struct 46 | { 47 | float x; 48 | float y; 49 | }; 50 | XMFLOAT2 XM; 51 | }; 52 | 53 | static Vector2 zero() 54 | { 55 | Vector2 res; 56 | XMStoreFloat2(&res.XM, XMVectorZero()); 57 | return res; 58 | } 59 | static Vector2 one() 60 | { 61 | Vector2 res; 62 | res.x = res.y = 1; 63 | return res; 64 | } 65 | 66 | Vector2() {}; 67 | Vector2(float num) 68 | { 69 | x = y = num; 70 | } 71 | Vector2(float X, float Y) 72 | { 73 | x = X; 74 | y = Y; 75 | } 76 | Vector2(const Vector2& v) 77 | { 78 | XMStoreFloat2(&XM, XMLoadFloat2(&v.XM)); 79 | } 80 | inline float SqurMagnitude() 81 | { 82 | float f; 83 | XMStoreFloat(&f, XMVector2LengthSq(XMLoadFloat2(&XM))); 84 | return f; 85 | } 86 | inline float Magnitude() 87 | { 88 | float f; 89 | XMStoreFloat(&f, XMVector2Length(XMLoadFloat2(&XM))); 90 | return f; 91 | } 92 | inline void Normalize() 93 | { 94 | XMStoreFloat2(&XM, XMVector2Normalize(XMLoadFloat2(&XM))); 95 | } 96 | inline Vector2 Normalized() 97 | { 98 | Vector2 res = *this; 99 | res.Normalize(); 100 | return res; 101 | } 102 | 103 | inline Vector2 operator +(Vector2& a) 104 | { 105 | Vector2 res; 106 | XMStoreFloat2(&res.XM, XMVectorAdd(XMLoadFloat2(&this->XM), XMLoadFloat2(&a.XM))); 107 | return res; 108 | } 109 | inline Vector2 operator -(Vector2& a) 110 | { 111 | Vector2 res; 112 | XMStoreFloat2(&res.XM, XMVectorSubtract(XMLoadFloat2(&this->XM), XMLoadFloat2(&a.XM))); 113 | return res; 114 | } 115 | inline Vector2 operator *(const float& v) 116 | { 117 | Vector2 res; 118 | XMStoreFloat2(&res.XM, XMVectorScale(XMLoadFloat2(&this->XM), v)); 119 | return res; 120 | } 121 | inline Vector2 operator /(const float& v) 122 | { 123 | Vector2 res; 124 | XMStoreFloat2(&res.XM, XMVectorScale(XMLoadFloat2(&this->XM), 1.f / v)); 125 | return res; 126 | } 127 | inline Vector2 operator *(const Vector2& v) 128 | { 129 | Vector2 res; 130 | res.x = x * v.x; 131 | res.y = y * v.y; 132 | return res; 133 | } 134 | 135 | inline Vector2 operator /(const Vector2& v) 136 | { 137 | Vector2 res; 138 | res.x = x / v.x; 139 | res.y = y / v.y; 140 | return res; 141 | } 142 | 143 | inline bool operator ==(Vector2& a) 144 | { 145 | return XMVector2Equal(XMLoadFloat2(&this->XM), XMLoadFloat2(&a.XM)); 146 | } 147 | inline Vector2 operator +=(Vector2& a) 148 | { 149 | XMStoreFloat2(&this->XM, XMVectorAdd(XMLoadFloat2(&this->XM), XMLoadFloat2(&a.XM))); 150 | return *this; 151 | } 152 | inline Vector2 operator -=(Vector2& a) 153 | { 154 | XMStoreFloat2(&this->XM, XMVectorSubtract(XMLoadFloat2(&this->XM), XMLoadFloat2(&a.XM))); 155 | return *this; 156 | } 157 | inline Vector2 operator -() 158 | { 159 | Vector2 res(0, 0); 160 | XMStoreFloat2(&res.XM, XMVectorSubtract(XMLoadFloat2(&res.XM), XMLoadFloat2(&this->XM))); 161 | return res; 162 | } 163 | Vector2 operator* (Matrix4x4& m); 164 | static inline float Dot(Vector2 a, Vector2 b) 165 | { 166 | float f; 167 | XMStoreFloat(&f, XMVector2Dot(XMLoadFloat2(&a.XM), XMLoadFloat2(&b.XM))); 168 | return f; 169 | } 170 | static inline float Cross(Vector2 a, Vector2 b) 171 | { 172 | float res; 173 | XMStoreFloat(&res, XMVector2Cross(XMLoadFloat2(&a.XM), XMLoadFloat2(&b.XM))); 174 | return res; 175 | } 176 | }; 177 | struct Vector3 178 | { 179 | public: 180 | union 181 | { 182 | struct 183 | { 184 | float x; 185 | float y; 186 | float z; 187 | }; 188 | XMFLOAT3 XM; 189 | }; 190 | static Vector3 zero() 191 | { 192 | Vector3 res; 193 | XMStoreFloat3(&res.XM, XMVectorZero()); 194 | return res; 195 | } 196 | static Vector3 one() 197 | { 198 | Vector3 res; 199 | res.x = res.y = res.z = 1; 200 | return res; 201 | } 202 | Vector3() = default; 203 | Vector3(float num) 204 | { 205 | x = y = z = num; 206 | } 207 | Vector3(float X, float Y) 208 | { 209 | x = X; 210 | y = Y; 211 | z = 0; 212 | } 213 | Vector3(float X, float Y, float Z) 214 | { 215 | x = X; 216 | y = Y; 217 | z = Z; 218 | } 219 | Vector3(const Vector3& v) 220 | { 221 | XMStoreFloat3(&XM, XMLoadFloat3(&v.XM)); 222 | } 223 | Vector3(const Vector2& v) 224 | { 225 | x = v.x; y = v.y; z = 0; 226 | //XMStoreFloat3(&XM, XMLoadFloat2(&v.XM)); 227 | } 228 | 229 | inline float SqurMagnitude() 230 | { 231 | float f; 232 | XMStoreFloat(&f, XMVector3LengthSq(XMLoadFloat3(&XM))); 233 | return f; 234 | } 235 | inline float Magnitude() 236 | { 237 | float f; 238 | XMStoreFloat(&f, XMVector3Length(XMLoadFloat3(&XM))); 239 | return f; 240 | } 241 | inline Vector3 Normalize() 242 | { 243 | XMStoreFloat3(&XM, XMVector3Normalize(XMLoadFloat3(&XM))); 244 | return *this; 245 | } 246 | inline Vector3 Normalized() 247 | { 248 | Vector3 res = *this; 249 | res.Normalize(); 250 | return res; 251 | } 252 | 253 | inline Vector3 operator +(Vector3& a) 254 | { 255 | Vector3 res; 256 | XMStoreFloat3(&res.XM, XMVectorAdd(XMLoadFloat3(&this->XM), XMLoadFloat3(&a.XM))); 257 | return res; 258 | } 259 | inline Vector3 operator -(Vector3& a) 260 | { 261 | Vector3 res; 262 | XMStoreFloat3(&res.XM, XMVectorSubtract(XMLoadFloat3(&this->XM), XMLoadFloat3(&a.XM))); 263 | return res; 264 | } 265 | inline Vector3 operator *(float s) 266 | { 267 | Vector3 res; 268 | XMStoreFloat3(&res.XM, XMLoadFloat3(&this->XM) * s); 269 | return res; 270 | } 271 | inline Vector3 operator /(float s) 272 | { 273 | Vector3 res; 274 | XMStoreFloat3(&res.XM, XMLoadFloat3(&this->XM) / s); 275 | return res; 276 | } 277 | inline void operator +=(Vector3& a) 278 | { 279 | XMStoreFloat3(&XM, XMVectorAdd(XMLoadFloat3(&this->XM), XMLoadFloat3(&a.XM))); 280 | } 281 | Vector3 operator* (Matrix4x4& m); 282 | inline void operator -=(Vector3& a) 283 | { 284 | XMStoreFloat3(&XM, XMVectorSubtract(XMLoadFloat3(&this->XM), XMLoadFloat3(&a.XM))); 285 | } 286 | inline bool operator ==(Vector3& a) 287 | { 288 | return XMVector3Equal(XMLoadFloat3(&this->XM), XMLoadFloat3(&a.XM)); 289 | } 290 | static inline float Dot(Vector3 a, Vector3 b) 291 | { 292 | float f; 293 | XMStoreFloat(&f, XMVector3Dot(XMLoadFloat3(&a.XM), XMLoadFloat3(&b.XM))); 294 | return f; 295 | } 296 | static inline Vector3 Cross(Vector3 a, Vector3 b) 297 | { 298 | Vector3 res; 299 | XMStoreFloat3(&res.XM, XMVector3Cross(XMLoadFloat3(&a.XM), XMLoadFloat3(&b.XM))); 300 | return res; 301 | } 302 | 303 | }; 304 | struct Vector4 305 | { 306 | union 307 | { 308 | struct 309 | { 310 | float x; 311 | float y; 312 | float z; 313 | float w; 314 | }; 315 | struct 316 | { 317 | float l; 318 | float t; 319 | union { 320 | struct 321 | { 322 | float r; 323 | float b; 324 | }; 325 | struct 326 | { 327 | float w; 328 | float h; 329 | }; 330 | }; 331 | 332 | }; 333 | XMFLOAT4 XM; 334 | }; 335 | static Vector4 zero() 336 | { 337 | Vector4 res; 338 | XMStoreFloat4(&res.XM, XMVectorZero()); 339 | return res; 340 | } 341 | static Vector3 one() 342 | { 343 | Vector3 res; 344 | res.x = res.y = res.z = 1; 345 | return res; 346 | } 347 | Vector4() = default; 348 | Vector4(float num) 349 | { 350 | x = y = z = w = num; 351 | } 352 | Vector4(float X, float Y, float Z, float W) 353 | { 354 | x = X; 355 | y = Y; 356 | z = Z; 357 | w = W; 358 | } 359 | Vector4(const Vector4& v) 360 | { 361 | XMStoreFloat4(&XM, XMLoadFloat4(&v.XM)); 362 | } 363 | inline Vector4 Normalize() 364 | { 365 | XMStoreFloat4(&XM, XMVector4Normalize(XMLoadFloat4(&XM))); 366 | return *this; 367 | } 368 | inline Vector4 Normalized() 369 | { 370 | Vector4 res = *this; 371 | res.Normalize(); 372 | return res; 373 | } 374 | 375 | inline Vector4 operator +(Vector4& a) 376 | { 377 | Vector4 res; 378 | XMStoreFloat4(&res.XM, XMVectorAdd(XMLoadFloat4(&this->XM), XMLoadFloat4(&a.XM))); 379 | return res; 380 | } 381 | inline Vector4 operator -(Vector4& a) 382 | { 383 | Vector4 res; 384 | XMStoreFloat4(&res.XM, XMVectorSubtract(XMLoadFloat4(&this->XM), XMLoadFloat4(&a.XM))); 385 | return res; 386 | } 387 | inline Vector4 operator *(float s) 388 | { 389 | Vector4 res; 390 | XMStoreFloat4(&res.XM, XMLoadFloat4(&this->XM) * s); 391 | return res; 392 | } 393 | inline Vector4 operator /(float s) 394 | { 395 | Vector4 res; 396 | XMStoreFloat4(&res.XM, XMLoadFloat4(&this->XM) / s); 397 | return res; 398 | } 399 | inline void operator +=(Vector4& a) 400 | { 401 | XMStoreFloat4(&XM, XMVectorAdd(XMLoadFloat4(&this->XM), XMLoadFloat4(&a.XM))); 402 | } 403 | Vector4 operator* (Matrix4x4& m); 404 | inline void operator -=(Vector4& a) 405 | { 406 | XMStoreFloat4(&XM, XMVectorSubtract(XMLoadFloat4(&this->XM), XMLoadFloat4(&a.XM))); 407 | } 408 | static inline float Dot(Vector4 a, Vector4 b) 409 | { 410 | float f; 411 | XMStoreFloat(&f, XMVector4Dot(XMLoadFloat4(&a.XM), XMLoadFloat4(&b.XM))); 412 | return f; 413 | } 414 | static inline Vector4 Cross(Vector4 a, Vector4 b, Vector4 c) 415 | { 416 | Vector4 res; 417 | XMStoreFloat4(&res.XM, XMVector4Cross(XMLoadFloat4(&a.XM), XMLoadFloat4(&b.XM), XMLoadFloat4(&c.XM))); 418 | return res; 419 | } 420 | 421 | }; 422 | struct Quaternion : Vector4 423 | { 424 | public: 425 | static Quaternion zero() 426 | { 427 | Quaternion res; 428 | XMStoreFloat4(&res.XM, XMVectorZero()); 429 | return res; 430 | } 431 | static Quaternion one() 432 | { 433 | Quaternion res; 434 | res.x = res.y = res.z = 1; 435 | return res; 436 | } 437 | static Quaternion identity() 438 | { 439 | Quaternion res; 440 | XMStoreFloat4(&res.XM, XMQuaternionIdentity()); 441 | return res; 442 | } 443 | Quaternion() = default; 444 | Quaternion(float num) 445 | { 446 | x = y = z = num; 447 | } 448 | Quaternion(float X, float Y, float Z, float W) 449 | { 450 | x = X; 451 | y = Y; 452 | z = Z; 453 | w = W; 454 | } 455 | Quaternion(const Quaternion& v) 456 | { 457 | XMStoreFloat4(&XM, XMLoadFloat4(&v.XM)); 458 | } 459 | Quaternion(const XMVECTORF32& v) 460 | { 461 | XMStoreFloat4(&XM, v); 462 | } 463 | inline float SqurMagnitude() 464 | { 465 | float f; 466 | XMStoreFloat(&f, XMVector4LengthSq(XMLoadFloat4(&XM))); 467 | return f; 468 | } 469 | inline float Magnitude() 470 | { 471 | float f; 472 | XMStoreFloat(&f, XMVector4Length(XMLoadFloat4(&XM))); 473 | return f; 474 | } 475 | inline void Normalize() 476 | { 477 | XMStoreFloat4(&XM, XMVector4Normalize(XMLoadFloat4(&XM))); 478 | } 479 | inline Quaternion Normalized() 480 | { 481 | Quaternion res = *this; 482 | res.Normalize(); 483 | return res; 484 | } 485 | inline Quaternion operator +(Quaternion& a) 486 | { 487 | Quaternion res; 488 | XMStoreFloat4(&res.XM, XMVectorAdd(XMLoadFloat4(&this->XM), XMLoadFloat4(&a.XM))); 489 | return res; 490 | } 491 | inline Quaternion operator -(Quaternion& a) 492 | { 493 | Quaternion res; 494 | XMStoreFloat4(&res.XM, XMVectorSubtract(XMLoadFloat4(&this->XM), XMLoadFloat4(&a.XM))); 495 | return res; 496 | } 497 | inline Quaternion operator *(Quaternion& a) 498 | { 499 | Quaternion res; 500 | XMStoreFloat4(&res.XM, XMQuaternionMultiply(XMLoadFloat4(&this->XM), XMLoadFloat4(&a.XM))); 501 | return res; 502 | } 503 | inline Vector3 operator *(Vector3& a) 504 | { 505 | Vector3 res; 506 | XMStoreFloat3(&res.XM, XMVector3Rotate(XMLoadFloat3(&a.XM), XMLoadFloat4(&XM))); 507 | //XMMatrixRotaionQu 508 | //XMVector3Transform 509 | //XMStoreFloat4(&res.XM, XMQuaternion(XMLoadFloat4(&this->XM), XMLoadFloat4(&a.XM))); 510 | return res; 511 | } 512 | Quaternion operator* (Matrix4x4& m); 513 | static inline float Dot(Quaternion a, Quaternion b) 514 | { 515 | float f; 516 | XMStoreFloat(&f, XMVector4Dot(XMLoadFloat4(&a.XM), XMLoadFloat4(&b.XM))); 517 | return f; 518 | } 519 | static inline Quaternion Cross(Quaternion a, Quaternion b) 520 | { 521 | Quaternion res; 522 | XMStoreFloat4(&res.XM, XMVector3Cross(XMLoadFloat4(&a.XM), XMLoadFloat4(&b.XM))); 523 | return res; 524 | } 525 | static inline Quaternion RollPitchYaw(float pitch, float yaw, float roll) 526 | { 527 | Quaternion res; 528 | XMStoreFloat4(&res.XM, XMQuaternionRotationRollPitchYaw(pitch, yaw, roll)); 529 | return res; 530 | } 531 | }; 532 | struct Matrix4x4 533 | { 534 | public: 535 | union 536 | { 537 | struct 538 | { 539 | float _11, _12, _13, _14; 540 | float _21, _22, _23, _24; 541 | float _31, _32, _33, _34; 542 | float _41, _42, _43, _44; 543 | }; 544 | float m[4][4]; 545 | XMFLOAT4X4 XM; 546 | }; 547 | Matrix4x4() 548 | { 549 | XMStoreFloat4x4(&XM, XMMatrixIdentity()); 550 | } 551 | static inline Matrix4x4 Identity() 552 | { 553 | Matrix4x4 res; 554 | XMStoreFloat4x4(&res.XM, XMMatrixIdentity()); 555 | return res; 556 | } 557 | static inline Matrix4x4 Translation(Vector3 v) 558 | { 559 | Matrix4x4 m; 560 | XMMATRIX xmm = XMMatrixTranslation(v.x, v.y, v.z); 561 | XMStoreFloat4x4(&m.XM, xmm); 562 | return m; 563 | } 564 | static inline Matrix4x4 Scaling(Vector3 v) 565 | { 566 | Matrix4x4 m; 567 | XMMATRIX xmm = XMMatrixScaling(v.x, v.y, v.z); 568 | XMStoreFloat4x4(&m.XM, xmm); 569 | return m; 570 | } 571 | static inline Matrix4x4 Rotation(Quaternion v) 572 | { 573 | Matrix4x4 m; 574 | XMMATRIX xmm = XMMatrixRotationQuaternion(XMLoadFloat4(&v.XM)); 575 | XMStoreFloat4x4(&m.XM, xmm); 576 | return m; 577 | } 578 | static inline Matrix4x4 Rotation(float y, float p, float r) 579 | { 580 | Matrix4x4 m; 581 | XMMATRIX xmm = XMMatrixRotationRollPitchYaw(p, y, r); 582 | XMStoreFloat4x4(&m.XM, xmm); 583 | return m; 584 | } 585 | static inline Matrix4x4 TRS(Vector3 t, Quaternion r, Vector3 s) 586 | { 587 | Matrix4x4 m; 588 | XMMATRIX xmm = XMMatrixScalingFromVector(XMLoadFloat3(&s.XM)) 589 | * XMMatrixRotationQuaternion(XMLoadFloat4(&r.XM)) 590 | * XMMatrixTranslation(t.x, t.y, t.z); 591 | XMStoreFloat4x4(&m.XM, xmm); 592 | return m; 593 | } 594 | Matrix4x4(const Matrix4x4& v) 595 | { 596 | XMStoreFloat4x4(&XM, XMLoadFloat4x4(&v.XM)); 597 | } 598 | inline Matrix4x4 Invers() 599 | { 600 | XMStoreFloat4x4(&XM, XMMatrixInverse(&XMMatrixDeterminant(XMLoadFloat4x4(&XM)), XMLoadFloat4x4(&XM))); 601 | return *this; 602 | } 603 | 604 | inline Matrix4x4 Inversed() 605 | { 606 | Matrix4x4 m = *this; 607 | return m.Invers(); 608 | } 609 | 610 | inline Matrix4x4 Transpose() 611 | { 612 | XMStoreFloat4x4(&XM, XMMatrixTranspose(XMLoadFloat4x4(&XM))); 613 | return *this; 614 | } 615 | 616 | inline Matrix4x4 Transposed() 617 | { 618 | Matrix4x4 m = *this; 619 | return m.Transpose(); 620 | 621 | } 622 | inline Matrix4x4 operator * (Matrix4x4& m) 623 | { 624 | Matrix4x4 res; 625 | XMStoreFloat4x4(&res.XM, XMMatrixMultiply(XMLoadFloat4x4(&this->XM), XMLoadFloat4x4(&m.XM))); 626 | return res; 627 | } 628 | static inline Matrix4x4 LookAt(Vector3 eyePoint, Vector3 target) 629 | { 630 | Matrix4x4 res; 631 | XMStoreFloat4x4(&res.XM, XMMatrixLookAtLH(XMLoadFloat3(&eyePoint.XM), XMLoadFloat3(&target.XM), XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f))); 632 | return res; 633 | } 634 | static inline Matrix4x4 LookTo(Vector3 eyePoint, Vector3 direction) 635 | { 636 | Matrix4x4 res; 637 | XMStoreFloat4x4(&res.XM, XMMatrixLookToLH(XMLoadFloat3(&eyePoint.XM), XMLoadFloat3(&direction.XM), XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f))); 638 | return res; 639 | } 640 | 641 | static inline Matrix4x4 Perspective(float yFov/*degree*/, float aspectRatio, float nearZ, float farZ) 642 | { 643 | Matrix4x4 res; 644 | XMStoreFloat4x4(&res.XM, XMMatrixPerspectiveFovLH(yFov * 3.1415926f / 180.f, aspectRatio, nearZ, farZ)); 645 | return res; 646 | } 647 | static inline Matrix4x4 Orthographic(float vw/*degree*/, float vh, float nearZ, float farZ) 648 | { 649 | Matrix4x4 res; 650 | XMStoreFloat4x4(&res.XM, XMMatrixOrthographicLH(vw, vh, nearZ, farZ)); 651 | return res; 652 | } 653 | 654 | }; 655 | struct Matrix3x2 656 | { 657 | union 658 | { 659 | struct 660 | { 661 | float _11, _12, _13; 662 | float _21, _22, _23; 663 | }; 664 | float m[3][2]; 665 | }; 666 | 667 | }; 668 | 669 | inline Vector2 Vector2::operator* (Matrix4x4& m) 670 | { 671 | Vector2 v; 672 | v = *this; 673 | auto r = XMVector2Transform(XMLoadFloat2(&v.XM), XMLoadFloat4x4(&m.XM)); 674 | XMStoreFloat2(&v.XM, r); 675 | return v; 676 | } 677 | inline Vector3 Vector3::operator* (Matrix4x4& m) 678 | { 679 | Vector3 v; 680 | v = *this; 681 | auto r = XMVector3Transform(XMLoadFloat3(&v.XM), XMLoadFloat4x4(&m.XM)); 682 | XMStoreFloat3(&v.XM, r); 683 | return v; 684 | } 685 | inline Vector4 Vector4::operator* (Matrix4x4& m) 686 | { 687 | Vector4 v; 688 | v = *this; 689 | auto r = XMVector4Transform(XMLoadFloat4(&v.XM), XMLoadFloat4x4(&m.XM)); 690 | XMStoreFloat4(&v.XM, r); 691 | return v; 692 | } 693 | 694 | inline Quaternion Quaternion::operator* (Matrix4x4& m) 695 | { 696 | Quaternion v; 697 | v = *this; 698 | auto r = XMVector3Transform(XMLoadFloat4(&v.XM), XMLoadFloat4x4(&m.XM)); 699 | XMStoreFloat4(&v.XM, r); 700 | return v; 701 | } 702 | 703 | typedef float Vector1; 704 | typedef Vector2 float2; 705 | typedef Vector3 float3; 706 | typedef Vector4 float4; 707 | typedef Matrix4x4 float4x4; 708 | } 709 | 710 | -------------------------------------------------------------------------------- /RLL/meshutil.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "math3d/Math3Df.h" 3 | 4 | struct LayoutMesh 5 | { 6 | Math3D::float3 *position; 7 | Math3D::float2 *uv; 8 | Math3D::float2 *pathnorm; 9 | 10 | int vertexCount; 11 | int triangleCount; 12 | 13 | bool Reserve(); 14 | bool Append(LayoutMesh&); 15 | 16 | private: 17 | void* Allocate(int vc,int tc); 18 | void Free(); 19 | }; -------------------------------------------------------------------------------- /RLL/perf_util.cpp: -------------------------------------------------------------------------------- 1 | #include "perf_util.h" 2 | #include 3 | #include 4 | #include 5 | 6 | struct TimeCheckPoint 7 | { 8 | char* name; 9 | uint64_t time_ms; 10 | }; 11 | std::vector tckps; 12 | float GetTime() 13 | { 14 | LARGE_INTEGER m_liPerfFreq = { 0 }; 15 | QueryPerformanceFrequency(&m_liPerfFreq); 16 | LARGE_INTEGER m_liPerfStart = { 0 }; 17 | QueryPerformanceCounter(&m_liPerfStart); 18 | return (float)m_liPerfStart.QuadPart / m_liPerfFreq.QuadPart * 1000.0f; 19 | 20 | } 21 | uint64_t time_freq = 0; 22 | uint64_t _GetTime() 23 | { 24 | LARGE_INTEGER m_liPerfFreq = { 0 }; 25 | QueryPerformanceFrequency(&m_liPerfFreq); 26 | LARGE_INTEGER m_liPerfStart = { 0 }; 27 | QueryPerformanceCounter(&m_liPerfStart); 28 | time_freq = m_liPerfFreq.QuadPart; 29 | return m_liPerfStart.QuadPart; 30 | } 31 | uint64_t time_begin = 0; 32 | void TimeCheck(char* name) 33 | { 34 | if (tckps.size() == 0) 35 | { 36 | time_begin = _GetTime(); 37 | } 38 | tckps.push_back({ name,_GetTime() - time_begin }); 39 | } 40 | void TimeCheckSum() 41 | { 42 | for (auto& i : tckps) 43 | { 44 | std::cout << "TimeChecker:\t" << i.name << "\tat: " << (float)i.time_ms/time_freq * 1000.f << "ms" << std::endl; 45 | } 46 | tckps.clear(); 47 | } -------------------------------------------------------------------------------- /RLL/perf_util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef NO_TIMECHECKER 4 | #include 5 | 6 | // return us 7 | inline float GetTime(); 8 | inline void TimeCheck(char* name); 9 | inline void TimeCheckSum(); 10 | #else 11 | #define GetTime(...) 12 | #define TimeCheck(...) 13 | #define TimeCheckSum(...) 14 | #endif -------------------------------------------------------------------------------- /RLL/reactive.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include "delegate.h" 5 | #define reactive 6 | template 7 | class Reactive 8 | { 9 | public: 10 | T* value; 11 | using WATCHER = void(T old, T nov); 12 | 13 | private: 14 | int* ref; 15 | delegate* listener_ptr; 16 | Reactive* weak_target = nullptr; 17 | void emit(T old, T nov) 18 | { 19 | (*listener_ptr)(std::move(old), std::move(*value)); 20 | } 21 | public: 22 | Reactive() 23 | { 24 | value = new T(); 25 | ref = new int(1); 26 | listener_ptr = new delegate(); 27 | } 28 | template 29 | Reactive(CTOR_VALS&&... vals) 30 | { 31 | value = new T(vals...); 32 | ref = new int(1); 33 | listener_ptr = new delegate(); 34 | } 35 | Reactive(const T& nov)//copy 36 | { 37 | value = new T(); 38 | ref = new int(1); 39 | listener_ptr = new delegate(); 40 | *value = nov; 41 | } 42 | Reactive(const Reactive& nov)//copy 43 | { 44 | ref = nov.ref; 45 | value = nov.value; 46 | listener_ptr = nov.listener_ptr; 47 | 48 | (*ref)++; 49 | } 50 | Reactive(T&& nov)//move 51 | { 52 | 53 | value = new T(nov); 54 | ref = new int(1); 55 | listener_ptr = new delegate(); 56 | } 57 | T& operator=(const T& nov) 58 | { 59 | T old = *value; 60 | *value = nov; 61 | emit(old, nov); 62 | return *value; 63 | } 64 | Reactive& operator=(const Reactive& nov) 65 | { 66 | Reactive::~Reactive(); 67 | ref = nov.ref; 68 | value = nov.value; 69 | (*ref)++; 70 | return *this; 71 | } 72 | 73 | T& operator->() 74 | { 75 | return *value; 76 | } 77 | delegate& listener() 78 | { 79 | return *listener_ptr; 80 | } 81 | ~Reactive() 82 | { 83 | (*ref)--; 84 | if (ref <= 0) 85 | { 86 | delete ref; 87 | delete value; 88 | delete listener_ptr; 89 | } 90 | ref = nullptr; 91 | value = nullptr; 92 | listener_ptr = nullptr; 93 | } 94 | }; 95 | 96 | #define R Reactive -------------------------------------------------------------------------------- /RLL/rlltest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "TextInterfaces.h" 3 | RLL::ISVG* hb_test(RLL::IFontFace* ff, RLL::ISVGBuilder* sb, wchar_t* tex); 4 | -------------------------------------------------------------------------------- /RLL/shader/core.hlsl: -------------------------------------------------------------------------------- 1 | #include "path.hlsli" 2 | SamplerState g_sampler : register(s0); 3 | 4 | float4 PS(VertexOut pin) : SV_Target 5 | { 6 | float2 uv = pin.uv; 7 | float3 uvw = float3(pin.uv.x, pin.uv.y, 1); 8 | 9 | float cov = 0; 10 | float2 pixelsPerEm = float2(1.0 / fwidth(pin.uv.x), 11 | 1.0 / fwidth(pin.uv.y)); 12 | int glyph_index = (int)pin.pnc.x; 13 | int curve_index = glyphs[glyph_index].hi; 14 | int curve_length = glyphs[glyph_index].hl; 15 | for (int i = 0; i < curve_length; i++) 16 | { 17 | 18 | float2 cb = curves[curve_index + i].begin - uv; 19 | float2 cc = curves[curve_index + i].control - uv; 20 | float2 ce = curves[curve_index + i].end - uv; 21 | if (max(max(cb.x, cc.x), ce.x) * pixelsPerEm.x < -0.5) 22 | break; 23 | 24 | uint code = (0x2E74U >> (((cb.y > 0.0) ? 2U : 0U) + 25 | ((cc.y > 0.0) ? 4U : 0U) + ((ce.y > 0.0) ? 8U : 0U))) & 26 | 3U; 27 | if (code != 0U) 28 | { 29 | float ax = cb.x - cc.x * 2.0 + ce.x; 30 | float ay = cb.y - cc.y * 2.0 + ce.y; 31 | float bx = cb.x - cc.x; 32 | float by = cb.y - cc.y; 33 | float ra = 1.0 / ay; 34 | 35 | float d = sqrt(max(by * by - ay * cb.y, 0.0)); 36 | float t1 = (by - d) * ra; 37 | float t2 = (by + d) * ra; 38 | 39 | // If the polynomial is nearly linear, then solve -2b t + c = 0. 40 | 41 | if (abs(ay) < 0.0001) 42 | t1 = t2 = cb.y * 0.5 / by; 43 | 44 | // Calculate the x coordinates where C(t) = 0, and transform 45 | // them so that the current pixel corresponds to the range 46 | // [0,1]. Clamp the results and use them for root contributions. 47 | 48 | float x1 = (ax * t1 - bx * 2.0) * t1 + cb.x; 49 | float x2 = (ax * t2 - bx * 2.0) * t2 + cb.x; 50 | x1 = clamp(x1 * pixelsPerEm.x + 0.5, 0.0, 1.0); 51 | x2 = clamp(x2 * pixelsPerEm.x + 0.5, 0.0, 1.0); 52 | 53 | if ((code & 1U) != 0U) 54 | cov += x1; 55 | if (code > 1U) 56 | cov -= x2; 57 | } 58 | } 59 | curve_index = glyphs[glyph_index].vi; 60 | curve_length = glyphs[glyph_index].vl; 61 | 62 | for (i = 0; i < curve_length; i++) 63 | { 64 | float2 cb = curves[curve_index + i].begin - uv; 65 | float2 cc = curves[curve_index + i].control - uv; 66 | float2 ce = curves[curve_index + i].end - uv; 67 | if (max(max(cb.y, cc.y), ce.y) * pixelsPerEm.y < -0.5) 68 | break; 69 | uint code = (0x2E74U >> (((cb.x > 0.0) ? 2U : 0U) + 70 | ((cc.x > 0.0) ? 4U : 0U) + ((ce.x > 0.0) ? 8U : 0U))) & 71 | 3U; 72 | if (code != 0U) 73 | { 74 | float ax = cb.y - cc.y * 2.0 + ce.y; 75 | float ay = cb.x - cc.x * 2.0 + ce.x; 76 | float bx = cb.y - cc.y; 77 | float by = cb.x - cc.x; 78 | float ra = 1.0 / ay; 79 | 80 | float d = sqrt(max(by * by - ay * cb.x, 0.0)); 81 | float t1 = (by - d) * ra; 82 | float t2 = (by + d) * ra; 83 | 84 | if (abs(ay) < 0.0001) 85 | t1 = t2 = cb.x * 0.5 / by; 86 | 87 | float x1 = (ax * t1 - bx * 2.0) * t1 + cb.y; 88 | float x2 = (ax * t2 - bx * 2.0) * t2 + cb.y; 89 | x1 = clamp(x1 * pixelsPerEm.y + 0.5, 0.0, 1.0); 90 | x2 = clamp(x2 * pixelsPerEm.y + 0.5, 0.0, 1.0); 91 | 92 | if ((code & 1U) != 0U) 93 | cov -= x1; 94 | if (code > 1U) 95 | cov += x2; 96 | } 97 | } 98 | float gscl = sqrt(clamp(abs(cov) * 0.5, 0.0, 1.0)); 99 | // float gscl = pow(clamp(abs(cov), 0.0, 1.0), 0.4545); //gamma 100 | // float gscl = clamp(abs(cov), 0, 1); 101 | float4 color = float4(1, 0, 1, 1); 102 | Brush cg = brushes[pin.pnc.z]; 103 | switch (cg.type & 0xff) 104 | { 105 | case 0: 106 | color = dColor; 107 | break; 108 | case 1: 109 | color = gradientDir(cg, uv, cg.center); 110 | break; 111 | case 2: 112 | color = gradientRad(cg, uv, cg.center, cg.radius, cg.focus); 113 | break; 114 | case 3: 115 | color = gradientSwe(cg, uv, cg.center, cg.radius); 116 | break; 117 | case 4: 118 | color = g_texture[cg.texid].Sample(g_sampler, uv); 119 | break; 120 | } 121 | // color = float4(1,0,0,0); 122 | // return float4(gradientSwe(uv,float2(0.5,0.50),time * 0.2).xyz * gscl,1); 123 | // return float4(frac(uv), 0, gscl * 0.5 + 0.5); 124 | return float4(color.xyz, (1 - color.w) * gscl); 125 | } 126 | 127 | /* 128 | uv0: brush uv 129 | uv1: path coordinate 130 | 131 | glyph data:* 132 | glyph index* ushort 133 | glyph paths* buffer 134 | 135 | fill 136 | */ -------------------------------------------------------------------------------- /RLL/shader/core_anim.hlsl: -------------------------------------------------------------------------------- 1 | #include "path.hlsli" 2 | SamplerState g_sampler : register(s0); 3 | 4 | float4 PS(VertexOut pin) : SV_Target 5 | { 6 | float2 uv = pin.uv; 7 | float3 uvw = float3(pin.uv.x, pin.uv.y, 1); 8 | 9 | float cov = 0; 10 | float2 pixelsPerEm = float2(1.0 / fwidth(pin.uv.x), 11 | 1.0 / fwidth(pin.uv.y)); 12 | int glyph_index = (int) pin.pnc.x; 13 | int curve_index = glyphs[glyph_index].hi; 14 | int curve_length = glyphs[glyph_index].hl; 15 | for (int i = 0; i < curve_length; i++) 16 | { 17 | 18 | float2 cb = curves[curve_index + i].begin - uv; 19 | float2 cc = curves[curve_index + i].control - uv; 20 | float2 ce = curves[curve_index + i].end - uv; 21 | if (max(max(cb.x, cc.x), ce.x) * pixelsPerEm.x < -0.5) 22 | break; 23 | 24 | uint code = (0x2E74U >> (((cb.y > 0.0) ? 2U : 0U) + 25 | ((cc.y > 0.0) ? 4U : 0U) + ((ce.y > 0.0) ? 8U : 0U))) & 26 | 3U; 27 | if (code != 0U) 28 | { 29 | float ax = cb.x - cc.x * 2.0 + ce.x; 30 | float ay = cb.y - cc.y * 2.0 + ce.y; 31 | float bx = cb.x - cc.x; 32 | float by = cb.y - cc.y; 33 | float ra = 1.0 / ay; 34 | 35 | float d = sqrt(max(by * by - ay * cb.y, 0.0)); 36 | float t1 = (by - d) * ra; 37 | float t2 = (by + d) * ra; 38 | 39 | // If the polynomial is nearly linear, then solve -2b t + c = 0. 40 | 41 | if (abs(ay) < 0.0001) 42 | t1 = t2 = cb.y * 0.5 / by; 43 | 44 | // Calculate the x coordinates where C(t) = 0, and transform 45 | // them so that the current pixel corresponds to the range 46 | // [0,1]. Clamp the results and use them for root contributions. 47 | 48 | float x1 = (ax * t1 - bx * 2.0) * t1 + cb.x; 49 | float x2 = (ax * t2 - bx * 2.0) * t2 + cb.x; 50 | x1 = clamp(x1 * pixelsPerEm.x + 0.5, 0.0, 1.0); 51 | x2 = clamp(x2 * pixelsPerEm.x + 0.5, 0.0, 1.0); 52 | 53 | if ((code & 1U) != 0U) 54 | cov += x1; 55 | if (code > 1U) 56 | cov -= x2; 57 | } 58 | } 59 | curve_index = glyphs[glyph_index].vi; 60 | curve_length = glyphs[glyph_index].vl; 61 | 62 | for (i = 0; i < curve_length; i++) 63 | { 64 | float2 cb = curves[curve_index + i].begin - uv; 65 | float2 cc = curves[curve_index + i].control - uv; 66 | float2 ce = curves[curve_index + i].end - uv; 67 | if (max(max(cb.y, cc.y), ce.y) * pixelsPerEm.y < -0.5) 68 | break; 69 | uint code = (0x2E74U >> (((cb.x > 0.0) ? 2U : 0U) + 70 | ((cc.x > 0.0) ? 4U : 0U) + ((ce.x > 0.0) ? 8U : 0U))) & 71 | 3U; 72 | if (code != 0U) 73 | { 74 | float ax = cb.y - cc.y * 2.0 + ce.y; 75 | float ay = cb.x - cc.x * 2.0 + ce.x; 76 | float bx = cb.y - cc.y; 77 | float by = cb.x - cc.x; 78 | float ra = 1.0 / ay; 79 | 80 | float d = sqrt(max(by * by - ay * cb.x, 0.0)); 81 | float t1 = (by - d) * ra; 82 | float t2 = (by + d) * ra; 83 | 84 | if (abs(ay) < 0.0001) 85 | t1 = t2 = cb.x * 0.5 / by; 86 | 87 | float x1 = (ax * t1 - bx * 2.0) * t1 + cb.y; 88 | float x2 = (ax * t2 - bx * 2.0) * t2 + cb.y; 89 | x1 = clamp(x1 * pixelsPerEm.y + 0.5, 0.0, 1.0); 90 | x2 = clamp(x2 * pixelsPerEm.y + 0.5, 0.0, 1.0); 91 | 92 | if ((code & 1U) != 0U) 93 | cov -= x1; 94 | if (code > 1U) 95 | cov += x2; 96 | } 97 | } 98 | float gscl = sqrt(clamp(abs(cov) * 0.5, 0.0, 1.0)); 99 | // float gscl = pow(clamp(abs(cov), 0.0, 1.0), 0.4545); //gamma 100 | // float gscl = clamp(abs(cov), 0, 1); 101 | float4 color = float4(1, 0, 1, 1); 102 | Brush cg = brushes[pin.pnc.z]; 103 | switch (cg.type & 0xff) 104 | { 105 | case 0: 106 | color = dColor; 107 | break; 108 | case 1: 109 | color = gradientDir(cg, uv, cg.center); 110 | break; 111 | case 2: 112 | color = gradientRad(cg, uv, cg.center, cg.radius, cg.focus); 113 | break; 114 | case 3: 115 | color = gradientSwe(cg, uv, cg.center, cg.radius); 116 | break; 117 | case 4: 118 | color = g_texture[cg.texid].Sample(g_sampler, uv); 119 | break; 120 | } 121 | // color = float4(1,0,0,0); 122 | // return float4(gradientSwe(uv,float2(0.5,0.50),time * 0.2).xyz * gscl,1); 123 | // return float4(frac(uv), 0, gscl * 0.5 + 0.5); 124 | return float4(color.xyz, (1 - color.w) * gscl); 125 | } 126 | 127 | /* 128 | uv0: brush uv 129 | uv1: path coordinate 130 | 131 | glyph data:* 132 | glyph index* ushort 133 | glyph paths* buffer 134 | 135 | fill 136 | */ -------------------------------------------------------------------------------- /RLL/shader/core_vertex.hlsl: -------------------------------------------------------------------------------- 1 | #include "path.hlsli" 2 | 3 | VertexOut VS(VertexIn vin, uint id : SV_InstanceID) 4 | { 5 | VertexOut vout; 6 | float2 n = float2(cos(vin.pnc.y), sin(vin.pnc.y)); 7 | float3 p = float3(vin.PosL, 0); 8 | float2 uv = vin.uv; 9 | float4x4 m = mul(objToWorld, gWorldViewProj); 10 | 11 | float s = m[0][3] * p.x + m[1][3] * p.y + m[3][3]; 12 | float t = m[0][3] * n.x + m[1][3] * n.y; 13 | float u = vwh.x * 14 | (s * (m[0][0] * n.x + m[1][0] * n.y) - t * (m[0][0] * p.x + m[1][0] * p.y + m[3][0])); 15 | 16 | float v = vwh.y * 17 | (s * (m[0][1] * n.x + m[1][1] * n.y) - t * (m[0][1] * p.x + m[1][1] * p.y + m[3][1])); 18 | float d = (s * s * s * t + s * s * sqrt(u * u + v * v)) / (u * u + v * v - s * s * t * t + 0.0001); 19 | // vin.PosL += float3(1.2f, 0, 0) * vin.path_norm.x; 20 | p += float3(n * d, 0); 21 | uv += mul(n * d, float2x2(vin.tf.xy, vin.tf.zw)); 22 | //uv += n * d; 23 | vout.uv = uv; 24 | vout.PosH = mul(float4(p, 1.0f), m); //+ float4(d * n.x / 400.0, d * n.y / 300., 0, 0); 25 | vout.pnc = vin.pnc; 26 | vout.pnc1 = vin.pnc1; 27 | return vout; 28 | } -------------------------------------------------------------------------------- /RLL/shader/dbgWire.hlsl: -------------------------------------------------------------------------------- 1 | #include "path.hlsli" 2 | 3 | VertexOut VS(VertexIn vin, uint id 4 | : SV_InstanceID) 5 | { 6 | VertexOut vout; 7 | float2 n = float2(cos(vin.pnc.y), sin(vin.pnc.y)); 8 | float3 p = float3(vin.PosL,0); 9 | float2 uv = vin.uv; 10 | float4x4 m = mul(objToWorld, gWorldViewProj); 11 | 12 | float s = m[0][3] * p.x + m[1][3] * p.y + m[3][3]; 13 | float t = m[0][3] * n.x + m[1][3] * n.y; 14 | float u = vwh.x * 15 | (s * (m[0][0] * n.x + m[1][0] * n.y) 16 | - t * (m[0][0] * p.x + m[1][0] * p.y + m[3][0])); 17 | 18 | float v = vwh.y * 19 | (s * (m[0][1] * n.x + m[1][1] * n.y) 20 | - t * (m[0][1] * p.x + m[1][1] * p.y + m[3][1])); 21 | float d = (s * s * s * t + s * s * sqrt(u * u + v * v)) / (u * u + v * v - s * s * t * t + 0.0001); 22 | // vin.PosL += float3(1.2f, 0, 0) * vin.path_norm.x; 23 | p += float3(n * d, 0); 24 | 25 | // s = m[0][3] * uv.x + m[1][3] * uv.y + m[3][3]; 26 | // t = m[0][3] * n.x + m[1][3] * n.y; 27 | // u = vwh.x * (s * (m[0][0] * n.x + m[1][0] * n.y) - t * (m[0][0] * uv.x + m[1][0] * uv.y + m[3][0])); 28 | // v = vwh.y * (s * (m[0][1] * n.x + m[1][1] * n.y) - t * (m[0][1] * uv.x + m[1][1] * uv.y + m[3][1])); 29 | // d = (s * s * s * t + s * s * sqrt(u * u + v * v)) / (u * u + v * v - s * s * t * t + 0.0001); 30 | //uv += n * d; 31 | vout.uv = uv; 32 | vout.PosH = mul(float4(p, 1.0f), m); //+ float4(d * n.x / 400.0, d * n.y / 300., 0, 0); 33 | vout.pnc = vin.pnc; 34 | return vout; 35 | } 36 | float4 PS(VertexOut pin) :SV_Target 37 | { 38 | return float4(0.5,0.5,0.5,1); 39 | } -------------------------------------------------------------------------------- /RLL/shader/path.hlsli: -------------------------------------------------------------------------------- 1 | cbuffer cbObject : register(b0) 2 | { 3 | float4x4 objToWorld; 4 | int sampleType; 5 | float timeBegin; 6 | float timePeriod; 7 | int timeLoop; 8 | } 9 | 10 | // cbuffer cbPass :register(b1) 11 | //{ 12 | // 13 | // 14 | // }; 15 | 16 | cbuffer cbFrame : register(b1) 17 | { 18 | float4x4 gWorldViewProj; 19 | float4 dColor; 20 | float time; 21 | int2 vwh; 22 | float reservedCBF; 23 | }; 24 | 25 | struct Brush 26 | { 27 | float2 center; // in directional is direction 28 | float2 focus; 29 | float radius; 30 | uint type; // color mode: 0:foreground 1:directional 2:radial 3:sweep 4:tex 31 | uint texid; // texture index 32 | float pad; 33 | float pos[8]; 34 | float4 stops[8]; 35 | }; 36 | struct Path 37 | { 38 | uint hi; 39 | uint vi; 40 | uint hl; 41 | uint vl; 42 | }; 43 | struct Curve 44 | { 45 | float2 begin; 46 | float2 control; 47 | float2 end; 48 | }; 49 | 50 | struct VertexIn 51 | { 52 | float2 PosL : POSITION; 53 | // float3 norms : NORMAL;//vNormal uvNormal uvNorLen 54 | float2 uv : TEXCOORD; 55 | float4 tf : TENSOR; 56 | float3 pnc : PNB0; // path normal color 57 | float3 pnc1 : PNB1; 58 | }; 59 | 60 | struct VertexOut 61 | { 62 | float4 PosH : SV_POSITION; 63 | float2 uv : TEXCOORD; 64 | nointerpolation float3 pnc : PNB0; 65 | nointerpolation float3 pnc1 : PNB1; 66 | }; 67 | 68 | Texture2D g_texture[1024] : register(t0); // albedo normal ORM 69 | StructuredBuffer glyphs : register(t0, space1); 70 | StructuredBuffer curves : register(t1, space1); 71 | StructuredBuffer brushes : register(t1, space2); 72 | 73 | float4 sampleColor(Brush c, float p) 74 | { 75 | //float p = fwidth(pos); 76 | float4 77 | fin = lerp(c.stops[0], c.stops[1], clamp((p - c.pos[0]) / (c.pos[1] - c.pos[0]), 0, 1)); 78 | fin = lerp(fin, c.stops[2], clamp((p - c.pos[1]) / (c.pos[2] - c.pos[1]), 0, 1)); 79 | fin = lerp(fin, c.stops[3], clamp((p - c.pos[2]) / (c.pos[3] - c.pos[2]), 0, 1)); 80 | 81 | return fin; 82 | } 83 | float4 sampleColorAA(Brush c, float p) 84 | { 85 | float dp = fwidth(p); 86 | float4 87 | fin = 0.333f * (sampleColor(c, frac(p - 0.333f * dp)) + sampleColor(c, frac(p)) + sampleColor(c, frac(p + 0.333f * dp))); 88 | 89 | return fin; 90 | } 91 | float4 gradientDir(Brush c, float2 uv, float2 direction) 92 | { 93 | return sampleColor(c, frac(uv.x * direction.x + uv.y * direction.y)); 94 | } 95 | float4 gradientRad(Brush clr, float2 uv, float2 center, float radius, float2 focus) 96 | { 97 | /// APPLY FOCUS MODIFIER 98 | // project a point on the circle such that it passes through the focus and through the coord, 99 | // and then get the distance of the focus from that point. 100 | // that is the effective gradient length 101 | float gradLength = 1.0; 102 | float2 diff = focus - center; 103 | float2 rayDir = normalize(uv - focus); 104 | float a = dot(rayDir, rayDir); 105 | float b = 2.0 * dot(rayDir, diff); 106 | float c = dot(diff, diff) - radius * radius; 107 | float disc = b * b - 4.0 * a * c; 108 | if (disc >= 0.0) 109 | { 110 | float t = (-b + sqrt(abs(disc))) / (2.0 * a); 111 | float2 projection = focus + rayDir * t; 112 | gradLength = distance(projection, focus); 113 | } 114 | else 115 | { 116 | // gradient is undefined for this coordinate 117 | } 118 | 119 | /// OUTPUT 120 | float grad = distance(uv, focus) / gradLength; 121 | return sampleColor(clr, frac(grad)); 122 | } 123 | float4 gradientSwe(Brush c, float2 uv, float2 center, float axis) 124 | { 125 | uv = uv - center; 126 | float angel = atan2(uv.x, uv.y); 127 | return sampleColor(c, frac((angel / 3.1415926 / 2) + axis - 0.25)); 128 | } 129 | -------------------------------------------------------------------------------- /RLL/test.cpp: -------------------------------------------------------------------------------- 1 | #include "rlltest.h" 2 | #include "fi_ft.h" 3 | 4 | #include "harfbuzz/hb.h" 5 | #include "harfbuzz/hb-ft.h" 6 | #include "harfbuzz/hb-icu.h" 7 | 8 | #include "unicode/ucnv.h" 9 | #include "unicode/ubidi.h" 10 | #include "unicode/ustring.h" 11 | #include "unicode/uscript.h" 12 | #include "unicode/brkiter.h" 13 | 14 | #include "perf_util.h" 15 | 16 | #pragma comment(lib, "harfbuzz.lib") 17 | #pragma comment(lib, "harfbuzz-icu.lib") 18 | 19 | #pragma comment(lib, "icuuc.lib") 20 | #pragma comment(lib, "icutu.lib") 21 | #pragma comment(lib, "icuio.lib") 22 | #pragma comment(lib, "icuin.lib") 23 | #pragma comment(lib, "icudt.lib") 24 | 25 | 26 | using namespace Math3D; 27 | using namespace RLL; 28 | 29 | void hb_init() 30 | { 31 | } 32 | void ft_hb_destroy(void*) 33 | { 34 | 35 | } 36 | 37 | RLL::ISVG* hb_test(RLL::IFontFace* ff, RLL::ISVGBuilder* sb, wchar_t* tex) 38 | { 39 | sb->Reset(); 40 | auto f = (FTFace*)ff; 41 | FT_Set_Char_Size(f->face, 72 * 64, 0, 32, 32); 42 | //scale / 65536.f * u/em / 64.f = px 43 | //render unit = 1/(u/em) 44 | 45 | Math3D::Vector2 scale( 46 | f->face->size->metrics.x_scale / 65536.f * f->face->units_per_EM, 47 | f->face->size->metrics.y_scale / 65536.f * f->face->units_per_EM); 48 | auto t = scale * 2048; 49 | 50 | hb_position_t cursor_x = 0; 51 | hb_position_t cursor_y = 0; 52 | //hb_buffer_guess_segment_properties(buf); 53 | auto font = hb_ft_font_create_referenced(f->face); 54 | UChar* ucs = new UChar[wcslen(tex) + 1]; 55 | int32_t tsl = 0; 56 | UErrorCode uec = U_ZERO_ERROR; 57 | u_strFromWCS(ucs, wcslen(tex) + 1, &tsl, tex, -1, &uec); 58 | 59 | auto utx = utext_openUChars(nullptr, ucs, tsl, &uec); 60 | 61 | 62 | auto brki = icu::BreakIterator::createLineInstance(icu::Locale::getDefault(), uec); 63 | brki->setText(utx, uec); 64 | 65 | int32_t p = brki->first(); 66 | setlocale(LC_ALL, ""); 67 | int32_t p_l = p; 68 | printf("%ls\n", tex); 69 | while (p != icu::BreakIterator::DONE) { 70 | //printf("Boundary at position %d\n", p); 71 | if (p_l != p) 72 | { 73 | UChar* word = new UChar[p - p_l + 1]{0}; 74 | utext_extract(utx, p_l, p, word, 999999, &uec); 75 | printf("%ls|", word); 76 | delete[] word; 77 | } 78 | p_l = p; 79 | p = brki->next(); 80 | } 81 | printf("\n"); 82 | delete brki; 83 | utext_close(utx); 84 | 85 | UBiDi* bidi = ubidi_open(); 86 | UBiDiLevel bidiReq = UBIDI_DEFAULT_LTR; 87 | int stringLen = wcslen(tex); 88 | if (bidi) { 89 | UErrorCode status = U_ZERO_ERROR; 90 | ubidi_setPara(bidi, ucs, stringLen, bidiReq, NULL, &status); 91 | 92 | if (U_SUCCESS(status)) { 93 | //int paraDir = ubidi_getParaLevel(bidi); 94 | size_t rc = ubidi_countRuns(bidi, &status); 95 | for (size_t i = 0; i < size_t(rc); ++i) { 96 | 97 | hb_buffer_t* buf = hb_buffer_create();; 98 | 99 | int32_t startRun = -1; 100 | int32_t lengthRun = -1; 101 | UBiDiDirection runDir = ubidi_getVisualRun(bidi, i, &startRun, &lengthRun); 102 | //u_charTo 103 | UChar32 c32; 104 | u_strToUTF32(&c32, 1, nullptr, &ucs[startRun], 1, &status); 105 | auto sc = uscript_getScript(c32, &status); 106 | bool isRTL = (runDir == UBIDI_RTL); 107 | //printf("Processing Bidi Run = %d -- run-start = %d, run-len = %d, isRTL = %d\n", 108 | // i, startRun, lengthRun, isRTL); 109 | hb_buffer_add_utf16(buf, (uint16_t*)ucs, -1, startRun, lengthRun); 110 | 111 | hb_buffer_set_direction(buf, isRTL ? HB_DIRECTION_RTL : HB_DIRECTION_LTR); 112 | hb_buffer_set_script(buf, hb_icu_script_to_script(sc)); 113 | hb_buffer_set_language(buf, hb_language_from_string("en-US", -1)); 114 | 115 | hb_shape(font, buf, NULL, 0); 116 | 117 | unsigned int glyph_count; 118 | hb_glyph_info_t* glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count); 119 | hb_glyph_position_t* glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count); 120 | //TimeCheck("Getglyf start"); 121 | 122 | for (unsigned int i = 0; i < glyph_count; i++) { 123 | auto& info = glyph_info[i]; 124 | hb_codepoint_t glyphid = glyph_info[i].codepoint; 125 | hb_position_t x_offset = glyph_pos[i].x_offset; 126 | hb_position_t y_offset = glyph_pos[i].y_offset; 127 | hb_position_t x_advance = glyph_pos[i].x_advance; 128 | hb_position_t y_advance = glyph_pos[i].y_advance; 129 | /* draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset); */ 130 | //std::cout << x_advance / 64.f << "\t" << y_advance / 64.f << std::endl; 131 | auto sg = ff->GetGlyph(glyphid); 132 | hb_position_t x = cursor_x + x_offset; 133 | hb_position_t y = cursor_y + y_offset; 134 | if (sg) 135 | sb->Push(sg, &(Matrix4x4::Translation({ x / scale.x ,y / scale.y ,0 }))); 136 | cursor_x += x_advance; 137 | cursor_y += y_advance; 138 | } 139 | //TimeCheck("Getglyf end"); 140 | //TimeCheckSum(); 141 | hb_buffer_destroy(buf); 142 | 143 | //UScriptRun scriptRun(tex, startRun, lengthRun); 144 | //while (scriptRun.next()) { 145 | // int32_t start = scriptRun.getScriptStart(); 146 | // int32_t end = scriptRun.getScriptEnd(); 147 | // UScriptCode code = scriptRun.getScriptCode(); 148 | 149 | // printf("Script '%s' from %d to %d.\n", uscript_getName(code), start, end); 150 | //} 151 | } 152 | } 153 | } 154 | 155 | 156 | 157 | 158 | hb_font_destroy(font); 159 | return sb->Commit(); 160 | } -------------------------------------------------------------------------------- /RLL/test/format.txt: -------------------------------------------------------------------------------- 1 | language=c++ 2 | { 3 | #include "xxxx.h" 4 | } 5 | frame(width=800,height=600,style="uni",mvable,!sizable,id=xxx){ 6 | div() 7 | { 8 | title() 9 | { 10 | List display 11 | } 12 | { 13 | "div(){text(weight=bold){to display a var name use \$ on left of the var.}}" 14 | for(int i = 1;i <= 2; i++) 15 | { 16 | "div(){text(weight=bold){column$i}}" 17 | } 18 | for(auto i : list) 19 | { 20 | auto name = i.name.c_str(); 21 | auto age = i.age.c_str(); 22 | "div(){text(){$name} text(){age}}"; 23 | } 24 | } 25 | } 26 | } 27 | 28 | /* 29 | compiled content: 30 | 31 | #include "xxxx.h" 32 | int EntryPoint() 33 | { 34 | auto frame_hexid = new Frame(); 35 | frame_hexid->width(800); 36 | frame_hexid->height(600); 37 | frame_hexid->style("uni") 38 | frame_hexid->movable(true); 39 | frame_hexid->sizable(false); 40 | frame_hexid->id("xxx"); 41 | 42 | auto div_xxx = new Div(); 43 | frame_hexid->place(div_xxx); 44 | 45 | auto title_xxx = new Title(); 46 | title_xxx->place("List display"); 47 | 48 | for(int i = 1;i <= 2; i++) 49 | { 50 | //"text(weight=bold){column$i}" 51 | auto text_xx = new Text(); 52 | text_xx->weight("bold") 53 | text_xx->plcae("column"+formatter(i)); 54 | } 55 | for(auto i : list) 56 | { 57 | auto name = i.name.c_str(); 58 | auto age = i.age.c_str(); 59 | //"text(){$name} text(){age}"; 60 | 61 | } 62 | 63 | } 64 | */ -------------------------------------------------------------------------------- /RLL/win32acrylic.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaazar/RLL/f82af45fa96038485a10bef3f6a514242f79e978/RLL/win32acrylic.cpp -------------------------------------------------------------------------------- /RLL/win32acrylic.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "win32internal.h" 3 | #define DWM_TNP_FREEZE 0x100000 4 | #define DWM_TNP_ENABLE3D 0x4000000 5 | #define DWM_TNP_DISABLE3D 0x8000000 6 | #define DWM_TNP_FORCECVI 0x40000000 7 | #define DWM_TNP_DISABLEFORCECVI 0x80000000 8 | 9 | namespace Acrylic 10 | { 11 | enum BackdropSource 12 | { 13 | BACKDROP_SOURCE_DESKTOP = 0x0, 14 | BACKDROP_SOURCE_HOSTBACKDROP = 0x1 15 | }; 16 | struct AcrylicEffectParameter 17 | { 18 | float blurAmount; 19 | float saturationAmount; 20 | D2D1_COLOR_F tintColor; 21 | D2D1_COLOR_F fallbackColor; 22 | }; 23 | enum WINDOWCOMPOSITIONATTRIB 24 | { 25 | WCA_UNDEFINED = 0x0, 26 | WCA_NCRENDERING_ENABLED = 0x1, 27 | WCA_NCRENDERING_POLICY = 0x2, 28 | WCA_TRANSITIONS_FORCEDISABLED = 0x3, 29 | WCA_ALLOW_NCPAINT = 0x4, 30 | WCA_CAPTION_BUTTON_BOUNDS = 0x5, 31 | WCA_NONCLIENT_RTL_LAYOUT = 0x6, 32 | WCA_FORCE_ICONIC_REPRESENTATION = 0x7, 33 | WCA_EXTENDED_FRAME_BOUNDS = 0x8, 34 | WCA_HAS_ICONIC_BITMAP = 0x9, 35 | WCA_THEME_ATTRIBUTES = 0xA, 36 | WCA_NCRENDERING_EXILED = 0xB, 37 | WCA_NCADORNMENTINFO = 0xC, 38 | WCA_EXCLUDED_FROM_LIVEPREVIEW = 0xD, 39 | WCA_VIDEO_OVERLAY_ACTIVE = 0xE, 40 | WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 0xF, 41 | WCA_DISALLOW_PEEK = 0x10, 42 | WCA_CLOAK = 0x11, 43 | WCA_CLOAKED = 0x12, 44 | WCA_ACCENT_POLICY = 0x13, 45 | WCA_FREEZE_REPRESENTATION = 0x14, 46 | WCA_EVER_UNCLOAKED = 0x15, 47 | WCA_VISUAL_OWNER = 0x16, 48 | WCA_HOLOGRAPHIC = 0x17, 49 | WCA_EXCLUDED_FROM_DDA = 0x18, 50 | WCA_PASSIVEUPDATEMODE = 0x19, 51 | WCA_LAST = 0x1A, 52 | }; 53 | 54 | struct WINDOWCOMPOSITIONATTRIBDATA 55 | { 56 | WINDOWCOMPOSITIONATTRIB Attrib; 57 | void* pvData; 58 | DWORD cbData; 59 | }; 60 | 61 | typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW); 62 | typedef BOOL(WINAPI* SetWindowCompositionAttribute)(IN HWND hwnd, IN WINDOWCOMPOSITIONATTRIBDATA* pwcad); 63 | typedef HRESULT(WINAPI* DwmpCreateSharedThumbnailVisual)(IN HWND hwndDestination, IN HWND hwndSource, IN DWORD dwThumbnailFlags, IN DWM_THUMBNAIL_PROPERTIES* pThumbnailProperties, IN VOID* pDCompDevice, OUT VOID** ppVisual, OUT PHTHUMBNAIL phThumbnailId); 64 | typedef HRESULT(WINAPI* DwmpCreateSharedMultiWindowVisual)(IN HWND hwndDestination, IN VOID* pDCompDevice, OUT VOID** ppVisual, OUT PHTHUMBNAIL phThumbnailId); 65 | typedef HRESULT(WINAPI* DwmpUpdateSharedMultiWindowVisual)(IN HTHUMBNAIL hThumbnailId, IN HWND* phwndsInclude, IN DWORD chwndsInclude, IN HWND* phwndsExclude, IN DWORD chwndsExclude, OUT RECT* prcSource, OUT SIZE* pDestinationSize, IN DWORD dwFlags); 66 | typedef HRESULT(WINAPI* DwmpCreateSharedVirtualDesktopVisual)(IN HWND hwndDestination, IN VOID* pDCompDevice, OUT VOID** ppVisual, OUT PHTHUMBNAIL phThumbnailId); 67 | typedef HRESULT(WINAPI* DwmpUpdateSharedVirtualDesktopVisual)(IN HTHUMBNAIL hThumbnailId, IN HWND* phwndsInclude, IN DWORD chwndsInclude, IN HWND* phwndsExclude, IN DWORD chwndsExclude, OUT RECT* prcSource, OUT SIZE* pDestinationSize); 68 | 69 | DwmpCreateSharedThumbnailVisual DwmCreateSharedThumbnailVisual; 70 | DwmpCreateSharedMultiWindowVisual DwmCreateSharedMultiWindowVisual; 71 | DwmpUpdateSharedMultiWindowVisual DwmUpdateSharedMultiWindowVisual; 72 | DwmpCreateSharedVirtualDesktopVisual DwmCreateSharedVirtualDesktopVisual; 73 | DwmpUpdateSharedVirtualDesktopVisual DwmUpdateSharedVirtualDesktopVisual; 74 | SetWindowCompositionAttribute DwmSetWindowCompositionAttribute; 75 | RtlGetVersionPtr GetVersionInfo; 76 | 77 | long GetBuildVersion(); 78 | bool Initiate(); 79 | } -------------------------------------------------------------------------------- /RLL/win32core.cpp: -------------------------------------------------------------------------------- 1 | #include "win32internal.h" 2 | #include "win32paint_d12.h" 3 | #include "DirectXColors.h" 4 | #include "fi_ft.h" 5 | #include "rlltest.h" 6 | #include "TextInterfaces.h" 7 | #include 8 | 9 | #pragma comment(lib, "user32.lib") 10 | #pragma comment(lib, "uxtheme.lib") 11 | 12 | using namespace Math3D; 13 | using namespace RLL; 14 | #define ARRLEN(x) (sizeof(x)/sizeof(*x)) 15 | #define SHADER_CORE L"shader\\core.hlsl" 16 | #define MSAA 0 17 | 18 | #ifndef GET_X_PARAM 19 | #define GET_X_PARAM(lp) ((int)(short)LOWORD(lp)) 20 | #endif 21 | 22 | #ifndef GET_Y_PARAM 23 | #define GET_Y_PARAM(lp) ((int)(short)HIWORD(lp)) 24 | #endif 25 | 26 | 27 | Vector2 dpiScaleFactor = { 1,1 }; 28 | wchar_t locale[LOCALE_NAME_MAX_LENGTH]; 29 | RLL::IPaintDevice* paintDevice; 30 | 31 | //TestField 32 | RLL::ISVG* cm_t_glfs; 33 | RLL::ISVG* cm_t_cir; 34 | RLL::ISVG* cm_t_tly; 35 | RLL::ISVGBuilder* sb; 36 | RLL::IGeometryBuilder* gb; 37 | UINT m4xMsaaQuality; 38 | Vector2 cam_t = { 0,0 }; 39 | Vector1 cam_s = 1; 40 | Vector2 cam_md = { -1,0 }; 41 | Matrix4x4 vtf; 42 | 43 | #pragma region util 44 | bool PointInRect(Math3D::Vector2 pt, Vector4 r) 45 | { 46 | if (pt.x < r.l) return false; 47 | if (pt.y < r.t) return false; 48 | if (pt.x > r.r) return false; 49 | if (pt.y > r.b) return false; 50 | return true; 51 | } 52 | struct DWM_COLORIZATION_PARAMS 53 | { 54 | COLORREF clrColor; 55 | COLORREF clrAfterGlow; 56 | UINT nIntensity; 57 | UINT clrAfterGlowBalance; 58 | UINT clrBlurBalance; 59 | UINT clrGlassReflectionIntensity; 60 | BOOL fOpaque; 61 | }; 62 | #include "win32whelper.h" 63 | #pragma endregion 64 | #pragma region api 65 | //RLL 66 | wchar_t* RLL::GetLocale() 67 | { 68 | return locale; 69 | } 70 | Math3D::Vector2 RLL::GetScale() 71 | { 72 | return dpiScaleFactor; 73 | } 74 | RLL::IFrame* RLL::CreateFrame(IFrame* parent, Math3D::Vector2 size, Math3D::Vector2 pos) 75 | { 76 | return new Frame(reinterpret_cast(parent), size, pos); 77 | } 78 | int gFlags; 79 | void RLL::Initiate(int flags) 80 | { 81 | gFlags = flags; 82 | HRESULT hr; 83 | SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE); 84 | 85 | GetUserDefaultLocaleName(locale, sizeof(locale)); 86 | //TextLayoutInit(); 87 | 88 | } 89 | int RLL::GetFlags() 90 | { 91 | return gFlags; 92 | } 93 | #pragma endregion 94 | 95 | LRESULT wndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 96 | { 97 | LRESULT result = 0; 98 | if (msg == WM_NCCREATE) { 99 | auto userdata = reinterpret_cast(lp)->lpCreateParams; 100 | // store window instance pointer in window user data 101 | ::SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast(userdata)); 102 | } 103 | if (auto window_ptr = reinterpret_cast(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))) 104 | { 105 | auto& frame = *window_ptr; 106 | result = frame.WndProc(hwnd, msg, wp, lp); 107 | } 108 | return result; 109 | } 110 | LRESULT Frame::NextProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) 111 | { 112 | return DefWindowProc(hwnd, msg, wp, lp); 113 | } 114 | Frame::Frame(Frame* parent, Vector2 size, Vector2 pos) 115 | { 116 | HWND hWnd_parent = NULL; 117 | if (parent) 118 | hWnd_parent = parent->hWnd; 119 | 120 | static const wchar_t* window_class_name = L"WIN32_CONTAINER_WINDOW"; 121 | WNDCLASSEXW window_class = { 0 }; 122 | { 123 | window_class.cbSize = sizeof(window_class); 124 | window_class.lpszClassName = window_class_name; 125 | // Set the procedure that will receive window messages (events) 126 | window_class.lpfnWndProc = wndProc; 127 | // Ask to send WM_PAINT when resizing horizontally and vertically 128 | window_class.style = CS_HREDRAW | CS_VREDRAW; 129 | } 130 | RegisterClassExW(&window_class); 131 | 132 | int window_style 133 | = WS_THICKFRAME // required for a standard resizeable window 134 | | WS_SYSMENU // Explicitly ask for the titlebar to support snapping via Win + ← / Win + → 135 | | WS_MAXIMIZEBOX // Add maximize button to support maximizing via mouse dragging 136 | | WS_CAPTION // to the top of the screen 137 | | WS_MINIMIZEBOX // Add minimize button to support minimizing by clicking on the taskbar icon 138 | | WS_POPUP; 139 | 140 | hWnd = CreateWindowExW( 141 | WS_EX_APPWINDOW | WS_EX_NOREDIRECTIONBITMAP, 142 | window_class_name, 143 | L"Win32 Custom Title Bar Example", 144 | // The 145 | window_style, 146 | CW_USEDEFAULT, 147 | CW_USEDEFAULT, 148 | 800, 149 | 600, 150 | hWnd_parent, 151 | 0, 152 | 0, 153 | this 154 | ); 155 | 156 | //HRESULT hr; 157 | //HWND hWnd_parent = NULL; 158 | //if (parent) 159 | // hWnd_parent = parent->hWnd; 160 | //SIZE scaledsz{ (LONG)(size.x * dpiScaleFactor.x) ,(LONG)(size.y * dpiScaleFactor.x) }; 161 | //POINT posi{ (LONG)pos.x,(LONG)pos.y }; 162 | //hWnd = create_window(hWnd_parent, wndProc, this, scaledsz, posi, extStyles | WS_EX_NOREDIRECTIONBITMAP); 163 | 164 | AquireWindowRect(); 165 | 166 | //TestField. 167 | paintDevice = RLL::CreatePaintDevice(); 168 | paintCtx = (D3D12FramePaintContext*)paintDevice->CreateContextForFrame(this); 169 | 170 | auto ffact = RLL::CreateFontFactory(paintDevice); 171 | auto fc_tms = ffact->LoadFromFile("c:/windows/fonts/times.ttf"); 172 | auto fc_rob = ffact->LoadFromFile("c:/windows/fonts/Roboto-Regular.ttf"); 173 | auto fc_dsm = ffact->LoadFromFile("c:/windows/fonts/DroidSansMono.ttf"); 174 | auto fc_msyh = ffact->LoadFromFile("c:/windows/fonts/msyh.ttc"); 175 | auto fc_emj = ffact->LoadFromFile("c:/windows/fonts/seguiemj.ttf"); 176 | auto fc_khm = ffact->LoadFromFile("c:/windows/fonts/Khmer.ttf"); 177 | auto fc_sun = ffact->LoadFromFile("c:/windows/fonts/simsun.ttc"); 178 | auto fc_fsun = ffact->LoadFromFile("c:/windows/fonts/simfang.TTF"); 179 | auto fc_arial = ffact->LoadFromFile("c:/windows/fonts/arial.ttf"); 180 | auto fc_nirm = ffact->LoadFromFile("c:/windows/fonts/Nirmala.ttf"); 181 | auto fc_leelw = ffact->LoadFromFile("c:/windows/fonts/LeelawUI.ttf"); 182 | gb = paintDevice->CreateGeometryBuilder(); 183 | auto go = fc_msyh->GetGlyph(U'默'); 184 | gb->Reset(); 185 | auto go2 = (D3D12Geometry*)fc_msyh->GetPlainGlyph(U'字'); 186 | 187 | gb->Reset(); 188 | auto go1 = (D3D12Geometry*)fc_msyh->GetPlainGlyph(U'M'); 189 | 190 | auto tmat = Matrix4x4::Scaling(1.234f) * Matrix4x4::Translation({ 200,300 }) * Matrix4x4::Rotation(1, 0, 0); 191 | RLL::ColorGradient cg; 192 | cg.colors[0] = { 1,1,0,0 }; 193 | cg.colors[1] = { 0.3f,1,0.3f,0 }; 194 | cg.positions[1] = 1; 195 | auto br_yg = paintDevice->CreateRadialBrush({ 0,0 }, 1.0, &cg); 196 | 197 | cg.colors[0] = { 1,0.87f,0,0 }; 198 | cg.colors[1] = { 1,0.27f,0.3f,0 }; 199 | auto br_dps = paintDevice->CreateRadialBrush({ 0,0 }, 1, &cg); 200 | br_dps->Release(); 201 | auto br_yg_tex = paintDevice->CreateRadialBrush({ 0.5,0.5 }, 1, &cg); 202 | auto br_rec = paintDevice->CreateRadialBrush({ 0,0 }, 1, &cg); 203 | 204 | auto fs_df = new IFontStack(); 205 | fs_df->Push(fc_emj); 206 | fs_df->Push(fc_nirm); 207 | fs_df->Push(fc_leelw); 208 | fs_df->Push(fc_arial); 209 | fs_df->Push(fc_msyh); 210 | 211 | auto tl = new TextLayout(L"\ 212 | TextLayout. 这次职业生涯规划。\ 213 | Français Abc defgh a123c 1.2f.\ 214 | nbsp left. done? emj\ 215 | कोहियर से नमस्ते!😎🧑🏿🧑🏿🥳|אָלֶף־בֵּית 🧑🏿🥳עִבְרִי/ ltr🥵rtl |اللغة العربية/\ 216 | Olá do Cohere! Крупнокалиберный Переполох. ให้เคอรี่มาส่งได้บ่? RLO‮fdp.exe‬PDF,LRO‭|اللغة العربية/‬PDF\ 217 | 微笑世界•处处D\ 218 | 微笑世界·处处D" 219 | , { 330,50 }, fs_df); 220 | //tl->Break();//TextLayout文本布局。Abc defgh a123c 1.234ff. nbsp left. done? emj😎🧑🏿🧑🏿 221 | //tl->Metrics(); 222 | cm_t_tly = tl->Commit(paintDevice); 223 | wchar_t* khm = L"אָלֶף־בֵּית"; 224 | 225 | sb = paintDevice->CreateSVGBuilder(); 226 | ISVG* svg_sb = fc_rob ? (D3D12SVG*)hb_test(fc_rob, sb, L"Roboto Regular. AWAVfifiifjflft. 中字默。abcDT") : nullptr; 227 | sb->Reset(); 228 | ISVG* svg_sbt = fc_tms ? (D3D12SVG*)hb_test(fc_tms, sb, L"Times New Roman. AWAVfifiifjflftfL. 中字默。abcDT nbsp 1 km/h RLO‮fdp.exe‬LRO") : nullptr; 229 | sb->Reset(); 230 | ISVG* svg_sbk = fc_khm ? (D3D12SVG*)hb_test(fc_khm, sb, L"ញុំបានមើ khmer") : nullptr;//ញុំបានមើ khmer 231 | sb->Reset(); 232 | ISVG* svg_sbc = fc_msyh ? (D3D12SVG*)hb_test(fc_msyh, sb, L"雅黑。这次职业生涯规划生涯人物访谈,中字默一(十)川(abc)七abc八123abc毫") : nullptr;//ញុំបានមើ khmer 233 | sb->Reset(); 234 | ISVG* svg_sbcs = fc_sun ? (D3D12SVG*)hb_test(fc_sun, sb, L"宋体。这次职业生涯规划生涯人物访谈,中字默一(十)川(abc)七abc八123abc毫") : nullptr;//ញុំបានមើ khmer 235 | sb->Reset(); 236 | ISVG* svg_sbcfs = fc_fsun ? (D3D12SVG*)hb_test(fc_fsun, sb, L"仿宋。这次职业生涯规划生涯人物访谈,中字默一(十)川(abc)七abc八123abc毫") : nullptr;//ញុំបានមើ khmer 237 | sb->Reset(); 238 | ISVG* svg_dsm = fc_dsm ? (D3D12SVG*)hb_test(fc_dsm, sb, L"Latin series TrueType DroidSansMono.") : nullptr; 239 | sb->Reset(); 240 | ISVG* svg_heb = fc_arial ? (D3D12SVG*)hb_test(fc_arial, sb, L"Hebrew: אָלֶף־בֵּית עִבְרִי, Arabic: اللغة العربية, All 12pt") : nullptr; 241 | sb->Reset(); 242 | ISVG* svg_emj = fc_emj ? (D3D12SVG*)hb_test(fc_emj, sb, L"🧑🧑🏻🧑🏼🧑🏽🧑🏾🧑🏿🥵😰") : nullptr; 243 | 244 | sb->Reset(); 245 | sb->Push(go); 246 | sb->Push(go1, br_yg, &Matrix4x4::Translation(Vector3(1, 0, 0) * 1.2)); 247 | sb->Push(go2, br_yg_tex, &Matrix4x4::Translation(Vector3(0, 1, 0) * 1.2)); 248 | auto glf_clr = fc_emj->GetGlyph(U'🥳'); 249 | sb->Push(glf_clr, &Matrix4x4::Translation(Vector3(2, 0, 0) * 1.2)); 250 | glf_clr = fc_emj->GetGlyph(U'😍'); 251 | sb->Push(glf_clr, &Matrix4x4::Translation(Vector3(3, 0, 0) * 1.2)); 252 | if (svg_sb) sb->Push(svg_sb, &Matrix4x4::Translation(Vector3(0, 2, 0) * 1.2)); 253 | if (svg_sbt)sb->Push(svg_sbt, &Matrix4x4::Translation(Vector3(0, 3, 0) * 1.2)); 254 | if (svg_sbk)sb->Push(svg_sbk, &Matrix4x4::Translation(Vector3(0, 4, 0) * 1.2)); 255 | if (svg_sbc)sb->Push(svg_sbc, &Matrix4x4::Translation(Vector3(0, 6, 0) * 1.2)); 256 | if (svg_sbcs)sb->Push(svg_sbcs, &Matrix4x4::Translation(Vector3(0, 7, 0) * 1.2)); 257 | if (svg_sbcfs)sb->Push(svg_sbcfs, &Matrix4x4::Translation(Vector3(0, 8, 0) * 1.2)); 258 | if (svg_dsm)sb->Push(svg_dsm, &Matrix4x4::Translation(Vector3(0, 9, 0) * 1.2)); 259 | if (svg_heb)sb->Push(svg_heb, &Matrix4x4::Translation(Vector3(0, 10, 0) * 1.2)); 260 | if (svg_emj)sb->Push(svg_emj, &Matrix4x4::Translation(Vector3(0, 11, 0) * 1.2)); 261 | cm_t_glfs = sb->Commit(); 262 | //cm_t_glfs = svg_sb->mesh; 263 | gb->Reset(); 264 | gb->Ellipse({ 0,0 }, { 1,1.3 }); 265 | gb->Ellipse({ 0.8,0 }, { 1 * 0.9,1.3 * .9 }, true); 266 | auto go_circle = gb->Fill(); 267 | 268 | sb->Reset(); 269 | sb->Push(go_circle, br_yg, &(Matrix4x4::Scaling(60) * Matrix4x4::Translation({ -100,-70 }))); 270 | gb->Reset(); 271 | gb->Ellipse({ 0,0 }, { 1,1 }); 272 | gb->Ellipse({ -0.7,0 }, { 0.9,0.9 }, true); 273 | go_circle = gb->Fill(); 274 | gb->Reset(); 275 | gb->Rectangle({ -1,-1 }, { 1,1 }); 276 | auto go_geo = gb->Fill(); 277 | 278 | sb->Push(go_circle, br_yg, &(Matrix4x4::Scaling(60) * Matrix4x4::Translation({ -100,70 }))); 279 | sb->Push(go_geo, br_rec, &(Matrix4x4::Scaling(40) * Matrix4x4::Translation({ -300,100 }) * Matrix4x4::Rotation(Quaternion::RollPitchYaw(0, 0, 1)))); 280 | 281 | gb->Reset(); 282 | gb->Triangle({ -1,0 }, { 1,0 }, { 1.5,1.26 }); 283 | go_geo = gb->Fill(); 284 | 285 | sb->Push(go_geo, br_yg_tex, &(Matrix4x4::Scaling(50) * Matrix4x4::Translation({ 50,-100 }))); 286 | 287 | gb->Reset(); 288 | gb->RoundRectangle({ -1,0 }, { 1,1 }, { 0.1,0.1 }); 289 | gb->Ellipse({ 0,0.5 }, { 0.3,0.3 }, true); 290 | gb->RoundRectangle({ -0.5,0.1 }, { 0.5,0.5 }, { 0.05,0.1 }, true); 291 | go_geo = gb->Fill(); 292 | sb->Push(go_geo, nullptr, &(Matrix4x4::Scaling(90) * Matrix4x4::Translation({ -100,250 }))); 293 | 294 | gb->Reset(); 295 | gb->Begin({ 0,0 }); 296 | gb->ArcTo({ 0,0 }, { 1.3,1 }, 0, Deg2Rad(138)); 297 | gb->End(true); 298 | go_geo = gb->Fill(); 299 | sb->Push(go_geo, br_yg, &(Matrix4x4::Scaling(50) * Matrix4x4::Translation({ -200,200 }))); 300 | 301 | gb->Reset(); 302 | gb->Begin({ 0,0 }); 303 | //gb->SetBackgroundTransform(&Matrix4x4::Scaling({ 1.f/200, 1.f/200, 1 })); 304 | gb->QuadraticTo({ 250,-100 }, { 200,0 }); 305 | gb->LineTo({ 300,50 }); 306 | //gb->MoveTo({ 200,0 }); 307 | gb->End(true); 308 | 309 | gb->Begin({ 0,50 }); 310 | gb->CubicTo({ -250,150 }, { 50,150 }, { -200,50 }); 311 | gb->End(false); 312 | 313 | //below convhull bug 314 | //gb->Begin({ 50,0 }); 315 | //gb->CubicTo({ -250,150 }, { 50,150 }, { -200,50 }); 316 | //gb->End(false); //bug test end 317 | 318 | go_geo = gb->Stroke(5, nullptr, &Matrix4x4::Scaling({ 1 / 200.f, 1 / 200.f, 1 })); 319 | //go_geo = gb->Stroke(5, nullptr); 320 | //go_geo = gb->Fill(&Matrix4x4::Scaling({ 1.f / 200, 1.f / 200, 1 })); 321 | sb->Push(go_geo, br_yg_tex, &(Matrix4x4::Translation({ -180,-150 }))); 322 | //sb->Push(svg_tly); 323 | cm_t_cir = sb->Commit(); 324 | paintCtx->Flush(); 325 | //rbo_glyph = paintDevice->CreateUploadBuffer(sizeof(CBObject)); 326 | //rbo_circ = paintDevice->CreateUploadBuffer(sizeof(CBObject)); 327 | //rbf_root = paintDevice->CreateUploadBuffer(sizeof(CBFrame)); 328 | 329 | //cbo_t_glyph.lerpTime = 0; 330 | //cbo_t_glyph.sampleType = 0; 331 | //cbo_t_glyph.objToWorld = Matrix4x4::Scaling({ 13 * 96 / 72 }); // px = pt * dpi / 72 332 | //cbo_t_circ.lerpTime = 0; 333 | //cbo_t_circ.sampleType = 0; 334 | //cbo_t_circ.objToWorld = Matrix4x4::Scaling(1); // px = pt * dpi / 72 335 | 336 | //cbf_root.dColor = { 0,0,0,0 }; 337 | //cbf_root.gWorldViewProj = Matrix4x4::LookTo({ 0,0,-500 }, { 0,0,1 }) * 338 | // Matrix4x4::Scaling({ 1,-1,1 }) * 339 | // Matrix4x4::Orthographic(800, 600, 1, 1000); 340 | //cbf_root.vwh = { 800,600 }; 341 | 342 | //rbo_glyph.Sync(cbo_t_glyph); 343 | //rbo_circ.Sync(cbo_t_circ); 344 | //rbf_root.Sync(cbf_root); 345 | } 346 | static bool win32_window_is_maximized(HWND handle) 347 | { 348 | WINDOWPLACEMENT placement = { 0 }; 349 | placement.length = sizeof(WINDOWPLACEMENT); 350 | if (GetWindowPlacement(handle, &placement)) { 351 | return placement.showCmd == SW_SHOWMAXIMIZED; 352 | } 353 | return false; 354 | } 355 | 356 | static int win32_dpi_scale(int value, UINT dpi) { 357 | return (int)((float)value * dpi / 96); 358 | } 359 | 360 | // Adopted from: 361 | // https://github.com/oberth/custom-chrome/blob/master/source/gui/window_helper.hpp#L52-L64 362 | static RECT win32_titlebar_rect(HWND handle) { 363 | SIZE title_bar_size = { 0 }; 364 | const int top_and_bottom_borders = 2; 365 | HTHEME theme = OpenThemeData(handle, L"WINDOW"); 366 | UINT dpi = GetDpiForWindow(handle); 367 | GetThemePartSize(theme, NULL, WP_CAPTION, CS_ACTIVE, NULL, TS_TRUE, &title_bar_size); 368 | CloseThemeData(theme); 369 | 370 | int height = win32_dpi_scale(title_bar_size.cy, dpi) + top_and_bottom_borders; 371 | 372 | RECT rect; 373 | GetClientRect(handle, &rect); 374 | rect.bottom = rect.top + height; 375 | return rect; 376 | } 377 | 378 | // Set this to 0 to remove the fake shadow painting 379 | #define WIN32_FAKE_SHADOW_HEIGHT 1 380 | // The offset of the 2 rectangles of the maximized window button 381 | #define WIN32_MAXIMIZED_RECTANGLE_OFFSET 2 382 | 383 | static RECT win32_fake_shadow_rect(HWND handle) { 384 | RECT rect; 385 | GetClientRect(handle, &rect); 386 | rect.bottom = rect.top + WIN32_FAKE_SHADOW_HEIGHT; 387 | return rect; 388 | } 389 | 390 | LRESULT Frame::WndProc(HWND handle, UINT message, WPARAM w_param, LPARAM l_param) 391 | { 392 | 393 | switch (message) 394 | { 395 | case WM_CREATE: 396 | //std::cout << "WMC\n"; 397 | hWnd = handle; 398 | SetWindowPos( 399 | handle, NULL, 400 | 0, 0, 0, 0, 401 | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER 402 | ); break; 403 | case WM_NCCALCSIZE: 404 | { 405 | if (!w_param) return DefWindowProc(handle, message, w_param, l_param); 406 | UINT dpi = GetDpiForWindow(handle); 407 | 408 | int frame_x = GetSystemMetricsForDpi(SM_CXFRAME, dpi); 409 | int frame_y = GetSystemMetricsForDpi(SM_CYFRAME, dpi); 410 | int padding = GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); 411 | 412 | NCCALCSIZE_PARAMS* params = (NCCALCSIZE_PARAMS*)l_param; 413 | RECT* requested_client_rect = params->rgrc; 414 | 415 | requested_client_rect->right -= frame_x + padding; 416 | requested_client_rect->left += frame_x + padding; 417 | requested_client_rect->bottom -= frame_y + padding; 418 | 419 | if (win32_window_is_maximized(handle)) { 420 | requested_client_rect->top += padding; 421 | } 422 | 423 | return 0; 424 | } 425 | case WM_NCHITTEST: 426 | // When we have no border or title bar, we need to perform our 427 | // own hit testing to allow resizing and moving. 428 | { 429 | // Let the default procedure handle resizing areas 430 | LRESULT hit = DefWindowProc(handle, message, w_param, l_param); 431 | switch (hit) { 432 | case HTNOWHERE: 433 | case HTRIGHT: 434 | case HTLEFT: 435 | case HTTOPLEFT: 436 | case HTTOP: 437 | case HTTOPRIGHT: 438 | case HTBOTTOMRIGHT: 439 | case HTBOTTOM: 440 | case HTBOTTOMLEFT: { 441 | return hit; 442 | } 443 | } 444 | // Check if hover button is on maximize to support SnapLayout on Windows 11 445 | //if (title_bar_hovered_button == CustomTitleBarHoveredButton_Maximize) { 446 | // return HTMAXBUTTON; 447 | //} 448 | 449 | // Looks like adjustment happening in NCCALCSIZE is messing with the detection 450 | // of the top hit area so manually fixing that. 451 | UINT dpi = GetDpiForWindow(handle); 452 | int frame_y = GetSystemMetricsForDpi(SM_CYFRAME, dpi); 453 | int padding = GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi); 454 | POINT cursor_point = { 0 }; 455 | cursor_point.x = GET_X_PARAM(l_param); 456 | cursor_point.y = GET_Y_PARAM(l_param); 457 | ScreenToClient(handle, &cursor_point); 458 | 459 | // We should not return HTTOP when hit-testing a maximized window 460 | if (!win32_window_is_maximized(handle) && cursor_point.y > 0 && cursor_point.y < frame_y + padding) { 461 | return HTTOP; 462 | } 463 | 464 | // Since we are drawing our own caption, this needs to be a custom test 465 | if (cursor_point.y < win32_titlebar_rect(handle).bottom) { 466 | return HTCAPTION; 467 | } 468 | 469 | return HTCLIENT; 470 | } 471 | break; 472 | case WM_NCACTIVATE: 473 | if (!composition_enabled()) { 474 | // Prevents window frame reappearing on window activation 475 | // in "basic" theme, where no aero shadow is present. 476 | return 1; 477 | } 478 | break; 479 | case WM_PAINT: 480 | { 481 | //OutputDebugString(L"Paint\n"); 482 | paintCtx->BeginDraw(); 483 | paintCtx->Clear({ 1,1,1, 1.f }); 484 | paintCtx->SetTransform(Matrix4x4::Scaling({ 12 * 96 / 72 }) * vtf); 485 | paintCtx->DrawSVG(cm_t_glfs); 486 | paintCtx->SetTransform(vtf); 487 | paintCtx->DrawSVG(cm_t_cir); 488 | paintCtx->SetTransform(Matrix4x4::Translation({ 0,-200,0 }) * vtf); 489 | paintCtx->DrawSVG(cm_t_tly); 490 | paintCtx->EndDraw(); 491 | //SUCCESS(dCompDevice->Commit()); 492 | break; 493 | } 494 | case WM_SIZE: 495 | if (paintDevice) 496 | { 497 | AquireWindowRect(); 498 | paintCtx->ResizeView(); 499 | } 500 | break; 501 | case WM_MOUSEMOVE: 502 | case WM_NCMOUSEMOVE: 503 | { 504 | 505 | //break; 506 | } 507 | case WM_LBUTTONUP: 508 | case WM_LBUTTONDOWN: 509 | { 510 | //WndProc(hwnd, WM_MOUSEMOVE, wp, lp); 511 | } 512 | case WM_RBUTTONDOWN: 513 | case WM_RBUTTONUP: 514 | case WM_MBUTTONDOWN: 515 | case WM_MBUTTONUP: 516 | //case WM_SETCURSOR: 517 | { 518 | if (message == WM_MBUTTONUP) 519 | _DBG_D3DLIVE_OBJ(); 520 | 521 | //WndProc(hwnd, WM_MOUSEMOVE, wp, lp); 522 | Vector2 mouse{ GET_X_LPARAM(l_param) / dpiScaleFactor.x,GET_Y_LPARAM(l_param) / dpiScaleFactor.y }; 523 | POINT cm; 524 | cm.x = mouse.x * dpiScaleFactor.x; 525 | cm.y = mouse.y * dpiScaleFactor.y; 526 | if (message == WM_LBUTTONDOWN) 527 | { 528 | cam_md = { (float)cm.x,(float)cm.y }; 529 | } 530 | else if (message == WM_LBUTTONUP) 531 | { 532 | cam_md.x = -1; 533 | } 534 | else if (message == WM_MOUSEMOVE && cam_md.x != -1) 535 | { 536 | Vector2 mp(cm.x, cm.y); 537 | auto d = mp - cam_md; 538 | cam_t = cam_t + Vector2(d.x, d.y) * 1.01; 539 | cam_md = mp; 540 | 541 | vtf = Matrix4x4::TRS({ cam_t.x,cam_t.y,0 }, Quaternion::identity(), { cam_s,cam_s,cam_s }); 542 | //rbf_root.Sync(cbf_root); 543 | PostMessage(handle, WM_PAINT, 0, 0); 544 | 545 | } 546 | //std::cout << cam_md.x << "\t" << cam_s << "\t" << cam_t.x << ", " << cam_t.y << std::endl; 547 | LRESULT ret = 0; 548 | return ret; 549 | } 550 | case WM_NCLBUTTONDOWN: 551 | case WM_NCLBUTTONUP: 552 | case WM_NCRBUTTONDOWN: 553 | case WM_NCRBUTTONUP: 554 | case WM_NCMBUTTONDOWN: 555 | case WM_NCMBUTTONUP: 556 | { 557 | RECT wr; 558 | GetWindowRect(hWnd, &wr); 559 | POINT mouse{ (GET_X_LPARAM(l_param) - wr.left) ,(GET_Y_LPARAM(l_param) - wr.top) }; 560 | //WndProc(hwnd, msg + 0x160, wp, mouse.x | (mouse.y << 16)); 561 | //if (msg == WM_NCLBUTTONDOWN) frame.flags.nclbd = true; 562 | break; 563 | } 564 | case WM_SYSCOMMAND: 565 | { 566 | if ((w_param & SC_MAXIMIZE) || (w_param & SC_RESTORE)) 567 | { 568 | PostMessageW(handle, WM_EXITSIZEMOVE, 0, 0); 569 | if ((w_param & SC_MAXIMIZE) == SC_MAXIMIZE) 570 | { 571 | //frame.flags.maximized = true; 572 | //frame.View::Position(); 573 | } 574 | if ((w_param & SC_RESTORE) == SC_RESTORE) 575 | { 576 | //frame.flags.maximized = false; 577 | //frame.View::Position(); 578 | } 579 | } 580 | break; 581 | } 582 | case WM_MOUSEWHEEL: 583 | { 584 | auto dta = GET_WHEEL_DELTA_WPARAM(w_param); 585 | float ds = (1 + (float)dta / 120 * 0.1f); 586 | Vector2 mouse{ GET_X_LPARAM(l_param) / dpiScaleFactor.x,GET_Y_LPARAM(l_param) / dpiScaleFactor.y }; 587 | cam_s *= ds; 588 | vtf = Matrix4x4::TRS({ cam_t.x,cam_t.y,0 }, Quaternion::identity(), { cam_s,cam_s,cam_s }); 589 | 590 | //rbf_root.Sync(cbf_root); 591 | 592 | PostMessage(handle, WM_PAINT, 0, 0); 593 | } 594 | case WM_CHAR: 595 | case WM_KEYDOWN: 596 | case WM_KEYUP: 597 | case WM_IME_COMPOSITION: 598 | case WM_IME_STARTCOMPOSITION: 599 | case WM_IME_ENDCOMPOSITION: 600 | { 601 | break; 602 | } 603 | case WM_DESTROY: 604 | { 605 | break; 606 | } 607 | case WM_KILLFOCUS: 608 | { 609 | 610 | break; 611 | } 612 | case WM_MOUSELEAVE: 613 | { 614 | break; 615 | } 616 | case WM_SETCURSOR: 617 | { 618 | SetCursor(LoadCursor(NULL, IDC_ARROW)); 619 | break; 620 | } 621 | case WM_MOVE: 622 | case WM_EXITSIZEMOVE: 623 | int x = GET_X_LPARAM(l_param); 624 | int y = GET_Y_LPARAM(l_param); 625 | AquireWindowRect(); 626 | 627 | break; 628 | 629 | } 630 | return NextProc(handle, message, w_param, l_param); 631 | } 632 | void Frame::Show() 633 | { 634 | set_borderless_shadow(hWnd, true); 635 | ShowWindow(hWnd, SW_SHOW); 636 | } 637 | void Frame::Run() 638 | { 639 | MSG msg; 640 | HWND phWnd = 0; 641 | //if (modeled && parent) 642 | //{ 643 | // phWnd = ((Frame*)parent)->GetNative(); 644 | // EnableWindow(phWnd, false); 645 | //} 646 | while (::GetMessageW(&msg, 0, 0, 0) == TRUE) 647 | { 648 | //MainThreadDispatch(); 649 | ::TranslateMessage(&msg); 650 | ::DispatchMessageW(&msg); 651 | } 652 | //if (modeled && phWnd) 653 | // EnableWindow(phWnd, true), SetForegroundWindow(phWnd); 654 | } 655 | void Frame::SetViewRect(RECT& rc) 656 | { 657 | viewRect.left = rc.left; 658 | viewRect.top = rc.top; 659 | viewRect.right = rc.right; 660 | viewRect.bottom = rc.bottom; 661 | } 662 | 663 | Math3D::Vector4 Frame::AquireWindowRect() 664 | { 665 | RECT wr; 666 | GetWindowRect(hWnd, &wr); 667 | SetViewRect(wr); 668 | return { (float)wr.left,(float)wr.top,(float)wr.right,(float)wr.bottom }; 669 | } 670 | 671 | -------------------------------------------------------------------------------- /RLL/win32core_mesh.cpp: -------------------------------------------------------------------------------- 1 | #include "win32core_mesh.h" 2 | #include "win32impl.h" 3 | #include "win32paint_d12.h" 4 | #include 5 | #include 6 | using namespace RLL; 7 | using namespace Math3D; 8 | 9 | 10 | void CoreMesh::Upload(D3D12PaintDevice* device) 11 | { 12 | indexBuffer.data = &indices; 13 | indexBuffer.size = idxCount * sizeof(short); 14 | //indexBuffer.gpuBuffer = device->CreateDefaultBuffer(indices, idxCount * sizeof(short)); 15 | 16 | uvBuffer.data = &uvs; 17 | uvBuffer.size = vertCount * sizeof(Vector2); 18 | //uvBuffer.gpuBuffer = device->CreateDefaultBuffer(uvs, vertCount * sizeof(Vector2)); 19 | pnbBuffer.data = &pnbs; 20 | pnbBuffer.size = vertCount * sizeof(Vector3); 21 | if (pnbs) 22 | { 23 | pnbBuffer1.data = &pnbs1; 24 | pnbBuffer1.size = vertCount * sizeof(Vector3); 25 | } 26 | 27 | //pnbBuffer.gpuBuffer = device->CreateDefaultBuffer(pnbs, vertCount * sizeof(Vector3)); 28 | vertBuffer.data = &vertices; 29 | vertBuffer.size = vertCount * sizeof(Vector2); 30 | //vertBuffer.gpuBuffer = device->CreateDefaultBuffer(vertices, vertCount * sizeof(Vector3)); 31 | tfBuffer.data = &tfs; 32 | tfBuffer.size = vertCount * sizeof(Vector4); 33 | 34 | ibv.Format = DXGI_FORMAT_R16_UINT; 35 | ibv.SizeInBytes = indexBuffer.size; 36 | //ibv.BufferLocation = indexBuffer.gpuBuffer->GetGPUVirtualAddress(); 37 | //0: vert 1:uv 2:pnb 38 | vbv[0].SizeInBytes = vertBuffer.size; 39 | //vbv[0].BufferLocation = vertBuffer.gpuBuffer->GetGPUVirtualAddress(); 40 | //vbv[0].StrideInBytes = 12; 41 | 42 | vbv[1].SizeInBytes = uvBuffer.size; 43 | //vbv[1].BufferLocation = uvBuffer.gpuBuffer->GetGPUVirtualAddress(); 44 | //vbv[1].StrideInBytes = 8; 45 | 46 | vbv[2].SizeInBytes = tfBuffer.size; 47 | //vbv[2].BufferLocation = pnbBuffer.gpuBuffer->GetGPUVirtualAddress(); 48 | //vbv[2].StrideInBytes = 12; 49 | vbv[3].SizeInBytes = pnbBuffer.size; 50 | vbv[4].SizeInBytes = pnbBuffer1.size; 51 | device->UploadMesh(this); 52 | } 53 | void CoreMesh::Uploaded(ID3D12Resource** gRes, int ioffset, int voffset) 54 | { 55 | for (int i = 0; i < 6; i++) 56 | { 57 | if (gRes[i]) 58 | gRes[i]->AddRef(); 59 | } 60 | indexBuffer.gpuBuffer = gRes[0]; 61 | vertBuffer.gpuBuffer = gRes[1]; 62 | uvBuffer.gpuBuffer = gRes[2]; 63 | tfBuffer.gpuBuffer = gRes[3]; 64 | pnbBuffer.gpuBuffer = gRes[4]; 65 | pnbBuffer1.gpuBuffer = gRes[5]; 66 | 67 | ibv.Format = DXGI_FORMAT_R16_UINT; 68 | ibv.SizeInBytes = indexBuffer.size; 69 | ibv.BufferLocation = gRes[0]->GetGPUVirtualAddress() + ioffset * sizeof(*indices); 70 | //0: vert 1:uv 2:pnb 71 | vbv[0].SizeInBytes = vertBuffer.size; 72 | vbv[0].BufferLocation = gRes[1]->GetGPUVirtualAddress() + voffset * sizeof(*vertices);; 73 | vbv[0].StrideInBytes = 8; 74 | 75 | vbv[1].SizeInBytes = uvBuffer.size; 76 | vbv[1].BufferLocation = gRes[2]->GetGPUVirtualAddress() + voffset * sizeof(*uvs);; 77 | vbv[1].StrideInBytes = 8; 78 | 79 | vbv[2].SizeInBytes = tfBuffer.size; 80 | vbv[2].BufferLocation = gRes[3]->GetGPUVirtualAddress() + voffset * sizeof(*tfs);; 81 | vbv[2].StrideInBytes = 16; 82 | 83 | vbv[3].SizeInBytes = pnbBuffer.size; 84 | vbv[3].BufferLocation = gRes[4]->GetGPUVirtualAddress() + voffset * sizeof(*pnbs);; 85 | vbv[3].StrideInBytes = 12; 86 | 87 | if (pnbs1) 88 | { 89 | vbv[4].SizeInBytes = tfBuffer.size; 90 | vbv[4].BufferLocation = gRes[5]->GetGPUVirtualAddress() + voffset * sizeof(*pnbs1);; 91 | vbv[4].StrideInBytes = 12; 92 | } 93 | 94 | } 95 | 96 | CoreMesh::~CoreMesh() 97 | { 98 | ibv = {}; 99 | vbv[0] = {}; 100 | vbv[1] = {}; 101 | vbv[2] = {}; 102 | vbv[3] = {}; 103 | delete[] uvs; 104 | delete[] vertices; 105 | delete[] pnbs; 106 | delete[] indices; 107 | if (pnbs1) 108 | delete[] pnbs1; 109 | //delete[] tfs; 110 | uvs = nullptr; 111 | vertices = nullptr; 112 | pnbs = nullptr; 113 | indices = nullptr; 114 | tfs = nullptr; 115 | indexBuffer.gpuBuffer->Release(); 116 | vertBuffer.gpuBuffer->Release(); 117 | uvBuffer.gpuBuffer->Release(); 118 | tfBuffer.gpuBuffer->Release(); 119 | pnbBuffer.gpuBuffer->Release(); 120 | if (pnbBuffer1.gpuBuffer) pnbBuffer1.gpuBuffer->Release(); 121 | 122 | } 123 | -------------------------------------------------------------------------------- /RLL/win32core_mesh.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "win32internal.h" 3 | 4 | 5 | //struct FilledGeometrySet : public RLL::ISVGBuilder, public RLL::ISVG // svg, submesh 6 | //{ 7 | // PathBuffer* buffer; 8 | // int geomCount = 0; 9 | // std::vector indices; 10 | // std::vector verts; 11 | // std::vector uv; 12 | // std::vector path_norm_fill; 13 | // 14 | // FilledGeometrySet(PathBuffer* path) :buffer(path) {}; 15 | // void PushGeometry(RLL::IGeometry* geom, RLL::IBrush* filler) 16 | // { 17 | // auto ptrg = dynamic_cast(geom); 18 | // auto& g = *ptrg; 19 | // float fil = 0; 20 | // if (filler) 21 | // { 22 | // fil = ((Filling*)filler)->index; 23 | // } 24 | // int ibegin = verts.size() - 1; 25 | // verts.insert(verts.end(), g.verts.begin(), g.verts.end()); 26 | // uv.insert(uv.end(), g.verts.begin(), g.verts.end()); 27 | // for (auto i : g.path_norm) 28 | // { 29 | // path_norm_fill.push_back({ i.x,i.y,fil }); 30 | // } 31 | // for (int i = 0; i < g.indices.size(); i++) 32 | // { 33 | // indices.push_back(ibegin + g.indices[i]); 34 | // } 35 | // geomCount++; 36 | // }; 37 | // void PushGeometry(RLL::IGeometry* geom, Math3D::Matrix4x4& transform, RLL::IFilling* filler)// 2D transform, dont modify z-axis 38 | // { 39 | // auto ptrg = dynamic_cast(geom); 40 | // auto& g = *ptrg; 41 | // float fil = 0; 42 | // if (filler) 43 | // { 44 | // fil = ((Filling*)filler)->index; 45 | // } 46 | // int ibegin = verts.size() - 1; 47 | // uv.insert(uv.end(), g.verts.begin(), g.verts.end()); 48 | // for (auto i : g.verts) 49 | // { 50 | // Math3D::Vector4 pt{ i.x,i.y,0,1 }; 51 | // pt = pt * transform; 52 | // verts.push_back({ pt.x,pt.y }); 53 | // } 54 | // for (auto i : g.path_norm) 55 | // { 56 | // path_norm_fill.push_back({ i.x,i.y,fil }); 57 | // } 58 | // for (int i = 0; i < g.indices.size(); i++) 59 | // { 60 | // indices.push_back(ibegin + g.indices[i]); 61 | // } 62 | // geomCount++; 63 | // }; 64 | //}; 65 | //final image is made with sets of vs/this 66 | //for sets of fgs/svg to layout and paint 67 | struct ViewCanvas 68 | { 69 | 70 | 71 | }; 72 | struct CBFrame 73 | { 74 | Math3D::Matrix4x4 gWorldViewProj; 75 | Math3D::float4 dColor; 76 | float time; 77 | struct { 78 | unsigned int width; 79 | unsigned int height; 80 | }vwh; 81 | float reservedCBF; 82 | 83 | }; 84 | struct CBObject 85 | { 86 | Math3D::Matrix4x4 objToWorld; 87 | int sampleType; 88 | float lerpTime; 89 | }; 90 | class D3D12PaintDevice; 91 | struct CoreMesh 92 | { 93 | struct SubMesh; 94 | enum VERTEX_FORMAT 95 | { 96 | VERTEX_FORMAT_POSITION, 97 | VERTEX_FORMAT_NORMAL, 98 | VERTEX_FORMAT_TANGENT, 99 | VERTEX_FORMAT_BONE_WEIGHT, 100 | VERTEX_FORMAT_COLOR, 101 | VERTEX_FORMAT_BONE_INDEX, 102 | VERTEX_FORMAT_UV, 103 | VERTEX_FORMAT_UV1, 104 | VERTEX_FORMAT_UV2, 105 | VERTEX_FORMAT_UV3, 106 | }; 107 | Math3D::Vector2* vertices = nullptr; 108 | Math3D::Vector2* uvs = nullptr; 109 | Math3D::Vector4* tfs = nullptr; 110 | Math3D::Vector3* pnbs = nullptr; 111 | Math3D::Vector3* pnbs1 = nullptr; 112 | unsigned short* indices = nullptr; 113 | 114 | unsigned int vertCount; 115 | unsigned int idxCount; 116 | UINT32 subMeshCount; 117 | SubMesh* subMeshs; 118 | 119 | ResourceBlob vertBuffer; 120 | ResourceBlob uvBuffer; 121 | ResourceBlob pnbBuffer; 122 | ResourceBlob pnbBuffer1; 123 | ResourceBlob tfBuffer; 124 | ResourceBlob indexBuffer; 125 | 126 | D3D12_INDEX_BUFFER_VIEW ibv; 127 | D3D12_VERTEX_BUFFER_VIEW vbv[5]; 128 | 129 | public: 130 | CoreMesh() 131 | { 132 | idxCount = vertCount = subMeshCount = 0; 133 | vertices = nullptr; 134 | indices = nullptr; 135 | uvs = nullptr; 136 | pnbs = nullptr; 137 | tfs = nullptr; 138 | subMeshs = nullptr; 139 | vertBuffer.data = reinterpret_cast(&vertices); 140 | indexBuffer.data = reinterpret_cast(&indices); 141 | uvBuffer.data = reinterpret_cast(&uvs); 142 | tfBuffer.data = reinterpret_cast(&tfs); 143 | pnbBuffer.data = reinterpret_cast(&pnbs); 144 | pnbBuffer1.data = reinterpret_cast(&pnbs1); 145 | } 146 | struct SubMesh 147 | { 148 | CoreMesh* mesh; 149 | uint16_t startIndex; 150 | uint16_t indexCount; 151 | uint16_t startVertex; 152 | 153 | SubMesh() = default; 154 | SubMesh(CoreMesh* m, uint16_t si, uint16_t ic, uint16_t sv) 155 | { 156 | mesh = m; 157 | startIndex = si; 158 | indexCount = ic; 159 | startVertex = sv; 160 | } 161 | }; 162 | 163 | void Upload(D3D12PaintDevice* device); 164 | void Uploaded(ID3D12Resource** gRes, int ioffset, int voffset); 165 | ~CoreMesh(); 166 | }; 167 | 168 | 169 | -------------------------------------------------------------------------------- /RLL/win32impl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "windows.h" 3 | #include "Interfaces.h" 4 | #include "PathGeometry.h" 5 | #define INIT_DIRECTX_DEBUG_LAYER (0x1) 6 | #define INIT_DEVELOP (0x2) 7 | 8 | void _DBG_D3DLIVE_OBJ(); -------------------------------------------------------------------------------- /RLL/win32internal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "win32impl.h" 3 | #include "Interfaces.h" 4 | 5 | #include "windows.h" 6 | #include "shellscalingapi.h" 7 | #include "dwmapi.h" 8 | #include "windowsx.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "d3dx12.h" 15 | 16 | 17 | using namespace Microsoft::WRL; 18 | 19 | #pragma comment(lib, "dwmapi.lib") 20 | #pragma comment(lib, "Shcore.lib") 21 | #pragma comment(lib, "dcomp.lib") 22 | #pragma comment(lib, "d3d12.lib") 23 | #pragma comment(lib, "dxguid.lib") 24 | #pragma comment(lib, "dxgi.lib") 25 | #pragma comment(lib, "d3dcompiler.lib") 26 | inline void SUCCESS(HRESULT hr) 27 | { 28 | if (hr != S_OK) 29 | throw(hr); 30 | } 31 | class D3D12FramePaintContext; 32 | struct Frame : public RLL::IFrame 33 | { 34 | DWORD extStyles = 0; 35 | HWND hWnd; 36 | D3D12FramePaintContext* paintCtx; 37 | RLL::RectangleI viewRect; 38 | 39 | Math3D::Vector4 AquireWindowRect(); 40 | void SetViewRect(RECT&); 41 | 42 | Frame(Frame* parent, Math3D::Vector2 size, Math3D::Vector2 pos); 43 | LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); 44 | LRESULT NextProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); 45 | void Show(); 46 | void Run(); 47 | }; 48 | 49 | struct ResourceBlob 50 | { 51 | int size = 0; 52 | void* data = nullptr; 53 | ID3D12Resource* gpuBuffer; 54 | void Sync(void* data) 55 | { 56 | memcpy(this->data, data, size); 57 | } 58 | template 59 | void Sync(T& st) 60 | { 61 | Sync(&st); 62 | } 63 | }; 64 | -------------------------------------------------------------------------------- /RLL/win32paint_d12.cpp: -------------------------------------------------------------------------------- 1 | #include "win32paint_d12.h" 2 | #include 3 | #include "curve_tools.h" 4 | 5 | #define NO_TIMECHECKER 6 | #include "perf_util.h" 7 | using namespace RLL; 8 | using namespace std; 9 | using namespace Math3D; 10 | 11 | 12 | void D3D12Brush::Dispose() 13 | { 14 | if (brush) 15 | brush->pad = 1; 16 | //device->flag |= FLAG_D12PD_BRUSH_DIRTY; 17 | delete this; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /RLL/win32paint_d12.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "Painter.h" 3 | #include "vector" 4 | #include "win32core_mesh.h" 5 | #include "DescriptorHeap.h" 6 | 7 | #define ELLIPSE_QUALITY 8 8 | 9 | #ifdef _DEBUG 10 | #include 11 | #endif 12 | 13 | struct D3D12GPUPath { 14 | int hi = 0; 15 | int vi = 0; 16 | int hl = 0; 17 | int vl = 0; 18 | }; 19 | struct D3D12GPUCurve { 20 | Math3D::Vector2 begin; 21 | Math3D::Vector2 control; 22 | Math3D::Vector2 end; 23 | bool IsLine() 24 | { 25 | return Math3D::Vector2::Cross(control - begin, end - control) == 0.f; 26 | } 27 | bool IsVertical() 28 | { 29 | if (!IsLine()) 30 | return false; 31 | return (end - begin).x == 0; 32 | } 33 | bool IsHorizontal() 34 | { 35 | if (!IsLine()) 36 | return false; 37 | return (end - begin).y == 0; 38 | 39 | } 40 | Math3D::Vector2 Max() 41 | { 42 | Math3D::Vector2 mx = begin; 43 | mx.x = max(mx.x, control.x); 44 | mx.x = max(mx.x, end.x); 45 | 46 | mx.y = max(mx.y, control.y); 47 | mx.y = max(mx.y, end.y); 48 | return mx; 49 | 50 | } 51 | }; 52 | struct D3D12GPUBrush 53 | { 54 | public: 55 | Math3D::Vector2 center = { 0 }; //in directional is direction 56 | Math3D::Vector2 focus = { 0 }; 57 | float radius = 0; 58 | unsigned int type = 0;// color mode: 0:foreground 1:directional 2:radial 3:sweep 4:tex 59 | unsigned int texid = 0; 60 | float pad = 0; 61 | float pos[8] = { 0 }; 62 | RLL::Color stops[8] = {}; 63 | static D3D12GPUBrush Foreground() 64 | { 65 | D3D12GPUBrush grads; 66 | grads.type = 0; 67 | return grads; 68 | }; 69 | static D3D12GPUBrush Directional( 70 | Math3D::Vector2 direction, 71 | float pos0, RLL::Color col0, 72 | float pos1 = 2, RLL::Color col1 = { 0,0,0,0 }, 73 | float pos2 = 2, RLL::Color col2 = { 0,0,0,0 }, 74 | float pos3 = 2, RLL::Color col3 = { 0,0,0,0 }, 75 | float pos4 = 2, RLL::Color col4 = { 0,0,0,0 }, 76 | float pos5 = 2, RLL::Color col5 = { 0,0,0,0 }, 77 | float pos6 = 2, RLL::Color col6 = { 0,0,0,0 }, 78 | float pos7 = 2, RLL::Color col7 = { 0,0,0,0 } 79 | ) 80 | { 81 | D3D12GPUBrush grads; 82 | grads.center = direction; 83 | grads.type = 1; 84 | grads.pos[0] = pos0; 85 | grads.pos[1] = pos1; 86 | grads.pos[2] = pos2; 87 | grads.pos[3] = pos3; 88 | grads.pos[4] = pos4; 89 | grads.pos[5] = pos5; 90 | grads.pos[6] = pos6; 91 | grads.pos[7] = pos7; 92 | 93 | grads.stops[0] = col0; 94 | grads.stops[1] = col1; 95 | grads.stops[2] = col2; 96 | grads.stops[3] = col3; 97 | grads.stops[4] = col4; 98 | grads.stops[5] = col5; 99 | grads.stops[6] = col6; 100 | grads.stops[7] = col7; 101 | return grads; 102 | } 103 | static D3D12GPUBrush Solid( 104 | RLL::Color col) 105 | { 106 | return Directional({ 1,0 }, 0, col, 1, col); 107 | } 108 | static D3D12GPUBrush Radial( 109 | Math3D::Vector2 center, 110 | float radius, 111 | float pos0, RLL::Color col0, 112 | float pos1 = 2, RLL::Color col1 = { 0,0,0,0 }, 113 | float pos2 = 2, RLL::Color col2 = { 0,0,0,0 }, 114 | float pos3 = 2, RLL::Color col3 = { 0,0,0,0 }, 115 | float pos4 = 2, RLL::Color col4 = { 0,0,0,0 }, 116 | float pos5 = 2, RLL::Color col5 = { 0,0,0,0 }, 117 | float pos6 = 2, RLL::Color col6 = { 0,0,0,0 }, 118 | float pos7 = 2, RLL::Color col7 = { 0,0,0,0 } 119 | ) 120 | { 121 | D3D12GPUBrush grads; 122 | grads.center = center; 123 | grads.radius = radius; 124 | grads.focus = center; 125 | grads.type = 2; 126 | grads.pos[0] = pos0; 127 | grads.pos[1] = pos1; 128 | grads.pos[2] = pos2; 129 | grads.pos[3] = pos3; 130 | grads.pos[4] = pos4; 131 | grads.pos[5] = pos5; 132 | grads.pos[6] = pos6; 133 | grads.pos[7] = pos7; 134 | 135 | grads.stops[0] = col0; 136 | grads.stops[1] = col1; 137 | grads.stops[2] = col2; 138 | grads.stops[3] = col3; 139 | grads.stops[4] = col4; 140 | grads.stops[5] = col5; 141 | grads.stops[6] = col6; 142 | grads.stops[7] = col7; 143 | return grads; 144 | } 145 | static D3D12GPUBrush Sweep( 146 | Math3D::Vector2 center, 147 | float degree, 148 | float pos0, RLL::Color col0, 149 | float pos1 = 2, RLL::Color col1 = { 0,0,0,0 }, 150 | float pos2 = 2, RLL::Color col2 = { 0,0,0,0 }, 151 | float pos3 = 2, RLL::Color col3 = { 0,0,0,0 }, 152 | float pos4 = 2, RLL::Color col4 = { 0,0,0,0 }, 153 | float pos5 = 2, RLL::Color col5 = { 0,0,0,0 }, 154 | float pos6 = 2, RLL::Color col6 = { 0,0,0,0 }, 155 | float pos7 = 2, RLL::Color col7 = { 0,0,0,0 } 156 | ) 157 | { 158 | D3D12GPUBrush grads; 159 | grads.center = center; 160 | grads.radius = degree; 161 | grads.type = 3; 162 | grads.pos[0] = pos0; 163 | grads.pos[1] = pos1; 164 | grads.pos[2] = pos2; 165 | grads.pos[3] = pos3; 166 | grads.pos[4] = pos4; 167 | grads.pos[5] = pos5; 168 | grads.pos[6] = pos6; 169 | grads.pos[7] = pos7; 170 | 171 | grads.stops[0] = col0; 172 | grads.stops[1] = col1; 173 | grads.stops[2] = col2; 174 | grads.stops[3] = col3; 175 | grads.stops[4] = col4; 176 | grads.stops[5] = col5; 177 | grads.stops[6] = col6; 178 | grads.stops[7] = col7; 179 | return grads; 180 | } 181 | static D3D12GPUBrush Texture(unsigned int texture) 182 | { 183 | D3D12GPUBrush grads; 184 | grads.texid = texture; 185 | return grads; 186 | } 187 | }; 188 | struct D3D12GeometryMesh 189 | { 190 | std::vector indices; 191 | std::vector verts; 192 | std::vector uv; 193 | std::vector path_norm; 194 | Math3D::Matrix4x4 uvTransform = Math3D::Matrix4x4::Identity(); 195 | void MakeIndex(int off = 0) 196 | { 197 | std::vector idcs; 198 | auto vs = verts.size() - off; 199 | 200 | if (vs == 3) 201 | { 202 | idcs = { 0,1,2 }; 203 | } 204 | else if (vs == 4) 205 | { 206 | idcs = { 0,1,2,0,2,3 }; 207 | } 208 | else if (vs == 5) 209 | { 210 | idcs = { 0,1,2,2,3,0,0,3,4 }; 211 | } 212 | else if (vs == 6) 213 | { 214 | idcs = { 0,1,2,2,3,4,4,5,0,0,2,4 }; 215 | } 216 | else 217 | { 218 | idcs.resize((vs - 2) * 3); 219 | for (int x = 0; x < idcs.size() / 3; x++) 220 | { 221 | idcs[x * 3 + 0] = 0; 222 | idcs[x * 3 + 1] = x + 1; 223 | idcs[x * 3 + 2] = x + 2; 224 | } 225 | } 226 | for (auto& i : idcs) 227 | { 228 | i += off; 229 | } 230 | indices.insert(indices.end(), idcs.begin(), idcs.end()); 231 | } 232 | void SetPath(int index) 233 | { 234 | for (auto& i : path_norm) 235 | i.x = index; 236 | } 237 | void MakeNormal() 238 | { 239 | if (path_norm.size() != verts.size()) 240 | path_norm.resize(verts.size()); 241 | 242 | for (int v = 0; v < verts.size(); v++) 243 | { 244 | Math3D::Vector2 v_a, v_b; 245 | if (v == 0) 246 | { 247 | v_a = verts[0] - verts[verts.size() - 1]; 248 | } 249 | else 250 | { 251 | v_a = verts[v] - verts[v - 1]; 252 | } 253 | if (v == verts.size() - 1) 254 | { 255 | v_b = verts[v] - verts[0]; 256 | } 257 | else 258 | { 259 | v_b = verts[v] - verts[v + 1]; 260 | } 261 | auto norm = (v_a.Normalized() + v_b.Normalized()); 262 | path_norm[v].y = atan2f(norm.y, norm.x); 263 | } 264 | } 265 | void MakeUV(Math3D::Matrix4x4& t) 266 | { 267 | uvTransform = t; 268 | uv.reserve(verts.size()); 269 | for (auto& i : verts) 270 | { 271 | //auto u = i * t; 272 | uv.push_back(i * t); 273 | } 274 | } 275 | float GetArea() { return 0; }; 276 | float GetCircumference() { return 0; }; 277 | }; 278 | 279 | struct PathBuffer 280 | { 281 | std::vector paths; 282 | std::vector curves; 283 | std::vector brushes; 284 | std::vector meshes; 285 | }; 286 | #define FLAG_D12PD_PATH_DIRTY 0x1 287 | #define FLAG_D12PD_CURVE_DIRTY 0x2 288 | #define FLAG_D12PD_BRUSH_DIRTY 0x4 289 | #define FLAG_D12PD_MESH_DIRTY 0x8 290 | #define FLAG_D12PC_FRAME_CONTEXT 0x1 291 | #define FLAG_D12PC_NONE 0x0; 292 | 293 | struct MeshGroup 294 | { 295 | std::vector meshs; 296 | ID3D12Resource* resource[6] = {0}; 297 | ResourceBlob uploads[6] = {0}; 298 | }; 299 | class D3D12PaintContext; 300 | class D3D12FramePaintContext; 301 | 302 | class D3D12PaintDevice : public RLL::IPaintDevice 303 | { 304 | friend class D3D12GeometryBuilder; 305 | friend class D3D12SVGBuilder; 306 | friend class CoreMesh; 307 | friend class D3D12Geometry; 308 | friend class D3D12SVG; 309 | friend class D3D12PaintContext; 310 | friend class D3D12FramePaintContext; 311 | 312 | int flag = 0b111; 313 | ComPtr < ID3D12Device5> d3dDevice = nullptr; 314 | 315 | UINT cFence = 0; 316 | ComPtr gFence; 317 | ComPtr cmdQueue; 318 | ComPtr cmdAllocator; 319 | ComPtr cmdList; 320 | //ComPtr cmdAllocatorCopy; 321 | //ComPtr cmdListCopy; 322 | ComPtr dxgiDevice; 323 | ComPtr dxgiFactory; 324 | 325 | ComPtr coreSignature; 326 | ComPtr corePSO; 327 | ComPtr coreMorphSignature; 328 | ComPtr coreMorphPSO; 329 | ComPtr dbgWirePSO; 330 | std::vector contexs; 331 | 332 | PathBuffer paths; 333 | std::vector meshGroups; 334 | MeshGroup cMeshGroup; 335 | ComPtr gpuPath; 336 | ComPtr gpuCurve; 337 | ComPtr gpuBrush; 338 | DescriptorHeap gpuTextureHeap; 339 | bool msaaEnable = false; 340 | UINT msaaQuality; 341 | 342 | void CreateDevices(int flags); 343 | void CommitChange(); 344 | //void Flush(); 345 | void PostFlush(); 346 | void UploadMesh(CoreMesh* m); 347 | ID3D12Resource* MakeDefaultBuffer(ID3D12Resource* upload, int size); 348 | int AllocateBrush(); 349 | int AllocatePath(D3D12GPUPath&); 350 | int AllocateMesh(); 351 | void LoadShaders(); 352 | void Wait(); 353 | 354 | 355 | public: 356 | D3D12PaintDevice(); 357 | 358 | void Dispose() { NOIMPL; }; 359 | RLL::IBrush* CreateSolidColorBrush(RLL::Color c); 360 | RLL::IBrush* CreateDirectionalBrush(Math3D::Vector2 direction, RLL::ColorGradient* grad); 361 | RLL::IBrush* CreateRadialBrush(Math3D::Vector2 center, float radius, RLL::ColorGradient* grad); 362 | RLL::IBrush* CreateSweepBrush(Math3D::Vector2 center, float degree, RLL::ColorGradient* grad); 363 | RLL::IBrush* CreateTexturedBrush(RLL::ITexture* tex, void* sampleMode) { NOIMPL; return nullptr; }; 364 | RLL::ITexture* CreateTexture() { NOIMPL; return nullptr; }; 365 | RLL::ITexture* CreateTexture(RLL::IBitmap* bmp) { NOIMPL; return nullptr; }; 366 | RLL::IRenderTarget* CreateRenderTarget() { NOIMPL; return nullptr; }; 367 | 368 | RLL::IGeometryBuilder* CreateGeometryBuilder(); 369 | RLL::ISVGBuilder* CreateSVGBuilder(); 370 | 371 | RLL::IPaintContext* CreateContext(int flags = 0); 372 | RLL::IPaintContext* CreateContextForFrame(RLL::IFrame* f, int flags = 0); 373 | 374 | void CopyTexture(RLL::ITexture* src, RLL::ITexture* dst) { NOIMPL; return; }; 375 | void CopyTextureRegion(RLL::ITexture* src, RLL::ITexture* dst, RLL::RectangleI) { NOIMPL; return; }; 376 | 377 | 378 | ID3D12Resource* CreateDefaultBuffer(const void* initData, UINT64 size, D3D12_RESOURCE_FLAGS flag = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET); 379 | ResourceBlob CreateUploadBuffer(UINT64 size); 380 | }; 381 | class D3D12PaintContext :public RLL::IPaintContext 382 | { 383 | friend class D3D12PaintDevice; 384 | friend class D3D12FramePaintContext; 385 | D3D12PaintDevice* device = nullptr; 386 | std::vector transformCache; 387 | int cTransform; 388 | std::vector clips; 389 | ComPtr cmdAllocator; 390 | ComPtr cmdList; 391 | ComPtr rt; 392 | CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle; 393 | bool flushAvaliable = false; 394 | D3D12_RESOURCE_STATES state; 395 | CD3DX12_VIEWPORT viewport; 396 | CD3DX12_RECT scissorRect; 397 | ResourceBlob gpuCbFrame; 398 | ResourceBlob gpuCbObject; 399 | CBFrame cbFrame; 400 | CBObject cbObjTest; 401 | 402 | D3D12PaintContext(D3D12PaintDevice* pdev); 403 | void Dispose() { NOIMPL; }; 404 | public: 405 | RLL::IPaintDevice* GetDevice() { return device; }; 406 | void SetRenderTarget(RLL::IRenderTarget* rt); 407 | //virtual ITexture* GetRenderTarget() = 0; 408 | void BeginDraw(); 409 | void Clear(RLL::Color clear = {}); 410 | void PushClip(RLL::Rectangle clip); 411 | void PopClip(); 412 | void EndDraw(); 413 | void SetTransform(Math3D::Matrix4x4& tfCache); 414 | void DrawSVG(RLL::ISVG* svg); 415 | void DrawAVG(RLL::IAVG* avg); 416 | void DrawMorph() { NOIMPL; }; 417 | void Flush(); 418 | 419 | }; 420 | class D3D12FramePaintContext :public D3D12PaintContext 421 | { 422 | friend class D3D12PaintDevice; 423 | 424 | ComPtr swapChain; 425 | ComPtr dcompTarget; 426 | ComPtr dcompVisual; 427 | DescriptorHeap rtvHeap; 428 | ComPtr scBuffer[2]; 429 | ComPtr maBuffer[2]; 430 | ComPtr dCompDevice; 431 | 432 | CD3DX12_VIEWPORT viewport; 433 | CD3DX12_RECT scissorRect; 434 | UINT rtvDescriptorSize; 435 | UINT currentBuffer; 436 | Frame* frame; 437 | 438 | 439 | D3D12FramePaintContext(D3D12PaintDevice* pdev, Frame* f); 440 | void CreateRenderTargets(); 441 | 442 | public: 443 | void ResizeView(); 444 | void SetRenderTarget(RLL::IRenderTarget* rt) { SetError("Frame Context dose not need to set RenderTargets."); }; 445 | void BeginDraw(); 446 | void Clear(RLL::Color clear = {}); 447 | void EndDraw(); 448 | void Flush(); 449 | 450 | }; 451 | 452 | class D3D12Brush : public RLL::IBrush 453 | { 454 | friend class D3D12PaintDevice; 455 | friend class D3D12SVGBuilder; 456 | D3D12PaintDevice* device; 457 | int id; 458 | D3D12GPUBrush* brush; 459 | D3D12Brush(D3D12PaintDevice* dev) :device(dev) { id = 0; brush = nullptr; }; 460 | public: 461 | void Dispose(); 462 | }; 463 | class D3D12Geometry : public RLL::IGeometry 464 | { 465 | friend class D3D12GeometryBuilder; 466 | friend class D3D12SVGBuilder; 467 | public: 468 | D3D12PaintDevice* device; 469 | int pathID = -1; 470 | D3D12GPUPath* path = nullptr; 471 | D3D12GeometryMesh* mesh = nullptr; 472 | 473 | D3D12Geometry(D3D12PaintDevice* dev) :device(dev) { }; 474 | public: 475 | void Dispose(); 476 | 477 | }; 478 | class D3D12GeometryBuilder : public RLL::IGeometryBuilder 479 | { 480 | D3D12PaintDevice* device; 481 | struct SubPath 482 | { 483 | std::vector curves; 484 | bool closed = false; 485 | }; 486 | Math3D::float2 o; 487 | std::vector paths; 488 | std::vector points; 489 | SubPath cPath; 490 | bool opening = false; 491 | 492 | friend class D3D12PaintDevice; 493 | D3D12GeometryBuilder(D3D12PaintDevice* dev) :device(dev) { cPath.curves.reserve(256); points.reserve(256); }; 494 | public: 495 | void Begin(Math3D::Vector2 p); 496 | void End(bool close); 497 | void LineTo(Math3D::Vector2 to); 498 | void QuadraticTo(Math3D::Vector2 control, Math3D::Vector2 to); 499 | void CubicTo(Math3D::Vector2 control0, Math3D::Vector2 control1, Math3D::Vector2 to); 500 | void ArcTo(Math3D::Vector2 center, Math3D::Vector2 radius, float begin_rad, float end_rad, RLL::ARC_TYPE t); 501 | void Ellipse(Math3D::Vector2 center, Math3D::Vector2 radius, bool inv); 502 | void Rectangle(Math3D::Vector2 lt, Math3D::Vector2 rb, bool inv); 503 | void Triangle(Math3D::Vector2 p0, Math3D::Vector2 p1, Math3D::Vector2 p2, bool inv); 504 | void RoundRectangle(Math3D::Vector2 lt, Math3D::Vector2 rb, Math3D::Vector2 radius, bool inv); 505 | 506 | RLL::IGeometry* Fill(Math3D::Matrix4x4* bgTransform); 507 | RLL::IGeometry* Stroke(float stroke, RLL::StrokeStyle* type, Math3D::Matrix4x4* bgTransform); 508 | void Reset(); 509 | void Dispose(); 510 | 511 | }; 512 | 513 | class D3D12SVG :public RLL::ISVG 514 | { 515 | friend class D3D12SVGBuilder; 516 | public: 517 | D3D12PaintDevice* device; 518 | int id = -1; 519 | CoreMesh* mesh = nullptr; 520 | D3D12SVG(D3D12PaintDevice* dev) :device(dev) { }; 521 | public: 522 | void Dispose(); 523 | 524 | }; 525 | 526 | class D3D12SVGBuilder : public::RLL::ISVGBuilder 527 | { 528 | friend class D3D12PaintDevice; 529 | D3D12PaintDevice* device = nullptr; 530 | struct Layer 531 | { 532 | enum class TYPE 533 | { 534 | TYPE_GEOMETRY, 535 | TYPE_SVG 536 | }; 537 | union 538 | { 539 | struct { 540 | D3D12Geometry* geometry; 541 | D3D12Brush* brush; 542 | }; 543 | D3D12SVG* svg; 544 | }; 545 | TYPE type = TYPE::TYPE_GEOMETRY; 546 | Math3D::Matrix4x4 transform; 547 | Layer() 548 | { 549 | geometry = nullptr; 550 | brush = nullptr; 551 | svg = nullptr; 552 | transform = {}; 553 | } 554 | Layer(const Layer& l) : Layer() 555 | { 556 | memcpy(this, &l, sizeof(l)); 557 | if (type == TYPE::TYPE_GEOMETRY) 558 | { 559 | geometry->AddRef(); 560 | if (brush) 561 | brush->AddRef(); 562 | } 563 | else if (type == TYPE::TYPE_SVG) 564 | { 565 | svg->AddRef(); 566 | } 567 | } 568 | ~Layer() 569 | { 570 | //std::cout << "Layer desctruct." << std::endl; 571 | if (type == TYPE::TYPE_GEOMETRY) 572 | { 573 | geometry->Release(); 574 | if (brush) 575 | brush->Release(); 576 | } 577 | else if (type == TYPE::TYPE_SVG) 578 | { 579 | svg->Release(); 580 | } 581 | } 582 | }; 583 | std::vector layers; 584 | 585 | D3D12SVGBuilder(D3D12PaintDevice* dev) :device(dev) { }; 586 | public: 587 | void Push(RLL::IGeometry* geom, RLL::IBrush* brush, Math3D::Matrix4x4* transform = nullptr); 588 | void Push(RLL::ISVG* svg, Math3D::Matrix4x4* transform = nullptr); 589 | void Reset(); 590 | RLL::ISVG* Commit(); 591 | void Dispose(); 592 | }; 593 | 594 | void InitatePaint(int flags); -------------------------------------------------------------------------------- /RLL/win32paint_d12context.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaazar/RLL/f82af45fa96038485a10bef3f6a514242f79e978/RLL/win32paint_d12context.cpp -------------------------------------------------------------------------------- /RLL/win32paint_d12device.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gaazar/RLL/f82af45fa96038485a10bef3f6a514242f79e978/RLL/win32paint_d12device.cpp -------------------------------------------------------------------------------- /RLL/win32paint_d12svg.cpp: -------------------------------------------------------------------------------- 1 | #include "win32paint_d12.h" 2 | using namespace RLL; 3 | using namespace std; 4 | using namespace Math3D; 5 | 6 | void D3D12SVGBuilder::Push(RLL::IGeometry* geom, RLL::IBrush* brush, Matrix4x4* transform) 7 | { 8 | if (geom == nullptr) 9 | { 10 | SetError("parameter geom is a null pointer."); 11 | return; 12 | } 13 | Layer l; 14 | l.type = Layer::TYPE::TYPE_GEOMETRY; 15 | l.geometry = (D3D12Geometry*)geom; 16 | l.brush = (D3D12Brush*)brush; 17 | if (transform) 18 | l.transform = *transform; 19 | else 20 | l.transform = Matrix4x4::Identity(); 21 | layers.push_back(l); 22 | geom->AddRef(); 23 | if (brush) brush->AddRef(); 24 | } 25 | void D3D12SVGBuilder::Push(RLL::ISVG* svg, Matrix4x4* transform) 26 | { 27 | if (svg == nullptr) 28 | { 29 | SetError("parameter svg is a null pointer."); 30 | return; 31 | } 32 | Layer l; 33 | l.type = Layer::TYPE::TYPE_SVG; 34 | l.geometry = (D3D12Geometry*)svg; 35 | if (transform) 36 | l.transform = *transform; 37 | else 38 | l.transform = Matrix4x4::Identity(); 39 | layers.push_back(l); 40 | svg->AddRef(); 41 | } 42 | void D3D12SVGBuilder::Reset() 43 | { 44 | layers.clear(); 45 | } 46 | RLL::ISVG* D3D12SVGBuilder::Commit() 47 | { 48 | if (!layers.size()) 49 | { 50 | SetError("Empty SVGBuilder. No layers pushed."); 51 | return nullptr; 52 | } 53 | 54 | vector uv; 55 | vector pos; 56 | vector pnb; 57 | vector tfs; 58 | vector ind; 59 | int vb = 0, ib = 0; 60 | uv.reserve(512); 61 | pos.reserve(512); 62 | pnb.reserve(512); 63 | ind.reserve(512); 64 | tfs.reserve(512); 65 | 66 | for (auto& i : layers) 67 | { 68 | switch (i.type) 69 | { 70 | case Layer::TYPE::TYPE_GEOMETRY: 71 | { 72 | //uvMat._41 = i.transform._41; 73 | //uvMat._42 = i.transform._42; 74 | D3D12GeometryMesh& m = *i.geometry->mesh; 75 | auto uvMat = (i.transform).Inversed() * m.uvTransform; 76 | for (auto& n : m.verts) 77 | { 78 | pos.push_back(n * i.transform); 79 | tfs.push_back({ uvMat._11,uvMat._12,uvMat._21,uvMat._22 }); 80 | } 81 | for (auto& n : m.uv) 82 | { 83 | uv.push_back(n); 84 | } 85 | for (auto& n : m.indices) 86 | ind.push_back(n + vb); 87 | auto normT = i.transform; 88 | normT._41 = 0; 89 | normT._42 = 0; 90 | normT._43 = 0; 91 | for (auto& n : m.path_norm) 92 | { 93 | auto norm = Vector2(cosf(n.y), sinf(n.y)); 94 | norm = norm * normT; 95 | auto ny = atan2f(norm.y, norm.x); 96 | 97 | if (i.brush) 98 | pnb.push_back({ n.x,ny,(float)i.brush->id }); 99 | else 100 | pnb.push_back({ n.x,ny,0.f }); 101 | } 102 | 103 | vb += m.verts.size(); 104 | ib += m.indices.size(); 105 | } 106 | break; 107 | case Layer::TYPE::TYPE_SVG: 108 | { 109 | CoreMesh& v = *i.svg->mesh; 110 | for (int n = 0; n < v.vertCount; n++) 111 | { 112 | pos.push_back(v.vertices[n] * i.transform); 113 | uv.push_back(v.uvs[n]); 114 | 115 | 116 | auto normT = i.transform; 117 | normT._41 = 0; 118 | normT._42 = 0; 119 | normT._43 = 0; 120 | 121 | auto norm = Vector2(cosf(v.pnbs[n].y), sinf(v.pnbs[n].y)); 122 | norm = norm * normT; 123 | auto ny = atan2f(norm.y, norm.x); 124 | auto pnbT = v.pnbs[n]; 125 | pnbT.y = ny; 126 | pnb.push_back(pnbT); 127 | 128 | auto ruvT = Matrix4x4::Identity(); 129 | ruvT._11 = v.tfs[n].x; 130 | ruvT._12 = v.tfs[n].y; 131 | ruvT._21 = v.tfs[n].z; 132 | ruvT._22 = v.tfs[n].w; 133 | auto uvMat = (i.transform).Inversed() * ruvT; 134 | 135 | tfs.push_back({ uvMat._11,uvMat._12,uvMat._21,uvMat._22 }); 136 | } 137 | for (int n = 0; n < v.idxCount; n++) 138 | { 139 | ind.push_back(vb + v.indices[n]); 140 | } 141 | 142 | vb += v.vertCount; 143 | ib += v.idxCount; 144 | //NOIMPL; 145 | } 146 | break; 147 | 148 | default: 149 | break; 150 | } 151 | } 152 | if (pos.size() < 3) 153 | { 154 | SetError("Invalid svg, vertices less than 3."); 155 | return nullptr; 156 | } 157 | auto svg = new D3D12SVG(device); 158 | svg->id = device->AllocateMesh(); 159 | auto corem = device->paths.meshes[svg->id]; 160 | svg->mesh = corem; 161 | corem->vertCount = uv.size(); 162 | corem->idxCount = ind.size(); 163 | corem->indices = new unsigned short[corem->idxCount]; 164 | corem->uvs = new Vector2[corem->vertCount]; 165 | corem->pnbs = new Vector3[corem->vertCount]; 166 | corem->vertices = new Vector2[corem->vertCount]; 167 | corem->tfs = new Vector4[corem->vertCount]; 168 | #define vecize(x) (sizeof(x[0]) * x.size()) 169 | memcpy(corem->indices, &ind[0], vecize(ind)); 170 | memcpy(corem->uvs, &uv[0], vecize(uv)); 171 | memcpy(corem->pnbs, &pnb[0], vecize(pnb)); 172 | memcpy(corem->vertices, &pos[0], vecize(pos)); 173 | memcpy(corem->tfs, &tfs[0], vecize(tfs)); 174 | 175 | //corem.UploadToGPUMemory 176 | corem->Upload(device); 177 | device->flag |= FLAG_D12PD_PATH_DIRTY | FLAG_D12PD_CURVE_DIRTY; 178 | return svg; 179 | } 180 | void D3D12SVGBuilder::Dispose() 181 | { 182 | delete this; 183 | } 184 | void D3D12SVG::Dispose() 185 | { 186 | delete mesh; 187 | device->paths.meshes[id] = nullptr; 188 | id = -1; 189 | delete this; 190 | } 191 | -------------------------------------------------------------------------------- /RLL/win32whelper.h: -------------------------------------------------------------------------------- 1 | #include "win32internal.h" 2 | 3 | enum class Style : DWORD { 4 | windowed = WS_OVERLAPPEDWINDOW | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, 5 | aero_borderless = WS_POPUP | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, 6 | basic_borderless = WS_POPUP | WS_THICKFRAME | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX, 7 | noanim_borderless = WS_SYSMENU 8 | }; 9 | 10 | bool maximized(HWND hwnd) 11 | { 12 | WINDOWPLACEMENT placement; 13 | if (!::GetWindowPlacement(hwnd, &placement)) { 14 | return false; 15 | } 16 | 17 | return placement.showCmd == SW_MAXIMIZE; 18 | } 19 | 20 | void adjust_maximized_client_rect(HWND window, RECT& rect) 21 | { 22 | if (!maximized(window)) { 23 | return; 24 | } 25 | 26 | auto monitor = ::MonitorFromWindow(window, MONITOR_DEFAULTTONULL); 27 | if (!monitor) { 28 | return; 29 | } 30 | 31 | MONITORINFO monitor_info{}; 32 | monitor_info.cbSize = sizeof(monitor_info); 33 | if (!::GetMonitorInfoW(monitor, &monitor_info)) { 34 | return; 35 | } 36 | 37 | // when maximized, make the client area fill just the monitor (without task bar) rect, 38 | // not the whole window rect which extends beyond the monitor. 39 | rect = monitor_info.rcWork; 40 | } 41 | 42 | LRESULT hit_test(HWND hWnd, POINT cursor, bool dragable, bool sizable) 43 | { 44 | // identify borders and corners to allow resizing the window. 45 | // Note: On Windows 10, windows behave differently and 46 | // allow resizing outside the visible window frame. 47 | // This implementation does not replicate that behavior. 48 | const POINT border{ 49 | ::GetSystemMetrics(SM_CXFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER), 50 | ::GetSystemMetrics(SM_CYFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER) 51 | }; 52 | RECT window; 53 | if (!::GetWindowRect(hWnd, &window)) { 54 | return HTNOWHERE; 55 | } 56 | 57 | const auto drag = dragable ? HTCAPTION : HTCLIENT; 58 | 59 | enum region_mask { 60 | client = 0b0000, 61 | left = 0b0001, 62 | right = 0b0010, 63 | top = 0b0100, 64 | bottom = 0b1000, 65 | }; 66 | 67 | const auto result = 68 | left * (cursor.x < (window.left + border.x)) | 69 | right * (cursor.x >= (window.right - border.x)) | 70 | top * (cursor.y < (window.top + border.y)) | 71 | bottom * (cursor.y >= (window.bottom - border.y)); 72 | 73 | switch (result) { 74 | case left: return sizable ? HTLEFT : drag; 75 | case right: return sizable ? HTRIGHT : drag; 76 | case top: return sizable ? HTTOP : drag; 77 | case bottom: return sizable ? HTBOTTOM : drag; 78 | case top | left: return sizable ? HTTOPLEFT : drag; 79 | case top | right: return sizable ? HTTOPRIGHT : drag; 80 | case bottom | left: return sizable ? HTBOTTOMLEFT : drag; 81 | case bottom | right: return sizable ? HTBOTTOMRIGHT : drag; 82 | case client: return drag; 83 | default: return HTNOWHERE; 84 | } 85 | } 86 | 87 | bool composition_enabled() { 88 | BOOL composition_enabled = FALSE; 89 | bool success = ::DwmIsCompositionEnabled(&composition_enabled) == S_OK; 90 | return composition_enabled && success; 91 | } 92 | const wchar_t* window_class(WNDPROC wndproc) 93 | { 94 | static const wchar_t* window_class_name = [&] { 95 | WNDCLASSEXW wcx{}; 96 | wcx.cbSize = sizeof(wcx); 97 | wcx.style = CS_HREDRAW | CS_VREDRAW; 98 | wcx.hInstance = nullptr; 99 | wcx.lpfnWndProc = wndproc; 100 | wcx.lpszClassName = L"Frame"; 101 | wcx.hbrBackground = CreateSolidBrush(0x00FF00FF); 102 | wcx.hCursor = ::LoadCursorW(nullptr, IDC_ARROW); 103 | const ATOM result = ::RegisterClassExW(&wcx); 104 | assert(result); 105 | 106 | return wcx.lpszClassName; 107 | }(); 108 | return window_class_name; 109 | } 110 | 111 | HWND create_window(HWND parent, WNDPROC wndproc, void* userdata, SIZE size, POINT posi, DWORD extStyles = 0) { 112 | auto handle = CreateWindowExW( 113 | extStyles, window_class(wndproc), L"Frame", 114 | static_cast(Style::aero_borderless), posi.x, posi.y, 115 | size.cx, size.cy, parent, nullptr, nullptr, userdata 116 | ); 117 | assert(handle);//failed to create window 118 | 119 | return handle; 120 | } 121 | 122 | void set_shadow(HWND handle, bool enabled) { 123 | if (composition_enabled()) { 124 | static const MARGINS shadow_state[2]{ { 0,0,0,0 },{ 0,0,1,0 } }; 125 | ::DwmExtendFrameIntoClientArea(handle, &shadow_state[enabled]); 126 | } 127 | } 128 | Style select_borderless_style() 129 | { 130 | return composition_enabled() ? Style::aero_borderless : Style::basic_borderless; 131 | } 132 | 133 | void set_borderless(HWND hWnd, bool enabled) { 134 | Style new_style = (enabled) ? select_borderless_style() : Style::windowed; 135 | Style old_style = static_cast