You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trezor-firmware/core/src/trezor/ui/qr.py

45 lines
1.5 KiB

from typing import Sequence
from trezor import ui
from trezor.ui.constants import QR_SIDE_MAX
_QR_WIDTHS = (21, 25, 29, 33, 37, 41, 45, 49, 53, 57)
_THRESHOLDS_BINARY = (14, 26, 42, 62, 84, 106, 122, 152, 180, 213)
_THRESHOLDS_ALPHANUM = (20, 38, 61, 90, 122, 154, 178, 221, 262, 311)
def _qr_version_index(data: str, thresholds: Sequence[int]) -> int:
for i, threshold in enumerate(thresholds):
if len(data) <= threshold:
return i
raise ValueError # data too long
def is_alphanum_only(data: str) -> bool:
return all(c in "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $*+-./:" for c in data)
class Qr(ui.Component):
def __init__(self, data: str, case_sensitive: bool, x: int, y: int) -> None:
super().__init__()
if case_sensitive and not is_alphanum_only(data):
# must encode in BINARY mode
version_idx = _qr_version_index(data, _THRESHOLDS_BINARY)
else:
# can make the QR code more readable by using the best version
version_idx = _qr_version_index(data, _THRESHOLDS_ALPHANUM)
if len(data) > _THRESHOLDS_BINARY[version_idx]:
data = data.upper()
size = _QR_WIDTHS[version_idx]
self.data = data
self.x = x
self.y = y
self.scale = QR_SIDE_MAX // size
def on_render(self) -> None:
if self.repaint:
ui.display.qrcode(self.x, self.y, self.data, self.scale)
self.repaint = False