## date_default_timezone_set(getenv('SLATE_TZ') ?: 'UTC'); $W = (int)($argv[1] ?? 1072); $H = (int)($argv[2] ?? 1448); $MARGIN = 44; ## Left clear for the battery line, which only the device can draw. $FOOTER = 60; $INK = 'black'; $FADED = '#9a9a9a'; $RULE = '#c8c8c8'; ## One display line. Meetings become their own indented lines under their box. function lines_from_stdin() { $lines = []; while (($raw = fgets(STDIN)) !== false) { $raw = rtrim($raw, "\n"); if ($raw === '') continue; $f = explode('|', $raw); if (count($f) < 5) continue; $lines[] = [ 'kind' => 'box', 'time' => $f[0], 'label' => $f[1], 'left' => (int)$f[3], 'status' => $f[4], ]; ## trailing triples: status|id|title for ($i = 5; $i + 2 < count($f) + 1; $i += 3) { if (!isset($f[$i + 2])) break; $lines[] = [ 'kind' => 'meeting', 'time' => '', 'label' => $f[$i + 2], 'left' => null, 'status' => $f[$i], ]; } } return $lines; } function esc($s) { return str_replace(["\\", "'"], ["\\\\", "\\'"], $s); } ## ImageMagick anchors draw text on the left, and the font is mono, so a ## right edge has to be worked out from the string length function right_x($text, $fs, $right_edge) { return (int)($right_edge - strlen($text) * $fs * 0.60); } function ink($status, $kind) { global $INK, $FADED; if ($status === 'past') return $FADED; return $INK; } $rows = lines_from_stdin(); ## A day with every row behind it, for the header to say so. $spent = count($rows) > 0; foreach ($rows as $r) { if ($r['status'] !== 'past') { $spent = false; break; } } $head_h = 132; $avail = $H - $head_h - $MARGIN - $FOOTER; $n = max(count($rows), 1); $row_h = min(96, intdiv($avail, $n)); $fs_box = (int)($row_h * 0.46); $fs_meet = (int)($row_h * 0.36); $fs_time = $fs_box; $out = []; $out[] = "push graphic-context"; ## header: date, and a heavy rule under it $today = date('D j M'); $out[] = "font-size 60"; $out[] = "fill $INK"; $out[] = sprintf("text %d,%d '%s'", $MARGIN, 74, esc($today)); $out[] = "font-size 30"; $out[] = "fill $FADED"; $out[] = sprintf("text %d,%d '%s'", $MARGIN, 110, esc($spent ? 'work day - done' : 'work day')); ## when this was rendered -- the slate keeps showing the last one it got, so ## staleness has to be visible on the slate itself $stamp = 'as of ' . date('H:i'); $out[] = sprintf("text %d,%d '%s'", right_x($stamp, 30, $W - $MARGIN), 74, esc($stamp)); $out[] = "fill $INK"; $out[] = sprintf("rectangle %d,%d %d,%d", $MARGIN, 124, $W - $MARGIN, 127); $y = $head_h; foreach ($rows as $r) { $y += $row_h; $base = $y - (int)($row_h * 0.28); $colour = ink($r['status'], $r['kind']); if ($r['kind'] === 'box') { ## a "now" row gets a filled left marker so it is findable at a glance if ($r['status'] === 'now') { $out[] = "fill $INK"; $out[] = sprintf("rectangle %d,%d %d,%d", $MARGIN - 22, $y - $row_h + 12, $MARGIN - 12, $y - 4); } $out[] = "font-size $fs_time"; $out[] = "fill $colour"; $out[] = sprintf("text %d,%d '%s'", $MARGIN, $base, esc($r['time'])); $out[] = "font-size $fs_box"; $out[] = sprintf("text %d,%d '%s'", $MARGIN + 170, $base, esc($r['label'])); if ($r['left'] > 0) { $out[] = "font-size $fs_meet"; $out[] = "fill $colour"; $out[] = sprintf("text %d,%d '%dm'", $W - $MARGIN - 90, $base, $r['left']); } $out[] = "fill $RULE"; $out[] = sprintf("rectangle %d,%d %d,%d", $MARGIN, $y + 2, $W - $MARGIN, $y + 3); } else { $out[] = "font-size $fs_meet"; $out[] = "fill $colour"; ## truncate to what actually fits between the indent and the right margin $indent = $MARGIN + 200; $room = (int)((($W - $MARGIN) - $indent) / ($fs_meet * 0.60)) - 3; $title = $r['label']; if (strlen($title) > $room) $title = substr($title, 0, $room - 3) . '...'; $out[] = sprintf("text %d,%d '%s %s'", $MARGIN + 200, $base, "\xe2\x80\xa2", esc($title)); } } $out[] = "pop graphic-context"; echo implode("\n", $out), "\n";