mirror of
https://github.com/penpot/penpot.git
synced 2025-12-12 06:24:17 +01:00
🐛 Fix default font size in text spans
This commit is contained in:
@@ -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))))
|
||||||
|
|||||||
@@ -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")))
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user