feature: font style and weight is configurable but not persistant
Some checks failed
/ test (push) Failing after 5m27s

This commit is contained in:
Chris Cochrun 2026-02-13 14:44:28 -06:00
parent 6327ed51b4
commit bf2fa842cd
3 changed files with 104 additions and 10 deletions

View file

@ -3,7 +3,11 @@ use std::{
};
use cosmic::{
cosmic_theme::palette::Srgb, iced::clipboard::mime::AsMimeTypes,
cosmic_theme::palette::Srgb,
iced::{
clipboard::mime::AsMimeTypes,
font::{Style, Weight},
},
};
use crisp::types::{Keyword, Symbol, Value};
use itertools::Itertools;
@ -44,6 +48,8 @@ pub struct Song {
pub text_alignment: Option<TextAlignment>,
pub font: Option<String>,
pub font_size: Option<i32>,
pub font_weight: Option<Weight>,
pub font_style: Option<Style>,
pub text_color: Option<Srgb>,
pub stroke_size: Option<u16>,
pub stroke_color: Option<Srgb>,
@ -295,6 +301,12 @@ impl ServiceTrait for Song {
.clone()
.unwrap_or_else(|| "Calibri".into()),
)
.style(
self.font_style.clone().unwrap_or_default(),
)
.weight(
self.font_weight.clone().unwrap_or_default(),
)
.size(self.font_size.unwrap_or(100) as u8);
let stroke_size =
self.stroke_size.unwrap_or_default();

View file

@ -9,8 +9,12 @@ use cosmic::{
dialog::file_chooser::{FileFilter, open::Dialog},
iced::{
Background as ContainerBackground, Border, Color, Length,
Padding, Shadow, Vector, alignment::Vertical, color,
futures::StreamExt, task,
Padding, Shadow, Vector,
alignment::Vertical,
color,
font::{Style, Weight},
futures::StreamExt,
task,
},
iced_core::widget::tree,
iced_wgpu::graphics::text::cosmic_text::fontdb,
@ -107,6 +111,7 @@ pub enum Message {
ChangeSong(Song),
UpdateSong(Song),
ChangeFont(String),
ChangeFontStyle,
ChangeFontSize(String),
ChangeTitle(String),
ChangeVerseOrder(String),
@ -143,6 +148,7 @@ pub enum Message {
UpdateShadowSize(u16),
UpdateShadowOffsetX(i16),
UpdateShadowOffsetY(i16),
ChangeFontWeight,
}
impl SongEditor {
@ -151,10 +157,10 @@ impl SongEditor {
debug!(?fonts);
let mut fonts: Vec<String> = font_db
.faces()
.map(|f| f.families[0].0.clone())
.map(|f| f.families[0].0.clone().trim().to_string())
.collect();
fonts.dedup();
fonts.sort();
fonts.dedup();
let stroke_sizes = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let font_sizes = vec![
"5".to_string(),
@ -329,6 +335,46 @@ impl SongEditor {
return Action::Task(self.update_song(song));
}
}
Message::ChangeFontStyle => {
if let Some(song) = &mut self.song {
if let Some(font_style) = &mut song.font_style {
match font_style {
cosmic::iced::font::Style::Normal => {
*font_style = Style::Italic;
}
cosmic::iced::font::Style::Italic => {
*font_style = Style::Normal;
}
cosmic::iced::font::Style::Oblique => {
*font_style = Style::Normal;
}
}
} else {
song.font_style = Some(Style::Italic);
}
let song = song.clone();
return Action::Task(self.update_song(song));
}
}
Message::ChangeFontWeight => {
if let Some(song) = &mut self.song {
if let Some(font_weight) = &mut song.font_weight {
match font_weight {
Weight::Normal => {
*font_weight = Weight::Bold
}
Weight::Bold => {
*font_weight = Weight::Normal
}
_ => *font_weight = Weight::Normal,
}
} else {
song.font_weight = Some(Weight::Bold);
}
let song = song.clone();
return Action::Task(self.update_song(song));
}
}
Message::ChangeFontSize(size) => {
if let Ok(size) = size.parse() {
self.font_size = size;
@ -1218,13 +1264,23 @@ impl SongEditor {
let bold_button = tooltip(
button::icon(icon::from_name("format-text-bold"))
.on_press(Message::None),
.selected(self.song.as_ref().is_some_and(|song| {
song.font_weight.is_some_and(|font_weight| {
font_weight == Weight::Bold
})
}))
.on_press(Message::ChangeFontWeight),
"Bold",
tooltip::Position::Bottom,
);
let italic_button = tooltip(
button::icon(icon::from_name("format-text-italic"))
.on_press(Message::None),
.selected(self.song.as_ref().is_some_and(|song| {
song.font_style.is_some_and(|font_style| {
font_style == Style::Italic
})
}))
.on_press(Message::ChangeFontStyle),
"Italicize",
tooltip::Position::Bottom,
);

View file

@ -21,7 +21,7 @@ use resvg::{
usvg::{Tree, fontdb},
};
use serde::{Deserialize, Serialize};
use tracing::error;
use tracing::{debug, error};
use crate::TextAlignment;
@ -350,6 +350,24 @@ impl TextSvg {
}
};
let font_style = match self.font.style {
Style::Normal => "normal",
Style::Italic => "italic",
Style::Oblique => "oblique",
};
let font_weight = match self.font.weight {
Weight::Thin => "lighter",
Weight::ExtraLight => "lighter",
Weight::Light => "lighter",
Weight::Normal => "normal",
Weight::Medium => "normal",
Weight::Semibold => "bold",
Weight::Bold => "bold",
Weight::ExtraBold => "bolder",
Weight::Black => "bolder",
};
final_svg.push_str(&format!("<svg width=\"{}\" height=\"{}\" viewBox=\"0 0 {} {}\" xmlns=\"http://www.w3.org/2000/svg\"><defs>", size.width, size.height, size.width, size.height));
if let Some(shadow) = &self.shadow {
@ -368,7 +386,15 @@ impl TextSvg {
// "<style> text { letter-spacing: 0em; } </style>",
// );
final_svg.push_str(&format!("<text x=\"0\" y=\"50%\" transform=\"translate({}, 0)\" dominant-baseline=\"middle\" text-anchor=\"{}\" font-weight=\"bold\" font-family=\"{}\" font-size=\"{}\" fill=\"{}\" ", text_x_position, text_anchor, self.font.name, font_size, self.fill));
final_svg.push_str(&format!("<text x=\"0\" y=\"50%\" transform=\"translate({}, 0)\" dominant-baseline=\"middle\" text-anchor=\"{}\" font-style=\"{}\" font-weight=\"{}\" font-family=\"{}\" font-size=\"{}\" fill=\"{}\" ",
text_x_position,
text_anchor,
font_style,
font_weight,
self.font.name,
font_size,
self.fill
));
if let Some(stroke) = &self.stroke {
final_svg.push_str(&format!(
@ -523,7 +549,7 @@ pub fn text_svg_generator_with_cache(
};
let text_svg =
text_svg.font(font).fontdb(Arc::clone(&fontdb));
// debug!(fill = ?text_svg.fill, font = ?text_svg.font, stroke = ?text_svg.stroke, shadow = ?text_svg.shadow, text = ?text_svg.text);
debug!(fill = ?text_svg.fill, font = ?text_svg.font, stroke = ?text_svg.stroke, shadow = ?text_svg.shadow, text = ?text_svg.text);
let text_svg =
text_svg.build(Size::new(1280.0, 720.0), cache);
slide.text_svg = Some(text_svg);