🐛 Fix default font size in text spans

This commit is contained in:
Elena Torro
2025-10-29 12:29:08 +01:00
parent 2cdc76f1af
commit 9dfb0ebe84
6 changed files with 84 additions and 74 deletions

View File

@@ -699,17 +699,17 @@
(if (< index total) (if (< index total)
(let [paragraph (nth paragraphs index) (let [paragraph (nth paragraphs index)
leaves (get paragraph :children)] spans (get paragraph :children)]
(if (empty? (seq leaves)) (if (empty? (seq spans))
(recur (inc index) (recur (inc index)
emoji? emoji?
langs) langs)
(let [text (apply str (map :text leaves)) (let [text (apply str (map :text spans))
emoji? (if emoji? emoji? (t/contains-emoji? text)) emoji? (if emoji? emoji? (t/contains-emoji? text))
langs (t/collect-used-languages langs text)] langs (t/collect-used-languages langs text)]
(t/write-shape-text leaves paragraph text) (t/write-shape-text spans paragraph text)
(recur (inc index) (recur (inc index)
emoji? emoji?
langs)))) langs))))

View File

@@ -16,7 +16,7 @@
[app.render-wasm.wasm :as wasm])) [app.render-wasm.wasm :as wasm]))
(def ^:const PARAGRAPH-ATTR-U8-SIZE 44) (def ^:const PARAGRAPH-ATTR-U8-SIZE 44)
(def ^:const SPAN-ATTR-U8-SIZE 60) (def ^:const SPAN-ATTR-U8-SIZE 64)
(def ^:const MAX-TEXT-FILLS types.fills.impl/MAX-FILLS) (def ^:const MAX-TEXT-FILLS types.fills.impl/MAX-FILLS)
(defn- encode-text (defn- encode-text
@@ -74,68 +74,73 @@
(mem/write-uuid dview (d/nilv typography-ref-id uuid/zero)) (mem/write-uuid dview (d/nilv typography-ref-id uuid/zero))
(mem/assert-written offset PARAGRAPH-ATTR-U8-SIZE)))) (mem/assert-written offset PARAGRAPH-ATTR-U8-SIZE))))
(defn- write-leaves (defn- write-spans
[offset dview leaves paragraph] [offset dview spans paragraph]
(reduce (fn [offset span] (let [paragraph-font-size (get paragraph :font-size)
(let [font-style (sr/translate-font-style (get span :font-style)) paragraph-font-weight (get paragraph :font-weight)
font-size (get span :font-size) paragraph-line-height (get paragraph :line-height)]
letter-spacing (get span :letter-spacing) (reduce (fn [offset span]
font-weight (get span :font-weight) (let [font-style (sr/translate-font-style (get span :font-style))
font-id (f/normalize-font-id (get span :font-id)) font-size (get span :font-size paragraph-font-size)
font-family (hash (get span :font-family)) line-height (get span :line-height paragraph-line-height)
letter-spacing (get span :letter-spacing)
font-weight (get span :font-weight paragraph-font-weight)
font-id (f/normalize-font-id (get span :font-id))
font-family (hash (get span :font-family))
text-buffer (encode-text (get span :text)) text-buffer (encode-text (get span :text))
text-length (mem/size text-buffer) text-length (mem/size text-buffer)
fills (take MAX-TEXT-FILLS (get span :fills)) fills (take MAX-TEXT-FILLS (get span :fills))
font-variant-id
(get span :font-variant-id)
font-variant-id
(if (uuid? font-variant-id)
font-variant-id font-variant-id
uuid/zero) (get span :font-variant-id)
text-decoration font-variant-id
(or (sr/translate-text-decoration (:text-decoration span)) (if (uuid? font-variant-id)
(sr/translate-text-decoration (:text-decoration paragraph)) font-variant-id
(sr/translate-text-decoration "none")) uuid/zero)
text-transform text-decoration
(or (sr/translate-text-transform (:text-transform span)) (or (sr/translate-text-decoration (:text-decoration span))
(sr/translate-text-transform (:text-transform paragraph)) (sr/translate-text-decoration (:text-decoration paragraph))
(sr/translate-text-transform "none")) (sr/translate-text-decoration "none"))
text-direction text-transform
(or (sr/translate-text-direction (:text-direction span)) (or (sr/translate-text-transform (:text-transform span))
(sr/translate-text-direction (:text-direction paragraph)) (sr/translate-text-transform (:text-transform paragraph))
(sr/translate-text-direction "ltr"))] (sr/translate-text-transform "none"))
(-> offset text-direction
(mem/write-u8 dview font-style) (or (sr/translate-text-direction (:text-direction span))
(mem/write-u8 dview text-decoration) (sr/translate-text-direction (:text-direction paragraph))
(mem/write-u8 dview text-transform) (sr/translate-text-direction "ltr"))]
(mem/write-u8 dview text-direction)
(mem/write-f32 dview font-size) (-> offset
(mem/write-f32 dview letter-spacing) (mem/write-u8 dview font-style)
(mem/write-u32 dview font-weight) (mem/write-u8 dview text-decoration)
(mem/write-u8 dview text-transform)
(mem/write-u8 dview text-direction)
(mem/write-uuid dview font-id) (mem/write-f32 dview font-size)
(mem/write-i32 dview font-family) (mem/write-f32 dview line-height)
(mem/write-uuid dview (d/nilv font-variant-id uuid/zero)) (mem/write-f32 dview letter-spacing)
(mem/write-u32 dview font-weight)
(mem/write-i32 dview text-length) (mem/write-uuid dview font-id)
(mem/write-i32 dview (count fills)) (mem/write-i32 dview font-family)
(mem/assert-written offset SPAN-ATTR-U8-SIZE) (mem/write-uuid dview (d/nilv font-variant-id uuid/zero))
(write-span-fills dview fills)))) (mem/write-i32 dview text-length)
offset (mem/write-i32 dview (count fills))
leaves)) (mem/assert-written offset SPAN-ATTR-U8-SIZE)
(write-span-fills dview fills))))
offset
spans)))
(defn write-shape-text (defn write-shape-text
;; buffer has the following format: ;; buffer has the following format:
;; [<num-leaves> <paragraph_attributes> <leaves_attributes> <text>] ;; [<num-spans> <paragraph_attributes> <spans_attributes> <text>]
[spans paragraph text] [spans paragraph text]
(let [num-spans (count spans) (let [num-spans (count spans)
fills-size (* types.fills.impl/FILL-U8-SIZE MAX-TEXT-FILLS) fills-size (* types.fills.impl/FILL-U8-SIZE MAX-TEXT-FILLS)
@@ -153,7 +158,7 @@
(-> offset (-> offset
(mem/write-u32 dview num-spans) (mem/write-u32 dview num-spans)
(write-paragraph dview paragraph) (write-paragraph dview paragraph)
(write-leaves dview spans paragraph) (write-spans dview spans paragraph)
(mem/write-buffer heapu8 text-buffer)) (mem/write-buffer heapu8 text-buffer))
(h/call wasm/internal-module "_set_shape_text_content"))) (h/call wasm/internal-module "_set_shape_text_content")))

View File

@@ -221,21 +221,16 @@ fn draw_text(
for paragraph_builder_group in paragraph_builder_groups { for paragraph_builder_group in paragraph_builder_groups {
let mut group_offset_y = global_offset_y; let mut group_offset_y = global_offset_y;
let total_paragraphs = paragraph_builder_group.len(); let group_len = paragraph_builder_group.len();
for (paragraph_index, paragraph_builder) in paragraph_builder_group.iter_mut().enumerate() { for (paragraph_index, paragraph_builder) in paragraph_builder_group.iter_mut().enumerate() {
let mut paragraph = paragraph_builder.build(); let mut paragraph = paragraph_builder.build();
paragraph.layout(text_width); paragraph.layout(text_width);
let _paragraph_height = paragraph.height();
// FIXME: I've kept the _paragraph_height variable to have
// a reminder in the future to keep digging why the ideographic_baseline
// works so well and not the paragraph_height. I think we should test
// this more.
let xy = (shape.selrect().x(), shape.selrect().y() + group_offset_y); let xy = (shape.selrect().x(), shape.selrect().y() + group_offset_y);
paragraph.paint(canvas, xy); paragraph.paint(canvas, xy);
if paragraph_index == total_paragraphs - 1 { if paragraph_index == group_len - 1 {
group_offset_y += paragraph.ideographic_baseline(); group_offset_y += paragraph.height();
} }
for line_metrics in paragraph.get_line_metrics().iter() { for line_metrics in paragraph.get_line_metrics().iter() {

View File

@@ -630,6 +630,7 @@ pub struct TextSpan {
text: String, text: String,
font_family: FontFamily, font_family: FontFamily,
font_size: f32, font_size: f32,
line_height: f32,
letter_spacing: f32, letter_spacing: f32,
font_weight: i32, font_weight: i32,
font_variant_id: Uuid, font_variant_id: Uuid,
@@ -645,6 +646,7 @@ impl TextSpan {
text: String, text: String,
font_family: FontFamily, font_family: FontFamily,
font_size: f32, font_size: f32,
line_height: f32,
letter_spacing: f32, letter_spacing: f32,
text_decoration: Option<TextDecoration>, text_decoration: Option<TextDecoration>,
text_transform: Option<TextTransform>, text_transform: Option<TextTransform>,
@@ -657,6 +659,7 @@ impl TextSpan {
text, text,
font_family, font_family,
font_size, font_size,
line_height,
letter_spacing, letter_spacing,
text_decoration, text_decoration,
text_transform, text_transform,
@@ -680,10 +683,9 @@ impl TextSpan {
content_bounds: &Rect, content_bounds: &Rect,
fallback_fonts: &HashSet<String>, fallback_fonts: &HashSet<String>,
remove_alpha: bool, remove_alpha: bool,
paragraph_line_height: f32, // Add this parameter paragraph_line_height: f32,
) -> skia::textlayout::TextStyle { ) -> skia::textlayout::TextStyle {
let mut style = skia::textlayout::TextStyle::default(); let mut style = skia::textlayout::TextStyle::default();
let mut paint = paint::Paint::default(); let mut paint = paint::Paint::default();
if remove_alpha { if remove_alpha {
@@ -693,9 +695,14 @@ impl TextSpan {
paint = merge_fills(&self.fills, *content_bounds); paint = merge_fills(&self.fills, *content_bounds);
} }
style.set_height(paragraph_line_height); // FIXME
style.set_height_override(true); if self.line_height <= 0.0 {
style.set_height(paragraph_line_height);
} else {
style.set_height(self.line_height);
}
style.set_height_override(true);
style.set_foreground_paint(&paint); style.set_foreground_paint(&paint);
style.set_decoration_type(match self.text_decoration { style.set_decoration_type(match self.text_decoration {
Some(text_decoration) => text_decoration, Some(text_decoration) => text_decoration,

View File

@@ -75,6 +75,7 @@ pub extern "C" fn set_shape_fills() {
// Skip the first 4 bytes (header with fill count) and parse only the actual fills // Skip the first 4 bytes (header with fill count) and parse only the actual fills
let fills = parse_fills_from_bytes(&bytes[4..], num_fills); let fills = parse_fills_from_bytes(&bytes[4..], num_fills);
shape.set_fills(fills); shape.set_fills(fills);
mem::free_bytes();
}); });
} }

View File

@@ -130,6 +130,7 @@ pub struct RawTextSpan {
text_transform: RawTextTransform, text_transform: RawTextTransform,
text_direction: RawTextDirection, text_direction: RawTextDirection,
font_size: f32, font_size: f32,
line_height: f32,
letter_spacing: f32, letter_spacing: f32,
font_weight: i32, font_weight: i32,
font_id: [u32; 4], font_id: [u32; 4],
@@ -178,6 +179,7 @@ impl From<RawTextSpan> for shapes::TextSpan {
text, text,
font_family, font_family,
value.font_size, value.font_size,
value.line_height,
value.letter_spacing, value.letter_spacing,
value.text_decoration.into(), value.text_decoration.into(),
value.text_transform.into(), value.text_transform.into(),
@@ -193,7 +195,7 @@ impl From<RawTextSpan> for shapes::TextSpan {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct RawParagraph { pub struct RawParagraph {
attrs: RawParagraphData, attrs: RawParagraphData,
leaves: Vec<RawTextSpan>, spans: Vec<RawTextSpan>,
text_buffer: Vec<u8>, text_buffer: Vec<u8>,
} }
@@ -204,19 +206,19 @@ impl TryFrom<&Vec<u8>> for RawParagraph {
fn try_from(bytes: &Vec<u8>) -> Result<Self, Self::Error> { fn try_from(bytes: &Vec<u8>) -> Result<Self, Self::Error> {
let attrs = RawParagraphData::try_from(&bytes[..RAW_PARAGRAPH_DATA_SIZE])?; let attrs = RawParagraphData::try_from(&bytes[..RAW_PARAGRAPH_DATA_SIZE])?;
let mut offset = RAW_PARAGRAPH_DATA_SIZE; let mut offset = RAW_PARAGRAPH_DATA_SIZE;
let mut raw_text_leaves: Vec<RawTextSpan> = Vec::new(); let mut raw_text_spans: Vec<RawTextSpan> = Vec::new();
for _ in 0..attrs.span_count { for _ in 0..attrs.span_count {
let text_span = RawTextSpan::try_from(&bytes[offset..(offset + RAW_SPAN_DATA_SIZE)])?; let text_span = RawTextSpan::try_from(&bytes[offset..(offset + RAW_SPAN_DATA_SIZE)])?;
offset += RAW_SPAN_DATA_SIZE; offset += RAW_SPAN_DATA_SIZE;
raw_text_leaves.push(text_span); raw_text_spans.push(text_span);
} }
let text_buffer = &bytes[offset..]; let text_buffer = &bytes[offset..];
Ok(Self { Ok(Self {
attrs, attrs,
leaves: raw_text_leaves, spans: raw_text_spans,
text_buffer: text_buffer.to_vec(), text_buffer: text_buffer.to_vec(),
}) })
} }
@@ -227,10 +229,10 @@ impl From<RawParagraph> for shapes::Paragraph {
let typography_ref_file = uuid_from_u32(value.attrs.typography_ref_file); let typography_ref_file = uuid_from_u32(value.attrs.typography_ref_file);
let typography_ref_id = uuid_from_u32(value.attrs.typography_ref_id); let typography_ref_id = uuid_from_u32(value.attrs.typography_ref_id);
let mut leaves = vec![]; let mut spans = vec![];
let mut offset = 0; let mut offset = 0;
for raw_span in value.leaves.into_iter() { for raw_span in value.spans.into_iter() {
let delta = raw_span.text_length as usize; let delta = raw_span.text_length as usize;
let text_buffer = &value.text_buffer[offset..offset + delta]; let text_buffer = &value.text_buffer[offset..offset + delta];
@@ -239,7 +241,7 @@ impl From<RawParagraph> for shapes::Paragraph {
span.set_text(String::from_utf8_lossy(text_buffer).to_string()); span.set_text(String::from_utf8_lossy(text_buffer).to_string());
} }
leaves.push(span); spans.push(span);
offset += delta; offset += delta;
} }
@@ -252,7 +254,7 @@ impl From<RawParagraph> for shapes::Paragraph {
value.attrs.letter_spacing, value.attrs.letter_spacing,
typography_ref_file, typography_ref_file,
typography_ref_id, typography_ref_id,
leaves, spans,
) )
} }
} }