From 284cba698fb5e82678b5059f3c8ef3e1885c703c Mon Sep 17 00:00:00 2001 From: Le Tan Date: Tue, 31 Jul 2018 20:33:57 +0800 Subject: [PATCH] PegMarkdownHighlight: refine fast parse --- src/pegmarkdownhighlighter.cpp | 112 ++++++++++++++------------------- src/pegmarkdownhighlighter.h | 10 +++ 2 files changed, 57 insertions(+), 65 deletions(-) diff --git a/src/pegmarkdownhighlighter.cpp b/src/pegmarkdownhighlighter.cpp index 3ea29231..59d1e4fe 100644 --- a/src/pegmarkdownhighlighter.cpp +++ b/src/pegmarkdownhighlighter.cpp @@ -56,6 +56,8 @@ void PegMarkdownHighlighter::init(const QVector &p_styles, m_result.reset(new PegHighlighterResult()); m_fastResult.reset(new PegHighlighterFastResult()); + m_fastParseBlocks = QPair(-1, -1); + m_parser = new PegParser(this); connect(m_parser, &PegParser::parseResultReady, this, &PegMarkdownHighlighter::handleParseResult); @@ -78,14 +80,9 @@ void PegMarkdownHighlighter::init(const QVector &p_styles, return; } - const QVector> &hls = result->m_blocksHighlights; - for (int i = 0; i < hls.size(); ++i) { - if (!hls[i].isEmpty()) { - QTextBlock block = m_doc->findBlockByNumber(i); - if (PegMarkdownHighlighter::blockTimeStamp(block) != m_timeStamp) { - rehighlightBlock(block); - } - } + for (int i = m_fastParseBlocks.first; i <= m_fastParseBlocks.second; ++i) { + QTextBlock block = m_doc->findBlockByNumber(i); + rehighlightBlock(block); } }); @@ -135,14 +132,16 @@ void PegMarkdownHighlighter::highlightBlock(const QString &p_text) highlightBlockOne(result->m_blocksHighlights, blockNum, cacheValid ? cache : NULL); } else { - if (preHighlightSingleFormatBlock(m_fastResult->m_blocksHighlights, blockNum, p_text)) { - cacheValid = false; - } - // If fast result cover this block, we do not need to use the outdated one. - if (highlightBlockOne(m_fastResult->m_blocksHighlights, blockNum, NULL)) { + if (isFastParseBlock(blockNum)) { + preHighlightSingleFormatBlock(m_fastResult->m_blocksHighlights, blockNum, p_text); + highlightBlockOne(m_fastResult->m_blocksHighlights, blockNum, NULL); cacheValid = false; } else { + if (preHighlightSingleFormatBlock(result->m_blocksHighlights, blockNum, p_text)) { + cacheValid = false; + } + highlightBlockOne(result->m_blocksHighlights, blockNum, cacheValid ? cache : NULL); } } @@ -288,6 +287,9 @@ void PegMarkdownHighlighter::startFastParse(int p_position, int p_charsRemoved, block = block.next(); } + m_fastParseBlocks.first = firstBlockNum; + m_fastParseBlocks.second = lastBlockNum; + QSharedPointer config(new PegParseConfig()); config->m_timeStamp = m_timeStamp; config->m_data = text.toUtf8(); @@ -671,85 +673,65 @@ void PegMarkdownHighlighter::getFastParseBlockRange(int p_position, } int num = lastBlock.blockNumber() - firstBlock.blockNumber() + 1; - if (num >= maxNumOfBlocks) { + if (num > maxNumOfBlocks) { p_firstBlock = p_lastBlock = -1; return; } // Look up. - // Find empty block. - // When firstBlock is an empty block at first, we should always skip it. while (firstBlock.isValid() && num < maxNumOfBlocks) { - QTextBlock block = firstBlock.previous(); - if (block.isValid() && !VEditUtils::isEmptyBlock(block)) { - firstBlock = block; - ++num; - } else { + QTextBlock preBlock = firstBlock.previous(); + if (!preBlock.isValid()) { break; } - } - // Cross code block. - while (firstBlock.isValid() && num < maxNumOfBlocks) { + // Check code block. int state = firstBlock.userState(); if (state == HighlightBlockState::CodeBlock || state == HighlightBlockState::CodeBlockEnd) { - QTextBlock block = firstBlock.previous(); - if (block.isValid()) { - firstBlock = block; - ++num; - } else { - break; - } - } else { - break; + goto goup; } - } - // Till the block with 0 indentation to handle contents in list. - while (firstBlock.isValid() && num < maxNumOfBlocks) { - if (VEditUtils::fetchIndentation(firstBlock) == 0 - && !VEditUtils::isEmptyBlock(firstBlock)) { - break; - } else { - QTextBlock block = firstBlock.previous(); - if (block.isValid()) { - firstBlock = block; - ++num; - } else { + // Empty block. + if (VEditUtils::isEmptyBlock(firstBlock)) { + goto goup; + } + + int indent = VEditUtils::fetchIndentation(firstBlock); + if (indent == 0) { + // If previous block is empty, then we could stop now. + if (VEditUtils::isEmptyBlock(preBlock)) { break; } } + +goup: + firstBlock = preBlock; + ++num; } // Look down. - // Find empty block. - // If lastBlock is an empty block at first, we should always skip it. while (lastBlock.isValid() && num < maxNumOfBlocks) { - QTextBlock block = lastBlock.next(); - if (block.isValid() && !VEditUtils::isEmptyBlock(block)) { - lastBlock = block; - ++num; - } else { + QTextBlock nextBlock = lastBlock.next(); + if (!nextBlock.isValid()) { break; } - } - // Cross code block. - while (lastBlock.isValid() && num < maxNumOfBlocks) { + // Check code block. int state = lastBlock.userState(); - if (state == HighlightBlockState::CodeBlock - || state == HighlightBlockState::CodeBlockStart) { - QTextBlock block = lastBlock.next(); - if (block.isValid()) { - lastBlock = block; - ++num; - } else { - break; - } - } else { + if (state == HighlightBlockState::CodeBlockStart + || state == HighlightBlockState::CodeBlock) { + goto godown; + } + + // Empty block. + if (VEditUtils::isEmptyBlock(nextBlock)) { break; } + +godown: + lastBlock = nextBlock; + ++num; } p_firstBlock = firstBlock.blockNumber(); diff --git a/src/pegmarkdownhighlighter.h b/src/pegmarkdownhighlighter.h index bac05844..2e3378d3 100644 --- a/src/pegmarkdownhighlighter.h +++ b/src/pegmarkdownhighlighter.h @@ -131,6 +131,8 @@ private: TimeStamp nextCodeBlockTimeStamp(); + bool isFastParseBlock(int p_blockNum) const; + static VTextBlockData *getBlockData(const QTextBlock &p_block); static bool isEmptyCodeBlockHighlights(const QVector> &p_highlights); @@ -163,6 +165,9 @@ private: QSharedPointer m_fastResult; + // Block range of fast parse, inclusive. + QPair m_fastParseBlocks; + // Block number of those blocks which possible contains previewed image. QSet m_possiblePreviewBlocks; @@ -318,4 +323,9 @@ inline TimeStamp PegMarkdownHighlighter::nextCodeBlockTimeStamp() { return ++m_codeBlockTimeStamp; } + +inline bool PegMarkdownHighlighter::isFastParseBlock(int p_blockNum) const +{ + return p_blockNum >= m_fastParseBlocks.first && p_blockNum <= m_fastParseBlocks.second; +} #endif // PEGMARKDOWNHIGHLIGHTER_H