From b059b3f3ca6542f348e56f82031ce402bc235a9c Mon Sep 17 00:00:00 2001 From: Adam Obuchowicz Date: Mon, 30 May 2022 12:32:43 +0200 Subject: [PATCH] Fix depth-ordering update (#3486) There are two dirty flags in layers: depth_order_dirty and element_depth_order_dirty - one marking changed in Layer, second marking change in one of sublayers. The depth_order_dirty has a proper callback for setting element_depth_order_dirty of its parent. However, the latter did not propagate up. I fixed it by adding callback for element_depth_order_dirty which sets the depth_order_dirty of the parent. # Important Notes * The question to @wdanilo : is it possible, that I can propagate dirty directly to element_depth_order_dirty, without setting depth_order_dirty? As far as I understand the code, it would also work (and we would omit some unnecessary updates). * I tried to leave some logs, but I don't feel how to do that: the tooling I used was very specific, only the concrete ids of symbols and layers were logged, and I don't know how to generalize it. --- CHANGELOG.md | 2 ++ .../ensogl/core/src/display/scene/layer.rs | 27 ++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d06116cd797b9..6cf57f6534e5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ - [You can change font and set letters bold in the text::Area component][3385]. Use the set_font and set_bold_bytes respectively. +- [Fixed a text rendering issue in nested sublayer][3486]. #### Enso Standard Library @@ -201,6 +202,7 @@ [3462]: https://github.com/enso-org/enso/pull/3462 [3463]: https://github.com/enso-org/enso/pull/3463 [3472]: https://github.com/enso-org/enso/pull/3472 +[3486]: https://github.com/enso-org/enso/pull/3486 [3478]: https://github.com/enso-org/enso/pull/3478 #### Enso Compiler diff --git a/lib/rust/ensogl/core/src/display/scene/layer.rs b/lib/rust/ensogl/core/src/display/scene/layer.rs index d4fd171840fcc..5b7d6c458b504 100644 --- a/lib/rust/ensogl/core/src/display/scene/layer.rs +++ b/lib/rust/ensogl/core/src/display/scene/layer.rs @@ -22,7 +22,6 @@ use smallvec::alloc::collections::BTreeSet; use std::any::TypeId; - // ============= // === Layer === // ============= @@ -365,7 +364,7 @@ impl LayerModel { let on_mut = on_depth_order_dirty(&parents); let depth_order_dirty = dirty::SharedBool::new(logger_dirty, on_mut); let global_element_depth_order = default(); - let sublayers = Sublayers::new(Logger::new_sub(&logger, "registry")); + let sublayers = Sublayers::new(Logger::new_sub(&logger, "registry"), &parents); let mask = default(); let scissor_box = default(); let mem_mark = default(); @@ -800,12 +799,14 @@ impl LayerModel { } } -/// Unboxed callback. +/// The callback setting `element_depth_order_dirty` in parents. pub type OnDepthOrderDirty = impl Fn(); fn on_depth_order_dirty(parents: &Rc>>) -> OnDepthOrderDirty { let parents = parents.clone(); move || { for parent in &*parents.borrow() { + // It's safe to do it having parents borrowed, because the only possible callback called + // [`OnElementDepthOrderDirty`], which don't borrow_mut at any point. parent.element_depth_order_dirty.set() } } @@ -851,11 +852,24 @@ impl LayerDynamicShapeInstance { // === Sublayers === // ================= +/// The callback propagating `element_depth_order_dirty` flag to parents. +pub type OnElementDepthOrderDirty = impl Fn(); +fn on_element_depth_order_dirty(parents: &Rc>>) -> OnElementDepthOrderDirty { + let parents = parents.clone_ref(); + move || { + for sublayers in parents.borrow().iter() { + // It's safe to do it having parents borrowed, because the only possible callback called + // [`OnElementDepthOrderDirty`], which don't borrow_mut at any point. + sublayers.element_depth_order_dirty.set() + } + } +} + /// Abstraction for layer sublayers. #[derive(Clone, CloneRef, Debug)] pub struct Sublayers { model: Rc>, - element_depth_order_dirty: dirty::SharedBool, + element_depth_order_dirty: dirty::SharedBool, } impl Deref for Sublayers { @@ -874,10 +888,11 @@ impl PartialEq for Sublayers { impl Sublayers { /// Constructor. - pub fn new(logger: impl AnyLogger) -> Self { + pub fn new(logger: impl AnyLogger, parents: &Rc>>) -> Self { let element_dirty_logger = Logger::new_sub(&logger, "dirty"); let model = default(); - let element_depth_order_dirty = dirty::SharedBool::new(element_dirty_logger, ()); + let dirty_on_mut = on_element_depth_order_dirty(parents); + let element_depth_order_dirty = dirty::SharedBool::new(element_dirty_logger, dirty_on_mut); Self { model, element_depth_order_dirty } } }