1
0
mirror of https://github.com/emilk/egui.git synced 2026-08-30 13:20:05 -04:00

Use Rgba (4xf32) instead of Color32 in all interfaces

This simplifies a few things, but some benchmarks gets worse,
probably due to the increased memory use (and thus more cache misses).

I don't plan to merge this, but leave it here as an experiment
This commit is contained in:
Emil Ernerfeldt
2021-08-15 20:15:14 +02:00
parent 96c45716be
commit 5dd68337c4
42 changed files with 285 additions and 371 deletions

View File

@@ -201,6 +201,7 @@ impl Rgba {
pub const RED: Rgba = Rgba::from_rgb(1.0, 0.0, 0.0);
pub const GREEN: Rgba = Rgba::from_rgb(0.0, 1.0, 0.0);
pub const BLUE: Rgba = Rgba::from_rgb(0.0, 0.0, 1.0);
pub const LIGHT_BLUE: Rgba = Rgba::from_rgb(0.26, 0.35, 1.0);
#[inline(always)]
pub const fn from_rgba_premultiplied(r: f32, g: f32, b: f32, a: f32) -> Self {
@@ -753,10 +754,11 @@ impl From<Hsva> for HsvaGamma {
/// Cheap and ugly.
/// Made for graying out disabled `Ui`:s.
pub fn tint_color_towards(color: Color32, target: Color32) -> Color32 {
pub fn tint_color32_towards(color: Color32, target: Color32) -> Color32 {
let [mut r, mut g, mut b, mut a] = color.to_array();
if a == 0 {
// Additive color.
r /= 2;
g /= 2;
b /= 2;
@@ -776,6 +778,11 @@ pub fn tint_color_towards(color: Color32, target: Color32) -> Color32 {
Color32::from_rgba_premultiplied(r, g, b, a)
}
pub fn tint_rgba_towards(color: Rgba, target: Rgba) -> Rgba {
// sRGBA (gamma) is more of a perceptual color space, so we use that
tint_color32_towards(color.into(), target.into()).into()
}
#[cfg(feature = "cint")]
mod impl_cint {
use super::*;

View File

@@ -134,7 +134,7 @@ pub(crate) struct PaintRect {
pub rect: emath::Rect,
/// How rounded the corners are. Use `0.0` for no rounding.
pub corner_radius: f32,
pub fill: Color32,
pub fill: Rgba,
pub stroke: Stroke,
}

View File

@@ -9,15 +9,15 @@ use emath::*;
pub struct Vertex {
/// Logical pixel coordinates (points).
/// (0,0) is the top left corner of the screen.
pub pos: Pos2, // 64 bit
pub pos: Pos2, // 2xf32 (64 bit)
/// Normalized texture coordinates.
/// (0, 0) is the top left corner of the texture.
/// (1, 1) is the bottom right corner of the texture.
pub uv: Pos2, // 64 bit
pub uv: Pos2, // 2xf32 (64 bit)
/// sRGBA with premultiplied alpha
pub color: Color32, // 32 bit
/// Linear RGBA with premultiplied alpha
pub color: Rgba, // 4xf32 (128 bit)
}
/// Textured triangles in two dimensions.
@@ -93,7 +93,7 @@ impl Mesh {
}
#[inline(always)]
pub fn colored_vertex(&mut self, pos: Pos2, color: Color32) {
pub fn colored_vertex(&mut self, pos: Pos2, color: Rgba) {
crate::epaint_assert!(self.texture_id == TextureId::Egui);
self.vertices.push(Vertex {
pos,
@@ -125,7 +125,7 @@ impl Mesh {
}
/// Rectangle with a texture and color.
pub fn add_rect_with_uv(&mut self, rect: Rect, uv: Rect, color: Color32) {
pub fn add_rect_with_uv(&mut self, rect: Rect, uv: Rect, color: Rgba) {
#![allow(clippy::identity_op)]
let idx = self.vertices.len() as u32;
@@ -156,7 +156,7 @@ impl Mesh {
/// Uniformly colored rectangle.
#[inline(always)]
pub fn add_colored_rect(&mut self, rect: Rect, color: Color32) {
pub fn add_colored_rect(&mut self, rect: Rect, color: Rgba) {
crate::epaint_assert!(self.texture_id == TextureId::Egui);
self.add_rect_with_uv(rect, [WHITE_UV, WHITE_UV].into(), color)
}

View File

@@ -10,7 +10,7 @@ pub struct Shadow {
pub extrusion: f32,
/// Color of the opaque center of the shadow.
pub color: Color32,
pub color: Rgba,
}
impl Shadow {
@@ -18,7 +18,7 @@ impl Shadow {
pub fn small_dark() -> Self {
Self {
extrusion: 16.0,
color: Color32::from_black_alpha(96),
color: Color32::from_black_alpha(96).into(),
}
}
@@ -26,7 +26,7 @@ impl Shadow {
pub fn small_light() -> Self {
Self {
extrusion: 16.0,
color: Color32::from_black_alpha(32),
color: Color32::from_black_alpha(32).into(),
}
}
@@ -34,7 +34,7 @@ impl Shadow {
pub fn big_dark() -> Self {
Self {
extrusion: 32.0,
color: Color32::from_black_alpha(96),
color: Color32::from_black_alpha(96).into(),
}
}
@@ -42,7 +42,7 @@ impl Shadow {
pub fn big_light() -> Self {
Self {
extrusion: 32.0,
color: Color32::from_black_alpha(40),
color: Color32::from_black_alpha(40).into(),
}
}

View File

@@ -1,6 +1,6 @@
use crate::{
text::{Fonts, Galley, TextStyle},
Color32, Mesh, Stroke,
Mesh, Rgba, Stroke,
};
use emath::*;
@@ -17,7 +17,7 @@ pub enum Shape {
Circle {
center: Pos2,
radius: f32,
fill: Color32,
fill: Rgba,
stroke: Stroke,
},
LineSegment {
@@ -30,14 +30,14 @@ pub enum Shape {
/// This is required if `fill != TRANSPARENT`.
closed: bool,
/// Fill is only supported for convex polygons.
fill: Color32,
fill: Rgba,
stroke: Stroke,
},
Rect {
rect: Rect,
/// How rounded the corners are. Use `0.0` for no rounding.
corner_radius: f32,
fill: Color32,
fill: Rgba,
stroke: Stroke,
},
Text {
@@ -46,7 +46,7 @@ pub enum Shape {
/// The layed out text.
galley: std::sync::Arc<Galley>,
/// Text color (foreground).
color: Color32,
color: Rgba,
/// If true, tilt the letters for a hacky italics effect.
fake_italics: bool,
},
@@ -89,7 +89,7 @@ impl Shape {
/// Turn a line into equally spaced dots.
pub fn dotted_line(
points: &[Pos2],
color: impl Into<Color32>,
color: impl Into<Rgba>,
spacing: f32,
radius: f32,
) -> Vec<Self> {
@@ -113,7 +113,7 @@ impl Shape {
/// A convex polygon with a fill and optional stroke.
pub fn convex_polygon(
points: Vec<Pos2>,
fill: impl Into<Color32>,
fill: impl Into<Rgba>,
stroke: impl Into<Stroke>,
) -> Self {
Self::Path {
@@ -125,11 +125,11 @@ impl Shape {
}
#[deprecated = "Renamed convex_polygon"]
pub fn polygon(points: Vec<Pos2>, fill: impl Into<Color32>, stroke: impl Into<Stroke>) -> Self {
pub fn polygon(points: Vec<Pos2>, fill: impl Into<Rgba>, stroke: impl Into<Stroke>) -> Self {
Self::convex_polygon(points, fill, stroke)
}
pub fn circle_filled(center: Pos2, radius: f32, fill_color: impl Into<Color32>) -> Self {
pub fn circle_filled(center: Pos2, radius: f32, fill_color: impl Into<Rgba>) -> Self {
Self::Circle {
center,
radius,
@@ -147,7 +147,7 @@ impl Shape {
}
}
pub fn rect_filled(rect: Rect, corner_radius: f32, fill_color: impl Into<Color32>) -> Self {
pub fn rect_filled(rect: Rect, corner_radius: f32, fill_color: impl Into<Rgba>) -> Self {
Self::Rect {
rect,
corner_radius,
@@ -172,7 +172,7 @@ impl Shape {
anchor: Align2,
text: impl ToString,
text_style: TextStyle,
color: Color32,
color: Rgba,
) -> Self {
let galley = fonts.layout_multiline(text_style, text.to_string(), f32::INFINITY);
let rect = anchor.anchor_rect(Rect::from_min_size(pos, galley.size));
@@ -190,7 +190,7 @@ fn points_from_line(
line: &[Pos2],
spacing: f32,
radius: f32,
color: Color32,
color: Rgba,
shapes: &mut Vec<Shape>,
) {
let mut position_on_segment = 0.0;

View File

@@ -1,6 +1,6 @@
use crate::*;
pub fn adjust_colors(shape: &mut Shape, adjust_color: &impl Fn(&mut Color32)) {
pub fn adjust_colors(shape: &mut Shape, adjust_color: &impl Fn(&mut Rgba)) {
#![allow(clippy::match_same_arms)]
match shape {
Shape::Noop => {}

View File

@@ -7,16 +7,16 @@ use super::*;
#[cfg_attr(feature = "persistence", derive(serde::Deserialize, serde::Serialize))]
pub struct Stroke {
pub width: f32,
pub color: Color32,
pub color: Rgba,
}
impl Stroke {
/// Same as [`Stroke::default`].
pub fn none() -> Self {
Self::new(0.0, Color32::TRANSPARENT)
Self::new(0.0, Rgba::TRANSPARENT)
}
pub fn new(width: impl Into<f32>, color: impl Into<Color32>) -> Self {
pub fn new(width: impl Into<f32>, color: impl Into<Rgba>) -> Self {
Self {
width: width.into(),
color: color.into(),
@@ -26,7 +26,7 @@ impl Stroke {
impl<Color> From<(f32, Color)> for Stroke
where
Color: Into<Color32>,
Color: Into<Rgba>,
{
fn from((width, color): (f32, Color)) -> Stroke {
Stroke::new(width, color)

View File

@@ -272,13 +272,8 @@ impl TessellationOptions {
}
/// Tessellate the given convex area into a polygon.
fn fill_closed_path(
path: &[PathPoint],
color: Color32,
options: TessellationOptions,
out: &mut Mesh,
) {
if color == Color32::TRANSPARENT {
fn fill_closed_path(path: &[PathPoint], color: Rgba, options: TessellationOptions, out: &mut Mesh) {
if color == Rgba::TRANSPARENT {
return;
}
@@ -286,7 +281,7 @@ fn fill_closed_path(
if options.anti_alias {
out.reserve_triangles(3 * n as usize);
out.reserve_vertices(2 * n as usize);
let color_outer = Color32::TRANSPARENT;
let color_outer = Rgba::TRANSPARENT;
let idx_inner = out.vertices.len() as u32;
let idx_outer = idx_inner + 1;
for i in 2..n {
@@ -324,7 +319,7 @@ fn stroke_path(
options: TessellationOptions,
out: &mut Mesh,
) {
if stroke.width <= 0.0 || stroke.color == Color32::TRANSPARENT {
if stroke.width <= 0.0 || stroke.color == Rgba::TRANSPARENT {
return;
}
@@ -333,7 +328,7 @@ fn stroke_path(
if options.anti_alias {
let color_inner = stroke.color;
let color_outer = Color32::TRANSPARENT;
let color_outer = Rgba::TRANSPARENT;
let thin_line = stroke.width <= options.aa_size;
if thin_line {
@@ -346,7 +341,7 @@ fn stroke_path(
// Fade out as it gets thinner:
let color_inner = mul_color(color_inner, stroke.width / options.aa_size);
if color_inner == Color32::TRANSPARENT {
if color_inner == Rgba::TRANSPARENT {
return;
}
@@ -438,7 +433,7 @@ fn stroke_path(
// Fade out thin lines rather than making them thinner
let radius = options.aa_size / 2.0;
let color = mul_color(stroke.color, stroke.width / options.aa_size);
if color == Color32::TRANSPARENT {
if color == Rgba::TRANSPARENT {
return;
}
for p in path {
@@ -455,11 +450,10 @@ fn stroke_path(
}
}
fn mul_color(color: Color32, factor: f32) -> Color32 {
#[inline]
fn mul_color(color: Rgba, factor: f32) -> Rgba {
crate::epaint_assert!(0.0 <= factor && factor <= 1.0);
// As an unfortunate side-effect of using premultiplied alpha
// we need a somewhat expensive conversion to linear space and back.
color.linear_multiply(factor)
color * factor
}
// ----------------------------------------------------------------------------
@@ -552,7 +546,7 @@ impl Tessellator {
path.add_open_points(&points);
}
if fill != Color32::TRANSPARENT {
if fill != Rgba::TRANSPARENT {
crate::epaint_assert!(
closed,
"You asked to fill a path that is not closed. That makes no sense."
@@ -634,11 +628,11 @@ impl Tessellator {
tex_size: [usize; 2],
pos: Pos2,
galley: &super::Galley,
color: Color32,
color: Rgba,
fake_italics: bool,
out: &mut Mesh,
) {
if color == Color32::TRANSPARENT || galley.is_empty() {
if color == Rgba::TRANSPARENT || galley.is_empty() {
return;
}
if cfg!(any(