Merge remote-tracking branch 'origin' into feature/add-epub-css-parsing
* origin: fix: truncate chapter names that are too long (#422) feat: dict based Hyphenation (#305) fix: render U+FFFD replacement character instead of ? (#366) fix: Invert colors on home screen cover overlay when recent book is selected (#390) Adds KOReader Sync support (#232) feat: Change keyboard "caps" to "shift" & Wrap Keyboard (#377) fix: XTC 1-bit thumb BMP polarity inversion (#373)
This commit is contained in:
@@ -88,7 +88,7 @@ void ChapterHtmlSlimParser::startNewTextBlock(const TextBlock::Style style, cons
|
||||
|
||||
makePages();
|
||||
}
|
||||
currentTextBlock.reset(new ParsedText(style, extraParagraphSpacing, blockStyle));
|
||||
currentTextBlock.reset(new ParsedText(style, extraParagraphSpacing, hyphenationEnabled, blockStyle));
|
||||
}
|
||||
|
||||
void ChapterHtmlSlimParser::startNewTextBlock(const TextBlock::Style style) { startNewTextBlock(style, BlockStyle{}); }
|
||||
@@ -356,21 +356,6 @@ void XMLCALL ChapterHtmlSlimParser::characterData(void* userData, const XML_Char
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip soft-hyphen with UTF-8 representation (U+00AD) = 0xC2 0xAD
|
||||
const XML_Char SHY_BYTE_1 = static_cast<XML_Char>(0xC2);
|
||||
const XML_Char SHY_BYTE_2 = static_cast<XML_Char>(0xAD);
|
||||
// 1. Check for the start of the 2-byte Soft Hyphen sequence
|
||||
if (s[i] == SHY_BYTE_1) {
|
||||
// 2. Check if the next byte exists AND if it completes the sequence
|
||||
// We must check i + 1 < len to prevent reading past the end of the buffer.
|
||||
if ((i + 1 < len) && (s[i + 1] == SHY_BYTE_2)) {
|
||||
// Sequence 0xC2 0xAD found!
|
||||
// Skip the current byte (0xC2) and the next byte (0xAD)
|
||||
i++; // Increment 'i' one more time to skip the 0xAD byte
|
||||
continue; // Skip the rest of the loop and move to the next iteration
|
||||
}
|
||||
}
|
||||
|
||||
// Skip Zero Width No-Break Space / BOM (U+FEFF) = 0xEF 0xBB 0xBF
|
||||
const XML_Char FEFF_BYTE_1 = static_cast<XML_Char>(0xEF);
|
||||
const XML_Char FEFF_BYTE_2 = static_cast<XML_Char>(0xBB);
|
||||
|
||||
@@ -39,6 +39,7 @@ class ChapterHtmlSlimParser {
|
||||
uint8_t paragraphAlignment;
|
||||
uint16_t viewportWidth;
|
||||
uint16_t viewportHeight;
|
||||
bool hyphenationEnabled;
|
||||
const CssParser* cssParser;
|
||||
|
||||
// Style tracking (replaces depth-based approach)
|
||||
@@ -67,7 +68,7 @@ class ChapterHtmlSlimParser {
|
||||
explicit ChapterHtmlSlimParser(const std::string& filepath, GfxRenderer& renderer, const int fontId,
|
||||
const float lineCompression, const bool extraParagraphSpacing,
|
||||
const uint8_t paragraphAlignment, const uint16_t viewportWidth,
|
||||
const uint16_t viewportHeight,
|
||||
const uint16_t viewportHeight, const bool hyphenationEnabled,
|
||||
const std::function<void(std::unique_ptr<Page>)>& completePageFn,
|
||||
const std::function<void(int)>& progressFn = nullptr,
|
||||
const CssParser* cssParser = nullptr)
|
||||
@@ -79,6 +80,7 @@ class ChapterHtmlSlimParser {
|
||||
paragraphAlignment(paragraphAlignment),
|
||||
viewportWidth(viewportWidth),
|
||||
viewportHeight(viewportHeight),
|
||||
hyphenationEnabled(hyphenationEnabled),
|
||||
completePageFn(completePageFn),
|
||||
progressFn(progressFn),
|
||||
cssParser(cssParser) {}
|
||||
|
||||
@@ -108,6 +108,11 @@ void XMLCALL ContentOpfParser::startElement(void* userData, const XML_Char* name
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_METADATA && strcmp(name, "dc:language") == 0) {
|
||||
self->state = IN_BOOK_LANGUAGE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_PACKAGE && (strcmp(name, "manifest") == 0 || strcmp(name, "opf:manifest") == 0)) {
|
||||
self->state = IN_MANIFEST;
|
||||
if (!SdMan.openFileForWrite("COF", self->cachePath + itemCacheFile, self->tempItemStore)) {
|
||||
@@ -272,6 +277,11 @@ void XMLCALL ContentOpfParser::characterData(void* userData, const XML_Char* s,
|
||||
self->author.append(s, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_BOOK_LANGUAGE) {
|
||||
self->language.append(s, len);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void XMLCALL ContentOpfParser::endElement(void* userData, const XML_Char* name) {
|
||||
@@ -306,6 +316,11 @@ void XMLCALL ContentOpfParser::endElement(void* userData, const XML_Char* name)
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_BOOK_LANGUAGE && strcmp(name, "dc:language") == 0) {
|
||||
self->state = IN_METADATA;
|
||||
return;
|
||||
}
|
||||
|
||||
if (self->state == IN_METADATA && (strcmp(name, "metadata") == 0 || strcmp(name, "opf:metadata") == 0)) {
|
||||
self->state = IN_PACKAGE;
|
||||
return;
|
||||
|
||||
@@ -15,6 +15,7 @@ class ContentOpfParser final : public Print {
|
||||
IN_METADATA,
|
||||
IN_BOOK_TITLE,
|
||||
IN_BOOK_AUTHOR,
|
||||
IN_BOOK_LANGUAGE,
|
||||
IN_MANIFEST,
|
||||
IN_SPINE,
|
||||
IN_GUIDE,
|
||||
@@ -36,6 +37,7 @@ class ContentOpfParser final : public Print {
|
||||
public:
|
||||
std::string title;
|
||||
std::string author;
|
||||
std::string language;
|
||||
std::string tocNcxPath;
|
||||
std::string tocNavPath; // EPUB 3 nav document path
|
||||
std::string coverItemHref;
|
||||
|
||||
Reference in New Issue
Block a user