[PYTHON] Verwenden Sie BMFont als Schriftart für Pyglet

Einführung

Ich konnte BMFont in die Schriftart von pyglet integrieren, daher werde ich es veröffentlichen. Geschrieben in Python 3.5 Es ist nicht bestätigt, ob es mit 2 Systemen funktioniert.

Was ist BMFont?

Software zur Erstellung von Texturschriftarten. http://www.angelcode.com/products/bmfont/ Einige andere Software kann im gleichen Format exportiert werden, daher handelt es sich um eine relativ große Software.

Quelle

Die Lizenz sollte mit pyglet identisch sein.

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

Wie benutzt man

Speichern Sie den obigen Code als "bmfont.py" an einem geeigneten Ort. Bereiten Sie eine mit BMFont und erstellte Schriftart vor Legen Sie den zu registrierenden Schriftnamen und die .fnt-Datei fest.

python


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

Geben Sie danach den registrierten Schriftnamen an und verwenden Sie ihn. Etikett oder Dokument.

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)

Verschiedene Vorsichtsmaßnahmen

Vergleichen Sie mit Pyglet-Schrift

Sie können die ttf-Schriftart in pyglet verwenden, sie sieht jedoch etwas verschwommen aus. Wenn Sie sie also klar anzeigen möchten, ist dies meiner Meinung nach besser. 2016-09-27_14h52_55.png Es ist jedoch schwierig, die Texturschrift jedes Mal neu zu erstellen, wenn Sie Zeichen hinzufügen.

schließlich

Es war einfacher zu integrieren als ich erwartet hatte, also dachte ich, es wäre, als hätte ich erwartet, BMFont zu verwenden.

Die verwendete Schriftart wurde von der folgenden Site ausgeliehen. http://itouhiro.hatenablog.com/entry/20130602/font

Recommended Posts

Verwenden Sie BMFont als Schriftart für Pyglet
Verwenden Sie Flask als nächsten Schritt für SimpleHTTPServer
So verwenden Sie MkDocs zum ersten Mal
Verwenden Sie das elektronische Papiermodul als Aufgabenliste
Verwenden Sie get so viel wie möglich für Referenzen vom Typ Wörterbuch
Verwenden Sie für MeCab das Wörterbuch zur Erkennung von Firmennamen "JCLdic"
[Python] Verwendung von Matplotlib, einer Bibliothek zum Zeichnen von Diagrammen
Tipps für Python-Anfänger, um das Scikit-Image-Beispiel für sich selbst zu verwenden