use noesis_runtime::brushes::{
BlurEffect, DropShadowEffect, GradientStop, ImageBrush, LinearGradientBrush,
RadialGradientBrush, SolidColorBrush,
};
use noesis_runtime::transforms::{
CompositeFields, CompositeTransform, MatrixTransform, RotateTransform, ScaleTransform,
SkewTransform, TransformGroup, TranslateTransform,
};
use noesis_runtime::view::FrameworkElement;
const NS: &str = r#"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml""#;
fn approx(a: f32, b: f32) -> bool {
(a - b).abs() < 1.0e-4
}
fn approx4(a: [f32; 4], b: [f32; 4]) -> bool {
a.iter().zip(b.iter()).all(|(x, y)| approx(*x, *y))
}
#[test]
fn brushes_transforms_effects_round_trip() {
if let (Ok(name), Ok(key)) = (
std::env::var("NOESIS_LICENSE_NAME"),
std::env::var("NOESIS_LICENSE_KEY"),
) {
noesis_runtime::set_license(&name, &key);
}
noesis_runtime::init();
{
let red = [0.9_f32, 0.1, 0.2, 1.0];
let mut brush = SolidColorBrush::new(red);
assert!(approx4(brush.color(), red), "solid color round-trip");
brush.set_color([0.0, 0.5, 1.0, 0.5]);
assert!(
approx4(brush.color(), [0.0, 0.5, 1.0, 0.5]),
"solid color set_color round-trip"
);
brush.set_color(red);
let border_xaml = format!("<Border {NS}/>");
let mut border = FrameworkElement::parse(&border_xaml).expect("parse Border");
assert!(
border.get_component("Background").is_none(),
"Border Background starts unset"
);
assert!(
border.solid_brush_color("Background").is_none(),
"unset Background has no solid color"
);
assert!(border.set_background(&brush), "set Background");
let bg = border
.get_component("Background")
.expect("Background set after set_background");
assert_eq!(
bg.as_ptr(),
brush.raw(),
"Background is the exact brush we assigned"
);
assert!(
approx4(
border
.solid_brush_color("Background")
.expect("Background reads back as a solid color"),
red
),
"solid_brush_color reads the assigned color"
);
let mut grad = LinearGradientBrush::new();
grad.set_start_point(0.0, 0.0);
grad.set_end_point(1.0, 1.0);
let (s, e) = grad.points();
assert!(
approx(s[0], 0.0) && approx(e[0], 1.0) && approx(e[1], 1.0),
"gradient start/end points round-trip"
);
assert_eq!(
grad.add_stop(GradientStop::new(0.0, [0.0, 0.0, 1.0, 1.0])),
Some(0)
);
assert_eq!(
grad.add_stop(GradientStop::new(1.0, [1.0, 0.0, 0.0, 1.0])),
Some(1)
);
assert_eq!(grad.stop_count(), 2, "two gradient stops");
let stop0 = grad.stop(0).expect("stop 0");
let stop1 = grad.stop(1).expect("stop 1");
assert!(approx(stop0.offset, 0.0) && approx4(stop0.color, [0.0, 0.0, 1.0, 1.0]));
assert!(approx(stop1.offset, 1.0) && approx4(stop1.color, [1.0, 0.0, 0.0, 1.0]));
assert!(grad.stop(2).is_none(), "out-of-range stop is None");
let rect_xaml = format!("<Rectangle {NS} Width=\"50\" Height=\"50\"/>");
let mut rect = FrameworkElement::parse(&rect_xaml).expect("parse Rectangle");
assert!(
rect.get_component("Fill").is_none(),
"Rectangle Fill starts unset"
);
assert!(rect.set_fill(&grad), "set Fill");
assert_eq!(
rect.get_component("Fill").expect("Fill set").as_ptr(),
grad.raw(),
"Fill is the exact gradient brush"
);
assert!(
rect.solid_brush_color("Fill").is_none(),
"gradient Fill has no single solid color"
);
assert!(!border.set_fill(&brush), "Border has no Fill");
let mut radial = RadialGradientBrush::new();
radial.set_radius(0.75, 0.25);
radial.set_center(0.5, 0.5);
radial.set_gradient_origin(0.4, 0.6);
let (rx, ry) = radial.radius();
assert!(
approx(rx, 0.75) && approx(ry, 0.25),
"radial radius round-trip"
);
radial.add_stop(GradientStop::new(0.5, [0.2, 0.2, 0.2, 1.0]));
assert_eq!(radial.stop_count(), 1);
let ib = ImageBrush::new();
assert!(
ib.image_source().is_none(),
"fresh ImageBrush has no source"
);
let border2_xaml = format!("<Border {NS}/>");
let mut border2 = FrameworkElement::parse(&border2_xaml).expect("parse Border2");
assert!(
border2.get_component("Background").is_none(),
"Border2 Background starts unset"
);
assert!(border2.set_background(&ib), "set Background (ImageBrush)");
assert_eq!(
border2
.get_component("Background")
.expect("Background set after set_background")
.as_ptr(),
ib.raw(),
"Background is the exact ImageBrush we assigned"
);
let tb_xaml = format!("<TextBlock {NS} Text=\"x\"/>");
let mut tb = FrameworkElement::parse(&tb_xaml).expect("parse TextBlock");
assert!(tb.set_foreground(&brush), "set Foreground");
assert_eq!(
tb.get_component("Foreground")
.expect("Foreground set")
.as_ptr(),
brush.raw(),
"Foreground is the exact brush we assigned"
);
assert!(rect.set_stroke(&radial), "set Stroke");
assert_eq!(
rect.get_component("Stroke").expect("Stroke set").as_ptr(),
radial.raw(),
"Stroke is the exact radial brush we assigned"
);
let translate = TranslateTransform::new(3.0, -4.0);
assert_eq!(translate.get(), (3.0, -4.0), "translate round-trip");
let scale = ScaleTransform::new(2.0, 3.0, 10.0, 20.0);
let s = scale.get();
assert!(
approx(s[0], 2.0) && approx(s[1], 3.0) && approx(s[2], 10.0) && approx(s[3], 20.0),
"scale round-trip"
);
let mut rotate = RotateTransform::new(45.0, 5.0, 6.0);
assert!(approx(rotate.angle(), 45.0), "rotate angle round-trip");
rotate.set_angle(90.0);
assert!(approx(rotate.angle(), 90.0), "rotate set_angle round-trip");
let r = rotate.get();
assert!(
approx(r[1], 5.0) && approx(r[2], 6.0),
"rotate center round-trip"
);
let skew = SkewTransform::new(15.0, 25.0, 1.0, 2.0);
let sk = skew.get();
assert!(
approx(sk[0], 15.0) && approx(sk[1], 25.0),
"skew round-trip"
);
let m = [1.0, 0.0, 0.0, 1.0, 7.0, 8.0];
let matrix = MatrixTransform::new(m);
let got = matrix.get();
assert!(
got.iter().zip(m.iter()).all(|(a, b)| approx(*a, *b)),
"matrix round-trip"
);
let composite = CompositeTransform::new(CompositeFields {
scale_x: 2.0,
scale_y: 2.0,
rotation: 30.0,
translate_x: 11.0,
..CompositeFields::default()
});
let cf = composite.get();
assert!(
approx(cf.scale_x, 2.0) && approx(cf.rotation, 30.0) && approx(cf.translate_x, 11.0),
"composite round-trip"
);
let mut group = TransformGroup::new();
assert_eq!(group.child_count(), 0, "group starts empty");
assert!(group.add_child(&scale));
assert!(group.add_child(&rotate));
assert_eq!(group.child_count(), 2, "group has two children");
let panel_xaml =
format!("<Border {NS} Width=\"100\" Height=\"100\"><TextBlock Text=\"x\"/></Border>");
let mut panel = FrameworkElement::parse(&panel_xaml).expect("parse panel");
assert!(panel.set_render_transform(&group), "set RenderTransform");
assert_eq!(
panel
.get_component("RenderTransform")
.expect("RenderTransform set")
.as_ptr(),
group.raw(),
"RenderTransform is the exact group we assigned"
);
let mut blur = BlurEffect::new(8.0);
assert!(approx(blur.radius(), 8.0), "blur radius round-trip");
blur.set_radius(3.5);
assert!(approx(blur.radius(), 3.5), "blur set_radius round-trip");
assert!(panel.set_effect(&blur), "set Effect");
assert_eq!(
panel.get_component("Effect").expect("Effect set").as_ptr(),
blur.raw(),
"Effect is the exact blur we assigned"
);
let shadow = DropShadowEffect::new([0.1, 0.2, 0.3, 0.8], 6.0, 315.0, 4.0, 0.7);
let p = shadow.params();
assert!(
approx4(p.color, [0.1, 0.2, 0.3, 0.8]),
"shadow color round-trip"
);
assert!(
approx(p.blur_radius, 6.0)
&& approx(p.direction, 315.0)
&& approx(p.shadow_depth, 4.0)
&& approx(p.opacity, 0.7),
"shadow params round-trip"
);
assert!(panel.set_bitmap_scaling_mode(2), "set BitmapScalingMode");
assert_eq!(
panel.bitmap_scaling_mode(),
Some(2),
"BitmapScalingMode round-trip"
);
assert!(
panel.set_bitmap_scaling_mode(1),
"set BitmapScalingMode again"
);
assert_eq!(panel.bitmap_scaling_mode(), Some(1));
}
noesis_runtime::shutdown();
}