Merge pull request #6456 from penpot/alotor-perf-text-grow-2

 Reflow flex on grow text height
This commit is contained in:
Elena Torró 2025-05-12 14:16:29 +02:00 committed by GitHub
commit 33c260c35b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 13 deletions

View file

@ -217,11 +217,14 @@
;; When the horizontal/vertical scale a flex children with auto/fill ;; When the horizontal/vertical scale a flex children with auto/fill
;; we change it too fixed ;; we change it too fixed
set-fix-width? change-width?
(not (mth/close? (dm/get-prop scalev :x) 1)) (not (mth/close? (dm/get-prop scalev :x) 1))
set-fix-height? change-height?
(not (mth/close? (dm/get-prop scalev :y) 1))] (not (mth/close? (dm/get-prop scalev :y) 1))
auto-width-text? (and (cfh/text-shape? shape) (= :auto-width (dm/get-prop shape :grow-type)))
auto-height-text? (and (cfh/text-shape? shape) (= :auto-height (dm/get-prop shape :grow-type)))]
(cond-> (ctm/empty) (cond-> (ctm/empty)
(some? displacement) (some? displacement)
@ -230,12 +233,18 @@
:always :always
(ctm/resize scalev resize-origin shape-transform shape-transform-inverse) (ctm/resize scalev resize-origin shape-transform shape-transform-inverse)
^boolean set-fix-width? ^boolean change-width?
(ctm/change-property :layout-item-h-sizing :fix) (ctm/change-property :layout-item-h-sizing :fix)
^boolean set-fix-height? ^boolean change-height?
(ctm/change-property :layout-item-v-sizing :fix) (ctm/change-property :layout-item-v-sizing :fix)
(and auto-width-text? (or change-width? change-height?))
(ctm/change-property :grow-type :fixed)
(and auto-height-text? change-height?)
(ctm/change-property :grow-type :fixed)
^boolean scale-text ^boolean scale-text
(ctm/scale-content (dm/get-prop scalev :x))))) (ctm/scale-content (dm/get-prop scalev :x)))))

View file

@ -6,10 +6,10 @@ mod grid_layout;
use common::GetBounds; use common::GetBounds;
use crate::math::{identitish, Bounds, Matrix, Point}; use crate::math::{self as math, identitish, Bounds, Matrix, Point};
use crate::shapes::{ use crate::shapes::{
modified_children_ids, ConstraintH, ConstraintV, Frame, Group, Layout, Modifier, Shape, auto_height, modified_children_ids, set_paragraphs_width, ConstraintH, ConstraintV, Frame,
StructureEntry, TransformEntry, Type, Group, GrowType, Layout, Modifier, Shape, StructureEntry, TransformEntry, Type,
}; };
use crate::state::State; use crate::state::State;
use crate::uuid::Uuid; use crate::uuid::Uuid;
@ -106,6 +106,7 @@ fn calculate_group_bounds(
pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec<TransformEntry> { pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec<TransformEntry> {
let shapes = &state.shapes; let shapes = &state.shapes;
let font_col = state.render_state.fonts.font_collection();
let mut entries: VecDeque<_> = modifiers let mut entries: VecDeque<_> = modifiers
.iter() .iter()
.map(|entry| Modifier::Transform(entry.clone())) .map(|entry| Modifier::Transform(entry.clone()))
@ -137,7 +138,25 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
}; };
let shape_bounds_before = bounds.find(&shape); let shape_bounds_before = bounds.find(&shape);
let shape_bounds_after = shape_bounds_before.transform(&entry.transform); let mut shape_bounds_after = shape_bounds_before.transform(&entry.transform);
let mut transform = entry.transform;
if let Type::Text(content) = &shape.shape_type {
if content.grow_type() == GrowType::AutoHeight {
let mut paragraphs = content.get_skia_paragraphs(font_col);
set_paragraphs_width(shape_bounds_after.width(), &mut paragraphs);
let height = auto_height(&paragraphs);
let resize_transform = math::resize_matrix(
&shape_bounds_after,
&shape_bounds_after,
shape_bounds_after.width(),
height,
);
shape_bounds_after = shape_bounds_after.transform(&resize_transform);
transform.post_concat(&resize_transform);
}
}
if entry.propagate { if entry.propagate {
let mut children = propagate_children( let mut children = propagate_children(
@ -145,11 +164,10 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
shapes, shapes,
&shape_bounds_before, &shape_bounds_before,
&shape_bounds_after, &shape_bounds_after,
entry.transform, transform,
&bounds, &bounds,
&state.structure, &state.structure,
); );
entries.append(&mut children); entries.append(&mut children);
} }
@ -158,7 +176,7 @@ pub fn propagate_modifiers(state: &State, modifiers: Vec<TransformEntry>) -> Vec
let default_matrix = Matrix::default(); let default_matrix = Matrix::default();
let mut shape_modif = let mut shape_modif =
modifiers.get(&shape.id).unwrap_or(&default_matrix).clone(); modifiers.get(&shape.id).unwrap_or(&default_matrix).clone();
shape_modif.post_concat(&entry.transform); shape_modif.post_concat(&transform);
modifiers.insert(shape.id, shape_modif); modifiers.insert(shape.id, shape_modif);
if let Some(parent) = shape.parent_id.and_then(|id| shapes.get(&id)) { if let Some(parent) = shape.parent_id.and_then(|id| shapes.get(&id)) {

View file

@ -40,7 +40,11 @@ pub struct TextContent {
pub fn set_paragraphs_width(width: f32, paragraphs: &mut Vec<Vec<skia::textlayout::Paragraph>>) { pub fn set_paragraphs_width(width: f32, paragraphs: &mut Vec<Vec<skia::textlayout::Paragraph>>) {
for group in paragraphs { for group in paragraphs {
for paragraph in group { for paragraph in group {
paragraph.layout(width) // We first set max so we can get the min_intrinsic_width (this is the min word size)
// then after we set either the real with or the min.
// This is done this way so the words are not break into lines.
paragraph.layout(f32::MAX);
paragraph.layout(f32::max(width, paragraph.min_intrinsic_width().ceil()));
} }
} }
} }