diff options
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | examples/geometry/src/main.rs | 19 | ||||
-rw-r--r-- | graphics/Cargo.toml | 1 | ||||
-rw-r--r-- | graphics/src/color.rs | 46 | ||||
-rw-r--r-- | graphics/src/gradient.rs | 8 | ||||
-rw-r--r-- | graphics/src/lib.rs | 1 | ||||
-rw-r--r-- | graphics/src/primitive.rs | 3 | ||||
-rw-r--r-- | renderer/Cargo.toml | 1 | ||||
-rw-r--r-- | wgpu/Cargo.toml | 1 | ||||
-rw-r--r-- | wgpu/src/backend.rs | 3 | ||||
-rw-r--r-- | wgpu/src/geometry.rs | 7 | ||||
-rw-r--r-- | wgpu/src/layer.rs | 3 | ||||
-rw-r--r-- | wgpu/src/quad.rs | 5 | ||||
-rw-r--r-- | wgpu/src/quad/solid.rs | 3 | ||||
-rw-r--r-- | wgpu/src/text.rs | 4 | ||||
-rw-r--r-- | wgpu/src/window/compositor.rs | 22 |
16 files changed, 99 insertions, 30 deletions
@@ -37,6 +37,8 @@ smol = ["iced_futures/smol"] palette = ["iced_core/palette"] # Enables querying system information system = ["iced_winit/system"] +# Enables broken "sRGB linear" blending to reproduce color management of the Web +web-colors = ["iced_renderer/web-colors"] # Enables the advanced module advanced = [] diff --git a/examples/geometry/src/main.rs b/examples/geometry/src/main.rs index 5cb41184..a4183db9 100644 --- a/examples/geometry/src/main.rs +++ b/examples/geometry/src/main.rs @@ -3,6 +3,7 @@ mod rainbow { use iced_graphics::primitive::{ColoredVertex2D, Primitive}; + use iced::advanced::graphics::color; use iced::advanced::layout::{self, Layout}; use iced::advanced::renderer; use iced::advanced::widget::{self, Widget}; @@ -84,39 +85,39 @@ mod rainbow { vertices: vec![ ColoredVertex2D { position: posn_center, - color: [1.0, 1.0, 1.0, 1.0], + color: color::pack([1.0, 1.0, 1.0, 1.0]), }, ColoredVertex2D { position: posn_tl, - color: color_r, + color: color::pack(color_r), }, ColoredVertex2D { position: posn_t, - color: color_o, + color: color::pack(color_o), }, ColoredVertex2D { position: posn_tr, - color: color_y, + color: color::pack(color_y), }, ColoredVertex2D { position: posn_r, - color: color_g, + color: color::pack(color_g), }, ColoredVertex2D { position: posn_br, - color: color_gb, + color: color::pack(color_gb), }, ColoredVertex2D { position: posn_b, - color: color_b, + color: color::pack(color_b), }, ColoredVertex2D { position: posn_bl, - color: color_i, + color: color::pack(color_i), }, ColoredVertex2D { position: posn_l, - color: color_v, + color: color::pack(color_v), }, ], indices: vec![ diff --git a/graphics/Cargo.toml b/graphics/Cargo.toml index 903a2069..0e22227d 100644 --- a/graphics/Cargo.toml +++ b/graphics/Cargo.toml @@ -14,6 +14,7 @@ categories = ["gui"] geometry = ["lyon_path"] opengl = [] image = ["dep:image", "kamadak-exif"] +web-colors = [] [dependencies] glam = "0.24" diff --git a/graphics/src/color.rs b/graphics/src/color.rs new file mode 100644 index 00000000..92448a68 --- /dev/null +++ b/graphics/src/color.rs @@ -0,0 +1,46 @@ +//! Manage colors for shaders. +use crate::core::Color; + +use bytemuck::{Pod, Zeroable}; + +/// A color packed as 4 floats representing RGBA channels. +#[derive(Debug, Clone, Copy, PartialEq, Zeroable, Pod)] +#[repr(C)] +pub struct Packed([f32; 4]); + +impl Packed { + /// Returns the internal components of the [`Packed`] color. + pub fn components(self) -> [f32; 4] { + self.0 + } +} + +/// A flag that indicates whether the renderer should perform gamma correction. +pub const GAMMA_CORRECTION: bool = internal::GAMMA_CORRECTION; + +/// Packs a [`Color`]. +pub fn pack(color: impl Into<Color>) -> Packed { + Packed(internal::pack(color.into())) +} + +#[cfg(not(feature = "web-colors"))] +mod internal { + use crate::core::Color; + + pub const GAMMA_CORRECTION: bool = true; + + pub fn pack(color: Color) -> [f32; 4] { + color.into_linear() + } +} + +#[cfg(feature = "web-colors")] +mod internal { + use crate::core::Color; + + pub const GAMMA_CORRECTION: bool = false; + + pub fn pack(color: Color) -> [f32; 4] { + [color.r, color.g, color.b, color.a] + } +} diff --git a/graphics/src/gradient.rs b/graphics/src/gradient.rs index d3eabb6f..d26b5665 100644 --- a/graphics/src/gradient.rs +++ b/graphics/src/gradient.rs @@ -3,8 +3,10 @@ //! For a gradient that you can use as a background variant for a widget, see [`Gradient`]. //! //! [`Gradient`]: crate::core::Gradient; +use crate::color; use crate::core::gradient::ColorStop; use crate::core::{self, Color, Point, Rectangle}; + use std::cmp::Ordering; #[derive(Debug, Clone, PartialEq)] @@ -101,7 +103,8 @@ impl Linear { for (index, stop) in self.stops.iter().enumerate() { let [r, g, b, a] = - stop.map_or(Color::default(), |s| s.color).into_linear(); + color::pack(stop.map_or(Color::default(), |s| s.color)) + .components(); data[index * 4] = r; data[(index * 4) + 1] = g; @@ -133,7 +136,8 @@ pub fn pack(gradient: &core::Gradient, bounds: Rectangle) -> Packed { for (index, stop) in linear.stops.iter().enumerate() { let [r, g, b, a] = - stop.map_or(Color::default(), |s| s.color).into_linear(); + color::pack(stop.map_or(Color::default(), |s| s.color)) + .components(); data[index * 4] = r; data[(index * 4) + 1] = g; diff --git a/graphics/src/lib.rs b/graphics/src/lib.rs index bfaac19f..f6bc87fb 100644 --- a/graphics/src/lib.rs +++ b/graphics/src/lib.rs @@ -27,6 +27,7 @@ mod transformation; mod viewport; pub mod backend; +pub mod color; pub mod compositor; pub mod damage; pub mod gradient; diff --git a/graphics/src/primitive.rs b/graphics/src/primitive.rs index 2d4f5511..187c6c6c 100644 --- a/graphics/src/primitive.rs +++ b/graphics/src/primitive.rs @@ -1,4 +1,5 @@ //! Draw using different graphical primitives. +use crate::color; use crate::core::alignment; use crate::core::image; use crate::core::svg; @@ -248,7 +249,7 @@ pub struct ColoredVertex2D { pub position: [f32; 2], /// The color of the vertex in __linear__ RGBA. - pub color: [f32; 4], + pub color: color::Packed, } /// A vertex which contains 2D position & packed gradient data. diff --git a/renderer/Cargo.toml b/renderer/Cargo.toml index 640ac996..ddfb6445 100644 --- a/renderer/Cargo.toml +++ b/renderer/Cargo.toml @@ -9,6 +9,7 @@ image = ["iced_tiny_skia/image", "iced_wgpu?/image"] svg = ["iced_tiny_skia/svg", "iced_wgpu?/svg"] geometry = ["iced_graphics/geometry", "iced_tiny_skia/geometry", "iced_wgpu?/geometry"] tracing = ["iced_wgpu?/tracing"] +web-colors = ["iced_wgpu?/web-colors"] [dependencies] raw-window-handle = "0.5" diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index b5401626..badd165b 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -11,6 +11,7 @@ repository = "https://github.com/iced-rs/iced" geometry = ["iced_graphics/geometry", "lyon"] image = ["iced_graphics/image"] svg = ["resvg"] +web-colors = ["iced_graphics/web-colors"] [dependencies] wgpu = "0.16" diff --git a/wgpu/src/backend.rs b/wgpu/src/backend.rs index 844987f2..b524c615 100644 --- a/wgpu/src/backend.rs +++ b/wgpu/src/backend.rs @@ -1,6 +1,7 @@ use crate::core; use crate::core::{Color, Font, Point, Size}; use crate::graphics::backend; +use crate::graphics::color; use crate::graphics::{Primitive, Transformation, Viewport}; use crate::quad; use crate::text; @@ -239,7 +240,7 @@ impl Backend { load: match clear_color { Some(background_color) => wgpu::LoadOp::Clear({ let [r, g, b, a] = - background_color.into_linear(); + color::pack(background_color).components(); wgpu::Color { r: f64::from(r), diff --git a/wgpu/src/geometry.rs b/wgpu/src/geometry.rs index 740ec20c..f81b5b2f 100644 --- a/wgpu/src/geometry.rs +++ b/wgpu/src/geometry.rs @@ -1,5 +1,6 @@ //! Build and draw geometry. use crate::core::{Point, Rectangle, Size, Vector}; +use crate::graphics::color; use crate::graphics::geometry::fill::{self, Fill}; use crate::graphics::geometry::{ LineCap, LineDash, LineJoin, Path, Stroke, Style, Text, @@ -68,7 +69,7 @@ impl BufferStack { (Style::Solid(color), Buffer::Solid(buffer)) => { Box::new(tessellation::BuffersBuilder::new( buffer, - TriangleVertex2DBuilder(color.into_linear()), + TriangleVertex2DBuilder(color::pack(*color)), )) } (Style::Gradient(gradient), Buffer::Gradient(buffer)) => { @@ -91,7 +92,7 @@ impl BufferStack { (Style::Solid(color), Buffer::Solid(buffer)) => { Box::new(tessellation::BuffersBuilder::new( buffer, - TriangleVertex2DBuilder(color.into_linear()), + TriangleVertex2DBuilder(color::pack(*color)), )) } (Style::Gradient(gradient), Buffer::Gradient(buffer)) => { @@ -526,7 +527,7 @@ impl tessellation::StrokeVertexConstructor<primitive::GradientVertex2D> } } -struct TriangleVertex2DBuilder([f32; 4]); +struct TriangleVertex2DBuilder(color::Packed); impl tessellation::FillVertexConstructor<primitive::ColoredVertex2D> for TriangleVertex2DBuilder diff --git a/wgpu/src/layer.rs b/wgpu/src/layer.rs index 1a870c15..71570e3d 100644 --- a/wgpu/src/layer.rs +++ b/wgpu/src/layer.rs @@ -11,6 +11,7 @@ pub use text::Text; use crate::core; use crate::core::alignment; use crate::core::{Color, Font, Point, Rectangle, Size, Vector}; +use crate::graphics::color; use crate::graphics::{Primitive, Viewport}; use crate::quad::{self, Quad}; @@ -150,7 +151,7 @@ impl<'a> Layer<'a> { bounds.y + translation.y, ], size: [bounds.width, bounds.height], - border_color: border_color.into_linear(), + border_color: color::pack(*border_color), border_radius: *border_radius, border_width: *border_width, }; diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index 9c5ed05f..37d0c623 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -5,6 +5,7 @@ use gradient::Gradient; use solid::Solid; use crate::core::{Background, Rectangle}; +use crate::graphics::color; use crate::graphics::{self, Transformation}; use bytemuck::{Pod, Zeroable}; @@ -217,7 +218,7 @@ pub struct Quad { pub size: [f32; 2], /// The border color of the [`Quad`], in __linear RGB__. - pub border_color: [f32; 4], + pub border_color: color::Packed, /// The border radii of the [`Quad`]. pub border_radius: [f32; 4], @@ -250,7 +251,7 @@ impl Batch { let kind = match background { Background::Color(color) => { self.solids.push(Solid { - color: color.into_linear(), + color: color::pack(*color), quad, }); diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs index f667c42c..f8f1e3a5 100644 --- a/wgpu/src/quad/solid.rs +++ b/wgpu/src/quad/solid.rs @@ -1,3 +1,4 @@ +use crate::graphics::color; use crate::quad::{self, Quad}; use crate::Buffer; @@ -9,7 +10,7 @@ use std::ops::Range; #[repr(C)] pub struct Solid { /// The background color data of the quad. - pub color: [f32; 4], + pub color: color::Packed, /// The [`Quad`] data of the [`Solid`]. pub quad: Quad, diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index 714e0400..a12bc9f7 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -2,6 +2,7 @@ use crate::core::alignment; use crate::core::font::{self, Font}; use crate::core::text::{Hit, LineHeight, Shaping}; use crate::core::{Pixels, Point, Rectangle, Size}; +use crate::graphics::color; use crate::layer::Text; use rustc_hash::{FxHashMap, FxHashSet}; @@ -155,7 +156,8 @@ impl Pipeline { bottom: (clip_bounds.y + clip_bounds.height) as i32, }, default_color: { - let [r, g, b, a] = section.color.into_linear(); + let [r, g, b, a] = + color::pack(section.color).components(); glyphon::Color::rgba( (r * 255.0) as u8, diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index 500458e8..2eaafde0 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -1,6 +1,7 @@ //! Connect a window with a renderer. use crate::core::Color; use crate::graphics; +use crate::graphics::color; use crate::graphics::compositor; use crate::graphics::{Error, Primitive, Viewport}; use crate::{Backend, Renderer, Settings}; @@ -69,16 +70,19 @@ impl<Theme> Compositor<Theme> { let format = compatible_surface.as_ref().and_then(|surface| { let capabilities = surface.get_capabilities(&adapter); - capabilities - .formats - .iter() - .copied() - .find(wgpu::TextureFormat::is_srgb) - .or_else(|| { - log::warn!("No sRGB format found!"); + let mut formats = capabilities.formats.iter().copied(); - capabilities.formats.first().copied() - }) + let format = if color::GAMMA_CORRECTION { + formats.find(wgpu::TextureFormat::is_srgb) + } else { + formats.find(|format| !wgpu::TextureFormat::is_srgb(format)) + }; + + format.or_else(|| { + log::warn!("No format found!"); + + capabilities.formats.first().copied() + }) })?; log::info!("Selected format: {:?}", format); |