数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 81|回复: 2

[other] u8g2-js:打通单色屏开发 Web 仿真的最后一公里

[复制链接]
发表于 4 小时前 | 显示全部楼层 |阅读模式
u8g2-js

U8G2 单色图形库纯 JS 移植到浏览器 / Node, 像素级还原真机渲染,用于 AI 生成代码 + 浏览器仿真,方便后续基于 U8G2 做小型设备开发。


  • 零构建、零依赖:原生 ES Module,浏览器 file:// 直接可用,Node 同样可跑。
  • 像素级还原:帧缓冲布局、draw_color 0/1/2、字体 RLE 位流解码、draw_l90 旋转变换、 Bresenham 图元 —— 全部与 C 源码 1:1 移植,已与原版 C 库逐字节交叉验证(见 验证)。
  • 字体运行时加载:字体本质就是 Uint8Array 字节流,运行时用你自己的 JS 载入, 支持任意 U8G2 字体(含 bdfconv 生成的中文字体)。
  • API 兼容:Arduino U8g2lib 风格 camelCase 为主,同时提供 C 风格 snake_case / u8g2_* 别名。


在线演示
一个 212×102 单色墨水屏传感器仪表盘(CO₂ / PM2.5 / 温湿度趋势),基于 u8g2-js 构建—— 在浏览器里对真实墨水屏做像素级仿真:


u8g2-js 在线演示 —— 212x102 墨水屏 CO2 趋势界面


该演示把 u8g2-js 作为 git 子模块引入,跑的是和真机完全一致的同一套渲染引擎。



基于的上游版本
本移植对照 U8G2 上游 master 分支的基准提交:
  1. commit ab9e48b2228351e9476682a70b7f3ee4909cd585
  2. Date: 2026-06-27 16:10:31 +0200
  3. Subject: Merge pull request #2786 from iggymayer/fix-flipmode-ssd1362z-OEL1M0033WE
复制代码
原版 C 库已浅克隆到本仓库旁边的 u8g2/ 目录(仅此提交), tools/cverify/build.sh逐字节交叉验证正是针对这一版 C 库进行的。 要升级基准版本:重新 git clone https://github.com/olikraus/u8g2.git 到最新 master, 并重跑 bash tools/cverify/build.sh 确认一致性后即可。



快速开始
  1. // 浏览器:<script type="module">
  2. import { U8g2, U8g2Font } from './u8g2-js/src/index.js';

  3. // 建一块 SSD1306 128x64 屏
  4. const u8g2 = new U8g2({ display: 'ssd1306_128x64_noname_f' });

  5. // 运行时载入字体(字体就是字节数组)
  6. const font = await U8g2Font.load('./u8g2-js/demo/fonts/u8g2_font_5x7_tf.bin');
  7. u8g2.setFont(font);

  8. // 画图 —— 与 Arduino 写法一致
  9. u8g2.clearBuffer();
  10. u8g2.drawStr(0, 10, 'Hello');
  11. u8g2.drawBox(0, 20, 10, 5);
  12. u8g2.drawCircle(60, 30, 8, 15);
  13. u8g2.sendBuffer();

  14. // 挂到 <canvas> 上显示
  15. u8g2.attachCanvas(document.getElementById('screen'));
复制代码
Node 端同样可用(无头导出 PBM/原始字节,适合测试):
  1. import { U8g2, U8g2Font, toPBM } from './u8g2-js/src/index.js';
  2. const u8g2 = new U8g2({ display: 'ssd1306_128x64_noname_f' });
  3. u8g2.setFont(await U8g2Font.load('demo/fonts/u8g2_font_5x7_tf.bin'));
  4. u8g2.drawStr(0, 10, 'Hello');
  5. console.log(toPBM(u8g2)); // 导出 P4 PBM
复制代码


演示(demo)
打开 demo/demo-standalone.html —— 自包含单文件,直接双击就能跑(file://,无需服务器)。

里面是一个交互式仿真器:选屏、旋转、缩放、网格、写 U8G2 代码、动画循环、运行时加载任意字体 (下拉 / .bin 文件 / 粘贴 base64)。默认示例就是一个中文仪表盘(温度传感器 / 湿度 / 状态), 演示内置的全量中文字库。

开发态可改 demo/demo.html(ESM,需本地服务器),改完重新打包:
  1. node tools/build-demo.js # 生成 demo/demo-standalone.html
  2. node tools/check-demo.js # 启动自检(DOM stub 冒烟测试)
复制代码


内置中文字库(全量)
demo 内置 chinese_full_12 / chinese_full_16 / chinese_full_24 三个全量中文字库 (字体源:SimSun 宋体 C:\Windows\Fonts\simsun.ttc),字符集覆盖:

  • 全部 CJK 统一汉字 U+4E00–U+9FFF(20902 字,含生僻字)+ CJK 扩展 A U+3400–4DBF
  • 全 ASCII 0x20–0x7E + Latin-1(° ± × ÷ · …)
  • 中文标点、℃ ℉ 等符号、全角形式、CJK 兼容形式
~2.8 万字形,模拟器里 AI 生成/写出的任意中文都能渲染。

垂直对齐说明:字体用 bdfconv 公共高度模式 -b 1 生成,所有字形共享统一的 em 方框(12px→15 高 / 16px→18 高 / 24px→26 高,行高一致、多行对齐正确)。 改用 SimSun 宋体后,CJK 字形统一坐基线(底部对齐基线、顶部一致),不再有 MapleMono 那种"度"笔画探出基线、字浮动的问题。每个字形内部的墨迹高低仍然不同 (如"一"是短横、位于框中下部)——这是位图字体的正常行为,U8G2 官方 CJK 字体一致。 另外 map 中排除了 U+3031/3032(〱〲 竖排重复记号),它们的 BBox 高达 30px, 会把公共高度/行高错误地顶高。

备选字体:NotoSansSC-VF.ttf(OFL 开源,但 VF 默认字重偏细)、MapleMono(原用,CJK 基线不齐)。 改 gen_full.py 里的 FONT 路径即可换源。

这三个字体由 tools/fontgen/gen_full.py 生成:
  1. python tools/fontgen/gen_full.py # 调 Python_u8g2_Fonts_Tools 的 otf2bdf + bdfconv
  2. node tools/convert-fonts.js tools/fontgen/out/cn16/code/chinese_full.c -o demo/fonts --format bin,js
复制代码
⚠️ 生成全量字库的 bdfconv 注意:字库工具旧版捆绑的 bdfconv.exe(per-entry=100)在约 2 万 Unicode 字形时会断言失败;已把工具的 bdfconv.exe 换成 olikraus/u8g2 当前源码的构建 (per-entry=101,无此问题)。生成结果经原版 C 库逐字节验证一致。

字库生成工具(otf2bdf + bdfconv + 中文提取,本项目字体由它生成): Easy-u8g2-font-generate-tools



字体:运行时动态加载
字体就是与真机一致的字节流(U8G2 "new font format")。四种载入方式:
  1. // 1) 从转换工具产物(base64)
  2. U8g2Font.fromBase64("AP//AA...")

  3. // 2) 直接贴 .c 源文件里的 C 字符串(八进制转义)
  4. U8g2Font.fromC("\\277\\0\\2\\2\\3\\3...")

  5. // 3) 就是数组
  6. U8g2Font.fromArray(new Uint8Array([​...​]))

  7. // 4) 远程 / 本地文件
  8. await U8g2Font.load("/fonts/u8g2_font_5x7_tf.bin") // 浏览器 fetch / Node 读文件
复制代码
注册进运行时注册表后可 setFont(名字)
  1. U8g2Font.register('my_font', fontData); // fontData 可以是 U8g2Font / Uint8Array / base64
  2. u8g2.setFont('my_font');
复制代码
setFont() 也直接接受 U8g2Font 实例、Uint8Array 或 base64 字符串,随你方便。



转换自己的字体
任意 U8G2 字体 .c 文件(含 bdfconv 生成的中文字体,格式相同)都能转:
  1. # 单个:demo/fonts/u8g2_font_5x7_tf.c -> .bin(推荐,直接 fetch/读文件)
  2. node tools/convert-fonts.js ../u8g2/tools/font/build/single_font_files/u8g2_font_5x7_tf.c \
  3.   -o demo/fonts --format bin

  4. # 输出 .js(base64 模块,import 即用)或 .json
  5. node tools/convert-fonts.js .../u8g2_font_myfont.c -o myfonts --format js

  6. # 批量转一整个目录
  7. node tools/convert-fonts.js --batch .../single_font_files -o myfonts --format bin
复制代码
demo/fonts/ 里已内置 9 个经典示例字体 + 3 个全量中文字库(均含 .bin + .js)。



官方字体包 —— 全部 2174 个 U8G2 字体预编译成 JS
官方 U8G2 全部字体已预编译成可直接 import 的 JS 模块,放在 fonts/ 下 (一个字体一个文件:u8g2_font_5x7_tf.jsu8x8_font_8x16_1x2_f.js …)。 数据逐字节取自 C 数组,与真机编译到设备里的字体字节完全一致 (已用 gcc 编译出的参考数组逐字节对拍验证;每个字体的长度也按 .c 头里声明的 [​N​] 校验过)。
  1. import b64 from 'u8g2-js/fonts/u8g2_font_10x20_tf.js';

  2. const font = U8g2Font.fromBase64(b64); // -> U8g2Font
  3. U8g2Font.register('u8g2_font_10x20_tf', font); // 然后 setFont('u8g2_font_10x20_tf')
复制代码
每个模块都是自包含的小 ESM,只导出一个 base64 字符串——不想一次全打进来的话, 可以按需 import,交给打包器 tree-shake。

fonts/index.json 是所有 2174 个字体的轻量清单:{ name, file, size, glyphs }, 适合用来搭字体选择器(比如仿真器里的下拉列表),不用把字体数据本身全加载进来。

从上游 C 源重新生成 / 刷新这个包:
  1. node tools/convert-all-fonts.js # 读 ../u8g2/tools/font/build/single_font_files
  2.                                            # 生成 fonts/*.js + fonts/index.json
复制代码


显示设备
setup.js 里注册了 ~30 种常见屏(参数取自 u8x8_d_*.c 的 display_info):

控制器型号
SSD1306128x64 / 128x32 / 96x16 / 64x32 / 72x40
SH1106128x64 / 72x40 / 64x32
SSD1305 / 1309 / 1315 / 1316 / 1325128x32 / 128x64 / 128x128 / 96x32 …
ST7920(横向字节布局)128x64 / 256x32 / 144x32 / 160x32 / 192x32
UC1701 / ST7565102x64 / 128x64 / 132x32
墨水屏SSD1606 172x72 / SSD1607 200x200 / IL3820 296x128
任意尺寸自定义屏(含 250×122 IL3829 这类,树里没有的型号):
  1. new U8g2({ width: 250, height: 122, layout: 'vertical', xOffset: 0 });
复制代码
listPresets() 列出全部预设名。



API
主 API 与 Arduino U8g2 类一致(drawStr / setFont / sendBuffer …), 同时提供 C 风格别名(u8g2_draw_str / u8g2_DrawStr / draw_str),代码可平移到真机。

生命周期/页缓冲begin clearBuffer sendBuffer firstPage nextPage clearDisplay clear setAutoPageClear getBufferPtr/Size/TileWidth/TileHeight updateDisplay updateDisplayArea

颜色setDrawColor(0/1/2) getDrawColor setBitmapMode

图元drawPixel drawLine drawHLine drawVLine drawHVLine drawBox drawFrame drawRBox drawRFrame drawCircle drawDisc drawEllipse drawFilledEllipse drawArc drawTriangle clearPolygonXY/addPolygonXY/drawPolygon drawXBM drawXBMP drawBitmap

文本/字体setFont setFontMode setFontDirection setFontPosBaseline|Top|Bottom|Center setFontRefHeightText|ExtendedText|All drawStr drawStrX2 drawUTF8 drawUTF8X2 drawGlyph drawGlyphX2 drawExtendedUTF8 drawExtUTF8(字距) drawHB getStrWidth getUTF8Width getGlyphWidth getXOffsetGlyph|UTF8 getStrX isGlyph isAllValidUTF8 getAscent getDescent getMaxCharWidth|Height getFontBBX*

裁剪/窗口setClipWindow setMaxClipWindow isIntersection getClipWindow

杂项setDisplayRotation(R0-R3) setFlipMode setContrast setPowerSave drawButtonFrame drawButtonUTF8 setCursor home print println sleepOn|Off getDisplayWidth|Height getWidth|Height

不做(如实标注):drawLinePattern/Gradient(本版本 U8G2 已移除)、 u8x8 底层 I2C/SPI 协议字节流(浏览器仿真无需)、8x8 文本屏、drawLog/U8G2LOG



目录结构
  1. u8g2-js/
  2.   src/
  3.     u8g2.js # U8g2 主类:生命周期/页缓冲/文本/裁剪/旋转
  4.     draw.js # 图元:box/line/circle/ellipse/arc/triangle/xbm/button
  5.     hvline.js # 底层像素写入(vertical_top_lsb / horizontal_right_lsb)
  6.     font.js # U8g2Font:头解析/字形查找/RLE 位流解码
  7.     utf8.js # UTF-8 解码(u8x8_utf8_next 移植)
  8.     setup.js # 显示屏预设表 + 自定义屏
  9.     renderer/ # canvas.js(浏览器显示) + pbm.js(无头导出)
  10.     index.js # 统一出口
  11.   demo/ # 交互式仿真页(demo.html + demo-standalone.html)
  12.   fonts/ # 官方字体包:2174 个预编译 JS 模块 + index.json
  13.   tools/
  14.     convert-fonts.js # .c 字体 -> .bin/.js/.json(含批量)
  15.     convert-all-fonts.js # 全部 .c 字体 -> fonts/*.js + fonts/index.json
  16.     build-demo.js # 打包自包含 demo-standalone.html
  17.     check-demo.js # demo 启动自检
  18.     cverify/ # 与原版 C 库逐字节交叉验证
  19.   test/test.js # Node 无头测试套件(30 项)
复制代码


验证
1. 与原版 C 库逐字节交叉验证tools/cverify/build.sh,需 gcc): 编译真 U8G2 C 库渲染 18 项场景/检查(文本/图形/旋转/裁剪/XOR/按钮/Unicode/全量中文字库渲染、 字体数据一致),与 JS 移植逐字节比对 —— 全部一致。 2. Node 无头测试node --test,30 项全过。

3. Demo 自检node tools/check-demo.js



License
BSD-2-Clause。本库是 U8G2 的 JS 移植(含转换后的字体数据),保留原作者版权声明。

参考:原始 C 库已克隆到相邻目录 u8g2/,可对照阅读。




build 06 August 2026 07:57 (UTC+8)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

打赏

参与人数 1家元 +9 收起 理由
free2_citiz + 9 涨见识

查看全部打赏

 楼主| 发表于 4 小时前 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

发表于 3 小时前 | 显示全部楼层
游客请登录后查看回复内容
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|数码之家-技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2026-8-6 12:26 , Processed in 0.202800 second(s), 9 queries , Gzip On, Redis On.

Powered by Discuz!

© MyDigit.Net Since 2006

快速回复 返回顶部 返回列表