Add `emath::OrderedFloat` (moved from `epaint::util::OrderedFloat`) (#4389)
It makes much more sense in `emath`
This commit is contained in:
parent
46b241eb94
commit
87b294534e
|
|
@ -1242,6 +1242,7 @@ dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"document-features",
|
"document-features",
|
||||||
|
"emath",
|
||||||
"epaint",
|
"epaint",
|
||||||
"log",
|
"log",
|
||||||
"nohash-hasher",
|
"nohash-hasher",
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ impl std::ops::IndexMut<usize> for Rgba {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Deterministically hash an `f32`, treating all NANs as equal, and ignoring the sign of zero.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn f32_hash<H: std::hash::Hasher>(state: &mut H, f: f32) {
|
pub(crate) fn f32_hash<H: std::hash::Hasher>(state: &mut H, f: f32) {
|
||||||
if f == 0.0 {
|
if f == 0.0 {
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ unity = ["epaint/unity"]
|
||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
emath = { workspace = true, default-features = false }
|
||||||
epaint = { workspace = true, default-features = false }
|
epaint = { workspace = true, default-features = false }
|
||||||
|
|
||||||
ahash.workspace = true
|
ahash.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -55,23 +55,21 @@
|
||||||
mod bytes_loader;
|
mod bytes_loader;
|
||||||
mod texture_loader;
|
mod texture_loader;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::{
|
||||||
use std::fmt::Debug;
|
borrow::Cow,
|
||||||
use std::ops::Deref;
|
fmt::{Debug, Display},
|
||||||
use std::{fmt::Display, sync::Arc};
|
ops::Deref,
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use ahash::HashMap;
|
use ahash::HashMap;
|
||||||
|
|
||||||
use epaint::mutex::Mutex;
|
use emath::{Float, OrderedFloat};
|
||||||
use epaint::util::FloatOrd;
|
use epaint::{mutex::Mutex, textures::TextureOptions, ColorImage, TextureHandle, TextureId, Vec2};
|
||||||
use epaint::util::OrderedFloat;
|
|
||||||
use epaint::TextureHandle;
|
|
||||||
use epaint::{textures::TextureOptions, ColorImage, TextureId, Vec2};
|
|
||||||
|
|
||||||
use crate::Context;
|
use crate::Context;
|
||||||
|
|
||||||
pub use self::bytes_loader::DefaultBytesLoader;
|
pub use self::{bytes_loader::DefaultBytesLoader, texture_loader::DefaultTextureLoader};
|
||||||
pub use self::texture_loader::DefaultTextureLoader;
|
|
||||||
|
|
||||||
/// Represents a failed attempt at loading an image.
|
/// Represents a failed attempt at loading an image.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use crate::load::TextureLoadResult;
|
use emath::{Float as _, Rot2};
|
||||||
|
use epaint::RectShape;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
load::{Bytes, SizeHint, SizedTexture, TexturePoll},
|
load::{Bytes, SizeHint, SizedTexture, TextureLoadResult, TexturePoll},
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
use emath::Rot2;
|
|
||||||
use epaint::{util::FloatOrd, RectShape};
|
|
||||||
|
|
||||||
/// A widget which displays an image.
|
/// A widget which displays an image.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
use epaint::{emath::Rot2, util::FloatOrd, Mesh};
|
use epaint::{emath::Rot2, Mesh};
|
||||||
|
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ use std::{cmp::Ordering, ops::RangeInclusive, sync::Arc};
|
||||||
|
|
||||||
use egui::ahash::HashMap;
|
use egui::ahash::HashMap;
|
||||||
use egui::*;
|
use egui::*;
|
||||||
use epaint::{util::FloatOrd, Hsva};
|
use emath::Float as _;
|
||||||
|
use epaint::Hsva;
|
||||||
|
|
||||||
pub use crate::{
|
pub use crate::{
|
||||||
axis::{Axis, AxisHints, HPlacement, Placement, VPlacement},
|
axis::{Axis, AxisHints, HPlacement, Placement, VPlacement},
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ use std::ops::{Add, Div, Mul, RangeInclusive, Sub};
|
||||||
pub mod align;
|
pub mod align;
|
||||||
mod history;
|
mod history;
|
||||||
mod numeric;
|
mod numeric;
|
||||||
|
mod ordered_float;
|
||||||
mod pos2;
|
mod pos2;
|
||||||
mod range;
|
mod range;
|
||||||
mod rect;
|
mod rect;
|
||||||
|
|
@ -40,10 +41,11 @@ mod ts_transform;
|
||||||
mod vec2;
|
mod vec2;
|
||||||
mod vec2b;
|
mod vec2b;
|
||||||
|
|
||||||
pub use {
|
pub use self::{
|
||||||
align::{Align, Align2},
|
align::{Align, Align2},
|
||||||
history::History,
|
history::History,
|
||||||
numeric::*,
|
numeric::*,
|
||||||
|
ordered_float::*,
|
||||||
pos2::*,
|
pos2::*,
|
||||||
range::Rangef,
|
range::Rangef,
|
||||||
rect::*,
|
rect::*,
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,12 @@ use std::hash::{Hash, Hasher};
|
||||||
/// Wraps a floating-point value to add total order and hash.
|
/// Wraps a floating-point value to add total order and hash.
|
||||||
/// Possible types for `T` are `f32` and `f64`.
|
/// Possible types for `T` are `f32` and `f64`.
|
||||||
///
|
///
|
||||||
/// See also [`FloatOrd`].
|
/// All NaNs are considered equal to each other.
|
||||||
|
/// The size of zero is ignored.
|
||||||
|
///
|
||||||
|
/// See also [`Float`].
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct OrderedFloat<T>(T);
|
pub struct OrderedFloat<T>(pub T);
|
||||||
|
|
||||||
impl<T: Float + Copy> OrderedFloat<T> {
|
impl<T: Float + Copy> OrderedFloat<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
@ -68,44 +71,34 @@ impl<T> From<T> for OrderedFloat<T> {
|
||||||
///
|
///
|
||||||
/// Example with `f64`:
|
/// Example with `f64`:
|
||||||
/// ```
|
/// ```
|
||||||
/// use epaint::util::FloatOrd;
|
/// use emath::Float as _;
|
||||||
///
|
///
|
||||||
/// let array = [1.0, 2.5, 2.0];
|
/// let array = [1.0, 2.5, 2.0];
|
||||||
/// let max = array.iter().max_by_key(|val| val.ord());
|
/// let max = array.iter().max_by_key(|val| val.ord());
|
||||||
///
|
///
|
||||||
/// assert_eq!(max, Some(&2.5));
|
/// assert_eq!(max, Some(&2.5));
|
||||||
/// ```
|
/// ```
|
||||||
pub trait FloatOrd {
|
pub trait Float: PartialOrd + PartialEq + private::FloatImpl {
|
||||||
/// Type to provide total order, useful as key in sorted contexts.
|
/// Type to provide total order, useful as key in sorted contexts.
|
||||||
fn ord(self) -> OrderedFloat<Self>
|
fn ord(self) -> OrderedFloat<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatOrd for f32 {
|
impl Float for f32 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ord(self) -> OrderedFloat<Self> {
|
fn ord(self) -> OrderedFloat<Self> {
|
||||||
OrderedFloat(self)
|
OrderedFloat(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatOrd for f64 {
|
impl Float for f64 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ord(self) -> OrderedFloat<Self> {
|
fn ord(self) -> OrderedFloat<Self> {
|
||||||
OrderedFloat(self)
|
OrderedFloat(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// Internal abstraction over floating point types
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub trait Float: PartialOrd + PartialEq + private::FloatImpl {}
|
|
||||||
|
|
||||||
impl Float for f32 {}
|
|
||||||
|
|
||||||
impl Float for f64 {}
|
|
||||||
|
|
||||||
// Keep this trait in private module, to avoid exposing its methods as extensions in user code
|
// Keep this trait in private module, to avoid exposing its methods as extensions in user code
|
||||||
mod private {
|
mod private {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
@ -124,7 +117,13 @@ mod private {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
crate::f32_hash(state, *self);
|
if *self == 0.0 {
|
||||||
|
state.write_u8(0);
|
||||||
|
} else if self.is_nan() {
|
||||||
|
state.write_u8(1);
|
||||||
|
} else {
|
||||||
|
self.to_bits().hash(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +135,13 @@ mod private {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
crate::f64_hash(state, *self);
|
if *self == 0.0 {
|
||||||
|
state.write_u8(0);
|
||||||
|
} else if self.is_nan() {
|
||||||
|
state.write_u8(1);
|
||||||
|
} else {
|
||||||
|
self.to_bits().hash(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -152,32 +152,6 @@ macro_rules! epaint_assert {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) fn f32_hash<H: std::hash::Hasher>(state: &mut H, f: f32) {
|
|
||||||
if f == 0.0 {
|
|
||||||
state.write_u8(0);
|
|
||||||
} else if f.is_nan() {
|
|
||||||
state.write_u8(1);
|
|
||||||
} else {
|
|
||||||
use std::hash::Hash;
|
|
||||||
f.to_bits().hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) fn f64_hash<H: std::hash::Hasher>(state: &mut H, f: f64) {
|
|
||||||
if f == 0.0 {
|
|
||||||
state.write_u8(0);
|
|
||||||
} else if f.is_nan() {
|
|
||||||
state.write_u8(1);
|
|
||||||
} else {
|
|
||||||
use std::hash::Hash;
|
|
||||||
f.to_bits().hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/// Was epaint compiled with the `rayon` feature?
|
/// Was epaint compiled with the `rayon` feature?
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ impl std::hash::Hash for Stroke {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
let Self { width, color } = *self;
|
let Self { width, color } = *self;
|
||||||
crate::f32_hash(state, width);
|
emath::OrderedFloat(width).hash(state);
|
||||||
color.hash(state);
|
color.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
TextureAtlas,
|
TextureAtlas,
|
||||||
};
|
};
|
||||||
use emath::NumExt as _;
|
use emath::{NumExt as _, OrderedFloat};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -56,7 +56,7 @@ impl std::hash::Hash for FontId {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
let Self { size, family } = self;
|
let Self { size, family } = self;
|
||||||
crate::f32_hash(state, *size);
|
emath::OrderedFloat(*size).hash(state);
|
||||||
family.hash(state);
|
family.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -567,21 +567,6 @@ impl FontsAndCache {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
||||||
struct HashableF32(f32);
|
|
||||||
|
|
||||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
|
||||||
impl std::hash::Hash for HashableF32 {
|
|
||||||
#[inline(always)]
|
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
||||||
crate::f32_hash(state, self.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Eq for HashableF32 {}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
/// The collection of fonts used by `epaint`.
|
/// The collection of fonts used by `epaint`.
|
||||||
///
|
///
|
||||||
/// Required in order to paint text.
|
/// Required in order to paint text.
|
||||||
|
|
@ -591,7 +576,7 @@ pub struct FontsImpl {
|
||||||
definitions: FontDefinitions,
|
definitions: FontDefinitions,
|
||||||
atlas: Arc<Mutex<TextureAtlas>>,
|
atlas: Arc<Mutex<TextureAtlas>>,
|
||||||
font_impl_cache: FontImplCache,
|
font_impl_cache: FontImplCache,
|
||||||
sized_family: ahash::HashMap<(HashableF32, FontFamily), Font>,
|
sized_family: ahash::HashMap<(OrderedFloat<f32>, FontFamily), Font>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontsImpl {
|
impl FontsImpl {
|
||||||
|
|
@ -641,7 +626,7 @@ impl FontsImpl {
|
||||||
let FontId { size, family } = font_id;
|
let FontId { size, family } = font_id;
|
||||||
|
|
||||||
self.sized_family
|
self.sized_family
|
||||||
.entry((HashableF32(*size), family.clone()))
|
.entry((OrderedFloat(*size), family.clone()))
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| {
|
||||||
let fonts = &self.definitions.families.get(family);
|
let fonts = &self.definitions.families.get(family);
|
||||||
let fonts = fonts
|
let fonts = fonts
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ impl std::hash::Hash for LayoutJob {
|
||||||
text.hash(state);
|
text.hash(state);
|
||||||
sections.hash(state);
|
sections.hash(state);
|
||||||
wrap.hash(state);
|
wrap.hash(state);
|
||||||
crate::f32_hash(state, *first_row_min_height);
|
emath::OrderedFloat(*first_row_min_height).hash(state);
|
||||||
break_on_newline.hash(state);
|
break_on_newline.hash(state);
|
||||||
halign.hash(state);
|
halign.hash(state);
|
||||||
justify.hash(state);
|
justify.hash(state);
|
||||||
|
|
@ -214,7 +214,7 @@ impl std::hash::Hash for LayoutSection {
|
||||||
byte_range,
|
byte_range,
|
||||||
format,
|
format,
|
||||||
} = self;
|
} = self;
|
||||||
crate::f32_hash(state, *leading_space);
|
OrderedFloat(*leading_space).hash(state);
|
||||||
byte_range.hash(state);
|
byte_range.hash(state);
|
||||||
format.hash(state);
|
format.hash(state);
|
||||||
}
|
}
|
||||||
|
|
@ -293,9 +293,9 @@ impl std::hash::Hash for TextFormat {
|
||||||
valign,
|
valign,
|
||||||
} = self;
|
} = self;
|
||||||
font_id.hash(state);
|
font_id.hash(state);
|
||||||
crate::f32_hash(state, *extra_letter_spacing);
|
emath::OrderedFloat(*extra_letter_spacing).hash(state);
|
||||||
if let Some(line_height) = *line_height {
|
if let Some(line_height) = *line_height {
|
||||||
crate::f32_hash(state, line_height);
|
emath::OrderedFloat(line_height).hash(state);
|
||||||
}
|
}
|
||||||
color.hash(state);
|
color.hash(state);
|
||||||
background.hash(state);
|
background.hash(state);
|
||||||
|
|
@ -375,7 +375,7 @@ impl std::hash::Hash for TextWrapping {
|
||||||
break_anywhere,
|
break_anywhere,
|
||||||
overflow_character,
|
overflow_character,
|
||||||
} = self;
|
} = self;
|
||||||
crate::f32_hash(state, *max_width);
|
emath::OrderedFloat(*max_width).hash(state);
|
||||||
max_rows.hash(state);
|
max_rows.hash(state);
|
||||||
break_anywhere.hash(state);
|
break_anywhere.hash(state);
|
||||||
overflow_character.hash(state);
|
overflow_character.hash(state);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
mod ordered_float;
|
#[deprecated = "Use emath::OrderedFloat instead"]
|
||||||
|
pub use emath::OrderedFloat;
|
||||||
pub use ordered_float::*;
|
|
||||||
|
|
||||||
/// Hash the given value with a predictable hasher.
|
/// Hash the given value with a predictable hasher.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue