Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
389
third-party/vendor/tiny-skia-path/src/lib.rs
vendored
Normal file
389
third-party/vendor/tiny-skia-path/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,389 @@
|
|||
// Copyright 2006 The Android Open Source Project
|
||||
// Copyright 2020 Yevhenii Reizner
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
//! A [tiny-skia](https://github.com/RazrFalcon/tiny-skia) Bezier path implementation.
|
||||
//!
|
||||
//! Provides a memory-efficient Bezier path container, path builder, path stroker and path dasher.
|
||||
//!
|
||||
//! Also provides some basic geometry types, but they will be moved to an external crate eventually.
|
||||
//!
|
||||
//! Note that all types use single precision floats (`f32`), just like [Skia](https://skia.org/).
|
||||
|
||||
#![no_std]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(missing_copy_implementations)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![allow(clippy::approx_constant)]
|
||||
#![allow(clippy::collapsible_if)]
|
||||
#![allow(clippy::eq_op)]
|
||||
#![allow(clippy::excessive_precision)]
|
||||
#![allow(clippy::identity_op)]
|
||||
#![allow(clippy::manual_range_contains)]
|
||||
#![allow(clippy::neg_cmp_op_on_partial_ord)]
|
||||
#![allow(clippy::too_many_arguments)]
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![allow(clippy::wrong_self_convention)]
|
||||
|
||||
#[cfg(not(any(feature = "std", feature = "no-std-float")))]
|
||||
compile_error!("You have to activate either the `std` or the `no-std-float` feature.");
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
extern crate std;
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
mod dash;
|
||||
mod f32x2_t;
|
||||
mod f32x4_t;
|
||||
mod floating_point;
|
||||
mod path;
|
||||
mod path_builder;
|
||||
pub mod path_geometry;
|
||||
mod rect;
|
||||
mod scalar;
|
||||
mod stroker;
|
||||
mod transform;
|
||||
|
||||
pub use dash::StrokeDash;
|
||||
pub use f32x2_t::f32x2;
|
||||
pub use floating_point::*;
|
||||
pub use path::*;
|
||||
pub use path_builder::*;
|
||||
pub use rect::*;
|
||||
pub use scalar::*;
|
||||
pub use stroker::*;
|
||||
pub use transform::*;
|
||||
|
||||
/// An integer length that is guarantee to be > 0
|
||||
type LengthU32 = core::num::NonZeroU32;
|
||||
|
||||
/// A point.
|
||||
///
|
||||
/// Doesn't guarantee to be finite.
|
||||
#[allow(missing_docs)]
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, PartialEq, Default, Debug)]
|
||||
pub struct Point {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
}
|
||||
|
||||
impl From<(f32, f32)> for Point {
|
||||
#[inline]
|
||||
fn from(v: (f32, f32)) -> Self {
|
||||
Point { x: v.0, y: v.1 }
|
||||
}
|
||||
}
|
||||
|
||||
impl Point {
|
||||
/// Creates a new `Point`.
|
||||
pub fn from_xy(x: f32, y: f32) -> Self {
|
||||
Point { x, y }
|
||||
}
|
||||
|
||||
/// Creates a new `Point` from `f32x2`.
|
||||
pub fn from_f32x2(r: f32x2) -> Self {
|
||||
Point::from_xy(r.x(), r.y())
|
||||
}
|
||||
|
||||
/// Converts a `Point` into a `f32x2`.
|
||||
pub fn to_f32x2(&self) -> f32x2 {
|
||||
f32x2::new(self.x, self.y)
|
||||
}
|
||||
|
||||
/// Creates a point at 0x0 position.
|
||||
pub fn zero() -> Self {
|
||||
Point { x: 0.0, y: 0.0 }
|
||||
}
|
||||
|
||||
/// Returns true if x and y are both zero.
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.x == 0.0 && self.y == 0.0
|
||||
}
|
||||
|
||||
/// Returns true if both x and y are measurable values.
|
||||
///
|
||||
/// Both values are other than infinities and NaN.
|
||||
pub fn is_finite(&self) -> bool {
|
||||
(self.x * self.y).is_finite()
|
||||
}
|
||||
|
||||
/// Checks that two `Point`s are almost equal.
|
||||
pub(crate) fn almost_equal(&self, other: Point) -> bool {
|
||||
!(*self - other).can_normalize()
|
||||
}
|
||||
|
||||
/// Checks that two `Point`s are almost equal using the specified tolerance.
|
||||
pub(crate) fn equals_within_tolerance(&self, other: Point, tolerance: f32) -> bool {
|
||||
(self.x - other.x).is_nearly_zero_within_tolerance(tolerance)
|
||||
&& (self.y - other.y).is_nearly_zero_within_tolerance(tolerance)
|
||||
}
|
||||
|
||||
/// Scales (fX, fY) so that length() returns one, while preserving ratio of fX to fY,
|
||||
/// if possible.
|
||||
///
|
||||
/// If prior length is nearly zero, sets vector to (0, 0) and returns
|
||||
/// false; otherwise returns true.
|
||||
pub fn normalize(&mut self) -> bool {
|
||||
self.set_length_from(self.x, self.y, 1.0)
|
||||
}
|
||||
|
||||
/// Sets vector to (x, y) scaled so length() returns one, and so that (x, y)
|
||||
/// is proportional to (x, y).
|
||||
///
|
||||
/// If (x, y) length is nearly zero, sets vector to (0, 0) and returns false;
|
||||
/// otherwise returns true.
|
||||
pub fn set_normalize(&mut self, x: f32, y: f32) -> bool {
|
||||
self.set_length_from(x, y, 1.0)
|
||||
}
|
||||
|
||||
pub(crate) fn can_normalize(&self) -> bool {
|
||||
self.x.is_finite() && self.y.is_finite() && (self.x != 0.0 || self.y != 0.0)
|
||||
}
|
||||
|
||||
/// Returns the Euclidean distance from origin.
|
||||
pub fn length(&self) -> f32 {
|
||||
let mag2 = self.x * self.x + self.y * self.y;
|
||||
if mag2.is_finite() {
|
||||
mag2.sqrt()
|
||||
} else {
|
||||
let xx = f64::from(self.x);
|
||||
let yy = f64::from(self.y);
|
||||
(xx * xx + yy * yy).sqrt() as f32
|
||||
}
|
||||
}
|
||||
|
||||
/// Scales vector so that distanceToOrigin() returns length, if possible.
|
||||
///
|
||||
/// If former length is nearly zero, sets vector to (0, 0) and return false;
|
||||
/// otherwise returns true.
|
||||
pub fn set_length(&mut self, length: f32) -> bool {
|
||||
self.set_length_from(self.x, self.y, length)
|
||||
}
|
||||
|
||||
/// Sets vector to (x, y) scaled to length, if possible.
|
||||
///
|
||||
/// If former length is nearly zero, sets vector to (0, 0) and return false;
|
||||
/// otherwise returns true.
|
||||
pub fn set_length_from(&mut self, x: f32, y: f32, length: f32) -> bool {
|
||||
set_point_length(self, x, y, length, &mut None)
|
||||
}
|
||||
|
||||
/// Returns the Euclidean distance from origin.
|
||||
pub fn distance(&self, other: Point) -> f32 {
|
||||
(*self - other).length()
|
||||
}
|
||||
|
||||
/// Returns the dot product of two points.
|
||||
pub fn dot(&self, other: Point) -> f32 {
|
||||
self.x * other.x + self.y * other.y
|
||||
}
|
||||
|
||||
/// Returns the cross product of vector and vec.
|
||||
///
|
||||
/// Vector and vec form three-dimensional vectors with z-axis value equal to zero.
|
||||
/// The cross product is a three-dimensional vector with x-axis and y-axis values
|
||||
/// equal to zero. The cross product z-axis component is returned.
|
||||
pub fn cross(&self, other: Point) -> f32 {
|
||||
self.x * other.y - self.y * other.x
|
||||
}
|
||||
|
||||
pub(crate) fn distance_to_sqd(&self, pt: Point) -> f32 {
|
||||
let dx = self.x - pt.x;
|
||||
let dy = self.y - pt.y;
|
||||
dx * dx + dy * dy
|
||||
}
|
||||
|
||||
pub(crate) fn length_sqd(&self) -> f32 {
|
||||
self.dot(*self)
|
||||
}
|
||||
|
||||
/// Scales Point in-place by scale.
|
||||
pub fn scale(&mut self, scale: f32) {
|
||||
self.x *= scale;
|
||||
self.y *= scale;
|
||||
}
|
||||
|
||||
pub(crate) fn scaled(&self, scale: f32) -> Self {
|
||||
Point::from_xy(self.x * scale, self.y * scale)
|
||||
}
|
||||
|
||||
pub(crate) fn swap_coords(&mut self) {
|
||||
core::mem::swap(&mut self.x, &mut self.y);
|
||||
}
|
||||
|
||||
pub(crate) fn rotate_cw(&mut self) {
|
||||
self.swap_coords();
|
||||
self.x = -self.x;
|
||||
}
|
||||
|
||||
pub(crate) fn rotate_ccw(&mut self) {
|
||||
self.swap_coords();
|
||||
self.y = -self.y;
|
||||
}
|
||||
}
|
||||
|
||||
// We have to worry about 2 tricky conditions:
|
||||
// 1. underflow of mag2 (compared against nearlyzero^2)
|
||||
// 2. overflow of mag2 (compared w/ isfinite)
|
||||
//
|
||||
// If we underflow, we return false. If we overflow, we compute again using
|
||||
// doubles, which is much slower (3x in a desktop test) but will not overflow.
|
||||
fn set_point_length(
|
||||
pt: &mut Point,
|
||||
mut x: f32,
|
||||
mut y: f32,
|
||||
length: f32,
|
||||
orig_length: &mut Option<f32>,
|
||||
) -> bool {
|
||||
// our mag2 step overflowed to infinity, so use doubles instead.
|
||||
// much slower, but needed when x or y are very large, other wise we
|
||||
// divide by inf. and return (0,0) vector.
|
||||
let xx = x as f64;
|
||||
let yy = y as f64;
|
||||
let dmag = (xx * xx + yy * yy).sqrt();
|
||||
let dscale = length as f64 / dmag;
|
||||
x *= dscale as f32;
|
||||
y *= dscale as f32;
|
||||
|
||||
// check if we're not finite, or we're zero-length
|
||||
if !x.is_finite() || !y.is_finite() || (x == 0.0 && y == 0.0) {
|
||||
*pt = Point::zero();
|
||||
return false;
|
||||
}
|
||||
|
||||
let mut mag = 0.0;
|
||||
if orig_length.is_some() {
|
||||
mag = dmag as f32;
|
||||
}
|
||||
|
||||
*pt = Point::from_xy(x, y);
|
||||
|
||||
if orig_length.is_some() {
|
||||
*orig_length = Some(mag);
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
impl core::ops::Neg for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn neg(self) -> Self::Output {
|
||||
Point {
|
||||
x: -self.x,
|
||||
y: -self.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Add for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn add(self, other: Point) -> Self::Output {
|
||||
Point::from_xy(self.x + other.x, self.y + other.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::AddAssign for Point {
|
||||
fn add_assign(&mut self, other: Point) {
|
||||
self.x += other.x;
|
||||
self.y += other.y;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Sub for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn sub(self, other: Point) -> Self::Output {
|
||||
Point::from_xy(self.x - other.x, self.y - other.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::SubAssign for Point {
|
||||
fn sub_assign(&mut self, other: Point) {
|
||||
self.x -= other.x;
|
||||
self.y -= other.y;
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::Mul for Point {
|
||||
type Output = Point;
|
||||
|
||||
fn mul(self, other: Point) -> Self::Output {
|
||||
Point::from_xy(self.x * other.x, self.y * other.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::ops::MulAssign for Point {
|
||||
fn mul_assign(&mut self, other: Point) {
|
||||
self.x *= other.x;
|
||||
self.y *= other.y;
|
||||
}
|
||||
}
|
||||
|
||||
/// An integer size.
|
||||
///
|
||||
/// # Guarantees
|
||||
///
|
||||
/// - Width and height are positive and non-zero.
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub struct IntSize {
|
||||
width: LengthU32,
|
||||
height: LengthU32,
|
||||
}
|
||||
|
||||
impl IntSize {
|
||||
/// Creates a new `IntSize` from width and height.
|
||||
pub fn from_wh(width: u32, height: u32) -> Option<Self> {
|
||||
Some(IntSize {
|
||||
width: LengthU32::new(width)?,
|
||||
height: LengthU32::new(height)?,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns width.
|
||||
pub fn width(&self) -> u32 {
|
||||
self.width.get()
|
||||
}
|
||||
|
||||
/// Returns height.
|
||||
pub fn height(&self) -> u32 {
|
||||
self.height.get()
|
||||
}
|
||||
|
||||
/// Converts the current size into a `IntRect` at a provided position.
|
||||
pub fn to_int_rect(&self, x: i32, y: i32) -> IntRect {
|
||||
IntRect::from_xywh(x, y, self.width.get(), self.height.get()).unwrap()
|
||||
}
|
||||
|
||||
/// Converts the current size into a `IntRect` at a provided position.
|
||||
pub fn to_screen_int_rect(&self, x: u32, y: u32) -> ScreenIntRect {
|
||||
ScreenIntRect::from_xywh_safe(x, y, self.width, self.height)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn int_size_tests() {
|
||||
assert_eq!(IntSize::from_wh(0, 0), None);
|
||||
assert_eq!(IntSize::from_wh(1, 0), None);
|
||||
assert_eq!(IntSize::from_wh(0, 1), None);
|
||||
|
||||
let size = IntSize::from_wh(3, 4).unwrap();
|
||||
assert_eq!(
|
||||
size.to_int_rect(1, 2),
|
||||
IntRect::from_xywh(1, 2, 3, 4).unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
size.to_screen_int_rect(1, 2),
|
||||
ScreenIntRect::from_xywh(1, 2, 3, 4).unwrap()
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue