aboutsummaryrefslogtreecommitdiff
path: root/lib/python/qmk/painter.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python/qmk/painter.py')
-rw-r--r--lib/python/qmk/painter.py102
1 files changed, 102 insertions, 0 deletions
diff --git a/lib/python/qmk/painter.py b/lib/python/qmk/painter.py
index 381a996443..512a486ce8 100644
--- a/lib/python/qmk/painter.py
+++ b/lib/python/qmk/painter.py
@@ -1,5 +1,6 @@
"""Functions that help us work with Quantum Painter's file formats.
"""
+import datetime
import math
import re
from string import Template
@@ -79,6 +80,105 @@ valid_formats = {
}
}
+
+def _render_text(values):
+ # FIXME: May need more chars with GIFs containing lots of frames (or longer durations)
+ return "|".join([f"{i:4d}" for i in values])
+
+
+def _render_numeration(metadata):
+ return _render_text(range(len(metadata)))
+
+
+def _render_values(metadata, key):
+ return _render_text([i[key] for i in metadata])
+
+
+def _render_image_metadata(metadata):
+ size = metadata.pop(0)
+
+ lines = [
+ "// Image's metadata",
+ "// ----------------",
+ f"// Width: {size['width']}",
+ f"// Height: {size['height']}",
+ ]
+
+ if len(metadata) == 1:
+ lines.append("// Single frame")
+
+ else:
+ lines.extend([
+ f"// Frame: {_render_numeration(metadata)}",
+ f"// Duration(ms): {_render_values(metadata, 'delay')}",
+ f"// Compression: {_render_values(metadata, 'compression')} >> See qp.h, painter_compression_t",
+ f"// Delta: {_render_values(metadata, 'delta')}",
+ ])
+
+ deltas = []
+ for i, v in enumerate(metadata):
+ # Not a delta frame, go to next one
+ if not v["delta"]:
+ continue
+
+ # Unpack rect's coords
+ l, t, r, b = v["delta_rect"]
+
+ delta_px = (r - l) * (b - t)
+ px = size["width"] * size["height"]
+
+ # FIXME: May need need more chars here too
+ deltas.append(f"// Frame {i:3d}: ({l:3d}, {t:3d}) - ({r:3d}, {b:3d}) >> {delta_px:4d}/{px:4d} pixels ({100*delta_px/px:.2f}%)")
+
+ if deltas:
+ lines.append("// Areas on delta frames")
+ lines.extend(deltas)
+
+ return "\n".join(lines)
+
+
+def generate_subs(cli, out_bytes, *, font_metadata=None, image_metadata=None, command):
+ if font_metadata is not None and image_metadata is not None:
+ raise ValueError("Cant generate subs for font and image at the same time")
+
+ subs = {
+ "year": datetime.date.today().strftime("%Y"),
+ "input_file": cli.args.input.name,
+ "sane_name": re.sub(r"[^a-zA-Z0-9]", "_", cli.args.input.stem),
+ "byte_count": len(out_bytes),
+ "bytes_lines": render_bytes(out_bytes),
+ "format": cli.args.format,
+ "generator_command": command,
+ }
+
+ if font_metadata is not None:
+ subs.update({
+ "generated_type": "font",
+ "var_prefix": "font",
+ # not using triple quotes to avoid extra indentation/weird formatted code
+ "metadata": "\n".join([
+ "// Font's metadata",
+ "// ---------------",
+ f"// Glyphs: {', '.join([i for i in font_metadata['glyphs']])}",
+ ]),
+ })
+
+ elif image_metadata is not None:
+ subs.update({
+ "generated_type": "image",
+ "var_prefix": "gfx",
+ "generator_command": command,
+ "metadata": _render_image_metadata(image_metadata),
+ })
+
+ else:
+ raise ValueError("Pass metadata for either an image or a font")
+
+ subs.update({"license": render_license(subs)})
+
+ return subs
+
+
license_template = """\
// Copyright ${year} QMK -- generated source code only, ${generated_type} retains original copyright
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -110,6 +210,8 @@ def render_header(subs):
source_file_template = """\
${license}
+${metadata}
+
#include <qp.h>
const uint32_t ${var_prefix}_${sane_name}_length = ${byte_count};