pythonpython-3.xpygamepygame2

test equality for pygame.font.Font


I was trying to make a font cache like this:

from ._utils import SizedDict
def copysurf(x,mod):
    if mod:
        return cs(x)
    return ImmutableSurface(x)
class FontCache:
    def __init__(self):
        self.cache = SizedDict(20)
        self.fmisses = 0
        self.fhits = 0
        self.cmisses = {}
        self.chits = {}
    def getfor(self,font,char,aa,color):
        if font not in self.cache:
            self.cmisses[font] = 0
            self.chits[font] = 0
            self.cache[font] = SizedDict(300)
        if char not in self.cache[font]:
            self.cache[font][char] = font.render(char,aa,color)
        return self.cache[font][char].copy()
fontCache = FontCache()

(Sized dicts are also made by me,they are dicts that deletes the oldest entry if it exeeds the capacity specified in the constructor.)

But the problem arises when i tried to cache the font.You see,

pygame.font.SysFont("Courier",22) == pygame.font.SysFont("Courier",22)

is false,and the hash() function returned different values.As i know,there aren't any methods that returns the original NAME of the font,and we can't test equality by merely knowing the size and the bold and italic flags.

Any thoughts?


Solution

  • You could subclass pygame.font.Font, store the metadata when the font is created. Something like this:

    import pygame
    
    pygame.init()
    
    
    class Font(pygame.font.Font):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.properties = (args, tuple(kwargs.items()))
    
        def __hash__(self):
            return hash(self.properties)
    
        def __eq__(self, other):
            return self.properties == other.properties
    
        @classmethod
        def construct(cls, fontpath, size, bold, italic):
            font = cls(fontpath, size)
            font.strong = bold
            font.oblique = italic
            return font
    
    
    # Prints True
    print(
        pygame.font.SysFont("Courier", 22, constructor=Font.construct)
        == pygame.font.SysFont("Courier", 22, constructor=Font.construct)
    )