diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java index 40531f53318c..4d035cd990fb 100644 --- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java +++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java @@ -830,18 +830,18 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co // 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()) { @@ -885,7 +885,7 @@ public class SimpleColoredComponent extends JComponent implements Accessible, Co 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; diff --git a/platform/platform-api/src/com/intellij/ui/paint/EffectPainter.java b/platform/platform-api/src/com/intellij/ui/paint/EffectPainter.java index 0b48426310c6..632edb25cf58 100644 --- a/platform/platform-api/src/com/intellij/ui/paint/EffectPainter.java +++ b/platform/platform-api/src/com/intellij/ui/paint/EffectPainter.java @@ -15,7 +15,6 @@ */ 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; @@ -24,6 +23,7 @@ import com.intellij.util.ui.UIUtil; 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; @@ -31,7 +31,7 @@ import java.util.concurrent.ConcurrentHashMap; /** * @author Sergey.Malenkov */ -public enum EffectPainter implements RegionPainter { +public enum EffectPainter implements RegionPainter { /** * @see com.intellij.openapi.editor.markup.EffectType#LINE_UNDERSCORE */ @@ -44,17 +44,15 @@ public enum EffectPainter implements RegionPainter { * @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); } } }, @@ -70,18 +68,16 @@ public enum EffectPainter implements RegionPainter { * @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); } } }, @@ -97,16 +93,12 @@ public enum EffectPainter implements RegionPainter { * @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); } } }, @@ -122,16 +114,15 @@ public enum EffectPainter implements RegionPainter { * @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); } } }, @@ -147,13 +138,21 @@ public enum EffectPainter implements RegionPainter { * @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); + } } } }; @@ -162,16 +161,28 @@ public enum EffectPainter implements RegionPainter { 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) { @@ -180,6 +191,10 @@ public enum EffectPainter implements RegionPainter { 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; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 870585cb01dc..83bea60533a6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -2456,21 +2456,26 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } 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)); } } } @@ -3568,6 +3573,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (effectColor != null) { final Color savedColor = g.getColor(); + g.setColor(effectColor); // myBorderEffect.flushIfCantProlong(g, this, effectType, effectColor); int xEnd = x; @@ -3583,25 +3589,26 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } 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; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java index 61ba33408d26..986bdac24bb5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorPainter.java @@ -431,26 +431,30 @@ class EditorPainter implements TextDrawingCallback { } 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); } } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 03d437856f27..3a1526a70026 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -830,6 +830,8 @@ ide.text.effect.new=true 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