diff --git a/skia-safe/src/codec/_codec.rs b/skia-safe/src/codec/_codec.rs index c24f8fea2..544315d5b 100644 --- a/skia-safe/src/codec/_codec.rs +++ b/skia-safe/src/codec/_codec.rs @@ -23,7 +23,7 @@ variant_name!(SelectionPolicy::PreferStillImage, selection_policy_naming); pub use sb::SkCodec_ZeroInitialized as ZeroInitialized; variant_name!(ZeroInitialized::Yes, zero_initialized_naming); -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct Options { pub zero_initialized: ZeroInitialized, pub subset: Option, diff --git a/skia-safe/src/codec/encoded_origin.rs b/skia-safe/src/codec/encoded_origin.rs index 67ff0d8cc..990c111b9 100644 --- a/skia-safe/src/codec/encoded_origin.rs +++ b/skia-safe/src/codec/encoded_origin.rs @@ -7,7 +7,7 @@ use skia_bindings::{self as sb, SkEncodedOrigin}; /// These values match the orientation www.exif.org/Exif2-2.PDF. #[repr(i32)] -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub enum EncodedOrigin { /// Default TopLeft = SkEncodedOrigin::TopLeft as _, diff --git a/skia-safe/src/core/color.rs b/skia-safe/src/core/color.rs index e4be29c75..a870808d7 100644 --- a/skia-safe/src/core/color.rs +++ b/skia-safe/src/core/color.rs @@ -10,7 +10,7 @@ use std::ops::{BitAnd, BitOr, Index, IndexMut, Mul}; // Note: SkColor _is_ a u32, and therefore its components are // endian dependent, so we can't expose it as (transmuted) individual // argb fields. -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Default, Debug)] #[repr(transparent)] pub struct Color(SkColor); @@ -69,8 +69,8 @@ impl Color { Self(argb) } - // note: we don't use the u8cpu type in the arguments here, because we trust the Rust - // compiler to optimize the storage type. + // We don't use the `u8cpu` Skia type in the arguments here, because we trust the Rust compiler + // to optimize the parameter layout. pub const fn from_argb(a: u8, r: u8, g: u8, b: u8) -> Color { Self(((a as u8cpu) << 24) | ((r as u8cpu) << 16) | ((g as u8cpu) << 8) | (b as u8cpu)) } @@ -79,24 +79,24 @@ impl Color { Self::from_argb(0xff, r, g, b) } - pub fn a(self) -> u8 { - (self.into_native() >> 24) as _ + pub const fn a(self) -> u8 { + (self.0 >> 24) as _ } - pub fn r(self) -> u8 { - (self.into_native() >> 16) as _ + pub const fn r(self) -> u8 { + (self.0 >> 16) as _ } - pub fn g(self) -> u8 { - (self.into_native() >> 8) as _ + pub const fn g(self) -> u8 { + (self.0 >> 8) as _ } - pub fn b(self) -> u8 { - self.into_native() as _ + pub const fn b(self) -> u8 { + self.0 as _ } #[must_use] - pub fn with_a(self, a: u8) -> Self { + pub const fn with_a(self, a: u8) -> Self { Self::from_argb(a, self.r(), self.g(), self.b()) } @@ -113,8 +113,12 @@ impl Color { pub const CYAN: Self = Self(sb::SK_ColorCYAN); pub const MAGENTA: Self = Self(sb::SK_ColorMAGENTA); - pub fn to_rgb(self) -> RGB { - (self.r(), self.g(), self.b()).into() + pub const fn to_rgb(self) -> RGB { + RGB { + r: self.r(), + g: self.g(), + b: self.b(), + } } pub fn to_hsv(self) -> HSV { @@ -122,7 +126,7 @@ impl Color { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct RGB { pub r: u8, pub g: u8, diff --git a/skia-safe/src/core/color_space.rs b/skia-safe/src/core/color_space.rs index befd67466..9b6bccd98 100644 --- a/skia-safe/src/core/color_space.rs +++ b/skia-safe/src/core/color_space.rs @@ -180,7 +180,7 @@ impl ColorSpace { // TODO: hash()? } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub struct XYZD50Hash(pub u32); #[cfg(test)] diff --git a/skia-safe/src/core/matrix.rs b/skia-safe/src/core/matrix.rs index 387fdb65f..0472ca469 100644 --- a/skia-safe/src/core/matrix.rs +++ b/skia-safe/src/core/matrix.rs @@ -51,7 +51,7 @@ impl Mul for Matrix { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Member { ScaleX = 0, SkewX = 1, @@ -64,7 +64,7 @@ pub enum Member { Persp2 = 8, } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum AffineMember { ScaleX = 0, SkewY = 1, diff --git a/skia-safe/src/core/point.rs b/skia-safe/src/core/point.rs index 38441234f..ff5e468be 100644 --- a/skia-safe/src/core/point.rs +++ b/skia-safe/src/core/point.rs @@ -5,7 +5,7 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi pub use IPoint as IVector; #[repr(C)] -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Default, Debug)] pub struct IPoint { pub x: i32, pub y: i32, @@ -92,6 +92,10 @@ impl IPoint { pub fn equals(self, x: i32, y: i32) -> bool { self == IPoint::new(x, y) } + + pub fn to_isize(self) -> ISize { + (self.x, self.y).into() + } } pub type Vector = Point; @@ -306,6 +310,10 @@ impl Point { pub fn dot(self, vec: Vector) -> scalar { Self::dot_product(self, vec) } + + pub fn to_size(self) -> Size { + (self.x, self.y).into() + } } impl From<(i32, i32)> for IPoint { @@ -314,12 +322,24 @@ impl From<(i32, i32)> for IPoint { } } +impl From for (i32, i32) { + fn from(p: IPoint) -> Self { + (p.x, p.y) + } +} + impl From<(scalar, scalar)> for Point { fn from(source: (scalar, scalar)) -> Self { Point::new(source.0, source.1) } } +impl From for (scalar, scalar) { + fn from(p: Point) -> Self { + (p.x, p.y) + } +} + impl From for Point { fn from(source: IPoint) -> Self { Self::new(source.x as _, source.y as _) diff --git a/skia-safe/src/core/point3.rs b/skia-safe/src/core/point3.rs index 350503d88..e2cbe44c4 100644 --- a/skia-safe/src/core/point3.rs +++ b/skia-safe/src/core/point3.rs @@ -21,6 +21,12 @@ impl From<(scalar, scalar, scalar)> for Point3 { } } +impl From for (scalar, scalar, scalar) { + fn from(p: Point3) -> Self { + (p.x, p.y, p.z) + } +} + impl Neg for Point3 { type Output = Self; fn neg(self) -> Self::Output { diff --git a/skia-safe/src/core/rect.rs b/skia-safe/src/core/rect.rs index a9aae990b..ec07e342d 100644 --- a/skia-safe/src/core/rect.rs +++ b/skia-safe/src/core/rect.rs @@ -10,7 +10,7 @@ use std::{ }; #[repr(C)] -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Default, Debug)] pub struct IRect { pub left: i32, pub top: i32, @@ -794,6 +794,12 @@ impl From<(IPoint, ISize)> for IRect { } } +impl From for (IPoint, ISize) { + fn from(r: IRect) -> Self { + (IPoint::new(r.x(), r.y()), r.size()) + } +} + impl From<(Point, Size)> for Rect { fn from((point, size): (Point, Size)) -> Self { Rect::new( @@ -805,6 +811,12 @@ impl From<(Point, Size)> for Rect { } } +impl From for (Point, Size) { + fn from(r: Rect) -> Self { + (Point::new(r.x(), r.y()), r.size()) + } +} + impl From for Rect { fn from(isize: ISize) -> Self { Self::from_isize(isize) diff --git a/skia-safe/src/core/size.rs b/skia-safe/src/core/size.rs index 5bb436c0a..c33a0fbb9 100644 --- a/skia-safe/src/core/size.rs +++ b/skia-safe/src/core/size.rs @@ -3,7 +3,7 @@ use skia_bindings::{self as sb, SkISize, SkSize}; use std::ops::{Div, DivAssign, Mul, MulAssign}; #[repr(C)] -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Default, Debug)] pub struct ISize { pub width: i32, pub height: i32, @@ -120,12 +120,24 @@ impl From<(i32, i32)> for ISize { } } +impl From for (i32, i32) { + fn from(size: ISize) -> Self { + (size.width, size.height) + } +} + impl From<(scalar, scalar)> for Size { fn from(source: (scalar, scalar)) -> Self { Self::new(source.0, source.1) } } +impl From for (scalar, scalar) { + fn from(size: Size) -> Self { + (size.width, size.height) + } +} + impl From for Size { fn from(size: ISize) -> Self { Self::new(size.width as _, size.height as _) diff --git a/skia-safe/src/core/surface_props.rs b/skia-safe/src/core/surface_props.rs index f1b478634..75c280c2e 100644 --- a/skia-safe/src/core/surface_props.rs +++ b/skia-safe/src/core/surface_props.rs @@ -3,7 +3,7 @@ use skia_bindings::{self as sb, SkPixelGeometry, SkSurfaceProps}; use std::fmt; // TODO: use the enum rewriter and strip underscores? -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[repr(i32)] pub enum PixelGeometry { Unknown = SkPixelGeometry::kUnknown_SkPixelGeometry as _, diff --git a/skia-safe/src/core/typeface.rs b/skia-safe/src/core/typeface.rs index bb408ec04..441528923 100644 --- a/skia-safe/src/core/typeface.rs +++ b/skia-safe/src/core/typeface.rs @@ -19,7 +19,7 @@ variant_name!( serialize_behavior_naming ); -#[derive(Clone, PartialEq, Eq, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub struct LocalizedString { pub string: String, pub language: String, diff --git a/skia-safe/src/core/types.rs b/skia-safe/src/core/types.rs index 3db5ff38a..d83fd19a9 100644 --- a/skia-safe/src/core/types.rs +++ b/skia-safe/src/core/types.rs @@ -14,7 +14,7 @@ pub(crate) const SK_MIN_S32: i32 = -SK_MAX_S32; // FourByteTag // -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Debug)] #[repr(transparent)] pub struct FourByteTag(SkFourByteTag); @@ -82,7 +82,7 @@ pub type Unichar = skia_bindings::SkUnichar; // pub(crate) const MSEC_MAX: u32 = std::i32::MAX as u32; #[repr(C)] -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub struct Budgeted(bool); native_transmutable!(SkBudgeted, Budgeted, budgeted_layout); diff --git a/skia-safe/src/effects/runtime_effect.rs b/skia-safe/src/effects/runtime_effect.rs index 51d788f0a..e791a9299 100644 --- a/skia-safe/src/effects/runtime_effect.rs +++ b/skia-safe/src/effects/runtime_effect.rs @@ -121,7 +121,7 @@ impl NativeRefCountedBase for SkRuntimeEffect { } #[repr(C)] -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct Options { pub force_no_inline: bool, enforce_es2_restrictions: bool, diff --git a/skia-safe/src/gpu/direct_context.rs b/skia-safe/src/gpu/direct_context.rs index a6226e77e..e54dbfd1f 100644 --- a/skia-safe/src/gpu/direct_context.rs +++ b/skia-safe/src/gpu/direct_context.rs @@ -18,7 +18,7 @@ use std::{ }; #[repr(C)] -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct DirectContextId { id: u32, } @@ -49,13 +49,13 @@ impl DerefMut for DirectContext { } } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct ResourceCacheLimits { pub max_resources: usize, pub max_resource_bytes: usize, } -#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct ResourceCacheUsage { pub resource_count: usize, pub resource_bytes: usize, diff --git a/skia-safe/src/gpu/gl/types.rs b/skia-safe/src/gpu/gl/types.rs index bd6823a6e..7d6ac7994 100644 --- a/skia-safe/src/gpu/gl/types.rs +++ b/skia-safe/src/gpu/gl/types.rs @@ -35,7 +35,7 @@ impl TextureInfo { } } -#[derive(Copy, Clone, PartialEq, Eq, Default, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Default, Debug)] #[repr(C)] pub struct FramebufferInfo { pub fboid: UInt, diff --git a/skia-safe/src/gpu/vk.rs b/skia-safe/src/gpu/vk.rs index 348a8ebe7..25ab5e3fc 100644 --- a/skia-safe/src/gpu/vk.rs +++ b/skia-safe/src/gpu/vk.rs @@ -116,7 +116,7 @@ impl From for u64 { } #[repr(transparent)] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)] pub struct Version(u32); impl Version { diff --git a/skia-safe/src/lib.rs b/skia-safe/src/lib.rs index 3b1f951c1..63ef06118 100644 --- a/skia-safe/src/lib.rs +++ b/skia-safe/src/lib.rs @@ -34,7 +34,9 @@ extern crate bitflags; extern crate lazy_static; // Prelude re-exports -pub use crate::prelude::{Borrows, ConditionallySend, Handle, RCHandle, RefHandle, Sendable}; +pub use crate::prelude::{ + Borrows, ConditionallySend, Handle, NativeRefCounted, RCHandle, RefHandle, Sendable, +}; /// All Sk* types are accessible via skia_safe:: pub use crate::core::*; diff --git a/skia-safe/src/modules/paragraph.rs b/skia-safe/src/modules/paragraph.rs index 6fb9b7e46..3ec0356dc 100644 --- a/skia-safe/src/modules/paragraph.rs +++ b/skia-safe/src/modules/paragraph.rs @@ -1,5 +1,5 @@ use crate::interop::AsStr; -use std::ops::Index; +use std::{fmt, ops::Index}; mod dart_types; mod font_arguments; @@ -29,9 +29,15 @@ pub use typeface_font_provider::*; /// Efficient reference type to a C++ vector of font family SkStrings. /// /// Use indexer or .iter() to access the Rust str references. -#[derive(Debug)] pub struct FontFamilies<'a>(&'a [skia_bindings::SkString]); +impl fmt::Debug for FontFamilies<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let families: Vec<_> = self.iter().collect(); + f.debug_tuple("FontFamilies").field(&families).finish() + } +} + impl Index for FontFamilies<'_> { type Output = str; fn index(&self, index: usize) -> &Self::Output { diff --git a/skia-safe/src/prelude.rs b/skia-safe/src/prelude.rs index e981aa329..ae07790fa 100644 --- a/skia-safe/src/prelude.rs +++ b/skia-safe/src/prelude.rs @@ -7,8 +7,7 @@ use std::{ marker::PhantomData, mem::{self, MaybeUninit}, ops::{Deref, DerefMut, Index, IndexMut}, - ptr::{self, NonNull}, - slice, + ptr, slice, }; // Re-export TryFrom / TryInto to make them available in all modules that use prelude::*. @@ -560,10 +559,9 @@ impl RCHandle { unsafe { transmute_ref(n) } } - /// Returns the pointer to the handle. - #[allow(unused)] - pub(crate) fn as_ptr(&self) -> &NonNull { - &self.0 + /// Returns the address of the native value. + pub(crate) fn as_ptr(&self) -> *const N { + ptr::NonNull::as_ptr(self.0) } } diff --git a/skia-safe/src/wrapper.rs b/skia-safe/src/wrapper.rs index 184edf0ae..eac9d9d27 100644 --- a/skia-safe/src/wrapper.rs +++ b/skia-safe/src/wrapper.rs @@ -1,8 +1,12 @@ +use crate::prelude::*; ///! FFI interoperability for skia-safe's wrapper types. ///! -///! This module is only meant to be used by external code. Internal code should continue to use the traits in -///! the `prelude` module. -use crate::prelude::*; +///! This module is only meant to be used by external code. Internal code should continue to use the +///! traits in the `prelude` module. +use std::{ + hash::{Hash, Hasher}, + ops::{Deref, DerefMut}, +}; /// This trait supports the conversion of a wrapper into it's wrapped C/C++ pointer and back. /// @@ -10,10 +14,11 @@ use crate::prelude::*; /// /// # Safety /// -/// The native value `N` _should_ be treated as opaque, because its definition may change -/// without adhering to semantic versioning and depends on what the tool bindgen is able to generate. +/// The native value `N` _should_ be treated as opaque, because its definition may change without +/// adhering to semantic versioning and depends on what the tool bindgen is able to generate. /// -/// Converting from a Rust wrapper to the wrapped value loses the automatic ability to free associated resources. +/// Converting from a Rust wrapper to the wrapped value loses the automatic ability to free +/// associated resources. pub unsafe trait PointerWrapper where Self: Sized, @@ -33,14 +38,16 @@ where /// /// The wrapped value can be accessed through the functions `inner` and `inner_mut`. /// -/// This trait is implemented for all wrapper types that manage C++/C values in Rust without an pointer indirection. +/// This trait is implemented for all wrapper types that manage C++/C values in Rust without an +/// pointer indirection. /// /// # Safety /// -/// The native type `N` _should_ be treated as opaque, because its definition may change -/// without adhering to semantic versioning and depends on what the tool bindgen is able to generate. +/// The native type `N` _should_ be treated as opaque because its definition may change without +/// adhering to semantic versioning and depends on what the tool bindgen is able to generate. /// -/// Converting from a Rust wrapper to a wrapped value may lose the automatic ability to free associated memory. +/// Converting from a Rust wrapper to a wrapped value may lose the automatic ability to free +/// associated memory. pub unsafe trait ValueWrapper { fn wrap(native: N) -> Self; fn unwrap(self) -> N; @@ -86,6 +93,57 @@ pub unsafe trait RefWrapper { fn inner_mut(&mut self) -> &mut N; } +/// Trait that enables a reference counted type to be compared by pointer equality. +pub trait PtrEq { + fn ptr_eq(this: &Self, other: &Self) -> bool; + fn ptr_hash(this: &Self, h: &mut H); +} + +/// A wrapper to wrap values that implement [`PtrEq`] so that [`PartialEq`] and [`Eq`] are +/// implemented by pointer equality. +/// +/// This way, reference counted Skia types can be used as hash map keys, for example. +#[derive(Clone, Debug)] +pub struct EqByPointer(T); + +impl EqByPointer { + /// Wrap a value that implements [`PtrEq`]. + pub fn new(t: T) -> Self { + Self(t) + } +} + +impl Deref for EqByPointer { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for EqByPointer { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl PartialEq for EqByPointer { + fn eq(&self, other: &Self) -> bool { + ::ptr_eq(self, other) + } +} + +impl Eq for EqByPointer {} + +impl Hash for EqByPointer { + fn hash(&self, h: &mut H) + where + H: Hasher, + { + ::ptr_hash(self, h) + } +} + // // Handle // @@ -185,6 +243,19 @@ where } } +impl PtrEq for RCHandle +where + N: NativeRefCounted, +{ + fn ptr_eq(this: &Self, other: &Self) -> bool { + this.as_ptr() == other.as_ptr() + } + + fn ptr_hash(this: &Self, h: &mut H) { + std::ptr::hash(this.as_ptr(), h) + } +} + // // NativeTransmutable //