Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
1
third-party/vendor/orbclient/.cargo-checksum.json
vendored
Normal file
1
third-party/vendor/orbclient/.cargo-checksum.json
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"files":{"CHANGELOG.md":"6908aec25684b4e9f568234c37a5ee0fc93fcff6bb1ab9139b1c3a41fc7d8cdc","Cargo.lock":"cfa44773f90d5545dc486e2060ed5b05478c2a130c90ba5ea8acdac12f6dbfdd","Cargo.toml":"c970efb3408aa4d2e612282db11601e0c50cd1b06c1fb86adbcb7857dd890483","LICENSE":"3d3568e12e4408beb59fe51fd3265faa1fa7d2299f3064502a63e80ce208ca63","README.md":"2185df9d718141547a641ff6eb2c2680bd4d024fcf4523c3aa346f1f96249cea","build.rs":"9546b9f7fba07d603293b0f009f951ebff1a66ea2babc050145b893c35778d6a","examples/image_bench.rs":"d539811f348b3c41c56c95e94c163f4cd59c10e592670919a222f8604aef4efc","examples/rect_bench.rs":"6d59796e798c1daa6e260f83039d1595f6231ce636c19a43da7b582b02eb5aec","examples/simple.rs":"7937cbbeebc8c5f7bb24ac02440127958a321e1d56c3c089e184097689b0c199","res/unifont-license.txt":"95d93c1634f6982250d51940ff5c81b93a657c295b5c24dfa4214a13c6100495","res/unifont.font":"5aafb8bc638ec2abce5cd5970fd9145ae4b454ef2276a7d18d4915965b5b7ec8","res/unifont.hex":"099d8f0c6027ed1effa4a452a5c0874a012a6ee3ab5b1cd346aa3fbeb3368fda","res/unifont.rs":"5b9605aad29f9aef41b999c20815c120256c06318c7536dbe0befff15ea18147","rustfmt.toml":"c8b7f6a73f6d54a0f4ecf6b67a202490067d515684034d0e3ce4f45eec6d7227","src/blur.rs":"ac0cc6d661b120d740d2e8c955ba7a9d5190babe99f453055cc85ef496542445","src/color.rs":"593e73f79c55abaed50ad3b6bbbe95e25d851e5e67d538f2315bc55d0b68c66e","src/event.rs":"e23ef1f5f230f168f98c564b1eb13d02cf6ccead28fc10f2df42e7647ea0263f","src/graphicspath.rs":"2274758baeb3e57f12a83f2df829f56c91c8595f4b83a04847a94624e3cd668c","src/lib.rs":"3568d0850b77ef2e8ec0bb9aea13b3a9c19aa0fe81f262920410368142cd2e13","src/renderer.rs":"cf73bb9ff118da7f638e5ac9ce712ab05309ca2c5bea570e87d024a45e6eaa37","src/sys/orbital.rs":"0f32e660407d13f409da6a9d65eb4f0abc63e8c1bd6cb2d6d1e0a586836a262c","src/sys/sdl2.rs":"0932779a6ec3294a18dbd56cc444b334079aaa3d834271326b71bf4a7f6af4c3"},"package":"52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166"}
|
||||
42
third-party/vendor/orbclient/CHANGELOG.md
vendored
Normal file
42
third-party/vendor/orbclient/CHANGELOG.md
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## unreleased
|
||||
|
||||
* Replaced `no_std` feature with `std` feature, selected by default
|
||||
* `no_std` environments are now built by setting `default-features = false`
|
||||
* Added new `sdl` feature for building SDL2 without bundling
|
||||
* Included by `bundled`, so only one or the other needs to be selected
|
||||
|
||||
## 0.3.35
|
||||
|
||||
* Better fix for macOS builds
|
||||
|
||||
## 0.3.34
|
||||
|
||||
* Pin SDL2 for macOS compatibility
|
||||
|
||||
## 0.3.33
|
||||
|
||||
* Support multi-character SDL text input
|
||||
|
||||
## 0.3.32
|
||||
|
||||
* Change Rust edition from 2015 to 2018
|
||||
* Change `Color` from `repr(packed)` to `repr(transparent)`
|
||||
* Fix compiling against wayland > 1.20.0
|
||||
|
||||
## 0.3.31
|
||||
|
||||
* Web support
|
||||
|
||||
## 0.3.28
|
||||
|
||||
* Add sdl2 bundled and static feature
|
||||
* Add HiDPi support for sdl2 sys
|
||||
* Add DropEvent (file | text) for sdl2 sys
|
||||
* Add raw-window-handle implementation for sdl2
|
||||
* Add TextInputEvent
|
||||
255
third-party/vendor/orbclient/Cargo.lock
generated
vendored
Normal file
255
third-party/vendor/orbclient/Cargo.lock
generated
vendored
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
|
||||
dependencies = [
|
||||
"bitflags 2.4.1",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||
|
||||
[[package]]
|
||||
name = "orbclient"
|
||||
version = "0.3.47"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libredox",
|
||||
"raw-window-handle",
|
||||
"sdl2",
|
||||
"sdl2-sys",
|
||||
"serde_derive",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sdl2"
|
||||
version = "0.35.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7959277b623f1fb9e04aea73686c3ca52f01b2145f8ea16f4ff30d8b7623b1a"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"sdl2-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sdl2-sys"
|
||||
version = "0.35.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3586be2cf6c0a8099a79a12b4084357aa9b3e0b0d7980e3b67aaf7a9d55f9f0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cmake",
|
||||
"libc",
|
||||
"version-compare",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.190"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.19.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "version-compare"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "579a42fc0b8e0c63b76519a339be31bed574929511fa53c1a3acae26eb258f29"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
76
third-party/vendor/orbclient/Cargo.toml
vendored
Normal file
76
third-party/vendor/orbclient/Cargo.toml
vendored
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
||||
#
|
||||
# When uploading crates to the registry Cargo will automatically
|
||||
# "normalize" Cargo.toml files for maximal compatibility
|
||||
# with all versions of Cargo and also rewrite `path` dependencies
|
||||
# to registry (e.g., crates.io) dependencies.
|
||||
#
|
||||
# If you are reading this file be aware that the original Cargo.toml
|
||||
# will likely look very different (and much more reasonable).
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "orbclient"
|
||||
version = "0.3.47"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
description = "The Orbital Client Library"
|
||||
documentation = "https://docs.rs/orbclient"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"orbital",
|
||||
"redox",
|
||||
"ui",
|
||||
]
|
||||
license = "MIT"
|
||||
repository = "https://gitlab.redox-os.org/redox-os/orbclient"
|
||||
|
||||
[lib]
|
||||
name = "orbclient"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[dev-dependencies.serde_derive]
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.toml]
|
||||
version = "0.7"
|
||||
|
||||
[features]
|
||||
bundled = [
|
||||
"sdl",
|
||||
"sdl2/bundled",
|
||||
"sdl2/static-link",
|
||||
"sdl2-sys/bundled",
|
||||
"sdl2-sys/static-link",
|
||||
]
|
||||
default = [
|
||||
"std",
|
||||
"sdl",
|
||||
"unifont",
|
||||
]
|
||||
sdl = [
|
||||
"sdl2",
|
||||
"sdl2-sys",
|
||||
"libc",
|
||||
]
|
||||
std = []
|
||||
unifont = []
|
||||
|
||||
[target."cfg(not(target_os = \"redox\"))".dependencies.libc]
|
||||
version = "0.2"
|
||||
optional = true
|
||||
|
||||
[target."cfg(not(target_os = \"redox\"))".dependencies.raw-window-handle]
|
||||
version = "0.5.2"
|
||||
optional = true
|
||||
|
||||
[target."cfg(not(target_os = \"redox\"))".dependencies.sdl2]
|
||||
version = "0.35.2"
|
||||
optional = true
|
||||
|
||||
[target."cfg(not(target_os = \"redox\"))".dependencies.sdl2-sys]
|
||||
version = "0.35.2"
|
||||
optional = true
|
||||
|
||||
[target."cfg(target_os = \"redox\")".dependencies.libredox]
|
||||
version = "0.0.2"
|
||||
21
third-party/vendor/orbclient/LICENSE
vendored
Normal file
21
third-party/vendor/orbclient/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015-2019 Jeremy Soller
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
42
third-party/vendor/orbclient/README.md
vendored
Normal file
42
third-party/vendor/orbclient/README.md
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# orbclient
|
||||
The Orbital Client Library. Compatible with Redox and SDL2 (on Linux and Macos).
|
||||
|
||||
[](https://gitlab.redox-os.org/redox-os/orbclient/pipelines)
|
||||
[](./LICENSE)
|
||||
[](https://crates.io/crates/orbclient)
|
||||
[](https://docs.rs/orbclient)
|
||||
|
||||
## Dependencies
|
||||
If you are *NOT* using the "bundled" feature (which is off by default) then you need SDL (sdl2)
|
||||
installed on your system.
|
||||
|
||||
### macos
|
||||
On macos you can install the SDL2 library using `brew install sdl2`
|
||||
|
||||
## Features
|
||||
The `"serde"`feature can be used to include code for `Color` deserialization using the `serde` crate (which is an
|
||||
optional dependency). This is not enabled by default. To enable, either build using the `--features "serde"` command
|
||||
line option, or use `features = ["serde"]` in your crate, where it declares a dependency on orbclient.
|
||||
|
||||
The `std` feature is used to allow building `orbclient` with our without rust `std`.
|
||||
This is to enable use by some UEFI apps (e.g. System76 firmware setup, System76 firmware updater) that don't have `std`.
|
||||
|
||||
The `"unifont` feature (on by default is used to include the "unifont" font).
|
||||
|
||||
The `bundled` feature removes the need to have SDL2 installed locally. The SDL library is compiled from source
|
||||
as part of the crate build and bundled with it.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
* Make sure that you work with the current ```nightly``` version of Rust
|
||||
* To make sure of that, please use [rustup](https://github.com/rust-lang-nursery/rustup.rs)
|
||||
* Don't forget to override your work directory with ```rustup override set nightly```
|
||||
* Don't forget to update the ```nightly``` version of Rust with ```rustup update nightly```
|
||||
* SDL2 should be automatically with orbclient if you have trouble try to install it ```libsdl2-dev``` manually
|
||||
* For example, with Ubuntu, please to type ```sudo apt-get install libsdl2-dev``` in your console
|
||||
* On fedora please type ```sudo dnf install SDL2-devel SDL2-static``` in your console before building.
|
||||
* if during building, this message comes up ```could not find native static library `SDL2main`, perhaps an -L flag is missing?```.
|
||||
Providing the path to the static library might help. You can provide this path via ```RUSTFLAGS='-L <path-to-folder-with-libSDL2.a>' cargo b ...```.
|
||||
At the moment of writing, the SDL2 library is stored under **/usr/lib64** on fedora. In this case you would type ```RUSTFLAGS='-L /usr/lib64' cargo r --example simple```
|
||||
to start the simple example.
|
||||
* Other problem? Do not hesitate to create a new issue!
|
||||
5
third-party/vendor/orbclient/build.rs
vendored
Normal file
5
third-party/vendor/orbclient/build.rs
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
fn main() {
|
||||
if std::env::var("CARGO_CFG_TARGET_OS") == Ok("macos".to_string()) {
|
||||
println!("cargo:rustc-link-lib=framework=CoreHaptics");
|
||||
}
|
||||
}
|
||||
79
third-party/vendor/orbclient/examples/image_bench.rs
vendored
Normal file
79
third-party/vendor/orbclient/examples/image_bench.rs
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use orbclient::{Color, EventOption, Renderer, Window};
|
||||
|
||||
const TIMES: usize = 10;
|
||||
|
||||
macro_rules! time {
|
||||
($msg:tt, $block: block) => ({
|
||||
let _time_instant = ::std::time::Instant::now();
|
||||
$block
|
||||
let _time_duration = _time_instant.elapsed();
|
||||
let _time_fractional = _time_duration.as_secs() as f64
|
||||
+ (_time_duration.subsec_nanos() as f64)/1000000000.0;
|
||||
println!(
|
||||
"{}: {} ms",
|
||||
$msg,
|
||||
_time_fractional * 1000.0
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {
|
||||
//let (width, height) = orbclient::get_display_size().unwrap();
|
||||
|
||||
let mut window = Window::new(10, 10, 800, 600, "IMAGE BENCHMARK").unwrap();
|
||||
|
||||
window.set(Color::rgb(255, 255, 255));
|
||||
|
||||
//create image data : a green square
|
||||
let data = vec![Color::rgba(100, 200, 10, 20); 412500];
|
||||
let data2 = vec![Color::rgba(200, 100, 10, 20); 412500];
|
||||
let data3 = vec![Color::rgba(10, 100, 100, 20); 412500];
|
||||
let data4 = vec![Color::rgba(10, 100, 200, 20); 480000];
|
||||
|
||||
//draw image benchmarking
|
||||
println!("Benchmarking implementations to draw an image on window:");
|
||||
|
||||
time!("image_legacy", {
|
||||
for _i in 0..TIMES {
|
||||
window.image_legacy(15, 15, 750, 550, &data[..]);
|
||||
}
|
||||
});
|
||||
|
||||
time!("image_fast", {
|
||||
for _i in 0..TIMES {
|
||||
window.image_fast(20, 20, 750, 550, &data2[..]);
|
||||
}
|
||||
});
|
||||
|
||||
time!("image_opaque", {
|
||||
for _i in 0..TIMES {
|
||||
window.image_opaque(50, 50, 750, 550, &data3[..]);
|
||||
}
|
||||
});
|
||||
|
||||
time!("image_over", {
|
||||
for _i in 0..TIMES {
|
||||
window.image_over(50, &data4[..360000]);
|
||||
}
|
||||
});
|
||||
|
||||
println!("------------------------------------------------");
|
||||
|
||||
window.sync();
|
||||
|
||||
'events: loop {
|
||||
for event in window.events() {
|
||||
match event.to_option() {
|
||||
EventOption::Quit(_quit_event) => break 'events,
|
||||
EventOption::Mouse(evt) => println!(
|
||||
"At position {:?} pixel color is : {:?}",
|
||||
(evt.x, evt.y),
|
||||
window.getpixel(evt.x, evt.y)
|
||||
),
|
||||
event_option => println!("{:?}", event_option),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
50
third-party/vendor/orbclient/examples/rect_bench.rs
vendored
Normal file
50
third-party/vendor/orbclient/examples/rect_bench.rs
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use orbclient::{Color, EventOption, Renderer, Window};
|
||||
|
||||
macro_rules! time {
|
||||
($msg:tt, $block: block) => ({
|
||||
let _time_instant = ::std::time::Instant::now();
|
||||
$block
|
||||
let _time_duration = _time_instant.elapsed();
|
||||
let _time_fractional = _time_duration.as_secs() as f64
|
||||
+ (_time_duration.subsec_nanos() as f64)/1000000000.0;
|
||||
println!(
|
||||
"{}: {} ms",
|
||||
$msg,
|
||||
_time_fractional * 1000.0
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut window = Window::new(10, 10, 800, 600, "RECTANGLE BENCHMARK").unwrap();
|
||||
|
||||
time!("set", { window.set(Color::rgb(255, 255, 255)) });
|
||||
|
||||
time!("rect 400x400", {
|
||||
window.rect(0, 0, 400, 400, Color::rgb(0, 0, 255))
|
||||
});
|
||||
|
||||
time!("rect 200x200", {
|
||||
window.rect(0, 0, 200, 200, Color::rgb(0, 255, 0))
|
||||
});
|
||||
|
||||
time!("rect 100x100", {
|
||||
window.rect(0, 0, 100, 100, Color::rgb(255, 0, 0))
|
||||
});
|
||||
|
||||
time!("sync", {
|
||||
window.sync();
|
||||
});
|
||||
|
||||
'events: loop {
|
||||
for event in window.events() {
|
||||
#[allow(clippy::single_match)]
|
||||
match event.to_option() {
|
||||
EventOption::Quit(_quit_event) => break 'events,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
145
third-party/vendor/orbclient/examples/simple.rs
vendored
Normal file
145
third-party/vendor/orbclient/examples/simple.rs
vendored
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use orbclient::{Color, EventOption, GraphicsPath, Mode, Renderer, Window};
|
||||
|
||||
fn main() {
|
||||
let (width, height) = orbclient::get_display_size().unwrap();
|
||||
|
||||
let mut window = Window::new(
|
||||
(width as i32) / 4,
|
||||
(height as i32) / 4,
|
||||
width / 2,
|
||||
height / 2,
|
||||
"TITLE",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let (win_w, win_h) = (width / 2, height / 2);
|
||||
|
||||
// top left -> bottom rigth
|
||||
window.linear_gradient(
|
||||
0,
|
||||
0,
|
||||
win_w / 3,
|
||||
win_h,
|
||||
0,
|
||||
0,
|
||||
(win_w / 3) as i32,
|
||||
(win_h / 2) as i32,
|
||||
Color::rgb(128, 128, 128),
|
||||
Color::rgb(255, 255, 255),
|
||||
);
|
||||
// horizontal gradient
|
||||
window.linear_gradient(
|
||||
(win_w / 3) as i32,
|
||||
0,
|
||||
win_w / 3,
|
||||
win_h,
|
||||
(win_w / 3) as i32,
|
||||
0,
|
||||
(2 * win_w / 3) as i32,
|
||||
0,
|
||||
Color::rgb(128, 255, 255),
|
||||
Color::rgb(255, 255, 255),
|
||||
);
|
||||
// vertical gradient
|
||||
window.linear_gradient(
|
||||
(2 * win_w / 3) as i32,
|
||||
0,
|
||||
win_w / 3,
|
||||
win_h,
|
||||
(2 * win_w / 3) as i32,
|
||||
0,
|
||||
(2 * win_w / 3) as i32,
|
||||
win_h as i32,
|
||||
Color::rgb(0, 128, 0),
|
||||
Color::rgb(255, 255, 255),
|
||||
);
|
||||
window.arc(100, 100, -25, 1 << 0 | 1 << 2, Color::rgb(0, 0, 255));
|
||||
window.arc(100, 100, -25, 1 << 1 | 1 << 3, Color::rgb(0, 255, 255));
|
||||
window.arc(100, 100, -25, 1 << 4 | 1 << 6, Color::rgb(255, 0, 255));
|
||||
window.arc(100, 100, -25, 1 << 5 | 1 << 7, Color::rgb(255, 255, 0));
|
||||
window.circle(100, 100, 25, Color::rgb(0, 0, 0));
|
||||
window.circle(100, 101, -25, Color::rgb(0, 255, 0));
|
||||
window.circle(220, 220, -100, Color::rgba(128, 128, 128, 80));
|
||||
window.wu_circle(150, 220, 100, Color::rgba(255, 0, 0, 255));
|
||||
window.line(0, 0, 200, 200, Color::rgb(255, 0, 0));
|
||||
window.line(0, 200, 200, 0, Color::rgb(128, 255, 0));
|
||||
// vertical and horizontal line test
|
||||
window.line(100, 0, 100, 200, Color::rgb(0, 0, 255));
|
||||
window.line(0, 100, 200, 100, Color::rgb(255, 255, 0));
|
||||
window.wu_line(100, 220, 400, 250, Color::rgba(255, 0, 0, 255));
|
||||
window.line(100, 230, 400, 260, Color::rgba(255, 0, 0, 255));
|
||||
|
||||
// path and bezier curve example draw a cloud
|
||||
let mut cloud_path = GraphicsPath::new();
|
||||
cloud_path.move_to(170, 80);
|
||||
cloud_path.bezier_curve_to(130, 100, 130, 150, 230, 150);
|
||||
cloud_path.bezier_curve_to(250, 180, 320, 180, 340, 150);
|
||||
cloud_path.bezier_curve_to(420, 150, 420, 120, 390, 100);
|
||||
cloud_path.bezier_curve_to(430, 40, 370, 30, 340, 50);
|
||||
cloud_path.bezier_curve_to(320, 5, 250, 20, 250, 50);
|
||||
cloud_path.bezier_curve_to(200, 5, 150, 20, 170, 80);
|
||||
window.draw_path_stroke(cloud_path, Color::rgb(0, 0, 255));
|
||||
|
||||
// path and quadratic curve example draw a balloon
|
||||
let mut balloon_path = GraphicsPath::new();
|
||||
balloon_path.move_to(75, 25);
|
||||
balloon_path.quadratic_curve_to(25, 25, 25, 62);
|
||||
balloon_path.quadratic_curve_to(25, 100, 50, 100);
|
||||
balloon_path.quadratic_curve_to(50, 120, 30, 125);
|
||||
balloon_path.quadratic_curve_to(60, 120, 65, 100);
|
||||
balloon_path.quadratic_curve_to(125, 100, 125, 62);
|
||||
balloon_path.quadratic_curve_to(125, 25, 75, 25);
|
||||
window.draw_path_stroke(balloon_path, Color::rgb(0, 0, 255));
|
||||
|
||||
window.char(200, 200, '═', Color::rgb(0, 0, 0));
|
||||
window.char(208, 200, '═', Color::rgb(0, 0, 0));
|
||||
|
||||
// testing for non existent x,y position : does not panic but returns Color(0,0,0,0)
|
||||
let _non_existent_pixel = window.getpixel(width as i32 + 10, height as i32 + 10);
|
||||
|
||||
// testing PartialEq for Color
|
||||
if Color::rgb(11, 2, 3) == Color::rgba(1, 2, 3, 100) {
|
||||
println!("Testing colors: they are the same!")
|
||||
} else {
|
||||
println!("Testing colors: they are NOT the same!")
|
||||
}
|
||||
|
||||
//Draw a transparent rectangle over window content
|
||||
// default mode is Blend
|
||||
window.rect(250, 200, 80, 80, Color::rgba(100, 100, 100, 100));
|
||||
|
||||
//Draw an opaque rectangle replacing window content
|
||||
window.mode().set(Mode::Overwrite); // set window drawing mode to Overwrite from now on
|
||||
window.rect(300, 220, 80, 80, Color::rgb(100, 100, 100));
|
||||
|
||||
//Draw a hole in the window replacing alpha channel (Only in Orbital, not in SDL2)
|
||||
window.rect(300, 100, 80, 80, Color::rgba(10, 10, 10, 1));
|
||||
|
||||
//Draw a transparent rectangle over window content
|
||||
window.mode().set(Mode::Blend); //set mode to Blend fron now on
|
||||
window.rect(200, 230, 80, 80, Color::rgba(100, 100, 100, 100));
|
||||
|
||||
//Draw a blured box over window content
|
||||
window.box_blur(170, 100, 150, 150, 10);
|
||||
|
||||
//Draw a shadow around a box
|
||||
window.box_shadow(170, 100, 150, 150, 0, 0, 20, Color::rgba(0, 0, 0, 255));
|
||||
|
||||
window.sync();
|
||||
|
||||
'events: loop {
|
||||
for event in window.events() {
|
||||
match event.to_option() {
|
||||
EventOption::Quit(_quit_event) => break 'events,
|
||||
EventOption::Mouse(evt) => println!(
|
||||
"At position {:?} pixel color is : {:?}",
|
||||
(evt.x, evt.y),
|
||||
window.getpixel(evt.x, evt.y)
|
||||
),
|
||||
event_option => println!("{:?}", event_option),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
371
third-party/vendor/orbclient/res/unifont-license.txt
vendored
Normal file
371
third-party/vendor/orbclient/res/unifont-license.txt
vendored
Normal file
|
|
@ -0,0 +1,371 @@
|
|||
LICENSE
|
||||
-------
|
||||
The source code for everything except the compiled fonts in this current
|
||||
release is licensed as follows:
|
||||
|
||||
License for this current distribution of program source
|
||||
files (i.e., everything except the fonts) is released under
|
||||
the terms of the GNU General Public License version 2,
|
||||
or (at your option) a later version.
|
||||
|
||||
See the section below for a copy of the GNU General Public License
|
||||
version 2.
|
||||
|
||||
The license for the compiled fonts is covered by the above GPL terms
|
||||
with the GNU font embedding exception, as follows:
|
||||
|
||||
As a special exception, if you create a document which uses this font,
|
||||
and embed this font or unaltered portions of this font into the document,
|
||||
this font does not by itself cause the resulting document to be covered
|
||||
by the GNU General Public License. This exception does not however
|
||||
invalidate any other reasons why the document might be covered by the
|
||||
GNU General Public License. If you modify this font, you may extend
|
||||
this exception to your version of the font, but you are not obligated
|
||||
to do so. If you do not wish to do so, delete this exception statement
|
||||
from your version.
|
||||
|
||||
See "http://www.gnu.org/licenses/gpl-faq.html#FontException" for more details.
|
||||
|
||||
|
||||
GPL VERSION 2
|
||||
-------------
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
BIN
third-party/vendor/orbclient/res/unifont.font
vendored
Normal file
BIN
third-party/vendor/orbclient/res/unifont.font
vendored
Normal file
Binary file not shown.
57086
third-party/vendor/orbclient/res/unifont.hex
vendored
Normal file
57086
third-party/vendor/orbclient/res/unifont.hex
vendored
Normal file
File diff suppressed because it is too large
Load diff
35
third-party/vendor/orbclient/res/unifont.rs
vendored
Normal file
35
third-party/vendor/orbclient/res/unifont.rs
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#![feature(str_checked_slicing)]
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Write};
|
||||
|
||||
fn main() {
|
||||
let input = File::open("unifont.hex").unwrap();
|
||||
let mut output = File::create("unifont.font").unwrap();
|
||||
|
||||
let mut count = 0;
|
||||
for line_res in BufReader::new(input).lines() {
|
||||
let line = line_res.unwrap();
|
||||
|
||||
let mut parts = line.split(":");
|
||||
let num = u32::from_str_radix(parts.next().unwrap(), 16).unwrap();
|
||||
|
||||
while count < num {
|
||||
output.write(&[0; 16]).unwrap();
|
||||
count += 1;
|
||||
}
|
||||
|
||||
assert_eq!(num, count);
|
||||
|
||||
let mut data = [0; 16];
|
||||
let data_part = parts.next().unwrap();
|
||||
for i in 0..data.len() {
|
||||
let string = data_part.get(i * 2 .. i * 2 + 2).unwrap_or("00");
|
||||
data[i] = u8::from_str_radix(string, 16).unwrap();
|
||||
}
|
||||
println!("{:>04X}:{:?}", num, data);
|
||||
|
||||
output.write(&data).unwrap();
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
22
third-party/vendor/orbclient/rustfmt.toml
vendored
Normal file
22
third-party/vendor/orbclient/rustfmt.toml
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
max_width = 100
|
||||
hard_tabs = false
|
||||
tab_spaces = 4
|
||||
newline_style = "Unix"
|
||||
indent_style = "Block"
|
||||
format_strings = false
|
||||
empty_item_single_line = true
|
||||
fn_single_line = false
|
||||
where_single_line = false
|
||||
imports_indent = "Visual"
|
||||
imports_layout = "Mixed"
|
||||
fn_args_density = "Tall"
|
||||
brace_style = "SameLineWhere"
|
||||
trailing_comma = "Vertical"
|
||||
blank_lines_upper_bound = 1
|
||||
blank_lines_lower_bound = 0
|
||||
force_explicit_abi = true
|
||||
disable_all_formatting = false
|
||||
skip_children = false
|
||||
hide_parse_errors = false
|
||||
report_todo = "Never"
|
||||
report_fixme = "Never"
|
||||
218
third-party/vendor/orbclient/src/blur.rs
vendored
Normal file
218
third-party/vendor/orbclient/src/blur.rs
vendored
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
/*
|
||||
Inspired from http://blog.ivank.net/fastest-gaussian-blur.html the algorithm 4.
|
||||
The struct MathColor is needed for the calculate with bigger numbers, the Color struct save the r,g,b values with a u8.
|
||||
*/
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use core::ops::{Add, AddAssign, Sub};
|
||||
use crate::color::Color;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct MathColor {
|
||||
pub r: isize,
|
||||
pub g: isize,
|
||||
pub b: isize,
|
||||
}
|
||||
|
||||
impl MathColor {
|
||||
pub fn new(color: Color) -> Self {
|
||||
MathColor {
|
||||
r: color.r() as isize,
|
||||
g: color.g() as isize,
|
||||
b: color.b() as isize,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_multiplied_color(&mut self, iarr: f32) -> Color {
|
||||
Color::rgb(
|
||||
(self.r as f32 * iarr).round() as u8,
|
||||
(self.g as f32 * iarr).round() as u8,
|
||||
(self.b as f32 * iarr).round() as u8,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for MathColor {
|
||||
type Output = MathColor;
|
||||
|
||||
#[inline(always)]
|
||||
fn add(self, color: MathColor) -> MathColor {
|
||||
MathColor {
|
||||
r: self.r + color.r,
|
||||
g: self.g + color.g,
|
||||
b: self.b + color.b,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for MathColor {
|
||||
#[inline(always)]
|
||||
fn add_assign(&mut self, color: MathColor) {
|
||||
*self = MathColor {
|
||||
r: self.r + color.r,
|
||||
g: self.g + color.g,
|
||||
b: self.b + color.b,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl Sub for MathColor {
|
||||
type Output = MathColor;
|
||||
|
||||
#[inline(always)]
|
||||
fn sub(self, color: MathColor) -> MathColor {
|
||||
MathColor {
|
||||
r: self.r - color.r,
|
||||
g: self.g - color.g,
|
||||
b: self.b - color.b,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gauss_blur(data: &mut [Color], w: u32, h: u32, r: f32) {
|
||||
let bxs = boxes_for_gauss(r, 3);
|
||||
let mut tcl = data.to_owned();
|
||||
|
||||
box_blur(
|
||||
&mut tcl,
|
||||
data,
|
||||
w as usize,
|
||||
h as usize,
|
||||
((bxs[0] - 1) / 2) as usize,
|
||||
);
|
||||
box_blur(
|
||||
&mut tcl,
|
||||
data,
|
||||
w as usize,
|
||||
h as usize,
|
||||
((bxs[1] - 1) / 2) as usize,
|
||||
);
|
||||
box_blur(
|
||||
&mut tcl,
|
||||
data,
|
||||
w as usize,
|
||||
h as usize,
|
||||
((bxs[2] - 1) / 2) as usize,
|
||||
);
|
||||
}
|
||||
|
||||
fn boxes_for_gauss(sigma: f32, n: usize) -> Vec<i32> {
|
||||
let w_ideal: f32 = ((12.0 * sigma * sigma / n as f32) + 1.0).sqrt();
|
||||
let mut wl: i32 = w_ideal.floor() as i32;
|
||||
if wl % 2 == 0 {
|
||||
wl -= 1;
|
||||
};
|
||||
let wu: i32 = wl + 2;
|
||||
|
||||
let m_ideal: f32 = (12.0 * sigma * sigma
|
||||
- n as f32 * wl as f32 * wl as f32
|
||||
- 4.0 * n as f32 * wl as f32
|
||||
- 3.0 * n as f32)
|
||||
/ (-4.0 * wl as f32 - 4.0);
|
||||
let m: usize = m_ideal.round() as usize;
|
||||
|
||||
let mut sizes = Vec::<i32>::new();
|
||||
for i in 0..n {
|
||||
sizes.push(if i < m { wl } else { wu });
|
||||
}
|
||||
sizes
|
||||
}
|
||||
|
||||
fn box_blur(tcl: &mut [Color], scl: &mut [Color], w: usize, h: usize, r: usize) {
|
||||
box_blur_t(scl, tcl, w, h, r);
|
||||
box_blur_h(tcl, scl, w, h, r);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn box_blur_h(tcl: &mut [Color], scl: &mut [Color], w: usize, h: usize, r: usize) {
|
||||
let iarr: f32 = 1.0 / (r + r + 1) as f32;
|
||||
|
||||
for i in 0..h {
|
||||
let mut ti: usize = i * w;
|
||||
let mut li: usize = ti;
|
||||
let mut ri: usize = ti + r;
|
||||
let fv = MathColor::new(tcl[ti]);
|
||||
let lv = MathColor::new(tcl[ti + w - 1]);
|
||||
|
||||
let mut val: MathColor = MathColor {
|
||||
r: (r + 1) as isize * fv.r,
|
||||
g: (r + 1) as isize * fv.g,
|
||||
b: (r + 1) as isize * fv.b,
|
||||
};
|
||||
|
||||
for j in 0..r {
|
||||
val += MathColor::new(tcl[ti + j]);
|
||||
}
|
||||
|
||||
for _ in 0..(r + 1) {
|
||||
val += MathColor::new(tcl[ri]) - fv;
|
||||
scl[ti] = val.get_multiplied_color(iarr);
|
||||
ti += 1;
|
||||
ri += 1;
|
||||
}
|
||||
|
||||
for _ in (r + 1)..(w - r) {
|
||||
val += MathColor::new(tcl[ri]) - MathColor::new(tcl[li]);
|
||||
scl[ti] = val.get_multiplied_color(iarr);
|
||||
ti += 1;
|
||||
ri += 1;
|
||||
li += 1;
|
||||
}
|
||||
|
||||
for _ in (w - r)..w {
|
||||
val += lv - MathColor::new(tcl[li]);
|
||||
scl[ti] = val.get_multiplied_color(iarr);
|
||||
ti += 1;
|
||||
li += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn box_blur_t(tcl: &mut [Color], scl: &mut [Color], w: usize, h: usize, r: usize) {
|
||||
let iarr: f32 = 1.0 / (r + r + 1) as f32;
|
||||
|
||||
for i in 0..w {
|
||||
let mut ti: usize = i;
|
||||
let mut li: usize = ti;
|
||||
let mut ri: usize = ti + r * w;
|
||||
let fv = MathColor::new(tcl[ti]);
|
||||
let lv = MathColor::new(tcl[ti + w * (h - 1)]);
|
||||
|
||||
let mut val: MathColor = MathColor {
|
||||
r: (r + 1) as isize * fv.r,
|
||||
g: (r + 1) as isize * fv.g,
|
||||
b: (r + 1) as isize * fv.b,
|
||||
};
|
||||
|
||||
for j in 0..r {
|
||||
val += MathColor::new(tcl[ti + j * w]);
|
||||
}
|
||||
|
||||
for _ in 0..(r + 1) {
|
||||
val += MathColor::new(tcl[ri]) - fv;
|
||||
scl[ti] = val.get_multiplied_color(iarr);
|
||||
ti += w;
|
||||
ri += w;
|
||||
}
|
||||
|
||||
for _ in (r + 1)..(h - r) {
|
||||
val += MathColor::new(tcl[ri]) - MathColor::new(tcl[li]);
|
||||
scl[ti] = val.get_multiplied_color(iarr);
|
||||
ti += w;
|
||||
ri += w;
|
||||
li += w;
|
||||
}
|
||||
|
||||
for _ in (h - r)..h {
|
||||
val += lv - MathColor::new(tcl[li]);
|
||||
scl[ti] = val.get_multiplied_color(iarr);
|
||||
ti += w;
|
||||
li += w;
|
||||
}
|
||||
}
|
||||
}
|
||||
203
third-party/vendor/orbclient/src/color.rs
vendored
Normal file
203
third-party/vendor/orbclient/src/color.rs
vendored
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use core::fmt;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::de::{self, Deserializer};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::Deserialize;
|
||||
|
||||
/// A color
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct Color {
|
||||
pub data: u32,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
/// Create a new color from RGB
|
||||
pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
|
||||
Color {
|
||||
data: 0xFF000000 | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32),
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the alpha
|
||||
pub const fn rgba(r: u8, g: u8, b: u8, a: u8) -> Self {
|
||||
Color {
|
||||
data: ((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the r value
|
||||
pub fn r(&self) -> u8 {
|
||||
((self.data & 0x00FF0000) >> 16) as u8
|
||||
}
|
||||
|
||||
/// Get the g value
|
||||
pub fn g(&self) -> u8 {
|
||||
((self.data & 0x0000FF00) >> 8) as u8
|
||||
}
|
||||
|
||||
/// Get the b value
|
||||
pub fn b(&self) -> u8 {
|
||||
(self.data & 0x000000FF) as u8
|
||||
}
|
||||
|
||||
/// Get the alpha value
|
||||
pub fn a(&self) -> u8 {
|
||||
((self.data & 0xFF000000) >> 24) as u8
|
||||
}
|
||||
|
||||
/// Interpolate between two colors
|
||||
pub fn interpolate(start_color: Color, end_color: Color, scale: f64) -> Color {
|
||||
let r = Color::interp(start_color.r(), end_color.r(), scale);
|
||||
let g = Color::interp(start_color.g(), end_color.g(), scale);
|
||||
let b = Color::interp(start_color.b(), end_color.b(), scale);
|
||||
let a = Color::interp(start_color.a(), end_color.a(), scale);
|
||||
Color::rgba(r, g, b, a)
|
||||
}
|
||||
|
||||
fn interp(start_color: u8, end_color: u8, scale: f64) -> u8 {
|
||||
((end_color as f64 - start_color as f64) * scale + start_color as f64) as u8
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare two colors (Do not take care of alpha)
|
||||
impl PartialEq for Color {
|
||||
fn eq(&self, other: &Color) -> bool {
|
||||
self.r() == other.r() && self.g() == other.g() && self.b() == other.b()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Color {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(f, "{:#010X}", { self.data })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de> Deserialize<'de> for Color {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Color, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
deserializer.deserialize_i32(ColorVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
struct ColorVisitor;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de> de::Visitor<'de> for ColorVisitor {
|
||||
type Value = Color;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("Color specification in HEX format '#ARGB'")
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, color_spec: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
if color_spec.len() != 9 {
|
||||
return Err(E::custom(format!("Color spec must be of format '#AARRGGBB' ('{}')", color_spec)))
|
||||
}
|
||||
|
||||
if &color_spec[0..1] != "#" {
|
||||
return Err(E::custom(format!("Color spec must begin with '#' ('{}')", color_spec)));
|
||||
}
|
||||
|
||||
let a = u8::from_str_radix(&color_spec[1..3], 16)
|
||||
.map_err(|e| E::custom(e))?;
|
||||
let r = u8::from_str_radix(&color_spec[3..5], 16)
|
||||
.map_err(|e| E::custom(e.to_string()))?;
|
||||
let g = u8::from_str_radix(&color_spec[5..7], 16)
|
||||
.map_err(|e| E::custom(e.to_string()))?;
|
||||
let b = u8::from_str_radix(&color_spec[7..9], 16)
|
||||
.map_err(|e| E::custom(e.to_string()))?;
|
||||
|
||||
Ok(Color::rgba(r, g, b, a))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn partial_eq() {
|
||||
assert_eq!(Color::rgb(1, 2, 3), Color::rgba(1, 2, 3, 200));
|
||||
assert_ne!(Color::rgb(1, 2, 3), Color::rgba(11, 2, 3, 200));
|
||||
assert_eq!(Color::rgba(1, 2, 3, 200), Color::rgba(1, 2, 3, 200));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alignment() {
|
||||
assert_eq!(4, core::mem::size_of::<Color>());
|
||||
assert_eq!(8, core::mem::size_of::<[Color; 2]>());
|
||||
assert_eq!(12, core::mem::size_of::<[Color; 3]>());
|
||||
assert_eq!(16, core::mem::size_of::<[Color; 4]>());
|
||||
assert_eq!(20, core::mem::size_of::<[Color; 5]>());
|
||||
}
|
||||
|
||||
#[cfg(features = "serde")]
|
||||
mod serde {
|
||||
use serde_derive::Deserialize;
|
||||
use toml;
|
||||
use crate::Color;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct TestColor {
|
||||
color: Color,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_ok() {
|
||||
let color_spec = r##"color = "#00010203""##;
|
||||
let test_color: TestColor = toml::from_str(color_spec).expect("Color spec did not parse correctly");
|
||||
assert_eq!(test_color.color.a(), 0, "Alpha channel incorrect");
|
||||
assert_eq!(test_color.color.r(), 1, "Red channel incorrect");
|
||||
assert_eq!(test_color.color.g(), 2, "Green channel incorrect");
|
||||
assert_eq!(test_color.color.b(), 3, "Blue channel incorrect");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_hex() {
|
||||
let color_spec = r##"color = "#AABBCCDD""##;
|
||||
let _: TestColor = toml::from_str(color_spec).expect("Color spec did not parse HEX correctly");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_no_hash() {
|
||||
let color_spec = r##"color = "$00010203""##;
|
||||
let test_color: Result<TestColor, _> = toml::from_str(color_spec);
|
||||
assert!(test_color.is_err(), "Color spec should not parse correctly without leading '#'");
|
||||
assert!(test_color.err().unwrap().to_string().contains("must begin with '#'"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_not_hex() {
|
||||
let color_spec = r##"color = "#GG010203""##;
|
||||
let test_color: Result<TestColor, _> = toml::from_str(color_spec);
|
||||
assert!(test_color.is_err(), "Color spec should not parse invalid HEX correctly");
|
||||
assert!(test_color.err().unwrap().to_string().contains("invalid digit"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_str_too_long() {
|
||||
let color_spec = r##"color = "#0001020304""##;
|
||||
let test_color: Result<TestColor, _> = toml::from_str(color_spec);
|
||||
assert!(test_color.is_err(), "Color spec should not parse invalid spec correctly");
|
||||
assert!(test_color.err().unwrap().to_string().contains("must be of format '#AARRGGBB'"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_str_too_short() {
|
||||
let color_spec = r##"color = "#000102""##;
|
||||
let test_color: Result<TestColor, _> = toml::from_str(color_spec);
|
||||
assert!(test_color.is_err(), "Color spec should not parse invalid spec correctly");
|
||||
assert!(test_color.err().unwrap().to_string().contains("must be of format '#AARRGGBB'"));
|
||||
}
|
||||
}
|
||||
}
|
||||
647
third-party/vendor/orbclient/src/event.rs
vendored
Normal file
647
third-party/vendor/orbclient/src/event.rs
vendored
Normal file
|
|
@ -0,0 +1,647 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use core::{char, mem, slice};
|
||||
|
||||
pub const EVENT_NONE: i64 = 0;
|
||||
pub const EVENT_KEY: i64 = 1;
|
||||
pub const EVENT_MOUSE: i64 = 2;
|
||||
pub const EVENT_BUTTON: i64 = 3;
|
||||
pub const EVENT_SCROLL: i64 = 4;
|
||||
pub const EVENT_QUIT: i64 = 5;
|
||||
pub const EVENT_FOCUS: i64 = 6;
|
||||
pub const EVENT_MOVE: i64 = 7;
|
||||
pub const EVENT_RESIZE: i64 = 8;
|
||||
pub const EVENT_SCREEN: i64 = 9;
|
||||
pub const EVENT_CLIPBOARD: i64 = 10;
|
||||
pub const EVENT_MOUSE_RELATIVE: i64 = 11;
|
||||
pub const EVENT_DROP: i64 = 12;
|
||||
pub const EVENT_TEXT_INPUT: i64 = 13;
|
||||
pub const EVENT_CLIPBOARD_UPDATE: i64 = 14;
|
||||
pub const EVENT_HOVER: i64 = 15;
|
||||
|
||||
/// An optional event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum EventOption {
|
||||
/// A key event
|
||||
Key(KeyEvent),
|
||||
/// A text input event
|
||||
TextInput(TextInputEvent),
|
||||
/// A mouse event (absolute)
|
||||
Mouse(MouseEvent),
|
||||
/// A mouse event (relative)
|
||||
MouseRelative(MouseRelativeEvent),
|
||||
/// A mouse button event
|
||||
Button(ButtonEvent),
|
||||
/// A mouse scroll event
|
||||
Scroll(ScrollEvent),
|
||||
/// A quit request event
|
||||
Quit(QuitEvent),
|
||||
/// A focus event
|
||||
Focus(FocusEvent),
|
||||
/// A move event
|
||||
Move(MoveEvent),
|
||||
/// A resize event
|
||||
Resize(ResizeEvent),
|
||||
/// A screen report event
|
||||
Screen(ScreenEvent),
|
||||
/// A clipboard event
|
||||
Clipboard(ClipboardEvent),
|
||||
/// A clipboard update event
|
||||
ClipboardUpdate(ClipboardUpdateEvent),
|
||||
/// A drop file / text event (available on linux, windows and macOS)
|
||||
Drop(DropEvent),
|
||||
/// A hover event
|
||||
Hover(HoverEvent),
|
||||
/// An unknown event
|
||||
Unknown(Event),
|
||||
/// No event
|
||||
None,
|
||||
}
|
||||
|
||||
/// An event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(packed)]
|
||||
pub struct Event {
|
||||
pub code: i64,
|
||||
pub a: i64,
|
||||
pub b: i64,
|
||||
}
|
||||
|
||||
#[allow(clippy::new_without_default)]
|
||||
impl Event {
|
||||
/// Create a null event
|
||||
pub fn new() -> Event {
|
||||
Event {
|
||||
code: 0,
|
||||
a: 0,
|
||||
b: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert the event ot an optional event
|
||||
// TODO: Consider doing this via a From trait.
|
||||
pub fn to_option(self) -> EventOption {
|
||||
match self.code {
|
||||
EVENT_NONE => EventOption::None,
|
||||
EVENT_KEY => EventOption::Key(KeyEvent::from_event(self)),
|
||||
EVENT_TEXT_INPUT => EventOption::TextInput(TextInputEvent::from_event(self)),
|
||||
EVENT_MOUSE => EventOption::Mouse(MouseEvent::from_event(self)),
|
||||
EVENT_MOUSE_RELATIVE => {
|
||||
EventOption::MouseRelative(MouseRelativeEvent::from_event(self))
|
||||
}
|
||||
EVENT_BUTTON => EventOption::Button(ButtonEvent::from_event(self)),
|
||||
EVENT_SCROLL => EventOption::Scroll(ScrollEvent::from_event(self)),
|
||||
EVENT_QUIT => EventOption::Quit(QuitEvent::from_event(self)),
|
||||
EVENT_FOCUS => EventOption::Focus(FocusEvent::from_event(self)),
|
||||
EVENT_MOVE => EventOption::Move(MoveEvent::from_event(self)),
|
||||
EVENT_RESIZE => EventOption::Resize(ResizeEvent::from_event(self)),
|
||||
EVENT_SCREEN => EventOption::Screen(ScreenEvent::from_event(self)),
|
||||
EVENT_CLIPBOARD => EventOption::Clipboard(ClipboardEvent::from_event(self)),
|
||||
EVENT_CLIPBOARD_UPDATE => {
|
||||
EventOption::ClipboardUpdate(ClipboardUpdateEvent::from_event(self))
|
||||
}
|
||||
EVENT_DROP => EventOption::Drop(DropEvent::from_event(self)),
|
||||
EVENT_HOVER => EventOption::Hover(HoverEvent::from_event(self)),
|
||||
_ => EventOption::Unknown(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Event {
|
||||
type Target = [u8];
|
||||
fn deref(&self) -> &[u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::<Event>())
|
||||
as &[u8]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Event {
|
||||
fn deref_mut(&mut self) -> &mut [u8] {
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::<Event>())
|
||||
as &mut [u8]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const K_A: u8 = 0x1E;
|
||||
pub const K_B: u8 = 0x30;
|
||||
pub const K_C: u8 = 0x2E;
|
||||
pub const K_D: u8 = 0x20;
|
||||
pub const K_E: u8 = 0x12;
|
||||
pub const K_F: u8 = 0x21;
|
||||
pub const K_G: u8 = 0x22;
|
||||
pub const K_H: u8 = 0x23;
|
||||
pub const K_I: u8 = 0x17;
|
||||
pub const K_J: u8 = 0x24;
|
||||
pub const K_K: u8 = 0x25;
|
||||
pub const K_L: u8 = 0x26;
|
||||
pub const K_M: u8 = 0x32;
|
||||
pub const K_N: u8 = 0x31;
|
||||
pub const K_O: u8 = 0x18;
|
||||
pub const K_P: u8 = 0x19;
|
||||
pub const K_Q: u8 = 0x10;
|
||||
pub const K_R: u8 = 0x13;
|
||||
pub const K_S: u8 = 0x1F;
|
||||
pub const K_T: u8 = 0x14;
|
||||
pub const K_U: u8 = 0x16;
|
||||
pub const K_V: u8 = 0x2F;
|
||||
pub const K_W: u8 = 0x11;
|
||||
pub const K_X: u8 = 0x2D;
|
||||
pub const K_Y: u8 = 0x15;
|
||||
pub const K_Z: u8 = 0x2C;
|
||||
pub const K_0: u8 = 0x0B;
|
||||
pub const K_1: u8 = 0x02;
|
||||
pub const K_2: u8 = 0x03;
|
||||
pub const K_3: u8 = 0x04;
|
||||
pub const K_4: u8 = 0x05;
|
||||
pub const K_5: u8 = 0x06;
|
||||
pub const K_6: u8 = 0x07;
|
||||
pub const K_7: u8 = 0x08;
|
||||
pub const K_8: u8 = 0x09;
|
||||
pub const K_9: u8 = 0x0A;
|
||||
|
||||
// Numpad keys (codes 0x70-0x79)
|
||||
pub const K_NUM_0: u8 = 0x70;
|
||||
pub const K_NUM_1: u8 = 0x71;
|
||||
pub const K_NUM_2: u8 = 0x72;
|
||||
pub const K_NUM_3: u8 = 0x73;
|
||||
pub const K_NUM_4: u8 = 0x74;
|
||||
pub const K_NUM_5: u8 = 0x75;
|
||||
pub const K_NUM_6: u8 = 0x76;
|
||||
pub const K_NUM_7: u8 = 0x77;
|
||||
pub const K_NUM_8: u8 = 0x78;
|
||||
pub const K_NUM_9: u8 = 0x79;
|
||||
|
||||
/// Tick/tilde key
|
||||
pub const K_TICK: u8 = 0x29;
|
||||
/// Minus/underline key
|
||||
pub const K_MINUS: u8 = 0x0C;
|
||||
/// Equals/plus key
|
||||
pub const K_EQUALS: u8 = 0x0D;
|
||||
/// Backslash/pipe key
|
||||
pub const K_BACKSLASH: u8 = 0x2B;
|
||||
/// Bracket open key
|
||||
pub const K_BRACE_OPEN: u8 = 0x1A;
|
||||
/// Bracket close key
|
||||
pub const K_BRACE_CLOSE: u8 = 0x1B;
|
||||
/// Semicolon key
|
||||
pub const K_SEMICOLON: u8 = 0x27;
|
||||
/// Quote key
|
||||
pub const K_QUOTE: u8 = 0x28;
|
||||
/// Comma key
|
||||
pub const K_COMMA: u8 = 0x33;
|
||||
/// Period key
|
||||
pub const K_PERIOD: u8 = 0x34;
|
||||
/// Slash key
|
||||
pub const K_SLASH: u8 = 0x35;
|
||||
/// Backspace key
|
||||
pub const K_BKSP: u8 = 0x0E;
|
||||
/// Space key
|
||||
pub const K_SPACE: u8 = 0x39;
|
||||
/// Tab key
|
||||
pub const K_TAB: u8 = 0x0F;
|
||||
/// Capslock
|
||||
pub const K_CAPS: u8 = 0x3A;
|
||||
/// Left shift
|
||||
pub const K_LEFT_SHIFT: u8 = 0x2A;
|
||||
/// Right shift
|
||||
pub const K_RIGHT_SHIFT: u8 = 0x36;
|
||||
/// Control key
|
||||
pub const K_CTRL: u8 = 0x1D;
|
||||
/// Alt key
|
||||
pub const K_ALT: u8 = 0x38;
|
||||
/// AltGr key
|
||||
pub const K_ALT_GR: u8 = 0x64;
|
||||
/// Enter key
|
||||
pub const K_ENTER: u8 = 0x1C;
|
||||
/// Escape key
|
||||
pub const K_ESC: u8 = 0x01;
|
||||
/// F1 key
|
||||
pub const K_F1: u8 = 0x3B;
|
||||
/// F2 key
|
||||
pub const K_F2: u8 = 0x3C;
|
||||
/// F3 key
|
||||
pub const K_F3: u8 = 0x3D;
|
||||
/// F4 key
|
||||
pub const K_F4: u8 = 0x3E;
|
||||
/// F5 key
|
||||
pub const K_F5: u8 = 0x3F;
|
||||
/// F6 key
|
||||
pub const K_F6: u8 = 0x40;
|
||||
/// F7 key
|
||||
pub const K_F7: u8 = 0x41;
|
||||
/// F8 key
|
||||
pub const K_F8: u8 = 0x42;
|
||||
/// F9 key
|
||||
pub const K_F9: u8 = 0x43;
|
||||
/// F10 key
|
||||
pub const K_F10: u8 = 0x44;
|
||||
/// Home key
|
||||
pub const K_HOME: u8 = 0x47;
|
||||
/// Up key
|
||||
pub const K_UP: u8 = 0x48;
|
||||
/// Page up key
|
||||
pub const K_PGUP: u8 = 0x49;
|
||||
/// Left key
|
||||
pub const K_LEFT: u8 = 0x4B;
|
||||
/// Right key
|
||||
pub const K_RIGHT: u8 = 0x4D;
|
||||
/// End key
|
||||
pub const K_END: u8 = 0x4F;
|
||||
/// Down key
|
||||
pub const K_DOWN: u8 = 0x50;
|
||||
/// Page down key
|
||||
pub const K_PGDN: u8 = 0x51;
|
||||
/// Delete key
|
||||
pub const K_DEL: u8 = 0x53;
|
||||
/// F11 key
|
||||
pub const K_F11: u8 = 0x57;
|
||||
/// F12 key
|
||||
pub const K_F12: u8 = 0x58;
|
||||
/// SUPER/META/WIN Key
|
||||
pub const K_SUPER : u8 = 0x5B;
|
||||
/// Media Key for Volume toggle (mute/unmute)
|
||||
pub const K_VOLUME_TOGGLE : u8 = 0x80 + 0x20;
|
||||
/// Media Key for Volume Down
|
||||
pub const K_VOLUME_DOWN : u8 = 0x80 + 0x2E;
|
||||
/// Media Key for Volume Up
|
||||
pub const K_VOLUME_UP : u8 = 0x80 + 0x30;
|
||||
|
||||
/// A key event (such as a pressed key)
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct KeyEvent {
|
||||
/// The character of the key
|
||||
pub character: char,
|
||||
/// The scancode of the key
|
||||
pub scancode: u8,
|
||||
/// Was it pressed?
|
||||
pub pressed: bool,
|
||||
}
|
||||
|
||||
impl KeyEvent {
|
||||
/// Convert to an `Event`
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_KEY,
|
||||
a: self.character as i64,
|
||||
b: self.scancode as i64 | (self.pressed as i64) << 8,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert from an `Event`
|
||||
pub fn from_event(event: Event) -> KeyEvent {
|
||||
KeyEvent {
|
||||
character: char::from_u32(event.a as u32).unwrap_or('\0'),
|
||||
scancode: event.b as u8,
|
||||
pressed: event.b & 1 << 8 == 1 << 8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct TextInputEvent {
|
||||
pub character: char,
|
||||
}
|
||||
|
||||
impl TextInputEvent {
|
||||
/// Convert to an `Event`
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_TEXT_INPUT,
|
||||
a: self.character as i64,
|
||||
b: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert from an `Event`
|
||||
pub fn from_event(event: Event) -> TextInputEvent {
|
||||
TextInputEvent {
|
||||
character: char::from_u32(event.a as u32).unwrap_or('\0'),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A event related to the mouse (absolute position)
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct MouseEvent {
|
||||
/// The x coordinate of the mouse
|
||||
pub x: i32,
|
||||
/// The y coordinate of the mouse
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl MouseEvent {
|
||||
/// Convert to an `Event`
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_MOUSE,
|
||||
a: self.x as i64,
|
||||
b: self.y as i64,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an `Event` to a `MouseEvent`
|
||||
pub fn from_event(event: Event) -> MouseEvent {
|
||||
MouseEvent {
|
||||
x: event.a as i32,
|
||||
y: event.b as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A event related to the mouse (relative position)
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct MouseRelativeEvent {
|
||||
/// The x coordinate of the mouse
|
||||
pub dx: i32,
|
||||
/// The y coordinate of the mouse
|
||||
pub dy: i32,
|
||||
}
|
||||
|
||||
impl MouseRelativeEvent {
|
||||
/// Convert to an `Event`
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_MOUSE_RELATIVE,
|
||||
a: self.dx as i64,
|
||||
b: self.dy as i64,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an `Event` to a `MouseRelativeEvent`
|
||||
pub fn from_event(event: Event) -> MouseRelativeEvent {
|
||||
MouseRelativeEvent {
|
||||
dx: event.a as i32,
|
||||
dy: event.b as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A event for clicking the mouse
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ButtonEvent {
|
||||
/// Was the left button pressed?
|
||||
pub left: bool,
|
||||
/// Was the middle button pressed?
|
||||
pub middle: bool,
|
||||
/// Was the right button pressed?
|
||||
pub right: bool,
|
||||
}
|
||||
|
||||
impl ButtonEvent {
|
||||
/// Convert to an `Event`
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_BUTTON,
|
||||
a: self.left as i64 | (self.middle as i64) << 1 | (self.right as i64) << 2,
|
||||
b: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an `Event` to a `ButtonEvent`
|
||||
pub fn from_event(event: Event) -> ButtonEvent {
|
||||
ButtonEvent {
|
||||
left: event.a & 1 == 1,
|
||||
middle: event.a & 2 == 2,
|
||||
right: event.a & 4 == 4,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A event for scrolling the mouse
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ScrollEvent {
|
||||
/// The x distance of the scroll
|
||||
pub x: i32,
|
||||
/// The y distance of the scroll
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl ScrollEvent {
|
||||
/// Convert to an `Event`
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_SCROLL,
|
||||
a: self.x as i64,
|
||||
b: self.y as i64,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert an `Event` to a `ScrollEvent`
|
||||
pub fn from_event(event: Event) -> ScrollEvent {
|
||||
ScrollEvent {
|
||||
x: event.a as i32,
|
||||
y: event.b as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct QuitEvent;
|
||||
|
||||
impl QuitEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_QUIT,
|
||||
a: 0,
|
||||
b: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(_: Event) -> QuitEvent {
|
||||
QuitEvent
|
||||
}
|
||||
}
|
||||
|
||||
/// A focus event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct FocusEvent {
|
||||
/// True if window has been focused, false if not
|
||||
pub focused: bool,
|
||||
}
|
||||
|
||||
impl FocusEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_FOCUS,
|
||||
a: self.focused as i64,
|
||||
b: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(event: Event) -> FocusEvent {
|
||||
FocusEvent {
|
||||
focused: event.a > 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A move event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct MoveEvent {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl MoveEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_MOVE,
|
||||
a: self.x as i64,
|
||||
b: self.y as i64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(event: Event) -> MoveEvent {
|
||||
MoveEvent {
|
||||
x: event.a as i32,
|
||||
y: event.b as i32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A resize event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ResizeEvent {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl ResizeEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_RESIZE,
|
||||
a: self.width as i64,
|
||||
b: self.height as i64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(event: Event) -> ResizeEvent {
|
||||
ResizeEvent {
|
||||
width: event.a as u32,
|
||||
height: event.b as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A screen report event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ScreenEvent {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl ScreenEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_SCREEN,
|
||||
a: self.width as i64,
|
||||
b: self.height as i64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(event: Event) -> ScreenEvent {
|
||||
ScreenEvent {
|
||||
width: event.a as u32,
|
||||
height: event.b as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const CLIPBOARD_COPY: u8 = 0;
|
||||
pub const CLIPBOARD_CUT: u8 = 1;
|
||||
pub const CLIPBOARD_PASTE: u8 = 2;
|
||||
|
||||
/// A clipboard event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ClipboardUpdateEvent;
|
||||
|
||||
impl ClipboardUpdateEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_CLIPBOARD_UPDATE,
|
||||
a: 0,
|
||||
b: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(_: Event) -> ClipboardUpdateEvent {
|
||||
ClipboardUpdateEvent
|
||||
}
|
||||
}
|
||||
|
||||
/// A clipboard event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ClipboardEvent {
|
||||
pub kind: u8,
|
||||
pub size: usize,
|
||||
}
|
||||
|
||||
impl ClipboardEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_CLIPBOARD,
|
||||
a: self.kind as i64,
|
||||
b: self.size as i64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(event: Event) -> ClipboardEvent {
|
||||
ClipboardEvent {
|
||||
kind: event.a as u8,
|
||||
size: event.b as usize,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub const DROP_FILE: u8 = 0;
|
||||
pub const DROP_TEXT: u8 = 1;
|
||||
|
||||
/// A drop file event.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct DropEvent {
|
||||
pub kind: u8,
|
||||
}
|
||||
|
||||
impl DropEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_DROP,
|
||||
a: self.kind as i64,
|
||||
b: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(event: Event) -> DropEvent {
|
||||
DropEvent {
|
||||
kind: event.a as u8,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A hover event
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct HoverEvent {
|
||||
/// True if window has been entered, false if exited
|
||||
pub entered: bool,
|
||||
}
|
||||
|
||||
impl HoverEvent {
|
||||
pub fn to_event(&self) -> Event {
|
||||
Event {
|
||||
code: EVENT_HOVER,
|
||||
a: self.entered as i64,
|
||||
b: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_event(event: Event) -> HoverEvent {
|
||||
HoverEvent {
|
||||
entered: event.a > 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
120
third-party/vendor/orbclient/src/graphicspath.rs
vendored
Normal file
120
third-party/vendor/orbclient/src/graphicspath.rs
vendored
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
|
||||
/// point type (is the point a new position or a connection point)
|
||||
pub enum PointType {
|
||||
Move,
|
||||
Connect,
|
||||
None,
|
||||
}
|
||||
|
||||
/// graphic path with similar functions like html canvas
|
||||
pub struct GraphicsPath {
|
||||
x: i32,
|
||||
y: i32,
|
||||
pub points: Vec<(i32, i32, PointType)>,
|
||||
}
|
||||
|
||||
#[allow(clippy::new_without_default)]
|
||||
impl GraphicsPath {
|
||||
pub fn new() -> GraphicsPath {
|
||||
GraphicsPath {
|
||||
x: 0,
|
||||
y: 0,
|
||||
points: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// move to position
|
||||
pub fn move_to(&mut self, x: i32, y: i32) {
|
||||
self.points.push((x, y, PointType::Move));
|
||||
self.x = x;
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
/// create a line between the last and new point
|
||||
pub fn line_to(&mut self, x: i32, y: i32) {
|
||||
self.points.push((x, y, PointType::Connect));
|
||||
self.x = x;
|
||||
self.y = y;
|
||||
}
|
||||
|
||||
/// quadratic bezier curve
|
||||
pub fn quadratic_curve_to(&mut self, argx1: i32, argy1: i32, argx2: i32, argy2: i32) {
|
||||
let mut t: f32 = 0.0;
|
||||
let mut u: f32;
|
||||
let mut tt: f32;
|
||||
let mut uu: f32;
|
||||
let mut x: f32;
|
||||
let mut y: f32;
|
||||
|
||||
while t < 1.0 {
|
||||
u = 1.0 - t;
|
||||
uu = u * u;
|
||||
tt = t * t;
|
||||
|
||||
x = (self.x as f32) * uu;
|
||||
y = (self.y as f32) * uu;
|
||||
|
||||
x += 2.0 * u * t * (argx1 as f32);
|
||||
y += 2.0 * u * t * (argy1 as f32);
|
||||
|
||||
x += tt * (argx2 as f32);
|
||||
y += tt * (argy2 as f32);
|
||||
|
||||
t += 0.01;
|
||||
self.points.push((x as i32, y as i32, PointType::Connect));
|
||||
}
|
||||
|
||||
self.x = argx2;
|
||||
self.y = argy2;
|
||||
}
|
||||
|
||||
/// cubic bezier curve
|
||||
pub fn bezier_curve_to(
|
||||
&mut self,
|
||||
argx1: i32,
|
||||
argy1: i32,
|
||||
argx2: i32,
|
||||
argy2: i32,
|
||||
argx3: i32,
|
||||
argy3: i32,
|
||||
) {
|
||||
let mut t: f32 = 0.0;
|
||||
let mut u: f32;
|
||||
let mut tt: f32;
|
||||
let mut uu: f32;
|
||||
let mut uuu: f32;
|
||||
let mut ttt: f32;
|
||||
let mut x: f32;
|
||||
let mut y: f32;
|
||||
|
||||
while t < 1.0 {
|
||||
u = 1.0 - t;
|
||||
tt = t * t;
|
||||
uu = u * u;
|
||||
uuu = uu * u;
|
||||
ttt = tt * t;
|
||||
|
||||
x = (self.x as f32) * uuu;
|
||||
y = (self.y as f32) * uuu;
|
||||
|
||||
x += 3.0 * uu * t * (argx1 as f32);
|
||||
y += 3.0 * uu * t * (argy1 as f32);
|
||||
|
||||
x += 3.0 * u * tt * (argx2 as f32);
|
||||
y += 3.0 * u * tt * (argy2 as f32);
|
||||
|
||||
x += ttt * (argx3 as f32);
|
||||
y += ttt * (argy3 as f32);
|
||||
|
||||
t += 0.01;
|
||||
self.points.push((x as i32, y as i32, PointType::Connect));
|
||||
}
|
||||
|
||||
self.x = argx3;
|
||||
self.y = argy3;
|
||||
}
|
||||
}
|
||||
49
third-party/vendor/orbclient/src/lib.rs
vendored
Normal file
49
third-party/vendor/orbclient/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
extern crate alloc;
|
||||
|
||||
#[cfg(all(feature = "std", not(target_os = "redox")))]
|
||||
#[path = "sys/sdl2.rs"]
|
||||
mod sys;
|
||||
|
||||
#[cfg(all(feature = "std", target_os = "redox"))]
|
||||
#[path = "sys/orbital.rs"]
|
||||
mod sys;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub use sys::{get_display_size, EventIter, Window};
|
||||
|
||||
#[cfg(feature = "unifont")]
|
||||
pub static FONT: &[u8] = include_bytes!("../res/unifont.font");
|
||||
|
||||
pub use color::Color;
|
||||
pub use event::*;
|
||||
pub use graphicspath::GraphicsPath;
|
||||
pub use renderer::Renderer;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
mod blur;
|
||||
pub mod color;
|
||||
pub mod event;
|
||||
pub mod graphicspath;
|
||||
pub mod renderer;
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum WindowFlag {
|
||||
Async,
|
||||
Back,
|
||||
Front,
|
||||
Borderless,
|
||||
Resizable,
|
||||
Transparent,
|
||||
Unclosable,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Mode {
|
||||
Blend, //Composite
|
||||
Overwrite, //Replace
|
||||
}
|
||||
886
third-party/vendor/orbclient/src/renderer.rs
vendored
Normal file
886
third-party/vendor/orbclient/src/renderer.rs
vendored
Normal file
|
|
@ -0,0 +1,886 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use core::cell::Cell;
|
||||
use core::cmp;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::blur;
|
||||
use crate::color::Color;
|
||||
use crate::graphicspath::GraphicsPath;
|
||||
use crate::graphicspath::PointType;
|
||||
use crate::Mode;
|
||||
|
||||
pub trait Renderer {
|
||||
/// Get width
|
||||
fn width(&self) -> u32;
|
||||
|
||||
/// Get height
|
||||
fn height(&self) -> u32;
|
||||
|
||||
/// Access the pixel buffer
|
||||
fn data(&self) -> &[Color];
|
||||
|
||||
/// Access the pixel buffer mutably
|
||||
fn data_mut(&mut self) -> &mut [Color];
|
||||
|
||||
/// Flip the buffer
|
||||
fn sync(&mut self) -> bool;
|
||||
|
||||
/// Set/get drawing mode
|
||||
fn mode(&self) -> &Cell<Mode>;
|
||||
|
||||
///Draw a pixel
|
||||
//faster pixel implementation (multiplexing)
|
||||
fn pixel(&mut self, x: i32, y: i32, color: Color) {
|
||||
let replace = match self.mode().get() {
|
||||
Mode::Blend => false,
|
||||
Mode::Overwrite => true,
|
||||
};
|
||||
let w = self.width();
|
||||
let h = self.height();
|
||||
let data = self.data_mut();
|
||||
|
||||
if x >= 0 && y >= 0 && x < w as i32 && y < h as i32 {
|
||||
let new = color.data;
|
||||
let alpha = (new >> 24) & 0xFF;
|
||||
let old = &mut data[y as usize * w as usize + x as usize].data;
|
||||
|
||||
if alpha >= 255 || replace {
|
||||
*old = new;
|
||||
} else if alpha > 0 {
|
||||
let n_alpha = 255 - alpha;
|
||||
let rb = ((n_alpha * (*old & 0x00FF00FF)) + (alpha * (new & 0x00FF00FF))) >> 8;
|
||||
let ag = (n_alpha * ((*old & 0xFF00FF00) >> 8))
|
||||
+ (alpha * (0x01000000 | ((new & 0x0000FF00) >> 8)));
|
||||
|
||||
*old = (rb & 0x00FF00FF) | (ag & 0xFF00FF00);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a piece of an arc. Negative radius will fill in the inside
|
||||
fn arc(&mut self, x0: i32, y0: i32, radius: i32, parts: u8, color: Color) {
|
||||
let mut x = radius.abs();
|
||||
let mut y = 0;
|
||||
let mut err = 0;
|
||||
|
||||
// https://github.com/rust-lang/rust-clippy/issues/5354
|
||||
#[allow(clippy::comparison_chain)]
|
||||
while x >= y {
|
||||
if radius < 0 {
|
||||
if parts & 1 << 0 != 0 {
|
||||
self.rect(x0 - x, y0 + y, x as u32, 1, color);
|
||||
}
|
||||
if parts & 1 << 1 != 0 {
|
||||
self.rect(x0, y0 + y, x as u32 + 1, 1, color);
|
||||
}
|
||||
if parts & 1 << 2 != 0 {
|
||||
self.rect(x0 - y, y0 + x, y as u32, 1, color);
|
||||
}
|
||||
if parts & 1 << 3 != 0 {
|
||||
self.rect(x0, y0 + x, y as u32 + 1, 1, color);
|
||||
}
|
||||
if parts & 1 << 4 != 0 {
|
||||
self.rect(x0 - x, y0 - y, x as u32, 1, color);
|
||||
}
|
||||
if parts & 1 << 5 != 0 {
|
||||
self.rect(x0, y0 - y, x as u32 + 1, 1, color);
|
||||
}
|
||||
if parts & 1 << 6 != 0 {
|
||||
self.rect(x0 - y, y0 - x, y as u32, 1, color);
|
||||
}
|
||||
if parts & 1 << 7 != 0 {
|
||||
self.rect(x0, y0 - x, y as u32 + 1, 1, color);
|
||||
}
|
||||
} else if radius == 0 {
|
||||
self.pixel(x0, y0, color);
|
||||
} else {
|
||||
if parts & 1 << 0 != 0 {
|
||||
self.pixel(x0 - x, y0 + y, color);
|
||||
}
|
||||
if parts & 1 << 1 != 0 {
|
||||
self.pixel(x0 + x, y0 + y, color);
|
||||
}
|
||||
if parts & 1 << 2 != 0 {
|
||||
self.pixel(x0 - y, y0 + x, color);
|
||||
}
|
||||
if parts & 1 << 3 != 0 {
|
||||
self.pixel(x0 + y, y0 + x, color);
|
||||
}
|
||||
if parts & 1 << 4 != 0 {
|
||||
self.pixel(x0 - x, y0 - y, color);
|
||||
}
|
||||
if parts & 1 << 5 != 0 {
|
||||
self.pixel(x0 + x, y0 - y, color);
|
||||
}
|
||||
if parts & 1 << 6 != 0 {
|
||||
self.pixel(x0 - y, y0 - x, color);
|
||||
}
|
||||
if parts & 1 << 7 != 0 {
|
||||
self.pixel(x0 + y, y0 - x, color);
|
||||
}
|
||||
}
|
||||
|
||||
y += 1;
|
||||
err += 1 + 2 * y;
|
||||
if 2 * (err - x) + 1 > 0 {
|
||||
x -= 1;
|
||||
err += 1 - 2 * x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a circle. Negative radius will fill in the inside
|
||||
fn circle(&mut self, x0: i32, y0: i32, radius: i32, color: Color) {
|
||||
let mut x = radius.abs();
|
||||
let mut y = 0;
|
||||
let mut err = -radius.abs();
|
||||
|
||||
match radius {
|
||||
radius if radius > 0 => {
|
||||
err = 0;
|
||||
while x >= y {
|
||||
self.pixel(x0 - x, y0 + y, color);
|
||||
self.pixel(x0 + x, y0 + y, color);
|
||||
self.pixel(x0 - y, y0 + x, color);
|
||||
self.pixel(x0 + y, y0 + x, color);
|
||||
self.pixel(x0 - x, y0 - y, color);
|
||||
self.pixel(x0 + x, y0 - y, color);
|
||||
self.pixel(x0 - y, y0 - x, color);
|
||||
self.pixel(x0 + y, y0 - x, color);
|
||||
|
||||
y += 1;
|
||||
err += 1 + 2 * y;
|
||||
if 2 * (err - x) + 1 > 0 {
|
||||
x -= 1;
|
||||
err += 1 - 2 * x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
radius if radius < 0 => {
|
||||
while x >= y {
|
||||
let lasty = y;
|
||||
err += y;
|
||||
y += 1;
|
||||
err += y;
|
||||
self.line4points(x0, y0, x, lasty, color);
|
||||
if err >= 0 {
|
||||
if x != lasty {
|
||||
self.line4points(x0, y0, lasty, x, color);
|
||||
}
|
||||
err -= x;
|
||||
x -= 1;
|
||||
err -= x;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
self.pixel(x0, y0, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn line4points(&mut self, x0: i32, y0: i32, x: i32, y: i32, color: Color) {
|
||||
//self.line(x0 - x, y0 + y, (x+x0), y0 + y, color);
|
||||
self.rect(x0 - x, y0 + y, x as u32 * 2 + 1, 1, color);
|
||||
if y != 0 {
|
||||
//self.line(x0 - x, y0 - y, (x+x0), y0-y , color);
|
||||
self.rect(x0 - x, y0 - y, x as u32 * 2 + 1, 1, color);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a line
|
||||
fn line(&mut self, argx1: i32, argy1: i32, argx2: i32, argy2: i32, color: Color) {
|
||||
let mut x = argx1;
|
||||
let mut y = argy1;
|
||||
|
||||
let dx = if argx1 > argx2 {
|
||||
argx1 - argx2
|
||||
} else {
|
||||
argx2 - argx1
|
||||
};
|
||||
let dy = if argy1 > argy2 {
|
||||
argy1 - argy2
|
||||
} else {
|
||||
argy2 - argy1
|
||||
};
|
||||
|
||||
let sx = if argx1 < argx2 { 1 } else { -1 };
|
||||
let sy = if argy1 < argy2 { 1 } else { -1 };
|
||||
|
||||
let mut err = if dx > dy { dx } else { -dy } / 2;
|
||||
let mut err_tolerance;
|
||||
|
||||
loop {
|
||||
self.pixel(x, y, color);
|
||||
|
||||
if x == argx2 && y == argy2 {
|
||||
break;
|
||||
};
|
||||
|
||||
err_tolerance = 2 * err;
|
||||
|
||||
if err_tolerance > -dx {
|
||||
err -= dy;
|
||||
x += sx;
|
||||
}
|
||||
if err_tolerance < dy {
|
||||
err += dx;
|
||||
y += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lines(&mut self, points: &[[i32; 2]], color: Color) {
|
||||
if points.is_empty() {
|
||||
// when no points given, do nothing
|
||||
} else if points.len() == 1 {
|
||||
self.pixel(points[0][0], points[0][1], color);
|
||||
} else {
|
||||
for i in 0..points.len() - 1 {
|
||||
self.line(
|
||||
points[i][0],
|
||||
points[i][1],
|
||||
points[i + 1][0],
|
||||
points[i + 1][1],
|
||||
color,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a path (GraphicsPath)
|
||||
fn draw_path_stroke(&mut self, graphicspath: GraphicsPath, color: Color) {
|
||||
let mut x: i32 = 0;
|
||||
let mut y: i32 = 0;
|
||||
|
||||
for point in graphicspath.points {
|
||||
if let PointType::Connect = point.2 {
|
||||
self.line(x, y, point.0, point.1, color)
|
||||
}
|
||||
x = point.0;
|
||||
y = point.1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a character, using the loaded font
|
||||
#[cfg(feature = "unifont")]
|
||||
fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
|
||||
let mut offset = (c as usize) * 16;
|
||||
for row in 0..16 {
|
||||
let row_data = if offset < crate::FONT.len() {
|
||||
crate::FONT[offset]
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
for col in 0..8 {
|
||||
let pixel = (row_data >> (7 - col)) & 1;
|
||||
if pixel > 0 {
|
||||
self.pixel(x + col, y + row, color);
|
||||
}
|
||||
}
|
||||
offset += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Set entire window to a color
|
||||
fn set(&mut self, color: Color) {
|
||||
let data = self.data_mut();
|
||||
let data_ptr = data.as_mut_ptr();
|
||||
for i in 0..data.len() as isize {
|
||||
unsafe { *data_ptr.offset(i) = color }
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the whole window to black
|
||||
fn clear(&mut self) {
|
||||
self.set(Color::rgb(0, 0, 0));
|
||||
}
|
||||
|
||||
fn rect(&mut self, x: i32, y: i32, w: u32, h: u32, color: Color) {
|
||||
let replace = match self.mode().get() {
|
||||
Mode::Blend => false,
|
||||
Mode::Overwrite => true,
|
||||
};
|
||||
let self_w = self.width();
|
||||
let self_h = self.height();
|
||||
|
||||
let start_y = cmp::max(0, cmp::min(self_h as i32 - 1, y));
|
||||
let end_y = cmp::max(start_y, cmp::min(self_h as i32, y + h as i32));
|
||||
|
||||
let start_x = cmp::max(0, cmp::min(self_w as i32 - 1, x));
|
||||
let len = cmp::max(start_x, cmp::min(self_w as i32, x + w as i32)) - start_x;
|
||||
|
||||
let alpha = (color.data >> 24) & 0xFF;
|
||||
//if alpha > 0 {
|
||||
if alpha >= 255 || replace {
|
||||
let data = self.data_mut();
|
||||
let data_ptr = data.as_mut_ptr();
|
||||
for y in start_y..end_y {
|
||||
let start = (y * self_w as i32 + start_x) as isize;
|
||||
let end = start + len as isize;
|
||||
for i in start..end {
|
||||
unsafe {
|
||||
*data_ptr.offset(i) = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for y in start_y..end_y {
|
||||
for x in start_x..start_x + len {
|
||||
self.pixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
fn box_blur(&mut self, x: i32, y: i32, w: u32, h: u32, r: i32) {
|
||||
let self_w = self.width();
|
||||
let self_h = self.height();
|
||||
|
||||
let start_y = cmp::max(0, cmp::min(self_h as i32 - 1, y));
|
||||
let end_y = cmp::max(start_y, cmp::min(self_h as i32, y + h as i32));
|
||||
|
||||
let start_x = cmp::max(0, cmp::min(self_w as i32 - 1, x));
|
||||
let end_x = cmp::max(start_x, cmp::min(self_w as i32, x + w as i32));
|
||||
|
||||
let data = self.data_mut();
|
||||
let mut blur_data: Vec<Color> = Vec::new();
|
||||
for y in start_y..end_y {
|
||||
for x in start_x..end_x {
|
||||
let old = data[y as usize * self_w as usize + x as usize];
|
||||
blur_data.push(old);
|
||||
}
|
||||
}
|
||||
let real_w = end_x - start_x;
|
||||
let real_h = end_y - start_y;
|
||||
blur::gauss_blur(&mut blur_data, real_w as u32, real_h as u32, r as f32);
|
||||
|
||||
let mut counter: u32 = 0;
|
||||
for y in start_y..end_y {
|
||||
for x in start_x..end_x {
|
||||
let a = blur_data[counter as usize];
|
||||
let old = &mut data[y as usize * self_w as usize + x as usize].data;
|
||||
|
||||
*old = a.data;
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[cfg(feature = "std")]
|
||||
fn box_shadow(
|
||||
&mut self,
|
||||
x: i32,
|
||||
y: i32,
|
||||
w: u32,
|
||||
h: u32,
|
||||
offset_x: i32,
|
||||
offset_y: i32,
|
||||
r: i32,
|
||||
color: Color,
|
||||
) {
|
||||
let real_w = w + (2 * r as u32);
|
||||
let real_h = h + (2 * r as u32);
|
||||
|
||||
let mut blur_data: Vec<Color> = Vec::new();
|
||||
for new_x in x..x + real_w as i32 {
|
||||
for new_y in y..y + real_h as i32 {
|
||||
if new_x < x + r
|
||||
|| new_y < y + r
|
||||
|| new_y >= y + h as i32 + r
|
||||
|| new_x >= x + w as i32 + r
|
||||
{
|
||||
blur_data.push(Color::rgb(255, 0, 255));
|
||||
} else {
|
||||
blur_data.push(Color::rgb(0, 0, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
blur::gauss_blur(&mut blur_data, real_w, real_h, r as f32 / 3.0);
|
||||
|
||||
let mut counter: u32 = 0;
|
||||
for new_x in (x - r)..(x + real_w as i32 - r) {
|
||||
for new_y in (y - r)..(y + real_h as i32 - r) {
|
||||
let c = blur_data[counter as usize];
|
||||
|
||||
let alpha: u8 = if color.a() < 255 - c.r() {
|
||||
color.a()
|
||||
} else {
|
||||
255 - c.r()
|
||||
};
|
||||
let col = Color::rgba(color.r(), color.g(), color.b(), alpha);
|
||||
|
||||
let new_x_b = new_x + offset_x;
|
||||
let new_y_b = new_y + offset_y;
|
||||
if new_x_b < x
|
||||
|| new_x_b > x + w as i32 - 1
|
||||
|| new_y_b < y
|
||||
|| new_y_b > y + h as i32 - 1
|
||||
{
|
||||
self.pixel(new_x_b, new_y_b, col);
|
||||
}
|
||||
counter += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Display an image
|
||||
fn image(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, data: &[Color]) {
|
||||
match self.mode().get() {
|
||||
Mode::Blend => self.image_fast(start_x, start_y, w, h, data),
|
||||
Mode::Overwrite => self.image_opaque(start_x, start_y, w, h, data),
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Improve speed
|
||||
#[inline(always)]
|
||||
fn image_legacy(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, data: &[Color]) {
|
||||
let mut i = 0;
|
||||
for y in start_y..start_y + h as i32 {
|
||||
for x in start_x..start_x + w as i32 {
|
||||
if i < data.len() {
|
||||
self.pixel(x, y, data[i])
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Display an image overwriting a portion of window starting at given line : very quick!!
|
||||
fn image_over(&mut self, start: i32, image_data: &[Color]) {
|
||||
let start = start as usize * self.width() as usize;
|
||||
let window_data = self.data_mut();
|
||||
let stop = cmp::min(start + image_data.len(), window_data.len());
|
||||
let end = cmp::min(image_data.len(), window_data.len() - start);
|
||||
|
||||
window_data[start..stop].copy_from_slice(&image_data[..end]);
|
||||
}
|
||||
|
||||
///Display an image using non transparent method
|
||||
#[inline(always)]
|
||||
fn image_opaque(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, image_data: &[Color]) {
|
||||
let w = w as usize;
|
||||
let mut h = h as usize;
|
||||
let width = self.width() as usize;
|
||||
let height = self.height() as usize;
|
||||
let start_x = start_x as usize;
|
||||
let start_y = start_y as usize;
|
||||
|
||||
//check boundaries
|
||||
if start_x >= width || start_y >= height {
|
||||
return;
|
||||
}
|
||||
if h + start_y > height {
|
||||
h = height - start_y;
|
||||
}
|
||||
let window_data = self.data_mut();
|
||||
let offset = start_y * width + start_x;
|
||||
//copy image slices to window line by line
|
||||
for l in 0..h {
|
||||
let start = offset + l * width;
|
||||
let mut stop = start + w;
|
||||
let begin = l * w;
|
||||
let mut end = begin + w;
|
||||
//check boundaries
|
||||
if start_x + w > width {
|
||||
stop = (start_y + l + 1) * width - 1;
|
||||
end = begin + stop - start;
|
||||
}
|
||||
window_data[start..stop].copy_from_slice(&image_data[begin..end]);
|
||||
}
|
||||
}
|
||||
|
||||
// Speed improved, image can be outside of window boundary
|
||||
#[inline(always)]
|
||||
fn image_fast(&mut self, start_x: i32, start_y: i32, w: u32, h: u32, image_data: &[Color]) {
|
||||
let w = w as usize;
|
||||
let h = h as usize;
|
||||
let width = self.width() as usize;
|
||||
let start_x = start_x as usize;
|
||||
let start_y = start_y as usize;
|
||||
|
||||
//simply return if image is outside of window
|
||||
if start_x >= width || start_y >= self.height() as usize {
|
||||
return;
|
||||
}
|
||||
let window_data = self.data_mut();
|
||||
let offset = start_y * width + start_x;
|
||||
|
||||
//copy image slices to window line by line
|
||||
for l in 0..h {
|
||||
let start = offset + l * width;
|
||||
let mut stop = start + w;
|
||||
let begin = l * w;
|
||||
let end = begin + w;
|
||||
|
||||
//check boundaries
|
||||
if start_x + w > width {
|
||||
stop = (start_y + l + 1) * width;
|
||||
}
|
||||
let mut k = 0;
|
||||
for i in begin..end {
|
||||
if i < image_data.len() {
|
||||
let new = image_data[i].data;
|
||||
let alpha = (new >> 24) & 0xFF;
|
||||
if alpha > 0 && (start + k) < window_data.len() && (start + k) < stop {
|
||||
let old = &mut window_data[start + k].data;
|
||||
if alpha >= 255 {
|
||||
*old = new;
|
||||
} else {
|
||||
let n_alpha = 255 - alpha;
|
||||
let rb = ((n_alpha * (*old & 0x00FF00FF))
|
||||
+ (alpha * (new & 0x00FF00FF)))
|
||||
>> 8;
|
||||
let ag = (n_alpha * ((*old & 0xFF00FF00) >> 8))
|
||||
+ (alpha * (0x01000000 | ((new & 0x0000FF00) >> 8)));
|
||||
|
||||
*old = (rb & 0x00FF00FF) | (ag & 0xFF00FF00);
|
||||
}
|
||||
}
|
||||
k += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a linear gradient in a rectangular region
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[cfg(feature = "std")]
|
||||
fn linear_gradient(
|
||||
&mut self,
|
||||
rect_x: i32,
|
||||
rect_y: i32,
|
||||
rect_width: u32,
|
||||
rect_height: u32,
|
||||
start_x: i32,
|
||||
start_y: i32,
|
||||
end_x: i32,
|
||||
end_y: i32,
|
||||
start_color: Color,
|
||||
end_color: Color,
|
||||
) {
|
||||
if (start_x == end_x) && (start_y == end_y) {
|
||||
// Degenerate gradient
|
||||
self.rect(rect_x, rect_y, rect_width, rect_height, start_color);
|
||||
} else if start_x == end_x {
|
||||
// Vertical gradient
|
||||
for y in rect_y..(rect_y + rect_height as i32) {
|
||||
let proj = (y as f64 - start_y as f64) / (end_y as f64 - start_y as f64);
|
||||
let scale = if proj < 0.0 {
|
||||
0.0
|
||||
} else if proj > 1.0 {
|
||||
1.0
|
||||
} else {
|
||||
proj
|
||||
};
|
||||
let color = Color::interpolate(start_color, end_color, scale);
|
||||
self.line(rect_x, y, rect_x + rect_width as i32 - 1, y, color);
|
||||
}
|
||||
} else if start_y == end_y {
|
||||
// Horizontal gradient
|
||||
for x in rect_x..(rect_x + rect_width as i32) {
|
||||
let proj = (x as f64 - start_x as f64) / (end_x as f64 - start_x as f64);
|
||||
let scale = if proj < 0.0 {
|
||||
0.0
|
||||
} else if proj > 1.0 {
|
||||
1.0
|
||||
} else {
|
||||
proj
|
||||
};
|
||||
let color = Color::interpolate(start_color, end_color, scale);
|
||||
self.line(x, rect_y, x, rect_y + rect_height as i32 - 1, color);
|
||||
}
|
||||
} else {
|
||||
// Non axis-aligned gradient
|
||||
// Gradient vector
|
||||
let grad_x = end_x as f64 - start_x as f64;
|
||||
let grad_y = end_y as f64 - start_y as f64;
|
||||
let grad_len = grad_x * grad_x + grad_y * grad_y;
|
||||
|
||||
for y in rect_y..(rect_y + rect_height as i32) {
|
||||
for x in rect_x..(rect_x + rect_width as i32) {
|
||||
// Pixel vector
|
||||
let pix_x = x as f64 - start_x as f64;
|
||||
let pix_y = y as f64 - start_y as f64;
|
||||
// Scalar projection
|
||||
let proj = (pix_x * grad_x + pix_y * grad_y) / grad_len;
|
||||
// Saturation
|
||||
let scale = if proj < 0.0 {
|
||||
0.0
|
||||
} else if proj > 1.0 {
|
||||
1.0
|
||||
} else {
|
||||
proj
|
||||
};
|
||||
// Interpolation
|
||||
let color = Color::interpolate(start_color, end_color, scale);
|
||||
self.pixel(x, y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw a rect with rounded corners
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn rounded_rect(
|
||||
&mut self,
|
||||
x: i32,
|
||||
y: i32,
|
||||
w: u32,
|
||||
h: u32,
|
||||
radius: u32,
|
||||
filled: bool,
|
||||
color: Color,
|
||||
) {
|
||||
let w = w as i32;
|
||||
let h = h as i32;
|
||||
let r = radius as i32;
|
||||
|
||||
if filled {
|
||||
//Draw inside corners
|
||||
self.arc(x + r, y + r, -r, 1 << 4 | 1 << 6, color);
|
||||
self.arc(x + w - 1 - r, y + r, -r, 1 << 5 | 1 << 7, color);
|
||||
self.arc(x + r, y + h - 1 - r, -r, 1 << 0 | 1 << 2, color);
|
||||
self.arc(x + w - 1 - r, y + h - 1 - r, -r, 1 << 1 | 1 << 3, color);
|
||||
|
||||
// Draw inside rectangles
|
||||
self.rect(x + r, y, (w - 1 - r * 2) as u32, r as u32 + 1, color);
|
||||
self.rect(
|
||||
x + r,
|
||||
y + h - 1 - r,
|
||||
(w - 1 - r * 2) as u32,
|
||||
r as u32 + 1,
|
||||
color,
|
||||
);
|
||||
self.rect(x, y + r + 1, w as u32, (h - 2 - r * 2) as u32, color);
|
||||
} else {
|
||||
//Draw outside corners
|
||||
self.arc(x + r, y + r, r, 1 << 4 | 1 << 6, color);
|
||||
self.arc(x + w - 1 - r, y + r, r, 1 << 5 | 1 << 7, color);
|
||||
self.arc(x + r, y + h - 1 - r, r, 1 << 0 | 1 << 2, color);
|
||||
self.arc(x + w - 1 - r, y + h - 1 - r, r, 1 << 1 | 1 << 3, color);
|
||||
|
||||
// Draw outside rectangles
|
||||
self.rect(x + r + 1, y, (w - 2 - r * 2) as u32, 1, color);
|
||||
self.rect(x + r + 1, y + h - 1, (w - 2 - r * 2) as u32, 1, color);
|
||||
self.rect(x, y + r + 1, 1, (h - 2 - r * 2) as u32, color);
|
||||
self.rect(x + w - 1, y + r + 1, 1, (h - 2 - r * 2) as u32, color);
|
||||
}
|
||||
}
|
||||
|
||||
/// Draws antialiased line
|
||||
#[cfg(feature = "std")]
|
||||
fn wu_line(&mut self, x0: i32, y0: i32, x1: i32, y1: i32, color: Color) {
|
||||
//adapted from https://rosettacode.org/wiki/Xiaolin_Wu's_line_algorithm#C.23
|
||||
let mut x0 = x0 as f64;
|
||||
let mut y0 = y0 as f64;
|
||||
let mut x1 = x1 as f64;
|
||||
let mut y1 = y1 as f64;
|
||||
let r = color.r();
|
||||
let g = color.g();
|
||||
let b = color.b();
|
||||
let a = color.a() as f64;
|
||||
|
||||
fn ipart(x: f64) -> i32 {
|
||||
x.trunc() as i32
|
||||
}
|
||||
|
||||
fn fpart(x: f64) -> f64 {
|
||||
if x < 0.0 {
|
||||
return 1.0 - (x - x.floor());
|
||||
}
|
||||
x - x.floor()
|
||||
}
|
||||
|
||||
fn rfpart(x: f64) -> f64 {
|
||||
1.0 - fpart(x)
|
||||
}
|
||||
|
||||
fn chkalpha(mut alpha: f64) -> u8 {
|
||||
if alpha > 255.0 {
|
||||
alpha = 255.0
|
||||
};
|
||||
if alpha < 0.0 {
|
||||
alpha = 0.0
|
||||
};
|
||||
alpha as u8
|
||||
}
|
||||
|
||||
let steep: bool = (y1 - y0).abs() > (x1 - x0).abs();
|
||||
let mut temp;
|
||||
if steep {
|
||||
temp = x0;
|
||||
x0 = y0;
|
||||
y0 = temp;
|
||||
temp = x1;
|
||||
x1 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
if x0 > x1 {
|
||||
temp = x0;
|
||||
x0 = x1;
|
||||
x1 = temp;
|
||||
temp = y0;
|
||||
y0 = y1;
|
||||
y1 = temp;
|
||||
}
|
||||
let dx = x1 - x0;
|
||||
let dy = y1 - y0;
|
||||
let gradient = dy / dx;
|
||||
|
||||
let mut xend: f64 = x0.round();
|
||||
let mut yend: f64 = y0 + gradient * (xend - x0);
|
||||
let mut xgap: f64 = rfpart(x0 + 0.5);
|
||||
let xpixel1 = xend as i32;
|
||||
let ypixel1 = ipart(yend);
|
||||
|
||||
if steep {
|
||||
self.pixel(
|
||||
ypixel1,
|
||||
xpixel1,
|
||||
Color::rgba(r, g, b, chkalpha(rfpart(yend) * xgap * a)),
|
||||
);
|
||||
self.pixel(
|
||||
ypixel1 + 1,
|
||||
xpixel1,
|
||||
Color::rgba(r, g, b, chkalpha(fpart(yend) * xgap * a)),
|
||||
);
|
||||
} else {
|
||||
self.pixel(
|
||||
xpixel1,
|
||||
ypixel1,
|
||||
Color::rgba(r, g, b, chkalpha(rfpart(yend) * xgap * a)),
|
||||
);
|
||||
self.pixel(
|
||||
xpixel1 + 1,
|
||||
ypixel1,
|
||||
Color::rgba(r, g, b, chkalpha(fpart(yend) * xgap * a)),
|
||||
);
|
||||
}
|
||||
let mut intery: f64 = yend + gradient;
|
||||
xend = x1.round();
|
||||
yend = y1 + gradient * (xend - x1);
|
||||
xgap = fpart(x1 + 0.5);
|
||||
let xpixel2 = xend as i32;
|
||||
let ypixel2 = ipart(yend) ;
|
||||
if steep {
|
||||
self.pixel(
|
||||
ypixel2,
|
||||
xpixel2,
|
||||
Color::rgba(r, g, b, chkalpha(rfpart(yend) * xgap * a)),
|
||||
);
|
||||
self.pixel(
|
||||
ypixel2 + 1,
|
||||
xpixel2,
|
||||
Color::rgba(r, g, b, chkalpha(fpart(yend) * xgap * a)),
|
||||
);
|
||||
} else {
|
||||
self.pixel(
|
||||
xpixel2,
|
||||
ypixel2,
|
||||
Color::rgba(r, g, b, chkalpha(rfpart(yend) * xgap * a)),
|
||||
);
|
||||
self.pixel(
|
||||
xpixel2 + 1,
|
||||
ypixel2,
|
||||
Color::rgba(r, g, b, chkalpha(fpart(yend) * xgap * a)),
|
||||
);
|
||||
}
|
||||
if steep {
|
||||
for x in (xpixel1 + 1)..(xpixel2) {
|
||||
self.pixel(
|
||||
ipart(intery),
|
||||
x,
|
||||
Color::rgba(r, g, b, chkalpha(a * rfpart(intery))),
|
||||
);
|
||||
self.pixel(
|
||||
ipart(intery) + 1,
|
||||
x,
|
||||
Color::rgba(r, g, b, chkalpha(a * fpart(intery))),
|
||||
);
|
||||
intery += gradient;
|
||||
}
|
||||
} else {
|
||||
for x in (xpixel1 + 1)..(xpixel2) {
|
||||
self.pixel(
|
||||
x,
|
||||
ipart(intery),
|
||||
Color::rgba(r, g, b, chkalpha(a * rfpart(intery))),
|
||||
);
|
||||
self.pixel(
|
||||
x,
|
||||
ipart(intery) + 1,
|
||||
Color::rgba(r, g, b, chkalpha(a * fpart(intery))),
|
||||
);
|
||||
intery += gradient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///Draws antialiased circle
|
||||
#[cfg(feature = "std")]
|
||||
fn wu_circle(&mut self, x0: i32, y0: i32, radius: i32, color: Color) {
|
||||
let r = color.r();
|
||||
let g = color.g();
|
||||
let b = color.b();
|
||||
let a = color.a();
|
||||
let mut y = 0;
|
||||
let mut x = radius;
|
||||
let mut d = 0_f64;
|
||||
|
||||
self.pixel(x0 + x, y0 + y, color);
|
||||
self.pixel(x0 - x, y0 - y, color);
|
||||
self.pixel(x0 + y, y0 - x, color);
|
||||
self.pixel(x0 - y, y0 + x, color);
|
||||
|
||||
while x > y {
|
||||
let di = dist(radius, y);
|
||||
if di < d {
|
||||
x -= 1;
|
||||
}
|
||||
let col = Color::rgba(r, g, b, (a as f64 * (1.0 - di)) as u8);
|
||||
let col2 = Color::rgba(r, g, b, (a as f64 * di) as u8);
|
||||
|
||||
self.pixel(x0 + x, y0 + y, col);
|
||||
self.pixel(x0 + x - 1, y0 + y, col2); //-
|
||||
self.pixel(x0 - x, y0 + y, col);
|
||||
self.pixel(x0 - x + 1, y0 + y, col2); //+
|
||||
self.pixel(x0 + x, y0 - y, col);
|
||||
self.pixel(x0 + x - 1, y0 - y, col2); //-
|
||||
self.pixel(x0 - x, y0 - y, col);
|
||||
self.pixel(x0 - x + 1, y0 - y, col2); //+
|
||||
|
||||
self.pixel(x0 + y, y0 + x, col);
|
||||
self.pixel(x0 + y, y0 + x - 1, col2);
|
||||
self.pixel(x0 - y, y0 + x, col);
|
||||
self.pixel(x0 - y, y0 + x - 1, col2);
|
||||
self.pixel(x0 + y, y0 - x, col);
|
||||
self.pixel(x0 + y, y0 - x + 1, col2);
|
||||
self.pixel(x0 - y, y0 - x, col);
|
||||
self.pixel(x0 - y, y0 - x + 1, col2);
|
||||
d = di;
|
||||
y += 1;
|
||||
}
|
||||
|
||||
fn dist(r: i32, y: i32) -> f64 {
|
||||
let x: f64 = ((r * r - y * y) as f64).sqrt();
|
||||
x.ceil() - x
|
||||
}
|
||||
}
|
||||
|
||||
///Gets pixel color at x,y position
|
||||
fn getpixel(&self, x: i32, y: i32) -> Color {
|
||||
let p = (self.width() as i32 * y + x) as usize;
|
||||
if p >= self.data().len() {
|
||||
return Color::rgba(0, 0, 0, 0);
|
||||
}
|
||||
self.data()[p]
|
||||
}
|
||||
}
|
||||
440
third-party/vendor/orbclient/src/sys/orbital.rs
vendored
Normal file
440
third-party/vendor/orbclient/src/sys/orbital.rs
vendored
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::{env, mem, slice, thread};
|
||||
|
||||
use libredox::{call as redox, flag};
|
||||
|
||||
use crate::color::Color;
|
||||
use crate::event::{Event, EVENT_RESIZE};
|
||||
use crate::renderer::Renderer;
|
||||
use crate::Mode;
|
||||
use crate::WindowFlag;
|
||||
|
||||
pub fn get_display_size() -> Result<(u32, u32), String> {
|
||||
let display_path = env::var("DISPLAY").or(Err("DISPLAY not set"))?;
|
||||
match File::open(&display_path) {
|
||||
Ok(display) => {
|
||||
let mut buf: [u8; 4096] = [0; 4096];
|
||||
let count = redox::fpath(display.as_raw_fd() as usize, &mut buf)
|
||||
.map_err(|err| format!("{}", err))?;
|
||||
let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
|
||||
let res = path.split(":").nth(1).unwrap_or("");
|
||||
let width = res
|
||||
.split("/")
|
||||
.nth(1)
|
||||
.unwrap_or("")
|
||||
.parse::<u32>()
|
||||
.unwrap_or(0);
|
||||
let height = res
|
||||
.split("/")
|
||||
.nth(2)
|
||||
.unwrap_or("")
|
||||
.parse::<u32>()
|
||||
.unwrap_or(0);
|
||||
Ok((width, height))
|
||||
}
|
||||
Err(err) => Err(format!("{}", err)),
|
||||
}
|
||||
}
|
||||
|
||||
/// A window
|
||||
pub struct Window {
|
||||
/// The x coordinate of the window
|
||||
x: i32,
|
||||
/// The y coordinate of the window
|
||||
y: i32,
|
||||
/// The width of the window
|
||||
w: u32,
|
||||
/// The height of the window
|
||||
h: u32,
|
||||
/// The title of the window
|
||||
t: String,
|
||||
/// True if the window should not wait for events
|
||||
window_async: bool,
|
||||
/// True if the window can be resized
|
||||
resizable: bool,
|
||||
/// Drawing mode
|
||||
mode: Cell<Mode>,
|
||||
/// The input scheme
|
||||
file_opt: Option<File>,
|
||||
/// Window data
|
||||
data_opt: Option<&'static mut [Color]>,
|
||||
}
|
||||
|
||||
impl Renderer for Window {
|
||||
/// Get width
|
||||
fn width(&self) -> u32 {
|
||||
self.w
|
||||
}
|
||||
|
||||
/// Get height
|
||||
fn height(&self) -> u32 {
|
||||
self.h
|
||||
}
|
||||
|
||||
/// Access pixel buffer
|
||||
fn data(&self) -> &[Color] {
|
||||
self.data_opt.as_ref().unwrap()
|
||||
}
|
||||
|
||||
/// Access pixel buffer mutably
|
||||
fn data_mut(&mut self) -> &mut [Color] {
|
||||
self.data_opt.as_mut().unwrap()
|
||||
}
|
||||
|
||||
/// Flip the buffer
|
||||
fn sync(&mut self) -> bool {
|
||||
self.file_mut().sync_data().is_ok()
|
||||
}
|
||||
|
||||
/// Set/get mode
|
||||
fn mode(&self) -> &Cell<Mode> {
|
||||
&self.mode
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
/// Create a new window
|
||||
pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
|
||||
Window::new_flags(x, y, w, h, title, &[])
|
||||
}
|
||||
|
||||
/// Create a new window with flags
|
||||
pub fn new_flags(
|
||||
x: i32,
|
||||
y: i32,
|
||||
w: u32,
|
||||
h: u32,
|
||||
title: &str,
|
||||
flags: &[WindowFlag],
|
||||
) -> Option<Self> {
|
||||
let mut flag_str = String::new();
|
||||
|
||||
let mut window_async = false;
|
||||
let mut resizable = false;
|
||||
for &flag in flags.iter() {
|
||||
match flag {
|
||||
WindowFlag::Async => {
|
||||
window_async = true;
|
||||
flag_str.push('a');
|
||||
}
|
||||
WindowFlag::Back => flag_str.push('b'),
|
||||
WindowFlag::Front => flag_str.push('f'),
|
||||
WindowFlag::Borderless => flag_str.push('l'),
|
||||
WindowFlag::Resizable => {
|
||||
resizable = true;
|
||||
flag_str.push('r');
|
||||
}
|
||||
WindowFlag::Transparent => flag_str.push('t'),
|
||||
WindowFlag::Unclosable => flag_str.push('u'),
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(file) = File::open(&format!(
|
||||
"orbital:{}/{}/{}/{}/{}/{}",
|
||||
flag_str, x, y, w, h, title
|
||||
)) {
|
||||
let mut window = Window {
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
t: title.to_string(),
|
||||
window_async,
|
||||
resizable,
|
||||
mode: Cell::new(Mode::Blend),
|
||||
file_opt: Some(file),
|
||||
data_opt: None,
|
||||
};
|
||||
unsafe { window.remap(); }
|
||||
Some(window)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clipboard(&self) -> String {
|
||||
let mut text = String::new();
|
||||
let window_fd = self.file().as_raw_fd();
|
||||
if let Ok(clipboard_fd) = redox::dup(window_fd as usize, b"clipboard") {
|
||||
let mut clipboard_file = unsafe { File::from_raw_fd(clipboard_fd as RawFd) };
|
||||
let _ = clipboard_file.read_to_string(&mut text);
|
||||
}
|
||||
text
|
||||
}
|
||||
|
||||
pub fn set_clipboard(&mut self, text: &str) {
|
||||
let window_fd = self.file().as_raw_fd();
|
||||
if let Ok(clipboard_fd) = redox::dup(window_fd as usize, b"clipboard") {
|
||||
let mut clipboard_file = unsafe { File::from_raw_fd(clipboard_fd as RawFd) };
|
||||
let _ = clipboard_file.write(text.as_bytes());
|
||||
}
|
||||
}
|
||||
|
||||
/// Not yet available on Redox OS.
|
||||
pub fn pop_drop_content(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
// TODO: Replace with smarter mechanism, maybe a move event?
|
||||
pub fn sync_path(&mut self) {
|
||||
let mut buf: [u8; 4096] = [0; 4096];
|
||||
if let Ok(count) = redox::fpath(self.file().as_raw_fd() as usize, &mut buf) {
|
||||
let path = unsafe { String::from_utf8_unchecked(Vec::from(&buf[..count])) };
|
||||
// orbital:/x/y/w/h/t
|
||||
let mut parts = path.split('/');
|
||||
if let Some(flags) = parts.next() {
|
||||
self.window_async = flags.contains('a');
|
||||
self.resizable = flags.contains('r');
|
||||
}
|
||||
if let Some(x) = parts.next() {
|
||||
self.x = x.parse::<i32>().unwrap_or(0);
|
||||
}
|
||||
if let Some(y) = parts.next() {
|
||||
self.y = y.parse::<i32>().unwrap_or(0);
|
||||
}
|
||||
if let Some(w) = parts.next() {
|
||||
self.w = w.parse::<u32>().unwrap_or(0);
|
||||
}
|
||||
if let Some(h) = parts.next() {
|
||||
self.h = h.parse::<u32>().unwrap_or(0);
|
||||
}
|
||||
if let Some(t) = parts.next() {
|
||||
self.t = t.to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Get x
|
||||
// TODO: Sync with window movements
|
||||
pub fn x(&self) -> i32 {
|
||||
self.x
|
||||
}
|
||||
|
||||
/// Get y
|
||||
// TODO: Sync with window movements
|
||||
pub fn y(&self) -> i32 {
|
||||
self.y
|
||||
}
|
||||
|
||||
/// Get title
|
||||
pub fn title(&self) -> String {
|
||||
self.t.clone()
|
||||
}
|
||||
|
||||
/// Get async
|
||||
pub fn is_async(&self) -> bool {
|
||||
self.window_async
|
||||
}
|
||||
|
||||
/// Set async
|
||||
pub fn set_async(&mut self, is_async: bool) {
|
||||
self.window_async = is_async;
|
||||
let _ = self.file_mut().write(if is_async { b"A,1" } else { b"A,0" });
|
||||
}
|
||||
|
||||
/// Set cursor visibility
|
||||
pub fn set_mouse_cursor(&mut self, visible: bool) {
|
||||
let _ = self.file_mut().write(if visible { b"M,C,1" } else { b"M,C,0" });
|
||||
}
|
||||
|
||||
/// Set mouse grabbing
|
||||
pub fn set_mouse_grab(&mut self, grab: bool) {
|
||||
let _ = self.file_mut().write(if grab { b"M,G,1" } else { b"M,G,0" });
|
||||
}
|
||||
|
||||
/// Set mouse relative mode
|
||||
pub fn set_mouse_relative(&mut self, relative: bool) {
|
||||
let _ = self.file_mut().write(if relative { b"M,R,1" } else { b"M,R,0" });
|
||||
}
|
||||
|
||||
/// Set position
|
||||
pub fn set_pos(&mut self, x: i32, y: i32) {
|
||||
let _ = self.file_mut().write(&format!("P,{},{}", x, y).as_bytes());
|
||||
self.sync_path();
|
||||
}
|
||||
|
||||
/// Set size
|
||||
pub fn set_size(&mut self, width: u32, height: u32) {
|
||||
//TODO: Improve safety and reliability
|
||||
unsafe { self.unmap(); }
|
||||
|
||||
let _ = self
|
||||
.file_mut()
|
||||
.write(&format!("S,{},{}", width, height).as_bytes());
|
||||
self.sync_path();
|
||||
|
||||
unsafe { self.remap(); }
|
||||
}
|
||||
|
||||
/// Set title
|
||||
pub fn set_title(&mut self, title: &str) {
|
||||
let _ = self.file_mut().write(&format!("T,{}", title).as_bytes());
|
||||
self.sync_path();
|
||||
}
|
||||
|
||||
/// Blocking iterator over events
|
||||
pub fn events(&mut self) -> EventIter {
|
||||
let mut iter = EventIter {
|
||||
extra: None,
|
||||
events: [Event::new(); 16],
|
||||
i: 0,
|
||||
count: 0,
|
||||
};
|
||||
|
||||
'blocking: loop {
|
||||
if iter.count == iter.events.len() {
|
||||
if iter.extra.is_none() {
|
||||
iter.extra = Some(Vec::with_capacity(32));
|
||||
}
|
||||
iter.extra.as_mut().unwrap().extend_from_slice(&iter.events);
|
||||
iter.count = 0;
|
||||
}
|
||||
let bytes = unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
iter.events[iter.count..].as_mut_ptr() as *mut u8,
|
||||
iter.events[iter.count..].len() * mem::size_of::<Event>(),
|
||||
)
|
||||
};
|
||||
match self.file_mut().read(bytes) {
|
||||
Ok(0) => {
|
||||
if !self.window_async && iter.extra.is_none() && iter.count == 0 {
|
||||
thread::yield_now();
|
||||
} else {
|
||||
break 'blocking;
|
||||
}
|
||||
}
|
||||
Ok(count) => {
|
||||
let count = count / mem::size_of::<Event>();
|
||||
let events = &iter.events[iter.count..][..count];
|
||||
iter.count += count;
|
||||
|
||||
if self.resizable {
|
||||
let mut resize = None;
|
||||
for event in events {
|
||||
let event = *event;
|
||||
if event.code == EVENT_RESIZE {
|
||||
resize = Some((event.a as u32, event.b as u32));
|
||||
}
|
||||
}
|
||||
if let Some((w, h)) = resize {
|
||||
self.set_size(w, h);
|
||||
}
|
||||
}
|
||||
if !self.window_async {
|
||||
// Synchronous windows are blocking, can't attempt another read
|
||||
break 'blocking;
|
||||
}
|
||||
}
|
||||
Err(_) => break 'blocking,
|
||||
}
|
||||
}
|
||||
|
||||
iter
|
||||
}
|
||||
|
||||
fn file(&self) -> &File {
|
||||
self.file_opt.as_ref().unwrap()
|
||||
}
|
||||
|
||||
fn file_mut(&mut self) -> &mut File {
|
||||
self.file_opt.as_mut().unwrap()
|
||||
}
|
||||
|
||||
unsafe fn remap(&mut self) {
|
||||
self.unmap();
|
||||
|
||||
let size = (self.w * self.h) as usize;
|
||||
let address = redox::mmap(redox::MmapArgs {
|
||||
fd: self.file().as_raw_fd() as usize,
|
||||
offset: 0,
|
||||
length: size * mem::size_of::<Color>(),
|
||||
flags: flag::MAP_SHARED,
|
||||
prot: flag::PROT_READ | flag::PROT_WRITE,
|
||||
addr: core::ptr::null_mut(),
|
||||
}).expect("orbclient: failed to map memory");
|
||||
|
||||
self.data_opt = Some(
|
||||
slice::from_raw_parts_mut(address.cast::<Color>(), size)
|
||||
);
|
||||
}
|
||||
|
||||
unsafe fn unmap(&mut self) {
|
||||
if let Some(data) = self.data_opt.take() {
|
||||
redox::munmap(
|
||||
data.as_mut_ptr().cast(),
|
||||
data.len() * mem::size_of::<Color>(),
|
||||
).expect("orbclient: failed to unmap memory");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
unsafe { self.unmap(); }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Window {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.file().as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for Window {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Window {
|
||||
let mut window = Window {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 0,
|
||||
h: 0,
|
||||
t: String::new(),
|
||||
window_async: false,
|
||||
resizable: false,
|
||||
mode: Cell::new(Mode::Blend),
|
||||
file_opt: Some(File::from_raw_fd(fd)),
|
||||
data_opt: None,
|
||||
};
|
||||
window.sync_path();
|
||||
window.remap();
|
||||
window
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for Window {
|
||||
fn into_raw_fd(mut self) -> RawFd {
|
||||
self.file_opt.take().unwrap().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
/// Event iterator
|
||||
pub struct EventIter {
|
||||
extra: Option<Vec<Event>>,
|
||||
events: [Event; 16],
|
||||
i: usize,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl Iterator for EventIter {
|
||||
type Item = Event;
|
||||
fn next(&mut self) -> Option<Event> {
|
||||
let mut i = self.i;
|
||||
if let Some(ref mut extra) = self.extra {
|
||||
if i < extra.len() {
|
||||
self.i += 1;
|
||||
return Some(extra[i]);
|
||||
}
|
||||
i -= extra.len();
|
||||
}
|
||||
if i < self.count {
|
||||
self.i += 1;
|
||||
return Some(self.events[i]);
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
624
third-party/vendor/orbclient/src/sys/sdl2.rs
vendored
Normal file
624
third-party/vendor/orbclient/src/sys/sdl2.rs
vendored
Normal file
|
|
@ -0,0 +1,624 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::{mem, ptr, slice};
|
||||
|
||||
use crate::color::Color;
|
||||
use crate::event::*;
|
||||
use crate::renderer::Renderer;
|
||||
use crate::Mode;
|
||||
use crate::WindowFlag;
|
||||
|
||||
static SDL_USAGES: AtomicUsize = AtomicUsize::new(0);
|
||||
/// SDL2 Context
|
||||
static mut SDL_CTX: *mut sdl2::Sdl = ptr::null_mut();
|
||||
/// Video Context
|
||||
static mut VIDEO_CTX: *mut sdl2::VideoSubsystem = ptr::null_mut();
|
||||
/// Event Pump
|
||||
static mut EVENT_PUMP: *mut sdl2::EventPump = ptr::null_mut();
|
||||
|
||||
//Call this when the CTX needs to be used is created
|
||||
#[inline]
|
||||
unsafe fn init() {
|
||||
if SDL_USAGES.fetch_add(1, Ordering::Relaxed) == 0 {
|
||||
SDL_CTX = Box::into_raw(Box::new(sdl2::init().unwrap()));
|
||||
VIDEO_CTX = Box::into_raw(Box::new((*SDL_CTX).video().unwrap()));
|
||||
EVENT_PUMP = Box::into_raw(Box::new((*SDL_CTX).event_pump().unwrap()));
|
||||
}
|
||||
}
|
||||
|
||||
// Call this when drop the sdl2 CTX.
|
||||
#[inline]
|
||||
unsafe fn cleanup() {
|
||||
if SDL_USAGES.fetch_sub(1, Ordering::Relaxed) == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
drop(Box::from_raw(SDL_CTX));
|
||||
drop(Box::from_raw(VIDEO_CTX));
|
||||
drop(Box::from_raw(EVENT_PUMP));
|
||||
}
|
||||
|
||||
/// Return the (width, height) of the display in pixels
|
||||
pub fn get_display_size() -> Result<(u32, u32), String> {
|
||||
unsafe { init() };
|
||||
unsafe { &*VIDEO_CTX }
|
||||
.display_bounds(0)
|
||||
.map(|rect| (rect.width(), rect.height()))
|
||||
}
|
||||
|
||||
/// A window
|
||||
#[allow(dead_code)]
|
||||
pub struct Window {
|
||||
/// The x coordinate of the window
|
||||
x: i32,
|
||||
/// The y coordinate of the window
|
||||
y: i32,
|
||||
/// The width of the window
|
||||
w: u32,
|
||||
/// The height of the window
|
||||
h: u32,
|
||||
/// The title of the window
|
||||
t: String,
|
||||
/// True if the window should not wait for events
|
||||
window_async: bool,
|
||||
/// Drawing mode
|
||||
mode: Cell<Mode>,
|
||||
/// The inner renderer
|
||||
inner: sdl2::render::WindowCanvas,
|
||||
/// Mouse in relative mode
|
||||
mouse_relative: bool,
|
||||
/// Content of the last drop (file | text) operation
|
||||
drop_content: RefCell<Option<String>>,
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Renderer for Window {
|
||||
/// Get width
|
||||
fn width(&self) -> u32 {
|
||||
self.w
|
||||
}
|
||||
|
||||
/// Get height
|
||||
fn height(&self) -> u32 {
|
||||
self.h
|
||||
}
|
||||
|
||||
/// Access pixel buffer
|
||||
fn data(&self) -> &[Color] {
|
||||
let window = self.inner.window();
|
||||
let surface = window.surface(unsafe { &*EVENT_PUMP }).unwrap();
|
||||
let bytes = surface.without_lock().unwrap();
|
||||
unsafe {
|
||||
slice::from_raw_parts(
|
||||
bytes.as_ptr() as *const Color,
|
||||
bytes.len() / mem::size_of::<Color>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Access pixel buffer mutably
|
||||
fn data_mut(&mut self) -> &mut [Color] {
|
||||
let window = self.inner.window_mut();
|
||||
let mut surface = window.surface(unsafe { &*EVENT_PUMP }).unwrap();
|
||||
let bytes = surface.without_lock_mut().unwrap();
|
||||
unsafe {
|
||||
slice::from_raw_parts_mut(
|
||||
bytes.as_mut_ptr() as *mut Color,
|
||||
bytes.len() / mem::size_of::<Color>(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Flip the window buffer
|
||||
fn sync(&mut self) -> bool {
|
||||
self.inner.present();
|
||||
true
|
||||
}
|
||||
|
||||
/// Set/get mode
|
||||
fn mode(&self) -> &Cell<Mode> {
|
||||
&self.mode
|
||||
}
|
||||
}
|
||||
|
||||
impl Window {
|
||||
/// Create a new window
|
||||
pub fn new(x: i32, y: i32, w: u32, h: u32, title: &str) -> Option<Self> {
|
||||
Window::new_flags(x, y, w, h, title, &[])
|
||||
}
|
||||
|
||||
/// Create a new window with flags
|
||||
pub fn new_flags(
|
||||
x: i32,
|
||||
y: i32,
|
||||
w: u32,
|
||||
h: u32,
|
||||
title: &str,
|
||||
flags: &[WindowFlag],
|
||||
) -> Option<Self> {
|
||||
//Insure that init has been called
|
||||
unsafe { init() };
|
||||
|
||||
let mut window_async = false;
|
||||
//TODO: Use z-order
|
||||
let mut _back = false;
|
||||
let mut _front = false;
|
||||
let mut borderless = false;
|
||||
let mut resizable = false;
|
||||
//TODO: Transparent
|
||||
let mut _transparent = false;
|
||||
//TODO: Hide exit button
|
||||
let mut _unclosable = false;
|
||||
for &flag in flags.iter() {
|
||||
match flag {
|
||||
WindowFlag::Async => window_async = true,
|
||||
WindowFlag::Back => _back = true,
|
||||
WindowFlag::Front => _front = true,
|
||||
WindowFlag::Borderless => borderless = true,
|
||||
WindowFlag::Resizable => resizable = true,
|
||||
WindowFlag::Transparent => _transparent = true,
|
||||
WindowFlag::Unclosable => _unclosable = true,
|
||||
}
|
||||
}
|
||||
|
||||
let mut builder = unsafe { &*VIDEO_CTX }.window(title, w, h);
|
||||
|
||||
{
|
||||
builder.allow_highdpi();
|
||||
}
|
||||
|
||||
if borderless {
|
||||
builder.borderless();
|
||||
}
|
||||
|
||||
if resizable {
|
||||
builder.resizable();
|
||||
}
|
||||
|
||||
if x >= 0 || y >= 0 {
|
||||
builder.position(x, y);
|
||||
}
|
||||
|
||||
match builder.build() {
|
||||
Ok(window) => Some(Window {
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
t: title.to_string(),
|
||||
window_async,
|
||||
mode: Cell::new(Mode::Blend),
|
||||
inner: window.into_canvas().software().build().unwrap(),
|
||||
mouse_relative: false,
|
||||
drop_content: RefCell::new(None),
|
||||
}),
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn event_sender(&self) -> sdl2::event::EventSender {
|
||||
unsafe { &mut *SDL_CTX }.event().unwrap().event_sender()
|
||||
}
|
||||
|
||||
pub fn clipboard(&self) -> String {
|
||||
let result = unsafe { &*VIDEO_CTX }.clipboard().clipboard_text();
|
||||
|
||||
match result {
|
||||
Ok(value) => return value,
|
||||
Err(message) => println!("{}", message),
|
||||
}
|
||||
|
||||
String::default()
|
||||
}
|
||||
|
||||
pub fn set_clipboard(&mut self, text: &str) {
|
||||
let result = unsafe { &*VIDEO_CTX }.clipboard().set_clipboard_text(text);
|
||||
|
||||
if let Err(message) = result {
|
||||
println!("{}", message);
|
||||
}
|
||||
}
|
||||
|
||||
/// Pops the content of the last drop event from the window.
|
||||
pub fn pop_drop_content(&self) -> Option<String> {
|
||||
let result = self.drop_content.borrow().clone();
|
||||
*self.drop_content.borrow_mut() = None;
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn sync_path(&mut self) {
|
||||
let window = self.inner.window();
|
||||
let pos = window.position();
|
||||
let size = window.size();
|
||||
let title = window.title();
|
||||
self.x = pos.0;
|
||||
self.y = pos.1;
|
||||
self.w = size.0;
|
||||
self.h = size.1;
|
||||
self.t = title.to_string();
|
||||
}
|
||||
|
||||
/// Get x
|
||||
// TODO: Sync with window movements
|
||||
pub fn x(&self) -> i32 {
|
||||
self.x
|
||||
}
|
||||
|
||||
/// Get y
|
||||
// TODO: Sync with window movements
|
||||
pub fn y(&self) -> i32 {
|
||||
self.y
|
||||
}
|
||||
|
||||
/// Get title
|
||||
pub fn title(&self) -> String {
|
||||
self.t.clone()
|
||||
}
|
||||
|
||||
/// Get async
|
||||
pub fn is_async(&self) -> bool {
|
||||
self.window_async
|
||||
}
|
||||
|
||||
/// Set async
|
||||
pub fn set_async(&mut self, is_async: bool) {
|
||||
self.window_async = is_async;
|
||||
}
|
||||
|
||||
/// Set cursor visibility
|
||||
pub fn set_mouse_cursor(&mut self, visible: bool) {
|
||||
unsafe { &mut *SDL_CTX }.mouse().show_cursor(visible);
|
||||
}
|
||||
|
||||
/// Set mouse grabbing
|
||||
pub fn set_mouse_grab(&mut self, grab: bool) {
|
||||
unsafe { &mut *SDL_CTX }.mouse().capture(grab);
|
||||
}
|
||||
|
||||
/// Set mouse relative mode
|
||||
pub fn set_mouse_relative(&mut self, relative: bool) {
|
||||
unsafe { &mut *SDL_CTX }
|
||||
.mouse()
|
||||
.set_relative_mouse_mode(relative);
|
||||
self.mouse_relative = relative;
|
||||
}
|
||||
|
||||
/// Set position
|
||||
pub fn set_pos(&mut self, x: i32, y: i32) {
|
||||
self.inner.window_mut().set_position(
|
||||
sdl2::video::WindowPos::Positioned(x),
|
||||
sdl2::video::WindowPos::Positioned(y),
|
||||
);
|
||||
self.sync_path();
|
||||
}
|
||||
|
||||
/// Set size
|
||||
pub fn set_size(&mut self, width: u32, height: u32) {
|
||||
let _ = self.inner.window_mut().set_size(width, height);
|
||||
self.sync_path();
|
||||
}
|
||||
|
||||
/// Set title
|
||||
pub fn set_title(&mut self, title: &str) {
|
||||
let _ = self.inner.window_mut().set_title(title);
|
||||
self.sync_path();
|
||||
}
|
||||
|
||||
fn convert_scancode(
|
||||
&self,
|
||||
scancode_option: Option<sdl2::keyboard::Scancode>,
|
||||
shift: bool,
|
||||
) -> Option<(char, u8)> {
|
||||
if let Some(scancode) = scancode_option {
|
||||
match scancode {
|
||||
sdl2::keyboard::Scancode::A => Some((if shift { 'A' } else { 'a' }, K_A)),
|
||||
sdl2::keyboard::Scancode::B => Some((if shift { 'B' } else { 'b' }, K_B)),
|
||||
sdl2::keyboard::Scancode::C => Some((if shift { 'C' } else { 'c' }, K_C)),
|
||||
sdl2::keyboard::Scancode::D => Some((if shift { 'D' } else { 'd' }, K_D)),
|
||||
sdl2::keyboard::Scancode::E => Some((if shift { 'E' } else { 'e' }, K_E)),
|
||||
sdl2::keyboard::Scancode::F => Some((if shift { 'F' } else { 'f' }, K_F)),
|
||||
sdl2::keyboard::Scancode::G => Some((if shift { 'G' } else { 'g' }, K_G)),
|
||||
sdl2::keyboard::Scancode::H => Some((if shift { 'H' } else { 'h' }, K_H)),
|
||||
sdl2::keyboard::Scancode::I => Some((if shift { 'I' } else { 'i' }, K_I)),
|
||||
sdl2::keyboard::Scancode::J => Some((if shift { 'J' } else { 'j' }, K_J)),
|
||||
sdl2::keyboard::Scancode::K => Some((if shift { 'K' } else { 'k' }, K_K)),
|
||||
sdl2::keyboard::Scancode::L => Some((if shift { 'L' } else { 'l' }, K_L)),
|
||||
sdl2::keyboard::Scancode::M => Some((if shift { 'M' } else { 'm' }, K_M)),
|
||||
sdl2::keyboard::Scancode::N => Some((if shift { 'N' } else { 'n' }, K_N)),
|
||||
sdl2::keyboard::Scancode::O => Some((if shift { 'O' } else { 'o' }, K_O)),
|
||||
sdl2::keyboard::Scancode::P => Some((if shift { 'P' } else { 'p' }, K_P)),
|
||||
sdl2::keyboard::Scancode::Q => Some((if shift { 'Q' } else { 'q' }, K_Q)),
|
||||
sdl2::keyboard::Scancode::R => Some((if shift { 'R' } else { 'r' }, K_R)),
|
||||
sdl2::keyboard::Scancode::S => Some((if shift { 'S' } else { 's' }, K_S)),
|
||||
sdl2::keyboard::Scancode::T => Some((if shift { 'T' } else { 't' }, K_T)),
|
||||
sdl2::keyboard::Scancode::U => Some((if shift { 'U' } else { 'u' }, K_U)),
|
||||
sdl2::keyboard::Scancode::V => Some((if shift { 'V' } else { 'v' }, K_V)),
|
||||
sdl2::keyboard::Scancode::W => Some((if shift { 'W' } else { 'w' }, K_W)),
|
||||
sdl2::keyboard::Scancode::X => Some((if shift { 'X' } else { 'x' }, K_X)),
|
||||
sdl2::keyboard::Scancode::Y => Some((if shift { 'Y' } else { 'y' }, K_Y)),
|
||||
sdl2::keyboard::Scancode::Z => Some((if shift { 'Z' } else { 'z' }, K_Z)),
|
||||
sdl2::keyboard::Scancode::Num0 => Some((if shift { ')' } else { '0' }, K_0)),
|
||||
sdl2::keyboard::Scancode::Num1 => Some((if shift { '!' } else { '1' }, K_1)),
|
||||
sdl2::keyboard::Scancode::Num2 => Some((if shift { '@' } else { '2' }, K_2)),
|
||||
sdl2::keyboard::Scancode::Num3 => Some((if shift { '#' } else { '3' }, K_3)),
|
||||
sdl2::keyboard::Scancode::Num4 => Some((if shift { '$' } else { '4' }, K_4)),
|
||||
sdl2::keyboard::Scancode::Num5 => Some((if shift { '%' } else { '5' }, K_5)),
|
||||
sdl2::keyboard::Scancode::Num6 => Some((if shift { '^' } else { '6' }, K_6)),
|
||||
sdl2::keyboard::Scancode::Num7 => Some((if shift { '&' } else { '7' }, K_7)),
|
||||
sdl2::keyboard::Scancode::Num8 => Some((if shift { '*' } else { '8' }, K_8)),
|
||||
sdl2::keyboard::Scancode::Num9 => Some((if shift { '(' } else { '9' }, K_9)),
|
||||
sdl2::keyboard::Scancode::Grave => Some((if shift { '~' } else { '`' }, K_TICK)),
|
||||
sdl2::keyboard::Scancode::Minus => Some((if shift { '_' } else { '-' }, K_MINUS)),
|
||||
sdl2::keyboard::Scancode::Equals => Some((if shift { '+' } else { '=' }, K_EQUALS)),
|
||||
sdl2::keyboard::Scancode::LeftBracket => {
|
||||
Some((if shift { '{' } else { '[' }, K_BRACE_OPEN))
|
||||
}
|
||||
sdl2::keyboard::Scancode::RightBracket => {
|
||||
Some((if shift { '}' } else { ']' }, K_BRACE_CLOSE))
|
||||
}
|
||||
sdl2::keyboard::Scancode::Backslash => {
|
||||
Some((if shift { '|' } else { '\\' }, K_BACKSLASH))
|
||||
}
|
||||
sdl2::keyboard::Scancode::Semicolon => {
|
||||
Some((if shift { ':' } else { ';' }, K_SEMICOLON))
|
||||
}
|
||||
sdl2::keyboard::Scancode::Apostrophe => {
|
||||
Some((if shift { '"' } else { '\'' }, K_QUOTE))
|
||||
}
|
||||
sdl2::keyboard::Scancode::Comma => Some((if shift { '<' } else { ',' }, K_COMMA)),
|
||||
sdl2::keyboard::Scancode::Period => Some((if shift { '>' } else { '.' }, K_PERIOD)),
|
||||
sdl2::keyboard::Scancode::Slash => Some((if shift { '?' } else { '/' }, K_SLASH)),
|
||||
sdl2::keyboard::Scancode::Space => Some((' ', K_SPACE)),
|
||||
sdl2::keyboard::Scancode::Backspace => Some(('\0', K_BKSP)),
|
||||
sdl2::keyboard::Scancode::Tab => Some(('\t', K_TAB)),
|
||||
sdl2::keyboard::Scancode::LCtrl => Some(('\0', K_CTRL)),
|
||||
sdl2::keyboard::Scancode::RCtrl => Some(('\0', K_CTRL)),
|
||||
sdl2::keyboard::Scancode::LAlt => Some(('\0', K_ALT)),
|
||||
sdl2::keyboard::Scancode::RAlt => Some(('\0', K_ALT)),
|
||||
sdl2::keyboard::Scancode::Return => Some(('\n', K_ENTER)),
|
||||
sdl2::keyboard::Scancode::Escape => Some(('\x1B', K_ESC)),
|
||||
sdl2::keyboard::Scancode::F1 => Some(('\0', K_F1)),
|
||||
sdl2::keyboard::Scancode::F2 => Some(('\0', K_F2)),
|
||||
sdl2::keyboard::Scancode::F3 => Some(('\0', K_F3)),
|
||||
sdl2::keyboard::Scancode::F4 => Some(('\0', K_F4)),
|
||||
sdl2::keyboard::Scancode::F5 => Some(('\0', K_F5)),
|
||||
sdl2::keyboard::Scancode::F6 => Some(('\0', K_F6)),
|
||||
sdl2::keyboard::Scancode::F7 => Some(('\0', K_F7)),
|
||||
sdl2::keyboard::Scancode::F8 => Some(('\0', K_F8)),
|
||||
sdl2::keyboard::Scancode::F9 => Some(('\0', K_F9)),
|
||||
sdl2::keyboard::Scancode::F10 => Some(('\0', K_F10)),
|
||||
sdl2::keyboard::Scancode::Home => Some(('\0', K_HOME)),
|
||||
sdl2::keyboard::Scancode::LGui => Some(('\0', K_HOME)),
|
||||
sdl2::keyboard::Scancode::Up => Some(('\0', K_UP)),
|
||||
sdl2::keyboard::Scancode::PageUp => Some(('\0', K_PGUP)),
|
||||
sdl2::keyboard::Scancode::Left => Some(('\0', K_LEFT)),
|
||||
sdl2::keyboard::Scancode::Right => Some(('\0', K_RIGHT)),
|
||||
sdl2::keyboard::Scancode::End => Some(('\0', K_END)),
|
||||
sdl2::keyboard::Scancode::Down => Some(('\0', K_DOWN)),
|
||||
sdl2::keyboard::Scancode::PageDown => Some(('\0', K_PGDN)),
|
||||
sdl2::keyboard::Scancode::Delete => Some(('\0', K_DEL)),
|
||||
sdl2::keyboard::Scancode::F11 => Some(('\0', K_F11)),
|
||||
sdl2::keyboard::Scancode::F12 => Some(('\0', K_F12)),
|
||||
sdl2::keyboard::Scancode::LShift => Some(('\0', K_LEFT_SHIFT)),
|
||||
sdl2::keyboard::Scancode::RShift => Some(('\0', K_RIGHT_SHIFT)),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mouse_position(&self) -> (i32, i32) {
|
||||
unsafe {
|
||||
let p_x: *mut i32 = libc::malloc(mem::size_of::<i32>()) as *mut i32;
|
||||
let p_y: *mut i32 = libc::malloc(mem::size_of::<i32>()) as *mut i32;
|
||||
sdl2_sys::SDL_GetMouseState(p_x, p_y);
|
||||
|
||||
(*p_x, *p_y)
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_event(&self, event: sdl2::event::Event) -> Vec<Event> {
|
||||
let mut events = Vec::new();
|
||||
|
||||
let button_event = || -> Event {
|
||||
let mouse = unsafe { &mut *EVENT_PUMP }.mouse_state();
|
||||
ButtonEvent {
|
||||
left: mouse.left(),
|
||||
middle: mouse.middle(),
|
||||
right: mouse.right(),
|
||||
}
|
||||
.to_event()
|
||||
};
|
||||
|
||||
let mods = unsafe { &mut *SDL_CTX }.keyboard().mod_state();
|
||||
let shift = mods.contains(sdl2::keyboard::Mod::CAPSMOD)
|
||||
|| mods.contains(sdl2::keyboard::Mod::LSHIFTMOD)
|
||||
|| mods.contains(sdl2::keyboard::Mod::RSHIFTMOD);
|
||||
|
||||
match event {
|
||||
sdl2::event::Event::RenderTargetsReset { .. } => {
|
||||
events.push(Event::new());
|
||||
}
|
||||
sdl2::event::Event::Window { win_event, .. } => match win_event {
|
||||
sdl2::event::WindowEvent::Moved(x, y) => {
|
||||
events.push(MoveEvent { x, y }.to_event())
|
||||
}
|
||||
sdl2::event::WindowEvent::Resized(w, h) => events.push(
|
||||
ResizeEvent {
|
||||
width: w as u32,
|
||||
height: h as u32,
|
||||
}
|
||||
.to_event(),
|
||||
),
|
||||
sdl2::event::WindowEvent::FocusGained => {
|
||||
events.push(FocusEvent { focused: true }.to_event())
|
||||
}
|
||||
sdl2::event::WindowEvent::FocusLost => {
|
||||
events.push(FocusEvent { focused: false }.to_event())
|
||||
}
|
||||
sdl2::event::WindowEvent::Enter => {
|
||||
events.push(HoverEvent { entered: true }.to_event())
|
||||
}
|
||||
sdl2::event::WindowEvent::Leave => {
|
||||
events.push(HoverEvent { entered: false }.to_event())
|
||||
}
|
||||
sdl2::event::WindowEvent::None => events.push(Event::new()),
|
||||
_ => (),
|
||||
},
|
||||
sdl2::event::Event::ClipboardUpdate { .. } => {
|
||||
events.push(ClipboardUpdateEvent.to_event())
|
||||
}
|
||||
sdl2::event::Event::MouseMotion {
|
||||
x, y, xrel, yrel, ..
|
||||
} => {
|
||||
if self.mouse_relative {
|
||||
events.push(MouseRelativeEvent { dx: xrel, dy: yrel }.to_event())
|
||||
} else {
|
||||
events.push(MouseEvent { x, y }.to_event())
|
||||
}
|
||||
}
|
||||
sdl2::event::Event::MouseButtonDown { .. } => events.push(button_event()),
|
||||
sdl2::event::Event::MouseButtonUp { .. } => events.push(button_event()),
|
||||
sdl2::event::Event::MouseWheel { x, y, .. } => {
|
||||
events.push(ScrollEvent { x, y }.to_event())
|
||||
}
|
||||
sdl2::event::Event::TextInput { text, .. } => {
|
||||
for character in text.chars() {
|
||||
events.push(
|
||||
TextInputEvent {
|
||||
character,
|
||||
}
|
||||
.to_event(),
|
||||
);
|
||||
}
|
||||
}
|
||||
sdl2::event::Event::KeyDown { scancode, .. } => {
|
||||
if let Some(code) = self.convert_scancode(scancode, shift) {
|
||||
events.push(
|
||||
KeyEvent {
|
||||
character: code.0,
|
||||
scancode: code.1,
|
||||
pressed: true,
|
||||
}
|
||||
.to_event(),
|
||||
);
|
||||
}
|
||||
}
|
||||
sdl2::event::Event::DropFile { filename, .. } => {
|
||||
*self.drop_content.borrow_mut() = Some(filename);
|
||||
|
||||
let (x, y) = self.get_mouse_position();
|
||||
|
||||
events.push(MouseEvent { x, y }.to_event());
|
||||
|
||||
events.push(DropEvent { kind: DROP_FILE }.to_event())
|
||||
}
|
||||
sdl2::event::Event::DropText { filename, .. } => {
|
||||
*self.drop_content.borrow_mut() = Some(filename);
|
||||
|
||||
let (x, y) = self.get_mouse_position();
|
||||
|
||||
events.push(MouseEvent { x, y }.to_event());
|
||||
events.push(DropEvent { kind: DROP_TEXT }.to_event())
|
||||
}
|
||||
sdl2::event::Event::KeyUp { scancode, .. } => {
|
||||
if let Some(code) = self.convert_scancode(scancode, shift) {
|
||||
events.push(
|
||||
KeyEvent {
|
||||
character: code.0,
|
||||
scancode: code.1,
|
||||
pressed: false,
|
||||
}
|
||||
.to_event(),
|
||||
);
|
||||
}
|
||||
}
|
||||
sdl2::event::Event::Quit { .. } => events.push(QuitEvent.to_event()),
|
||||
_ => (),
|
||||
}
|
||||
|
||||
events
|
||||
}
|
||||
|
||||
/// Blocking iterator over events
|
||||
pub fn events(&mut self) -> EventIter {
|
||||
let mut iter = EventIter {
|
||||
events: [Event::new(); 16],
|
||||
i: 0,
|
||||
count: 0,
|
||||
};
|
||||
|
||||
if !self.window_async {
|
||||
let event = unsafe { &mut *EVENT_PUMP }.wait_event();
|
||||
if let sdl2::event::Event::Window { .. } = event {
|
||||
self.sync_path();
|
||||
}
|
||||
for converted_event in self.convert_event(event) {
|
||||
if iter.count < iter.events.len() {
|
||||
iter.events[iter.count] = converted_event;
|
||||
iter.count += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while let Some(event) = unsafe { &mut *EVENT_PUMP }.poll_event() {
|
||||
if let sdl2::event::Event::Window { .. } = event {
|
||||
self.sync_path();
|
||||
}
|
||||
for converted_event in self.convert_event(event) {
|
||||
if iter.count < iter.events.len() {
|
||||
iter.events[iter.count] = converted_event;
|
||||
iter.count += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if iter.count + 2 < iter.events.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iter
|
||||
}
|
||||
|
||||
/// Returns the id
|
||||
pub fn id(&self) -> u32 {
|
||||
self.inner.window().id()
|
||||
}
|
||||
}
|
||||
|
||||
/// Event iterator
|
||||
pub struct EventIter {
|
||||
events: [Event; 16],
|
||||
i: usize,
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl Iterator for EventIter {
|
||||
type Item = Event;
|
||||
fn next(&mut self) -> Option<Event> {
|
||||
if self.i < self.count {
|
||||
if let Some(event) = self.events.get(self.i) {
|
||||
self.i += 1;
|
||||
Some(*event)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue