Painter optimization

ligature support
This commit is contained in:
Roy Qu 2024-02-25 11:22:49 +08:00
parent effecc80f9
commit 7ac35a86b8
5 changed files with 112 additions and 53 deletions

View File

@ -1493,7 +1493,7 @@ void Settings::Editor::doLoad()
mFontSize = intValue("font_size",12);
mFontOnlyMonospaced = boolValue("font_only_monospaced",true);
mLineSpacing = doubleValue("line_spacing",1.0);
mEnableLigaturesSupport = boolValue("enable_ligatures_support", false);
mEnableLigaturesSupport = boolValue("enable_ligatures_support", true);
mShowLeadingSpaces = boolValue("show_leading_spaces", false);
mShowTrailingSpaces = boolValue("show_trailing_spaces", false);

View File

@ -957,16 +957,17 @@ int Document::charToGlyphIndex(int line, int charIdx)
int Document::charToGlyphIndex(const QString& str, QList<int> glyphStartCharList, int charIdx) const
{
Q_ASSERT(charIdx>=0);
if (charIdx>=str.length())
return glyphStartCharList.length();
for (int i=0;i<glyphStartCharList.length();i++) {
if (glyphStartCharList[i]>charIdx) {
Q_ASSERT(i-1>=0);
return i-1;
}
}
Q_ASSERT(glyphStartCharList.length()-1>=0);
return glyphStartCharList.length()-1;
return searchForSegmentIdx(glyphStartCharList, 0, str.length(), charIdx);
// if (charIdx>=str.length())
// return glyphStartCharList.length();
// for (int i=0;i<glyphStartCharList.length();i++) {
// if (glyphStartCharList[i]>charIdx) {
// Q_ASSERT(i-1>=0);
// return i-1;
// }
// }
// Q_ASSERT(glyphStartCharList.length()-1>=0);
// return glyphStartCharList.length()-1;
}
QList<int> Document::calcLineWidth(const QString &lineText, const QList<int> &glyphStartCharList, int &width)
@ -985,14 +986,15 @@ int Document::xposToGlyphIndex(int line, int xpos)
int Document::xposToGlyphIndex(int strWidth, QList<int> glyphPositionList, int xpos) const
{
if (xpos>=strWidth)
return glyphPositionList.length();
for (int i=0;i<glyphPositionList.length();i++) {
if (glyphPositionList[i]>xpos) {
return i-1;
}
}
return glyphPositionList.length()-1;
return searchForSegmentIdx(glyphPositionList,0,strWidth,xpos);
// if (xpos>=strWidth)
// return glyphPositionList.length();
// for (int i=0;i<glyphPositionList.length();i++) {
// if (glyphPositionList[i]>xpos) {
// return i-1;
// }
// }
// return glyphPositionList.length()-1;
}
int Document::charToGlyphStartPosition(int line, int charPos)
@ -1673,4 +1675,31 @@ BinaryFileError::BinaryFileError(const QString& reason):
}
int searchForSegmentIdx(const QList<int> segList, int minVal, int maxVal, int value)
{
if (value<minVal)
return 0;
if (value>=maxVal)
return segList.length();
int start = 0;
int end = segList.length()-1;
while ( start<=end ) {
int mid = (start+end) / 2;
if (segList[mid]==value) {
//skip zero length segs
while(mid+1<segList.length() && segList[mid+1]==value)
mid++;
return mid;
} else if (segList[mid]>value) {
end = mid-1;
} else if (mid+1>=segList.length() || segList[mid+1]>value ) {
return mid;
} else {
start = mid+1;
}
}
//Not found, should not happen
Q_ASSERT(false);
}
}

View File

@ -30,6 +30,8 @@
namespace QSynedit {
int searchForSegmentIdx(const QList<int> segList, int minVal, int maxVal, int value);
QList<int> calcGlyphStartCharList(const QString &text);
class Document;

View File

@ -51,8 +51,7 @@ QSynEditPainter::QSynEditPainter(QSynEdit *edit, QPainter *painter, int firstRow
mFirstRow{firstRow},
mLastRow{lastRow},
mLeft{left},
mRight{right},
mLastGlyphAscii{false}
mRight{right}
{
}
@ -361,6 +360,8 @@ void QSynEditPainter::paintToken(
{
bool startPaint;
int nX;
bool lastGlyphAscii = false;
bool fontInited = false;
// qDebug()<<"Paint token"<<token<<tokenWidth<<tokenLeft<<first<<last<<rcToken;
@ -388,33 +389,61 @@ void QSynEditPainter::paintToken(
startPaint = true;
}
}
if (tokenWidth+glyphWidth > last)
break;
//painter->drawText(nX,rcToken.bottom()-painter->fontMetrics().descent()*edit->dpiFactor() , Token[i]);
if (startPaint) {
bool drawed = false;
if (mPainter->fontInfo().fixedPitch()
&& mEdit->mOptions.testFlag(eoLigatureSupport)
&& OperatorGlyphs.contains(glyph)) {
QString textToPaint = glyph;
while(i+1<token.length()) {
int glyphStart = glyphStartCharList[i+1];
int glyphEnd =(i+2<glyphStartCharList.length())?glyphStartCharList[i+2]:token.length();
QString glyph2 = token.mid(glyphStart,glyphEnd-glyphStart);
if (!OperatorGlyphs.contains(glyph))
break;
i+=1;
glyphWidth += mEdit->document()->glyphWidth(glyph2,0);
textToPaint+=glyph2;
if (mEdit->mOptions.testFlag(eoLigatureSupport)) {
bool tryLigature = false;
bool isAscii = false;
if (glyph.length()==0) {
} else if (glyph.length()==1 && glyph.front().unicode()<=32){
} else if (glyph.length()==1
&& glyph.front().unicode()>32
&& glyph.front().unicode()<128) {
tryLigature = true;
isAscii = true;
} else {
tryLigature = true;
isAscii = false;
}
if (tryLigature) {
QString textToPaint = glyph;
while(i+1<glyphStartCharList.length()) {
int glyphStart = glyphStartCharList[i+1];
int glyphEnd =(i+2<glyphStartCharList.length())?glyphStartCharList[i+2]:token.length();
QString glyph2 = token.mid(glyphStart,glyphEnd-glyphStart);
// if (!OperatorGlyphs.contains(glyph))
// break;
if (isAscii) {
if ( glyph.length()!=1
|| glyph.front().unicode()<=32
|| glyph.front().unicode()>=128)
break;
} else {
if ( glyph.length()<1
||
(glyph.length()==1
&& glyph.front().unicode()>32
&& glyph.front().unicode()<128))
break;
}
i+=1;
glyphWidth += mEdit->document()->glyphWidth(glyph2,0);
textToPaint+=glyph2;
if (tokenWidth + glyphWidth > last )
break;
}
if (!fontInited || lastGlyphAscii!=isAscii) {
mPainter->setFont(font);
lastGlyphAscii = isAscii;
fontInited = true;
}
mPainter->drawText(nX,rcToken.bottom()-mPainter->fontMetrics().descent() , textToPaint);
drawed = true;
}
if (!mLastGlyphAscii)
mPainter->setFont(font);
mPainter->drawText(nX,rcToken.bottom()-mPainter->fontMetrics().descent() , textToPaint);
mLastGlyphAscii = true;
drawed = true;
}
if (!drawed) {
if (glyph.length()==1 && glyph.front().unicode()<=0xFF) {
if (glyph.length()==1 && glyph.front().unicode()<128) {
QString ch;
int padding=0;
if (showGlyphs) {
@ -433,24 +462,29 @@ void QSynEditPainter::paintToken(
ch=glyph;
}
if (ch!=" " && ch!="\t") {
if (!mLastGlyphAscii)
if (!fontInited || !lastGlyphAscii) {
mPainter->setFont(font);
fontInited = true;
lastGlyphAscii = true;
}
mPainter->drawText(nX+padding,rcToken.bottom()-mPainter->fontMetrics().descent() , ch);
mLastGlyphAscii = true;
}
//qDebug()<<"Drawing"<<glyph<<nX<<glyphWidth;
} else {
if (mLastGlyphAscii)
if (!fontInited || lastGlyphAscii) {
mPainter->setFont(fontForNonAscii);
fontInited = true;
lastGlyphAscii = false;
}
mPainter->drawText(nX,rcToken.bottom()-mPainter->fontMetrics().descent() , glyph);
mLastGlyphAscii = false;
}
drawed = true;
}
nX += glyphWidth;
}
tokenWidth += glyphWidth;
if (tokenWidth > last)
break;
}
}
@ -549,8 +583,6 @@ void QSynEditPainter::paintHighlightToken(bool bFillToEOL)
font.setItalic(mTokenAccu.style & FontStyle::fsItalic);
font.setStrikeOut(mTokenAccu.style & FontStyle::fsStrikeOut);
font.setUnderline(mTokenAccu.style & FontStyle::fsUnderline);
mPainter->setFont(font);
mLastGlyphAscii=true;
QFont nonAsciiFont = mEdit->fontForNonAscii();
nonAsciiFont.setBold(mTokenAccu.style & FontStyle::fsBold);
nonAsciiFont.setItalic(mTokenAccu.style & FontStyle::fsItalic);
@ -835,8 +867,6 @@ void QSynEditPainter::paintLines()
int nFold;
QString sFold;
mLastGlyphAscii = false;
// Initialize rcLine for drawing. Note that Top and Bottom are updated
// inside the loop. Get only the starting point for this.
rcLine = mClip;

View File

@ -91,8 +91,6 @@ private:
int mFirstRow, mLastRow, mLeft, mRight;
SynTokenAccu mTokenAccu;
bool mLastGlyphAscii;
static QSet<QString> OperatorGlyphs;
};