Add font family selector for watermark text
Font picker using GTK FontDialog/FontDialogButton lets users choose any installed system font for text watermarks. The selected font family is passed through the processing pipeline and used to find the matching font file on disk.
This commit is contained in:
@@ -203,6 +203,7 @@ pub enum WatermarkConfig {
|
||||
font_size: f32,
|
||||
opacity: f32,
|
||||
color: [u8; 4],
|
||||
font_family: Option<String>,
|
||||
},
|
||||
Image {
|
||||
path: std::path::PathBuf,
|
||||
|
||||
@@ -46,7 +46,8 @@ pub fn apply_watermark(
|
||||
font_size,
|
||||
opacity,
|
||||
color,
|
||||
} => apply_text_watermark(img, text, *position, *font_size, *opacity, *color),
|
||||
font_family,
|
||||
} => apply_text_watermark(img, text, *position, *font_size, *opacity, *color, font_family.as_deref()),
|
||||
WatermarkConfig::Image {
|
||||
path,
|
||||
position,
|
||||
@@ -56,7 +57,38 @@ pub fn apply_watermark(
|
||||
}
|
||||
}
|
||||
|
||||
fn find_system_font() -> Result<Vec<u8>> {
|
||||
fn find_system_font(family: Option<&str>) -> Result<Vec<u8>> {
|
||||
// If a specific font family was requested, try to find it via fontconfig
|
||||
if let Some(name) = family {
|
||||
if !name.is_empty() {
|
||||
// Try common font paths with the family name
|
||||
let search_dirs = [
|
||||
"/usr/share/fonts",
|
||||
"/usr/local/share/fonts",
|
||||
];
|
||||
let name_lower = name.to_lowercase();
|
||||
for dir in &search_dirs {
|
||||
if let Ok(entries) = walkdir(std::path::Path::new(dir)) {
|
||||
for path in entries {
|
||||
let file_name = path.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.unwrap_or("")
|
||||
.to_lowercase();
|
||||
if file_name.contains(&name_lower)
|
||||
&& (file_name.ends_with(".ttf") || file_name.ends_with(".otf"))
|
||||
&& (file_name.contains("regular") || !file_name.contains("bold") && !file_name.contains("italic"))
|
||||
{
|
||||
if let Ok(data) = std::fs::read(&path) {
|
||||
return Ok(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to default system fonts
|
||||
let candidates = [
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
||||
"/usr/share/fonts/TTF/DejaVuSans.ttf",
|
||||
@@ -78,6 +110,25 @@ fn find_system_font() -> Result<Vec<u8>> {
|
||||
})
|
||||
}
|
||||
|
||||
/// Recursively walk a directory and collect file paths
|
||||
fn walkdir(dir: &std::path::Path) -> std::io::Result<Vec<std::path::PathBuf>> {
|
||||
let mut results = Vec::new();
|
||||
if dir.is_dir() {
|
||||
for entry in std::fs::read_dir(dir)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if path.is_dir() {
|
||||
if let Ok(sub) = walkdir(&path) {
|
||||
results.extend(sub);
|
||||
}
|
||||
} else {
|
||||
results.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
fn apply_text_watermark(
|
||||
img: DynamicImage,
|
||||
text: &str,
|
||||
@@ -85,8 +136,9 @@ fn apply_text_watermark(
|
||||
font_size: f32,
|
||||
opacity: f32,
|
||||
color: [u8; 4],
|
||||
font_family: Option<&str>,
|
||||
) -> Result<DynamicImage> {
|
||||
let font_data = find_system_font()?;
|
||||
let font_data = find_system_font(font_family)?;
|
||||
let font = ab_glyph::FontArc::try_from_vec(font_data).map_err(|_| {
|
||||
PixstripError::Processing {
|
||||
operation: "watermark".into(),
|
||||
|
||||
Reference in New Issue
Block a user