Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -76,82 +76,117 @@ def render_translated_overlay(original_image: Image.Image, text_to_overlay: str,
|
|
76 |
font_size = 100
|
77 |
final_wrapped_lines = []
|
78 |
|
79 |
-
# ### --- FIX --- ###:
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
print(f"RTL processing error: {e}")
|
86 |
-
processed_text = text_to_overlay # Fallback to original text
|
87 |
-
|
88 |
-
while font_size > 10:
|
89 |
-
font = ImageFont.truetype(PERSIAN_FONT_PATH, font_size)
|
90 |
-
|
91 |
-
# ### --- FIX --- ###: Split by spaces but work with processed RTL text
|
92 |
-
words = processed_text.split()
|
93 |
-
if not words:
|
94 |
-
break
|
95 |
-
|
96 |
-
raw_lines = []
|
97 |
-
current_line = ""
|
98 |
|
99 |
for word in words:
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
-
if
|
105 |
-
|
106 |
else:
|
107 |
-
|
108 |
-
|
109 |
-
|
|
|
110 |
|
111 |
-
|
112 |
-
|
|
|
113 |
|
114 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
total_height = 0
|
116 |
-
for line in
|
117 |
-
|
118 |
-
|
119 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
120 |
|
121 |
if total_height <= overlay_height * 0.9:
|
122 |
-
final_wrapped_lines =
|
123 |
break
|
124 |
else:
|
125 |
font_size -= 2
|
126 |
|
127 |
-
if not final_wrapped_lines
|
128 |
-
final_wrapped_lines =
|
129 |
|
130 |
-
# ### ---
|
131 |
final_font = ImageFont.truetype(PERSIAN_FONT_PATH, font_size)
|
132 |
line_spacing = font_size * 0.3
|
133 |
|
134 |
-
# Calculate line heights
|
135 |
line_heights = []
|
|
|
|
|
136 |
for line in final_wrapped_lines:
|
137 |
-
|
138 |
-
|
139 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
140 |
|
141 |
-
total_text_height = sum(line_heights) + (len(
|
142 |
y_start = (overlay_height - total_text_height) / 2
|
143 |
|
|
|
144 |
current_y = y_start
|
145 |
-
for i,
|
146 |
# Calculate line width and center position
|
147 |
-
line_bbox = draw.textbbox((0, 0),
|
148 |
line_width = line_bbox[2] - line_bbox[0]
|
149 |
x_position = (overlay_width - line_width) / 2
|
150 |
|
151 |
# Draw shadow for better readability
|
152 |
-
draw.text((x_position + 1, current_y + 1),
|
153 |
# Draw main text
|
154 |
-
draw.text((x_position, current_y),
|
155 |
|
156 |
current_y += line_heights[i] + line_spacing
|
157 |
|
|
|
76 |
font_size = 100
|
77 |
final_wrapped_lines = []
|
78 |
|
79 |
+
# ### --- COMPLETE FIX --- ###: Handle RTL text properly
|
80 |
+
def wrap_persian_text(text, font, max_width):
|
81 |
+
"""Properly wrap Persian text maintaining RTL flow"""
|
82 |
+
words = text.split() # Split ORIGINAL text, not processed text
|
83 |
+
lines = []
|
84 |
+
current_line_words = []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
85 |
|
86 |
for word in words:
|
87 |
+
# Test with current line + new word
|
88 |
+
test_words = current_line_words + [word]
|
89 |
+
test_line = ' '.join(test_words)
|
90 |
+
|
91 |
+
# Process this test line for RTL to get actual display width
|
92 |
+
try:
|
93 |
+
reshaped_test = arabic_reshaper.reshape(test_line)
|
94 |
+
display_test = get_display(reshaped_test)
|
95 |
+
test_width = draw.textbbox((0, 0), display_test, font=font)[2]
|
96 |
+
except:
|
97 |
+
# Fallback if RTL processing fails
|
98 |
+
test_width = draw.textbbox((0, 0), test_line, font=font)[2]
|
99 |
|
100 |
+
if test_width <= max_width:
|
101 |
+
current_line_words.append(word)
|
102 |
else:
|
103 |
+
# Save current line and start new one
|
104 |
+
if current_line_words:
|
105 |
+
lines.append(' '.join(current_line_words))
|
106 |
+
current_line_words = [word]
|
107 |
|
108 |
+
# Don't forget the last line
|
109 |
+
if current_line_words:
|
110 |
+
lines.append(' '.join(current_line_words))
|
111 |
|
112 |
+
return lines
|
113 |
+
|
114 |
+
# Find the right font size
|
115 |
+
while font_size > 10:
|
116 |
+
font = ImageFont.truetype(PERSIAN_FONT_PATH, font_size)
|
117 |
+
|
118 |
+
# Wrap text with current font size
|
119 |
+
wrapped_lines = wrap_persian_text(text_to_overlay, font, target_width)
|
120 |
+
|
121 |
+
# Calculate total height needed
|
122 |
total_height = 0
|
123 |
+
for line in wrapped_lines:
|
124 |
+
try:
|
125 |
+
# Process each line for RTL to get accurate height
|
126 |
+
reshaped_line = arabic_reshaper.reshape(line)
|
127 |
+
display_line = get_display(reshaped_line)
|
128 |
+
line_bbox = draw.textbbox((0, 0), display_line, font=font)
|
129 |
+
line_height = line_bbox[3] - line_bbox[1]
|
130 |
+
total_height += line_height
|
131 |
+
except:
|
132 |
+
# Fallback height calculation
|
133 |
+
line_bbox = draw.textbbox((0, 0), line, font=font)
|
134 |
+
line_height = line_bbox[3] - line_bbox[1]
|
135 |
+
total_height += line_height
|
136 |
+
|
137 |
+
# Add spacing between lines
|
138 |
+
total_height += (len(wrapped_lines) - 1) * (font_size * 0.3)
|
139 |
|
140 |
if total_height <= overlay_height * 0.9:
|
141 |
+
final_wrapped_lines = wrapped_lines
|
142 |
break
|
143 |
else:
|
144 |
font_size -= 2
|
145 |
|
146 |
+
if not final_wrapped_lines: # Fallback
|
147 |
+
final_wrapped_lines = [text_to_overlay]
|
148 |
|
149 |
+
# ### --- RENDER TEXT WITH PROPER RTL --- ###
|
150 |
final_font = ImageFont.truetype(PERSIAN_FONT_PATH, font_size)
|
151 |
line_spacing = font_size * 0.3
|
152 |
|
153 |
+
# Calculate line heights and positions
|
154 |
line_heights = []
|
155 |
+
processed_lines = [] # Store the RTL-processed lines
|
156 |
+
|
157 |
for line in final_wrapped_lines:
|
158 |
+
try:
|
159 |
+
# Process each line individually for RTL
|
160 |
+
reshaped_line = arabic_reshaper.reshape(line)
|
161 |
+
display_line = get_display(reshaped_line)
|
162 |
+
processed_lines.append(display_line)
|
163 |
+
|
164 |
+
line_bbox = draw.textbbox((0, 0), display_line, font=final_font)
|
165 |
+
line_height = line_bbox[3] - line_bbox[1]
|
166 |
+
line_heights.append(line_height)
|
167 |
+
except Exception as e:
|
168 |
+
print(f"RTL processing failed for line '{line}': {e}")
|
169 |
+
# Fallback to original line
|
170 |
+
processed_lines.append(line)
|
171 |
+
line_bbox = draw.textbbox((0, 0), line, font=final_font)
|
172 |
+
line_height = line_bbox[3] - line_bbox[1]
|
173 |
+
line_heights.append(line_height)
|
174 |
|
175 |
+
total_text_height = sum(line_heights) + (len(processed_lines) - 1) * line_spacing
|
176 |
y_start = (overlay_height - total_text_height) / 2
|
177 |
|
178 |
+
# Draw each line
|
179 |
current_y = y_start
|
180 |
+
for i, display_line in enumerate(processed_lines):
|
181 |
# Calculate line width and center position
|
182 |
+
line_bbox = draw.textbbox((0, 0), display_line, font=final_font)
|
183 |
line_width = line_bbox[2] - line_bbox[0]
|
184 |
x_position = (overlay_width - line_width) / 2
|
185 |
|
186 |
# Draw shadow for better readability
|
187 |
+
draw.text((x_position + 1, current_y + 1), display_line, font=final_font, fill=(0, 0, 0, 180))
|
188 |
# Draw main text
|
189 |
+
draw.text((x_position, current_y), display_line, font=final_font, fill=(255, 255, 255, 255))
|
190 |
|
191 |
current_y += line_heights[i] + line_spacing
|
192 |
|