mirror of
https://github.com/ALLFATHER-BV/wadamesh.git
synced 2026-11-11 17:47:35 +00:00
The 273 baked RGB565+alpha emoji images in src/ui-touch/emoji_data.c are 208,908 B of the Tanmatsu's application.bin, which may not exceed 50 x 64 KB pages. Deflated as one stream they are 105,053 B. The Tanmatsu's IDF build now leaves emoji_data.c out and compiles variants/tanmatsu/emoji_deflated.cpp, which provides the same emojiGlyphLookup() / kEmojiGlyphCount. Its header is generated at build time from emoji_data.c by scripts/build/gen-emoji-deflated.py (a CMake custom command into the build dir, nothing committed), so emoji_data.c stays the one source and add-emoji.py keeps working unchanged. The script inflates its own output and checks every image and glyph mapping against the source before writing, so a bad blob fails the build. On the first lookup that hits a known emoji the blob is inflated with the ROM tinfl (no flash cost) into one 208,908 B PSRAM block plus 273 descriptors; lookups that miss never inflate. An allocation failure gives "no glyph" and is retried on a later lookup; a blob that will not inflate is not retried per draw. Same pixels, same headers, same sharing of one image by several codepoints (U+FE0F, U+200D, ...). S3 boards, the web build and the other P4 builds do not compile anything here (variants/tanmatsu is only globbed by tanmatsu/), so their images do not change. Host test test/test_emoji_deflated.cpp compares the deflated lookup with the raw emoji_data.c for every codepoint up to U+10FFFF and drives the out-of-memory and corrupt-blob paths (zlib stands in for the ROM tinfl). run-host-tests.sh gains per-test prep (generate the header under $OUT) and link flags. Measured with WADA_FW_TAG=beta_99: 3,179,904 -> 3,076,400 B. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
3.2 KiB
C++
80 lines
3.2 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
//
|
|
// The Tanmatsu ships its colour emoji deflated (variants/tanmatsu/emoji_deflated.cpp,
|
|
// header generated from src/ui-touch/emoji_data.c by scripts/build/gen-emoji-deflated.py).
|
|
// This checks the deflated path against the raw one for EVERY codepoint up to
|
|
// U+10FFFF: same hits and misses, same header, same size, same pixels. Then the
|
|
// failure paths: out of memory (no glyph, retried later) and a blob that will not
|
|
// inflate (no glyph, never retried).
|
|
//
|
|
// Build (scripts/run-host-tests.sh does this): generate the header into a directory
|
|
// on the include path, then
|
|
// g++ -std=c++17 -I test/emoji_fakes -I <gen dir> -I src -I src/ui-touch \
|
|
// test/test_emoji_deflated.cpp -lz
|
|
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
// The raw table, renamed so both implementations link into one binary.
|
|
#define emojiGlyphLookup rawEmojiGlyphLookup
|
|
#define kEmojiGlyphCount rawEmojiGlyphCount
|
|
#include "ui-touch/emoji_data.c"
|
|
#undef emojiGlyphLookup
|
|
#undef kEmojiGlyphCount
|
|
|
|
#define WADA_EMOJI_DEFLATED 1
|
|
#include "../variants/tanmatsu/emoji_deflated.cpp"
|
|
|
|
static bool sameImage(const lv_img_dsc_t* a, const lv_img_dsc_t* b) {
|
|
return a->header.cf == b->header.cf && a->header.w == b->header.w && a->header.h == b->header.h &&
|
|
a->header.always_zero == b->header.always_zero && a->data_size == b->data_size &&
|
|
memcmp(a->data, b->data, a->data_size) == 0;
|
|
}
|
|
|
|
int main() {
|
|
assert(kEmojiGlyphCount == rawEmojiGlyphCount);
|
|
|
|
// A miss never inflates (or even allocates): presence checks stay free.
|
|
assert(emojiGlyphLookup(0x41) == nullptr);
|
|
assert(g_fake_allocs == 0 && s_emoji_dsc == nullptr);
|
|
|
|
// Out of memory: a known emoji has no glyph, nothing is marked broken, and the
|
|
// next lookup with memory available succeeds.
|
|
g_fake_alloc_fail = 1;
|
|
assert(emojiGlyphLookup(0x1F60A) == nullptr);
|
|
assert(!s_emoji_broken && s_emoji_dsc == nullptr);
|
|
g_fake_alloc_fail = 0;
|
|
|
|
// Every codepoint: the deflated lookup matches the raw one exactly.
|
|
int hits = 0;
|
|
for (uint32_t cp = 0; cp <= 0x10FFFF; ++cp) {
|
|
const lv_img_dsc_t* raw = rawEmojiGlyphLookup(cp);
|
|
const lv_img_dsc_t* z = emojiGlyphLookup(cp);
|
|
if (!raw) { assert(!z); continue; }
|
|
assert(z);
|
|
if (!sameImage(raw, z)) { printf("U+%X differs\n", (unsigned)cp); return 1; }
|
|
++hits;
|
|
}
|
|
printf("%d codepoints match\n", hits);
|
|
assert(hits == (int)(sizeof(kGlyphs) / sizeof(kGlyphs[0])));
|
|
|
|
// Codepoints that share one image in the source still share one image here.
|
|
assert(emojiGlyphLookup(0xFE0F) == emojiGlyphLookup(0x200D));
|
|
// Inflated exactly once: pixels, descriptors and the decompressor state.
|
|
assert(g_fake_allocs == 3);
|
|
|
|
// A blob that will not inflate: no glyph, and it is not inflated again per draw.
|
|
heap_caps_free((void*)s_emoji_dsc[0].data); // the pixel block (image 0 sits at offset 0)
|
|
heap_caps_free(s_emoji_dsc);
|
|
s_emoji_dsc = nullptr;
|
|
g_fake_tinfl_corrupt = 1;
|
|
const int before = g_fake_allocs;
|
|
assert(emojiGlyphLookup(0x1F60A) == nullptr);
|
|
assert(s_emoji_broken);
|
|
assert(emojiGlyphLookup(0x1F60A) == nullptr);
|
|
assert(g_fake_allocs == before + 3); // one attempt only
|
|
puts("ok");
|
|
return 0;
|
|
}
|