#!/usr/bin/python3 # coding: utf-8 import cairo import subprocess import math import lxml from lxml import etree FONT_SIZE = 30 MARGIN = int(FONT_SIZE / 3) #python3-lxml utility is required def get_keymaps(): xml = etree.XML(bytes(open('/usr/share/X11/xkb/rules/evdev.xml', 'r').read(), encoding="utf-8")) keymaps_x11 = xml.xpath('//layout/configItem/description/text()') keymaps = subprocess.check_output(["localectl", "list-keymaps"]).decode("utf-8").strip().split() # Note when changing this you MUST keep ply_keymap_normalize_keymap() # from src/libply-splash-graphics/ply-keymap-icon.c in sync def normalize_keymaps(keymap): parts = keymap.replace("_", "-").replace(".", "-").split("-") # Special case for dvorak, E.g. when mixing "us" and "us-dvorak" # on machines returning "us" for both is not useful. # Presumably users using dvorak now which variant they use # so we just describe all dvorak layouts as "dvorak". if "dvorak" in keymap.lower(): return "dvorak" # mac / sun keymaps are prefixes with mac / sun / sun[4-6]t for prefix in ["mac", "sun" ]: if keymap.startswith(prefix) and len(parts) > 1: return parts[1] return parts[0] keymaps = list(map(normalize_keymaps ,keymaps)) #Remove duplicates keymaps_dedupe = [] for k in keymaps: if k not in keymaps_dedupe: keymaps_dedupe.append(k) ret = [] for k in keymaps_dedupe: ret.append((k, "PLY_LAYOUT_TERMINAL")) for k in keymaps_x11: ret.append((k, "PLY_LAYOUT_XKB")) return ret # Calculate size sf = cairo.ImageSurface(cairo.FORMAT_ARGB32, 1, 1) ct = cairo.Context(sf) ct.select_font_face("Cantarell", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) ct.set_font_size(FONT_SIZE) max_height = 0.0 total_width = 0.0 for i in get_keymaps(): text=i[0] extents = ct.text_extents(text) h = extents.height if h > max_height: max_height = h total_width += extents.width total_width += MARGIN * 2 ascent, descent, _h, _max_x, max_y = ct.font_extents() # Create image sf = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(total_width), int(max_height + MARGIN * 2)) ct = cairo.Context(sf) ct.save() ct.set_source_rgba(0, 0, 0, 0) ct.set_operator (cairo.OPERATOR_SOURCE) ct.paint() ct.restore() ct.select_font_face("Cantarell", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD) ct.set_font_size(FONT_SIZE) ct.set_source_rgba(0.75, 0.75, 0.75, 1.0) ct.move_to(MARGIN, MARGIN + max_height - descent) current_x, current_y = (MARGIN, MARGIN + max_height - descent) metadata = [] for km in get_keymaps(): km_text=km[0] km_type=km[1] extents = ct.text_extents(km_text) ct.show_text(km_text) metadata.append((km_text, current_x, extents.width + MARGIN * 2, km_type)) current_x += extents.width + (MARGIN * 2) ct.move_to(current_x, current_y) sf.write_to_png("keymap-render.png") print("/* This file is autogenerated by running:") print(" * scripts/keymap-render.py > src/libply-splash-graphics/ply-keymap-metadata.h") print(" */") print("typedef struct {") print(" const char *name;") print(" int offset;") print(" int width;") print(" int type;") print("} ply_keymap_metadata_t;") print("") print("typedef enum {") print(" PLY_LAYOUT_TERMINAL,") print(" PLY_LAYOUT_XKB,") print("} ply_layout_types_t;") print("") print("static ply_keymap_metadata_t ply_keymap_metadata[] = {") for i in metadata: print((" { \"%s\", %d, %d, %s}," % (i[0],i[1],i[2],i[3]))) print(" { NULL, } /* End of array marker */ ") print("};")