2025, Oct 06 05:33

Arcade में .ttf फ़ॉन्ट लोड करें और internal font name से रेंडरिंग ठीक करें

Arcade/pyglet में कस्टम .ttf सही तरह रेंडर करें: FreeType से internal font name निकालें और वही font_name दें. चरण-दर-चरण कोड व Windows/Linux टिप्स शामिल.

Arcade प्रोजेक्ट में कस्टम .ttf जोड़ना भ्रामक हो सकता है: फ़ॉन्ट फ़ाइल बिना किसी त्रुटि के लोड हो जाती है, लेकिन टेक्स्ट Segoe UI जैसी फ़ॉलबैक से रेंडर होता है। आम शंकाएं—फ़ाइल नाम, फ़ॉन्ट व्यूअर में दिखने वाला डिस्प्ले नाम, या मेटाडेटा स्ट्रिंग्स—ज़रूरी नहीं कि उसी पहचानकर्ता से मेल खाएँ जिसका उपयोग Arcade/pyglet ड्रॉ करते समय वास्तव में करता है। असली कुंजी फ़ॉन्ट के भीतर एम्बेड किया हुआ उसका internal font name है.

समस्या का परिदृश्य

आप फ़ॉन्ट फ़ाइल लोड करते हैं और Arcade टेक्स्ट ऑब्जेक्ट बनाते समय एक सही दिखने वाला नाम पास करते हैं, फिर भी फ़ॉलबैक लग जाता है:

arcade.load_font("Assets/Fonts/CopperplateGothic.ttf")
self.label_actions = arcade.Text(
    "Actions",
    font_name="CopperplateGothicStd-32BC",
    color=accent_color,
    font_size=32,
    x=0,
    y=btn_y + btn_h + 20,
    batch=self.title_batch,
)
print(self.label_actions.font_name)

Windows फ़ॉन्ट व्यूअर में दिखने वाला लेबल (उदाहरण के लिए, “Copperplate Std 32 BC”), फ़ाइल प्रॉपर्टी का मान (“CopperplateGothicStd-32BC”), या फ़ाइल नाम एक्सटेंशन के साथ/बिना आज़माने से भी कुछ नहीं बदलता। वहीं, “MS Comic Sans” जैसा कोई ज्ञात सिस्टम फ़ॉन्ट चुनना अपेक्षानुसार काम करता है, जिससे स्पष्ट होता है कि फ़ॉन्ट खोज स्वयं काम कर रही है।

असल में हो क्या रहा है

Arcade फ़ॉन्ट प्रबंधन के लिए अंदरूनी तौर पर pyglet का उपयोग करता है। font_name में जो स्ट्रिंग आप पास करते हैं, उसे pyglet फ़ॉन्ट के internal name से मिलाता है—ना कि किसी भी डिस्प्ले नाम या फ़ाइल नाम से। यह internal name pyglet के FreeType-आधारित लोडर से पढ़ा जाता है और UI टूल्स में दिखने वाले नाम से अलग हो सकता है। अगर आप कोई और स्ट्रिंग देते हैं, तो pyglet फ़ेस को resolve नहीं कर पाता और चुपचाप फ़ॉलबैक कर देता है।

pyglet के FreeTypeFace से आप सीधे internal name देख सकते हैं:

import pyglet.font.freetype
font_path = "Copperplate-Gothic-Std-32-BC.ttf"
face = pyglet.font.freetype.FreeTypeFace.from_file(font_path)
print(face.name)

परीक्षित फ़ाइल के लिए यह “Copperplate Gothic Std” प्रिंट करता है। यही वह मान है जिसे pyglet फ़ॉन्ट चुनते समय resolve करता है, और arcade.load_font भी इसी तंत्र का उपयोग करता है (अंदरूनी तौर पर pyglet.font.add_file पर निर्भर करता है)।

आप सीधे pyglet से भी सत्यापित कर सकते हैं कि यह नाम उपयोग के लिए मान्य है:

import pyglet
font_path = "Copperplate-Gothic-Std-32-BC.ttf"
pyglet.font.add_file(font_path)
family_name = "Copperplate Gothic Std"
resolved = pyglet.font.load(family_name)
print(resolved.name)

Arcade में उपयोग कैसे ठीक करें

जब आपके पास internal font family आ जाए, तो Arcade टेक्स्ट बनाते समय उसी मान को font_name के रूप में दें। नीचे एक छोटा उदाहरण है जो फ़ाइल लोड करता है और ठीक उसी नाम से रेंडर करता है:

import arcade
WIN_W = 400
WIN_H = 300
APP_TITLE = "Example"
font_path = "Copperplate-Gothic-Std-32-BC.ttf"
family_name = "Copperplate Gothic Std"
class Demo(arcade.Window):
    def __init__(self):
        super().__init__(WIN_W, WIN_H, APP_TITLE)
        arcade.load_font(font_path)
        self.lbl = arcade.Text(
            "Actions",
            font_name=family_name,
            font_size=32,
            x=WIN_W // 2,
            y=WIN_H // 2,
            anchor_x="center",
            anchor_y="center",
        )
        print(self.lbl.font_name)
    def on_draw(self):
        self.clear()
        self.lbl.draw()
if __name__ == "__main__":
    Demo()
    arcade.run()

प्लेटफॉर्म नोट्स

pyglet में लोडिंग पथ OS के अनुसार भिन्न हो सकता है। खासकर Windows पर Win32DirectWriteFont या GDIPlusFont का उपयोग हो सकता है, जबकि ऊपर का परीक्षण Linux पर किया गया था। एक मामले में, वही फ़ॉन्ट और वही कोड Linux पर सही रेंडर हुआ, लेकिन Windows पर दिखाई नहीं दिया; बस कोई दूसरा फ़ॉन्ट चुनने से समस्या दूर हो गई।

यह क्यों मायने रखता है

टेक्स्ट रेंडरिंग UI का मूल हिस्सा है। गलत पहचानकर्ता इस्तेमाल करने से अनपेक्षित फ़ॉलबैक, असंगत स्टाइलिंग और मुश्किल से दोहराए जाने वाले बग सामने आते हैं। Internal font name लेकर आप सुनिश्चित करते हैं कि रेंडरर इच्छित फ़ेस ही चुने और हर रन में सुसंगत परिणाम दे। अलग-अलग ऑपरेटिंग सिस्टम पर डीबग करते समय चयन-तंत्र को ठीक-ठीक जानना फीडबैक चक्र को छोटा कर देता है।

मुख्य निष्कर्ष

Arcade के जरिए .ttf लोड करें, लेकिन फ़ॉन्ट का चयन pyglet के FreeTypeFace द्वारा बताए गए उसके internal name से करें और वही मान font_name में पास करें। यदि किसी विशेष प्लेटफॉर्म पर फ़ॉन्ट अपेक्षित रूप से रेंडर नहीं होता, तो मान लें कि OS का फ़ॉन्ट बैकएंड अलग तरह से व्यवहार कर सकता है और किसी वैकल्पिक फ़ॉन्ट फ़ाइल के साथ परीक्षण करें।

यह लेख StackOverflow पर प्रश्न (लेखक: JediKnightBoB) और furas के उत्तर पर आधारित है।