<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tinyfont | Go Education Project</title><link>https://goeducation.net/docs/tinyfont/</link><atom:link href="https://goeducation.net/docs/tinyfont/index.xml" rel="self" type="application/rss+xml"/><description>Tinyfont</description><generator>HugoBlox Kit (https://hugoblox.com)</generator><language>en-us</language><image><url>https://goeducation.net/media/logo.svg</url><title>Tinyfont</title><link>https://goeducation.net/docs/tinyfont/</link></image><item><title>Getting Started</title><link>https://goeducation.net/docs/tinyfont/getting-started/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://goeducation.net/docs/tinyfont/getting-started/</guid><description>&lt;p&gt;
is a lightweight font rendering library designed for microcontrollers. It works with any display that implements the &lt;code&gt;drivers.Displayer&lt;/code&gt; interface — OLEDs, TFT screens, e-ink panels — and draws text one pixel at a time, making it ideal for resource-constrained environments where a full font engine would be too large.&lt;/p&gt;
&lt;h2 id="quick-start"&gt;Quick start&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;image/color&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;tinygo.org/x/tinyfont&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// disp is any drivers.Displayer (e.g. an SSD1306 OLED or ILI9341 TFT)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;tinyfont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;tinyfont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TomThumb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RGBA&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;R&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0xff&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;WriteLine&lt;/code&gt; signature:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;display&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;drivers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Displayer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;font&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Fonter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RGBA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;display&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Target display — anything with &lt;code&gt;SetPixel&lt;/code&gt; + &lt;code&gt;Size&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;font&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A &lt;code&gt;Fonter&lt;/code&gt; value — pointer to one of the font variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;x&lt;/code&gt;, &lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Top-left origin of the text baseline (pixels)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The string to render (ASCII; full Unicode depends on font)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Foreground color as &lt;code&gt;color.RGBA&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="built-in-fonts"&gt;Built-in fonts&lt;/h2&gt;
&lt;p&gt;The root package ships four bitmap fonts that range from tiny to small:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tinyfont.Tiny3x3a2pt7b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3×3 px&lt;/td&gt;
&lt;td&gt;Status indicators, tiny labels&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tinyfont.Picopixel&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;~5 px&lt;/td&gt;
&lt;td&gt;Dense data on small OLEDs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tinyfont.TomThumb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;~6 px&lt;/td&gt;
&lt;td&gt;Compact, very readable at small sizes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;tinyfont.Org01&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;~6 px&lt;/td&gt;
&lt;td&gt;Clean monospace look&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Sub-packages (&lt;code&gt;freemono&lt;/code&gt;, &lt;code&gt;freesans&lt;/code&gt;, &lt;code&gt;freeserif&lt;/code&gt;, &lt;code&gt;notosans&lt;/code&gt;, &lt;code&gt;proggy&lt;/code&gt;, &lt;code&gt;gophers&lt;/code&gt;) add larger proportional and monospace faces at the cost of binary size.&lt;/p&gt;</description></item><item><title>API Reference &amp; Examples</title><link>https://goeducation.net/docs/tinyfont/reference/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://goeducation.net/docs/tinyfont/reference/</guid><description>&lt;h2 id="the-driversdisplayer-interface"&gt;The &lt;code&gt;drivers.Displayer&lt;/code&gt; interface&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Displayer&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// SetPixel draws a single pixel at (x, y) with color c.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;SetPixel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RGBA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Size returns the display dimensions in pixels.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;int16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Display flushes buffered data to the hardware (no-op for direct-write displays).&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Display&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Any struct that satisfies these three methods can be passed to &lt;code&gt;tinyfont.WriteLine&lt;/code&gt;. The TinyGo drivers package provides ready-made implementations for most common displays.&lt;/p&gt;
&lt;h2 id="multi-line-text"&gt;Multi-line text&lt;/h2&gt;
&lt;p&gt;For displays with limited height, you can call &lt;code&gt;WriteLine&lt;/code&gt; multiple times advancing &lt;code&gt;y&lt;/code&gt; by the font&amp;rsquo;s line height:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;lineH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;int16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lineH&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;range&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;#34;\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tinyfont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;disp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;tinyfont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TomThumb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;white&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lineH&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="font-tester"&gt;Font tester&lt;/h2&gt;
&lt;p&gt;Try out the built-in fonts directly in the browser. The widget below runs the same rendering code you would use on a real microcontroller, compiled with TinyGo to WebAssembly.&lt;/p&gt;
&lt;div id="tft-root" class="not-prose my-8"&gt;
&lt;div class="tft-screen-wrap"&gt;
&lt;div class="tft-screen-bezel"&gt;
&lt;canvas id="tft-canvas" class="tft-canvas"&gt;&lt;/canvas&gt;
&lt;/div&gt;
&lt;div id="tft-overlay" class="tft-overlay"&gt;
&lt;span id="tft-status"&gt;Loading WASM…&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div class="tft-controls" id="tft-controls" aria-disabled="true"&gt;
&lt;div class="tft-row"&gt;
&lt;label class="tft-label" for="tft-text"&gt;Text&lt;/label&gt;
&lt;input id="tft-text" type="text" class="tft-input tft-input--wide"
value="Hello, TinyGo!" maxlength="64"
placeholder="Type something…"&gt;
&lt;/div&gt;
&lt;div class="tft-row"&gt;
&lt;label class="tft-label" for="tft-font"&gt;Font&lt;/label&gt;
&lt;select id="tft-font" class="tft-input"&gt;&lt;/select&gt;
&lt;/div&gt;
&lt;div class="tft-row tft-row--colors"&gt;
&lt;div&gt;
&lt;label class="tft-label" for="tft-fg"&gt;Foreground&lt;/label&gt;
&lt;input id="tft-fg" type="color" class="tft-color" value="#1DCAD4"&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;label class="tft-label" for="tft-bg"&gt;Background&lt;/label&gt;
&lt;input id="tft-bg" type="color" class="tft-color" value="#0f1e35"&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;label class="tft-label" for="tft-display"&gt;Display&lt;/label&gt;
&lt;select id="tft-display" class="tft-input"&gt;
&lt;option value="128,64" selected&gt;128 × 64 (OLED SSD1306)&lt;/option&gt;
&lt;option value="128,128"&gt;128 × 128 (OLED SH1107)&lt;/option&gt;
&lt;option value="240,135"&gt;240 × 135 (TFT ST7789)&lt;/option&gt;
&lt;option value="320,240"&gt;320 × 240 (TFT ILI9341)&lt;/option&gt;
&lt;/select&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;label class="tft-label" for="tft-scale"&gt;Scale&lt;/label&gt;
&lt;select id="tft-scale" class="tft-input"&gt;
&lt;option value="3"&gt;3×&lt;/option&gt;
&lt;option value="4" selected&gt;4×&lt;/option&gt;
&lt;option value="6"&gt;6×&lt;/option&gt;
&lt;/select&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p id="tft-build-notice" class="tft-hidden text-sm text-amber-600 dark:text-amber-400 mt-3"&gt;
⚠️ WASM binary not found. Run &lt;code&gt;./build-wasm.sh&lt;/code&gt; to build it.
&lt;/p&gt;
&lt;/div&gt;
&lt;style&gt;
#tft-root { font-family: inherit; }
.tft-screen-wrap {
position: relative;
display: inline-block;
width: 100%;
}
.tft-screen-bezel {
background: #0a0e1a;
border-radius: 0.75rem;
padding: 1rem 1.25rem;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 0 2px #1DCAD433, inset 0 1px 4px #00000099;
min-height: 6rem;
}
.tft-canvas {
image-rendering: pixelated;
image-rendering: crisp-edges;
display: block;
border-radius: 4px;
box-shadow: 0 0 12px #1DCAD422;
}
.tft-overlay {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 0.75rem;
background: rgba(10,14,26,0.85);
color: #1DCAD4;
font-size: 0.875rem;
font-family: monospace;
transition: opacity 0.3s;
}
.tft-overlay.tft-ready { opacity: 0; pointer-events: none; }
.tft-controls {
margin-top: 1rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.tft-controls[aria-disabled="true"] { opacity: 0.5; pointer-events: none; }
.tft-row {
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
}
.tft-row--colors { align-items: flex-start; gap: 1.25rem; }
.tft-row--colors &gt; div { display: flex; flex-direction: column; gap: 0.25rem; }
.tft-label {
font-size: 0.75rem;
font-weight: 600;
color: rgb(107 114 128);
min-width: 5rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.dark .tft-label { color: rgb(156 163 175); }
.tft-input {
padding: 0.375rem 0.625rem;
border-radius: 0.5rem;
border: 1.5px solid rgb(209 213 219);
background: white;
color: rgb(17 24 39);
font-size: 0.875rem;
outline: none;
transition: border-color 0.15s;
}
.tft-input:focus { border-color: #1DCAD4; }
.dark .tft-input { background: rgb(17 24 39); border-color: rgb(75 85 99); color: rgb(229 231 235); }
.tft-input--wide { flex: 1; min-width: 12rem; }
.tft-color {
width: 2.5rem;
height: 2.25rem;
border-radius: 0.5rem;
border: 1.5px solid rgb(209 213 219);
padding: 2px;
cursor: pointer;
background: none;
}
.dark .tft-color { border-color: rgb(75 85 99); }
.tft-hidden { display: none !important; }
&lt;/style&gt;
&lt;script&gt;
(function () {
'use strict';
const WASM_URL = '/wasm/tinyfont-tester.wasm';
const EXEC_URL = '/wasm/wasm_exec.js';
const canvas = document.getElementById('tft-canvas');
const overlay = document.getElementById('tft-overlay');
const status = document.getElementById('tft-status');
const controls = document.getElementById('tft-controls');
const txtInput = document.getElementById('tft-text');
const fontSel = document.getElementById('tft-font');
const fgPicker = document.getElementById('tft-fg');
const bgPicker = document.getElementById('tft-bg');
const displaySel= document.getElementById('tft-display');
const scaleSel = document.getElementById('tft-scale');
const notice = document.getElementById('tft-build-notice');
let offscreen = document.createElement('canvas');
let offCtx = offscreen.getContext('2d');
let mainCtx = canvas.getContext('2d');
let ready = false;
function hexToRgb(hex) {
const r = parseInt(hex.slice(1,3),16);
const g = parseInt(hex.slice(3,5),16);
const b = parseInt(hex.slice(5,7),16);
return [r, g, b];
}
function setScale(scale, w, h) {
canvas.width = w * scale;
canvas.height = h * scale;
canvas.style.maxWidth = '100%';
mainCtx.imageSmoothingEnabled = false;
}
function render() {
if (!ready) return;
const [fw, fh] = window.tinyFontGetSize();
const scale = parseInt(scaleSel.value, 10);
const fg = hexToRgb(fgPicker.value);
const bg = hexToRgb(bgPicker.value);
setScale(scale, fw, fh);
offscreen.width = fw;
offscreen.height = fh;
window.tinyFontRender(
txtInput.value,
fontSel.selectedIndex,
fg[0], fg[1], fg[2],
bg[0], bg[1], bg[2]
);
const pixels = window.tinyFontGetPixels();
const imgData = offCtx.createImageData(fw, fh);
imgData.data.set(pixels);
offCtx.putImageData(imgData, 0, 0);
mainCtx.drawImage(offscreen, 0, 0, fw * scale, fh * scale);
}
function applyDisplay() {
if (!ready) return;
const [w, h] = displaySel.value.split(',').map(Number);
window.tinyFontResize(w, h);
render();
}
function populateFonts() {
const names = window.tinyFontGetFonts();
for (let i = 0; i &lt; names.length; i++) {
const opt = document.createElement('option');
opt.value = i;
opt.textContent = names[i];
fontSel.appendChild(opt);
}
}
function onReady() {
ready = true;
populateFonts();
applyDisplay();
overlay.classList.add('tft-ready');
controls.removeAttribute('aria-disabled');
txtInput.addEventListener('input', render);
fontSel.addEventListener('change', render);
fgPicker.addEventListener('input', render);
bgPicker.addEventListener('input', render);
scaleSel.addEventListener('change', render);
displaySel.addEventListener('change', applyDisplay);
}
function setStatus(msg) { status.textContent = msg; }
async function load() {
try {
const probe = await fetch(WASM_URL, { method: 'HEAD' });
if (!probe.ok) throw new Error('not found');
} catch {
notice.classList.remove('tft-hidden');
overlay.classList.add('tft-ready');
setStatus('');
return;
}
setStatus('Loading runtime…');
await new Promise((resolve, reject) =&gt; {
const s = document.createElement('script');
s.src = EXEC_URL;
s.onload = resolve;
s.onerror = reject;
document.head.appendChild(s);
});
window.tinyFontReady = onReady;
setStatus('Loading WASM…');
const go = new Go();
let result;
try {
result = await WebAssembly.instantiateStreaming(
fetch(WASM_URL),
go.importObject
);
} catch {
const bytes = await (await fetch(WASM_URL)).arrayBuffer();
result = await WebAssembly.instantiate(bytes, go.importObject);
}
setStatus('Starting…');
go.run(result.instance);
}
load().catch(err =&gt; {
setStatus('Error: ' + err.message);
console.error('[tinyfont-tester]', err);
});
})();
&lt;/script&gt;
&lt;p&gt;Select a font, adjust colors, choose a display size, and type your text to preview exactly how it will look on the target hardware.&lt;/p&gt;</description></item></channel></rss>