IDEA-157087 slow text rendering on OS X when ligatures are enabled

This commit is contained in:
Dmitry Batrak
2016-06-08 11:50:39 +03:00
parent c60e97cd08
commit 6225f7a4c8
2 changed files with 66 additions and 6 deletions
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.editor.impl.view;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.BitUtil;
import org.jetbrains.annotations.NotNull;
@@ -27,6 +28,7 @@ import java.awt.geom.Rectangle2D;
* GlyphVector-based text fragment. Used for non-Latin text or when ligatures are enabled
*/
class ComplexTextFragment extends TextFragment {
private static final Logger LOG = Logger.getInstance(ComplexTextFragment.class);
private static final double CLIP_MARGIN = 1e4;
@NotNull
@@ -90,18 +92,57 @@ class ComplexTextFragment extends TextFragment {
}
}
boolean isRtl() {
return BitUtil.isSet(myGlyphVector.getLayoutFlags(), GlyphVector.FLAG_RUN_RTL);
}
// Drawing a portion of glyph vector using clipping might be not very effective
// (we still pass all glyphs to the rendering code, and filtering by clipping might occur late in the processing,
// on OS X larger number of glyphs passed for processing is known to slow down rendering significantly).
// So we try to merge drawing of adjacent glyph vector fragments, if possible.
private static ComplexTextFragment lastFragment;
private static int lastStartColumn;
private static int lastEndColumn;
private static Color lastColor;
private static float lastStartX;
private static float lastEndX;
private static float lastY;
@SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
@Override
public void draw(Graphics2D g, float x, float y, int startColumn, int endColumn) {
assert startColumn >= 0;
assert startColumn >= 0;
assert endColumn <= myCharPositions.length;
assert startColumn < endColumn;
Color color = g.getColor();
assert color != null;
float newX = x - getX(startColumn) + getX(endColumn);
if (lastFragment == this && lastEndColumn == startColumn && lastEndX == x && lastY == y && color.equals(lastColor)) {
lastEndColumn = endColumn;
lastEndX = newX;
return;
}
flushDrawingCache(g);
lastFragment = this;
lastStartColumn = startColumn;
lastEndColumn = endColumn;
lastColor = color;
lastStartX = x;
lastEndX = newX;
lastY = y;
}
private void doDraw(Graphics2D g, float x, float y, int startColumn, int endColumn) {
updateStats(endColumn - startColumn, myCharPositions.length);
if (startColumn == 0 && endColumn == myCharPositions.length) {
g.drawGlyphVector(myGlyphVector, x, y);
}
else {
Shape savedClip = g.getClip();
float startX = x - getX(startColumn);
// We define clip region here assuming that glyphs do not extend further than CLIP_MARGIN pixels from baseline
// We define clip region here assuming that glyphs do not extend further than CLIP_MARGIN pixels from baseline
// vertically (both up and down) and horizontally (from the region defined by glyph vector's total advance)
double xMin = x - (startColumn == 0 ? CLIP_MARGIN : 0);
double xMax = startX + getX(endColumn) + (endColumn == myCharPositions.length ? CLIP_MARGIN : 0);
@@ -112,8 +153,26 @@ class ComplexTextFragment extends TextFragment {
g.setClip(savedClip);
}
}
boolean isRtl() {
return BitUtil.isSet(myGlyphVector.getLayoutFlags(), GlyphVector.FLAG_RUN_RTL);
public static void flushDrawingCache(Graphics2D g) {
if (lastFragment != null) {
g.setColor(lastColor);
lastFragment.doDraw(g, lastStartX, lastY, lastStartColumn, lastEndColumn);
lastFragment = null;
}
}
private static long ourDrawingCount;
private static long ourCharsProcessed;
private static long ourGlyphsProcessed;
private static void updateStats(int charCount, int glyphCount) {
if (!LOG.isDebugEnabled()) return;
ourCharsProcessed += charCount;
ourGlyphsProcessed += glyphCount;
if ((++ourDrawingCount) % 10000 == 0) {
LOG.debug("Text rendering stats: " + ourCharsProcessed + " chars, " + ourGlyphsProcessed + " glyps, ratio - " +
((float) ourGlyphsProcessed) / ourCharsProcessed);
}
}
}
@@ -35,7 +35,6 @@ import com.intellij.openapi.wm.impl.IdeBackgroundUtil;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.util.Processor;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import gnu.trove.TFloatArrayList;
@@ -400,6 +399,7 @@ class EditorPainter implements TextDrawingCallback {
});
visLinesIterator.advance();
}
ComplexTextFragment.flushDrawingCache(g);
}
private float paintLineLayoutWithEffect(Graphics2D g, LineLayout layout, float x, float y,
@@ -832,6 +832,7 @@ class EditorPainter implements TextDrawingCallback {
break;
}
}
ComplexTextFragment.flushDrawingCache(g);
}
}
}