import os import enum import cairo from hexagram.svg import render_to_image class Icon(): __slots__ = 'name', 'width', 'height', 'style', 'variants', \ '_path', '_surfaces', __dirs__ = ('./icons', '/usr/local/share/hexagram/icons' '/usr/share/hexagram/icons') @staticmethod def _locate(name: str): for dir in Icon.__dirs__: path = "%s/%s.svg" % (dir, name) if os.path.exists(path): return path raise FileNotFoundError(name + '.svg') STYLE = 'rect,path,circle{stroke:%(s)s;}' def __init__(self, name: str, width: float, height: float, variants: dict, style: str=STYLE): self.name = name self.width = width self.height = height self.style = style self.variants = variants self._path = Icon._locate(name) self._surfaces: dict[enum.Enum, cairo.ImageSurface] = dict() def __del__(self): for key in self._surfaces: self._surfaces[key].finish() def _surface(self, status) -> cairo.ImageSurface: surface = self._surfaces.get(status) if surface is not None: return surface color = self.variants[status] surface = render_to_image(self._path, self.width, self.height, self.style % {'s': color}) self._surfaces[status] = surface return surface def drawable(self, status: enum.Enum): return status in self.variants def draw(self, cr: cairo.Context, x: float, y: float, status): surface = self._surface(status) cr.set_source_surface(surface, x, y) cr.rectangle(x, y, self.width, self.height) cr.fill()