16#include <goodisplay/gdey029T94.h>
17#include <Fonts/FreeMonoBold9pt7b.h>
20static const char*
TAG =
"QRCodeView";
49 int size = esp_qrcode_get_size(qrcode);
63 LOG_D(
TAG,
"QR size=%d, scale=%d, pos=(%d,%d)", size,
scale, x0, y0);
65 for (
int y = 0; y < size; y++) {
66 for (
int x = 0; x < size; x++) {
67 bool black = esp_qrcode_get_module(qrcode, x, y);
68 uint16_t color = black ? EPD_BLACK : EPD_WHITE;
71 for (
int dy = 0; dy <
scale; dy++) {
72 for (
int dx = 0; dx <
scale; dx++) {
91 customHint_ =
nullptr;
98 LOG_D(
TAG,
"init: data='%s', title='%s'",
99 data ? data :
"(null)", title ? title :
"(null)");
108 if (key ==
'N' || key ==
'n') {
122 return ui::tr(
"core.hint_back");
129void QRCodeView::calculateLayout() {
133 esp_qrcode_config_t cfg = {
135 .max_qrcode_version = 20,
136 .qrcode_ecc_level = ESP_QRCODE_ECC_LOW,
144 esp_err_t err = esp_qrcode_generate(&cfg, data_);
146 LOG_E(
TAG,
"QR sizing failed: %s", esp_err_to_name(err));
149 qrModuleCount_ =
s_qrCtx.actualSize;
150 if (qrModuleCount_ <= 0) qrModuleCount_ = 97;
157 qrScale_ = maxQrHeight / qrModuleCount_;
158 if (qrScale_ < 1) qrScale_ = 1;
161 int qrPixelSize = qrModuleCount_ * qrScale_;
164 int unusedHeight = maxQrHeight - qrPixelSize;
166 qrOffsetY_ = unusedHeight / 2;
168 LOG_I(
TAG,
"Layout: %d modules, scale=%d, %dx%d px",
169 qrModuleCount_, qrScale_, qrPixelSize, qrPixelSize);
176void QRCodeView::renderQrCode() {
182 auto* gfx =
static_cast<Gdey029T94*
>(
display->getNativeHandle());
192 esp_qrcode_config_t cfg = {
194 .max_qrcode_version = 20,
195 .qrcode_ecc_level = ESP_QRCODE_ECC_LOW,
199 esp_err_t err = esp_qrcode_generate(&cfg, data_);
201 LOG_E(
TAG,
"QR render failed: %s", esp_err_to_name(err));
202 gfx->setFont(
nullptr);
203 gfx->setCursor(10, 64);
212void QRCodeView::renderText() {
216 auto* gfx =
static_cast<Gdey029T94*
>(
display->getNativeHandle());
223 int textAreaX = QR_AREA_WIDTH + 4;
230 if (title_ && title_[0]) {
232 static const GFXfont*
const TITLE_FONTS[] = {
237 gfx, title_, textAreaWidth, TITLE_FONTS, std::size(TITLE_FONTS),
false);
239 const bool bold9pt = (chosen == &FreeMonoBold9pt7b);
240 const int charW = bold9pt ? 7 : 6;
241 const int lineH = bold9pt ? 16 : 10;
242 const int maxYStop = 80;
243 int maxChars = textAreaWidth / charW;
244 if (maxChars > 31) maxChars = 31;
246 const char* p = title_;
248 while (*p && y < maxYStop) {
250 while (p[len] && len < maxChars) {
256 gfx->setCursor(textAreaX, y);
265 if (subtitle_ && subtitle_[0]) {
266 gfx->setFont(
nullptr);
267 int maxChars = textAreaWidth / 6;
268 if (maxChars > 31) maxChars = 31;
270 const char* p = subtitle_;
273 while (*p && y < 110) {
275 while (p[len] && p[len] !=
'\n' && len < maxChars) {
281 gfx->setCursor(textAreaX, y);
291 gfx->setFont(
nullptr);
294 gfx->setCursor(textAreaX, 116);
308 auto* gfx =
static_cast<Gdey029T94*
>(
display->getNativeHandle());
312 gfx->fillScreen(EPD_WHITE);
314 gfx->setTextColor(EPD_BLACK);
317 gfx->setFont(
nullptr);
318 gfx->setCursor(10, 64);
325 if (qrModuleCount_ == 0) {
353 const char* subtitle,
const char* hint) {
Internationalization with English fallbacks in code and overlay translations loaded at runtime from a...
static constexpr int DISPLAY_WIDTH
static constexpr int QR_MARGIN
static constexpr int DISPLAY_HEIGHT
CDC Log: logging over TinyUSB CDC and UART.
#define LOG_D(tag, fmt,...)
#define LOG_I(tag, fmt,...)
#define LOG_E(tag, fmt,...)
void render(bool partial) override
Renders the complete QR code view.
const char * getFooterHint() const override
Returns footer hint text.
InputResult onKey(char key) override
Handles key input by closing the QR view.
void init(const char *data, const char *title=nullptr, const char *subtitle=nullptr)
Initializes QR code content and layout state.
static ViewStack & instance()
Returns singleton view-stack instance.
void push(IView *view, void *context=nullptr)
IDisplay * getDisplayInstance()
Returns lazily created singleton display instance.
void drawText(Gdey029T94 *gfx, const char *text, const GFXfont *font)
Draws CP437-encoded text correctly for the given font: the built-in glcdfont (font == nullptr) is CP4...
const GFXfont * pickFontThatFits(Gdey029T94 *gfx, const char *text, int maxWidthPx, const GFXfont *const *candidates, size_t count, bool cp437=false)
Picks the largest font from candidates whose rendered width of text fits within maxWidthPx....
void printText(Gdey029T94 *gfx, const char *text)
Draws CP437 text with the built-in 6x8 glyph font, byte-for-byte.
Centralized key-code constants for cdc_views.
const char * tr(const char *key)
Look up a translation by string key.
const GFXfont * getGfxFont(FontId id)
Resolves a FontId to its underlying GFX font pointer.
static QRCodeView s_sharedQRCodeView
Convenience factory/helper function.
static struct cdc::ui::@307147344135044151327247213066152362355352344260 s_qrCtx
QR rendering context used by callback-driven rendering.
FontId
Canonical font identifier shared by firmware UI and plugin host API.
@ Builtin
Adafruit-GFX 6x8. Umlauts present at CP437 codepoints (0x84..0x9C). Pass raw CP437 bytes to draw them...
static void qrDisplayCallback(esp_qrcode_handle_t qrcode)
Renders or measures the QR code through the ESP QR callback.
QRCodeView * showQRCode(const char *data, const char *title=nullptr, const char *subtitle=nullptr, const char *hint=nullptr)
Shows a shared QR code view instance.