Merge pull request #221 from jpirnay/feat-hr-epub
feat: Add support for horizontal rulers
This commit is contained in:
@@ -49,6 +49,25 @@ std::unique_ptr<PageImage> PageImage::deserialize(FsFile& file) {
|
||||
return std::unique_ptr<PageImage>(new PageImage(std::move(ib), xPos, yPos));
|
||||
}
|
||||
|
||||
void PageHR::render(GfxRenderer& renderer, const int fontId, const int xOffset, const int yOffset) {
|
||||
renderer.drawLine(xPos + xOffset, yPos + yOffset, xPos + xOffset + width - 1, yPos + yOffset);
|
||||
}
|
||||
|
||||
bool PageHR::serialize(FsFile& file) {
|
||||
serialization::writePod(file, xPos);
|
||||
serialization::writePod(file, yPos);
|
||||
serialization::writePod(file, width);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<PageHR> PageHR::deserialize(FsFile& file) {
|
||||
int16_t xPos, yPos, width;
|
||||
serialization::readPod(file, xPos);
|
||||
serialization::readPod(file, yPos);
|
||||
serialization::readPod(file, width);
|
||||
return std::unique_ptr<PageHR>(new PageHR(xPos, yPos, width));
|
||||
}
|
||||
|
||||
void PageTableFragment::render(GfxRenderer& renderer, const int fontId, const int xOffset, const int yOffset) {
|
||||
const int drawX = xPos + xOffset;
|
||||
const int drawY = yPos + yOffset;
|
||||
@@ -237,6 +256,10 @@ std::unique_ptr<Page> Page::deserialize(FsFile& file) {
|
||||
auto pt = PageTableFragment::deserialize(file);
|
||||
if (!pt) return nullptr;
|
||||
page->elements.push_back(std::move(pt));
|
||||
} else if (tag == TAG_PageHR) {
|
||||
auto hr = PageHR::deserialize(file);
|
||||
if (!hr) return nullptr;
|
||||
page->elements.push_back(std::move(hr));
|
||||
} else {
|
||||
LOG_ERR("PGE", "Deserialization failed: Unknown tag %u", tag);
|
||||
return nullptr;
|
||||
|
||||
@@ -21,6 +21,7 @@ enum PageElementTag : uint8_t {
|
||||
TAG_PageLine = 1,
|
||||
TAG_PageImage = 2,
|
||||
TAG_PageTable = 3,
|
||||
TAG_PageHR = 4,
|
||||
};
|
||||
|
||||
// represents something that has been added to a page
|
||||
@@ -63,6 +64,17 @@ class PageImage final : public PageElement {
|
||||
const ImageBlock& getImageBlock() const { return *imageBlock; }
|
||||
};
|
||||
|
||||
class PageHR final : public PageElement {
|
||||
int16_t width;
|
||||
|
||||
public:
|
||||
PageHR(const int16_t xPos, const int16_t yPos, const int16_t width) : PageElement(xPos, yPos), width(width) {}
|
||||
void render(GfxRenderer& renderer, int fontId, int xOffset, int yOffset) override;
|
||||
bool serialize(FsFile& file) override;
|
||||
PageElementTag getTag() const override { return TAG_PageHR; }
|
||||
static std::unique_ptr<PageHR> deserialize(FsFile& file);
|
||||
};
|
||||
|
||||
struct TableCell {
|
||||
std::vector<std::shared_ptr<TextBlock>> lines;
|
||||
bool isHeader = false;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "parsers/ChapterHtmlSlimParser.h"
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t SECTION_FILE_VERSION = 27;
|
||||
constexpr uint8_t SECTION_FILE_VERSION = 28;
|
||||
constexpr uint32_t HEADER_SIZE = sizeof(uint8_t) + // SECTION_FILE_VERSION
|
||||
sizeof(int) + // fontId
|
||||
sizeof(float) + // lineCompression
|
||||
|
||||
@@ -1049,6 +1049,28 @@ void XMLCALL ChapterHtmlSlimParser::startElement(void* userData, const XML_Char*
|
||||
self->preUntilDepth = std::min(self->preUntilDepth, self->depth);
|
||||
}
|
||||
}
|
||||
} else if (strcmp(name, "hr") == 0) {
|
||||
if (self->partWordBufferIndex > 0) {
|
||||
if (!self->flushPartWordBuffer()) return;
|
||||
}
|
||||
self->makePages();
|
||||
if (!self->currentPage) {
|
||||
self->currentPage.reset(new Page());
|
||||
self->currentPageNextY = 0;
|
||||
}
|
||||
const int lineHeight = static_cast<int>(self->renderer.getLineHeight(self->fontId) * self->lineCompression + 0.5f);
|
||||
const int16_t marginV = static_cast<int16_t>(lineHeight / 2);
|
||||
self->currentPageNextY += marginV;
|
||||
if (self->currentPageNextY + 1 + marginV > self->viewportHeight) {
|
||||
self->emitPage(self->lastBodyChildByteOffset);
|
||||
self->currentPage.reset(new Page());
|
||||
self->currentPageNextY = 0;
|
||||
}
|
||||
self->currentPage->elements.push_back(
|
||||
std::make_shared<PageHR>(0, self->currentPageNextY, static_cast<int16_t>(self->viewportWidth)));
|
||||
self->currentPageNextY += 1 + marginV;
|
||||
BlockStyle emptyStyle;
|
||||
self->startNewTextBlock(emptyStyle);
|
||||
} else if (matches(name, UNDERLINE_TAGS, NUM_UNDERLINE_TAGS) ||
|
||||
matches(name, STRIKETHROUGH_TAGS, NUM_STRIKETHROUGH_TAGS)) {
|
||||
// Flush buffer before style change so preceding text gets current style
|
||||
|
||||
@@ -1014,6 +1014,7 @@ def main():
|
||||
<li>pre element: intrinsic line breaks preserved</li>
|
||||
<li>pre element: leading/trailing blank lines</li>
|
||||
<li>pre with inline code element</li>
|
||||
<li>horizontal rules between paragraphs</li>
|
||||
</ul>
|
||||
""",
|
||||
),
|
||||
@@ -1061,6 +1062,29 @@ Fifth line (blank line above)</pre>
|
||||
|
||||
greet("World");</code></pre>
|
||||
<p>Normal paragraph after pre/code block.</p>
|
||||
""",
|
||||
),
|
||||
[],
|
||||
),
|
||||
(
|
||||
"4. Horizontal Rules",
|
||||
make_chapter(
|
||||
"Horizontal Rule Tests",
|
||||
"""
|
||||
<p>A plain <hr> between two paragraphs. A thin line should appear between the two blocks of text.</p>
|
||||
<p>Paragraph before the first rule. Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
|
||||
<hr/>
|
||||
<p>Paragraph after the first rule. The rule above should be a full-width horizontal line.</p>
|
||||
<hr/>
|
||||
<p>Second rule above. Two rules in a row with no text between them:</p>
|
||||
<hr/>
|
||||
<hr/>
|
||||
<p>Two rules appeared above. Now a rule right after the heading:</p>
|
||||
<hr/>
|
||||
<p>Rule appeared right after the paragraph above. Finally, a rule near the end of the page to verify it does not cause a spurious page break when there is still room:</p>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
|
||||
<hr/>
|
||||
<p>End of horizontal rule tests.</p>
|
||||
""",
|
||||
),
|
||||
[],
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user