PegMarkdownHighlight: refine fast parse

This commit is contained in:
Le Tan 2018-07-31 20:33:57 +08:00
parent bfac189cb7
commit 284cba698f
2 changed files with 57 additions and 65 deletions

View File

@ -56,6 +56,8 @@ void PegMarkdownHighlighter::init(const QVector<HighlightingStyle> &p_styles,
m_result.reset(new PegHighlighterResult()); m_result.reset(new PegHighlighterResult());
m_fastResult.reset(new PegHighlighterFastResult()); m_fastResult.reset(new PegHighlighterFastResult());
m_fastParseBlocks = QPair<int, int>(-1, -1);
m_parser = new PegParser(this); m_parser = new PegParser(this);
connect(m_parser, &PegParser::parseResultReady, connect(m_parser, &PegParser::parseResultReady,
this, &PegMarkdownHighlighter::handleParseResult); this, &PegMarkdownHighlighter::handleParseResult);
@ -78,15 +80,10 @@ void PegMarkdownHighlighter::init(const QVector<HighlightingStyle> &p_styles,
return; return;
} }
const QVector<QVector<HLUnit>> &hls = result->m_blocksHighlights; for (int i = m_fastParseBlocks.first; i <= m_fastParseBlocks.second; ++i) {
for (int i = 0; i < hls.size(); ++i) {
if (!hls[i].isEmpty()) {
QTextBlock block = m_doc->findBlockByNumber(i); QTextBlock block = m_doc->findBlockByNumber(i);
if (PegMarkdownHighlighter::blockTimeStamp(block) != m_timeStamp) {
rehighlightBlock(block); rehighlightBlock(block);
} }
}
}
}); });
m_rehighlightTimer = new QTimer(this); m_rehighlightTimer = new QTimer(this);
@ -135,14 +132,16 @@ void PegMarkdownHighlighter::highlightBlock(const QString &p_text)
highlightBlockOne(result->m_blocksHighlights, blockNum, cacheValid ? cache : NULL); highlightBlockOne(result->m_blocksHighlights, blockNum, cacheValid ? cache : NULL);
} else { } else {
if (preHighlightSingleFormatBlock(m_fastResult->m_blocksHighlights, blockNum, p_text)) { // If fast result cover this block, we do not need to use the outdated one.
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; 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)) {
cacheValid = false;
} else {
highlightBlockOne(result->m_blocksHighlights, blockNum, cacheValid ? cache : NULL); highlightBlockOne(result->m_blocksHighlights, blockNum, cacheValid ? cache : NULL);
} }
} }
@ -288,6 +287,9 @@ void PegMarkdownHighlighter::startFastParse(int p_position, int p_charsRemoved,
block = block.next(); block = block.next();
} }
m_fastParseBlocks.first = firstBlockNum;
m_fastParseBlocks.second = lastBlockNum;
QSharedPointer<PegParseConfig> config(new PegParseConfig()); QSharedPointer<PegParseConfig> config(new PegParseConfig());
config->m_timeStamp = m_timeStamp; config->m_timeStamp = m_timeStamp;
config->m_data = text.toUtf8(); config->m_data = text.toUtf8();
@ -671,85 +673,65 @@ void PegMarkdownHighlighter::getFastParseBlockRange(int p_position,
} }
int num = lastBlock.blockNumber() - firstBlock.blockNumber() + 1; int num = lastBlock.blockNumber() - firstBlock.blockNumber() + 1;
if (num >= maxNumOfBlocks) { if (num > maxNumOfBlocks) {
p_firstBlock = p_lastBlock = -1; p_firstBlock = p_lastBlock = -1;
return; return;
} }
// Look up. // Look up.
// Find empty block.
// When firstBlock is an empty block at first, we should always skip it.
while (firstBlock.isValid() && num < maxNumOfBlocks) { while (firstBlock.isValid() && num < maxNumOfBlocks) {
QTextBlock block = firstBlock.previous(); QTextBlock preBlock = firstBlock.previous();
if (block.isValid() && !VEditUtils::isEmptyBlock(block)) { if (!preBlock.isValid()) {
firstBlock = block;
++num;
} else {
break; break;
} }
}
// Cross code block. // Check code block.
while (firstBlock.isValid() && num < maxNumOfBlocks) {
int state = firstBlock.userState(); int state = firstBlock.userState();
if (state == HighlightBlockState::CodeBlock if (state == HighlightBlockState::CodeBlock
|| state == HighlightBlockState::CodeBlockEnd) { || state == HighlightBlockState::CodeBlockEnd) {
QTextBlock block = firstBlock.previous(); goto goup;
if (block.isValid()) {
firstBlock = block;
++num;
} else {
break;
} }
} 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; break;
} }
} }
// Till the block with 0 indentation to handle contents in list. goup:
while (firstBlock.isValid() && num < maxNumOfBlocks) { firstBlock = preBlock;
if (VEditUtils::fetchIndentation(firstBlock) == 0
&& !VEditUtils::isEmptyBlock(firstBlock)) {
break;
} else {
QTextBlock block = firstBlock.previous();
if (block.isValid()) {
firstBlock = block;
++num; ++num;
} else {
break;
}
}
} }
// Look down. // Look down.
// Find empty block.
// If lastBlock is an empty block at first, we should always skip it.
while (lastBlock.isValid() && num < maxNumOfBlocks) { while (lastBlock.isValid() && num < maxNumOfBlocks) {
QTextBlock block = lastBlock.next(); QTextBlock nextBlock = lastBlock.next();
if (block.isValid() && !VEditUtils::isEmptyBlock(block)) { if (!nextBlock.isValid()) {
lastBlock = block;
++num;
} else {
break; break;
} }
}
// Cross code block. // Check code block.
while (lastBlock.isValid() && num < maxNumOfBlocks) {
int state = lastBlock.userState(); int state = lastBlock.userState();
if (state == HighlightBlockState::CodeBlock if (state == HighlightBlockState::CodeBlockStart
|| state == HighlightBlockState::CodeBlockStart) { || state == HighlightBlockState::CodeBlock) {
QTextBlock block = lastBlock.next(); goto godown;
if (block.isValid()) { }
lastBlock = block;
// Empty block.
if (VEditUtils::isEmptyBlock(nextBlock)) {
break;
}
godown:
lastBlock = nextBlock;
++num; ++num;
} else {
break;
}
} else {
break;
}
} }
p_firstBlock = firstBlock.blockNumber(); p_firstBlock = firstBlock.blockNumber();

View File

@ -131,6 +131,8 @@ private:
TimeStamp nextCodeBlockTimeStamp(); TimeStamp nextCodeBlockTimeStamp();
bool isFastParseBlock(int p_blockNum) const;
static VTextBlockData *getBlockData(const QTextBlock &p_block); static VTextBlockData *getBlockData(const QTextBlock &p_block);
static bool isEmptyCodeBlockHighlights(const QVector<QVector<HLUnitStyle>> &p_highlights); static bool isEmptyCodeBlockHighlights(const QVector<QVector<HLUnitStyle>> &p_highlights);
@ -163,6 +165,9 @@ private:
QSharedPointer<PegHighlighterFastResult> m_fastResult; QSharedPointer<PegHighlighterFastResult> m_fastResult;
// Block range of fast parse, inclusive.
QPair<int, int> m_fastParseBlocks;
// Block number of those blocks which possible contains previewed image. // Block number of those blocks which possible contains previewed image.
QSet<int> m_possiblePreviewBlocks; QSet<int> m_possiblePreviewBlocks;
@ -318,4 +323,9 @@ inline TimeStamp PegMarkdownHighlighter::nextCodeBlockTimeStamp()
{ {
return ++m_codeBlockTimeStamp; 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 #endif // PEGMARKDOWNHIGHLIGHTER_H