refactored borders

This commit is contained in:
Evan Almloff 2022-02-22 19:41:45 -06:00
parent 5a00816fc9
commit a4fdb22197
5 changed files with 326 additions and 217 deletions

View file

@ -30,7 +30,6 @@
*/
use stretch2::{prelude::*, style::PositionType, style::Style};
use tui::style::{Color, Style as TuiStyle};
use crate::style::{RinkColor, RinkStyle};
@ -40,16 +39,50 @@ pub struct StyleModifer {
pub tui_modifier: TuiModifier,
}
#[derive(Default)]
pub struct TuiModifier {
// border arrays start at the top and proceed clockwise
pub border_colors: [Option<RinkColor>; 4],
pub border_types: [BorderType; 4],
pub border_widths: [UnitSystem; 4],
pub border_radi: [UnitSystem; 4],
pub borders: Borders,
}
#[derive(Default)]
pub struct Borders {
pub top: BorderEdge,
pub right: BorderEdge,
pub bottom: BorderEdge,
pub left: BorderEdge,
}
impl Borders {
fn slice(&mut self) -> [&mut BorderEdge; 4] {
[
&mut self.top,
&mut self.right,
&mut self.bottom,
&mut self.left,
]
}
}
pub struct BorderEdge {
pub color: Option<RinkColor>,
pub style: BorderStyle,
pub width: UnitSystem,
pub radius: UnitSystem,
}
impl Default for BorderEdge {
fn default() -> Self {
Self {
color: None,
style: BorderStyle::NONE,
width: UnitSystem::Point(0.0),
radius: UnitSystem::Point(0.0),
}
}
}
#[derive(Clone, Copy)]
pub enum BorderType {
pub enum BorderStyle {
DOTTED,
DASHED,
SOLID,
@ -62,13 +95,30 @@ pub enum BorderType {
NONE,
}
impl Default for TuiModifier {
fn default() -> Self {
Self {
border_colors: [None; 4],
border_types: [BorderType::NONE; 4],
border_widths: [UnitSystem::Point(0.0); 4],
border_radi: [UnitSystem::Point(0.0); 4],
impl BorderStyle {
pub fn symbol_set(&self) -> Option<tui::symbols::line::Set> {
use tui::symbols::line::*;
const DASHED: Set = Set {
horizontal: "",
vertical: "",
..NORMAL
};
const DOTTED: Set = Set {
horizontal: "",
vertical: "",
..NORMAL
};
match self {
BorderStyle::DOTTED => Some(DOTTED),
BorderStyle::DASHED => Some(DASHED),
BorderStyle::SOLID => Some(NORMAL),
BorderStyle::DOUBLE => Some(DOUBLE),
BorderStyle::GROOVE => Some(NORMAL),
BorderStyle::RIDGE => Some(NORMAL),
BorderStyle::INSET => Some(NORMAL),
BorderStyle::OUTSET => Some(NORMAL),
BorderStyle::HIDDEN => None,
BorderStyle::NONE => None,
}
}
}
@ -345,8 +395,8 @@ fn parse_value(value: &str) -> Option<UnitSystem> {
} else {
None
}
} else if value.ends_with("%") {
if let Ok(pct) = value.trim_end_matches("%").parse::<f32>() {
} else if value.ends_with('%') {
if let Ok(pct) = value.trim_end_matches('%').parse::<f32>() {
Some(UnitSystem::Percent(pct))
} else {
None
@ -421,18 +471,18 @@ fn apply_background(name: &str, value: &str, style: &mut StyleModifer) {
}
fn apply_border(name: &str, value: &str, style: &mut StyleModifer) {
fn parse_border_type(v: &str) -> BorderType {
fn parse_border_style(v: &str) -> BorderStyle {
match v {
"dotted" => BorderType::DOTTED,
"dashed" => BorderType::DASHED,
"solid" => BorderType::SOLID,
"double" => BorderType::DOUBLE,
"groove" => BorderType::GROOVE,
"ridge" => BorderType::RIDGE,
"inset" => BorderType::INSET,
"outset" => BorderType::OUTSET,
"none" => BorderType::NONE,
"hidden" => BorderType::HIDDEN,
"dotted" => BorderStyle::DOTTED,
"dashed" => BorderStyle::DASHED,
"solid" => BorderStyle::SOLID,
"double" => BorderStyle::DOUBLE,
"groove" => BorderStyle::GROOVE,
"ridge" => BorderStyle::RIDGE,
"inset" => BorderStyle::INSET,
"outset" => BorderStyle::OUTSET,
"none" => BorderStyle::NONE,
"hidden" => BorderStyle::HIDDEN,
_ => todo!(),
}
}
@ -441,23 +491,25 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) {
"border-bottom" => {}
"border-bottom-color" => {
if let Ok(c) = value.parse() {
style.tui_modifier.border_colors[2] = Some(c);
style.tui_modifier.borders.bottom.color = Some(c);
}
}
"border-bottom-left-radius" => {
if let Some(v) = parse_value(value) {
style.tui_modifier.border_radi[2] = v;
style.tui_modifier.borders.left.radius = v;
}
}
"border-bottom-right-radius" => {
if let Some(v) = parse_value(value) {
style.tui_modifier.border_radi[1] = v;
style.tui_modifier.borders.right.radius = v;
}
}
"border-bottom-style" => style.tui_modifier.border_types[2] = parse_border_type(value),
"border-bottom-style" => {
style.tui_modifier.borders.bottom.style = parse_border_style(value)
}
"border-bottom-width" => {
if let Some(v) = parse_value(value) {
style.tui_modifier.border_widths[2] = v;
style.tui_modifier.borders.bottom.width = v;
}
}
"border-collapse" => {}
@ -465,14 +517,20 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) {
let values: Vec<_> = value.split(' ').collect();
if values.len() == 1 {
if let Ok(c) = values[0].parse() {
for i in 0..4 {
style.tui_modifier.border_colors[i] = Some(c);
}
style
.tui_modifier
.borders
.slice()
.iter_mut()
.for_each(|b| b.color = Some(c));
}
} else {
for (i, v) in values.into_iter().enumerate() {
for (v, b) in values
.into_iter()
.zip(style.tui_modifier.borders.slice().iter_mut())
{
if let Ok(c) = v.parse() {
style.tui_modifier.border_colors[i] = Some(c);
b.color = Some(c);
}
}
}
@ -486,27 +544,33 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) {
"border-left" => {}
"border-left-color" => {
if let Ok(c) = value.parse() {
style.tui_modifier.border_colors[3] = Some(c);
style.tui_modifier.borders.left.color = Some(c);
}
}
"border-left-style" => style.tui_modifier.border_types[3] = parse_border_type(value),
"border-left-style" => style.tui_modifier.borders.left.style = parse_border_style(value),
"border-left-width" => {
if let Some(v) = parse_value(value) {
style.tui_modifier.border_widths[3] = v;
style.tui_modifier.borders.left.width = v;
}
}
"border-radius" => {
let values: Vec<_> = value.split(' ').collect();
if values.len() == 1 {
if let Some(r) = parse_value(values[0]) {
for i in 0..4 {
style.tui_modifier.border_radi[i] = r;
}
style
.tui_modifier
.borders
.slice()
.iter_mut()
.for_each(|b| b.radius = r);
}
} else {
for (i, v) in values.into_iter().enumerate() {
for (v, b) in values
.into_iter()
.zip(style.tui_modifier.borders.slice().iter_mut())
{
if let Some(r) = parse_value(v) {
style.tui_modifier.border_radi[i] = r;
b.radius = r;
}
}
}
@ -514,55 +578,76 @@ fn apply_border(name: &str, value: &str, style: &mut StyleModifer) {
"border-right" => {}
"border-right-color" => {
if let Ok(c) = value.parse() {
style.tui_modifier.border_colors[1] = Some(c);
style.tui_modifier.borders.right.color = Some(c);
}
}
"border-right-style" => style.tui_modifier.border_types[1] = parse_border_type(value),
"border-right-style" => style.tui_modifier.borders.right.style = parse_border_style(value),
"border-right-width" => {
if let Some(v) = parse_value(value) {
style.tui_modifier.border_widths[1] = v;
style.tui_modifier.borders.right.width = v;
}
}
"border-spacing" => {}
"border-style" => {
let values: Vec<_> = value.split(' ').collect();
if values.len() == 1 {
let border = parse_border_type(values[0]);
for i in 0..4 {
style.tui_modifier.border_types[i] = border;
}
let border_style = parse_border_style(values[0]);
style
.tui_modifier
.borders
.slice()
.iter_mut()
.for_each(|b| b.style = border_style);
} else {
for (i, v) in values.into_iter().enumerate() {
style.tui_modifier.border_types[i] = parse_border_type(v);
for (v, b) in values
.into_iter()
.zip(style.tui_modifier.borders.slice().iter_mut())
{
b.style = parse_border_style(v);
}
}
}
"border-top" => {}
"border-top-color" => {
if let Ok(c) = value.parse() {
style.tui_modifier.border_colors[0] = Some(c);
style.tui_modifier.borders.top.color = Some(c);
}
}
"border-top-left-radius" => {
if let Some(v) = parse_value(value) {
style.tui_modifier.border_radi[3] = v;
style.tui_modifier.borders.left.radius = v;
}
}
"border-top-right-radius" => {
if let Some(v) = parse_value(value) {
style.tui_modifier.border_radi[0] = v;
style.tui_modifier.borders.right.radius = v;
}
}
"border-top-style" => style.tui_modifier.border_types[0] = parse_border_type(value),
"border-top-style" => style.tui_modifier.borders.top.style = parse_border_style(value),
"border-top-width" => {
if let Some(v) = parse_value(value) {
style.tui_modifier.border_widths[0] = v;
style.tui_modifier.borders.top.width = v;
}
}
"border-width" => {
if let Some(v) = parse_value(value) {
for i in 0..4 {
style.tui_modifier.border_widths[i] = v;
let values: Vec<_> = value.split(' ').collect();
if values.len() == 1 {
if let Some(w) = parse_value(values[0]) {
style
.tui_modifier
.borders
.slice()
.iter_mut()
.for_each(|b| b.width = w);
}
} else {
for (v, b) in values
.into_iter()
.zip(style.tui_modifier.borders.slice().iter_mut())
{
if let Some(w) = parse_value(v) {
b.width = w;
}
}
}
}
@ -654,11 +739,11 @@ fn apply_flex(name: &str, value: &str, style: &mut StyleModifer) {
fn apply_font(name: &str, value: &str, style: &mut StyleModifer) {
use tui::style::Modifier;
match name {
"font" => todo!(),
"font-family" => todo!(),
"font-size" => todo!(),
"font-size-adjust" => todo!(),
"font-stretch" => todo!(),
"font" => (),
"font-family" => (),
"font-size" => (),
"font-size-adjust" => (),
"font-stretch" => (),
"font-style" => match value {
"italic" => style.tui_style = style.tui_style.add_modifier(Modifier::ITALIC),
"oblique" => style.tui_style = style.tui_style.add_modifier(Modifier::ITALIC),

View file

@ -1,6 +1,5 @@
use dioxus::core::*;
use std::collections::HashMap;
use tui::style::Style as TuiStyle;
use crate::{
attributes::{apply_attributes, StyleModifer},
@ -88,7 +87,7 @@ pub fn collect_layout<'a>(
node.mounted_id(),
TuiNode {
node,
block_style: modifier.tui_style.into(),
block_style: modifier.tui_style,
tui_modifier: modifier.tui_modifier,
layout: layout.new_node(modifier.style, &child_layout).unwrap(),
},

View file

@ -10,7 +10,7 @@ use tui::{backend::CrosstermBackend, layout::Rect};
use crate::{
style::{RinkColor, RinkStyle},
widget::{RinkBuffer, RinkCell, RinkWidget, WidgetWithContext},
BorderType, Config, TuiNode, UnitSystem,
BorderEdge, BorderStyle, Config, TuiNode, UnitSystem,
};
const RADIUS_MULTIPLIER: [f32; 2] = [1.0, 0.5];
@ -72,10 +72,6 @@ pub fn render_vnode<'a>(
}
}
// let s = Span::raw(t.text);
// Block::default().
let label = Label {
text: t.text,
style: *style,
@ -190,7 +186,7 @@ impl<'a> RinkWidget for TuiNode<'a> {
arc_angle: f32,
radius: f32,
symbols: &Set,
mut buf: &mut RinkBuffer,
buf: &mut RinkBuffer,
color: &Option<RinkColor>,
) {
if radius < 0.0 {
@ -202,6 +198,7 @@ impl<'a> RinkWidget for TuiNode<'a> {
(starting_angle.cos() * (radius * RADIUS_MULTIPLIER[0])) as i32,
(starting_angle.sin() * (radius * RADIUS_MULTIPLIER[1])) as i32,
];
// keep track of the last 3 point to allow filling diagonals
let mut points_history = [
[0, 0],
{
@ -238,16 +235,16 @@ impl<'a> RinkWidget for TuiNode<'a> {
_ => todo!(),
};
draw(
&mut buf,
buf,
[points_history[0], points_history[1], connecting_point],
&symbols,
symbols,
pos,
color,
);
points_history = [points_history[1], connecting_point, points_history[2]];
}
draw(&mut buf, points_history, &symbols, pos, color);
draw(buf, points_history, symbols, pos, color);
}
}
@ -268,7 +265,21 @@ impl<'a> RinkWidget for TuiNode<'a> {
}
}];
draw(&mut buf, points_history, &symbols, pos, color);
draw(buf, points_history, symbols, pos, color);
}
fn get_radius(border: &BorderEdge, area: Rect) -> f32 {
match border.style {
BorderStyle::HIDDEN => 0.0,
BorderStyle::NONE => 0.0,
_ => match border.radius {
UnitSystem::Percent(p) => p * area.width as f32 / 100.0,
UnitSystem::Point(p) => p,
}
.abs()
.min((area.width as f32 / RADIUS_MULTIPLIER[0]) / 2.0)
.min((area.height as f32 / RADIUS_MULTIPLIER[1]) / 2.0),
}
}
if area.area() == 0 {
@ -286,128 +297,146 @@ impl<'a> RinkWidget for TuiNode<'a> {
}
}
for i in 0..4 {
let borders = self.tui_modifier.borders;
let last_edge = &borders.left;
let current_edge = &borders.top;
if let Some(symbols) = current_edge.style.symbol_set() {
// the radius for the curve between this line and the next
let r = match self.tui_modifier.border_types[(i + 1) % 4] {
BorderType::HIDDEN => 0.0,
BorderType::NONE => 0.0,
_ => match self.tui_modifier.border_radi[i] {
UnitSystem::Percent(p) => p * area.width as f32 / 100.0,
UnitSystem::Point(p) => p,
}
.abs()
.min((area.width as f32 / RADIUS_MULTIPLIER[0]) / 2.0)
.min((area.height as f32 / RADIUS_MULTIPLIER[1]) / 2.0),
};
let r = get_radius(current_edge, area);
let radius = [
(r * RADIUS_MULTIPLIER[0]) as u16,
(r * RADIUS_MULTIPLIER[1]) as u16,
];
// the radius for the curve between this line and the last
let last_idx = if i == 0 { 3 } else { i - 1 };
let last_r = match self.tui_modifier.border_types[last_idx] {
BorderType::HIDDEN => 0.0,
BorderType::NONE => 0.0,
_ => match self.tui_modifier.border_radi[last_idx] {
UnitSystem::Percent(p) => p * area.width as f32 / 100.0,
UnitSystem::Point(p) => p,
}
.abs()
.min((area.width as f32 / RADIUS_MULTIPLIER[0]) / 2.0)
.min((area.height as f32 / RADIUS_MULTIPLIER[1]) / 2.0),
};
let last_r = get_radius(last_edge, area);
let last_radius = [
(last_r * RADIUS_MULTIPLIER[0]) as u16,
(last_r * RADIUS_MULTIPLIER[1]) as u16,
];
let symbols = match self.tui_modifier.border_types[i] {
BorderType::DOTTED => NORMAL,
BorderType::DASHED => NORMAL,
BorderType::SOLID => NORMAL,
BorderType::DOUBLE => DOUBLE,
BorderType::GROOVE => NORMAL,
BorderType::RIDGE => NORMAL,
BorderType::INSET => NORMAL,
BorderType::OUTSET => NORMAL,
BorderType::HIDDEN => continue,
BorderType::NONE => continue,
};
let color = self.tui_modifier.border_colors[i].or(self.block_style.fg);
let color = current_edge.color.or(self.block_style.fg);
let mut new_cell = RinkCell::default();
if let Some(c) = color {
new_cell.fg = c;
}
match i {
0 => {
for x in (area.left() + last_radius[0] + 1)..(area.right() - radius[0]) {
new_cell.symbol = symbols.horizontal.to_string();
buf.set(x, area.top(), &new_cell);
}
}
1 => {
for y in (area.top() + last_radius[1] + 1)..(area.bottom() - radius[1]) {
new_cell.symbol = symbols.vertical.to_string();
buf.set(area.right() - 1, y, &new_cell);
}
}
2 => {
for x in (area.left() + radius[0])..(area.right() - last_radius[0] - 1) {
new_cell.symbol = symbols.horizontal.to_string();
buf.set(x, area.bottom() - 1, &new_cell);
}
}
3 => {
for y in (area.top() + radius[1])..(area.bottom() - last_radius[1] - 1) {
new_cell.symbol = symbols.vertical.to_string();
buf.set(area.left(), y, &new_cell);
}
}
_ => (),
for x in (area.left() + last_radius[0] + 1)..(area.right() - radius[0]) {
new_cell.symbol = symbols.horizontal.to_string();
buf.set(x, area.top(), &new_cell);
}
draw_arc(
[area.right() - radius[0] - 1, area.top() + radius[1]],
std::f32::consts::FRAC_PI_2 * 3.0,
std::f32::consts::FRAC_PI_2,
r,
&symbols,
&mut buf,
&color,
);
}
match i {
0 => draw_arc(
[area.right() - radius[0] - 1, area.top() + radius[1]],
std::f32::consts::FRAC_PI_2 * 3.0,
std::f32::consts::FRAC_PI_2,
r,
&symbols,
&mut buf,
&color,
),
1 => draw_arc(
[area.right() - radius[0] - 1, area.bottom() - radius[1] - 1],
0.0,
std::f32::consts::FRAC_PI_2,
r,
&symbols,
&mut buf,
&color,
),
2 => draw_arc(
[area.left() + radius[0], area.bottom() - radius[1] - 1],
std::f32::consts::FRAC_PI_2,
std::f32::consts::FRAC_PI_2,
r,
&symbols,
&mut buf,
&color,
),
3 => draw_arc(
[area.left() + radius[0], area.top() + radius[1]],
std::f32::consts::PI,
std::f32::consts::FRAC_PI_2,
r,
&symbols,
&mut buf,
&color,
),
_ => panic!("more than 4 sides?"),
let last_edge = &borders.top;
let current_edge = &borders.right;
if let Some(symbols) = current_edge.style.symbol_set() {
// the radius for the curve between this line and the next
let r = get_radius(current_edge, area);
let radius = [
(r * RADIUS_MULTIPLIER[0]) as u16,
(r * RADIUS_MULTIPLIER[1]) as u16,
];
// the radius for the curve between this line and the last
let last_r = get_radius(last_edge, area);
let last_radius = [
(last_r * RADIUS_MULTIPLIER[0]) as u16,
(last_r * RADIUS_MULTIPLIER[1]) as u16,
];
let color = current_edge.color.or(self.block_style.fg);
let mut new_cell = RinkCell::default();
if let Some(c) = color {
new_cell.fg = c;
}
for y in (area.top() + last_radius[1] + 1)..(area.bottom() - radius[1]) {
new_cell.symbol = symbols.vertical.to_string();
buf.set(area.right() - 1, y, &new_cell);
}
draw_arc(
[area.right() - radius[0] - 1, area.bottom() - radius[1] - 1],
0.0,
std::f32::consts::FRAC_PI_2,
r,
&symbols,
&mut buf,
&color,
);
}
let last_edge = &borders.right;
let current_edge = &borders.bottom;
if let Some(symbols) = current_edge.style.symbol_set() {
// the radius for the curve between this line and the next
let r = get_radius(current_edge, area);
let radius = [
(r * RADIUS_MULTIPLIER[0]) as u16,
(r * RADIUS_MULTIPLIER[1]) as u16,
];
// the radius for the curve between this line and the last
let last_r = get_radius(last_edge, area);
let last_radius = [
(last_r * RADIUS_MULTIPLIER[0]) as u16,
(last_r * RADIUS_MULTIPLIER[1]) as u16,
];
let color = current_edge.color.or(self.block_style.fg);
let mut new_cell = RinkCell::default();
if let Some(c) = color {
new_cell.fg = c;
}
for x in (area.left() + radius[0])..(area.right() - last_radius[0] - 1) {
new_cell.symbol = symbols.horizontal.to_string();
buf.set(x, area.bottom() - 1, &new_cell);
}
draw_arc(
[area.left() + radius[0], area.bottom() - radius[1] - 1],
std::f32::consts::FRAC_PI_2,
std::f32::consts::FRAC_PI_2,
r,
&symbols,
&mut buf,
&color,
);
}
let last_edge = &borders.bottom;
let current_edge = &borders.left;
if let Some(symbols) = current_edge.style.symbol_set() {
// the radius for the curve between this line and the next
let r = get_radius(current_edge, area);
let radius = [
(r * RADIUS_MULTIPLIER[0]) as u16,
(r * RADIUS_MULTIPLIER[1]) as u16,
];
// the radius for the curve between this line and the last
let last_r = get_radius(last_edge, area);
let last_radius = [
(last_r * RADIUS_MULTIPLIER[0]) as u16,
(last_r * RADIUS_MULTIPLIER[1]) as u16,
];
let color = current_edge.color.or(self.block_style.fg);
let mut new_cell = RinkCell::default();
if let Some(c) = color {
new_cell.fg = c;
}
for y in (area.top() + radius[1])..(area.bottom() - last_radius[1] - 1) {
new_cell.symbol = symbols.vertical.to_string();
buf.set(area.left(), y, &new_cell);
}
draw_arc(
[area.left() + radius[0], area.top() + radius[1]],
std::f32::consts::PI,
std::f32::consts::FRAC_PI_2,
r,
&symbols,
&mut buf,
&color,
);
}
}
}

View file

@ -23,26 +23,23 @@ impl RinkColor {
pub fn blend(self, other: Color) -> Color {
if self.color == Color::Reset {
Color::Reset
} else if self.alpha == 0.0 {
other
} else {
if self.alpha == 0.0 {
other
} else {
let [sr, sg, sb] = to_rgb(self.color);
let [or, og, ob] = to_rgb(other);
let (sr, sg, sb, sa) = (
sr as f32 / 255.0,
sg as f32 / 255.0,
sb as f32 / 255.0,
self.alpha,
);
let (or, og, ob) = (or as f32 / 255.0, og as f32 / 255.0, ob as f32 / 255.0);
let c = Color::Rgb(
(255.0 * (sr * sa + or * (1.0 - sa))) as u8,
(255.0 * (sg * sa + og * (1.0 - sa))) as u8,
(255.0 * (sb * sa + ob * (1.0 - sa))) as u8,
);
c
}
let [sr, sg, sb] = to_rgb(self.color);
let [or, og, ob] = to_rgb(other);
let (sr, sg, sb, sa) = (
sr as f32 / 255.0,
sg as f32 / 255.0,
sb as f32 / 255.0,
self.alpha,
);
let (or, og, ob) = (or as f32 / 255.0, og as f32 / 255.0, ob as f32 / 255.0);
Color::Rgb(
(255.0 * (sr * sa + or * (1.0 - sa))) as u8,
(255.0 * (sg * sa + og * (1.0 - sa))) as u8,
(255.0 * (sb * sa + ob * (1.0 - sa))) as u8,
)
}
}
}
@ -52,8 +49,8 @@ fn parse_value(
current_max_output: f32,
required_max_output: f32,
) -> Result<f32, ParseFloatError> {
if v.ends_with('%') {
Ok((v[..v.len() - 1].trim().parse::<f32>()? / 100.0) * required_max_output)
if let Some(stripped) = v.strip_suffix('%') {
Ok((stripped.trim().parse::<f32>()? / 100.0) * required_max_output)
} else {
Ok((v.trim().parse::<f32>()? / current_max_output) * required_max_output)
}
@ -224,8 +221,8 @@ impl FromStr for RinkColor {
color: c,
alpha: 1.0,
})
} else if color.starts_with("rgb(") {
let color_values = color[4..].trim_end_matches(')');
} else if let Some(stripped) = color.strip_prefix("rgb(") {
let color_values = stripped.trim_end_matches(')');
if color.matches(',').count() == 3 {
let (alpha, rgb_values) =
color_values.rsplit_once(',').ok_or(ParseColorError)?;
@ -240,8 +237,8 @@ impl FromStr for RinkColor {
alpha: 1.0,
})
}
} else if color.starts_with("rgba(") {
let color_values = color[5..].trim_end_matches(')');
} else if let Some(stripped) = color.strip_prefix("rgba(") {
let color_values = stripped.trim_end_matches(')');
if color.matches(',').count() == 3 {
let (rgb_values, alpha) =
color_values.rsplit_once(',').ok_or(ParseColorError)?;
@ -256,8 +253,8 @@ impl FromStr for RinkColor {
alpha: 1.0,
})
}
} else if color.starts_with("hsl(") {
let color_values = color[4..].trim_end_matches(')');
} else if let Some(stripped) = color.strip_prefix("hsl(") {
let color_values = stripped.trim_end_matches(')');
if color.matches(',').count() == 3 {
let (rgb_values, alpha) =
color_values.rsplit_once(',').ok_or(ParseColorError)?;
@ -272,8 +269,8 @@ impl FromStr for RinkColor {
alpha: 1.0,
})
}
} else if color.starts_with("hsla(") {
let color_values = color[5..].trim_end_matches(')');
} else if let Some(stripped) = color.strip_prefix("hsla(") {
let color_values = stripped.trim_end_matches(')');
if color.matches(',').count() == 3 {
let (rgb_values, alpha) =
color_values.rsplit_once(',').ok_or(ParseColorError)?;
@ -332,7 +329,6 @@ fn to_rgb(c: Color) -> [u8; 3] {
_ => [0, 0, 0],
},
Color::Reset => [0, 0, 0],
_ => todo!("{c:?}"),
}
}
@ -384,7 +380,7 @@ fn rgb_to_ansi() {
if rgb[0] != rgb[1] || rgb[1] != rgb[2] {
assert_eq!(idxed, converted);
} else {
assert!(i >= 232 && i <= 255);
assert!(i >= 232);
}
} else {
panic!("color is not indexed")

View file

@ -23,8 +23,8 @@ impl<'a> RinkBuffer<'a> {
pub fn set(&mut self, x: u16, y: u16, new: &RinkCell) {
let mut cell = self.buf.get_mut(x, y);
cell.bg = convert(self.cfg.rendering_mode, new.bg.blend(cell.bg));
if &new.symbol == "" {
if &cell.symbol != "" {
if new.symbol.is_empty() {
if !cell.symbol.is_empty() {
// allows text to "shine through" transparent backgrounds
cell.fg = convert(self.cfg.rendering_mode, new.bg.blend(cell.fg));
}