mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-157087 slow text rendering on OS X when ligatures are enabled
This commit is contained in:
+64
-5
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user