diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2025-06-01 13:27:50 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2025-06-01 13:27:50 (GMT) |
commit | 07333983ff99b22994a79c8a7cbf4fad0b80158f (patch) | |
tree | ea38a27b114212b662f31feadfe2db1347a53148 /tools | |
parent | bde358e3a0b8333fd796c89a3be998d8ad5b1826 (diff) |
Build a static image for the About dialog box background.gtk4
Diffstat (limited to 'tools')
-rw-r--r-- | tools/about/build.py | 120 | ||||
-rw-r--r-- | tools/about/courier-10-pitch-bold_EQ97V.zip | bin | 0 -> 21114 bytes | |||
-rw-r--r-- | tools/about/courier10point.zip | bin | 0 -> 61784 bytes | |||
-rwxr-xr-x | tools/about/gen.sh | 52 | ||||
-rw-r--r-- | tools/about/logo.png | bin | 0 -> 633982 bytes | |||
-rw-r--r-- | tools/about/noise.png | bin | 0 -> 136944 bytes | |||
-rw-r--r-- | tools/about/ttf.py | 111 |
7 files changed, 283 insertions, 0 deletions
diff --git a/tools/about/build.py b/tools/about/build.py new file mode 100644 index 0000000..2267492 --- /dev/null +++ b/tools/about/build.py @@ -0,0 +1,120 @@ + +# apt install libcairo2-dev pkg-config python3-dev +# pip install pycairo + +import cairo +import math +import sys + +from enum import IntEnum + +from ttf import create_cairo_font_face_for_file + + +WIDTH = 350 +HEIGHT = 430 + + +def deg2rad(degrees): + return degrees * (math.pi / 180) + + +class TextAlignment(IntEnum): + LEFT = 1 + CENTER = 2 + RIGHT = 3 + + +def draw_text(ctx, text, pos, fsize, noise, theta = 0.0, align = TextAlignment.CENTER): + """Dessine un texte en respectant des propriétées.""" + + ctx.save() + + ctx.set_font_size(fsize) + + fascent, fdescent, fheight, fxadvance, fyadvance = ctx.font_extents() + x_off, y_off, tw, th = ctx.text_extents(text)[:4] + + if align == TextAlignment.LEFT: + nx = 0 + elif align == TextAlignment.RIGHT: + nx = -tw + else: + nx = -tw / 2.0 + + ny = fheight / 2 + + ctx.translate(pos[0], pos[1]) + ctx.rotate(theta) + ctx.translate(nx, ny) + ctx.move_to(0,0) + + ctx.text_path(text) + ctx.set_source_surface(noise, 0, -fheight) + ctx.fill_preserve() + ctx.set_source_rgb(1.0, 1.0, 1.0) + ctx.set_line_width(1) + ctx.stroke() + + ctx.restore() + + +if __name__ == '__main__': + """Point d'entrée du script.""" + + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) + + cr = cairo.Context(surface) + + face = create_cairo_font_face_for_file('cour10p_b.ttf') + cr.set_font_face(face) + + noise = cairo.ImageSurface.create_from_png('noise.png') + + # Type d'édition + + if len(sys.argv) > 2: + + draw_text(cr, sys.argv[2], [ 300, 25 ], 32, noise, + theta = deg2rad(270), align = TextAlignment.RIGHT) + + cr.set_source_rgb(0, 0, 0) + cr.paint_with_alpha(0.4) + + # Numéro de version + + draw_text(cr, sys.argv[1], [ 149, 10 + 259 + 14 + 42 + 2 ], 23, noise, align=TextAlignment.LEFT) + + cr.set_source_rgb(0, 0, 0) + cr.paint_with_alpha(0.5) + + # Logo + + logo = cairo.ImageSurface.create_from_png('logo.png') + + scale_y = 259 / logo.get_height() + + cr.save() + + cr.translate((WIDTH - (logo.get_width() * scale_y)) / 2, 12) + + cr.scale(scale_y, scale_y) + + cr.set_source_surface(logo, 0, 0) + cr.paint() + + cr.restore() + + # Titre + + draw_text(cr, 'Chrysalide', [ WIDTH / 2, 10 + 259 + 14 + 4 ], 42, noise) + + # cr.rectangle(265, 30, 10, 10) + # cr.set_source_rgb(1, 0, 0) + # cr.fill() + + # cr.rectangle(265, 255, 10, 10) + # cr.set_source_rgb(1, 0, 0) + # cr.fill() + + surface.write_to_png('bg.png') diff --git a/tools/about/courier-10-pitch-bold_EQ97V.zip b/tools/about/courier-10-pitch-bold_EQ97V.zip Binary files differnew file mode 100644 index 0000000..0585fe6 --- /dev/null +++ b/tools/about/courier-10-pitch-bold_EQ97V.zip diff --git a/tools/about/courier10point.zip b/tools/about/courier10point.zip Binary files differnew file mode 100644 index 0000000..82cd0de --- /dev/null +++ b/tools/about/courier10point.zip diff --git a/tools/about/gen.sh b/tools/about/gen.sh new file mode 100755 index 0000000..c22ec59 --- /dev/null +++ b/tools/about/gen.sh @@ -0,0 +1,52 @@ +#!/bin/bash + + +# Cf. https://stackoverflow.com/questions/59895/how-do-i-get-the-directory-where-a-bash-script-is-located-from-within-the-script/246128#246128 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +pushd $SCRIPT_DIR > /dev/null + + +# Obtention de la police Courier-10-Pitch-Bold +# -------------------------------------------- + +# https://fontsgeek.com/fonts/Courier-10-Pitch-Bold +# https://fontsgeek.com/terms-and-conditions + +# => courier-10-pitch-bold_EQ97V.zip + + +# Courier 10 Pitch font missing after upgrade to 17.04? +# https://askubuntu.com/questions/914352/courier-10-pitch-font-missing-after-upgrade-to-17-04 + +# https://groups.google.com/g/trelby/c/CGkpcMBXW9U +# -> http://www.trelby.org/files/release/font/courier10point.zip +# --> https://web.archive.org/web/20140326080337/http://www.trelby.org/files/release/font/courier10point.zip + +# https://news.ycombinator.com/item?id=18802628 +# -> https://www.trelby.org/assets/courier10point.zip + +# => courier10point.zip + +if [ ! -f cour10p_b.ttf ]; then + + unzip -p courier10point.zip courier10point/cour10p_b.ttf > cour10p_b.ttf + +fi + + +# Construction de l'image de fond +#-------------------------------- + +if [ $# -lt 1 -o $# -gt 2 ]; then + + echo "Usage: $0 <version> <edition>" + exit 123 + +fi + +python3 ./build.py $* + +cp bg.png ../../src/data/images/about-bg.png + +popd > /dev/null diff --git a/tools/about/logo.png b/tools/about/logo.png Binary files differnew file mode 100644 index 0000000..9bf9969 --- /dev/null +++ b/tools/about/logo.png diff --git a/tools/about/noise.png b/tools/about/noise.png Binary files differnew file mode 100644 index 0000000..b5d6b91 --- /dev/null +++ b/tools/about/noise.png diff --git a/tools/about/ttf.py b/tools/about/ttf.py new file mode 100644 index 0000000..eb6c027 --- /dev/null +++ b/tools/about/ttf.py @@ -0,0 +1,111 @@ + +# Source: https://www.cairographics.org/cookbook/freetypepython/ + +import ctypes as ct +import cairo + +_initialized = False +def create_cairo_font_face_for_file (filename, faceindex=0, loadoptions=0): + "given the name of a font file, and optional faceindex to pass to FT_New_Face" \ + " and loadoptions to pass to cairo_ft_font_face_create_for_ft_face, creates" \ + " a cairo.FontFace object that may be used to render text with that font." + global _initialized + global _freetype_so + global _cairo_so + global _ft_lib + global _ft_destroy_key + global _surface + + CAIRO_STATUS_SUCCESS = 0 + FT_Err_Ok = 0 + + if not _initialized: + # find shared objects + _freetype_so = ct.CDLL("libfreetype.so.6") + _cairo_so = ct.CDLL("libcairo.so.2") + _cairo_so.cairo_ft_font_face_create_for_ft_face.restype = ct.c_void_p + _cairo_so.cairo_ft_font_face_create_for_ft_face.argtypes = [ ct.c_void_p, ct.c_int ] + _cairo_so.cairo_font_face_get_user_data.restype = ct.c_void_p + _cairo_so.cairo_font_face_get_user_data.argtypes = (ct.c_void_p, ct.c_void_p) + _cairo_so.cairo_font_face_set_user_data.argtypes = (ct.c_void_p, ct.c_void_p, ct.c_void_p, ct.c_void_p) + _cairo_so.cairo_set_font_face.argtypes = [ ct.c_void_p, ct.c_void_p ] + _cairo_so.cairo_font_face_status.argtypes = [ ct.c_void_p ] + _cairo_so.cairo_font_face_destroy.argtypes = (ct.c_void_p,) + _cairo_so.cairo_status.argtypes = [ ct.c_void_p ] + # initialize freetype + _ft_lib = ct.c_void_p() + status = _freetype_so.FT_Init_FreeType(ct.byref(_ft_lib)) + if status != FT_Err_Ok : + raise RuntimeError("Error %d initializing FreeType library." % status) + #end if + + class PycairoContext(ct.Structure): + _fields_ = \ + [ + ("PyObject_HEAD", ct.c_byte * object.__basicsize__), + ("ctx", ct.c_void_p), + ("base", ct.c_void_p), + ] + #end PycairoContext + + _surface = cairo.ImageSurface(cairo.FORMAT_A8, 0, 0) + _ft_destroy_key = ct.c_int() # dummy address + _initialized = True + #end if + + ft_face = ct.c_void_p() + cr_face = None + try : + # load FreeType face + status = _freetype_so.FT_New_Face(_ft_lib, filename.encode("utf-8"), faceindex, ct.byref(ft_face)) + if status != FT_Err_Ok : + raise RuntimeError("Error %d creating FreeType font face for %s" % (status, filename)) + #end if + + # create Cairo font face for freetype face + cr_face = _cairo_so.cairo_ft_font_face_create_for_ft_face(ft_face, loadoptions) + status = _cairo_so.cairo_font_face_status(cr_face) + if status != CAIRO_STATUS_SUCCESS : + raise RuntimeError("Error %d creating cairo font face for %s" % (status, filename)) + #end if + # Problem: Cairo doesn't know to call FT_Done_Face when its font_face object is + # destroyed, so we have to do that for it, by attaching a cleanup callback to + # the font_face. This only needs to be done once for each font face, while + # cairo_ft_font_face_create_for_ft_face will return the same font_face if called + # twice with the same FT Face. + # The following check for whether the cleanup has been attached or not is + # actually unnecessary in our situation, because each call to FT_New_Face + # will return a new FT Face, but we include it here to show how to handle the + # general case. + if _cairo_so.cairo_font_face_get_user_data(cr_face, ct.byref(_ft_destroy_key)) == None : + status = _cairo_so.cairo_font_face_set_user_data \ + ( + cr_face, + ct.byref(_ft_destroy_key), + ft_face, + _freetype_so.FT_Done_Face + ) + if status != CAIRO_STATUS_SUCCESS : + raise RuntimeError("Error %d doing user_data dance for %s" % (status, filename)) + #end if + ft_face = None # Cairo has stolen my reference + #end if + + # set Cairo font face into Cairo context + cairo_ctx = cairo.Context(_surface) + cairo_t = PycairoContext.from_address(id(cairo_ctx)).ctx + _cairo_so.cairo_set_font_face(cairo_t, cr_face) + status = _cairo_so.cairo_font_face_status(cairo_t) + if status != CAIRO_STATUS_SUCCESS : + raise RuntimeError("Error %d creating cairo font face for %s" % (status, filename)) + #end if + + finally : + _cairo_so.cairo_font_face_destroy(cr_face) + _freetype_so.FT_Done_Face(ft_face) + #end try + + # get back Cairo font face as a Python object + face = cairo_ctx.get_font_face() + return face +#end create_cairo_font_face_for_file |