Download fonts at app startup instead

We can't bake the font into the Docker image as such, because we mount
the volumes which blows away anything we have in the app tree
beforehand.

We could stash it somewhere in the image and then copy it from there on
app startup or something, but at that point we might as well just
download it as part of the app startup.
This commit is contained in:
Joel Bradshaw 2022-01-25 00:22:13 -08:00
parent 766a0cc652
commit 9e6390662b
4 changed files with 66 additions and 20 deletions

View file

@ -6,13 +6,6 @@ RUN mkdir /app /app/static /app/images
WORKDIR /app
# Use RUN curl because ADD will re-download the file every time to make sure it
# hasn't changed, which is exactly what we don't want
RUN mkdir -p /app/static/fonts/source_han_sans
RUN curl \
https://github.com/adobe-fonts/source-han-sans/raw/release/Variable/OTC/SourceHanSans-VF.ttf.ttc \
-o /app/static/fonts/source_han_sans/SourceHanSans-VF.ttf.ttc
COPY requirements.txt /app/
RUN pip install -r requirements.txt --no-cache-dir
RUN apt-get update && apt-get install -y gettext libgettextpo-dev tidy && apt-get clean

35
bookwyrm/apps.py Normal file
View file

@ -0,0 +1,35 @@
import os
import urllib
import logging
from django.apps import AppConfig
from bookwyrm import settings
logger = logging.getLogger(__name__)
def download_file(url, destination):
try:
stream = urllib.request.urlopen(url)
with open(destination, "b+w") as f:
f.write(stream.read())
except (urllib.error.HTTPError, urllib.error.URLError):
logger.error("Failed to download file %s", url)
class BookwyrmConfig(AppConfig):
name = "bookwyrm"
verbose_name = "BookWyrm"
def ready(self):
if settings.ENABLE_PREVIEW_IMAGES and settings.FONTS:
# Download any fonts that we don't have yet
logger.debug("Downloading fonts..")
for name, config in settings.FONTS.items():
font_path = os.path.join(
settings.FONT_DIR, config["directory"], config["filename"]
)
if "url" in config and not os.path.exists(font_path):
logger.info("Just a sec, downloading %s", name)
download_file(config["url"], font_path)

View file

@ -4,6 +4,8 @@ import os
import textwrap
from io import BytesIO
from uuid import uuid4
import urllib
import logging
import colorsys
from colorthief import ColorThief
@ -17,29 +19,37 @@ from django.db.models import Avg
from bookwyrm import models, settings
from bookwyrm.tasks import app
logger = logging.getLogger(__name__)
IMG_WIDTH = settings.PREVIEW_IMG_WIDTH
IMG_HEIGHT = settings.PREVIEW_IMG_HEIGHT
BG_COLOR = settings.PREVIEW_BG_COLOR
TEXT_COLOR = settings.PREVIEW_TEXT_COLOR
DEFAULT_COVER_COLOR = settings.PREVIEW_DEFAULT_COVER_COLOR
DEFAULT_FONT = settings.PREVIEW_DEFAULT_FONT
TRANSPARENT_COLOR = (0, 0, 0, 0)
margin = math.floor(IMG_HEIGHT / 10)
gutter = math.floor(margin / 2)
inner_img_height = math.floor(IMG_HEIGHT * 0.8)
inner_img_width = math.floor(inner_img_height * 0.7)
font_dir = os.path.join(settings.STATIC_ROOT, "fonts/source_han_sans")
def get_imagefont(name, size):
try:
config = settings.FONTS[name]
path = os.path.join(settings.FONT_DIR, config["directory"], config["filename"])
return ImageFont.truetype(path, size)
except KeyError:
logger.error("Font %s not found in config", name)
except OSError:
logger.error("Could not load font %s from file", name)
return ImageFont.load_default()
def get_font(weight, size=28):
"""Loads custom font"""
font_path = os.path.join(font_dir, "SourceHanSans-VF.ttf.ttc")
try:
font = ImageFont.truetype(font_path, size)
except OSError:
font = ImageFont.load_default()
font = get_imagefont(DEFAULT_FONT, size)
try:
if weight == "light":

View file

@ -35,6 +35,9 @@ LOCALE_PATHS = [
]
LANGUAGE_COOKIE_NAME = env.str("LANGUAGE_COOKIE_NAME", "django_language")
STATIC_ROOT = os.path.join(BASE_DIR, env("STATIC_ROOT", "static"))
MEDIA_ROOT = os.path.join(BASE_DIR, env("MEDIA_ROOT", "images"))
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
# Preview image
@ -44,6 +47,16 @@ PREVIEW_TEXT_COLOR = env.str("PREVIEW_TEXT_COLOR", "#363636")
PREVIEW_IMG_WIDTH = env.int("PREVIEW_IMG_WIDTH", 1200)
PREVIEW_IMG_HEIGHT = env.int("PREVIEW_IMG_HEIGHT", 630)
PREVIEW_DEFAULT_COVER_COLOR = env.str("PREVIEW_DEFAULT_COVER_COLOR", "#002549")
PREVIEW_DEFAULT_FONT = env.str("PREVIEW_DEFAULT_FONT", "Source Han Sans")
FONTS = {
"Source Han Sans": {
"directory": "source_han_sans",
"filename": "SourceHanSans-VF.ttf.ttc",
"url": "https://github.com/adobe-fonts/source-han-sans/raw/release/Variable/OTC/SourceHanSans-VF.ttf.ttc",
}
}
FONT_DIR = os.path.join(STATIC_ROOT, "fonts")
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
@ -310,13 +323,8 @@ if USE_S3:
MEDIA_FULL_URL = MEDIA_URL
STATIC_FULL_URL = STATIC_URL
DEFAULT_FILE_STORAGE = "bookwyrm.storage_backends.ImagesStorage"
# I don't know if it's used, but the site crashes without it
STATIC_ROOT = os.path.join(BASE_DIR, env("STATIC_ROOT", "static"))
MEDIA_ROOT = os.path.join(BASE_DIR, env("MEDIA_ROOT", "images"))
else:
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, env("STATIC_ROOT", "static"))
MEDIA_URL = "/images/"
MEDIA_FULL_URL = f"{PROTOCOL}://{DOMAIN}{MEDIA_URL}"
STATIC_FULL_URL = f"{PROTOCOL}://{DOMAIN}{STATIC_URL}"
MEDIA_ROOT = os.path.join(BASE_DIR, env("MEDIA_ROOT", "images"))