From 539ba6a657671e5318d9a425b97b721246f9b7fe Mon Sep 17 00:00:00 2001 From: Jim Huang Date: Thu, 20 Nov 2025 04:12:33 +0800 Subject: [PATCH] Replace inline ASCII art with generated PNG logo This converts README logo from inline HTML
 block to PNG image for
better rendering consistency across platforms. It adds automated logo
generation script using ImageMagick with Intel One Mono font.
- README.md: Replace 
 with  tag, move ASCII art to comment
- scripts/generate-logo.sh: Automated PNG generation with font fallback
---
 .editorconfig            |   3 +-
 Documentation/logo.png   | Bin 0 -> 5731 bytes
 README.md                |  17 ++--
 scripts/generate-logo.sh | 206 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 219 insertions(+), 7 deletions(-)
 create mode 100644 Documentation/logo.png
 create mode 100755 scripts/generate-logo.sh

diff --git a/.editorconfig b/.editorconfig
index 21de05aa..0900d177 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -2,13 +2,14 @@
 root = true
 
 # Shell script-specific settings
+# Aligns with .ci/check-format.sh: shfmt -i 4 -bn -ci -sr
 [*.sh]
 indent_style = space
 indent_size = 4
 end_of_line = lf
 trim_trailing_whitespace = true
 insert_final_newline = true
-function_next_line = true
+function_next_line = false
 switch_case_indent = true
 space_redirects = true
 binary_next_line = true
diff --git a/Documentation/logo.png b/Documentation/logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..a717ab058bdfb297c832a909471adf9947f88f66
GIT binary patch
literal 5731
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

literal 0
HcmV?d00001

diff --git a/README.md b/README.md
index 26dd0a7b..cb2cf3da 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,10 @@
 # Linmo: A Simple Multi-tasking Operating System Kernel
-```
+
+
+Linmo Logo +
+ + Linmo is a preemptive, multi-tasking operating system kernel built as an educational showcase for resource-constrained systems. It offers a lightweight environment where all tasks share a single address space, diff --git a/scripts/generate-logo.sh b/scripts/generate-logo.sh new file mode 100755 index 00000000..a43635ce --- /dev/null +++ b/scripts/generate-logo.sh @@ -0,0 +1,206 @@ +#!/usr/bin/env bash + +# Generate logo PNG from ASCII art in README.md +# +# This script extracts ASCII art from a specially formatted comment block +# in README.md and converts it to a PNG image using ImageMagick. +# +# Requirements: +# - ImageMagick (magick or convert command) +# - Intel One Mono font (with fallback to Menlo/Courier) + +set -euo pipefail + +# Configuration +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +README="$PROJECT_ROOT/README.md" +OUTPUT_DIR="$PROJECT_ROOT/Documentation" +OUTPUT_FILE="$OUTPUT_DIR/logo.png" + +# Font preferences (in order of preference) +FONTS=("Intel-One-Mono" "Menlo-Regular" "Courier-New" "Courier") + +# ImageMagick parameters +POINTSIZE=15 +INTERLINE_SPACING=-4 +KERNING=0 +CANVAS_WIDTH=1600 + +# Expected minimum number of lines in ASCII art +MIN_LINES=10 + +# Extract ASCII art from README.md comment block +extract_ascii_art() { + if [[ ! -f "$README" ]]; then + echo "Error: README.md not found at $README" >&2 + return 1 + fi + + local ascii_art + ascii_art=$(awk '//' "$README" \ + | sed '1d;$d' \ + | sed 's/^ //') + + if [[ -z "$ascii_art" ]]; then + echo "Error: No ASCII art found in README.md comment block" >&2 + echo "Expected block format:" >&2 + echo " " >&2 + return 1 + fi + + # Validate line count + local line_count + line_count=$(echo "$ascii_art" | wc -l | tr -d ' ') + if [[ "$line_count" -lt "$MIN_LINES" ]]; then + echo "Warning: ASCII art has only $line_count lines (expected at least $MIN_LINES)" >&2 + fi + + echo "$ascii_art" +} + +# Detect available ImageMagick command +detect_imagemagick() { + if command -v magick &> /dev/null; then + echo "magick" + elif command -v convert &> /dev/null; then + echo "convert" + else + return 1 + fi +} + +# Detect available font from preference list +detect_font() { + local available_fonts + available_fonts=$(magick -list font 2> /dev/null | grep -i "Font:" | awk '{print $2}' || echo "") + + for font in "${FONTS[@]}"; do + if echo "$available_fonts" | grep -qi "^$font$"; then + echo "$font" + return 0 + fi + done + + # No preferred font found, return first available monospace font + echo "Courier" +} + +# Generate PNG using ImageMagick +generate_png() { + local ascii_art="$1" + + # Detect ImageMagick command + local magick_cmd + if ! magick_cmd=$(detect_imagemagick); then + echo "Error: ImageMagick is not installed." >&2 + echo "Please install ImageMagick:" >&2 + echo " macOS: brew install imagemagick" >&2 + echo " Ubuntu/Debian: sudo apt-get install imagemagick" >&2 + echo " Fedora/RHEL: sudo dnf install ImageMagick" >&2 + exit 1 + fi + + # Detect best available font + local font + font=$(detect_font) + echo "Using font: $font" + + # Ensure output directory exists + if [[ ! -d "$OUTPUT_DIR" ]]; then + echo "Creating output directory: $OUTPUT_DIR" + mkdir -p "$OUTPUT_DIR" + fi + + # Generate PNG with optimized parameters + # - background: black for dark theme + # - fill: white text for maximum contrast + # - font: Intel One Mono for excellent Unicode support + # - pointsize: 16 for compact yet readable text + # - interline-spacing: -4 for tight vertical spacing + # - kerning: 0 for standard character spacing + # - caption: better text rendering than label + # - trim: remove excess whitespace + # - +repage: reset virtual canvas + echo "$ascii_art" | $magick_cmd \ + -background black \ + -fill white \ + -font "$font" \ + -pointsize "$POINTSIZE" \ + -interline-spacing "$INTERLINE_SPACING" \ + -kerning "$KERNING" \ + -size "${CANVAS_WIDTH}x" \ + caption:@- \ + -trim \ + +repage \ + "$OUTPUT_FILE" + + # Verify output file was created + if [[ ! -f "$OUTPUT_FILE" ]]; then + echo "Error: Failed to generate $OUTPUT_FILE" >&2 + return 1 + fi + + # Display output information + local size + size=$(identify "$OUTPUT_FILE" 2> /dev/null | awk '{print $3}' || echo "unknown") + echo "✓ Logo generated successfully" + echo " Output: $OUTPUT_FILE" + echo " Size: $size" +} + +# Display usage information +usage() { + cat << EOF +Usage: $(basename "$0") [OPTIONS] + +Generate Linmo logo PNG from ASCII art in README.md + +Options: + -h, --help Display this help message + +Environment Variables: + POINTSIZE Font size (default: $POINTSIZE) + INTERLINE_SPACING Line spacing (default: $INTERLINE_SPACING) + KERNING Character spacing (default: $KERNING) + +Example: + $0 + POINTSIZE=20 $0 + +EOF +} + +# Main execution +main() { + # Parse command line arguments + while [[ $# -gt 0 ]]; do + case "$1" in + -h | --help) + usage + exit 0 + ;; + *) + echo "Error: Unknown option: $1" >&2 + usage + exit 1 + ;; + esac + shift + done + + echo "Extracting ASCII art from README.md..." + local ascii_art + if ! ascii_art=$(extract_ascii_art); then + exit 1 + fi + + echo "Generating PNG image..." + if ! generate_png "$ascii_art"; then + exit 1 + fi +} + +main "$@"