I was able to incorporate BMFont into the font of pyglet, so I will publish it. Written in Python 3.5 It is unconfirmed whether it works with 2 systems.
Texture font creation software. http://www.angelcode.com/products/bmfont/ Some other software can export in the same format, so it's a relatively major software.
The license should be the same as 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
Save the above code as bmfont.py in a suitable location.
Prepare a font created with BMFont and
Set the font name to be registered and the .fnt file.
python
import bmfont
font = bmfont.load("myfont", file_name="font.fnt")
After that, specify the normally registered font name and use it. Label or 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)
font.fnt file in the path of resource.font.fnt file is only XML format.I can use the ttf font in pyglet, but it looks a little blurry, so I think this is better if you want to display it clearly.
However, it is troublesome to recreate the texture font every time you add characters.
It was easier to incorporate than I expected, so I thought it was as if I was expecting to use BMFont.
The font used was borrowed from the following site. http://itouhiro.hatenablog.com/entry/20130602/font
Recommended Posts