Zirnavis / styles /blue_cloud.py
Transfer Bot
Moved to Hugging Face automatically
34d3ca9
Raw
History Blame Contribute Delete
7.2 kB
from PIL import Image, ImageDraw, ImageFont, ImageFilter
config = {
"ids": ["blue_cloud"],
"name": "Blue Cloud",
"panels": ["font", "size", "position"],
"default_font": "lalezar"
}
frontend_template = ""
def draw_frame(draw, img, width, height, style_config, lines, line_metrics, active_idx, font, color_parser, word_infos=None):
is_rtl = getattr(style_config, 'text_direction', 'rtl') != 'ltr'
# --- محاسبات جایگاه متن ---
line_height_px = int(style_config.fontSize * 1.5)
total_text_height = len(lines) * line_height_px
center_x = width / 2 + (style_config.x or 0)
bottom_margin = style_config.marginV
start_y = height - bottom_margin - total_text_height
vertical_correction = int(style_config.fontSize * 0.1)
current_text_y = start_y - vertical_correction
# --- تنظیمات رنگ دقیق (داینامیک شده) ---
# دریافت رنگ متن از پنل کاربر (پیش‌فرض آبی روشن اگر چیزی انتخاب نکرده باشد)
custom_hex = style_config.styleColors.get('blue_cloud', '#00b4ff')
text_fill = color_parser(custom_hex, (0, 180, 255, 255))
stroke_color = (255, 255, 255, 255) # سفید خالص
# --- اصلاح ضخامت‌ها و فاصله‌ها ---
# ضخامت حاشیه سفید (کاهش یافته برای ظرافت)
stroke_w = max(2, int(style_config.fontSize * 0.072))
# ضخامت هاله
cloud_stroke_w = max(5, int(style_config.fontSize * 0.275))
cloud_blur = 5
# استانداردسازی دقیق فاصله کلمات (دقیقاً مشابه استایل‌های ساده)
space_w = draw.textlength(" ", font=font)
actual_space_w = space_w
# --- مرحله ۱: جمع‌آوری مختصات دقیق تمام کلمات ---
words_to_draw = []
global_word_counter = 0
for line_idx, metrics in enumerate(line_metrics):
# عرض خط دقیقاً همان عرض محاسبه شده پیش‌فرض است بدون هیچ فاصله اضافی
total_extra_spacing = 0
adjusted_line_width = metrics["width"] + total_extra_spacing
cursor_x = (center_x + (adjusted_line_width / 2)) if is_rtl else (center_x - (adjusted_line_width / 2))
for w_i, word in enumerate(metrics["words"]):
w_len = metrics["word_widths"][w_i]
word_x = int(cursor_x - w_len) if is_rtl else int(cursor_x)
word_y = int(current_text_y)
# تعیین رنگ کلمه فعال (پیش‌فرض همان رنگ متن)
is_active = (global_word_counter == active_idx) and getattr(style_config, 'useActiveColor', True)
active_hex = style_config.styleActiveColors.get('blue_cloud', custom_hex)
current_word_color = color_parser(active_hex, text_fill) if is_active else text_fill
# اگر کاربر از ابزار رنگ کلمات برای رنگ کردن یک کلمه خاص استفاده کرده باشد، اینجا اعمال می‌شود
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 = True
is_typewriter = getattr(style_config, 'typewriter', False)
if 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 = 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 = int(cursor_x - sub_w) if is_rtl else draw_x
if should_draw and display_word:
words_to_draw.append({
"text": display_word,
"x": draw_x,
"y": word_y,
"color": current_word_color
})
cursor_x += (-(w_len + actual_space_w) if is_rtl else (w_len + actual_space_w))
global_word_counter += 1
current_text_y += line_height_px
# --- مرحله ۲: رسم هاله (Cloud) با رنگ داینامیک و تراز هوشمند ---
glow_layer = Image.new('RGBA', (width, height), (0, 0, 0, 0))
g_draw = ImageDraw.Draw(glow_layer)
# اصلاح تراز عمودی هاله (ابر) اختصاصاً برای فونت‌های خاص
glow_y_offset = 0
if style_config.font == 'pinar':
glow_y_offset = -int(cloud_stroke_w * 0.6) # هدایت به سمت بالا
elif style_config.font in ['dastnevis', 'entazar', 'kamran']:
glow_y_offset = int(cloud_stroke_w * 0.6) # هدایت به سمت پایین
for item in words_to_draw:
# استخراج رنگ خودِ این کلمه و اختصاص آن به ابرش (با کمی شفافیت: 230)
r, g, b, _ = item["color"]
current_cloud_color = (r, g, b, 230)
g_draw.text((item["x"], item["y"] + glow_y_offset), item["text"], font=font, fill=current_cloud_color,
stroke_width=cloud_stroke_w, stroke_fill=current_cloud_color,
direction=getattr(style_config, 'text_direction', 'rtl'), language=getattr(style_config, 'lang_code', 'fa'))
# محو کردن کل لایه هاله
glow_layer = glow_layer.filter(ImageFilter.GaussianBlur(cloud_blur))
# چسباندن لایه هاله در پس‌زمینه
img.paste(glow_layer, (0, 0), glow_layer)
# --- مرحله ۳: رسم حاشیه سفید ---
for item in words_to_draw:
draw.text((item["x"], item["y"]), item["text"], font=font, fill=stroke_color,
stroke_width=stroke_w, stroke_fill=stroke_color,
direction=getattr(style_config, 'text_direction', 'rtl'), language=getattr(style_config, 'lang_code', 'fa'))
# --- مرحله ۴: رسم رنگ اصلی متن روی لایه‌های قبلی ---
for item in words_to_draw:
draw.text((item["x"], item["y"]), item["text"], font=font, fill=item["color"],
direction=getattr(style_config, 'text_direction', 'rtl'), language=getattr(style_config, 'lang_code', 'fa'))