feat: Slim dictionary (#2583)

Co-authored-by: Ryan Hitchman <hitchmanr@gmail.com>
Co-authored-by: Kurtis Grant <kurtis.b.grant@gmail.com>
Co-authored-by: kemonine <kemonine@kemonine.info>
Co-authored-by: DustinHu <hu.dustin@gmail.com>
Co-authored-by: Justin Mitchell <justin@jmitch.com>
This commit is contained in:
Uri Tauber
2026-07-19 17:57:16 +03:00
committed by GitHub
co-authored by Ryan Hitchman Kurtis Grant kemonine DustinHu Justin Mitchell
parent 5ba1d5747f
commit b1d1d757ba
27 changed files with 1919 additions and 10 deletions
@@ -0,0 +1,84 @@
#pragma once
#include <Epub/Page.h>
#include <I18n.h>
#include <memory>
#include <vector>
#include "activities/Activity.h"
#include "util/Dictionary.h"
// Button-driven word selection over the current reader page: Left/Right step
// through words in reading order, Up/Down jump rows, Confirm looks the word up
// and opens DictionaryDefinitionActivity, Back returns to the reader.
class DictionaryWordSelectActivity final : public Activity {
public:
explicit DictionaryWordSelectActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
std::unique_ptr<Page> page, int marginLeft, int marginTop)
: Activity("DictionaryWordSelect", renderer, mappedInput),
page(std::move(page)),
marginLeft(marginLeft),
marginTop(marginTop) {}
void onEnter() override;
void loop() override;
void render(RenderLock&&) override;
private:
// Screen box of one selectable word. `text` points into the owned Page's
// TextBlock arena (NUL-terminated), valid for this activity's lifetime.
struct WordBox {
int16_t x;
int16_t y;
int16_t width;
uint16_t row;
const char* text;
EpdFontFamily::Style style;
};
enum class Popup : uint8_t { None, Busy, NotFound, Error };
void extractWords();
int closestInRow(uint16_t row, int centerX) const;
void moveVertical(int direction);
void performLookup();
bool drawHighlightWithSnapshot();
void drawHints() const;
std::unique_ptr<Page> page;
const int marginLeft;
const int marginTop;
int fontId = 0;
int lineHeight = 0;
std::vector<WordBox> words;
int selected = 0;
uint16_t rowCount = 0;
Dictionary dict;
bool dictOpenAttempted = false;
bool dictOpenOk = false;
Popup popup = Popup::None;
StrId popupMsg = StrId::STR_DICT_NOT_FOUND;
unsigned long popupTime = 0;
// Differential highlight repaint: the pixels under the current highlight
// box, so a cursor move restores them and repaints only the two affected
// boxes instead of re-running the full two-pass page render (which also
// reloads every SD-font glyph on the page). snapshotIdx is the word whose
// under-pixels are saved; -1 means the framebuffer no longer holds a clean
// page (popup drawn, sub-activity shown) and the next render must be full.
static constexpr size_t SNAPSHOT_CAPACITY = 4096;
std::unique_ptr<uint8_t[]> snapshot;
int16_t snapshotX = 0;
int16_t snapshotY = 0;
int16_t snapshotW = 0;
int16_t snapshotH = 0;
int snapshotIdx = -1;
// The activity is entered while Confirm is still held (long-press trigger):
// ignore the stale release until a fresh press is seen.
bool confirmPressSeen = false;
};