Monorepo for Aesthetic.Computer aesthetic.computer
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Unifont Moods Fix - Progress Report#

Problem#

The unifont typeface in moods.mjs is rendering with multicolored/weird appearance after recent text rendering changes. Need to update unifont pipeline to be in parity with chunky8 and font_1.

Current State Analysis#

Files Involved#

  1. /workspaces/aesthetic-computer/system/public/aesthetic.computer/disks/moods.mjs - Uses unifont on lines 367 and 381
  2. /workspaces/aesthetic-computer/system/public/aesthetic.computer/lib/disk.mjs - Main text rendering pipeline

Key Findings#

Unifont Usage in Moods#

  • Line 367: text.box(mood, undefined, undefined, scale, "unifont").box.width;
  • Line 381: api.ink(moodColor).write(mood, { x: textX, y: 2, size: scale }, undefined, undefined, false, "unifont");

Text Rendering Pipeline (disk.mjs)#

The main pipeline has special handling for certain fonts:

// Line 192-196: ensureTypefaceLoaded function
function ensureTypefaceLoaded(typeface) {
  if (!typeface || typeof typeface.load !== "function") return;
  const requiresLoad =
    typeface.data?.bdfFont ||
    typeface.name === "unifont" ||
    typeface.name === "MatrixChunky8";

Key observation: Unifont is treated as a font that requires loading (like MatrixChunky8)

Color Preservation Logic#

Lines 425, 441+ in disk.mjs show special color handling:

const shouldPreserveColors = preserveColors || (typefaceName === "MatrixChunky8" && containsColorCodes);

Issue identified: MatrixChunky8 has special color preservation logic that unifont doesn't have!

MatrixChunky8 vs Unifont#

  • MatrixChunky8: Extensive color code handling, preserveColors flag support
  • Unifont: Listed in ensureTypefaceLoaded but missing color handling logic
  • Both are BDF fonts that require async loading

Root Cause#

Unifont is being treated as a "special" font (requires loading) but doesn't have the same color preservation and rendering logic as MatrixChunky8. The recent text changes likely added color code processing that's affecting unifont incorrectly.

Solution Approach#

Option 1: Add Unifont to Color Preservation Logic#

Update the shouldPreserveColors check to include unifont:

const shouldPreserveColors = preserveColors || 
  ((typefaceName === "MatrixChunky8" || typefaceName === "unifont") && containsColorCodes);

Option 2: Treat Unifont Like MatrixChunky8 Throughout Pipeline#

Add unifont checks wherever MatrixChunky8 is specially handled in the text rendering pipeline.

Option 3: Force Simple Rendering for Moods#

Since moods.mjs explicitly passes false for the preserveColors parameter (line 381), ensure unifont respects this flag.

Next Steps#

  1. Search for all color code handling logic in disk.mjs where MatrixChunky8 is mentioned
  2. Determine if unifont should:
    • Always disable color codes (simple monochrome)
    • Support color codes like MatrixChunky8
    • Be treated differently based on context
  3. Update rendering functions to handle unifont consistently
  4. Test in moods.mjs to verify fix

Files to Edit#

  • /workspaces/aesthetic-computer/system/public/aesthetic.computer/lib/disk.mjs - Add unifont handling
  • Possibly /workspaces/aesthetic-computer/system/public/aesthetic.computer/disks/moods.mjs - Verify usage

Status#

FIXED - Implementation complete.

Changes Made#

1. Color Preservation Fix (disk.mjs)#

Updated color preservation and shadow logic to treat unifont like MatrixChunky8:

  • Line 425: Added unifont to shouldPreserveColors check
  • Line 441: Added unifont to shadow rendering check
  • Line 3928: Added unifont to diagnostic logging check

2. Font Width Stability Fix (type.mjs)#

Fixed erratic marquee by forcing consistent 8px width:

  • Line 564-569: Added early return in getAdvance() to force unifont to always return 8px
  • Prevents width from changing when glyphs load asynchronously
  • Bypasses advance cache entirely for unifont

3. Subpixel Rendering Fix (moods.mjs)#

Fixed flickering by rounding positions to whole pixels:

  • Line 338: Round y position with Math.floor(y)
  • Line 387: Round textX position with Math.floor(-osc * bounceAmount)
  • Prevents subpixel rendering that causes jittery appearance with pixel fonts

4. Text Cleanup and Marquee Improvements (moods.mjs)#

Better text handling and animation:

  • Line 341-344: Improved newline/whitespace cleaning with regex
  • Line 386-387: Always apply subtle bounce (4px minimum) even for short text
  • Makes short moods more visually interesting

5. Font Metadata (fonts.mjs)#

  • Kept proportional: false for unifont
  • glyphWidth: 8 used as the fixed width

Known Issue: Question Mark Glyph#

Question marks may not display with unifont glyph initially because:

  • Unifont glyphs load asynchronously via BDF API
  • Early return in getAdvance() bypasses glyph loading check
  • May fall back to default font_1 until glyph loads
  • Potential fix: Preload common punctuation glyphs or ensure unifont glyph loading still works

Root Cause Summary#

  1. Color artifacts: Unifont wasn't in the color code stripping logic
  2. Erratic marquee: Async glyph loading changed width calculations mid-animation
  3. Flickering: Fractional pixel positions (0.25px increments) caused subpixel rendering jitter
  4. Solution: Force 8px width + round all positions to whole pixels

Testing#

Test in moods by running the piece and verifying:

  • ✓ Text renders in solid colors (no multicolor artifacts)
  • ✓ Horizontal scrolling/marquee is smooth (no jank)
  • ✓ Character spacing is correct at 8px per character
  • ✓ Text measurements match actual rendering

Generated: 2025-09-30 Updated: 2025-09-30 (Fixed)