From d53ccc857da4d4cda769904342aeb5a82a64f146 Mon Sep 17 00:00:00 2001 From: Bingus Date: Wed, 12 Jul 2023 19:21:05 -0700 Subject: refactored window storage; new helper window events (Destroyed, Created); clippy + fmt; --- tiny_skia/src/window/compositor.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 775cf9e5..1aaba2c9 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -8,6 +8,7 @@ use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use std::marker::PhantomData; pub struct Compositor { + settings: Settings, _theme: PhantomData, } @@ -33,6 +34,10 @@ impl crate::graphics::Compositor for Compositor { Ok((compositor, Renderer::new(backend))) } + fn renderer(&self) -> Self::Renderer { + Renderer::new(Backend::new(self.settings)) + } + fn create_surface( &mut self, window: &W, @@ -116,6 +121,7 @@ impl crate::graphics::Compositor for Compositor { pub fn new(settings: Settings) -> (Compositor, Backend) { ( Compositor { + settings, _theme: PhantomData, }, Backend::new(settings), -- cgit From 346af3f8b0baa418fd37b878bc2930ff0bd57cc0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 11 Sep 2023 02:47:24 +0200 Subject: Make `FontSystem` global and simplify `Paragraph` API --- tiny_skia/src/backend.rs | 5 ----- tiny_skia/src/text.rs | 21 +++++++++++---------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index c721d96e..72184c8a 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -1,6 +1,5 @@ use crate::core::{Background, Color, Gradient, Rectangle, Vector}; use crate::graphics::backend; -use crate::graphics::text; use crate::graphics::{Damage, Viewport}; use crate::primitive::{self, Primitive}; @@ -805,10 +804,6 @@ impl iced_graphics::Backend for Backend { } impl backend::Text for Backend { - fn font_system(&self) -> &text::FontSystem { - self.text_pipeline.font_system() - } - fn load_font(&mut self, font: Cow<'static, [u8]>) { self.text_pipeline.load_font(font); } diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index cb3ef54c..4f6e3941 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -2,8 +2,8 @@ use crate::core::alignment; use crate::core::text::{LineHeight, Shaping}; use crate::core::{Color, Font, Pixels, Point, Rectangle}; use crate::graphics::text::cache::{self, Cache}; +use crate::graphics::text::font_system; use crate::graphics::text::paragraph; -use crate::graphics::text::FontSystem; use rustc_hash::{FxHashMap, FxHashSet}; use std::borrow::Cow; @@ -12,7 +12,6 @@ use std::collections::hash_map; #[allow(missing_debug_implementations)] pub struct Pipeline { - font_system: FontSystem, glyph_cache: GlyphCache, cache: RefCell, } @@ -20,18 +19,16 @@ pub struct Pipeline { impl Pipeline { pub fn new() -> Self { Pipeline { - font_system: FontSystem::new(), glyph_cache: GlyphCache::new(), cache: RefCell::new(Cache::new()), } } - pub fn font_system(&self) -> &FontSystem { - &self.font_system - } - pub fn load_font(&mut self, bytes: Cow<'static, [u8]>) { - self.font_system.load_font(bytes); + font_system() + .write() + .expect("Write font system") + .load_font(bytes); self.cache = RefCell::new(Cache::new()); } @@ -51,8 +48,10 @@ impl Pipeline { return; }; + let mut font_system = font_system().write().expect("Write font system"); + draw( - self.font_system.get_mut(), + font_system.raw(), &mut self.glyph_cache, paragraph.buffer(), Rectangle::new(position, paragraph.min_bounds()), @@ -82,7 +81,9 @@ impl Pipeline { ) { let line_height = f32::from(line_height.to_absolute(size)); - let font_system = self.font_system.get_mut(); + let mut font_system = font_system().write().expect("Write font system"); + let font_system = font_system.raw(); + let key = cache::Key { bounds: bounds.size(), content, -- cgit From 6448429103c9c82b90040ac5a5a097bdded23f82 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 12 Sep 2023 14:51:00 +0200 Subject: Draft `Editor` API and `TextEditor` widget --- tiny_skia/src/backend.rs | 25 +++++++++++++++++++++++++ tiny_skia/src/text.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index 72184c8a..5f66dff2 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -383,6 +383,31 @@ impl Backend { clip_mask, ); } + Primitive::Editor { + editor, + position, + color, + } => { + let physical_bounds = + (Rectangle::new(*position, editor.bounds) + translation) + * scale_factor; + + if !clip_bounds.intersects(&physical_bounds) { + return; + } + + let clip_mask = (!physical_bounds.is_within(&clip_bounds)) + .then_some(clip_mask as &_); + + self.text_pipeline.draw_editor( + editor, + *position + translation, + *color, + scale_factor, + pixels, + clip_mask, + ); + } Primitive::Text { content, bounds, diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index 4f6e3941..d055c749 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -2,6 +2,7 @@ use crate::core::alignment; use crate::core::text::{LineHeight, Shaping}; use crate::core::{Color, Font, Pixels, Point, Rectangle}; use crate::graphics::text::cache::{self, Cache}; +use crate::graphics::text::editor; use crate::graphics::text::font_system; use crate::graphics::text::paragraph; @@ -64,6 +65,37 @@ impl Pipeline { ); } + pub fn draw_editor( + &mut self, + editor: &editor::Weak, + position: Point, + color: Color, + scale_factor: f32, + pixels: &mut tiny_skia::PixmapMut<'_>, + clip_mask: Option<&tiny_skia::Mask>, + ) { + use crate::core::text::Editor as _; + + let Some(editor) = editor.upgrade() else { + return; + }; + + let mut font_system = font_system().write().expect("Write font system"); + + draw( + font_system.raw(), + &mut self.glyph_cache, + editor.buffer(), + Rectangle::new(position, editor.min_bounds()), + color, + alignment::Horizontal::Left, + alignment::Vertical::Top, + scale_factor, + pixels, + clip_mask, + ); + } + pub fn draw_cached( &mut self, content: &str, -- cgit From c7d02e24e6f8265c205a68bd97b2643d40ae30ee Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 14 Sep 2023 18:57:09 +0200 Subject: Remove `Editor::min_bounds` and use `bounds` instead --- tiny_skia/src/text.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index d055c749..96cfbf32 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -86,7 +86,7 @@ impl Pipeline { font_system.raw(), &mut self.glyph_cache, editor.buffer(), - Rectangle::new(position, editor.min_bounds()), + Rectangle::new(position, editor.bounds()), color, alignment::Horizontal::Left, alignment::Vertical::Top, -- cgit From 9af0a27e675b71164f32f8d82eb4cde9cdd459f3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 Sep 2023 22:28:28 +0200 Subject: Draw colored glyphs in `iced_tiny_skia` --- tiny_skia/src/text.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index 96cfbf32..d1b33293 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -188,7 +188,7 @@ fn draw( if let Some((buffer, placement)) = glyph_cache.allocate( physical_glyph.cache_key, - color, + glyph.color_opt.map(from_color).unwrap_or(color), font_system, &mut swash, ) { @@ -213,6 +213,12 @@ fn draw( } } +fn from_color(color: cosmic_text::Color) -> Color { + let [r, g, b, a] = color.as_rgba(); + + Color::from_rgba8(r, g, b, a as f32 / 255.0) +} + #[derive(Debug, Clone, Default)] struct GlyphCache { entries: FxHashMap< -- cgit From be340a8cd822be1ea0fe4c1b1f3a62ca66d705b4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 19 Sep 2023 23:00:20 +0200 Subject: Fix gamma correction for colored glyphs in `iced_wgpu` --- tiny_skia/src/text.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index d1b33293..70e95d01 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -1,6 +1,7 @@ use crate::core::alignment; use crate::core::text::{LineHeight, Shaping}; use crate::core::{Color, Font, Pixels, Point, Rectangle}; +use crate::graphics::color; use crate::graphics::text::cache::{self, Cache}; use crate::graphics::text::editor; use crate::graphics::text::font_system; @@ -216,7 +217,18 @@ fn draw( fn from_color(color: cosmic_text::Color) -> Color { let [r, g, b, a] = color.as_rgba(); - Color::from_rgba8(r, g, b, a as f32 / 255.0) + if color::GAMMA_CORRECTION { + // `cosmic_text::Color` is linear RGB in this case, so we + // need to convert back to sRGB + Color::from_linear_rgba( + r as f32 / 255.0, + g as f32 / 255.0, + b as f32 / 255.0, + a as f32 / 255.0, + ) + } else { + Color::from_rgba8(r, g, b, a as f32 / 255.0) + } } #[derive(Debug, Clone, Default)] -- cgit From 2aaaf2cd0cb56f9efc946159a0232270f8d37eeb Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 11 Nov 2023 04:03:25 +0100 Subject: Call `convert_text` on `svg` node before rendering `tiny-skia` does not support text rendering, so we convert the text nodes to path nodes prior to that. --- tiny_skia/src/vector.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/vector.rs b/tiny_skia/src/vector.rs index a1cd269d..9c2893a2 100644 --- a/tiny_skia/src/vector.rs +++ b/tiny_skia/src/vector.rs @@ -1,7 +1,8 @@ use crate::core::svg::{Data, Handle}; use crate::core::{Color, Rectangle, Size}; +use crate::graphics::text; -use resvg::usvg; +use resvg::usvg::{self, TreeTextToPath}; use rustc_hash::{FxHashMap, FxHashSet}; use std::cell::RefCell; @@ -77,7 +78,7 @@ impl Cache { let id = handle.id(); if let hash_map::Entry::Vacant(entry) = self.trees.entry(id) { - let svg = match handle.data() { + let mut svg = match handle.data() { Data::Path(path) => { fs::read_to_string(path).ok().and_then(|contents| { usvg::Tree::from_str( @@ -92,6 +93,15 @@ impl Cache { } }; + if let Some(svg) = &mut svg { + if svg.has_text_nodes() { + let mut font_system = + text::font_system().write().expect("Read font system"); + + svg.convert_text(font_system.raw().db_mut()); + } + } + let _ = entry.insert(svg); } -- cgit From 5759096a4c33935fcdf5f96606143e4f21159186 Mon Sep 17 00:00:00 2001 From: Remmirad Date: Wed, 31 May 2023 15:46:21 +0200 Subject: Implement texture filtering options --- tiny_skia/src/raster.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/raster.rs b/tiny_skia/src/raster.rs index d13b1167..95f74ad1 100644 --- a/tiny_skia/src/raster.rs +++ b/tiny_skia/src/raster.rs @@ -39,12 +39,17 @@ impl Pipeline { let transform = transform.pre_scale(width_scale, height_scale); + let quality = match handle.filter().mag { + raster::FilterMethod::Linear => tiny_skia::FilterQuality::Bilinear, + raster::FilterMethod::Nearest => tiny_skia::FilterQuality::Nearest, + }; + pixels.draw_pixmap( (bounds.x / width_scale) as i32, (bounds.y / height_scale) as i32, image, &tiny_skia::PixmapPaint { - quality: tiny_skia::FilterQuality::Bilinear, + quality: quality, ..Default::default() }, transform, -- cgit From 4b32a488808e371313ce78e727c9d98ab2eb759e Mon Sep 17 00:00:00 2001 From: Remmirad Date: Fri, 4 Aug 2023 13:50:16 +0200 Subject: Fix clippy + fmt --- tiny_skia/src/raster.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/raster.rs b/tiny_skia/src/raster.rs index 95f74ad1..3f35ee78 100644 --- a/tiny_skia/src/raster.rs +++ b/tiny_skia/src/raster.rs @@ -40,8 +40,12 @@ impl Pipeline { let transform = transform.pre_scale(width_scale, height_scale); let quality = match handle.filter().mag { - raster::FilterMethod::Linear => tiny_skia::FilterQuality::Bilinear, - raster::FilterMethod::Nearest => tiny_skia::FilterQuality::Nearest, + raster::FilterMethod::Linear => { + tiny_skia::FilterQuality::Bilinear + } + raster::FilterMethod::Nearest => { + tiny_skia::FilterQuality::Nearest + } }; pixels.draw_pixmap( @@ -49,7 +53,7 @@ impl Pipeline { (bounds.y / height_scale) as i32, image, &tiny_skia::PixmapPaint { - quality: quality, + quality, ..Default::default() }, transform, -- cgit From a5125d6fea824df1191777fe3eb53a2f748208b9 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 11 Nov 2023 07:02:01 +0100 Subject: Refactor texture image filtering - Support only `Linear` or `Nearest` - Simplify `Layer` groups - Move `FilterMethod` to `Image` and `image::Viewer` --- tiny_skia/src/backend.rs | 16 +++++++++++++--- tiny_skia/src/raster.rs | 3 ++- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index 3c6fe288..f2905b00 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -445,7 +445,11 @@ impl Backend { ); } #[cfg(feature = "image")] - Primitive::Image { handle, bounds } => { + Primitive::Image { + handle, + filter_method, + bounds, + } => { let physical_bounds = (*bounds + translation) * scale_factor; if !clip_bounds.intersects(&physical_bounds) { @@ -461,8 +465,14 @@ impl Backend { ) .post_scale(scale_factor, scale_factor); - self.raster_pipeline - .draw(handle, *bounds, pixels, transform, clip_mask); + self.raster_pipeline.draw( + handle, + *filter_method, + *bounds, + pixels, + transform, + clip_mask, + ); } #[cfg(not(feature = "image"))] Primitive::Image { .. } => { diff --git a/tiny_skia/src/raster.rs b/tiny_skia/src/raster.rs index 3f35ee78..5f17ae60 100644 --- a/tiny_skia/src/raster.rs +++ b/tiny_skia/src/raster.rs @@ -28,6 +28,7 @@ impl Pipeline { pub fn draw( &mut self, handle: &raster::Handle, + filter_method: raster::FilterMethod, bounds: Rectangle, pixels: &mut tiny_skia::PixmapMut<'_>, transform: tiny_skia::Transform, @@ -39,7 +40,7 @@ impl Pipeline { let transform = transform.pre_scale(width_scale, height_scale); - let quality = match handle.filter().mag { + let quality = match filter_method { raster::FilterMethod::Linear => { tiny_skia::FilterQuality::Bilinear } -- cgit From 936d480267578d7e80675e78ec1880aaaaab72d6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 1 Dec 2023 16:04:27 +0100 Subject: Clip text to `viewport` bounds instead of layout bounds --- tiny_skia/src/backend.rs | 17 +++++++---------- tiny_skia/src/geometry.rs | 15 +++++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index f2905b00..cc0f72d1 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -1,6 +1,6 @@ use crate::core::{Background, Color, Gradient, Rectangle, Vector}; use crate::graphics::backend; -use crate::graphics::{Damage, Viewport}; +use crate::graphics::Viewport; use crate::primitive::{self, Primitive}; use std::borrow::Cow; @@ -361,11 +361,9 @@ impl Backend { paragraph, position, color, + viewport, } => { - let physical_bounds = - (Rectangle::new(*position, paragraph.min_bounds) - + translation) - * scale_factor; + let physical_bounds = (*viewport + translation) * scale_factor; if !clip_bounds.intersects(&physical_bounds) { return; @@ -387,10 +385,9 @@ impl Backend { editor, position, color, + viewport, } => { - let physical_bounds = - (Rectangle::new(*position, editor.bounds) + translation) - * scale_factor; + let physical_bounds = (*viewport + translation) * scale_factor; if !clip_bounds.intersects(&physical_bounds) { return; @@ -418,9 +415,9 @@ impl Backend { horizontal_alignment, vertical_alignment, shaping, + viewport, } => { - let physical_bounds = - (primitive.bounds() + translation) * scale_factor; + let physical_bounds = (*viewport + translation) * scale_factor; if !clip_bounds.intersects(&physical_bounds) { return; diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 1d14aa03..b73f84a9 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -109,15 +109,17 @@ impl Frame { Point::new(transformed[0].x, transformed[0].y) }; + let bounds = Rectangle { + x: position.x, + y: position.y, + width: f32::INFINITY, + height: f32::INFINITY, + }; + // TODO: Use vectorial text instead of primitive self.primitives.push(Primitive::Text { content: text.content, - bounds: Rectangle { - x: position.x, - y: position.y, - width: f32::INFINITY, - height: f32::INFINITY, - }, + bounds, color: text.color, size: text.size, line_height: text.line_height, @@ -125,6 +127,7 @@ impl Frame { horizontal_alignment: text.horizontal_alignment, vertical_alignment: text.vertical_alignment, shaping: text.shaping, + viewport: bounds, }); } -- cgit From b526ce4958b28208395276dd4078ffe0d780e1d7 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 2 Dec 2023 15:53:02 +0100 Subject: Rename `viewport` to `clip_bounds` --- tiny_skia/src/backend.rs | 15 +++++++++------ tiny_skia/src/geometry.rs | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index cc0f72d1..3e9bd2a5 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -361,9 +361,10 @@ impl Backend { paragraph, position, color, - viewport, + clip_bounds: text_clip_bounds, } => { - let physical_bounds = (*viewport + translation) * scale_factor; + let physical_bounds = + (*text_clip_bounds + translation) * scale_factor; if !clip_bounds.intersects(&physical_bounds) { return; @@ -385,9 +386,10 @@ impl Backend { editor, position, color, - viewport, + clip_bounds: text_clip_bounds, } => { - let physical_bounds = (*viewport + translation) * scale_factor; + let physical_bounds = + (*text_clip_bounds + translation) * scale_factor; if !clip_bounds.intersects(&physical_bounds) { return; @@ -415,9 +417,10 @@ impl Backend { horizontal_alignment, vertical_alignment, shaping, - viewport, + clip_bounds: text_clip_bounds, } => { - let physical_bounds = (*viewport + translation) * scale_factor; + let physical_bounds = + (*text_clip_bounds + translation) * scale_factor; if !clip_bounds.intersects(&physical_bounds) { return; diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index b73f84a9..5f28b737 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -127,7 +127,7 @@ impl Frame { horizontal_alignment: text.horizontal_alignment, vertical_alignment: text.vertical_alignment, shaping: text.shaping, - viewport: bounds, + clip_bounds: Rectangle::with_size(Size::INFINITY), }); } -- cgit From b152ecda63238136f77b6eda3c582fa1eff99737 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Sat, 2 Dec 2023 20:49:47 +0100 Subject: Separate `Compositor::new` from `Compositor::create_renderer` --- tiny_skia/src/window/compositor.rs | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 32095e23..87ded746 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -28,20 +28,11 @@ impl crate::graphics::Compositor for Compositor { fn new( settings: Self::Settings, _compatible_window: Option<&W>, - ) -> Result<(Self, Self::Renderer), Error> { - let (compositor, backend) = new(settings); - - Ok(( - compositor, - Renderer::new( - backend, - settings.default_font, - settings.default_text_size, - ), - )) + ) -> Result { + Ok(new(settings)) } - fn renderer(&self) -> Self::Renderer { + fn create_renderer(&self) -> Self::Renderer { Renderer::new( Backend::new(), self.settings.default_font, @@ -130,14 +121,11 @@ impl crate::graphics::Compositor for Compositor { } } -pub fn new(settings: Settings) -> (Compositor, Backend) { - ( - Compositor { - settings, - _theme: PhantomData, - }, - Backend::new(), - ) +pub fn new(settings: Settings) -> Compositor { + Compositor { + settings, + _theme: PhantomData, + } } pub fn present>( -- cgit From 603832e66c710ea39a95009ddc905de20c6856bd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 5 Dec 2023 02:19:17 +0100 Subject: Introduce `RawText` to `Primitive` in `iced_graphics` This should allow users to directly render a `cosmic_text::Buffer`. --- tiny_skia/src/backend.rs | 30 ++++++++++++++++++++++++++++++ tiny_skia/src/text.rs | 29 ++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index 3e9bd2a5..706db40e 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -1,5 +1,6 @@ use crate::core::{Background, Color, Gradient, Rectangle, Vector}; use crate::graphics::backend; +use crate::graphics::text; use crate::graphics::Viewport; use crate::primitive::{self, Primitive}; @@ -444,6 +445,35 @@ impl Backend { clip_mask, ); } + Primitive::RawText(text::Raw { + buffer, + position, + color, + clip_bounds: text_clip_bounds, + }) => { + let Some(buffer) = buffer.upgrade() else { + return; + }; + + let physical_bounds = + (*text_clip_bounds + translation) * scale_factor; + + if !clip_bounds.intersects(&physical_bounds) { + return; + } + + let clip_mask = (!physical_bounds.is_within(&clip_bounds)) + .then_some(clip_mask as &_); + + self.text_pipeline.draw_raw( + &buffer, + *position + translation, + *color, + scale_factor, + pixels, + clip_mask, + ); + } #[cfg(feature = "image")] Primitive::Image { handle, diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index 70e95d01..a5a0a1b6 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -1,6 +1,6 @@ use crate::core::alignment; use crate::core::text::{LineHeight, Shaping}; -use crate::core::{Color, Font, Pixels, Point, Rectangle}; +use crate::core::{Color, Font, Pixels, Point, Rectangle, Size}; use crate::graphics::color; use crate::graphics::text::cache::{self, Cache}; use crate::graphics::text::editor; @@ -149,6 +149,33 @@ impl Pipeline { ); } + pub fn draw_raw( + &mut self, + buffer: &cosmic_text::Buffer, + position: Point, + color: Color, + scale_factor: f32, + pixels: &mut tiny_skia::PixmapMut<'_>, + clip_mask: Option<&tiny_skia::Mask>, + ) { + let mut font_system = font_system().write().expect("Write font system"); + + let (width, height) = buffer.size(); + + draw( + font_system.raw(), + &mut self.glyph_cache, + buffer, + Rectangle::new(position, Size::new(width, height)), + color, + alignment::Horizontal::Left, + alignment::Vertical::Top, + scale_factor, + pixels, + clip_mask, + ); + } + pub fn trim_cache(&mut self) { self.cache.get_mut().trim(); self.glyph_cache.trim(); -- cgit From bb30b137d8b836b7e877d938c4cc62feefb9113f Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 11 Dec 2023 10:47:17 +0100 Subject: Fix `expect` message in `iced_tiny_skia::vector` --- tiny_skia/src/vector.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/vector.rs b/tiny_skia/src/vector.rs index 9c2893a2..fd1ab3de 100644 --- a/tiny_skia/src/vector.rs +++ b/tiny_skia/src/vector.rs @@ -96,7 +96,7 @@ impl Cache { if let Some(svg) = &mut svg { if svg.has_text_nodes() { let mut font_system = - text::font_system().write().expect("Read font system"); + text::font_system().write().expect("Write font system"); svg.convert_text(font_system.raw().db_mut()); } -- cgit From d948ca6f0979bc8120dcf3ce7ba78eac54755ce3 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Mon, 15 Jan 2024 23:45:24 +0100 Subject: Update `glyphon` to `0.4` `Color` is now always in the sRGB color space. --- tiny_skia/src/text.rs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/text.rs b/tiny_skia/src/text.rs index a5a0a1b6..9413e311 100644 --- a/tiny_skia/src/text.rs +++ b/tiny_skia/src/text.rs @@ -1,7 +1,6 @@ use crate::core::alignment; use crate::core::text::{LineHeight, Shaping}; use crate::core::{Color, Font, Pixels, Point, Rectangle, Size}; -use crate::graphics::color; use crate::graphics::text::cache::{self, Cache}; use crate::graphics::text::editor; use crate::graphics::text::font_system; @@ -244,18 +243,7 @@ fn draw( fn from_color(color: cosmic_text::Color) -> Color { let [r, g, b, a] = color.as_rgba(); - if color::GAMMA_CORRECTION { - // `cosmic_text::Color` is linear RGB in this case, so we - // need to convert back to sRGB - Color::from_linear_rgba( - r as f32 / 255.0, - g as f32 / 255.0, - b as f32 / 255.0, - a as f32 / 255.0, - ) - } else { - Color::from_rgba8(r, g, b, a as f32 / 255.0) - } + Color::from_rgba8(r, g, b, a as f32 / 255.0) } #[derive(Debug, Clone, Default)] -- cgit From 5aa741a177e6220640ea884827f93f152cbd07d1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 17 Jan 2024 13:27:39 +0100 Subject: Apply scaling during `Frame::fill_text` in `iced_tiny_skia` --- tiny_skia/src/geometry.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 5f28b737..4cc04c6e 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -1,4 +1,5 @@ -use crate::core::{Point, Rectangle, Size, Vector}; +use crate::core::text::LineHeight; +use crate::core::{Pixels, Point, Rectangle, Size, Vector}; use crate::graphics::geometry::fill::{self, Fill}; use crate::graphics::geometry::stroke::{self, Stroke}; use crate::graphics::geometry::{Path, Style, Text}; @@ -96,17 +97,32 @@ impl Frame { pub fn fill_text(&mut self, text: impl Into) { let text = text.into(); - let position = if self.transform.is_identity() { - text.position + let (position, size, line_height) = if self.transform.is_identity() { + (text.position, text.size, text.line_height) } else { - let mut transformed = [tiny_skia::Point { + let mut position = [tiny_skia::Point { x: text.position.x, y: text.position.y, }]; - self.transform.map_points(&mut transformed); + self.transform.map_points(&mut position); - Point::new(transformed[0].x, transformed[0].y) + let (_, scale_y) = self.transform.get_scale(); + + let size = text.size.0 * scale_y; + + let line_height = match text.line_height { + LineHeight::Absolute(size) => { + LineHeight::Absolute(Pixels(size.0 * scale_y)) + } + LineHeight::Relative(factor) => LineHeight::Relative(factor), + }; + + ( + Point::new(position[0].x, position[0].y), + size.into(), + line_height, + ) }; let bounds = Rectangle { @@ -121,8 +137,8 @@ impl Frame { content: text.content, bounds, color: text.color, - size: text.size, - line_height: text.line_height, + size, + line_height, font: text.font, horizontal_alignment: text.horizontal_alignment, vertical_alignment: text.vertical_alignment, -- cgit From 4cb53a6e225f9e533126eb03d3cc34be3fd09f1d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 17 Jan 2024 14:48:33 +0100 Subject: Implement vectorial text support for `iced_tiny_skia` --- tiny_skia/src/geometry.rs | 99 ++++++++++++++++++++++++++--------------------- 1 file changed, 55 insertions(+), 44 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 4cc04c6e..b00f4676 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -97,54 +97,65 @@ impl Frame { pub fn fill_text(&mut self, text: impl Into) { let text = text.into(); - let (position, size, line_height) = if self.transform.is_identity() { - (text.position, text.size, text.line_height) - } else { - let mut position = [tiny_skia::Point { - x: text.position.x, - y: text.position.y, - }]; - - self.transform.map_points(&mut position); - - let (_, scale_y) = self.transform.get_scale(); - - let size = text.size.0 * scale_y; + let (scale_x, scale_y) = self.transform.get_scale(); + + if self.transform.is_scale_translate() + && scale_x == scale_y + && scale_x > 0.0 + && scale_y > 0.0 + { + let (position, size, line_height) = if self.transform.is_identity() + { + (text.position, text.size, text.line_height) + } else { + let mut position = [tiny_skia::Point { + x: text.position.x, + y: text.position.y, + }]; + + self.transform.map_points(&mut position); + + let size = text.size.0 * scale_y; + + let line_height = match text.line_height { + LineHeight::Absolute(size) => { + LineHeight::Absolute(Pixels(size.0 * scale_y)) + } + LineHeight::Relative(factor) => { + LineHeight::Relative(factor) + } + }; + + ( + Point::new(position[0].x, position[0].y), + size.into(), + line_height, + ) + }; - let line_height = match text.line_height { - LineHeight::Absolute(size) => { - LineHeight::Absolute(Pixels(size.0 * scale_y)) - } - LineHeight::Relative(factor) => LineHeight::Relative(factor), + let bounds = Rectangle { + x: position.x, + y: position.y, + width: f32::INFINITY, + height: f32::INFINITY, }; - ( - Point::new(position[0].x, position[0].y), - size.into(), + // TODO: Honor layering! + self.primitives.push(Primitive::Text { + content: text.content, + bounds, + color: text.color, + size, line_height, - ) - }; - - let bounds = Rectangle { - x: position.x, - y: position.y, - width: f32::INFINITY, - height: f32::INFINITY, - }; - - // TODO: Use vectorial text instead of primitive - self.primitives.push(Primitive::Text { - content: text.content, - bounds, - color: text.color, - size, - line_height, - font: text.font, - horizontal_alignment: text.horizontal_alignment, - vertical_alignment: text.vertical_alignment, - shaping: text.shaping, - clip_bounds: Rectangle::with_size(Size::INFINITY), - }); + font: text.font, + horizontal_alignment: text.horizontal_alignment, + vertical_alignment: text.vertical_alignment, + shaping: text.shaping, + clip_bounds: Rectangle::with_size(Size::INFINITY), + }); + } else { + text.draw_with(|path, color| self.fill(&path, color)); + } } pub fn push_transform(&mut self) { -- cgit From acee3b030baf4df24a871e56789772c677b66bcf Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 17 Jan 2024 15:31:29 +0100 Subject: Fix paths with negative coordinates in `iced_tiny_skia` --- tiny_skia/src/backend.rs | 18 ++++++++++-------- tiny_skia/src/geometry.rs | 17 +++++++++++------ tiny_skia/src/primitive.rs | 4 ---- 3 files changed, 21 insertions(+), 18 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/backend.rs b/tiny_skia/src/backend.rs index 706db40e..d1393b4d 100644 --- a/tiny_skia/src/backend.rs +++ b/tiny_skia/src/backend.rs @@ -543,7 +543,6 @@ impl Backend { path, paint, rule, - transform, }) => { let bounds = path.bounds(); @@ -566,9 +565,11 @@ impl Backend { path, paint, *rule, - transform - .post_translate(translation.x, translation.y) - .post_scale(scale_factor, scale_factor), + tiny_skia::Transform::from_translate( + translation.x, + translation.y, + ) + .post_scale(scale_factor, scale_factor), clip_mask, ); } @@ -576,7 +577,6 @@ impl Backend { path, paint, stroke, - transform, }) => { let bounds = path.bounds(); @@ -599,9 +599,11 @@ impl Backend { path, paint, stroke, - transform - .post_translate(translation.x, translation.y) - .post_scale(scale_factor, scale_factor), + tiny_skia::Transform::from_translate( + translation.x, + translation.y, + ) + .post_scale(scale_factor, scale_factor), clip_mask, ); } diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index b00f4676..501638e0 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -40,9 +40,12 @@ impl Frame { } pub fn fill(&mut self, path: &Path, fill: impl Into) { - let Some(path) = convert_path(path) else { + let Some(path) = + convert_path(path).and_then(|path| path.transform(self.transform)) + else { return; }; + let fill = fill.into(); self.primitives @@ -50,7 +53,6 @@ impl Frame { path, paint: into_paint(fill.style), rule: into_fill_rule(fill.rule), - transform: self.transform, })); } @@ -60,9 +62,12 @@ impl Frame { size: Size, fill: impl Into, ) { - let Some(path) = convert_path(&Path::rectangle(top_left, size)) else { + let Some(path) = convert_path(&Path::rectangle(top_left, size)) + .and_then(|path| path.transform(self.transform)) + else { return; }; + let fill = fill.into(); self.primitives @@ -73,12 +78,13 @@ impl Frame { ..into_paint(fill.style) }, rule: into_fill_rule(fill.rule), - transform: self.transform, })); } pub fn stroke<'a>(&mut self, path: &Path, stroke: impl Into>) { - let Some(path) = convert_path(path) else { + let Some(path) = + convert_path(path).and_then(|path| path.transform(self.transform)) + else { return; }; @@ -90,7 +96,6 @@ impl Frame { path, paint: into_paint(stroke.style), stroke: skia_stroke, - transform: self.transform, })); } diff --git a/tiny_skia/src/primitive.rs b/tiny_skia/src/primitive.rs index 0ed24969..7718d542 100644 --- a/tiny_skia/src/primitive.rs +++ b/tiny_skia/src/primitive.rs @@ -13,8 +13,6 @@ pub enum Custom { paint: tiny_skia::Paint<'static>, /// The fill rule to follow. rule: tiny_skia::FillRule, - /// The transform to apply to the path. - transform: tiny_skia::Transform, }, /// A path stroked with some paint. Stroke { @@ -24,8 +22,6 @@ pub enum Custom { paint: tiny_skia::Paint<'static>, /// The stroke settings. stroke: tiny_skia::Stroke, - /// The transform to apply to the path. - transform: tiny_skia::Transform, }, } -- cgit From 5d4c55c07a80d93e6009e94c2a861ad549d30aab Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Wed, 17 Jan 2024 15:53:08 +0100 Subject: Fix `paint` not being transformed in `iced_tiny_skia` --- tiny_skia/src/geometry.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/geometry.rs b/tiny_skia/src/geometry.rs index 501638e0..74a08d38 100644 --- a/tiny_skia/src/geometry.rs +++ b/tiny_skia/src/geometry.rs @@ -48,10 +48,13 @@ impl Frame { let fill = fill.into(); + let mut paint = into_paint(fill.style); + paint.shader.transform(self.transform); + self.primitives .push(Primitive::Custom(primitive::Custom::Fill { path, - paint: into_paint(fill.style), + paint, rule: into_fill_rule(fill.rule), })); } @@ -70,13 +73,16 @@ impl Frame { let fill = fill.into(); + let mut paint = tiny_skia::Paint { + anti_alias: false, + ..into_paint(fill.style) + }; + paint.shader.transform(self.transform); + self.primitives .push(Primitive::Custom(primitive::Custom::Fill { path, - paint: tiny_skia::Paint { - anti_alias: false, - ..into_paint(fill.style) - }, + paint, rule: into_fill_rule(fill.rule), })); } @@ -91,10 +97,13 @@ impl Frame { let stroke = stroke.into(); let skia_stroke = into_stroke(&stroke); + let mut paint = into_paint(stroke.style); + paint.shader.transform(self.transform); + self.primitives .push(Primitive::Custom(primitive::Custom::Stroke { path, - paint: into_paint(stroke.style), + paint, stroke: skia_stroke, })); } -- cgit From ff268c8c4268d930fc337636302175d44e201448 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 9 Jan 2024 12:25:53 -0800 Subject: Update to `softbuffer` 0.3, tracking up to `age` sets of primitives --- tiny_skia/src/window/compositor.rs | 121 +++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 44 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 87ded746..d99b85d4 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -5,18 +5,21 @@ use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use std::collections::VecDeque; use std::marker::PhantomData; +use std::num::NonZeroU32; pub struct Compositor { + context: Option, settings: Settings, _theme: PhantomData, } pub struct Surface { - window: softbuffer::GraphicsContext, - buffer: Vec, + window: softbuffer::Surface, clip_mask: tiny_skia::Mask, - primitives: Option>, + // Primitives of existing buffers, by decreasing age + primitives: VecDeque>, background_color: Color, } @@ -27,9 +30,9 @@ impl crate::graphics::Compositor for Compositor { fn new( settings: Self::Settings, - _compatible_window: Option<&W>, + compatible_window: Option<&W>, ) -> Result { - Ok(new(settings)) + Ok(new(settings, compatible_window)) } fn create_renderer(&self) -> Self::Renderer { @@ -47,16 +50,21 @@ impl crate::graphics::Compositor for Compositor { height: u32, ) -> Surface { #[allow(unsafe_code)] - let window = - unsafe { softbuffer::GraphicsContext::new(window, window) } - .expect("Create softbuffer for window"); + let window = if let Some(context) = self.context.as_ref() { + unsafe { softbuffer::Surface::new(context, window) } + .expect("Create softbuffer surface for window") + } else { + let context = unsafe { softbuffer::Context::new(window) } + .expect("Create softbuffer context for window"); + unsafe { softbuffer::Surface::new(&context, window) } + .expect("Create softbuffer surface for window") + }; Surface { window, - buffer: vec![0; width as usize * height as usize], clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), - primitives: None, + primitives: VecDeque::new(), background_color: Color::BLACK, } } @@ -67,10 +75,9 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) { - surface.buffer.resize((width * height) as usize, 0); surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); - surface.primitives = None; + surface.primitives.clear(); } fn fetch_information(&self) -> Information { @@ -121,8 +128,15 @@ impl crate::graphics::Compositor for Compositor { } } -pub fn new(settings: Settings) -> Compositor { +pub fn new( + settings: Settings, + compatible_window: Option<&W>, +) -> Compositor { + #[allow(unsafe_code)] + let context = compatible_window + .and_then(|w| unsafe { softbuffer::Context::new(w) }.ok()); Compositor { + context, settings, _theme: PhantomData, } @@ -139,48 +153,67 @@ pub fn present>( let physical_size = viewport.physical_size(); let scale_factor = viewport.scale_factor() as f32; - let mut pixels = tiny_skia::PixmapMut::from_bytes( - bytemuck::cast_slice_mut(&mut surface.buffer), - physical_size.width, - physical_size.height, - ) - .expect("Create pixel map"); + surface + .window + .resize( + NonZeroU32::new(physical_size.width).unwrap(), + NonZeroU32::new(physical_size.height).unwrap(), + ) + .unwrap(); + + // TODO Add variants to `SurfaceError`? + let mut buffer = surface + .window + .buffer_mut() + .map_err(|_| compositor::SurfaceError::Lost)?; + + let age = buffer.age(); - let damage = surface - .primitives - .as_deref() + // Forget primatives for back buffers older than `age` + // Or if this is a new buffer, keep at most two. + let max = if age == 0 { 2 } else { age }; + while surface.primitives.len() as u8 > max { + let _ = surface.primitives.pop_front(); + } + + let last_primitives = if surface.primitives.len() as u8 == age { + surface.primitives.pop_front() + } else { + None + }; + + let damage = last_primitives .and_then(|last_primitives| { (surface.background_color == background_color) - .then(|| damage::list(last_primitives, primitives)) + .then(|| damage::list(&last_primitives, primitives)) }) .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); - if damage.is_empty() { - return Ok(()); - } - - surface.primitives = Some(primitives.to_vec()); + surface.primitives.push_back(primitives.to_vec()); surface.background_color = background_color; - let damage = damage::group(damage, scale_factor, physical_size); + if !damage.is_empty() { + let damage = damage::group(damage, scale_factor, physical_size); - backend.draw( - &mut pixels, - &mut surface.clip_mask, - primitives, - viewport, - &damage, - background_color, - overlay, - ); + let mut pixels = tiny_skia::PixmapMut::from_bytes( + bytemuck::cast_slice_mut(&mut buffer), + physical_size.width, + physical_size.height, + ) + .expect("Create pixel map"); - surface.window.set_buffer( - &surface.buffer, - physical_size.width as u16, - physical_size.height as u16, - ); + backend.draw( + &mut pixels, + &mut surface.clip_mask, + primitives, + viewport, + &damage, + background_color, + overlay, + ); + } - Ok(()) + buffer.present().map_err(|_| compositor::SurfaceError::Lost) } pub fn screenshot>( -- cgit From 7289b6091b61b0aa448a756cfe32211c78a4cce0 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Tue, 9 Jan 2024 07:19:15 -0800 Subject: WIP raw-window-handle 0.6 --- tiny_skia/src/window/compositor.rs | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index d99b85d4..788d7297 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -4,33 +4,36 @@ use crate::graphics::damage; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::collections::VecDeque; use std::marker::PhantomData; use std::num::NonZeroU32; -pub struct Compositor { - context: Option, +pub struct Compositor { + context: Option>, settings: Settings, _theme: PhantomData, } -pub struct Surface { - window: softbuffer::Surface, +pub struct Surface { + window: softbuffer::Surface, clip_mask: tiny_skia::Mask, // Primitives of existing buffers, by decreasing age primitives: VecDeque>, background_color: Color, } -impl crate::graphics::Compositor for Compositor { +// XXX avoid clone bound? +impl + crate::graphics::Compositor for Compositor +{ type Settings = Settings; type Renderer = Renderer; - type Surface = Surface; + type Surface = Surface; - fn new( + fn new( settings: Self::Settings, - compatible_window: Option<&W>, + compatible_window: Option, ) -> Result { Ok(new(settings, compatible_window)) } @@ -43,20 +46,19 @@ impl crate::graphics::Compositor for Compositor { ) } - fn create_surface( + fn create_surface( &mut self, - window: &W, + window: W, width: u32, height: u32, - ) -> Surface { - #[allow(unsafe_code)] + ) -> Surface { let window = if let Some(context) = self.context.as_ref() { - unsafe { softbuffer::Surface::new(context, window) } + softbuffer::Surface::new(context, window) .expect("Create softbuffer surface for window") } else { - let context = unsafe { softbuffer::Context::new(window) } + let context = softbuffer::Context::new(window.clone()) .expect("Create softbuffer context for window"); - unsafe { softbuffer::Surface::new(&context, window) } + softbuffer::Surface::new(&context, window) .expect("Create softbuffer surface for window") }; @@ -71,7 +73,7 @@ impl crate::graphics::Compositor for Compositor { fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Surface, width: u32, height: u32, ) { @@ -90,7 +92,7 @@ impl crate::graphics::Compositor for Compositor { fn present>( &mut self, renderer: &mut Self::Renderer, - surface: &mut Self::Surface, + surface: &mut Surface, viewport: &Viewport, background_color: Color, overlay: &[T], @@ -128,13 +130,13 @@ impl crate::graphics::Compositor for Compositor { } } -pub fn new( +pub fn new( settings: Settings, - compatible_window: Option<&W>, -) -> Compositor { + compatible_window: Option, +) -> Compositor { #[allow(unsafe_code)] - let context = compatible_window - .and_then(|w| unsafe { softbuffer::Context::new(w) }.ok()); + let context = + compatible_window.and_then(|w| softbuffer::Context::new(w).ok()); Compositor { context, settings, @@ -142,9 +144,9 @@ pub fn new( } } -pub fn present>( +pub fn present>( backend: &mut Backend, - surface: &mut Surface, + surface: &mut Surface, primitives: &[Primitive], viewport: &Viewport, background_color: Color, @@ -216,8 +218,8 @@ pub fn present>( buffer.present().map_err(|_| compositor::SurfaceError::Lost) } -pub fn screenshot>( - surface: &mut Surface, +pub fn screenshot>( + surface: &mut Surface, backend: &mut Backend, primitives: &[Primitive], viewport: &Viewport, -- cgit From 8bf238697226e827dc983f9d89afbd0e252c5254 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 09:55:27 +0100 Subject: Remove `Compositor` window generic And update `glyphon` and `window_clipboard` --- tiny_skia/src/window/compositor.rs | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 788d7297..b5e9bcd8 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -4,34 +4,33 @@ use crate::graphics::damage; use crate::graphics::{Error, Viewport}; use crate::{Backend, Primitive, Renderer, Settings}; -use raw_window_handle::{HasDisplayHandle, HasWindowHandle}; use std::collections::VecDeque; use std::marker::PhantomData; use std::num::NonZeroU32; -pub struct Compositor { - context: Option>, +pub struct Compositor { + context: Option>>, settings: Settings, _theme: PhantomData, } -pub struct Surface { - window: softbuffer::Surface, +pub struct Surface { + window: softbuffer::Surface< + Box, + Box, + >, clip_mask: tiny_skia::Mask, // Primitives of existing buffers, by decreasing age primitives: VecDeque>, background_color: Color, } -// XXX avoid clone bound? -impl - crate::graphics::Compositor for Compositor -{ +impl crate::graphics::Compositor for Compositor { type Settings = Settings; type Renderer = Renderer; - type Surface = Surface; + type Surface = Surface; - fn new( + fn new( settings: Self::Settings, compatible_window: Option, ) -> Result { @@ -46,19 +45,21 @@ impl ) } - fn create_surface( + fn create_surface( &mut self, window: W, width: u32, height: u32, - ) -> Surface { + ) -> Surface { let window = if let Some(context) = self.context.as_ref() { - softbuffer::Surface::new(context, window) + softbuffer::Surface::new(context, Box::new(window.clone()) as _) .expect("Create softbuffer surface for window") } else { - let context = softbuffer::Context::new(window.clone()) - .expect("Create softbuffer context for window"); - softbuffer::Surface::new(&context, window) + let context = + softbuffer::Context::new(Box::new(window.clone()) as _) + .expect("Create softbuffer context for window"); + + softbuffer::Surface::new(&context, Box::new(window.clone()) as _) .expect("Create softbuffer surface for window") }; @@ -73,7 +74,7 @@ impl fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Surface, width: u32, height: u32, ) { @@ -92,7 +93,7 @@ impl fn present>( &mut self, renderer: &mut Self::Renderer, - surface: &mut Surface, + surface: &mut Surface, viewport: &Viewport, background_color: Color, overlay: &[T], @@ -130,13 +131,14 @@ impl } } -pub fn new( +pub fn new( settings: Settings, compatible_window: Option, -) -> Compositor { +) -> Compositor { #[allow(unsafe_code)] - let context = - compatible_window.and_then(|w| softbuffer::Context::new(w).ok()); + let context = compatible_window + .and_then(|w| softbuffer::Context::new(Box::new(w) as _).ok()); + Compositor { context, settings, @@ -144,9 +146,9 @@ pub fn new( } } -pub fn present>( +pub fn present>( backend: &mut Backend, - surface: &mut Surface, + surface: &mut Surface, primitives: &[Primitive], viewport: &Viewport, background_color: Color, @@ -218,8 +220,8 @@ pub fn present>( buffer.present().map_err(|_| compositor::SurfaceError::Lost) } -pub fn screenshot>( - surface: &mut Surface, +pub fn screenshot>( + surface: &mut Surface, backend: &mut Backend, primitives: &[Primitive], viewport: &Viewport, -- cgit From 5fc49edc55a0e64c4c46ca55eddafe9d4e8232e1 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:06:30 +0100 Subject: Make `compatible_window` mandatory in `Compositor` --- tiny_skia/src/window/compositor.rs | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index b5e9bcd8..86400aa0 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -9,7 +9,7 @@ use std::marker::PhantomData; use std::num::NonZeroU32; pub struct Compositor { - context: Option>>, + context: softbuffer::Context>, settings: Settings, _theme: PhantomData, } @@ -32,7 +32,7 @@ impl crate::graphics::Compositor for Compositor { fn new( settings: Self::Settings, - compatible_window: Option, + compatible_window: W, ) -> Result { Ok(new(settings, compatible_window)) } @@ -51,17 +51,11 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) -> Surface { - let window = if let Some(context) = self.context.as_ref() { - softbuffer::Surface::new(context, Box::new(window.clone()) as _) - .expect("Create softbuffer surface for window") - } else { - let context = - softbuffer::Context::new(Box::new(window.clone()) as _) - .expect("Create softbuffer context for window"); - - softbuffer::Surface::new(&context, Box::new(window.clone()) as _) - .expect("Create softbuffer surface for window") - }; + let window = softbuffer::Surface::new( + &self.context, + Box::new(window.clone()) as _, + ) + .expect("Create softbuffer surface for window"); Surface { window, @@ -133,11 +127,11 @@ impl crate::graphics::Compositor for Compositor { pub fn new( settings: Settings, - compatible_window: Option, + compatible_window: W, ) -> Compositor { #[allow(unsafe_code)] - let context = compatible_window - .and_then(|w| softbuffer::Context::new(Box::new(w) as _).ok()); + let context = softbuffer::Context::new(Box::new(compatible_window) as _) + .expect("Create softbuffer context"); Compositor { context, -- cgit From 4b7744b9806397c9891b1fc179df8a61eaa3670d Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:35:27 +0100 Subject: Support out-of-order `Buffer` ages in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 86400aa0..c0aabdb6 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -20,9 +20,9 @@ pub struct Surface { Box, >, clip_mask: tiny_skia::Mask, - // Primitives of existing buffers, by decreasing age - primitives: VecDeque>, + primitive_stack: VecDeque>, background_color: Color, + max_age: u8, } impl crate::graphics::Compositor for Compositor { @@ -61,8 +61,9 @@ impl crate::graphics::Compositor for Compositor { window, clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), - primitives: VecDeque::new(), + primitive_stack: VecDeque::new(), background_color: Color::BLACK, + max_age: 0, } } @@ -74,7 +75,7 @@ impl crate::graphics::Compositor for Compositor { ) { surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); - surface.primitives.clear(); + surface.primitive_stack.clear(); } fn fetch_information(&self) -> Information { @@ -159,7 +160,6 @@ pub fn present>( ) .unwrap(); - // TODO Add variants to `SurfaceError`? let mut buffer = surface .window .buffer_mut() @@ -167,27 +167,25 @@ pub fn present>( let age = buffer.age(); - // Forget primatives for back buffers older than `age` - // Or if this is a new buffer, keep at most two. - let max = if age == 0 { 2 } else { age }; - while surface.primitives.len() as u8 > max { - let _ = surface.primitives.pop_front(); - } + let last_primitives = { + surface.max_age = surface.max_age.max(age); + surface.primitive_stack.truncate(surface.max_age as usize); - let last_primitives = if surface.primitives.len() as u8 == age { - surface.primitives.pop_front() - } else { - None + if age > 0 { + surface.primitive_stack.get(age as usize - 1) + } else { + None + } }; let damage = last_primitives .and_then(|last_primitives| { (surface.background_color == background_color) - .then(|| damage::list(&last_primitives, primitives)) + .then(|| damage::list(last_primitives, primitives)) }) .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); - surface.primitives.push_back(primitives.to_vec()); + surface.primitive_stack.push_front(primitives.to_vec()); surface.background_color = background_color; if !damage.is_empty() { -- cgit From b6b3e9b9f995abf5cc65814e143418b6f1ec7464 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:42:02 +0100 Subject: Avoid stacking new primitives when undamaged --- tiny_skia/src/window/compositor.rs | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index c0aabdb6..dae57975 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -185,29 +185,31 @@ pub fn present>( }) .unwrap_or_else(|| vec![Rectangle::with_size(viewport.logical_size())]); + if damage.is_empty() { + return Ok(()); + } + surface.primitive_stack.push_front(primitives.to_vec()); surface.background_color = background_color; - if !damage.is_empty() { - let damage = damage::group(damage, scale_factor, physical_size); + let damage = damage::group(damage, scale_factor, physical_size); - let mut pixels = tiny_skia::PixmapMut::from_bytes( - bytemuck::cast_slice_mut(&mut buffer), - physical_size.width, - physical_size.height, - ) - .expect("Create pixel map"); - - backend.draw( - &mut pixels, - &mut surface.clip_mask, - primitives, - viewport, - &damage, - background_color, - overlay, - ); - } + let mut pixels = tiny_skia::PixmapMut::from_bytes( + bytemuck::cast_slice_mut(&mut buffer), + physical_size.width, + physical_size.height, + ) + .expect("Create pixel map"); + + backend.draw( + &mut pixels, + &mut surface.clip_mask, + primitives, + viewport, + &damage, + background_color, + overlay, + ); buffer.present().map_err(|_| compositor::SurfaceError::Lost) } -- cgit From 150ce65e209414847ae133a70c833addd3086e15 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:43:52 +0100 Subject: Nest `age` declaration inside `last_primitives` --- tiny_skia/src/window/compositor.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index dae57975..08a49bc5 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -165,9 +165,9 @@ pub fn present>( .buffer_mut() .map_err(|_| compositor::SurfaceError::Lost)?; - let age = buffer.age(); - let last_primitives = { + let age = buffer.age(); + surface.max_age = surface.max_age.max(age); surface.primitive_stack.truncate(surface.max_age as usize); -- cgit From 3cf8f77d6537f9d864f4a554b2fff46676a761f6 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:52:25 +0100 Subject: Resize surface in `configure_surface` in `iced_tiny_skia` --- tiny_skia/src/window/compositor.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 08a49bc5..17d21100 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -57,14 +57,18 @@ impl crate::graphics::Compositor for Compositor { ) .expect("Create softbuffer surface for window"); - Surface { + let mut surface = Surface { window, clip_mask: tiny_skia::Mask::new(width, height) .expect("Create clip mask"), primitive_stack: VecDeque::new(), background_color: Color::BLACK, max_age: 0, - } + }; + + self.configure_surface(&mut surface, width, height); + + surface } fn configure_surface( @@ -73,6 +77,14 @@ impl crate::graphics::Compositor for Compositor { width: u32, height: u32, ) { + surface + .window + .resize( + NonZeroU32::new(width).expect("Non-zero width"), + NonZeroU32::new(height).expect("Non-zero height"), + ) + .expect("Resize surface"); + surface.clip_mask = tiny_skia::Mask::new(width, height).expect("Create clip mask"); surface.primitive_stack.clear(); @@ -152,14 +164,6 @@ pub fn present>( let physical_size = viewport.physical_size(); let scale_factor = viewport.scale_factor() as f32; - surface - .window - .resize( - NonZeroU32::new(physical_size.width).unwrap(), - NonZeroU32::new(physical_size.height).unwrap(), - ) - .unwrap(); - let mut buffer = surface .window .buffer_mut() -- cgit From c929e6f5dd30044df4e7400ab633eaf0a53ce3dd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 18 Jan 2024 10:56:02 +0100 Subject: Use `Self::Surface` in `Compositor` implementors --- tiny_skia/src/window/compositor.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'tiny_skia/src') diff --git a/tiny_skia/src/window/compositor.rs b/tiny_skia/src/window/compositor.rs index 17d21100..781ed8a5 100644 --- a/tiny_skia/src/window/compositor.rs +++ b/tiny_skia/src/window/compositor.rs @@ -50,7 +50,7 @@ impl crate::graphics::Compositor for Compositor { window: W, width: u32, height: u32, - ) -> Surface { + ) -> Self::Surface { let window = softbuffer::Surface::new( &self.context, Box::new(window.clone()) as _, @@ -73,7 +73,7 @@ impl crate::graphics::Compositor for Compositor { fn configure_surface( &mut self, - surface: &mut Surface, + surface: &mut Self::Surface, width: u32, height: u32, ) { @@ -100,7 +100,7 @@ impl crate::graphics::Compositor for Compositor { fn present>( &mut self, renderer: &mut Self::Renderer, - surface: &mut Surface, + surface: &mut Self::Surface, viewport: &Viewport, background_color: Color, overlay: &[T], -- cgit