fix(epub): NFC-normalize EPUB text so NFD diacritics render correctly (#2277)
Co-authored-by: Uri Tauber <uritaube@gmail.com> Co-authored-by: Julia <julia@uxj.io>
This commit is contained in:
co-authored by
Uri Tauber
Julia
parent
7d639cf880
commit
16b0853654
+4
-2
@@ -5,6 +5,7 @@
|
||||
#include <JpegToBmpConverter.h>
|
||||
#include <Logging.h>
|
||||
#include <PngToBmpConverter.h>
|
||||
#include <Utf8.h>
|
||||
#include <ZipFile.h>
|
||||
|
||||
#include "Epub/parsers/ContainerParser.h"
|
||||
@@ -73,8 +74,9 @@ bool Epub::parseContentOpf(BookMetadataCache::BookMetadata& bookMetadata, const
|
||||
return false;
|
||||
}
|
||||
|
||||
// Grab data from opfParser into epub
|
||||
bookMetadata.title = opfParser.title;
|
||||
// Grab data from opfParser into epub. Normalize titles to NFC so NFD (combining
|
||||
// mark) text renders correctly — the device fonts have no mark positioning.
|
||||
bookMetadata.title = utf8ComposeNfc(opfParser.title);
|
||||
bookMetadata.author = opfParser.author;
|
||||
bookMetadata.language = opfParser.language;
|
||||
bookMetadata.coverItemHref = opfParser.coverItemHref;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <Logging.h>
|
||||
#include <Serialization.h>
|
||||
#include <Utf8.h>
|
||||
#include <ZipFile.h>
|
||||
|
||||
#include <deque>
|
||||
@@ -9,7 +10,7 @@
|
||||
#include "FsHelpers.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t BOOK_CACHE_VERSION = 7;
|
||||
constexpr uint8_t BOOK_CACHE_VERSION = 8; // v8: TOC/book titles stored NFC-composed
|
||||
constexpr char bookBinFile[] = "/book.bin";
|
||||
constexpr char tmpSpineBinFile[] = "/spine.bin.tmp";
|
||||
constexpr char tmpTocBinFile[] = "/toc.bin.tmp";
|
||||
@@ -364,7 +365,9 @@ void BookMetadataCache::createTocEntry(const std::string& title, const std::stri
|
||||
}
|
||||
}
|
||||
|
||||
const TocEntry entry(title, href, anchor, level, spineIndex);
|
||||
// Compose the title to NFC at index time so the cache stores precomposed glyphs;
|
||||
// device fonts have no combining-mark positioning, so NFD titles render broken.
|
||||
const TocEntry entry(utf8ComposeNfc(title), href, anchor, level, spineIndex);
|
||||
writeTocEntry(tocFile, entry);
|
||||
tocCount++;
|
||||
}
|
||||
|
||||
@@ -254,6 +254,14 @@ void ParsedText::addWord(std::string word, const EpdFontFamily::Style fontStyle,
|
||||
const bool attachToPrevious) {
|
||||
if (word.empty()) return;
|
||||
|
||||
// The device fonts carry no combining-mark positioning, so EPUB text stored in NFD
|
||||
// (a base letter followed by separate combining accents -- common for Vietnamese,
|
||||
// and used for many EPUB <h1> chapter headings) renders with the marks detached or
|
||||
// misplaced. Compose to NFC here, the single funnel every word passes through, so a
|
||||
// precomposed glyph is used instead. This runs once per word at layout time (the
|
||||
// result is cached in the section file) and is a cheap no-op for mark-free text.
|
||||
word = utf8ComposeNfc(word);
|
||||
|
||||
EpdFontFamily::Style baseStyle = fontStyle;
|
||||
if (underline) {
|
||||
baseStyle = static_cast<EpdFontFamily::Style>(baseStyle | EpdFontFamily::UNDERLINE);
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
#include "parsers/ChapterHtmlSlimParser.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t SECTION_FILE_VERSION = 26;
|
||||
// v27: words NFC-composed at layout time; bump invalidates NFD section caches.
|
||||
constexpr uint8_t SECTION_FILE_VERSION = 27;
|
||||
constexpr uint32_t HEADER_SIZE = sizeof(uint8_t) + sizeof(int) + sizeof(float) + sizeof(bool) + sizeof(uint8_t) +
|
||||
sizeof(uint16_t) + sizeof(uint16_t) + sizeof(uint16_t) + sizeof(bool) + sizeof(bool) +
|
||||
sizeof(uint8_t) + sizeof(bool) + sizeof(uint32_t) + sizeof(uint32_t) +
|
||||
|
||||
Reference in New Issue
Block a user