Zirnavis100 / styles /classic.py
Transfer Bot
Moved to Hugging Face automatically
8e64a96
Raw
History Blame Contribute Delete
8.18 kB
from PIL import Image, ImageDraw, ImageFont
config = {
"ids": ["classic", "plain_white", "white_outline", "progressive_write"],
"name": "Classic Styles",
"panels": ["color", "font", "size", "position", "radius", "padding"],
"default_font": "vazir"
}
def draw_frame(draw, img, width, height, style_config, lines, line_metrics, active_idx, font, color_parser, word_infos=None):
style_name = style_config.name
is_rtl = getattr(style_config, 'text_direction', 'rtl') != 'ltr'
base_text_color = color_parser(style_config.primaryColor, (255, 255, 255, 255))
stroke_color = color_parser(style_config.outlineColor, (0, 0, 0, 255))
stroke_width = 0
if style_name == "plain_white":
c_hex = style_config.styleColors.get('plain_white', '#ffffff')
base_text_color = color_parser(c_hex, (255, 255, 255, 255))
elif style_name == "white_outline":
c_hex = style_config.styleColors.get('white_outline', '#ffffff')
base_text_color = color_parser(c_hex, (255, 255, 255, 255))
custom_stroke_hex = style_config.styleBgColors.get('white_outline_stroke', '#000000')
stroke_color = color_parser(custom_stroke_hex, (0, 0, 0, 255))
stroke_width = max(2, int(style_config.fontSize / 12))
elif style_config.backType == 'outline':
stroke_width = max(2, int(style_config.fontSize / 12))
line_height_px = int(style_config.fontSize * 1.5)
total_block_height = len(lines) * line_height_px
bottom_reference = height - style_config.marginV
start_y_of_block = bottom_reference - total_block_height
space_w = draw.textlength(" ", font=font)
max_line_width = 0
for m in line_metrics:
# محاسبه واقعی عرض خط با جمع زدن تک تک کلمات برای دقت صد در صد
actual_w = sum(m["word_widths"]) + max(0, len(m["words"]) - 1) * space_w
if actual_w > max_line_width: max_line_width = actual_w
# --- رسم کادر کلی (Container) ---
should_draw_box = False
box_fill_color = (0,0,0,0)
if style_name in ["classic", "progressive_write"] and style_config.backType in ['solid', 'transparent']:
should_draw_box = True
fill_color_tuple = color_parser(style_config.outlineColor, (0, 0, 0, 255))
if style_config.backType == 'transparent' and fill_color_tuple[3] == 255:
fill_color_tuple = (fill_color_tuple[0], fill_color_tuple[1], fill_color_tuple[2], 160)
box_fill_color = fill_color_tuple
# استخراج محاسبات کادر به بیرون از شرط برای استفاده به عنوان مبنای رسم متن
ratio = height / width
box_center_y_adjustment = 0
if ratio > 1.6: box_center_y_adjustment = 5
elif ratio > 1.1: box_center_y_adjustment = 10
else: box_center_y_adjustment = 15
box_center_x = width / 2 + style_config.x
# کاهش 16 پیکسل از عرض کادر برای جمع‌تر شدن در سمت چپ و راست
box_width = max_line_width + (style_config.paddingX * 2) - 16
box_x1 = box_center_x - (box_width / 2)
box_x2 = box_center_x + (box_width / 2)
visual_top_correction = int(style_config.fontSize * 0.12)
# نقطه مبنای رسم کادر (برای حفظ جایگاه دقیق متن)
base_y1 = start_y_of_block - style_config.paddingY + box_center_y_adjustment + visual_top_correction
# تنظیم دقیق ارتفاع کادر: کاهش تنها ۱۵ درصدی (برای متعادل شدن بالا و پایین کادر)
box_y1 = base_y1 + (style_config.paddingY * 0.15)
box_y2 = start_y_of_block + total_block_height + (style_config.paddingY * 0.85) + box_center_y_adjustment - (line_height_px * 0.3)
if should_draw_box:
draw.rounded_rectangle([box_x1, box_y1, box_x2, box_y2], radius=style_config.radius, fill=box_fill_color)
# --- رسم متن ---
# تراز کردن متن نسبت به نقطه مبنا (base_y1) تا با کوچک شدن کادر، متن جابجا نشود
text_start_y = base_y1 + (style_config.paddingY * 0.35)
vertical_corr = int(style_config.fontSize * 0.1)
current_line_y = text_start_y - vertical_corr
global_word_counter = 0
for line_idx, metrics in enumerate(line_metrics):
# محاسبه عرض دقیق و واقعی خط برای وسط‌چین شدن کامل درون کادر
actual_line_width = sum(metrics["word_widths"]) + max(0, len(metrics["words"]) - 1) * space_w
if is_rtl:
start_x = (width + actual_line_width) / 2 + style_config.x
else:
start_x = (width - actual_line_width) / 2 + style_config.x
cursor_x = start_x
text_y_pos = current_line_y
for w_i, word in enumerate(metrics["words"]):
w_len = metrics["word_widths"][w_i]
word_x = (cursor_x - w_len) if is_rtl else cursor_x
# تنظیم رنگ پیش‌فرض
current_word_color = base_text_color
# --- تغییر جدید: اعمال رنگ کلمه فعال برای تمامی استایل‌های کلاسیک و تایپی ---
if style_name in ["white_outline", "plain_white", "classic", "progressive_write"] and active_idx != -1 and global_word_counter == active_idx and getattr(style_config, 'useActiveColor', True):
active_hex = style_config.styleActiveColors.get(style_name, '#ffffff')
current_word_color = color_parser(active_hex, base_text_color)
# ------------------------------------------------------------
current_stroke_fill = stroke_color
current_stroke_width = stroke_width
if word_infos and global_word_counter < len(word_infos):
w_obj = word_infos[global_word_counter]
if hasattr(w_obj, 'color') and w_obj.color:
current_word_color = color_parser(w_obj.color, current_word_color)
display_word = word
draw_x = word_x
should_draw_this_word = True
is_typewriter = getattr(style_config, 'typewriter', False)
if style_name == "progressive_write":
if active_idx != -1 and global_word_counter > active_idx:
should_draw_this_word = False
elif is_typewriter and word_infos and global_word_counter < len(word_infos):
w_info = word_infos[global_word_counter]
current_t = getattr(style_config, 'current_render_time', 0.0)
if current_t < w_info.start:
should_draw_this_word = False
elif current_t >= w_info.start and current_t < w_info.end:
char_len = len(word)
progress = (current_t - w_info.start) / max(0.001, w_info.end - w_info.start)
visible_chars = min(char_len, int(progress * char_len) + 1)
display_word = word[:visible_chars]
try: sub_w = draw.textlength(display_word, font=font, direction=getattr(style_config, 'text_direction', 'rtl'), language=getattr(style_config, 'lang_code', 'fa'))
except: sub_w = font.getlength(display_word)
draw_x = (cursor_x - sub_w) if is_rtl else word_x
if should_draw_this_word and display_word:
draw.text((draw_x, text_y_pos), display_word, font=font, fill=current_word_color,
stroke_width=current_stroke_width, stroke_fill=current_stroke_fill,
direction=getattr(style_config, 'text_direction', 'rtl'), language=getattr(style_config, 'lang_code', 'fa'))
# مکان نما باید جلو برود حتی اگر کلمه رسم نشده باشد (تا جای خالی‌اش حفظ شود)
if is_rtl:
cursor_x -= (w_len + space_w)
else:
cursor_x += (w_len + space_w)
global_word_counter += 1
current_line_y += line_height_px