feat: Current page as QR (#1099)
## Summary * **What is the goal of this PR?** Implements QR text of the current page * **What changes are included?** ## Additional Context I saw this feature request at #982 It made sense to me so I implemented. But if the team thinks it is not necessary please let me know and we can close the PR. | Page | Menu | QR | |------|-------|----| |  |  |  | --- ### AI Usage Did you use AI tools to help write this code? _** YES --------- Co-authored-by: Eliz Kilic <elizk@google.com>
This commit is contained in:
54
src/util/QrUtils.cpp
Normal file
54
src/util/QrUtils.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "QrUtils.h"
|
||||
|
||||
#include <qrcode.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
void QrUtils::drawQrCode(const GfxRenderer& renderer, const Rect& bounds, const std::string& textPayload) {
|
||||
// Dynamically calculate the QR code version based on text length
|
||||
// Version 4 holds ~114 bytes, Version 10 ~395, Version 20 ~1066, up to 40
|
||||
// qrcode.h max version is 40.
|
||||
// Formula: approx version = size / 26 + 1 (very rough estimate, better to find best fit)
|
||||
const size_t len = textPayload.length();
|
||||
int version = 4;
|
||||
if (len > 114) version = 10;
|
||||
if (len > 395) version = 20;
|
||||
if (len > 1066) version = 30;
|
||||
if (len > 2110) version = 40;
|
||||
|
||||
// Make sure we have a large enough buffer on the heap to avoid blowing the stack
|
||||
uint32_t bufferSize = qrcode_getBufferSize(version);
|
||||
auto qrcodeBytes = std::make_unique<uint8_t[]>(bufferSize);
|
||||
|
||||
QRCode qrcode;
|
||||
// Initialize the QR code. We use ECC_LOW for max capacity.
|
||||
int8_t res = qrcode_initText(&qrcode, qrcodeBytes.get(), version, ECC_LOW, textPayload.c_str());
|
||||
|
||||
if (res == 0) {
|
||||
// Determine the optimal pixel size.
|
||||
const int maxDim = std::min(bounds.width, bounds.height);
|
||||
|
||||
int px = maxDim / qrcode.size;
|
||||
if (px < 1) px = 1;
|
||||
|
||||
// Calculate centering X and Y
|
||||
const int qrDisplaySize = qrcode.size * px;
|
||||
const int xOff = bounds.x + (bounds.width - qrDisplaySize) / 2;
|
||||
const int yOff = bounds.y + (bounds.height - qrDisplaySize) / 2;
|
||||
|
||||
// Draw the QR Code
|
||||
for (uint8_t cy = 0; cy < qrcode.size; cy++) {
|
||||
for (uint8_t cx = 0; cx < qrcode.size; cx++) {
|
||||
if (qrcode_getModule(&qrcode, cx, cy)) {
|
||||
renderer.fillRect(xOff + px * cx, yOff + px * cy, px, px, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If it fails (e.g. text too large), log an error
|
||||
LOG_ERR("QR", "Text too large for QR Code version %d", version);
|
||||
}
|
||||
}
|
||||
14
src/util/QrUtils.h
Normal file
14
src/util/QrUtils.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <GfxRenderer.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "components/themes/BaseTheme.h"
|
||||
|
||||
namespace QrUtils {
|
||||
|
||||
// Renders a QR code with the given text payload within the specified bounding box.
|
||||
void drawQrCode(const GfxRenderer& renderer, const Rect& bounds, const std::string& textPayload);
|
||||
|
||||
} // namespace QrUtils
|
||||
Reference in New Issue
Block a user