From cef2255da533fee2cc30016eb90b5eb2021cceb4 Mon Sep 17 00:00:00 2001 From: Marco Arnulfo <103679419+marcoarnulfo@users.noreply.github.com> Date: Sun, 18 Oct 2026 09:45:58 +0200 Subject: [PATCH] Edit text: a loaded font is applied to the paragraph being edited (part of #2591) (#2599) --- crates/ui-egui/src/edit_text_ui.rs | 15 +++++++++++++++ crates/ui-egui/src/files.rs | 25 ++++++++++++++++++------ crates/ui-egui/src/panels.rs | 31 +++++++++++++++++++----------- 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/crates/ui-egui/src/edit_text_ui.rs b/crates/ui-egui/src/edit_text_ui.rs index d8881ba47d..cbec130b86 100644 --- a/crates/ui-egui/src/edit_text_ui.rs +++ b/crates/ui-egui/src/edit_text_ui.rs @@ -1475,6 +1475,21 @@ mod tests { (app, ed) } + #[test] + fn a_loaded_font_is_applied_to_the_paragraph_being_edited() { + // Loading a font used to only register it on the page: the paragraph kept its source + // face until the font was found again in the document-font menu (#2591). + let (mut app, ed) = preview_app(); + app.views[0].line_editor = Some(ed); + let inter = include_bytes!("../../../assets/fonts/Inter-Regular.ttf").to_vec(); + app.use_files(crate::files::FilePurpose::TextFont { page: 0 }, vec![("Inter-Regular.ttf".into(), inter)]); + let doc = app.session.get(app.views[0].id).unwrap(); + let lines = doc.text_lines(0); + assert_eq!(lines.iter().map(|l| l.text.as_str()).collect::(), "Preview text"); + assert!(lines.iter().all(|l| l.base_font == "Inter-Regular"), "{:?}", lines.iter().map(|l| &l.base_font).collect::>()); + assert!(app.views[0].line_editor.is_some(), "the paragraph stays open for editing"); + } + #[test] fn text_background_is_cached_without_editing_and_released_on_cancel() { let (app, ed) = preview_app(); diff --git a/crates/ui-egui/src/files.rs b/crates/ui-egui/src/files.rs index f5e9e0319b..03c773807c 100644 --- a/crates/ui-egui/src/files.rs +++ b/crates/ui-egui/src/files.rs @@ -476,13 +476,26 @@ impl PdfCraftApp { match purpose { FilePurpose::TextFont { page } => { let Some((_, bytes)) = files.into_iter().next() else { return }; - if self.apply_edit(Edit::RegisterTextFont { page, bytes: Arc::new(bytes) }) - && let Some((index, id)) = self.active_ids() - && let Some(doc) = self.session.get(id) - && let Some(ed) = self.views[index].line_editor.as_mut() - && let Some(ctx) = self.ctx.as_ref() + let bytes = Arc::new(bytes); + if !self.apply_edit(Edit::RegisterTextFont { page, bytes: bytes.clone() }) { + return; + } + let Some((index, id)) = self.active_ids() else { return }; + let Some(mut ed) = self.views[index].line_editor.clone().filter(|ed| ed.page == page) else { return }; + // The font just loaded is the one the user wants: apply it to the paragraph, as + // choosing it from the document-font menu does, instead of only registering it (#2591). + let resource = self.session.get(id).and_then(|doc| { + doc.text_editor_fonts(page).into_iter().find(|f| f.bytes == *bytes && !f.resource.starts_with("PCApproved")).map(|f| f.resource) + }); + let ctx = self.ctx.clone(); + if resource.is_some() { + ed.font_resource = resource; + self.apply_line_format(index, ed, ctx.as_ref()); + } else if let Some(doc) = self.session.get(id) + && let Some(ctx) = ctx { - ed.fonts = crate::edit_text_ui::install_source_fonts(ctx, doc, page); + ed.fonts = crate::edit_text_ui::install_source_fonts(&ctx, doc, page); + self.views[index].line_editor = Some(ed); } } FilePurpose::Combine => self.stage_combine(files), diff --git a/crates/ui-egui/src/panels.rs b/crates/ui-egui/src/panels.rs index 2007dc0afa..fae129b308 100644 --- a/crates/ui-egui/src/panels.rs +++ b/crates/ui-egui/src/panels.rs @@ -418,17 +418,7 @@ fn format_section(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) { } changed |= crate::edit_text_ui::extras_panel(ui, &mut ed.extras); if changed { - let edit = pdfcraft_engine::Edit::EditTextBlock { page: ed.page, block: ed.block, text: ed.text.clone(), style: ed.style() }; - if app.apply_edit(edit) { - ed.applied(); - if let Some(doc) = app.session.get(app.views[i].id) - && let Some(block) = doc.text_blocks(ed.page).get(ed.block) - { - ed.refresh_source(block, doc.text_lines(ed.page)); - ed.fonts = crate::edit_text_ui::install_source_fonts(ui.ctx(), doc, ed.page); - } - } - app.views[i].line_editor = Some(ed); + app.apply_line_format(i, ed, Some(ui.ctx())); } ui.add_space(6.0); ui.separator(); @@ -482,6 +472,25 @@ fn format_section(app: &mut PdfCraftApp, ui: &mut egui::Ui, t: &Tokens) { ui.separator(); } +impl PdfCraftApp { + /// Apply the open paragraph's formatting as one change; the paragraph stays open. + pub(crate) fn apply_line_format(&mut self, index: usize, mut ed: crate::edit_text_ui::LineEditor, ctx: Option<&egui::Context>) { + let edit = pdfcraft_engine::Edit::EditTextBlock { page: ed.page, block: ed.block, text: ed.text.clone(), style: ed.style() }; + if self.apply_edit(edit) { + ed.applied(); + if let Some(doc) = self.session.get(self.views[index].id) + && let Some(block) = doc.text_blocks(ed.page).get(ed.block) + { + ed.refresh_source(block, doc.text_lines(ed.page)); + if let Some(ctx) = ctx { + ed.fonts = crate::edit_text_ui::install_source_fonts(ctx, doc, ed.page); + } + } + } + self.views[index].line_editor = Some(ed); + } +} + // ───────────────────────────────────────────────────────────────────────────── right panels pub(crate) enum Nav {