blob: 1a19415600d4148d67ac1dc7c992deb04894f987 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::math::{self, Aabb, Mat};
#[derive(Clone, Copy, Debug)]
pub enum Fit {
Fill,
Contain,
Cover,
FitWidth,
FitHeight,
None,
ScaleDown,
}
#[derive(Clone, Copy, Debug)]
pub struct Alignment(math::Vec);
impl Alignment {
pub const fn new(x: f32, y: f32) -> Self {
Self(math::Vec::new(x, y))
}
pub const fn top_left() -> Self {
Self::new(-1.0, -1.0)
}
pub const fn top_center() -> Self {
Self::new(0.0, -1.0)
}
pub const fn top_right() -> Self {
Self::new(1.0, -1.0)
}
pub const fn center_left() -> Self {
Self::new(-1.0, 0.0)
}
pub const fn center() -> Self {
Self::new(0.0, 0.0)
}
pub const fn center_right() -> Self {
Self::new(1.0, 0.0)
}
pub const fn bottom_left() -> Self {
Self::new(-1.0, 1.0)
}
pub const fn bottom_center() -> Self {
Self::new(0.0, 1.0)
}
pub const fn bottom_right() -> Self {
Self::new(1.0, 1.0)
}
}
pub fn align(fit: Fit, alignment: Alignment, frame: Aabb, content: Aabb) -> Mat {
let content_size = content.size();
let conent_half_size = content_size * 0.5;
let pos = -content.min - conent_half_size - alignment.0 * conent_half_size;
let scale_vec = match fit {
Fit::Fill => frame.size() / content_size,
Fit::Contain => {
let scaled = frame.size() / content_size;
let min_scale = scaled.x.min(scaled.y);
math::Vec::new(min_scale, min_scale)
}
Fit::Cover => {
let scaled = frame.size() / content_size;
let max_scale = scaled.x.max(scaled.y);
math::Vec::new(max_scale, max_scale)
}
Fit::FitWidth => {
let min_scale = frame.size().x / content_size.x;
math::Vec::new(min_scale, min_scale)
}
Fit::FitHeight => {
let min_scale = frame.size().y / content_size.y;
math::Vec::new(min_scale, min_scale)
}
Fit::None => math::Vec::new(1.0, 1.0),
Fit::ScaleDown => {
let scaled = frame.size() / content_size;
let min_scale = scaled.x.min(scaled.y).min(1.0);
math::Vec::new(min_scale, min_scale)
}
};
let frame_half_size = frame.size() * 0.5;
let translation_vec = frame.min + frame_half_size + alignment.0 * frame_half_size;
let translation = Mat {
translate_x: translation_vec.x,
translate_y: translation_vec.y,
..Default::default()
};
let scale = Mat { scale_x: scale_vec.x, scale_y: scale_vec.y, ..Default::default() };
let translation_back = Mat { translate_x: pos.x, translate_y: pos.y, ..Default::default() };
translation * scale * translation_back
}