153 lines
6.2 KiB
Python
153 lines
6.2 KiB
Python
# Font validation and preview functionality
|
|
import bpy
|
|
import os
|
|
import platform
|
|
from PIL import Image, ImageDraw, ImageFont
|
|
|
|
def test_font_mixed_case_support(font_path):
|
|
"""
|
|
Test if a font properly supports mixed case rendering.
|
|
Returns True if the font supports mixed case, False if it only renders uppercase.
|
|
"""
|
|
try:
|
|
# Test string with mixed case
|
|
test_text = "AaBbCc"
|
|
|
|
# Create a test image to render the font
|
|
test_size = (200, 100)
|
|
test_image = Image.new('RGBA', test_size, (0, 0, 0, 0))
|
|
draw = ImageDraw.Draw(test_image)
|
|
|
|
# Try to load the font
|
|
try:
|
|
font = ImageFont.truetype(font_path, 24)
|
|
except (OSError, IOError):
|
|
print(f"Text Texture Generator: Could not load font for testing: {font_path}")
|
|
return False
|
|
|
|
# Render the test text
|
|
draw.text((10, 10), test_text, font=font, fill=(255, 255, 255, 255))
|
|
|
|
# Get the rendered pixels
|
|
pixels = list(test_image.getdata())
|
|
|
|
# Create another image with uppercase version
|
|
test_image_upper = Image.new('RGBA', test_size, (0, 0, 0, 0))
|
|
draw_upper = ImageDraw.Draw(test_image_upper)
|
|
draw_upper.text((10, 10), test_text.upper(), font=font, fill=(255, 255, 255, 255))
|
|
|
|
pixels_upper = list(test_image_upper.getdata())
|
|
|
|
# Compare the two renderings - if they're identical, the font only supports uppercase
|
|
if pixels == pixels_upper:
|
|
print(f"Text Texture Generator: Font only supports uppercase rendering: {os.path.basename(font_path)}")
|
|
return False
|
|
else:
|
|
print(f"Text Texture Generator: Font supports mixed case rendering: {os.path.basename(font_path)}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"Text Texture Generator: Error testing font mixed case support: {str(e)}")
|
|
return False
|
|
|
|
def get_validated_font(font_path, fallback_fonts=None):
|
|
"""
|
|
Get a validated font that supports mixed case rendering.
|
|
Returns the original font path if valid, otherwise returns a fallback font.
|
|
"""
|
|
if not font_path or not os.path.exists(font_path):
|
|
print(f"Text Texture Generator: Font file not found: {font_path}")
|
|
return get_system_fallback_fonts()[0] if get_system_fallback_fonts() else None
|
|
|
|
# Test if the font supports mixed case
|
|
if test_font_mixed_case_support(font_path):
|
|
return font_path
|
|
else:
|
|
print(f"Text Texture Generator: Font does not support mixed case, using fallback: {font_path}")
|
|
|
|
# Try fallback fonts if provided
|
|
if fallback_fonts:
|
|
for fallback_font in fallback_fonts:
|
|
if os.path.exists(fallback_font) and test_font_mixed_case_support(fallback_font):
|
|
print(f"Text Texture Generator: Using fallback font: {fallback_font}")
|
|
return fallback_font
|
|
|
|
# Use system fallback fonts
|
|
system_fallbacks = get_system_fallback_fonts()
|
|
for fallback_font in system_fallbacks:
|
|
if test_font_mixed_case_support(fallback_font):
|
|
print(f"Text Texture Generator: Using system fallback font: {fallback_font}")
|
|
return fallback_font
|
|
|
|
# If no valid font found, return the original (better than nothing)
|
|
print("Text Texture Generator: Warning - No valid mixed case font found, using original")
|
|
return font_path
|
|
|
|
def get_system_fallback_fonts():
|
|
"""
|
|
Get a list of system fallback fonts based on the operating system.
|
|
Returns a list of font paths that are likely to be available.
|
|
"""
|
|
system = platform.system()
|
|
fallback_fonts = []
|
|
|
|
if system == "Windows":
|
|
windows_fonts = [
|
|
"C:/Windows/Fonts/arial.ttf",
|
|
"C:/Windows/Fonts/calibri.ttf",
|
|
"C:/Windows/Fonts/verdana.ttf",
|
|
"C:/Windows/Fonts/tahoma.ttf",
|
|
"C:/Windows/Fonts/segoeui.ttf",
|
|
"C:/Windows/Fonts/times.ttf"
|
|
]
|
|
fallback_fonts.extend([f for f in windows_fonts if os.path.exists(f)])
|
|
|
|
elif system == "Darwin": # macOS
|
|
macos_fonts = [
|
|
"/System/Library/Fonts/Helvetica.ttc",
|
|
"/System/Library/Fonts/Arial.ttf",
|
|
"/System/Library/Fonts/Times.ttc",
|
|
"/System/Library/Fonts/Verdana.ttf",
|
|
"/Library/Fonts/Arial.ttf",
|
|
"/System/Library/Fonts/Courier.dfont"
|
|
]
|
|
fallback_fonts.extend([f for f in macos_fonts if os.path.exists(f)])
|
|
|
|
elif system == "Linux":
|
|
linux_fonts = [
|
|
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
|
|
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
|
|
"/usr/share/fonts/truetype/ubuntu/Ubuntu-R.ttf",
|
|
"/usr/share/fonts/truetype/noto/NotoSans-Regular.ttf",
|
|
"/usr/share/fonts/TTF/arial.ttf",
|
|
"/usr/share/fonts/truetype/ttf-bitstream-vera/Vera.ttf"
|
|
]
|
|
fallback_fonts.extend([f for f in linux_fonts if os.path.exists(f)])
|
|
|
|
# Also check common font directories
|
|
common_directories = [
|
|
"/usr/share/fonts",
|
|
"/usr/local/share/fonts",
|
|
os.path.expanduser("~/.fonts"),
|
|
os.path.expanduser("~/Library/Fonts")
|
|
]
|
|
|
|
for font_dir in common_directories:
|
|
if os.path.exists(font_dir):
|
|
for root, dirs, files in os.walk(font_dir):
|
|
for file in files:
|
|
if file.lower().endswith(('.ttf', '.otf')):
|
|
font_path = os.path.join(root, file)
|
|
if font_path not in fallback_fonts:
|
|
fallback_fonts.append(font_path)
|
|
# Limit the number of fallback fonts to prevent excessive scanning
|
|
if len(fallback_fonts) >= 20:
|
|
break
|
|
if len(fallback_fonts) >= 20:
|
|
break
|
|
|
|
print(f"Text Texture Generator: Found {len(fallback_fonts)} system fallback fonts")
|
|
for i, font in enumerate(fallback_fonts[:5]): # Log first 5 fonts
|
|
print(f"Text Texture Generator: Fallback font {i+1}: {font}")
|
|
|
|
return fallback_fonts |