From 7ce506827f5e4f029cb5c743c807a86f6ae9c4c2 Mon Sep 17 00:00:00 2001 From: iola1999 Date: Fri, 22 Nov 2024 03:07:09 +0800 Subject: [PATCH] fix: fontdb io issue --- index.d.ts | 1 + js-binding.d.ts | 6 +++--- src/fonts.rs | 46 +++++++++++++++++++++++++++++++++++++--------- src/options.rs | 7 +++++++ 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/index.d.ts b/index.d.ts index ce3ca848..ac2d6975 100755 --- a/index.d.ts +++ b/index.d.ts @@ -5,6 +5,7 @@ export type ResvgRenderOptions = { loadSystemFonts?: boolean // Default: true, if set to false, it will be faster. fontFiles?: string[] // A list of local font file paths to load. fontDirs?: string[] // A list of local font directories to load. + preloadFonts?: boolean // Default: false. When enabled, font files will be read into memory at once to avoid frequent IO. defaultFontSize?: number // Default: 12 defaultFontFamily?: string // Default: "", if `loadSystemFonts` is enabled, it will be set to the first font in the list of system fonts. serifFamily?: string diff --git a/js-binding.d.ts b/js-binding.d.ts index c51bd166..2f89e792 100644 --- a/js-binding.d.ts +++ b/js-binding.d.ts @@ -4,13 +4,13 @@ /* auto-generated by NAPI-RS */ export function renderAsync(svg: string | Buffer, options?: string | undefined | null, signal?: AbortSignal | undefined | null): Promise -export class BBox { +export declare class BBox { x: number y: number width: number height: number } -export class Resvg { +export declare class Resvg { constructor(svg: string | Buffer, options?: string | undefined | null) /** Renders an SVG in Node.js */ render(): RenderedImage @@ -40,7 +40,7 @@ export class Resvg { /** Get the SVG height */ get height(): number } -export class RenderedImage { +export declare class RenderedImage { /** Write the image data to Buffer */ asPng(): Buffer /** Get the RGBA pixels of the image */ diff --git a/src/fonts.rs b/src/fonts.rs index 6ccd83f9..78265bde 100644 --- a/src/fonts.rs +++ b/src/fonts.rs @@ -20,20 +20,48 @@ use woff2::decode::{convert_woff2_to_ttf, is_woff2}; /// Loads fonts. #[cfg(not(target_arch = "wasm32"))] pub fn load_fonts(font_options: &JsFontOptions) -> Database { - // Create a new font database let mut fontdb = Database::new(); let now = std::time::Instant::now(); - // 加载指定路径的字体 - for path in &font_options.font_files { - if let Err(e) = fontdb.load_font_file(path) { - warn!("Failed to load '{}' cause {}.", path, e); + if font_options.preload_fonts { + // 预加载模式: 一次性读取所有字体文件到内存 + for path in &font_options.font_files { + match std::fs::read(path) { + Ok(buffer) => { + let _ = fontdb.load_font_data(buffer); + } + Err(e) => { + warn!("Failed to read font file '{}' cause {}.", path, e); + } + } + } + + // 加载字体目录 + for dir in &font_options.font_dirs { + if let Ok(entries) = std::fs::read_dir(dir) { + for entry in entries.flatten() { + if let Ok(path) = entry.path().canonicalize() { + if path.is_file() { + if let Ok(buffer) = std::fs::read(&path) { + let _ = fontdb.load_font_data(buffer); + } + } + } + } + } + } + } else { + // 默认模式: 直接传递文件路径 + for path in &font_options.font_files { + if let Err(e) = fontdb.load_font_file(path) { + warn!("Failed to load '{}' cause {}.", path, e); + } } - } - // Load font directories - for path in &font_options.font_dirs { - fontdb.load_fonts_dir(path); + // Load font directories + for path in &font_options.font_dirs { + fontdb.load_fonts_dir(path); + } } // 加载系统字体 diff --git a/src/options.rs b/src/options.rs index 4a8d2c57..c377c8a7 100644 --- a/src/options.rs +++ b/src/options.rs @@ -238,6 +238,12 @@ pub struct JsFontOptions { /// A list of local font directories to load. pub font_dirs: Vec, + /// Whether to preload font files into memory to improve performance. + /// When enabled, font files will be read into memory at once to avoid frequent IO. + /// + /// Default: false + pub preload_fonts: bool, + /// The default font family. /// /// Will be used when no `font-family` attribute is set in the SVG. @@ -284,6 +290,7 @@ impl Default for JsFontOptions { load_system_fonts: true, font_files: vec![], font_dirs: vec![], + preload_fonts: false, default_font_family: "".to_string(), default_font_size: 12.0, serif_family: "Times New Roman".to_string(),