mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-07 08:07:40 +03:00
Compare commits
1 Commits
01182ca57a
...
4547dacdd9
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4547dacdd9 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,6 +4,5 @@
|
|||||||
.vscode
|
.vscode
|
||||||
lib/EpdFont/fontsrc
|
lib/EpdFont/fontsrc
|
||||||
*.generated.h
|
*.generated.h
|
||||||
.vs
|
|
||||||
build
|
build
|
||||||
**/__pycache__/
|
**/__pycache__/
|
||||||
@ -116,7 +116,6 @@ The Settings screen allows you to configure the device's behavior. There are a f
|
|||||||
- Back, Confirm, Left, Right (default)
|
- Back, Confirm, Left, Right (default)
|
||||||
- Left, Right, Back, Confirm
|
- Left, Right, Back, Confirm
|
||||||
- Left, Back, Confirm, Right
|
- Left, Back, Confirm, Right
|
||||||
- Back, Confirm, Right, Left
|
|
||||||
- **Side Button Layout (reader)**: Swap the order of the up and down volume buttons from Previous/Next to Next/Previous. This change is only in effect when reading.
|
- **Side Button Layout (reader)**: Swap the order of the up and down volume buttons from Previous/Next to Next/Previous. This change is only in effect when reading.
|
||||||
- **Long-press Chapter Skip**: Set whether long-pressing page turn buttons skip to the next/previous chapter.
|
- **Long-press Chapter Skip**: Set whether long-pressing page turn buttons skip to the next/previous chapter.
|
||||||
- "Chapter Skip" (default) - Long-pressing skips to next/previous chapter
|
- "Chapter Skip" (default) - Long-pressing skips to next/previous chapter
|
||||||
|
|||||||
@ -359,7 +359,7 @@ const std::string& Epub::getLanguage() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string Epub::getCoverBmpPath(bool cropped) const {
|
std::string Epub::getCoverBmpPath(bool cropped) const {
|
||||||
const auto coverFileName = std::string("cover") + (cropped ? "_crop" : "");
|
const auto coverFileName = "cover" + cropped ? "_crop" : "";
|
||||||
return cachePath + "/" + coverFileName + ".bmp";
|
return cachePath + "/" + coverFileName + ".bmp";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,7 +382,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
|
|||||||
|
|
||||||
if (coverImageHref.substr(coverImageHref.length() - 4) == ".jpg" ||
|
if (coverImageHref.substr(coverImageHref.length() - 4) == ".jpg" ||
|
||||||
coverImageHref.substr(coverImageHref.length() - 5) == ".jpeg") {
|
coverImageHref.substr(coverImageHref.length() - 5) == ".jpeg") {
|
||||||
Serial.printf("[%lu] [EBP] Generating BMP from JPG cover image (%s mode)\n", millis(), cropped ? "cropped" : "fit");
|
Serial.printf("[%lu] [EBP] Generating BMP from JPG cover image\n", millis());
|
||||||
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
|
const auto coverJpgTempPath = getCachePath() + "/.cover.jpg";
|
||||||
|
|
||||||
FsFile coverJpg;
|
FsFile coverJpg;
|
||||||
@ -401,7 +401,7 @@ bool Epub::generateCoverBmp(bool cropped) const {
|
|||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const bool success = JpegToBmpConverter::jpegFileToBmpStream(coverJpg, coverBmp, cropped);
|
const bool success = JpegToBmpConverter::jpegFileToBmpStream(coverJpg, coverBmp);
|
||||||
coverJpg.close();
|
coverJpg.close();
|
||||||
coverBmp.close();
|
coverBmp.close();
|
||||||
SdMan.remove(coverJpgTempPath.c_str());
|
SdMan.remove(coverJpgTempPath.c_str());
|
||||||
|
|||||||
@ -125,8 +125,6 @@ bool isExplicitHyphen(const uint32_t cp) {
|
|||||||
case 0xFE58: // small em dash
|
case 0xFE58: // small em dash
|
||||||
case 0xFE63: // small hyphen-minus
|
case 0xFE63: // small hyphen-minus
|
||||||
case 0xFF0D: // fullwidth hyphen-minus
|
case 0xFF0D: // fullwidth hyphen-minus
|
||||||
case 0x005F: // Underscore
|
|
||||||
case 0x2026: // Ellipsis
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -200,7 +200,7 @@ unsigned char JpegToBmpConverter::jpegReadCallback(unsigned char* pBuf, const un
|
|||||||
|
|
||||||
// Internal implementation with configurable target size and bit depth
|
// Internal implementation with configurable target size and bit depth
|
||||||
bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight,
|
bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight,
|
||||||
bool oneBit, bool crop) {
|
bool oneBit) {
|
||||||
Serial.printf("[%lu] [JPG] Converting JPEG to %s BMP (target: %dx%d)\n", millis(), oneBit ? "1-bit" : "2-bit",
|
Serial.printf("[%lu] [JPG] Converting JPEG to %s BMP (target: %dx%d)\n", millis(), oneBit ? "1-bit" : "2-bit",
|
||||||
targetWidth, targetHeight);
|
targetWidth, targetHeight);
|
||||||
|
|
||||||
@ -242,12 +242,8 @@ bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bm
|
|||||||
const float scaleToFitWidth = static_cast<float>(targetWidth) / imageInfo.m_width;
|
const float scaleToFitWidth = static_cast<float>(targetWidth) / imageInfo.m_width;
|
||||||
const float scaleToFitHeight = static_cast<float>(targetHeight) / imageInfo.m_height;
|
const float scaleToFitHeight = static_cast<float>(targetHeight) / imageInfo.m_height;
|
||||||
// We scale to the smaller dimension, so we can potentially crop later.
|
// We scale to the smaller dimension, so we can potentially crop later.
|
||||||
float scale = 1.0;
|
// TODO: ideally, we already crop here.
|
||||||
if (crop) { // if we will crop, scale to the smaller dimension
|
const float scale = (scaleToFitWidth > scaleToFitHeight) ? scaleToFitWidth : scaleToFitHeight;
|
||||||
scale = (scaleToFitWidth > scaleToFitHeight) ? scaleToFitWidth : scaleToFitHeight;
|
|
||||||
} else { // else, scale to the larger dimension to fit
|
|
||||||
scale = (scaleToFitWidth < scaleToFitHeight) ? scaleToFitWidth : scaleToFitHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
outWidth = static_cast<int>(imageInfo.m_width * scale);
|
outWidth = static_cast<int>(imageInfo.m_width * scale);
|
||||||
outHeight = static_cast<int>(imageInfo.m_height * scale);
|
outHeight = static_cast<int>(imageInfo.m_height * scale);
|
||||||
@ -554,8 +550,8 @@ bool JpegToBmpConverter::jpegFileToBmpStreamInternal(FsFile& jpegFile, Print& bm
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Core function: Convert JPEG file to 2-bit BMP (uses default target size)
|
// Core function: Convert JPEG file to 2-bit BMP (uses default target size)
|
||||||
bool JpegToBmpConverter::jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bool crop) {
|
bool JpegToBmpConverter::jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut) {
|
||||||
return jpegFileToBmpStreamInternal(jpegFile, bmpOut, TARGET_MAX_WIDTH, TARGET_MAX_HEIGHT, false, crop);
|
return jpegFileToBmpStreamInternal(jpegFile, bmpOut, TARGET_MAX_WIDTH, TARGET_MAX_HEIGHT, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert with custom target size (for thumbnails, 2-bit)
|
// Convert with custom target size (for thumbnails, 2-bit)
|
||||||
|
|||||||
@ -8,10 +8,10 @@ class JpegToBmpConverter {
|
|||||||
static unsigned char jpegReadCallback(unsigned char* pBuf, unsigned char buf_size,
|
static unsigned char jpegReadCallback(unsigned char* pBuf, unsigned char buf_size,
|
||||||
unsigned char* pBytes_actually_read, void* pCallback_data);
|
unsigned char* pBytes_actually_read, void* pCallback_data);
|
||||||
static bool jpegFileToBmpStreamInternal(class FsFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight,
|
static bool jpegFileToBmpStreamInternal(class FsFile& jpegFile, Print& bmpOut, int targetWidth, int targetHeight,
|
||||||
bool oneBit, bool crop = true);
|
bool oneBit);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static bool jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut, bool crop = true);
|
static bool jpegFileToBmpStream(FsFile& jpegFile, Print& bmpOut);
|
||||||
// Convert with custom target size (for thumbnails)
|
// Convert with custom target size (for thumbnails)
|
||||||
static bool jpegFileToBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight);
|
static bool jpegFileToBmpStreamWithSize(FsFile& jpegFile, Print& bmpOut, int targetMaxWidth, int targetMaxHeight);
|
||||||
// Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering
|
// Convert to 1-bit BMP (black and white only, no grays) for fast home screen rendering
|
||||||
|
|||||||
@ -32,12 +32,7 @@ class CrossPointSettings {
|
|||||||
// Front button layout options
|
// Front button layout options
|
||||||
// Default: Back, Confirm, Left, Right
|
// Default: Back, Confirm, Left, Right
|
||||||
// Swapped: Left, Right, Back, Confirm
|
// Swapped: Left, Right, Back, Confirm
|
||||||
enum FRONT_BUTTON_LAYOUT {
|
enum FRONT_BUTTON_LAYOUT { BACK_CONFIRM_LEFT_RIGHT = 0, LEFT_RIGHT_BACK_CONFIRM = 1, LEFT_BACK_CONFIRM_RIGHT = 2 };
|
||||||
BACK_CONFIRM_LEFT_RIGHT = 0,
|
|
||||||
LEFT_RIGHT_BACK_CONFIRM = 1,
|
|
||||||
LEFT_BACK_CONFIRM_RIGHT = 2,
|
|
||||||
BACK_CONFIRM_RIGHT_LEFT = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// Side button layout options
|
// Side button layout options
|
||||||
// Default: Previous, Next
|
// Default: Previous, Next
|
||||||
|
|||||||
@ -14,9 +14,6 @@ decltype(InputManager::BTN_BACK) MappedInputManager::mapButton(const Button butt
|
|||||||
case CrossPointSettings::LEFT_BACK_CONFIRM_RIGHT:
|
case CrossPointSettings::LEFT_BACK_CONFIRM_RIGHT:
|
||||||
return InputManager::BTN_CONFIRM;
|
return InputManager::BTN_CONFIRM;
|
||||||
case CrossPointSettings::BACK_CONFIRM_LEFT_RIGHT:
|
case CrossPointSettings::BACK_CONFIRM_LEFT_RIGHT:
|
||||||
/* fall through */
|
|
||||||
case CrossPointSettings::BACK_CONFIRM_RIGHT_LEFT:
|
|
||||||
/* fall through */
|
|
||||||
default:
|
default:
|
||||||
return InputManager::BTN_BACK;
|
return InputManager::BTN_BACK;
|
||||||
}
|
}
|
||||||
@ -27,22 +24,15 @@ decltype(InputManager::BTN_BACK) MappedInputManager::mapButton(const Button butt
|
|||||||
case CrossPointSettings::LEFT_BACK_CONFIRM_RIGHT:
|
case CrossPointSettings::LEFT_BACK_CONFIRM_RIGHT:
|
||||||
return InputManager::BTN_LEFT;
|
return InputManager::BTN_LEFT;
|
||||||
case CrossPointSettings::BACK_CONFIRM_LEFT_RIGHT:
|
case CrossPointSettings::BACK_CONFIRM_LEFT_RIGHT:
|
||||||
/* fall through */
|
|
||||||
case CrossPointSettings::BACK_CONFIRM_RIGHT_LEFT:
|
|
||||||
/* fall through */
|
|
||||||
default:
|
default:
|
||||||
return InputManager::BTN_CONFIRM;
|
return InputManager::BTN_CONFIRM;
|
||||||
}
|
}
|
||||||
case Button::Left:
|
case Button::Left:
|
||||||
switch (frontLayout) {
|
switch (frontLayout) {
|
||||||
case CrossPointSettings::LEFT_RIGHT_BACK_CONFIRM:
|
case CrossPointSettings::LEFT_RIGHT_BACK_CONFIRM:
|
||||||
/* fall through */
|
|
||||||
case CrossPointSettings::LEFT_BACK_CONFIRM_RIGHT:
|
case CrossPointSettings::LEFT_BACK_CONFIRM_RIGHT:
|
||||||
return InputManager::BTN_BACK;
|
return InputManager::BTN_BACK;
|
||||||
case CrossPointSettings::BACK_CONFIRM_RIGHT_LEFT:
|
|
||||||
return InputManager::BTN_RIGHT;
|
|
||||||
case CrossPointSettings::BACK_CONFIRM_LEFT_RIGHT:
|
case CrossPointSettings::BACK_CONFIRM_LEFT_RIGHT:
|
||||||
/* fall through */
|
|
||||||
default:
|
default:
|
||||||
return InputManager::BTN_LEFT;
|
return InputManager::BTN_LEFT;
|
||||||
}
|
}
|
||||||
@ -50,12 +40,8 @@ decltype(InputManager::BTN_BACK) MappedInputManager::mapButton(const Button butt
|
|||||||
switch (frontLayout) {
|
switch (frontLayout) {
|
||||||
case CrossPointSettings::LEFT_RIGHT_BACK_CONFIRM:
|
case CrossPointSettings::LEFT_RIGHT_BACK_CONFIRM:
|
||||||
return InputManager::BTN_CONFIRM;
|
return InputManager::BTN_CONFIRM;
|
||||||
case CrossPointSettings::BACK_CONFIRM_RIGHT_LEFT:
|
|
||||||
return InputManager::BTN_LEFT;
|
|
||||||
case CrossPointSettings::BACK_CONFIRM_LEFT_RIGHT:
|
case CrossPointSettings::BACK_CONFIRM_LEFT_RIGHT:
|
||||||
/* fall through */
|
|
||||||
case CrossPointSettings::LEFT_BACK_CONFIRM_RIGHT:
|
case CrossPointSettings::LEFT_BACK_CONFIRM_RIGHT:
|
||||||
/* fall through */
|
|
||||||
default:
|
default:
|
||||||
return InputManager::BTN_RIGHT;
|
return InputManager::BTN_RIGHT;
|
||||||
}
|
}
|
||||||
@ -70,7 +56,6 @@ decltype(InputManager::BTN_BACK) MappedInputManager::mapButton(const Button butt
|
|||||||
case CrossPointSettings::NEXT_PREV:
|
case CrossPointSettings::NEXT_PREV:
|
||||||
return InputManager::BTN_DOWN;
|
return InputManager::BTN_DOWN;
|
||||||
case CrossPointSettings::PREV_NEXT:
|
case CrossPointSettings::PREV_NEXT:
|
||||||
/* fall through */
|
|
||||||
default:
|
default:
|
||||||
return InputManager::BTN_UP;
|
return InputManager::BTN_UP;
|
||||||
}
|
}
|
||||||
@ -79,7 +64,6 @@ decltype(InputManager::BTN_BACK) MappedInputManager::mapButton(const Button butt
|
|||||||
case CrossPointSettings::NEXT_PREV:
|
case CrossPointSettings::NEXT_PREV:
|
||||||
return InputManager::BTN_UP;
|
return InputManager::BTN_UP;
|
||||||
case CrossPointSettings::PREV_NEXT:
|
case CrossPointSettings::PREV_NEXT:
|
||||||
/* fall through */
|
|
||||||
default:
|
default:
|
||||||
return InputManager::BTN_DOWN;
|
return InputManager::BTN_DOWN;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -261,7 +261,6 @@ void SleepActivity::renderCoverSleepScreen() const {
|
|||||||
if (SdMan.openFileForRead("SLP", coverBmpPath, file)) {
|
if (SdMan.openFileForRead("SLP", coverBmpPath, file)) {
|
||||||
Bitmap bitmap(file);
|
Bitmap bitmap(file);
|
||||||
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
if (bitmap.parseHeaders() == BmpReaderError::Ok) {
|
||||||
Serial.printf("[SLP] Rendering sleep cover: %s\n", coverBmpPath);
|
|
||||||
renderBitmapSleepScreen(bitmap);
|
renderBitmapSleepScreen(bitmap);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -427,7 +427,7 @@ void EpubReaderActivity::renderStatusBar(const int orientedMarginRight, const in
|
|||||||
|
|
||||||
// Right aligned text for progress counter
|
// Right aligned text for progress counter
|
||||||
char progressStr[32];
|
char progressStr[32];
|
||||||
snprintf(progressStr, sizeof(progressStr), "%d/%d %.0f%%", section->currentPage + 1, section->pageCount,
|
snprintf(progressStr, sizeof(progressStr), "%d/%d %.1f%%", section->currentPage + 1, section->pageCount,
|
||||||
bookProgress);
|
bookProgress);
|
||||||
const std::string progress = progressStr;
|
const std::string progress = progressStr;
|
||||||
progressTextWidth = renderer.getTextWidth(SMALL_FONT_ID, progress.c_str());
|
progressTextWidth = renderer.getTextWidth(SMALL_FONT_ID, progress.c_str());
|
||||||
|
|||||||
@ -37,9 +37,8 @@ const SettingInfo readerSettings[readerSettingsCount] = {
|
|||||||
|
|
||||||
constexpr int controlsSettingsCount = 4;
|
constexpr int controlsSettingsCount = 4;
|
||||||
const SettingInfo controlsSettings[controlsSettingsCount] = {
|
const SettingInfo controlsSettings[controlsSettingsCount] = {
|
||||||
SettingInfo::Enum(
|
SettingInfo::Enum("Front Button Layout", &CrossPointSettings::frontButtonLayout,
|
||||||
"Front Button Layout", &CrossPointSettings::frontButtonLayout,
|
{"Bck, Cnfrm, Lft, Rght", "Lft, Rght, Bck, Cnfrm", "Lft, Bck, Cnfrm, Rght"}),
|
||||||
{"Bck, Cnfrm, Lft, Rght", "Lft, Rght, Bck, Cnfrm", "Lft, Bck, Cnfrm, Rght", "Bck, Cnfrm, Rght, Lft"}),
|
|
||||||
SettingInfo::Enum("Side Button Layout (reader)", &CrossPointSettings::sideButtonLayout,
|
SettingInfo::Enum("Side Button Layout (reader)", &CrossPointSettings::sideButtonLayout,
|
||||||
{"Prev, Next", "Next, Prev"}),
|
{"Prev, Next", "Next, Prev"}),
|
||||||
SettingInfo::Toggle("Long-press Chapter Skip", &CrossPointSettings::longPressChapterSkip),
|
SettingInfo::Toggle("Long-press Chapter Skip", &CrossPointSettings::longPressChapterSkip),
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user