mirror of
https://github.com/penpot/penpot.git
synced 2025-05-28 09:56:11 +02:00
133 lines
3.1 KiB
Rust
133 lines
3.1 KiB
Rust
use crate::math::Rect;
|
|
use skia_safe::{
|
|
self as skia,
|
|
textlayout::{FontCollection, ParagraphBuilder},
|
|
};
|
|
|
|
use super::FontFamily;
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub struct TextContent {
|
|
paragraphs: Vec<Paragraph>,
|
|
bounds: Rect,
|
|
}
|
|
|
|
impl TextContent {
|
|
pub fn new(bounds: Rect) -> Self {
|
|
let mut res = Self::default();
|
|
res.bounds = bounds;
|
|
res
|
|
}
|
|
|
|
pub fn set_xywh(&mut self, x: f32, y: f32, w: f32, h: f32) {
|
|
self.bounds = Rect::from_xywh(x, y, w, h);
|
|
}
|
|
|
|
pub fn width(&self) -> f32 {
|
|
self.bounds.width()
|
|
}
|
|
|
|
pub fn x(&self) -> f32 {
|
|
self.bounds.x()
|
|
}
|
|
|
|
pub fn y(&self) -> f32 {
|
|
self.bounds.y()
|
|
}
|
|
|
|
pub fn add_paragraph(&mut self) {
|
|
let p = Paragraph::default();
|
|
self.paragraphs.push(p);
|
|
}
|
|
|
|
pub fn add_leaf(
|
|
&mut self,
|
|
text: String,
|
|
font_family: FontFamily,
|
|
font_size: f32,
|
|
) -> Result<(), String> {
|
|
let paragraph = self
|
|
.paragraphs
|
|
.last_mut()
|
|
.ok_or("No paragraph to add text leaf to")?;
|
|
|
|
paragraph.add_leaf(TextLeaf::new(text, font_family, font_size));
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn to_paragraphs(&self, fonts: &FontCollection) -> Vec<skia::textlayout::Paragraph> {
|
|
let mut paragraph_style = skia::textlayout::ParagraphStyle::default();
|
|
// TODO: read text direction, align, etc. from the shape
|
|
paragraph_style.set_text_direction(skia::textlayout::TextDirection::LTR);
|
|
|
|
self.paragraphs
|
|
.iter()
|
|
.map(|p| {
|
|
let mut builder = ParagraphBuilder::new(¶graph_style, fonts);
|
|
for leaf in &p.children {
|
|
builder.push_style(&leaf.to_style());
|
|
builder.add_text(&leaf.text);
|
|
builder.pop();
|
|
}
|
|
builder.build()
|
|
})
|
|
.collect()
|
|
}
|
|
}
|
|
|
|
impl Default for TextContent {
|
|
fn default() -> Self {
|
|
Self {
|
|
paragraphs: vec![],
|
|
bounds: Rect::default(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub struct Paragraph {
|
|
children: Vec<TextLeaf>,
|
|
}
|
|
|
|
impl Default for Paragraph {
|
|
fn default() -> Self {
|
|
Self { children: vec![] }
|
|
}
|
|
}
|
|
|
|
impl Paragraph {
|
|
fn add_leaf(&mut self, leaf: TextLeaf) {
|
|
self.children.push(leaf);
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, PartialEq, Clone)]
|
|
pub struct TextLeaf {
|
|
text: String,
|
|
font_family: FontFamily,
|
|
font_size: f32,
|
|
}
|
|
|
|
impl TextLeaf {
|
|
pub fn new(text: String, font_family: FontFamily, font_size: f32) -> Self {
|
|
Self {
|
|
text,
|
|
font_family,
|
|
font_size,
|
|
}
|
|
}
|
|
|
|
pub fn to_style(&self) -> skia::textlayout::TextStyle {
|
|
let mut style = skia::textlayout::TextStyle::default();
|
|
style.set_color(skia::Color::BLACK);
|
|
style.set_font_size(self.font_size);
|
|
style.set_font_families(&[self.serialized_font_family()]);
|
|
|
|
style
|
|
}
|
|
|
|
fn serialized_font_family(&self) -> String {
|
|
format!("{}", self.font_family)
|
|
}
|
|
}
|