Files
pdfcraft/crates/engine/src/text_preview.rs
Marco Arnulfo 801a2f1488 fix(ui): dragged added text follows the pointer before release (#1508)
* fix(ui): dragged added text follows the pointer before release (fixes #1488)

* fix(ui): keep a moved item in place until the page is redrawn (fixes #1488)
2026-10-13 00:05:43 -04:00

79 lines
3.3 KiB
Rust

//! The page beneath an inline text editor, with the source glyphs removed on a COS clone.
use std::sync::Arc;
use pdfcraft_render::{PageRenderer, RenderConfig, RenderPool, RenderRequest, RenderedPage};
use crate::{Document, guard};
pub struct TextEditPreview {
page: usize,
bytes: Arc<Vec<u8>>,
config: RenderConfig,
}
impl TextEditPreview {
pub fn renderer(&self) -> RenderPool {
RenderPool::new(self.bytes.clone(), 1, self.config.clone())
}
pub fn render_background(&self, scale: f32) -> Result<RenderedPage, String> {
if !scale.is_finite() || scale <= 0.0 {
return Err("preview scale must be finite and positive".into());
}
guard(|| {
let mut renderer = PageRenderer::new(self.bytes.clone(), self.config.clone());
let out = renderer.render(RenderRequest { page: self.page, scale, ..Default::default() });
if let Some(e) = &out.error {
return Err(e.clone());
}
Ok(out)
})?
}
}
impl Document {
/// Measure a draft without changing bytes, dirty state, or undo history.
pub fn text_edit_layout(
&self,
page: usize,
block: usize,
text: &str,
style: &pdfcraft_edit::BlockStyle,
) -> Result<pdfcraft_edit::text::TextEditLayout, String> {
guard(|| {
let editor = self.editor.as_ref().ok_or("the document can't be read")?;
pdfcraft_edit::text::text_edit_layout(&editor.cos, page, block, text, style).map_err(|e| e.to_string())
})?
}
/// Embedded source faces for a text editor, bounded and validated as sfnt programs.
/// This is read-only; no source font is installed or exported.
pub fn text_editor_fonts(&self, page: usize) -> Vec<pdfcraft_edit::text::TextEditorFont> {
self.editor.as_ref().and_then(|e| pdfcraft_edit::text::text_editor_fonts(&e.cos, page).ok()).unwrap_or_default()
}
/// Preparing the background never changes working bytes, dirty state or undo history.
pub fn text_edit_preview(&self, page: usize, block: usize) -> Result<TextEditPreview, String> {
guard(|| {
let editor = self.editor.as_ref().ok_or("the document can't be read")?;
let mut cos = editor.cos.clone();
pdfcraft_edit::clear_block(&mut cos, page, block).map_err(|e| e.to_string())?;
let bytes = Arc::new(pdfcraft_cos::write_incremental(&cos, &pdfcraft_cos::SaveOptions::default()).map_err(|e| e.to_string())?);
Ok(TextEditPreview { page, bytes, config: self.config.clone() })
})?
}
/// The page beneath an added item while it is dragged: `index` counts the page's added
/// items, as `Edit::DeleteContent` does. Read-only, like [`Self::text_edit_preview`].
pub fn added_content_preview(&self, page: usize, index: usize) -> Result<TextEditPreview, String> {
guard(|| {
let editor = self.editor.as_ref().ok_or("the document can't be read")?;
let mut cos = editor.cos.clone();
pdfcraft_edit::delete_content(&mut cos, page, index).map_err(|e| e.to_string())?;
let bytes = Arc::new(pdfcraft_cos::write_incremental(&cos, &pdfcraft_cos::SaveOptions::default()).map_err(|e| e.to_string())?);
Ok(TextEditPreview { page, bytes, config: self.config.clone() })
})?
}
}