optimize painter.

This commit is contained in:
Roy Qu 2024-04-04 23:12:12 +08:00
parent 3e1e4b0f01
commit 72481d7de8
6 changed files with 98 additions and 33 deletions

View File

@ -2245,6 +2245,7 @@ void Editor::onTooltipTimer()
void Editor::onEndParsing()
{
mIdentCache.clear();
document()->invalidateAllLineWidth();
invalidate();
}
@ -5562,7 +5563,8 @@ void Editor::applyColorScheme(const QString& schemeName)
mCurrentHighlighWordForeground = selectedForeground();
mCurrentHighlighWordBackground = selectedBackground();
}
this->invalidate();
document()->invalidateAllLineWidth();
invalidate();
}
void Editor::updateCaption(const QString& newCaption) {

View File

@ -1155,6 +1155,13 @@ void Document::internalClear()
}
}
bool Document::lineWidthValid(int line)
{
if (line<0 || line>=mLines.count())
return false;
return mLines[line]->mWidth>=0 && !mLines[line]->mIsTempWidth;
}
void Document::beginSetLinesWidth()
{
if (mSetLineWidthLockCount == 0) {
@ -1172,15 +1179,15 @@ void Document::endSetLinesWidth()
}
}
void Document::setLineWidth(int line, const QString &lineText, int newWidth, const QList<int> glyphStartPositionList)
void Document::setLineWidth(int line, int newWidth, const QList<int> glyphStartPositionList)
{
QMutexLocker locker(&mMutex);
if (line<0 || line>=count())
return ;
if (lineText != mLines[line]->lineText())
return;
int oldWidth = mLines[line]->mWidth;
//qDebug()<<line<<oldWidth<<newWidth;
mLines[line]->mWidth = newWidth;
mLines[line]->mIsTempWidth = false;
mLines[line]->mGlyphStartPositionList = glyphStartPositionList;
if (mIndexOfLongestLine<0) {
mIndexOfLongestLine = line;
@ -1246,6 +1253,23 @@ QList<int> Document::getGlyphStartCharList(int line, const QString &lineText)
return mLines[line]->glyphStartCharList();
}
QList<int> Document::getGlyphStartCharList(int line)
{
if (line<0 || line>=count())
return QList<int>();
return mLines[line]->glyphStartCharList();
}
QList<int> Document::getGlyphStartPositionList(int line)
{
return mLines[line]->glyphStartPositionList();
}
int Document::getLineWidth(int line)
{
return mLines[line]->mWidth;
}
NewlineType Document::getNewlineType()
{
QMutexLocker locker(&mMutex);
@ -1276,6 +1300,7 @@ void Document::invalidateAllLineWidth()
DocumentLine::DocumentLine(DocumentLine::UpdateWidthFunc updateWidthFunc):
mSyntaxState{},
mWidth{-1},
mIsTempWidth{true},
mUpdateWidthFunc{updateWidthFunc}
{
}

View File

@ -147,7 +147,7 @@ private:
void setLineText(const QString &newLineText);
void updateWidth();
void invalidateWidth() { mWidth = -1; mGlyphStartPositionList.clear(); }
void invalidateWidth() { mWidth = -1; mGlyphStartPositionList.clear(); mIsTempWidth = true;}
private:
QString mLineText; /* the unicode code points of the text */
/**
@ -181,7 +181,7 @@ private:
* so it must be recalculated each time the font is changed.
*/
int mWidth;
bool mIsTempWidth;
UpdateWidthFunc mUpdateWidthFunc;
friend class Document;
@ -576,9 +576,10 @@ protected:
void putTextStr(const QString& text);
void internalClear();
private:
bool lineWidthValid(int line);
void beginSetLinesWidth();
void endSetLinesWidth();
void setLineWidth(int line, const QString& lineText, int newWidth, const QList<int> glyphStartPositionList);
void setLineWidth(int line, int newWidth, const QList<int> glyphStartPositionList);
void updateMaxLineWidthChanged();
void updateMaxLineWidthAndNotify();
@ -595,6 +596,9 @@ private:
QList<int> calcGlyphPositionList(const QString& lineText, const QList<int> &glyphStartCharList, int left, int &right) const;
QList<int> calcGlyphPositionList(const QString& lineText, int &width) const;
QList<int> getGlyphStartCharList(int line, const QString &lineText);
QList<int> getGlyphStartCharList(int line);
QList<int> getGlyphStartPositionList(int line);
int getLineWidth(int line);
bool tryLoadFileByEncoding(QByteArray encodingName, QFile& file);
void loadUTF16BOMFile(QFile& file);
void loadUTF32BOMFile(QFile& file);

View File

@ -707,9 +707,25 @@ void QSynEditPainter::addHighlightToken(
const QList<int> glyphStartCharList,
int tokenStartChar,
int tokenEndChar,
bool calcGlyphPosition,
QList<int> &glyphStartPositionList,
int &tokenWidth)
{
int tokenRight;
int startGlyph, endGlyph;
if (!calcGlyphPosition) {
tokenRight = std::max(0,tokenLeft);
startGlyph = searchForSegmentIdx(glyphStartCharList,0,lineText.length(),tokenStartChar);
endGlyph = searchForSegmentIdx(glyphStartCharList,0,lineText.length(),tokenEndChar);
for (int i=startGlyph;i<endGlyph;i++) {
int gWidth = calcSegmentInterval(glyphStartPositionList, mCurrentLineWidth, i);
tokenRight += gWidth;
}
tokenWidth = tokenRight-tokenLeft;
if (tokenRight<mLeft) {
return;
}
}
QColor foreground, background;
FontStyles style;
@ -767,22 +783,22 @@ void QSynEditPainter::addHighlightToken(
mTokenAccu.font.setUnderline(style & FontStyle::fsUnderline);
}
//calculate width of the token ( and update it's glyph start positions )
int tokenRight;
int startGlyph, endGlyph;
tokenWidth = mEdit->mDocument->updateGlyphStartPositionList(
lineText,
glyphStartCharList,
tokenStartChar,
tokenEndChar,
QFontMetrics(mTokenAccu.font),
glyphStartPositionList,
tokenLeft,
tokenRight,
startGlyph,
endGlyph);
if (calcGlyphPosition) {
tokenWidth = mEdit->mDocument->updateGlyphStartPositionList(
lineText,
glyphStartCharList,
tokenStartChar,
tokenEndChar,
QFontMetrics(mTokenAccu.font),
glyphStartPositionList,
tokenLeft,
tokenRight,
startGlyph,
endGlyph);
}
// Only accumulate tokens if it's visible.
if (tokenLeft < mRight) {
if (tokenLeft < mRight && tokenRight>mLeft) {
if (bCanAppend) {
mTokenAccu.width += tokenWidth;
Q_ASSERT(startGlyph == mTokenAccu.endGlyph);
@ -951,6 +967,7 @@ void QSynEditPainter::paintLines()
BufferCoord selectionEnd= mEdit->blockEnd();
for (int row = mFirstRow; row<=mLastRow; row++) {
int vLine = mEdit->rowToLine(row);
bool lineTextChanged = false;
if (vLine > mEdit->mDocument->count() && mEdit->mDocument->count() != 0)
break;
@ -966,6 +983,7 @@ void QSynEditPainter::paintLines()
int ch = mEdit->mDocument->charToGlyphStartChar(mEdit->mCaretY-1,mEdit->mCaretX-1);
sLine = sLine.left(ch) + mEdit->mInputPreeditString
+ sLine.mid(ch);
lineTextChanged = true;
}
// Initialize the text and background colors, maybe the line should
// use special values for them.
@ -1036,10 +1054,23 @@ void QSynEditPainter::paintLines()
mRcToken = mRcLine;
QList<int> glyphStartCharList = mEdit->mDocument->getGlyphStartCharList(vLine-1,sLine);
QList<int> glyphStartCharList;
if (lineTextChanged) {
glyphStartCharList = mEdit->mDocument->getGlyphStartCharList(vLine-1,sLine);
} else {
glyphStartCharList = mEdit->mDocument->getGlyphStartCharList(vLine-1);
}
// Ensure the list has the right number of elements.
// Values in it doesn't matter, we'll recalculate them.
QList<int> glyphStartPositionsList = glyphStartCharList;
QList<int> glyphStartPositionsList;
bool lineWidthValid = mEdit->mDocument->lineWidthValid(vLine-1);
bool calculateGlyphPositions = ( mHasSelectionInLine || lineTextChanged || !lineWidthValid);
if (calculateGlyphPositions) {
glyphStartPositionsList = glyphStartCharList;
} else {
glyphStartPositionsList = mEdit->mDocument->getGlyphStartPositionList(vLine-1);
mCurrentLineWidth = mEdit->mDocument->getLineWidth(vLine-1);
}
// Initialize highlighter with line text and range info. It is
// necessary because we probably did not scan to the end of the last
// line - the internal highlighter range might be wrong.
@ -1061,15 +1092,6 @@ void QSynEditPainter::paintLines()
sToken = mEdit->mSyntaxer->getToken();
if (sToken.isEmpty()) {
continue;
// mEdit->mSyntaxer->next();
// if (mEdit->mSyntaxer->eol())
// break;
// sToken = mEdit->mSyntaxer->getToken();
// // Maybe should also test whether GetTokenPos changed...
// if (sToken.isEmpty()) {
// //qDebug()<<QSynEdit::tr("The highlighter seems to be in an infinite loop");
// throw BaseError(QSynEdit::tr("The syntaxer seems to be in an infinite loop"));
// }
}
int tokenStartChar = mEdit->mSyntaxer->getTokenPos();
int tokenEndChar = tokenStartChar + sToken.length();
@ -1130,13 +1152,21 @@ void QSynEditPainter::paintLines()
glyphStartCharList,
tokenStartChar,
tokenEndChar,
calculateGlyphPositions,
glyphStartPositionsList,
tokenWidth);
tokenLeft+=tokenWidth;
//We don't need to calculate line width,
//So we just quit if already out of the right edge of the editor
if (
(!calculateGlyphPositions || lineTextChanged)
&& (tokenLeft>mRight))
break;
// Let the highlighter scan the next token.
mEdit->mSyntaxer->next();
}
mEdit->mDocument->setLineWidth(vLine-1, sLine, tokenLeft, glyphStartPositionsList);
if (!lineWidthValid)
mEdit->mDocument->setLineWidth(vLine-1, tokenLeft, glyphStartPositionsList);
if (tokenLeft<mRight) {
QString addOnStr;
@ -1170,6 +1200,7 @@ void QSynEditPainter::paintLines()
glyphStartCharList,
oldLen,
sLine.length(),
calculateGlyphPositions,
glyphStartPositionsList,
tokenWidth);
tokenLeft += tokenWidth;

View File

@ -96,6 +96,7 @@ private:
const QList<int> glyphStartCharList,
int tokenStartChar,
int tokenEndChar,
bool calcGlyphPosition,
QList<int> &glyphStartPositionList,
int &tokenWidth
);
@ -121,6 +122,7 @@ private:
// info about selection of the current line
int mLineSelStart, mLineSelEnd;
bool mHasSelectionInLine;
int mCurrentLineWidth;
// painting the background and the text
QRect mRcLine, mRcToken;
int mFirstLine, mLastLine;

View File

@ -4678,6 +4678,7 @@ void QSynEdit::setSyntaxer(const PSyntaxer &syntaxer)
reparseDocument();
mDocument->endUpdate();
}
mDocument->invalidateAllLineWidth();
invalidate();
}