use crate::{
color::Rgba,
plane::Align,
sys::NcVisualFlag,
visual::{Blitter, Scale},
};
#[derive(Clone, Copy, Default, PartialEq, Eq)]
pub struct VisualOptions {
pub(crate) y: i32,
pub(crate) x: i32,
pub(crate) scale: Scale,
pub(crate) blitter: Blitter,
pub(crate) transcolor: Option<Rgba>,
pub(crate) cell_offset_xy: Option<(u32, u32)>,
pub(crate) region_xy_lenxy: Option<(u32, u32, u32, u32)>,
pub(crate) flags: NcVisualFlag,
}
mod core_impls {
use super::{Align, VisualOptions};
use crate::sys::{NcVisualOptions, NcVisualOptionsBuilder};
use core::fmt;
impl<'n> From<VisualOptions> for NcVisualOptionsBuilder<'n> {
fn from(vo: VisualOptions) -> NcVisualOptionsBuilder<'n> {
let mut builder = NcVisualOptionsBuilder::new();
if vo.is_horaligned() {
builder = builder.halign(vo.x);
} else {
builder = builder.x(vo.x);
}
if vo.is_veraligned() {
builder = builder.valign(vo.y);
} else {
builder = builder.y(vo.y);
}
builder = builder.scale(vo.scale);
builder = builder.blitter(vo.blitter);
if let Some(color) = vo.transcolor {
builder = builder.transcolor(Some(color));
}
if let Some((x, y)) = vo.cell_offset_xy {
builder = builder.cell_offset(x, y);
}
if let Some((x, y, lenx, leny)) = vo.region_xy_lenxy {
builder = builder.region(x, y, lenx, leny);
}
builder = builder.blend(vo.does_blend());
builder = builder.degrade(vo.does_degrade());
builder = builder.interpolate(vo.does_interpolate());
builder
}
}
impl From<VisualOptions> for NcVisualOptions {
fn from(vo: VisualOptions) -> NcVisualOptions {
let builder: NcVisualOptionsBuilder = vo.into();
builder.build()
}
}
impl From<NcVisualOptions> for VisualOptions {
fn from(ncvo: NcVisualOptions) -> VisualOptions {
let mut vo = VisualOptions::default();
vo.set_blend(ncvo.does_blend());
vo.set_degrade(ncvo.does_degrade());
vo.set_interpolate(ncvo.does_interpolate());
vo.set_blitter(ncvo.blitter.into());
vo.set_scale(ncvo.scaling.into());
if ncvo.does_alpha() {
vo.set_transparency(Some(ncvo.transcolor));
}
if ncvo.is_horaligned() {
vo.set_halign(ncvo.x.into());
}
if ncvo.is_veraligned() {
vo.set_valign(ncvo.y.into());
}
let cell_offset = (ncvo.pxoffx, ncvo.pxoffy);
if cell_offset != (0, 0) {
vo.set_cell_offset(Some(cell_offset));
}
let region = (ncvo.begx, ncvo.begy, ncvo.lenx, ncvo.leny);
if region != (0, 0, 0, 0) {
vo.set_region(Some(region));
}
vo
}
}
impl<'n> From<NcVisualOptionsBuilder<'n>> for VisualOptions {
fn from(ob: NcVisualOptionsBuilder<'n>) -> VisualOptions {
ob.build().into()
}
}
fn flags_string(options: &VisualOptions) -> String {
let mut flags = String::new();
if options.is_horaligned() {
flags += "HorAligned+";
}
if options.is_veraligned() {
flags += "VerAligned+";
}
if options.does_blend() {
flags += "Blend+";
}
if !options.does_degrade() {
flags += "NoDegrade+";
}
if !options.does_interpolate() {
flags += "NoInterpolate+";
}
flags.pop();
flags
}
impl fmt::Display for VisualOptions {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (x, y) = (self.x, self.y);
let (horizontal, vertical);
if self.is_horaligned() {
horizontal = Align::from(x).to_string();
} else {
horizontal = x.to_string();
}
if self.is_veraligned() {
vertical = Align::from(y).to_string();
} else {
vertical = y.to_string();
}
let transcolor = if let Some(color) = self.transcolor {
color.to_string()
} else {
"None".to_string()
};
let flags = flags_string(self);
write!(
f,
"({0}, {1}) scale:{2} {3} t:{4} o:{5:?} r:{6:?} [{flags}]",
horizontal, vertical, self.scale, self.blitter, transcolor, self.cell_offset_xy, self.region_xy_lenxy, )
}
}
impl fmt::Debug for VisualOptions {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let (x, y) = (self.x, self.y);
let (horizontal, vertical);
if self.is_horaligned() {
horizontal = Align::from(x).to_string();
} else {
horizontal = x.to_string();
}
if self.is_veraligned() {
vertical = Align::from(y).to_string();
} else {
vertical = y.to_string();
}
let transcolor = if let Some(color) = self.transcolor {
color.to_string()
} else {
"None".to_string()
};
let flags = flags_string(self);
write!(
f,
"VisualOptions {{ ({0}, {1}) Scale:{2} Blitter:{3} transp:{4} offset:{5:?} region:{6:?} [{flags}] }}",
horizontal, vertical, self.scale, self.blitter, transcolor, self.cell_offset_xy, self.region_xy_lenxy, )
}
}
}
impl VisualOptions {
pub fn set_x(&mut self, x: i32) {
self.x = x;
self.flags &= !NcVisualFlag::HorAligned;
}
pub fn set_y(&mut self, y: i32) {
self.y = y;
self.flags &= !NcVisualFlag::VerAligned;
}
pub fn set_halign(&mut self, horizontal: Align) {
self.x = horizontal.into();
self.flags |= NcVisualFlag::HorAligned;
}
pub fn set_valign(&mut self, vertical: Align) {
self.y = vertical.into();
self.flags |= NcVisualFlag::VerAligned;
}
pub fn set_region(&mut self, region: Option<(u32, u32, u32, u32)>) {
self.region_xy_lenxy = region;
}
pub fn set_cell_offset(&mut self, cell_offset: Option<(u32, u32)>) {
self.cell_offset_xy = cell_offset;
}
pub fn set_blitter(&mut self, blitter: Blitter) {
self.blitter = blitter;
}
pub fn set_scale(&mut self, scale: Scale) {
self.scale = scale;
}
pub fn set_transparency(&mut self, color: Option<impl Into<Rgba>>) {
if let Some(color) = color {
self.flags |= NcVisualFlag::AddAlpha;
self.transcolor = Some(color.into());
} else {
self.flags &= !NcVisualFlag::AddAlpha;
self.transcolor = None;
}
}
pub fn set_blend(&mut self, blend: bool) {
if blend {
self.flags |= NcVisualFlag::Blend;
} else {
self.flags &= !NcVisualFlag::Blend;
}
}
pub fn set_degrade(&mut self, degrade: bool) {
if degrade {
self.flags &= !NcVisualFlag::NoDegrade;
} else {
self.flags |= NcVisualFlag::NoDegrade;
}
}
pub fn set_interpolate(&mut self, interpolate: bool) {
if interpolate {
self.flags &= !NcVisualFlag::NoInterpolate;
} else {
self.flags |= NcVisualFlag::NoInterpolate;
}
}
}
impl VisualOptions {
pub fn is_veraligned(&self) -> bool {
self.flags & NcVisualFlag::VerAligned != NcVisualFlag::None
}
pub fn is_horaligned(&self) -> bool {
self.flags & NcVisualFlag::HorAligned != NcVisualFlag::None
}
pub fn does_blend(&self) -> bool {
self.flags & NcVisualFlag::Blend != NcVisualFlag::None
}
pub fn does_degrade(&self) -> bool {
self.flags & NcVisualFlag::NoDegrade == NcVisualFlag::None
}
pub fn does_interpolate(&self) -> bool {
self.flags & NcVisualFlag::NoInterpolate == NcVisualFlag::None
}
}