A fork of https://github.com/crosspoint-reader/crosspoint-reader
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: Implement guide-based cover image fallback (#830)

This partially fixes #769 but is dependent upon PR #827 being merged
along side this @daveallie. I removed my PNG conversion code after
finding out that PR was already created. Without this PR though that
book in #769 will still fail to load because of how it's stored in the
file

---------

Co-authored-by: Dave Allie <dave@daveallie.com>

authored by

Justin Mitchell
Dave Allie
and committed by
GitHub
67020609 0bc67474

+59 -11
+48
lib/Epub/Epub.cpp
··· 77 77 bookMetadata.author = opfParser.author; 78 78 bookMetadata.language = opfParser.language; 79 79 bookMetadata.coverItemHref = opfParser.coverItemHref; 80 + 81 + // Guide-based cover fallback: if no cover found via metadata/properties, 82 + // try extracting the image reference from the guide's cover page XHTML 83 + if (bookMetadata.coverItemHref.empty() && !opfParser.guideCoverPageHref.empty()) { 84 + LOG_DBG("EBP", "No cover from metadata, trying guide cover page: %s", opfParser.guideCoverPageHref.c_str()); 85 + size_t coverPageSize; 86 + uint8_t* coverPageData = readItemContentsToBytes(opfParser.guideCoverPageHref, &coverPageSize, true); 87 + if (coverPageData) { 88 + const std::string coverPageHtml(reinterpret_cast<char*>(coverPageData), coverPageSize); 89 + free(coverPageData); 90 + 91 + // Determine base path of the cover page for resolving relative image references 92 + std::string coverPageBase; 93 + const auto lastSlash = opfParser.guideCoverPageHref.rfind('/'); 94 + if (lastSlash != std::string::npos) { 95 + coverPageBase = opfParser.guideCoverPageHref.substr(0, lastSlash + 1); 96 + } 97 + 98 + // Search for image references: xlink:href="..." (SVG) and src="..." (img) 99 + std::string imageRef; 100 + for (const char* pattern : {"xlink:href=\"", "src=\""}) { 101 + auto pos = coverPageHtml.find(pattern); 102 + while (pos != std::string::npos) { 103 + pos += strlen(pattern); 104 + const auto endPos = coverPageHtml.find('"', pos); 105 + if (endPos != std::string::npos) { 106 + const auto ref = coverPageHtml.substr(pos, endPos - pos); 107 + // Check if it's an image file 108 + if (ref.length() >= 4) { 109 + const auto ext = ref.substr(ref.length() - 4); 110 + if (ext == ".png" || ext == ".jpg" || ext == "jpeg" || ext == ".gif") { 111 + imageRef = ref; 112 + break; 113 + } 114 + } 115 + } 116 + pos = coverPageHtml.find(pattern, pos); 117 + } 118 + if (!imageRef.empty()) break; 119 + } 120 + 121 + if (!imageRef.empty()) { 122 + bookMetadata.coverItemHref = FsHelpers::normalisePath(coverPageBase + imageRef); 123 + LOG_DBG("EBP", "Found cover image from guide: %s", bookMetadata.coverItemHref.c_str()); 124 + } 125 + } 126 + } 127 + 80 128 bookMetadata.textReferenceHref = opfParser.textReferenceHref; 81 129 82 130 if (!opfParser.tocNcxPath.empty()) {
+10 -11
lib/Epub/Epub/parsers/ContentOpfParser.cpp
··· 296 296 // parse the guide 297 297 if (self->state == IN_GUIDE && (strcmp(name, "reference") == 0 || strcmp(name, "opf:reference") == 0)) { 298 298 std::string type; 299 - std::string textHref; 299 + std::string guideHref; 300 300 for (int i = 0; atts[i]; i += 2) { 301 301 if (strcmp(atts[i], "type") == 0) { 302 302 type = atts[i + 1]; 303 - if (type == "text" || type == "start") { 304 - continue; 305 - } else { 306 - LOG_DBG("COF", "Skipping non-text reference in guide: %s", type.c_str()); 307 - break; 308 - } 309 303 } else if (strcmp(atts[i], "href") == 0) { 310 - textHref = FsHelpers::normalisePath(self->baseContentPath + atts[i + 1]); 304 + guideHref = FsHelpers::normalisePath(self->baseContentPath + atts[i + 1]); 311 305 } 312 306 } 313 - if ((type == "text" || (type == "start" && !self->textReferenceHref.empty())) && (textHref.length() > 0)) { 314 - LOG_DBG("COF", "Found %s reference in guide: %s.", type.c_str(), textHref.c_str()); 315 - self->textReferenceHref = textHref; 307 + if (!guideHref.empty()) { 308 + if (type == "text" || (type == "start" && !self->textReferenceHref.empty())) { 309 + LOG_DBG("COF", "Found %s reference in guide: %s", type.c_str(), guideHref.c_str()); 310 + self->textReferenceHref = guideHref; 311 + } else if ((type == "cover" || type == "cover-page") && self->guideCoverPageHref.empty()) { 312 + LOG_DBG("COF", "Found cover reference in guide: %s", guideHref.c_str()); 313 + self->guideCoverPageHref = guideHref; 314 + } 316 315 } 317 316 return; 318 317 }
+1
lib/Epub/Epub/parsers/ContentOpfParser.h
··· 63 63 std::string tocNcxPath; 64 64 std::string tocNavPath; // EPUB 3 nav document path 65 65 std::string coverItemHref; 66 + std::string guideCoverPageHref; // Guide reference with type="cover" or "cover-page" (points to XHTML wrapper) 66 67 std::string textReferenceHref; 67 68 std::vector<std::string> cssFiles; // CSS stylesheet paths 68 69