updated font handling

This commit is contained in:
Jörn-Michael Miehe 2023-11-01 01:30:33 +01:00
parent 7951363be8
commit 8a254d2958
6 changed files with 67 additions and 25 deletions

View file

@ -92,14 +92,6 @@ class Puzzle(BaseModel):
close_after: int = 90 close_after: int = 90
class TTFont(BaseModel):
# Dateiname (in "/files")
file: str
# Schriftgröße für den Font
size: int = 50
class Image(BaseModel): class Image(BaseModel):
# Quadrat, Seitenlänge in px # Quadrat, Seitenlänge in px
size: int = 1000 size: int = 1000
@ -107,10 +99,6 @@ class Image(BaseModel):
# Rand in px, wo keine Buchstaben untergebracht werden # Rand in px, wo keine Buchstaben untergebracht werden
border: int = 60 border: int = 60
# Schriftarten
# TODO
fonts: list[TTFont]
class Config(BaseModel): class Config(BaseModel):
# Login-Daten für Admin-Modus # Login-Daten für Admin-Modus

View file

@ -1,4 +1,5 @@
import re import re
from dataclasses import dataclass
from datetime import date from datetime import date
from io import BytesIO from io import BytesIO
from typing import cast from typing import cast
@ -11,8 +12,10 @@ from .calendar_config import CalendarConfig, get_calendar_config
from .config import Config, get_config from .config import Config, get_config
from .dav.webdav import WebDAV from .dav.webdav import WebDAV
from .helpers import ( from .helpers import (
RE_TTF,
EventDates, EventDates,
Random, Random,
list_fonts,
list_images_auto, list_images_auto,
list_images_manual, list_images_manual,
load_image, load_image,
@ -109,11 +112,46 @@ async def get_all_image_names(
return auto_image_names return auto_image_names
@dataclass(slots=True, frozen=True)
class TTFont:
# Dateiname
file_name: str
# Schriftgröße für den Font
size: int = 50
@property
async def font(self) -> "ImageFont._Font":
return ImageFont.truetype(
font=BytesIO(await WebDAV.read_bytes(self.file_name)),
size=100,
)
async def get_all_ttfonts(
font_names: list[str] = Depends(list_fonts),
) -> list[TTFont]:
result = []
for name in font_names:
assert (size_match := RE_TTF.search(name)) is not None
result.append(
TTFont(
file_name=name,
size=int(size_match.group(1)),
)
)
return result
async def gen_day_auto_image( async def gen_day_auto_image(
day: int, day: int,
cfg: Config, cfg: Config,
auto_image_names: dict[int, str], auto_image_names: dict[int, str],
day_parts: dict[int, str], day_parts: dict[int, str],
ttfonts: list[TTFont],
) -> Image.Image: ) -> Image.Image:
""" """
Automatisch generiertes Bild erstellen Automatisch generiertes Bild erstellen
@ -125,18 +163,14 @@ async def gen_day_auto_image(
rnd = await Random.get(day) rnd = await Random.get(day)
font = ImageFont.truetype(
font=BytesIO(await WebDAV.read_bytes("files/Lena.ttf")), # TODO
size=100,
)
# Buchstaben verstecken # Buchstaben verstecken
for letter in day_parts[day]: for letter in day_parts[day]:
xy_range = range(cfg.image.border, (cfg.image.size - cfg.image.border)) xy_range = range(cfg.image.border, (cfg.image.size - cfg.image.border))
await image.hide_text( await image.hide_text(
xy=cast(_XY, tuple(rnd.choices(xy_range, k=2))), xy=cast(_XY, tuple(rnd.choices(xy_range, k=2))),
text=letter, text=letter,
font=font, font=await rnd.choice(ttfonts).font,
) )
return image.img return image.img
@ -148,6 +182,7 @@ async def get_day_image(
cfg: Config = Depends(get_config), cfg: Config = Depends(get_config),
auto_image_names: dict[int, str] = Depends(get_all_auto_image_names), auto_image_names: dict[int, str] = Depends(get_all_auto_image_names),
day_parts: dict[int, str] = Depends(get_all_parts), day_parts: dict[int, str] = Depends(get_all_parts),
ttfonts: list[TTFont] = Depends(get_all_ttfonts),
) -> Image.Image | None: ) -> Image.Image | None:
""" """
Bild für einen Tag abrufen Bild für einen Tag abrufen
@ -167,5 +202,9 @@ async def get_day_image(
except RuntimeError: except RuntimeError:
# Erstelle automatisch generiertes Bild # Erstelle automatisch generiertes Bild
return await gen_day_auto_image( return await gen_day_auto_image(
day=day, cfg=cfg, auto_image_names=auto_image_names, day_parts=day_parts day=day,
cfg=cfg,
auto_image_names=auto_image_names,
day_parts=day_parts,
ttfonts=ttfonts,
) )

View file

@ -13,7 +13,7 @@ from .dav.webdav import WebDAV
T = TypeVar("T") T = TypeVar("T")
RE_IMG = re.compile(r"\.(gif|jpe?g|tiff?|png|bmp)$", flags=re.IGNORECASE) RE_IMG = re.compile(r"\.(gif|jpe?g|tiff?|png|bmp)$", flags=re.IGNORECASE)
RE_TTF = re.compile(r"\.(ttf)$", flags=re.IGNORECASE) RE_TTF = re.compile(r"_(\d+)\.ttf$", flags=re.IGNORECASE)
class Random(random.Random): class Random(random.Random):

View file

@ -7,7 +7,13 @@ from advent22_api.core.helpers import EventDates
from ..core.calendar_config import CalendarConfig, DoorsSaved, get_calendar_config from ..core.calendar_config import CalendarConfig, DoorsSaved, get_calendar_config
from ..core.config import Config, Image, get_config from ..core.config import Config, Image, get_config
from ..core.depends import get_all_event_dates, get_all_image_names, get_all_parts from ..core.depends import (
TTFont,
get_all_event_dates,
get_all_image_names,
get_all_parts,
get_all_ttfonts,
)
from ..core.settings import SETTINGS, RedisSettings from ..core.settings import SETTINGS, RedisSettings
from ._security import require_admin, user_is_admin from ._security import require_admin, user_is_admin
@ -39,6 +45,10 @@ class ConfigModel(BaseModel):
config_file: str config_file: str
background: str background: str
class __Font(BaseModel):
file: str
size: int
class __WebDAV(BaseModel): class __WebDAV(BaseModel):
url: str url: str
cache_ttl: int cache_ttl: int
@ -48,6 +58,7 @@ class ConfigModel(BaseModel):
puzzle: __Puzzle puzzle: __Puzzle
calendar: __Calendar calendar: __Calendar
image: Image image: Image
fonts: list[__Font]
redis: RedisSettings redis: RedisSettings
webdav: __WebDAV webdav: __WebDAV
@ -58,6 +69,7 @@ async def get_config_model(
cfg: Config = Depends(get_config), cfg: Config = Depends(get_config),
cal_cfg: CalendarConfig = Depends(get_calendar_config), cal_cfg: CalendarConfig = Depends(get_calendar_config),
event_dates: EventDates = Depends(get_all_event_dates), event_dates: EventDates = Depends(get_all_event_dates),
ttfonts: list[TTFont] = Depends(get_all_ttfonts),
) -> ConfigModel: ) -> ConfigModel:
""" """
Kombiniert aus privaten `settings`, `config` und `calendar_config` Kombiniert aus privaten `settings`, `config` und `calendar_config`
@ -83,6 +95,9 @@ async def get_config_model(
"background": cal_cfg.background, "background": cal_cfg.background,
}, },
"image": cfg.image, "image": cfg.image,
"fonts": [
{"file": ttfont.file_name, "size": ttfont.size} for ttfont in ttfonts
],
"redis": SETTINGS.redis, "redis": SETTINGS.redis,
"webdav": { "webdav": {
"url": SETTINGS.webdav.url, "url": SETTINGS.webdav.url,

View file

@ -101,10 +101,10 @@
<dt>Schriftarten</dt> <dt>Schriftarten</dt>
<dd <dd
v-for="(font, index) in config_model.image.fonts" v-for="(font, index) in config_model.fonts"
:key="`font-${index}`" :key="`font-${index}`"
> >
{{ font.file }} (Größe {{ font.size }}) {{ font.file }} ({{ font.size }} pt)
</dd> </dd>
</dl> </dl>
</div> </div>
@ -200,8 +200,8 @@ export default class extends Vue {
image: { image: {
size: 500, size: 500,
border: 0, border: 0,
fonts: [{ file: "consetetur", size: 0 }],
}, },
fonts: [{ file: "consetetur", size: 0 }],
redis: { redis: {
host: "0.0.0.0", host: "0.0.0.0",
port: 6379, port: 6379,

View file

@ -19,8 +19,8 @@ export interface ConfigModel {
image: { image: {
size: number; size: number;
border: number; border: number;
fonts: { file: string; size: number }[];
}; };
fonts: { file: string; size: number }[];
redis: { redis: {
host: string; host: string;
port: number; port: number;