prepend append
This commit is contained in:
BIN
Archive.zip
BIN
Archive.zip
Binary file not shown.
309
__init__.py
309
__init__.py
@@ -495,12 +495,57 @@ def generate_texture_image(props, width, height):
|
||||
print("WARNING: Using default font - this may not support mixed-case properly!")
|
||||
print("WARNING: Consider installing additional fonts for proper mixed-case support")
|
||||
|
||||
# Calculate text position
|
||||
text = props.text if props.text and props.text.strip() else "Hello World"
|
||||
# ============================================================================
|
||||
# PREPEND/APPEND TEXT PROCESSING
|
||||
# ============================================================================
|
||||
|
||||
# Get the main text
|
||||
main_text = props.text if props.text and props.text.strip() else "Hello World"
|
||||
|
||||
# Get prepend and append text
|
||||
prepend_text = props.prepend_text.strip() if props.prepend_text else ""
|
||||
append_text = props.append_text.strip() if props.append_text else ""
|
||||
|
||||
# Calculate margins as pixels (percentage of font size)
|
||||
prepend_margin_px = int((props.prepend_margin / 100.0) * font_size_pixels) if prepend_text else 0
|
||||
append_margin_px = int((props.append_margin / 100.0) * font_size_pixels) if append_text else 0
|
||||
|
||||
# Combine text based on layout
|
||||
if props.prepend_append_layout == 'HORIZONTAL':
|
||||
# Horizontal layout: [prepend] [margin] [main] [margin] [append]
|
||||
text_parts = []
|
||||
if prepend_text:
|
||||
text_parts.append(prepend_text)
|
||||
# Add proper spacing based on margin percentage
|
||||
if prepend_margin_px > 0:
|
||||
# Convert margin pixels to approximate space characters
|
||||
space_count = max(1, int(prepend_margin_px / (font_size_pixels * 0.3)))
|
||||
text_parts.append(" " * space_count)
|
||||
else:
|
||||
text_parts.append(" ") # Default single space
|
||||
|
||||
text_parts.append(main_text)
|
||||
|
||||
if append_text:
|
||||
# Add proper spacing based on margin percentage
|
||||
if append_margin_px > 0:
|
||||
space_count = max(1, int(append_margin_px / (font_size_pixels * 0.3)))
|
||||
text_parts.append(" " * space_count)
|
||||
else:
|
||||
text_parts.append(" ") # Default single space
|
||||
text_parts.append(append_text)
|
||||
|
||||
text = "".join(text_parts)
|
||||
else:
|
||||
# Vertical layout will be handled separately - for now use main text
|
||||
text = main_text
|
||||
|
||||
# ENHANCED DIAGNOSTIC LOGGING for uppercase text issue
|
||||
print(f"DEBUG UPPERCASE ISSUE - Original text input: '{props.text}'")
|
||||
print(f"DEBUG UPPERCASE ISSUE - Processed text: '{text}'")
|
||||
print(f"DEBUG PREPEND/APPEND - Original main text: '{props.text}'")
|
||||
print(f"DEBUG PREPEND/APPEND - Prepend text: '{prepend_text}'")
|
||||
print(f"DEBUG PREPEND/APPEND - Append text: '{append_text}'")
|
||||
print(f"DEBUG PREPEND/APPEND - Layout: '{props.prepend_append_layout}'")
|
||||
print(f"DEBUG PREPEND/APPEND - Final combined text: '{text}'")
|
||||
print(f"DEBUG UPPERCASE ISSUE - Text type: {type(text)}")
|
||||
print(f"DEBUG UPPERCASE ISSUE - Has upper chars: {any(c.isupper() for c in text)}")
|
||||
print(f"DEBUG UPPERCASE ISSUE - Has lower chars: {any(c.islower() for c in text)}")
|
||||
@@ -516,14 +561,52 @@ def generate_texture_image(props, width, height):
|
||||
print("WARNING: Current font may not support mixed-case rendering properly!")
|
||||
print("This could be the cause of uppercase-only text rendering")
|
||||
|
||||
try:
|
||||
bbox = draw.textbbox((0, 0), text, font=font)
|
||||
text_width = max(1, bbox[2] - bbox[0])
|
||||
text_height = max(1, bbox[3] - bbox[1])
|
||||
except (OSError, ZeroDivisionError, ValueError) as e:
|
||||
print(f"Error getting text bbox: {e}")
|
||||
text_width = int(len(text) * font_size_pixels * 0.6)
|
||||
text_height = font_size_pixels
|
||||
# Handle vertical layout separately if needed
|
||||
if props.prepend_append_layout == 'VERTICAL' and (prepend_text or append_text):
|
||||
# For vertical layout, we need to render each text part separately
|
||||
# and position them vertically with proper margins
|
||||
|
||||
# Calculate dimensions for each text part
|
||||
main_bbox = draw.textbbox((0, 0), main_text, font=font)
|
||||
main_width = max(1, main_bbox[2] - main_bbox[0])
|
||||
main_height = max(1, main_bbox[3] - main_bbox[1])
|
||||
|
||||
total_width = main_width
|
||||
total_height = main_height
|
||||
text_elements = [(main_text, main_width, main_height)]
|
||||
|
||||
if prepend_text:
|
||||
prepend_bbox = draw.textbbox((0, 0), prepend_text, font=font)
|
||||
prepend_width = max(1, prepend_bbox[2] - prepend_bbox[0])
|
||||
prepend_height = max(1, prepend_bbox[3] - prepend_bbox[1])
|
||||
total_width = max(total_width, prepend_width)
|
||||
total_height += prepend_height + prepend_margin_px
|
||||
text_elements.insert(0, (prepend_text, prepend_width, prepend_height))
|
||||
|
||||
if append_text:
|
||||
append_bbox = draw.textbbox((0, 0), append_text, font=font)
|
||||
append_width = max(1, append_bbox[2] - append_bbox[0])
|
||||
append_height = max(1, append_bbox[3] - append_bbox[1])
|
||||
total_width = max(total_width, append_width)
|
||||
total_height += append_height + append_margin_px
|
||||
text_elements.append((append_text, append_width, append_height))
|
||||
|
||||
text_width = total_width
|
||||
text_height = total_height
|
||||
|
||||
print(f"DEBUG VERTICAL LAYOUT - Total dimensions: {text_width}x{text_height}")
|
||||
print(f"DEBUG VERTICAL LAYOUT - Text elements: {len(text_elements)}")
|
||||
|
||||
else:
|
||||
# Standard bbox calculation for horizontal layout or single text
|
||||
try:
|
||||
bbox = draw.textbbox((0, 0), text, font=font)
|
||||
text_width = max(1, bbox[2] - bbox[0])
|
||||
text_height = max(1, bbox[3] - bbox[1])
|
||||
except (OSError, ZeroDivisionError, ValueError) as e:
|
||||
print(f"Error getting text bbox: {e}")
|
||||
text_width = int(len(text) * font_size_pixels * 0.6)
|
||||
text_height = font_size_pixels
|
||||
|
||||
# ============================================================================
|
||||
# ENHANCED POSITIONING SYSTEM - Replaces hardcoded vertical centering
|
||||
@@ -550,10 +633,41 @@ def generate_texture_image(props, width, height):
|
||||
if len(props.text_color) > 3:
|
||||
text_color += (int(props.text_color[3] * 255),)
|
||||
|
||||
print(f"DEBUG UPPERCASE ISSUE - About to draw text: '{text}' with font: {font}")
|
||||
draw.text((x, y), text, fill=text_color, font=font)
|
||||
print(f"Text drawn at ({x}, {y})")
|
||||
print(f"DEBUG UPPERCASE ISSUE - Text drawing completed")
|
||||
# Handle vertical layout rendering
|
||||
if props.prepend_append_layout == 'VERTICAL' and (prepend_text or append_text):
|
||||
print(f"DEBUG VERTICAL LAYOUT - Rendering vertical text layout")
|
||||
|
||||
# Calculate starting Y position for vertical stack
|
||||
current_y = y
|
||||
|
||||
# Render prepend text if exists
|
||||
if prepend_text:
|
||||
print(f"DEBUG VERTICAL LAYOUT - Drawing prepend text: '{prepend_text}' at y={current_y}")
|
||||
draw.text((x, current_y), prepend_text, fill=text_color, font=font)
|
||||
prepend_bbox = draw.textbbox((0, 0), prepend_text, font=font)
|
||||
prepend_height = prepend_bbox[3] - prepend_bbox[1]
|
||||
current_y += prepend_height + prepend_margin_px
|
||||
|
||||
# Render main text
|
||||
print(f"DEBUG VERTICAL LAYOUT - Drawing main text: '{main_text}' at y={current_y}")
|
||||
draw.text((x, current_y), main_text, fill=text_color, font=font)
|
||||
main_bbox = draw.textbbox((0, 0), main_text, font=font)
|
||||
main_height = main_bbox[3] - main_bbox[1]
|
||||
current_y += main_height + append_margin_px
|
||||
|
||||
# Render append text if exists
|
||||
if append_text:
|
||||
print(f"DEBUG VERTICAL LAYOUT - Drawing append text: '{append_text}' at y={current_y}")
|
||||
draw.text((x, current_y), append_text, fill=text_color, font=font)
|
||||
|
||||
print(f"DEBUG VERTICAL LAYOUT - Vertical text rendering completed")
|
||||
|
||||
else:
|
||||
# Standard horizontal rendering
|
||||
print(f"DEBUG UPPERCASE ISSUE - About to draw text: '{text}' with font: {font}")
|
||||
draw.text((x, y), text, fill=text_color, font=font)
|
||||
print(f"Text drawn at ({x}, {y})")
|
||||
print(f"DEBUG UPPERCASE ISSUE - Text drawing completed")
|
||||
|
||||
# Add text to elements list
|
||||
elements.append((0, 'text', text_img, 0, 0))
|
||||
@@ -851,6 +965,12 @@ class TEXT_TEXTURE_Properties(PropertyGroup):
|
||||
default=False
|
||||
)
|
||||
|
||||
expand_colors: BoolProperty(
|
||||
name="Colors",
|
||||
description="Show/hide Colors section",
|
||||
default=False
|
||||
)
|
||||
|
||||
text: StringProperty(
|
||||
name="Text",
|
||||
description="Text to render as texture",
|
||||
@@ -859,6 +979,54 @@ class TEXT_TEXTURE_Properties(PropertyGroup):
|
||||
update=update_live_preview
|
||||
)
|
||||
|
||||
# Prepend/Append Text Properties
|
||||
prepend_text: StringProperty(
|
||||
name="Prepend Text",
|
||||
description="Text to prepend before main text",
|
||||
default="",
|
||||
maxlen=512,
|
||||
update=update_live_preview
|
||||
)
|
||||
|
||||
append_text: StringProperty(
|
||||
name="Append Text",
|
||||
description="Text to append after main text",
|
||||
default="",
|
||||
maxlen=512,
|
||||
update=update_live_preview
|
||||
)
|
||||
|
||||
prepend_margin: FloatProperty(
|
||||
name="Prepend Margin",
|
||||
description="Margin between prepend text and main text as percentage of font size",
|
||||
default=50.0,
|
||||
min=0.0,
|
||||
max=200.0,
|
||||
precision=1,
|
||||
update=update_live_preview
|
||||
)
|
||||
|
||||
append_margin: FloatProperty(
|
||||
name="Append Margin",
|
||||
description="Margin between main text and append text as percentage of font size",
|
||||
default=50.0,
|
||||
min=0.0,
|
||||
max=200.0,
|
||||
precision=1,
|
||||
update=update_live_preview
|
||||
)
|
||||
|
||||
prepend_append_layout: EnumProperty(
|
||||
name="Layout",
|
||||
description="Layout arrangement for prepend/main/append text",
|
||||
items=[
|
||||
('HORIZONTAL', 'Horizontal', 'Arrange text horizontally: [prepend] [main] [append]'),
|
||||
('VERTICAL', 'Vertical', 'Arrange text vertically: prepend above, main center, append below'),
|
||||
],
|
||||
default='HORIZONTAL',
|
||||
update=update_live_preview
|
||||
)
|
||||
|
||||
texture_width: IntProperty(
|
||||
name="Width",
|
||||
description="Texture width in pixels",
|
||||
@@ -1442,8 +1610,16 @@ class TEXT_TEXTURE_OT_save_preset(Operator):
|
||||
|
||||
# Validate preset name characters (avoid filesystem issues)
|
||||
import re
|
||||
if not re.match(r'^[a-zA-Z0-9_\-\s]+$', preset_name):
|
||||
self.report({'ERROR'}, "Preset name can only contain letters, numbers, spaces, hyphens, and underscores")
|
||||
# Allow Unicode letters, numbers, spaces, hyphens, underscores, and common accented characters
|
||||
# This pattern supports international characters like ö, ü, ñ, etc.
|
||||
if not re.match(r'^[\w\s\-]+$', preset_name, re.UNICODE):
|
||||
self.report({'ERROR'}, "Preset name contains invalid characters for filesystem compatibility")
|
||||
return {'CANCELLED'}
|
||||
|
||||
# Additional check for filesystem-unsafe characters
|
||||
invalid_chars = ['<', '>', ':', '"', '|', '?', '*', '/', '\\']
|
||||
if any(char in preset_name for char in invalid_chars):
|
||||
self.report({'ERROR'}, f"Preset name cannot contain: {' '.join(invalid_chars)}")
|
||||
return {'CANCELLED'}
|
||||
|
||||
# Check for duplicate names
|
||||
@@ -1473,6 +1649,11 @@ class TEXT_TEXTURE_OT_save_preset(Operator):
|
||||
'custom_font_path': props.custom_font_path,
|
||||
'use_custom_font': props.use_custom_font,
|
||||
'text_align': props.text_align,
|
||||
'prepend_text': props.prepend_text,
|
||||
'append_text': props.append_text,
|
||||
'prepend_margin': props.prepend_margin,
|
||||
'append_margin': props.append_margin,
|
||||
'prepend_append_layout': props.prepend_append_layout,
|
||||
'image_overlays': []
|
||||
}
|
||||
|
||||
@@ -1587,6 +1768,11 @@ class TEXT_TEXTURE_OT_load_preset(Operator):
|
||||
props.custom_font_path = preset_data.get('custom_font_path', props.custom_font_path)
|
||||
props.use_custom_font = preset_data.get('use_custom_font', props.use_custom_font)
|
||||
props.text_align = preset_data.get('text_align', props.text_align)
|
||||
props.prepend_text = preset_data.get('prepend_text', props.prepend_text)
|
||||
props.append_text = preset_data.get('append_text', props.append_text)
|
||||
props.prepend_margin = preset_data.get('prepend_margin', props.prepend_margin)
|
||||
props.append_margin = preset_data.get('append_margin', props.append_margin)
|
||||
props.prepend_append_layout = preset_data.get('prepend_append_layout', props.prepend_append_layout)
|
||||
|
||||
# Load overlay data
|
||||
props.image_overlays.clear()
|
||||
@@ -1859,6 +2045,25 @@ def draw_positioning_section(layout, props):
|
||||
row.prop(props, "texture_width", text="Width")
|
||||
row.prop(props, "texture_height", text="Height")
|
||||
|
||||
layout.separator()
|
||||
|
||||
# Prepend/Append Text Section
|
||||
layout.label(text="Additional Text:", icon='TEXT')
|
||||
|
||||
# Compact layout selector
|
||||
layout.prop(props, "prepend_append_layout", text="Layout")
|
||||
|
||||
# Minimal prepend/append controls
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "prepend_text", text="Prepend")
|
||||
if props.prepend_text.strip():
|
||||
row.prop(props, "prepend_margin", text="", slider=True)
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "append_text", text="Append")
|
||||
if props.append_text.strip():
|
||||
row.prop(props, "append_margin", text="", slider=True)
|
||||
|
||||
layout.separator()
|
||||
layout.prop(props, "position_mode", text="Mode")
|
||||
|
||||
@@ -1927,20 +2132,26 @@ def draw_font_settings_section(layout, props):
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "padding")
|
||||
row.prop(props, "text_align")
|
||||
|
||||
def draw_colors_section(layout, props):
|
||||
"""Draw color controls for text and background"""
|
||||
layout.label(text="Text Color:", icon='COLOR')
|
||||
layout.prop(props, "text_color", text="")
|
||||
|
||||
layout.separator()
|
||||
layout.label(text="Colors:")
|
||||
layout.prop(props, "text_color")
|
||||
layout.label(text="Background Color:", icon='IMAGE_PLANE')
|
||||
layout.prop(props, "background_transparent")
|
||||
if not props.background_transparent:
|
||||
layout.prop(props, "background_color")
|
||||
layout.prop(props, "background_color", text="")
|
||||
|
||||
def draw_preview_options_section(layout, props):
|
||||
"""Draw preview options"""
|
||||
"""Draw preview options (preview-specific settings only)"""
|
||||
layout.prop(props, "preview_size", text="Preview Size")
|
||||
layout.separator()
|
||||
layout.label(text="Preview Background Display:", icon='SCENE')
|
||||
layout.prop(props, "preview_bg_type", text="Background")
|
||||
if props.preview_bg_type == 'color':
|
||||
layout.prop(props, "preview_bg_color", text="Background Color")
|
||||
layout.prop(props, "preview_bg_color", text="Preview Display Color")
|
||||
elif props.preview_bg_type == 'gradient':
|
||||
layout.prop(props, "preview_bg_color", text="Color 1")
|
||||
layout.prop(props, "preview_bg_color2", text="Color 2")
|
||||
@@ -2048,6 +2259,10 @@ class TEXT_TEXTURE_PT_panel(Panel):
|
||||
layout.separator()
|
||||
draw_generate_button(layout)
|
||||
|
||||
# Preview Button at top level
|
||||
layout.separator()
|
||||
layout.operator("text_texture.view_preview_zoom", text="Open Preview Window", icon='WINDOW')
|
||||
|
||||
layout.separator()
|
||||
|
||||
# COLLAPSIBLE SECTIONS
|
||||
@@ -2067,16 +2282,10 @@ class TEXT_TEXTURE_PT_panel(Panel):
|
||||
if font_section:
|
||||
draw_font_settings_section(font_section, props)
|
||||
|
||||
# Preview Options Section (collapsed by default)
|
||||
preview_section = draw_collapsible_header(layout, "expand_preview_options", "Preview Options", 'IMAGE_DATA')
|
||||
if preview_section:
|
||||
draw_preview_options_section(preview_section, props)
|
||||
|
||||
# Preview Button in expanded section
|
||||
layout.separator()
|
||||
preview_section.separator()
|
||||
button_row = preview_section.row()
|
||||
button_row.operator("text_texture.view_preview_zoom", text="Open Preview Window", icon='WINDOW')
|
||||
# Colors Section (collapsed by default)
|
||||
colors_section = draw_collapsible_header(layout, "expand_colors", "Colors", 'COLOR')
|
||||
if colors_section:
|
||||
draw_colors_section(colors_section, props)
|
||||
|
||||
# Presets Section (collapsed by default)
|
||||
presets_section = draw_collapsible_header(layout, "expand_presets", "Presets", 'PRESET')
|
||||
@@ -2108,6 +2317,10 @@ class TEXT_TEXTURE_PT_panel_3d(Panel):
|
||||
layout.separator()
|
||||
draw_generate_button(layout)
|
||||
|
||||
# Preview Button at top level
|
||||
layout.separator()
|
||||
layout.operator("text_texture.view_preview_zoom", text="Open Preview Window", icon='WINDOW')
|
||||
|
||||
layout.separator()
|
||||
|
||||
# COLLAPSIBLE SECTIONS
|
||||
@@ -2127,15 +2340,10 @@ class TEXT_TEXTURE_PT_panel_3d(Panel):
|
||||
if font_section:
|
||||
draw_font_settings_section(font_section, props)
|
||||
|
||||
# Preview Options Section (collapsed by default)
|
||||
preview_section = draw_collapsible_header(layout, "expand_preview_options", "Preview Options", 'IMAGE_DATA')
|
||||
if preview_section:
|
||||
draw_preview_options_section(preview_section, props)
|
||||
|
||||
# Preview Button in expanded section
|
||||
preview_section.separator()
|
||||
button_row = preview_section.row()
|
||||
button_row.operator("text_texture.view_preview_zoom", text="Open Preview Window", icon='WINDOW')
|
||||
# Colors Section (collapsed by default)
|
||||
colors_section = draw_collapsible_header(layout, "expand_colors", "Colors", 'COLOR')
|
||||
if colors_section:
|
||||
draw_colors_section(colors_section, props)
|
||||
|
||||
# Presets Section (collapsed by default)
|
||||
presets_section = draw_collapsible_header(layout, "expand_presets", "Presets", 'PRESET')
|
||||
@@ -2167,6 +2375,10 @@ class TEXT_TEXTURE_PT_panel_properties(Panel):
|
||||
layout.separator()
|
||||
draw_generate_button(layout)
|
||||
|
||||
# Preview Button at top level
|
||||
layout.separator()
|
||||
layout.operator("text_texture.view_preview_zoom", text="Open Preview Window", icon='WINDOW')
|
||||
|
||||
layout.separator()
|
||||
|
||||
# COLLAPSIBLE SECTIONS
|
||||
@@ -2186,15 +2398,10 @@ class TEXT_TEXTURE_PT_panel_properties(Panel):
|
||||
if font_section:
|
||||
draw_font_settings_section(font_section, props)
|
||||
|
||||
# Preview Options Section (collapsed by default)
|
||||
preview_section = draw_collapsible_header(layout, "expand_preview_options", "Preview Options", 'IMAGE_DATA')
|
||||
if preview_section:
|
||||
draw_preview_options_section(preview_section, props)
|
||||
|
||||
# Preview Button in expanded section
|
||||
preview_section.separator()
|
||||
button_row = preview_section.row()
|
||||
button_row.operator("text_texture.view_preview_zoom", text="Open Preview Window", icon='WINDOW')
|
||||
# Colors Section (collapsed by default)
|
||||
colors_section = draw_collapsible_header(layout, "expand_colors", "Colors", 'COLOR')
|
||||
if colors_section:
|
||||
draw_colors_section(colors_section, props)
|
||||
|
||||
# Presets Section (collapsed by default)
|
||||
presets_section = draw_collapsible_header(layout, "expand_presets", "Presets", 'PRESET')
|
||||
|
||||
150
test_preset_unicode.py
Normal file
150
test_preset_unicode.py
Normal file
@@ -0,0 +1,150 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script to verify that preset names with Unicode characters like 'ö' work correctly.
|
||||
This script tests the validation logic outside of Blender.
|
||||
"""
|
||||
|
||||
import re
|
||||
import json
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
def test_preset_name_validation():
|
||||
"""Test the new preset name validation regex"""
|
||||
|
||||
# Test cases with expected results
|
||||
test_cases = [
|
||||
# Valid names (should pass)
|
||||
("Test Preset", True),
|
||||
("Mein schönes Preset", True), # German with ö
|
||||
("Préférence française", True), # French with accents
|
||||
("Configuración español", True), # Spanish with ñ
|
||||
("Test_123", True),
|
||||
("Hello-World", True),
|
||||
("Тест", True), # Cyrillic
|
||||
("テスト", True), # Japanese
|
||||
("测试", True), # Chinese
|
||||
|
||||
# Invalid names (should fail)
|
||||
("Test<Preset", False), # Contains <
|
||||
("Test>Preset", False), # Contains >
|
||||
("Test:Preset", False), # Contains :
|
||||
("Test\"Preset", False), # Contains "
|
||||
("Test|Preset", False), # Contains |
|
||||
("Test?Preset", False), # Contains ?
|
||||
("Test*Preset", False), # Contains *
|
||||
("Test/Preset", False), # Contains /
|
||||
("Test\\Preset", False), # Contains \
|
||||
("", False), # Empty string
|
||||
]
|
||||
|
||||
print("Testing preset name validation...")
|
||||
|
||||
for preset_name, should_pass in test_cases:
|
||||
# Test the Unicode regex pattern
|
||||
unicode_pattern_match = bool(re.match(r'^[\w\s\-]+$', preset_name, re.UNICODE))
|
||||
|
||||
# Test filesystem-unsafe characters
|
||||
invalid_chars = ['<', '>', ':', '"', '|', '?', '*', '/', '\\']
|
||||
has_invalid_chars = any(char in preset_name for char in invalid_chars)
|
||||
|
||||
# Combined validation (same as in the actual code)
|
||||
validation_passes = unicode_pattern_match and not has_invalid_chars and preset_name.strip()
|
||||
|
||||
status = "✅ PASS" if validation_passes == should_pass else "❌ FAIL"
|
||||
print(f"{status}: '{preset_name}' -> Expected: {should_pass}, Got: {validation_passes}")
|
||||
|
||||
if validation_passes != should_pass:
|
||||
print(f" Unicode match: {unicode_pattern_match}, Has invalid chars: {has_invalid_chars}")
|
||||
|
||||
def test_json_serialization():
|
||||
"""Test that Unicode characters work correctly with JSON serialization/deserialization"""
|
||||
|
||||
print("\nTesting JSON serialization with Unicode characters...")
|
||||
|
||||
test_data = {
|
||||
'name': 'Schönes Preset',
|
||||
'text': 'Höllö Wörld',
|
||||
'texture_width': 1024,
|
||||
'texture_height': 1024,
|
||||
'font_size': 96
|
||||
}
|
||||
|
||||
try:
|
||||
# Test JSON encoding/decoding
|
||||
json_str = json.dumps(test_data, indent=2, ensure_ascii=False)
|
||||
decoded_data = json.loads(json_str)
|
||||
|
||||
print("✅ JSON serialization successful")
|
||||
print(f"Original name: {test_data['name']}")
|
||||
print(f"Decoded name: {decoded_data['name']}")
|
||||
print(f"Names match: {test_data['name'] == decoded_data['name']}")
|
||||
|
||||
# Test file I/O
|
||||
with tempfile.NamedTemporaryFile(mode='w', suffix='.json', delete=False) as f:
|
||||
json.dump(test_data, f, indent=2, ensure_ascii=False)
|
||||
temp_file = f.name
|
||||
|
||||
with open(temp_file, 'r', encoding='utf-8') as f:
|
||||
file_data = json.load(f)
|
||||
|
||||
os.unlink(temp_file)
|
||||
|
||||
print("✅ File I/O successful")
|
||||
print(f"File data name: {file_data['name']}")
|
||||
print(f"File names match: {test_data['name'] == file_data['name']}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ JSON serialization failed: {e}")
|
||||
|
||||
def test_filesystem_compatibility():
|
||||
"""Test creating files with Unicode names"""
|
||||
|
||||
print("\nTesting filesystem compatibility...")
|
||||
|
||||
test_names = [
|
||||
"schönes_preset",
|
||||
"café_preset",
|
||||
"naïve_preset",
|
||||
"test_ñ_preset"
|
||||
]
|
||||
|
||||
temp_dir = tempfile.mkdtemp()
|
||||
print(f"Testing in directory: {temp_dir}")
|
||||
|
||||
for name in test_names:
|
||||
try:
|
||||
filename = f"{name}.json"
|
||||
filepath = os.path.join(temp_dir, filename)
|
||||
|
||||
# Create file
|
||||
with open(filepath, 'w', encoding='utf-8') as f:
|
||||
json.dump({'name': name}, f, ensure_ascii=False)
|
||||
|
||||
# Read file back
|
||||
with open(filepath, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
# Clean up
|
||||
os.unlink(filepath)
|
||||
|
||||
print(f"✅ {name}: File created and read successfully")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ {name}: Failed - {e}")
|
||||
|
||||
# Clean up temp directory
|
||||
os.rmdir(temp_dir)
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("Testing Text Texture Generator Preset Unicode Support")
|
||||
print("=" * 60)
|
||||
|
||||
test_preset_name_validation()
|
||||
test_json_serialization()
|
||||
test_filesystem_compatibility()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("Test completed! Check results above.")
|
||||
print("=" * 60)
|
||||
Reference in New Issue
Block a user