#pragma once #include #include #include #include #include "../ParsedText.h" #include "../blocks/TextBlock.h" #include "../css/CssParser.h" #include "../css/CssStyle.h" class Page; class GfxRenderer; #define MAX_WORD_SIZE 200 class ChapterHtmlSlimParser { const std::string& filepath; GfxRenderer& renderer; std::function)> completePageFn; std::function popupFn; // Popup callback int depth = 0; int skipUntilDepth = INT_MAX; int boldUntilDepth = INT_MAX; int italicUntilDepth = INT_MAX; int underlineUntilDepth = INT_MAX; // buffer for building up words from characters, will auto break if longer than this // leave one char at end for null pointer char partWordBuffer[MAX_WORD_SIZE + 1] = {}; int partWordBufferIndex = 0; std::unique_ptr currentTextBlock = nullptr; std::unique_ptr currentPage = nullptr; int16_t currentPageNextY = 0; int fontId; float lineCompression; bool extraParagraphSpacing; uint8_t paragraphAlignment; uint16_t viewportWidth; uint16_t viewportHeight; bool hyphenationEnabled; const CssParser* cssParser; // Style tracking (replaces depth-based approach) struct StyleStackEntry { int depth = 0; bool hasBold = false, bold = false; bool hasItalic = false, italic = false; bool hasUnderline = false, underline = false; }; std::vector inlineStyleStack; CssStyle currentCssStyle; bool effectiveBold = false; bool effectiveItalic = false; bool effectiveUnderline = false; void updateEffectiveInlineStyle(); void startNewTextBlock(const BlockStyle& blockStyle); void flushPartWordBuffer(); void makePages(); // XML callbacks static void XMLCALL startElement(void* userData, const XML_Char* name, const XML_Char** atts); static void XMLCALL characterData(void* userData, const XML_Char* s, int len); static void XMLCALL endElement(void* userData, const XML_Char* name); public: 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 bool hyphenationEnabled, const std::function)>& completePageFn, const std::function& popupFn = nullptr, const CssParser* cssParser = nullptr) : filepath(filepath), renderer(renderer), fontId(fontId), lineCompression(lineCompression), extraParagraphSpacing(extraParagraphSpacing), paragraphAlignment(paragraphAlignment), viewportWidth(viewportWidth), viewportHeight(viewportHeight), hyphenationEnabled(hyphenationEnabled), completePageFn(completePageFn), popupFn(popupFn), cssParser(cssParser) {} ~ChapterHtmlSlimParser() = default; bool parseAndBuildPages(); void addLineToPage(std::shared_ptr line); };