// 1. Strikeout effect
if (attributes.isStrikeout() && !attributes.isSearchMatch()) {
- EffectPainter.STRIKE_THROUGH.paint(g, offset, textBaseline, fragmentWidth, getCharHeight(g), null);
+ EffectPainter.STRIKE_THROUGH.paint(g, offset, textBaseline, fragmentWidth, getCharHeight(g), font);
}
// 2. Waved effect
if (attributes.isWaved()) {
if (attributes.getWaveColor() != null) {
g.setColor(attributes.getWaveColor());
}
- EffectPainter.WAVE_UNDERSCORE.paint(g, offset, textBaseline + 1, fragmentWidth, Math.max(2, metrics.getDescent()), null);
+ EffectPainter.WAVE_UNDERSCORE.paint(g, offset, textBaseline + 1, fragmentWidth, Math.max(2, metrics.getDescent()), font);
}
// 3. Underline
if (attributes.isUnderline()) {
- EffectPainter.LINE_UNDERSCORE.paint(g, offset, textBaseline, fragmentWidth, metrics.getDescent(), null);
+ EffectPainter.LINE_UNDERSCORE.paint(g, offset, textBaseline, fragmentWidth, metrics.getDescent(), font);
}
// 4. Bold Dotted Line
if (attributes.isBoldDottedLine()) {
g.drawString(text, x1, baseline);
if (((SimpleTextAttributes)info[5]).isStrikeout()) {
- EffectPainter.STRIKE_THROUGH.paint(g, x1, baseline, x2 - x1, getCharHeight(g), null);
+ EffectPainter.STRIKE_THROUGH.paint(g, x1, baseline, x2 - x1, getCharHeight(g), g.getFont());
}
}
return offset;
*/
package com.intellij.ui.paint;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.util.JBHiDPIScaledImage;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.WavePainter;
import java.awt.*;
+import java.awt.font.LineMetrics;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author Sergey.Malenkov
*/
-public enum EffectPainter implements RegionPainter<Paint> {
+public enum EffectPainter implements RegionPainter<Font> {
/**
* @see com.intellij.openapi.editor.markup.EffectType#LINE_UNDERSCORE
*/
* @param y text baseline
* @param width text width
* @param height available space under text
- * @param paint optional color patterns
+ * @param font optional font to calculate line metrics
*/
@Override
- public void paint(Graphics2D g, int x, int y, int width, int height, Paint paint) {
+ public void paint(Graphics2D g, int x, int y, int width, int height, Font font) {
if (!Registry.is("ide.text.effect.new")) {
- if (paint != null) g.setPaint(paint);
g.drawLine(x, y + 1, x + width, y + 1);
}
else if (width > 0 && height > 0) {
- if (paint != null) g.setPaint(paint);
- drawLineUnderscore(g, x, y, width, height, 1, this);
+ drawLineUnderscore(g, x, y, width, height, font, 1, this);
}
}
},
* @param y text baseline
* @param width text width
* @param height available space under text
- * @param paint optional color patterns
+ * @param font optional font to calculate line metrics
*/
@Override
- public void paint(Graphics2D g, int x, int y, int width, int height, Paint paint) {
+ public void paint(Graphics2D g, int x, int y, int width, int height, Font font) {
if (!Registry.is("ide.text.effect.new")) {
- if (paint != null) g.setPaint(paint);
int h = JBUI.scale(Registry.intValue("editor.bold.underline.height", 2));
g.fillRect(x, y, width, h);
}
else if (width > 0 && height > 0) {
- if (paint != null) g.setPaint(paint);
- drawLineUnderscore(g, x, y, width, height, 2, this);
+ drawLineUnderscore(g, x, y, width, height, font, 2, this);
}
}
},
* @param y text baseline
* @param width text width
* @param height available space under text
- * @param paint optional color patterns
+ * @param font optional font to calculate line metrics
*/
@Override
- public void paint(Graphics2D g, int x, int y, int width, int height, Paint paint) {
- if (!Registry.is("ide.text.effect.new")) {
- UIUtil.drawBoldDottedLine(g, x, x + width, SystemInfo.isMac ? y : y + 1, g.getColor(), (Color)paint, false);
- }
- else if (width > 0 && height > 0) {
- if (paint != null) g.setPaint(paint);
- drawLineUnderscore(g, x, y, width, height, 2, this);
+ public void paint(Graphics2D g, int x, int y, int width, int height, Font font) {
+ if (width > 0 && height > 0) {
+ drawLineUnderscore(g, x, y, width, height, font, 2, this);
}
}
},
* @param y text baseline
* @param width text width
* @param height available space under text
- * @param paint optional color patterns
+ * @param font optional font to calculate line metrics
*/
@Override
- public void paint(Graphics2D g, int x, int y, int width, int height, Paint paint) {
+ public void paint(Graphics2D g, int x, int y, int width, int height, Font font) {
if (!Registry.is("ide.text.effect.new")) {
- if (paint != null) g.setPaint(paint);
WavePainter.forColor(g.getColor()).paint(g, x, x + width, y + height);
}
else if (width > 0 && height > 0) {
- Cached.WAVE_UNDERSCORE.paint(g, x, y, width, height, paint);
+ Cached.WAVE_UNDERSCORE.paint(g, x, y, width, height, null);
}
}
},
* @param y text baseline
* @param width text width
* @param height text height
- * @param paint optional color patterns
+ * @param font optional font to calculate line metrics
*/
@Override
- public void paint(Graphics2D g, int x, int y, int width, int height, Paint paint) {
+ public void paint(Graphics2D g, int x, int y, int width, int height, Font font) {
if (width > 0 && height > 0) {
- if (paint != null) g.setPaint(paint);
- drawLineCentered(g, x, y - height, width, height, 1, this);
+ if (!Registry.is("ide.text.effect.new.metrics")) {
+ drawLineCentered(g, x, y - height, width, height, 1, this);
+ }
+ else {
+ if (font == null) font = g.getFont();
+ LineMetrics metrics = font.getLineMetrics("", g.getFontRenderContext());
+ int offset = (int)(0.5 - metrics.getStrikethroughOffset());
+ int thickness = Math.max(1, (int)(0.5 + metrics.getStrikethroughThickness()));
+ drawLine(g, x, y - offset, width, thickness, this);
+ }
}
}
};
return height > 7 && Registry.is("ide.text.effect.new.scale") ? height >> 1 : 3;
}
- private static void drawLineUnderscore(Graphics2D g, int x, int y, int width, int height, int thickness, EffectPainter painter) {
- if (height > 3) {
- int max = getMaxHeight(height);
- y += height - max;
- height = max;
- if (thickness > 1 && height > 3) {
- thickness = JBUI.scale(thickness);
+ private static void drawLineUnderscore(Graphics2D g, int x, int y, int width, int height, Font font, int thickness,
+ EffectPainter painter) {
+ if (width > 0 && height > 0) {
+ if (Registry.is("ide.text.effect.new.metrics")) {
+ if (font == null) font = g.getFont();
+ LineMetrics metrics = font.getLineMetrics("", g.getFontRenderContext());
+ int offset = Math.max(1, (int)(0.5 + metrics.getUnderlineOffset()));
+ thickness = Math.max(thickness, (int)(0.5 + thickness * metrics.getUnderlineThickness()));
+ drawLine(g, x, y + offset, width, thickness, painter);
+ }
+ else {
+ if (height > 3) {
+ int max = getMaxHeight(height);
+ y += height - max;
+ height = max;
+ if (thickness > 1 && height > 3) {
+ thickness = JBUI.scale(thickness);
+ }
+ }
+ drawLineCentered(g, x, y, width, height, thickness, painter);
}
}
- drawLineCentered(g, x, y, width, height, thickness, painter);
}
private static void drawLineCentered(Graphics2D g, int x, int y, int width, int height, int thickness, EffectPainter painter) {
y += offset - (offset >> 1);
height = thickness;
}
+ drawLine(g, x, y, width, height, painter);
+ }
+
+ private static void drawLine(Graphics2D g, int x, int y, int width, int height, EffectPainter painter) {
if (painter == BOLD_DOTTED_UNDERSCORE) {
int dx = (x % height + height) % height;
int w = width + dx;
}
if (attributes != null && attributes.getEffectColor() != null) {
int y = visibleLineToY(visibleStartLine) + getAscent() + 1;
+ g.setColor(attributes.getEffectColor());
if (attributes.getEffectType() == EffectType.WAVE_UNDERSCORE) {
- EffectPainter.WAVE_UNDERSCORE.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getDescent(), attributes.getEffectColor());
+ EffectPainter.WAVE_UNDERSCORE.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getDescent(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (attributes.getEffectType() == EffectType.BOLD_DOTTED_LINE) {
- g.setColor(getBackgroundColor(attributes));
- EffectPainter.BOLD_DOTTED_UNDERSCORE.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getDescent(), attributes.getEffectColor());
+ EffectPainter.BOLD_DOTTED_UNDERSCORE.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getDescent(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (attributes.getEffectType() == EffectType.STRIKEOUT) {
- EffectPainter.STRIKE_THROUGH.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getCharHeight(), attributes.getEffectColor());
+ EffectPainter.STRIKE_THROUGH.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getCharHeight(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (attributes.getEffectType() == EffectType.BOLD_LINE_UNDERSCORE) {
- EffectPainter.BOLD_LINE_UNDERSCORE.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getDescent(), attributes.getEffectColor());
+ EffectPainter.BOLD_LINE_UNDERSCORE.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getDescent(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (attributes.getEffectType() != EffectType.BOXED) {
- EffectPainter.LINE_UNDERSCORE.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getDescent(), attributes.getEffectColor());
+ EffectPainter.LINE_UNDERSCORE.paint((Graphics2D)g, end.x, y - 1, charWidth - 1, getDescent(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
}
}
if (effectColor != null) {
final Color savedColor = g.getColor();
+ g.setColor(effectColor);
// myBorderEffect.flushIfCantProlong(g, this, effectType, effectColor);
int xEnd = x;
}
if (effectType == EffectType.LINE_UNDERSCORE) {
- EffectPainter.LINE_UNDERSCORE.paint((Graphics2D)g, xStart, y, xEnd - xStart, getDescent(), effectColor);
- g.setColor(savedColor);
+ EffectPainter.LINE_UNDERSCORE.paint((Graphics2D)g, xStart, y, xEnd - xStart, getDescent(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (effectType == EffectType.BOLD_LINE_UNDERSCORE) {
- EffectPainter.BOLD_LINE_UNDERSCORE.paint((Graphics2D)g, xStart, y, xEnd - xStart, getDescent(), effectColor);
- g.setColor(savedColor);
+ EffectPainter.BOLD_LINE_UNDERSCORE.paint((Graphics2D)g, xStart, y, xEnd - xStart, getDescent(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (effectType == EffectType.STRIKEOUT) {
- EffectPainter.STRIKE_THROUGH.paint((Graphics2D)g, xStart, y, xEnd - xStart, getCharHeight(), effectColor);
- g.setColor(savedColor);
+ EffectPainter.STRIKE_THROUGH.paint((Graphics2D)g, xStart, y, xEnd - xStart, getCharHeight(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (effectType == EffectType.WAVE_UNDERSCORE) {
- EffectPainter.WAVE_UNDERSCORE.paint((Graphics2D)g, xStart, y, xEnd - xStart, getDescent(), effectColor);
- g.setColor(savedColor);
+ EffectPainter.WAVE_UNDERSCORE.paint((Graphics2D)g, xStart, y, xEnd - xStart, getDescent(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (effectType == EffectType.BOLD_DOTTED_LINE) {
- g.setColor(getBackgroundColor());
- EffectPainter.BOLD_DOTTED_UNDERSCORE.paint((Graphics2D)g, xStart, y, xEnd - xStart, getDescent(), effectColor);
+ EffectPainter.BOLD_DOTTED_UNDERSCORE.paint((Graphics2D)g, xStart, y, xEnd - xStart, getDescent(),
+ getColorsScheme().getFont(EditorFontType.PLAIN));
}
+ g.setColor(savedColor);
}
return x;
}
private void paintTextEffect(Graphics2D g, float xFrom, float xTo, int y, Color effectColor, EffectType effectType, boolean allowBorder) {
+ g.setColor(effectColor);
int xStart = (int)xFrom;
int xEnd = (int)xTo;
if (effectType == EffectType.LINE_UNDERSCORE) {
- EffectPainter.LINE_UNDERSCORE.paint(g, xStart, y, xEnd - xStart, myView.getDescent(), effectColor);
+ EffectPainter.LINE_UNDERSCORE.paint(g, xStart, y, xEnd - xStart, myView.getDescent(),
+ myEditor.getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (effectType == EffectType.BOLD_LINE_UNDERSCORE) {
- EffectPainter.BOLD_LINE_UNDERSCORE.paint(g, xStart, y, xEnd - xStart, myView.getDescent(), effectColor);
+ EffectPainter.BOLD_LINE_UNDERSCORE.paint(g, xStart, y, xEnd - xStart, myView.getDescent(),
+ myEditor.getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (effectType == EffectType.STRIKEOUT) {
- EffectPainter.STRIKE_THROUGH.paint(g, xStart, y, xEnd - xStart, myView.getCharHeight(), effectColor);
+ EffectPainter.STRIKE_THROUGH.paint(g, xStart, y, xEnd - xStart, myView.getCharHeight(),
+ myEditor.getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (effectType == EffectType.WAVE_UNDERSCORE) {
- EffectPainter.WAVE_UNDERSCORE.paint(g, xStart, y, xEnd - xStart, myView.getDescent(), effectColor);
+ EffectPainter.WAVE_UNDERSCORE.paint(g, xStart, y, xEnd - xStart, myView.getDescent(),
+ myEditor.getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (effectType == EffectType.BOLD_DOTTED_LINE) {
- g.setColor(myEditor.getBackgroundColor());
- EffectPainter.BOLD_DOTTED_UNDERSCORE.paint(g, xStart, y, xEnd - xStart, myView.getDescent(), effectColor);
+ EffectPainter.BOLD_DOTTED_UNDERSCORE.paint(g, xStart, y, xEnd - xStart, myView.getDescent(),
+ myEditor.getColorsScheme().getFont(EditorFontType.PLAIN));
}
else if (allowBorder && (effectType == EffectType.BOXED || effectType == EffectType.ROUNDED_BOX)) {
- g.setColor(effectColor);
drawSimpleBorder(g, xStart, xEnd - 1, y - myView.getAscent(), effectType == EffectType.ROUNDED_BOX);
}
}
ide.text.effect.new.description=Enables new effect painter for text
ide.text.effect.new.scale=true
ide.text.effect.new.scale.description=Enables scalable effect painter for text
+ide.text.effect.new.metrics=true
+ide.text.effect.new.metrics.description=Use line metrics to calculate text offset in the effect painter
ide.intellij.laf.win10.ui=false
ide.intellij.laf.win10.ui.description=Enables Windows 10 look