diff options
| author | Danilo M. <danix@danix.xyz> | 2026-09-17 12:07:46 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-09-17 12:07:46 +0200 |
| commit | 64e8f20ce3a27dfc6cc2f37ae449dcb5eb91e7a9 (patch) | |
| tree | 6081ba303ad2fdead331220f29e9a211d47be715 | |
| parent | cfbd02e85f039a557cf6561b84b58097f70041d4 (diff) | |
| download | conky-theme-udt-64e8f20ce3a27dfc6cc2f37ae449dcb5eb91e7a9.tar.gz conky-theme-udt-64e8f20ce3a27dfc6cc2f37ae449dcb5eb91e7a9.zip | |
test: add an offscreen widget render harness
| -rw-r--r-- | test/render.lua | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/test/render.lua b/test/render.lua new file mode 100644 index 0000000..7d48d0e --- /dev/null +++ b/test/render.lua @@ -0,0 +1,87 @@ +-- Render a widget to a PNG without conky. +-- +-- Conky ships its Cairo bindings as a loadable module, so a widget's draw() +-- can be called against an image surface from plain Lua. That turns +-- edit-install-restart-toggle-screenshot into one command, which is how the +-- weather card's proportions were fixed. +-- +-- lua test/render.lua weather 16 12 3 5 /tmp/w.png +-- +-- Caveat: this crops to the single card. It says nothing about how the card +-- looks NEXT to its neighbours, which is a real failure mode (the weather +-- card's type once looked fine here and tiny beside the clock). Check the +-- live dashboard before believing anything about relative size. + +package.cpath = '/usr/lib64/conky/lib?.so;' .. package.cpath +package.path = './?.lua;' .. package.path +require 'cairo' + +local widget_name = arg[1] or error('usage: render.lua <widget> <cols> <rows> <w> <h> <out.png>') +local COLS = tonumber(arg[2]) or 8 +local ROWS = tonumber(arg[3]) or 6 +local wspan = tonumber(arg[4]) or 2 +local hspan = tonumber(arg[5]) or 3 +local out = arg[6] or '/tmp/widget.png' + +local GAP, MARGIN = 16, 28 +local sw, sh = 2560, 1080 + +-- The palette, read from the rendered conky.conf exactly as dashboard.lua +-- does, so the PNG uses the real scheme rather than invented colours. +local function config_colors() + local path = os.getenv('HOME') .. '/.config/conky/conky.conf' + local f = io.open(path, 'r') + if not f then return {} end + local src = f:read('*a') + f:close() + local c = {} + for k, v in src:gmatch("([%w_]+)%s*=%s*'(#%x%x%x%x%x%x)'") do c[k] = v end + return c +end + +local CFG = config_colors() + +local function hex(s, fallback) + local r, g, b = tostring(s or ''):match('^#?(%x%x)(%x%x)(%x%x)$') + if not r then return fallback or { 1, 0, 1 } end + return { tonumber(r, 16) / 255, tonumber(g, 16) / 255, tonumber(b, 16) / 255 } +end + +local colors = { + heading = hex(CFG.color1), label = hex(CFG.color2), + border = hex(CFG.color3), rule = hex(CFG.color3), + value = hex(CFG.color4), highlight = hex(CFG.color5), + ok = hex(CFG.color6), critical = hex(CFG.color7), + warning = hex(CFG.color8, { 0.88, 0.69, 0.41 }), + body = hex(CFG.default_color), + surface = hex(CFG.default_shade_color), +} + +local cw = (sw - MARGIN * 2 - GAP * (COLS - 1)) / COLS +local ch = (sh - MARGIN * 2 - GAP * (ROWS - 1)) / ROWS +local rect = { + x = MARGIN, y = MARGIN, + w = cw * wspan + GAP * (wspan - 1), + h = ch * hspan + GAP * (hspan - 1), +} + +local surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, rect.w + 40, rect.h + 40) +local cr = cairo_create(surf) +-- A backdrop close to the dashboard's own, so contrast reads honestly. +local bg = colors.surface +cairo_set_source_rgb(cr, bg[1] * 0.6, bg[2] * 0.6, bg[3] * 0.7) +cairo_paint(cr) +cairo_translate(cr, 20 - rect.x, 20 - rect.y) + +local ok, mod = pcall(require, 'widgets.' .. widget_name) +if not ok then + print('cannot load widget ' .. widget_name .. ': ' .. tostring(mod)) + os.exit(1) +end +local drew, err = pcall(mod.draw, cr, rect, colors) +if not drew then print('DRAW ERROR: ' .. tostring(err)) end + +cairo_destroy(cr) +cairo_surface_write_to_png(surf, out) +cairo_surface_destroy(surf) +print(string.format('%s at %dx%d on a %dx%d grid -> %s', widget_name, wspan, hspan, COLS, ROWS, out)) |
