Helpful_AI / backend /text_editor /font_detector.py
Kaushal05's picture
Upload 90 files
6c07fdf verified
Raw
History Blame Contribute Delete
4 kB
import os
from PIL import ImageFont
from backend.text_editor.font_downloader import download_google_font
def get_system_font_path(font_family: str = "Sans-Serif") -> str:
"""
Get the path to a standard system font on Windows.
Defaults to Arial (Sans-Serif), Times New Roman (Serif), or Courier New (Monospace).
"""
windows_font_dir = "C:\\Windows\\Fonts"
font_mapping = {
"Sans-Serif": ["arial.ttf", "calibri.ttf", "segoeui.ttf"],
"Serif": ["times.ttf", "georgia.ttf", "cambria.ttf"],
"Monospace": ["cour.ttf", "consola.ttf", "lucon.ttf"]
}
candidates = font_mapping.get(font_family, font_mapping["Sans-Serif"])
# Check if we are on Windows and directory exists
if os.path.exists(windows_font_dir):
for candidate in candidates:
path = os.path.join(windows_font_dir, candidate)
if os.path.exists(path):
return path
# Fallbacks for standard platform-independent locations or names
for candidate in candidates:
if os.path.exists(candidate):
return candidate
return ""
def load_matching_font(bbox_height: int, font_family: str = "Sans-Serif", size_multiplier: float = 0.85, text: str = "") -> tuple:
"""
Loads a PIL ImageFont matching the requested family (either standard or dynamic Google Font)
and scaled to the bounding box height. Auto-detects Hindi/Devanagari characters and overrides
fallbacks with appropriate Devanagari-supporting fonts.
Parameters:
- bbox_height: Height of the bounding box in pixels.
- font_family: Font style family or custom Google Font name.
- size_multiplier: Multiplier to adjust font size relative to bounding box height.
- text: The replacement text content to analyze for character-level font requirements.
Returns:
A tuple (font_object, font_size)
"""
font_size = max(8, int(bbox_height * size_multiplier))
# 1. Detect if the text contains Devanagari (Hindi) characters
is_hindi = False
for char in text:
if '\u0900' <= char <= '\u097F':
is_hindi = True
break
# 2. Intercept and auto-resolve Hindi fonts
if is_hindi:
# If standard family is chosen, automatically upgrade to Google Noto Sans Devanagari
if font_family in ["Sans-Serif", "Serif", "Monospace"]:
font_family = "Noto Sans Devanagari"
font_path = ""
# 3. Check if a custom Google Font (or auto-resolved Hindi font) is requested
if font_family not in ["Sans-Serif", "Serif", "Monospace"]:
font_path = download_google_font(font_family)
# 4. If it is standard family or download failed, resolve system fallback
if not font_path:
if is_hindi:
# Fallback to standard Windows Devanagari system fonts
windows_font_dir = "C:\\Windows\\Fonts"
hindi_candidates = ["mangal.ttf", "utsah.ttf", "aparaj.ttf", "kokila.ttf"]
for candidate in hindi_candidates:
path = os.path.join(windows_font_dir, candidate)
if os.path.exists(path):
font_path = path
break
# If still no path resolved, fallback to standard system families
if not font_path:
standard_family = "Sans-Serif"
if font_family in ["Serif", "Monospace"]:
standard_family = font_family
font_path = get_system_font_path(standard_family)
if font_path:
try:
font = ImageFont.truetype(font_path, font_size)
return font, font_size
except Exception as e:
print(f"Failed to load TrueType font {font_path}: {e}")
# Ultimate fallback to default PIL font
try:
font = ImageFont.load_default()
return font, 12
except Exception:
return None, 0