зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1567241 - Update to euclid 0.20. r=kvark, emilio.
Differential Revision: https://phabricator.services.mozilla.com/D38530 --HG-- extra : source : d65512e23a13164f540430ff0c85a1f2a147d8a0
This commit is contained in:
Родитель
97bc08cce4
Коммит
a58ba90d31
|
@ -1063,24 +1063,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.19.9"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "euclid_macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.3"
|
||||
|
@ -1749,7 +1738,7 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashglobe 0.1.0",
|
||||
"selectors 0.21.0",
|
||||
"servo_arc 0.1.1",
|
||||
|
@ -2229,7 +2218,7 @@ dependencies = [
|
|||
name = "peek-poke"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke-derive 0.2.0",
|
||||
]
|
||||
|
||||
|
@ -2301,11 +2290,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "plane-split"
|
||||
version = "0.13.8"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -2979,7 +2968,7 @@ dependencies = [
|
|||
"byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fallible 0.0.1",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hashglobe 0.1.0",
|
||||
|
@ -3040,7 +3029,7 @@ dependencies = [
|
|||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cssparser 0.25.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of 0.0.1",
|
||||
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3651,7 +3640,7 @@ dependencies = [
|
|||
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cstr 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3661,7 +3650,7 @@ dependencies = [
|
|||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plane-split 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3687,7 +3676,7 @@ dependencies = [
|
|||
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke 0.2.0",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3706,7 +3695,7 @@ dependencies = [
|
|||
"core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"foreign-types 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3803,7 +3792,7 @@ name = "wr_malloc_size_of"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4003,8 +3992,7 @@ dependencies = [
|
|||
"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed"
|
||||
"checksum env_logger 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0561146661ae44c579e993456bc76d11ce1e0c7d745e57b2fa7146b6e49fa2ad"
|
||||
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
|
||||
"checksum euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)" = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"
|
||||
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
|
||||
"checksum euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"
|
||||
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
|
||||
"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
|
@ -4108,7 +4096,7 @@ dependencies = [
|
|||
"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2"
|
||||
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
|
||||
"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
"checksum plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)" = "91c621d83b9c5a85b7ca7ca2bec643136debb327ad29d0a08768db1325780365"
|
||||
"checksum plane-split 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91821c7436aefc1b912552d494232efcaf9810c0189918749532be1e9dbace59"
|
||||
"checksum plist 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "95bef0807b4fe77618f8d24f0c4ec37a4ad1dad9348c3b27d8b624c824d8cf48"
|
||||
"checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"
|
||||
"checksum podio 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e5422a1ee1bc57cc47ae717b0137314258138f38fd5f3cea083f43a9725383a0"
|
||||
|
|
|
@ -11,7 +11,7 @@ webrender_debugger = ["webrender/debugger"]
|
|||
rayon = "1"
|
||||
num_cpus = "1.7.0"
|
||||
thread_profiler = "0.1.1"
|
||||
euclid = { version = "0.19.4", features = ["serde"] }
|
||||
euclid = { version = "0.20.0", features = ["serde"] }
|
||||
app_units = "0.7"
|
||||
gleam = "0.6.14"
|
||||
log = "0.4"
|
||||
|
|
|
@ -388,7 +388,7 @@ static bool Moz2DRenderCallback(const Range<const uint8_t> aBlob,
|
|||
auto bounds = gfx::IntRect(origin, aSize);
|
||||
|
||||
if (aDirtyRect) {
|
||||
Rect dirty(aDirtyRect->origin.x, aDirtyRect->origin.y,
|
||||
gfx::Rect dirty(aDirtyRect->origin.x, aDirtyRect->origin.y,
|
||||
aDirtyRect->size.width, aDirtyRect->size.height);
|
||||
dt->PushClipRect(dirty);
|
||||
bounds = bounds.Intersect(
|
||||
|
|
|
@ -1138,10 +1138,10 @@ void DisplayListBuilder::PushBorderGradient(
|
|||
const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
|
||||
bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths,
|
||||
const int32_t aWidth, const int32_t aHeight, bool aFill,
|
||||
const wr::SideOffsets2D<int32_t>& aSlice,
|
||||
const wr::DeviceIntSideOffsets& aSlice,
|
||||
const wr::LayoutPoint& aStartPoint, const wr::LayoutPoint& aEndPoint,
|
||||
const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
|
||||
const wr::SideOffsets2D<float>& aOutset) {
|
||||
const wr::LayoutSideOffsets& aOutset) {
|
||||
wr_dp_push_border_gradient(mWrState, aBounds, MergeClipLeaf(aClip),
|
||||
aIsBackfaceVisible, &mCurrentSpaceAndClipChain,
|
||||
aWidths, aWidth, aHeight, aFill, aSlice,
|
||||
|
@ -1154,7 +1154,7 @@ void DisplayListBuilder::PushBorderRadialGradient(
|
|||
bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill,
|
||||
const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius,
|
||||
const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
|
||||
const wr::SideOffsets2D<float>& aOutset) {
|
||||
const wr::LayoutSideOffsets& aOutset) {
|
||||
wr_dp_push_border_radial_gradient(
|
||||
mWrState, aBounds, MergeClipLeaf(aClip), aIsBackfaceVisible,
|
||||
&mCurrentSpaceAndClipChain, aWidths, aFill, aCenter, aRadius,
|
||||
|
|
|
@ -511,19 +511,19 @@ class DisplayListBuilder final {
|
|||
const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
|
||||
const wr::LayoutSideOffsets& aWidths,
|
||||
const int32_t aWidth, const int32_t aHeight,
|
||||
bool aFill, const wr::SideOffsets2D<int32_t>& aSlice,
|
||||
bool aFill, const wr::DeviceIntSideOffsets& aSlice,
|
||||
const wr::LayoutPoint& aStartPoint,
|
||||
const wr::LayoutPoint& aEndPoint,
|
||||
const nsTArray<wr::GradientStop>& aStops,
|
||||
wr::ExtendMode aExtendMode,
|
||||
const wr::SideOffsets2D<float>& aOutset);
|
||||
const wr::LayoutSideOffsets& aOutset);
|
||||
|
||||
void PushBorderRadialGradient(
|
||||
const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
|
||||
bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill,
|
||||
const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius,
|
||||
const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
|
||||
const wr::SideOffsets2D<float>& aOutset);
|
||||
const wr::LayoutSideOffsets& aOutset);
|
||||
|
||||
void PushText(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
|
||||
bool aIsBackfaceVisible, const wr::ColorF& aColor,
|
||||
|
|
|
@ -627,11 +627,11 @@ static inline wr::LayoutSideOffsets ToBorderWidths(float top, float right,
|
|||
return bw;
|
||||
}
|
||||
|
||||
static inline wr::SideOffsets2D<int32_t> ToSideOffsets2D_i32(int32_t top,
|
||||
int32_t right,
|
||||
int32_t bottom,
|
||||
int32_t left) {
|
||||
SideOffsets2D<int32_t> offset;
|
||||
static inline wr::DeviceIntSideOffsets ToDeviceIntSideOffsets(int32_t top,
|
||||
int32_t right,
|
||||
int32_t bottom,
|
||||
int32_t left) {
|
||||
wr::DeviceIntSideOffsets offset;
|
||||
offset.top = top;
|
||||
offset.right = right;
|
||||
offset.bottom = bottom;
|
||||
|
@ -639,11 +639,11 @@ static inline wr::SideOffsets2D<int32_t> ToSideOffsets2D_i32(int32_t top,
|
|||
return offset;
|
||||
}
|
||||
|
||||
static inline wr::SideOffsets2D<float> ToSideOffsets2D_f32(float top,
|
||||
float right,
|
||||
float bottom,
|
||||
float left) {
|
||||
SideOffsets2D<float> offset;
|
||||
static inline wr::LayoutSideOffsets ToLayoutSideOffsets(float top,
|
||||
float right,
|
||||
float bottom,
|
||||
float left) {
|
||||
wr::LayoutSideOffsets offset;
|
||||
offset.top = top;
|
||||
offset.right = right;
|
||||
offset.bottom = bottom;
|
||||
|
|
|
@ -2780,8 +2780,8 @@ pub struct WrBorderImage {
|
|||
width: i32,
|
||||
height: i32,
|
||||
fill: bool,
|
||||
slice: SideOffsets2D<i32>,
|
||||
outset: SideOffsets2D<f32>,
|
||||
slice: DeviceIntSideOffsets,
|
||||
outset: LayoutSideOffsets,
|
||||
repeat_horizontal: RepeatMode,
|
||||
repeat_vertical: RepeatMode,
|
||||
}
|
||||
|
@ -2832,13 +2832,13 @@ pub extern "C" fn wr_dp_push_border_gradient(state: &mut WrState,
|
|||
width: i32,
|
||||
height: i32,
|
||||
fill: bool,
|
||||
slice: SideOffsets2D<i32>,
|
||||
slice: DeviceIntSideOffsets,
|
||||
start_point: LayoutPoint,
|
||||
end_point: LayoutPoint,
|
||||
stops: *const GradientStop,
|
||||
stops_count: usize,
|
||||
extend_mode: ExtendMode,
|
||||
outset: SideOffsets2D<f32>) {
|
||||
outset: LayoutSideOffsets) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
|
||||
let stops_slice = unsafe { make_slice(stops, stops_count) };
|
||||
|
@ -2893,7 +2893,7 @@ pub extern "C" fn wr_dp_push_border_radial_gradient(state: &mut WrState,
|
|||
stops: *const GradientStop,
|
||||
stops_count: usize,
|
||||
extend_mode: ExtendMode,
|
||||
outset: SideOffsets2D<f32>) {
|
||||
outset: LayoutSideOffsets) {
|
||||
debug_assert!(unsafe { is_in_main_thread() });
|
||||
|
||||
let stops_slice = unsafe { make_slice(stops, stops_count) };
|
||||
|
|
|
@ -423,7 +423,7 @@ dependencies = [
|
|||
name = "direct-composition"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender 0.60.0",
|
||||
|
@ -480,24 +480,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "euclid"
|
||||
version = "0.19.9"
|
||||
version = "0.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "euclid_macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "expat-sys"
|
||||
version = "2.1.5"
|
||||
|
@ -1140,7 +1129,7 @@ dependencies = [
|
|||
name = "peek-poke"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke-derive 0.2.0",
|
||||
]
|
||||
|
||||
|
@ -1167,11 +1156,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "plane-split"
|
||||
version = "0.13.8"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"binary-space-partition 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -1883,7 +1872,7 @@ dependencies = [
|
|||
"core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cstr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1894,7 +1883,7 @@ dependencies = [
|
|||
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mozangle 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plane-split 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1918,7 +1907,7 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1936,7 +1925,7 @@ dependencies = [
|
|||
"core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"peek-poke 0.2.0",
|
||||
|
@ -2028,7 +2017,7 @@ name = "wr_malloc_size_of"
|
|||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2045,7 +2034,7 @@ dependencies = [
|
|||
"crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"font-loader 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin 0.21.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2189,8 +2178,7 @@ dependencies = [
|
|||
"checksum dwrote 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bd1369e02db5e9b842a9b67bce8a2fcc043beafb2ae8a799dd482d46ea1ff0d"
|
||||
"checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
|
||||
"checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a"
|
||||
"checksum euclid 0.19.9 (registry+https://github.com/rust-lang/crates.io-index)" = "596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"
|
||||
"checksum euclid_macros 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"
|
||||
"checksum euclid 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"
|
||||
"checksum expat-sys 2.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c470ccb972f2088549b023db8029ed9da9426f5affbf9b62efff7009ab8ed5b1"
|
||||
"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
|
@ -2268,7 +2256,7 @@ dependencies = [
|
|||
"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f"
|
||||
"checksum plane-split 0.13.8 (registry+https://github.com/rust-lang/crates.io-index)" = "91c621d83b9c5a85b7ca7ca2bec643136debb327ad29d0a08768db1325780365"
|
||||
"checksum plane-split 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "91821c7436aefc1b912552d494232efcaf9810c0189918749532be1e9dbace59"
|
||||
"checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9"
|
||||
"checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d"
|
||||
"checksum procedural-masquerade 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9a1574a51c3fd37b26d2c0032b649d08a7d51d4cca9c41bbc5bf7118fa4509d0"
|
||||
|
|
|
@ -6,7 +6,7 @@ license = "MPL-2.0"
|
|||
edition = "2018"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
gleam = "0.6.2"
|
||||
mozangle = {version = "0.1", features = ["egl"]}
|
||||
webrender = {path = "../webrender"}
|
||||
|
|
|
@ -133,10 +133,10 @@ impl Rectangle {
|
|||
self.visual.make_current();
|
||||
|
||||
let pipeline_id = api::PipelineId(0, 0);
|
||||
let layout_size = self.size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
|
||||
let layout_size = self.size.to_f32() / euclid::Scale::new(device_pixel_ratio);
|
||||
let mut builder = api::DisplayListBuilder::new(pipeline_id, layout_size);
|
||||
|
||||
let rect = euclid::TypedRect::new(euclid::TypedPoint2D::zero(), layout_size);
|
||||
let rect = euclid::Rect::new(euclid::Point2D::zero(), layout_size);
|
||||
|
||||
let region = api::ComplexClipRegion::new(
|
||||
rect,
|
||||
|
|
|
@ -60,7 +60,7 @@ debug = ["webrender/capture", "webrender/debugger", "webrender/profiler"]
|
|||
[dependencies]
|
||||
app_units = "0.7"
|
||||
env_logger = "0.5"
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
gleam = "0.6.2"
|
||||
glutin = "0.21"
|
||||
rayon = "1"
|
||||
|
|
|
@ -192,7 +192,7 @@ pub fn main_wrapper<E: Example>(
|
|||
|
||||
let epoch = Epoch(0);
|
||||
let pipeline_id = PipelineId(0, 0);
|
||||
let layout_size = device_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
|
||||
let layout_size = device_size.to_f32() / euclid::Scale::new(device_pixel_ratio);
|
||||
let mut builder = DisplayListBuilder::new(pipeline_id, layout_size);
|
||||
let mut txn = Transaction::new();
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ extern crate winit;
|
|||
mod boilerplate;
|
||||
|
||||
use crate::boilerplate::Example;
|
||||
use euclid::TypedScale;
|
||||
use euclid::Scale;
|
||||
use webrender::api::*;
|
||||
use webrender::api::units::*;
|
||||
|
||||
|
@ -78,7 +78,7 @@ impl App {
|
|||
pipeline_id,
|
||||
content_rect: LayoutRect::new(
|
||||
LayoutPoint::origin(),
|
||||
bounds.size.to_f32() / TypedScale::new(device_pixel_ratio),
|
||||
bounds.size.to_f32() / Scale::new(device_pixel_ratio),
|
||||
),
|
||||
color,
|
||||
});
|
||||
|
|
|
@ -12,7 +12,7 @@ extern crate winit;
|
|||
mod boilerplate;
|
||||
|
||||
use crate::boilerplate::{Example, HandyDandyRectBuilder};
|
||||
use euclid::TypedScale;
|
||||
use euclid::Scale;
|
||||
use gleam::gl;
|
||||
use webrender::api::*;
|
||||
use webrender::api::units::*;
|
||||
|
@ -92,7 +92,7 @@ impl App {
|
|||
pipeline_id,
|
||||
content_rect: LayoutRect::new(
|
||||
LayoutPoint::zero(),
|
||||
device_size.to_f32() / TypedScale::new(device_pixel_ratio),
|
||||
device_size.to_f32() / Scale::new(device_pixel_ratio),
|
||||
),
|
||||
color,
|
||||
};
|
||||
|
|
|
@ -181,7 +181,7 @@ impl Window {
|
|||
.to_physical(device_pixel_ratio as f64);
|
||||
DeviceIntSize::new(size.width as i32, size.height as i32)
|
||||
};
|
||||
let layout_size = device_size.to_f32() / euclid::TypedScale::new(device_pixel_ratio);
|
||||
let layout_size = device_size.to_f32() / euclid::Scale::new(device_pixel_ratio);
|
||||
let mut txn = Transaction::new();
|
||||
let mut builder = DisplayListBuilder::new(self.pipeline_id, layout_size);
|
||||
let space_and_clip = SpaceAndClipInfo::root_scroll(self.pipeline_id);
|
||||
|
|
|
@ -6,7 +6,7 @@ license = "MIT/Apache-2.0"
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
euclid = { version = "0.19", optional = true }
|
||||
euclid = { version = "0.20.0", optional = true }
|
||||
peek-poke-derive = { version = "0.2", path = "./peek-poke-derive", optional = true }
|
||||
|
||||
[features]
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
// except according to those terms.
|
||||
|
||||
use crate::{Peek, Poke};
|
||||
use euclid::{TypedPoint2D, TypedRect, TypedSideOffsets2D, TypedSize2D, TypedTransform3D, TypedVector2D};
|
||||
use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Transform3D, Vector2D};
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedPoint2D<T, U> {
|
||||
unsafe impl<T: Poke, U> Poke for Point2D<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
2 * T::max_size()
|
||||
|
@ -23,7 +23,7 @@ unsafe impl<T: Poke, U> Poke for TypedPoint2D<T, U> {
|
|||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedPoint2D<T, U> {
|
||||
impl<T: Peek, U> Peek for Point2D<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).x);
|
||||
|
@ -32,10 +32,10 @@ impl<T: Peek, U> Peek for TypedPoint2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedRect<T, U> {
|
||||
unsafe impl<T: Poke, U> Poke for Rect<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
TypedPoint2D::<T, U>::max_size() + TypedSize2D::<T, U>::max_size()
|
||||
Point2D::<T, U>::max_size() + Size2D::<T, U>::max_size()
|
||||
}
|
||||
#[inline(always)]
|
||||
unsafe fn poke_into(&self, bytes: *mut u8) -> *mut u8 {
|
||||
|
@ -44,16 +44,16 @@ unsafe impl<T: Poke, U> Poke for TypedRect<T, U> {
|
|||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedRect<T, U> {
|
||||
impl<T: Peek, U> Peek for Rect<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = TypedPoint2D::<T, U>::peek_from(bytes, &mut (*output).origin);
|
||||
let bytes = TypedSize2D::<T, U>::peek_from(bytes, &mut (*output).size);
|
||||
let bytes = Point2D::<T, U>::peek_from(bytes, &mut (*output).origin);
|
||||
let bytes = Size2D::<T, U>::peek_from(bytes, &mut (*output).size);
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedSideOffsets2D<T, U> {
|
||||
unsafe impl<T: Poke, U> Poke for SideOffsets2D<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
4 * T::max_size()
|
||||
|
@ -67,7 +67,7 @@ unsafe impl<T: Poke, U> Poke for TypedSideOffsets2D<T, U> {
|
|||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedSideOffsets2D<T, U> {
|
||||
impl<T: Peek, U> Peek for SideOffsets2D<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).top);
|
||||
|
@ -78,7 +78,7 @@ impl<T: Peek, U> Peek for TypedSideOffsets2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedSize2D<T, U> {
|
||||
unsafe impl<T: Poke, U> Poke for Size2D<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
2 * T::max_size()
|
||||
|
@ -90,7 +90,7 @@ unsafe impl<T: Poke, U> Poke for TypedSize2D<T, U> {
|
|||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedSize2D<T, U> {
|
||||
impl<T: Peek, U> Peek for Size2D<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).width);
|
||||
|
@ -99,7 +99,7 @@ impl<T: Peek, U> Peek for TypedSize2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, S, D> Poke for TypedTransform3D<T, S, D> {
|
||||
unsafe impl<T: Poke, S, D> Poke for Transform3D<T, S, D> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
16 * T::max_size()
|
||||
|
@ -125,7 +125,7 @@ unsafe impl<T: Poke, S, D> Poke for TypedTransform3D<T, S, D> {
|
|||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, S, D> Peek for TypedTransform3D<T, S, D> {
|
||||
impl<T: Peek, S, D> Peek for Transform3D<T, S, D> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).m11);
|
||||
|
@ -148,7 +148,7 @@ impl<T: Peek, S, D> Peek for TypedTransform3D<T, S, D> {
|
|||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Poke, U> Poke for TypedVector2D<T, U> {
|
||||
unsafe impl<T: Poke, U> Poke for Vector2D<T, U> {
|
||||
#[inline(always)]
|
||||
fn max_size() -> usize {
|
||||
2 * T::max_size()
|
||||
|
@ -160,7 +160,7 @@ unsafe impl<T: Poke, U> Poke for TypedVector2D<T, U> {
|
|||
bytes
|
||||
}
|
||||
}
|
||||
impl<T: Peek, U> Peek for TypedVector2D<T, U> {
|
||||
impl<T: Peek, U> Peek for Vector2D<T, U> {
|
||||
#[inline(always)]
|
||||
unsafe fn peek_from(bytes: *const u8, output: *mut Self) -> *const u8 {
|
||||
let bytes = T::peek_from(bytes, &mut (*output).x);
|
||||
|
|
|
@ -29,7 +29,7 @@ bitflags = "1.0"
|
|||
byteorder = "1.0"
|
||||
cfg-if = "0.1.2"
|
||||
cstr = "0.1.2"
|
||||
euclid = { version = "0.19.5", features = ["serde"] }
|
||||
euclid = { version = "0.20.0", features = ["serde"] }
|
||||
fxhash = "0.2.1"
|
||||
gleam = "0.6.17"
|
||||
image_loader = { optional = true, version = "0.21", package = "image", default-features = false, features = ["png_codec"] }
|
||||
|
@ -37,7 +37,7 @@ lazy_static = "1"
|
|||
log = "0.4"
|
||||
malloc_size_of_derive = "0.1"
|
||||
num-traits = "0.2"
|
||||
plane-split = "0.13.7"
|
||||
plane-split = "0.14.0"
|
||||
png = { optional = true, version = "0.14" }
|
||||
rayon = "1"
|
||||
ron = { optional = true, version = "0.1.7" }
|
||||
|
|
|
@ -1336,7 +1336,7 @@ impl BatchBuilder {
|
|||
// Get the GPU cache address of the extra data handle.
|
||||
let shadow_prim_address = gpu_cache.get_address(shadow_gpu_data);
|
||||
|
||||
let shadow_rect = prim_header.local_rect.translate(&shadow.offset);
|
||||
let shadow_rect = prim_header.local_rect.translate(shadow.offset);
|
||||
|
||||
let shadow_prim_header = PrimitiveHeader {
|
||||
local_rect: shadow_rect,
|
||||
|
@ -2081,7 +2081,7 @@ impl BatchBuilder {
|
|||
gpu_blocks.push([-1.0, 0.0, 0.0, 0.0].into()); //stretch size
|
||||
// negative first value makes the shader code ignore it and use the local size instead
|
||||
for tile in chunk {
|
||||
let tile_rect = tile.local_rect.translate(&-prim_rect.origin.to_vector());
|
||||
let tile_rect = tile.local_rect.translate(-prim_rect.origin.to_vector());
|
||||
gpu_blocks.push(tile_rect.into());
|
||||
gpu_blocks.push(GpuBlockData::EMPTY);
|
||||
}
|
||||
|
@ -2909,7 +2909,7 @@ impl ClipBatcher {
|
|||
p1.y - p0.y,
|
||||
),
|
||||
).to_f32();
|
||||
let world_sub_rect = normalized_sub_rect.translate(&mask_origin);
|
||||
let world_sub_rect = normalized_sub_rect.translate(mask_origin);
|
||||
|
||||
// If the clip rect completely contains this tile rect, then drawing
|
||||
// these pixels would be redundant - since this clip can't possibly
|
||||
|
|
|
@ -1072,7 +1072,7 @@ fn add_corner_segment(
|
|||
}
|
||||
|
||||
let texture_rect = segment_rect
|
||||
.translate(&-image_rect.origin.to_vector())
|
||||
.translate(-image_rect.origin.to_vector())
|
||||
.scale(1.0 / image_rect.size.width, 1.0 / image_rect.size.height);
|
||||
|
||||
brush_segments.push(
|
||||
|
|
|
@ -100,7 +100,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
// exists in the local space of the primitive.
|
||||
let shadow_rect = prim_info
|
||||
.rect
|
||||
.translate(box_offset)
|
||||
.translate(*box_offset)
|
||||
.inflate(spread_amount, spread_amount);
|
||||
|
||||
// If blur radius is zero, we can use a fast path with
|
||||
|
@ -201,7 +201,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
let shadow_clip_source = ClipItemKey::box_shadow(
|
||||
shadow_rect,
|
||||
shadow_radius,
|
||||
dest_rect.translate(&LayoutVector2D::new(-prim_info.rect.origin.x, -prim_info.rect.origin.y)),
|
||||
dest_rect.translate(LayoutVector2D::new(-prim_info.rect.origin.x, -prim_info.rect.origin.y)),
|
||||
blur_radius,
|
||||
clip_mode,
|
||||
);
|
||||
|
|
|
@ -958,7 +958,7 @@ impl<I: Iterator<Item = ComplexClipRegion>> Iterator for ComplexTranslateIter<I>
|
|||
self.source
|
||||
.next()
|
||||
.map(|mut complex| {
|
||||
complex.rect = complex.rect.translate(&self.offset);
|
||||
complex.rect = complex.rect.translate(self.offset);
|
||||
complex
|
||||
})
|
||||
}
|
||||
|
@ -982,11 +982,11 @@ impl<J> ClipRegion<ComplexTranslateIter<J>> {
|
|||
J: Iterator<Item = ComplexClipRegion>
|
||||
{
|
||||
if let Some(ref mut image_mask) = image_mask {
|
||||
image_mask.rect = image_mask.rect.translate(reference_frame_relative_offset);
|
||||
image_mask.rect = image_mask.rect.translate(*reference_frame_relative_offset);
|
||||
}
|
||||
|
||||
ClipRegion {
|
||||
main: rect.translate(reference_frame_relative_offset),
|
||||
main: rect.translate(*reference_frame_relative_offset),
|
||||
image_mask,
|
||||
complex_clips: ComplexTranslateIter {
|
||||
source: complex_clips,
|
||||
|
@ -1002,7 +1002,7 @@ impl ClipRegion<Option<ComplexClipRegion>> {
|
|||
reference_frame_relative_offset: &LayoutVector2D
|
||||
) -> Self {
|
||||
ClipRegion {
|
||||
main: local_clip.translate(reference_frame_relative_offset),
|
||||
main: local_clip.translate(*reference_frame_relative_offset),
|
||||
image_mask: None,
|
||||
complex_clips: None,
|
||||
}
|
||||
|
@ -1494,7 +1494,7 @@ pub fn rounded_rectangle_contains_point(
|
|||
rect: &LayoutRect,
|
||||
radii: &BorderRadius
|
||||
) -> bool {
|
||||
if !rect.contains(point) {
|
||||
if !rect.contains(*point) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1532,10 +1532,10 @@ pub fn project_inner_rect(
|
|||
rect: &LayoutRect,
|
||||
) -> Option<WorldRect> {
|
||||
let points = [
|
||||
transform.transform_point2d(&rect.origin)?,
|
||||
transform.transform_point2d(&rect.top_right())?,
|
||||
transform.transform_point2d(&rect.bottom_left())?,
|
||||
transform.transform_point2d(&rect.bottom_right())?,
|
||||
transform.transform_point2d(rect.origin)?,
|
||||
transform.transform_point2d(rect.top_right())?,
|
||||
transform.transform_point2d(rect.bottom_left())?,
|
||||
transform.transform_point2d(rect.bottom_right())?,
|
||||
];
|
||||
|
||||
let mut xs = [points[0].x, points[1].x, points[2].x, points[3].x];
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use api::{ExternalScrollId, PropertyBinding, ReferenceFrameKind, TransformStyle};
|
||||
use api::{PipelineId, ScrollClamping, ScrollNodeState, ScrollLocation, ScrollSensitivity};
|
||||
use api::units::*;
|
||||
use euclid::TypedTransform3D;
|
||||
use euclid::Transform3D;
|
||||
use crate::gpu_types::TransformPalette;
|
||||
use crate::internal_types::{FastHashMap, FastHashSet};
|
||||
use crate::print_tree::{PrintableTree, PrintTree, PrintTreePrinter};
|
||||
|
@ -146,13 +146,13 @@ pub struct TransformUpdateState {
|
|||
pub enum CoordinateSpaceMapping<Src, Dst> {
|
||||
Local,
|
||||
ScaleOffset(ScaleOffset),
|
||||
Transform(TypedTransform3D<f32, Src, Dst>),
|
||||
Transform(Transform3D<f32, Src, Dst>),
|
||||
}
|
||||
|
||||
impl<Src, Dst> CoordinateSpaceMapping<Src, Dst> {
|
||||
pub fn into_transform(self) -> TypedTransform3D<f32, Src, Dst> {
|
||||
pub fn into_transform(self) -> Transform3D<f32, Src, Dst> {
|
||||
match self {
|
||||
CoordinateSpaceMapping::Local => TypedTransform3D::identity(),
|
||||
CoordinateSpaceMapping::Local => Transform3D::identity(),
|
||||
CoordinateSpaceMapping::ScaleOffset(scale_offset) => scale_offset.to_transform(),
|
||||
CoordinateSpaceMapping::Transform(transform) => transform,
|
||||
}
|
||||
|
@ -287,10 +287,10 @@ impl ClipScrollTree {
|
|||
}
|
||||
|
||||
coordinate_system_id = coord_system.parent.expect("invalid parent!");
|
||||
transform = transform.post_mul(&coord_system.transform);
|
||||
transform = transform.post_transform(&coord_system.transform);
|
||||
}
|
||||
|
||||
transform = transform.post_mul(
|
||||
transform = transform.post_transform(
|
||||
&parent.content_transform
|
||||
.inverse()
|
||||
.to_transform(),
|
||||
|
@ -320,7 +320,7 @@ impl ClipScrollTree {
|
|||
};
|
||||
let transform = scale_offset
|
||||
.to_transform()
|
||||
.post_mul(&system.world_transform);
|
||||
.post_transform(&system.world_transform);
|
||||
|
||||
CoordinateSpaceMapping::Transform(transform)
|
||||
}
|
||||
|
@ -715,7 +715,7 @@ fn test_pt(
|
|||
|
||||
let p = LayoutPoint::new(px, py);
|
||||
let m = cst.get_relative_transform(child, parent).into_transform();
|
||||
let pt = m.transform_point2d(&p).unwrap();
|
||||
let pt = m.transform_point2d(p).unwrap();
|
||||
assert!(pt.x.approx_eq_eps(&expected_x, &EPSILON) &&
|
||||
pt.y.approx_eq_eps(&expected_y, &EPSILON),
|
||||
"p: {:?} -> {:?}\nm={:?}",
|
||||
|
|
|
@ -7,7 +7,7 @@ use api::units::*;
|
|||
use crate::debug_font_data;
|
||||
use crate::device::{Device, Program, Texture, TextureSlot, VertexDescriptor, ShaderError, VAO};
|
||||
use crate::device::{TextureFilter, VertexAttribute, VertexAttributeKind, VertexUsageHint};
|
||||
use euclid::{Point2D, Rect, Size2D, Transform3D};
|
||||
use euclid::{Point2D, Rect, Size2D, Transform3D, default};
|
||||
use crate::internal_types::{ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE};
|
||||
use std::f32;
|
||||
|
||||
|
@ -193,7 +193,7 @@ impl DebugRenderer {
|
|||
text: &str,
|
||||
color: ColorU,
|
||||
bounds: Option<DeviceRect>,
|
||||
) -> Rect<f32> {
|
||||
) -> default::Rect<f32> {
|
||||
let mut x_start = x;
|
||||
let ipw = 1.0 / debug_font_data::BMP_WIDTH as f32;
|
||||
let iph = 1.0 / debug_font_data::BMP_HEIGHT as f32;
|
||||
|
|
|
@ -6,7 +6,7 @@ use super::super::shader_source::SHADERS;
|
|||
use api::{ColorF, ImageDescriptor, ImageFormat, MemoryReport};
|
||||
use api::{MixBlendMode, TextureTarget, VoidPtrToSizeFn};
|
||||
use api::units::*;
|
||||
use euclid::Transform3D;
|
||||
use euclid::default::Transform3D;
|
||||
use gleam::gl;
|
||||
use crate::internal_types::{FastHashMap, LayerIndex, RenderTargetInfo};
|
||||
use log::Level;
|
||||
|
@ -1045,7 +1045,7 @@ pub enum DrawTarget {
|
|||
|
||||
impl DrawTarget {
|
||||
pub fn new_default(size: DeviceIntSize) -> Self {
|
||||
let total_size = FramebufferIntSize::from_untyped(&size.to_untyped());
|
||||
let total_size = FramebufferIntSize::from_untyped(size.to_untyped());
|
||||
DrawTarget::Default {
|
||||
rect: total_size.into(),
|
||||
total_size,
|
||||
|
@ -1085,9 +1085,9 @@ impl DrawTarget {
|
|||
/// Returns the dimensions of this draw-target.
|
||||
pub fn dimensions(&self) -> DeviceIntSize {
|
||||
match *self {
|
||||
DrawTarget::Default { total_size, .. } => DeviceIntSize::from_untyped(&total_size.to_untyped()),
|
||||
DrawTarget::Default { total_size, .. } => DeviceIntSize::from_untyped(total_size.to_untyped()),
|
||||
DrawTarget::Texture { dimensions, .. } => dimensions,
|
||||
DrawTarget::External { size, .. } => DeviceIntSize::from_untyped(&size.to_untyped()),
|
||||
DrawTarget::External { size, .. } => DeviceIntSize::from_untyped(size.to_untyped()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1117,7 +1117,7 @@ impl DrawTarget {
|
|||
match scissor_rect {
|
||||
Some(scissor_rect) => match *self {
|
||||
DrawTarget::Default { ref rect, .. } => {
|
||||
self.to_framebuffer_rect(scissor_rect.translate(&-content_origin.to_vector()))
|
||||
self.to_framebuffer_rect(scissor_rect.translate(-content_origin.to_vector()))
|
||||
.intersection(rect)
|
||||
.unwrap_or_else(FramebufferIntRect::zero)
|
||||
}
|
||||
|
@ -1128,7 +1128,7 @@ impl DrawTarget {
|
|||
None => {
|
||||
FramebufferIntRect::new(
|
||||
FramebufferIntPoint::zero(),
|
||||
FramebufferIntSize::from_untyped(&dimensions.to_untyped()),
|
||||
FramebufferIntSize::from_untyped(dimensions.to_untyped()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1599,7 +1599,7 @@ impl Device {
|
|||
DrawTarget::Texture { dimensions, fbo_id, with_depth, .. } => {
|
||||
let rect = FramebufferIntRect::new(
|
||||
FramebufferIntPoint::zero(),
|
||||
FramebufferIntSize::from_untyped(&dimensions.to_untyped()),
|
||||
FramebufferIntSize::from_untyped(dimensions.to_untyped()),
|
||||
);
|
||||
(fbo_id, rect, with_depth)
|
||||
},
|
||||
|
@ -2004,7 +2004,7 @@ impl Device {
|
|||
} else {
|
||||
let rect = FramebufferIntRect::new(
|
||||
FramebufferIntPoint::zero(),
|
||||
FramebufferIntSize::from_untyped(&src.get_dimensions().to_untyped()),
|
||||
FramebufferIntSize::from_untyped(src.get_dimensions().to_untyped()),
|
||||
);
|
||||
for layer in 0..src.layer_count.min(dst.layer_count) as LayerIndex {
|
||||
self.blit_render_target(
|
||||
|
|
|
@ -704,7 +704,7 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
parent_node_index: SpatialNodeIndex,
|
||||
) {
|
||||
let current_offset = self.current_offset(parent_node_index);
|
||||
let frame_rect = info.bounds.translate(¤t_offset);
|
||||
let frame_rect = info.bounds.translate(current_offset);
|
||||
let sticky_frame_info = StickyFrameInfo::new(
|
||||
frame_rect,
|
||||
info.margins,
|
||||
|
@ -966,8 +966,8 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
|
||||
let current_offset = self.current_offset(clip_and_scroll.spatial_node_index);
|
||||
|
||||
let clip_rect = common.clip_rect.translate(¤t_offset);
|
||||
let rect = bounds.translate(¤t_offset);
|
||||
let clip_rect = common.clip_rect.translate(current_offset);
|
||||
let rect = bounds.translate(current_offset);
|
||||
let layout = LayoutPrimitiveInfo {
|
||||
rect,
|
||||
clip_rect,
|
||||
|
@ -2530,9 +2530,9 @@ impl<'a> DisplayListFlattener<'a> {
|
|||
{
|
||||
// Offset the local rect and clip rect by the shadow offset.
|
||||
let mut info = pending_primitive.info.clone();
|
||||
info.rect = info.rect.translate(&pending_shadow.shadow.offset);
|
||||
info.rect = info.rect.translate(pending_shadow.shadow.offset);
|
||||
info.clip_rect = info.clip_rect.translate(
|
||||
&pending_shadow.shadow.offset
|
||||
pending_shadow.shadow.offset
|
||||
);
|
||||
|
||||
// Construct and add a primitive for the given shadow.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use api::units::*;
|
||||
use euclid::TypedSize2D;
|
||||
use euclid::Size2D;
|
||||
use std::f32::consts::FRAC_PI_2;
|
||||
|
||||
|
||||
|
@ -13,12 +13,12 @@ const STEP_COUNT: usize = 20;
|
|||
/// Represents an ellipse centred at a local space origin.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Ellipse<U> {
|
||||
pub radius: TypedSize2D<f32, U>,
|
||||
pub radius: Size2D<f32, U>,
|
||||
pub total_arc_length: f32,
|
||||
}
|
||||
|
||||
impl<U> Ellipse<U> {
|
||||
pub fn new(radius: TypedSize2D<f32, U>) -> Ellipse<U> {
|
||||
pub fn new(radius: Size2D<f32, U>) -> Ellipse<U> {
|
||||
// Approximate the total length of the first quadrant of this ellipse.
|
||||
let total_arc_length = get_simpson_length(FRAC_PI_2, radius.width, radius.height);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ use api::{DebugFlags, DocumentId, PremultipliedColorF};
|
|||
#[cfg(test)]
|
||||
use api::IdNamespace;
|
||||
use api::units::TexelRect;
|
||||
use euclid::{HomogeneousVector, TypedRect};
|
||||
use euclid::{HomogeneousVector, Rect};
|
||||
use crate::internal_types::{FastHashMap, FastHashSet};
|
||||
use crate::profiler::GpuCacheProfileCounters;
|
||||
use crate::render_backend::{FrameStamp, FrameId};
|
||||
|
@ -102,8 +102,8 @@ impl From<[f32; 4]> for GpuBlockData {
|
|||
}
|
||||
}
|
||||
|
||||
impl<P> From<TypedRect<f32, P>> for GpuBlockData {
|
||||
fn from(r: TypedRect<f32, P>) -> Self {
|
||||
impl<P> From<Rect<f32, P>> for GpuBlockData {
|
||||
fn from(r: Rect<f32, P>) -> Self {
|
||||
GpuBlockData {
|
||||
data: [
|
||||
r.origin.x,
|
||||
|
|
|
@ -197,9 +197,9 @@ impl HitTestRegion {
|
|||
pub fn contains(&self, point: &LayoutPoint) -> bool {
|
||||
match *self {
|
||||
HitTestRegion::Rectangle(ref rectangle, ClipMode::Clip) =>
|
||||
rectangle.contains(point),
|
||||
rectangle.contains(*point),
|
||||
HitTestRegion::Rectangle(ref rectangle, ClipMode::ClipOut) =>
|
||||
!rectangle.contains(point),
|
||||
!rectangle.contains(*point),
|
||||
HitTestRegion::RoundedRectangle(rect, radii, ClipMode::Clip) =>
|
||||
rounded_rectangle_contains_point(point, &rect, &radii),
|
||||
HitTestRegion::RoundedRectangle(rect, radii, ClipMode::ClipOut) =>
|
||||
|
@ -342,7 +342,7 @@ impl HitTester {
|
|||
.world_content_transform;
|
||||
let transformed_point = match transform
|
||||
.inverse()
|
||||
.and_then(|inverted| inverted.transform_point2d(&point))
|
||||
.and_then(|inverted| inverted.transform_point2d(point))
|
||||
{
|
||||
Some(point) => point,
|
||||
None => {
|
||||
|
@ -375,7 +375,7 @@ impl HitTester {
|
|||
point_in_layer = scroll_node
|
||||
.world_content_transform
|
||||
.inverse()
|
||||
.and_then(|inverted| inverted.transform_point2d(&point));
|
||||
.and_then(|inverted| inverted.transform_point2d(point));
|
||||
|
||||
current_spatial_node_index = item.spatial_node_index;
|
||||
}
|
||||
|
@ -384,10 +384,10 @@ impl HitTester {
|
|||
if let Some(point_in_layer) = point_in_layer {
|
||||
// If the item's rect or clip rect don't contain this point,
|
||||
// it's not a valid hit.
|
||||
if !item.rect.contains(&point_in_layer) {
|
||||
if !item.rect.contains(point_in_layer) {
|
||||
continue;
|
||||
}
|
||||
if !item.clip_rect.contains(&point_in_layer) {
|
||||
if !item.clip_rect.contains(point_in_layer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -436,7 +436,7 @@ impl HitTester {
|
|||
point_in_layer = scroll_node
|
||||
.world_content_transform
|
||||
.inverse()
|
||||
.and_then(|inverted| inverted.transform_point2d(&point));
|
||||
.and_then(|inverted| inverted.transform_point2d(point));
|
||||
current_spatial_node_index = item.spatial_node_index;
|
||||
}
|
||||
|
||||
|
@ -444,10 +444,10 @@ impl HitTester {
|
|||
if let Some(point_in_layer) = point_in_layer {
|
||||
// If the item's rect or clip rect don't contain this point,
|
||||
// it's not a valid hit.
|
||||
if !item.rect.contains(&point_in_layer) {
|
||||
if !item.rect.contains(point_in_layer) {
|
||||
continue;
|
||||
}
|
||||
if !item.clip_rect.contains(&point_in_layer) {
|
||||
if !item.clip_rect.contains(point_in_layer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -480,7 +480,7 @@ impl HitTester {
|
|||
point_in_viewport = root_node
|
||||
.world_viewport_transform
|
||||
.inverse()
|
||||
.and_then(|inverted| inverted.transform_point2d(&point))
|
||||
.and_then(|inverted| inverted.transform_point2d(point))
|
||||
.map(|pt| pt - scroll_node.external_scroll_offset);
|
||||
|
||||
current_root_spatial_node_index = root_spatial_node_index;
|
||||
|
@ -562,7 +562,7 @@ impl HitTest {
|
|||
return self.point;
|
||||
}
|
||||
|
||||
let point = &LayoutPoint::new(self.point.x, self.point.y);
|
||||
let point = LayoutPoint::new(self.point.x, self.point.y);
|
||||
self.pipeline_id
|
||||
.and_then(|id|
|
||||
hit_tester
|
||||
|
|
|
@ -12,7 +12,7 @@ use crate::clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX,
|
|||
ClipScrollTree, CoordinateSpaceMapping, SpatialNodeIndex, VisibleFace, CoordinateSystemId
|
||||
};
|
||||
use crate::debug_colors;
|
||||
use euclid::{vec3, TypedPoint2D, TypedScale, TypedSize2D, Vector2D, TypedRect};
|
||||
use euclid::{vec3, Point2D, Scale, Size2D, Vector2D, Rect};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use crate::filterdata::SFilterData;
|
||||
use crate::frame_builder::{FrameVisibilityContext, FrameVisibilityState};
|
||||
|
@ -139,9 +139,9 @@ impl RetainedTiles {
|
|||
pub struct TileCoordinate;
|
||||
|
||||
// Geometry types for tile coordinates.
|
||||
pub type TileOffset = TypedPoint2D<i32, TileCoordinate>;
|
||||
pub type TileSize = TypedSize2D<i32, TileCoordinate>;
|
||||
pub type TileRect = TypedRect<i32, TileCoordinate>;
|
||||
pub type TileOffset = Point2D<i32, TileCoordinate>;
|
||||
pub type TileSize = Size2D<i32, TileCoordinate>;
|
||||
pub type TileRect = Rect<i32, TileCoordinate>;
|
||||
|
||||
/// The size in device pixels of a cached tile. The currently chosen
|
||||
/// size is arbitrary. We should do some profiling to find the best
|
||||
|
@ -1613,7 +1613,7 @@ impl PictureCompositeMode {
|
|||
let inflation_factor = primitive.shadow.blur_radius.round() * BLUR_SAMPLE_SCALE;
|
||||
let input = primitive.input.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect);
|
||||
let shadow_rect = input.inflate(inflation_factor, inflation_factor);
|
||||
input.union(&shadow_rect.translate(&(primitive.shadow.offset * TypedScale::new(1.0))))
|
||||
input.union(&shadow_rect.translate(primitive.shadow.offset * Scale::new(1.0)))
|
||||
}
|
||||
FilterPrimitiveKind::Blend(ref primitive) => {
|
||||
primitive.input1.to_index(cur_index).map(|index| output_rects[index]).unwrap_or(picture_rect)
|
||||
|
@ -2691,7 +2691,7 @@ impl PicturePrimitive {
|
|||
match transform {
|
||||
CoordinateSpaceMapping::Local => {
|
||||
let polygon = Polygon::from_rect(
|
||||
local_rect * TypedScale::new(1.0),
|
||||
local_rect * Scale::new(1.0),
|
||||
plane_split_anchor,
|
||||
);
|
||||
splitter.add(polygon);
|
||||
|
@ -2754,10 +2754,10 @@ impl PicturePrimitive {
|
|||
};
|
||||
|
||||
let local_points = [
|
||||
transform.transform_point3d(&poly.points[0].cast()).unwrap(),
|
||||
transform.transform_point3d(&poly.points[1].cast()).unwrap(),
|
||||
transform.transform_point3d(&poly.points[2].cast()).unwrap(),
|
||||
transform.transform_point3d(&poly.points[3].cast()).unwrap(),
|
||||
transform.transform_point3d(poly.points[0].cast()).unwrap(),
|
||||
transform.transform_point3d(poly.points[1].cast()).unwrap(),
|
||||
transform.transform_point3d(poly.points[2].cast()).unwrap(),
|
||||
transform.transform_point3d(poly.points[3].cast()).unwrap(),
|
||||
];
|
||||
let gpu_blocks = [
|
||||
[local_points[0].x, local_points[0].y, local_points[1].x, local_points[1].y].into(),
|
||||
|
@ -2961,7 +2961,7 @@ impl PicturePrimitive {
|
|||
// This inflaction factor is to be applied to the surface itself.
|
||||
surface.rect = raster_config.composite_mode.inflate_picture_rect(surface.rect, surface.inflation_factor);
|
||||
|
||||
let mut surface_rect = surface.rect * TypedScale::new(1.0);
|
||||
let mut surface_rect = surface.rect * Scale::new(1.0);
|
||||
|
||||
// Pop this surface from the stack
|
||||
let surface_index = state.pop_surface();
|
||||
|
@ -2988,7 +2988,7 @@ impl PicturePrimitive {
|
|||
PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
|
||||
for shadow in shadows {
|
||||
let content_rect = surface_rect;
|
||||
let shadow_rect = surface_rect.translate(&shadow.offset);
|
||||
let shadow_rect = surface_rect.translate(shadow.offset);
|
||||
surface_rect = content_rect.union(&shadow_rect);
|
||||
}
|
||||
}
|
||||
|
@ -3050,7 +3050,7 @@ impl PicturePrimitive {
|
|||
// Basic brush primitive header is (see end of prepare_prim_for_render_inner in prim_store.rs)
|
||||
// [brush specific data]
|
||||
// [segment_rect, segment data]
|
||||
let shadow_rect = self.snapped_local_rect.translate(&shadow.offset);
|
||||
let shadow_rect = self.snapped_local_rect.translate(shadow.offset);
|
||||
|
||||
// ImageBrush colors
|
||||
request.push(shadow.color.premultiplied());
|
||||
|
@ -3113,7 +3113,7 @@ fn calculate_screen_uv(
|
|||
device_pixel_scale: DevicePixelScale,
|
||||
supports_snapping: bool,
|
||||
) -> DeviceHomogeneousVector {
|
||||
let raster_pos = transform.transform_point2d_homogeneous(local_pos);
|
||||
let raster_pos = transform.transform_point2d_homogeneous(*local_pos);
|
||||
|
||||
let mut device_vec = DeviceHomogeneousVector::new(
|
||||
raster_pos.x * device_pixel_scale.0,
|
||||
|
|
|
@ -22,7 +22,7 @@ use core_graphics::geometry::{CG_AFFINE_TRANSFORM_IDENTITY, CGRect};
|
|||
use core_text;
|
||||
use core_text::font::{CTFont, CTFontRef};
|
||||
use core_text::font_descriptor::{kCTFontDefaultOrientation, kCTFontColorGlyphsTrait};
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
use crate::gamma_lut::{ColorLut, GammaLut};
|
||||
use crate::glyph_rasterizer::{FontInstance, FontTransform, GlyphKey};
|
||||
use crate::glyph_rasterizer::{GlyphFormat, GlyphRasterError, GlyphRasterResult, RasterizedGlyph};
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::clip::{ClipDataStore, ClipNodeFlags, ClipChainId, ClipChainInstance,
|
|||
use crate::debug_colors;
|
||||
use crate::debug_render::DebugItem;
|
||||
use crate::display_list_flattener::{CreateShadow, IsVisible};
|
||||
use euclid::{SideOffsets2D, TypedTransform3D, TypedRect, TypedScale, TypedSize2D, TypedPoint2D};
|
||||
use euclid::{SideOffsets2D, Transform3D, Rect, Scale, Size2D, Point2D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
|
||||
use crate::frame_builder::{FrameVisibilityContext, FrameVisibilityState};
|
||||
|
@ -134,14 +134,14 @@ pub struct SpaceMapper<F, T> {
|
|||
kind: CoordinateSpaceMapping<F, T>,
|
||||
pub ref_spatial_node_index: SpatialNodeIndex,
|
||||
pub current_target_spatial_node_index: SpatialNodeIndex,
|
||||
pub bounds: TypedRect<f32, T>,
|
||||
pub bounds: Rect<f32, T>,
|
||||
visible_face: VisibleFace,
|
||||
}
|
||||
|
||||
impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
|
||||
pub fn new(
|
||||
ref_spatial_node_index: SpatialNodeIndex,
|
||||
bounds: TypedRect<f32, T>,
|
||||
bounds: Rect<f32, T>,
|
||||
) -> Self {
|
||||
SpaceMapper {
|
||||
kind: CoordinateSpaceMapping::Local,
|
||||
|
@ -155,7 +155,7 @@ impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
|
|||
pub fn new_with_target(
|
||||
ref_spatial_node_index: SpatialNodeIndex,
|
||||
target_node_index: SpatialNodeIndex,
|
||||
bounds: TypedRect<f32, T>,
|
||||
bounds: Rect<f32, T>,
|
||||
clip_scroll_tree: &ClipScrollTree,
|
||||
) -> Self {
|
||||
let mut mapper = Self::new(ref_spatial_node_index, bounds);
|
||||
|
@ -195,10 +195,10 @@ impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
|
|||
self.current_target_spatial_node_index = target_node_index;
|
||||
}
|
||||
|
||||
pub fn get_transform(&self) -> TypedTransform3D<f32, F, T> {
|
||||
pub fn get_transform(&self) -> Transform3D<f32, F, T> {
|
||||
match self.kind {
|
||||
CoordinateSpaceMapping::Local => {
|
||||
TypedTransform3D::identity()
|
||||
Transform3D::identity()
|
||||
}
|
||||
CoordinateSpaceMapping::ScaleOffset(ref scale_offset) => {
|
||||
scale_offset.to_transform()
|
||||
|
@ -209,10 +209,10 @@ impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn unmap(&self, rect: &TypedRect<f32, T>) -> Option<TypedRect<f32, F>> {
|
||||
pub fn unmap(&self, rect: &Rect<f32, T>) -> Option<Rect<f32, F>> {
|
||||
match self.kind {
|
||||
CoordinateSpaceMapping::Local => {
|
||||
Some(TypedRect::from_untyped(&rect.to_untyped()))
|
||||
Some(Rect::from_untyped(&rect.to_untyped()))
|
||||
}
|
||||
CoordinateSpaceMapping::ScaleOffset(ref scale_offset) => {
|
||||
Some(scale_offset.unmap_rect(rect))
|
||||
|
@ -223,10 +223,10 @@ impl<F, T> SpaceMapper<F, T> where F: fmt::Debug {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn map(&self, rect: &TypedRect<f32, F>) -> Option<TypedRect<f32, T>> {
|
||||
pub fn map(&self, rect: &Rect<f32, F>) -> Option<Rect<f32, T>> {
|
||||
match self.kind {
|
||||
CoordinateSpaceMapping::Local => {
|
||||
Some(TypedRect::from_untyped(&rect.to_untyped()))
|
||||
Some(Rect::from_untyped(&rect.to_untyped()))
|
||||
}
|
||||
CoordinateSpaceMapping::ScaleOffset(ref scale_offset) => {
|
||||
Some(scale_offset.map_rect(rect))
|
||||
|
@ -407,19 +407,8 @@ impl From<SideOffsetsKey> for LayoutSideOffsets {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<LayoutSideOffsets> for SideOffsetsKey {
|
||||
fn from(offsets: LayoutSideOffsets) -> SideOffsetsKey {
|
||||
SideOffsetsKey {
|
||||
top: offsets.top,
|
||||
right: offsets.right,
|
||||
bottom: offsets.bottom,
|
||||
left: offsets.left,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SideOffsets2D<f32>> for SideOffsetsKey {
|
||||
fn from(offsets: SideOffsets2D<f32>) -> SideOffsetsKey {
|
||||
impl<U> From<SideOffsets2D<f32, U>> for SideOffsetsKey {
|
||||
fn from(offsets: SideOffsets2D<f32, U>) -> SideOffsetsKey {
|
||||
SideOffsetsKey {
|
||||
top: offsets.top,
|
||||
right: offsets.right,
|
||||
|
@ -453,8 +442,8 @@ impl From<SizeKey> for LayoutSize {
|
|||
}
|
||||
}
|
||||
|
||||
impl<U> From<TypedSize2D<f32, U>> for SizeKey {
|
||||
fn from(size: TypedSize2D<f32, U>) -> SizeKey {
|
||||
impl<U> From<Size2D<f32, U>> for SizeKey {
|
||||
fn from(size: Size2D<f32, U>) -> SizeKey {
|
||||
SizeKey {
|
||||
w: size.width,
|
||||
h: size.height,
|
||||
|
@ -1210,7 +1199,7 @@ impl ClipData {
|
|||
pub struct NinePatchDescriptor {
|
||||
pub width: i32,
|
||||
pub height: i32,
|
||||
pub slice: SideOffsets2D<i32>,
|
||||
pub slice: DeviceIntSideOffsets,
|
||||
pub fill: bool,
|
||||
pub repeat_horizontal: RepeatMode,
|
||||
pub repeat_vertical: RepeatMode,
|
||||
|
@ -1942,7 +1931,7 @@ impl PrimitiveStore {
|
|||
PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
|
||||
let mut rect = LayoutRect::zero();
|
||||
for shadow in shadows {
|
||||
rect = rect.union(&pic.snapped_local_rect.translate(&shadow.offset));
|
||||
rect = rect.union(&pic.snapped_local_rect.translate(shadow.offset));
|
||||
}
|
||||
|
||||
rect
|
||||
|
@ -2256,7 +2245,7 @@ impl PrimitiveStore {
|
|||
|
||||
// Layout space for the picture is picture space from the
|
||||
// perspective of its child primitives.
|
||||
let pic_local_rect = surface_rect * TypedScale::new(1.0);
|
||||
let pic_local_rect = surface_rect * Scale::new(1.0);
|
||||
if pic.snapped_local_rect != pic_local_rect {
|
||||
match raster_config.composite_mode {
|
||||
PictureCompositeMode::Filter(Filter::DropShadows(..)) => {
|
||||
|
@ -2788,7 +2777,7 @@ impl PrimitiveStore {
|
|||
if let Some(cache_key) = line_dec_data.cache_key.as_ref() {
|
||||
// TODO(gw): Do we ever need / want to support scales for text decorations
|
||||
// based on the current transform?
|
||||
let scale_factor = TypedScale::new(1.0) * device_pixel_scale;
|
||||
let scale_factor = Scale::new(1.0) * device_pixel_scale;
|
||||
let task_size = (LayoutSize::from_au(cache_key.size) * scale_factor).ceil().to_i32();
|
||||
|
||||
// Request a pre-rendered image task.
|
||||
|
@ -3496,7 +3485,7 @@ impl<'a> GpuDataRequest<'a> {
|
|||
// ensures clip-mask tasks get allocated for these
|
||||
// pixel regions, even if no other clips affect them.
|
||||
let prim_shadow_rect = info.prim_shadow_rect.translate(
|
||||
&LayoutVector2D::new(clip_instance.local_pos.x, clip_instance.local_pos.y),
|
||||
LayoutVector2D::new(clip_instance.local_pos.x, clip_instance.local_pos.y),
|
||||
);
|
||||
segment_builder.push_mask_region(
|
||||
prim_shadow_rect,
|
||||
|
@ -3650,7 +3639,7 @@ impl PrimitiveInstance {
|
|||
frame_state.segment_builder.build(|segment| {
|
||||
segments.push(
|
||||
BrushSegment::new(
|
||||
segment.rect.translate(&-prim_local_rect.origin.to_vector()),
|
||||
segment.rect.translate(-prim_local_rect.origin.to_vector()),
|
||||
segment.has_mask,
|
||||
segment.edge_flags,
|
||||
[0.0; 4],
|
||||
|
@ -3820,7 +3809,7 @@ impl PrimitiveInstance {
|
|||
let segment_clip_chain = frame_state
|
||||
.clip_store
|
||||
.build_clip_chain_instance(
|
||||
segment.local_rect.translate(&LayoutVector2D::new(
|
||||
segment.local_rect.translate(LayoutVector2D::new(
|
||||
self.prim_origin.x,
|
||||
self.prim_origin.y,
|
||||
)),
|
||||
|
@ -3966,12 +3955,12 @@ fn mix(x: f32, y: f32, a: f32) -> f32 {
|
|||
/// Given a point within a local rectangle, and the device space corners
|
||||
/// of a snapped primitive, return the snap offsets.
|
||||
fn compute_snap_offset_impl<PixelSpace>(
|
||||
reference_pos: TypedPoint2D<f32, PixelSpace>,
|
||||
reference_rect: TypedRect<f32, PixelSpace>,
|
||||
reference_pos: Point2D<f32, PixelSpace>,
|
||||
reference_rect: Rect<f32, PixelSpace>,
|
||||
prim_top_left: DevicePoint,
|
||||
prim_bottom_right: DevicePoint,
|
||||
) -> DeviceVector2D {
|
||||
let normalized_snap_pos = TypedPoint2D::<f32, PixelSpace>::new(
|
||||
let normalized_snap_pos = Point2D::<f32, PixelSpace>::new(
|
||||
(reference_pos.x - reference_rect.origin.x) / reference_rect.size.width,
|
||||
(reference_pos.y - reference_rect.origin.y) / reference_rect.size.height,
|
||||
);
|
||||
|
@ -3997,8 +3986,8 @@ fn compute_snap_offset_impl<PixelSpace>(
|
|||
/// This *must* exactly match the logic in the GLSL
|
||||
/// compute_snap_offset function.
|
||||
pub fn recompute_snap_offsets<PixelSpace>(
|
||||
local_rect: TypedRect<f32, PixelSpace>,
|
||||
prim_rect: TypedRect<f32, PixelSpace>,
|
||||
local_rect: Rect<f32, PixelSpace>,
|
||||
prim_rect: Rect<f32, PixelSpace>,
|
||||
snap_offsets: SnapOffsets,
|
||||
) -> SnapOffsets
|
||||
{
|
||||
|
@ -4006,12 +3995,12 @@ pub fn recompute_snap_offsets<PixelSpace>(
|
|||
return SnapOffsets::empty();
|
||||
}
|
||||
|
||||
let normalized_top_left = TypedPoint2D::<f32, PixelSpace>::new(
|
||||
let normalized_top_left = Point2D::<f32, PixelSpace>::new(
|
||||
(local_rect.origin.x - prim_rect.origin.x) / prim_rect.size.width,
|
||||
(local_rect.origin.y - prim_rect.origin.y) / prim_rect.size.height,
|
||||
);
|
||||
|
||||
let normalized_bottom_right = TypedPoint2D::<f32, PixelSpace>::new(
|
||||
let normalized_bottom_right = Point2D::<f32, PixelSpace>::new(
|
||||
(local_rect.origin.x + local_rect.size.width - prim_rect.origin.x) / prim_rect.size.width,
|
||||
(local_rect.origin.y + local_rect.size.height - prim_rect.origin.y) / prim_rect.size.height,
|
||||
);
|
||||
|
@ -4039,7 +4028,7 @@ fn get_unclipped_device_rect(
|
|||
device_pixel_scale: DevicePixelScale,
|
||||
) -> Option<DeviceRect> {
|
||||
let raster_rect = map_to_raster.map(&prim_rect)?;
|
||||
let world_rect = raster_rect * TypedScale::new(1.0);
|
||||
let world_rect = raster_rect * Scale::new(1.0);
|
||||
Some(world_rect * device_pixel_scale)
|
||||
}
|
||||
|
||||
|
@ -4056,9 +4045,9 @@ fn get_clipped_device_rect(
|
|||
device_pixel_scale: DevicePixelScale,
|
||||
) -> Option<(DeviceIntRect, SnapOffsets)> {
|
||||
let unclipped_raster_rect = {
|
||||
let world_rect = *unclipped * TypedScale::new(1.0);
|
||||
let world_rect = *unclipped * Scale::new(1.0);
|
||||
let raster_rect = world_rect * device_pixel_scale.inv();
|
||||
TypedRect::from_untyped(&raster_rect.to_untyped())
|
||||
Rect::from_untyped(&raster_rect.to_untyped())
|
||||
};
|
||||
|
||||
let unclipped_world_rect = map_to_world.map(&unclipped_raster_rect)?;
|
||||
|
@ -4142,10 +4131,10 @@ pub fn get_raster_rects(
|
|||
/// axis-aligned. It return the snapped rect transformed back into the
|
||||
/// given pixel space, and the snap offsets in device space.
|
||||
pub fn get_snapped_rect<PixelSpace>(
|
||||
prim_rect: TypedRect<f32, PixelSpace>,
|
||||
prim_rect: Rect<f32, PixelSpace>,
|
||||
map_to_raster: &SpaceMapper<PixelSpace, RasterPixel>,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) -> Option<(TypedRect<f32, PixelSpace>, SnapOffsets)> where PixelSpace: fmt::Debug {
|
||||
) -> Option<(Rect<f32, PixelSpace>, SnapOffsets)> where PixelSpace: fmt::Debug {
|
||||
let is_axis_aligned = match map_to_raster.kind {
|
||||
CoordinateSpaceMapping::Local |
|
||||
CoordinateSpaceMapping::ScaleOffset(..) => true,
|
||||
|
@ -4156,7 +4145,7 @@ pub fn get_snapped_rect<PixelSpace>(
|
|||
let raster_rect = map_to_raster.map(&prim_rect)?;
|
||||
|
||||
let device_rect = {
|
||||
let world_rect = raster_rect * TypedScale::new(1.0);
|
||||
let world_rect = raster_rect * Scale::new(1.0);
|
||||
world_rect * device_pixel_scale
|
||||
};
|
||||
|
||||
|
@ -4185,7 +4174,7 @@ pub fn get_snapped_rect<PixelSpace>(
|
|||
);
|
||||
|
||||
let snapped_world_rect = snapped_device_rect / device_pixel_scale;
|
||||
let snapped_raster_rect = snapped_world_rect * TypedScale::new(1.0);
|
||||
let snapped_raster_rect = snapped_world_rect * Scale::new(1.0);
|
||||
let snapped_prim_rect = map_to_raster.unmap(&snapped_raster_rect)?;
|
||||
Some((snapped_prim_rect, snap_offsets))
|
||||
} else {
|
||||
|
|
|
@ -323,7 +323,7 @@ impl TextRunPrimitive {
|
|||
glyphs.iter().map(|src| {
|
||||
let src_point = src.point + prim_offset;
|
||||
let world_offset = self.used_font.transform.transform(&src_point);
|
||||
let device_offset = device_pixel_scale.transform_point(&world_offset);
|
||||
let device_offset = device_pixel_scale.transform_point(world_offset);
|
||||
GlyphKey::new(src.index, device_offset, subpx_dir)
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use api::{ColorF, ColorU};
|
||||
use crate::debug_render::DebugRenderer;
|
||||
use crate::device::query::{GpuSampler, GpuTimer, NamedTag};
|
||||
use euclid::{Point2D, Rect, Size2D, vec2};
|
||||
use euclid::{Point2D, Rect, Size2D, vec2, default};
|
||||
use crate::internal_types::FastHashMap;
|
||||
use crate::renderer::{MAX_VERTEX_TEXTURE_WIDTH, wr_has_been_initialized};
|
||||
use std::collections::vec_deque::VecDeque;
|
||||
|
@ -687,7 +687,7 @@ impl ProfileGraph {
|
|||
y: f32,
|
||||
description: &'static str,
|
||||
debug_renderer: &mut DebugRenderer,
|
||||
) -> Rect<f32> {
|
||||
) -> default::Rect<f32> {
|
||||
let size = Size2D::new(600.0, 120.0);
|
||||
let line_height = debug_renderer.line_height();
|
||||
let graph_rect = Rect::new(Point2D::new(x, y), size);
|
||||
|
@ -812,7 +812,7 @@ impl GpuFrameCollection {
|
|||
}
|
||||
|
||||
impl GpuFrameCollection {
|
||||
fn draw(&self, x: f32, y: f32, debug_renderer: &mut DebugRenderer) -> Rect<f32> {
|
||||
fn draw(&self, x: f32, y: f32, debug_renderer: &mut DebugRenderer) -> default::Rect<f32> {
|
||||
let graph_rect = Rect::new(
|
||||
Point2D::new(x, y),
|
||||
Size2D::new(GRAPH_WIDTH, GRAPH_HEIGHT),
|
||||
|
@ -1019,7 +1019,7 @@ impl Profiler {
|
|||
label_color: ColorU,
|
||||
counters: &[(ColorU, &IntProfileCounter)],
|
||||
debug_renderer: &mut DebugRenderer,
|
||||
) -> Rect<f32> {
|
||||
) -> default::Rect<f32> {
|
||||
let mut rect = debug_renderer.add_text(
|
||||
self.draw_state.x_left,
|
||||
self.draw_state.y_left,
|
||||
|
|
|
@ -1723,8 +1723,8 @@ impl RenderTask {
|
|||
};
|
||||
|
||||
if let Some(mut request) = gpu_cache.request(cache_handle) {
|
||||
let p0 = target_rect.origin.to_f32();
|
||||
let p1 = target_rect.bottom_right().to_f32();
|
||||
let p0 = target_rect.min().to_f32();
|
||||
let p1 = target_rect.max().to_f32();
|
||||
let image_source = ImageSource {
|
||||
p0,
|
||||
p1,
|
||||
|
|
|
@ -55,7 +55,7 @@ use crate::device::{ShaderError, TextureFilter, TextureFlags,
|
|||
VertexUsageHint, VAO, VBO, CustomVAO};
|
||||
use crate::device::{ProgramCache};
|
||||
use crate::device::query::GpuTimer;
|
||||
use euclid::{rect, Transform3D, TypedScale};
|
||||
use euclid::{rect, Transform3D, Scale, default};
|
||||
use crate::frame_builder::{ChasePrimitive, FrameBuilderConfig};
|
||||
use gleam::gl;
|
||||
use crate::glyph_cache::GlyphCache;
|
||||
|
@ -3321,7 +3321,7 @@ impl Renderer {
|
|||
readback_rect.size,
|
||||
);
|
||||
let mut dest = readback_rect.to_i32();
|
||||
let device_to_framebuffer = TypedScale::new(1i32);
|
||||
let device_to_framebuffer = Scale::new(1i32);
|
||||
|
||||
// Need to invert the y coordinates and flip the image vertically when
|
||||
// reading back from the framebuffer.
|
||||
|
@ -3397,7 +3397,7 @@ impl Renderer {
|
|||
read_target.into(),
|
||||
read_target.to_framebuffer_rect(source_rect),
|
||||
draw_target,
|
||||
draw_target.to_framebuffer_rect(blit.target_rect.translate(&-content_origin.to_vector())),
|
||||
draw_target.to_framebuffer_rect(blit.target_rect.translate(-content_origin.to_vector())),
|
||||
TextureFilter::Linear,
|
||||
);
|
||||
}
|
||||
|
@ -3407,7 +3407,7 @@ impl Renderer {
|
|||
&mut self,
|
||||
scalings: &[ScalingInstance],
|
||||
source: TextureSource,
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
if scalings.is_empty() {
|
||||
|
@ -3437,7 +3437,7 @@ impl Renderer {
|
|||
&mut self,
|
||||
textures: &BatchTextures,
|
||||
svg_filters: &[SvgFilterInstance],
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
if svg_filters.is_empty() {
|
||||
|
@ -3465,7 +3465,7 @@ impl Renderer {
|
|||
target: &PictureCacheTarget,
|
||||
draw_target: DrawTarget,
|
||||
content_origin: DeviceIntPoint,
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
render_tasks: &RenderTaskGraph,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
|
@ -3508,7 +3508,7 @@ impl Renderer {
|
|||
draw_target: DrawTarget,
|
||||
content_origin: DeviceIntPoint,
|
||||
framebuffer_kind: FramebufferKind,
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
render_tasks: &RenderTaskGraph,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
|
@ -3718,7 +3718,7 @@ impl Renderer {
|
|||
clear_color: Option<[f32; 4]>,
|
||||
clear_depth: Option<f32>,
|
||||
render_tasks: &RenderTaskGraph,
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
frame_id: GpuFrameId,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
|
@ -3874,7 +3874,7 @@ impl Renderer {
|
|||
let (src_rect, _) = render_tasks[output.task_id].get_target_rect();
|
||||
self.device.blit_render_target_invert_y(
|
||||
draw_target.into(),
|
||||
draw_target.to_framebuffer_rect(src_rect.translate(&-content_origin.to_vector())),
|
||||
draw_target.to_framebuffer_rect(src_rect.translate(-content_origin.to_vector())),
|
||||
DrawTarget::External { fbo: fbo_id, size: output_size },
|
||||
output_size.into(),
|
||||
);
|
||||
|
@ -3887,7 +3887,7 @@ impl Renderer {
|
|||
fn draw_clip_batch_list(
|
||||
&mut self,
|
||||
list: &ClipBatchList,
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
if self.debug_flags.contains(DebugFlags::DISABLE_CLIP_MASKS) {
|
||||
|
@ -3968,7 +3968,7 @@ impl Renderer {
|
|||
&mut self,
|
||||
draw_target: DrawTarget,
|
||||
target: &AlphaRenderTarget,
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
render_tasks: &RenderTaskGraph,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
|
@ -4508,7 +4508,7 @@ impl Renderer {
|
|||
ORTHO_FAR_PLANE,
|
||||
);
|
||||
|
||||
let fb_scale = TypedScale::<_, _, FramebufferPixel>::new(1i32);
|
||||
let fb_scale = Scale::<_, _, FramebufferPixel>::new(1i32);
|
||||
let mut fb_rect = frame.device_rect * fb_scale;
|
||||
fb_rect.origin.y = device_size.height - fb_rect.origin.y - fb_rect.size.height;
|
||||
|
||||
|
@ -4695,7 +4695,7 @@ impl Renderer {
|
|||
pub fn init_pixel_local_storage(
|
||||
&mut self,
|
||||
task_rect: DeviceIntRect,
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
self.device.enable_pixel_local_storage(true);
|
||||
|
@ -4725,7 +4725,7 @@ impl Renderer {
|
|||
pub fn resolve_pixel_local_storage(
|
||||
&mut self,
|
||||
task_rect: DeviceIntRect,
|
||||
projection: &Transform3D<f32>,
|
||||
projection: &default::Transform3D<f32>,
|
||||
stats: &mut RendererStats,
|
||||
) {
|
||||
self.shaders
|
||||
|
@ -4888,7 +4888,7 @@ impl Renderer {
|
|||
|
||||
let texture_rect = FramebufferIntRect::new(
|
||||
FramebufferIntPoint::zero(),
|
||||
FramebufferIntSize::from_untyped(&source_rect.size.to_untyped()),
|
||||
FramebufferIntSize::from_untyped(source_rect.size.to_untyped()),
|
||||
);
|
||||
|
||||
debug_renderer.add_rect(
|
||||
|
@ -5145,7 +5145,7 @@ impl Renderer {
|
|||
|
||||
pub fn read_gpu_cache(&mut self) -> (DeviceIntSize, Vec<u8>) {
|
||||
let texture = self.gpu_cache_texture.texture.as_ref().unwrap();
|
||||
let size = FramebufferIntSize::from_untyped(&texture.get_dimensions().to_untyped());
|
||||
let size = FramebufferIntSize::from_untyped(texture.get_dimensions().to_untyped());
|
||||
let mut texels = vec![0; (size.width * size.height * 16) as usize];
|
||||
self.device.begin_frame();
|
||||
self.device.bind_read_target(ReadTarget::from_texture(texture, 0));
|
||||
|
@ -5666,7 +5666,7 @@ impl Renderer {
|
|||
// read from textures directly with `get_tex_image*`.
|
||||
|
||||
for layer_id in 0 .. texture.get_layer_count() {
|
||||
let rect = FramebufferIntSize::from_untyped(&rect_size.to_untyped()).into();
|
||||
let rect = FramebufferIntSize::from_untyped(rect_size.to_untyped()).into();
|
||||
|
||||
device.attach_read_texture(texture, layer_id);
|
||||
#[cfg(feature = "png")]
|
||||
|
|
|
@ -718,16 +718,16 @@ impl ResourceCache {
|
|||
};
|
||||
|
||||
tiles.retain(|tile, _| {
|
||||
!req.original_tile_range.contains(tile) ||
|
||||
req.actual_tile_range.contains(tile)
|
||||
!req.original_tile_range.contains(*tile) ||
|
||||
req.actual_tile_range.contains(*tile)
|
||||
});
|
||||
|
||||
let texture_cache = &mut self.texture_cache;
|
||||
match self.cached_images.try_get_mut(&req.key.as_image()) {
|
||||
Some(&mut ImageResult::Multi(ref mut entries)) => {
|
||||
entries.retain(|key, entry| {
|
||||
if !req.original_tile_range.contains(&key.tile.unwrap()) ||
|
||||
req.actual_tile_range.contains(&key.tile.unwrap()) {
|
||||
if !req.original_tile_range.contains(key.tile.unwrap()) ||
|
||||
req.actual_tile_range.contains(key.tile.unwrap()) {
|
||||
return true;
|
||||
}
|
||||
entry.mark_unused(texture_cache);
|
||||
|
@ -1386,13 +1386,13 @@ impl ResourceCache {
|
|||
tile_size,
|
||||
);
|
||||
|
||||
tiles.retain(|tile, _| { tile_range.contains(tile) });
|
||||
tiles.retain(|tile, _| { tile_range.contains(*tile) });
|
||||
|
||||
let texture_cache = &mut self.texture_cache;
|
||||
match self.cached_images.try_get_mut(&key.as_image()) {
|
||||
Some(&mut ImageResult::Multi(ref mut entries)) => {
|
||||
entries.retain(|key, entry| {
|
||||
if key.tile.is_none() || tile_range.contains(&key.tile.unwrap()) {
|
||||
if key.tile.is_none() || tile_range.contains(key.tile.unwrap()) {
|
||||
return true;
|
||||
}
|
||||
entry.mark_unused(texture_cache);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use crate::batch::{BatchKey, BatchKind, BrushBatchKind, BatchFeatures};
|
||||
use crate::device::{Device, Program, ShaderError};
|
||||
use euclid::{Transform3D};
|
||||
use euclid::default::Transform3D;
|
||||
use crate::glyph_rasterizer::GlyphFormat;
|
||||
use crate::renderer::{
|
||||
desc,
|
||||
|
|
|
@ -309,8 +309,8 @@ impl SpatialNode {
|
|||
// Do a change-basis operation on the
|
||||
// perspective matrix using the scroll offset.
|
||||
source_transform
|
||||
.pre_translate(&scroll_offset)
|
||||
.post_translate(&-scroll_offset)
|
||||
.pre_translate(scroll_offset)
|
||||
.post_translate(-scroll_offset)
|
||||
}
|
||||
ReferenceFrameKind::Perspective { scrolling_relative_to: None } |
|
||||
ReferenceFrameKind::Transform => source_transform,
|
||||
|
@ -318,14 +318,14 @@ impl SpatialNode {
|
|||
|
||||
let resolved_transform =
|
||||
LayoutFastTransform::with_vector(info.origin_in_parent_reference_frame)
|
||||
.pre_mul(&source_transform);
|
||||
.pre_transform(&source_transform);
|
||||
|
||||
// The transformation for this viewport in world coordinates is the transformation for
|
||||
// our parent reference frame, plus any accumulated scrolling offsets from nodes
|
||||
// between our reference frame and this node. Finally, we also include
|
||||
// whatever local transformation this reference frame provides.
|
||||
let relative_transform = resolved_transform
|
||||
.post_translate(&state.parent_accumulated_scroll_offset)
|
||||
.post_translate(state.parent_accumulated_scroll_offset)
|
||||
.to_transform()
|
||||
.with_destination::<LayoutPixel>();
|
||||
|
||||
|
@ -352,7 +352,7 @@ impl SpatialNode {
|
|||
// new incompatible coordinate system with which we cannot share clips without masking.
|
||||
let transform = state.coordinate_system_relative_scale_offset
|
||||
.to_transform()
|
||||
.pre_mul(&relative_transform);
|
||||
.pre_transform(&relative_transform);
|
||||
|
||||
// Push that new coordinate system and record the new id.
|
||||
let coord_system = {
|
||||
|
@ -361,7 +361,7 @@ impl SpatialNode {
|
|||
if parent_system.should_flatten {
|
||||
cur_transform.flatten_z_output();
|
||||
}
|
||||
let world_transform = cur_transform.post_mul(&parent_system.world_transform);
|
||||
let world_transform = cur_transform.post_transform(&parent_system.world_transform);
|
||||
let determinant = world_transform.determinant();
|
||||
info.invertible = determinant != 0.0 && !determinant.is_nan();
|
||||
|
||||
|
@ -437,7 +437,7 @@ impl SpatialNode {
|
|||
// between the scrolled content and unscrolled viewport we adjust the viewport's
|
||||
// position by the scroll offset in order to work with their relative positions on the
|
||||
// page.
|
||||
let sticky_rect = info.frame_rect.translate(viewport_scroll_offset);
|
||||
let sticky_rect = info.frame_rect.translate(*viewport_scroll_offset);
|
||||
|
||||
let mut sticky_offset = LayoutVector2D::zero();
|
||||
if let Some(margin) = info.margins.top {
|
||||
|
@ -560,7 +560,7 @@ impl SpatialNode {
|
|||
let translation = -info.origin_in_parent_reference_frame;
|
||||
state.nearest_scrolling_ancestor_viewport =
|
||||
state.nearest_scrolling_ancestor_viewport
|
||||
.translate(&translation);
|
||||
.translate(translation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -763,7 +763,7 @@ pub struct ReferenceFrameInfo {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct StickyFrameInfo {
|
||||
pub frame_rect: LayoutRect,
|
||||
pub margins: SideOffsets2D<Option<f32>>,
|
||||
pub margins: SideOffsets2D<Option<f32>, LayoutPixel>,
|
||||
pub vertical_offset_bounds: StickyOffsetBounds,
|
||||
pub horizontal_offset_bounds: StickyOffsetBounds,
|
||||
pub previously_applied_offset: LayoutVector2D,
|
||||
|
@ -773,7 +773,7 @@ pub struct StickyFrameInfo {
|
|||
impl StickyFrameInfo {
|
||||
pub fn new(
|
||||
frame_rect: LayoutRect,
|
||||
margins: SideOffsets2D<Option<f32>>,
|
||||
margins: SideOffsets2D<Option<f32>, LayoutPixel>,
|
||||
vertical_offset_bounds: StickyOffsetBounds,
|
||||
horizontal_offset_bounds: StickyOffsetBounds,
|
||||
previously_applied_offset: LayoutVector2D
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
use api::BorderRadius;
|
||||
use api::units::*;
|
||||
use euclid::{TypedPoint2D, TypedRect, TypedSize2D, Vector2D};
|
||||
use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D, TypedScale};
|
||||
use euclid::{Point2D, Rect, Size2D, Vector2D};
|
||||
use euclid::{default, Transform2D, Transform3D, Scale};
|
||||
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
|
||||
use plane_split::{Clipper, Polygon};
|
||||
use std::{i32, f32, fmt, ptr};
|
||||
|
@ -119,8 +119,8 @@ impl<T> VecHelper<T> for Vec<T> {
|
|||
#[derive(Debug, Clone, Copy, MallocSizeOf)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
pub struct ScaleOffset {
|
||||
pub scale: Vector2D<f32>,
|
||||
pub offset: Vector2D<f32>,
|
||||
pub scale: default::Vector2D<f32>,
|
||||
pub offset: default::Vector2D<f32>,
|
||||
}
|
||||
|
||||
impl ScaleOffset {
|
||||
|
@ -134,7 +134,7 @@ impl ScaleOffset {
|
|||
// Construct a ScaleOffset from a transform. Returns
|
||||
// None if the matrix is not a pure scale / translation.
|
||||
pub fn from_transform<F, T>(
|
||||
m: &TypedTransform3D<f32, F, T>,
|
||||
m: &Transform3D<f32, F, T>,
|
||||
) -> Option<ScaleOffset> {
|
||||
|
||||
// To check that we have a pure scale / translation:
|
||||
|
@ -178,7 +178,7 @@ impl ScaleOffset {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn offset(&self, offset: Vector2D<f32>) -> Self {
|
||||
pub fn offset(&self, offset: default::Vector2D<f32>) -> Self {
|
||||
self.accumulate(
|
||||
&ScaleOffset {
|
||||
scale: Vector2D::new(1.0, 1.0),
|
||||
|
@ -189,7 +189,7 @@ impl ScaleOffset {
|
|||
|
||||
/// Produce a ScaleOffset that includes both self and other.
|
||||
/// The 'self' ScaleOffset is applied after other.
|
||||
/// This is equivalent to `TypedTransform3D::pre_mul`.
|
||||
/// This is equivalent to `Transform3D::pre_transform`.
|
||||
pub fn accumulate(&self, other: &ScaleOffset) -> Self {
|
||||
ScaleOffset {
|
||||
scale: Vector2D::new(
|
||||
|
@ -203,34 +203,34 @@ impl ScaleOffset {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn map_rect<F, T>(&self, rect: &TypedRect<f32, F>) -> TypedRect<f32, T> {
|
||||
TypedRect::new(
|
||||
TypedPoint2D::new(
|
||||
pub fn map_rect<F, T>(&self, rect: &Rect<f32, F>) -> Rect<f32, T> {
|
||||
Rect::new(
|
||||
Point2D::new(
|
||||
rect.origin.x * self.scale.x + self.offset.x,
|
||||
rect.origin.y * self.scale.y + self.offset.y,
|
||||
),
|
||||
TypedSize2D::new(
|
||||
Size2D::new(
|
||||
rect.size.width * self.scale.x,
|
||||
rect.size.height * self.scale.y,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn unmap_rect<F, T>(&self, rect: &TypedRect<f32, F>) -> TypedRect<f32, T> {
|
||||
TypedRect::new(
|
||||
TypedPoint2D::new(
|
||||
pub fn unmap_rect<F, T>(&self, rect: &Rect<f32, F>) -> Rect<f32, T> {
|
||||
Rect::new(
|
||||
Point2D::new(
|
||||
(rect.origin.x - self.offset.x) / self.scale.x,
|
||||
(rect.origin.y - self.offset.y) / self.scale.y,
|
||||
),
|
||||
TypedSize2D::new(
|
||||
Size2D::new(
|
||||
rect.size.width / self.scale.x,
|
||||
rect.size.height / self.scale.y,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_transform<F, T>(&self) -> TypedTransform3D<f32, F, T> {
|
||||
TypedTransform3D::row_major(
|
||||
pub fn to_transform<F, T>(&self) -> Transform3D<f32, F, T> {
|
||||
Transform3D::row_major(
|
||||
self.scale.x,
|
||||
0.0,
|
||||
0.0,
|
||||
|
@ -264,8 +264,8 @@ pub trait MatrixHelpers<Src, Dst> {
|
|||
/// Check if the matrix post-scaling on either the X or Y axes could cause geometry
|
||||
/// transformed by this matrix to have scaling exceeding the supplied limit.
|
||||
fn exceeds_2d_scale(&self, limit: f64) -> bool;
|
||||
fn inverse_project(&self, target: &TypedPoint2D<f32, Dst>) -> Option<TypedPoint2D<f32, Src>>;
|
||||
fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> Option<TypedRect<f32, Src>>;
|
||||
fn inverse_project(&self, target: &Point2D<f32, Dst>) -> Option<Point2D<f32, Src>>;
|
||||
fn inverse_rect_footprint(&self, rect: &Rect<f32, Dst>) -> Option<Rect<f32, Src>>;
|
||||
fn transform_kind(&self) -> TransformedRectKind;
|
||||
fn is_simple_translation(&self) -> bool;
|
||||
fn is_simple_2d_translation(&self) -> bool;
|
||||
|
@ -274,13 +274,13 @@ pub trait MatrixHelpers<Src, Dst> {
|
|||
/// This function returns a point in the `Src` space that projects into zero XY.
|
||||
/// It ignores the Z coordinate and is usable for "flattened" transformations,
|
||||
/// since they are not generally inversible.
|
||||
fn inverse_project_2d_origin(&self) -> Option<TypedPoint2D<f32, Src>>;
|
||||
fn inverse_project_2d_origin(&self) -> Option<Point2D<f32, Src>>;
|
||||
/// Turn Z transformation into identity. This is useful when crossing "flat"
|
||||
/// transform styled stacking contexts upon traversing the coordinate systems.
|
||||
fn flatten_z_output(&mut self);
|
||||
}
|
||||
|
||||
impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
||||
impl<Src, Dst> MatrixHelpers<Src, Dst> for Transform3D<f32, Src, Dst> {
|
||||
fn preserves_2d_axis_alignment(&self) -> bool {
|
||||
if self.m14 != 0.0 || self.m24 != 0.0 {
|
||||
return false;
|
||||
|
@ -328,9 +328,9 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
|||
self.m21 * self.m21 + self.m22 * self.m22 > limit2
|
||||
}
|
||||
|
||||
fn inverse_project(&self, target: &TypedPoint2D<f32, Dst>) -> Option<TypedPoint2D<f32, Src>> {
|
||||
let m: TypedTransform2D<f32, Src, Dst>;
|
||||
m = TypedTransform2D::column_major(
|
||||
fn inverse_project(&self, target: &Point2D<f32, Dst>) -> Option<Point2D<f32, Src>> {
|
||||
let m: Transform2D<f32, Src, Dst>;
|
||||
m = Transform2D::column_major(
|
||||
self.m11 - target.x * self.m14,
|
||||
self.m21 - target.x * self.m24,
|
||||
self.m41 - target.x * self.m44,
|
||||
|
@ -338,11 +338,11 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
|||
self.m22 - target.y * self.m24,
|
||||
self.m42 - target.y * self.m44,
|
||||
);
|
||||
m.inverse().map(|inv| TypedPoint2D::new(inv.m31, inv.m32))
|
||||
m.inverse().map(|inv| Point2D::new(inv.m31, inv.m32))
|
||||
}
|
||||
|
||||
fn inverse_rect_footprint(&self, rect: &TypedRect<f32, Dst>) -> Option<TypedRect<f32, Src>> {
|
||||
Some(TypedRect::from_points(&[
|
||||
fn inverse_rect_footprint(&self, rect: &Rect<f32, Dst>) -> Option<Rect<f32, Src>> {
|
||||
Some(Rect::from_points(&[
|
||||
self.inverse_project(&rect.origin)?,
|
||||
self.inverse_project(&rect.top_right())?,
|
||||
self.inverse_project(&rect.bottom_left())?,
|
||||
|
@ -385,12 +385,12 @@ impl<Src, Dst> MatrixHelpers<Src, Dst> for TypedTransform3D<f32, Src, Dst> {
|
|||
self.m11 * self.m22 - self.m12 * self.m21
|
||||
}
|
||||
|
||||
fn inverse_project_2d_origin(&self) -> Option<TypedPoint2D<f32, Src>> {
|
||||
fn inverse_project_2d_origin(&self) -> Option<Point2D<f32, Src>> {
|
||||
let det = self.determinant_2d();
|
||||
if det != 0.0 {
|
||||
let x = (self.m21 * self.m42 - self.m41 * self.m22) / det;
|
||||
let y = (self.m12 * self.m41 - self.m11 * self.m42) / det;
|
||||
Some(TypedPoint2D::new(x, y))
|
||||
Some(Point2D::new(x, y))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -412,11 +412,11 @@ where
|
|||
fn is_well_formed_and_nonempty(&self) -> bool;
|
||||
}
|
||||
|
||||
impl<U> RectHelpers<U> for TypedRect<f32, U> {
|
||||
impl<U> RectHelpers<U> for Rect<f32, U> {
|
||||
fn from_floats(x0: f32, y0: f32, x1: f32, y1: f32) -> Self {
|
||||
TypedRect::new(
|
||||
TypedPoint2D::new(x0, y0),
|
||||
TypedSize2D::new(x1 - x0, y1 - y0),
|
||||
Rect::new(
|
||||
Point2D::new(x0, y0),
|
||||
Size2D::new(x1 - x0, y1 - y0),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -445,10 +445,10 @@ pub fn pack_as_float(value: u32) -> f32 {
|
|||
|
||||
#[inline]
|
||||
fn extract_inner_rect_impl<U>(
|
||||
rect: &TypedRect<f32, U>,
|
||||
rect: &Rect<f32, U>,
|
||||
radii: &BorderRadius,
|
||||
k: f32,
|
||||
) -> Option<TypedRect<f32, U>> {
|
||||
) -> Option<Rect<f32, U>> {
|
||||
// `k` defines how much border is taken into account
|
||||
// We enforce the offsets to be rounded to pixel boundaries
|
||||
// by `ceil`-ing and `floor`-ing them
|
||||
|
@ -460,9 +460,9 @@ fn extract_inner_rect_impl<U>(
|
|||
(rect.size.height - k * radii.bottom_left.height.max(radii.bottom_right.height)).floor();
|
||||
|
||||
if xl <= xr && yt <= yb {
|
||||
Some(TypedRect::new(
|
||||
TypedPoint2D::new(rect.origin.x + xl, rect.origin.y + yt),
|
||||
TypedSize2D::new(xr - xl, yb - yt),
|
||||
Some(Rect::new(
|
||||
Point2D::new(rect.origin.x + xl, rect.origin.y + yt),
|
||||
Size2D::new(xr - xl, yb - yt),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
|
@ -472,9 +472,9 @@ fn extract_inner_rect_impl<U>(
|
|||
/// Return an aligned rectangle that is inside the clip region and doesn't intersect
|
||||
/// any of the bounding rectangles of the rounded corners.
|
||||
pub fn extract_inner_rect_safe<U>(
|
||||
rect: &TypedRect<f32, U>,
|
||||
rect: &Rect<f32, U>,
|
||||
radii: &BorderRadius,
|
||||
) -> Option<TypedRect<f32, U>> {
|
||||
) -> Option<Rect<f32, U>> {
|
||||
// value of `k==1.0` is used for extraction of the corner rectangles
|
||||
// see `SEGMENT_CORNER_*` in `clip_shared.glsl`
|
||||
extract_inner_rect_impl(rect, radii, 1.0)
|
||||
|
@ -483,7 +483,8 @@ pub fn extract_inner_rect_safe<U>(
|
|||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use euclid::{Point2D, Angle, Transform3D};
|
||||
use euclid::default::{Point2D, Transform3D};
|
||||
use euclid::Angle;
|
||||
use std::f32::consts::PI;
|
||||
|
||||
#[test]
|
||||
|
@ -516,7 +517,7 @@ pub mod test {
|
|||
validate_convert(&xref);
|
||||
|
||||
let xref = LayoutTransform::create_translation(50.0, 240.0, 0.0)
|
||||
.pre_mul(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
|
||||
.pre_transform(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
|
||||
validate_convert(&xref);
|
||||
}
|
||||
|
||||
|
@ -544,12 +545,12 @@ pub mod test {
|
|||
validate_inverse(&xref);
|
||||
|
||||
let xref = LayoutTransform::create_translation(50.0, 240.0, 0.0)
|
||||
.pre_mul(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
|
||||
.pre_transform(&LayoutTransform::create_scale(30.0, 11.0, 1.0));
|
||||
validate_inverse(&xref);
|
||||
}
|
||||
|
||||
fn validate_accumulate(x0: &LayoutTransform, x1: &LayoutTransform) {
|
||||
let x = x0.pre_mul(x1);
|
||||
let x = x0.pre_transform(x1);
|
||||
|
||||
let s0 = ScaleOffset::from_transform(x0).unwrap();
|
||||
let s1 = ScaleOffset::from_transform(x1).unwrap();
|
||||
|
@ -580,7 +581,7 @@ pub mod test {
|
|||
m.m42 = 0.5;
|
||||
let origin = m.inverse_project_2d_origin().unwrap();
|
||||
assert_eq!(origin, Point2D::new(1.0, 0.5));
|
||||
assert_eq!(m.transform_point2d(&origin), Some(Point2D::zero()));
|
||||
assert_eq!(m.transform_point2d(origin), Some(Point2D::zero()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,7 +598,7 @@ impl MaxRect for DeviceIntRect {
|
|||
}
|
||||
}
|
||||
|
||||
impl<U> MaxRect for TypedRect<f32, U> {
|
||||
impl<U> MaxRect for Rect<f32, U> {
|
||||
fn max_rect() -> Self {
|
||||
// Having an unlimited bounding box is fine up until we try
|
||||
// to cast it to `i32`, where we get `-2147483648` for any
|
||||
|
@ -607,9 +608,9 @@ impl<U> MaxRect for TypedRect<f32, U> {
|
|||
// with explanation left as an exercise for the reader.
|
||||
const MAX_COORD: f32 = 1.0e9;
|
||||
|
||||
TypedRect::new(
|
||||
TypedPoint2D::new(-MAX_COORD, -MAX_COORD),
|
||||
TypedSize2D::new(2.0 * MAX_COORD, 2.0 * MAX_COORD),
|
||||
Rect::new(
|
||||
Point2D::new(-MAX_COORD, -MAX_COORD),
|
||||
Size2D::new(2.0 * MAX_COORD, 2.0 * MAX_COORD),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -619,12 +620,12 @@ impl<U> MaxRect for TypedRect<f32, U> {
|
|||
#[derive(Debug, MallocSizeOf)]
|
||||
pub enum FastTransform<Src, Dst> {
|
||||
/// A simple offset, which can be used without doing any matrix math.
|
||||
Offset(TypedVector2D<f32, Src>),
|
||||
Offset(Vector2D<f32, Src>),
|
||||
|
||||
/// A 2D transformation with an inverse.
|
||||
Transform {
|
||||
transform: TypedTransform3D<f32, Src, Dst>,
|
||||
inverse: Option<TypedTransform3D<f32, Dst, Src>>,
|
||||
transform: Transform3D<f32, Src, Dst>,
|
||||
inverse: Option<Transform3D<f32, Dst, Src>>,
|
||||
is_2d: bool,
|
||||
},
|
||||
}
|
||||
|
@ -639,16 +640,16 @@ impl<Src, Dst> Copy for FastTransform<Src, Dst> { }
|
|||
|
||||
impl<Src, Dst> FastTransform<Src, Dst> {
|
||||
pub fn identity() -> Self {
|
||||
FastTransform::Offset(TypedVector2D::zero())
|
||||
FastTransform::Offset(Vector2D::zero())
|
||||
}
|
||||
|
||||
pub fn with_vector(offset: TypedVector2D<f32, Src>) -> Self {
|
||||
pub fn with_vector(offset: Vector2D<f32, Src>) -> Self {
|
||||
FastTransform::Offset(offset)
|
||||
}
|
||||
|
||||
pub fn with_scale_offset(scale_offset: ScaleOffset) -> Self {
|
||||
if scale_offset.scale == Vector2D::new(1.0, 1.0) {
|
||||
FastTransform::Offset(TypedVector2D::from_untyped(&scale_offset.offset))
|
||||
FastTransform::Offset(Vector2D::from_untyped(scale_offset.offset))
|
||||
} else {
|
||||
FastTransform::Transform {
|
||||
transform: scale_offset.to_transform(),
|
||||
|
@ -659,19 +660,19 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn with_transform(transform: TypedTransform3D<f32, Src, Dst>) -> Self {
|
||||
pub fn with_transform(transform: Transform3D<f32, Src, Dst>) -> Self {
|
||||
if transform.is_simple_2d_translation() {
|
||||
return FastTransform::Offset(TypedVector2D::new(transform.m41, transform.m42));
|
||||
return FastTransform::Offset(Vector2D::new(transform.m41, transform.m42));
|
||||
}
|
||||
let inverse = transform.inverse();
|
||||
let is_2d = transform.is_2d();
|
||||
FastTransform::Transform { transform, inverse, is_2d}
|
||||
}
|
||||
|
||||
pub fn to_transform(&self) -> Cow<TypedTransform3D<f32, Src, Dst>> {
|
||||
pub fn to_transform(&self) -> Cow<Transform3D<f32, Src, Dst>> {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) => Cow::Owned(
|
||||
TypedTransform3D::create_translation(offset.x, offset.y, 0.0)
|
||||
Transform3D::create_translation(offset.x, offset.y, 0.0)
|
||||
),
|
||||
FastTransform::Transform { ref transform, .. } => Cow::Borrowed(transform),
|
||||
}
|
||||
|
@ -682,19 +683,19 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
pub fn is_identity(&self)-> bool {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) => {
|
||||
offset == TypedVector2D::zero()
|
||||
offset == Vector2D::zero()
|
||||
}
|
||||
FastTransform::Transform { ref transform, .. } => {
|
||||
*transform == TypedTransform3D::identity()
|
||||
*transform == Transform3D::identity()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn post_mul<NewDst>(&self, other: &FastTransform<Dst, NewDst>) -> FastTransform<Src, NewDst> {
|
||||
pub fn post_transform<NewDst>(&self, other: &FastTransform<Dst, NewDst>) -> FastTransform<Src, NewDst> {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) => match *other {
|
||||
FastTransform::Offset(other_offset) => {
|
||||
FastTransform::Offset(offset + other_offset * TypedScale::<_, _, Src>::new(1.0))
|
||||
FastTransform::Offset(offset + other_offset * Scale::<_, _, Src>::new(1.0))
|
||||
}
|
||||
FastTransform::Transform { transform: ref other_transform, .. } => {
|
||||
FastTransform::with_transform(
|
||||
|
@ -714,9 +715,9 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
}
|
||||
FastTransform::Transform { transform: ref other_transform, inverse: ref other_inverse, is_2d: other_is_2d } => {
|
||||
FastTransform::Transform {
|
||||
transform: transform.post_mul(other_transform),
|
||||
transform: transform.post_transform(other_transform),
|
||||
inverse: inverse.as_ref().and_then(|self_inv|
|
||||
other_inverse.as_ref().map(|other_inv| self_inv.pre_mul(other_inv))
|
||||
other_inverse.as_ref().map(|other_inv| self_inv.pre_transform(other_inv))
|
||||
),
|
||||
is_2d: is_2d & other_is_2d,
|
||||
}
|
||||
|
@ -725,26 +726,26 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn pre_mul<NewSrc>(
|
||||
pub fn pre_transform<NewSrc>(
|
||||
&self,
|
||||
other: &FastTransform<NewSrc, Src>
|
||||
) -> FastTransform<NewSrc, Dst> {
|
||||
other.post_mul(self)
|
||||
other.post_transform(self)
|
||||
}
|
||||
|
||||
pub fn pre_translate(&self, other_offset: &TypedVector2D<f32, Src>) -> Self {
|
||||
pub fn pre_translate(&self, other_offset: Vector2D<f32, Src>) -> Self {
|
||||
match *self {
|
||||
FastTransform::Offset(ref offset) =>
|
||||
FastTransform::Offset(*offset + *other_offset),
|
||||
FastTransform::Offset(offset) =>
|
||||
FastTransform::Offset(offset + other_offset),
|
||||
FastTransform::Transform { transform, .. } =>
|
||||
FastTransform::with_transform(transform.pre_translate(other_offset.to_3d()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn post_translate(&self, other_offset: &TypedVector2D<f32, Dst>) -> Self {
|
||||
pub fn post_translate(&self, other_offset: Vector2D<f32, Dst>) -> Self {
|
||||
match *self {
|
||||
FastTransform::Offset(ref offset) => {
|
||||
FastTransform::Offset(*offset + *other_offset * TypedScale::<_, _, Src>::new(1.0))
|
||||
FastTransform::Offset(offset) => {
|
||||
FastTransform::Offset(offset + other_offset * Scale::<_, _, Src>::new(1.0))
|
||||
}
|
||||
FastTransform::Transform { ref transform, .. } => {
|
||||
let transform = transform.post_translate(other_offset.to_3d());
|
||||
|
@ -765,11 +766,11 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn transform_point2d(&self, point: &TypedPoint2D<f32, Src>) -> Option<TypedPoint2D<f32, Dst>> {
|
||||
pub fn transform_point2d(&self, point: Point2D<f32, Src>) -> Option<Point2D<f32, Dst>> {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) => {
|
||||
let new_point = *point + offset;
|
||||
Some(TypedPoint2D::from_untyped(&new_point.to_untyped()))
|
||||
let new_point = point + offset;
|
||||
Some(Point2D::from_untyped(new_point.to_untyped()))
|
||||
}
|
||||
FastTransform::Transform { ref transform, .. } => transform.transform_point2d(point),
|
||||
}
|
||||
|
@ -779,7 +780,7 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
pub fn inverse(&self) -> Option<FastTransform<Dst, Src>> {
|
||||
match *self {
|
||||
FastTransform::Offset(offset) =>
|
||||
Some(FastTransform::Offset(TypedVector2D::new(-offset.x, -offset.y))),
|
||||
Some(FastTransform::Offset(Vector2D::new(-offset.x, -offset.y))),
|
||||
FastTransform::Transform { transform, inverse: Some(inverse), is_2d, } =>
|
||||
Some(FastTransform::Transform {
|
||||
transform: inverse,
|
||||
|
@ -792,14 +793,14 @@ impl<Src, Dst> FastTransform<Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<Src, Dst> From<TypedTransform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
|
||||
fn from(transform: TypedTransform3D<f32, Src, Dst>) -> Self {
|
||||
impl<Src, Dst> From<Transform3D<f32, Src, Dst>> for FastTransform<Src, Dst> {
|
||||
fn from(transform: Transform3D<f32, Src, Dst>) -> Self {
|
||||
FastTransform::with_transform(transform)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Src, Dst> From<TypedVector2D<f32, Src>> for FastTransform<Src, Dst> {
|
||||
fn from(vector: TypedVector2D<f32, Src>) -> Self {
|
||||
impl<Src, Dst> From<Vector2D<f32, Src>> for FastTransform<Src, Dst> {
|
||||
fn from(vector: Vector2D<f32, Src>) -> Self {
|
||||
FastTransform::with_vector(vector)
|
||||
}
|
||||
}
|
||||
|
@ -808,17 +809,17 @@ pub type LayoutFastTransform = FastTransform<LayoutPixel, LayoutPixel>;
|
|||
pub type LayoutToWorldFastTransform = FastTransform<LayoutPixel, WorldPixel>;
|
||||
|
||||
pub fn project_rect<F, T>(
|
||||
transform: &TypedTransform3D<f32, F, T>,
|
||||
rect: &TypedRect<f32, F>,
|
||||
bounds: &TypedRect<f32, T>,
|
||||
) -> Option<TypedRect<f32, T>>
|
||||
transform: &Transform3D<f32, F, T>,
|
||||
rect: &Rect<f32, F>,
|
||||
bounds: &Rect<f32, T>,
|
||||
) -> Option<Rect<f32, T>>
|
||||
where F: fmt::Debug
|
||||
{
|
||||
let homogens = [
|
||||
transform.transform_point2d_homogeneous(&rect.origin),
|
||||
transform.transform_point2d_homogeneous(&rect.top_right()),
|
||||
transform.transform_point2d_homogeneous(&rect.bottom_left()),
|
||||
transform.transform_point2d_homogeneous(&rect.bottom_right()),
|
||||
transform.transform_point2d_homogeneous(rect.origin),
|
||||
transform.transform_point2d_homogeneous(rect.top_right()),
|
||||
transform.transform_point2d_homogeneous(rect.bottom_left()),
|
||||
transform.transform_point2d_homogeneous(rect.bottom_right()),
|
||||
];
|
||||
|
||||
// Note: we only do the full frustum collision when the polygon approaches the camera plane.
|
||||
|
@ -844,19 +845,19 @@ pub fn project_rect<F, T>(
|
|||
return None
|
||||
}
|
||||
|
||||
Some(TypedRect::from_points(results
|
||||
Some(Rect::from_points(results
|
||||
.into_iter()
|
||||
// filter out parts behind the view plane
|
||||
.flat_map(|poly| &poly.points)
|
||||
.map(|p| {
|
||||
let mut homo = transform.transform_point2d_homogeneous(&p.to_2d());
|
||||
let mut homo = transform.transform_point2d_homogeneous(p.to_2d());
|
||||
homo.w = homo.w.max(0.00000001); // avoid infinite values
|
||||
homo.to_point2d().unwrap()
|
||||
})
|
||||
))
|
||||
} else {
|
||||
// we just checked for all the points to be in positive hemisphere, so `unwrap` is valid
|
||||
Some(TypedRect::from_points(&[
|
||||
Some(Rect::from_points(&[
|
||||
homogens[0].to_point2d().unwrap(),
|
||||
homogens[1].to_point2d().unwrap(),
|
||||
homogens[2].to_point2d().unwrap(),
|
||||
|
@ -869,7 +870,7 @@ pub fn raster_rect_to_device_pixels(
|
|||
rect: RasterRect,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
) -> DeviceRect {
|
||||
let world_rect = rect * TypedScale::new(1.0);
|
||||
let world_rect = rect * Scale::new(1.0);
|
||||
let device_rect = world_rect * device_pixel_scale;
|
||||
device_rect.round_out()
|
||||
}
|
||||
|
@ -1128,7 +1129,7 @@ impl<T: MallocSizeOf> MallocSizeOf for PrimaryArc<T> {
|
|||
///
|
||||
/// * Removed `xMajor` parameter.
|
||||
pub fn scale_factors<Src, Dst>(
|
||||
mat: &TypedTransform3D<f32, Src, Dst>
|
||||
mat: &Transform3D<f32, Src, Dst>
|
||||
) -> (f32, f32) {
|
||||
// Determinant is just of the 2D component.
|
||||
let det = mat.m11 * mat.m22 - mat.m12 * mat.m21;
|
||||
|
|
|
@ -20,7 +20,7 @@ bitflags = "1.0"
|
|||
byteorder = "1.2.1"
|
||||
derive_more = "0.13"
|
||||
ipc-channel = {version = "0.11.0", optional = true}
|
||||
euclid = { version = "0.19.9", features = ["serde"] }
|
||||
euclid = { version = "0.20.0", features = ["serde"] }
|
||||
malloc_size_of_derive = "0.1"
|
||||
serde = { version = "=1.0.88", features = ["rc"] }
|
||||
serde_derive = "=1.0.88"
|
||||
|
|
|
@ -206,7 +206,7 @@ pub struct StickyFrameDisplayItem {
|
|||
/// The margins that should be maintained between the edge of the parent viewport and this
|
||||
/// sticky frame. A margin of None indicates that the sticky frame should not stick at all
|
||||
/// to that particular edge of the viewport.
|
||||
pub margins: SideOffsets2D<Option<f32>>,
|
||||
pub margins: SideOffsets2D<Option<f32>, LayoutPixel>,
|
||||
|
||||
/// The minimum and maximum vertical offsets for this sticky frame. Ignoring these constraints,
|
||||
/// the sticky frame will continue to stick to the edge of the viewport as its original
|
||||
|
@ -424,7 +424,7 @@ pub struct NinePatchBorder {
|
|||
/// stretching.
|
||||
/// Slices can be overlapping. In that case, the same pixels from the
|
||||
/// 9-part image will show up in multiple parts of the resulting border.
|
||||
pub slice: SideOffsets2D<i32>,
|
||||
pub slice: DeviceIntSideOffsets,
|
||||
|
||||
/// Controls whether the center of the 9 patch image is rendered or
|
||||
/// ignored. The center is never rendered if the slices are overlapping.
|
||||
|
@ -440,7 +440,7 @@ pub struct NinePatchBorder {
|
|||
|
||||
/// The outset for the border.
|
||||
/// TODO(mrobinson): This should be removed and handled by the client.
|
||||
pub outset: SideOffsets2D<f32>,
|
||||
pub outset: LayoutSideOffsets, // TODO: what unit is this in?
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
|
||||
|
|
|
@ -1408,7 +1408,7 @@ impl DisplayListBuilder {
|
|||
&mut self,
|
||||
parent_spatial_id: di::SpatialId,
|
||||
frame_rect: LayoutRect,
|
||||
margins: SideOffsets2D<Option<f32>>,
|
||||
margins: SideOffsets2D<Option<f32>, LayoutPixel>,
|
||||
vertical_offset_bounds: di::StickyOffsetBounds,
|
||||
horizontal_offset_bounds: di::StickyOffsetBounds,
|
||||
previously_applied_offset: LayoutVector2D,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#![deny(missing_docs)]
|
||||
|
||||
use euclid::{size2, TypedRect, num::Zero};
|
||||
use euclid::{size2, Rect, num::Zero};
|
||||
use peek_poke::PeekPoke;
|
||||
use std::ops::{Add, Sub};
|
||||
use std::sync::Arc;
|
||||
|
@ -381,7 +381,7 @@ pub enum DirtyRect<T: Copy, U> {
|
|||
/// Everything is Dirty, equivalent to Partial(image_bounds)
|
||||
All,
|
||||
/// Some specific amount is dirty
|
||||
Partial(TypedRect<T, U>)
|
||||
Partial(Rect<T, U>)
|
||||
}
|
||||
|
||||
impl<T, U> DirtyRect<T, U>
|
||||
|
@ -394,7 +394,7 @@ where
|
|||
{
|
||||
/// Creates an empty DirtyRect (indicating nothing is invalid)
|
||||
pub fn empty() -> Self {
|
||||
DirtyRect::Partial(TypedRect::zero())
|
||||
DirtyRect::Partial(Rect::zero())
|
||||
}
|
||||
|
||||
/// Returns whether the dirty rect is empty
|
||||
|
@ -412,7 +412,7 @@ where
|
|||
|
||||
/// Maps over the contents of Partial.
|
||||
pub fn map<F>(self, func: F) -> Self
|
||||
where F: FnOnce(TypedRect<T, U>) -> TypedRect<T, U>,
|
||||
where F: FnOnce(Rect<T, U>) -> Rect<T, U>,
|
||||
{
|
||||
use crate::DirtyRect::*;
|
||||
|
||||
|
@ -439,18 +439,18 @@ where
|
|||
match (*self, *other) {
|
||||
(All, rect) | (rect, All) => rect,
|
||||
(Partial(rect1), Partial(rect2)) => Partial(rect1.intersection(&rect2)
|
||||
.unwrap_or_else(TypedRect::zero))
|
||||
.unwrap_or_else(Rect::zero))
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts the dirty rect into a subrect of the given one via intersection.
|
||||
pub fn to_subrect_of(&self, rect: &TypedRect<T, U>) -> TypedRect<T, U> {
|
||||
pub fn to_subrect_of(&self, rect: &Rect<T, U>) -> Rect<T, U> {
|
||||
use crate::DirtyRect::*;
|
||||
|
||||
match *self {
|
||||
All => *rect,
|
||||
Partial(dirty_rect) => dirty_rect.intersection(rect)
|
||||
.unwrap_or_else(TypedRect::zero),
|
||||
.unwrap_or_else(Rect::zero),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -460,8 +460,8 @@ impl<T: Copy, U> Clone for DirtyRect<T, U> {
|
|||
fn clone(&self) -> Self { *self }
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<TypedRect<T, U>> for DirtyRect<T, U> {
|
||||
fn from(rect: TypedRect<T, U>) -> Self {
|
||||
impl<T: Copy, U> From<Rect<T, U>> for DirtyRect<T, U> {
|
||||
fn from(rect: Rect<T, U>) -> Self {
|
||||
DirtyRect::Partial(rect)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
//! in the context of coordinate systems.
|
||||
|
||||
pub use app_units::Au;
|
||||
use euclid::{Length, TypedRect, TypedScale, TypedSize2D, TypedTransform3D, TypedTranslation2D};
|
||||
use euclid::{TypedPoint2D, TypedPoint3D, TypedVector2D, TypedVector3D, TypedSideOffsets2D};
|
||||
use euclid::{Length, Rect, Scale, Size2D, Transform3D, Translation2D};
|
||||
use euclid::{Point2D, Point3D, Vector2D, Vector3D, SideOffsets2D};
|
||||
use euclid::HomogeneousVector;
|
||||
use peek_poke::PeekPoke;
|
||||
// local imports
|
||||
|
@ -25,16 +25,16 @@ use crate::image::DirtyRect;
|
|||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct DevicePixel;
|
||||
|
||||
pub type DeviceIntRect = TypedRect<i32, DevicePixel>;
|
||||
pub type DeviceIntPoint = TypedPoint2D<i32, DevicePixel>;
|
||||
pub type DeviceIntSize = TypedSize2D<i32, DevicePixel>;
|
||||
pub type DeviceIntRect = Rect<i32, DevicePixel>;
|
||||
pub type DeviceIntPoint = Point2D<i32, DevicePixel>;
|
||||
pub type DeviceIntSize = Size2D<i32, DevicePixel>;
|
||||
pub type DeviceIntLength = Length<i32, DevicePixel>;
|
||||
pub type DeviceIntSideOffsets = TypedSideOffsets2D<i32, DevicePixel>;
|
||||
pub type DeviceIntSideOffsets = SideOffsets2D<i32, DevicePixel>;
|
||||
|
||||
pub type DeviceRect = TypedRect<f32, DevicePixel>;
|
||||
pub type DevicePoint = TypedPoint2D<f32, DevicePixel>;
|
||||
pub type DeviceVector2D = TypedVector2D<f32, DevicePixel>;
|
||||
pub type DeviceSize = TypedSize2D<f32, DevicePixel>;
|
||||
pub type DeviceRect = Rect<f32, DevicePixel>;
|
||||
pub type DevicePoint = Point2D<f32, DevicePixel>;
|
||||
pub type DeviceVector2D = Vector2D<f32, DevicePixel>;
|
||||
pub type DeviceSize = Size2D<f32, DevicePixel>;
|
||||
pub type DeviceHomogeneousVector = HomogeneousVector<f32, DevicePixel>;
|
||||
|
||||
/// Geometry in the coordinate system of the framebuffer in physical pixels.
|
||||
|
@ -42,24 +42,24 @@ pub type DeviceHomogeneousVector = HomogeneousVector<f32, DevicePixel>;
|
|||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
pub struct FramebufferPixel;
|
||||
|
||||
pub type FramebufferIntPoint = TypedPoint2D<i32, FramebufferPixel>;
|
||||
pub type FramebufferIntSize = TypedSize2D<i32, FramebufferPixel>;
|
||||
pub type FramebufferIntRect = TypedRect<i32, FramebufferPixel>;
|
||||
pub type FramebufferIntPoint = Point2D<i32, FramebufferPixel>;
|
||||
pub type FramebufferIntSize = Size2D<i32, FramebufferPixel>;
|
||||
pub type FramebufferIntRect = Rect<i32, FramebufferPixel>;
|
||||
|
||||
/// Geometry in the coordinate system of a Picture (intermediate
|
||||
/// surface) in physical pixels.
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct PicturePixel;
|
||||
|
||||
pub type PictureIntRect = TypedRect<i32, PicturePixel>;
|
||||
pub type PictureIntPoint = TypedPoint2D<i32, PicturePixel>;
|
||||
pub type PictureIntSize = TypedSize2D<i32, PicturePixel>;
|
||||
pub type PictureRect = TypedRect<f32, PicturePixel>;
|
||||
pub type PicturePoint = TypedPoint2D<f32, PicturePixel>;
|
||||
pub type PictureSize = TypedSize2D<f32, PicturePixel>;
|
||||
pub type PicturePoint3D = TypedPoint3D<f32, PicturePixel>;
|
||||
pub type PictureVector2D = TypedVector2D<f32, PicturePixel>;
|
||||
pub type PictureVector3D = TypedVector3D<f32, PicturePixel>;
|
||||
pub type PictureIntRect = Rect<i32, PicturePixel>;
|
||||
pub type PictureIntPoint = Point2D<i32, PicturePixel>;
|
||||
pub type PictureIntSize = Size2D<i32, PicturePixel>;
|
||||
pub type PictureRect = Rect<f32, PicturePixel>;
|
||||
pub type PicturePoint = Point2D<f32, PicturePixel>;
|
||||
pub type PictureSize = Size2D<f32, PicturePixel>;
|
||||
pub type PicturePoint3D = Point3D<f32, PicturePixel>;
|
||||
pub type PictureVector2D = Vector2D<f32, PicturePixel>;
|
||||
pub type PictureVector3D = Vector3D<f32, PicturePixel>;
|
||||
|
||||
/// Geometry gets rasterized in a given root coordinate space. This
|
||||
/// is often the root spatial node (world space), but may be a local
|
||||
|
@ -67,81 +67,81 @@ pub type PictureVector3D = TypedVector3D<f32, PicturePixel>;
|
|||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct RasterPixel;
|
||||
|
||||
pub type RasterIntRect = TypedRect<i32, RasterPixel>;
|
||||
pub type RasterIntPoint = TypedPoint2D<i32, RasterPixel>;
|
||||
pub type RasterIntSize = TypedSize2D<i32, RasterPixel>;
|
||||
pub type RasterRect = TypedRect<f32, RasterPixel>;
|
||||
pub type RasterPoint = TypedPoint2D<f32, RasterPixel>;
|
||||
pub type RasterSize = TypedSize2D<f32, RasterPixel>;
|
||||
pub type RasterPoint3D = TypedPoint3D<f32, RasterPixel>;
|
||||
pub type RasterVector2D = TypedVector2D<f32, RasterPixel>;
|
||||
pub type RasterVector3D = TypedVector3D<f32, RasterPixel>;
|
||||
pub type RasterIntRect = Rect<i32, RasterPixel>;
|
||||
pub type RasterIntPoint = Point2D<i32, RasterPixel>;
|
||||
pub type RasterIntSize = Size2D<i32, RasterPixel>;
|
||||
pub type RasterRect = Rect<f32, RasterPixel>;
|
||||
pub type RasterPoint = Point2D<f32, RasterPixel>;
|
||||
pub type RasterSize = Size2D<f32, RasterPixel>;
|
||||
pub type RasterPoint3D = Point3D<f32, RasterPixel>;
|
||||
pub type RasterVector2D = Vector2D<f32, RasterPixel>;
|
||||
pub type RasterVector3D = Vector3D<f32, RasterPixel>;
|
||||
|
||||
/// Geometry in a stacking context's local coordinate space (logical pixels).
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize, PeekPoke)]
|
||||
pub struct LayoutPixel;
|
||||
|
||||
pub type LayoutRect = TypedRect<f32, LayoutPixel>;
|
||||
pub type LayoutPoint = TypedPoint2D<f32, LayoutPixel>;
|
||||
pub type LayoutPoint3D = TypedPoint3D<f32, LayoutPixel>;
|
||||
pub type LayoutVector2D = TypedVector2D<f32, LayoutPixel>;
|
||||
pub type LayoutVector3D = TypedVector3D<f32, LayoutPixel>;
|
||||
pub type LayoutSize = TypedSize2D<f32, LayoutPixel>;
|
||||
pub type LayoutSideOffsets = TypedSideOffsets2D<f32, LayoutPixel>;
|
||||
pub type LayoutRect = Rect<f32, LayoutPixel>;
|
||||
pub type LayoutPoint = Point2D<f32, LayoutPixel>;
|
||||
pub type LayoutPoint3D = Point3D<f32, LayoutPixel>;
|
||||
pub type LayoutVector2D = Vector2D<f32, LayoutPixel>;
|
||||
pub type LayoutVector3D = Vector3D<f32, LayoutPixel>;
|
||||
pub type LayoutSize = Size2D<f32, LayoutPixel>;
|
||||
pub type LayoutSideOffsets = SideOffsets2D<f32, LayoutPixel>;
|
||||
|
||||
pub type LayoutIntRect = TypedRect<i32, LayoutPixel>;
|
||||
pub type LayoutIntPoint = TypedPoint2D<i32, LayoutPixel>;
|
||||
pub type LayoutIntSize = TypedSize2D<i32, LayoutPixel>;
|
||||
pub type LayoutIntRect = Rect<i32, LayoutPixel>;
|
||||
pub type LayoutIntPoint = Point2D<i32, LayoutPixel>;
|
||||
pub type LayoutIntSize = Size2D<i32, LayoutPixel>;
|
||||
|
||||
/// Geometry in the document's coordinate space (logical pixels).
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd)]
|
||||
pub struct WorldPixel;
|
||||
|
||||
pub type WorldRect = TypedRect<f32, WorldPixel>;
|
||||
pub type WorldPoint = TypedPoint2D<f32, WorldPixel>;
|
||||
pub type WorldSize = TypedSize2D<f32, WorldPixel>;
|
||||
pub type WorldPoint3D = TypedPoint3D<f32, WorldPixel>;
|
||||
pub type WorldVector2D = TypedVector2D<f32, WorldPixel>;
|
||||
pub type WorldVector3D = TypedVector3D<f32, WorldPixel>;
|
||||
pub type WorldRect = Rect<f32, WorldPixel>;
|
||||
pub type WorldPoint = Point2D<f32, WorldPixel>;
|
||||
pub type WorldSize = Size2D<f32, WorldPixel>;
|
||||
pub type WorldPoint3D = Point3D<f32, WorldPixel>;
|
||||
pub type WorldVector2D = Vector2D<f32, WorldPixel>;
|
||||
pub type WorldVector3D = Vector3D<f32, WorldPixel>;
|
||||
|
||||
/// Offset in number of tiles.
|
||||
#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||
pub struct Tiles;
|
||||
pub type TileOffset = TypedPoint2D<i32, Tiles>;
|
||||
pub type TileRange = TypedRect<i32, Tiles>;
|
||||
pub type TileOffset = Point2D<i32, Tiles>;
|
||||
pub type TileRange = Rect<i32, Tiles>;
|
||||
|
||||
/// Scaling ratio from world pixels to device pixels.
|
||||
pub type DevicePixelScale = TypedScale<f32, WorldPixel, DevicePixel>;
|
||||
pub type DevicePixelScale = Scale<f32, WorldPixel, DevicePixel>;
|
||||
/// Scaling ratio from layout to world. Used for cases where we know the layout
|
||||
/// is in world space, or specifically want to treat it this way.
|
||||
pub type LayoutToWorldScale = TypedScale<f32, LayoutPixel, WorldPixel>;
|
||||
pub type LayoutToWorldScale = Scale<f32, LayoutPixel, WorldPixel>;
|
||||
/// A complete scaling ratio from layout space to device pixel space.
|
||||
pub type LayoutToDeviceScale = TypedScale<f32, LayoutPixel, DevicePixel>;
|
||||
pub type LayoutToDeviceScale = Scale<f32, LayoutPixel, DevicePixel>;
|
||||
|
||||
pub type LayoutTransform = TypedTransform3D<f32, LayoutPixel, LayoutPixel>;
|
||||
pub type LayoutToWorldTransform = TypedTransform3D<f32, LayoutPixel, WorldPixel>;
|
||||
pub type WorldToLayoutTransform = TypedTransform3D<f32, WorldPixel, LayoutPixel>;
|
||||
pub type LayoutTransform = Transform3D<f32, LayoutPixel, LayoutPixel>;
|
||||
pub type LayoutToWorldTransform = Transform3D<f32, LayoutPixel, WorldPixel>;
|
||||
pub type WorldToLayoutTransform = Transform3D<f32, WorldPixel, LayoutPixel>;
|
||||
|
||||
pub type LayoutToPictureTransform = TypedTransform3D<f32, LayoutPixel, PicturePixel>;
|
||||
pub type PictureToLayoutTransform = TypedTransform3D<f32, PicturePixel, LayoutPixel>;
|
||||
pub type LayoutToPictureTransform = Transform3D<f32, LayoutPixel, PicturePixel>;
|
||||
pub type PictureToLayoutTransform = Transform3D<f32, PicturePixel, LayoutPixel>;
|
||||
|
||||
pub type LayoutToRasterTransform = TypedTransform3D<f32, LayoutPixel, RasterPixel>;
|
||||
pub type RasterToLayoutTransform = TypedTransform3D<f32, RasterPixel, LayoutPixel>;
|
||||
pub type LayoutToRasterTransform = Transform3D<f32, LayoutPixel, RasterPixel>;
|
||||
pub type RasterToLayoutTransform = Transform3D<f32, RasterPixel, LayoutPixel>;
|
||||
|
||||
pub type PictureToRasterTransform = TypedTransform3D<f32, PicturePixel, RasterPixel>;
|
||||
pub type RasterToPictureTransform = TypedTransform3D<f32, RasterPixel, PicturePixel>;
|
||||
pub type PictureToRasterTransform = Transform3D<f32, PicturePixel, RasterPixel>;
|
||||
pub type RasterToPictureTransform = Transform3D<f32, RasterPixel, PicturePixel>;
|
||||
|
||||
// Fixed position coordinates, to avoid float precision errors.
|
||||
pub type LayoutPointAu = TypedPoint2D<Au, LayoutPixel>;
|
||||
pub type LayoutRectAu = TypedRect<Au, LayoutPixel>;
|
||||
pub type LayoutSizeAu = TypedSize2D<Au, LayoutPixel>;
|
||||
pub type LayoutVector2DAu = TypedVector2D<Au, LayoutPixel>;
|
||||
pub type LayoutSideOffsetsAu = TypedSideOffsets2D<Au, LayoutPixel>;
|
||||
pub type LayoutPointAu = Point2D<Au, LayoutPixel>;
|
||||
pub type LayoutRectAu = Rect<Au, LayoutPixel>;
|
||||
pub type LayoutSizeAu = Size2D<Au, LayoutPixel>;
|
||||
pub type LayoutVector2DAu = Vector2D<Au, LayoutPixel>;
|
||||
pub type LayoutSideOffsetsAu = SideOffsets2D<Au, LayoutPixel>;
|
||||
|
||||
pub type ImageDirtyRect = DirtyRect<i32, DevicePixel>;
|
||||
pub type BlobDirtyRect = DirtyRect<i32, LayoutPixel>;
|
||||
|
||||
pub type BlobToDeviceTranslation = TypedTranslation2D<i32, LayoutPixel, DevicePixel>;
|
||||
pub type BlobToDeviceTranslation = Translation2D<i32, LayoutPixel, DevicePixel>;
|
||||
|
||||
/// Stores two coordinates in texel space. The coordinates
|
||||
/// are stored in texel coordinates because the texture atlas
|
||||
|
@ -266,3 +266,27 @@ impl AuHelpers<LayoutSideOffsetsAu> for LayoutSideOffsets {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RectExt {
|
||||
type Point;
|
||||
fn top_left(&self) -> Self::Point;
|
||||
fn top_right(&self) -> Self::Point;
|
||||
fn bottom_left(&self) -> Self::Point;
|
||||
fn bottom_right(&self) -> Self::Point;
|
||||
}
|
||||
|
||||
impl<U> RectExt for Rect<f32, U> {
|
||||
type Point = Point2D<f32, U>;
|
||||
fn top_left(&self) -> Self::Point {
|
||||
self.min()
|
||||
}
|
||||
fn top_right(&self) -> Self::Point {
|
||||
Point2D::new(self.max_x(), self.min_y())
|
||||
}
|
||||
fn bottom_left(&self) -> Self::Point {
|
||||
Point2D::new(self.min_x(), self.max_y())
|
||||
}
|
||||
fn bottom_right(&self) -> Self::Point {
|
||||
self.max()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,4 +11,4 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
app_units = "0.7"
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
|
|
|
@ -316,25 +316,25 @@ impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedScale<T, Src, Dst> {
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedPoint2D<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.x.size_of(ops) + self.y.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedRect<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.origin.size_of(ops) + self.size.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSideOffsets2D<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.top.size_of(ops) +
|
||||
self.right.size_of(ops) +
|
||||
|
@ -343,13 +343,13 @@ impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSideOffsets2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSize2D<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.width.size_of(ops) + self.height.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform2D<T, Src, Dst> {
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.m11.size_of(ops) +
|
||||
self.m12.size_of(ops) +
|
||||
|
@ -360,7 +360,7 @@ impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform2D<T, Src
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform3D<T, Src, Dst> {
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.m11.size_of(ops) +
|
||||
self.m12.size_of(ops) +
|
||||
|
@ -381,7 +381,7 @@ impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform3D<T, Src
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedVector2D<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.x.size_of(ops) + self.y.size_of(ops)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ base64 = "0.10"
|
|||
bincode = "1.0"
|
||||
byteorder = "1.0"
|
||||
env_logger = { version = "0.5", optional = true }
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
gleam = "0.6.2"
|
||||
glutin = "0.21"
|
||||
app_units = "0.7"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
extern crate yaml_rust;
|
||||
|
||||
use euclid::{TypedPoint2D, TypedRect, TypedSize2D, TypedTransform3D, TypedVector2D};
|
||||
use euclid::{Point2D, Rect, Size2D, Transform3D, Vector2D};
|
||||
use image::{save_buffer, ColorType};
|
||||
use crate::premultiply::unpremultiply;
|
||||
use crate::scene::{Scene, SceneProperties};
|
||||
|
@ -84,19 +84,19 @@ fn color_node(parent: &mut Table, key: &str, value: ColorF) {
|
|||
yaml_node(parent, key, Yaml::String(color_to_string(value)));
|
||||
}
|
||||
|
||||
fn point_node<U>(parent: &mut Table, key: &str, value: &TypedPoint2D<f32, U>) {
|
||||
fn point_node<U>(parent: &mut Table, key: &str, value: &Point2D<f32, U>) {
|
||||
f32_vec_node(parent, key, &[value.x, value.y]);
|
||||
}
|
||||
|
||||
fn vector_node<U>(parent: &mut Table, key: &str, value: &TypedVector2D<f32, U>) {
|
||||
fn vector_node<U>(parent: &mut Table, key: &str, value: &Vector2D<f32, U>) {
|
||||
f32_vec_node(parent, key, &[value.x, value.y]);
|
||||
}
|
||||
|
||||
fn size_node<U>(parent: &mut Table, key: &str, value: &TypedSize2D<f32, U>) {
|
||||
fn size_node<U>(parent: &mut Table, key: &str, value: &Size2D<f32, U>) {
|
||||
f32_vec_node(parent, key, &[value.width, value.height]);
|
||||
}
|
||||
|
||||
fn rect_yaml<U>(value: &TypedRect<f32, U>) -> Yaml {
|
||||
fn rect_yaml<U>(value: &Rect<f32, U>) -> Yaml {
|
||||
f32_vec_yaml(
|
||||
&[
|
||||
value.origin.x,
|
||||
|
@ -108,11 +108,11 @@ fn rect_yaml<U>(value: &TypedRect<f32, U>) -> Yaml {
|
|||
)
|
||||
}
|
||||
|
||||
fn rect_node<U>(parent: &mut Table, key: &str, value: &TypedRect<f32, U>) {
|
||||
fn rect_node<U>(parent: &mut Table, key: &str, value: &Rect<f32, U>) {
|
||||
yaml_node(parent, key, rect_yaml(value));
|
||||
}
|
||||
|
||||
fn matrix4d_node<U1, U2>(parent: &mut Table, key: &str, value: &TypedTransform3D<f32, U1, U2>) {
|
||||
fn matrix4d_node<U1, U2>(parent: &mut Table, key: &str, value: &Transform3D<f32, U1, U2>) {
|
||||
f32_vec_node(parent, key, &value.to_row_major_array());
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use euclid::{Angle, TypedSize2D};
|
||||
use euclid::{Angle, Size2D};
|
||||
use crate::parse_function::parse_function;
|
||||
use std::f32;
|
||||
use std::str::FromStr;
|
||||
|
@ -179,7 +179,7 @@ fn make_rotation(
|
|||
let transform =
|
||||
LayoutTransform::identity().pre_rotate(axis_x, axis_y, axis_z, Angle::radians(theta));
|
||||
|
||||
pre_transform.pre_mul(&transform).pre_mul(&post_transform)
|
||||
pre_transform.pre_transform(&transform).pre_transform(&post_transform)
|
||||
}
|
||||
|
||||
pub fn make_perspective(
|
||||
|
@ -189,7 +189,7 @@ pub fn make_perspective(
|
|||
let pre_transform = LayoutTransform::create_translation(origin.x, origin.y, 0.0);
|
||||
let post_transform = LayoutTransform::create_translation(-origin.x, -origin.y, -0.0);
|
||||
let transform = LayoutTransform::create_perspective(perspective);
|
||||
pre_transform.pre_mul(&transform).pre_mul(&post_transform)
|
||||
pre_transform.pre_transform(&transform).pre_transform(&post_transform)
|
||||
}
|
||||
|
||||
// Create a skew matrix, specified in degrees.
|
||||
|
@ -422,7 +422,7 @@ impl YamlHelper for Yaml {
|
|||
break;
|
||||
}
|
||||
};
|
||||
transform = transform.post_mul(&mx);
|
||||
transform = transform.post_transform(&mx);
|
||||
}
|
||||
Some(transform)
|
||||
}
|
||||
|
@ -430,7 +430,7 @@ impl YamlHelper for Yaml {
|
|||
let transform = array.iter().fold(
|
||||
LayoutTransform::identity(),
|
||||
|u, yaml| match yaml.as_transform(transform_origin) {
|
||||
Some(ref transform) => u.pre_mul(transform),
|
||||
Some(ref transform) => u.pre_transform(transform),
|
||||
None => u,
|
||||
},
|
||||
);
|
||||
|
@ -497,7 +497,7 @@ impl YamlHelper for Yaml {
|
|||
if let Yaml::Integer(integer) = *self {
|
||||
return LayoutSize::new(integer as f32, integer as f32);
|
||||
}
|
||||
self.as_size().unwrap_or(TypedSize2D::zero())
|
||||
self.as_size().unwrap_or(Size2D::zero())
|
||||
}
|
||||
|
||||
fn as_border_radius(&self) -> Option<BorderRadius> {
|
||||
|
|
|
@ -3652,8 +3652,8 @@ ImgDrawResult nsCSSBorderImageRenderer::CreateWebRenderCommands(
|
|||
mImageSize.width / appUnitsPerDevPixel,
|
||||
mImageSize.height / appUnitsPerDevPixel,
|
||||
mFill,
|
||||
wr::ToSideOffsets2D_i32(slice[0], slice[1], slice[2], slice[3]),
|
||||
wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2], outset[3]),
|
||||
wr::ToDeviceIntSideOffsets(slice[0], slice[1], slice[2], slice[3]),
|
||||
wr::ToLayoutSideOffsets(outset[0], outset[1], outset[2], outset[3]),
|
||||
wr::ToRepeatMode(mRepeatModeHorizontal),
|
||||
wr::ToRepeatMode(mRepeatModeVertical)};
|
||||
|
||||
|
@ -3684,10 +3684,10 @@ ImgDrawResult nsCSSBorderImageRenderer::CreateWebRenderCommands(
|
|||
wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
|
||||
(float)(mImageSize.width) / appUnitsPerDevPixel,
|
||||
(float)(mImageSize.height) / appUnitsPerDevPixel, mFill,
|
||||
wr::ToSideOffsets2D_i32(slice[0], slice[1], slice[2], slice[3]),
|
||||
wr::ToDeviceIntSideOffsets(slice[0], slice[1], slice[2], slice[3]),
|
||||
wr::ToLayoutPoint(startPoint), wr::ToLayoutPoint(endPoint), stops,
|
||||
extendMode,
|
||||
wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2],
|
||||
wr::ToLayoutSideOffsets(outset[0], outset[1], outset[2],
|
||||
outset[3]));
|
||||
} else {
|
||||
aBuilder.PushBorderRadialGradient(
|
||||
|
@ -3695,7 +3695,7 @@ ImgDrawResult nsCSSBorderImageRenderer::CreateWebRenderCommands(
|
|||
wr::ToBorderWidths(widths[0], widths[1], widths[2], widths[3]),
|
||||
mFill, wr::ToLayoutPoint(lineStart),
|
||||
wr::ToLayoutSize(gradientRadius), stops, extendMode,
|
||||
wr::ToSideOffsets2D_f32(outset[0], outset[1], outset[2],
|
||||
wr::ToLayoutSideOffsets(outset[0], outset[1], outset[2],
|
||||
outset[3]));
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -27,7 +27,7 @@ servo = [
|
|||
app_units = "0.7"
|
||||
crossbeam-channel = { version = "0.3", optional = true }
|
||||
cssparser = "0.25"
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
hyper = { version = "0.12", optional = true }
|
||||
hyper_serde = { version = "0.11", optional = true }
|
||||
|
|
|
@ -625,25 +625,25 @@ impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedScale<T, Src, Dst> {
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedPoint2D<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.x.size_of(ops) + self.y.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedRect<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.origin.size_of(ops) + self.size.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSideOffsets2D<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.top.size_of(ops) +
|
||||
self.right.size_of(ops) +
|
||||
|
@ -652,13 +652,13 @@ impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSideOffsets2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSize2D<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.width.size_of(ops) + self.height.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform2D<T, Src, Dst> {
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.m11.size_of(ops) +
|
||||
self.m12.size_of(ops) +
|
||||
|
@ -669,7 +669,7 @@ impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform2D<T, Src
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform3D<T, Src, Dst> {
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.m11.size_of(ops) +
|
||||
self.m12.size_of(ops) +
|
||||
|
@ -690,7 +690,7 @@ impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform3D<T, Src
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedVector2D<T, U> {
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.x.size_of(ops) + self.y.size_of(ops)
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ crossbeam-channel = { version = "0.3", optional = true }
|
|||
derive_more = "0.13"
|
||||
new_debug_unreachable = "1.0"
|
||||
encoding_rs = {version = "0.8", optional = true}
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
fallible = { path = "../fallible" }
|
||||
fxhash = "0.2"
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
|
|
|
@ -31,8 +31,8 @@ use crate::traversal_flags::TraversalFlags;
|
|||
use app_units::Au;
|
||||
#[cfg(feature = "servo")]
|
||||
use crossbeam_channel::Sender;
|
||||
use euclid::Size2D;
|
||||
use euclid::TypedScale;
|
||||
use euclid::default::Size2D;
|
||||
use euclid::Scale;
|
||||
use fxhash::FxHashMap;
|
||||
#[cfg(feature = "servo")]
|
||||
use parking_lot::RwLock;
|
||||
|
@ -195,7 +195,7 @@ impl<'a> SharedStyleContext<'a> {
|
|||
}
|
||||
|
||||
/// The device pixel ratio
|
||||
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
|
||||
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
|
||||
self.stylist.device().device_pixel_ratio()
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::values::computed::CSSPixelLength;
|
|||
use crate::values::computed::Resolution;
|
||||
use crate::Atom;
|
||||
use app_units::Au;
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
|
||||
fn viewport_size(device: &Device) -> Size2D<Au> {
|
||||
if let Some(pc) = device.pres_context() {
|
||||
|
|
|
@ -16,8 +16,8 @@ use crate::values::{CustomIdent, KeyframesName};
|
|||
use app_units::Au;
|
||||
use app_units::AU_PER_PX;
|
||||
use cssparser::RGBA;
|
||||
use euclid::Size2D;
|
||||
use euclid::TypedScale;
|
||||
use euclid::default::Size2D;
|
||||
use euclid::Scale;
|
||||
use servo_arc::Arc;
|
||||
use std::fmt;
|
||||
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
|
||||
|
@ -247,20 +247,20 @@ impl Device {
|
|||
}
|
||||
|
||||
/// Returns the device pixel ratio.
|
||||
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
|
||||
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
|
||||
let pc = match self.pres_context() {
|
||||
Some(pc) => pc,
|
||||
None => return TypedScale::new(1.),
|
||||
None => return Scale::new(1.),
|
||||
};
|
||||
|
||||
let override_dppx = pc.mOverrideDPPX;
|
||||
if override_dppx > 0.0 {
|
||||
return TypedScale::new(override_dppx);
|
||||
return Scale::new(override_dppx);
|
||||
}
|
||||
|
||||
let au_per_dpx = pc.mCurAppUnitsPerDevPixel as f32;
|
||||
let au_per_px = AU_PER_PX as f32;
|
||||
TypedScale::new(au_per_px / au_per_dpx)
|
||||
Scale::new(au_per_px / au_per_dpx)
|
||||
}
|
||||
|
||||
/// Returns whether document colors are enabled.
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use crate::properties::style_structs;
|
||||
use euclid::num::Zero;
|
||||
use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
|
||||
use euclid::default::{Point2D, Rect, Size2D, SideOffsets2D};
|
||||
use std::cmp::{max, min};
|
||||
use std::fmt::{self, Debug, Error, Formatter};
|
||||
use std::ops::{Add, Sub};
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::values::computed::CSSPixelLength;
|
|||
use crate::values::KeyframesName;
|
||||
use app_units::Au;
|
||||
use cssparser::RGBA;
|
||||
use euclid::{Size2D, TypedScale, TypedSize2D};
|
||||
use euclid::{Size2D, Scale, Size2D};
|
||||
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
||||
use style_traits::viewport::ViewportConstraints;
|
||||
use style_traits::{CSSPixel, DevicePixel};
|
||||
|
@ -29,9 +29,9 @@ pub struct Device {
|
|||
/// The current media type used by de device.
|
||||
media_type: MediaType,
|
||||
/// The current viewport size, in CSS pixels.
|
||||
viewport_size: TypedSize2D<f32, CSSPixel>,
|
||||
viewport_size: Size2D<f32, CSSPixel>,
|
||||
/// The current device pixel ratio, from CSS pixels to device pixels.
|
||||
device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
|
||||
|
||||
/// The font size of the root element
|
||||
/// This is set when computing the style of the root
|
||||
|
@ -59,8 +59,8 @@ impl Device {
|
|||
/// Trivially construct a new `Device`.
|
||||
pub fn new(
|
||||
media_type: MediaType,
|
||||
viewport_size: TypedSize2D<f32, CSSPixel>,
|
||||
device_pixel_ratio: TypedScale<f32, CSSPixel, DevicePixel>,
|
||||
viewport_size: Size2D<f32, CSSPixel>,
|
||||
device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
|
||||
) -> Device {
|
||||
Device {
|
||||
media_type,
|
||||
|
@ -140,7 +140,7 @@ impl Device {
|
|||
}
|
||||
|
||||
/// Returns the device pixel ratio.
|
||||
pub fn device_pixel_ratio(&self) -> TypedScale<f32, CSSPixel, DevicePixel> {
|
||||
pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
|
||||
self.device_pixel_ratio
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::values::specified::{NonNegativeLengthPercentageOrAuto, ViewportPercen
|
|||
use app_units::Au;
|
||||
use cssparser::CowRcStr;
|
||||
use cssparser::{parse_important, AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
|
||||
use euclid::TypedSize2D;
|
||||
use euclid::Size2D;
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
|
@ -832,7 +832,7 @@ impl MaybeNew for ViewportConstraints {
|
|||
});
|
||||
|
||||
Some(ViewportConstraints {
|
||||
size: TypedSize2D::new(width.to_f32_px(), height.to_f32_px()),
|
||||
size: Size2D::new(width.to_f32_px(), height.to_f32_px()),
|
||||
|
||||
// TODO: compute a zoom factor for 'auto' as suggested by DEVICE-ADAPT § 10.
|
||||
initial_zoom: PinchZoomFactor::new(initial_zoom.unwrap_or(1.)),
|
||||
|
|
|
@ -23,7 +23,7 @@ use crate::rule_cache::RuleCacheConditions;
|
|||
use crate::Atom;
|
||||
#[cfg(feature = "servo")]
|
||||
use crate::Prefix;
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp;
|
||||
use std::f32;
|
||||
|
|
|
@ -10,7 +10,7 @@ use crate::values::animated::ToAnimatedZero;
|
|||
use crate::values::computed::{Angle, Integer, Length, LengthPercentage, Number, Percentage};
|
||||
use crate::values::generics::transform as generic;
|
||||
use crate::Zero;
|
||||
use euclid::{Transform3D, Vector3D};
|
||||
use euclid::default::{Transform3D, Vector3D};
|
||||
|
||||
pub use crate::values::generics::transform::TransformStyle;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//! Machinery to compute distances between animatable values.
|
||||
|
||||
use app_units::Au;
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
use std::iter::Sum;
|
||||
use std::ops::Add;
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercent
|
|||
use crate::values::{computed, CSSFloat};
|
||||
use crate::Zero;
|
||||
use app_units::Au;
|
||||
use euclid::{self, Rect, Transform3D};
|
||||
use euclid::default::{Rect, Transform3D};
|
||||
use euclid;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ToCss};
|
||||
|
||||
|
@ -562,7 +563,7 @@ impl<T: ToMatrix> Transform<T> {
|
|||
for operation in &*self.0 {
|
||||
let matrix = operation.to_3d_matrix(reference_box)?;
|
||||
contain_3d |= operation.is_3d();
|
||||
transform = transform.pre_mul(&matrix);
|
||||
transform = transform.pre_transform(&matrix);
|
||||
}
|
||||
|
||||
Ok((transform, contain_3d))
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::values::CSSFloat;
|
|||
use crate::Zero;
|
||||
use app_units::Au;
|
||||
use cssparser::{Parser, Token};
|
||||
use euclid::Size2D;
|
||||
use euclid::default::Size2D;
|
||||
use std::cmp;
|
||||
use std::ops::{Add, Mul};
|
||||
use style_traits::values::specified::AllowedNumericType;
|
||||
|
|
|
@ -17,7 +17,7 @@ gecko = []
|
|||
app_units = "0.7"
|
||||
cssparser = "0.25"
|
||||
bitflags = "1.0"
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
lazy_static = "1"
|
||||
malloc_size_of = { path = "../malloc_size_of" }
|
||||
malloc_size_of_derive = "0.1"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
use crate::{CSSPixel, CssWriter, ParseError, PinchZoomFactor, ToCss};
|
||||
use cssparser::Parser;
|
||||
use euclid::TypedSize2D;
|
||||
use euclid::Size2D;
|
||||
use std::fmt::{self, Write};
|
||||
|
||||
define_css_keyword_enum! {
|
||||
|
@ -33,7 +33,7 @@ pub struct ViewportConstraints {
|
|||
/// Width and height:
|
||||
/// * https://drafts.csswg.org/css-device-adapt/#width-desc
|
||||
/// * https://drafts.csswg.org/css-device-adapt/#height-desc
|
||||
pub size: TypedSize2D<f32, CSSPixel>,
|
||||
pub size: Size2D<f32, CSSPixel>,
|
||||
/// <https://drafts.csswg.org/css-device-adapt/#zoom-desc>
|
||||
pub initial_zoom: PinchZoomFactor,
|
||||
/// <https://drafts.csswg.org/css-device-adapt/#min-max-width-desc>
|
||||
|
|
|
@ -13,7 +13,7 @@ doctest = false
|
|||
byteorder = "1.0"
|
||||
app_units = "0.7"
|
||||
cssparser = "0.25"
|
||||
euclid = "0.19"
|
||||
euclid = "0.20"
|
||||
html5ever = "0.22"
|
||||
parking_lot = "0.8"
|
||||
rayon = "1"
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use euclid::TypedScale;
|
||||
use euclid::TypedSize2D;
|
||||
use euclid::Scale;
|
||||
use euclid::Size2D;
|
||||
use servo_arc::Arc;
|
||||
use servo_url::ServoUrl;
|
||||
use std::borrow::ToOwned;
|
||||
|
@ -27,7 +27,7 @@ where
|
|||
let stylesheet = Stylesheet::from_str(
|
||||
css, url, Origin::Author, media_list, lock,
|
||||
None, None, QuirksMode::NoQuirks, 0);
|
||||
let dummy = Device::new(MediaType::screen(), TypedSize2D::new(200.0, 100.0), TypedScale::new(1.0));
|
||||
let dummy = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
|
||||
let mut rule_count = 0;
|
||||
let guard = stylesheet.shared_lock.read();
|
||||
for rule in stylesheet.iter_rules::<AllRules>(&dummy, &guard) {
|
||||
|
@ -333,7 +333,7 @@ fn test_mq_malformed_expressions() {
|
|||
|
||||
#[test]
|
||||
fn test_matching_simple() {
|
||||
let device = Device::new(MediaType::screen(), TypedSize2D::new(200.0, 100.0), TypedScale::new(1.0));
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
|
||||
|
||||
media_query_test(&device, "@media not all { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media not screen { a { color: red; } }", 0);
|
||||
|
@ -349,7 +349,7 @@ fn test_matching_simple() {
|
|||
|
||||
#[test]
|
||||
fn test_matching_width() {
|
||||
let device = Device::new(MediaType::screen(), TypedSize2D::new(200.0, 100.0), TypedScale::new(1.0));
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
|
||||
|
||||
media_query_test(&device, "@media { a { color: red; } }", 1);
|
||||
|
||||
|
@ -390,7 +390,7 @@ fn test_matching_width() {
|
|||
|
||||
#[test]
|
||||
fn test_matching_invalid() {
|
||||
let device = Device::new(MediaType::screen(), TypedSize2D::new(200.0, 100.0), TypedScale::new(1.0));
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(200.0, 100.0), Scale::new(1.0));
|
||||
|
||||
media_query_test(&device, "@media fridge { a { color: red; } }", 0);
|
||||
media_query_test(&device, "@media screen and (height: 100px) { a { color: red; } }", 0);
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::SourceLocation;
|
||||
use euclid::TypedScale;
|
||||
use euclid::TypedSize2D;
|
||||
use euclid::Scale;
|
||||
use euclid::Size2D;
|
||||
use selectors::parser::{AncestorHashes, Selector};
|
||||
use servo_arc::Arc;
|
||||
use servo_atoms::Atom;
|
||||
|
@ -179,7 +179,7 @@ fn test_insert() {
|
|||
}
|
||||
|
||||
fn mock_stylist() -> Stylist {
|
||||
let device = Device::new(MediaType::screen(), TypedSize2D::new(0f32, 0f32), TypedScale::new(1.0));
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(0f32, 0f32), Scale::new(1.0));
|
||||
Stylist::new(device, QuirksMode::NoQuirks)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use cssparser::{Parser, ParserInput};
|
||||
use euclid::TypedScale;
|
||||
use euclid::TypedSize2D;
|
||||
use euclid::Scale;
|
||||
use euclid::Size2D;
|
||||
use servo_arc::Arc;
|
||||
use servo_config::prefs::{PREFS, PrefValue};
|
||||
use servo_url::ServoUrl;
|
||||
|
@ -96,7 +96,7 @@ macro_rules! viewport_length {
|
|||
|
||||
#[test]
|
||||
fn empty_viewport_rule() {
|
||||
let device = Device::new(MediaType::screen(), TypedSize2D::new(800., 600.), TypedScale::new(1.0));
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(800., 600.), Scale::new(1.0));
|
||||
|
||||
test_viewport_rule("@viewport {}", &device, |declarations, css| {
|
||||
println!("{}", css);
|
||||
|
@ -119,7 +119,7 @@ macro_rules! assert_decl_eq {
|
|||
|
||||
#[test]
|
||||
fn simple_viewport_rules() {
|
||||
let device = Device::new(MediaType::screen(), TypedSize2D::new(800., 600.), TypedScale::new(1.0));
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(800., 600.), Scale::new(1.0));
|
||||
|
||||
test_viewport_rule("@viewport { width: auto; height: auto;\
|
||||
zoom: auto; min-zoom: 0; max-zoom: 200%;\
|
||||
|
@ -191,7 +191,7 @@ fn simple_meta_viewport_contents() {
|
|||
|
||||
#[test]
|
||||
fn cascading_within_viewport_rule() {
|
||||
let device = Device::new(MediaType::screen(), TypedSize2D::new(800., 600.), TypedScale::new(1.0));
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(800., 600.), Scale::new(1.0));
|
||||
|
||||
// normal order of appearance
|
||||
test_viewport_rule("@viewport { min-width: 200px; min-width: auto; }",
|
||||
|
@ -257,7 +257,7 @@ fn cascading_within_viewport_rule() {
|
|||
#[test]
|
||||
fn multiple_stylesheets_cascading() {
|
||||
PREFS.set("layout.viewport.enabled", PrefValue::Boolean(true));
|
||||
let device = Device::new(MediaType::screen(), TypedSize2D::new(800., 600.), TypedScale::new(1.0));
|
||||
let device = Device::new(MediaType::screen(), Size2D::new(800., 600.), Scale::new(1.0));
|
||||
let shared_lock = SharedRwLock::new();
|
||||
let stylesheets = vec![
|
||||
stylesheet!("@viewport { min-width: 100px; min-height: 100px; zoom: 1; }",
|
||||
|
@ -317,8 +317,8 @@ fn constrain_viewport() {
|
|||
}
|
||||
}
|
||||
|
||||
let initial_viewport = TypedSize2D::new(800., 600.);
|
||||
let device = Device::new(MediaType::screen(), initial_viewport, TypedScale::new(1.0));
|
||||
let initial_viewport = Size2D::new(800., 600.);
|
||||
let device = Device::new(MediaType::screen(), initial_viewport, Scale::new(1.0));
|
||||
let mut input = ParserInput::new("");
|
||||
assert_eq!(ViewportConstraints::maybe_new(&device, from_css!(input), QuirksMode::NoQuirks), None);
|
||||
|
||||
|
@ -366,12 +366,12 @@ fn constrain_viewport() {
|
|||
orientation: Orientation::Auto
|
||||
}));
|
||||
|
||||
let initial_viewport = TypedSize2D::new(200., 150.);
|
||||
let device = Device::new(MediaType::screen(), initial_viewport, TypedScale::new(1.0));
|
||||
let initial_viewport = Size2D::new(200., 150.);
|
||||
let device = Device::new(MediaType::screen(), initial_viewport, Scale::new(1.0));
|
||||
let mut input = ParserInput::new("width: 320px auto");
|
||||
assert_eq!(ViewportConstraints::maybe_new(&device, from_css!(input), QuirksMode::NoQuirks),
|
||||
Some(ViewportConstraints {
|
||||
size: TypedSize2D::new(320., 240.),
|
||||
size: Size2D::new(320., 240.),
|
||||
|
||||
initial_zoom: PinchZoomFactor::new(1.),
|
||||
min_zoom: None,
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"6ed8512d0e0c349a53eddd15a806e67e84359c1071d7d4a404f513cca091d5f5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/approxord.rs":"087e0a8d24b8a9bed4c1cc571eec5e50cc7afa184c6ac4961c7409a69456ec7b","src/box2d.rs":"5e2d634cf2181fd9f556a600d4339cb6a098341ac71f72e0bc7521b3b3fb2f19","src/box3d.rs":"8d87e7e487d0772462cc2c6033bcd05f4fee44127c4aa0a4d72407ac6a02e03b","src/homogen.rs":"7b02aa671fffcb554557ad790f598bd5d7440dc1aa4a6d1c5a97d8bc3c8f64d6","src/length.rs":"3171315822707728b1bfbdd04a4190ffb7206b4bfc59e9dd072bb2caa05ff292","src/lib.rs":"e8bbae14e1b284fba3529af44396e488cbc48f8b3d20ddb26da5919d9c02601b","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"b51cf9b7713d9a48452d833cfbc97bb95e0c2202c4f77cadd02633ce80a600df","src/rect.rs":"2e4036f3f7e2ca62e6f9a52787ca9b9765b401a11cf1e70dff6c81142bdd91ed","src/rigid.rs":"e50a5df42add328ed5164e1954592406ce6d8f564beb4ca375c5cca920e93fbc","src/rotation.rs":"3d1a934a7c59bd7ca8501d17d463d5af41fb529c5aa8fe8c3bb8a2b236d4abc0","src/scale.rs":"fc07bcf47f3a1215023c830059f0d270e570cbd37fe8c367ef4a47b191f4ae3e","src/side_offsets.rs":"d9b1463672e1204bf8e7dd6fe0f7601eb75b6690ec6eb18debcee07f5ca92ee3","src/size.rs":"c4e38966c280ab5b4963961eebdbb12e0f448aea624cbe760b02ca2221a004e5","src/transform2d.rs":"7657d447993dc820e404ea9fbde6cb2900d874d4f5c735e85c6225c9f3b4110d","src/transform3d.rs":"af3d909ee103d02fec5f59599055cc3cee5217975b030e0089e1f1d99ad5139e","src/translation.rs":"b21d1d81a34b80d3285d42f33e8039fdb787749f017d2a7a2295d036c2f50548","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"dcd0904757ed0e7d12da1c612746da3e32c56e2248ec13041d1f3786811af51c"},"package":"596b99621b9477e7a5f94d2d8dd13a9c5c302ac358b822c67a42b6f1054450e1"}
|
||||
{"files":{"COPYRIGHT":"ec82b96487e9e778ee610c7ab245162464782cfa1f555c2299333f8dbe5c036a","Cargo.toml":"7ae5531c88ac476361c06e6ee5531839eff3b301c66ba05619570b3ab7926467","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","README.md":"625bec69c76ce5423fdd05cfe46922b2680ec517f97c5854ce34798d1d8a9541","src/approxeq.rs":"6594377e8f6c20f88f628520d8de9b9a59c5892a0ee9a6ccd13c8400c1499911","src/approxord.rs":"087e0a8d24b8a9bed4c1cc571eec5e50cc7afa184c6ac4961c7409a69456ec7b","src/box2d.rs":"0dc013b9bfe088e62df8675674a5430580ecfaff202d0966ba5d316e7ff0165e","src/box3d.rs":"f15962fa34ef4dec099ca7403651ac92d5be55eba7aee0300b1a2837643dcb86","src/homogen.rs":"5c14355182b4fb7c148fc65c1f63b25607019ae8d763e187d659925e2ca210a3","src/length.rs":"b1f44beb961b193bea814f5a15aee713cab97d076de13e51e294891fd7153f27","src/lib.rs":"d58eecf5847b37f68ac6604c5b5a16962756faf04f9af1f5293228486b120378","src/macros.rs":"3b475e84d00cceee6c7e96e9f2c97ba15d8dc7f4094efb82c5ed10bd60d86a64","src/nonempty.rs":"865d51dc1ae785ee2e6e94eb2ee935f29a86b9efa8daa322bca7992fa9ae70fc","src/num.rs":"4439479fad5729073e0bfe0b96b547672a237430d48e564519759b9550baa033","src/point.rs":"b0eeed9f99cdd81525dd32b4d76caff862447e129b29bf55d003a35425e93ab6","src/rect.rs":"8298e2b67c7aadd255a53d42a6e5b19968aa47fcff05f8c60f4073da0a808dfc","src/rigid.rs":"aab59591562938695e63487230504b2d94df6e3a7b7740069166c8499d4fa930","src/rotation.rs":"307b22df279f30e4ac4aa35a0d69fb7f9196bd553c06b7f519692655e1e353d3","src/scale.rs":"6a4c3da9444c72e967d5217bbe5442a8517448857cb32472f883d6da58b8f846","src/side_offsets.rs":"eaa52aa64f0fa041fbd5c1c9165a01614db6c37d4746a56c3294a388bd5e0616","src/size.rs":"b3478be99f4409d3083e7553f5906c8ac314beddb83cc87492415c02785b8311","src/transform2d.rs":"8a0b4f097c8e98408dfe709b3ef0e8530562a6e1b68f62d6cd86c906cc0bb7eb","src/transform3d.rs":"6a6d56b67fdb1b6d4bfd725959d6b95cf4fa5ffbc272ae9f1508a400a3a4b30e","src/translation.rs":"67afb126179e3cb5a2c1bd462a8f5c87630233a68f63ff6a2194dbd3b229d734","src/trig.rs":"97a263c4f178b0332501659ca8143f9f637a0755aca189dd31ac551bcd4cb73c","src/vector.rs":"ca39c30729f781dd5e64b5fea1516e676b6ab4fc57788895fa2ca5309ad73ec3"},"package":"2c4786521fec183792e755bf32cd0188e4e7628c6d0fcfd51426435b9081a106"}
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "euclid"
|
||||
version = "0.19.9"
|
||||
version = "0.20.0"
|
||||
authors = ["The Servo Project Developers"]
|
||||
description = "Geometry primitives"
|
||||
documentation = "https://docs.rs/euclid/"
|
||||
|
@ -20,9 +20,6 @@ keywords = ["matrix", "vector", "linear-algebra", "geometry"]
|
|||
categories = ["science"]
|
||||
license = "MIT / Apache-2.0"
|
||||
repository = "https://github.com/servo/euclid"
|
||||
[dependencies.euclid_macros]
|
||||
version = "0.1"
|
||||
|
||||
[dependencies.mint]
|
||||
version = "0.5.1"
|
||||
optional = true
|
||||
|
@ -34,9 +31,6 @@ version = "0.2"
|
|||
version = "1.0"
|
||||
features = ["serde_derive"]
|
||||
optional = true
|
||||
[dev-dependencies.rand]
|
||||
version = "0.4"
|
||||
|
||||
[dev-dependencies.serde_test]
|
||||
version = "1.0"
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@
|
|||
// except according to those terms.
|
||||
|
||||
use super::UnknownUnit;
|
||||
use scale::TypedScale;
|
||||
use scale::Scale;
|
||||
use num::*;
|
||||
use rect::TypedRect;
|
||||
use point::{point2, TypedPoint2D};
|
||||
use vector::{vec2, TypedVector2D};
|
||||
use side_offsets::TypedSideOffsets2D;
|
||||
use size::TypedSize2D;
|
||||
use rect::Rect;
|
||||
use point::{point2, Point2D};
|
||||
use vector::{vec2, Vector2D};
|
||||
use side_offsets::SideOffsets2D;
|
||||
use size::Size2D;
|
||||
use nonempty::NonEmpty;
|
||||
use approxord::{min, max};
|
||||
|
||||
use num_traits::NumCast;
|
||||
|
@ -32,73 +33,70 @@ use core::ops::{Add, Div, Mul, Sub};
|
|||
#[repr(C)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
|
||||
pub struct TypedBox2D<T, U> {
|
||||
pub min: TypedPoint2D<T, U>,
|
||||
pub max: TypedPoint2D<T, U>,
|
||||
pub struct Box2D<T, U> {
|
||||
pub min: Point2D<T, U>,
|
||||
pub max: Point2D<T, U>,
|
||||
}
|
||||
|
||||
/// The default box 2d type with no unit.
|
||||
pub type Box2D<T> = TypedBox2D<T, UnknownUnit>;
|
||||
|
||||
impl<T: Hash, U> Hash for TypedBox2D<T, U> {
|
||||
impl<T: Hash, U> Hash for Box2D<T, U> {
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
self.min.hash(h);
|
||||
self.max.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for TypedBox2D<T, U> {}
|
||||
impl<T: Copy, U> Copy for Box2D<T, U> {}
|
||||
|
||||
impl<T: Copy, U> Clone for TypedBox2D<T, U> {
|
||||
impl<T: Copy, U> Clone for Box2D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, U> PartialEq<TypedBox2D<T, U>> for TypedBox2D<T, U> {
|
||||
impl<T: PartialEq, U> PartialEq<Box2D<T, U>> for Box2D<T, U> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.min.eq(&other.min) && self.max.eq(&other.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq, U> Eq for TypedBox2D<T, U> {}
|
||||
impl<T: Eq, U> Eq for Box2D<T, U> {}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedBox2D<T, U> {
|
||||
impl<T: fmt::Debug, U> fmt::Debug for Box2D<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "TypedBox2D({:?}, {:?})", self.min, self.max)
|
||||
write!(f, "Box2D({:?}, {:?})", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for TypedBox2D<T, U> {
|
||||
impl<T: fmt::Display, U> fmt::Display for Box2D<T, U> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "Box2D({}, {})", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U> {
|
||||
impl<T, U> Box2D<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(min: TypedPoint2D<T, U>, max: TypedPoint2D<T, U>) -> Self {
|
||||
TypedBox2D {
|
||||
pub fn new(min: Point2D<T, U>, max: Point2D<T, U>) -> Self {
|
||||
Box2D {
|
||||
min,
|
||||
max,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
/// Creates a Box2D of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: TypedSize2D<T, U>) -> Self {
|
||||
let zero = TypedPoint2D::zero();
|
||||
pub fn from_size(size: Size2D<T, U>) -> Self {
|
||||
let zero = Point2D::zero();
|
||||
let point = size.to_vector().to_point();
|
||||
TypedBox2D::from_points(&[zero, point])
|
||||
Box2D::from_points(&[zero, point])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
|
@ -117,6 +115,15 @@ where
|
|||
self.max.x <= self.min.x || self.max.y <= self.min.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
|
||||
if self.is_empty_or_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(NonEmpty(*self))
|
||||
}
|
||||
|
||||
/// Returns true if the two boxes intersect.
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
|
@ -131,7 +138,7 @@ where
|
|||
/// The result is a negative box if the boxes do not intersect.
|
||||
#[inline]
|
||||
pub fn intersection(&self, other: &Self) -> Self {
|
||||
TypedBox2D {
|
||||
Box2D {
|
||||
min: point2(
|
||||
max(self.min.x, other.min.x),
|
||||
max(self.min.y, other.min.y),
|
||||
|
@ -145,29 +152,32 @@ where
|
|||
|
||||
/// Computes the intersection of two boxes, returning `None` if the boxes do not intersect.
|
||||
#[inline]
|
||||
pub fn try_intersection(&self, other: &Self) -> Option<Self> {
|
||||
pub fn try_intersection(&self, other: &Self) -> Option<NonEmpty<Self>> {
|
||||
let intersection = self.intersection(other);
|
||||
|
||||
if intersection.is_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(intersection)
|
||||
Some(NonEmpty(intersection))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>,
|
||||
{
|
||||
/// Returns the same box, translated by a vector.
|
||||
#[inline]
|
||||
pub fn translate(&self, by: &TypedVector2D<T, U>) -> Self {
|
||||
Self::new(self.min + *by, self.max + *by)
|
||||
pub fn translate(&self, by: Vector2D<T, U>) -> Self {
|
||||
Box2D {
|
||||
min: self.min + by,
|
||||
max: self.max + by,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero,
|
||||
{
|
||||
|
@ -175,13 +185,13 @@ where
|
|||
/// in the box if they are on the front, left or top faces, but outside if they
|
||||
/// are on the back, right or bottom faces.
|
||||
#[inline]
|
||||
pub fn contains(&self, p: &TypedPoint2D<T, U>) -> bool {
|
||||
pub fn contains(&self, p: Point2D<T, U>) -> bool {
|
||||
self.min.x <= p.x && p.x < self.max.x
|
||||
&& self.min.y <= p.y && p.y < self.max.y
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero + Sub<T, Output = T>,
|
||||
{
|
||||
|
@ -196,40 +206,40 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn size(&self)-> TypedSize2D<T, U> {
|
||||
pub fn size(&self)-> Size2D<T, U> {
|
||||
(self.max - self.min).to_size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_rect(&self) -> TypedRect<T, U> {
|
||||
TypedRect {
|
||||
pub fn to_rect(&self) -> Rect<T, U> {
|
||||
Rect {
|
||||
origin: self.min,
|
||||
size: self.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
/// Inflates the box by the specified sizes on each side respectively.
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn inflate(&self, width: T, height: T) -> Self {
|
||||
TypedBox2D {
|
||||
Box2D {
|
||||
min: point2(self.min.x - width, self.min.y - height),
|
||||
max: point2(self.max.x + width, self.max.y + height),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
|
@ -237,8 +247,8 @@ where
|
|||
///
|
||||
/// Subtracts the side offsets from all sides. The horizontal, vertical
|
||||
/// and applicate offsets must not be larger than the original side length.
|
||||
pub fn inner_box(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
|
||||
TypedBox2D {
|
||||
pub fn inner_box(&self, offsets: SideOffsets2D<T, U>) -> Self {
|
||||
Box2D {
|
||||
min: self.min + vec2(offsets.left, offsets.top),
|
||||
max: self.max - vec2(offsets.right, offsets.bottom),
|
||||
}
|
||||
|
@ -247,8 +257,8 @@ where
|
|||
/// Calculate the b and position of an outer box.
|
||||
///
|
||||
/// Add the offsets to all sides. The expanded box is returned.
|
||||
pub fn outer_box(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
|
||||
TypedBox2D {
|
||||
pub fn outer_box(&self, offsets: SideOffsets2D<T, U>) -> Self {
|
||||
Box2D {
|
||||
min: self.min - vec2(offsets.left, offsets.top),
|
||||
max: self.max + vec2(offsets.right, offsets.bottom),
|
||||
}
|
||||
|
@ -256,7 +266,7 @@ where
|
|||
}
|
||||
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
|
@ -264,14 +274,14 @@ where
|
|||
pub fn from_points<I>(points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<TypedPoint2D<T, U>>,
|
||||
I::Item: Borrow<Point2D<T, U>>,
|
||||
{
|
||||
let mut points = points.into_iter();
|
||||
|
||||
// Need at least 2 different points for a valid box (ie: volume > 0).
|
||||
let (mut min_x, mut min_y) = match points.next() {
|
||||
Some(first) => (first.borrow().x, first.borrow().y),
|
||||
None => return TypedBox2D::zero(),
|
||||
None => return Box2D::zero(),
|
||||
};
|
||||
let (mut max_x, mut max_y) = (min_x, min_y);
|
||||
|
||||
|
@ -294,7 +304,7 @@ where
|
|||
|
||||
match points.next() {
|
||||
Some(second) => assign_min_max(second),
|
||||
None => return TypedBox2D::zero(),
|
||||
None => return Box2D::zero(),
|
||||
}
|
||||
|
||||
for point in points {
|
||||
|
@ -302,14 +312,14 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
TypedBox2D {
|
||||
Box2D {
|
||||
min: point2(min_x, min_y),
|
||||
max: point2(max_x, max_y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
|
@ -325,23 +335,23 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Div<Output = T>,
|
||||
{
|
||||
pub fn center(&self) -> TypedPoint2D<T, U> {
|
||||
pub fn center(&self) -> Point2D<T, U> {
|
||||
let two = T::one() + T::one();
|
||||
(self.min + self.max.to_vector()) / two
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
TypedBox2D {
|
||||
Box2D {
|
||||
min: point2(
|
||||
min(self.min.x, other.min.x),
|
||||
min(self.min.y, other.min.y),
|
||||
|
@ -354,7 +364,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
|
@ -363,14 +373,14 @@ where
|
|||
where
|
||||
T: Mul<S, Output = T>
|
||||
{
|
||||
TypedBox2D {
|
||||
Box2D {
|
||||
min: point2(self.min.x * x, self.min.y * y),
|
||||
max: point2(self.max.x * x, self.max.y * y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
|
@ -381,17 +391,17 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Copy + Zero,
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
TypedBox2D::new(TypedPoint2D::zero(), TypedPoint2D::zero())
|
||||
Box2D::new(Point2D::zero(), Point2D::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
|
@ -402,69 +412,69 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> Mul<T> for TypedBox2D<T, U>
|
||||
impl<T, U> Mul<T> for Box2D<T, U>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
TypedBox2D::new(self.min * scale, self.max * scale)
|
||||
Box2D::new(self.min * scale, self.max * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Div<T> for TypedBox2D<T, U>
|
||||
impl<T, U> Div<T> for Box2D<T, U>
|
||||
where
|
||||
T: Copy + Div<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
TypedBox2D::new(self.min / scale, self.max / scale)
|
||||
Box2D::new(self.min / scale, self.max / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedBox2D<T, U1>
|
||||
impl<T, U1, U2> Mul<Scale<T, U1, U2>> for Box2D<T, U1>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T>,
|
||||
{
|
||||
type Output = TypedBox2D<T, U2>;
|
||||
type Output = Box2D<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedBox2D<T, U2> {
|
||||
TypedBox2D::new(self.min * scale, self.max * scale)
|
||||
fn mul(self, scale: Scale<T, U1, U2>) -> Box2D<T, U2> {
|
||||
Box2D::new(self.min * scale, self.max * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U1, U2> Div<TypedScale<T, U1, U2>> for TypedBox2D<T, U2>
|
||||
impl<T, U1, U2> Div<Scale<T, U1, U2>> for Box2D<T, U2>
|
||||
where
|
||||
T: Copy + Div<T, Output = T>,
|
||||
{
|
||||
type Output = TypedBox2D<T, U1>;
|
||||
type Output = Box2D<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedBox2D<T, U1> {
|
||||
TypedBox2D::new(self.min / scale, self.max / scale)
|
||||
fn div(self, scale: Scale<T, U1, U2>) -> Box2D<T, U1> {
|
||||
Box2D::new(self.min / scale, self.max / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Unit> TypedBox2D<T, Unit>
|
||||
impl<T, Unit> Box2D<T, Unit>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Box2D<T> {
|
||||
TypedBox2D::new(self.min.to_untyped(), self.max.to_untyped())
|
||||
pub fn to_untyped(&self) -> Box2D<T, UnknownUnit> {
|
||||
Box2D::new(self.min.to_untyped(), self.max.to_untyped())
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(c: &Box2D<T>) -> TypedBox2D<T, Unit> {
|
||||
TypedBox2D::new(
|
||||
TypedPoint2D::from_untyped(&c.min),
|
||||
TypedPoint2D::from_untyped(&c.max),
|
||||
pub fn from_untyped(c: &Box2D<T, UnknownUnit>) -> Box2D<T, Unit> {
|
||||
Box2D::new(
|
||||
Point2D::from_untyped(c.min),
|
||||
Point2D::from_untyped(c.max),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0, Unit> TypedBox2D<T0, Unit>
|
||||
impl<T0, Unit> Box2D<T0, Unit>
|
||||
where
|
||||
T0: NumCast + Copy,
|
||||
{
|
||||
|
@ -473,8 +483,8 @@ where
|
|||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> TypedBox2D<T1, Unit> {
|
||||
TypedBox2D::new(
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Box2D<T1, Unit> {
|
||||
Box2D::new(
|
||||
self.min.cast(),
|
||||
self.max.cast(),
|
||||
)
|
||||
|
@ -485,15 +495,15 @@ where
|
|||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedBox2D<T1, Unit>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Box2D<T1, Unit>> {
|
||||
match (self.min.try_cast(), self.max.try_cast()) {
|
||||
(Some(a), Some(b)) => Some(TypedBox2D::new(a, b)),
|
||||
(Some(a), Some(b)) => Some(Box2D::new(a, b)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Round,
|
||||
{
|
||||
|
@ -506,44 +516,44 @@ where
|
|||
/// avoid pixel rounding errors.
|
||||
/// Note that this is *not* rounding to nearest integer if the values are negative.
|
||||
/// They are always rounding as floor(n + 0.5).
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round(&self) -> Self {
|
||||
TypedBox2D::new(self.min.round(), self.max.round())
|
||||
Box2D::new(self.min.round(), self.max.round())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox2D<T, U>
|
||||
impl<T, U> Box2D<T, U>
|
||||
where
|
||||
T: Floor + Ceil,
|
||||
{
|
||||
/// Return a box with faces/edges rounded to integer coordinates, such that
|
||||
/// the original box contains the resulting box.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round_in(&self) -> Self {
|
||||
let min = self.min.ceil();
|
||||
let max = self.max.floor();
|
||||
TypedBox2D { min, max }
|
||||
Box2D { min, max }
|
||||
}
|
||||
|
||||
/// Return a box with faces/edges rounded to integer coordinates, such that
|
||||
/// the original box is contained in the resulting box.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round_out(&self) -> Self {
|
||||
let min = self.min.floor();
|
||||
let max = self.max.ceil();
|
||||
TypedBox2D { min, max }
|
||||
Box2D { min, max }
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, Unit> TypedBox2D<T, Unit> {
|
||||
impl<T: NumCast + Copy, Unit> Box2D<T, Unit> {
|
||||
/// Cast into an `f32` box.
|
||||
pub fn to_f32(&self) -> TypedBox2D<f32, Unit> {
|
||||
pub fn to_f32(&self) -> Box2D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` box.
|
||||
pub fn to_f64(&self) -> TypedBox2D<f64, Unit> {
|
||||
pub fn to_f64(&self) -> Box2D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -552,7 +562,7 @@ impl<T: NumCast + Copy, Unit> TypedBox2D<T, Unit> {
|
|||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> TypedBox2D<usize, Unit> {
|
||||
pub fn to_usize(&self) -> Box2D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -561,7 +571,7 @@ impl<T: NumCast + Copy, Unit> TypedBox2D<T, Unit> {
|
|||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> TypedBox2D<u32, Unit> {
|
||||
pub fn to_u32(&self) -> Box2D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -570,7 +580,7 @@ impl<T: NumCast + Copy, Unit> TypedBox2D<T, Unit> {
|
|||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> TypedBox2D<i32, Unit> {
|
||||
pub fn to_i32(&self) -> Box2D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -579,16 +589,16 @@ impl<T: NumCast + Copy, Unit> TypedBox2D<T, Unit> {
|
|||
/// When casting from floating point boxes, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> TypedBox2D<i64, Unit> {
|
||||
pub fn to_i64(&self) -> Box2D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<TypedSize2D<T, U>> for TypedBox2D<T, U>
|
||||
impl<T, U> From<Size2D<T, U>> for Box2D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
fn from(b: TypedSize2D<T, U>) -> Self {
|
||||
fn from(b: Size2D<T, U>) -> Self {
|
||||
Self::from_size(b)
|
||||
}
|
||||
}
|
||||
|
@ -596,9 +606,9 @@ where
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use side_offsets::SideOffsets2D;
|
||||
use size::size2;
|
||||
use point::Point2D;
|
||||
use super::*;
|
||||
use {Point2D, point2, vec2, size2};
|
||||
use default::Box2D;
|
||||
//use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_size() {
|
||||
|
@ -688,7 +698,7 @@ mod tests {
|
|||
let b = Box2D::from_size(size);
|
||||
assert_eq!(b.center(), center);
|
||||
let translation = vec2(10.0, 2.5);
|
||||
let b = b.translate(&translation);
|
||||
let b = b.translate(translation);
|
||||
center += translation;
|
||||
assert_eq!(b.center(), center);
|
||||
assert_eq!(b.max.x, 25.0);
|
||||
|
@ -760,7 +770,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_contains() {
|
||||
let b = Box2D::from_points(&[point2(-20.0, -20.0), point2(20.0, 20.0)]);
|
||||
assert!(b.contains(&point2(-15.3, 10.5)));
|
||||
assert!(b.contains(point2(-15.3, 10.5)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
// except according to those terms.
|
||||
|
||||
use super::UnknownUnit;
|
||||
use length::Length;
|
||||
use scale::TypedScale;
|
||||
use scale::Scale;
|
||||
use num::*;
|
||||
use point::TypedPoint3D;
|
||||
use vector::TypedVector3D;
|
||||
use size::TypedSize3D;
|
||||
use point::Point3D;
|
||||
use vector::Vector3D;
|
||||
use size::Size3D;
|
||||
use approxord::{min, max};
|
||||
use nonempty::NonEmpty;
|
||||
|
||||
use num_traits::NumCast;
|
||||
#[cfg(feature = "serde")]
|
||||
|
@ -31,73 +31,70 @@ use core::ops::{Add, Div, Mul, Sub};
|
|||
#[repr(C)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
|
||||
pub struct TypedBox3D<T, U> {
|
||||
pub min: TypedPoint3D<T, U>,
|
||||
pub max: TypedPoint3D<T, U>,
|
||||
pub struct Box3D<T, U> {
|
||||
pub min: Point3D<T, U>,
|
||||
pub max: Point3D<T, U>,
|
||||
}
|
||||
|
||||
/// The default box 3d type with no unit.
|
||||
pub type Box3D<T> = TypedBox3D<T, UnknownUnit>;
|
||||
|
||||
impl<T: Hash, U> Hash for TypedBox3D<T, U> {
|
||||
impl<T: Hash, U> Hash for Box3D<T, U> {
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
self.min.hash(h);
|
||||
self.max.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for TypedBox3D<T, U> {}
|
||||
impl<T: Copy, U> Copy for Box3D<T, U> {}
|
||||
|
||||
impl<T: Copy, U> Clone for TypedBox3D<T, U> {
|
||||
impl<T: Copy, U> Clone for Box3D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, U> PartialEq<TypedBox3D<T, U>> for TypedBox3D<T, U> {
|
||||
impl<T: PartialEq, U> PartialEq<Box3D<T, U>> for Box3D<T, U> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.min.eq(&other.min) && self.max.eq(&other.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq, U> Eq for TypedBox3D<T, U> {}
|
||||
impl<T: Eq, U> Eq for Box3D<T, U> {}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedBox3D<T, U> {
|
||||
impl<T: fmt::Debug, U> fmt::Debug for Box3D<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "TypedBox3D({:?}, {:?})", self.min, self.max)
|
||||
write!(f, "Box3D({:?}, {:?})", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for TypedBox3D<T, U> {
|
||||
impl<T: fmt::Display, U> fmt::Display for Box3D<T, U> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "Box3D({}, {})", self.min, self.max)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U> {
|
||||
impl<T, U> Box3D<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(min: TypedPoint3D<T, U>, max: TypedPoint3D<T, U>) -> Self {
|
||||
TypedBox3D {
|
||||
pub fn new(min: Point3D<T, U>, max: Point3D<T, U>) -> Self {
|
||||
Box3D {
|
||||
min,
|
||||
max,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
/// Creates a Box3D of the given size, at offset zero.
|
||||
#[inline]
|
||||
pub fn from_size(size: TypedSize3D<T, U>) -> Self {
|
||||
let zero = TypedPoint3D::zero();
|
||||
pub fn from_size(size: Size3D<T, U>) -> Self {
|
||||
let zero = Point3D::zero();
|
||||
let point = size.to_vector().to_point();
|
||||
TypedBox3D::from_points(&[zero, point])
|
||||
Box3D::from_points(&[zero, point])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
|
@ -116,6 +113,14 @@ where
|
|||
self.max.x <= self.min.x || self.max.y <= self.min.y || self.max.z <= self.min.z
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
|
||||
if self.is_empty_or_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(NonEmpty(*self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn intersects(&self, other: &Self) -> bool {
|
||||
|
@ -128,47 +133,50 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_intersection(&self, other: &Self) -> Option<Self> {
|
||||
pub fn try_intersection(&self, other: &Self) -> Option<NonEmpty<Self>> {
|
||||
if !self.intersects(other) {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(self.intersection(other))
|
||||
Some(NonEmpty(self.intersection(other)))
|
||||
}
|
||||
|
||||
pub fn intersection(&self, other: &Self) -> Self {
|
||||
let intersection_min = TypedPoint3D::new(
|
||||
let intersection_min = Point3D::new(
|
||||
max(self.min.x, other.min.x),
|
||||
max(self.min.y, other.min.y),
|
||||
max(self.min.z, other.min.z),
|
||||
);
|
||||
|
||||
let intersection_max = TypedPoint3D::new(
|
||||
let intersection_max = Point3D::new(
|
||||
min(self.max.x, other.max.x),
|
||||
min(self.max.y, other.max.y),
|
||||
min(self.max.z, other.max.z),
|
||||
);
|
||||
|
||||
TypedBox3D::new(
|
||||
Box3D::new(
|
||||
intersection_min,
|
||||
intersection_max,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>,
|
||||
{
|
||||
/// Returns the same box3d, translated by a vector.
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn translate(&self, by: &TypedVector3D<T, U>) -> Self {
|
||||
Self::new(self.min + *by, self.max + *by)
|
||||
#[must_use]
|
||||
pub fn translate(&self, by: Vector3D<T, U>) -> Self {
|
||||
Box3D {
|
||||
min: self.min + by,
|
||||
max: self.max + by,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero,
|
||||
{
|
||||
|
@ -176,14 +184,14 @@ where
|
|||
/// in the box3d if they are on the front, left or top faces, but outside if they
|
||||
/// are on the back, right or bottom faces.
|
||||
#[inline]
|
||||
pub fn contains(&self, other: &TypedPoint3D<T, U>) -> bool {
|
||||
pub fn contains(&self, other: Point3D<T, U>) -> bool {
|
||||
self.min.x <= other.x && other.x < self.max.x
|
||||
&& self.min.y <= other.y && other.y < self.max.y
|
||||
&& self.min.z <= other.z && other.z < self.max.z
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialOrd + Zero + Sub<T, Output = T>,
|
||||
{
|
||||
|
@ -199,13 +207,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn size(&self)-> TypedSize3D<T, U> {
|
||||
TypedSize3D::new(
|
||||
pub fn size(&self)-> Size3D<T, U> {
|
||||
Size3D::new(
|
||||
self.max.x - self.min.x,
|
||||
self.max.y - self.min.y,
|
||||
self.max.z - self.min.z,
|
||||
|
@ -213,28 +221,22 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
/// Inflates the box by the specified sizes on each side respectively.
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn inflate(&self, width: T, height: T, depth: T) -> Self {
|
||||
TypedBox3D::new(
|
||||
TypedPoint3D::new(self.min.x - width, self.min.y - height, self.min.z - depth),
|
||||
TypedPoint3D::new(self.max.x + width, self.max.y + height, self.max.z + depth),
|
||||
Box3D::new(
|
||||
Point3D::new(self.min.x - width, self.min.y - height, self.min.z - depth),
|
||||
Point3D::new(self.max.x + width, self.max.y + height, self.max.z + depth),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn inflate_typed(&self, width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
|
||||
self.inflate(width.get(), height.get(), depth.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
|
@ -242,14 +244,14 @@ where
|
|||
pub fn from_points<I>(points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<TypedPoint3D<T, U>>,
|
||||
I::Item: Borrow<Point3D<T, U>>,
|
||||
{
|
||||
let mut points = points.into_iter();
|
||||
|
||||
// Need at least 2 different points for a valid box3d (ie: volume > 0).
|
||||
let (mut min_x, mut min_y, mut min_z) = match points.next() {
|
||||
Some(first) => (first.borrow().x, first.borrow().y, first.borrow().z),
|
||||
None => return TypedBox3D::zero(),
|
||||
None => return Box3D::zero(),
|
||||
};
|
||||
let (mut max_x, mut max_y, mut max_z) = (min_x, min_y, min_z);
|
||||
|
||||
|
@ -278,7 +280,7 @@ where
|
|||
|
||||
match points.next() {
|
||||
Some(second) => assign_min_max(second),
|
||||
None => return TypedBox3D::zero(),
|
||||
None => return Box3D::zero(),
|
||||
}
|
||||
|
||||
for point in points {
|
||||
|
@ -286,11 +288,11 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
Self::new(TypedPoint3D::new(min_x, min_y, min_z), TypedPoint3D::new(max_x, max_y, max_z))
|
||||
Self::new(Point3D::new(min_x, min_y, min_z), Point3D::new(max_x, max_y, max_z))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
|
@ -306,29 +308,29 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Div<Output = T>,
|
||||
{
|
||||
pub fn center(&self) -> TypedPoint3D<T, U> {
|
||||
pub fn center(&self) -> Point3D<T, U> {
|
||||
let two = T::one() + T::one();
|
||||
(self.min + self.max.to_vector()) / two
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &Self) -> Self {
|
||||
TypedBox3D::new(
|
||||
TypedPoint3D::new(
|
||||
Box3D::new(
|
||||
Point3D::new(
|
||||
min(self.min.x, other.min.x),
|
||||
min(self.min.y, other.min.y),
|
||||
min(self.min.z, other.min.z),
|
||||
),
|
||||
TypedPoint3D::new(
|
||||
Point3D::new(
|
||||
max(self.max.x, other.max.x),
|
||||
max(self.max.y, other.max.y),
|
||||
max(self.max.z, other.max.z),
|
||||
|
@ -337,7 +339,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
|
@ -346,14 +348,14 @@ where
|
|||
where
|
||||
T: Mul<S, Output = T>
|
||||
{
|
||||
TypedBox3D::new(
|
||||
TypedPoint3D::new(self.min.x * x, self.min.y * y, self.min.z * z),
|
||||
TypedPoint3D::new(self.max.x * x, self.max.y * y, self.max.z * z),
|
||||
Box3D::new(
|
||||
Point3D::new(self.min.x * x, self.min.y * y, self.min.z * z),
|
||||
Point3D::new(self.max.x * x, self.max.y * y, self.max.z * z),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
|
@ -382,17 +384,17 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Copy + Zero,
|
||||
{
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
TypedBox3D::new(TypedPoint3D::zero(), TypedPoint3D::zero())
|
||||
Box3D::new(Point3D::zero(), Point3D::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: PartialEq,
|
||||
{
|
||||
|
@ -403,69 +405,74 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> Mul<T> for TypedBox3D<T, U>
|
||||
impl<T, U> Mul<T> for Box3D<T, U>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
TypedBox3D::new(self.min * scale, self.max * scale)
|
||||
Box3D::new(self.min * scale, self.max * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Div<T> for TypedBox3D<T, U>
|
||||
impl<T, U> Div<T> for Box3D<T, U>
|
||||
where
|
||||
T: Copy + Div<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
TypedBox3D::new(self.min / scale, self.max / scale)
|
||||
Box3D::new(self.min / scale, self.max / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedBox3D<T, U1>
|
||||
impl<T, U1, U2> Mul<Scale<T, U1, U2>> for Box3D<T, U1>
|
||||
where
|
||||
T: Copy + Mul<T, Output = T>,
|
||||
{
|
||||
type Output = TypedBox3D<T, U2>;
|
||||
type Output = Box3D<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedBox3D<T, U2> {
|
||||
TypedBox3D::new(self.min * scale, self.max * scale)
|
||||
fn mul(self, scale: Scale<T, U1, U2>) -> Box3D<T, U2> {
|
||||
Box3D::new(self.min * scale, self.max * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U1, U2> Div<TypedScale<T, U1, U2>> for TypedBox3D<T, U2>
|
||||
impl<T, U1, U2> Div<Scale<T, U1, U2>> for Box3D<T, U2>
|
||||
where
|
||||
T: Copy + Div<T, Output = T>,
|
||||
{
|
||||
type Output = TypedBox3D<T, U1>;
|
||||
type Output = Box3D<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedBox3D<T, U1> {
|
||||
TypedBox3D::new(self.min / scale, self.max / scale)
|
||||
fn div(self, scale: Scale<T, U1, U2>) -> Box3D<T, U1> {
|
||||
Box3D::new(self.min / scale, self.max / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Unit> TypedBox3D<T, Unit>
|
||||
impl<T, Unit> Box3D<T, Unit>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Box3D<T> {
|
||||
TypedBox3D::new(self.min.to_untyped(), self.max.to_untyped())
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Box3D<T, UnknownUnit> {
|
||||
Box3D {
|
||||
min: self.min.to_untyped(),
|
||||
max: self.max.to_untyped(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(c: &Box3D<T>) -> TypedBox3D<T, Unit> {
|
||||
TypedBox3D::new(
|
||||
TypedPoint3D::from_untyped(&c.min),
|
||||
TypedPoint3D::from_untyped(&c.max),
|
||||
)
|
||||
#[inline]
|
||||
pub fn from_untyped(c: &Box3D<T, UnknownUnit>) -> Box3D<T, Unit> {
|
||||
Box3D {
|
||||
min: Point3D::from_untyped(c.min),
|
||||
max: Point3D::from_untyped(c.max),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0, Unit> TypedBox3D<T0, Unit>
|
||||
impl<T0, Unit> Box3D<T0, Unit>
|
||||
where
|
||||
T0: NumCast + Copy,
|
||||
{
|
||||
|
@ -474,8 +481,8 @@ where
|
|||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> TypedBox3D<T1, Unit> {
|
||||
TypedBox3D::new(
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Box3D<T1, Unit> {
|
||||
Box3D::new(
|
||||
self.min.cast(),
|
||||
self.max.cast(),
|
||||
)
|
||||
|
@ -486,15 +493,15 @@ where
|
|||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedBox3D<T1, Unit>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Box3D<T1, Unit>> {
|
||||
match (self.min.try_cast(), self.max.try_cast()) {
|
||||
(Some(a), Some(b)) => Some(TypedBox3D::new(a, b)),
|
||||
(Some(a), Some(b)) => Some(Box3D::new(a, b)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Round,
|
||||
{
|
||||
|
@ -507,21 +514,21 @@ where
|
|||
/// avoid pixel rounding errors.
|
||||
/// Note that this is *not* rounding to nearest integer if the values are negative.
|
||||
/// They are always rounding as floor(n + 0.5).
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round(&self) -> Self {
|
||||
TypedBox3D::new(self.min.round(), self.max.round())
|
||||
Box3D::new(self.min.round(), self.max.round())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedBox3D<T, U>
|
||||
impl<T, U> Box3D<T, U>
|
||||
where
|
||||
T: Floor + Ceil,
|
||||
{
|
||||
/// Return a box3d with faces/edges rounded to integer coordinates, such that
|
||||
/// the original box3d contains the resulting box3d.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round_in(&self) -> Self {
|
||||
TypedBox3D {
|
||||
Box3D {
|
||||
min: self.min.ceil(),
|
||||
max: self.max.floor(),
|
||||
}
|
||||
|
@ -529,9 +536,9 @@ where
|
|||
|
||||
/// Return a box3d with faces/edges rounded to integer coordinates, such that
|
||||
/// the original box3d is contained in the resulting box3d.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round_out(&self) -> Self {
|
||||
TypedBox3D {
|
||||
Box3D {
|
||||
min: self.min.floor(),
|
||||
max: self.max.ceil(),
|
||||
}
|
||||
|
@ -539,14 +546,14 @@ where
|
|||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, Unit> TypedBox3D<T, Unit> {
|
||||
impl<T: NumCast + Copy, Unit> Box3D<T, Unit> {
|
||||
/// Cast into an `f32` box3d.
|
||||
pub fn to_f32(&self) -> TypedBox3D<f32, Unit> {
|
||||
pub fn to_f32(&self) -> Box3D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` box3d.
|
||||
pub fn to_f64(&self) -> TypedBox3D<f64, Unit> {
|
||||
pub fn to_f64(&self) -> Box3D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -555,7 +562,7 @@ impl<T: NumCast + Copy, Unit> TypedBox3D<T, Unit> {
|
|||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> TypedBox3D<usize, Unit> {
|
||||
pub fn to_usize(&self) -> Box3D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -564,7 +571,7 @@ impl<T: NumCast + Copy, Unit> TypedBox3D<T, Unit> {
|
|||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> TypedBox3D<u32, Unit> {
|
||||
pub fn to_u32(&self) -> Box3D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -573,7 +580,7 @@ impl<T: NumCast + Copy, Unit> TypedBox3D<T, Unit> {
|
|||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> TypedBox3D<i32, Unit> {
|
||||
pub fn to_i32(&self) -> Box3D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -582,31 +589,29 @@ impl<T: NumCast + Copy, Unit> TypedBox3D<T, Unit> {
|
|||
/// When casting from floating point cuboids, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> TypedBox3D<i64, Unit> {
|
||||
pub fn to_i64(&self) -> Box3D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<TypedSize3D<T, U>> for TypedBox3D<T, U>
|
||||
impl<T, U> From<Size3D<T, U>> for Box3D<T, U>
|
||||
where
|
||||
T: Copy + Zero + PartialOrd,
|
||||
{
|
||||
fn from(b: TypedSize3D<T, U>) -> Self {
|
||||
fn from(b: Size3D<T, U>) -> Self {
|
||||
Self::from_size(b)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorthand for `TypedBox3D::new(TypedPoint3D::new(x1, y1, z1), TypedPoint3D::new(x2, y2, z2))`.
|
||||
pub fn box3d<T: Copy, U>(min_x: T, min_y: T, min_z: T, max_x: T, max_y: T, max_z: T) -> TypedBox3D<T, U> {
|
||||
TypedBox3D::new(TypedPoint3D::new(min_x, min_y, min_z), TypedPoint3D::new(max_x, max_y, max_z))
|
||||
/// Shorthand for `Box3D::new(Point3D::new(x1, y1, z1), Point3D::new(x2, y2, z2))`.
|
||||
pub fn box3d<T: Copy, U>(min_x: T, min_y: T, min_z: T, max_x: T, max_y: T, max_z: T) -> Box3D<T, U> {
|
||||
Box3D::new(Point3D::new(min_x, min_y, min_z), Point3D::new(max_x, max_y, max_z))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use vector::vec3;
|
||||
use size::size3;
|
||||
use point::{point3, Point3D};
|
||||
use super::*;
|
||||
use {point3, size3, vec3};
|
||||
use default::{Box3D, Point3D};
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
|
@ -714,7 +719,7 @@ mod tests {
|
|||
let b = Box3D::from_size(size);
|
||||
assert!(b.center() == center);
|
||||
let translation = vec3(10.0, 2.5, 9.5);
|
||||
let b = b.translate(&translation);
|
||||
let b = b.translate(translation);
|
||||
center += translation;
|
||||
assert!(b.center() == center);
|
||||
assert!(b.max.x == 25.0);
|
||||
|
@ -808,7 +813,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_contains() {
|
||||
let b = Box3D::from_points(&[point3(-20.0, -20.0, -20.0), point3(20.0, 20.0, 20.0)]);
|
||||
assert!(b.contains(&point3(-15.3, 10.5, 18.4)));
|
||||
assert!(b.contains(point3(-15.3, 10.5, 18.4)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -7,18 +7,21 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use point::{TypedPoint2D, TypedPoint3D};
|
||||
use vector::{TypedVector2D, TypedVector3D};
|
||||
use point::{Point2D, Point3D};
|
||||
use vector::{Vector2D, Vector3D};
|
||||
|
||||
use num::{One, Zero};
|
||||
|
||||
use core::fmt;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::Div;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
|
||||
/// Homogeneous vector in 3D space.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct HomogeneousVector<T, U> {
|
||||
pub x: T,
|
||||
|
@ -29,6 +32,63 @@ pub struct HomogeneousVector<T, U> {
|
|||
pub _unit: PhantomData<U>,
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for HomogeneousVector<T, U> {}
|
||||
|
||||
impl<T: Clone, U> Clone for HomogeneousVector<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
HomogeneousVector {
|
||||
x: self.x.clone(),
|
||||
y: self.y.clone(),
|
||||
z: self.z.clone(),
|
||||
w: self.w.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T, U> serde::Deserialize<'de> for HomogeneousVector<T, U>
|
||||
where T: serde::Deserialize<'de>
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (x, y, z, w) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(HomogeneousVector { x, y, z, w, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, U> serde::Serialize for HomogeneousVector<T, U>
|
||||
where T: serde::Serialize
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: serde::Serializer
|
||||
{
|
||||
(&self.x, &self.y, &self.z, &self.w).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Eq for HomogeneousVector<T, U> where T: Eq {}
|
||||
|
||||
impl<T, U> PartialEq for HomogeneousVector<T, U>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.x == other.x && self.y == other.y && self.z == other.z && self.w == other.w
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Hash for HomogeneousVector<T, U>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.x.hash(h);
|
||||
self.y.hash(h);
|
||||
self.z.hash(h);
|
||||
self.w.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> HomogeneousVector<T, U> {
|
||||
/// Constructor taking scalar values directly.
|
||||
|
@ -44,9 +104,9 @@ impl<T: Copy + Div<T, Output=T> + Zero + PartialOrd, U> HomogeneousVector<T, U>
|
|||
///
|
||||
/// Returns None if the point is on or behind the W=0 hemisphere.
|
||||
#[inline]
|
||||
pub fn to_point2d(&self) -> Option<TypedPoint2D<T, U>> {
|
||||
pub fn to_point2d(&self) -> Option<Point2D<T, U>> {
|
||||
if self.w > T::zero() {
|
||||
Some(TypedPoint2D::new(self.x / self.w, self.y / self.w))
|
||||
Some(Point2D::new(self.x / self.w, self.y / self.w))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -56,39 +116,39 @@ impl<T: Copy + Div<T, Output=T> + Zero + PartialOrd, U> HomogeneousVector<T, U>
|
|||
///
|
||||
/// Returns None if the point is on or behind the W=0 hemisphere.
|
||||
#[inline]
|
||||
pub fn to_point3d(&self) -> Option<TypedPoint3D<T, U>> {
|
||||
pub fn to_point3d(&self) -> Option<Point3D<T, U>> {
|
||||
if self.w > T::zero() {
|
||||
Some(TypedPoint3D::new(self.x / self.w, self.y / self.w, self.z / self.w))
|
||||
Some(Point3D::new(self.x / self.w, self.y / self.w, self.z / self.w))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> From<TypedVector2D<T, U>> for HomogeneousVector<T, U> {
|
||||
impl<T: Zero, U> From<Vector2D<T, U>> for HomogeneousVector<T, U> {
|
||||
#[inline]
|
||||
fn from(v: TypedVector2D<T, U>) -> Self {
|
||||
fn from(v: Vector2D<T, U>) -> Self {
|
||||
HomogeneousVector::new(v.x, v.y, T::zero(), T::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> From<TypedVector3D<T, U>> for HomogeneousVector<T, U> {
|
||||
impl<T: Zero, U> From<Vector3D<T, U>> for HomogeneousVector<T, U> {
|
||||
#[inline]
|
||||
fn from(v: TypedVector3D<T, U>) -> Self {
|
||||
fn from(v: Vector3D<T, U>) -> Self {
|
||||
HomogeneousVector::new(v.x, v.y, v.z, T::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero + One, U> From<TypedPoint2D<T, U>> for HomogeneousVector<T, U> {
|
||||
impl<T: Zero + One, U> From<Point2D<T, U>> for HomogeneousVector<T, U> {
|
||||
#[inline]
|
||||
fn from(p: TypedPoint2D<T, U>) -> Self {
|
||||
fn from(p: Point2D<T, U>) -> Self {
|
||||
HomogeneousVector::new(p.x, p.y, T::zero(), T::one())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: One, U> From<TypedPoint3D<T, U>> for HomogeneousVector<T, U> {
|
||||
impl<T: One, U> From<Point3D<T, U>> for HomogeneousVector<T, U> {
|
||||
#[inline]
|
||||
fn from(p: TypedPoint3D<T, U>) -> Self {
|
||||
fn from(p: Point3D<T, U>) -> Self {
|
||||
HomogeneousVector::new(p.x, p.y, p.z, T::one())
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +169,7 @@ impl<T: fmt::Display, U> fmt::Display for HomogeneousVector<T, U> {
|
|||
#[cfg(test)]
|
||||
mod homogeneous {
|
||||
use super::HomogeneousVector;
|
||||
use point::{Point2D, Point3D};
|
||||
use default::{Point2D, Point3D};
|
||||
|
||||
#[test]
|
||||
fn roundtrip() {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// except according to those terms.
|
||||
//! A one-dimensional length, tagged with its units.
|
||||
|
||||
use scale::TypedScale;
|
||||
use scale::Scale;
|
||||
use num::Zero;
|
||||
|
||||
use num_traits::{NumCast, Saturating};
|
||||
|
@ -30,10 +30,10 @@ use core::fmt;
|
|||
/// expression that requires a different unit. It may be a type without values, such as an empty
|
||||
/// enum.
|
||||
///
|
||||
/// You can multiply a `Length` by a `scale::TypedScale` to convert it from one unit to
|
||||
/// another. See the [`TypedScale`] docs for an example.
|
||||
/// You can multiply a `Length` by a `scale::Scale` to convert it from one unit to
|
||||
/// another. See the [`Scale`] docs for an example.
|
||||
///
|
||||
/// [`TypedScale`]: struct.TypedScale.html
|
||||
/// [`Scale`]: struct.Scale.html
|
||||
#[repr(C)]
|
||||
pub struct Length<T, Unit>(pub T, #[doc(hidden)] pub PhantomData<Unit>);
|
||||
|
||||
|
@ -141,10 +141,10 @@ impl<U, T: Clone + Saturating> Saturating for Length<T, U> {
|
|||
|
||||
// length / length
|
||||
impl<Src, Dst, T: Clone + Div<T, Output = T>> Div<Length<T, Src>> for Length<T, Dst> {
|
||||
type Output = TypedScale<T, Src, Dst>;
|
||||
type Output = Scale<T, Src, Dst>;
|
||||
#[inline]
|
||||
fn div(self, other: Length<T, Src>) -> TypedScale<T, Src, Dst> {
|
||||
TypedScale::new(self.get() / other.get())
|
||||
fn div(self, other: Length<T, Src>) -> Scale<T, Src, Dst> {
|
||||
Scale::new(self.get() / other.get())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,19 +183,19 @@ impl<T: Copy + Div<T, Output = T>, U> DivAssign<T> for Length<T, U> {
|
|||
}
|
||||
|
||||
// length * scaleFactor
|
||||
impl<Src, Dst, T: Clone + Mul<T, Output = T>> Mul<TypedScale<T, Src, Dst>> for Length<T, Src> {
|
||||
impl<Src, Dst, T: Clone + Mul<T, Output = T>> Mul<Scale<T, Src, Dst>> for Length<T, Src> {
|
||||
type Output = Length<T, Dst>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, Src, Dst>) -> Length<T, Dst> {
|
||||
fn mul(self, scale: Scale<T, Src, Dst>) -> Length<T, Dst> {
|
||||
Length::new(self.get() * scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
// length / scaleFactor
|
||||
impl<Src, Dst, T: Clone + Div<T, Output = T>> Div<TypedScale<T, Src, Dst>> for Length<T, Dst> {
|
||||
impl<Src, Dst, T: Clone + Div<T, Output = T>> Div<Scale<T, Src, Dst>> for Length<T, Dst> {
|
||||
type Output = Length<T, Src>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, Src, Dst>) -> Length<T, Src> {
|
||||
fn div(self, scale: Scale<T, Src, Dst>) -> Length<T, Src> {
|
||||
Length::new(self.get() / scale.get())
|
||||
}
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ mod tests {
|
|||
use num::Zero;
|
||||
|
||||
use num_traits::Saturating;
|
||||
use scale::TypedScale;
|
||||
use scale::Scale;
|
||||
use core::f32::INFINITY;
|
||||
|
||||
enum Inch {}
|
||||
|
@ -379,21 +379,21 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_division_by_length() {
|
||||
// Division results in a TypedScale from denominator units
|
||||
// Division results in a Scale from denominator units
|
||||
// to numerator units.
|
||||
let length: Length<f32, Cm> = Length::new(5.0);
|
||||
let duration: Length<f32, Second> = Length::new(10.0);
|
||||
|
||||
let result = length / duration;
|
||||
|
||||
let expected: TypedScale<f32, Second, Cm> = TypedScale::new(0.5);
|
||||
let expected: Scale<f32, Second, Cm> = Scale::new(0.5);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiplication() {
|
||||
let length_mm: Length<f32, Mm> = Length::new(10.0);
|
||||
let cm_per_mm: TypedScale<f32, Mm, Cm> = TypedScale::new(0.1);
|
||||
let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
|
||||
|
||||
let result = length_mm * cm_per_mm;
|
||||
|
||||
|
@ -424,7 +424,7 @@ mod tests {
|
|||
#[test]
|
||||
fn test_division_by_scalefactor() {
|
||||
let length: Length<f32, Cm> = Length::new(5.0);
|
||||
let cm_per_second: TypedScale<f32, Second, Cm> = TypedScale::new(10.0);
|
||||
let cm_per_second: Scale<f32, Second, Cm> = Scale::new(10.0);
|
||||
|
||||
let result = length / cm_per_second;
|
||||
|
||||
|
@ -514,7 +514,7 @@ mod tests {
|
|||
|
||||
let result = length / length_zero;
|
||||
|
||||
let expected: TypedScale<f32, Cm, Cm> = TypedScale::new(INFINITY);
|
||||
let expected: Scale<f32, Cm, Cm> = Scale::new(INFINITY);
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![cfg_attr(feature = "unstable", feature(fn_must_use))]
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
|
||||
//! A collection of strongly typed math tools for computer graphics with an inclination
|
||||
|
@ -19,42 +18,26 @@
|
|||
//! a screen-space position by a world-space vector and this can be expressed using
|
||||
//! the generic Unit parameter.
|
||||
//!
|
||||
//! This unit system is not mandatory and all Typed* structures have an alias
|
||||
//! This unit system is not mandatory and all * structures have an alias
|
||||
//! with the default unit: `UnknownUnit`.
|
||||
//! for example ```Point2D<T>``` is equivalent to ```TypedPoint2D<T, UnknownUnit>```.
|
||||
//! for example ```Point2D<T>``` is equivalent to ```Point2D<T, UnknownUnit>```.
|
||||
//! Client code typically creates a set of aliases for each type and doesn't need
|
||||
//! to deal with the specifics of typed units further. For example:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use euclid::*;
|
||||
//! pub struct ScreenSpace;
|
||||
//! pub type ScreenPoint = TypedPoint2D<f32, ScreenSpace>;
|
||||
//! pub type ScreenSize = TypedSize2D<f32, ScreenSpace>;
|
||||
//! pub type ScreenPoint = Point2D<f32, ScreenSpace>;
|
||||
//! pub type ScreenSize = Size2D<f32, ScreenSpace>;
|
||||
//! pub struct WorldSpace;
|
||||
//! pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
|
||||
//! pub type ProjectionMatrix = TypedTransform3D<f32, WorldSpace, ScreenSpace>;
|
||||
//! pub type WorldPoint = Point3D<f32, WorldSpace>;
|
||||
//! pub type ProjectionMatrix = Transform3D<f32, WorldSpace, ScreenSpace>;
|
||||
//! // etc...
|
||||
//! ```
|
||||
//!
|
||||
//! All euclid types are marked `#[repr(C)]` in order to facilitate exposing them to
|
||||
//! foreign function interfaces (provided the underlying scalar type is also `repr(C)`).
|
||||
//!
|
||||
//! Components are accessed in their scalar form by default for convenience, and most
|
||||
//! types additionally implement strongly typed accessors which return typed ```Length``` wrappers.
|
||||
//! For example:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # use euclid::*;
|
||||
//! # pub struct WorldSpace;
|
||||
//! # pub type WorldPoint = TypedPoint3D<f32, WorldSpace>;
|
||||
//! let p = WorldPoint::new(0.0, 1.0, 1.0);
|
||||
//! // p.x is an f32.
|
||||
//! println!("p.x = {:?} ", p.x);
|
||||
//! // p.x is a Length<f32, WorldSpace>.
|
||||
//! println!("p.x_typed() = {:?} ", p.x_typed());
|
||||
//! // Length::get returns the scalar value (f32).
|
||||
//! assert_eq!(p.x, p.x_typed().get());
|
||||
//! ```
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[macro_use]
|
||||
|
@ -62,31 +45,28 @@ extern crate serde;
|
|||
|
||||
#[cfg(feature = "mint")]
|
||||
pub extern crate mint;
|
||||
#[macro_use]
|
||||
extern crate euclid_macros;
|
||||
extern crate num_traits;
|
||||
#[cfg(test)]
|
||||
extern crate rand;
|
||||
#[cfg(test)]
|
||||
use std as core;
|
||||
|
||||
pub use box2d::{TypedBox2D, Box2D};
|
||||
pub use box2d::Box2D;
|
||||
pub use length::Length;
|
||||
pub use scale::TypedScale;
|
||||
pub use transform2d::{Transform2D, TypedTransform2D};
|
||||
pub use transform3d::{Transform3D, TypedTransform3D};
|
||||
pub use point::{Point2D, Point3D, TypedPoint2D, TypedPoint3D, point2, point3};
|
||||
pub use vector::{TypedVector2D, TypedVector3D, Vector2D, Vector3D, vec2, vec3};
|
||||
pub use scale::Scale;
|
||||
pub use transform2d::Transform2D;
|
||||
pub use transform3d::Transform3D;
|
||||
pub use point::{Point2D, Point3D, point2, point3};
|
||||
pub use vector::{Vector2D, Vector3D, vec2, vec3};
|
||||
pub use vector::{BoolVector2D, BoolVector3D, bvec2, bvec3};
|
||||
pub use homogen::HomogeneousVector;
|
||||
pub use nonempty::NonEmpty;
|
||||
|
||||
pub use rect::{rect, Rect, TypedRect};
|
||||
pub use rigid::{RigidTransform3D, TypedRigidTransform3D};
|
||||
pub use box3d::{box3d, Box3D, TypedBox3D};
|
||||
pub use translation::{TypedTranslation2D, TypedTranslation3D};
|
||||
pub use rotation::{Angle, Rotation2D, Rotation3D, TypedRotation2D, TypedRotation3D};
|
||||
pub use side_offsets::{SideOffsets2D, TypedSideOffsets2D};
|
||||
pub use size::{Size2D, TypedSize2D, size2};
|
||||
pub use rect::{rect, Rect};
|
||||
pub use rigid::{RigidTransform3D};
|
||||
pub use box3d::{box3d, Box3D};
|
||||
pub use translation::{Translation2D, Translation3D};
|
||||
pub use rotation::{Angle, Rotation2D, Rotation3D};
|
||||
pub use side_offsets::SideOffsets2D;
|
||||
pub use size::{Size2D, Size3D, size2, size3};
|
||||
pub use trig::Trig;
|
||||
|
||||
#[macro_use]
|
||||
|
@ -111,31 +91,30 @@ mod translation;
|
|||
mod trig;
|
||||
mod vector;
|
||||
mod box3d;
|
||||
mod nonempty;
|
||||
|
||||
/// The default unit.
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct UnknownUnit;
|
||||
|
||||
/// Temporary alias to facilitate the transition to the new naming scheme
|
||||
#[deprecated]
|
||||
pub type Matrix2D<T> = Transform2D<T>;
|
||||
|
||||
/// Temporary alias to facilitate the transition to the new naming scheme
|
||||
#[deprecated]
|
||||
pub type TypedMatrix2D<T, Src, Dst> = TypedTransform2D<T, Src, Dst>;
|
||||
|
||||
/// Temporary alias to facilitate the transition to the new naming scheme
|
||||
#[deprecated]
|
||||
pub type Matrix4D<T> = Transform3D<T>;
|
||||
|
||||
/// Temporary alias to facilitate the transition to the new naming scheme
|
||||
#[deprecated]
|
||||
pub type TypedMatrix4D<T, Src, Dst> = TypedTransform3D<T, Src, Dst>;
|
||||
|
||||
/// Temporary alias to facilitate the transition to the new naming scheme
|
||||
#[deprecated]
|
||||
pub type ScaleFactor<T, Src, Dst> = TypedScale<T, Src, Dst>;
|
||||
|
||||
/// Temporary alias to facilitate the transition to the new naming scheme
|
||||
#[deprecated]
|
||||
pub use Angle as Radians;
|
||||
pub mod default {
|
||||
use super::UnknownUnit;
|
||||
pub type Point2D<T> = super::Point2D<T, UnknownUnit>;
|
||||
pub type Point3D<T> = super::Point3D<T, UnknownUnit>;
|
||||
pub type Vector2D<T> = super::Vector2D<T, UnknownUnit>;
|
||||
pub type Vector3D<T> = super::Vector3D<T, UnknownUnit>;
|
||||
pub type HomogeneousVector<T> = super::HomogeneousVector<T, UnknownUnit>;
|
||||
pub type Size2D<T> = super::Size2D<T, UnknownUnit>;
|
||||
pub type Size3D<T> = super::Size3D<T, UnknownUnit>;
|
||||
pub type Rect<T> = super::Rect<T, UnknownUnit>;
|
||||
pub type Box2D<T> = super::Box2D<T, UnknownUnit>;
|
||||
pub type Box3D<T> = super::Box3D<T, UnknownUnit>;
|
||||
pub type SideOffsets2D<T> = super::SideOffsets2D<T, UnknownUnit>;
|
||||
pub type Transform2D<T> = super::Transform2D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Transform3D<T> = super::Transform3D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Rotation2D<T> = super::Rotation2D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Rotation3D<T> = super::Rotation3D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Translation3D<T> = super::Translation3D<T, UnknownUnit, UnknownUnit>;
|
||||
pub type Scale<T> = super::Scale<T, UnknownUnit, UnknownUnit>;
|
||||
pub type RigidTransform3D<T> = super::RigidTransform3D<T, UnknownUnit, UnknownUnit>;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,259 @@
|
|||
use {Rect, Box2D, Box3D, Vector2D, Vector3D, size2, point2, point3};
|
||||
use approxord::{min, max};
|
||||
use num::Zero;
|
||||
use core::ops::Deref;
|
||||
use core::ops::{Add, Sub};
|
||||
use core::cmp::{PartialEq};
|
||||
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(transparent))]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct NonEmpty<T>(pub(crate) T);
|
||||
|
||||
impl<T> Deref for NonEmpty<T> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> NonEmpty<T> {
|
||||
#[inline]
|
||||
pub fn get(&self) -> &T {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> NonEmpty<Rect<T, U>>
|
||||
where
|
||||
T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &NonEmpty<Rect<T, U>>) -> NonEmpty<Rect<T, U>> {
|
||||
let origin = point2(
|
||||
min(self.min_x(), other.min_x()),
|
||||
min(self.min_y(), other.min_y()),
|
||||
);
|
||||
|
||||
let lower_right_x = max(self.max_x(), other.max_x());
|
||||
let lower_right_y = max(self.max_y(), other.max_y());
|
||||
|
||||
NonEmpty(Rect {
|
||||
origin,
|
||||
size: size2(
|
||||
lower_right_x - origin.x,
|
||||
lower_right_y - origin.y,
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains_rect(&self, rect: &Self) -> bool {
|
||||
self.min_x() <= rect.min_x()
|
||||
&& rect.max_x() <= self.max_x()
|
||||
&& self.min_y() <= rect.min_y()
|
||||
&& rect.max_y() <= self.max_y()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn translate(&self, by: Vector2D<T, U>) -> Self {
|
||||
NonEmpty(self.0.translate(by))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> NonEmpty<Box2D<T, U>>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &NonEmpty<Box2D<T, U>>) -> NonEmpty<Box2D<T, U>> {
|
||||
NonEmpty(Box2D {
|
||||
min: point2(
|
||||
min(self.min.x, other.min.x),
|
||||
min(self.min.y, other.min.y),
|
||||
),
|
||||
max: point2(
|
||||
max(self.max.x, other.max.x),
|
||||
max(self.max.y, other.max.y),
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true if this box contains the interior of the other box.
|
||||
#[inline]
|
||||
pub fn contains_box(&self, other: &Self) -> bool {
|
||||
self.min.x <= other.min.x
|
||||
&& other.max.x <= self.max.x
|
||||
&& self.min.y <= other.min.y
|
||||
&& other.max.y <= self.max.y
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> NonEmpty<Box2D<T, U>>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn translate(&self, by: Vector2D<T, U>) -> Self {
|
||||
NonEmpty(self.0.translate(by))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> NonEmpty<Box3D<T, U>>
|
||||
where
|
||||
T: Copy + PartialOrd,
|
||||
{
|
||||
#[inline]
|
||||
pub fn union(&self, other: &NonEmpty<Box3D<T, U>>) -> NonEmpty<Box3D<T, U>> {
|
||||
NonEmpty(Box3D {
|
||||
min: point3(
|
||||
min(self.min.x, other.min.x),
|
||||
min(self.min.y, other.min.y),
|
||||
min(self.min.z, other.min.z),
|
||||
),
|
||||
max: point3(
|
||||
max(self.max.x, other.max.x),
|
||||
max(self.max.y, other.max.y),
|
||||
max(self.max.z, other.max.z),
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns true if this box contains the interior of the other box.
|
||||
#[inline]
|
||||
pub fn contains_box(&self, other: &Self) -> bool {
|
||||
self.min.x <= other.min.x
|
||||
&& other.max.x <= self.max.x
|
||||
&& self.min.y <= other.min.y
|
||||
&& other.max.y <= self.max.y
|
||||
&& self.min.z <= other.min.z
|
||||
&& other.max.z <= self.max.z
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> NonEmpty<Box3D<T, U>>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn translate(&self, by: Vector3D<T, U>) -> Self {
|
||||
NonEmpty(self.0.translate(by))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_nonempty() {
|
||||
use default;
|
||||
|
||||
// zero-width
|
||||
let box1: default::Box2D<i32> = Box2D {
|
||||
min: point2(-10, 2),
|
||||
max: point2(-10, 12),
|
||||
};
|
||||
// zero-height
|
||||
let box2: default::Box2D<i32> = Box2D {
|
||||
min: point2(0, 11),
|
||||
max: point2(2, 11),
|
||||
};
|
||||
// negative width
|
||||
let box3: default::Box2D<i32> = Box2D {
|
||||
min: point2(1, 11),
|
||||
max: point2(0, 12),
|
||||
};
|
||||
// negative height
|
||||
let box4: default::Box2D<i32> = Box2D {
|
||||
min: point2(0, 11),
|
||||
max: point2(5, 10),
|
||||
};
|
||||
|
||||
assert!(box1.to_non_empty().is_none());
|
||||
assert!(box2.to_non_empty().is_none());
|
||||
assert!(box3.to_non_empty().is_none());
|
||||
assert!(box4.to_non_empty().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nonempty_union() {
|
||||
use default;
|
||||
|
||||
let box1: default::Box2D<i32> = Box2D {
|
||||
min: point2(-10, 2),
|
||||
max: point2(15, 12),
|
||||
};
|
||||
let box2 = Box2D {
|
||||
min: point2(-2, -5),
|
||||
max: point2(10, 5),
|
||||
};
|
||||
|
||||
assert_eq!(box1.union(&box2), *box1.to_non_empty().unwrap().union(&box2.to_non_empty().unwrap()));
|
||||
|
||||
let box3: default::Box3D<i32> = Box3D {
|
||||
min: point3(1, -10, 2),
|
||||
max: point3(6, 15, 12),
|
||||
};
|
||||
let box4 = Box3D {
|
||||
min: point3(0, -2, -5),
|
||||
max: point3(7, 10, 5),
|
||||
};
|
||||
|
||||
assert_eq!(box3.union(&box4), *box3.to_non_empty().unwrap().union(&box4.to_non_empty().unwrap()));
|
||||
|
||||
let rect1: default::Rect<i32> = Rect {
|
||||
origin: point2(1, 2),
|
||||
size: size2(3, 4),
|
||||
};
|
||||
let rect2 = Rect {
|
||||
origin: point2(-1, 5),
|
||||
size: size2(1, 10),
|
||||
};
|
||||
|
||||
assert_eq!(rect1.union(&rect2), *rect1.to_non_empty().unwrap().union(&rect2.to_non_empty().unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nonempty_contains() {
|
||||
use default;
|
||||
use {vec2, vec3};
|
||||
|
||||
let r: NonEmpty<default::Rect<i32>> = Rect {
|
||||
origin: point2(-20, 15),
|
||||
size: size2(100, 200),
|
||||
}.to_non_empty().unwrap();
|
||||
|
||||
assert!(r.contains_rect(&r));
|
||||
assert!(!r.contains_rect(&r.translate(vec2(1, 0))));
|
||||
assert!(!r.contains_rect(&r.translate(vec2(-1, 0))));
|
||||
assert!(!r.contains_rect(&r.translate(vec2(0, 1))));
|
||||
assert!(!r.contains_rect(&r.translate(vec2(0, -1))));
|
||||
|
||||
let b: NonEmpty<default::Box2D<i32>> = Box2D {
|
||||
min: point2(-10, 5),
|
||||
max: point2(30, 100),
|
||||
}.to_non_empty().unwrap();
|
||||
|
||||
assert!(b.contains_box(&b));
|
||||
assert!(!b.contains_box(&b.translate(vec2(1, 0))));
|
||||
assert!(!b.contains_box(&b.translate(vec2(-1, 0))));
|
||||
assert!(!b.contains_box(&b.translate(vec2(0, 1))));
|
||||
assert!(!b.contains_box(&b.translate(vec2(0, -1))));
|
||||
|
||||
let b: NonEmpty<default::Box3D<i32>> = Box3D {
|
||||
min: point3(-1, -10, 5),
|
||||
max: point3(10, 30, 100),
|
||||
}.to_non_empty().unwrap();
|
||||
|
||||
assert!(b.contains_box(&b));
|
||||
assert!(!b.contains_box(&b.translate(vec3(0, 1, 0))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(0, -1, 0))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(0, 0, 1))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(0, 0, -1))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(1, 1, 0))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(1, -1, 0))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(1, 0, 1))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(1, 0, -1))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(-1, 1, 0))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(-1, -1, 0))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(-1, 0, 1))));
|
||||
assert!(!b.contains_box(&b.translate(vec3(-1, 0, -1))));
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,19 +8,19 @@
|
|||
// except according to those terms.
|
||||
|
||||
use super::UnknownUnit;
|
||||
use length::Length;
|
||||
use scale::TypedScale;
|
||||
use scale::Scale;
|
||||
use num::*;
|
||||
use box2d::TypedBox2D;
|
||||
use point::TypedPoint2D;
|
||||
use vector::TypedVector2D;
|
||||
use side_offsets::TypedSideOffsets2D;
|
||||
use size::TypedSize2D;
|
||||
use box2d::Box2D;
|
||||
use point::Point2D;
|
||||
use vector::Vector2D;
|
||||
use side_offsets::SideOffsets2D;
|
||||
use size::Size2D;
|
||||
use approxord::{min, max};
|
||||
use nonempty::NonEmpty;
|
||||
|
||||
use num_traits::NumCast;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use core::borrow::Borrow;
|
||||
use core::cmp::PartialOrd;
|
||||
|
@ -31,100 +31,78 @@ use core::ops::{Add, Div, Mul, Sub, Range};
|
|||
|
||||
/// A 2d Rectangle optionally tagged with a unit.
|
||||
#[repr(C)]
|
||||
pub struct TypedRect<T, U = UnknownUnit> {
|
||||
pub origin: TypedPoint2D<T, U>,
|
||||
pub size: TypedSize2D<T, U>,
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
|
||||
pub struct Rect<T, U> {
|
||||
pub origin: Point2D<T, U>,
|
||||
pub size: Size2D<T, U>,
|
||||
}
|
||||
|
||||
/// The default rectangle type with no unit.
|
||||
pub type Rect<T> = TypedRect<T, UnknownUnit>;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T: Copy + Deserialize<'de>, U> Deserialize<'de> for TypedRect<T, U> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let (origin, size) = try!(Deserialize::deserialize(deserializer));
|
||||
Ok(TypedRect::new(origin, size))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T: Serialize, U> Serialize for TypedRect<T, U> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
(&self.origin, &self.size).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Hash, U> Hash for TypedRect<T, U> {
|
||||
impl<T: Hash, U> Hash for Rect<T, U> {
|
||||
fn hash<H: Hasher>(&self, h: &mut H) {
|
||||
self.origin.hash(h);
|
||||
self.size.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Copy for TypedRect<T, U> {}
|
||||
impl<T: Copy, U> Copy for Rect<T, U> {}
|
||||
|
||||
impl<T: Copy, U> Clone for TypedRect<T, U> {
|
||||
impl<T: Copy, U> Clone for Rect<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PartialEq, U> PartialEq<TypedRect<T, U>> for TypedRect<T, U> {
|
||||
impl<T: PartialEq, U> PartialEq<Rect<T, U>> for Rect<T, U> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.origin.eq(&other.origin) && self.size.eq(&other.size)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Eq, U> Eq for TypedRect<T, U> {}
|
||||
impl<T: Eq, U> Eq for Rect<T, U> {}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedRect<T, U> {
|
||||
impl<T: fmt::Debug, U> fmt::Debug for Rect<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "TypedRect({:?} at {:?})", self.size, self.origin)
|
||||
write!(f, "Rect({:?} at {:?})", self.size, self.origin)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for TypedRect<T, U> {
|
||||
impl<T: fmt::Display, U> fmt::Display for Rect<T, U> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "Rect({} at {})", self.size, self.origin)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedRect<T, U> {
|
||||
impl<T: Default, U> Default for Rect<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedRect::new(Default::default(), Default::default())
|
||||
Rect::new(Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedRect<T, U> {
|
||||
impl<T, U> Rect<T, U> {
|
||||
/// Constructor.
|
||||
pub fn new(origin: TypedPoint2D<T, U>, size: TypedSize2D<T, U>) -> Self {
|
||||
TypedRect {
|
||||
pub fn new(origin: Point2D<T, U>, size: Size2D<T, U>) -> Self {
|
||||
Rect {
|
||||
origin,
|
||||
size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedRect<T, U>
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + Zero
|
||||
{
|
||||
/// Creates a rect of the given size, at offset zero.
|
||||
pub fn from_size(size: TypedSize2D<T, U>) -> Self {
|
||||
TypedRect {
|
||||
origin: TypedPoint2D::zero(),
|
||||
pub fn from_size(size: Size2D<T, U>) -> Self {
|
||||
Rect {
|
||||
origin: Point2D::zero(),
|
||||
size,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedRect<T, U>
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + Clone + Zero + PartialOrd + PartialEq + Add<T, Output = T> + Sub<T, Output = T>,
|
||||
{
|
||||
|
@ -136,6 +114,16 @@ where
|
|||
&& other.origin.y < self.origin.y + self.size.height
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn min(&self) -> Point2D<T, U> {
|
||||
self.origin
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn max(&self) -> Point2D<T, U> {
|
||||
self.origin + self.size
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn max_x(&self) -> T {
|
||||
self.origin.x + self.size.width
|
||||
|
@ -156,26 +144,6 @@ where
|
|||
self.origin.y
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn max_x_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.max_x())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn min_x_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.min_x())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn max_y_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.max_y())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn min_y_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.min_y())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn x_range(&self) -> Range<T> {
|
||||
self.min_x()..self.max_x()
|
||||
|
@ -192,31 +160,31 @@ where
|
|||
return None;
|
||||
}
|
||||
|
||||
let upper_left = TypedPoint2D::new(
|
||||
let upper_left = Point2D::new(
|
||||
max(self.min_x(), other.min_x()),
|
||||
max(self.min_y(), other.min_y()),
|
||||
);
|
||||
let lower_right_x = min(self.max_x(), other.max_x());
|
||||
let lower_right_y = min(self.max_y(), other.max_y());
|
||||
|
||||
Some(TypedRect::new(
|
||||
Some(Rect::new(
|
||||
upper_left,
|
||||
TypedSize2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y),
|
||||
Size2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y),
|
||||
))
|
||||
}
|
||||
|
||||
/// Returns the same rectangle, translated by a vector.
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn translate(&self, by: &TypedVector2D<T, U>) -> Self {
|
||||
Self::new(self.origin + *by, self.size)
|
||||
#[must_use]
|
||||
pub fn translate(&self, by: Vector2D<T, U>) -> Self {
|
||||
Self::new(self.origin + by, self.size)
|
||||
}
|
||||
|
||||
/// Returns true if this rectangle contains the point. Points are considered
|
||||
/// in the rectangle if they are on the left or top edge, but outside if they
|
||||
/// are on the right or bottom edge.
|
||||
#[inline]
|
||||
pub fn contains(&self, other: &TypedPoint2D<T, U>) -> bool {
|
||||
pub fn contains(&self, other: Point2D<T, U>) -> bool {
|
||||
self.origin.x <= other.x && other.x < self.origin.x + self.size.width
|
||||
&& self.origin.y <= other.y && other.y < self.origin.y + self.size.height
|
||||
}
|
||||
|
@ -226,17 +194,17 @@ where
|
|||
/// nonempty but this rectangle is empty.
|
||||
#[inline]
|
||||
pub fn contains_rect(&self, rect: &Self) -> bool {
|
||||
rect.is_empty()
|
||||
rect.is_empty_or_negative()
|
||||
|| (self.min_x() <= rect.min_x() && rect.max_x() <= self.max_x()
|
||||
&& self.min_y() <= rect.min_y() && rect.max_y() <= self.max_y())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn inflate(&self, width: T, height: T) -> Self {
|
||||
TypedRect::new(
|
||||
TypedPoint2D::new(self.origin.x - width, self.origin.y - height),
|
||||
TypedSize2D::new(
|
||||
Rect::new(
|
||||
Point2D::new(self.origin.x - width, self.origin.y - height),
|
||||
Size2D::new(
|
||||
self.size.width + width + width,
|
||||
self.size.height + height + height,
|
||||
),
|
||||
|
@ -244,51 +212,25 @@ where
|
|||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn inflate_typed(&self, width: Length<T, U>, height: Length<T, U>) -> Self {
|
||||
self.inflate(width.get(), height.get())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn top_right(&self) -> TypedPoint2D<T, U> {
|
||||
TypedPoint2D::new(self.max_x(), self.origin.y)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bottom_left(&self) -> TypedPoint2D<T, U> {
|
||||
TypedPoint2D::new(self.origin.x, self.max_y())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn bottom_right(&self) -> TypedPoint2D<T, U> {
|
||||
TypedPoint2D::new(self.max_x(), self.max_y())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_box2d(&self) -> TypedBox2D<T, U> {
|
||||
TypedBox2D {
|
||||
min: self.origin,
|
||||
max: self.bottom_right(),
|
||||
pub fn to_box2d(&self) -> Box2D<T, U> {
|
||||
Box2D {
|
||||
min: self.min(),
|
||||
max: self.max(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn translate_by_size(&self, size: &TypedSize2D<T, U>) -> Self {
|
||||
self.translate(&size.to_vector())
|
||||
}
|
||||
|
||||
/// Calculate the size and position of an inner rectangle.
|
||||
///
|
||||
/// Subtracts the side offsets from all sides. The horizontal and vertical
|
||||
/// offsets must not be larger than the original side length.
|
||||
pub fn inner_rect(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
|
||||
let rect = TypedRect::new(
|
||||
TypedPoint2D::new(
|
||||
/// This method assumes y oriented downward.
|
||||
pub fn inner_rect(&self, offsets: SideOffsets2D<T, U>) -> Self {
|
||||
let rect = Rect::new(
|
||||
Point2D::new(
|
||||
self.origin.x + offsets.left,
|
||||
self.origin.y + offsets.top
|
||||
),
|
||||
TypedSize2D::new(
|
||||
Size2D::new(
|
||||
self.size.width - offsets.horizontal(),
|
||||
self.size.height - offsets.vertical()
|
||||
)
|
||||
|
@ -301,13 +243,14 @@ where
|
|||
/// Calculate the size and position of an outer rectangle.
|
||||
///
|
||||
/// Add the offsets to all sides. The expanded rectangle is returned.
|
||||
pub fn outer_rect(&self, offsets: TypedSideOffsets2D<T, U>) -> Self {
|
||||
TypedRect::new(
|
||||
TypedPoint2D::new(
|
||||
/// This method assumes y oriented downward.
|
||||
pub fn outer_rect(&self, offsets: SideOffsets2D<T, U>) -> Self {
|
||||
Rect::new(
|
||||
Point2D::new(
|
||||
self.origin.x - offsets.left,
|
||||
self.origin.y - offsets.top
|
||||
),
|
||||
TypedSize2D::new(
|
||||
Size2D::new(
|
||||
self.size.width + offsets.horizontal(),
|
||||
self.size.height + offsets.vertical()
|
||||
)
|
||||
|
@ -326,13 +269,13 @@ where
|
|||
pub fn from_points<I>(points: I) -> Self
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: Borrow<TypedPoint2D<T, U>>,
|
||||
I::Item: Borrow<Point2D<T, U>>,
|
||||
{
|
||||
let mut points = points.into_iter();
|
||||
|
||||
let (mut min_x, mut min_y) = match points.next() {
|
||||
Some(first) => (first.borrow().x, first.borrow().y),
|
||||
None => return TypedRect::zero(),
|
||||
None => return Rect::zero(),
|
||||
};
|
||||
|
||||
let (mut max_x, mut max_y) = (min_x, min_y);
|
||||
|
@ -351,14 +294,14 @@ where
|
|||
max_y = p.y
|
||||
}
|
||||
}
|
||||
TypedRect::new(
|
||||
TypedPoint2D::new(min_x, min_y),
|
||||
TypedSize2D::new(max_x - min_x, max_y - min_y),
|
||||
Rect::new(
|
||||
Point2D::new(min_x, min_y),
|
||||
Size2D::new(max_x - min_x, max_y - min_y),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedRect<T, U>
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
|
@ -374,17 +317,17 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedRect<T, U>
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Div<Output = T>,
|
||||
{
|
||||
pub fn center(&self) -> TypedPoint2D<T, U> {
|
||||
pub fn center(&self) -> Point2D<T, U> {
|
||||
let two = T::one() + T::one();
|
||||
self.origin + self.size.to_vector() / two
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedRect<T, U>
|
||||
impl<T, U> Rect<T, U>
|
||||
where
|
||||
T: Copy + Clone + PartialOrd + Add<T, Output = T> + Sub<T, Output = T> + Zero,
|
||||
{
|
||||
|
@ -397,7 +340,7 @@ where
|
|||
return *self;
|
||||
}
|
||||
|
||||
let upper_left = TypedPoint2D::new(
|
||||
let upper_left = Point2D::new(
|
||||
min(self.min_x(), other.min_x()),
|
||||
min(self.min_y(), other.min_y()),
|
||||
);
|
||||
|
@ -405,37 +348,37 @@ where
|
|||
let lower_right_x = max(self.max_x(), other.max_x());
|
||||
let lower_right_y = max(self.max_y(), other.max_y());
|
||||
|
||||
TypedRect::new(
|
||||
Rect::new(
|
||||
upper_left,
|
||||
TypedSize2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y),
|
||||
Size2D::new(lower_right_x - upper_left.x, lower_right_y - upper_left.y),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedRect<T, U> {
|
||||
impl<T, U> Rect<T, U> {
|
||||
#[inline]
|
||||
pub fn scale<S: Copy>(&self, x: S, y: S) -> Self
|
||||
where
|
||||
T: Copy + Clone + Mul<S, Output = T>,
|
||||
{
|
||||
TypedRect::new(
|
||||
TypedPoint2D::new(self.origin.x * x, self.origin.y * y),
|
||||
TypedSize2D::new(self.size.width * x, self.size.height * y),
|
||||
Rect::new(
|
||||
Point2D::new(self.origin.x * x, self.origin.y * y),
|
||||
Size2D::new(self.size.width * x, self.size.height * y),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Clone + Mul<T, Output = T>, U> TypedRect<T, U> {
|
||||
impl<T: Copy + Clone + Mul<T, Output = T>, U> Rect<T, U> {
|
||||
#[inline]
|
||||
pub fn area(&self) -> T {
|
||||
self.size.area()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + PartialEq + Zero, U> TypedRect<T, U> {
|
||||
impl<T: Copy + PartialEq + Zero, U> Rect<T, U> {
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
TypedRect::new(TypedPoint2D::origin(), TypedSize2D::zero())
|
||||
Rect::new(Point2D::origin(), Size2D::zero())
|
||||
}
|
||||
|
||||
/// Returns true if the size is zero, regardless of the origin's value.
|
||||
|
@ -444,61 +387,80 @@ impl<T: Copy + PartialEq + Zero, U> TypedRect<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedRect<T, U> {
|
||||
impl<T: Copy + Zero + PartialOrd, U> Rect<T, U> {
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
self.size.is_empty_or_negative()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_non_empty(&self) -> Option<NonEmpty<Self>> {
|
||||
if self.is_empty_or_negative() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(NonEmpty(*self))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for Rect<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
TypedRect::new(self.origin * scale, self.size * scale)
|
||||
Rect::new(self.origin * scale, self.size * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedRect<T, U> {
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for Rect<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
TypedRect::new(self.origin / scale, self.size / scale)
|
||||
Rect::new(self.origin / scale, self.size / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedRect<T, U1> {
|
||||
type Output = TypedRect<T, U2>;
|
||||
impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<Scale<T, U1, U2>> for Rect<T, U1> {
|
||||
type Output = Rect<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedRect<T, U2> {
|
||||
TypedRect::new(self.origin * scale, self.size * scale)
|
||||
fn mul(self, scale: Scale<T, U1, U2>) -> Rect<T, U2> {
|
||||
Rect::new(self.origin * scale, self.size * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedRect<T, U2> {
|
||||
type Output = TypedRect<T, U1>;
|
||||
impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Rect<T, U2> {
|
||||
type Output = Rect<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedRect<T, U1> {
|
||||
TypedRect::new(self.origin / scale, self.size / scale)
|
||||
fn div(self, scale: Scale<T, U1, U2>) -> Rect<T, U1> {
|
||||
Rect::new(self.origin / scale, self.size / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Unit> TypedRect<T, Unit> {
|
||||
impl<T: Copy, Unit> Rect<T, Unit> {
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Rect<T> {
|
||||
TypedRect::new(self.origin.to_untyped(), self.size.to_untyped())
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Rect<T, UnknownUnit> {
|
||||
Rect::new(self.origin.to_untyped(), self.size.to_untyped())
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(r: &Rect<T>) -> TypedRect<T, Unit> {
|
||||
TypedRect::new(
|
||||
TypedPoint2D::from_untyped(&r.origin),
|
||||
TypedSize2D::from_untyped(&r.size),
|
||||
#[inline]
|
||||
pub fn from_untyped(r: &Rect<T, UnknownUnit>) -> Rect<T, Unit> {
|
||||
Rect::new(
|
||||
Point2D::from_untyped(r.origin),
|
||||
Size2D::from_untyped(r.size),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T0: NumCast + Copy, Unit> TypedRect<T0, Unit> {
|
||||
impl<T0: NumCast + Copy, Unit> Rect<T0, Unit> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> TypedRect<T1, Unit> {
|
||||
TypedRect::new(
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Rect<T1, Unit> {
|
||||
Rect::new(
|
||||
self.origin.cast(),
|
||||
self.size.cast(),
|
||||
)
|
||||
|
@ -509,15 +471,15 @@ impl<T0: NumCast + Copy, Unit> TypedRect<T0, Unit> {
|
|||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using round(), round_in or round_out() before casting.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedRect<T1, Unit>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Rect<T1, Unit>> {
|
||||
match (self.origin.try_cast(), self.size.try_cast()) {
|
||||
(Some(origin), Some(size)) => Some(TypedRect::new(origin, size)),
|
||||
(Some(origin), Some(size)) => Some(Rect::new(origin, size)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> TypedRect<T, U> {
|
||||
impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> Rect<T, U> {
|
||||
/// Return a rectangle with edges rounded to integer coordinates, such that
|
||||
/// the returned rectangle has the same set of pixel centers as the original
|
||||
/// one.
|
||||
|
@ -527,41 +489,41 @@ impl<T: Floor + Ceil + Round + Add<T, Output = T> + Sub<T, Output = T>, U> Typed
|
|||
/// avoid pixel rounding errors.
|
||||
/// Note that this is *not* rounding to nearest integer if the values are negative.
|
||||
/// They are always rounding as floor(n + 0.5).
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round(&self) -> Self {
|
||||
let origin = self.origin.round();
|
||||
let size = self.origin.add_size(&self.size).round() - origin;
|
||||
TypedRect::new(origin, TypedSize2D::new(size.x, size.y))
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
|
||||
/// Return a rectangle with edges rounded to integer coordinates, such that
|
||||
/// the original rectangle contains the resulting rectangle.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round_in(&self) -> Self {
|
||||
let origin = self.origin.ceil();
|
||||
let size = self.origin.add_size(&self.size).floor() - origin;
|
||||
TypedRect::new(origin, TypedSize2D::new(size.x, size.y))
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
|
||||
/// Return a rectangle with edges rounded to integer coordinates, such that
|
||||
/// the original rectangle is contained in the resulting rectangle.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn round_out(&self) -> Self {
|
||||
let origin = self.origin.floor();
|
||||
let size = self.origin.add_size(&self.size).ceil() - origin;
|
||||
TypedRect::new(origin, TypedSize2D::new(size.x, size.y))
|
||||
Rect::new(origin, Size2D::new(size.x, size.y))
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience functions for common casts
|
||||
impl<T: NumCast + Copy, Unit> TypedRect<T, Unit> {
|
||||
impl<T: NumCast + Copy, Unit> Rect<T, Unit> {
|
||||
/// Cast into an `f32` rectangle.
|
||||
pub fn to_f32(&self) -> TypedRect<f32, Unit> {
|
||||
pub fn to_f32(&self) -> Rect<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` rectangle.
|
||||
pub fn to_f64(&self) -> TypedRect<f64, Unit> {
|
||||
pub fn to_f64(&self) -> Rect<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -570,7 +532,7 @@ impl<T: NumCast + Copy, Unit> TypedRect<T, Unit> {
|
|||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> TypedRect<usize, Unit> {
|
||||
pub fn to_usize(&self) -> Rect<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -579,7 +541,7 @@ impl<T: NumCast + Copy, Unit> TypedRect<T, Unit> {
|
|||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> TypedRect<u32, Unit> {
|
||||
pub fn to_u32(&self) -> Rect<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -588,7 +550,7 @@ impl<T: NumCast + Copy, Unit> TypedRect<T, Unit> {
|
|||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> TypedRect<i32, Unit> {
|
||||
pub fn to_i32(&self) -> Rect<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -597,36 +559,34 @@ impl<T: NumCast + Copy, Unit> TypedRect<T, Unit> {
|
|||
/// When casting from floating point rectangles, it is worth considering whether
|
||||
/// to `round()`, `round_in()` or `round_out()` before the cast in order to
|
||||
/// obtain the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> TypedRect<i64, Unit> {
|
||||
pub fn to_i64(&self) -> Rect<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> From<TypedSize2D<T, U>> for TypedRect<T, U>
|
||||
impl<T, U> From<Size2D<T, U>> for Rect<T, U>
|
||||
where T: Copy + Zero
|
||||
{
|
||||
fn from(size: TypedSize2D<T, U>) -> Self {
|
||||
fn from(size: Size2D<T, U>) -> Self {
|
||||
Self::from_size(size)
|
||||
}
|
||||
}
|
||||
|
||||
/// Shorthand for `TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(w, h))`.
|
||||
pub fn rect<T: Copy, U>(x: T, y: T, w: T, h: T) -> TypedRect<T, U> {
|
||||
TypedRect::new(TypedPoint2D::new(x, y), TypedSize2D::new(w, h))
|
||||
/// Shorthand for `Rect::new(Point2D::new(x, y), Size2D::new(w, h))`.
|
||||
pub fn rect<T: Copy, U>(x: T, y: T, w: T, h: T) -> Rect<T, U> {
|
||||
Rect::new(Point2D::new(x, y), Size2D::new(w, h))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use point::{Point2D, point2};
|
||||
use vector::vec2;
|
||||
use default::{Point2D, Rect, Size2D};
|
||||
use {point2, vec2, rect, size2};
|
||||
use side_offsets::SideOffsets2D;
|
||||
use size::Size2D;
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_translate() {
|
||||
let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32));
|
||||
let pp = p.translate(&vec2(10, 15));
|
||||
let pp = p.translate(vec2(10, 15));
|
||||
|
||||
assert!(pp.size.width == 50);
|
||||
assert!(pp.size.height == 40);
|
||||
|
@ -634,26 +594,7 @@ mod tests {
|
|||
assert!(pp.origin.y == 15);
|
||||
|
||||
let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40));
|
||||
let rr = r.translate(&vec2(0, -10));
|
||||
|
||||
assert!(rr.size.width == 50);
|
||||
assert!(rr.size.height == 40);
|
||||
assert!(rr.origin.x == -10);
|
||||
assert!(rr.origin.y == -15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_translate_by_size() {
|
||||
let p = Rect::new(Point2D::new(0u32, 0u32), Size2D::new(50u32, 40u32));
|
||||
let pp = p.translate_by_size(&Size2D::new(10, 15));
|
||||
|
||||
assert!(pp.size.width == 50);
|
||||
assert!(pp.size.height == 40);
|
||||
assert!(pp.origin.x == 10);
|
||||
assert!(pp.origin.y == 15);
|
||||
|
||||
let r = Rect::new(Point2D::new(-10, -5), Size2D::new(50, 40));
|
||||
let rr = r.translate_by_size(&Size2D::new(0, -10));
|
||||
let rr = r.translate(vec2(0, -10));
|
||||
|
||||
assert!(rr.size.width == 50);
|
||||
assert!(rr.size.height == 40);
|
||||
|
@ -707,42 +648,42 @@ mod tests {
|
|||
fn test_contains() {
|
||||
let r = Rect::new(Point2D::new(-20, 15), Size2D::new(100, 200));
|
||||
|
||||
assert!(r.contains(&Point2D::new(0, 50)));
|
||||
assert!(r.contains(&Point2D::new(-10, 200)));
|
||||
assert!(r.contains(Point2D::new(0, 50)));
|
||||
assert!(r.contains(Point2D::new(-10, 200)));
|
||||
|
||||
// The `contains` method is inclusive of the top/left edges, but not the
|
||||
// bottom/right edges.
|
||||
assert!(r.contains(&Point2D::new(-20, 15)));
|
||||
assert!(!r.contains(&Point2D::new(80, 15)));
|
||||
assert!(!r.contains(&Point2D::new(80, 215)));
|
||||
assert!(!r.contains(&Point2D::new(-20, 215)));
|
||||
assert!(r.contains(Point2D::new(-20, 15)));
|
||||
assert!(!r.contains(Point2D::new(80, 15)));
|
||||
assert!(!r.contains(Point2D::new(80, 215)));
|
||||
assert!(!r.contains(Point2D::new(-20, 215)));
|
||||
|
||||
// Points beyond the top-left corner.
|
||||
assert!(!r.contains(&Point2D::new(-25, 15)));
|
||||
assert!(!r.contains(&Point2D::new(-15, 10)));
|
||||
assert!(!r.contains(Point2D::new(-25, 15)));
|
||||
assert!(!r.contains(Point2D::new(-15, 10)));
|
||||
|
||||
// Points beyond the top-right corner.
|
||||
assert!(!r.contains(&Point2D::new(85, 20)));
|
||||
assert!(!r.contains(&Point2D::new(75, 10)));
|
||||
assert!(!r.contains(Point2D::new(85, 20)));
|
||||
assert!(!r.contains(Point2D::new(75, 10)));
|
||||
|
||||
// Points beyond the bottom-right corner.
|
||||
assert!(!r.contains(&Point2D::new(85, 210)));
|
||||
assert!(!r.contains(&Point2D::new(75, 220)));
|
||||
assert!(!r.contains(Point2D::new(85, 210)));
|
||||
assert!(!r.contains(Point2D::new(75, 220)));
|
||||
|
||||
// Points beyond the bottom-left corner.
|
||||
assert!(!r.contains(&Point2D::new(-25, 210)));
|
||||
assert!(!r.contains(&Point2D::new(-15, 220)));
|
||||
assert!(!r.contains(Point2D::new(-25, 210)));
|
||||
assert!(!r.contains(Point2D::new(-15, 220)));
|
||||
|
||||
let r = Rect::new(Point2D::new(-20.0, 15.0), Size2D::new(100.0, 200.0));
|
||||
assert!(r.contains_rect(&r));
|
||||
assert!(!r.contains_rect(&r.translate(&vec2(0.1, 0.0))));
|
||||
assert!(!r.contains_rect(&r.translate(&vec2(-0.1, 0.0))));
|
||||
assert!(!r.contains_rect(&r.translate(&vec2(0.0, 0.1))));
|
||||
assert!(!r.contains_rect(&r.translate(&vec2(0.0, -0.1))));
|
||||
assert!(!r.contains_rect(&r.translate(vec2(0.1, 0.0))));
|
||||
assert!(!r.contains_rect(&r.translate(vec2(-0.1, 0.0))));
|
||||
assert!(!r.contains_rect(&r.translate(vec2(0.0, 0.1))));
|
||||
assert!(!r.contains_rect(&r.translate(vec2(0.0, -0.1))));
|
||||
// Empty rectangles are always considered as contained in other rectangles,
|
||||
// even if their origin is not.
|
||||
let p = Point2D::new(1.0, 1.0);
|
||||
assert!(!r.contains(&p));
|
||||
assert!(!r.contains(p));
|
||||
assert!(r.contains_rect(&Rect::new(p, Size2D::zero())));
|
||||
}
|
||||
|
||||
|
@ -786,7 +727,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_inner_outer_rect() {
|
||||
let inner_rect: Rect<i32> = Rect::new(Point2D::new(20, 40), Size2D::new(80, 100));
|
||||
let inner_rect = Rect::new(point2(20, 40), size2(80, 100));
|
||||
let offsets = SideOffsets2D::new(20, 10, 10, 10);
|
||||
let outer_rect = inner_rect.outer_rect(offsets);
|
||||
assert_eq!(outer_rect.origin.x, 10);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use approxeq::ApproxEq;
|
||||
use num_traits::Float;
|
||||
use trig::Trig;
|
||||
use {TypedRotation3D, TypedTransform3D, TypedVector3D, UnknownUnit};
|
||||
use {Rotation3D, Transform3D, Vector3D};
|
||||
|
||||
/// A rigid transformation. All lengths are preserved under such a transformation.
|
||||
///
|
||||
|
@ -14,21 +14,19 @@ use {TypedRotation3D, TypedTransform3D, TypedVector3D, UnknownUnit};
|
|||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(C)]
|
||||
pub struct TypedRigidTransform3D<T, Src, Dst> {
|
||||
pub rotation: TypedRotation3D<T, Src, Dst>,
|
||||
pub translation: TypedVector3D<T, Dst>,
|
||||
pub struct RigidTransform3D<T, Src, Dst> {
|
||||
pub rotation: Rotation3D<T, Src, Dst>,
|
||||
pub translation: Vector3D<T, Dst>,
|
||||
}
|
||||
|
||||
pub type RigidTransform3D<T> = TypedRigidTransform3D<T, UnknownUnit, UnknownUnit>;
|
||||
|
||||
// All matrix multiplication in this file is in row-vector notation,
|
||||
// i.e. a vector `v` is transformed with `v * T`, and if you want to apply `T1`
|
||||
// before `T2` you use `T1 * T2`
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> RigidTransform3D<T, Src, Dst> {
|
||||
/// Construct a new rigid transformation, where the `rotation` applies first
|
||||
#[inline]
|
||||
pub fn new(rotation: TypedRotation3D<T, Src, Dst>, translation: TypedVector3D<T, Dst>) -> Self {
|
||||
pub fn new(rotation: Rotation3D<T, Src, Dst>, translation: Vector3D<T, Dst>) -> Self {
|
||||
Self {
|
||||
rotation,
|
||||
translation,
|
||||
|
@ -39,16 +37,16 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
Self {
|
||||
rotation: TypedRotation3D::identity(),
|
||||
translation: TypedVector3D::zero(),
|
||||
rotation: Rotation3D::identity(),
|
||||
translation: Vector3D::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a new rigid transformation, where the `translation` applies first
|
||||
#[inline]
|
||||
pub fn new_from_reversed(
|
||||
translation: TypedVector3D<T, Src>,
|
||||
rotation: TypedRotation3D<T, Src, Dst>,
|
||||
translation: Vector3D<T, Src>,
|
||||
rotation: Rotation3D<T, Src, Dst>,
|
||||
) -> Self {
|
||||
// T * R
|
||||
// = (R * R^-1) * T * R
|
||||
|
@ -59,7 +57,7 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
// It is equivalent to the translation matrix obtained by rotating the
|
||||
// translation by R
|
||||
|
||||
let translation = rotation.rotate_vector3d(&translation);
|
||||
let translation = rotation.transform_vector3d(translation);
|
||||
Self {
|
||||
rotation,
|
||||
translation,
|
||||
|
@ -67,18 +65,18 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_rotation(rotation: TypedRotation3D<T, Src, Dst>) -> Self {
|
||||
pub fn from_rotation(rotation: Rotation3D<T, Src, Dst>) -> Self {
|
||||
Self {
|
||||
rotation,
|
||||
translation: TypedVector3D::zero(),
|
||||
translation: Vector3D::zero(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_translation(translation: TypedVector3D<T, Dst>) -> Self {
|
||||
pub fn from_translation(translation: Vector3D<T, Dst>) -> Self {
|
||||
Self {
|
||||
translation,
|
||||
rotation: TypedRotation3D::identity(),
|
||||
rotation: Rotation3D::identity(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +84,7 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
///
|
||||
/// i.e., the translation is applied _first_
|
||||
#[inline]
|
||||
pub fn decompose_reversed(&self) -> (TypedVector3D<T, Src>, TypedRotation3D<T, Src, Dst>) {
|
||||
pub fn decompose_reversed(&self) -> (Vector3D<T, Src>, Rotation3D<T, Src, Dst>) {
|
||||
// self = R * T
|
||||
// = R * T * (R^-1 * R)
|
||||
// = (R * T * R^-1) * R)
|
||||
|
@ -94,7 +92,7 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
//
|
||||
// T' = (R^ * T * R^-1) is T rotated by R^-1
|
||||
|
||||
let translation = self.rotation.inverse().rotate_vector3d(&self.translation);
|
||||
let translation = self.rotation.inverse().transform_vector3d(self.translation);
|
||||
(translation, self.rotation)
|
||||
}
|
||||
|
||||
|
@ -103,10 +101,10 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
///
|
||||
/// i.e., this produces `self * other` in row-vector notation
|
||||
#[inline]
|
||||
pub fn post_mul<Dst2>(
|
||||
pub fn post_transform<Dst2>(
|
||||
&self,
|
||||
other: &TypedRigidTransform3D<T, Dst, Dst2>,
|
||||
) -> TypedRigidTransform3D<T, Src, Dst2> {
|
||||
other: &RigidTransform3D<T, Dst, Dst2>,
|
||||
) -> RigidTransform3D<T, Src, Dst2> {
|
||||
// self = R1 * T1
|
||||
// other = R2 * T2
|
||||
// result = R1 * T1 * R2 * T2
|
||||
|
@ -121,10 +119,10 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
|
||||
let t_prime = other
|
||||
.rotation
|
||||
.rotate_vector3d(&self.translation);
|
||||
.transform_vector3d(self.translation);
|
||||
let r_prime = self.rotation.post_rotate(&other.rotation);
|
||||
let t_prime2 = t_prime + other.translation;
|
||||
TypedRigidTransform3D {
|
||||
RigidTransform3D {
|
||||
rotation: r_prime,
|
||||
translation: t_prime2,
|
||||
}
|
||||
|
@ -135,16 +133,16 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
///
|
||||
/// i.e., this produces `other * self` in row-vector notation
|
||||
#[inline]
|
||||
pub fn pre_mul<Src2>(
|
||||
pub fn pre_transform<Src2>(
|
||||
&self,
|
||||
other: &TypedRigidTransform3D<T, Src2, Src>,
|
||||
) -> TypedRigidTransform3D<T, Src2, Dst> {
|
||||
other.post_mul(&self)
|
||||
other: &RigidTransform3D<T, Src2, Src>,
|
||||
) -> RigidTransform3D<T, Src2, Dst> {
|
||||
other.post_transform(&self)
|
||||
}
|
||||
|
||||
/// Inverts the transformation
|
||||
#[inline]
|
||||
pub fn inverse(&self) -> TypedRigidTransform3D<T, Dst, Src> {
|
||||
pub fn inverse(&self) -> RigidTransform3D<T, Dst, Src> {
|
||||
// result = (self)^-1
|
||||
// = (R * T)^-1
|
||||
// = T^-1 * R^-1
|
||||
|
@ -157,34 +155,34 @@ impl<T: Float + ApproxEq<T>, Src, Dst> TypedRigidTransform3D<T, Src, Dst> {
|
|||
//
|
||||
// An easier way of writing this is to use new_from_reversed() with R^-1 and T^-1
|
||||
|
||||
TypedRigidTransform3D::new_from_reversed(
|
||||
RigidTransform3D::new_from_reversed(
|
||||
-self.translation,
|
||||
self.rotation.inverse(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn to_transform(&self) -> TypedTransform3D<T, Src, Dst>
|
||||
pub fn to_transform(&self) -> Transform3D<T, Src, Dst>
|
||||
where
|
||||
T: Trig,
|
||||
{
|
||||
self.translation
|
||||
.to_transform()
|
||||
.pre_mul(&self.rotation.to_transform())
|
||||
.pre_transform(&self.rotation.to_transform())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> From<TypedRotation3D<T, Src, Dst>>
|
||||
for TypedRigidTransform3D<T, Src, Dst>
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> From<Rotation3D<T, Src, Dst>>
|
||||
for RigidTransform3D<T, Src, Dst>
|
||||
{
|
||||
fn from(rot: TypedRotation3D<T, Src, Dst>) -> Self {
|
||||
fn from(rot: Rotation3D<T, Src, Dst>) -> Self {
|
||||
Self::from_rotation(rot)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> From<TypedVector3D<T, Dst>>
|
||||
for TypedRigidTransform3D<T, Src, Dst>
|
||||
impl<T: Float + ApproxEq<T>, Src, Dst> From<Vector3D<T, Dst>>
|
||||
for RigidTransform3D<T, Src, Dst>
|
||||
{
|
||||
fn from(t: TypedVector3D<T, Dst>) -> Self {
|
||||
fn from(t: Vector3D<T, Dst>) -> Self {
|
||||
Self::from_translation(t)
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +190,7 @@ impl<T: Float + ApproxEq<T>, Src, Dst> From<TypedVector3D<T, Dst>>
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::RigidTransform3D;
|
||||
use {Rotation3D, TypedTransform3D, Vector3D};
|
||||
use default::{Rotation3D, Transform3D, Vector3D};
|
||||
|
||||
#[test]
|
||||
fn test_rigid_construction() {
|
||||
|
@ -202,13 +200,13 @@ mod test {
|
|||
let rigid = RigidTransform3D::new(rotation, translation);
|
||||
assert!(rigid
|
||||
.to_transform()
|
||||
.approx_eq(&translation.to_transform().pre_mul(&rotation.to_transform())));
|
||||
.approx_eq(&translation.to_transform().pre_transform(&rotation.to_transform())));
|
||||
|
||||
let rigid = RigidTransform3D::new_from_reversed(translation, rotation);
|
||||
assert!(rigid.to_transform().approx_eq(
|
||||
&translation
|
||||
.to_transform()
|
||||
.post_mul(&rotation.to_transform())
|
||||
.post_transform(&rotation.to_transform())
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -221,7 +219,7 @@ mod test {
|
|||
let (t2, r2) = rigid.decompose_reversed();
|
||||
assert!(rigid
|
||||
.to_transform()
|
||||
.approx_eq(&t2.to_transform().post_mul(&r2.to_transform())));
|
||||
.approx_eq(&t2.to_transform().post_transform(&r2.to_transform())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -232,9 +230,9 @@ mod test {
|
|||
let rigid = RigidTransform3D::new(rotation, translation);
|
||||
let inverse = rigid.inverse();
|
||||
assert!(rigid
|
||||
.post_mul(&inverse)
|
||||
.post_transform(&inverse)
|
||||
.to_transform()
|
||||
.approx_eq(&TypedTransform3D::identity()));
|
||||
.approx_eq(&Transform3D::identity()));
|
||||
assert!(inverse
|
||||
.to_transform()
|
||||
.approx_eq(&rigid.to_transform().inverse().unwrap()));
|
||||
|
@ -250,12 +248,12 @@ mod test {
|
|||
let rigid2 = RigidTransform3D::new(rotation2, translation2);
|
||||
|
||||
assert!(rigid
|
||||
.post_mul(&rigid2)
|
||||
.post_transform(&rigid2)
|
||||
.to_transform()
|
||||
.approx_eq(&rigid.to_transform().post_mul(&rigid2.to_transform())));
|
||||
.approx_eq(&rigid.to_transform().post_transform(&rigid2.to_transform())));
|
||||
assert!(rigid
|
||||
.pre_mul(&rigid2)
|
||||
.pre_transform(&rigid2)
|
||||
.to_transform()
|
||||
.approx_eq(&rigid.to_transform().pre_mul(&rigid2.to_transform())));
|
||||
.approx_eq(&rigid.to_transform().pre_transform(&rigid2.to_transform())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,13 @@ use num_traits::{Float, FloatConst, One, Zero, NumCast};
|
|||
use core::fmt;
|
||||
use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, Sub, SubAssign};
|
||||
use core::marker::PhantomData;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
use trig::Trig;
|
||||
use {TypedPoint2D, TypedPoint3D, TypedVector2D, TypedVector3D, Vector3D, point2, point3, vec3};
|
||||
use {TypedTransform2D, TypedTransform3D, UnknownUnit};
|
||||
use {Point2D, Point3D, Vector2D, Vector3D, point2, point3, vec3};
|
||||
use {Transform2D, Transform3D, UnknownUnit};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
/// An angle in radians
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
|
||||
|
@ -186,22 +190,49 @@ impl<T: Neg<Output = T>> Neg for Angle<T> {
|
|||
}
|
||||
|
||||
/// A transform that can represent rotations in 2d, represented as an angle in radians.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedRotation2D<T, Src, Dst> {
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: serde::Serialize", deserialize = "T: serde::Deserialize<'de>")))]
|
||||
pub struct Rotation2D<T, Src, Dst> {
|
||||
pub angle : T,
|
||||
#[doc(hidden)]
|
||||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
/// The default 2d rotation type with no units.
|
||||
pub type Rotation2D<T> = TypedRotation2D<T, UnknownUnit, UnknownUnit>;
|
||||
impl<T: Copy, Src, Dst> Copy for Rotation2D<T, Src, Dst> {}
|
||||
|
||||
impl<T, Src, Dst> TypedRotation2D<T, Src, Dst> {
|
||||
impl<T: Clone, Src, Dst> Clone for Rotation2D<T, Src, Dst> {
|
||||
fn clone(&self) -> Self {
|
||||
Rotation2D {
|
||||
angle: self.angle.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Eq for Rotation2D<T, Src, Dst> where T: Eq {}
|
||||
|
||||
impl<T, Src, Dst> PartialEq for Rotation2D<T, Src, Dst>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.angle == other.angle
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Hash for Rotation2D<T, Src, Dst>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.angle.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Rotation2D<T, Src, Dst> {
|
||||
#[inline]
|
||||
/// Creates a rotation from an angle in radians.
|
||||
pub fn new(angle: Angle<T>) -> Self {
|
||||
TypedRotation2D {
|
||||
Rotation2D {
|
||||
angle: angle.radians,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
|
@ -221,7 +252,7 @@ impl<T, Src, Dst> TypedRotation2D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedRotation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Rotation2D<T, Src, Dst>
|
||||
where
|
||||
T: Clone,
|
||||
{
|
||||
|
@ -231,7 +262,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedRotation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Rotation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
|
@ -247,31 +278,31 @@ where
|
|||
{
|
||||
/// Creates a 3d rotation (around the z axis) from this 2d rotation.
|
||||
#[inline]
|
||||
pub fn to_3d(&self) -> TypedRotation3D<T, Src, Dst> {
|
||||
TypedRotation3D::around_z(self.get_angle())
|
||||
pub fn to_3d(&self) -> Rotation3D<T, Src, Dst> {
|
||||
Rotation3D::around_z(self.get_angle())
|
||||
}
|
||||
|
||||
/// Returns the inverse of this rotation.
|
||||
#[inline]
|
||||
pub fn inverse(&self) -> TypedRotation2D<T, Dst, Src> {
|
||||
TypedRotation2D::radians(-self.angle)
|
||||
pub fn inverse(&self) -> Rotation2D<T, Dst, Src> {
|
||||
Rotation2D::radians(-self.angle)
|
||||
}
|
||||
|
||||
/// Returns a rotation representing the other rotation followed by this rotation.
|
||||
#[inline]
|
||||
pub fn pre_rotate<NewSrc>(
|
||||
&self,
|
||||
other: &TypedRotation2D<T, NewSrc, Src>,
|
||||
) -> TypedRotation2D<T, NewSrc, Dst> {
|
||||
TypedRotation2D::radians(self.angle + other.angle)
|
||||
other: &Rotation2D<T, NewSrc, Src>,
|
||||
) -> Rotation2D<T, NewSrc, Dst> {
|
||||
Rotation2D::radians(self.angle + other.angle)
|
||||
}
|
||||
|
||||
/// Returns a rotation representing this rotation followed by the other rotation.
|
||||
#[inline]
|
||||
pub fn post_rotate<NewDst>(
|
||||
&self,
|
||||
other: &TypedRotation2D<T, Dst, NewDst>,
|
||||
) -> TypedRotation2D<T, Src, NewDst> {
|
||||
other: &Rotation2D<T, Dst, NewDst>,
|
||||
) -> Rotation2D<T, Src, NewDst> {
|
||||
other.pre_rotate(self)
|
||||
}
|
||||
|
||||
|
@ -279,7 +310,7 @@ where
|
|||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
#[inline]
|
||||
pub fn transform_point(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
|
||||
pub fn transform_point(&self, point: Point2D<T, Src>) -> Point2D<T, Dst> {
|
||||
let (sin, cos) = Float::sin_cos(self.angle);
|
||||
point2(point.x * cos - point.y * sin, point.y * cos + point.x * sin)
|
||||
}
|
||||
|
@ -288,12 +319,12 @@ where
|
|||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
#[inline]
|
||||
pub fn transform_vector(&self, vector: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
|
||||
self.transform_point(&vector.to_point()).to_vector()
|
||||
pub fn transform_vector(&self, vector: Vector2D<T, Src>) -> Vector2D<T, Dst> {
|
||||
self.transform_point(vector.to_point()).to_vector()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedRotation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Rotation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
|
@ -308,8 +339,8 @@ where
|
|||
{
|
||||
/// Returns the matrix representation of this rotation.
|
||||
#[inline]
|
||||
pub fn to_transform(&self) -> TypedTransform2D<T, Src, Dst> {
|
||||
TypedTransform2D::create_rotation(self.get_angle())
|
||||
pub fn to_transform(&self) -> Transform2D<T, Src, Dst> {
|
||||
Transform2D::create_rotation(self.get_angle())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,9 +353,10 @@ where
|
|||
/// Some people use the `x, y, z, w` (or `w, x, y, z`) notations. The equivalence is
|
||||
/// as follows: `x -> i`, `y -> j`, `z -> k`, `w -> r`.
|
||||
/// The memory layout of this type corresponds to the `x, y, z, w` notation
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedRotation3D<T, Src, Dst> {
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: serde::Serialize", deserialize = "T: serde::Deserialize<'de>")))]
|
||||
pub struct Rotation3D<T, Src, Dst> {
|
||||
/// Component multiplied by the imaginary number `i`.
|
||||
pub i: T,
|
||||
/// Component multiplied by the imaginary number `j`.
|
||||
|
@ -337,10 +369,45 @@ pub struct TypedRotation3D<T, Src, Dst> {
|
|||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
/// The default 3d rotation type with no units.
|
||||
pub type Rotation3D<T> = TypedRotation3D<T, UnknownUnit, UnknownUnit>;
|
||||
impl<T: Copy, Src, Dst> Copy for Rotation3D<T, Src, Dst> {}
|
||||
|
||||
impl<T, Src, Dst> TypedRotation3D<T, Src, Dst> {
|
||||
impl<T: Clone, Src, Dst> Clone for Rotation3D<T, Src, Dst> {
|
||||
fn clone(&self) -> Self {
|
||||
Rotation3D {
|
||||
i: self.i.clone(),
|
||||
j: self.j.clone(),
|
||||
k: self.k.clone(),
|
||||
r: self.r.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Eq for Rotation3D<T, Src, Dst> where T: Eq {}
|
||||
|
||||
impl<T, Src, Dst> PartialEq for Rotation3D<T, Src, Dst>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.i == other.i &&
|
||||
self.j == other.j &&
|
||||
self.k == other.k &&
|
||||
self.r == other.r
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Hash for Rotation3D<T, Src, Dst>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.i.hash(h);
|
||||
self.j.hash(h);
|
||||
self.k.hash(h);
|
||||
self.r.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Rotation3D<T, Src, Dst> {
|
||||
/// Creates a rotation around from a quaternion representation.
|
||||
///
|
||||
/// The parameters are a, b, c and r compose the quaternion `a*i + b*j + c*k + r`
|
||||
|
@ -350,7 +417,7 @@ impl<T, Src, Dst> TypedRotation3D<T, Src, Dst> {
|
|||
/// The resulting quaternion is not necessarily normalized. See `unit_quaternion`.
|
||||
#[inline]
|
||||
pub fn quaternion(a: T, b: T, c: T, r: T) -> Self {
|
||||
TypedRotation3D {
|
||||
Rotation3D {
|
||||
i: a,
|
||||
j: b,
|
||||
k: c,
|
||||
|
@ -360,18 +427,18 @@ impl<T, Src, Dst> TypedRotation3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedRotation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Rotation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
/// Returns the vector part (i, j, k) of this quaternion.
|
||||
#[inline]
|
||||
pub fn vector_part(&self) -> Vector3D<T> {
|
||||
pub fn vector_part(&self) -> Vector3D<T, UnknownUnit> {
|
||||
vec3(self.i, self.j, self.k)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedRotation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Rotation3D<T, Src, Dst>
|
||||
where
|
||||
T: Float,
|
||||
{
|
||||
|
@ -394,7 +461,7 @@ where
|
|||
}
|
||||
|
||||
/// Creates a rotation around a given axis.
|
||||
pub fn around_axis(axis: TypedVector3D<T, Src>, angle: Angle<T>) -> Self {
|
||||
pub fn around_axis(axis: Vector3D<T, Src>, angle: Angle<T>) -> Self {
|
||||
let axis = axis.normalize();
|
||||
let two = T::one() + T::one();
|
||||
let (sin, cos) = Angle::sin_cos(angle / two);
|
||||
|
@ -449,8 +516,8 @@ where
|
|||
|
||||
/// Returns the inverse of this rotation.
|
||||
#[inline]
|
||||
pub fn inverse(&self) -> TypedRotation3D<T, Dst, Src> {
|
||||
TypedRotation3D::quaternion(-self.i, -self.j, -self.k, self.r)
|
||||
pub fn inverse(&self) -> Rotation3D<T, Dst, Src> {
|
||||
Rotation3D::quaternion(-self.i, -self.j, -self.k, self.r)
|
||||
}
|
||||
|
||||
/// Computes the norm of this quaternion
|
||||
|
@ -533,7 +600,7 @@ where
|
|||
/// Returns the given 3d point transformed by this rotation.
|
||||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
pub fn rotate_point3d(&self, point: &TypedPoint3D<T, Src>) -> TypedPoint3D<T, Dst>
|
||||
pub fn transform_point3d(&self, point: Point3D<T, Src>) -> Point3D<T, Dst>
|
||||
where
|
||||
T: ApproxEq<T>,
|
||||
{
|
||||
|
@ -553,38 +620,38 @@ where
|
|||
///
|
||||
/// The input point must be use the unit Src, and the returned point has the unit Dst.
|
||||
#[inline]
|
||||
pub fn rotate_point2d(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst>
|
||||
pub fn transform_point2d(&self, point: Point2D<T, Src>) -> Point2D<T, Dst>
|
||||
where
|
||||
T: ApproxEq<T>,
|
||||
{
|
||||
self.rotate_point3d(&point.to_3d()).xy()
|
||||
self.transform_point3d(point.to_3d()).xy()
|
||||
}
|
||||
|
||||
/// Returns the given 3d vector transformed by this rotation.
|
||||
///
|
||||
/// The input vector must be use the unit Src, and the returned point has the unit Dst.
|
||||
#[inline]
|
||||
pub fn rotate_vector3d(&self, vector: &TypedVector3D<T, Src>) -> TypedVector3D<T, Dst>
|
||||
pub fn transform_vector3d(&self, vector: Vector3D<T, Src>) -> Vector3D<T, Dst>
|
||||
where
|
||||
T: ApproxEq<T>,
|
||||
{
|
||||
self.rotate_point3d(&vector.to_point()).to_vector()
|
||||
self.transform_point3d(vector.to_point()).to_vector()
|
||||
}
|
||||
|
||||
/// Returns the given 2d vector transformed by this rotation then projected on the xy plane.
|
||||
///
|
||||
/// The input vector must be use the unit Src, and the returned point has the unit Dst.
|
||||
#[inline]
|
||||
pub fn rotate_vector2d(&self, vector: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst>
|
||||
pub fn transform_vector2d(&self, vector: Vector2D<T, Src>) -> Vector2D<T, Dst>
|
||||
where
|
||||
T: ApproxEq<T>,
|
||||
{
|
||||
self.rotate_vector3d(&vector.to_3d()).xy()
|
||||
self.transform_vector3d(vector.to_3d()).xy()
|
||||
}
|
||||
|
||||
/// Returns the matrix representation of this rotation.
|
||||
#[inline]
|
||||
pub fn to_transform(&self) -> TypedTransform3D<T, Src, Dst>
|
||||
pub fn to_transform(&self) -> Transform3D<T, Src, Dst>
|
||||
where
|
||||
T: ApproxEq<T>,
|
||||
{
|
||||
|
@ -618,7 +685,7 @@ where
|
|||
let m32 = jk - ri;
|
||||
let m33 = one - (ii + jj);
|
||||
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
m11,
|
||||
m12,
|
||||
m13,
|
||||
|
@ -641,13 +708,13 @@ where
|
|||
/// Returns a rotation representing the other rotation followed by this rotation.
|
||||
pub fn pre_rotate<NewSrc>(
|
||||
&self,
|
||||
other: &TypedRotation3D<T, NewSrc, Src>,
|
||||
) -> TypedRotation3D<T, NewSrc, Dst>
|
||||
other: &Rotation3D<T, NewSrc, Src>,
|
||||
) -> Rotation3D<T, NewSrc, Dst>
|
||||
where
|
||||
T: ApproxEq<T>,
|
||||
{
|
||||
debug_assert!(self.is_normalized());
|
||||
TypedRotation3D::quaternion(
|
||||
Rotation3D::quaternion(
|
||||
self.i * other.r + self.r * other.i + self.j * other.k - self.k * other.j,
|
||||
self.j * other.r + self.r * other.j + self.k * other.i - self.i * other.k,
|
||||
self.k * other.r + self.r * other.k + self.i * other.j - self.j * other.i,
|
||||
|
@ -659,8 +726,8 @@ where
|
|||
#[inline]
|
||||
pub fn post_rotate<NewDst>(
|
||||
&self,
|
||||
other: &TypedRotation3D<T, Dst, NewDst>,
|
||||
) -> TypedRotation3D<T, Src, NewDst>
|
||||
other: &Rotation3D<T, Dst, NewDst>,
|
||||
) -> Rotation3D<T, Src, NewDst>
|
||||
where
|
||||
T: ApproxEq<T>,
|
||||
{
|
||||
|
@ -701,7 +768,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for TypedRotation3D<T, Src, Dst> {
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for Rotation3D<T, Src, Dst> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
|
@ -711,7 +778,7 @@ impl<T: fmt::Debug, Src, Dst> fmt::Debug for TypedRotation3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, Src, Dst> fmt::Display for TypedRotation3D<T, Src, Dst> {
|
||||
impl<T: fmt::Display, Src, Dst> fmt::Display for Rotation3D<T, Src, Dst> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
|
@ -721,7 +788,7 @@ impl<T: fmt::Display, Src, Dst> fmt::Display for TypedRotation3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> ApproxEq<T> for TypedRotation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> ApproxEq<T> for Rotation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Neg<Output = T> + ApproxEq<T>,
|
||||
{
|
||||
|
@ -745,72 +812,78 @@ where
|
|||
#[test]
|
||||
fn simple_rotation_2d() {
|
||||
use core::f32::consts::{FRAC_PI_2, PI};
|
||||
use default::Rotation2D;
|
||||
|
||||
let ri = Rotation2D::identity();
|
||||
let r90 = Rotation2D::radians(FRAC_PI_2);
|
||||
let rm90 = Rotation2D::radians(-FRAC_PI_2);
|
||||
let r180 = Rotation2D::radians(PI);
|
||||
|
||||
assert!(
|
||||
ri.transform_point(&point2(1.0, 2.0))
|
||||
ri.transform_point(point2(1.0, 2.0))
|
||||
.approx_eq(&point2(1.0, 2.0))
|
||||
);
|
||||
assert!(
|
||||
r90.transform_point(&point2(1.0, 2.0))
|
||||
r90.transform_point(point2(1.0, 2.0))
|
||||
.approx_eq(&point2(-2.0, 1.0))
|
||||
);
|
||||
assert!(
|
||||
rm90.transform_point(&point2(1.0, 2.0))
|
||||
rm90.transform_point(point2(1.0, 2.0))
|
||||
.approx_eq(&point2(2.0, -1.0))
|
||||
);
|
||||
assert!(
|
||||
r180.transform_point(&point2(1.0, 2.0))
|
||||
r180.transform_point(point2(1.0, 2.0))
|
||||
.approx_eq(&point2(-1.0, -2.0))
|
||||
);
|
||||
|
||||
assert!(
|
||||
r90.inverse()
|
||||
.inverse()
|
||||
.transform_point(&point2(1.0, 2.0))
|
||||
.approx_eq(&r90.transform_point(&point2(1.0, 2.0)))
|
||||
.transform_point(point2(1.0, 2.0))
|
||||
.approx_eq(&r90.transform_point(point2(1.0, 2.0)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn simple_rotation_3d_in_2d() {
|
||||
use core::f32::consts::{FRAC_PI_2, PI};
|
||||
use default::Rotation3D;
|
||||
|
||||
let ri = Rotation3D::identity();
|
||||
let r90 = Rotation3D::around_z(Angle::radians(FRAC_PI_2));
|
||||
let rm90 = Rotation3D::around_z(Angle::radians(-FRAC_PI_2));
|
||||
let r180 = Rotation3D::around_z(Angle::radians(PI));
|
||||
|
||||
assert!(
|
||||
ri.rotate_point2d(&point2(1.0, 2.0))
|
||||
ri.transform_point2d(point2(1.0, 2.0))
|
||||
.approx_eq(&point2(1.0, 2.0))
|
||||
);
|
||||
assert!(
|
||||
r90.rotate_point2d(&point2(1.0, 2.0))
|
||||
r90.transform_point2d(point2(1.0, 2.0))
|
||||
.approx_eq(&point2(-2.0, 1.0))
|
||||
);
|
||||
assert!(
|
||||
rm90.rotate_point2d(&point2(1.0, 2.0))
|
||||
rm90.transform_point2d(point2(1.0, 2.0))
|
||||
.approx_eq(&point2(2.0, -1.0))
|
||||
);
|
||||
assert!(
|
||||
r180.rotate_point2d(&point2(1.0, 2.0))
|
||||
r180.transform_point2d(point2(1.0, 2.0))
|
||||
.approx_eq(&point2(-1.0, -2.0))
|
||||
);
|
||||
|
||||
assert!(
|
||||
r90.inverse()
|
||||
.inverse()
|
||||
.rotate_point2d(&point2(1.0, 2.0))
|
||||
.approx_eq(&r90.rotate_point2d(&point2(1.0, 2.0)))
|
||||
.transform_point2d(point2(1.0, 2.0))
|
||||
.approx_eq(&r90.transform_point2d(point2(1.0, 2.0)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pre_post() {
|
||||
use core::f32::consts::FRAC_PI_2;
|
||||
use default::Rotation3D;
|
||||
|
||||
let r1 = Rotation3D::around_x(Angle::radians(FRAC_PI_2));
|
||||
let r2 = Rotation3D::around_y(Angle::radians(FRAC_PI_2));
|
||||
let r3 = Rotation3D::around_z(Angle::radians(FRAC_PI_2));
|
||||
|
@ -823,18 +896,20 @@ fn pre_post() {
|
|||
|
||||
// Check that the order of transformations is correct (corresponds to what
|
||||
// we do in Transform3D).
|
||||
let p1 = r1.post_rotate(&r2).post_rotate(&r3).rotate_point3d(&p);
|
||||
let p2 = t1.post_mul(&t2).post_mul(&t3).transform_point3d(&p);
|
||||
let p1 = r1.post_rotate(&r2).post_rotate(&r3).transform_point3d(p);
|
||||
let p2 = t1.post_transform(&t2).post_transform(&t3).transform_point3d(p);
|
||||
|
||||
assert!(p1.approx_eq(&p2.unwrap()));
|
||||
|
||||
// Check that changing the order indeed matters.
|
||||
let p3 = t3.post_mul(&t1).post_mul(&t2).transform_point3d(&p);
|
||||
let p3 = t3.post_transform(&t1).post_transform(&t2).transform_point3d(p);
|
||||
assert!(!p1.approx_eq(&p3.unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn to_transform3d() {
|
||||
use default::Rotation3D;
|
||||
|
||||
use core::f32::consts::{FRAC_PI_2, PI};
|
||||
let rotations = [
|
||||
Rotation3D::identity(),
|
||||
|
@ -857,8 +932,8 @@ fn to_transform3d() {
|
|||
];
|
||||
|
||||
for rotation in &rotations {
|
||||
for point in &points {
|
||||
let p1 = rotation.rotate_point3d(point);
|
||||
for &point in &points {
|
||||
let p1 = rotation.transform_point3d(point);
|
||||
let p2 = rotation.to_transform().transform_point3d(point);
|
||||
assert!(p1.approx_eq(&p2.unwrap()));
|
||||
}
|
||||
|
@ -867,6 +942,8 @@ fn to_transform3d() {
|
|||
|
||||
#[test]
|
||||
fn slerp() {
|
||||
use default::Rotation3D;
|
||||
|
||||
let q1 = Rotation3D::quaternion(1.0, 0.0, 0.0, 0.0);
|
||||
let q2 = Rotation3D::quaternion(0.0, 1.0, 0.0, 0.0);
|
||||
let q3 = Rotation3D::quaternion(0.0, 0.0, -1.0, 0.0);
|
||||
|
@ -936,22 +1013,23 @@ fn slerp() {
|
|||
#[test]
|
||||
fn around_axis() {
|
||||
use core::f32::consts::{FRAC_PI_2, PI};
|
||||
use default::Rotation3D;
|
||||
|
||||
// Two sort of trivial cases:
|
||||
let r1 = Rotation3D::around_axis(vec3(1.0, 1.0, 0.0), Angle::radians(PI));
|
||||
let r2 = Rotation3D::around_axis(vec3(1.0, 1.0, 0.0), Angle::radians(FRAC_PI_2));
|
||||
assert!(
|
||||
r1.rotate_point3d(&point3(1.0, 2.0, 0.0))
|
||||
r1.transform_point3d(point3(1.0, 2.0, 0.0))
|
||||
.approx_eq(&point3(2.0, 1.0, 0.0))
|
||||
);
|
||||
assert!(
|
||||
r2.rotate_point3d(&point3(1.0, 0.0, 0.0))
|
||||
r2.transform_point3d(point3(1.0, 0.0, 0.0))
|
||||
.approx_eq(&point3(0.5, 0.5, -0.5.sqrt()))
|
||||
);
|
||||
|
||||
// A more arbitrary test (made up with numpy):
|
||||
let r3 = Rotation3D::around_axis(vec3(0.5, 1.0, 2.0), Angle::radians(2.291288));
|
||||
assert!(r3.rotate_point3d(&point3(1.0, 0.0, 0.0)).approx_eq(&point3(
|
||||
assert!(r3.transform_point3d(point3(1.0, 0.0, 0.0)).approx_eq(&point3(
|
||||
-0.58071821,
|
||||
0.81401868,
|
||||
-0.01182979
|
||||
|
@ -961,6 +1039,7 @@ fn around_axis() {
|
|||
#[test]
|
||||
fn from_euler() {
|
||||
use core::f32::consts::FRAC_PI_2;
|
||||
use default::Rotation3D;
|
||||
|
||||
// First test simple separate yaw pitch and roll rotations, because it is easy to come
|
||||
// up with the corresponding quaternion.
|
||||
|
@ -974,20 +1053,20 @@ fn from_euler() {
|
|||
// roll
|
||||
let roll_re = Rotation3D::euler(angle, zero, zero);
|
||||
let roll_rq = Rotation3D::around_x(angle);
|
||||
let roll_pe = roll_re.rotate_point3d(&p);
|
||||
let roll_pq = roll_rq.rotate_point3d(&p);
|
||||
let roll_pe = roll_re.transform_point3d(p);
|
||||
let roll_pq = roll_rq.transform_point3d(p);
|
||||
|
||||
// pitch
|
||||
let pitch_re = Rotation3D::euler(zero, angle, zero);
|
||||
let pitch_rq = Rotation3D::around_y(angle);
|
||||
let pitch_pe = pitch_re.rotate_point3d(&p);
|
||||
let pitch_pq = pitch_rq.rotate_point3d(&p);
|
||||
let pitch_pe = pitch_re.transform_point3d(p);
|
||||
let pitch_pq = pitch_rq.transform_point3d(p);
|
||||
|
||||
// yaw
|
||||
let yaw_re = Rotation3D::euler(zero, zero, angle);
|
||||
let yaw_rq = Rotation3D::around_z(angle);
|
||||
let yaw_pe = yaw_re.rotate_point3d(&p);
|
||||
let yaw_pq = yaw_rq.rotate_point3d(&p);
|
||||
let yaw_pe = yaw_re.transform_point3d(p);
|
||||
let yaw_pq = yaw_rq.transform_point3d(p);
|
||||
|
||||
assert!(roll_pe.approx_eq(&roll_pq));
|
||||
assert!(pitch_pe.approx_eq(&pitch_pq));
|
||||
|
@ -997,8 +1076,8 @@ fn from_euler() {
|
|||
// the proper order: roll -> pitch -> yaw.
|
||||
let ypr_e = Rotation3D::euler(angle, angle, angle);
|
||||
let ypr_q = roll_rq.post_rotate(&pitch_rq).post_rotate(&yaw_rq);
|
||||
let ypr_pe = ypr_e.rotate_point3d(&p);
|
||||
let ypr_pq = ypr_q.rotate_point3d(&p);
|
||||
let ypr_pe = ypr_e.transform_point3d(p);
|
||||
let ypr_pq = ypr_q.transform_point3d(p);
|
||||
|
||||
assert!(ypr_pe.approx_eq(&ypr_pq));
|
||||
}
|
||||
|
@ -1006,6 +1085,7 @@ fn from_euler() {
|
|||
#[test]
|
||||
fn wrap_angles() {
|
||||
use core::f32::consts::{FRAC_PI_2, PI};
|
||||
|
||||
assert!(Angle::radians(0.0).positive().radians.approx_eq(&0.0));
|
||||
assert!(
|
||||
Angle::radians(FRAC_PI_2)
|
||||
|
|
|
@ -12,162 +12,135 @@ use num::One;
|
|||
|
||||
use num_traits::NumCast;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use serde;
|
||||
use core::fmt;
|
||||
use core::ops::{Add, Div, Mul, Neg, Sub};
|
||||
use core::marker::PhantomData;
|
||||
use {TypedPoint2D, TypedRect, TypedSize2D, TypedVector2D};
|
||||
use {Point2D, Rect, Size2D, Vector2D};
|
||||
|
||||
/// A scaling factor between two different units of measurement.
|
||||
///
|
||||
/// This is effectively a type-safe float, intended to be used in combination with other types like
|
||||
/// `length::Length` to enforce conversion between systems of measurement at compile time.
|
||||
///
|
||||
/// `Src` and `Dst` represent the units before and after multiplying a value by a `TypedScale`. They
|
||||
/// `Src` and `Dst` represent the units before and after multiplying a value by a `Scale`. They
|
||||
/// may be types without values, such as empty enums. For example:
|
||||
///
|
||||
/// ```rust
|
||||
/// use euclid::TypedScale;
|
||||
/// use euclid::Scale;
|
||||
/// use euclid::Length;
|
||||
/// enum Mm {};
|
||||
/// enum Inch {};
|
||||
///
|
||||
/// let mm_per_inch: TypedScale<f32, Inch, Mm> = TypedScale::new(25.4);
|
||||
/// let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
|
||||
///
|
||||
/// let one_foot: Length<f32, Inch> = Length::new(12.0);
|
||||
/// let one_foot_in_mm: Length<f32, Mm> = one_foot * mm_per_inch;
|
||||
/// ```
|
||||
#[repr(C)]
|
||||
pub struct TypedScale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: serde::Serialize", deserialize = "T: serde::Deserialize<'de>")))]
|
||||
pub struct Scale<T, Src, Dst>(pub T, #[doc(hidden)] pub PhantomData<(Src, Dst)>);
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T, Src, Dst> Deserialize<'de> for TypedScale<T, Src, Dst>
|
||||
where
|
||||
T: Deserialize<'de>,
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<TypedScale<T, Src, Dst>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(TypedScale(
|
||||
try!(Deserialize::deserialize(deserializer)),
|
||||
PhantomData,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, Src, Dst> Serialize for TypedScale<T, Src, Dst>
|
||||
where
|
||||
T: Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
self.0.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedScale<T, Src, Dst> {
|
||||
impl<T, Src, Dst> Scale<T, Src, Dst> {
|
||||
pub fn new(x: T) -> Self {
|
||||
TypedScale(x, PhantomData)
|
||||
Scale(x, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, Src, Dst> TypedScale<T, Src, Dst> {
|
||||
impl<T: Clone, Src, Dst> Scale<T, Src, Dst> {
|
||||
pub fn get(&self) -> T {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Src, Dst> TypedScale<f32, Src, Dst> {
|
||||
impl<Src, Dst> Scale<f32, Src, Dst> {
|
||||
/// Identity scaling, could be used to safely transit from one space to another.
|
||||
pub const ONE: Self = TypedScale(1.0, PhantomData);
|
||||
pub const ONE: Self = Scale(1.0, PhantomData);
|
||||
}
|
||||
|
||||
impl<T: Clone + One + Div<T, Output = T>, Src, Dst> TypedScale<T, Src, Dst> {
|
||||
/// The inverse TypedScale (1.0 / self).
|
||||
pub fn inv(&self) -> TypedScale<T, Dst, Src> {
|
||||
impl<T: Clone + One + Div<T, Output = T>, Src, Dst> Scale<T, Src, Dst> {
|
||||
/// The inverse Scale (1.0 / self).
|
||||
pub fn inv(&self) -> Scale<T, Dst, Src> {
|
||||
let one: T = One::one();
|
||||
TypedScale::new(one / self.get())
|
||||
Scale::new(one / self.get())
|
||||
}
|
||||
}
|
||||
|
||||
// scale0 * scale1
|
||||
impl<T: Clone + Mul<T, Output = T>, A, B, C> Mul<TypedScale<T, B, C>> for TypedScale<T, A, B> {
|
||||
type Output = TypedScale<T, A, C>;
|
||||
impl<T: Clone + Mul<T, Output = T>, A, B, C> Mul<Scale<T, B, C>> for Scale<T, A, B> {
|
||||
type Output = Scale<T, A, C>;
|
||||
#[inline]
|
||||
fn mul(self, other: TypedScale<T, B, C>) -> TypedScale<T, A, C> {
|
||||
TypedScale::new(self.get() * other.get())
|
||||
fn mul(self, other: Scale<T, B, C>) -> Scale<T, A, C> {
|
||||
Scale::new(self.get() * other.get())
|
||||
}
|
||||
}
|
||||
|
||||
// scale0 + scale1
|
||||
impl<T: Clone + Add<T, Output = T>, Src, Dst> Add for TypedScale<T, Src, Dst> {
|
||||
type Output = TypedScale<T, Src, Dst>;
|
||||
impl<T: Clone + Add<T, Output = T>, Src, Dst> Add for Scale<T, Src, Dst> {
|
||||
type Output = Scale<T, Src, Dst>;
|
||||
#[inline]
|
||||
fn add(self, other: TypedScale<T, Src, Dst>) -> TypedScale<T, Src, Dst> {
|
||||
TypedScale::new(self.get() + other.get())
|
||||
fn add(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
|
||||
Scale::new(self.get() + other.get())
|
||||
}
|
||||
}
|
||||
|
||||
// scale0 - scale1
|
||||
impl<T: Clone + Sub<T, Output = T>, Src, Dst> Sub for TypedScale<T, Src, Dst> {
|
||||
type Output = TypedScale<T, Src, Dst>;
|
||||
impl<T: Clone + Sub<T, Output = T>, Src, Dst> Sub for Scale<T, Src, Dst> {
|
||||
type Output = Scale<T, Src, Dst>;
|
||||
#[inline]
|
||||
fn sub(self, other: TypedScale<T, Src, Dst>) -> TypedScale<T, Src, Dst> {
|
||||
TypedScale::new(self.get() - other.get())
|
||||
fn sub(self, other: Scale<T, Src, Dst>) -> Scale<T, Src, Dst> {
|
||||
Scale::new(self.get() - other.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Clone, Src, Dst0> TypedScale<T, Src, Dst0> {
|
||||
impl<T: NumCast + Clone, Src, Dst0> Scale<T, Src, Dst0> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
pub fn cast<T1: NumCast + Clone>(&self) -> TypedScale<T1, Src, Dst0> {
|
||||
pub fn cast<T1: NumCast + Clone>(&self) -> Scale<T1, Src, Dst0> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<TypedScale<T1, Src, Dst0>> {
|
||||
NumCast::from(self.get()).map(TypedScale::new)
|
||||
pub fn try_cast<T1: NumCast + Clone>(&self) -> Option<Scale<T1, Src, Dst0>> {
|
||||
NumCast::from(self.get()).map(Scale::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedScale<T, Src, Dst>
|
||||
impl<T, Src, Dst> Scale<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Clone + Mul<T, Output = T> + Neg<Output = T> + PartialEq + One,
|
||||
{
|
||||
/// Returns the given point transformed by this scale.
|
||||
#[inline]
|
||||
pub fn transform_point(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
|
||||
TypedPoint2D::new(point.x * self.get(), point.y * self.get())
|
||||
pub fn transform_point(&self, point: Point2D<T, Src>) -> Point2D<T, Dst> {
|
||||
Point2D::new(point.x * self.get(), point.y * self.get())
|
||||
}
|
||||
|
||||
/// Returns the given vector transformed by this scale.
|
||||
#[inline]
|
||||
pub fn transform_vector(&self, vec: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
|
||||
TypedVector2D::new(vec.x * self.get(), vec.y * self.get())
|
||||
pub fn transform_vector(&self, vec: Vector2D<T, Src>) -> Vector2D<T, Dst> {
|
||||
Vector2D::new(vec.x * self.get(), vec.y * self.get())
|
||||
}
|
||||
|
||||
/// Returns the given vector transformed by this scale.
|
||||
#[inline]
|
||||
pub fn transform_size(&self, size: &TypedSize2D<T, Src>) -> TypedSize2D<T, Dst> {
|
||||
TypedSize2D::new(size.width * self.get(), size.height * self.get())
|
||||
pub fn transform_size(&self, size: Size2D<T, Src>) -> Size2D<T, Dst> {
|
||||
Size2D::new(size.width * self.get(), size.height * self.get())
|
||||
}
|
||||
|
||||
/// Returns the given rect transformed by this scale.
|
||||
#[inline]
|
||||
pub fn transform_rect(&self, rect: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
|
||||
TypedRect::new(
|
||||
self.transform_point(&rect.origin),
|
||||
self.transform_size(&rect.size),
|
||||
pub fn transform_rect(&self, rect: &Rect<T, Src>) -> Rect<T, Dst> {
|
||||
Rect::new(
|
||||
self.transform_point(rect.origin),
|
||||
self.transform_size(rect.size),
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the inverse of this scale.
|
||||
#[inline]
|
||||
pub fn inverse(&self) -> TypedScale<T, Dst, Src> {
|
||||
TypedScale::new(-self.get())
|
||||
pub fn inverse(&self) -> Scale<T, Dst, Src> {
|
||||
Scale::new(-self.get())
|
||||
}
|
||||
|
||||
/// Returns true if this scale has no effect.
|
||||
|
@ -180,27 +153,27 @@ where
|
|||
// FIXME: Switch to `derive(PartialEq, Clone)` after this Rust issue is fixed:
|
||||
// https://github.com/mozilla/rust/issues/7671
|
||||
|
||||
impl<T: PartialEq, Src, Dst> PartialEq for TypedScale<T, Src, Dst> {
|
||||
fn eq(&self, other: &TypedScale<T, Src, Dst>) -> bool {
|
||||
impl<T: PartialEq, Src, Dst> PartialEq for Scale<T, Src, Dst> {
|
||||
fn eq(&self, other: &Scale<T, Src, Dst>) -> bool {
|
||||
self.0 == other.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, Src, Dst> Clone for TypedScale<T, Src, Dst> {
|
||||
fn clone(&self) -> TypedScale<T, Src, Dst> {
|
||||
TypedScale::new(self.get())
|
||||
impl<T: Clone, Src, Dst> Clone for Scale<T, Src, Dst> {
|
||||
fn clone(&self) -> Scale<T, Src, Dst> {
|
||||
Scale::new(self.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Src, Dst> Copy for TypedScale<T, Src, Dst> {}
|
||||
impl<T: Copy, Src, Dst> Copy for Scale<T, Src, Dst> {}
|
||||
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for TypedScale<T, Src, Dst> {
|
||||
impl<T: fmt::Debug, Src, Dst> fmt::Debug for Scale<T, Src, Dst> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, Src, Dst> fmt::Display for TypedScale<T, Src, Dst> {
|
||||
impl<T: fmt::Display, Src, Dst> fmt::Display for Scale<T, Src, Dst> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
|
@ -208,7 +181,7 @@ impl<T: fmt::Display, Src, Dst> fmt::Display for TypedScale<T, Src, Dst> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::TypedScale;
|
||||
use super::Scale;
|
||||
|
||||
enum Inch {}
|
||||
enum Cm {}
|
||||
|
@ -216,20 +189,20 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_scale() {
|
||||
let mm_per_inch: TypedScale<f32, Inch, Mm> = TypedScale::new(25.4);
|
||||
let cm_per_mm: TypedScale<f32, Mm, Cm> = TypedScale::new(0.1);
|
||||
let mm_per_inch: Scale<f32, Inch, Mm> = Scale::new(25.4);
|
||||
let cm_per_mm: Scale<f32, Mm, Cm> = Scale::new(0.1);
|
||||
|
||||
let mm_per_cm: TypedScale<f32, Cm, Mm> = cm_per_mm.inv();
|
||||
let mm_per_cm: Scale<f32, Cm, Mm> = cm_per_mm.inv();
|
||||
assert_eq!(mm_per_cm.get(), 10.0);
|
||||
|
||||
let cm_per_inch: TypedScale<f32, Inch, Cm> = mm_per_inch * cm_per_mm;
|
||||
assert_eq!(cm_per_inch, TypedScale::new(2.54));
|
||||
let cm_per_inch: Scale<f32, Inch, Cm> = mm_per_inch * cm_per_mm;
|
||||
assert_eq!(cm_per_inch, Scale::new(2.54));
|
||||
|
||||
let a: TypedScale<isize, Inch, Inch> = TypedScale::new(2);
|
||||
let b: TypedScale<isize, Inch, Inch> = TypedScale::new(3);
|
||||
let a: Scale<isize, Inch, Inch> = Scale::new(2);
|
||||
let b: Scale<isize, Inch, Inch> = Scale::new(3);
|
||||
assert!(a != b);
|
||||
assert_eq!(a, a.clone());
|
||||
assert_eq!(a.clone() + b.clone(), TypedScale::new(5));
|
||||
assert_eq!(a - b, TypedScale::new(-1));
|
||||
assert_eq!(a.clone() + b.clone(), Scale::new(5));
|
||||
assert_eq!(a - b, Scale::new(-1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,18 +10,22 @@
|
|||
//! A group of side offsets, which correspond to top/left/bottom/right for borders, padding,
|
||||
//! and margins in CSS.
|
||||
|
||||
use super::UnknownUnit;
|
||||
use length::Length;
|
||||
use num::Zero;
|
||||
use core::fmt;
|
||||
use core::ops::Add;
|
||||
use core::marker::PhantomData;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A group of 2D side offsets, which correspond to top/left/bottom/right for borders, padding,
|
||||
/// and margins in CSS, optionally tagged with a unit.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedSideOffsets2D<T, U> {
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")))]
|
||||
pub struct SideOffsets2D<T, U> {
|
||||
pub top: T,
|
||||
pub right: T,
|
||||
pub bottom: T,
|
||||
|
@ -30,7 +34,45 @@ pub struct TypedSideOffsets2D<T, U> {
|
|||
pub _unit: PhantomData<U>,
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedSideOffsets2D<T, U> {
|
||||
impl<T: Copy, U> Copy for SideOffsets2D<T, U> {}
|
||||
|
||||
impl<T: Clone, U> Clone for SideOffsets2D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
SideOffsets2D {
|
||||
top: self.top.clone(),
|
||||
right: self.right.clone(),
|
||||
bottom: self.bottom.clone(),
|
||||
left: self.left.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Eq for SideOffsets2D<T, U> where T: Eq {}
|
||||
|
||||
impl<T, U> PartialEq for SideOffsets2D<T, U>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.top == other.top &&
|
||||
self.right == other.right &&
|
||||
self.bottom == other.bottom &&
|
||||
self.left == other.left
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Hash for SideOffsets2D<T, U>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.top.hash(h);
|
||||
self.right.hash(h);
|
||||
self.bottom.hash(h);
|
||||
self.left.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for SideOffsets2D<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
|
@ -40,9 +82,9 @@ impl<T: fmt::Debug, U> fmt::Debug for TypedSideOffsets2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedSideOffsets2D<T, U> {
|
||||
impl<T: Default, U> Default for SideOffsets2D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedSideOffsets2D {
|
||||
SideOffsets2D {
|
||||
top: Default::default(),
|
||||
right: Default::default(),
|
||||
bottom: Default::default(),
|
||||
|
@ -52,13 +94,10 @@ impl<T: Default, U> Default for TypedSideOffsets2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The default 2D side offset type with no unit.
|
||||
pub type SideOffsets2D<T> = TypedSideOffsets2D<T, UnknownUnit>;
|
||||
|
||||
impl<T: Copy, U> TypedSideOffsets2D<T, U> {
|
||||
impl<T: Copy, U> SideOffsets2D<T, U> {
|
||||
/// Constructor taking a scalar for each side.
|
||||
pub fn new(top: T, right: T, bottom: T, left: T) -> Self {
|
||||
TypedSideOffsets2D {
|
||||
SideOffsets2D {
|
||||
top,
|
||||
right,
|
||||
bottom,
|
||||
|
@ -74,41 +113,21 @@ impl<T: Copy, U> TypedSideOffsets2D<T, U> {
|
|||
bottom: Length<T, U>,
|
||||
left: Length<T, U>,
|
||||
) -> Self {
|
||||
TypedSideOffsets2D::new(top.0, right.0, bottom.0, left.0)
|
||||
}
|
||||
|
||||
/// Access self.top as a typed Length instead of a scalar value.
|
||||
pub fn top_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.top)
|
||||
}
|
||||
|
||||
/// Access self.right as a typed Length instead of a scalar value.
|
||||
pub fn right_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.right)
|
||||
}
|
||||
|
||||
/// Access self.bottom as a typed Length instead of a scalar value.
|
||||
pub fn bottom_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.bottom)
|
||||
}
|
||||
|
||||
/// Access self.left as a typed Length instead of a scalar value.
|
||||
pub fn left_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.left)
|
||||
SideOffsets2D::new(top.0, right.0, bottom.0, left.0)
|
||||
}
|
||||
|
||||
/// Constructor setting the same value to all sides, taking a scalar value directly.
|
||||
pub fn new_all_same(all: T) -> Self {
|
||||
TypedSideOffsets2D::new(all, all, all, all)
|
||||
SideOffsets2D::new(all, all, all, all)
|
||||
}
|
||||
|
||||
/// Constructor setting the same value to all sides, taking a typed Length.
|
||||
pub fn from_length_all_same(all: Length<T, U>) -> Self {
|
||||
TypedSideOffsets2D::new_all_same(all.0)
|
||||
SideOffsets2D::new_all_same(all.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSideOffsets2D<T, U>
|
||||
impl<T, U> SideOffsets2D<T, U>
|
||||
where
|
||||
T: Add<T, Output = T> + Copy,
|
||||
{
|
||||
|
@ -119,23 +138,15 @@ where
|
|||
pub fn vertical(&self) -> T {
|
||||
self.top + self.bottom
|
||||
}
|
||||
|
||||
pub fn horizontal_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.horizontal())
|
||||
}
|
||||
|
||||
pub fn vertical_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.vertical())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Add for TypedSideOffsets2D<T, U>
|
||||
impl<T, U> Add for SideOffsets2D<T, U>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>,
|
||||
{
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
TypedSideOffsets2D::new(
|
||||
SideOffsets2D::new(
|
||||
self.top + other.top,
|
||||
self.right + other.right,
|
||||
self.bottom + other.bottom,
|
||||
|
@ -144,9 +155,9 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Zero, U> TypedSideOffsets2D<T, U> {
|
||||
impl<T: Copy + Zero, U> SideOffsets2D<T, U> {
|
||||
/// Constructor, setting all sides to zero.
|
||||
pub fn zero() -> Self {
|
||||
TypedSideOffsets2D::new(Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
|
||||
SideOffsets2D::new(Zero::zero(), Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,53 +11,105 @@ use super::UnknownUnit;
|
|||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
use length::Length;
|
||||
use scale::TypedScale;
|
||||
use vector::{TypedVector2D, vec2, BoolVector2D};
|
||||
use vector::{TypedVector3D, vec3, BoolVector3D};
|
||||
use scale::Scale;
|
||||
use vector::{Vector2D, vec2, BoolVector2D};
|
||||
use vector::{Vector3D, vec3, BoolVector3D};
|
||||
use num::*;
|
||||
|
||||
use num_traits::{Float, NumCast, Signed};
|
||||
use core::fmt;
|
||||
use core::ops::{Add, Div, Mul, Sub};
|
||||
use core::marker::PhantomData;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
/// A 2d size tagged with a unit.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedSize2D<T, U> {
|
||||
pub struct Size2D<T, U> {
|
||||
pub width: T,
|
||||
pub height: T,
|
||||
#[doc(hidden)]
|
||||
pub _unit: PhantomData<U>,
|
||||
}
|
||||
|
||||
/// Default 2d size type with no unit.
|
||||
///
|
||||
/// `Size2D` provides the same methods as `TypedSize2D`.
|
||||
pub type Size2D<T> = TypedSize2D<T, UnknownUnit>;
|
||||
impl<T: Copy, U> Copy for Size2D<T, U> {}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedSize2D<T, U> {
|
||||
impl<T: Clone, U> Clone for Size2D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
Size2D {
|
||||
width: self.width.clone(),
|
||||
height: self.height.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T, U> serde::Deserialize<'de> for Size2D<T, U>
|
||||
where T: serde::Deserialize<'de>
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (width, height) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(Size2D { width, height, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, U> serde::Serialize for Size2D<T, U>
|
||||
where T: serde::Serialize
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: serde::Serializer
|
||||
{
|
||||
(&self.width, &self.height).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Eq for Size2D<T, U> where T: Eq {}
|
||||
|
||||
impl<T, U> PartialEq for Size2D<T, U>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.width == other.width && self.height == other.height
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Hash for Size2D<T, U>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.width.hash(h);
|
||||
self.height.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for Size2D<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}×{:?}", self.width, self.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for TypedSize2D<T, U> {
|
||||
impl<T: fmt::Display, U> fmt::Display for Size2D<T, U> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "({}x{})", self.width, self.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedSize2D<T, U> {
|
||||
impl<T: Default, U> Default for Size2D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedSize2D::new(Default::default(), Default::default())
|
||||
Size2D::new(Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize2D<T, U> {
|
||||
impl<T, U> Size2D<T, U> {
|
||||
/// Constructor taking scalar values.
|
||||
pub fn new(width: T, height: T) -> Self {
|
||||
TypedSize2D {
|
||||
Size2D {
|
||||
width,
|
||||
height,
|
||||
_unit: PhantomData,
|
||||
|
@ -65,61 +117,61 @@ impl<T, U> TypedSize2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, U> TypedSize2D<T, U> {
|
||||
impl<T: Clone, U> Size2D<T, U> {
|
||||
/// Constructor taking scalar strongly typed lengths.
|
||||
pub fn from_lengths(width: Length<T, U>, height: Length<T, U>) -> Self {
|
||||
TypedSize2D::new(width.get(), height.get())
|
||||
Size2D::new(width.get(), height.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Round, U> TypedSize2D<T, U> {
|
||||
impl<T: Round, U> Size2D<T, U> {
|
||||
/// Rounds each component to the nearest integer value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn round(&self) -> Self {
|
||||
TypedSize2D::new(self.width.round(), self.height.round())
|
||||
Size2D::new(self.width.round(), self.height.round())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ceil, U> TypedSize2D<T, U> {
|
||||
impl<T: Ceil, U> Size2D<T, U> {
|
||||
/// Rounds each component to the smallest integer equal or greater than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn ceil(&self) -> Self {
|
||||
TypedSize2D::new(self.width.ceil(), self.height.ceil())
|
||||
Size2D::new(self.width.ceil(), self.height.ceil())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Floor, U> TypedSize2D<T, U> {
|
||||
impl<T: Floor, U> Size2D<T, U> {
|
||||
/// Rounds each component to the biggest integer equal or lower than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn floor(&self) -> Self {
|
||||
TypedSize2D::new(self.width.floor(), self.height.floor())
|
||||
Size2D::new(self.width.floor(), self.height.floor())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add for TypedSize2D<T, U> {
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add for Size2D<T, U> {
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
TypedSize2D::new(self.width + other.width, self.height + other.height)
|
||||
Size2D::new(self.width + other.width, self.height + other.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedSize2D<T, U> {
|
||||
impl<T: Copy + Sub<T, Output = T>, U> Sub for Size2D<T, U> {
|
||||
type Output = Self;
|
||||
fn sub(self, other: Self) -> Self {
|
||||
TypedSize2D::new(self.width - other.width, self.height - other.height)
|
||||
Size2D::new(self.width - other.width, self.height - other.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Clone + Mul<T>, U> TypedSize2D<T, U> {
|
||||
impl<T: Copy + Clone + Mul<T>, U> Size2D<T, U> {
|
||||
pub fn area(&self) -> T::Output {
|
||||
self.width * self.height
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize2D<T, U>
|
||||
impl<T, U> Size2D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
|
@ -136,70 +188,59 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Zero + PartialOrd, U> TypedSize2D<T, U> {
|
||||
impl<T: Zero + PartialOrd, U> Size2D<T, U> {
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
let zero = T::zero();
|
||||
self.width <= zero || self.height <= zero
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> TypedSize2D<T, U> {
|
||||
impl<T: Zero, U> Size2D<T, U> {
|
||||
pub fn zero() -> Self {
|
||||
TypedSize2D::new(Zero::zero(), Zero::zero())
|
||||
Size2D::new(Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> Zero for TypedSize2D<T, U> {
|
||||
impl<T: Zero, U> Zero for Size2D<T, U> {
|
||||
fn zero() -> Self {
|
||||
TypedSize2D::new(Zero::zero(), Zero::zero())
|
||||
Size2D::new(Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedSize2D<T, U> {
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for Size2D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
TypedSize2D::new(self.width * scale, self.height * scale)
|
||||
Size2D::new(self.width * scale, self.height * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedSize2D<T, U> {
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for Size2D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
TypedSize2D::new(self.width / scale, self.height / scale)
|
||||
Size2D::new(self.width / scale, self.height / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedSize2D<T, U1> {
|
||||
type Output = TypedSize2D<T, U2>;
|
||||
impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<Scale<T, U1, U2>> for Size2D<T, U1> {
|
||||
type Output = Size2D<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedSize2D<T, U2> {
|
||||
TypedSize2D::new(self.width * scale.get(), self.height * scale.get())
|
||||
fn mul(self, scale: Scale<T, U1, U2>) -> Size2D<T, U2> {
|
||||
Size2D::new(self.width * scale.get(), self.height * scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedSize2D<T, U2> {
|
||||
type Output = TypedSize2D<T, U1>;
|
||||
impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Size2D<T, U2> {
|
||||
type Output = Size2D<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedSize2D<T, U1> {
|
||||
TypedSize2D::new(self.width / scale.get(), self.height / scale.get())
|
||||
fn div(self, scale: Scale<T, U1, U2>) -> Size2D<T, U1> {
|
||||
Size2D::new(self.width / scale.get(), self.height / scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> TypedSize2D<T, U> {
|
||||
impl<T: Copy, U> Size2D<T, U> {
|
||||
/// Returns self.width as a Length carrying the unit.
|
||||
#[inline]
|
||||
pub fn width_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.width)
|
||||
}
|
||||
|
||||
/// Returns self.height as a Length carrying the unit.
|
||||
#[inline]
|
||||
pub fn height_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.height)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_array(&self) -> [T; 2] {
|
||||
[self.width, self.height]
|
||||
|
@ -211,28 +252,28 @@ impl<T: Copy, U> TypedSize2D<T, U> {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_vector(&self) -> TypedVector2D<T, U> {
|
||||
pub fn to_vector(&self) -> Vector2D<T, U> {
|
||||
vec2(self.width, self.height)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Size2D<T> {
|
||||
TypedSize2D::new(self.width, self.height)
|
||||
pub fn to_untyped(&self) -> Size2D<T, UnknownUnit> {
|
||||
Size2D::new(self.width, self.height)
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(p: &Size2D<T>) -> Self {
|
||||
TypedSize2D::new(p.width, p.height)
|
||||
pub fn from_untyped(p: Size2D<T, UnknownUnit>) -> Self {
|
||||
Size2D::new(p.width, p.height)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
|
||||
impl<T: NumCast + Copy, Unit> Size2D<T, Unit> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> TypedSize2D<NewT, Unit> {
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> Size2D<NewT, Unit> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
|
@ -241,9 +282,9 @@ impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
|
|||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedSize2D<NewT, Unit>> {
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Size2D<NewT, Unit>> {
|
||||
match (NumCast::from(self.width), NumCast::from(self.height)) {
|
||||
(Some(w), Some(h)) => Some(TypedSize2D::new(w, h)),
|
||||
(Some(w), Some(h)) => Some(Size2D::new(w, h)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -251,12 +292,12 @@ impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
|
|||
// Convenience functions for common casts
|
||||
|
||||
/// Cast into an `f32` size.
|
||||
pub fn to_f32(&self) -> TypedSize2D<f32, Unit> {
|
||||
pub fn to_f32(&self) -> Size2D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` size.
|
||||
pub fn to_f64(&self) -> TypedSize2D<f64, Unit> {
|
||||
pub fn to_f64(&self) -> Size2D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -265,7 +306,7 @@ impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
|
|||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> TypedSize2D<usize, Unit> {
|
||||
pub fn to_usize(&self) -> Size2D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -274,7 +315,7 @@ impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
|
|||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> TypedSize2D<u32, Unit> {
|
||||
pub fn to_u32(&self) -> Size2D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -283,7 +324,7 @@ impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
|
|||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> TypedSize2D<i32, Unit> {
|
||||
pub fn to_i32(&self) -> Size2D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -292,12 +333,12 @@ impl<T: NumCast + Copy, Unit> TypedSize2D<T, Unit> {
|
|||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> TypedSize2D<i64, Unit> {
|
||||
pub fn to_i64(&self) -> Size2D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize2D<T, U>
|
||||
impl<T, U> Size2D<T, U>
|
||||
where
|
||||
T: Signed,
|
||||
{
|
||||
|
@ -310,15 +351,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd, U> TypedSize2D<T, U> {
|
||||
pub fn greater_than(&self, other: &Self) -> BoolVector2D {
|
||||
impl<T: PartialOrd, U> Size2D<T, U> {
|
||||
pub fn greater_than(&self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
x: self.width > other.width,
|
||||
y: self.height > other.height,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_than(&self, other: &Self) -> BoolVector2D {
|
||||
pub fn lower_than(&self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
x: self.width < other.width,
|
||||
y: self.height < other.height,
|
||||
|
@ -327,15 +368,15 @@ impl<T: PartialOrd, U> TypedSize2D<T, U> {
|
|||
}
|
||||
|
||||
|
||||
impl<T: PartialEq, U> TypedSize2D<T, U> {
|
||||
pub fn equal(&self, other: &Self) -> BoolVector2D {
|
||||
impl<T: PartialEq, U> Size2D<T, U> {
|
||||
pub fn equal(&self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
x: self.width == other.width,
|
||||
y: self.height == other.height,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn not_equal(&self, other: &Self) -> BoolVector2D {
|
||||
pub fn not_equal(&self, other: Self) -> BoolVector2D {
|
||||
BoolVector2D {
|
||||
x: self.width != other.width,
|
||||
y: self.height != other.height,
|
||||
|
@ -343,7 +384,7 @@ impl<T: PartialEq, U> TypedSize2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> TypedSize2D<T, U> {
|
||||
impl<T: Float, U> Size2D<T, U> {
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
size2(
|
||||
|
@ -367,15 +408,15 @@ impl<T: Float, U> TypedSize2D<T, U> {
|
|||
}
|
||||
|
||||
|
||||
/// Shorthand for `TypedSize2D::new(w, h)`.
|
||||
pub fn size2<T, U>(w: T, h: T) -> TypedSize2D<T, U> {
|
||||
TypedSize2D::new(w, h)
|
||||
/// Shorthand for `Size2D::new(w, h)`.
|
||||
pub fn size2<T, U>(w: T, h: T) -> Size2D<T, U> {
|
||||
Size2D::new(w, h)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> From<mint::Vector2<T>> for TypedSize2D<T, U> {
|
||||
impl<T, U> From<mint::Vector2<T>> for Size2D<T, U> {
|
||||
fn from(v: mint::Vector2<T>) -> Self {
|
||||
TypedSize2D {
|
||||
Size2D {
|
||||
width: v.x,
|
||||
height: v.y,
|
||||
_unit: PhantomData,
|
||||
|
@ -383,7 +424,7 @@ impl<T, U> From<mint::Vector2<T>> for TypedSize2D<T, U> {
|
|||
}
|
||||
}
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> Into<mint::Vector2<T>> for TypedSize2D<T, U> {
|
||||
impl<T, U> Into<mint::Vector2<T>> for Size2D<T, U> {
|
||||
fn into(self) -> mint::Vector2<T> {
|
||||
mint::Vector2 {
|
||||
x: self.width,
|
||||
|
@ -392,25 +433,35 @@ impl<T, U> Into<mint::Vector2<T>> for TypedSize2D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<[T; 2]> for TypedSize2D<T, U> {
|
||||
impl<T, U> From<Vector2D<T, U>> for Size2D<T, U> {
|
||||
fn from(v: Vector2D<T, U>) -> Self {
|
||||
Size2D {
|
||||
width: v.x,
|
||||
height: v.y,
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<[T; 2]> for Size2D<T, U> {
|
||||
fn into(self) -> [T; 2] {
|
||||
self.to_array()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<[T; 2]> for TypedSize2D<T, U> {
|
||||
impl<T: Copy, U> From<[T; 2]> for Size2D<T, U> {
|
||||
fn from(array: [T; 2]) -> Self {
|
||||
size2(array[0], array[1])
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> Into<(T, T)> for TypedSize2D<T, U> {
|
||||
impl<T: Copy, U> Into<(T, T)> for Size2D<T, U> {
|
||||
fn into(self) -> (T, T) {
|
||||
self.to_tuple()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> From<(T, T)> for TypedSize2D<T, U> {
|
||||
impl<T: Copy, U> From<(T, T)> for Size2D<T, U> {
|
||||
fn from(tuple: (T, T)) -> Self {
|
||||
size2(tuple.0, tuple.1)
|
||||
}
|
||||
|
@ -418,7 +469,7 @@ impl<T: Copy, U> From<(T, T)> for TypedSize2D<T, U> {
|
|||
|
||||
#[cfg(test)]
|
||||
mod size2d {
|
||||
use super::Size2D;
|
||||
use default::Size2D;
|
||||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
|
||||
|
@ -478,9 +529,8 @@ mod size2d {
|
|||
}
|
||||
|
||||
/// A 3d size tagged with a unit.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedSize3D<T, U> {
|
||||
pub struct Size3D<T, U> {
|
||||
pub width: T,
|
||||
pub height: T,
|
||||
pub depth: T,
|
||||
|
@ -488,33 +538,84 @@ pub struct TypedSize3D<T, U> {
|
|||
pub _unit: PhantomData<U>,
|
||||
}
|
||||
|
||||
/// Default 3d size type with no unit.
|
||||
///
|
||||
/// `Size3D` provides the same methods as `TypedSize3D`.
|
||||
pub type Size3D<T> = TypedSize3D<T, UnknownUnit>;
|
||||
impl<T: Copy, U> Copy for Size3D<T, U> {}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for TypedSize3D<T, U> {
|
||||
impl<T: Clone, U> Clone for Size3D<T, U> {
|
||||
fn clone(&self) -> Self {
|
||||
Size3D {
|
||||
width: self.width.clone(),
|
||||
height: self.height.clone(),
|
||||
depth: self.depth.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T, U> serde::Deserialize<'de> for Size3D<T, U>
|
||||
where T: serde::Deserialize<'de>
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (width, height, depth) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(Size3D { width, height, depth, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, U> serde::Serialize for Size3D<T, U>
|
||||
where T: serde::Serialize
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: serde::Serializer
|
||||
{
|
||||
(&self.width, &self.height, &self.depth).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Eq for Size3D<T, U> where T: Eq {}
|
||||
|
||||
impl<T, U> PartialEq for Size3D<T, U>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.width == other.width && self.height == other.height && self.depth == other.depth
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> Hash for Size3D<T, U>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.width.hash(h);
|
||||
self.height.hash(h);
|
||||
self.depth.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Debug, U> fmt::Debug for Size3D<T, U> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{:?}×{:?}×{:?}", self.width, self.height, self.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Display, U> fmt::Display for TypedSize3D<T, U> {
|
||||
impl<T: fmt::Display, U> fmt::Display for Size3D<T, U> {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(formatter, "({}x{}x{})", self.width, self.height, self.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Default, U> Default for TypedSize3D<T, U> {
|
||||
impl<T: Default, U> Default for Size3D<T, U> {
|
||||
fn default() -> Self {
|
||||
TypedSize3D::new(Default::default(), Default::default(), Default::default())
|
||||
Size3D::new(Default::default(), Default::default(), Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize3D<T, U> {
|
||||
impl<T, U> Size3D<T, U> {
|
||||
/// Constructor taking scalar values.
|
||||
pub fn new(width: T, height: T, depth: T) -> Self {
|
||||
TypedSize3D {
|
||||
Size3D {
|
||||
width,
|
||||
height,
|
||||
depth,
|
||||
|
@ -523,61 +624,61 @@ impl<T, U> TypedSize3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Clone, U> TypedSize3D<T, U> {
|
||||
impl<T: Clone, U> Size3D<T, U> {
|
||||
/// Constructor taking scalar strongly typed lengths.
|
||||
pub fn from_lengths(width: Length<T, U>, height: Length<T, U>, depth: Length<T, U>) -> Self {
|
||||
TypedSize3D::new(width.get(), height.get(), depth.get())
|
||||
Size3D::new(width.get(), height.get(), depth.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Round, U> TypedSize3D<T, U> {
|
||||
impl<T: Round, U> Size3D<T, U> {
|
||||
/// Rounds each component to the nearest integer value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn round(&self) -> Self {
|
||||
TypedSize3D::new(self.width.round(), self.height.round(), self.depth.round())
|
||||
Size3D::new(self.width.round(), self.height.round(), self.depth.round())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ceil, U> TypedSize3D<T, U> {
|
||||
impl<T: Ceil, U> Size3D<T, U> {
|
||||
/// Rounds each component to the smallest integer equal or greater than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn ceil(&self) -> Self {
|
||||
TypedSize3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
|
||||
Size3D::new(self.width.ceil(), self.height.ceil(), self.depth.ceil())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Floor, U> TypedSize3D<T, U> {
|
||||
impl<T: Floor, U> Size3D<T, U> {
|
||||
/// Rounds each component to the biggest integer equal or lower than the original value.
|
||||
///
|
||||
/// This behavior is preserved for negative values (unlike the basic cast).
|
||||
pub fn floor(&self) -> Self {
|
||||
TypedSize3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
|
||||
Size3D::new(self.width.floor(), self.height.floor(), self.depth.floor())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add for TypedSize3D<T, U> {
|
||||
impl<T: Copy + Add<T, Output = T>, U> Add for Size3D<T, U> {
|
||||
type Output = Self;
|
||||
fn add(self, other: Self) -> Self {
|
||||
TypedSize3D::new(self.width + other.width, self.height + other.height, self.depth + other.depth)
|
||||
Size3D::new(self.width + other.width, self.height + other.height, self.depth + other.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Sub<T, Output = T>, U> Sub for TypedSize3D<T, U> {
|
||||
impl<T: Copy + Sub<T, Output = T>, U> Sub for Size3D<T, U> {
|
||||
type Output = Self;
|
||||
fn sub(self, other: Self) -> Self {
|
||||
TypedSize3D::new(self.width - other.width, self.height - other.height, self.depth - other.depth)
|
||||
Size3D::new(self.width - other.width, self.height - other.height, self.depth - other.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Clone + Mul<T, Output=T>, U> TypedSize3D<T, U> {
|
||||
impl<T: Copy + Clone + Mul<T, Output=T>, U> Size3D<T, U> {
|
||||
pub fn volume(&self) -> T {
|
||||
self.width * self.height * self.depth
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize3D<T, U>
|
||||
impl<T, U> Size3D<T, U>
|
||||
where
|
||||
T: Copy + One + Add<Output = T> + Sub<Output = T> + Mul<Output = T>,
|
||||
{
|
||||
|
@ -595,104 +696,87 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Zero + PartialOrd, U> TypedSize3D<T, U> {
|
||||
impl<T: Zero + PartialOrd, U> Size3D<T, U> {
|
||||
pub fn is_empty_or_negative(&self) -> bool {
|
||||
let zero = T::zero();
|
||||
self.width <= zero || self.height <= zero || self.depth <= zero
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> TypedSize3D<T, U> {
|
||||
impl<T: Zero, U> Size3D<T, U> {
|
||||
pub fn zero() -> Self {
|
||||
TypedSize3D::new(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Zero, U> Zero for TypedSize3D<T, U> {
|
||||
impl<T: Zero, U> Zero for Size3D<T, U> {
|
||||
fn zero() -> Self {
|
||||
TypedSize3D::new(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
Size3D::new(Zero::zero(), Zero::zero(), Zero::zero())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for TypedSize3D<T, U> {
|
||||
impl<T: Copy + Mul<T, Output = T>, U> Mul<T> for Size3D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(self, scale: T) -> Self {
|
||||
TypedSize3D::new(self.width * scale, self.height * scale, self.depth * scale)
|
||||
Size3D::new(self.width * scale, self.height * scale, self.depth * scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for TypedSize3D<T, U> {
|
||||
impl<T: Copy + Div<T, Output = T>, U> Div<T> for Size3D<T, U> {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn div(self, scale: T) -> Self {
|
||||
TypedSize3D::new(self.width / scale, self.height / scale, self.depth / scale)
|
||||
Size3D::new(self.width / scale, self.height / scale, self.depth / scale)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<TypedScale<T, U1, U2>> for TypedSize3D<T, U1> {
|
||||
type Output = TypedSize3D<T, U2>;
|
||||
impl<T: Copy + Mul<T, Output = T>, U1, U2> Mul<Scale<T, U1, U2>> for Size3D<T, U1> {
|
||||
type Output = Size3D<T, U2>;
|
||||
#[inline]
|
||||
fn mul(self, scale: TypedScale<T, U1, U2>) -> TypedSize3D<T, U2> {
|
||||
TypedSize3D::new(self.width * scale.get(), self.height * scale.get(), self.depth * scale.get())
|
||||
fn mul(self, scale: Scale<T, U1, U2>) -> Size3D<T, U2> {
|
||||
Size3D::new(self.width * scale.get(), self.height * scale.get(), self.depth * scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + Div<T, Output = T>, U1, U2> Div<TypedScale<T, U1, U2>> for TypedSize3D<T, U2> {
|
||||
type Output = TypedSize3D<T, U1>;
|
||||
impl<T: Copy + Div<T, Output = T>, U1, U2> Div<Scale<T, U1, U2>> for Size3D<T, U2> {
|
||||
type Output = Size3D<T, U1>;
|
||||
#[inline]
|
||||
fn div(self, scale: TypedScale<T, U1, U2>) -> TypedSize3D<T, U1> {
|
||||
TypedSize3D::new(self.width / scale.get(), self.height / scale.get(), self.depth / scale.get())
|
||||
fn div(self, scale: Scale<T, U1, U2>) -> Size3D<T, U1> {
|
||||
Size3D::new(self.width / scale.get(), self.height / scale.get(), self.depth / scale.get())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, U> TypedSize3D<T, U> {
|
||||
impl<T: Copy, U> Size3D<T, U> {
|
||||
/// Returns self.width as a Length carrying the unit.
|
||||
#[inline]
|
||||
pub fn width_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.width)
|
||||
}
|
||||
|
||||
/// Returns self.height as a Length carrying the unit.
|
||||
#[inline]
|
||||
pub fn height_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.height)
|
||||
}
|
||||
|
||||
/// Returns self.depth as a Length carrying the unit.
|
||||
#[inline]
|
||||
pub fn depth_typed(&self) -> Length<T, U> {
|
||||
Length::new(self.depth)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_array(&self) -> [T; 3] {
|
||||
[self.width, self.height, self.depth]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn to_vector(&self) -> TypedVector3D<T, U> {
|
||||
pub fn to_vector(&self) -> Vector3D<T, U> {
|
||||
vec3(self.width, self.height, self.depth)
|
||||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Size3D<T> {
|
||||
TypedSize3D::new(self.width, self.height, self.depth)
|
||||
pub fn to_untyped(&self) -> Size3D<T, UnknownUnit> {
|
||||
Size3D::new(self.width, self.height, self.depth)
|
||||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(p: &Size3D<T>) -> Self {
|
||||
TypedSize3D::new(p.width, p.height, p.depth)
|
||||
pub fn from_untyped(p: Size3D<T, UnknownUnit>) -> Self {
|
||||
Size3D::new(p.width, p.height, p.depth)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
|
||||
impl<T: NumCast + Copy, Unit> Size3D<T, Unit> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
///
|
||||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> TypedSize3D<NewT, Unit> {
|
||||
pub fn cast<NewT: NumCast + Copy>(&self) -> Size3D<NewT, Unit> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
|
@ -701,9 +785,9 @@ impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
|
|||
/// When casting from floating point to integer coordinates, the decimals are truncated
|
||||
/// as one would expect from a simple cast, but this behavior does not always make sense
|
||||
/// geometrically. Consider using `round()`, `ceil()` or `floor()` before casting.
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<TypedSize3D<NewT, Unit>> {
|
||||
pub fn try_cast<NewT: NumCast + Copy>(&self) -> Option<Size3D<NewT, Unit>> {
|
||||
match (NumCast::from(self.width), NumCast::from(self.height), NumCast::from(self.depth)) {
|
||||
(Some(w), Some(h), Some(d)) => Some(TypedSize3D::new(w, h, d)),
|
||||
(Some(w), Some(h), Some(d)) => Some(Size3D::new(w, h, d)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -711,12 +795,12 @@ impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
|
|||
// Convenience functions for common casts
|
||||
|
||||
/// Cast into an `f32` size.
|
||||
pub fn to_f32(&self) -> TypedSize3D<f32, Unit> {
|
||||
pub fn to_f32(&self) -> Size3D<f32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
/// Cast into an `f64` size.
|
||||
pub fn to_f64(&self) -> TypedSize3D<f64, Unit> {
|
||||
pub fn to_f64(&self) -> Size3D<f64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -725,7 +809,7 @@ impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
|
|||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_usize(&self) -> TypedSize3D<usize, Unit> {
|
||||
pub fn to_usize(&self) -> Size3D<usize, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -734,7 +818,7 @@ impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
|
|||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_u32(&self) -> TypedSize3D<u32, Unit> {
|
||||
pub fn to_u32(&self) -> Size3D<u32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -743,7 +827,7 @@ impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
|
|||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i32(&self) -> TypedSize3D<i32, Unit> {
|
||||
pub fn to_i32(&self) -> Size3D<i32, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
|
||||
|
@ -752,12 +836,12 @@ impl<T: NumCast + Copy, Unit> TypedSize3D<T, Unit> {
|
|||
/// When casting from floating point sizes, it is worth considering whether
|
||||
/// to `round()`, `ceil()` or `floor()` before the cast in order to obtain
|
||||
/// the desired conversion behavior.
|
||||
pub fn to_i64(&self) -> TypedSize3D<i64, Unit> {
|
||||
pub fn to_i64(&self) -> Size3D<i64, Unit> {
|
||||
self.cast()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, U> TypedSize3D<T, U>
|
||||
impl<T, U> Size3D<T, U>
|
||||
where
|
||||
T: Signed,
|
||||
{
|
||||
|
@ -770,8 +854,8 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: PartialOrd, U> TypedSize3D<T, U> {
|
||||
pub fn greater_than(&self, other: &Self) -> BoolVector3D {
|
||||
impl<T: PartialOrd, U> Size3D<T, U> {
|
||||
pub fn greater_than(&self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width > other.width,
|
||||
y: self.height > other.height,
|
||||
|
@ -779,7 +863,7 @@ impl<T: PartialOrd, U> TypedSize3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn lower_than(&self, other: &Self) -> BoolVector3D {
|
||||
pub fn lower_than(&self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width < other.width,
|
||||
y: self.height < other.height,
|
||||
|
@ -789,8 +873,8 @@ impl<T: PartialOrd, U> TypedSize3D<T, U> {
|
|||
}
|
||||
|
||||
|
||||
impl<T: PartialEq, U> TypedSize3D<T, U> {
|
||||
pub fn equal(&self, other: &Self) -> BoolVector3D {
|
||||
impl<T: PartialEq, U> Size3D<T, U> {
|
||||
pub fn equal(&self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width == other.width,
|
||||
y: self.height == other.height,
|
||||
|
@ -798,7 +882,7 @@ impl<T: PartialEq, U> TypedSize3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn not_equal(&self, other: &Self) -> BoolVector3D {
|
||||
pub fn not_equal(&self, other: Self) -> BoolVector3D {
|
||||
BoolVector3D {
|
||||
x: self.width != other.width,
|
||||
y: self.height != other.height,
|
||||
|
@ -807,7 +891,7 @@ impl<T: PartialEq, U> TypedSize3D<T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Float, U> TypedSize3D<T, U> {
|
||||
impl<T: Float, U> Size3D<T, U> {
|
||||
#[inline]
|
||||
pub fn min(self, other: Self) -> Self {
|
||||
size3(
|
||||
|
@ -833,15 +917,15 @@ impl<T: Float, U> TypedSize3D<T, U> {
|
|||
}
|
||||
|
||||
|
||||
/// Shorthand for `TypedSize3D::new(w, h, d)`.
|
||||
pub fn size3<T, U>(w: T, h: T, d: T) -> TypedSize3D<T, U> {
|
||||
TypedSize3D::new(w, h, d)
|
||||
/// Shorthand for `Size3D::new(w, h, d)`.
|
||||
pub fn size3<T, U>(w: T, h: T, d: T) -> Size3D<T, U> {
|
||||
Size3D::new(w, h, d)
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> From<mint::Vector3<T>> for TypedSize3D<T, U> {
|
||||
impl<T, U> From<mint::Vector3<T>> for Size3D<T, U> {
|
||||
fn from(v: mint::Vector3<T>) -> Self {
|
||||
TypedSize3D {
|
||||
Size3D {
|
||||
width: v.x,
|
||||
height: v.y,
|
||||
depth: v.z,
|
||||
|
@ -850,7 +934,7 @@ impl<T, U> From<mint::Vector3<T>> for TypedSize3D<T, U> {
|
|||
}
|
||||
}
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, U> Into<mint::Vector3<T>> for TypedSize3D<T, U> {
|
||||
impl<T, U> Into<mint::Vector3<T>> for Size3D<T, U> {
|
||||
fn into(self) -> mint::Vector3<T> {
|
||||
mint::Vector3 {
|
||||
x: self.width,
|
||||
|
|
|
@ -13,23 +13,27 @@ use super::{UnknownUnit, Angle};
|
|||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
use num::{One, Zero};
|
||||
use point::TypedPoint2D;
|
||||
use vector::{TypedVector2D, vec2};
|
||||
use rect::TypedRect;
|
||||
use transform3d::TypedTransform3D;
|
||||
use point::{Point2D, point2};
|
||||
use vector::{Vector2D, vec2};
|
||||
use rect::Rect;
|
||||
use transform3d::Transform3D;
|
||||
use core::ops::{Add, Mul, Div, Sub, Neg};
|
||||
use core::marker::PhantomData;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
use approxeq::ApproxEq;
|
||||
use trig::Trig;
|
||||
use core::fmt;
|
||||
use num_traits::NumCast;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
/// A 2d transform stored as a 3 by 2 matrix in row-major order in memory.
|
||||
///
|
||||
/// Transforms can be parametrized over the source and destination units, to describe a
|
||||
/// transformation from a space to another.
|
||||
/// For example, `TypedTransform2D<f32, WorldSpace, ScreenSpace>::transform_point4d`
|
||||
/// takes a `TypedPoint2D<f32, WorldSpace>` and returns a `TypedPoint2D<f32, ScreenSpace>`.
|
||||
/// For example, `Transform2D<f32, WorldSpace, ScreenSpace>::transform_point4d`
|
||||
/// takes a `Point2D<f32, WorldSpace>` and returns a `Point2D<f32, ScreenSpace>`.
|
||||
///
|
||||
/// Transforms expose a set of convenience methods for pre- and post-transformations.
|
||||
/// A pre-transformation corresponds to adding an operation that is applied before
|
||||
|
@ -40,8 +44,7 @@ use num_traits::NumCast;
|
|||
/// a vector is `v * T`. If your library is using column vectors, use `row_major` functions when you
|
||||
/// are asked for `column_major` representations and vice versa.
|
||||
#[repr(C)]
|
||||
#[derive(EuclidMatrix)]
|
||||
pub struct TypedTransform2D<T, Src, Dst> {
|
||||
pub struct Transform2D<T, Src, Dst> {
|
||||
pub m11: T, pub m12: T,
|
||||
pub m21: T, pub m22: T,
|
||||
pub m31: T, pub m32: T,
|
||||
|
@ -49,17 +52,94 @@ pub struct TypedTransform2D<T, Src, Dst> {
|
|||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
/// The default 2d transform type with no units.
|
||||
pub type Transform2D<T> = TypedTransform2D<T, UnknownUnit, UnknownUnit>;
|
||||
impl<T: Copy, Src, Dst> Copy for Transform2D<T, Src, Dst> {}
|
||||
|
||||
impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
impl<T: Clone, Src, Dst> Clone for Transform2D<T, Src, Dst> {
|
||||
fn clone(&self) -> Self {
|
||||
Transform2D {
|
||||
m11: self.m11.clone(),
|
||||
m12: self.m12.clone(),
|
||||
m21: self.m21.clone(),
|
||||
m22: self.m22.clone(),
|
||||
m31: self.m31.clone(),
|
||||
m32: self.m32.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T, Src, Dst> serde::Deserialize<'de> for Transform2D<T, Src, Dst>
|
||||
where T: serde::Deserialize<'de>
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
m31, m32,
|
||||
) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(Transform2D {
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
m31, m32,
|
||||
_unit: PhantomData
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, Src, Dst> serde::Serialize for Transform2D<T, Src, Dst>
|
||||
where T: serde::Serialize
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: serde::Serializer
|
||||
{
|
||||
(
|
||||
&self.m11, &self.m12,
|
||||
&self.m21, &self.m22,
|
||||
&self.m31, &self.m32,
|
||||
).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Eq for Transform2D<T, Src, Dst> where T: Eq {}
|
||||
|
||||
impl<T, Src, Dst> PartialEq for Transform2D<T, Src, Dst>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.m11 == other.m11 &&
|
||||
self.m12 == other.m12 &&
|
||||
self.m21 == other.m21 &&
|
||||
self.m22 == other.m22 &&
|
||||
self.m31 == other.m31 &&
|
||||
self.m32 == other.m32
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Hash for Transform2D<T, Src, Dst>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.m11.hash(h);
|
||||
self.m12.hash(h);
|
||||
self.m21.hash(h);
|
||||
self.m22.hash(h);
|
||||
self.m31.hash(h);
|
||||
self.m32.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
/// Create a transform specifying its matrix elements in row-major order.
|
||||
///
|
||||
/// Beware: This library is written with the assumption that row vectors
|
||||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `column_major`
|
||||
pub fn row_major(m11: T, m12: T, m21: T, m22: T, m31: T, m32: T) -> Self {
|
||||
TypedTransform2D {
|
||||
Transform2D {
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
m31, m32,
|
||||
|
@ -73,7 +153,7 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
|||
/// are being used. If your matrices use column vectors (i.e. transforming a vector
|
||||
/// is `T * v`), then please use `row_major`
|
||||
pub fn column_major(m11: T, m21: T, m31: T, m12: T, m22: T, m32: T) -> Self {
|
||||
TypedTransform2D {
|
||||
Transform2D {
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
m31, m32,
|
||||
|
@ -150,7 +230,7 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
|||
}
|
||||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
pub fn to_untyped(&self) -> Transform2D<T> {
|
||||
pub fn to_untyped(&self) -> Transform2D<T, UnknownUnit, UnknownUnit> {
|
||||
Transform2D::row_major(
|
||||
self.m11, self.m12,
|
||||
self.m21, self.m22,
|
||||
|
@ -159,8 +239,8 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
|||
}
|
||||
|
||||
/// Tag a unitless value with units.
|
||||
pub fn from_untyped(p: &Transform2D<T>) -> Self {
|
||||
TypedTransform2D::row_major(
|
||||
pub fn from_untyped(p: &Transform2D<T, UnknownUnit, UnknownUnit>) -> Self {
|
||||
Transform2D::row_major(
|
||||
p.m11, p.m12,
|
||||
p.m21, p.m22,
|
||||
p.m31, p.m32
|
||||
|
@ -168,21 +248,21 @@ impl<T: Copy, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T0: NumCast + Copy, Src, Dst> TypedTransform2D<T0, Src, Dst> {
|
||||
impl<T0: NumCast + Copy, Src, Dst> Transform2D<T0, Src, Dst> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> TypedTransform2D<T1, Src, Dst> {
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Transform2D<T1, Src, Dst> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedTransform2D<T1, Src, Dst>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Transform2D<T1, Src, Dst>> {
|
||||
match (NumCast::from(self.m11), NumCast::from(self.m12),
|
||||
NumCast::from(self.m21), NumCast::from(self.m22),
|
||||
NumCast::from(self.m31), NumCast::from(self.m32)) {
|
||||
(Some(m11), Some(m12),
|
||||
Some(m21), Some(m22),
|
||||
Some(m31), Some(m32)) => {
|
||||
Some(TypedTransform2D::row_major(
|
||||
Some(Transform2D::row_major(
|
||||
m11, m12,
|
||||
m21, m22,
|
||||
m31, m32
|
||||
|
@ -193,13 +273,13 @@ impl<T0: NumCast + Copy, Src, Dst> TypedTransform2D<T0, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTransform2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Transform2D<T, Src, Dst>
|
||||
where T: Copy +
|
||||
PartialEq +
|
||||
One + Zero {
|
||||
pub fn identity() -> Self {
|
||||
let (_0, _1) = (Zero::zero(), One::one());
|
||||
TypedTransform2D::row_major(
|
||||
Transform2D::row_major(
|
||||
_1, _0,
|
||||
_0, _1,
|
||||
_0, _0
|
||||
|
@ -210,11 +290,11 @@ where T: Copy +
|
|||
// while most consumers will probably want some sort of approximate
|
||||
// equivalence to deal with floating-point errors.
|
||||
fn is_identity(&self) -> bool {
|
||||
*self == TypedTransform2D::identity()
|
||||
*self == Transform2D::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTransform2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Transform2D<T, Src, Dst>
|
||||
where T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
Mul<T, Output=T> +
|
||||
|
@ -228,9 +308,9 @@ where T: Copy + Clone +
|
|||
/// applies after self's transformation.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to self * mat
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn post_mul<NewDst>(&self, mat: &TypedTransform2D<T, Dst, NewDst>) -> TypedTransform2D<T, Src, NewDst> {
|
||||
TypedTransform2D::row_major(
|
||||
#[must_use]
|
||||
pub fn post_transform<NewDst>(&self, mat: &Transform2D<T, Dst, NewDst>) -> Transform2D<T, Src, NewDst> {
|
||||
Transform2D::row_major(
|
||||
self.m11 * mat.m11 + self.m12 * mat.m21,
|
||||
self.m11 * mat.m12 + self.m12 * mat.m22,
|
||||
self.m21 * mat.m11 + self.m22 * mat.m21,
|
||||
|
@ -244,15 +324,17 @@ where T: Copy + Clone +
|
|||
/// applies before self's transformation.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to mat * self
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn pre_mul<NewSrc>(&self, mat: &TypedTransform2D<T, NewSrc, Src>) -> TypedTransform2D<T, NewSrc, Dst> {
|
||||
mat.post_mul(self)
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn pre_transform<NewSrc>(&self, mat: &Transform2D<T, NewSrc, Src>) -> Transform2D<T, NewSrc, Dst> {
|
||||
mat.post_transform(self)
|
||||
}
|
||||
|
||||
/// Returns a translation transform.
|
||||
#[inline]
|
||||
pub fn create_translation(x: T, y: T) -> Self {
|
||||
let (_0, _1): (T, T) = (Zero::zero(), One::one());
|
||||
TypedTransform2D::row_major(
|
||||
Transform2D::row_major(
|
||||
_1, _0,
|
||||
_0, _1,
|
||||
x, y
|
||||
|
@ -260,21 +342,23 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Applies a translation after self's transformation and returns the resulting transform.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn post_translate(&self, v: TypedVector2D<T, Dst>) -> Self {
|
||||
self.post_mul(&TypedTransform2D::create_translation(v.x, v.y))
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn post_translate(&self, v: Vector2D<T, Dst>) -> Self {
|
||||
self.post_transform(&Transform2D::create_translation(v.x, v.y))
|
||||
}
|
||||
|
||||
/// Applies a translation before self's transformation and returns the resulting transform.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn pre_translate(&self, v: TypedVector2D<T, Src>) -> Self {
|
||||
self.pre_mul(&TypedTransform2D::create_translation(v.x, v.y))
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn pre_translate(&self, v: Vector2D<T, Src>) -> Self {
|
||||
self.pre_transform(&Transform2D::create_translation(v.x, v.y))
|
||||
}
|
||||
|
||||
/// Returns a scale transform.
|
||||
pub fn create_scale(x: T, y: T) -> Self {
|
||||
let _0 = Zero::zero();
|
||||
TypedTransform2D::row_major(
|
||||
Transform2D::row_major(
|
||||
x, _0,
|
||||
_0, y,
|
||||
_0, _0
|
||||
|
@ -282,15 +366,17 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Applies a scale after self's transformation and returns the resulting transform.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn post_scale(&self, x: T, y: T) -> Self {
|
||||
self.post_mul(&TypedTransform2D::create_scale(x, y))
|
||||
self.post_transform(&Transform2D::create_scale(x, y))
|
||||
}
|
||||
|
||||
/// Applies a scale before self's transformation and returns the resulting transform.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn pre_scale(&self, x: T, y: T) -> Self {
|
||||
TypedTransform2D::row_major(
|
||||
Transform2D::row_major(
|
||||
self.m11 * x, self.m12,
|
||||
self.m21, self.m22 * y,
|
||||
self.m31, self.m32
|
||||
|
@ -298,11 +384,12 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Returns a rotation transform.
|
||||
#[inline]
|
||||
pub fn create_rotation(theta: Angle<T>) -> Self {
|
||||
let _0 = Zero::zero();
|
||||
let cos = theta.get().cos();
|
||||
let sin = theta.get().sin();
|
||||
TypedTransform2D::row_major(
|
||||
Transform2D::row_major(
|
||||
cos, _0 - sin,
|
||||
sin, cos,
|
||||
_0, _0
|
||||
|
@ -310,33 +397,37 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Applies a rotation after self's transformation and returns the resulting transform.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn post_rotate(&self, theta: Angle<T>) -> Self {
|
||||
self.post_mul(&TypedTransform2D::create_rotation(theta))
|
||||
self.post_transform(&Transform2D::create_rotation(theta))
|
||||
}
|
||||
|
||||
/// Applies a rotation after self's transformation and returns the resulting transform.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
/// Applies a rotation before self's transformation and returns the resulting transform.
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn pre_rotate(&self, theta: Angle<T>) -> Self {
|
||||
self.pre_mul(&TypedTransform2D::create_rotation(theta))
|
||||
self.pre_transform(&Transform2D::create_rotation(theta))
|
||||
}
|
||||
|
||||
/// Returns the given point transformed by this transform.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn transform_point(&self, point: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
|
||||
TypedPoint2D::new(point.x * self.m11 + point.y * self.m21 + self.m31,
|
||||
point.x * self.m12 + point.y * self.m22 + self.m32)
|
||||
#[must_use]
|
||||
pub fn transform_point(&self, point: Point2D<T, Src>) -> Point2D<T, Dst> {
|
||||
Point2D::new(
|
||||
point.x * self.m11 + point.y * self.m21 + self.m31,
|
||||
point.x * self.m12 + point.y * self.m22 + self.m32
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns the given vector transformed by this matrix.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to `v * self`
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn transform_vector(&self, vec: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
|
||||
#[must_use]
|
||||
pub fn transform_vector(&self, vec: Vector2D<T, Src>) -> Vector2D<T, Dst> {
|
||||
vec2(vec.x * self.m11 + vec.y * self.m21,
|
||||
vec.x * self.m12 + vec.y * self.m22)
|
||||
}
|
||||
|
@ -344,13 +435,15 @@ where T: Copy + Clone +
|
|||
/// Returns a rectangle that encompasses the result of transforming the given rectangle by this
|
||||
/// transform.
|
||||
#[inline]
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn transform_rect(&self, rect: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
|
||||
TypedRect::from_points(&[
|
||||
self.transform_point(&rect.origin),
|
||||
self.transform_point(&rect.top_right()),
|
||||
self.transform_point(&rect.bottom_left()),
|
||||
self.transform_point(&rect.bottom_right()),
|
||||
#[must_use]
|
||||
pub fn transform_rect(&self, rect: &Rect<T, Src>) -> Rect<T, Dst> {
|
||||
let min = rect.min();
|
||||
let max = rect.max();
|
||||
Rect::from_points(&[
|
||||
self.transform_point(min),
|
||||
self.transform_point(max),
|
||||
self.transform_point(point2(max.x, min.y)),
|
||||
self.transform_point(point2(min.x, max.y)),
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -360,8 +453,8 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Returns the inverse transform if possible.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn inverse(&self) -> Option<TypedTransform2D<T, Dst, Src>> {
|
||||
#[must_use]
|
||||
pub fn inverse(&self) -> Option<Transform2D<T, Dst, Src>> {
|
||||
let det = self.determinant();
|
||||
|
||||
let _0: T = Zero::zero();
|
||||
|
@ -372,7 +465,7 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
let inv_det = _1 / det;
|
||||
Some(TypedTransform2D::row_major(
|
||||
Some(Transform2D::row_major(
|
||||
inv_det * self.m22,
|
||||
inv_det * (_0 - self.m12),
|
||||
inv_det * (_0 - self.m21),
|
||||
|
@ -384,8 +477,8 @@ where T: Copy + Clone +
|
|||
|
||||
/// Returns the same transform with a different destination unit.
|
||||
#[inline]
|
||||
pub fn with_destination<NewDst>(&self) -> TypedTransform2D<T, Src, NewDst> {
|
||||
TypedTransform2D::row_major(
|
||||
pub fn with_destination<NewDst>(&self) -> Transform2D<T, Src, NewDst> {
|
||||
Transform2D::row_major(
|
||||
self.m11, self.m12,
|
||||
self.m21, self.m22,
|
||||
self.m31, self.m32,
|
||||
|
@ -394,8 +487,8 @@ where T: Copy + Clone +
|
|||
|
||||
/// Returns the same transform with a different source unit.
|
||||
#[inline]
|
||||
pub fn with_source<NewSrc>(&self) -> TypedTransform2D<T, NewSrc, Dst> {
|
||||
TypedTransform2D::row_major(
|
||||
pub fn with_source<NewSrc>(&self) -> Transform2D<T, NewSrc, Dst> {
|
||||
Transform2D::row_major(
|
||||
self.m11, self.m12,
|
||||
self.m21, self.m22,
|
||||
self.m31, self.m32,
|
||||
|
@ -403,7 +496,7 @@ where T: Copy + Clone +
|
|||
}
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> TypedTransform2D<T, Src, Dst>
|
||||
impl <T, Src, Dst> Transform2D<T, Src, Dst>
|
||||
where T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
|
@ -414,13 +507,13 @@ where T: Copy + Clone +
|
|||
Trig +
|
||||
One + Zero {
|
||||
/// Create a 3D transform from the current transform
|
||||
pub fn to_3d(&self) -> TypedTransform3D<T, Src, Dst> {
|
||||
TypedTransform3D::row_major_2d(self.m11, self.m12, self.m21, self.m22, self.m31, self.m32)
|
||||
pub fn to_3d(&self) -> Transform3D<T, Src, Dst> {
|
||||
Transform3D::row_major_2d(self.m11, self.m12, self.m21, self.m22, self.m31, self.m32)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Default for TypedTransform2D<T, Src, Dst>
|
||||
impl <T, Src, Dst> Default for Transform2D<T, Src, Dst>
|
||||
where T: Copy + PartialEq + One + Zero
|
||||
{
|
||||
fn default() -> Self {
|
||||
|
@ -428,7 +521,7 @@ impl <T, Src, Dst> Default for TypedTransform2D<T, Src, Dst>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: ApproxEq<T>, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
||||
impl<T: ApproxEq<T>, Src, Dst> Transform2D<T, Src, Dst> {
|
||||
pub fn approx_eq(&self, other: &Self) -> bool {
|
||||
self.m11.approx_eq(&other.m11) && self.m12.approx_eq(&other.m12) &&
|
||||
self.m21.approx_eq(&other.m21) && self.m22.approx_eq(&other.m22) &&
|
||||
|
@ -436,7 +529,7 @@ impl<T: ApproxEq<T>, Src, Dst> TypedTransform2D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy + fmt::Debug, Src, Dst> fmt::Debug for TypedTransform2D<T, Src, Dst>
|
||||
impl<T: Copy + fmt::Debug, Src, Dst> fmt::Debug for Transform2D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug +
|
||||
PartialEq +
|
||||
One + Zero {
|
||||
|
@ -450,9 +543,9 @@ where T: Copy + fmt::Debug +
|
|||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, Src, Dst> From<mint::RowMatrix3x2<T>> for TypedTransform2D<T, Src, Dst> {
|
||||
impl<T, Src, Dst> From<mint::RowMatrix3x2<T>> for Transform2D<T, Src, Dst> {
|
||||
fn from(m: mint::RowMatrix3x2<T>) -> Self {
|
||||
TypedTransform2D {
|
||||
Transform2D {
|
||||
m11: m.x.x, m12: m.x.y,
|
||||
m21: m.y.x, m22: m.y.y,
|
||||
m31: m.z.x, m32: m.z.y,
|
||||
|
@ -461,7 +554,7 @@ impl<T, Src, Dst> From<mint::RowMatrix3x2<T>> for TypedTransform2D<T, Src, Dst>
|
|||
}
|
||||
}
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, Src, Dst> Into<mint::RowMatrix3x2<T>> for TypedTransform2D<T, Src, Dst> {
|
||||
impl<T, Src, Dst> Into<mint::RowMatrix3x2<T>> for Transform2D<T, Src, Dst> {
|
||||
fn into(self) -> mint::RowMatrix3x2<T> {
|
||||
mint::RowMatrix3x2 {
|
||||
x: mint::Vector2 { x: self.m11, y: self.m12 },
|
||||
|
@ -475,15 +568,14 @@ impl<T, Src, Dst> Into<mint::RowMatrix3x2<T>> for TypedTransform2D<T, Src, Dst>
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use default;
|
||||
use approxeq::ApproxEq;
|
||||
use point::Point2D;
|
||||
use Angle;
|
||||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
|
||||
use core::f32::consts::FRAC_PI_2;
|
||||
|
||||
type Mat = Transform2D<f32>;
|
||||
type Mat = default::Transform2D<f32>;
|
||||
|
||||
fn rad(v: f32) -> Angle<f32> { Angle::radians(v) }
|
||||
|
||||
|
@ -495,9 +587,9 @@ mod test {
|
|||
assert_eq!(t1, t2);
|
||||
assert_eq!(t1, t3);
|
||||
|
||||
assert_eq!(t1.transform_point(&Point2D::new(1.0, 1.0)), Point2D::new(2.0, 3.0));
|
||||
assert_eq!(t1.transform_point(Point2D::new(1.0, 1.0)), Point2D::new(2.0, 3.0));
|
||||
|
||||
assert_eq!(t1.post_mul(&t1), Mat::create_translation(2.0, 4.0));
|
||||
assert_eq!(t1.post_transform(&t1), Mat::create_translation(2.0, 4.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -508,9 +600,9 @@ mod test {
|
|||
assert_eq!(r1, r2);
|
||||
assert_eq!(r1, r3);
|
||||
|
||||
assert!(r1.transform_point(&Point2D::new(1.0, 2.0)).approx_eq(&Point2D::new(2.0, -1.0)));
|
||||
assert!(r1.transform_point(Point2D::new(1.0, 2.0)).approx_eq(&Point2D::new(2.0, -1.0)));
|
||||
|
||||
assert!(r1.post_mul(&r1).approx_eq(&Mat::create_rotation(rad(FRAC_PI_2*2.0))));
|
||||
assert!(r1.post_transform(&r1).approx_eq(&Mat::create_rotation(rad(FRAC_PI_2*2.0))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -521,7 +613,7 @@ mod test {
|
|||
assert_eq!(s1, s2);
|
||||
assert_eq!(s1, s3);
|
||||
|
||||
assert!(s1.transform_point(&Point2D::new(2.0, 2.0)).approx_eq(&Point2D::new(4.0, 6.0)));
|
||||
assert!(s1.transform_point(Point2D::new(2.0, 2.0)).approx_eq(&Point2D::new(4.0, 6.0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -550,14 +642,14 @@ mod test {
|
|||
pub fn test_inverse_scale() {
|
||||
let m1 = Mat::create_scale(1.5, 0.3);
|
||||
let m2 = m1.inverse().unwrap();
|
||||
assert!(m1.pre_mul(&m2).approx_eq(&Mat::identity()));
|
||||
assert!(m1.pre_transform(&m2).approx_eq(&Mat::identity()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_inverse_translate() {
|
||||
let m1 = Mat::create_translation(-132.0, 0.3);
|
||||
let m2 = m1.inverse().unwrap();
|
||||
assert!(m1.pre_mul(&m2).approx_eq(&Mat::identity()));
|
||||
assert!(m1.pre_transform(&m2).approx_eq(&Mat::identity()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -568,8 +660,8 @@ mod test {
|
|||
|
||||
#[test]
|
||||
pub fn test_pre_post() {
|
||||
let m1 = Transform2D::identity().post_scale(1.0, 2.0).post_translate(vec2(1.0, 2.0));
|
||||
let m2 = Transform2D::identity().pre_translate(vec2(1.0, 2.0)).pre_scale(1.0, 2.0);
|
||||
let m1 = default::Transform2D::identity().post_scale(1.0, 2.0).post_translate(vec2(1.0, 2.0));
|
||||
let m2 = default::Transform2D::identity().pre_translate(vec2(1.0, 2.0)).pre_scale(1.0, 2.0);
|
||||
assert!(m1.approx_eq(&m2));
|
||||
|
||||
let r = Mat::create_rotation(rad(FRAC_PI_2));
|
||||
|
@ -577,25 +669,25 @@ mod test {
|
|||
|
||||
let a = Point2D::new(1.0, 1.0);
|
||||
|
||||
assert!(r.post_mul(&t).transform_point(&a).approx_eq(&Point2D::new(3.0, 2.0)));
|
||||
assert!(t.post_mul(&r).transform_point(&a).approx_eq(&Point2D::new(4.0, -3.0)));
|
||||
assert!(t.post_mul(&r).transform_point(&a).approx_eq(&r.transform_point(&t.transform_point(&a))));
|
||||
assert!(r.post_transform(&t).transform_point(a).approx_eq(&Point2D::new(3.0, 2.0)));
|
||||
assert!(t.post_transform(&r).transform_point(a).approx_eq(&Point2D::new(4.0, -3.0)));
|
||||
assert!(t.post_transform(&r).transform_point(a).approx_eq(&r.transform_point(t.transform_point(a))));
|
||||
|
||||
assert!(r.pre_mul(&t).transform_point(&a).approx_eq(&Point2D::new(4.0, -3.0)));
|
||||
assert!(t.pre_mul(&r).transform_point(&a).approx_eq(&Point2D::new(3.0, 2.0)));
|
||||
assert!(t.pre_mul(&r).transform_point(&a).approx_eq(&t.transform_point(&r.transform_point(&a))));
|
||||
assert!(r.pre_transform(&t).transform_point(a).approx_eq(&Point2D::new(4.0, -3.0)));
|
||||
assert!(t.pre_transform(&r).transform_point(a).approx_eq(&Point2D::new(3.0, 2.0)));
|
||||
assert!(t.pre_transform(&r).transform_point(a).approx_eq(&t.transform_point(r.transform_point(a))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_size_of() {
|
||||
use core::mem::size_of;
|
||||
assert_eq!(size_of::<Transform2D<f32>>(), 6*size_of::<f32>());
|
||||
assert_eq!(size_of::<Transform2D<f64>>(), 6*size_of::<f64>());
|
||||
assert_eq!(size_of::<default::Transform2D<f32>>(), 6*size_of::<f32>());
|
||||
assert_eq!(size_of::<default::Transform2D<f64>>(), 6*size_of::<f64>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_is_identity() {
|
||||
let m1 = Transform2D::identity();
|
||||
let m1 = default::Transform2D::identity();
|
||||
assert!(m1.is_identity());
|
||||
let m2 = m1.post_translate(vec2(0.1, 0.0));
|
||||
assert!(!m2.is_identity());
|
||||
|
@ -606,7 +698,7 @@ mod test {
|
|||
// Translation does not apply to vectors.
|
||||
let m1 = Mat::create_translation(1.0, 1.0);
|
||||
let v1 = vec2(10.0, -10.0);
|
||||
assert_eq!(v1, m1.transform_vector(&v1));
|
||||
assert_eq!(v1, m1.transform_vector(v1));
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
|
|
|
@ -15,23 +15,27 @@ use homogen::HomogeneousVector;
|
|||
#[cfg(feature = "mint")]
|
||||
use mint;
|
||||
use trig::Trig;
|
||||
use point::{TypedPoint2D, TypedPoint3D};
|
||||
use vector::{TypedVector2D, TypedVector3D, vec2, vec3};
|
||||
use rect::TypedRect;
|
||||
use transform2d::TypedTransform2D;
|
||||
use scale::TypedScale;
|
||||
use point::{Point2D, point2, Point3D};
|
||||
use vector::{Vector2D, Vector3D, vec2, vec3};
|
||||
use rect::Rect;
|
||||
use transform2d::Transform2D;
|
||||
use scale::Scale;
|
||||
use num::{One, Zero};
|
||||
use core::ops::{Add, Mul, Sub, Div, Neg};
|
||||
use core::marker::PhantomData;
|
||||
use core::fmt;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
use num_traits::NumCast;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
/// A 3d transform stored as a 4 by 4 matrix in row-major order in memory.
|
||||
///
|
||||
/// Transforms can be parametrized over the source and destination units, to describe a
|
||||
/// transformation from a space to another.
|
||||
/// For example, `TypedTransform3D<f32, WorldSpace, ScreenSpace>::transform_point3d`
|
||||
/// takes a `TypedPoint3D<f32, WorldSpace>` and returns a `TypedPoint3D<f32, ScreenSpace>`.
|
||||
/// For example, `Transform3D<f32, WorldSpace, ScreenSpace>::transform_point3d`
|
||||
/// takes a `Point3D<f32, WorldSpace>` and returns a `Point3D<f32, ScreenSpace>`.
|
||||
///
|
||||
/// Transforms expose a set of convenience methods for pre- and post-transformations.
|
||||
/// A pre-transformation corresponds to adding an operation that is applied before
|
||||
|
@ -41,9 +45,8 @@ use num_traits::NumCast;
|
|||
/// These transforms are for working with _row vectors_, so the matrix math for transforming
|
||||
/// a vector is `v * T`. If your library is using column vectors, use `row_major` functions when you
|
||||
/// are asked for `column_major` representations and vice versa.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedTransform3D<T, Src, Dst> {
|
||||
pub struct Transform3D<T, Src, Dst> {
|
||||
pub m11: T, pub m12: T, pub m13: T, pub m14: T,
|
||||
pub m21: T, pub m22: T, pub m23: T, pub m24: T,
|
||||
pub m31: T, pub m32: T, pub m33: T, pub m34: T,
|
||||
|
@ -52,10 +55,120 @@ pub struct TypedTransform3D<T, Src, Dst> {
|
|||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
/// The default 3d transform type with no units.
|
||||
pub type Transform3D<T> = TypedTransform3D<T, UnknownUnit, UnknownUnit>;
|
||||
impl<T: Copy, Src, Dst> Copy for Transform3D<T, Src, Dst> {}
|
||||
|
||||
impl<T, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
impl<T: Clone, Src, Dst> Clone for Transform3D<T, Src, Dst> {
|
||||
fn clone(&self) -> Self {
|
||||
Transform3D {
|
||||
m11: self.m11.clone(),
|
||||
m12: self.m12.clone(),
|
||||
m13: self.m13.clone(),
|
||||
m14: self.m14.clone(),
|
||||
m21: self.m21.clone(),
|
||||
m22: self.m22.clone(),
|
||||
m23: self.m23.clone(),
|
||||
m24: self.m24.clone(),
|
||||
m31: self.m31.clone(),
|
||||
m32: self.m32.clone(),
|
||||
m33: self.m33.clone(),
|
||||
m34: self.m34.clone(),
|
||||
m41: self.m41.clone(),
|
||||
m42: self.m42.clone(),
|
||||
m43: self.m43.clone(),
|
||||
m44: self.m44.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T, Src, Dst> serde::Deserialize<'de> for Transform3D<T, Src, Dst>
|
||||
where T: serde::Deserialize<'de>
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44,
|
||||
) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(Transform3D {
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44,
|
||||
_unit: PhantomData
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, Src, Dst> serde::Serialize for Transform3D<T, Src, Dst>
|
||||
where T: serde::Serialize
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: serde::Serializer
|
||||
{
|
||||
(
|
||||
&self.m11, &self.m12, &self.m13, &self.m14,
|
||||
&self.m21, &self.m22, &self.m23, &self.m24,
|
||||
&self.m31, &self.m32, &self.m33, &self.m34,
|
||||
&self.m41, &self.m42, &self.m43, &self.m44,
|
||||
).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Eq for Transform3D<T, Src, Dst> where T: Eq {}
|
||||
|
||||
impl<T, Src, Dst> PartialEq for Transform3D<T, Src, Dst>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.m11 == other.m11 &&
|
||||
self.m12 == other.m12 &&
|
||||
self.m13 == other.m13 &&
|
||||
self.m14 == other.m14 &&
|
||||
self.m21 == other.m21 &&
|
||||
self.m22 == other.m22 &&
|
||||
self.m23 == other.m23 &&
|
||||
self.m24 == other.m24 &&
|
||||
self.m31 == other.m31 &&
|
||||
self.m32 == other.m32 &&
|
||||
self.m33 == other.m33 &&
|
||||
self.m34 == other.m34 &&
|
||||
self.m41 == other.m41 &&
|
||||
self.m42 == other.m42 &&
|
||||
self.m43 == other.m43 &&
|
||||
self.m44 == other.m44
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Hash for Transform3D<T, Src, Dst>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.m11.hash(h);
|
||||
self.m12.hash(h);
|
||||
self.m13.hash(h);
|
||||
self.m14.hash(h);
|
||||
self.m21.hash(h);
|
||||
self.m22.hash(h);
|
||||
self.m23.hash(h);
|
||||
self.m24.hash(h);
|
||||
self.m31.hash(h);
|
||||
self.m32.hash(h);
|
||||
self.m33.hash(h);
|
||||
self.m34.hash(h);
|
||||
self.m41.hash(h);
|
||||
self.m42.hash(h);
|
||||
self.m43.hash(h);
|
||||
self.m44.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Create a transform specifying its components in row-major order.
|
||||
///
|
||||
/// For example, the translation terms m41, m42, m43 on the last row with the
|
||||
|
@ -72,7 +185,7 @@ impl<T, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
|||
m31: T, m32: T, m33: T, m34: T,
|
||||
m41: T, m42: T, m43: T, m44: T)
|
||||
-> Self {
|
||||
TypedTransform3D {
|
||||
Transform3D {
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
|
@ -97,7 +210,7 @@ impl<T, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
|||
m13: T, m23: T, m33: T, m43: T,
|
||||
m14: T, m24: T, m34: T, m44: T)
|
||||
-> Self {
|
||||
TypedTransform3D {
|
||||
Transform3D {
|
||||
m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
|
@ -107,14 +220,14 @@ impl<T, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> TypedTransform3D<T, Src, Dst>
|
||||
impl <T, Src, Dst> Transform3D<T, Src, Dst>
|
||||
where T: Copy + Clone +
|
||||
PartialEq +
|
||||
One + Zero {
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
let (_0, _1): (T, T) = (Zero::zero(), One::one());
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
_1, _0, _0, _0,
|
||||
_0, _1, _0, _0,
|
||||
_0, _0, _1, _0,
|
||||
|
@ -127,11 +240,11 @@ where T: Copy + Clone +
|
|||
// equivalence to deal with floating-point errors.
|
||||
#[inline]
|
||||
fn is_identity(&self) -> bool {
|
||||
*self == TypedTransform3D::identity()
|
||||
*self == Transform3D::identity()
|
||||
}
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> TypedTransform3D<T, Src, Dst>
|
||||
impl <T, Src, Dst> Transform3D<T, Src, Dst>
|
||||
where T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
Sub<T, Output=T> +
|
||||
|
@ -147,7 +260,7 @@ where T: Copy + Clone +
|
|||
#[inline]
|
||||
pub fn row_major_2d(m11: T, m12: T, m21: T, m22: T, m41: T, m42: T) -> Self {
|
||||
let (_0, _1): (T, T) = (Zero::zero(), One::one());
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
m11, m12, _0, _0,
|
||||
m21, m22, _0, _0,
|
||||
_0, _0, _1, _0,
|
||||
|
@ -165,7 +278,7 @@ where T: Copy + Clone +
|
|||
|
||||
let (_0, _1): (T, T) = (Zero::zero(), One::one());
|
||||
let _2 = _1 + _1;
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
_2 / (right - left), _0 , _0 , _0,
|
||||
_0 , _2 / (top - bottom), _0 , _0,
|
||||
_0 , _0 , -_2 / (far - near), _0,
|
||||
|
@ -173,7 +286,7 @@ where T: Copy + Clone +
|
|||
)
|
||||
}
|
||||
|
||||
/// Returns true if this transform can be represented with a `TypedTransform2D`.
|
||||
/// Returns true if this transform can be represented with a `Transform2D`.
|
||||
///
|
||||
/// See <https://drafts.csswg.org/css-transforms/#2d-transform>
|
||||
#[inline]
|
||||
|
@ -190,8 +303,8 @@ where T: Copy + Clone +
|
|||
///
|
||||
/// This method assumes that self represents a 2d transformation, callers
|
||||
/// should check that self.is_2d() returns true beforehand.
|
||||
pub fn to_2d(&self) -> TypedTransform2D<T, Src, Dst> {
|
||||
TypedTransform2D::row_major(
|
||||
pub fn to_2d(&self) -> Transform2D<T, Src, Dst> {
|
||||
Transform2D::row_major(
|
||||
self.m11, self.m12,
|
||||
self.m21, self.m22,
|
||||
self.m41, self.m42
|
||||
|
@ -224,8 +337,8 @@ where T: Copy + Clone +
|
|||
|
||||
/// Returns the same transform with a different destination unit.
|
||||
#[inline]
|
||||
pub fn with_destination<NewDst>(&self) -> TypedTransform3D<T, Src, NewDst> {
|
||||
TypedTransform3D::row_major(
|
||||
pub fn with_destination<NewDst>(&self) -> Transform3D<T, Src, NewDst> {
|
||||
Transform3D::row_major(
|
||||
self.m11, self.m12, self.m13, self.m14,
|
||||
self.m21, self.m22, self.m23, self.m24,
|
||||
self.m31, self.m32, self.m33, self.m34,
|
||||
|
@ -235,8 +348,8 @@ where T: Copy + Clone +
|
|||
|
||||
/// Returns the same transform with a different source unit.
|
||||
#[inline]
|
||||
pub fn with_source<NewSrc>(&self) -> TypedTransform3D<T, NewSrc, Dst> {
|
||||
TypedTransform3D::row_major(
|
||||
pub fn with_source<NewSrc>(&self) -> Transform3D<T, NewSrc, Dst> {
|
||||
Transform3D::row_major(
|
||||
self.m11, self.m12, self.m13, self.m14,
|
||||
self.m21, self.m22, self.m23, self.m24,
|
||||
self.m31, self.m32, self.m33, self.m34,
|
||||
|
@ -246,7 +359,7 @@ where T: Copy + Clone +
|
|||
|
||||
/// Drop the units, preserving only the numeric value.
|
||||
#[inline]
|
||||
pub fn to_untyped(&self) -> Transform3D<T> {
|
||||
pub fn to_untyped(&self) -> Transform3D<T, UnknownUnit, UnknownUnit> {
|
||||
Transform3D::row_major(
|
||||
self.m11, self.m12, self.m13, self.m14,
|
||||
self.m21, self.m22, self.m23, self.m24,
|
||||
|
@ -257,8 +370,8 @@ where T: Copy + Clone +
|
|||
|
||||
/// Tag a unitless value with units.
|
||||
#[inline]
|
||||
pub fn from_untyped(m: &Transform3D<T>) -> Self {
|
||||
TypedTransform3D::row_major(
|
||||
pub fn from_untyped(m: &Transform3D<T, UnknownUnit, UnknownUnit>) -> Self {
|
||||
Transform3D::row_major(
|
||||
m.m11, m.m12, m.m13, m.m14,
|
||||
m.m21, m.m22, m.m23, m.m24,
|
||||
m.m31, m.m32, m.m33, m.m34,
|
||||
|
@ -270,8 +383,9 @@ where T: Copy + Clone +
|
|||
/// applies after self's transformation.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to self * mat
|
||||
pub fn post_mul<NewDst>(&self, mat: &TypedTransform3D<T, Dst, NewDst>) -> TypedTransform3D<T, Src, NewDst> {
|
||||
TypedTransform3D::row_major(
|
||||
#[must_use]
|
||||
pub fn post_transform<NewDst>(&self, mat: &Transform3D<T, Dst, NewDst>) -> Transform3D<T, Src, NewDst> {
|
||||
Transform3D::row_major(
|
||||
self.m11 * mat.m11 + self.m12 * mat.m21 + self.m13 * mat.m31 + self.m14 * mat.m41,
|
||||
self.m11 * mat.m12 + self.m12 * mat.m22 + self.m13 * mat.m32 + self.m14 * mat.m42,
|
||||
self.m11 * mat.m13 + self.m12 * mat.m23 + self.m13 * mat.m33 + self.m14 * mat.m43,
|
||||
|
@ -295,12 +409,14 @@ where T: Copy + Clone +
|
|||
/// applies before self's transformation.
|
||||
///
|
||||
/// Assuming row vectors, this is equivalent to mat * self
|
||||
pub fn pre_mul<NewSrc>(&self, mat: &TypedTransform3D<T, NewSrc, Src>) -> TypedTransform3D<T, NewSrc, Dst> {
|
||||
mat.post_mul(self)
|
||||
#[inline]
|
||||
#[must_use]
|
||||
pub fn pre_transform<NewSrc>(&self, mat: &Transform3D<T, NewSrc, Src>) -> Transform3D<T, NewSrc, Dst> {
|
||||
mat.post_transform(self)
|
||||
}
|
||||
|
||||
/// Returns the inverse transform if possible.
|
||||
pub fn inverse(&self) -> Option<TypedTransform3D<T, Dst, Src>> {
|
||||
pub fn inverse(&self) -> Option<Transform3D<T, Dst, Src>> {
|
||||
let det = self.determinant();
|
||||
|
||||
if det == Zero::zero() {
|
||||
|
@ -309,7 +425,7 @@ where T: Copy + Clone +
|
|||
|
||||
// todo(gw): this could be made faster by special casing
|
||||
// for simpler transform types.
|
||||
let m = TypedTransform3D::row_major(
|
||||
let m = Transform3D::row_major(
|
||||
self.m23*self.m34*self.m42 - self.m24*self.m33*self.m42 +
|
||||
self.m24*self.m32*self.m43 - self.m22*self.m34*self.m43 -
|
||||
self.m23*self.m32*self.m44 + self.m22*self.m33*self.m44,
|
||||
|
@ -408,9 +524,9 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Multiplies all of the transform's component by a scalar and returns the result.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn mul_s(&self, x: T) -> Self {
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
self.m11 * x, self.m12 * x, self.m13 * x, self.m14 * x,
|
||||
self.m21 * x, self.m22 * x, self.m23 * x, self.m24 * x,
|
||||
self.m31 * x, self.m32 * x, self.m33 * x, self.m34 * x,
|
||||
|
@ -418,9 +534,9 @@ where T: Copy + Clone +
|
|||
)
|
||||
}
|
||||
|
||||
/// Convenience function to create a scale transform from a `TypedScale`.
|
||||
pub fn from_scale(scale: TypedScale<T, Src, Dst>) -> Self {
|
||||
TypedTransform3D::create_scale(scale.get(), scale.get(), scale.get())
|
||||
/// Convenience function to create a scale transform from a `Scale`.
|
||||
pub fn from_scale(scale: Scale<T, Src, Dst>) -> Self {
|
||||
Transform3D::create_scale(scale.get(), scale.get(), scale.get())
|
||||
}
|
||||
|
||||
/// Returns the homogeneous vector corresponding to the transformed 2d point.
|
||||
|
@ -430,7 +546,7 @@ where T: Copy + Clone +
|
|||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
pub fn transform_point2d_homogeneous(
|
||||
&self, p: &TypedPoint2D<T, Src>
|
||||
&self, p: Point2D<T, Src>
|
||||
) -> HomogeneousVector<T, Dst> {
|
||||
let x = p.x * self.m11 + p.y * self.m21 + self.m41;
|
||||
let y = p.x * self.m12 + p.y * self.m22 + self.m42;
|
||||
|
@ -447,14 +563,14 @@ where T: Copy + Clone +
|
|||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
pub fn transform_point2d(&self, p: &TypedPoint2D<T, Src>) -> Option<TypedPoint2D<T, Dst>> {
|
||||
pub fn transform_point2d(&self, p: Point2D<T, Src>) -> Option<Point2D<T, Dst>> {
|
||||
//Note: could use `transform_point2d_homogeneous()` but it would waste the calculus of `z`
|
||||
let w = p.x * self.m14 + p.y * self.m24 + self.m44;
|
||||
if w > T::zero() {
|
||||
let x = p.x * self.m11 + p.y * self.m21 + self.m41;
|
||||
let y = p.x * self.m12 + p.y * self.m22 + self.m42;
|
||||
|
||||
Some(TypedPoint2D::new(x / w, y / w))
|
||||
Some(Point2D::new(x / w, y / w))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -466,7 +582,7 @@ where T: Copy + Clone +
|
|||
///
|
||||
/// Assuming row vectors, this is equivalent to `v * self`
|
||||
#[inline]
|
||||
pub fn transform_vector2d(&self, v: &TypedVector2D<T, Src>) -> TypedVector2D<T, Dst> {
|
||||
pub fn transform_vector2d(&self, v: Vector2D<T, Src>) -> Vector2D<T, Dst> {
|
||||
vec2(
|
||||
v.x * self.m11 + v.y * self.m21,
|
||||
v.x * self.m12 + v.y * self.m22,
|
||||
|
@ -480,7 +596,7 @@ where T: Copy + Clone +
|
|||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
pub fn transform_point3d_homogeneous(
|
||||
&self, p: &TypedPoint3D<T, Src>
|
||||
&self, p: Point3D<T, Src>
|
||||
) -> HomogeneousVector<T, Dst> {
|
||||
let x = p.x * self.m11 + p.y * self.m21 + p.z * self.m31 + self.m41;
|
||||
let y = p.x * self.m12 + p.y * self.m22 + p.z * self.m32 + self.m42;
|
||||
|
@ -497,7 +613,7 @@ where T: Copy + Clone +
|
|||
///
|
||||
/// Assuming row vectors, this is equivalent to `p * self`
|
||||
#[inline]
|
||||
pub fn transform_point3d(&self, p: &TypedPoint3D<T, Src>) -> Option<TypedPoint3D<T, Dst>> {
|
||||
pub fn transform_point3d(&self, p: Point3D<T, Src>) -> Option<Point3D<T, Dst>> {
|
||||
self.transform_point3d_homogeneous(p).to_point3d()
|
||||
}
|
||||
|
||||
|
@ -507,7 +623,7 @@ where T: Copy + Clone +
|
|||
///
|
||||
/// Assuming row vectors, this is equivalent to `v * self`
|
||||
#[inline]
|
||||
pub fn transform_vector3d(&self, v: &TypedVector3D<T, Src>) -> TypedVector3D<T, Dst> {
|
||||
pub fn transform_vector3d(&self, v: Vector3D<T, Src>) -> Vector3D<T, Dst> {
|
||||
vec3(
|
||||
v.x * self.m11 + v.y * self.m21 + v.z * self.m31,
|
||||
v.x * self.m12 + v.y * self.m22 + v.z * self.m32,
|
||||
|
@ -517,19 +633,21 @@ where T: Copy + Clone +
|
|||
|
||||
/// Returns a rectangle that encompasses the result of transforming the given rectangle by this
|
||||
/// transform, if the transform makes sense for it, or `None` otherwise.
|
||||
pub fn transform_rect(&self, rect: &TypedRect<T, Src>) -> Option<TypedRect<T, Dst>> {
|
||||
Some(TypedRect::from_points(&[
|
||||
self.transform_point2d(&rect.origin)?,
|
||||
self.transform_point2d(&rect.top_right())?,
|
||||
self.transform_point2d(&rect.bottom_left())?,
|
||||
self.transform_point2d(&rect.bottom_right())?,
|
||||
pub fn transform_rect(&self, rect: &Rect<T, Src>) -> Option<Rect<T, Dst>> {
|
||||
let min = rect.min();
|
||||
let max = rect.max();
|
||||
Some(Rect::from_points(&[
|
||||
self.transform_point2d(min)?,
|
||||
self.transform_point2d(max)?,
|
||||
self.transform_point2d(point2(max.x, min.y))?,
|
||||
self.transform_point2d(point2(min.x, max.y))?,
|
||||
]))
|
||||
}
|
||||
|
||||
/// Create a 3d translation transform
|
||||
pub fn create_translation(x: T, y: T, z: T) -> Self {
|
||||
let (_0, _1): (T, T) = (Zero::zero(), One::one());
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
_1, _0, _0, _0,
|
||||
_0, _1, _0, _0,
|
||||
_0, _0, _1, _0,
|
||||
|
@ -538,15 +656,15 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Returns a transform with a translation applied before self's transformation.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn pre_translate(&self, v: TypedVector3D<T, Src>) -> Self {
|
||||
self.pre_mul(&TypedTransform3D::create_translation(v.x, v.y, v.z))
|
||||
#[must_use]
|
||||
pub fn pre_translate(&self, v: Vector3D<T, Src>) -> Self {
|
||||
self.pre_transform(&Transform3D::create_translation(v.x, v.y, v.z))
|
||||
}
|
||||
|
||||
/// Returns a transform with a translation applied after self's transformation.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
pub fn post_translate(&self, v: TypedVector3D<T, Dst>) -> Self {
|
||||
self.post_mul(&TypedTransform3D::create_translation(v.x, v.y, v.z))
|
||||
#[must_use]
|
||||
pub fn post_translate(&self, v: Vector3D<T, Dst>) -> Self {
|
||||
self.post_transform(&Transform3D::create_translation(v.x, v.y, v.z))
|
||||
}
|
||||
|
||||
/// Returns a projection of this transform in 2d space.
|
||||
|
@ -588,7 +706,7 @@ where T: Copy + Clone +
|
|||
/// Create a 3d scale transform
|
||||
pub fn create_scale(x: T, y: T, z: T) -> Self {
|
||||
let (_0, _1): (T, T) = (Zero::zero(), One::one());
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
x, _0, _0, _0,
|
||||
_0, y, _0, _0,
|
||||
_0, _0, z, _0,
|
||||
|
@ -597,9 +715,9 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Returns a transform with a scale applied before self's transformation.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn pre_scale(&self, x: T, y: T, z: T) -> Self {
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
self.m11 * x, self.m12, self.m13, self.m14,
|
||||
self.m21 , self.m22 * y, self.m23, self.m24,
|
||||
self.m31 , self.m32, self.m33 * z, self.m34,
|
||||
|
@ -608,9 +726,9 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Returns a transform with a scale applied after self's transformation.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn post_scale(&self, x: T, y: T, z: T) -> Self {
|
||||
self.post_mul(&TypedTransform3D::create_scale(x, y, z))
|
||||
self.post_transform(&Transform3D::create_scale(x, y, z))
|
||||
}
|
||||
|
||||
/// Create a 3d rotation transform from an angle / axis.
|
||||
|
@ -627,7 +745,7 @@ where T: Copy + Clone +
|
|||
let sc = half_theta.sin() * half_theta.cos();
|
||||
let sq = half_theta.sin() * half_theta.sin();
|
||||
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
_1 - _2 * (yy + zz) * sq,
|
||||
_2 * (x * y * sq - z * sc),
|
||||
_2 * (x * z * sq + y * sc),
|
||||
|
@ -651,15 +769,15 @@ where T: Copy + Clone +
|
|||
}
|
||||
|
||||
/// Returns a transform with a rotation applied after self's transformation.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn post_rotate(&self, x: T, y: T, z: T, theta: Angle<T>) -> Self {
|
||||
self.post_mul(&TypedTransform3D::create_rotation(x, y, z, theta))
|
||||
self.post_transform(&Transform3D::create_rotation(x, y, z, theta))
|
||||
}
|
||||
|
||||
/// Returns a transform with a rotation applied before self's transformation.
|
||||
#[cfg_attr(feature = "unstable", must_use)]
|
||||
#[must_use]
|
||||
pub fn pre_rotate(&self, x: T, y: T, z: T, theta: Angle<T>) -> Self {
|
||||
self.pre_mul(&TypedTransform3D::create_rotation(x, y, z, theta))
|
||||
self.pre_transform(&Transform3D::create_rotation(x, y, z, theta))
|
||||
}
|
||||
|
||||
/// Create a 2d skew transform.
|
||||
|
@ -668,7 +786,7 @@ where T: Copy + Clone +
|
|||
pub fn create_skew(alpha: Angle<T>, beta: Angle<T>) -> Self {
|
||||
let (_0, _1): (T, T) = (Zero::zero(), One::one());
|
||||
let (sx, sy) = (beta.get().tan(), alpha.get().tan());
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
_1, sx, _0, _0,
|
||||
sy, _1, _0, _0,
|
||||
_0, _0, _1, _0,
|
||||
|
@ -679,7 +797,7 @@ where T: Copy + Clone +
|
|||
/// Create a simple perspective projection transform
|
||||
pub fn create_perspective(d: T) -> Self {
|
||||
let (_0, _1): (T, T) = (Zero::zero(), One::one());
|
||||
TypedTransform3D::row_major(
|
||||
Transform3D::row_major(
|
||||
_1, _0, _0, _0,
|
||||
_0, _1, _0, _0,
|
||||
_0, _0, _1, -_1 / d,
|
||||
|
@ -688,7 +806,7 @@ where T: Copy + Clone +
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
||||
impl<T: Copy, Src, Dst> Transform3D<T, Src, Dst> {
|
||||
/// Returns an array containing this transform's terms in row-major order (the order
|
||||
/// in which the transform is actually laid out in memory).
|
||||
///
|
||||
|
@ -781,14 +899,14 @@ impl<T: Copy, Src, Dst> TypedTransform3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T0: NumCast + Copy, Src, Dst> TypedTransform3D<T0, Src, Dst> {
|
||||
impl<T0: NumCast + Copy, Src, Dst> Transform3D<T0, Src, Dst> {
|
||||
/// Cast from one numeric representation to another, preserving the units.
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> TypedTransform3D<T1, Src, Dst> {
|
||||
pub fn cast<T1: NumCast + Copy>(&self) -> Transform3D<T1, Src, Dst> {
|
||||
self.try_cast().unwrap()
|
||||
}
|
||||
|
||||
/// Fallible cast from one numeric representation to another, preserving the units.
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<TypedTransform3D<T1, Src, Dst>> {
|
||||
pub fn try_cast<T1: NumCast + Copy>(&self) -> Option<Transform3D<T1, Src, Dst>> {
|
||||
match (NumCast::from(self.m11), NumCast::from(self.m12),
|
||||
NumCast::from(self.m13), NumCast::from(self.m14),
|
||||
NumCast::from(self.m21), NumCast::from(self.m22),
|
||||
|
@ -801,7 +919,7 @@ impl<T0: NumCast + Copy, Src, Dst> TypedTransform3D<T0, Src, Dst> {
|
|||
Some(m21), Some(m22), Some(m23), Some(m24),
|
||||
Some(m31), Some(m32), Some(m33), Some(m34),
|
||||
Some(m41), Some(m42), Some(m43), Some(m44)) => {
|
||||
Some(TypedTransform3D::row_major(m11, m12, m13, m14,
|
||||
Some(Transform3D::row_major(m11, m12, m13, m14,
|
||||
m21, m22, m23, m24,
|
||||
m31, m32, m33, m34,
|
||||
m41, m42, m43, m44))
|
||||
|
@ -811,7 +929,7 @@ impl<T0: NumCast + Copy, Src, Dst> TypedTransform3D<T0, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Default for TypedTransform3D<T, Src, Dst>
|
||||
impl <T, Src, Dst> Default for Transform3D<T, Src, Dst>
|
||||
where T: Copy + PartialEq + One + Zero
|
||||
{
|
||||
fn default() -> Self {
|
||||
|
@ -819,7 +937,7 @@ impl <T, Src, Dst> Default for TypedTransform3D<T, Src, Dst>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> fmt::Debug for TypedTransform3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> fmt::Debug for Transform3D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug +
|
||||
PartialEq +
|
||||
One + Zero {
|
||||
|
@ -833,9 +951,9 @@ where T: Copy + fmt::Debug +
|
|||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, Src, Dst> From<mint::RowMatrix4<T>> for TypedTransform3D<T, Src, Dst> {
|
||||
impl<T, Src, Dst> From<mint::RowMatrix4<T>> for Transform3D<T, Src, Dst> {
|
||||
fn from(m: mint::RowMatrix4<T>) -> Self {
|
||||
TypedTransform3D {
|
||||
Transform3D {
|
||||
m11: m.x.x, m12: m.x.y, m13: m.x.z, m14: m.x.w,
|
||||
m21: m.y.x, m22: m.y.y, m23: m.y.z, m24: m.y.w,
|
||||
m31: m.z.x, m32: m.z.y, m33: m.z.z, m34: m.z.w,
|
||||
|
@ -845,7 +963,7 @@ impl<T, Src, Dst> From<mint::RowMatrix4<T>> for TypedTransform3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
#[cfg(feature = "mint")]
|
||||
impl<T, Src, Dst> Into<mint::RowMatrix4<T>> for TypedTransform3D<T, Src, Dst> {
|
||||
impl<T, Src, Dst> Into<mint::RowMatrix4<T>> for Transform3D<T, Src, Dst> {
|
||||
fn into(self) -> mint::RowMatrix4<T> {
|
||||
mint::RowMatrix4 {
|
||||
x: mint::Vector4 { x: self.m11, y: self.m12, z: self.m13, w: self.m14 },
|
||||
|
@ -860,14 +978,13 @@ impl<T, Src, Dst> Into<mint::RowMatrix4<T>> for TypedTransform3D<T, Src, Dst> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use approxeq::ApproxEq;
|
||||
use transform2d::Transform2D;
|
||||
use point::{point2, point3};
|
||||
use Angle;
|
||||
use super::*;
|
||||
use {point2, point3};
|
||||
use default;
|
||||
|
||||
use core::f32::consts::{FRAC_PI_2, PI};
|
||||
|
||||
type Mf32 = Transform3D<f32>;
|
||||
type Mf32 = default::Transform3D<f32>;
|
||||
|
||||
// For convenience.
|
||||
fn rad(v: f32) -> Angle<f32> { Angle::radians(v) }
|
||||
|
@ -880,10 +997,10 @@ mod tests {
|
|||
assert_eq!(t1, t2);
|
||||
assert_eq!(t1, t3);
|
||||
|
||||
assert_eq!(t1.transform_point3d(&point3(1.0, 1.0, 1.0)), Some(point3(2.0, 3.0, 4.0)));
|
||||
assert_eq!(t1.transform_point2d(&point2(1.0, 1.0)), Some(point2(2.0, 3.0)));
|
||||
assert_eq!(t1.transform_point3d(point3(1.0, 1.0, 1.0)), Some(point3(2.0, 3.0, 4.0)));
|
||||
assert_eq!(t1.transform_point2d(point2(1.0, 1.0)), Some(point2(2.0, 3.0)));
|
||||
|
||||
assert_eq!(t1.post_mul(&t1), Mf32::create_translation(2.0, 4.0, 6.0));
|
||||
assert_eq!(t1.post_transform(&t1), Mf32::create_translation(2.0, 4.0, 6.0));
|
||||
|
||||
assert!(!t1.is_2d());
|
||||
assert_eq!(Mf32::create_translation(1.0, 2.0, 3.0).to_2d(), Transform2D::create_translation(1.0, 2.0));
|
||||
|
@ -897,10 +1014,10 @@ mod tests {
|
|||
assert_eq!(r1, r2);
|
||||
assert_eq!(r1, r3);
|
||||
|
||||
assert!(r1.transform_point3d(&point3(1.0, 2.0, 3.0)).unwrap().approx_eq(&point3(2.0, -1.0, 3.0)));
|
||||
assert!(r1.transform_point2d(&point2(1.0, 2.0)).unwrap().approx_eq(&point2(2.0, -1.0)));
|
||||
assert!(r1.transform_point3d(point3(1.0, 2.0, 3.0)).unwrap().approx_eq(&point3(2.0, -1.0, 3.0)));
|
||||
assert!(r1.transform_point2d(point2(1.0, 2.0)).unwrap().approx_eq(&point2(2.0, -1.0)));
|
||||
|
||||
assert!(r1.post_mul(&r1).approx_eq(&Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2*2.0))));
|
||||
assert!(r1.post_transform(&r1).approx_eq(&Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2*2.0))));
|
||||
|
||||
assert!(r1.is_2d());
|
||||
assert!(r1.to_2d().approx_eq(&Transform2D::create_rotation(rad(FRAC_PI_2))));
|
||||
|
@ -914,10 +1031,10 @@ mod tests {
|
|||
assert_eq!(s1, s2);
|
||||
assert_eq!(s1, s3);
|
||||
|
||||
assert!(s1.transform_point3d(&point3(2.0, 2.0, 2.0)).unwrap().approx_eq(&point3(4.0, 6.0, 8.0)));
|
||||
assert!(s1.transform_point2d(&point2(2.0, 2.0)).unwrap().approx_eq(&point2(4.0, 6.0)));
|
||||
assert!(s1.transform_point3d(point3(2.0, 2.0, 2.0)).unwrap().approx_eq(&point3(4.0, 6.0, 8.0)));
|
||||
assert!(s1.transform_point2d(point2(2.0, 2.0)).unwrap().approx_eq(&point2(4.0, 6.0)));
|
||||
|
||||
assert_eq!(s1.post_mul(&s1), Mf32::create_scale(4.0, 9.0, 16.0));
|
||||
assert_eq!(s1.post_transform(&s1), Mf32::create_scale(4.0, 9.0, 16.0));
|
||||
|
||||
assert!(!s1.is_2d());
|
||||
assert_eq!(Mf32::create_scale(2.0, 3.0, 0.0).to_2d(), Transform2D::create_scale(2.0, 3.0));
|
||||
|
@ -985,34 +1102,34 @@ mod tests {
|
|||
pub fn test_inverse_scale() {
|
||||
let m1 = Mf32::create_scale(1.5, 0.3, 2.1);
|
||||
let m2 = m1.inverse().unwrap();
|
||||
assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
|
||||
assert!(m1.pre_transform(&m2).approx_eq(&Mf32::identity()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_inverse_translate() {
|
||||
let m1 = Mf32::create_translation(-132.0, 0.3, 493.0);
|
||||
let m2 = m1.inverse().unwrap();
|
||||
assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
|
||||
assert!(m1.pre_transform(&m2).approx_eq(&Mf32::identity()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_inverse_rotate() {
|
||||
let m1 = Mf32::create_rotation(0.0, 1.0, 0.0, rad(1.57));
|
||||
let m2 = m1.inverse().unwrap();
|
||||
assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
|
||||
assert!(m1.pre_transform(&m2).approx_eq(&Mf32::identity()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_inverse_transform_point_2d() {
|
||||
let m1 = Mf32::create_translation(100.0, 200.0, 0.0);
|
||||
let m2 = m1.inverse().unwrap();
|
||||
assert!(m1.pre_mul(&m2).approx_eq(&Mf32::identity()));
|
||||
assert!(m1.pre_transform(&m2).approx_eq(&Mf32::identity()));
|
||||
|
||||
let p1 = point2(1000.0, 2000.0);
|
||||
let p2 = m1.transform_point2d(&p1);
|
||||
let p2 = m1.transform_point2d(p1);
|
||||
assert_eq!(p2, Some(point2(1100.0, 2200.0)));
|
||||
|
||||
let p3 = m2.transform_point2d(&p2.unwrap());
|
||||
let p3 = m2.transform_point2d(p2.unwrap());
|
||||
assert_eq!(p3, Some(p1));
|
||||
}
|
||||
|
||||
|
@ -1024,8 +1141,8 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
pub fn test_pre_post() {
|
||||
let m1 = Transform3D::identity().post_scale(1.0, 2.0, 3.0).post_translate(vec3(1.0, 2.0, 3.0));
|
||||
let m2 = Transform3D::identity().pre_translate(vec3(1.0, 2.0, 3.0)).pre_scale(1.0, 2.0, 3.0);
|
||||
let m1 = default::Transform3D::identity().post_scale(1.0, 2.0, 3.0).post_translate(vec3(1.0, 2.0, 3.0));
|
||||
let m2 = default::Transform3D::identity().pre_translate(vec3(1.0, 2.0, 3.0)).pre_scale(1.0, 2.0, 3.0);
|
||||
assert!(m1.approx_eq(&m2));
|
||||
|
||||
let r = Mf32::create_rotation(0.0, 0.0, 1.0, rad(FRAC_PI_2));
|
||||
|
@ -1033,20 +1150,20 @@ mod tests {
|
|||
|
||||
let a = point3(1.0, 1.0, 1.0);
|
||||
|
||||
assert!(r.post_mul(&t).transform_point3d(&a).unwrap().approx_eq(&point3(3.0, 2.0, 1.0)));
|
||||
assert!(t.post_mul(&r).transform_point3d(&a).unwrap().approx_eq(&point3(4.0, -3.0, 1.0)));
|
||||
assert!(t.post_mul(&r).transform_point3d(&a).unwrap().approx_eq(&r.transform_point3d(&t.transform_point3d(&a).unwrap()).unwrap()));
|
||||
assert!(r.post_transform(&t).transform_point3d(a).unwrap().approx_eq(&point3(3.0, 2.0, 1.0)));
|
||||
assert!(t.post_transform(&r).transform_point3d(a).unwrap().approx_eq(&point3(4.0, -3.0, 1.0)));
|
||||
assert!(t.post_transform(&r).transform_point3d(a).unwrap().approx_eq(&r.transform_point3d(t.transform_point3d(a).unwrap()).unwrap()));
|
||||
|
||||
assert!(r.pre_mul(&t).transform_point3d(&a).unwrap().approx_eq(&point3(4.0, -3.0, 1.0)));
|
||||
assert!(t.pre_mul(&r).transform_point3d(&a).unwrap().approx_eq(&point3(3.0, 2.0, 1.0)));
|
||||
assert!(t.pre_mul(&r).transform_point3d(&a).unwrap().approx_eq(&t.transform_point3d(&r.transform_point3d(&a).unwrap()).unwrap()));
|
||||
assert!(r.pre_transform(&t).transform_point3d(a).unwrap().approx_eq(&point3(4.0, -3.0, 1.0)));
|
||||
assert!(t.pre_transform(&r).transform_point3d(a).unwrap().approx_eq(&point3(3.0, 2.0, 1.0)));
|
||||
assert!(t.pre_transform(&r).transform_point3d(a).unwrap().approx_eq(&t.transform_point3d(r.transform_point3d(a).unwrap()).unwrap()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_size_of() {
|
||||
use core::mem::size_of;
|
||||
assert_eq!(size_of::<Transform3D<f32>>(), 16*size_of::<f32>());
|
||||
assert_eq!(size_of::<Transform3D<f64>>(), 16*size_of::<f64>());
|
||||
assert_eq!(size_of::<default::Transform3D<f32>>(), 16*size_of::<f32>());
|
||||
assert_eq!(size_of::<default::Transform3D<f64>>(), 16*size_of::<f64>());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1061,14 +1178,14 @@ mod tests {
|
|||
-2.5, 6.0, 1.0, 1.0);
|
||||
|
||||
let p = point3(1.0, 3.0, 5.0);
|
||||
let p1 = m2.pre_mul(&m1).transform_point3d(&p).unwrap();
|
||||
let p2 = m2.transform_point3d(&m1.transform_point3d(&p).unwrap()).unwrap();
|
||||
let p1 = m2.pre_transform(&m1).transform_point3d(p).unwrap();
|
||||
let p2 = m2.transform_point3d(m1.transform_point3d(p).unwrap()).unwrap();
|
||||
assert!(p1.approx_eq(&p2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_is_identity() {
|
||||
let m1 = Transform3D::identity();
|
||||
let m1 = default::Transform3D::identity();
|
||||
assert!(m1.is_identity());
|
||||
let m2 = m1.post_translate(vec3(0.1, 0.0, 0.0));
|
||||
assert!(!m2.is_identity());
|
||||
|
@ -1079,14 +1196,14 @@ mod tests {
|
|||
// Translation does not apply to vectors.
|
||||
let m = Mf32::create_translation(1.0, 2.0, 3.0);
|
||||
let v1 = vec3(10.0, -10.0, 3.0);
|
||||
assert_eq!(v1, m.transform_vector3d(&v1));
|
||||
assert_eq!(v1, m.transform_vector3d(v1));
|
||||
// While it does apply to points.
|
||||
assert_ne!(Some(v1.to_point()), m.transform_point3d(&v1.to_point()));
|
||||
assert_ne!(Some(v1.to_point()), m.transform_point3d(v1.to_point()));
|
||||
|
||||
// same thing with 2d vectors/points
|
||||
let v2 = vec2(10.0, -5.0);
|
||||
assert_eq!(v2, m.transform_vector2d(&v2));
|
||||
assert_ne!(Some(v2.to_point()), m.transform_point2d(&v2.to_point()));
|
||||
assert_eq!(v2, m.transform_vector2d(v2));
|
||||
assert_ne!(Some(v2.to_point()), m.transform_point2d(v2.to_point()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1117,11 +1234,11 @@ mod tests {
|
|||
-1.0, 1.0, -1.0, 2.0,
|
||||
);
|
||||
assert_eq!(
|
||||
m.transform_point2d_homogeneous(&point2(1.0, 2.0)),
|
||||
m.transform_point2d_homogeneous(point2(1.0, 2.0)),
|
||||
HomogeneousVector::new(6.0, 11.0, 0.0, 19.0),
|
||||
);
|
||||
assert_eq!(
|
||||
m.transform_point3d_homogeneous(&point3(1.0, 2.0, 4.0)),
|
||||
m.transform_point3d_homogeneous(point3(1.0, 2.0, 4.0)),
|
||||
HomogeneousVector::new(8.0, 7.0, 4.0, 15.0),
|
||||
);
|
||||
}
|
||||
|
@ -1130,12 +1247,12 @@ mod tests {
|
|||
pub fn test_perspective_division() {
|
||||
let p = point2(1.0, 2.0);
|
||||
let mut m = Mf32::identity();
|
||||
assert!(m.transform_point2d(&p).is_some());
|
||||
assert!(m.transform_point2d(p).is_some());
|
||||
m.m44 = 0.0;
|
||||
assert_eq!(None, m.transform_point2d(&p));
|
||||
assert_eq!(None, m.transform_point2d(p));
|
||||
m.m44 = 1.0;
|
||||
m.m24 = -1.0;
|
||||
assert_eq!(None, m.transform_point2d(&p));
|
||||
assert_eq!(None, m.transform_point2d(p));
|
||||
}
|
||||
|
||||
#[cfg(feature = "mint")]
|
||||
|
|
|
@ -7,47 +7,83 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use {TypedVector2D, TypedPoint2D, TypedVector3D, TypedPoint3D, TypedTransform2D, TypedTransform3D};
|
||||
use {TypedSize2D, TypedRect, vec2, point2, vec3, point3};
|
||||
use {Vector2D, Point2D, Vector3D, Point3D, Transform2D, Transform3D};
|
||||
use {Size2D, Rect, vec2, point2, vec3, point3};
|
||||
use num::*;
|
||||
use trig::Trig;
|
||||
use core::ops::{Add, Sub, Neg, Mul, Div};
|
||||
use core::marker::PhantomData;
|
||||
use core::fmt;
|
||||
use core::cmp::{Eq, PartialEq};
|
||||
use core::hash::{Hash};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde;
|
||||
|
||||
/// A 2d transformation from a space to another that can only express translations.
|
||||
///
|
||||
/// The main benefit of this type over a TypedVector2D is the ability to cast
|
||||
/// The main benefit of this type over a Vector2D is the ability to cast
|
||||
/// between a source and a destination spaces.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ```
|
||||
/// use euclid::{TypedTranslation2D, TypedPoint2D, point2};
|
||||
/// use euclid::{Translation2D, Point2D, point2};
|
||||
/// struct ParentSpace;
|
||||
/// struct ChildSpace;
|
||||
/// type ScrollOffset = TypedTranslation2D<i32, ParentSpace, ChildSpace>;
|
||||
/// type ParentPoint = TypedPoint2D<i32, ParentSpace>;
|
||||
/// type ChildPoint = TypedPoint2D<i32, ChildSpace>;
|
||||
/// type ScrollOffset = Translation2D<i32, ParentSpace, ChildSpace>;
|
||||
/// type ParentPoint = Point2D<i32, ParentSpace>;
|
||||
/// type ChildPoint = Point2D<i32, ChildSpace>;
|
||||
///
|
||||
/// let scrolling = ScrollOffset::new(0, 100);
|
||||
/// let p1: ParentPoint = point2(0, 0);
|
||||
/// let p2: ChildPoint = scrolling.transform_point(&p1);
|
||||
/// let p2: ChildPoint = scrolling.transform_point(p1);
|
||||
/// ```
|
||||
///
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedTranslation2D<T, Src, Dst> {
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(bound(serialize = "T: serde::Serialize", deserialize = "T: serde::Deserialize<'de>")))]
|
||||
pub struct Translation2D<T, Src, Dst> {
|
||||
pub x: T,
|
||||
pub y: T,
|
||||
#[doc(hidden)]
|
||||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst> {
|
||||
impl<T: Copy, Src, Dst> Copy for Translation2D<T, Src, Dst> {}
|
||||
|
||||
impl<T: Clone, Src, Dst> Clone for Translation2D<T, Src, Dst> {
|
||||
fn clone(&self) -> Self {
|
||||
Translation2D {
|
||||
x: self.x.clone(),
|
||||
y: self.y.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Eq for Translation2D<T, Src, Dst> where T: Eq {}
|
||||
|
||||
impl<T, Src, Dst> PartialEq for Translation2D<T, Src, Dst>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.x == other.x && self.y == other.y
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Hash for Translation2D<T, Src, Dst>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.x.hash(h);
|
||||
self.y.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst> {
|
||||
#[inline]
|
||||
pub fn new(x: T, y: T) -> Self {
|
||||
TypedTranslation2D {
|
||||
Translation2D {
|
||||
x,
|
||||
y,
|
||||
_unit: PhantomData,
|
||||
|
@ -55,7 +91,7 @@ impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T : Copy
|
||||
{
|
||||
|
@ -70,18 +106,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T : Copy + Zero
|
||||
{
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
let _0 = T::zero();
|
||||
TypedTranslation2D::new(_0, _0)
|
||||
Translation2D::new(_0, _0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Zero + PartialEq
|
||||
{
|
||||
|
@ -91,56 +127,56 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>
|
||||
{
|
||||
/// Translate a point and cast its unit.
|
||||
#[inline]
|
||||
pub fn transform_point(&self, p: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
|
||||
pub fn transform_point(&self, p: Point2D<T, Src>) -> Point2D<T, Dst> {
|
||||
point2(p.x + self.x, p.y + self.y)
|
||||
}
|
||||
|
||||
/// Translate a rectangle and cast its unit.
|
||||
#[inline]
|
||||
pub fn transform_rect(&self, r: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
|
||||
TypedRect {
|
||||
origin: self.transform_point(&r.origin),
|
||||
size: self.transform_size(&r.size),
|
||||
pub fn transform_rect(&self, r: &Rect<T, Src>) -> Rect<T, Dst> {
|
||||
Rect {
|
||||
origin: self.transform_point(r.origin),
|
||||
size: self.transform_size(r.size),
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op, just cast the unit.
|
||||
#[inline]
|
||||
pub fn transform_size(&self, s: &TypedSize2D<T, Src>) -> TypedSize2D<T, Dst> {
|
||||
TypedSize2D::new(s.width, s.height)
|
||||
pub fn transform_size(&self, s: Size2D<T, Src>) -> Size2D<T, Dst> {
|
||||
Size2D::new(s.width, s.height)
|
||||
}
|
||||
|
||||
/// Cast into a 2D vector.
|
||||
pub fn to_vector(&self) -> TypedVector2D<T, Src> {
|
||||
pub fn to_vector(&self) -> Vector2D<T, Src> {
|
||||
vec2(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Neg<Output = T>
|
||||
{
|
||||
/// Return the inverse transformation.
|
||||
#[inline]
|
||||
pub fn inverse(&self) -> TypedTranslation2D<T, Dst, Src> {
|
||||
TypedTranslation2D::new(-self.x, -self.y)
|
||||
pub fn inverse(&self) -> Translation2D<T, Dst, Src> {
|
||||
Translation2D::new(-self.x, -self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst1, Dst2> Add<TypedTranslation2D<T, Dst1, Dst2>>
|
||||
for TypedTranslation2D<T, Src, Dst1>
|
||||
impl<T, Src, Dst1, Dst2> Add<Translation2D<T, Dst1, Dst2>>
|
||||
for Translation2D<T, Src, Dst1>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>
|
||||
{
|
||||
type Output = TypedTranslation2D<T, Src, Dst2>;
|
||||
fn add(self, other: TypedTranslation2D<T, Dst1, Dst2>) -> TypedTranslation2D<T, Src, Dst2> {
|
||||
TypedTranslation2D::new(
|
||||
type Output = Translation2D<T, Src, Dst2>;
|
||||
fn add(self, other: Translation2D<T, Dst1, Dst2>) -> Translation2D<T, Src, Dst2> {
|
||||
Translation2D::new(
|
||||
self.x + other.x,
|
||||
self.y + other.y,
|
||||
)
|
||||
|
@ -148,21 +184,21 @@ where
|
|||
}
|
||||
|
||||
impl<T, Src, Dst1, Dst2>
|
||||
Sub<TypedTranslation2D<T, Dst1, Dst2>>
|
||||
for TypedTranslation2D<T, Src, Dst2>
|
||||
Sub<Translation2D<T, Dst1, Dst2>>
|
||||
for Translation2D<T, Src, Dst2>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>
|
||||
{
|
||||
type Output = TypedTranslation2D<T, Src, Dst1>;
|
||||
fn sub(self, other: TypedTranslation2D<T, Dst1, Dst2>) -> TypedTranslation2D<T, Src, Dst1> {
|
||||
TypedTranslation2D::new(
|
||||
type Output = Translation2D<T, Src, Dst1>;
|
||||
fn sub(self, other: Translation2D<T, Dst1, Dst2>) -> Translation2D<T, Src, Dst1> {
|
||||
Translation2D::new(
|
||||
self.x - other.x,
|
||||
self.y - other.y,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
|
@ -177,30 +213,30 @@ where
|
|||
{
|
||||
/// Returns the matrix representation of this translation.
|
||||
#[inline]
|
||||
pub fn to_transform(&self) -> TypedTransform2D<T, Src, Dst> {
|
||||
TypedTransform2D::create_translation(self.x, self.y)
|
||||
pub fn to_transform(&self) -> Transform2D<T, Src, Dst> {
|
||||
Transform2D::create_translation(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> From<TypedVector2D<T, Src>> for TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> From<Vector2D<T, Src>> for Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
fn from(v: TypedVector2D<T, Src>) -> Self {
|
||||
TypedTranslation2D::new(v.x, v.y)
|
||||
fn from(v: Vector2D<T, Src>) -> Self {
|
||||
Translation2D::new(v.x, v.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Into<TypedVector2D<T, Src>> for TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Into<Vector2D<T, Src>> for Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
fn into(self) -> TypedVector2D<T, Src> {
|
||||
fn into(self) -> Vector2D<T, Src> {
|
||||
vec2(self.x, self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Into<TypedTransform2D<T, Src, Dst>> for TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Into<Transform2D<T, Src, Dst>> for Translation2D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
+ Clone
|
||||
|
@ -213,12 +249,12 @@ where
|
|||
+ One
|
||||
+ Zero,
|
||||
{
|
||||
fn into(self) -> TypedTransform2D<T, Src, Dst> {
|
||||
fn into(self) -> Transform2D<T, Src, Dst> {
|
||||
self.to_transform()
|
||||
}
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Default for TypedTranslation2D<T, Src, Dst>
|
||||
impl <T, Src, Dst> Default for Translation2D<T, Src, Dst>
|
||||
where T: Copy + Zero
|
||||
{
|
||||
fn default() -> Self {
|
||||
|
@ -226,7 +262,7 @@ impl <T, Src, Dst> Default for TypedTranslation2D<T, Src, Dst>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> fmt::Debug for TypedTranslation2D<T, Src, Dst>
|
||||
impl<T, Src, Dst> fmt::Debug for Translation2D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.to_array().fmt(f)
|
||||
|
@ -237,11 +273,10 @@ where T: Copy + fmt::Debug {
|
|||
|
||||
/// A 3d transformation from a space to another that can only express translations.
|
||||
///
|
||||
/// The main benefit of this type over a TypedVector3D is the ability to cast
|
||||
/// The main benefit of this type over a Vector3D is the ability to cast
|
||||
/// between a source and a destination spaces.
|
||||
#[derive(EuclidMatrix)]
|
||||
#[repr(C)]
|
||||
pub struct TypedTranslation3D<T, Src, Dst> {
|
||||
pub struct Translation3D<T, Src, Dst> {
|
||||
pub x: T,
|
||||
pub y: T,
|
||||
pub z: T,
|
||||
|
@ -249,10 +284,66 @@ pub struct TypedTranslation3D<T, Src, Dst> {
|
|||
pub _unit: PhantomData<(Src, Dst)>,
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst> {
|
||||
impl<T: Copy, Src, Dst> Copy for Translation3D<T, Src, Dst> {}
|
||||
|
||||
impl<T: Clone, Src, Dst> Clone for Translation3D<T, Src, Dst> {
|
||||
fn clone(&self) -> Self {
|
||||
Translation3D {
|
||||
x: self.x.clone(),
|
||||
y: self.y.clone(),
|
||||
z: self.z.clone(),
|
||||
_unit: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, T, Src, Dst> serde::Deserialize<'de> for Translation3D<T, Src, Dst>
|
||||
where T: serde::Deserialize<'de>
|
||||
{
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where D: serde::Deserializer<'de>
|
||||
{
|
||||
let (x, y, z) = try!(serde::Deserialize::deserialize(deserializer));
|
||||
Ok(Translation3D { x, y, z, _unit: PhantomData })
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T, Src, Dst> serde::Serialize for Translation3D<T, Src, Dst>
|
||||
where T: serde::Serialize
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: serde::Serializer
|
||||
{
|
||||
(&self.x, &self.y, &self.z).serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Eq for Translation3D<T, Src, Dst> where T: Eq {}
|
||||
|
||||
impl<T, Src, Dst> PartialEq for Translation3D<T, Src, Dst>
|
||||
where T: PartialEq
|
||||
{
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.x == other.x && self.y == other.y && self.z == other.z
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Hash for Translation3D<T, Src, Dst>
|
||||
where T: Hash
|
||||
{
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
self.x.hash(h);
|
||||
self.y.hash(h);
|
||||
self.z.hash(h);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst> {
|
||||
#[inline]
|
||||
pub fn new(x: T, y: T, z: T) -> Self {
|
||||
TypedTranslation3D {
|
||||
Translation3D {
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
|
@ -261,7 +352,7 @@ impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
|
@ -276,18 +367,18 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Zero
|
||||
{
|
||||
#[inline]
|
||||
pub fn identity() -> Self {
|
||||
let _0 = T::zero();
|
||||
TypedTranslation3D::new(_0, _0, _0)
|
||||
Translation3D::new(_0, _0, _0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Zero + PartialEq
|
||||
{
|
||||
|
@ -297,62 +388,62 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>
|
||||
{
|
||||
/// Translate a point and cast its unit.
|
||||
#[inline]
|
||||
pub fn transform_point3d(&self, p: &TypedPoint3D<T, Src>) -> TypedPoint3D<T, Dst> {
|
||||
pub fn transform_point3d(&self, p: &Point3D<T, Src>) -> Point3D<T, Dst> {
|
||||
point3(p.x + self.x, p.y + self.y, p.z + self.z)
|
||||
}
|
||||
|
||||
/// Translate a point and cast its unit.
|
||||
#[inline]
|
||||
pub fn transform_point2d(&self, p: &TypedPoint2D<T, Src>) -> TypedPoint2D<T, Dst> {
|
||||
pub fn transform_point2d(&self, p: &Point2D<T, Src>) -> Point2D<T, Dst> {
|
||||
point2(p.x + self.x, p.y + self.y)
|
||||
}
|
||||
|
||||
/// Translate a rectangle and cast its unit.
|
||||
#[inline]
|
||||
pub fn transform_rect(&self, r: &TypedRect<T, Src>) -> TypedRect<T, Dst> {
|
||||
TypedRect {
|
||||
pub fn transform_rect(&self, r: &Rect<T, Src>) -> Rect<T, Dst> {
|
||||
Rect {
|
||||
origin: self.transform_point2d(&r.origin),
|
||||
size: self.transform_size(&r.size),
|
||||
size: self.transform_size(r.size),
|
||||
}
|
||||
}
|
||||
|
||||
/// No-op, just cast the unit.
|
||||
#[inline]
|
||||
pub fn transform_size(&self, s: &TypedSize2D<T, Src>) -> TypedSize2D<T, Dst> {
|
||||
TypedSize2D::new(s.width, s.height)
|
||||
pub fn transform_size(self, s: Size2D<T, Src>) -> Size2D<T, Dst> {
|
||||
Size2D::new(s.width, s.height)
|
||||
}
|
||||
|
||||
/// Cast into a 3D vector.
|
||||
pub fn to_vector(&self) -> TypedVector3D<T, Src> {
|
||||
pub fn to_vector(&self) -> Vector3D<T, Src> {
|
||||
vec3(self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Neg<Output = T>
|
||||
{
|
||||
/// Return the inverse transformation.
|
||||
#[inline]
|
||||
pub fn inverse(&self) -> TypedTranslation3D<T, Dst, Src> {
|
||||
TypedTranslation3D::new(-self.x, -self.y, -self.z)
|
||||
pub fn inverse(&self) -> Translation3D<T, Dst, Src> {
|
||||
Translation3D::new(-self.x, -self.y, -self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst1, Dst2> Add<TypedTranslation3D<T, Dst1, Dst2>>
|
||||
for TypedTranslation3D<T, Src, Dst1>
|
||||
impl<T, Src, Dst1, Dst2> Add<Translation3D<T, Dst1, Dst2>>
|
||||
for Translation3D<T, Src, Dst1>
|
||||
where
|
||||
T: Copy + Add<T, Output = T>
|
||||
{
|
||||
type Output = TypedTranslation3D<T, Src, Dst2>;
|
||||
fn add(self, other: TypedTranslation3D<T, Dst1, Dst2>) -> TypedTranslation3D<T, Src, Dst2> {
|
||||
TypedTranslation3D::new(
|
||||
type Output = Translation3D<T, Src, Dst2>;
|
||||
fn add(self, other: Translation3D<T, Dst1, Dst2>) -> Translation3D<T, Src, Dst2> {
|
||||
Translation3D::new(
|
||||
self.x + other.x,
|
||||
self.y + other.y,
|
||||
self.z + other.z,
|
||||
|
@ -361,14 +452,14 @@ where
|
|||
}
|
||||
|
||||
impl<T, Src, Dst1, Dst2>
|
||||
Sub<TypedTranslation3D<T, Dst1, Dst2>>
|
||||
for TypedTranslation3D<T, Src, Dst2>
|
||||
Sub<Translation3D<T, Dst1, Dst2>>
|
||||
for Translation3D<T, Src, Dst2>
|
||||
where
|
||||
T: Copy + Sub<T, Output = T>
|
||||
{
|
||||
type Output = TypedTranslation3D<T, Src, Dst1>;
|
||||
fn sub(self, other: TypedTranslation3D<T, Dst1, Dst2>) -> TypedTranslation3D<T, Src, Dst1> {
|
||||
TypedTranslation3D::new(
|
||||
type Output = Translation3D<T, Src, Dst1>;
|
||||
fn sub(self, other: Translation3D<T, Dst1, Dst2>) -> Translation3D<T, Src, Dst1> {
|
||||
Translation3D::new(
|
||||
self.x - other.x,
|
||||
self.y - other.y,
|
||||
self.z - other.z,
|
||||
|
@ -376,7 +467,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
|
@ -390,30 +481,30 @@ where
|
|||
{
|
||||
/// Returns the matrix representation of this translation.
|
||||
#[inline]
|
||||
pub fn to_transform(&self) -> TypedTransform3D<T, Src, Dst> {
|
||||
TypedTransform3D::create_translation(self.x, self.y, self.z)
|
||||
pub fn to_transform(&self) -> Transform3D<T, Src, Dst> {
|
||||
Transform3D::create_translation(self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> From<TypedVector3D<T, Src>> for TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> From<Vector3D<T, Src>> for Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
fn from(v: TypedVector3D<T, Src>) -> Self {
|
||||
TypedTranslation3D::new(v.x, v.y, v.z)
|
||||
fn from(v: Vector3D<T, Src>) -> Self {
|
||||
Translation3D::new(v.x, v.y, v.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Into<TypedVector3D<T, Src>> for TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Into<Vector3D<T, Src>> for Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy
|
||||
{
|
||||
fn into(self) -> TypedVector3D<T, Src> {
|
||||
fn into(self) -> Vector3D<T, Src> {
|
||||
vec3(self.x, self.y, self.z)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> Into<TypedTransform3D<T, Src, Dst>> for TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> Into<Transform3D<T, Src, Dst>> for Translation3D<T, Src, Dst>
|
||||
where
|
||||
T: Copy + Clone +
|
||||
Add<T, Output=T> +
|
||||
|
@ -425,12 +516,12 @@ where
|
|||
Trig +
|
||||
One + Zero,
|
||||
{
|
||||
fn into(self) -> TypedTransform3D<T, Src, Dst> {
|
||||
fn into(self) -> Transform3D<T, Src, Dst> {
|
||||
self.to_transform()
|
||||
}
|
||||
}
|
||||
|
||||
impl <T, Src, Dst> Default for TypedTranslation3D<T, Src, Dst>
|
||||
impl <T, Src, Dst> Default for Translation3D<T, Src, Dst>
|
||||
where T: Copy + Zero
|
||||
{
|
||||
fn default() -> Self {
|
||||
|
@ -438,7 +529,7 @@ impl <T, Src, Dst> Default for TypedTranslation3D<T, Src, Dst>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, Src, Dst> fmt::Debug for TypedTranslation3D<T, Src, Dst>
|
||||
impl<T, Src, Dst> fmt::Debug for Translation3D<T, Src, Dst>
|
||||
where T: Copy + fmt::Debug {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.to_array().fmt(f)
|
||||
|
@ -452,9 +543,9 @@ fn simple_translation2d() {
|
|||
struct A;
|
||||
struct B;
|
||||
|
||||
type Translation = TypedTranslation2D<i32, A, B>;
|
||||
type SrcRect = TypedRect<i32, A>;
|
||||
type DstRect = TypedRect<i32, B>;
|
||||
type Translation = Translation2D<i32, A, B>;
|
||||
type SrcRect = Rect<i32, A>;
|
||||
type DstRect = Rect<i32, B>;
|
||||
|
||||
let tx = Translation::new(10, -10);
|
||||
let r1: SrcRect = rect(10, 20, 30, 40);
|
||||
|
@ -472,9 +563,9 @@ fn simple_translation3d() {
|
|||
struct A;
|
||||
struct B;
|
||||
|
||||
type Translation = TypedTranslation3D<i32, A, B>;
|
||||
type SrcPoint = TypedPoint3D<i32, A>;
|
||||
type DstPoint = TypedPoint3D<i32, B>;
|
||||
type Translation = Translation3D<i32, A, B>;
|
||||
type SrcPoint = Point3D<i32, A>;
|
||||
type DstPoint = Point3D<i32, B>;
|
||||
|
||||
let tx = Translation::new(10, -10, 100);
|
||||
let p1: SrcPoint = point3(10, 20, 30);
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1 +0,0 @@
|
|||
{"files":{"Cargo.toml":"12f4357876f09242153fbbd912c70861b03d5a8f983fce3de0d3696389452be6","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"62065228e42caebca7e7d7db1204cbb867033de5982ca4009928915e4095f3a3","euclid_matrix.rs":"0643b38d8284278c3d54a3791aa0eae7edd5f73a54e1edec38e1bcdb4af66e0b","lib.rs":"845b9a82365e06d51edce03560a5abe617f955c9c640e90140c87fb594c65fbd"},"package":"fdcb84c18ea5037a1c5a23039b4ff29403abce2e0d6b1daa11cf0bde2b30be15"}
|
|
@ -1,31 +0,0 @@
|
|||
# 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 believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
# editing this file be aware that the upstream Cargo.toml
|
||||
# will likely look very different (and much more reasonable)
|
||||
|
||||
[package]
|
||||
name = "euclid_macros"
|
||||
version = "0.1.0"
|
||||
authors = ["Emilio Cobos Álvarez <emilio@crisal.io>", "The Servo project developers"]
|
||||
description = "Euclid implementation detail"
|
||||
license = "MIT / Apache-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
proc-macro = true
|
||||
[dependencies.proc-macro2]
|
||||
version = "0.4"
|
||||
|
||||
[dependencies.quote]
|
||||
version = "0.6"
|
||||
|
||||
[dependencies.syn]
|
||||
version = "0.15"
|
||||
features = ["visit"]
|
|
@ -1,201 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -1,25 +0,0 @@
|
|||
Copyright (c) 2012-2013 Mozilla Foundation
|
||||
|
||||
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.
|
|
@ -1,247 +0,0 @@
|
|||
use proc_macro2::TokenStream;
|
||||
use syn::{self, DeriveInput};
|
||||
|
||||
type Fields = syn::punctuated::Punctuated<syn::Field, syn::token::Comma>;
|
||||
|
||||
fn derive_trait<F>(
|
||||
input: &DeriveInput,
|
||||
trait_name: TokenStream,
|
||||
generics: &syn::Generics,
|
||||
body: F
|
||||
) -> TokenStream
|
||||
where
|
||||
F: FnOnce() -> TokenStream,
|
||||
{
|
||||
let struct_name = &input.ident;
|
||||
|
||||
let (impl_generics, _, where_clause) = generics.split_for_impl();
|
||||
let (_, ty_generics, _) = input.generics.split_for_impl();
|
||||
|
||||
let body = body();
|
||||
quote! {
|
||||
impl #impl_generics #trait_name for #struct_name #ty_generics #where_clause {
|
||||
#body
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn derive_simple_trait<F>(
|
||||
input: &DeriveInput,
|
||||
trait_name: TokenStream,
|
||||
t: &syn::TypeParam,
|
||||
body: F,
|
||||
) -> TokenStream
|
||||
where
|
||||
F: FnOnce() -> TokenStream,
|
||||
{
|
||||
let mut generics = input.generics.clone();
|
||||
generics
|
||||
.make_where_clause()
|
||||
.predicates
|
||||
.push(parse_quote!(#t: #trait_name));
|
||||
derive_trait(input, trait_name, &generics, body)
|
||||
}
|
||||
|
||||
fn each_field_except_unit<F>(
|
||||
fields: &Fields,
|
||||
unit: &syn::Field,
|
||||
mut field_expr: F,
|
||||
) -> TokenStream
|
||||
where
|
||||
F: FnMut(&syn::Ident) -> TokenStream,
|
||||
{
|
||||
fields.iter().filter(|f| f.ident != unit.ident).fold(quote! {}, |body, field| {
|
||||
let name = field.ident.as_ref().unwrap();
|
||||
let expr = field_expr(name);
|
||||
quote! {
|
||||
#body
|
||||
#expr
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
fn derive_struct_body<F>(
|
||||
fields: &Fields,
|
||||
unit: &syn::Field,
|
||||
mut field_expr: F,
|
||||
) -> TokenStream
|
||||
where
|
||||
F: FnMut(&syn::Ident) -> TokenStream,
|
||||
{
|
||||
let body = each_field_except_unit(fields, unit, |name| {
|
||||
let expr = field_expr(name);
|
||||
quote! {
|
||||
#name: #expr,
|
||||
}
|
||||
});
|
||||
|
||||
let unit_name = unit.ident.as_ref().unwrap();
|
||||
quote! {
|
||||
Self {
|
||||
#body
|
||||
#unit_name: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
|
||||
derive_simple_trait(input, quote! { Clone }, t, || {
|
||||
let body = derive_struct_body(fields, unit, |name| {
|
||||
quote! { self.#name.clone() }
|
||||
});
|
||||
quote! {
|
||||
fn clone(&self) -> Self {
|
||||
#body
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn copy_impl(input: &DeriveInput, t: &syn::TypeParam) -> TokenStream {
|
||||
derive_simple_trait(input, quote!{ Copy }, t, || quote! {})
|
||||
}
|
||||
|
||||
fn eq_impl(input: &DeriveInput, t: &syn::TypeParam) -> TokenStream {
|
||||
derive_simple_trait(input, quote!{ ::core::cmp::Eq }, t, || quote! {})
|
||||
}
|
||||
|
||||
fn partialeq_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
|
||||
derive_simple_trait(input, quote!{ ::core::cmp::PartialEq }, t, || {
|
||||
let body = each_field_except_unit(fields, unit, |name| {
|
||||
quote! { && self.#name == other.#name }
|
||||
});
|
||||
|
||||
quote! {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
true #body
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn hash_impl(input: &DeriveInput, fields: &Fields, unit: &syn::Field, t: &syn::TypeParam) -> TokenStream {
|
||||
derive_simple_trait(input, quote!{ ::core::hash::Hash }, t, || {
|
||||
let body = each_field_except_unit(fields, unit, |name| {
|
||||
quote! { self.#name.hash(h); }
|
||||
});
|
||||
|
||||
quote! {
|
||||
fn hash<H: ::core::hash::Hasher>(&self, h: &mut H) {
|
||||
#body
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn serde_impl(
|
||||
input: &DeriveInput,
|
||||
fields: &Fields,
|
||||
unit: &syn::Field,
|
||||
t: &syn::TypeParam,
|
||||
) -> TokenStream {
|
||||
let deserialize_impl = {
|
||||
let mut generics = input.generics.clone();
|
||||
generics.params.insert(0, parse_quote!('de));
|
||||
generics
|
||||
.make_where_clause()
|
||||
.predicates
|
||||
.push(parse_quote!(#t: ::serde::Deserialize<'de>));
|
||||
derive_trait(input, quote!{ ::serde::Deserialize<'de> }, &generics, || {
|
||||
let tuple = each_field_except_unit(fields, unit, |name| {
|
||||
quote! { #name, }
|
||||
});
|
||||
let body = derive_struct_body(fields, unit, |name| quote! { #name });
|
||||
quote! {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: ::serde::Deserializer<'de>,
|
||||
{
|
||||
let (#tuple) = ::serde::Deserialize::deserialize(deserializer)?;
|
||||
Ok(#body)
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let serialize_impl = derive_simple_trait(input, quote! { ::serde::Serialize }, t, || {
|
||||
let tuple = each_field_except_unit(fields, unit, |name| {
|
||||
quote! { &self.#name, }
|
||||
});
|
||||
quote! {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: ::serde::Serializer,
|
||||
{
|
||||
(#tuple).serialize(serializer)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
quote! {
|
||||
#[cfg(feature = "serde")]
|
||||
#serialize_impl
|
||||
#[cfg(feature = "serde")]
|
||||
#deserialize_impl
|
||||
}
|
||||
}
|
||||
|
||||
pub fn derive(input: DeriveInput) -> TokenStream {
|
||||
let s = match input.data {
|
||||
syn::Data::Struct(ref s) => s,
|
||||
_ => panic!("Need to derive this on a struct"),
|
||||
};
|
||||
|
||||
let fields = match s.fields {
|
||||
syn::Fields::Named(ref named) => &named.named,
|
||||
_ => panic!("Need to use named fields"),
|
||||
};
|
||||
|
||||
assert!(!fields.is_empty());
|
||||
|
||||
let unit_field = fields.last().unwrap();
|
||||
assert_eq!(
|
||||
unit_field.value().ident.as_ref().unwrap().to_string(),
|
||||
"_unit",
|
||||
"You need to have a _unit field to derive this trait",
|
||||
);
|
||||
|
||||
assert!(match unit_field.value().vis {
|
||||
syn::Visibility::Public(..) => true,
|
||||
_ => false,
|
||||
}, "Unit field should be public");
|
||||
|
||||
assert!(input.attrs.iter().filter_map(|attr| attr.interpret_meta()).any(|attr| {
|
||||
match attr {
|
||||
syn::Meta::Word(..) |
|
||||
syn::Meta::NameValue(..) => false,
|
||||
syn::Meta::List(ref list) => {
|
||||
list.ident == "repr" && list.nested.iter().any(|meta| {
|
||||
match *meta {
|
||||
syn::NestedMeta::Meta(syn::Meta::Word(ref w)) => w == "C",
|
||||
_ => false,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}), "struct should be #[repr(C)]");
|
||||
|
||||
let type_param =
|
||||
input.generics.type_params().next().cloned().expect("Need a T");
|
||||
|
||||
let clone = clone_impl(&input, fields, unit_field.value(), &type_param);
|
||||
let copy = copy_impl(&input, &type_param);
|
||||
let serde = serde_impl(&input, fields, unit_field.value(), &type_param);
|
||||
let eq = eq_impl(&input, &type_param);
|
||||
let partialeq = partialeq_impl(&input, fields, unit_field.value(), &type_param);
|
||||
let hash = hash_impl(&input, fields, unit_field.value(), &type_param);
|
||||
|
||||
quote! {
|
||||
#clone
|
||||
#copy
|
||||
#serde
|
||||
#eq
|
||||
#partialeq
|
||||
#hash
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
extern crate proc_macro;
|
||||
extern crate proc_macro2;
|
||||
#[macro_use]
|
||||
extern crate quote;
|
||||
#[macro_use]
|
||||
extern crate syn;
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
|
||||
mod euclid_matrix;
|
||||
|
||||
#[proc_macro_derive(EuclidMatrix)]
|
||||
pub fn derive_euclid_matrix(input: TokenStream) -> TokenStream {
|
||||
let input = syn::parse(input).unwrap();
|
||||
euclid_matrix::derive(input).into()
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"files":{"Cargo.toml":"73beabab6ca9844d6746f5946e01a97a60c9a4f0276076a9592265135bda649b","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"a65ed5c817c867fe23bc2029f34baea4a645a07dd5d101a0027e796d2923be58","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"2ccdca9bfc7d9a52621fcf91c441e924eb2068291b48daa8235ec000932a7790","src/clip.rs":"b58bb753b85b822eee2a0a88ea4eb5dff6a69276168ca61202486a6fb95eb95e","src/lib.rs":"57a6c885819b18ead087968937017b6330378bdcc10f285052c9d76e7a1b2226","src/polygon.rs":"e50f6671f953f6811f97a3b92e90e4a268c0d520e73528ba28a746f09e04c7ab","tests/clip.rs":"3335364fd6849697d3919084be5dce6c49acb31d8c53adc93a4cd05ee2ea93a9","tests/main.rs":"7c50a23d32eb8b0742bd533e98ba95c96110c4773b27ae0c40121c347feb9325","tests/split.rs":"88fe8192f8e0d03ac2b4b526c377ceeccbee4e3c35f4fa00be160d1402af09a2"},"package":"91c621d83b9c5a85b7ca7ca2bec643136debb327ad29d0a08768db1325780365"}
|
||||
{"files":{"Cargo.toml":"2770453e4940bce81fed8d763daec0eecefcb4d14b1f296e467ef6ac22c24bfc","LICENSE":"b946744aeda89b467929585fe8eeb5461847695220c1b168fb375d8abd4ea3d0","README.md":"a65ed5c817c867fe23bc2029f34baea4a645a07dd5d101a0027e796d2923be58","benches/split.rs":"632a011dfc6d8235dea853785061b7bbfe0362eb85b91b3b01fbf77a7f1c7f26","src/bsp.rs":"964182582d53a160a86809231c61ba6512f38dde14b83c42b8145ef782064d30","src/clip.rs":"edb729a136706ad2e0d93fb8f79ec27ba9e1128d0debd2350e458d67beceb192","src/lib.rs":"aec71888fa99939b02e3fa3486817ce0d49d5bd5dc8e857fadbf7f48f24bf111","src/polygon.rs":"305af53f5d9334a10481f32ff60729e43e8c497d563c72e926b67dd7b68a261e","tests/clip.rs":"64e24fa6ea0ce05a7bfb837ef0e827f11a4c1c096cbac68283b74a2b32c47bb3","tests/main.rs":"238b0108b4605b8f7c77b2a886c9fb6ccb5ddc2644def166afb4eaedaec3a7c7","tests/split.rs":"f8f0784b9d2f1b3dbc0a0f25fc667ec3aa301b2ae4346f5b7ca0024c535570bc"},"package":"91821c7436aefc1b912552d494232efcaf9810c0189918749532be1e9dbace59"}
|
|
@ -3,7 +3,7 @@
|
|||
# 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
|
||||
# to registry (e.g., crates.io) dependencies
|
||||
#
|
||||
# If you believe there's an error in this file please file an
|
||||
# issue against the rust-lang/cargo repository. If you're
|
||||
|
@ -12,7 +12,7 @@
|
|||
|
||||
[package]
|
||||
name = "plane-split"
|
||||
version = "0.13.8"
|
||||
version = "0.14.0"
|
||||
authors = ["Dzmitry Malyshau <kvark@mozilla.com>"]
|
||||
description = "Plane splitting"
|
||||
documentation = "https://docs.rs/plane-split"
|
||||
|
@ -23,7 +23,7 @@ repository = "https://github.com/servo/plane-split"
|
|||
version = "0.1.2"
|
||||
|
||||
[dependencies.euclid]
|
||||
version = "0.19"
|
||||
version = "0.20"
|
||||
|
||||
[dependencies.log]
|
||||
version = "0.4"
|
||||
|
|
|
@ -2,7 +2,7 @@ use {Intersection, Plane, Polygon, Splitter};
|
|||
use is_zero;
|
||||
|
||||
use binary_space_partition::{BspNode, Plane as BspPlane, PlaneCut};
|
||||
use euclid::{TypedPoint3D, TypedVector3D};
|
||||
use euclid::{Point3D, Vector3D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use num_traits::{Float, One, Zero};
|
||||
|
||||
|
@ -127,10 +127,10 @@ impl<T, U> Splitter<T, U> for BspSplitter<T, U> where
|
|||
self.tree.insert(poly);
|
||||
}
|
||||
|
||||
fn sort(&mut self, view: TypedVector3D<T, U>) -> &[Polygon<T, U>] {
|
||||
fn sort(&mut self, view: Vector3D<T, U>) -> &[Polygon<T, U>] {
|
||||
//debug!("\t\ttree before sorting {:?}", self.tree);
|
||||
let poly = Polygon {
|
||||
points: [TypedPoint3D::origin(); 4],
|
||||
points: [Point3D::origin(); 4],
|
||||
plane: Plane {
|
||||
normal: -view, //Note: BSP `order()` is back to front
|
||||
offset: T::zero(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use {Intersection, NegativeHemisphereError, Plane, Polygon};
|
||||
|
||||
use euclid::{Trig, TypedRect, TypedScale, TypedTransform3D, TypedVector3D};
|
||||
use euclid::{Trig, Rect, Scale, Transform3D, Vector3D};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use num_traits::{Float, One, Zero};
|
||||
|
||||
|
@ -38,35 +38,35 @@ impl<
|
|||
|
||||
/// Extract the clipping planes that define the frustum for a given transformation.
|
||||
pub fn frustum_planes<V>(
|
||||
t: &TypedTransform3D<T, U, V>,
|
||||
bounds: Option<TypedRect<T, V>>,
|
||||
t: &Transform3D<T, U, V>,
|
||||
bounds: Option<Rect<T, V>>,
|
||||
) -> Result<impl Iterator<Item = Plane<T, U>>, NegativeHemisphereError> {
|
||||
let mw = TypedVector3D::new(t.m14, t.m24, t.m34);
|
||||
let mw = Vector3D::new(t.m14, t.m24, t.m34);
|
||||
let plane_positive = Plane::from_unnormalized(mw, t.m44)?;
|
||||
|
||||
let bounds_iter_maybe = match bounds {
|
||||
Some(bounds) => {
|
||||
let mx = TypedVector3D::new(t.m11, t.m21, t.m31);
|
||||
let mx = Vector3D::new(t.m11, t.m21, t.m31);
|
||||
let left = bounds.origin.x;
|
||||
let plane_left = Plane::from_unnormalized(
|
||||
mx - mw * TypedScale::new(left),
|
||||
mx - mw * Scale::new(left),
|
||||
t.m41 - t.m44 * left,
|
||||
)?;
|
||||
let right = bounds.origin.x + bounds.size.width;
|
||||
let plane_right = Plane::from_unnormalized(
|
||||
mw * TypedScale::new(right) - mx,
|
||||
mw * Scale::new(right) - mx,
|
||||
t.m44 * right - t.m41,
|
||||
)?;
|
||||
|
||||
let my = TypedVector3D::new(t.m12, t.m22, t.m32);
|
||||
let my = Vector3D::new(t.m12, t.m22, t.m32);
|
||||
let top = bounds.origin.y;
|
||||
let plane_top = Plane::from_unnormalized(
|
||||
my - mw * TypedScale::new(top),
|
||||
my - mw * Scale::new(top),
|
||||
t.m42 - t.m44 * top,
|
||||
)?;
|
||||
let bottom = bounds.origin.y + bounds.size.height;
|
||||
let plane_bottom = Plane::from_unnormalized(
|
||||
mw * TypedScale::new(bottom) - my,
|
||||
mw * Scale::new(bottom) - my,
|
||||
t.m44 * bottom - t.m42,
|
||||
)?;
|
||||
|
||||
|
@ -130,8 +130,8 @@ impl<
|
|||
pub fn clip_transformed<'a, V>(
|
||||
&'a mut self,
|
||||
polygon: Polygon<T, U>,
|
||||
transform: &'a TypedTransform3D<T, U, V>,
|
||||
bounds: Option<TypedRect<T, V>>,
|
||||
transform: &'a Transform3D<T, U, V>,
|
||||
bounds: Option<Rect<T, V>>,
|
||||
) -> Result<impl 'a + Iterator<Item = Polygon<T, V>>, NegativeHemisphereError>
|
||||
where
|
||||
T: Trig,
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче