diff --git a/gpui/examples/text.rs b/gpui/examples/text.rs index 58314b5e948ab7175394f78e32a8721e4fcd54c5..45aa5931129ed43f9e6bf76a1063392827063ed1 100644 --- a/gpui/examples/text.rs +++ b/gpui/examples/text.rs @@ -1,5 +1,5 @@ use gpui::{ - color::ColorU, + color::Color, fonts::{Properties, Weight}, DebugContext, Element as _, Quad, }; @@ -82,17 +82,17 @@ impl gpui::Element for TextElement { text, font_size, &[ - (1, normal, ColorU::default()), - (1, bold, ColorU::default()), - (1, normal, ColorU::default()), - (1, bold, ColorU::default()), - (text.len() - 4, normal, ColorU::default()), + (1, normal, Color::default()), + (1, bold, Color::default()), + (1, normal, Color::default()), + (1, bold, Color::default()), + (text.len() - 4, normal, Color::default()), ], ); cx.scene.push_quad(Quad { bounds: bounds, - background: Some(ColorU::white()), + background: Some(Color::white()), ..Default::default() }); line.paint(bounds.origin(), bounds, cx); diff --git a/gpui/src/color.rs b/gpui/src/color.rs index 95b966493e08c0005132d8942436f45ffd6dbe73..818b07111d590e126c341f4d63a55f0b392860cd 100644 --- a/gpui/src/color.rs +++ b/gpui/src/color.rs @@ -1,9 +1,78 @@ +use std::{ + fmt, + ops::{Deref, DerefMut}, +}; + use crate::json::ToJson; -pub use pathfinder_color::*; +use pathfinder_color::ColorU; +use serde::{Deserialize, Deserializer}; use serde_json::json; -impl ToJson for ColorU { +#[derive(Clone, Copy, Default, PartialEq, Eq, Hash)] +#[repr(transparent)] +pub struct Color(ColorU); + +impl Color { + pub fn transparent_black() -> Self { + Self(ColorU::transparent_black()) + } + + pub fn black() -> Self { + Self(ColorU::black()) + } + + pub fn white() -> Self { + Self(ColorU::white()) + } + + pub fn new(r: u8, g: u8, b: u8, a: u8) -> Self { + Self(ColorU::new(r, g, b, a)) + } + + pub fn from_u32(rgba: u32) -> Self { + Self(ColorU::from_u32(rgba)) + } +} + +impl<'de> Deserialize<'de> for Color { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let mut rgba = u32::deserialize(deserializer)?; + + if rgba <= 0xFFFFFF { + rgba = (rgba << 8) + 0xFF; + } + + Ok(Self::from_u32(rgba)) + } +} + +impl ToJson for Color { fn to_json(&self) -> serde_json::Value { - json!(format!("0x{:x}{:x}{:x}", self.r, self.g, self.b)) + json!(format!( + "0x{:x}{:x}{:x}{:x}", + self.0.r, self.0.g, self.0.b, self.0.a + )) + } +} + +impl Deref for Color { + type Target = ColorU; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Color { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl fmt::Debug for Color { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) } } diff --git a/gpui/src/elements/container.rs b/gpui/src/elements/container.rs index 9ae084193143a48db09a2d21af9305bd869dae90..212e349314e48cb4acc827770d51b14dc6cd30c4 100644 --- a/gpui/src/elements/container.rs +++ b/gpui/src/elements/container.rs @@ -1,20 +1,24 @@ use pathfinder_geometry::rect::RectF; +use serde::Deserialize; use serde_json::json; use crate::{ - color::ColorU, - geometry::vector::{vec2f, Vector2F}, + color::Color, + geometry::{ + deserialize_vec2f, + vector::{vec2f, Vector2F}, + }, json::ToJson, scene::{self, Border, Quad}, AfterLayoutContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext, SizeConstraint, }; -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, Deserialize)] pub struct ContainerStyle { margin: Margin, padding: Padding, - background_color: Option, + background_color: Option, border: Border, corner_radius: f32, shadow: Option, @@ -80,8 +84,8 @@ impl Container { self } - pub fn with_background_color(mut self, color: impl Into) -> Self { - self.style.background_color = Some(color.into()); + pub fn with_background_color(mut self, color: Color) -> Self { + self.style.background_color = Some(color); self } @@ -95,11 +99,11 @@ impl Container { self } - pub fn with_shadow(mut self, offset: Vector2F, blur: f32, color: impl Into) -> Self { + pub fn with_shadow(mut self, offset: Vector2F, blur: f32, color: Color) -> Self { self.style.shadow = Some(Shadow { offset, blur, - color: color.into(), + color, }); self } @@ -241,7 +245,7 @@ impl ToJson for ContainerStyle { } } -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, Deserialize)] pub struct Margin { top: f32, left: f32, @@ -268,7 +272,7 @@ impl ToJson for Margin { } } -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, Deserialize)] pub struct Padding { top: f32, left: f32, @@ -295,11 +299,12 @@ impl ToJson for Padding { } } -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, Deserialize)] pub struct Shadow { + #[serde(deserialize_with = "deserialize_vec2f")] offset: Vector2F, blur: f32, - color: ColorU, + color: Color, } impl ToJson for Shadow { diff --git a/gpui/src/elements/label.rs b/gpui/src/elements/label.rs index c64b1b8f00d22928d82512d51336aa040e5a84c6..ae1c4d17fd1628b258d2a76e0a4949698fdbafde 100644 --- a/gpui/src/elements/label.rs +++ b/gpui/src/elements/label.rs @@ -1,10 +1,7 @@ -use serde_json::json; -use smallvec::{smallvec, SmallVec}; - use crate::{ - color::ColorU, + color::Color, font_cache::FamilyId, - fonts::{FontId, Properties}, + fonts::{deserialize_font_properties, deserialize_option_font_properties, FontId, Properties}, geometry::{ rect::RectF, vector::{vec2f, Vector2F}, @@ -14,6 +11,9 @@ use crate::{ AfterLayoutContext, DebugContext, Element, Event, EventContext, FontCache, LayoutContext, PaintContext, SizeConstraint, }; +use serde::Deserialize; +use serde_json::json; +use smallvec::{smallvec, SmallVec}; pub struct Label { text: String, @@ -23,12 +23,14 @@ pub struct Label { highlight_indices: Vec, } -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug, Default, Deserialize)] pub struct LabelStyle { - pub default_color: ColorU, - pub highlight_color: ColorU, + pub color: Color, + pub highlight_color: Option, + #[serde(deserialize_with = "deserialize_font_properties")] pub font_properties: Properties, - pub highlight_font_properties: Properties, + #[serde(default, deserialize_with = "deserialize_option_font_properties")] + pub highlight_font_properties: Option, } impl Label { @@ -47,8 +49,8 @@ impl Label { self } - pub fn with_default_color(mut self, color: ColorU) -> Self { - self.style.default_color = color; + pub fn with_default_color(mut self, color: Color) -> Self { + self.style.color = color; self } @@ -61,13 +63,15 @@ impl Label { &self, font_cache: &FontCache, font_id: FontId, - ) -> SmallVec<[(usize, FontId, ColorU); 8]> { + ) -> SmallVec<[(usize, FontId, Color); 8]> { if self.highlight_indices.is_empty() { - return smallvec![(self.text.len(), font_id, self.style.default_color)]; + return smallvec![(self.text.len(), font_id, self.style.color)]; } - let highlight_font_id = font_cache - .select_font(self.family_id, &self.style.highlight_font_properties) + let highlight_font_id = self + .style + .highlight_font_properties + .and_then(|properties| font_cache.select_font(self.family_id, &properties).ok()) .unwrap_or(font_id); let mut highlight_indices = self.highlight_indices.iter().copied().peekable(); @@ -75,11 +79,11 @@ impl Label { for (char_ix, c) in self.text.char_indices() { let mut font_id = font_id; - let mut color = self.style.default_color; + let mut color = self.style.color; if let Some(highlight_ix) = highlight_indices.peek() { if char_ix == *highlight_ix { font_id = highlight_font_id; - color = self.style.highlight_color; + color = self.style.highlight_color.unwrap_or(self.style.color); highlight_indices.next(); } } @@ -179,7 +183,7 @@ impl Element for Label { impl ToJson for LabelStyle { fn to_json(&self) -> Value { json!({ - "default_color": self.default_color.to_json(), + "default_color": self.color.to_json(), "default_font_properties": self.font_properties.to_json(), "highlight_color": self.highlight_color.to_json(), "highlight_font_properties": self.highlight_font_properties.to_json(), @@ -204,14 +208,14 @@ mod tests { .font_cache() .select_font(menlo, Properties::new().weight(Weight::BOLD)) .unwrap(); - let black = ColorU::black(); - let red = ColorU::new(255, 0, 0, 255); + let black = Color::black(); + let red = Color::new(255, 0, 0, 255); let label = Label::new(".αβγδε.ⓐⓑⓒⓓⓔ.abcde.".to_string(), menlo, 12.0) .with_style(&LabelStyle { - default_color: black, - highlight_color: red, - highlight_font_properties: *Properties::new().weight(Weight::BOLD), + color: black, + highlight_color: Some(red), + highlight_font_properties: Some(*Properties::new().weight(Weight::BOLD)), ..Default::default() }) .with_highlights(vec![ diff --git a/gpui/src/elements/svg.rs b/gpui/src/elements/svg.rs index 855d30b1a3b619f902b06a354100dcebaac5276e..93d26f9656a45ba2328972c99226cc6a3c58588b 100644 --- a/gpui/src/elements/svg.rs +++ b/gpui/src/elements/svg.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use serde_json::json; use crate::{ - color::ColorU, + color::Color, geometry::{ rect::RectF, vector::{vec2f, Vector2F}, @@ -14,18 +14,18 @@ use crate::{ pub struct Svg { path: Cow<'static, str>, - color: ColorU, + color: Color, } impl Svg { pub fn new(path: impl Into>) -> Self { Self { path: path.into(), - color: ColorU::black(), + color: Color::black(), } } - pub fn with_color(mut self, color: ColorU) -> Self { + pub fn with_color(mut self, color: Color) -> Self { self.color = color; self } diff --git a/gpui/src/fonts.rs b/gpui/src/fonts.rs index e7e6b5dedb308de91635846a44d5fce340236235..b9fcc88b8240946c2556d6747664accf633f4e2a 100644 --- a/gpui/src/fonts.rs +++ b/gpui/src/fonts.rs @@ -1,14 +1,75 @@ -use crate::json::json; -pub use font_kit::metrics::Metrics; -pub use font_kit::properties::{Properties, Stretch, Style, Weight}; - -use crate::json::ToJson; +use crate::json::{json, ToJson}; +pub use font_kit::{ + metrics::Metrics, + properties::{Properties, Stretch, Style, Weight}, +}; +use serde::{Deserialize, Deserializer}; #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] pub struct FontId(pub usize); pub type GlyphId = u32; +#[allow(non_camel_case_types)] +#[derive(Deserialize)] +enum WeightJson { + thin, + extra_light, + light, + normal, + medium, + semibold, + bold, + extra_bold, + black, +} + +#[derive(Deserialize)] +struct PropertiesJson { + weight: Option, + #[serde(default)] + italic: bool, +} + +impl Into for PropertiesJson { + fn into(self) -> Properties { + let mut result = Properties::new(); + result.weight = match self.weight.unwrap_or(WeightJson::normal) { + WeightJson::thin => Weight::THIN, + WeightJson::extra_light => Weight::EXTRA_LIGHT, + WeightJson::light => Weight::LIGHT, + WeightJson::normal => Weight::NORMAL, + WeightJson::medium => Weight::MEDIUM, + WeightJson::semibold => Weight::SEMIBOLD, + WeightJson::bold => Weight::BOLD, + WeightJson::extra_bold => Weight::EXTRA_BOLD, + WeightJson::black => Weight::BLACK, + }; + if self.italic { + result.style = Style::Italic; + } + result + } +} + +pub fn deserialize_option_font_properties<'de, D>( + deserializer: D, +) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let json: Option = Deserialize::deserialize(deserializer)?; + Ok(json.map(Into::into)) +} + +pub fn deserialize_font_properties<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let json: PropertiesJson = Deserialize::deserialize(deserializer)?; + Ok(json.into()) +} + impl ToJson for Properties { fn to_json(&self) -> crate::json::Value { json!({ diff --git a/gpui/src/geometry.rs b/gpui/src/geometry.rs index cf8ec9cb40e681cadcfd38783f25742f0eccc401..705184fa6bae2f2b1ffd5f9ede4e713cbb9a828e 100644 --- a/gpui/src/geometry.rs +++ b/gpui/src/geometry.rs @@ -1,7 +1,8 @@ use super::scene::{Path, PathVertex}; -use crate::{color::ColorU, json::ToJson}; +use crate::{color::Color, json::ToJson}; pub use pathfinder_geometry::*; use rect::RectF; +use serde::{Deserialize, Deserializer}; use serde_json::json; use vector::{vec2f, Vector2F}; @@ -55,7 +56,7 @@ impl PathBuilder { self.current = point; } - pub fn build(mut self, color: ColorU, clip_bounds: Option) -> Path { + pub fn build(mut self, color: Color, clip_bounds: Option) -> Path { if let Some(clip_bounds) = clip_bounds { self.bounds = self .bounds @@ -108,6 +109,14 @@ impl PathBuilder { } } +pub fn deserialize_vec2f<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let [x, y]: [f32; 2] = Deserialize::deserialize(deserializer)?; + Ok(vec2f(x, y)) +} + impl ToJson for Vector2F { fn to_json(&self) -> serde_json::Value { json!([self.x(), self.y()]) diff --git a/gpui/src/platform.rs b/gpui/src/platform.rs index 7159e0c14969f72cf58f8c6877a7c348158aeccd..7107d7763dd373383d874cb90421c4eedd2d0ca2 100644 --- a/gpui/src/platform.rs +++ b/gpui/src/platform.rs @@ -8,7 +8,7 @@ pub mod current { } use crate::{ - color::ColorU, + color::Color, executor, fonts::{FontId, GlyphId, Metrics as FontMetrics, Properties as FontProperties}, geometry::{ @@ -134,7 +134,7 @@ pub trait FontSystem: Send + Sync { &self, text: &str, font_size: f32, - runs: &[(usize, FontId, ColorU)], + runs: &[(usize, FontId, Color)], ) -> LineLayout; fn wrap_line(&self, text: &str, font_id: FontId, font_size: f32, width: f32) -> Vec; } diff --git a/gpui/src/platform/mac/fonts.rs b/gpui/src/platform/mac/fonts.rs index 2f29625232e8f3d6ecd2c6e4c305c09d125fea39..d5bcc6695edb9e5444b52ba5662045cc3eafcb89 100644 --- a/gpui/src/platform/mac/fonts.rs +++ b/gpui/src/platform/mac/fonts.rs @@ -1,5 +1,5 @@ use crate::{ - color::ColorU, + color::Color, fonts::{FontId, GlyphId, Metrics, Properties}, geometry::{ rect::{RectF, RectI}, @@ -82,7 +82,7 @@ impl platform::FontSystem for FontSystem { &self, text: &str, font_size: f32, - runs: &[(usize, FontId, ColorU)], + runs: &[(usize, FontId, Color)], ) -> LineLayout { self.0.read().layout_line(text, font_size, runs) } @@ -191,7 +191,7 @@ impl FontSystemState { &self, text: &str, font_size: f32, - runs: &[(usize, FontId, ColorU)], + runs: &[(usize, FontId, Color)], ) -> LineLayout { let font_id_attr_name = CFString::from_static_string("zed_font_id"); @@ -436,9 +436,9 @@ mod tests { text, 16.0, &[ - (9, zapfino_regular, ColorU::default()), - (13, menlo_regular, ColorU::default()), - (text.len() - 22, zapfino_regular, ColorU::default()), + (9, zapfino_regular, Color::default()), + (13, menlo_regular, Color::default()), + (text.len() - 22, zapfino_regular, Color::default()), ], ); assert_eq!( diff --git a/gpui/src/platform/mac/renderer.rs b/gpui/src/platform/mac/renderer.rs index 82521cdf86464ddb548c0da1a9a64f611d6801f9..40ae31627d81151ae96ba73edd2ed8cb62043271 100644 --- a/gpui/src/platform/mac/renderer.rs +++ b/gpui/src/platform/mac/renderer.rs @@ -1,6 +1,6 @@ use super::{atlas::AtlasAllocator, sprite_cache::SpriteCache}; use crate::{ - color::ColorU, + color::Color, geometry::{ rect::RectF, vector::{vec2f, vec2i, Vector2F}, @@ -11,7 +11,7 @@ use crate::{ }; use cocoa::foundation::NSUInteger; use metal::{MTLPixelFormat, MTLResourceOptions, NSRange}; -use shaders::{ToFloat2 as _, ToUchar4 as _}; +use shaders::ToFloat2 as _; use std::{collections::HashMap, ffi::c_void, iter::Peekable, mem, sync::Arc, vec}; const SHADERS_METALLIB: &'static [u8] = @@ -438,7 +438,7 @@ impl Renderer { size: bounds.size().round().to_float2(), background_color: quad .background - .unwrap_or(ColorU::transparent_black()) + .unwrap_or(Color::transparent_black()) .to_uchar4(), border_top: border_width * (quad.border.top as usize as f32), border_right: border_width * (quad.border.right as usize as f32), @@ -447,7 +447,7 @@ impl Renderer { border_color: quad .border .color - .unwrap_or(ColorU::transparent_black()) + .unwrap_or(Color::transparent_black()) .to_uchar4(), corner_radius: quad.corner_radius * scene.scale_factor(), }; @@ -782,7 +782,7 @@ mod shaders { use pathfinder_geometry::vector::Vector2I; - use crate::{color::ColorU, geometry::vector::Vector2F}; + use crate::{color::Color, geometry::vector::Vector2F}; use std::mem; include!(concat!(env!("OUT_DIR"), "/shaders.rs")); @@ -791,10 +791,6 @@ mod shaders { fn to_float2(&self) -> vector_float2; } - pub trait ToUchar4 { - fn to_uchar4(&self) -> vector_uchar4; - } - impl ToFloat2 for (f32, f32) { fn to_float2(&self) -> vector_float2 { unsafe { @@ -823,8 +819,8 @@ mod shaders { } } - impl ToUchar4 for ColorU { - fn to_uchar4(&self) -> vector_uchar4 { + impl Color { + pub fn to_uchar4(&self) -> vector_uchar4 { let mut vec = self.a as vector_uchar4; vec <<= 8; vec |= self.b as vector_uchar4; diff --git a/gpui/src/scene.rs b/gpui/src/scene.rs index 10460ed2e0a526af5c4de1a7b6edac3bf823531f..b6d89cf3ae94de267e508295f29805c5edb7a6c3 100644 --- a/gpui/src/scene.rs +++ b/gpui/src/scene.rs @@ -1,9 +1,9 @@ -use std::borrow::Cow; - +use serde::Deserialize; use serde_json::json; +use std::borrow::Cow; use crate::{ - color::ColorU, + color::Color, fonts::{FontId, GlyphId}, geometry::{rect::RectF, vector::Vector2F}, json::ToJson, @@ -28,7 +28,7 @@ pub struct Layer { #[derive(Default, Debug)] pub struct Quad { pub bounds: RectF, - pub background: Option, + pub background: Option, pub border: Border, pub corner_radius: f32, } @@ -38,7 +38,7 @@ pub struct Shadow { pub bounds: RectF, pub corner_radius: f32, pub sigma: f32, - pub color: ColorU, + pub color: Color, } #[derive(Debug)] @@ -47,20 +47,20 @@ pub struct Glyph { pub font_size: f32, pub id: GlyphId, pub origin: Vector2F, - pub color: ColorU, + pub color: Color, } pub struct Icon { pub bounds: RectF, pub svg: usvg::Tree, pub path: Cow<'static, str>, - pub color: ColorU, + pub color: Color, } -#[derive(Clone, Copy, Default, Debug)] +#[derive(Clone, Copy, Default, Debug, Deserialize)] pub struct Border { pub width: f32, - pub color: Option, + pub color: Option, pub top: bool, pub right: bool, pub bottom: bool, @@ -70,7 +70,7 @@ pub struct Border { #[derive(Debug)] pub struct Path { pub bounds: RectF, - pub color: ColorU, + pub color: Color, pub vertices: Vec, } @@ -193,10 +193,10 @@ impl Layer { } impl Border { - pub fn new(width: f32, color: impl Into) -> Self { + pub fn new(width: f32, color: Color) -> Self { Self { width, - color: Some(color.into()), + color: Some(color), top: false, left: false, bottom: false, @@ -204,10 +204,10 @@ impl Border { } } - pub fn all(width: f32, color: impl Into) -> Self { + pub fn all(width: f32, color: Color) -> Self { Self { width, - color: Some(color.into()), + color: Some(color), top: true, left: true, bottom: true, @@ -215,25 +215,25 @@ impl Border { } } - pub fn top(width: f32, color: impl Into) -> Self { + pub fn top(width: f32, color: Color) -> Self { let mut border = Self::new(width, color); border.top = true; border } - pub fn left(width: f32, color: impl Into) -> Self { + pub fn left(width: f32, color: Color) -> Self { let mut border = Self::new(width, color); border.left = true; border } - pub fn bottom(width: f32, color: impl Into) -> Self { + pub fn bottom(width: f32, color: Color) -> Self { let mut border = Self::new(width, color); border.bottom = true; border } - pub fn right(width: f32, color: impl Into) -> Self { + pub fn right(width: f32, color: Color) -> Self { let mut border = Self::new(width, color); border.right = true; border diff --git a/gpui/src/text_layout.rs b/gpui/src/text_layout.rs index ee4401788fcc8691f0ba7d416e4cb24c6a8d6f6b..57556d61b6b25b25ee28bbda20893dd2c0c196b0 100644 --- a/gpui/src/text_layout.rs +++ b/gpui/src/text_layout.rs @@ -1,5 +1,5 @@ use crate::{ - color::ColorU, + color::Color, fonts::{FontId, GlyphId}, geometry::{ rect::RectF, @@ -43,7 +43,7 @@ impl TextLayoutCache { &'a self, text: &'a str, font_size: f32, - runs: &'a [(usize, FontId, ColorU)], + runs: &'a [(usize, FontId, Color)], ) -> Line { let key = &CacheKeyRef { text, @@ -94,7 +94,7 @@ impl<'a> Hash for (dyn CacheKey + 'a) { struct CacheKeyValue { text: String, font_size: OrderedFloat, - runs: SmallVec<[(usize, FontId, ColorU); 1]>, + runs: SmallVec<[(usize, FontId, Color); 1]>, } impl CacheKey for CacheKeyValue { @@ -123,7 +123,7 @@ impl<'a> Borrow for CacheKeyValue { struct CacheKeyRef<'a> { text: &'a str, font_size: OrderedFloat, - runs: &'a [(usize, FontId, ColorU)], + runs: &'a [(usize, FontId, Color)], } impl<'a> CacheKey for CacheKeyRef<'a> { @@ -135,7 +135,7 @@ impl<'a> CacheKey for CacheKeyRef<'a> { #[derive(Default, Debug)] pub struct Line { layout: Arc, - color_runs: SmallVec<[(u32, ColorU); 32]>, + color_runs: SmallVec<[(u32, Color); 32]>, } #[derive(Default, Debug)] @@ -162,7 +162,7 @@ pub struct Glyph { } impl Line { - fn new(layout: Arc, runs: &[(usize, FontId, ColorU)]) -> Self { + fn new(layout: Arc, runs: &[(usize, FontId, Color)]) -> Self { let mut color_runs = SmallVec::new(); for (len, _, color) in runs { color_runs.push((*len as u32, *color)); @@ -206,7 +206,7 @@ impl Line { let mut color_runs = self.color_runs.iter(); let mut color_end = 0; - let mut color = ColorU::black(); + let mut color = Color::black(); for run in &self.layout.runs { let max_glyph_width = cx @@ -230,7 +230,7 @@ impl Line { color = next_run.1; } else { color_end = self.layout.len; - color = ColorU::black(); + color = Color::black(); } } diff --git a/zed/src/editor.rs b/zed/src/editor.rs index 705afaeb20ab272987accad3a9e041feef821d4e..7283e8f6b458d3ff792b1d28a6e32f733ad61ca8 100644 --- a/zed/src/editor.rs +++ b/zed/src/editor.rs @@ -16,7 +16,7 @@ pub use display_map::DisplayPoint; use display_map::*; pub use element::*; use gpui::{ - color::ColorU, font_cache::FamilyId, fonts::Properties as FontProperties, + color::Color, font_cache::FamilyId, fonts::Properties as FontProperties, geometry::vector::Vector2F, keymap::Binding, text_layout, AppContext, ClipboardItem, Element, ElementBox, Entity, FontCache, ModelHandle, MutableAppContext, RenderContext, Task, TextLayoutCache, View, ViewContext, WeakViewHandle, @@ -2349,7 +2349,7 @@ impl Snapshot { .layout_str( "1".repeat(digit_count).as_str(), font_size, - &[(digit_count, font_id, ColorU::black())], + &[(digit_count, font_id, Color::black())], ) .width()) } @@ -2374,9 +2374,9 @@ impl Snapshot { { let display_row = rows.start + ix as u32; let color = if active_rows.contains_key(&display_row) { - theme.editor.line_number_active.0 + theme.editor.line_number_active } else { - theme.editor.line_number.0 + theme.editor.line_number }; if soft_wrapped { layouts.push(None); @@ -2485,7 +2485,7 @@ impl Snapshot { &[( self.display_snapshot.line_len(row) as usize, font_id, - ColorU::black(), + Color::black(), )], )) } diff --git a/zed/src/editor/display_map.rs b/zed/src/editor/display_map.rs index 2bebfeaf9e4798e023abfb4cce368a1d890fbb95..67246bd983575ebc8057201652bebd66099bddc1 100644 --- a/zed/src/editor/display_map.rs +++ b/zed/src/editor/display_map.rs @@ -340,7 +340,7 @@ mod tests { util::RandomCharIter, }; use buffer::{History, SelectionGoal}; - use gpui::{color::ColorU, MutableAppContext}; + use gpui::{color::Color, MutableAppContext}; use rand::{prelude::StdRng, Rng}; use std::{env, sync::Arc}; use Bias::*; @@ -656,12 +656,12 @@ mod tests { syntax: vec![ ( "mod.body".to_string(), - ColorU::from_u32(0xff0000ff), + Color::from_u32(0xff0000ff), Default::default(), ), ( "fn.name".to_string(), - ColorU::from_u32(0x00ff00ff), + Color::from_u32(0x00ff00ff), Default::default(), ), ], @@ -754,12 +754,12 @@ mod tests { syntax: vec![ ( "mod.body".to_string(), - ColorU::from_u32(0xff0000ff), + Color::from_u32(0xff0000ff), Default::default(), ), ( "fn.name".to_string(), - ColorU::from_u32(0x00ff00ff), + Color::from_u32(0x00ff00ff), Default::default(), ), ], diff --git a/zed/src/editor/element.rs b/zed/src/editor/element.rs index c2a486afdd884cc73019f5b40bb02f33dc9b8c30..44b283dee1d7bf7108be123c535578b33a402560 100644 --- a/zed/src/editor/element.rs +++ b/zed/src/editor/element.rs @@ -1,7 +1,7 @@ use super::{DisplayPoint, Editor, SelectAction, Snapshot}; use crate::time::ReplicaId; use gpui::{ - color::ColorU, + color::Color, geometry::{ rect::RectF, vector::{vec2f, Vector2F}, @@ -196,14 +196,14 @@ impl EditorElement { let theme = &settings.theme; cx.scene.push_quad(Quad { bounds: gutter_bounds, - background: Some(theme.editor.gutter_background.0), - border: Border::new(0., ColorU::transparent_black()), + background: Some(theme.editor.gutter_background), + border: Border::new(0., Color::transparent_black()), corner_radius: 0., }); cx.scene.push_quad(Quad { bounds: text_bounds, - background: Some(theme.editor.background.0), - border: Border::new(0., ColorU::transparent_black()), + background: Some(theme.editor.background), + border: Border::new(0., Color::transparent_black()), corner_radius: 0., }); @@ -229,7 +229,7 @@ impl EditorElement { ); cx.scene.push_quad(Quad { bounds: RectF::new(origin, size), - background: Some(theme.editor.active_line_background.0), + background: Some(theme.editor.active_line_background), border: Border::default(), corner_radius: 0., }); @@ -290,7 +290,7 @@ impl EditorElement { }; let selection = Selection { - color: replica_theme.selection.0, + color: replica_theme.selection, line_height: layout.line_height, start_y: content_origin.y() + row_range.start as f32 * layout.line_height - scroll_top, @@ -333,7 +333,7 @@ impl EditorElement { - scroll_left; let y = selection.end.row() as f32 * layout.line_height - scroll_top; cursors.push(Cursor { - color: replica_theme.cursor.0, + color: replica_theme.cursor, origin: content_origin + vec2f(x, y), line_height: layout.line_height, }); @@ -707,7 +707,7 @@ impl PaintState { struct Cursor { origin: Vector2F, line_height: f32, - color: ColorU, + color: Color, } impl Cursor { @@ -715,7 +715,7 @@ impl Cursor { cx.scene.push_quad(Quad { bounds: RectF::new(self.origin, vec2f(2.0, self.line_height)), background: Some(self.color), - border: Border::new(0., ColorU::black()), + border: Border::new(0., Color::black()), corner_radius: 0., }); } @@ -726,7 +726,7 @@ struct Selection { start_y: f32, line_height: f32, lines: Vec, - color: ColorU, + color: Color, } #[derive(Debug)] diff --git a/zed/src/file_finder.rs b/zed/src/file_finder.rs index faecae42f47462e71b6565be39567b92d9ea291f..36ff7c8312014cc3a12d9b195ee1c77edf9e376d 100644 --- a/zed/src/file_finder.rs +++ b/zed/src/file_finder.rs @@ -6,7 +6,7 @@ use crate::{ worktree::{match_paths, PathMatch, Worktree}, }; use gpui::{ - color::ColorF, + color::Color, elements::*, fonts::{Properties, Weight}, geometry::vector::vec2f, @@ -82,7 +82,7 @@ impl View for FileFinder { .with_uniform_padding(6.0) .with_corner_radius(6.0) .with_background_color(settings.theme.ui.modal_background) - .with_shadow(vec2f(0., 4.), 12., ColorF::new(0.0, 0.0, 0.0, 0.5).to_u8()) + .with_shadow(vec2f(0., 4.), 12., Color::new(0, 0, 0, 128)) .boxed(), ) .with_max_width(600.0) @@ -114,7 +114,7 @@ impl FileFinder { settings.ui_font_family, settings.ui_font_size, ) - .with_default_color(settings.theme.editor.default_text.0) + .with_default_color(settings.theme.editor.default_text) .boxed(), ) .with_margin_top(6.0) @@ -155,9 +155,9 @@ impl FileFinder { let bold = *Properties::new().weight(Weight::BOLD); let selected_index = self.selected_index(); let label_style = LabelStyle { - default_color: theme.modal_match_text.0, - highlight_color: theme.modal_match_text_highlight.0, - highlight_font_properties: bold, + color: theme.modal_match_text, + highlight_color: Some(theme.modal_match_text_highlight), + highlight_font_properties: Some(bold), ..Default::default() }; let mut container = Container::new( @@ -206,9 +206,9 @@ impl FileFinder { ) .with_uniform_padding(6.0) .with_background_color(if index == selected_index { - theme.modal_match_background_active.0 + theme.modal_match_background_active } else { - theme.modal_match_background.0 + theme.modal_match_background }); if index == selected_index || index < self.matches.len() - 1 { diff --git a/zed/src/settings.rs b/zed/src/settings.rs index 79ee243ae08c2f8cb86e5719ebebc24bbcac5d13..fcdf230130ec3296ef8e2a9c94b11a99d977f3cf 100644 --- a/zed/src/settings.rs +++ b/zed/src/settings.rs @@ -1,6 +1,6 @@ use anyhow::{anyhow, Context, Result}; use gpui::{ - color::ColorU, + color::Color, font_cache::{FamilyId, FontCache}, fonts::{Properties as FontProperties, Style as FontStyle, Weight as FontWeight}, AssetSource, @@ -9,12 +9,7 @@ use parking_lot::Mutex; use postage::watch; use serde::{de::value::MapDeserializer, Deserialize}; use serde_json::Value; -use std::{ - collections::HashMap, - fmt, - ops::{Deref, DerefMut}, - sync::Arc, -}; +use std::{collections::HashMap, sync::Arc}; const DEFAULT_STYLE_ID: StyleId = StyleId(u32::MAX); @@ -38,7 +33,7 @@ pub struct ThemeRegistry { pub struct Theme { pub ui: UiTheme, pub editor: EditorTheme, - pub syntax: Vec<(String, ColorU, FontProperties)>, + pub syntax: Vec<(String, Color, FontProperties)>, } #[derive(Deserialize)] @@ -93,9 +88,6 @@ pub struct ReplicaTheme { pub selection: Color, } -#[derive(Clone, Copy, Default)] -pub struct Color(pub ColorU); - #[derive(Clone, Debug)] pub struct ThemeMap(Arc<[StyleId]>); @@ -151,7 +143,7 @@ impl ThemeRegistry { } let theme_toml = self.load(name)?; - let mut syntax = Vec::<(String, ColorU, FontProperties)>::new(); + let mut syntax = Vec::<(String, Color, FontProperties)>::new(); for (key, style) in theme_toml.syntax.iter() { let mut color = Color::default(); let mut properties = FontProperties::new(); @@ -171,7 +163,7 @@ impl ThemeRegistry { } match syntax.binary_search_by_key(&key, |e| &e.0) { Ok(i) | Err(i) => { - syntax.insert(i, (key.to_string(), color.0, properties)); + syntax.insert(i, (key.to_string(), color, properties)); } } } @@ -234,11 +226,12 @@ impl ThemeRegistry { } impl Theme { - pub fn syntax_style(&self, id: StyleId) -> (ColorU, FontProperties) { - self.syntax.get(id.0 as usize).map_or( - (self.editor.default_text.0, FontProperties::new()), - |entry| (entry.1, entry.2), - ) + pub fn syntax_style(&self, id: StyleId) -> (Color, FontProperties) { + self.syntax + .get(id.0 as usize) + .map_or((self.editor.default_text, FontProperties::new()), |entry| { + (entry.1, entry.2) + }) } #[cfg(test)] @@ -313,53 +306,6 @@ impl Default for StyleId { } } -impl Color { - fn from_u32(rgba: u32) -> Self { - Self(ColorU::from_u32(rgba)) - } -} - -impl<'de> Deserialize<'de> for Color { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let rgb = u32::deserialize(deserializer)?; - Ok(Self::from_u32((rgb << 8) + 0xFF)) - } -} - -impl Into for Color { - fn into(self) -> ColorU { - self.0 - } -} - -impl Deref for Color { - type Target = ColorU; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Color { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl fmt::Debug for Color { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - -impl PartialEq for Color { - fn eq(&self, other: &ColorU) -> bool { - self.0.eq(other) - } -} - pub fn channel( font_cache: &FontCache, ) -> Result<(watch::Sender, watch::Receiver)> { @@ -478,25 +424,25 @@ mod tests { let registry = ThemeRegistry::new(assets); let theme = registry.get("my-theme").unwrap(); - assert_eq!(theme.ui.tab_background_active, ColorU::from_u32(0x100000ff)); - assert_eq!(theme.editor.background, ColorU::from_u32(0x00ed00ff)); - assert_eq!(theme.editor.line_number, ColorU::from_u32(0xddddddff)); + assert_eq!(theme.ui.tab_background_active, Color::from_u32(0x100000ff)); + assert_eq!(theme.editor.background, Color::from_u32(0x00ed00ff)); + assert_eq!(theme.editor.line_number, Color::from_u32(0xddddddff)); assert_eq!( theme.syntax, &[ ( "alpha.one".to_string(), - ColorU::from_u32(0x112233ff), + Color::from_u32(0x112233ff), *FontProperties::new().weight(FontWeight::BOLD) ), ( "beta.two".to_string(), - ColorU::from_u32(0xaabbccff), + Color::from_u32(0xaabbccff), *FontProperties::new().weight(FontWeight::NORMAL) ), ( "gamma.three".to_string(), - ColorU::from_u32(0x00000000), + Color::from_u32(0x00000000), *FontProperties::new() .weight(FontWeight::LIGHT) .style(FontStyle::Italic), @@ -553,10 +499,10 @@ mod tests { let registry = ThemeRegistry::new(assets); let theme = registry.get("light").unwrap(); - assert_eq!(theme.ui.tab_background, ColorU::from_u32(0x555555ff)); - assert_eq!(theme.ui.tab_text, ColorU::from_u32(0x333333ff)); - assert_eq!(theme.editor.background, ColorU::from_u32(0x666666ff)); - assert_eq!(theme.editor.default_text, ColorU::from_u32(0x444444ff)); + assert_eq!(theme.ui.tab_background, Color::from_u32(0x555555ff)); + assert_eq!(theme.ui.tab_text, Color::from_u32(0x333333ff)); + assert_eq!(theme.editor.background, Color::from_u32(0x666666ff)); + assert_eq!(theme.editor.default_text, Color::from_u32(0x444444ff)); assert_eq!( registry.list().collect::>(), @@ -577,12 +523,12 @@ mod tests { ui: Default::default(), editor: Default::default(), syntax: [ - ("function", ColorU::from_u32(0x100000ff)), - ("function.method", ColorU::from_u32(0x200000ff)), - ("function.async", ColorU::from_u32(0x300000ff)), - ("variable.builtin.self.rust", ColorU::from_u32(0x400000ff)), - ("variable.builtin", ColorU::from_u32(0x500000ff)), - ("variable", ColorU::from_u32(0x600000ff)), + ("function", Color::from_u32(0x100000ff)), + ("function.method", Color::from_u32(0x200000ff)), + ("function.async", Color::from_u32(0x300000ff)), + ("variable.builtin.self.rust", Color::from_u32(0x400000ff)), + ("variable.builtin", Color::from_u32(0x500000ff)), + ("variable", Color::from_u32(0x600000ff)), ] .iter() .map(|e| (e.0.to_string(), e.1, FontProperties::new())) diff --git a/zed/src/theme_selector.rs b/zed/src/theme_selector.rs index 55a32d94c5426c9f574e9dacab0506a6b1d63471..c88f1e70055dfa698bff7935787627516f5c40ec 100644 --- a/zed/src/theme_selector.rs +++ b/zed/src/theme_selector.rs @@ -9,7 +9,7 @@ use crate::{ }; use futures::lock::Mutex; use gpui::{ - color::ColorF, + color::Color, elements::{ Align, ChildView, ConstrainedBox, Container, Expanded, Flex, Label, LabelStyle, ParentElement, UniformList, UniformListState, @@ -199,7 +199,7 @@ impl ThemeSelector { settings.ui_font_family, settings.ui_font_size, ) - .with_default_color(settings.theme.editor.default_text.0) + .with_default_color(settings.theme.editor.default_text) .boxed(), ) .with_margin_top(6.0) @@ -241,9 +241,9 @@ impl ThemeSelector { settings.ui_font_size, ) .with_style(&LabelStyle { - default_color: theme.modal_match_text.0, - highlight_color: theme.modal_match_text_highlight.0, - highlight_font_properties: *Properties::new().weight(Weight::BOLD), + color: theme.modal_match_text, + highlight_color: Some(theme.modal_match_text_highlight), + highlight_font_properties: Some(*Properties::new().weight(Weight::BOLD)), ..Default::default() }) .with_highlights(theme_match.positions.clone()) @@ -251,9 +251,9 @@ impl ThemeSelector { ) .with_uniform_padding(6.0) .with_background_color(if index == self.selected_index { - theme.modal_match_background_active.0 + theme.modal_match_background_active } else { - theme.modal_match_background.0 + theme.modal_match_background }); if index == self.selected_index || index < self.matches.len() - 1 { @@ -288,7 +288,7 @@ impl View for ThemeSelector { .with_uniform_padding(6.0) .with_corner_radius(6.0) .with_background_color(settings.theme.ui.modal_background) - .with_shadow(vec2f(0., 4.), 12., ColorF::new(0.0, 0.0, 0.0, 0.5).to_u8()) + .with_shadow(vec2f(0., 4.), 12., Color::new(0, 0, 0, 128)) .boxed(), ) .with_max_width(600.0) diff --git a/zed/src/workspace/pane.rs b/zed/src/workspace/pane.rs index 9102e9f8136812432d10a29d1587b1640c462e68..a8eda55d9df799088f7878c492ad75e24338b2bf 100644 --- a/zed/src/workspace/pane.rs +++ b/zed/src/workspace/pane.rs @@ -1,7 +1,7 @@ use super::{ItemViewHandle, SplitDirection}; use crate::settings::{Settings, UiTheme}; use gpui::{ - color::ColorU, + color::Color, elements::*, geometry::{rect::RectF, vector::vec2f}, keymap::Binding, @@ -200,7 +200,7 @@ impl Pane { MouseEventHandler::new::(item.id(), cx, |mouse_state| { let title = item.title(cx); - let mut border = Border::new(1.0, theme.tab_border.0); + let mut border = Border::new(1.0, theme.tab_border); border.left = ix > 0; border.right = ix == last_item_ix; border.bottom = ix != self.active_item; @@ -215,9 +215,9 @@ impl Pane { settings.ui_font_size, ) .with_default_color(if is_active { - theme.tab_text_active.0 + theme.tab_text_active } else { - theme.tab_text.0 + theme.tab_text }) .boxed(), ) @@ -317,12 +317,12 @@ impl Pane { }; let icon = if tab_hovered { - let close_color = current_color.unwrap_or(theme.tab_icon_close).0; + let close_color = current_color.unwrap_or(theme.tab_icon_close); let icon = Svg::new("icons/x.svg").with_color(close_color); MouseEventHandler::new::(item_id, cx, |mouse_state| { if mouse_state.hovered { - Container::new(icon.with_color(ColorU::white()).boxed()) + Container::new(icon.with_color(Color::white()).boxed()) .with_background_color(if mouse_state.clicked { clicked_color } else { @@ -344,7 +344,7 @@ impl Pane { let square = RectF::new(bounds.origin(), vec2f(diameter, diameter)); cx.scene.push_quad(Quad { bounds: square, - background: Some(current_color.0), + background: Some(current_color), border: Default::default(), corner_radius: diameter / 2., }); diff --git a/zed/src/workspace/pane_group.rs b/zed/src/workspace/pane_group.rs index 46a00b3f2a0e63b7adde8fb44a1ed5b514a65da3..d5d0040009fba87bfd9bc0bb29acb6a533457336 100644 --- a/zed/src/workspace/pane_group.rs +++ b/zed/src/workspace/pane_group.rs @@ -1,9 +1,5 @@ use anyhow::{anyhow, Result}; -use gpui::{ - color::{rgbu, ColorU}, - elements::*, - Axis, Border, -}; +use gpui::{color::Color, elements::*, Axis, Border}; #[derive(Clone, Debug, Eq, PartialEq)] pub struct PaneGroup { @@ -388,6 +384,6 @@ fn border_width() -> f32 { } #[inline(always)] -fn border_color() -> ColorU { - rgbu(0xdb, 0xdb, 0xdc) +fn border_color() -> Color { + Color::new(0xdb, 0xdb, 0xdc, 0xff) }