@effindomv2/fui-rs 0.1.18 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +1 -1
- package/package.json +1 -1
- package/src/color.rs +112 -0
- package/src/controls/nav_link.rs +3 -4
- package/src/controls/shared.rs +2 -5
- package/src/controls/tests.rs +17 -0
- package/src/lib.rs +11 -7
- package/src/node/core.rs +20 -0
- package/src/node/mod.rs +79 -0
- package/src/node/text_node.rs +0 -4
- package/src/text.rs +24 -1
- package/src/theme.rs +6 -46
package/Cargo.toml
CHANGED
package/package.json
CHANGED
package/src/color.rs
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
pub const fn rgba(red: u32, green: u32, blue: u32, alpha: u32) -> u32 {
|
|
2
|
+
((red & 0xff) << 24) | ((green & 0xff) << 16) | ((blue & 0xff) << 8) | (alpha & 0xff)
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
pub const fn rgb(red: u32, green: u32, blue: u32) -> u32 {
|
|
6
|
+
rgba(red, green, blue, 0xff)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
pub const fn with_alpha(color: u32, alpha: u32) -> u32 {
|
|
10
|
+
(color & 0xffff_ff00) | (alpha & 0xff)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
pub(crate) fn color_red(color: u32) -> u32 {
|
|
14
|
+
(color >> 24) & 0xff
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
pub(crate) fn color_green(color: u32) -> u32 {
|
|
18
|
+
(color >> 16) & 0xff
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
pub(crate) fn color_blue(color: u32) -> u32 {
|
|
22
|
+
(color >> 8) & 0xff
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
pub(crate) fn color_alpha(color: u32) -> u32 {
|
|
26
|
+
color & 0xff
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
fn clamp_unit(value: f32) -> f32 {
|
|
30
|
+
value.clamp(0.0, 1.0)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
fn hue_to_rgb(p: f32, q: f32, mut t: f32) -> f32 {
|
|
34
|
+
if t < 0.0 {
|
|
35
|
+
t += 1.0;
|
|
36
|
+
}
|
|
37
|
+
if t > 1.0 {
|
|
38
|
+
t -= 1.0;
|
|
39
|
+
}
|
|
40
|
+
if t < 1.0 / 6.0 {
|
|
41
|
+
return p + (q - p) * 6.0 * t;
|
|
42
|
+
}
|
|
43
|
+
if t < 0.5 {
|
|
44
|
+
return q;
|
|
45
|
+
}
|
|
46
|
+
if t < 2.0 / 3.0 {
|
|
47
|
+
return p + (q - p) * ((2.0 / 3.0) - t) * 6.0;
|
|
48
|
+
}
|
|
49
|
+
p
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
pub fn hsl_to_color(hue: f32, saturation: f32, lightness: f32) -> u32 {
|
|
53
|
+
let normalized_hue = hue % 360.0;
|
|
54
|
+
let hue = if normalized_hue < 0.0 {
|
|
55
|
+
normalized_hue + 360.0
|
|
56
|
+
} else {
|
|
57
|
+
normalized_hue
|
|
58
|
+
};
|
|
59
|
+
let saturation = clamp_unit(saturation);
|
|
60
|
+
let lightness = clamp_unit(lightness);
|
|
61
|
+
if saturation <= 0.0 {
|
|
62
|
+
let channel = (lightness * 255.0) as u32;
|
|
63
|
+
return rgb(channel, channel, channel);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let hue_fraction = hue / 360.0;
|
|
67
|
+
let q = if lightness < 0.5 {
|
|
68
|
+
lightness * (1.0 + saturation)
|
|
69
|
+
} else {
|
|
70
|
+
lightness + saturation - (lightness * saturation)
|
|
71
|
+
};
|
|
72
|
+
let p = 2.0 * lightness - q;
|
|
73
|
+
rgba(
|
|
74
|
+
(clamp_unit(hue_to_rgb(p, q, hue_fraction + 1.0 / 3.0)) * 255.0) as u32,
|
|
75
|
+
(clamp_unit(hue_to_rgb(p, q, hue_fraction)) * 255.0) as u32,
|
|
76
|
+
(clamp_unit(hue_to_rgb(p, q, hue_fraction - 1.0 / 3.0)) * 255.0) as u32,
|
|
77
|
+
0xff,
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
fn mix_channel(from: u32, to: u32, amount: f32) -> u32 {
|
|
82
|
+
let weight = clamp_unit(amount);
|
|
83
|
+
(from as f32 + ((to as f32 - from as f32) * weight)).round() as u32
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
pub fn mix_color(from: u32, to: u32, amount: f32) -> u32 {
|
|
87
|
+
rgba(
|
|
88
|
+
mix_channel(color_red(from), color_red(to), amount),
|
|
89
|
+
mix_channel(color_green(from), color_green(to), amount),
|
|
90
|
+
mix_channel(color_blue(from), color_blue(to), amount),
|
|
91
|
+
mix_channel(color_alpha(from), color_alpha(to), amount),
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#[cfg(test)]
|
|
96
|
+
mod tests {
|
|
97
|
+
use super::*;
|
|
98
|
+
|
|
99
|
+
#[test]
|
|
100
|
+
fn color_helpers_match_effindom_rgba_packing() {
|
|
101
|
+
assert_eq!(rgb(0x12, 0x34, 0x56), 0x123456ff);
|
|
102
|
+
assert_eq!(rgba(0x12, 0x34, 0x56, 0x78), 0x12345678);
|
|
103
|
+
assert_eq!(with_alpha(0x123456ff, 0x78), 0x12345678);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
#[test]
|
|
107
|
+
fn color_helpers_mask_channels_and_interpolate() {
|
|
108
|
+
assert_eq!(rgba(0x112, 0x134, 0x156, 0x178), 0x12345678);
|
|
109
|
+
assert_eq!(mix_color(rgb(0, 0, 0), rgb(255, 255, 255), 0.5), rgba(128, 128, 128, 255));
|
|
110
|
+
assert_eq!(hsl_to_color(0.0, 1.0, 0.5), rgb(255, 0, 0));
|
|
111
|
+
}
|
|
112
|
+
}
|
package/src/controls/nav_link.rs
CHANGED
|
@@ -59,6 +59,8 @@ impl NavLink {
|
|
|
59
59
|
label_node
|
|
60
60
|
.font_family(theme.fonts.body_family.clone())
|
|
61
61
|
.font_size(15.0)
|
|
62
|
+
.text_color(theme.colors.accent)
|
|
63
|
+
.selectable(false)
|
|
62
64
|
.cursor(CursorStyle::Pointer);
|
|
63
65
|
root.justify_content(JustifyContent::Start)
|
|
64
66
|
.align_items(AlignItems::Center)
|
|
@@ -440,10 +442,7 @@ impl NavLinkEventTarget {
|
|
|
440
442
|
let color = if self.hovered.get() {
|
|
441
443
|
theme.colors.accent_hovered
|
|
442
444
|
} else {
|
|
443
|
-
self.text_color_override
|
|
444
|
-
.get()
|
|
445
|
-
.or_else(|| self.label.configured_text_color())
|
|
446
|
-
.unwrap_or(theme.colors.accent)
|
|
445
|
+
self.text_color_override.get().unwrap_or(theme.colors.accent)
|
|
447
446
|
};
|
|
448
447
|
if self.label.handle() != NodeHandle::INVALID {
|
|
449
448
|
ui::set_text_color(self.label.handle().raw(), color);
|
package/src/controls/shared.rs
CHANGED
|
@@ -59,10 +59,7 @@ pub(crate) fn update_semantic_checked(
|
|
|
59
59
|
state: SemanticCheckedState,
|
|
60
60
|
announce: bool,
|
|
61
61
|
) {
|
|
62
|
-
if let Some(
|
|
63
|
-
|
|
64
|
-
if announce {
|
|
65
|
-
ui::request_semantic_announcement(handle.raw());
|
|
66
|
-
}
|
|
62
|
+
if let Some(root) = weak_root.upgrade() {
|
|
63
|
+
root.set_semantic_checked(state, announce);
|
|
67
64
|
}
|
|
68
65
|
}
|
package/src/controls/tests.rs
CHANGED
|
@@ -2927,6 +2927,23 @@ fn checkbox_user_activation_emits_changed_and_semantic_announcement() {
|
|
|
2927
2927
|
Application::unmount();
|
|
2928
2928
|
}
|
|
2929
2929
|
|
|
2930
|
+
#[test]
|
|
2931
|
+
fn checkbox_prebuild_state_is_retained_into_semantic_build_state() {
|
|
2932
|
+
ffi::test::reset();
|
|
2933
|
+
let checkbox = checkbox("Agree");
|
|
2934
|
+
checkbox.check(true);
|
|
2935
|
+
|
|
2936
|
+
Application::mount(checkbox.clone());
|
|
2937
|
+
let handle = checkbox.retained_node_ref().handle().raw();
|
|
2938
|
+
let calls = ffi::test::take_calls();
|
|
2939
|
+
assert!(calls.iter().any(|call| matches!(
|
|
2940
|
+
call,
|
|
2941
|
+
Call::SetSemanticChecked { handle: checked_handle, checked_state_enum }
|
|
2942
|
+
if *checked_handle == handle && *checked_state_enum == SemanticCheckedState::True as u32
|
|
2943
|
+
)));
|
|
2944
|
+
Application::unmount();
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2930
2947
|
#[test]
|
|
2931
2948
|
fn radio_and_switch_programmatic_changes_emit_without_semantic_announcement() {
|
|
2932
2949
|
ffi::test::reset();
|
package/src/lib.rs
CHANGED
|
@@ -4,6 +4,7 @@ pub mod assets;
|
|
|
4
4
|
#[doc(hidden)]
|
|
5
5
|
pub mod bindings;
|
|
6
6
|
pub mod bitmap;
|
|
7
|
+
pub mod color;
|
|
7
8
|
#[doc(hidden)]
|
|
8
9
|
pub mod bridge_callbacks;
|
|
9
10
|
pub(crate) mod context_menu_manager;
|
|
@@ -408,6 +409,7 @@ pub mod prelude {
|
|
|
408
409
|
pub use crate::app::{Application, ApplicationRegistration, ManagedApplication};
|
|
409
410
|
pub use crate::bitmap::{Bitmap, BitmapTextReadyEventArgs};
|
|
410
411
|
pub use crate::bridge_callbacks::current_route;
|
|
412
|
+
pub use crate::color::{hsl_to_color, mix_color, rgb, rgba, with_alpha};
|
|
411
413
|
pub use crate::controls::{
|
|
412
414
|
anti_selection_area, button, checkbox, clear_control_templates, combo_box, context_menu,
|
|
413
415
|
create_default_button_presenter, create_default_checkbox_indicator_presenter,
|
|
@@ -486,10 +488,10 @@ pub mod prelude {
|
|
|
486
488
|
auto, column, custom_drawable, fill, flex_box, grid, image, pct, portal, px, row,
|
|
487
489
|
scroll_box, scroll_view, svg, text, viewport_height, viewport_width, virtual_list, Border,
|
|
488
490
|
Child, ContextMenuEventArgs, Corners, CustomDrawable, DrawableInvalidator, EdgeInsets,
|
|
489
|
-
FlexBox, FlexBoxSurface, GradientStop, Grid, GridTrack, HasFlexBoxRoot,
|
|
490
|
-
Length, Node, PresenterHostStyle, ScrollBar, ScrollBarStyle,
|
|
491
|
-
ScrollBox, ScrollState, ScrollView, Shadow, Svg, SvgNode, Text,
|
|
492
|
-
ThemeBindable, VirtualList,
|
|
491
|
+
FlexBox, FlexBoxSurface, GradientStop, Grid, GridTrack, HasFlexBoxRoot, HasTextNode, Image,
|
|
492
|
+
ImageNode, Length, Node, PresenterHostStyle, ScrollBar, ScrollBarStyle,
|
|
493
|
+
ScrollBarVisibility, ScrollBox, ScrollState, ScrollView, Shadow, Svg, SvgNode, Text,
|
|
494
|
+
TextCore, TextLayoutSurface, TextNode, ThemeBindable, VirtualList,
|
|
493
495
|
};
|
|
494
496
|
pub use crate::persisted;
|
|
495
497
|
pub use crate::platform;
|
|
@@ -534,6 +536,7 @@ pub use app::{Application, ApplicationRegistration, ManagedApplication};
|
|
|
534
536
|
pub use assets::*;
|
|
535
537
|
pub use bitmap::{Bitmap, BitmapTextReadyEventArgs};
|
|
536
538
|
pub use bridge_callbacks::current_route;
|
|
539
|
+
pub use color::{hsl_to_color, mix_color, rgb, rgba, with_alpha};
|
|
537
540
|
pub use controls::{
|
|
538
541
|
anti_selection_area, button, checkbox, clear_control_templates, combo_box, context_menu,
|
|
539
542
|
create_default_button_presenter, create_default_checkbox_indicator_presenter,
|
|
@@ -606,9 +609,10 @@ pub use node::{
|
|
|
606
609
|
auto, column, custom_drawable, fill, flex_box, grid, image, pct, portal, px, row, scroll_box,
|
|
607
610
|
scroll_view, svg, text, viewport_height, viewport_width, virtual_list, Border, Child,
|
|
608
611
|
ContextMenuEventArgs, Corners, CustomDrawable, DrawableInvalidator, EdgeInsets, FlexBox,
|
|
609
|
-
FlexBoxSurface, GradientStop, Grid, GridTrack, HasFlexBoxRoot, Image, ImageNode,
|
|
610
|
-
PresenterHostStyle, ScrollBar, ScrollBarStyle, ScrollBarVisibility, ScrollBox,
|
|
611
|
-
ScrollView, Shadow, Svg, SvgNode, Text, TextCore,
|
|
612
|
+
FlexBoxSurface, GradientStop, Grid, GridTrack, HasFlexBoxRoot, HasTextNode, Image, ImageNode,
|
|
613
|
+
Length, Node, PresenterHostStyle, ScrollBar, ScrollBarStyle, ScrollBarVisibility, ScrollBox,
|
|
614
|
+
ScrollState, ScrollView, Shadow, Svg, SvgNode, Text, TextCore, TextLayoutSurface, TextNode,
|
|
615
|
+
ThemeBindable, VirtualList,
|
|
612
616
|
};
|
|
613
617
|
pub use persisted::*;
|
|
614
618
|
pub use platform::*;
|
package/src/node/core.rs
CHANGED
|
@@ -513,6 +513,26 @@ impl NodeRef {
|
|
|
513
513
|
self.inner.borrow().handle
|
|
514
514
|
}
|
|
515
515
|
|
|
516
|
+
pub(crate) fn set_semantic_checked(
|
|
517
|
+
&self,
|
|
518
|
+
state: SemanticCheckedState,
|
|
519
|
+
announce: bool,
|
|
520
|
+
) {
|
|
521
|
+
let handle = {
|
|
522
|
+
let mut core = self.inner.borrow_mut();
|
|
523
|
+
core.behavior.semantic_checked = Some(state);
|
|
524
|
+
core.handle
|
|
525
|
+
};
|
|
526
|
+
if handle == NodeHandle::INVALID {
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
ui::set_semantic_checked(handle.raw(), state as u32);
|
|
530
|
+
if announce {
|
|
531
|
+
ui::request_semantic_announcement(handle.raw());
|
|
532
|
+
}
|
|
533
|
+
crate::frame_scheduler::mark_needs_commit();
|
|
534
|
+
}
|
|
535
|
+
|
|
516
536
|
pub(crate) fn ptr_eq(&self, other: &Self) -> bool {
|
|
517
537
|
Rc::ptr_eq(&self.inner, &other.inner)
|
|
518
538
|
}
|
package/src/node/mod.rs
CHANGED
|
@@ -100,6 +100,85 @@ impl ThemeBindable for FlexBox {
|
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
pub trait HasTextNode {
|
|
104
|
+
fn text_node(&self) -> &TextNode;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
pub trait TextLayoutSurface: HasTextNode {
|
|
108
|
+
fn width(&self, width: f32, unit: Unit) -> &Self {
|
|
109
|
+
self.text_node().width(width, unit);
|
|
110
|
+
self
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
fn height(&self, height: f32, unit: Unit) -> &Self {
|
|
114
|
+
self.text_node().height(height, unit);
|
|
115
|
+
self
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
fn fill_width(&self) -> &Self {
|
|
119
|
+
self.text_node().fill_width();
|
|
120
|
+
self
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
fn fill_height(&self) -> &Self {
|
|
124
|
+
self.text_node().fill_height();
|
|
125
|
+
self
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fn fill_size(&self) -> &Self {
|
|
129
|
+
self.text_node().fill_size();
|
|
130
|
+
self
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
fn line_height(&self, line_height: f32) -> &Self {
|
|
134
|
+
self.text_node().line_height(line_height);
|
|
135
|
+
self
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
fn text_align(&self, align: TextAlign) -> &Self {
|
|
139
|
+
self.text_node().text_align(align);
|
|
140
|
+
self
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
fn text_vertical_align(&self, align: TextVerticalAlign) -> &Self {
|
|
144
|
+
self.text_node().text_vertical_align(align);
|
|
145
|
+
self
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
fn text_limits(&self, max_chars: i32, max_lines: i32) -> &Self {
|
|
149
|
+
self.text_node().text_limits(max_chars, max_lines);
|
|
150
|
+
self
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
fn max_lines(&self, max_lines: i32) -> &Self {
|
|
154
|
+
self.text_node().max_lines(max_lines);
|
|
155
|
+
self
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
fn wrapping(&self, wrap: bool) -> &Self {
|
|
159
|
+
self.text_node().wrapping(wrap);
|
|
160
|
+
self
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
fn text_overflow(&self, overflow: TextOverflow) -> &Self {
|
|
164
|
+
self.text_node().text_overflow(overflow);
|
|
165
|
+
self
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
fn text_overflow_fade(&self, horizontal: bool, vertical: bool) -> &Self {
|
|
169
|
+
self.text_node().text_overflow_fade(horizontal, vertical);
|
|
170
|
+
self
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
impl<T: HasTextNode> TextLayoutSurface for T {}
|
|
175
|
+
|
|
176
|
+
impl HasTextNode for TextNode {
|
|
177
|
+
fn text_node(&self) -> &TextNode {
|
|
178
|
+
self
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
103
182
|
pub trait FlexBoxSurface: HasFlexBoxRoot {
|
|
104
183
|
fn width(&self, width: f32, unit: Unit) -> &Self {
|
|
105
184
|
self.flex_box_root().width(width, unit);
|
package/src/node/text_node.rs
CHANGED
|
@@ -164,10 +164,6 @@ impl TextNode {
|
|
|
164
164
|
self
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
-
pub(crate) fn configured_text_color(&self) -> Option<u32> {
|
|
168
|
-
self.props.borrow().text_color
|
|
169
|
-
}
|
|
170
|
-
|
|
171
167
|
pub fn style_runs(&self, words: Vec<u32>) -> &Self {
|
|
172
168
|
{
|
|
173
169
|
let mut props = self.props.borrow_mut();
|
package/src/text.rs
CHANGED
|
@@ -3,7 +3,7 @@ use crate::bindings::ui;
|
|
|
3
3
|
use crate::ffi::{TextAlign, TextOverflow, TextVerticalAlign, Unit};
|
|
4
4
|
use crate::frame_scheduler::on_loaded;
|
|
5
5
|
use crate::logger::error;
|
|
6
|
-
use crate::node::{Node, TextNode};
|
|
6
|
+
use crate::node::{HasTextNode, Node, TextNode, ThemeBindable};
|
|
7
7
|
use crate::theme;
|
|
8
8
|
use crate::typography::{FontFamily, FontStack, FontStyle, FontWeight};
|
|
9
9
|
use std::cell::RefCell;
|
|
@@ -247,6 +247,29 @@ impl Deref for RichText {
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
impl HasTextNode for RichText {
|
|
251
|
+
fn text_node(&self) -> &TextNode {
|
|
252
|
+
&self.node
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
impl ThemeBindable for RichText {
|
|
257
|
+
fn theme_binding_node(&self) -> crate::node::NodeRef {
|
|
258
|
+
self.node.retained_node_ref()
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
fn weak_theme_target(&self) -> Box<dyn Fn() -> Option<Self>> {
|
|
262
|
+
let weak_node = self.node.weak_theme_target();
|
|
263
|
+
let weak_state = Rc::downgrade(&self.state);
|
|
264
|
+
Box::new(move || {
|
|
265
|
+
Some(Self {
|
|
266
|
+
node: weak_node()?,
|
|
267
|
+
state: weak_state.upgrade()?,
|
|
268
|
+
})
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
250
273
|
impl Node for RichText {
|
|
251
274
|
fn retained_node_ref(&self) -> crate::node::NodeRef {
|
|
252
275
|
self.node.retained_node_ref()
|
package/src/theme.rs
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
use crate::generated::framework_host_services;
|
|
2
|
+
use crate::color::{
|
|
3
|
+
color_alpha, color_blue, color_green, color_red, mix_color, rgb, rgba, with_alpha,
|
|
4
|
+
};
|
|
2
5
|
use crate::signal::{Callback, Signal, SubscriptionGuard};
|
|
3
6
|
use crate::typography::{FontFamily, FontStack};
|
|
4
7
|
use std::cell::RefCell;
|
|
5
8
|
use std::rc::Rc;
|
|
6
9
|
|
|
7
|
-
const DEFAULT_ACCENT_COLOR: u32 =
|
|
8
|
-
const WHITE: u32 =
|
|
9
|
-
const BLACK: u32 =
|
|
10
|
+
const DEFAULT_ACCENT_COLOR: u32 = rgb(0x25, 0x63, 0xeb);
|
|
11
|
+
const WHITE: u32 = rgb(0xff, 0xff, 0xff);
|
|
12
|
+
const BLACK: u32 = rgb(0x00, 0x00, 0x00);
|
|
10
13
|
|
|
11
14
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
12
15
|
pub struct Colors {
|
|
@@ -166,49 +169,6 @@ fn default_fonts() -> Fonts {
|
|
|
166
169
|
}
|
|
167
170
|
}
|
|
168
171
|
|
|
169
|
-
const fn rgba(r: u32, g: u32, b: u32, a: u32) -> u32 {
|
|
170
|
-
(r << 24) | (g << 16) | (b << 8) | a
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
fn color_red(color: u32) -> u32 {
|
|
174
|
-
(color >> 24) & 0xff
|
|
175
|
-
}
|
|
176
|
-
fn color_green(color: u32) -> u32 {
|
|
177
|
-
(color >> 16) & 0xff
|
|
178
|
-
}
|
|
179
|
-
fn color_blue(color: u32) -> u32 {
|
|
180
|
-
(color >> 8) & 0xff
|
|
181
|
-
}
|
|
182
|
-
fn color_alpha(color: u32) -> u32 {
|
|
183
|
-
color & 0xff
|
|
184
|
-
}
|
|
185
|
-
fn clamp_unit(value: f32) -> f32 {
|
|
186
|
-
value.clamp(0.0, 1.0)
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
fn mix_channel(from: u32, to: u32, amount: f32) -> u32 {
|
|
190
|
-
let weight = clamp_unit(amount);
|
|
191
|
-
(from as f32 + ((to as f32 - from as f32) * weight)).round() as u32
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
fn mix_color(from: u32, to: u32, amount: f32) -> u32 {
|
|
195
|
-
rgba(
|
|
196
|
-
mix_channel(color_red(from), color_red(to), amount),
|
|
197
|
-
mix_channel(color_green(from), color_green(to), amount),
|
|
198
|
-
mix_channel(color_blue(from), color_blue(to), amount),
|
|
199
|
-
mix_channel(color_alpha(from), color_alpha(to), amount),
|
|
200
|
-
)
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
fn with_alpha(color: u32, alpha: u32) -> u32 {
|
|
204
|
-
rgba(
|
|
205
|
-
color_red(color),
|
|
206
|
-
color_green(color),
|
|
207
|
-
color_blue(color),
|
|
208
|
-
alpha,
|
|
209
|
-
)
|
|
210
|
-
}
|
|
211
|
-
|
|
212
172
|
fn normalize_accent_color(color: u32) -> u32 {
|
|
213
173
|
if color == 0 {
|
|
214
174
|
return DEFAULT_ACCENT_COLOR;
|