half_block.rs - icy_draw - [fork] icy_draw is the successor to mystic draw.
HTML git clone https://git.drkhsh.at/icy_draw.git
DIR Log
DIR Files
DIR Refs
DIR README
---
half_block.rs (4252B)
---
1 use crate::{AttributedChar, Buffer, Position, TextAttribute};
2
3 pub(crate) const FULL_BLOCK: char = 219 as char;
4 pub(crate) const HALF_BLOCK_TOP: char = 223 as char;
5 pub(crate) const HALF_BLOCK_BOTTOM: char = 220 as char;
6
7 pub(crate) struct HalfBlock {
8 pub upper_block_color: u32,
9 pub lower_block_color: u32,
10 pub is_top: bool,
11 }
12
13 impl HalfBlock {
14 pub fn from(buf: &Buffer, block: AttributedChar, pos: Position) -> Self {
15 let is_top = pos.y % 2 == 0;
16
17 let Some(font) = buf.get_font(block.get_font_page()) else {
18 return Self {
19 upper_block_color: block.attribute.get_background(),
20 lower_block_color: block.attribute.get_background(),
21 is_top,
22 };
23 };
24
25 let Some(glyph) = font.get_glyph(block.ch) else {
26 return Self {
27 upper_block_color: block.attribute.get_background(),
28 lower_block_color: block.attribute.get_background(),
29 is_top,
30 };
31 };
32
33 let mut upper = 0;
34 let mut lower = 0;
35 for i in 0..(glyph.data.len() / 2) {
36 upper += glyph.data[i].count_ones() as i32;
37 lower += glyph.data[glyph.data.len() / 2 + i].count_ones() as i32;
38 }
39 let upper_block_color = if upper > font.size.width * font.size.height / 4 {
40 block.attribute.get_foreground()
41 } else {
42 block.attribute.get_background()
43 };
44 let lower_block_color = if lower > font.size.width * font.size.height / 4 {
45 block.attribute.get_foreground()
46 } else {
47 block.attribute.get_background()
48 };
49
50 Self {
51 upper_block_color,
52 lower_block_color,
53 is_top,
54 }
55 }
56 }
57
58 pub fn get_halfblock(buf: &Buffer, cur_char: AttributedChar, pos: Position, color: u32, transparent_color: bool) -> AttributedChar {
59 let half_block = HalfBlock::from(buf, cur_char, pos);
60 let transparent_color = cur_char.is_transparent() && transparent_color;
61
62 let ch = if (half_block.is_top && half_block.lower_block_color == color) || (!half_block.is_top && half_block.upper_block_color == color) {
63 AttributedChar::new(FULL_BLOCK, TextAttribute::new(color, 0))
64 } else if half_block.is_top {
65 AttributedChar::new(
66 HALF_BLOCK_TOP,
67 TextAttribute::new(
68 color,
69 if transparent_color {
70 TextAttribute::TRANSPARENT_COLOR
71 } else {
72 half_block.lower_block_color
73 },
74 ),
75 )
76 } else {
77 AttributedChar::new(
78 HALF_BLOCK_BOTTOM,
79 TextAttribute::new(
80 color,
81 if transparent_color {
82 TextAttribute::TRANSPARENT_COLOR
83 } else {
84 half_block.upper_block_color
85 },
86 ),
87 )
88 };
89
90 optimize_block(ch)
91 }
92
93 fn flip_colors(attribute: TextAttribute) -> TextAttribute {
94 let mut result = attribute;
95 result.set_foreground(attribute.get_background());
96 result.set_background(attribute.get_foreground());
97 result
98 }
99
100 fn optimize_block(mut block: AttributedChar) -> AttributedChar {
101 if block.attribute.get_foreground() == 0 {
102 if block.attribute.get_background() == 0 || block.ch == FULL_BLOCK {
103 block.ch = ' ';
104 return block;
105 }
106 match block.ch {
107 HALF_BLOCK_BOTTOM => {
108 return AttributedChar::new(HALF_BLOCK_TOP, flip_colors(block.attribute));
109 }
110 HALF_BLOCK_TOP => {
111 return AttributedChar::new(HALF_BLOCK_BOTTOM, flip_colors(block.attribute));
112 }
113 _ => {}
114 }
115 } else if block.attribute.get_foreground() < 8 && block.attribute.get_background() >= 8 {
116 match block.ch {
117 HALF_BLOCK_BOTTOM => {
118 return AttributedChar::new(HALF_BLOCK_TOP, flip_colors(block.attribute));
119 }
120 HALF_BLOCK_TOP => {
121 return AttributedChar::new(HALF_BLOCK_BOTTOM, flip_colors(block.attribute));
122 }
123 _ => {}
124 }
125 }
126 block
127 }