ComfyUI/comfy/fonts.py
Gremlation 7f8d7ae309 Add ImageLabel node and FontManager
ImageLabel adds a label to the top or bottom of an image, extending its
dimensions as required.

This also introduces the FontManager class and ships the Roboto font.
2024-12-19 19:45:37 +08:00

78 lines
2.4 KiB
Python

import logging
from pathlib import Path
from typing import Tuple, Union
from PIL.ImageFont import FreeTypeFont, ImageFont, load_default as load_default_font, truetype as load_truetype
from folder_paths import base_path
default_font_path = Path(base_path) / "fonts"
AnyFont = Union[FreeTypeFont, ImageFont]
class FontCollection(dict):
"""
A dictionary that maps font names to PIL font objects.
"""
def __init__(self, directory: Path = default_font_path):
"""
Initialize the FontCollection with fonts found in the given directory (including subdirectories).
Args:
directory (Path): The path to the directory containing font files.
"""
paths = [font for font in directory.rglob("*.[tT][tT][fF]") if font.is_file()]
self.default_font_name, self.default_font = self.load_default_font()
fonts = {
self.default_font_name: self.default_font,
}
for path in paths:
font_info = self.load_font(path)
if font_info:
if font_info[0] in fonts:
logging.warning(f"Fonts with duplicate names found: {font_info[0]}")
fonts[font_info[0]] = font_info[1]
super().__init__(fonts)
@classmethod
def load_default_font(cls) -> Tuple[str, AnyFont]:
"""
Load the default PIL font.
Returns:
tuple[str, AnyFont]: The font's name and the font object.
"""
font = load_default_font()
family, style = None, None
if isinstance(font, FreeTypeFont):
family, style = font.getname()
family = family or "Unknown"
style = style or "Regular"
return " ".join([family, style]), font
@classmethod
def load_font(cls, path: Path) -> Tuple[str, FreeTypeFont]:
"""
Load a font and extract its name and style.
Args:
path (Path): The path to the font file.
Returns:
tuple[str, ImageFont.FreeTypeFont]: A tuple containing the font's name and the font object.
Raises:
OSError: If the font file could not be read.
ValueError: If the font size is not greater than zero.
"""
font = load_truetype(path)
family, style = font.getname()
family = family or "Unknown"
style = style or "Regular"
return " ".join([family, style]), font