[PYTHON] Utilisez BMFont comme police pour pyglet

introduction

J'ai pu intégrer BMFont dans la police de pyglet, je vais donc la publier. Écrit en Python 3.5 Il n'est pas confirmé s'il fonctionne avec 2 systèmes.

Qu'est-ce que BMFont?

Logiciel de création de polices de texture. http://www.angelcode.com/products/bmfont/ Certains autres logiciels peuvent exporter dans le même format, c'est donc un logiciel relativement important.

La source

La licence doit être la même que pyglet.

bmfont.py


from xml.etree import ElementTree
import weakref

import pyglet
from pyglet import gl
from pyglet.font import base


class DummyGlyphRenderer(base.GlyphRenderer):
    def __init__(self, font):
        super(DummyGlyphRenderer, self).__init__(font)
        self.font = font
    
    def render(self, text):
        glyph = self.font.create_dummy_glyph()
        glyph.set_bearings(0, 0, 0)
        return glyph


class BMFont(base.Font):
    glyph_renderer_class = DummyGlyphRenderer
    
    def __init__(self, file_name):
        super(BMFont, self).__init__()
        self._setup(file_name)
        
    def _setup(self, file_name):
        with pyglet.resource.file(file_name, mode="rb") as f:
            data = f.read()
        str_data = data.decode("utf-8", "ignore")
        root = ElementTree.fromstring(str_data)
        
        common = root.find("common")
        lineheight = int(common.attrib["lineHeight"])
        baseline = int(common.attrib["base"])
        scaleH = int(common.attrib["scaleH"])
        pages = int(common.attrib["pages"])
        self.ascent = baseline
        self.descent = -(lineheight - baseline)
        self.textures.extend([None] * pages)
        
        pages = root.find("pages")
        for page in pages:
            id_ = int(page.attrib["id"])
            file = page.attrib["file"]
            texture = pyglet.resource.texture(file)
            image_data = texture.get_image_data()
            texture = self.texture_class.create_for_size(gl.GL_TEXTURE_2D,
                texture.width, texture.height, gl.GL_RGBA, gl.GL_NEAREST,
                gl.GL_NEAREST)
            texture.blit_into(image_data, 0, 0, 0)
            self.textures[id_] = texture
        
        chars = root.find("chars")
        for char in chars:
            key = chr(int(char.attrib["id"]))
            x = int(char.attrib["x"])
            y = int(char.attrib["y"])
            width = int(char.attrib["width"])
            height = int(char.attrib["height"])
            xoffset = int(char.attrib["xoffset"])
            yoffset = int(char.attrib["yoffset"])
            xadvance = int(char.attrib["xadvance"])
            page = int(char.attrib["page"])
            
            texture = self.textures[page]
            y = scaleH - height - y
            glyph = texture.get_region(x, y, width, height)
            
            bottom = baseline - yoffset - height
            glyph.set_bearings(-bottom, xoffset, xadvance)
            
            self.glyphs[key] = glyph
    
    def create_dummy_glyph(self):
        return self.textures[0].get_region(0, 0, 0, 0)
        

def load(name, size=None, bold=False, italic=False, dpi=None, file_name=None):
    assert name
    assert file_name
    
    if size is None:
        size = 12

    if dpi is None:
        dpi = 96
    
    shared_object_space = gl.current_context.object_space
    if not hasattr(shared_object_space, 'pyglet_font_font_cache'):
        shared_object_space.pyglet_font_font_cache = \
            weakref.WeakValueDictionary()
        shared_object_space.pyglet_font_font_hold = []
    font_cache = shared_object_space.pyglet_font_font_cache
    font_hold = shared_object_space.pyglet_font_font_hold
    
    descriptor = (name, size, bold, italic, dpi)
    if descriptor in font_cache:
        return font_cache[descriptor]
    
    font = BMFont(file_name)
    
    font.name = name
    font.size = size
    font.bold = bold
    font.italic = italic
    font.dpi = dpi
    
    font_cache[descriptor] = font
    
    del font_hold[3:]
    font_hold.insert(0, font)
    
    return font

Comment utiliser

Enregistrez le code ci-dessus sous bmfont.py dans un emplacement approprié. Préparez une police créée avec BMFont et Définissez le nom de la police à enregistrer et le fichier .fnt.

python


import bmfont
font = bmfont.load("myfont", file_name="font.fnt")

Après cela, spécifiez le nom de la police enregistrée et utilisez-le. Étiquette ou document.

python


label = pyglet.text.Label("Hello World!", "myfont", x=10, y=10)

document = pyglet.text.decode_text("Hello world!")
document.set_style(0, len(document.text), {
    "font_name": "myfont",
    "color": (255, 255, 255, 255),
})
layout = pyglet.text.layout.TextLayout(document, 200, 200)

Diverses précautions

Comparer avec la police pyglet

Vous pouvez utiliser la police ttf dans pyglet, mais elle semble un peu floue, donc si vous voulez l'afficher clairement, je pense que c'est mieux. 2016-09-27_14h52_55.png Cependant, il est difficile de recréer la police de texture chaque fois que vous ajoutez des caractères.

à la fin

C'était plus facile à intégrer que ce à quoi je m'attendais, alors j'ai pensé que c'était comme si je m'attendais à utiliser BMFont.

La police utilisée a été empruntée au site suivant. http://itouhiro.hatenablog.com/entry/20130602/font

Recommended Posts

Utilisez BMFont comme police pour pyglet
Utilisez Flask comme étape suivante dans SimpleHTTPServer
Comment utiliser MkDocs pour la première fois
Utilisez le module de papier électronique comme liste de tâches
Utilisez get autant que possible pour les références de type dictionnaire
Utilisez le dictionnaire de reconnaissance de nom d'entreprise "JCLdic" pour MeCab
[python] Comment utiliser Matplotlib, une bibliothèque pour dessiner des graphiques
Conseils aux débutants en Python pour utiliser l'exemple Scikit-image par eux-mêmes