diff --git a/render-wasm/src/main.rs b/render-wasm/src/main.rs index 756d23336e..8a9a5fab30 100644 --- a/render-wasm/src/main.rs +++ b/render-wasm/src/main.rs @@ -7,6 +7,7 @@ mod performance; mod render; mod shapes; mod state; +mod textlayout; mod tiles; mod utils; mod uuid; diff --git a/render-wasm/src/shapes/modifiers.rs b/render-wasm/src/shapes/modifiers.rs index 4c8e00682f..6f70d32975 100644 --- a/render-wasm/src/shapes/modifiers.rs +++ b/render-wasm/src/shapes/modifiers.rs @@ -1,20 +1,20 @@ use std::collections::{HashMap, HashSet, VecDeque}; -pub mod common; + mod constraints; mod flex_layout; + +pub mod common; pub mod grid_layout; +use crate::math::{self as math, bools, identitish, Bounds, Matrix, Point}; use common::GetBounds; -use crate::math::bools; -use crate::math::{self as math, identitish, Bounds, Matrix, Point}; - use crate::shapes::{ - auto_height, ConstraintH, ConstraintV, Frame, Group, GrowType, Layout, Modifier, Shape, - StructureEntry, TransformEntry, Type, + ConstraintH, ConstraintV, Frame, Group, GrowType, Layout, Modifier, Shape, StructureEntry, + TransformEntry, Type, }; -use crate::state::ShapesPool; -use crate::state::State; +use crate::state::{ShapesPool, State}; +use crate::textlayout::auto_height; use crate::uuid::Uuid; #[allow(clippy::too_many_arguments)] diff --git a/render-wasm/src/shapes/text.rs b/render-wasm/src/shapes/text.rs index 825a3c24e7..acbca475b3 100644 --- a/render-wasm/src/shapes/text.rs +++ b/render-wasm/src/shapes/text.rs @@ -13,6 +13,7 @@ use std::collections::HashSet; use super::FontFamily; use crate::shapes::{self, merge_fills, set_paint_fill, Stroke, StrokeKind}; +use crate::textlayout::{auto_height, auto_width}; use crate::utils::{get_fallback_fonts, get_font_collection, uuid_from_u32}; use crate::wasm::fills::parse_fills_from_bytes; use crate::Uuid; @@ -42,30 +43,6 @@ pub struct TextContent { pub grow_type: GrowType, } -pub fn build_paragraphs_with_width( - paragraphs: &mut [Vec], - width: f32, -) -> Vec> { - paragraphs - .iter_mut() - .map(|builders| { - builders - .iter_mut() - .map(|builder| { - let mut paragraph = builder.build(); - // For auto-width, always layout with infinite width first to get intrinsic width - paragraph.layout(f32::MAX); - let intrinsic_width = paragraph.max_intrinsic_width().ceil(); - // Use the larger of the requested width or intrinsic width to prevent line breaks - let final_width = f32::max(width, intrinsic_width); - paragraph.layout(final_width); - paragraph - }) - .collect() - }) - .collect() -} - impl TextContent { pub fn new(bounds: Rect, grow_type: GrowType) -> Self { Self { @@ -742,34 +719,6 @@ impl From<&Vec> for RawTextData { } } -pub fn get_built_paragraphs( - paragraphs: &mut [Vec], - width: f32, -) -> Vec> { - build_paragraphs_with_width(paragraphs, width) -} - -pub fn auto_width(paragraphs: &mut [Vec], width: f32) -> f32 { - let built_paragraphs = get_built_paragraphs(paragraphs, width); - - built_paragraphs - .iter() - .flatten() - .fold(0.0, |auto_width, p| { - f32::max(p.max_intrinsic_width(), auto_width) - }) -} - -pub fn auto_height(paragraphs: &mut [Vec], width: f32) -> f32 { - paragraphs.iter_mut().fold(0.0, |auto_height, p| { - p.iter_mut().fold(auto_height, |auto_height, paragraph| { - let mut paragraph = paragraph.build(); - paragraph.layout(width); - auto_height + paragraph.height() - }) - }) -} - fn get_text_stroke_paints_with_shadows( stroke: &Stroke, blur: Option<&ImageFilter>, diff --git a/render-wasm/src/textlayout.rs b/render-wasm/src/textlayout.rs new file mode 100644 index 0000000000..23ce4e6ebc --- /dev/null +++ b/render-wasm/src/textlayout.rs @@ -0,0 +1,53 @@ +use skia_safe::textlayout::ParagraphBuilder; + +pub fn auto_width(paragraphs: &mut [Vec], width: f32) -> f32 { + let built_paragraphs = get_built_paragraphs(paragraphs, width); + + built_paragraphs + .iter() + .flatten() + .fold(0.0, |auto_width, p| { + f32::max(p.max_intrinsic_width(), auto_width) + }) +} + +pub fn auto_height(paragraphs: &mut [Vec], width: f32) -> f32 { + paragraphs.iter_mut().fold(0.0, |auto_height, p| { + p.iter_mut().fold(auto_height, |auto_height, paragraph| { + let mut paragraph = paragraph.build(); + paragraph.layout(width); + auto_height + paragraph.height() + }) + }) +} + +pub fn build_paragraphs_with_width( + paragraphs: &mut [Vec], + width: f32, +) -> Vec> { + paragraphs + .iter_mut() + .map(|builders| { + builders + .iter_mut() + .map(|builder| { + let mut paragraph = builder.build(); + // For auto-width, always layout with infinite width first to get intrinsic width + paragraph.layout(f32::MAX); + let intrinsic_width = paragraph.max_intrinsic_width().ceil(); + // Use the larger of the requested width or intrinsic width to prevent line breaks + let final_width = f32::max(width, intrinsic_width); + paragraph.layout(final_width); + paragraph + }) + .collect() + }) + .collect() +} + +fn get_built_paragraphs( + paragraphs: &mut [Vec], + width: f32, +) -> Vec> { + build_paragraphs_with_width(paragraphs, width) +} diff --git a/render-wasm/src/wasm/text.rs b/render-wasm/src/wasm/text.rs index 28976c66ff..886449dd5d 100644 --- a/render-wasm/src/wasm/text.rs +++ b/render-wasm/src/wasm/text.rs @@ -1,8 +1,7 @@ use crate::mem; -use crate::shapes::{auto_height, build_paragraphs_with_width, GrowType, RawTextData, Type}; - -use crate::STATE; -use crate::{with_current_shape, with_current_shape_mut}; +use crate::shapes::{GrowType, RawTextData, Type}; +use crate::textlayout::{auto_height, build_paragraphs_with_width}; +use crate::{with_current_shape, with_current_shape_mut, STATE}; #[no_mangle] pub extern "C" fn clear_shape_text() {