🔧 Refactor ParagraphBuilder and fix auto height

This commit is contained in:
Elena Torro 2025-07-11 13:29:22 +02:00
parent 4c21468850
commit b40b1fa2e4
9 changed files with 161 additions and 166 deletions

View file

@ -460,37 +460,44 @@ impl RenderState {
}); });
let text_content = text_content.new_bounds(shape.selrect()); let text_content = text_content.new_bounds(shape.selrect());
let paragraphs = text_content.get_skia_paragraphs(self.fonts.font_collection()); let mut paragraphs = text_content.get_skia_paragraphs();
shadows::render_text_drop_shadows(self, &shape, &paragraphs, antialias); shadows::render_text_drop_shadows(self, &shape, &mut paragraphs, antialias);
text::render(self, &shape, &paragraphs, None); text::render(self, &shape, &mut paragraphs, None);
if shape.has_inner_strokes() { if shape.has_inner_strokes() {
// Inner strokes paints need the text fill to apply correctly their blend modes // Inner strokes paints need the text fill to apply correctly their blend modes
// (e.g., SrcATop, DstOver) // (e.g., SrcATop, DstOver)
text::render(self, &shape, &paragraphs, Some(SurfaceId::Strokes)); text::render(self, &shape, &mut paragraphs, Some(SurfaceId::Strokes));
} }
for stroke in shape.strokes().rev() { for stroke in shape.strokes().rev() {
let stroke_paragraphs = text_content.get_skia_stroke_paragraphs( let mut stroke_paragraphs =
stroke, text_content.get_skia_stroke_paragraphs(stroke, &shape.selrect());
&shape.selrect(), shadows::render_text_drop_shadows(
self.fonts.font_collection(), self,
&shape,
&mut stroke_paragraphs,
antialias,
); );
shadows::render_text_drop_shadows(self, &shape, &stroke_paragraphs, antialias);
strokes::render( strokes::render(
self, self,
&shape, &shape,
stroke, stroke,
None, None,
None, None,
Some(&stroke_paragraphs), Some(&mut stroke_paragraphs),
antialias,
);
shadows::render_text_inner_shadows(
self,
&shape,
&mut stroke_paragraphs,
antialias, antialias,
); );
shadows::render_text_inner_shadows(self, &shape, &stroke_paragraphs, antialias);
} }
shadows::render_text_inner_shadows(self, &shape, &paragraphs, antialias); shadows::render_text_inner_shadows(self, &shape, &mut paragraphs, antialias);
} }
_ => { _ => {
let surface_ids = SurfaceId::Strokes as u32 let surface_ids = SurfaceId::Strokes as u32

View file

@ -2,7 +2,8 @@ use super::{RenderState, SurfaceId};
use crate::render::strokes; use crate::render::strokes;
use crate::render::text::{self}; use crate::render::text::{self};
use crate::shapes::{Shadow, Shape, Stroke, Type}; use crate::shapes::{Shadow, Shape, Stroke, Type};
use skia_safe::{canvas::SaveLayerRec, textlayout::Paragraph, Paint, Path}; use skia_safe::textlayout::ParagraphBuilder;
use skia_safe::{canvas::SaveLayerRec, Paint, Path};
// Fill Shadows // Fill Shadows
pub fn render_fill_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) { pub fn render_fill_drop_shadows(render_state: &mut RenderState, shape: &Shape, antialias: bool) {
@ -88,7 +89,7 @@ pub fn render_stroke_inner_shadows(
pub fn render_text_drop_shadows( pub fn render_text_drop_shadows(
render_state: &mut RenderState, render_state: &mut RenderState,
shape: &Shape, shape: &Shape,
paragraphs: &[Vec<Paragraph>], paragraphs: &mut [ParagraphBuilder],
antialias: bool, antialias: bool,
) { ) {
for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) { for shadow in shape.drop_shadows().rev().filter(|s| !s.hidden()) {
@ -123,7 +124,7 @@ pub fn render_text_drop_shadow(
render_state: &mut RenderState, render_state: &mut RenderState,
shape: &Shape, shape: &Shape,
shadow: &Shadow, shadow: &Shadow,
paragraphs: &[Vec<Paragraph>], paragraphs: &mut [ParagraphBuilder],
antialias: bool, antialias: bool,
) { ) {
let paint = shadow.get_drop_shadow_paint(antialias); let paint = shadow.get_drop_shadow_paint(antialias);
@ -145,7 +146,7 @@ pub fn render_text_drop_shadow(
pub fn render_text_inner_shadows( pub fn render_text_inner_shadows(
render_state: &mut RenderState, render_state: &mut RenderState,
shape: &Shape, shape: &Shape,
paragraphs: &[Vec<Paragraph>], paragraphs: &mut [ParagraphBuilder],
antialias: bool, antialias: bool,
) { ) {
for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) { for shadow in shape.inner_shadows().rev().filter(|s| !s.hidden()) {
@ -157,7 +158,7 @@ pub fn render_text_inner_shadow(
render_state: &mut RenderState, render_state: &mut RenderState,
shape: &Shape, shape: &Shape,
shadow: &Shadow, shadow: &Shadow,
paragraphs: &[Vec<Paragraph>], paragraphs: &mut [ParagraphBuilder],
antialias: bool, antialias: bool,
) { ) {
let paint = shadow.get_inner_shadow_paint(antialias); let paint = shadow.get_inner_shadow_paint(antialias);

View file

@ -3,7 +3,7 @@ use std::collections::HashMap;
use crate::math::{Matrix, Point, Rect}; use crate::math::{Matrix, Point, Rect};
use crate::shapes::{Corners, Fill, ImageFill, Path, Shape, Stroke, StrokeCap, StrokeKind, Type}; use crate::shapes::{Corners, Fill, ImageFill, Path, Shape, Stroke, StrokeCap, StrokeKind, Type};
use skia_safe::{self as skia, textlayout::Paragraph, ImageFilter, RRect}; use skia_safe::{self as skia, textlayout::ParagraphBuilder, ImageFilter, RRect};
use super::{RenderState, SurfaceId}; use super::{RenderState, SurfaceId};
use crate::render::text::{self}; use crate::render::text::{self};
@ -485,7 +485,7 @@ pub fn render(
stroke: &Stroke, stroke: &Stroke,
surface_id: Option<SurfaceId>, surface_id: Option<SurfaceId>,
shadow: Option<&ImageFilter>, shadow: Option<&ImageFilter>,
paragraphs: Option<&[Vec<Paragraph>]>, paragraphs: Option<&mut [ParagraphBuilder]>,
antialias: bool, antialias: bool,
) { ) {
let scale = render_state.get_scale(); let scale = render_state.get_scale();

View file

@ -1,11 +1,11 @@
use super::{RenderState, Shape, SurfaceId}; use super::{RenderState, Shape, SurfaceId};
use crate::shapes::VerticalAlign; use crate::shapes::VerticalAlign;
use skia_safe::{textlayout::Paragraph, FontMetrics, Paint, Path}; use skia_safe::{textlayout::ParagraphBuilder, FontMetrics, Paint, Path};
pub fn render( pub fn render(
render_state: &mut RenderState, render_state: &mut RenderState,
shape: &Shape, shape: &Shape,
paragraphs: &[Vec<Paragraph>], paragraphs: &mut [ParagraphBuilder],
surface_id: Option<SurfaceId>, surface_id: Option<SurfaceId>,
) { ) {
let canvas = render_state let canvas = render_state
@ -14,78 +14,70 @@ pub fn render(
let container_height = shape.selrect().height(); let container_height = shape.selrect().height();
for group in paragraphs { for builder in paragraphs {
let total_paragraphs_height: f32 = group.iter().map(|p| p.height()).sum(); let mut skia_paragraph = builder.build();
skia_paragraph.layout(shape.bounds().width());
let paragraph_height: f32 = skia_paragraph.height();
let mut offset_y = match shape.vertical_align() { let offset_y = match shape.vertical_align() {
VerticalAlign::Center => (container_height - total_paragraphs_height) / 2.0, VerticalAlign::Center => (container_height - paragraph_height) / 2.0,
VerticalAlign::Bottom => container_height - total_paragraphs_height, VerticalAlign::Bottom => container_height - paragraph_height,
_ => 0.0, _ => 0.0,
}; };
let mut offset_lines_y = offset_y; let xy = (shape.selrect().x(), shape.selrect().y() + offset_y);
skia_paragraph.paint(canvas, xy);
for skia_paragraph in group { for line_metrics in skia_paragraph.get_line_metrics().iter() {
let xy = (shape.selrect().x(), shape.selrect().y() + offset_y); let style_metrics: Vec<_> = line_metrics
skia_paragraph.paint(canvas, xy); .get_style_metrics(line_metrics.start_index..line_metrics.end_index)
offset_y += skia_paragraph.height(); .into_iter()
} .collect();
for skia_paragraph in group { let mut current_x_offset = 0.0;
let xy = (shape.selrect().x(), shape.selrect().y() + offset_lines_y); let total_line_width = line_metrics.width as f32;
let total_chars = line_metrics.end_index - line_metrics.start_index;
for line_metrics in skia_paragraph.get_line_metrics().iter() { for (i, (index, style_metric)) in style_metrics.iter().enumerate() {
let style_metrics: Vec<_> = line_metrics let text_style = style_metric.text_style;
.get_style_metrics(line_metrics.start_index..line_metrics.end_index) let font_metrics = style_metric.font_metrics;
.into_iter() let next_index = style_metrics
.collect(); .get(i + 1)
.map(|(next_i, _)| *next_i)
.unwrap_or(line_metrics.end_index);
let char_count = next_index - index;
let segment_width = if total_chars > 0 {
(char_count as f32 / total_chars as f32) * total_line_width
} else {
char_count as f32 * font_metrics.avg_char_width
};
let mut current_x_offset = 0.0; if text_style.decoration().ty
let total_line_width = line_metrics.width as f32; != skia_safe::textlayout::TextDecoration::NO_DECORATION
let total_chars = line_metrics.end_index - line_metrics.start_index; {
let decoration_type = text_style.decoration().ty;
let text_left = xy.0 + current_x_offset;
let text_top = xy.1 + line_metrics.baseline as f32 - line_metrics.ascent as f32;
let text_width = segment_width;
let line_height = line_metrics.height as f32;
for (i, (index, style_metric)) in style_metrics.iter().enumerate() { let r = calculate_text_decoration_rect(
let text_style = style_metric.text_style; decoration_type,
let font_metrics = style_metric.font_metrics; font_metrics,
let next_index = style_metrics text_left,
.get(i + 1) text_top,
.map(|(next_i, _)| *next_i) text_width,
.unwrap_or(line_metrics.end_index); line_height,
let char_count = next_index - index; );
let segment_width = if total_chars > 0 {
(char_count as f32 / total_chars as f32) * total_line_width
} else {
char_count as f32 * font_metrics.avg_char_width
};
if text_style.decoration().ty if let Some(decoration_rect) = r {
!= skia_safe::textlayout::TextDecoration::NO_DECORATION let decoration_paint = text_style.foreground();
{ canvas.draw_rect(decoration_rect, &decoration_paint);
let decoration_type = text_style.decoration().ty;
let text_left = xy.0 + current_x_offset;
let text_top =
xy.1 + line_metrics.baseline as f32 - line_metrics.ascent as f32;
let text_width = segment_width;
let line_height = line_metrics.height as f32;
let r = calculate_text_decoration_rect(
decoration_type,
font_metrics,
text_left,
text_top,
text_width,
line_height,
);
if let Some(decoration_rect) = r {
let decoration_paint = text_style.foreground().clone();
canvas.draw_rect(decoration_rect, &decoration_paint);
}
} }
current_x_offset += segment_width;
} }
current_x_offset += segment_width;
} }
offset_lines_y += skia_paragraph.height();
} }
} }
} }

View file

@ -164,8 +164,6 @@ fn propagate_transform(
}; };
let shapes = &state.shapes; let shapes = &state.shapes;
let font_col = state.render_state.fonts.font_collection();
let shape_bounds_before = bounds.find(shape); let shape_bounds_before = bounds.find(shape);
let mut shape_bounds_after = shape_bounds_before.transform(&entry.transform); let mut shape_bounds_after = shape_bounds_before.transform(&entry.transform);
@ -173,9 +171,9 @@ fn propagate_transform(
if let Type::Text(content) = &shape.shape_type { if let Type::Text(content) = &shape.shape_type {
if content.grow_type() == GrowType::AutoHeight { if content.grow_type() == GrowType::AutoHeight {
let mut paragraphs = content.get_skia_paragraphs(font_col); let mut paragraphs = content.get_skia_paragraphs();
set_paragraphs_width(shape_bounds_after.width(), &mut paragraphs); set_paragraphs_width(shape_bounds_after.width(), &mut paragraphs);
let height = auto_height(&paragraphs); let height = auto_height(&mut paragraphs, shape_bounds_after.width());
let resize_transform = math::resize_matrix( let resize_transform = math::resize_matrix(
&shape_bounds_after, &shape_bounds_after,
&shape_bounds_after, &shape_bounds_after,

View file

@ -5,13 +5,13 @@ use crate::{
use skia_safe::{ use skia_safe::{
self as skia, self as skia,
paint::Paint, paint::Paint,
textlayout::{FontCollection, ParagraphBuilder, ParagraphStyle}, textlayout::{ParagraphBuilder, ParagraphStyle},
}; };
use std::collections::HashSet; use std::collections::HashSet;
use super::FontFamily; use super::FontFamily;
use crate::shapes::{self, merge_fills, set_paint_fill, Stroke, StrokeKind}; use crate::shapes::{self, merge_fills, set_paint_fill, Stroke, StrokeKind};
use crate::utils::{get_fallback_fonts, uuid_from_u32}; use crate::utils::{get_fallback_fonts, get_font_collection, uuid_from_u32};
use crate::wasm::fills::parse_fills_from_bytes; use crate::wasm::fills::parse_fills_from_bytes;
use crate::Uuid; use crate::Uuid;
@ -40,15 +40,14 @@ pub struct TextContent {
pub grow_type: GrowType, pub grow_type: GrowType,
} }
pub fn set_paragraphs_width(width: f32, paragraphs: &mut Vec<Vec<skia::textlayout::Paragraph>>) { pub fn set_paragraphs_width(width: f32, paragraphs: &mut [ParagraphBuilder]) {
for group in paragraphs { for p in paragraphs {
for paragraph in group { // We first set max so we can get the min_intrinsic_width (this is the min word size)
// 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.
// then after we set either the real with or the min. // This is done this way so the words are not break into lines.
// This is done this way so the words are not break into lines. let mut paragraph = p.build();
paragraph.layout(f32::MAX); paragraph.layout(f32::MAX);
paragraph.layout(f32::max(width, paragraph.min_intrinsic_width().ceil())); paragraph.layout(f32::max(width, paragraph.min_intrinsic_width().ceil()));
}
} }
} }
@ -94,67 +93,61 @@ impl TextContent {
self.paragraphs.push(paragraph); self.paragraphs.push(paragraph);
} }
pub fn to_paragraphs(&self, fonts: &FontCollection) -> Vec<Vec<skia::textlayout::Paragraph>> { pub fn to_paragraphs(&self) -> Vec<ParagraphBuilder> {
let fonts = get_font_collection();
let fallback_fonts = get_fallback_fonts(); let fallback_fonts = get_fallback_fonts();
let mut paragraph_group = Vec::new(); self.paragraphs
let paragraphs = self
.paragraphs
.iter() .iter()
.map(|p| { .map(|p| {
let paragraph_style = p.paragraph_to_style(); let paragraph_style = p.paragraph_to_style();
let mut builder = ParagraphBuilder::new(&paragraph_style, fonts); let mut builder = ParagraphBuilder::new(&paragraph_style, fonts);
for leaf in &p.children { for leaf in &p.children {
let text_style = leaf.to_style(p, &self.bounds, fallback_fonts); // FIXME let text_style = leaf.to_style(p, &self.bounds, fallback_fonts);
let text = leaf.apply_text_transform(); let text = leaf.apply_text_transform();
builder.push_style(&text_style); builder.push_style(&text_style);
builder.add_text(&text); builder.add_text(&text);
builder.pop(); builder.pop();
} }
builder.build() builder
}) })
.collect(); .collect()
paragraph_group.push(paragraphs);
paragraph_group
} }
pub fn to_stroke_paragraphs( pub fn to_stroke_paragraphs(&self, stroke: &Stroke, bounds: &Rect) -> Vec<ParagraphBuilder> {
&self,
stroke: &Stroke,
bounds: &Rect,
fonts: &FontCollection,
) -> Vec<Vec<skia::textlayout::Paragraph>> {
let fallback_fonts = get_fallback_fonts(); let fallback_fonts = get_fallback_fonts();
let mut paragraph_group = Vec::new();
let stroke_paints = get_text_stroke_paints(stroke, bounds); let stroke_paints = get_text_stroke_paints(stroke, bounds);
let fonts = get_font_collection();
for stroke_paint in stroke_paints { stroke_paints
let mut stroke_paragraphs = Vec::new(); .into_iter()
for paragraph in &self.paragraphs { .flat_map(|stroke_paint| {
let paragraph_style = paragraph.paragraph_to_style(); self.paragraphs
let mut builder = ParagraphBuilder::new(&paragraph_style, fonts); .iter()
for leaf in &paragraph.children { .map(|paragraph| {
let stroke_style = let paragraph_style = paragraph.paragraph_to_style();
leaf.to_stroke_style(paragraph, &stroke_paint, fallback_fonts); let mut builder = ParagraphBuilder::new(&paragraph_style, fonts);
let text: String = leaf.apply_text_transform(); for leaf in &paragraph.children {
builder.push_style(&stroke_style); let stroke_style =
builder.add_text(&text); leaf.to_stroke_style(paragraph, &stroke_paint, fallback_fonts);
builder.pop(); let text: String = leaf.apply_text_transform();
} builder.push_style(&stroke_style);
let p = builder.build(); builder.add_text(&text);
stroke_paragraphs.push(p); builder.pop();
} }
paragraph_group.push(stroke_paragraphs); builder
} })
paragraph_group .collect::<Vec<_>>()
})
.collect()
} }
pub fn collect_paragraphs( pub fn collect_paragraphs(
&self, &self,
mut paragraphs: Vec<Vec<skia::textlayout::Paragraph>>, mut paragraphs: Vec<ParagraphBuilder>,
) -> Vec<Vec<skia::textlayout::Paragraph>> { ) -> Vec<ParagraphBuilder> {
if self.grow_type() == GrowType::AutoWidth { if self.grow_type() == GrowType::AutoWidth {
set_paragraphs_width(f32::MAX, &mut paragraphs); set_paragraphs_width(f32::MAX, &mut paragraphs);
let max_width = auto_width(&paragraphs).ceil(); let max_width = auto_width(&mut paragraphs).ceil();
set_paragraphs_width(max_width, &mut paragraphs); set_paragraphs_width(max_width, &mut paragraphs);
} else { } else {
set_paragraphs_width(self.width(), &mut paragraphs); set_paragraphs_width(self.width(), &mut paragraphs);
@ -162,20 +155,16 @@ impl TextContent {
paragraphs paragraphs
} }
pub fn get_skia_paragraphs( pub fn get_skia_paragraphs(&self) -> Vec<ParagraphBuilder> {
&self, self.collect_paragraphs(self.to_paragraphs())
fonts: &FontCollection,
) -> Vec<Vec<skia::textlayout::Paragraph>> {
self.collect_paragraphs(self.to_paragraphs(fonts))
} }
pub fn get_skia_stroke_paragraphs( pub fn get_skia_stroke_paragraphs(
&self, &self,
stroke: &Stroke, stroke: &Stroke,
bounds: &Rect, bounds: &Rect,
fonts: &FontCollection, ) -> Vec<ParagraphBuilder> {
) -> Vec<Vec<skia::textlayout::Paragraph>> { self.collect_paragraphs(self.to_stroke_paragraphs(stroke, bounds))
self.collect_paragraphs(self.to_stroke_paragraphs(stroke, bounds, fonts))
} }
pub fn grow_type(&self) -> GrowType { pub fn grow_type(&self) -> GrowType {
@ -627,24 +616,28 @@ impl From<&Vec<u8>> for RawTextData {
} }
} }
pub fn auto_width(paragraphs: &[Vec<skia::textlayout::Paragraph>]) -> f32 { pub fn auto_width(paragraphs: &mut [ParagraphBuilder]) -> f32 {
paragraphs.iter().flatten().fold(0.0, |auto_width, p| { paragraphs.iter_mut().fold(0.0, |auto_width, p| {
f32::max(p.max_intrinsic_width(), auto_width) let mut paragraph = p.build();
paragraph.layout(f32::MAX);
f32::max(paragraph.max_intrinsic_width(), auto_width)
}) })
} }
pub fn max_width(paragraphs: &[Vec<skia::textlayout::Paragraph>]) -> f32 { pub fn max_width(paragraphs: &mut [ParagraphBuilder]) -> f32 {
paragraphs paragraphs.iter_mut().fold(0.0, |max_width, p| {
.iter() let mut paragraph = p.build();
.flatten() paragraph.layout(f32::MAX);
.fold(0.0, |max_width, p| f32::max(p.max_width(), max_width)) f32::max(paragraph.max_width(), max_width)
})
} }
pub fn auto_height(paragraphs: &[Vec<skia::textlayout::Paragraph>]) -> f32 { pub fn auto_height(paragraphs: &mut [ParagraphBuilder], width: f32) -> f32 {
paragraphs paragraphs.iter_mut().fold(0.0, |auto_height, p| {
.iter() let mut paragraph = p.build();
.flatten() paragraph.layout(width);
.fold(0.0, |auto_height, p| auto_height + p.height()) auto_height + paragraph.height()
})
} }
fn get_text_stroke_paints(stroke: &Stroke, bounds: &Rect) -> Vec<Paint> { fn get_text_stroke_paints(stroke: &Stroke, bounds: &Rect) -> Vec<Paint> {

View file

@ -1,4 +1,4 @@
use skia_safe::{self as skia, Path, Point}; use skia_safe::{self as skia, textlayout::FontCollection, Path, Point};
use std::collections::HashMap; use std::collections::HashMap;
mod shapes_pool; mod shapes_pool;
@ -167,6 +167,10 @@ impl State {
.rebuild_modifier_tiles(&self.shapes, &self.modifiers); .rebuild_modifier_tiles(&self.shapes, &self.modifiers);
} }
pub fn font_collection(&self) -> &FontCollection {
self.render_state.fonts().font_collection()
}
pub fn get_grid_coords(&self, pos_x: f32, pos_y: f32) -> Option<(i32, i32)> { pub fn get_grid_coords(&self, pos_x: f32, pos_y: f32) -> Option<(i32, i32)> {
let shape = self.current_shape()?; let shape = self.current_shape()?;
let bounds = shape.bounds(); let bounds = shape.bounds();

View file

@ -1,3 +1,4 @@
use crate::skia::textlayout::FontCollection;
use crate::skia::Image; use crate::skia::Image;
use crate::uuid::Uuid; use crate::uuid::Uuid;
use crate::with_state_mut; use crate::with_state_mut;
@ -31,3 +32,7 @@ pub fn get_image(image_id: &Uuid) -> Option<&Image> {
pub fn get_fallback_fonts() -> &'static HashSet<String> { pub fn get_fallback_fonts() -> &'static HashSet<String> {
with_state_mut!(state, { state.render_state().fonts().get_fallback() }) with_state_mut!(state, { state.render_state().fonts().get_fallback() })
} }
pub fn get_font_collection() -> &'static FontCollection {
with_state_mut!(state, { state.font_collection() })
}

View file

@ -2,7 +2,7 @@ use crate::mem;
use crate::shapes::{auto_height, auto_width, max_width, GrowType, RawTextData, Type}; use crate::shapes::{auto_height, auto_width, max_width, GrowType, RawTextData, Type};
use crate::STATE; use crate::STATE;
use crate::{with_current_shape, with_current_shape_mut, with_state_mut}; use crate::{with_current_shape, with_current_shape_mut};
#[no_mangle] #[no_mangle]
pub extern "C" fn clear_shape_text() { pub extern "C" fn clear_shape_text() {
@ -35,11 +35,6 @@ pub extern "C" fn set_shape_grow_type(grow_type: u8) {
#[no_mangle] #[no_mangle]
pub extern "C" fn get_text_dimensions() -> *mut u8 { pub extern "C" fn get_text_dimensions() -> *mut u8 {
let font_col;
with_state_mut!(state, {
font_col = state.render_state.fonts.font_collection();
});
let mut width = 0.01; let mut width = 0.01;
let mut height = 0.01; let mut height = 0.01;
let mut m_width = 0.01; let mut m_width = 0.01;
@ -49,16 +44,16 @@ pub extern "C" fn get_text_dimensions() -> *mut u8 {
height = shape.selrect.height(); height = shape.selrect.height();
if let Type::Text(content) = &shape.shape_type { if let Type::Text(content) = &shape.shape_type {
let paragraphs = content.get_skia_paragraphs(font_col); let mut paragraphs = content.get_skia_paragraphs();
m_width = max_width(&paragraphs); m_width = max_width(&mut paragraphs);
match content.grow_type() { match content.grow_type() {
GrowType::AutoHeight => { GrowType::AutoHeight => {
height = auto_height(&paragraphs).ceil(); height = auto_height(&mut paragraphs, width).ceil();
} }
GrowType::AutoWidth => { GrowType::AutoWidth => {
width = auto_width(&paragraphs).ceil(); width = auto_width(&mut paragraphs).ceil();
height = auto_height(&paragraphs).ceil(); height = auto_height(&mut paragraphs, width).ceil();
} }
GrowType::Fixed => {} GrowType::Fixed => {}
} }