├── .gitattributes ├── .gitignore ├── Horizon.slnx ├── LICENSE ├── README.md ├── external ├── KeyboardShortcutsJS │ └── main.js └── QRCoder │ ├── AbstractQRCode.cs │ ├── BitmapByteQRCode.cs │ ├── Exceptions │ └── DataTooLongException.cs │ ├── Extensions │ └── BitArrayExtensions.cs │ ├── PayloadGenerator │ ├── Payload.cs │ └── Url.cs │ ├── Properties │ └── AssemblyInfo.cs │ ├── QRCodeData.cs │ ├── QRCodeGenerator.cs │ ├── QRCodeGenerator │ ├── AlignmentPattern.cs │ ├── CodewordBlock.cs │ ├── ECCInfo.cs │ ├── ECCLevel.cs │ ├── EciMode.cs │ ├── EncodingMode.cs │ ├── ModulePlacer.BlockedModules.cs │ ├── ModulePlacer.MaskPattern.cs │ ├── ModulePlacer.cs │ ├── Point.cs │ ├── Polynom.cs │ ├── PolynomItem.cs │ ├── Rectangle.cs │ ├── VersionInfo.cs │ └── VersionInfoDetails.cs │ └── QRCoder.csproj ├── images ├── ghreleasesbadge.png └── msstorebadge.png ├── package └── Horizon.Package │ ├── Assets │ ├── AppIcons │ │ ├── LargeTile.scale-100.png │ │ ├── LargeTile.scale-125.png │ │ ├── LargeTile.scale-150.png │ │ ├── LargeTile.scale-200.png │ │ ├── LargeTile.scale-400.png │ │ ├── SmallTile.scale-100.png │ │ ├── SmallTile.scale-125.png │ │ ├── SmallTile.scale-150.png │ │ ├── SmallTile.scale-200.png │ │ ├── SmallTile.scale-400.png │ │ ├── SplashScreen.scale-100.png │ │ ├── SplashScreen.scale-125.png │ │ ├── SplashScreen.scale-150.png │ │ ├── SplashScreen.scale-200.png │ │ ├── SplashScreen.scale-400.png │ │ ├── Square150x150Logo.scale-100.png │ │ ├── Square150x150Logo.scale-125.png │ │ ├── Square150x150Logo.scale-150.png │ │ ├── Square150x150Logo.scale-200.png │ │ ├── Square150x150Logo.scale-400.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-24.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-lightunplated_targetsize-48.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-16.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-256.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-32.png │ │ ├── Square44x44Logo.altform-unplated_targetsize-48.png │ │ ├── Square44x44Logo.scale-100.png │ │ ├── Square44x44Logo.scale-125.png │ │ ├── Square44x44Logo.scale-150.png │ │ ├── Square44x44Logo.scale-200.png │ │ ├── Square44x44Logo.scale-400.png │ │ ├── Square44x44Logo.targetsize-16.png │ │ ├── Square44x44Logo.targetsize-24.png │ │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ │ ├── Square44x44Logo.targetsize-256.png │ │ ├── Square44x44Logo.targetsize-32.png │ │ ├── Square44x44Logo.targetsize-48.png │ │ ├── StoreLogo.scale-100.png │ │ ├── StoreLogo.scale-125.png │ │ ├── StoreLogo.scale-150.png │ │ ├── StoreLogo.scale-200.png │ │ ├── StoreLogo.scale-400.png │ │ ├── Wide310x150Logo.scale-100.png │ │ ├── Wide310x150Logo.scale-125.png │ │ ├── Wide310x150Logo.scale-150.png │ │ ├── Wide310x150Logo.scale-200.png │ │ └── Wide310x150Logo.scale-400.png │ ├── FileIcons │ │ ├── document.png │ │ └── link.png │ ├── Icons │ │ ├── DevSanx.png │ │ └── paypal.png │ └── JS │ │ └── readability.js │ ├── Horizon.Package.wapproj │ └── Package.appxmanifest └── src ├── App.xaml ├── App.xaml.cs ├── Controls └── Tabs │ ├── Tab.cs │ └── WebTabCreationParams.cs ├── Core ├── AppVersionHelper.cs ├── Backdrops.cs ├── ClipboardHelper.cs ├── FileHelper.cs ├── FolderHelper.cs ├── IconHelper.cs ├── ModernAboutBlank.cs ├── SearchEngine.cs ├── SearchEngineHelper.cs ├── SettingsHelper.cs ├── UrlHelper.cs ├── WebView2ProfileHelper.cs ├── Win32Helper.cs ├── WindowHelper.cs └── WindowsHelloHelper.cs ├── GlobalUsings.cs ├── Horizon.csproj ├── Horizon.ico ├── Modules ├── Favorites │ ├── FavoriteItem.cs │ └── FavoritesHelper.cs ├── QRCodeGen │ └── QRCodeHelper.cs └── Readability │ └── ReadabilityHelper.cs ├── NativeMethods.txt ├── Pages ├── ExtensionsPage.xaml ├── ExtensionsPage.xaml.cs ├── SettingsPage.xaml ├── SettingsPage.xaml.cs ├── SplitTabPage.xaml ├── SplitTabPage.xaml.cs ├── WebViewPage.xaml └── WebViewPage.xaml.cs ├── Properties └── PublishProfiles │ ├── win-arm64.pubxml │ └── win-x64.pubxml ├── Styles └── Merged.xaml ├── ViewModels └── SettingsViewModel.cs ├── WindowChrome.xaml ├── WindowChrome.xaml.cs └── app.manifest /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.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/main/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 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual Studio profiler 105 | *.psess 106 | *.vsp 107 | *.vspx 108 | *.sap 109 | 110 | # Visual Studio Trace Files 111 | *.e2e 112 | 113 | # TFS 2012 Local Workspace 114 | $tf/ 115 | 116 | # Guidance Automation Toolkit 117 | *.gpState 118 | 119 | # ReSharper is a .NET coding add-in 120 | _ReSharper*/ 121 | *.[Rr]e[Ss]harper 122 | *.DotSettings.user 123 | 124 | # TeamCity is a build add-in 125 | _TeamCity* 126 | 127 | # DotCover is a Code Coverage Tool 128 | *.dotCover 129 | 130 | # AxoCover is a Code Coverage Tool 131 | .axoCover/* 132 | !.axoCover/settings.json 133 | 134 | # Coverlet is a free, cross platform Code Coverage Tool 135 | coverage*.json 136 | coverage*.xml 137 | coverage*.info 138 | 139 | # Visual Studio code coverage results 140 | *.coverage 141 | *.coveragexml 142 | 143 | # NCrunch 144 | _NCrunch_* 145 | .*crunch*.local.xml 146 | nCrunchTemp_* 147 | 148 | # MightyMoose 149 | *.mm.* 150 | AutoTest.Net/ 151 | 152 | # Web workbench (sass) 153 | .sass-cache/ 154 | 155 | # Installshield output folder 156 | [Ee]xpress/ 157 | 158 | # DocProject is a documentation generator add-in 159 | DocProject/buildhelp/ 160 | DocProject/Help/*.HxT 161 | DocProject/Help/*.HxC 162 | DocProject/Help/*.hhc 163 | DocProject/Help/*.hhk 164 | DocProject/Help/*.hhp 165 | DocProject/Help/Html2 166 | DocProject/Help/html 167 | 168 | # Click-Once directory 169 | publish/ 170 | 171 | # Publish Web Output 172 | *.[Pp]ublish.xml 173 | *.azurePubxml 174 | # Note: Comment the next line if you want to checkin your web deploy settings, 175 | # but database connection strings (with potential passwords) will be unencrypted 176 | # *.pubxml 177 | *.publishproj 178 | 179 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 180 | # checkin your Azure Web App publish settings, but sensitive information contained 181 | # in these scripts will be unencrypted 182 | PublishScripts/ 183 | 184 | # NuGet Packages 185 | *.nupkg 186 | # NuGet Symbol Packages 187 | *.snupkg 188 | # The packages folder can be ignored because of Package Restore 189 | **/[Pp]ackages/* 190 | # except build/, which is used as an MSBuild target. 191 | !**/[Pp]ackages/build/ 192 | # Uncomment if necessary however generally it will be regenerated when needed 193 | #!**/[Pp]ackages/repositories.config 194 | # NuGet v3's project.json files produces more ignorable files 195 | *.nuget.props 196 | *.nuget.targets 197 | 198 | # Microsoft Azure Build Output 199 | csx/ 200 | *.build.csdef 201 | 202 | # Microsoft Azure Emulator 203 | ecf/ 204 | rcf/ 205 | 206 | # Windows Store app package directories and files 207 | AppPackages/ 208 | BundleArtifacts/ 209 | Package.StoreAssociation.xml 210 | _pkginfo.txt 211 | *.appx 212 | *.appxbundle 213 | *.appxupload 214 | 215 | # Visual Studio cache files 216 | # files ending in .cache can be ignored 217 | *.[Cc]ache 218 | # but keep track of directories ending in .cache 219 | !?*.[Cc]ache/ 220 | 221 | # Others 222 | ClientBin/ 223 | ~$* 224 | *~ 225 | *.dbmdl 226 | *.dbproj.schemaview 227 | *.jfm 228 | *.pfx 229 | *.publishsettings 230 | orleans.codegen.cs 231 | 232 | # Including strong name files can present a security risk 233 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 234 | #*.snk 235 | 236 | # Since there are multiple workflows, uncomment next line to ignore bower_components 237 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 238 | #bower_components/ 239 | 240 | # RIA/Silverlight projects 241 | Generated_Code/ 242 | 243 | # Backup & report files from converting an old project file 244 | # to a newer Visual Studio version. Backup files are not needed, 245 | # because we have git ;-) 246 | _UpgradeReport_Files/ 247 | Backup*/ 248 | UpgradeLog*.XML 249 | UpgradeLog*.htm 250 | ServiceFabricBackup/ 251 | *.rptproj.bak 252 | 253 | # SQL Server files 254 | *.mdf 255 | *.ldf 256 | *.ndf 257 | 258 | # Business Intelligence projects 259 | *.rdl.data 260 | *.bim.layout 261 | *.bim_*.settings 262 | *.rptproj.rsuser 263 | *- [Bb]ackup.rdl 264 | *- [Bb]ackup ([0-9]).rdl 265 | *- [Bb]ackup ([0-9][0-9]).rdl 266 | 267 | # Microsoft Fakes 268 | FakesAssemblies/ 269 | 270 | # GhostDoc plugin setting file 271 | *.GhostDoc.xml 272 | 273 | # Node.js Tools for Visual Studio 274 | .ntvs_analysis.dat 275 | node_modules/ 276 | 277 | # Visual Studio 6 build log 278 | *.plg 279 | 280 | # Visual Studio 6 workspace options file 281 | *.opt 282 | 283 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 284 | *.vbw 285 | 286 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 287 | *.vbp 288 | 289 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 290 | *.dsw 291 | *.dsp 292 | 293 | # Visual Studio 6 technical files 294 | *.ncb 295 | *.aps 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 | # Visual Studio History (VSHistory) files 354 | .vshistory/ 355 | 356 | # BeatPulse healthcheck temp database 357 | healthchecksdb 358 | 359 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 360 | MigrationBackup/ 361 | 362 | # Ionide (cross platform F# VS Code tools) working folder 363 | .ionide/ 364 | 365 | # Fody - auto-generated XML schema 366 | FodyWeavers.xsd 367 | 368 | # VS Code files for those working on multiple tools 369 | .vscode/* 370 | !.vscode/settings.json 371 | !.vscode/tasks.json 372 | !.vscode/launch.json 373 | !.vscode/extensions.json 374 | *.code-workspace 375 | 376 | # Local History for Visual Studio Code 377 | .history/ 378 | 379 | # Windows Installer files from build outputs 380 | *.cab 381 | *.msi 382 | *.msix 383 | *.msm 384 | *.msp 385 | 386 | # JetBrains Rider 387 | *.sln.iml 388 | -------------------------------------------------------------------------------- /Horizon.slnx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Horizon screenshot 3 |

4 | 5 |

6 | 7 | 8 | 9 | 10 |

11 | 12 | Horizon is a modern webbrowser which enhances your browsing experience. It has been in active development for over two years, and is being constantly updated with bug fixes, performance improvements and new features. 13 | 14 | ## Headline features: 15 | - Responsive UI and quick startup time 16 | - Integrates nicely with other native Windows apps 17 | - Split tabs 18 | - Reading mode 19 | - Translate websites 20 | - Password lock 21 | - Generate QRCode for website 22 | - Export page to pdf (version 5.1 and newer) 23 | - Export page text content as txt (version 7.5 and newer) 24 | - New tab background images 25 | - Focus mode 26 | 27 | Check the app out to see them in action! 28 | 29 | ## Installing 30 | 31 | You can get Horizon from the main sources: 32 | 33 | ### Microsoft Store (recommended) 34 | 35 | This is the recommended source for most users, you can get Horizon easily [here](https://apps.microsoft.com/detail/9pfs0vxcd5sr) 36 | 37 | ### Winget 38 | 39 | If you prefer installing your apps from the command line, you can do so via winget 40 | 41 | ```batch 42 | winget install HorizonBrowser 43 | ``` 44 | 45 | ### GitHub releases (advanced) 46 | 47 | > [!WARNING] 48 | > You might not recive updates if you install Horizon this way, thus this method is only recommended for advanced users 49 | 50 | If you like to get the msix for yourself and install without winget or Microsoft Store, you can get the package [here](https://github.com/horizon-developers/browser/releases) 51 | 52 | You have to get the dependencies for your architecture (either X86, X64 or ARM64) as well as the main package. Then you can install them via PowerShell or App installer 53 | 54 | ```powershell 55 | Add-AppxPackage ".\Microsoft.WindowsAppRuntime.1.7_7000.456.1632.0_arm64__8wekyb3d8bbwe.msix" 56 | Add-AppxPackage ".\Microsoft.VCLibs.140.00_14.0.33519.0_arm64__8wekyb3d8bbwe.appx" 57 | Add-AppxPackage ".\Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_arm64__8wekyb3d8bbwe.appx" 58 | Add-AppxPackage ".\HorizonBrowser_10.0.5.0.msixbundle" 59 | ``` 60 | Be sure to replace them with the names of your packages according to your system and the latest versions 61 | ## Contributing 62 | 63 | ### Contributing source code 64 | You would like to contribute to this project? 65 | 66 | Awesome! Please first create an issue, so we can talk about the changes you like to implement 67 | 68 | ### Support the project by donating 69 | You would like to support this project because you love it, but do not have the time or expertise to contribute source code? 70 | 71 | A donation would be highly appreciated, and it helps me out a lot. Thanks :) 72 | 73 | [PayPal](https://www.paypal.com/paypalme/julianhasreiter) 74 | 75 | ## Building from source 76 | 77 | ### 1. Prerequisites 78 | - Visual Studio 2022, version 17.13 or newer 79 | - Windows 11 SDK (10.0.26100.0) 80 | - .NET 9 SDK 81 | - Windows Application Workload 82 | 83 | ### 2. Clone the repository 84 | ```batch 85 | git clone https://github.com/horizon-developers/browser.git 86 | ``` 87 | 88 | ### 3. Build the app 89 | In the newly cloned folder, navigate into the src folder and open Horizon.sln (or Horizon.slnx if you prefer that) 90 | On the top, select your configuration and platform and click on the play icon. 91 | Now VS should start building the app and will start it shortly. 92 | 93 | ## License 94 | GPL v3.0 95 | -------------------------------------------------------------------------------- /external/KeyboardShortcutsJS/main.js: -------------------------------------------------------------------------------- 1 | document.addEventListener("keydown", function (event) { 2 | if (event.ctrlKey && event.key === "l") { 3 | event.preventDefault(); 4 | window.chrome.webview.postMessage("ControlL"); 5 | } 6 | if (event.ctrlKey && event.key === "t") { 7 | event.preventDefault(); 8 | window.chrome.webview.postMessage("ControlT"); 9 | } 10 | }); -------------------------------------------------------------------------------- /external/QRCoder/AbstractQRCode.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | /// 4 | /// Abstract base class for generating QR codes. 5 | /// Derived classes typically render a QR code into a specific format (png, System.Drawing.Bitmap, PDF, etc). 6 | /// 7 | public abstract class AbstractQRCode 8 | { 9 | /// 10 | /// Gets or sets the QRCodeData used to generate the QR code. 11 | /// 12 | protected QRCodeData QrCodeData { get; set; } 13 | 14 | /// 15 | /// Initializes a new instance of the AbstractQRCode class. 16 | /// 17 | protected AbstractQRCode() 18 | { 19 | QrCodeData = null!; 20 | } 21 | 22 | /// 23 | /// Initializes a new instance of the AbstractQRCode class with the specified QRCodeData. 24 | /// 25 | /// The QRCodeData object generated by QRCodeGenerator.CreateQrCode(). 26 | protected AbstractQRCode(QRCodeData data) 27 | { 28 | QrCodeData = data; 29 | } 30 | 31 | /// 32 | /// Sets the QRCodeData object that will be used to generate the QR code. 33 | /// This method is useful for COM objects connections. 34 | /// 35 | /// The QRCodeData object generated by QRCodeGenerator.CreateQrCode(). 36 | public virtual void SetQRCodeData(QRCodeData data) 37 | => QrCodeData = data; 38 | 39 | /// 40 | /// Disposes the QRCodeData object. 41 | /// 42 | public void Dispose() 43 | { 44 | QrCodeData?.Dispose(); 45 | QrCodeData = null!; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /external/QRCoder/BitmapByteQRCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using static QRCoder.QRCodeGenerator; 3 | 4 | namespace QRCoder; 5 | 6 | 7 | /// 8 | /// Represents a QR code generator that outputs QR codes as bitmap byte arrays. 9 | /// 10 | // ReSharper disable once InconsistentNaming 11 | public class BitmapByteQRCode : AbstractQRCode, IDisposable 12 | { 13 | private static readonly byte[] _bitmapHeaderPart1 = new byte[] { 0x42, 0x4D }; 14 | private static readonly byte[] _bitmapHeaderPart2 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00 }; 15 | private static readonly byte[] _bitmapHeaderPartEnd = new byte[] { 0x01, 0x00, 0x18, 0x00 }; 16 | 17 | /// 18 | /// Initializes a new instance of the class. 19 | /// Constructor without parameters to be used in COM objects connections. 20 | /// 21 | public BitmapByteQRCode() { } 22 | 23 | /// 24 | /// Initializes a new instance of the class with the specified . 25 | /// 26 | /// generated by the QRCodeGenerator. 27 | public BitmapByteQRCode(QRCodeData data) : base(data) { } 28 | 29 | /// 30 | /// Returns the QR code graphic as a bitmap byte array. 31 | /// 32 | /// The number of pixels each dark/light module of the QR code will occupy in the final QR code image. 33 | /// Returns the QR code graphic as a bitmap byte array. 34 | public byte[] GetGraphic(int pixelsPerModule) 35 | => GetGraphic(pixelsPerModule, new byte[] { 0x00, 0x00, 0x00 }, new byte[] { 0xFF, 0xFF, 0xFF }); 36 | 37 | /// 38 | /// Returns the QR code graphic as a bitmap byte array. 39 | /// 40 | /// The number of pixels each dark/light module of the QR code will occupy in the final QR code image. 41 | /// The color of the dark modules in HTML hex format. 42 | /// The color of the light modules in HTML hex format. 43 | /// Returns the QR code graphic as a bitmap byte array. 44 | public byte[] GetGraphic(int pixelsPerModule, string darkColorHtmlHex, string lightColorHtmlHex) 45 | => GetGraphic(pixelsPerModule, HexColorToByteArray(darkColorHtmlHex), HexColorToByteArray(lightColorHtmlHex)); 46 | 47 | /// 48 | /// Returns the QR code graphic as a bitmap byte array. 49 | /// 50 | /// The number of pixels each dark/light module of the QR code will occupy in the final QR code image. 51 | /// The color of the dark modules as an RGB byte array. 52 | /// The color of the light modules as an RGB byte array. 53 | /// Returns the QR code graphic as a bitmap byte array. 54 | public byte[] GetGraphic(int pixelsPerModule, byte[] darkColorRgb, byte[] lightColorRgb) 55 | { 56 | var sideLength = QrCodeData.ModuleMatrix.Count * pixelsPerModule; 57 | 58 | // Pre-calculate color/module bytes 59 | byte[] moduleDark = new byte[pixelsPerModule * 3]; 60 | byte[] moduleLight = new byte[pixelsPerModule * 3]; 61 | for (int i = 0; i < pixelsPerModule * 3; i += 3) 62 | { 63 | moduleDark[i] = darkColorRgb[2]; 64 | moduleDark[i + 1] = darkColorRgb[1]; 65 | moduleDark[i + 2] = darkColorRgb[0]; 66 | moduleLight[i] = lightColorRgb[2]; 67 | moduleLight[i + 1] = lightColorRgb[1]; 68 | moduleLight[i + 2] = lightColorRgb[0]; 69 | } 70 | 71 | // Pre-calculate padding bytes 72 | var paddingLen = sideLength % 4; 73 | 74 | // Calculate filesize (header + pixel data + padding) 75 | var fileSize = 54 + (3 * (sideLength * sideLength)) + (sideLength * paddingLen); 76 | 77 | // Bitmap container 78 | byte[] bmp = new byte[fileSize]; 79 | int ix = 0; 80 | 81 | // Header part 1 82 | Array.Copy(_bitmapHeaderPart1, 0, bmp, ix, _bitmapHeaderPart1.Length); 83 | ix += _bitmapHeaderPart1.Length; 84 | 85 | // Filesize 86 | CopyIntAs4ByteToArray(fileSize, ix, bmp); 87 | ix += 4; 88 | 89 | // Header part 2 90 | Array.Copy(_bitmapHeaderPart2, 0, bmp, ix, _bitmapHeaderPart2.Length); 91 | ix += _bitmapHeaderPart2.Length; 92 | 93 | // Width 94 | CopyIntAs4ByteToArray(sideLength, ix, bmp); 95 | ix += 4; 96 | // Height 97 | CopyIntAs4ByteToArray(sideLength, ix, bmp); 98 | ix += 4; 99 | 100 | // Header end 101 | Array.Copy(_bitmapHeaderPartEnd, 0, bmp, ix, _bitmapHeaderPartEnd.Length); 102 | ix += _bitmapHeaderPartEnd.Length; 103 | 104 | // Add header null-bytes 105 | ix += 24; 106 | 107 | 108 | // Draw qr code 109 | for (var x = sideLength - 1; x >= 0; x -= pixelsPerModule) 110 | { 111 | var modMatrixX = (x + pixelsPerModule) / pixelsPerModule - 1; 112 | 113 | // Write data for first pixel of pixelsPerModule 114 | int posStartFirstPx = ix; 115 | for (var y = 0; y < sideLength; y += pixelsPerModule) 116 | { 117 | var module = QrCodeData.ModuleMatrix[modMatrixX][(y + pixelsPerModule) / pixelsPerModule - 1]; 118 | Array.Copy(module ? moduleDark : moduleLight, 0, bmp, ix, moduleDark.Length); 119 | ix += moduleDark.Length; 120 | } 121 | // Add padding (to make line length a multiple of 4) 122 | ix += paddingLen; 123 | int lenFirstPx = ix - posStartFirstPx; 124 | 125 | // Re-write (copy) first pixel (pixelsPerModule - 1) times 126 | for (int pm = 0; pm < (pixelsPerModule - 1); pm++) 127 | { 128 | // Draw pixels 129 | Array.Copy(bmp, posStartFirstPx, bmp, ix, lenFirstPx); 130 | ix += lenFirstPx; 131 | } 132 | } 133 | 134 | return bmp; 135 | } 136 | 137 | 138 | /// 139 | /// Converts a hex color string to a byte array. 140 | /// 141 | /// The hex color string to convert. 142 | /// Returns the color as a byte array. 143 | private byte[] HexColorToByteArray(string colorString) 144 | { 145 | if (colorString.StartsWith("#")) 146 | colorString = colorString.Substring(1); 147 | byte[] byteColor = new byte[colorString.Length / 2]; 148 | for (int i = 0; i < byteColor.Length; i++) 149 | byteColor[i] = byte.Parse(colorString.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture); 150 | return byteColor; 151 | } 152 | 153 | 154 | /// 155 | /// Converts an integer to a 4 bytes and writes them to a byte array at given position 156 | /// 157 | /// The integer to convert. 158 | /// Index of destinationArray where the converted bytes are written to 159 | /// Destination byte array that receives the bytes 160 | private void CopyIntAs4ByteToArray(int inp, int destinationIndex, byte[] destinationArray) 161 | { 162 | unchecked 163 | { 164 | destinationArray[destinationIndex + 3] = (byte)(inp >> 24); 165 | destinationArray[destinationIndex + 2] = (byte)(inp >> 16); 166 | destinationArray[destinationIndex + 1] = (byte)(inp >> 8); 167 | destinationArray[destinationIndex + 0] = (byte)(inp); 168 | } 169 | } 170 | } 171 | 172 | 173 | /// 174 | /// Provides helper functions for creating bitmap byte array QR codes. 175 | /// 176 | public static class BitmapByteQRCodeHelper 177 | { 178 | /// 179 | /// Creates a bitmap byte array QR code with a single function call. 180 | /// 181 | /// The text or payload to be encoded inside the QR code. 182 | /// The number of pixels each dark/light module of the QR code will occupy in the final QR code image. 183 | /// The color of the dark modules in HTML hex format. 184 | /// The color of the light modules in HTML hex format. 185 | /// The level of error correction data. 186 | /// Specifies whether the generator should be forced to work in UTF-8 mode. 187 | /// Specifies whether the byte-order-mark should be used. 188 | /// Specifies which ECI mode should be used. 189 | /// Sets the fixed QR code target version. 190 | /// Returns the QR code graphic as a bitmap byte array. 191 | public static byte[] GetQRCode(string plainText, int pixelsPerModule, string darkColorHtmlHex, 192 | string lightColorHtmlHex, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, 193 | EciMode eciMode = EciMode.Default, int requestedVersion = -1) 194 | { 195 | using var qrGenerator = new QRCodeGenerator(); 196 | using var qrCodeData = qrGenerator.CreateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, 197 | requestedVersion); 198 | using var qrCode = new BitmapByteQRCode(qrCodeData); 199 | return qrCode.GetGraphic(pixelsPerModule, darkColorHtmlHex, lightColorHtmlHex); 200 | } 201 | 202 | /// 203 | /// Creates a bitmap byte array QR code with a single function call. 204 | /// 205 | /// The text or payload to be encoded inside the QR code. 206 | /// The level of error correction data. 207 | /// The number of pixels each dark/light module of the QR code will occupy in the final QR code image. 208 | /// Returns the QR code graphic as a bitmap byte array. 209 | public static byte[] GetQRCode(string txt, QRCodeGenerator.ECCLevel eccLevel, int size) 210 | { 211 | using var qrGen = new QRCodeGenerator(); 212 | using var qrCode = qrGen.CreateQrCode(txt, eccLevel); 213 | using var qrBmp = new BitmapByteQRCode(qrCode); 214 | return qrBmp.GetGraphic(size); 215 | 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /external/QRCoder/Exceptions/DataTooLongException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace QRCoder.Exceptions; 4 | 5 | /// 6 | /// Exception thrown when the given payload exceeds the maximum size of the QR code standard. 7 | /// 8 | public class DataTooLongException : Exception 9 | { 10 | /// 11 | /// Initializes a new instance of the class with a specified error message. 12 | /// 13 | /// The error correction level of the QR code. 14 | /// The encoding mode of the QR code. 15 | /// The maximum size allowed for the given parameters in bytes. 16 | public DataTooLongException(string eccLevel, string encodingMode, int maxSizeByte) : base( 17 | $"The given payload exceeds the maximum size of the QR code standard. The maximum size allowed for the chosen parameters (ECC level={eccLevel}, EncodingMode={encodingMode}) is {maxSizeByte} bytes." 18 | ) 19 | { } 20 | 21 | /// 22 | /// Initializes a new instance of the class with a specified error message. 23 | /// 24 | /// The error correction level of the QR code. 25 | /// The encoding mode of the QR code. 26 | /// The fixed version of the QR code. 27 | /// The maximum size allowed for the given parameters in bytes. 28 | public DataTooLongException(string eccLevel, string encodingMode, int version, int maxSizeByte) : base( 29 | $"The given payload exceeds the maximum size of the QR code standard. The maximum size allowed for the chosen parameters (ECC level={eccLevel}, EncodingMode={encodingMode}, FixedVersion={version}) is {maxSizeByte} bytes." 30 | ) 31 | { } 32 | } 33 | -------------------------------------------------------------------------------- /external/QRCoder/Extensions/BitArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | 3 | namespace QRCoder; 4 | 5 | /// 6 | /// Helper methods for . 7 | /// 8 | internal static class BitArrayExtensions 9 | { 10 | /// 11 | /// Copies a specified number of elements from one to another starting at the specified offsets. 12 | /// 13 | /// The source from which elements will be copied. 14 | /// The zero-based index in the source at which copying begins. 15 | /// The destination to which elements will be copied. 16 | /// The zero-based index in the destination at which storing begins. 17 | /// The number of elements to copy. 18 | /// The index in the destination immediately following the last copied element. 19 | public static int CopyTo(this BitArray source, BitArray destination, int sourceOffset, int destinationOffset, int count) 20 | { 21 | for (int i = 0; i < count; i++) 22 | { 23 | destination[destinationOffset + i] = source[sourceOffset + i]; 24 | } 25 | return destinationOffset + count; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /external/QRCoder/PayloadGenerator/Payload.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | /// 4 | /// Contains classes and methods for generating payloads for QR codes. 5 | /// 6 | public static partial class PayloadGenerator 7 | { 8 | /// 9 | /// Represents the base class for all QR code payloads. 10 | /// 11 | public abstract class Payload 12 | { 13 | /// 14 | /// Gets the version of the QR code payload. 15 | /// 16 | public virtual int Version => -1; 17 | 18 | /// 19 | /// Gets the error correction level of the QR code payload. 20 | /// 21 | public virtual QRCodeGenerator.ECCLevel EccLevel => QRCodeGenerator.ECCLevel.Default; 22 | 23 | /// 24 | /// Gets the ECI mode of the QR code payload. 25 | /// 26 | public virtual QRCodeGenerator.EciMode EciMode => QRCodeGenerator.EciMode.Default; 27 | 28 | /// 29 | /// Returns a string representation of the QR code payload. 30 | /// 31 | /// A string representation of the QR code payload. 32 | public abstract override string ToString(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /external/QRCoder/PayloadGenerator/Url.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace QRCoder; 4 | 5 | public static partial class PayloadGenerator 6 | { 7 | /// 8 | /// Generates a URL payload for QR codes. 9 | /// 10 | public class Url : Payload 11 | { 12 | private readonly string _url; 13 | 14 | /// 15 | /// Initializes a new instance of the class. 16 | /// 17 | /// The target URL. If the protocol is not specified, the http protocol will be added. 18 | public Url(string url) 19 | { 20 | _url = url; 21 | } 22 | 23 | /// 24 | /// Returns the URL payload as a string. 25 | /// 26 | /// The URL payload as a string, ensuring it starts with "http://" if no protocol is specified. 27 | public override string ToString() 28 | => !_url.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? "http://" + _url : _url; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /external/QRCoder/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // Allgemeine Informationen über eine Assembly werden über die folgenden 5 | // Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, 6 | // die mit einer Assembly verknüpft sind. 7 | [assembly: AssemblyTitle("QRCoder")] 8 | [assembly: AssemblyDescription("QRCoder is a simple library, written in C#.NET, which enables you to create QR Codes. It's licensed under the MIT-license.")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("www.code-bude.net")] 11 | [assembly: AssemblyProduct("QRCoder")] 12 | [assembly: AssemblyCopyright("Copyright © www.code-bude.net / Raffael Herrmann. All rights reserved.")] 13 | [assembly: AssemblyTrademark("written by Raffael Herrmann")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 17 | // für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 18 | // COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. 19 | [assembly: ComVisible(true)] 20 | 21 | // Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird 22 | [assembly: Guid("e668b98b-83bb-4e60-b33c-4fd5ed9c0156")] 23 | 24 | // Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: 25 | // 26 | // Hauptversion 27 | // Nebenversion 28 | // Buildnummer 29 | // Revision 30 | // 31 | // Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 32 | // übernehmen, indem Sie "*" eingeben: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.6.1.0")] 35 | [assembly: AssemblyFileVersion("1.6.1.0")] 36 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.IO.Compression; 6 | 7 | namespace QRCoder; 8 | 9 | /// 10 | /// Represents the data structure of a QR code. 11 | /// 12 | public class QRCodeData : IDisposable 13 | { 14 | /// 15 | /// Gets or sets the module matrix of the QR code. 16 | /// 17 | public List ModuleMatrix { get; set; } 18 | 19 | /// 20 | /// Initializes a new instance of the class with the specified version. 21 | /// 22 | /// The version of the QR code. 23 | public QRCodeData(int version) 24 | { 25 | Version = version; 26 | var size = ModulesPerSideFromVersion(version); 27 | ModuleMatrix = new List(size); 28 | for (var i = 0; i < size; i++) 29 | ModuleMatrix.Add(new BitArray(size)); 30 | } 31 | 32 | /// 33 | /// Initializes a new instance of the class with the specified version and padding option. 34 | /// 35 | /// The version of the QR code. 36 | /// Indicates whether padding should be added to the QR code. 37 | public QRCodeData(int version, bool addPadding) 38 | { 39 | Version = version; 40 | var size = ModulesPerSideFromVersion(version) + (addPadding ? 8 : 0); 41 | ModuleMatrix = new List(size); 42 | for (var i = 0; i < size; i++) 43 | ModuleMatrix.Add(new BitArray(size)); 44 | } 45 | 46 | /// 47 | /// Initializes a new instance of the class with raw data from a specified path and compression mode. 48 | /// 49 | /// The path to the raw data file. 50 | /// The compression mode used for the raw data. 51 | public QRCodeData(string pathToRawData, Compression compressMode) : this(File.ReadAllBytes(pathToRawData), compressMode) 52 | { 53 | } 54 | 55 | /// 56 | /// Initializes a new instance of the class with raw data and compression mode. 57 | /// 58 | /// The raw data of the QR code. 59 | /// The compression mode used for the raw data. 60 | public QRCodeData(byte[] rawData, Compression compressMode) 61 | { 62 | var bytes = new List(rawData); 63 | 64 | //Decompress 65 | if (compressMode == Compression.Deflate) 66 | { 67 | using var input = new MemoryStream(bytes.ToArray()); 68 | using var output = new MemoryStream(); 69 | using (var dstream = new DeflateStream(input, CompressionMode.Decompress)) 70 | { 71 | dstream.CopyTo(output); 72 | } 73 | bytes = new List(output.ToArray()); 74 | } 75 | else if (compressMode == Compression.GZip) 76 | { 77 | using var input = new MemoryStream(bytes.ToArray()); 78 | using var output = new MemoryStream(); 79 | using (var dstream = new GZipStream(input, CompressionMode.Decompress)) 80 | { 81 | dstream.CopyTo(output); 82 | } 83 | bytes = new List(output.ToArray()); 84 | } 85 | 86 | if (bytes[0] != 0x51 || bytes[1] != 0x52 || bytes[2] != 0x52) 87 | throw new Exception("Invalid raw data file. Filetype doesn't match \"QRR\"."); 88 | 89 | //Set QR code version 90 | var sideLen = (int)bytes[4]; 91 | bytes.RemoveRange(0, 5); 92 | Version = (sideLen - 21 - 8) / 4 + 1; 93 | 94 | //Unpack 95 | var modules = new Queue(8 * bytes.Count); 96 | foreach (var b in bytes) 97 | { 98 | var bArr = new BitArray(new byte[] { b }); 99 | for (int i = 7; i >= 0; i--) 100 | { 101 | modules.Enqueue((b & (1 << i)) != 0); 102 | } 103 | } 104 | 105 | //Build module matrix 106 | ModuleMatrix = new List(sideLen); 107 | for (int y = 0; y < sideLen; y++) 108 | { 109 | ModuleMatrix.Add(new BitArray(sideLen)); 110 | for (int x = 0; x < sideLen; x++) 111 | { 112 | ModuleMatrix[y][x] = modules.Dequeue(); 113 | } 114 | } 115 | 116 | } 117 | 118 | /// 119 | /// Gets the raw data of the QR code with the specified compression mode. 120 | /// 121 | /// The compression mode used for the raw data. 122 | /// Returns the raw data of the QR code as a byte array. 123 | public byte[] GetRawData(Compression compressMode) 124 | { 125 | var bytes = new List(); 126 | 127 | //Add header - signature ("QRR") 128 | bytes.AddRange(new byte[] { 0x51, 0x52, 0x52, 0x00 }); 129 | 130 | //Add header - rowsize 131 | bytes.Add((byte)ModuleMatrix.Count); 132 | 133 | //Build data queue 134 | var dataQueue = new Queue(); 135 | foreach (var row in ModuleMatrix) 136 | { 137 | foreach (var module in row) 138 | { 139 | dataQueue.Enqueue((bool)module ? 1 : 0); 140 | } 141 | } 142 | for (int i = 0; i < 8 - (ModuleMatrix.Count * ModuleMatrix.Count) % 8; i++) 143 | { 144 | dataQueue.Enqueue(0); 145 | } 146 | 147 | //Process queue 148 | while (dataQueue.Count > 0) 149 | { 150 | byte b = 0; 151 | for (int i = 7; i >= 0; i--) 152 | { 153 | b += (byte)(dataQueue.Dequeue() << i); 154 | } 155 | bytes.Add(b); 156 | } 157 | var rawData = bytes.ToArray(); 158 | 159 | //Compress stream (optional) 160 | if (compressMode == Compression.Deflate) 161 | { 162 | using var output = new MemoryStream(); 163 | using (var dstream = new DeflateStream(output, CompressionMode.Compress)) 164 | { 165 | dstream.Write(rawData, 0, rawData.Length); 166 | } 167 | rawData = output.ToArray(); 168 | } 169 | else if (compressMode == Compression.GZip) 170 | { 171 | using var output = new MemoryStream(); 172 | using (var gzipStream = new GZipStream(output, CompressionMode.Compress, true)) 173 | { 174 | gzipStream.Write(rawData, 0, rawData.Length); 175 | } 176 | rawData = output.ToArray(); 177 | } 178 | return rawData; 179 | } 180 | 181 | /// 182 | /// Saves the raw data of the QR code to a specified file with the specified compression mode. 183 | /// 184 | /// The path to the file where the raw data will be saved. 185 | /// The compression mode used for the raw data. 186 | public void SaveRawData(string filePath, Compression compressMode) 187 | => File.WriteAllBytes(filePath, GetRawData(compressMode)); 188 | 189 | /// 190 | /// Gets the version of the QR code. 191 | /// 192 | public int Version { get; private set; } 193 | 194 | /// 195 | /// Gets the number of modules per side from the specified version. 196 | /// 197 | /// The version of the QR code. 198 | /// Returns the number of modules per side. 199 | private static int ModulesPerSideFromVersion(int version) 200 | => 21 + (version - 1) * 4; 201 | 202 | /// 203 | /// Releases all resources used by the . 204 | /// 205 | public void Dispose() 206 | { 207 | ModuleMatrix = null!; 208 | Version = 0; 209 | 210 | } 211 | 212 | /// 213 | /// Specifies the compression mode used for the raw data. 214 | /// 215 | public enum Compression 216 | { 217 | /// 218 | /// No compression. 219 | /// 220 | Uncompressed, 221 | /// 222 | /// Deflate compression. 223 | /// 224 | Deflate, 225 | /// 226 | /// GZip compression. 227 | /// 228 | GZip 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/AlignmentPattern.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QRCoder; 4 | 5 | public partial class QRCodeGenerator 6 | { 7 | /// 8 | /// Represents the alignment pattern used in QR codes, which helps ensure the code remains readable even if it is somewhat distorted. 9 | /// Each QR code version has its own specific alignment pattern locations which this struct encapsulates. 10 | /// 11 | private struct AlignmentPattern 12 | { 13 | /// 14 | /// The version of the QR code. Higher versions have more complex and numerous alignment patterns. 15 | /// 16 | public int Version; 17 | 18 | /// 19 | /// A list of points where alignment patterns are located within the QR code matrix. 20 | /// Each point represents the center of an alignment pattern. 21 | /// 22 | public List PatternPositions; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/CodewordBlock.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | public partial class QRCodeGenerator 4 | { 5 | /// 6 | /// Represents a block of codewords in a QR code. QR codes are divided into several blocks for error correction purposes. 7 | /// Each block contains a series of data codewords followed by error correction codewords. 8 | /// 9 | private struct CodewordBlock 10 | { 11 | /// 12 | /// Initializes a new instance of the CodewordBlock struct with specified arrays of code words and error correction (ECC) words. 13 | /// 14 | /// The offset of the data codewords within the main BitArray. Data codewords carry the actual information. 15 | /// The length in bits of the data codewords within the main BitArray. 16 | /// The array of error correction codewords for this block. These codewords help recover the data if the QR code is damaged. 17 | public CodewordBlock(int codeWordsOffset, int codeWordsLength, byte[] eccWords) 18 | { 19 | CodeWordsOffset = codeWordsOffset; 20 | CodeWordsLength = codeWordsLength; 21 | ECCWords = eccWords; 22 | } 23 | 24 | /// 25 | /// Gets the offset of the data codewords in the BitArray. 26 | /// 27 | public int CodeWordsOffset { get; } 28 | 29 | /// 30 | /// Gets the length of the data codewords in the BitArray. 31 | /// 32 | public int CodeWordsLength { get; } 33 | 34 | /// 35 | /// Gets the error correction codewords associated with this block. 36 | /// 37 | public byte[] ECCWords { get; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/ECCInfo.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | public partial class QRCodeGenerator 4 | { 5 | /// 6 | /// Represents the error correction coding (ECC) information for a specific version and error correction level of a QR code. 7 | /// 8 | private struct ECCInfo 9 | { 10 | /// 11 | /// Initializes a new instance of the ECCInfo struct with specified properties. 12 | /// 13 | /// The version number of the QR code. 14 | /// The error correction level used in the QR code. 15 | /// The total number of data codewords for this version and error correction level. 16 | /// The number of error correction codewords per block. 17 | /// The number of blocks in group 1. 18 | /// The number of codewords in each block of group 1. 19 | /// The number of blocks in group 2, if any. 20 | /// The number of codewords in each block of group 2, if any. 21 | public ECCInfo(int version, ECCLevel errorCorrectionLevel, int totalDataCodewords, int eccPerBlock, int blocksInGroup1, 22 | int codewordsInGroup1, int blocksInGroup2, int codewordsInGroup2) 23 | { 24 | Version = version; 25 | ErrorCorrectionLevel = errorCorrectionLevel; 26 | TotalDataCodewords = totalDataCodewords; 27 | ECCPerBlock = eccPerBlock; 28 | BlocksInGroup1 = blocksInGroup1; 29 | CodewordsInGroup1 = codewordsInGroup1; 30 | BlocksInGroup2 = blocksInGroup2; 31 | CodewordsInGroup2 = codewordsInGroup2; 32 | } 33 | 34 | /// 35 | /// Gets the version number of the QR code. 36 | /// 37 | public int Version { get; } 38 | 39 | /// 40 | /// Gets the error correction level of the QR code. 41 | /// 42 | public ECCLevel ErrorCorrectionLevel { get; } 43 | 44 | /// 45 | /// Gets the total number of data codewords for this version and error correction level. 46 | /// 47 | public int TotalDataCodewords { get; } 48 | 49 | /// 50 | /// Gets the number of error correction codewords per block. 51 | /// 52 | public int ECCPerBlock { get; } 53 | 54 | /// 55 | /// Gets the number of blocks in group 1. 56 | /// 57 | public int BlocksInGroup1 { get; } 58 | 59 | /// 60 | /// Gets the number of codewords in each block of group 1. 61 | /// 62 | public int CodewordsInGroup1 { get; } 63 | 64 | /// 65 | /// Gets the number of blocks in group 2, if any. 66 | /// 67 | public int BlocksInGroup2 { get; } 68 | 69 | /// 70 | /// Gets the number of codewords in each block of group 2, if any. 71 | /// 72 | public int CodewordsInGroup2 { get; } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/ECCLevel.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | public partial class QRCodeGenerator 4 | { 5 | /// 6 | /// Defines the levels of error correction available in QR codes. 7 | /// Each level specifies the proportion of data that can be recovered if the QR code is partially obscured or damaged. 8 | /// 9 | public enum ECCLevel 10 | { 11 | /// 12 | /// Default error correction level, which will select Level M (Medium) unless otherwise specified by the payload. 13 | /// Level M allows approximately 15% of data to be recovered, offering a balance between data capacity and error recovery. 14 | /// 15 | Default = -1, 16 | 17 | /// 18 | /// Level L: Low error correction (approximately 7% of data can be recovered). 19 | /// This level allows the highest data density. 20 | /// 21 | L = 0, 22 | 23 | /// 24 | /// Level M: Medium error correction (approximately 15% of data can be recovered). 25 | /// Offers a balance between data capacity and error recovery. 26 | /// 27 | M = 1, 28 | 29 | /// 30 | /// Level Q: Quartile error correction (approximately 25% of data can be recovered). 31 | /// More robust error correction at the cost of reduced data capacity. 32 | /// 33 | Q = 2, 34 | 35 | /// 36 | /// Level H: High error correction (approximately 30% of data can be recovered). 37 | /// Provides the highest level of error recovery, ideal for environments with high risk of data loss. 38 | /// 39 | H = 3 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/EciMode.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | public partial class QRCodeGenerator 4 | { 5 | /// 6 | /// Enumerates the Extended Channel Interpretation (ECI) modes used in QR codes to handle different character encoding standards. 7 | /// ECI mode allows QR codes to efficiently encode data using character sets other than the default ISO-8859-1. 8 | /// 9 | public enum EciMode 10 | { 11 | /// 12 | /// Default encoding mode (typically ISO-8859-1). Used when no ECI mode is explicitly specified. 13 | /// This mode is assumed in basic QR codes where no extended character sets are needed. 14 | /// 15 | Default = 0, 16 | 17 | /// 18 | /// Specifies the use of the ISO-8859-1 character set, covering most Western European languages. 19 | /// This mode explicitly sets the encoding to ISO-8859-1, which includes characters used in languages such as English, French, German, and Spanish. 20 | /// 21 | Iso8859_1 = 3, 22 | 23 | /// 24 | /// Specifies the use of the ISO-8859-2 character set, which is primarily used for Central and Eastern European languages. 25 | /// This includes characters used in languages such as Polish, Czech, Slovak, Hungarian, and Romanian. 26 | /// 27 | Iso8859_2 = 4, 28 | 29 | /// 30 | /// Specifies the use of UTF-8 encoding. 31 | /// UTF-8 can encode any Unicode character and is useful for QR codes that need to support multi-language content. 32 | /// 33 | Utf8 = 26 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/EncodingMode.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | public partial class QRCodeGenerator 4 | { 5 | /// 6 | /// Specifies the encoding modes for the characters in a QR code. 7 | /// 8 | private enum EncodingMode 9 | { 10 | /// 11 | /// Numeric encoding mode, which is used to encode numeric data (digits 0-9). 12 | /// Three characters are encoded into 10 bits. 13 | /// 14 | Numeric = 1, 15 | 16 | /// 17 | /// Alphanumeric encoding mode, which is used to encode alphanumeric characters (0-9, A-Z, space, and some punctuation). 18 | /// Two characters are encoded into 11 bits. 19 | /// 20 | Alphanumeric = 2, 21 | 22 | /// 23 | /// Byte encoding mode, primarily using the ISO-8859-1 character set. Each character is encoded into 8 bits. 24 | /// When combined with ECI, it can be adapted to use other character sets. 25 | /// 26 | Byte = 4, 27 | 28 | /// 29 | /// Kanji encoding mode, which is used to encode characters from the Shift JIS character set, primarily for Japanese Kanji and Kana characters. 30 | /// One character is encoded into 13 bits. This mode is not currently supported by QRCoder. 31 | /// 32 | Kanji = 8, 33 | 34 | /// 35 | /// Extended Channel Interpretation (ECI) mode, which specifies a character set via an 8-bit number followed by one of the other encoding modes. 36 | /// This allows adapting the byte encoding to accommodate various global text encodings. 37 | /// 38 | ECI = 7 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/ModulePlacer.BlockedModules.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Threading; 4 | 5 | namespace QRCoder; 6 | 7 | public partial class QRCodeGenerator 8 | { 9 | private static partial class ModulePlacer 10 | { 11 | /// 12 | /// Struct that represents blocked modules using rectangles. 13 | /// 14 | public struct BlockedModules : IDisposable 15 | { 16 | private readonly BitArray[] _blockedModules; 17 | 18 | private static BitArray[]? _staticBlockedModules; 19 | 20 | /// 21 | /// Initializes a new instance of the struct with a specified capacity. 22 | /// 23 | /// The initial capacity of the blocked modules list. 24 | public BlockedModules(int size) 25 | { 26 | _blockedModules = Interlocked.Exchange(ref _staticBlockedModules, null)!; 27 | if (_blockedModules != null && _blockedModules.Length >= size) 28 | { 29 | for (int i = 0; i < size; i++) 30 | _blockedModules[i].SetAll(false); 31 | } 32 | else 33 | { 34 | _blockedModules = new BitArray[size]; 35 | for (int i = 0; i < size; i++) 36 | _blockedModules[i] = new BitArray(size); 37 | } 38 | } 39 | 40 | /// 41 | /// Adds a blocked module at the specified coordinates. 42 | /// 43 | /// The x-coordinate of the module. 44 | /// The y-coordinate of the module. 45 | public void Add(int x, int y) 46 | => _blockedModules[y][x] = true; 47 | 48 | /// 49 | /// Adds a blocked module defined by the specified rectangle. 50 | /// 51 | /// The rectangle that defines the blocked module. 52 | public void Add(Rectangle rect) 53 | { 54 | for (int y = rect.Y; y < rect.Y + rect.Height; y++) 55 | { 56 | for (int x = rect.X; x < rect.X + rect.Width; x++) 57 | { 58 | _blockedModules[y][x] = true; 59 | } 60 | } 61 | } 62 | 63 | /// 64 | /// Checks if the specified coordinates are blocked. 65 | /// 66 | /// The x-coordinate to check. 67 | /// The y-coordinate to check. 68 | /// true if the coordinates are blocked; otherwise, false. 69 | public bool IsBlocked(int x, int y) 70 | => _blockedModules[y][x]; 71 | 72 | /// 73 | /// Checks if the specified rectangle is blocked. 74 | /// 75 | /// The rectangle to check. 76 | /// true if the rectangle is blocked; otherwise, false. 77 | public bool IsBlocked(Rectangle r1) 78 | { 79 | for (int y = r1.Y; y < r1.Y + r1.Height; y++) 80 | { 81 | for (int x = r1.X; x < r1.X + r1.Width; x++) 82 | { 83 | if (_blockedModules[y][x]) 84 | return true; 85 | } 86 | } 87 | return false; 88 | } 89 | 90 | public void Dispose() 91 | => Interlocked.CompareExchange(ref _staticBlockedModules, _blockedModules, null); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/ModulePlacer.MaskPattern.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace QRCoder; 5 | 6 | public partial class QRCodeGenerator 7 | { 8 | private static partial class ModulePlacer 9 | { 10 | /// 11 | /// Provides static methods and properties to handle mask patterns used in QR code generation. 12 | /// Mask patterns are applied to QR codes to break up patterns in the data matrix that might confuse scanners. 13 | /// 14 | private static class MaskPattern 15 | { 16 | /// 17 | /// A dictionary mapping each mask pattern index to its corresponding function that calculates whether a given pixel should be masked. 18 | /// 19 | public static readonly List> Patterns = 20 | new List>(8) { 21 | MaskPattern.Pattern1, MaskPattern.Pattern2, MaskPattern.Pattern3, MaskPattern.Pattern4, 22 | MaskPattern.Pattern5, MaskPattern.Pattern6, MaskPattern.Pattern7, MaskPattern.Pattern8 23 | }; 24 | 25 | /// 26 | /// Mask pattern 1: (x + y) % 2 == 0 27 | /// Applies a checkerboard mask on the QR code. 28 | /// 29 | public static bool Pattern1(int x, int y) 30 | => (x + y) % 2 == 0; 31 | 32 | /// 33 | /// Mask pattern 2: y % 2 == 0 34 | /// Applies a horizontal striping mask on the QR code. 35 | /// 36 | public static bool Pattern2(int x, int y) 37 | => y % 2 == 0; 38 | 39 | /// 40 | /// Mask pattern 3: x % 3 == 0 41 | /// Applies a vertical striping mask on the QR code. 42 | /// 43 | public static bool Pattern3(int x, int y) 44 | => x % 3 == 0; 45 | 46 | /// 47 | /// Mask pattern 4: (x + y) % 3 == 0 48 | /// Applies a diagonal striping mask on the QR code. 49 | /// 50 | public static bool Pattern4(int x, int y) 51 | => (x + y) % 3 == 0; 52 | 53 | /// 54 | /// Mask pattern 5: ((y / 2) + (x / 3)) % 2 == 0 55 | /// Applies a complex pattern mask on the QR code, mixing horizontal and vertical rules. 56 | /// 57 | public static bool Pattern5(int x, int y) 58 | => ((int)(Math.Floor(y / 2d) + Math.Floor(x / 3d)) % 2) == 0; 59 | 60 | /// 61 | /// Mask pattern 6: ((x * y) % 2 + (x * y) % 3) == 0 62 | /// Applies a mask based on the product of x and y coordinates modulo 2 and 3. 63 | /// 64 | public static bool Pattern6(int x, int y) 65 | => ((x * y) % 2) + ((x * y) % 3) == 0; 66 | 67 | /// 68 | /// Mask pattern 7: (((x * y) % 2 + (x * y) % 3) % 2) == 0 69 | /// Applies a mask based on a more complex function involving the product of x and y coordinates. 70 | /// 71 | public static bool Pattern7(int x, int y) 72 | => (((x * y) % 2) + ((x * y) % 3)) % 2 == 0; 73 | 74 | /// 75 | /// Mask pattern 8: (((x + y) % 2) + ((x * y) % 3) % 2) == 0 76 | /// Combines rules of checkers and complex multiplicative masks. 77 | /// 78 | public static bool Pattern8(int x, int y) 79 | => (((x + y) % 2) + ((x * y) % 3)) % 2 == 0; 80 | 81 | /// 82 | /// Calculates a penalty score for a QR code to evaluate the effectiveness of a mask pattern. 83 | /// A lower score indicates a QR code that is easier for decoders to read accurately. 84 | /// The score is the sum of four penalty rules applied to the QR code. 85 | /// 86 | /// The QR code data structure to be evaluated. 87 | /// The total penalty score of the QR code. 88 | public static int Score(QRCodeData qrCode) 89 | { 90 | int score1 = 0, // Penalty for groups of five or more same-color modules in a row (or column) 91 | score2 = 0, // Penalty for blocks of modules in the same color 92 | score3 = 0, // Penalty for specific patterns found within the QR code 93 | score4 = 0; // Penalty for having more than 50% black modules or more than 50% white modules 94 | var size = qrCode.ModuleMatrix.Count; 95 | 96 | //Penalty 1: Checking for consecutive modules of the same color in rows and columns 97 | for (var y = 0; y < size; y++) 98 | { 99 | var modInRow = 0; 100 | var modInColumn = 0; 101 | var lastValRow = qrCode.ModuleMatrix[y][0]; 102 | var lastValColumn = qrCode.ModuleMatrix[0][y]; 103 | for (var x = 0; x < size; x++) 104 | { 105 | // Check rows for consecutive modules 106 | if (qrCode.ModuleMatrix[y][x] == lastValRow) 107 | modInRow++; 108 | else 109 | modInRow = 1; 110 | if (modInRow == 5) 111 | score1 += 3; 112 | else if (modInRow > 5) 113 | score1++; 114 | lastValRow = qrCode.ModuleMatrix[y][x]; 115 | 116 | // Check columns for consecutive modules 117 | if (qrCode.ModuleMatrix[x][y] == lastValColumn) 118 | modInColumn++; 119 | else 120 | modInColumn = 1; 121 | if (modInColumn == 5) 122 | score1 += 3; 123 | else if (modInColumn > 5) 124 | score1++; 125 | lastValColumn = qrCode.ModuleMatrix[x][y]; 126 | } 127 | } 128 | 129 | //Penalty 2: Checking for blocks of modules in the same color 130 | for (var y = 0; y < size - 1; y++) 131 | { 132 | for (var x = 0; x < size - 1; x++) 133 | { 134 | if (qrCode.ModuleMatrix[y][x] == qrCode.ModuleMatrix[y][x + 1] && 135 | qrCode.ModuleMatrix[y][x] == qrCode.ModuleMatrix[y + 1][x] && 136 | qrCode.ModuleMatrix[y][x] == qrCode.ModuleMatrix[y + 1][x + 1]) 137 | score2 += 3; 138 | } 139 | } 140 | 141 | //Penalty 3: Checking for specific patterns within the QR code (patterns that should be avoided) 142 | for (var y = 0; y < size; y++) 143 | { 144 | for (var x = 0; x < size - 10; x++) 145 | { 146 | // Horizontal pattern matching 147 | if ((qrCode.ModuleMatrix[y][x] && 148 | !qrCode.ModuleMatrix[y][x + 1] && 149 | qrCode.ModuleMatrix[y][x + 2] && 150 | qrCode.ModuleMatrix[y][x + 3] && 151 | qrCode.ModuleMatrix[y][x + 4] && 152 | !qrCode.ModuleMatrix[y][x + 5] && 153 | qrCode.ModuleMatrix[y][x + 6] && 154 | !qrCode.ModuleMatrix[y][x + 7] && 155 | !qrCode.ModuleMatrix[y][x + 8] && 156 | !qrCode.ModuleMatrix[y][x + 9] && 157 | !qrCode.ModuleMatrix[y][x + 10]) || 158 | (!qrCode.ModuleMatrix[y][x] && 159 | !qrCode.ModuleMatrix[y][x + 1] && 160 | !qrCode.ModuleMatrix[y][x + 2] && 161 | !qrCode.ModuleMatrix[y][x + 3] && 162 | qrCode.ModuleMatrix[y][x + 4] && 163 | !qrCode.ModuleMatrix[y][x + 5] && 164 | qrCode.ModuleMatrix[y][x + 6] && 165 | qrCode.ModuleMatrix[y][x + 7] && 166 | qrCode.ModuleMatrix[y][x + 8] && 167 | !qrCode.ModuleMatrix[y][x + 9] && 168 | qrCode.ModuleMatrix[y][x + 10])) 169 | { 170 | score3 += 40; 171 | } 172 | 173 | // Vertical pattern matching 174 | if ((qrCode.ModuleMatrix[x][y] && 175 | !qrCode.ModuleMatrix[x + 1][y] && 176 | qrCode.ModuleMatrix[x + 2][y] && 177 | qrCode.ModuleMatrix[x + 3][y] && 178 | qrCode.ModuleMatrix[x + 4][y] && 179 | !qrCode.ModuleMatrix[x + 5][y] && 180 | qrCode.ModuleMatrix[x + 6][y] && 181 | !qrCode.ModuleMatrix[x + 7][y] && 182 | !qrCode.ModuleMatrix[x + 8][y] && 183 | !qrCode.ModuleMatrix[x + 9][y] && 184 | !qrCode.ModuleMatrix[x + 10][y]) || 185 | (!qrCode.ModuleMatrix[x][y] && 186 | !qrCode.ModuleMatrix[x + 1][y] && 187 | !qrCode.ModuleMatrix[x + 2][y] && 188 | !qrCode.ModuleMatrix[x + 3][y] && 189 | qrCode.ModuleMatrix[x + 4][y] && 190 | !qrCode.ModuleMatrix[x + 5][y] && 191 | qrCode.ModuleMatrix[x + 6][y] && 192 | qrCode.ModuleMatrix[x + 7][y] && 193 | qrCode.ModuleMatrix[x + 8][y] && 194 | !qrCode.ModuleMatrix[x + 9][y] && 195 | qrCode.ModuleMatrix[x + 10][y])) 196 | { 197 | score3 += 40; 198 | } 199 | } 200 | } 201 | 202 | //Penalty 4: Proportions of dark and light modules 203 | int blackModules = 0; 204 | foreach (var bitArray in qrCode.ModuleMatrix) 205 | for (var x = 0; x < size; x++) 206 | if (bitArray[x]) 207 | blackModules++; 208 | 209 | var percentDiv5 = blackModules * 20 / (qrCode.ModuleMatrix.Count * qrCode.ModuleMatrix.Count); 210 | var prevMultipleOf5 = Math.Abs(percentDiv5 - 10); 211 | var nextMultipleOf5 = Math.Abs(percentDiv5 - 9); 212 | score4 = Math.Min(prevMultipleOf5, nextMultipleOf5) * 10; 213 | 214 | // Return the sum of all four penalties 215 | return (score1 + score2) + (score3 + score4); 216 | } 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/Point.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reflection; 4 | 5 | namespace QRCoder; 6 | 7 | public partial class QRCodeGenerator 8 | { 9 | /// 10 | /// Represents a 2D point with integer coordinates. 11 | /// 12 | private readonly struct Point : IEquatable 13 | { 14 | /// 15 | /// Gets the X-coordinate of the point. 16 | /// 17 | public int X { get; } 18 | 19 | /// 20 | /// Gets the Y-coordinate of the point. 21 | /// 22 | public int Y { get; } 23 | 24 | /// 25 | /// Initializes a new instance of the struct with specified X and Y coordinates. 26 | /// 27 | /// The X-coordinate of the point. 28 | /// The Y-coordinate of the point. 29 | public Point(int x, int y) 30 | { 31 | X = x; 32 | Y = y; 33 | } 34 | 35 | /// 36 | /// Determines whether the specified is equal to the current . 37 | /// 38 | /// The to compare with the current . 39 | /// True if the specified has the same X and Y coordinates as the current ; otherwise, false. 40 | /// 41 | /// If this method which implements is not implemented, comparisons used by methods such as 42 | /// fall back to reflection, which causes heap allocations internally during the calls to . 43 | /// 44 | public bool Equals(Point other) 45 | => X == other.X && Y == other.Y; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/Polynom.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Text; 5 | 6 | namespace QRCoder; 7 | 8 | public partial class QRCodeGenerator 9 | { 10 | /// 11 | /// Represents a polynomial, which is a sum of polynomial terms. 12 | /// 13 | private struct Polynom : IDisposable 14 | { 15 | private PolynomItem[] _polyItems; 16 | 17 | /// 18 | /// Initializes a new instance of the struct with a specified number of initial capacity for polynomial terms. 19 | /// 20 | /// The initial capacity of the polynomial items list. 21 | public Polynom(int count) 22 | { 23 | Count = 0; 24 | _polyItems = RentArray(count); 25 | } 26 | 27 | /// 28 | /// Adds a polynomial term to the polynomial. 29 | /// 30 | public void Add(PolynomItem item) 31 | { 32 | AssertCapacity(Count + 1); 33 | _polyItems[Count++] = item; 34 | } 35 | 36 | /// 37 | /// Removes the polynomial term at the specified index. 38 | /// 39 | public void RemoveAt(int index) 40 | { 41 | if ((uint)index >= (uint)Count) 42 | throw new IndexOutOfRangeException(); 43 | 44 | if (index < Count - 1) 45 | Array.Copy(_polyItems, index + 1, _polyItems, index, Count - index - 1); 46 | 47 | Count--; 48 | } 49 | 50 | /// 51 | /// Gets or sets a polynomial term at the specified index. 52 | /// 53 | public PolynomItem this[int index] 54 | { 55 | get 56 | { 57 | if ((uint)index >= Count) 58 | ThrowIndexOutOfRangeException(); 59 | return _polyItems[index]; 60 | } 61 | set 62 | { 63 | if ((uint)index >= Count) 64 | ThrowIndexOutOfRangeException(); 65 | _polyItems[index] = value; 66 | } 67 | } 68 | 69 | #if NET6_0_OR_GREATER 70 | [StackTraceHidden] 71 | #endif 72 | private static void ThrowIndexOutOfRangeException() => throw new IndexOutOfRangeException(); 73 | 74 | 75 | /// 76 | /// Gets the number of polynomial terms in the polynomial. 77 | /// 78 | public int Count { get; private set; } 79 | 80 | /// 81 | /// Removes all polynomial terms from the polynomial. 82 | /// 83 | public void Clear() => Count = 0; 84 | 85 | /// 86 | /// Clones the polynomial, creating a new instance with the same polynomial terms. 87 | /// 88 | public Polynom Clone() 89 | { 90 | var newPolynom = new Polynom(Count); 91 | Array.Copy(_polyItems, newPolynom._polyItems, Count); 92 | newPolynom.Count = Count; 93 | return newPolynom; 94 | } 95 | 96 | /// 97 | /// Sorts the collection of using a custom comparer function. 98 | /// 99 | /// 100 | /// A function that compares two objects and returns an integer indicating their relative order: 101 | /// less than zero if the first is less than the second, zero if they are equal, or greater than zero if the first is greater than the second. 102 | /// 103 | public void Sort(Func comparer) 104 | { 105 | if (comparer == null) 106 | throw new ArgumentNullException(nameof(comparer)); 107 | 108 | var items = _polyItems ?? throw new ObjectDisposedException(nameof(Polynom)); 109 | 110 | if (Count <= 1) 111 | { 112 | return; // Nothing to sort if the list is empty or contains only one element 113 | } 114 | 115 | void QuickSort(int left, int right) 116 | { 117 | int i = left; 118 | int j = right; 119 | var pivot = items[(left + right) / 2]; 120 | 121 | while (i <= j) 122 | { 123 | while (comparer(items[i], pivot) < 0) 124 | i++; 125 | while (comparer(items[j], pivot) > 0) 126 | j--; 127 | 128 | if (i <= j) 129 | { 130 | // Swap items[i] and items[j] 131 | var temp = items[i]; 132 | items[i] = items[j]; 133 | items[j] = temp; 134 | i++; 135 | j--; 136 | } 137 | } 138 | 139 | // Recursively sort the sub-arrays 140 | if (left < j) 141 | QuickSort(left, j); 142 | if (i < right) 143 | QuickSort(i, right); 144 | } 145 | 146 | QuickSort(0, Count - 1); 147 | } 148 | 149 | /// 150 | /// Returns a string that represents the polynomial in standard algebraic notation. 151 | /// Example output: "a^2*x^3 + a^5*x^1 + a^3*x^0", which represents the polynomial 2x³ + 5x + 3. 152 | /// 153 | public override string ToString() 154 | { 155 | var sb = new StringBuilder(); 156 | 157 | foreach (var polyItem in _polyItems) 158 | { 159 | sb.Append("a^" + polyItem.Coefficient + "*x^" + polyItem.Exponent + " + "); 160 | } 161 | 162 | // Remove the trailing " + " if the string builder has added terms 163 | if (sb.Length > 0) 164 | sb.Length -= 3; 165 | 166 | return sb.ToString(); 167 | } 168 | 169 | /// 170 | public void Dispose() 171 | { 172 | ReturnArray(_polyItems); 173 | _polyItems = null!; 174 | } 175 | 176 | /// 177 | /// Ensures that the polynomial has enough capacity to store the specified number of polynomial terms. 178 | /// 179 | private void AssertCapacity(int min) 180 | { 181 | if (_polyItems.Length < min) 182 | { 183 | // All math by QRCoder should be done with fixed polynomials, so we don't need to grow the capacity. 184 | ThrowNotSupportedException(); 185 | 186 | // Sample code for growing the capacity: 187 | //var newArray = RentArray(Math.Max(min - 1, 8) * 2); // Grow by 2x, but at least by 8 188 | //Array.Copy(_polyItems, newArray, _length); 189 | //ReturnArray(_polyItems); 190 | //_polyItems = newArray; 191 | } 192 | 193 | #if NET6_0_OR_GREATER 194 | [StackTraceHidden] 195 | #endif 196 | void ThrowNotSupportedException() => throw new NotSupportedException("The polynomial capacity is fixed and cannot be increased."); 197 | } 198 | 199 | #if NETCOREAPP 200 | /// 201 | /// Rents memory for the polynomial terms from the shared memory pool. 202 | /// 203 | private static PolynomItem[] RentArray(int count) 204 | => System.Buffers.ArrayPool.Shared.Rent(count); 205 | 206 | /// 207 | /// Returns memory allocated for the polynomial terms back to the shared memory pool. 208 | /// 209 | private static void ReturnArray(PolynomItem[] array) 210 | => System.Buffers.ArrayPool.Shared.Return(array); 211 | #else 212 | // Implement a poor-man's array pool for .NET Framework 213 | [ThreadStatic] 214 | private static List? _arrayPool; 215 | 216 | /// 217 | /// Rents memory for the polynomial terms from a shared memory pool. 218 | /// 219 | private static PolynomItem[] RentArray(int count) 220 | { 221 | if (count <= 0) 222 | ThrowArgumentOutOfRangeException(); 223 | 224 | // Search for a suitable array in the thread-local pool, if it has been initialized 225 | if (_arrayPool != null) 226 | { 227 | for (int i = 0; i < _arrayPool.Count; i++) 228 | { 229 | var array = _arrayPool[i]; 230 | if (array.Length >= count) 231 | { 232 | _arrayPool.RemoveAt(i); 233 | return array; 234 | } 235 | } 236 | } 237 | 238 | // No suitable buffer found; create a new one 239 | return new PolynomItem[count]; 240 | 241 | void ThrowArgumentOutOfRangeException() => throw new ArgumentOutOfRangeException(nameof(count), "The count must be a positive number."); 242 | } 243 | 244 | /// 245 | /// Returns memory allocated for the polynomial terms back to a shared memory pool. 246 | /// 247 | private static void ReturnArray(PolynomItem[] array) 248 | { 249 | if (array == null) 250 | return; 251 | 252 | // Initialize the thread-local pool if it's not already done 253 | _arrayPool ??= new List(8); 254 | 255 | // Add the buffer back to the pool 256 | _arrayPool.Add(array); 257 | } 258 | #endif 259 | 260 | /// 261 | /// Returns an enumerator that iterates through the polynomial terms. 262 | /// 263 | public PolynumEnumerator GetEnumerator() => new PolynumEnumerator(this); 264 | 265 | /// 266 | /// Value type enumerator for the struct. 267 | /// 268 | public struct PolynumEnumerator 269 | { 270 | private Polynom _polynom; 271 | private int _index; 272 | 273 | public PolynumEnumerator(Polynom polynom) 274 | { 275 | _polynom = polynom; 276 | _index = -1; 277 | } 278 | 279 | public PolynomItem Current => _polynom[_index]; 280 | 281 | public bool MoveNext() => ++_index < _polynom.Count; 282 | } 283 | } 284 | } 285 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/PolynomItem.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | public partial class QRCodeGenerator 4 | { 5 | /// 6 | /// Represents an individual term of a polynomial, consisting of a coefficient and an exponent. 7 | /// For example, the term 3x² would be represented as a with a coefficient of 3 and an exponent of 2. 8 | /// 9 | private struct PolynomItem 10 | { 11 | /// 12 | /// Initializes a new instance of the struct with the specified coefficient and exponent. 13 | /// 14 | /// The coefficient of the polynomial term. For example, in the term 3x², the coefficient is 3. 15 | /// The exponent of the polynomial term. For example, in the term 3x², the exponent is 2. 16 | public PolynomItem(int coefficient, int exponent) 17 | { 18 | Coefficient = coefficient; 19 | Exponent = exponent; 20 | } 21 | 22 | /// 23 | /// Gets the coefficient of the polynomial term. 24 | /// 25 | public int Coefficient { get; } 26 | 27 | /// 28 | /// Gets the exponent of the polynomial term. 29 | /// 30 | public int Exponent { get; } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/Rectangle.cs: -------------------------------------------------------------------------------- 1 | namespace QRCoder; 2 | 3 | public partial class QRCodeGenerator 4 | { 5 | /// 6 | /// Represents a rectangle defined by its top-left corner's coordinates, width, and height. 7 | /// 8 | private readonly struct Rectangle 9 | { 10 | /// 11 | /// Gets the X-coordinate of the top-left corner of the rectangle. 12 | /// 13 | public int X { get; } 14 | 15 | /// 16 | /// Gets the Y-coordinate of the top-left corner of the rectangle. 17 | /// 18 | public int Y { get; } 19 | 20 | /// 21 | /// Gets the width of the rectangle. 22 | /// 23 | public int Width { get; } 24 | 25 | /// 26 | /// Gets the height of the rectangle. 27 | /// 28 | public int Height { get; } 29 | 30 | /// 31 | /// Initializes a new instance of the struct with the specified top-left corner coordinates, width, and height. 32 | /// 33 | /// The X-coordinate of the top-left corner of the rectangle. 34 | /// The Y-coordinate of the top-left corner of the rectangle. 35 | /// The width of the rectangle. 36 | /// The height of the rectangle. 37 | public Rectangle(int x, int y, int w, int h) 38 | { 39 | X = x; 40 | Y = y; 41 | Width = w; 42 | Height = h; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/VersionInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QRCoder; 4 | 5 | public partial class QRCodeGenerator 6 | { 7 | /// 8 | /// Represents version-specific information of a QR code. 9 | /// 10 | private struct VersionInfo 11 | { 12 | /// 13 | /// Initializes a new instance of the struct with a specific version number and its details. 14 | /// 15 | /// The version number of the QR code. Each version has a different module configuration. 16 | /// A list of detailed information related to error correction levels and capacity for each encoding mode. 17 | public VersionInfo(int version, List versionInfoDetails) 18 | { 19 | Version = version; 20 | Details = versionInfoDetails; 21 | } 22 | 23 | /// 24 | /// Gets the version number of the QR code. Each version number specifies a different size of the QR matrix. 25 | /// 26 | public int Version { get; } 27 | 28 | /// 29 | /// Gets a list of details about the QR code version, including the error correction levels and encoding capacities. 30 | /// 31 | public List Details { get; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /external/QRCoder/QRCodeGenerator/VersionInfoDetails.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace QRCoder; 4 | 5 | public partial class QRCodeGenerator 6 | { 7 | /// 8 | /// Represents the detailed information about each error correction level and its corresponding capacities in different encoding modes for a specific version of a QR code. 9 | /// 10 | private struct VersionInfoDetails 11 | { 12 | /// 13 | /// Initializes a new instance of the struct, detailing the error correction level and the capacity for each encoding mode. 14 | /// 15 | /// The error correction level, which determines how much of the code can be restored if the QR code gets damaged. 16 | /// A dictionary mapping each encoding mode to its capacity for the specific error correction level. 17 | public VersionInfoDetails(ECCLevel errorCorrectionLevel, Dictionary capacityDict) 18 | { 19 | ErrorCorrectionLevel = errorCorrectionLevel; 20 | CapacityDict = capacityDict; 21 | } 22 | 23 | /// 24 | /// Gets the error correction level of the QR code, influencing how robust the QR code is against errors and damage. 25 | /// 26 | public ECCLevel ErrorCorrectionLevel { get; } 27 | 28 | /// 29 | /// Gets a dictionary that contains the capacities of different encoding modes under the specified error correction level. 30 | /// These capacities dictate how many characters can be encoded under each mode. 31 | /// 32 | public Dictionary CapacityDict { get; } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /external/QRCoder/QRCoder.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net9.0 5 | false 6 | true 7 | true 8 | $(WarningsAsErrors);CS1591 9 | enable 10 | 11 | 12 | 13 | 14 | false 15 | QRCoder 16 | 1.6.0 17 | Raffael Herrmann 18 | Raffael Herrmann 19 | QRCoder 20 | MIT 21 | c# csharp qr qrcoder qrcode qr-generator qr-code-generator 22 | git 23 | QRCoder is a simple library, written in C#.NET, which enables you to create QR codes. This version has reduced functionality and has been adapted for use in Horizon 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /images/ghreleasesbadge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/images/ghreleasesbadge.png -------------------------------------------------------------------------------- /images/msstorebadge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/images/msstorebadge.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/LargeTile.scale-100.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/LargeTile.scale-125.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/LargeTile.scale-150.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/LargeTile.scale-200.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/LargeTile.scale-400.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SmallTile.scale-100.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SmallTile.scale-125.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SmallTile.scale-150.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SmallTile.scale-200.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SmallTile.scale-400.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-100.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-125.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-150.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square150x150Logo.scale-400.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-16.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-24.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-256.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-32.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-lightunplated_targetsize-48.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-16.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-256.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-32.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.altform-unplated_targetsize-48.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-100.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-125.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-150.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.scale-400.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-16.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-24.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-256.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-32.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Square44x44Logo.targetsize-48.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-100.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-125.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-150.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/AppIcons/Wide310x150Logo.scale-400.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/FileIcons/document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/FileIcons/document.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/FileIcons/link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/FileIcons/link.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/Icons/DevSanx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/Icons/DevSanx.png -------------------------------------------------------------------------------- /package/Horizon.Package/Assets/Icons/paypal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/package/Horizon.Package/Assets/Icons/paypal.png -------------------------------------------------------------------------------- /package/Horizon.Package/Horizon.Package.wapproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15.0 5 | 6 | 7 | 8 | Debug 9 | x64 10 | 11 | 12 | Release 13 | x64 14 | 15 | 16 | Debug 17 | ARM64 18 | 19 | 20 | Release 21 | ARM64 22 | 23 | 24 | 25 | $(MSBuildExtensionsPath)\Microsoft\DesktopBridge\ 26 | 27 | 28 | 29 | b6778c81-1666-4c6a-90d2-2dffe9002500 30 | 10.0.26100.0 31 | 10.0.17763.0 32 | en-US 33 | false 34 | $(NoWarn);NU1702 35 | ..\..\src\Horizon.csproj 36 | True 37 | False 38 | SHA256 39 | False 40 | False 41 | x64|arm64 42 | 0 43 | 44 | 45 | Always 46 | 47 | 48 | Always 49 | 50 | 51 | Always 52 | 53 | 54 | Always 55 | 56 | 57 | 58 | Designer 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | PreserveNewest 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /package/Horizon.Package/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | HorizonBrowser 19 | Pinguin2001 20 | Assets\AppIcons\StoreLogo.png 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 35 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | Horizon 54 | Assets/FileIcons/link.png 55 | 56 | 57 | 58 | 59 | Horizon 60 | Assets/FileIcons/link.png 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/App.xaml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon; 2 | 3 | /// 4 | /// Provides application-specific behavior to supplement the default Application class. 5 | /// 6 | public partial class App : Application 7 | { 8 | /// 9 | /// Initializes the singleton application object. This is the first line of authored code 10 | /// executed, and as such is the logical equivalent of main() or WinMain(). 11 | /// 12 | public App() 13 | { 14 | this.InitializeComponent(); 15 | SettingsHelper.LoadSettingsOnStartup(); 16 | UnhandledException += App_UnhandledException; 17 | } 18 | 19 | private void App_UnhandledException(object sender, Microsoft.UI.Xaml.UnhandledExceptionEventArgs e) 20 | { 21 | string AppVersion = AppVersionHelper.GetAppVersion(); 22 | string WV2RuntimeVersion; 23 | try 24 | { 25 | WV2RuntimeVersion = CoreWebView2Environment.GetAvailableBrowserVersionString(); 26 | } 27 | catch 28 | { 29 | WV2RuntimeVersion = "NOT INSTALLED"; 30 | } 31 | string dotnetver = Environment.Version.ToString(); 32 | string apparch = RuntimeInformation.ProcessArchitecture.ToString(); 33 | string BRI = 34 | $"Horizon version: {AppVersion}\n" + 35 | $"WebView2Runtime version: {WV2RuntimeVersion}\n" + 36 | $"DotNetRuntime version: {dotnetver}\n" + 37 | $"Host architecture: {apparch}\n" + 38 | "\n\n" + 39 | e.Exception.Message + 40 | e.Exception.StackTrace; 41 | Win32Helper.ShowMessageBox("Horizon crash handler", $"An unhandled exception occured!\nWe prevented the app from crashing, however you should report this bug!\nBug report information (press Ctrl + C to copy):\n" + BRI); 42 | e.Handled = true; 43 | } 44 | 45 | /// 46 | /// Invoked when the application is launched. 47 | /// 48 | /// Details about the launch request and process. 49 | protected override async void OnLaunched(LaunchActivatedEventArgs args) 50 | { 51 | var appArgs = AppInstance.GetCurrent().GetActivatedEventArgs(); 52 | var mainInstance = AppInstance.FindOrRegisterForKey("HorizonSingleInstance"); 53 | 54 | // If the main instance isn't this current instance 55 | if (!mainInstance.IsCurrent) 56 | { 57 | // Redirect activation to that instance 58 | await mainInstance.RedirectActivationToAsync(appArgs); 59 | 60 | // And exit our instance and stop 61 | System.Diagnostics.Process.GetCurrentProcess().Kill(); 62 | return; 63 | } 64 | 65 | // Otherwise, register for activation redirection 66 | AppInstance.GetCurrent().Activated += App_Activated; 67 | 68 | if (SettingsHelper.GetSetting("IsAppLockEnabled") == "true") 69 | { 70 | if (await WindowsHelloHelper.CheckSec()) 71 | { 72 | WindowHelper.CreateMainWindow(); 73 | WindowHelper.ActivateMainWindow(); 74 | } 75 | else 76 | { 77 | System.Diagnostics.Process.GetCurrentProcess().Kill(); 78 | return; 79 | } 80 | } 81 | else 82 | { 83 | WindowHelper.CreateMainWindow(); 84 | WindowHelper.ActivateMainWindow(); 85 | } 86 | 87 | HandleUriActivation(appArgs); 88 | 89 | if (Environment.IsPrivilegedProcess) 90 | { 91 | Win32Helper.ShowMessageBox("Horizon - Warning", "Warning!\nThis instance of Horizon is running elevated, which isn't recommened due to possible security issues."); 92 | } 93 | } 94 | 95 | private void App_Activated(object sender, AppActivationArguments e) 96 | { 97 | HandleUriActivation(e); 98 | WindowHelper.RestoreMainWindow(); 99 | } 100 | 101 | private static void HandleUriActivation(AppActivationArguments args) 102 | { 103 | string uri = string.Empty; 104 | if (args.Data != null && args.Kind is ExtendedActivationKind.Protocol) 105 | { 106 | WAMA.IProtocolActivatedEventArgs ProtocolArgs = args.Data.As(); 107 | uri = ProtocolArgs.Uri.ToString(); 108 | } 109 | WindowHelper.CreateNewTabInMainWindow("New tab", uri); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/Controls/Tabs/Tab.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Controls.Tabs; 2 | 3 | public partial class Tab : ObservableObject 4 | { 5 | private string _title; 6 | public string Title 7 | { 8 | get => _title; 9 | set => SetProperty(ref _title, value); 10 | } 11 | 12 | /*private Uri _icon; 13 | public Uri Icon 14 | { 15 | get => _icon; 16 | set => SetProperty(ref _icon, value); 17 | }*/ 18 | 19 | private UIElement _content; 20 | public UIElement Content 21 | { 22 | get => _content; 23 | set => SetProperty(ref _content, value); 24 | } 25 | } -------------------------------------------------------------------------------- /src/Controls/Tabs/WebTabCreationParams.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Controls.Tabs; 2 | 3 | public class WebTabCreationParams 4 | { 5 | public WebTabCreationParams() { } 6 | public string LaunchURL { get; set; } 7 | public Tab myTab { get; set; } 8 | public bool IsSplitTab { get; set; } = false; 9 | } 10 | -------------------------------------------------------------------------------- /src/Core/AppVersionHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public static class AppVersionHelper 4 | { 5 | public static string GetAppVersion() 6 | { 7 | WAM.Package package = WAM.Package.Current; 8 | WAM.PackageId packageId = package.Id; 9 | WAM.PackageVersion version = packageId.Version; 10 | 11 | return string.Format("{0}.{1}.{2}", version.Major, version.Minor, version.Build); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Core/Backdrops.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public static class Backdrops 4 | { 5 | public static readonly string[] BackdropsList = new string[] { 6 | "Acrylic", 7 | "Mica", 8 | "Mica Alt", 9 | }; 10 | } -------------------------------------------------------------------------------- /src/Core/ClipboardHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public static class ClipboardHelper 4 | { 5 | public static void CopyTextToClipboard(string text) 6 | { 7 | DataPackage package = new(); 8 | package.SetText(text); 9 | Clipboard.SetContent(package); 10 | } 11 | 12 | public static async Task PasteUriAsStringFromClipboardAsync() 13 | { 14 | var package = Clipboard.GetContent(); 15 | if (package.Contains(StandardDataFormats.Text)) 16 | { 17 | var text = await package.GetTextAsync(); 18 | return text.ToString(); 19 | } 20 | return string.Empty; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Core/FileHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public class FileHelper 4 | { 5 | public static async Task SaveBytesAsFileAsync(string fileName, byte[] buffer, string filetypefriendlyname, string filetype) => await SaveFileAsync(fileName, filetypefriendlyname, filetype, buffer, null); 6 | 7 | public static async Task SaveStringAsFileAsync(string fileName, string fileContent, string filetypefriendlyname, string filetype) => await SaveFileAsync(fileName, filetypefriendlyname, filetype, null, fileContent); 8 | 9 | private static async Task SaveFileAsync(string fileName, string filetypefriendlyname, string filetype, byte[] BytesFileContent = null, string TextFileContent = null) 10 | { 11 | // Create a file picker 12 | FileSavePicker savePicker = new() 13 | { 14 | // Set options for your file picker 15 | SuggestedStartLocation = PickerLocationId.DocumentsLibrary 16 | }; 17 | 18 | // See the sample code below for how to make the window accessible from the App class. 19 | var window = WindowHelper.MainWindow; 20 | 21 | // Retrieve the window handle (HWND) of the current WinUI 3 window. 22 | var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(window); 23 | 24 | // Initialize the file picker with the window handle (HWND). 25 | WinRT.Interop.InitializeWithWindow.Initialize(savePicker, hWnd); 26 | 27 | 28 | // Dropdown of file types the user can save the file as 29 | savePicker.FileTypeChoices.Add(filetypefriendlyname, new List() { filetype }); 30 | // Default file name if the user does not type one in or select a file to replace 31 | savePicker.SuggestedFileName = fileName; 32 | 33 | // Open the picker for the user to pick a file 34 | StorageFile file = await savePicker.PickSaveFileAsync(); 35 | if (file != null) 36 | { 37 | // Prevent updates to the remote version of the file until we finish making changes and call CompleteUpdatesAsync. 38 | CachedFileManager.DeferUpdates(file); 39 | 40 | // write to file 41 | // depending on which type we either write bytes or text 42 | if (BytesFileContent != null) 43 | { 44 | await FileIO.WriteBytesAsync(file, BytesFileContent); 45 | } 46 | if (TextFileContent != null) 47 | { 48 | await FileIO.WriteTextAsync(file, TextFileContent); 49 | } 50 | 51 | // Let Windows know that we're finished changing the file so the other app can update the remote version of the file. 52 | // Completing updates may require Windows to ask for user input. 53 | FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file); 54 | if (status == FileUpdateStatus.Complete) 55 | { 56 | //NotificationHelper.NotifyUser("Success", "File " + file.Name + " was saved to\n" + file.Path); 57 | } 58 | else 59 | { 60 | //await UI.ShowDialog("Error", "File " + file.Name + " couldn't be saved."); 61 | } 62 | } 63 | } 64 | 65 | public static async Task DeleteLocalFile(string fileName) 66 | { 67 | var file = await ApplicationData.Current.LocalFolder.TryGetItemAsync(fileName); 68 | if (file != null) 69 | await file.DeleteAsync(); 70 | } 71 | } -------------------------------------------------------------------------------- /src/Core/FolderHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core 2 | { 3 | internal static class FolderHelper 4 | { 5 | public static StorageFolder localFolder = ApplicationData.Current.LocalFolder; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/Core/IconHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public static class IconHelper 4 | { 5 | public static IconSource ConvFavURLToIconSource(string url) 6 | { 7 | try 8 | { 9 | System.Uri faviconUrl = new(url); 10 | BitmapIconSource iconsource = new() { UriSource = faviconUrl, ShowAsMonochrome = false }; 11 | return iconsource; 12 | } 13 | catch 14 | { 15 | IconSource iconsource = new SymbolIconSource() { Symbol = Symbol.Document }; 16 | return iconsource; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/Core/ModernAboutBlank.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | internal static class ModernAboutBlank 4 | { 5 | public static string MinifiedModernBlackPageHTML = ""; 6 | } -------------------------------------------------------------------------------- /src/Core/SearchEngine.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public class SearchEngine(string EngineFriendlyName, string SearchUrl) 4 | { 5 | public string EngineFriendlyName { get; set; } = EngineFriendlyName; 6 | public string SearchUrl { get; set; } = SearchUrl; 7 | } -------------------------------------------------------------------------------- /src/Core/SearchEngineHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public class SearchEngineHelper 4 | { 5 | public static void SetSearchEngine(SearchEngine engine) 6 | { 7 | SettingsHelper.SetSetting("EngineFriendlyName", engine.EngineFriendlyName); 8 | SettingsHelper.SetSetting("SearchUrl", engine.SearchUrl); 9 | SettingsHelper.CurrentSearchUrl = engine.SearchUrl; 10 | return; 11 | } 12 | 13 | public static IReadOnlyList SearchEngines = new SearchEngine[] 14 | { 15 | new("Ask", "https://www.ask.com/web?q="), 16 | new("Baidu", "https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd="), 17 | new("Bing", "https://www.bing.com?q="), 18 | new("Brave Search", "https://search.brave.com/search?q="), 19 | new("DuckDuckGo", "https://www.duckduckgo.com?q="), 20 | new("Ecosia", "https://www.ecosia.org/search?q="), 21 | new("Google", "https://www.google.com/search?q="), 22 | new("Kagi", "https://kagi.com/search?q="), 23 | new("Qwant", "https://www.qwant.com/?q="), 24 | new("Startpage", "https://www.startpage.com/search?q="), 25 | new("Unduck", "https://unduck.link?q="), 26 | new("Yahoo!", "https://search.yahoo.com/search?p="), 27 | new("Yandex", "https://yandex.com/search/?text=") 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/Core/SettingsHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public static class SettingsHelper 4 | { 5 | private static readonly ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; 6 | 7 | public static string GetSetting(string Setting) 8 | { 9 | string SettingValue = localSettings.Values[Setting] as string; 10 | return SettingValue; 11 | } 12 | 13 | public static void SetSetting(string Setting, string SettingValue) 14 | { 15 | localSettings.Values[Setting] = SettingValue; 16 | } 17 | 18 | public static void LoadSettingsOnStartup() 19 | { 20 | CurrentSearchUrl = GetSetting("SearchUrl") ?? DefaultSearchUrl; 21 | CurrentBackdrop = GetSetting("OverrideBackdropType") ?? DefaultBackdrop; 22 | } 23 | 24 | // Settings 25 | public static readonly string DefaultSearchUrl = "https://www.duckduckgo.com?q="; 26 | public static readonly string DefaultBackdrop = "Mica"; 27 | 28 | public static string CurrentSearchUrl { get; set; } 29 | public static string CurrentBackdrop { get; set; } 30 | } 31 | -------------------------------------------------------------------------------- /src/Core/UrlHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public static partial class UrlHelper 4 | { 5 | private static readonly Regex UrlMatch = UrlRegex(); 6 | private static readonly Regex IPMatch = IPRegex(); 7 | public static string GetInputType(string input) 8 | { 9 | string type; 10 | 11 | if (input.StartsWith("http://") || input.StartsWith("https://") || input.StartsWith("edge://")) 12 | { 13 | type = "url"; 14 | } 15 | else if (UrlMatch.IsMatch(input) || IPMatch.IsMatch(input)) 16 | { 17 | type = "urlNOProtocol"; 18 | } 19 | else 20 | { 21 | type = "searchquery"; 22 | } 23 | return type; 24 | } 25 | 26 | [GeneratedRegex("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(?::([0-9]{1,5}))?$", RegexOptions.Singleline)] 27 | private static partial Regex IPRegex(); 28 | [GeneratedRegex(@"^(http(s)?:\/\/)?(www.)?([a-zA-Z0-9])+([\-\.]{1}[a-zA-Z0-9]+)*\.[a-zA-Z]{2,63}(:[0-9]{1,5})?(\/[^\s]*)?$", RegexOptions.Singleline)] 29 | private static partial Regex UrlRegex(); 30 | } -------------------------------------------------------------------------------- /src/Core/WebView2ProfileHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | public static class WebView2ProfileHelper 4 | { 5 | public static async Task ClearAllProfileDataAsync(WebView2 wv2) 6 | { 7 | CoreWebView2Profile profile = wv2.CoreWebView2.Profile; 8 | await profile.ClearBrowsingDataAsync(); 9 | await FileHelper.DeleteLocalFile("Favorites.json"); 10 | SettingsViewModel.SettingsVM.FavoritesList.Clear(); 11 | } 12 | } -------------------------------------------------------------------------------- /src/Core/Win32Helper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | /// 4 | /// A helper class for Win32 api calls which have not yet been migrated to CsWin32 5 | /// 6 | internal class Win32Helper 7 | { 8 | [DllImport("user32.dll", CharSet = CharSet.Unicode)] 9 | static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type); 10 | 11 | public static void ShowMessageBox(string title, string message, IntPtr hwnd = 0) 12 | { 13 | MessageBox(hwnd, message, title, 0); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Core/WindowHelper.cs: -------------------------------------------------------------------------------- 1 | #nullable enable 2 | // This is fine here, there is no scenario where these should lead to a crash 3 | // at least that's what I hope lmao 4 | #pragma warning disable CS8618 5 | 6 | namespace Horizon.Core; 7 | 8 | /// 9 | /// A common helper for Window operations 10 | /// It allows for easy creation of new windows, modifing, accessing and closing them 11 | /// 12 | public static class WindowHelper 13 | { 14 | public static void SetFullScreen(bool fs) 15 | { 16 | switch (fs) 17 | { 18 | case true: 19 | MainAppWindow.SetPresenter(AppWindowPresenterKind.FullScreen); 20 | _ = MainWindow.DispatcherQueue.TryEnqueue(() => 21 | { 22 | MainWindow.TabContentPresenter.Margin = new Thickness(-42, -34, -192, -7); 23 | MainWindow.Sidebar.Visibility = Visibility.Collapsed; 24 | }); 25 | break; 26 | case false: 27 | MainAppWindow.SetPresenter(AppWindowPresenterKind.Default); 28 | _ = MainWindow.DispatcherQueue.TryEnqueue(() => 29 | { 30 | MainWindow.TabContentPresenter.Margin = new Thickness(0); 31 | MainWindow.Sidebar.Visibility = Visibility.Visible; 32 | }); 33 | break; 34 | } 35 | } 36 | 37 | public static bool IsWindowInFullScreen() 38 | { 39 | if (MainAppWindow.Presenter.Kind == AppWindowPresenterKind.FullScreen) 40 | return true; 41 | else 42 | return false; 43 | } 44 | 45 | static public void CreateMainWindow() 46 | { 47 | MainWindow = new(); 48 | MainAppWindow = MainWindow.AppWindow; 49 | MainWindow.Title = "Horizon"; 50 | MainWindow.ExtendsContentIntoTitleBar = true; 51 | SetMinWindowSize(); 52 | string Backdrop = SettingsHelper.GetSetting("OverrideBackdropType"); 53 | switch (Backdrop) 54 | { 55 | case "Acrylic": 56 | MainWindow.SystemBackdrop = new DesktopAcrylicBackdrop(); 57 | break; 58 | case "Mica Alt": 59 | MainWindow.SystemBackdrop = new MicaBackdrop 60 | { 61 | Kind = Microsoft.UI.Composition.SystemBackdrops.MicaKind.BaseAlt 62 | }; 63 | break; 64 | default: 65 | MainWindow.SystemBackdrop = new MicaBackdrop(); 66 | break; 67 | } 68 | MainWindow.SetTitleBar(MainWindow.TitleBarControl); 69 | if (SettingsHelper.GetSetting("IsScreencaptureBlocked") == "true") 70 | { 71 | BlockScreencaptureForMainWindow(true); 72 | } 73 | if (SettingsHelper.GetSetting("IsAlwaysOnTopEnabled") == "true") 74 | { 75 | SetMainWindowAlwaysOnTop(true); 76 | } 77 | } 78 | 79 | static public void ActivateMainWindow() 80 | { 81 | MainWindow.Activate(); 82 | } 83 | 84 | static public void RestoreMainWindow() 85 | { 86 | if (MainAppWindow.Presenter is OverlappedPresenter presenter) 87 | { 88 | presenter.Restore(); 89 | } 90 | } 91 | 92 | static public void CloseMainWindow() 93 | { 94 | MainWindow.Close(); 95 | } 96 | 97 | static public void CreateNewTabInMainWindow(string title, string uri) 98 | { 99 | _ = MainWindow.DispatcherQueue.TryEnqueue(() => 100 | { 101 | MainWindow.CreateWebTab(title, uri); 102 | }); 103 | } 104 | 105 | static public void CreateNativeTabInMainWindow(string title, Type page) 106 | { 107 | _ = MainWindow.DispatcherQueue.TryEnqueue(() => 108 | { 109 | MainWindow.CreateTab(title, page); 110 | }); 111 | } 112 | 113 | static public void SetMinWindowSize() 114 | { 115 | if (MainAppWindow.Presenter is OverlappedPresenter presenter) 116 | { 117 | presenter.PreferredMinimumWidth = 800; 118 | presenter.PreferredMinimumHeight = 500; 119 | } 120 | } 121 | 122 | static public void BlockScreencaptureForMainWindow(bool b) 123 | { 124 | var hwnd = (Windows.Win32.Foundation.HWND)WinRT.Interop.WindowNative.GetWindowHandle(MainWindow); 125 | switch (b) 126 | { 127 | case true: 128 | Windows.Win32.PInvoke.SetWindowDisplayAffinity(hwnd, WINDOW_DISPLAY_AFFINITY.WDA_MONITOR); 129 | break; 130 | case false: 131 | Windows.Win32.PInvoke.SetWindowDisplayAffinity(hwnd, WINDOW_DISPLAY_AFFINITY.WDA_NONE); 132 | break; 133 | } 134 | } 135 | 136 | static public void SetMainWindowAlwaysOnTop(bool t) 137 | { 138 | if (MainAppWindow.Presenter is OverlappedPresenter presenter) 139 | { 140 | presenter.IsAlwaysOnTop = t; 141 | } 142 | } 143 | 144 | public static WindowChrome MainWindow { get; set; } 145 | public static AppWindow MainAppWindow { get; private set; } 146 | } 147 | -------------------------------------------------------------------------------- /src/Core/WindowsHelloHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Core; 2 | 3 | /// 4 | /// A helper class for common Windows Hello functionality 5 | /// 6 | public class WindowsHelloHelper 7 | { 8 | /// 9 | /// Performs an authentication using Windows Hello 10 | /// 11 | /// If the authentication has been successful 12 | public static async Task CheckSec() 13 | { 14 | if (await CheckAvailability() == UserConsentVerifierAvailability.Available) 15 | { 16 | UserConsentVerificationResult consent = await UserConsentVerifier.RequestVerificationAsync(string.Empty); 17 | if (consent == UserConsentVerificationResult.Verified) 18 | { 19 | return true; 20 | } 21 | return false; 22 | } 23 | return true; 24 | } 25 | 26 | /// 27 | /// Checks if Windows Hello is currently available 28 | /// 29 | /// A UserConsentVerifierAvailability value that describes the result of the availability check operation. 30 | public static async Task CheckAvailability() 31 | { 32 | UserConsentVerifierAvailability availability = await UserConsentVerifier.CheckAvailabilityAsync(); 33 | return availability; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | global using CommunityToolkit.Mvvm.ComponentModel; 2 | global using CommunityToolkit.WinUI.Controls; 3 | global using Horizon.Controls.Tabs; 4 | global using Horizon.Core; 5 | global using Horizon.Modules.Favorites; 6 | global using Horizon.Pages; 7 | global using Horizon.ViewModels; 8 | global using Microsoft.UI.Windowing; 9 | global using Microsoft.UI.Xaml; 10 | global using Microsoft.UI.Xaml.Controls; 11 | global using Microsoft.UI.Xaml.Controls.Primitives; 12 | global using Microsoft.UI.Xaml.Input; 13 | global using Microsoft.UI.Xaml.Media; 14 | global using Microsoft.UI.Xaml.Media.Animation; 15 | global using Microsoft.UI.Xaml.Media.Imaging; 16 | global using Microsoft.UI.Xaml.Navigation; 17 | global using Microsoft.Web.WebView2.Core; 18 | global using Microsoft.Windows.AppLifecycle; 19 | global using QRCoder; 20 | global using System; 21 | global using System.Collections.Generic; 22 | global using System.Collections.ObjectModel; 23 | global using System.Runtime.InteropServices; 24 | global using System.Text.Json; 25 | global using System.Text.Json.Serialization; 26 | global using System.Text.RegularExpressions; 27 | global using System.Threading.Tasks; 28 | global using WAM = Windows.ApplicationModel; 29 | global using WAMA = Windows.ApplicationModel.Activation; 30 | global using Windows.ApplicationModel.DataTransfer; 31 | global using Windows.Security.Credentials.UI; 32 | global using Windows.Storage; 33 | global using Windows.Storage.Pickers; 34 | global using Windows.Storage.Provider; 35 | global using Windows.Storage.Streams; 36 | global using WS = Windows.System; 37 | global using Windows.Win32.UI.WindowsAndMessaging; 38 | global using WinRT; -------------------------------------------------------------------------------- /src/Horizon.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | WinExe 4 | net9.0-windows10.0.26100.0 5 | 10.0.17763.0 6 | Horizon 7 | app.manifest 8 | x64;ARM64 9 | win-x86;win-x64;win-arm64 10 | win-$(Platform).pubxml 11 | true 12 | Horizon.ico 13 | true 14 | true 15 | true 16 | Speed 17 | true 18 | true 19 | preview 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | all 30 | runtime; build; native; contentfiles; analyzers; buildtransitive 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | MSBuild:Compile 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/Horizon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horizon-developers/browser/7ee7950aa726389f85c2fb4c14a3753aad341a44/src/Horizon.ico -------------------------------------------------------------------------------- /src/Modules/Favorites/FavoriteItem.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Modules.Favorites; 2 | 3 | [JsonSerializable(typeof(ObservableCollection))] 4 | public partial class FavoriteItemSerializerContext : JsonSerializerContext 5 | { 6 | } 7 | 8 | public class FavoriteItem 9 | { 10 | public string Title { get; set; } 11 | public string Url { get; set; } 12 | } 13 | -------------------------------------------------------------------------------- /src/Modules/Favorites/FavoritesHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Modules.Favorites; 2 | 3 | public class FavoritesHelper 4 | { 5 | public static StorageFolder localFolder = ApplicationData.Current.LocalFolder; 6 | 7 | public static async void LoadFavoritesOnStartup() 8 | { 9 | SettingsViewModel.SettingsVM.FavoritesList = await GetFavoritesListAsync(); 10 | } 11 | 12 | public static async void CreateFirstFavorite(string title, string url) 13 | { 14 | // Generate json 15 | string json = "[{\"Title\":\"" + title + "\"," + "\"Url\":\"" + url + "\"}]"; 16 | // create json file 17 | var file = await localFolder.CreateFileAsync("Favorites.json", CreationCollisionOption.ReplaceExisting); 18 | // write json to json file 19 | await FileIO.WriteTextAsync(file, json); 20 | // new historyitem 21 | FavoriteItem newFavoriteItem = new() 22 | { 23 | Title = title, 24 | Url = url 25 | }; 26 | // add item to favorites list 27 | SettingsViewModel.SettingsVM.FavoritesList.Insert(0, newFavoriteItem); 28 | } 29 | 30 | public static async void AddFavorite(string title, string url) 31 | { 32 | var fileData = await localFolder.TryGetItemAsync("Favorites.json"); 33 | if (fileData == null) CreateFirstFavorite(title, url); 34 | else 35 | { 36 | // new historyitem 37 | FavoriteItem newFavoriteItem = new() 38 | { 39 | Title = title, 40 | Url = url 41 | }; 42 | // add item to favorites list 43 | SettingsViewModel.SettingsVM.FavoritesList.Insert(0, newFavoriteItem); 44 | SaveListChangesToDisk(); 45 | } 46 | } 47 | 48 | public static void RemoveFavorite(FavoriteItem item) 49 | { 50 | SettingsViewModel.SettingsVM.FavoritesList.Remove(item); 51 | SaveListChangesToDisk(); 52 | } 53 | 54 | public static async Task> GetFavoritesListAsync() 55 | { 56 | var fileData = await localFolder.TryGetItemAsync("Favorites.json"); 57 | if (fileData == null) 58 | { 59 | ObservableCollection placeholderItems = []; 60 | return placeholderItems; 61 | } 62 | else 63 | { 64 | System.Diagnostics.Debug.WriteLine("LOADED FAVORITES"); 65 | string filecontent = await FileIO.ReadTextAsync((IStorageFile)fileData); 66 | ObservableCollection Items = JsonSerializer.Deserialize(filecontent, FavoriteItemSerializerContext.Default.ObservableCollectionFavoriteItem); 67 | foreach (FavoriteItem item in Items) 68 | { 69 | System.Diagnostics.Debug.WriteLine(item.Url); 70 | } 71 | return Items; 72 | } 73 | } 74 | 75 | private static async void SaveListChangesToDisk() 76 | { 77 | var fileData = await localFolder.GetFileAsync("Favorites.json"); 78 | if (SettingsViewModel.SettingsVM.FavoritesList.Count < 1) 79 | { 80 | await fileData.DeleteAsync(); 81 | } 82 | else 83 | { 84 | // Convert list to json 85 | string newJson = JsonSerializer.Serialize(SettingsViewModel.SettingsVM.FavoritesList, FavoriteItemSerializerContext.Default.ObservableCollectionFavoriteItem); 86 | // Write json to json file 87 | await FileIO.WriteTextAsync(fileData, newJson); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Modules/QRCodeGen/QRCodeHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Modules.QRCodeGen; 2 | 3 | public static class QRCodeHelper 4 | { 5 | public static readonly QRCodeGenerator SingletonQrGenerator = new(); 6 | public static Task GenerateQRCodeFromUrlAsync(string url) 7 | { 8 | try 9 | { 10 | //Create raw qr code data 11 | 12 | QRCodeData qrCodeData = SingletonQrGenerator.CreateQrCode(url, QRCodeGenerator.ECCLevel.M); 13 | 14 | //Create byte/raw bitmap qr code 15 | BitmapByteQRCode qrCodeBmp = new(qrCodeData); 16 | 17 | return Task.FromResult(qrCodeBmp.GetGraphic(20)); 18 | } 19 | catch 20 | { 21 | return null; 22 | } 23 | } 24 | 25 | public static async Task ConvertBitmapBytesToImage(byte[] bytes) 26 | { 27 | var image = new BitmapImage(); 28 | using (InMemoryRandomAccessStream stream = new()) 29 | { 30 | using (DataWriter writer = new(stream.GetOutputStreamAt(0))) 31 | { 32 | writer.WriteBytes(bytes); 33 | await writer.StoreAsync(); 34 | } 35 | await image.SetSourceAsync(stream); 36 | } 37 | return image; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Modules/Readability/ReadabilityHelper.cs: -------------------------------------------------------------------------------- 1 | namespace Horizon.Modules.Readability; 2 | 3 | public class ReadabilityHelper 4 | { 5 | public static string JScript { private set; get; } 6 | 7 | public static async Task GetReadabilityScriptAsync() 8 | { 9 | if (JScript == null) 10 | { 11 | StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/JS/readability.js")); 12 | JScript = await FileIO.ReadTextAsync(file); 13 | } 14 | return JScript; 15 | } 16 | } -------------------------------------------------------------------------------- /src/NativeMethods.txt: -------------------------------------------------------------------------------- 1 | SetWindowDisplayAffinity -------------------------------------------------------------------------------- /src/Pages/ExtensionsPage.xaml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 22 | 23 | 28 | 34 | 35 | 36 | 40 |