286 lines
7.5 KiB
PHP
286 lines
7.5 KiB
PHP
<?php
|
|
|
|
const UNIT = 50;
|
|
const GAP = 3;
|
|
|
|
$infoFile = "../../keyboards/lily58/rev1/info.json";
|
|
$info = json_decode(file_get_contents($infoFile));
|
|
$positions = $info->layouts->LAYOUT->layout;
|
|
function determineTotalWidthAndHeight($positions): array
|
|
{
|
|
// Determine total width and height.
|
|
$width = $height = 0;
|
|
foreach ($positions as $i => $pos) {
|
|
$w = ($pos->w ?? 1) * UNIT;
|
|
$h = ($pos->h ?? 1) * UNIT;
|
|
$x = ($pos->x > 6 ? $pos->x - 2 : $pos->x) * UNIT;
|
|
$y = $pos->y * UNIT;
|
|
$newWidth = $x + $w + GAP;
|
|
$newHeight = $y + $h + GAP;
|
|
if ($newWidth > $width) {
|
|
$width = $newWidth;
|
|
}
|
|
if ($newHeight > $height) {
|
|
// Key 53/54 are the inner thumb keys, which are typically 1.5u.
|
|
$height = $newHeight;
|
|
}
|
|
}
|
|
|
|
return [$height, $width + UNIT - GAP];
|
|
}
|
|
|
|
[$height, $width] = determineTotalWidthAndHeight($positions);
|
|
|
|
$layersToRender = ["QUERTY", "COLEMAK", "NAVIGATION", "NUMBERS", "SYMBOLS", "FUNCTION", "MOUSE"];
|
|
$colors = [
|
|
"COLEMAK" => "darkorange",
|
|
"NAVIGATION" => "mediumaquamarine",
|
|
"NUMBERS" => "chocolate",
|
|
"SYMBOLS" => "thistle",
|
|
"FUNCTION" => "deepskyblue",
|
|
"MOUSE" => "navajowhite",
|
|
];
|
|
|
|
$layoutFile = "layout.h";
|
|
$file = file($layoutFile);
|
|
$currentDefine = null;
|
|
$continue = false;
|
|
$defineBuffer = [];
|
|
$defines = [];
|
|
$layerDefines = [];
|
|
$inEnum = false;
|
|
foreach ($file as $line) {
|
|
$line = trim($line);
|
|
if (str_starts_with($line, "enum ")) {
|
|
$inEnum = true;
|
|
continue;
|
|
}
|
|
if ($inEnum && $line === "};") {
|
|
$inEnum = false;
|
|
continue;
|
|
}
|
|
if ($inEnum) {
|
|
continue;
|
|
}
|
|
|
|
if (
|
|
$line === ""
|
|
|| str_starts_with($line, "//")
|
|
|| str_starts_with($line, "/*")
|
|
|| str_starts_with($line, "#pragma")
|
|
|| str_starts_with($line, "#include")
|
|
|| str_starts_with($line, "#ifndef")
|
|
|| str_starts_with($line, "#endif")
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
if (!$continue && $currentDefine !== null) {
|
|
if (is_array($defineBuffer) && count($defineBuffer) < 2) {
|
|
$defineBuffer = implode("", $defineBuffer);
|
|
}
|
|
if (in_array($currentDefine, $layersToRender)) {
|
|
$layerDefines[$currentDefine] = $defineBuffer;
|
|
} else {
|
|
$defines[$currentDefine] = $defineBuffer;
|
|
}
|
|
$currentDefine = null;
|
|
$defineBuffer = [];
|
|
$continue = false;
|
|
}
|
|
|
|
if (str_starts_with($line, "#define")) {
|
|
[, $currentDefine, $line] = preg_split("/\s+/", $line, 3);
|
|
}
|
|
|
|
$continue = str_ends_with($line, "\\");
|
|
$line = trim(rtrim($line, "\\"));
|
|
if (!$line) {
|
|
continue;
|
|
}
|
|
$bits = preg_split("/\s+/", $line);
|
|
foreach ($bits as $bit) {
|
|
$defineBuffer[] = rtrim($bit, ",");
|
|
}
|
|
unset($bit);
|
|
}
|
|
unset($bit, $bits, $currentDefine, $continue, $defineBuffer, $line);
|
|
|
|
$layers = [];
|
|
foreach ($layersToRender as $layerIndex => $layerName) {
|
|
if (!array_key_exists($layerName, $layerDefines)) {
|
|
continue;
|
|
}
|
|
$layer =& $layerDefines[$layerName];
|
|
$elements = [];
|
|
foreach ($layer as $keyIndex => $key) {
|
|
$color = "";
|
|
if (array_key_exists($key, $defines)) {
|
|
$key = $defines[$key];
|
|
}
|
|
if ($key === "KC_NO") {
|
|
$key = [""];
|
|
} elseif ($key === "KC_TRANS") {
|
|
$key = ["TRNS"];
|
|
} elseif ($key === "CW_TOGG") {
|
|
$key = ["Caps", "word"];
|
|
} elseif (str_starts_with($key, "KC_")) {
|
|
$key = [str_replace("KC_", "", $key)];
|
|
} elseif (preg_match("/^LT\((\d+),KC_(\w+)\)$/", $key, $m)) {
|
|
$toLayer = $layersToRender[$m[1]];
|
|
$key = [
|
|
$m[2],
|
|
"→" . substr($toLayer, 0, 3),
|
|
];
|
|
$color = $colors[$toLayer] ?? "";
|
|
} elseif (preg_match("/^TG\((\d+)\)$/", $key, $m)) {
|
|
$toLayer = $layersToRender[$m[1]];
|
|
$key = ["⇒" . substr($toLayer, 0, 3)];
|
|
$color = $colors[$toLayer] ?? "";
|
|
} elseif (preg_match("/^DF\((\d+)\)$/", $key, $m)) {
|
|
$toLayer = $layersToRender[$m[1]];
|
|
$key = ["D→" . substr($toLayer, 0, 3)];
|
|
$color = $colors[$toLayer] ?? "";
|
|
} elseif (preg_match("/^[RL](GUI|ALT|CTL|SFT)_T\(KC_(\w+)\)$/", $key, $m)) {
|
|
$key = [
|
|
$m[2],
|
|
$m[1],
|
|
];
|
|
} elseif (str_contains($key, "(")) {
|
|
$key = explode("(", $key);
|
|
$key[0] .= "(";
|
|
} else {
|
|
$key = [$key];
|
|
}
|
|
|
|
$pos =& $positions[$keyIndex];
|
|
if ($pos === null) {
|
|
error_log("encountered null pos at keyIndex $keyIndex in layer $layerName.");
|
|
continue;
|
|
}
|
|
|
|
$w = ($pos->w ?? 1) * UNIT;
|
|
$h = ($pos->h ?? 1) * UNIT;
|
|
$x = ($pos->x > 6 ? $pos->x - 2 : $pos->x) * (UNIT + GAP);
|
|
$y = $pos->y * (UNIT + GAP);
|
|
$tx = $x + GAP;
|
|
$ty = $y + 3 * GAP;
|
|
|
|
$key = implode(
|
|
"\n",
|
|
array_map(static fn(string $line) => "<tspan x=\"{$tx}\" dy=\"10\">{$line}</tspan>", $key)
|
|
);
|
|
$class = $color ? " {$color}" : "";
|
|
$elements[] = <<<ELEMENT
|
|
<g id="layer_{$layerIndex}_key_{$keyIndex}">
|
|
<rect class="key{$class}" x="{$x}" y="{$y}" width="{$w}" height="{$h}" rx="3" />
|
|
<text class="key-label" x="{$tx}" y="{$ty}">
|
|
{$key}
|
|
</text>
|
|
</g>
|
|
ELEMENT;
|
|
}
|
|
|
|
$elements = implode("\n", $elements);
|
|
$layerWidth = $width + 10;
|
|
$layerHeigth = $height + UNIT;
|
|
$offset = $layerIndex * ($height + GAP + UNIT) + UNIT;
|
|
$layers[] = <<<LAYER
|
|
|
|
<g class="layer" id="layer-{$layerName}" transform="translate(0,{$offset})">
|
|
<rect class="layer-border" height="{$layerHeigth}" width="{$layerWidth}" rx="10" />
|
|
<text class="layer-header" transform="translate(10,20)">Layer {$layerName}</text>
|
|
<g class="layer-keys" transform="translate(10,30)">
|
|
$elements
|
|
</g>
|
|
|
|
</g>
|
|
|
|
LAYER;
|
|
}
|
|
$layers = implode("\n", $layers);
|
|
|
|
/*echo '<?xml version="1.0" standalone="no" ?>'*/
|
|
?>
|
|
<svg xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 <?= $width + 10 ?> <?= $offset + $layerHeigth ?>">
|
|
<style>
|
|
g.layer .layer-border {
|
|
stroke-width: 1.5pt;
|
|
stroke: aliceblue;
|
|
fill: white;
|
|
}
|
|
.key {
|
|
fill: #eeeeee;
|
|
fill-opacity: 0.05;
|
|
stroke: #444444;
|
|
stroke-width: 1.2pt;
|
|
}
|
|
|
|
.key.navajowhite {
|
|
stroke: navajowhite;
|
|
}
|
|
|
|
.key.mediumaquamarine {
|
|
stroke: mediumaquamarine;
|
|
}
|
|
|
|
.key.chocolate {
|
|
stroke: chocolate;
|
|
}
|
|
|
|
.key.thistle {
|
|
stroke: thistle;
|
|
}
|
|
|
|
.key.deepskyblue {
|
|
stroke: deepskyblue;
|
|
}
|
|
|
|
/*.key.darkorange {*/
|
|
/* stroke: darkorange;*/
|
|
/*}*/
|
|
|
|
.layer.layer-NAVIGATION .key {
|
|
fill: mediumaquamarine;
|
|
}
|
|
|
|
.layer.layer-NUMBERS .key {
|
|
fill: chocolate;
|
|
}
|
|
|
|
.layer.layer-SYMBOLS .key {
|
|
fill: thistle;
|
|
}
|
|
|
|
.layer.layer-FUNCTION .key {
|
|
fill: deepskyblue;
|
|
}
|
|
|
|
.layer.layer-MOUSE .key {
|
|
fill: navajowhite;
|
|
}
|
|
|
|
/*.layer.layer-COLEMAK .key {*/
|
|
/* fill: darkorange;*/
|
|
/*}*/
|
|
|
|
.layer-border {
|
|
fill: none;
|
|
stroke-width: 1.5pt;
|
|
}
|
|
.layer-header {
|
|
font-size: 10pt;
|
|
font-weight: bold;
|
|
}
|
|
|
|
text {
|
|
font-size: 7pt;
|
|
text-align: left;
|
|
}
|
|
</style>
|
|
|
|
<?= $layers ?>
|
|
|
|
</svg>
|