# 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