diff options
author | Markus Keller | 2017-05-08 16:01:00 +0000 |
---|---|---|
committer | Markus Keller | 2017-05-08 16:01:00 +0000 |
commit | b128cfb79dcaa0c963a0db03afc0b124fdc5860a (patch) | |
tree | 1fd5a8ff95bcf6099e93038770c9ad624a1505de | |
parent | 215e0dc0221f3d88ffabede6eb7b08358c324f18 (diff) | |
download | eclipse.platform.text-b128cfb79dcaa0c963a0db03afc0b124fdc5860a.tar.gz eclipse.platform.text-b128cfb79dcaa0c963a0db03afc0b124fdc5860a.tar.xz eclipse.platform.text-b128cfb79dcaa0c963a0db03afc0b124fdc5860a.zip |
Bug 516293: [hidpi][cocoa] Blurry line number ruler on retina displayI20170510-2000I20170510-0800I20170509-2000I20170509-1300I20170509-1100I20170509-0945I20170509-0800I20170508-2000
4 files changed, 174 insertions, 23 deletions
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/revisions/RevisionPainter.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/revisions/RevisionPainter.java index 34cdcaaabb4..50a257aa4c1 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/revisions/RevisionPainter.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/revisions/RevisionPainter.java @@ -588,6 +588,11 @@ public final class RevisionPainter { * @since 3.3 */ private int fLastWidth= -1; + /** + * The zoom level for the current painting operation. Workaround for bug 516293. + * @since 3.12 + */ + private int fZoom= 100; /** * Creates a new revision painter for a vertical ruler column. @@ -658,6 +663,20 @@ public final class RevisionPainter { } /** + * Sets the zoom level for the current painting operation. Workaround for bug 516293. + * + * @param zoom the zoom to set + * @since 3.12 + */ + public void setZoom(int zoom) { + fZoom= zoom; + } + + private int autoScaleUp(int value) { + return value * fZoom / 100; + } + + /** * Delegates the painting of the quick diff colors to this painter. The painter will draw the * color boxes onto the passed {@link GC} for all model (document) lines in * <code>visibleModelLines</code>. @@ -1058,7 +1077,7 @@ public final class RevisionPainter { int y1= fWidget.getLinePixel(range.getStartLine()); int y2= fWidget.getLinePixel(range.getStartLine() + range.getNumberOfLines()); - return new Rectangle(0, y1, getWidth(), y2 - y1 - 1); + return new Rectangle(0, autoScaleUp(y1), autoScaleUp(getWidth()), autoScaleUp(y2 - y1 - 1)); } /** diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/source/DiffPainter.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/source/DiffPainter.java index 53c82fe958d..33a6fea6471 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/source/DiffPainter.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/source/DiffPainter.java @@ -82,6 +82,11 @@ public final class DiffPainter { private final AnnotationListener fAnnotationListener= new AnnotationListener(); /** The shared color provider, possibly <code>null</code>. */ private final ISharedTextColors fSharedColors; + /** + * The zoom level for the current painting operation. Workaround for bug 516293. + * @since 3.12 + */ + private int fZoom= 100; /** * Creates a new diff painter for a vertical ruler column. @@ -135,6 +140,20 @@ public final class DiffPainter { } /** + * Sets the zoom level for the current painting operation. Workaround for bug 516293. + * + * @param zoom the zoom to set + * @since 3.12 + */ + public void setZoom(int zoom) { + fZoom= zoom; + } + + private int autoScaleUp(int value) { + return value * fZoom / 100; + } + + /** * Delegates the painting of the quick diff colors to this painter. The painter will draw the * color boxes onto the passed {@link GC} for all model (document) lines in * <code>visibleModelLines</code>. @@ -226,7 +245,7 @@ public final class DiffPainter { // draw background color if special if (hasSpecialColor(info)) { gc.setBackground(getColor(info)); - gc.fillRectangle(0, y, width, lineHeight); + gc.fillRectangle(0, autoScaleUp(y), autoScaleUp(width), autoScaleUp(lineHeight)); } /* Deletion Indicator: Simply a horizontal line */ @@ -234,10 +253,11 @@ public final class DiffPainter { int delBelow= info.getRemovedLinesBelow(); if (delBefore > 0 || delBelow > 0) { gc.setForeground(deletionColor); + gc.setLineWidth(autoScaleUp(1)); if (delBefore > 0) - gc.drawLine(0, y, width, y); + gc.drawLine(0, autoScaleUp(y), autoScaleUp(width), autoScaleUp(y)); if (delBelow > 0) - gc.drawLine(0, y + lineHeight - 1, width, y + lineHeight - 1); + gc.drawLine(0, autoScaleUp(y + lineHeight - 1), autoScaleUp(width), autoScaleUp(y + lineHeight - 1)); } } } diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberChangeRulerColumn.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberChangeRulerColumn.java index 5a41b5db854..a835305b421 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberChangeRulerColumn.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberChangeRulerColumn.java @@ -166,10 +166,13 @@ public class LineNumberChangeRulerColumn extends LineNumberRulerColumn implement void doPaint(GC gc, ILineRange visibleLines) { Color foreground= gc.getForeground(); if (visibleLines != null) { - if (fRevisionPainter.hasInformation()) + if (fRevisionPainter.hasInformation()) { + fRevisionPainter.setZoom(fZoom); fRevisionPainter.paint(gc, visibleLines); - else if (fDiffPainter.hasInformation()) // don't paint quick diff colors if revisions are painted + } else if (fDiffPainter.hasInformation()) { // don't paint quick diff colors if revisions are painted + fDiffPainter.setZoom(fZoom); fDiffPainter.paint(gc, visibleLines); + } } gc.setForeground(foreground); if (fShowNumbers || fCharacterDisplay) diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java index 00b895e49e7..81002167fee 100644 --- a/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java +++ b/org.eclipse.jface.text/src/org/eclipse/jface/text/source/LineNumberRulerColumn.java @@ -14,6 +14,7 @@ *******************************************************************************/ package org.eclipse.jface.text.source; +import java.lang.ref.WeakReference; import java.util.Arrays; import org.eclipse.swt.SWT; @@ -30,9 +31,12 @@ import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.graphics.FontMetrics; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.ImageDataProvider; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Canvas; @@ -41,6 +45,8 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.TypedListener; +import org.eclipse.jface.util.Util; + import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; @@ -62,6 +68,17 @@ import org.eclipse.jface.text.TextEvent; public class LineNumberRulerColumn implements IVerticalRulerColumn { /** + * <code>true</code> if we're on a Mac, where drawing on an Image currently only draws at 100% zoom level, + * which results in blurry line numbers on a Retina display. + * + * @see <a href="https://bugs.eclipse.org/516293">bug 516293</a> + * @since 3.6 + */ + private final boolean IS_MAC_BUG_516293= Util.isMac() + && !"false".equals(System.getProperty("LineNumberRulerColumn.retina.workaround")) //$NON-NLS-1$ //$NON-NLS-2$ + && internalSupportsZoomedPaint(); + + /** * Internal listener class. */ class InternalListener implements IViewportListener, ITextListener { @@ -420,6 +437,13 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { }; /* @since 3.2 */ private MouseHandler fMouseHandler; + /* + * Zoom level and cached font for the current painting operation. Workaround for bug 516293. + * @since 3.12 + */ + int fZoom= 100; + private WeakReference<Font> fLastFont; + private Font fLastZoomedFont; /** @@ -666,6 +690,12 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { fBuffer.dispose(); fBuffer= null; } + + if (fLastZoomedFont != null) { + fLastZoomedFont.dispose(); + fLastZoomedFont= null; + fLastFont= null; + } } /** @@ -687,31 +717,110 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { fBuffer= null; } } - if (fBuffer == null) - fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y); - GC gc= new GC(fBuffer); - gc.setFont(fCanvas.getFont()); - if (fForeground != null) - gc.setForeground(fForeground); + ILineRange visibleLines= JFaceTextUtil.getVisibleModelLines(fCachedTextViewer); + if (visibleLines == null) + return; - try { - gc.setBackground(getBackground(fCanvas.getDisplay())); - gc.fillRectangle(0, 0, size.x, size.y); + if (IS_MAC_BUG_516293) { + /* FIXME: Workaround (bug 516293): + * Relies on SWT implementation detail that GC drawing on macOS only draws at 100% zoom level. + * For higher zoom levels (200%), we manually scale the font and drawing coordinates, + * and then use getImageData(100) to extract the high-resolution image data. */ + fBuffer= new Image(fCanvas.getDisplay(), (ImageDataProvider) zoom -> { + fZoom = zoom; + internalSetZoom(zoom); + int width= size.x * zoom / 100; + int height= size.y * zoom / 100; + Image gcImage= new Image(fCanvas.getDisplay(), width, height); + + GC gc= new GC(gcImage); + Font font= fCanvas.getFont(); + if (zoom != 100) { + if (fLastFont != null && font == fLastFont.get()) { + font= fLastZoomedFont; + } else { + fLastFont= new WeakReference<>(font); + FontData fontData= font.getFontData()[0]; + fontData.setHeight(fontData.getHeight() * zoom / 100); + font= new Font(font.getDevice(), fontData); + fLastZoomedFont= font; + } + } + gc.setFont(font); + if (fForeground != null) + gc.setForeground(fForeground); + + try { + gc.setBackground(getBackground(fCanvas.getDisplay())); + gc.fillRectangle(0, 0, width, height); + + fScrollPos= fCachedTextWidget.getTopPixel(); + doPaint(gc, visibleLines); + } finally { + gc.dispose(); + fZoom= 100; + } - ILineRange visibleLines= JFaceTextUtil.getVisibleModelLines(fCachedTextViewer); - if (visibleLines == null) - return; - fScrollPos= fCachedTextWidget.getTopPixel(); - doPaint(gc, visibleLines); - } finally { - gc.dispose(); + ImageData imageData= gcImage.getImageData(100); + gcImage.dispose(); + return imageData; + }); + + } else { + if (fBuffer == null) + fBuffer= new Image(fCanvas.getDisplay(), size.x, size.y); + + GC gc= new GC(fBuffer); + gc.setFont(fCanvas.getFont()); + if (fForeground != null) + gc.setForeground(fForeground); + + try { + gc.setBackground(getBackground(fCanvas.getDisplay())); + gc.fillRectangle(0, 0, size.x, size.y); + + fScrollPos= fCachedTextWidget.getTopPixel(); + doPaint(gc, visibleLines); + } finally { + gc.dispose(); + } } dest.drawImage(fBuffer, 0, 0); } /** + * This method is not API and it is expected to disappear in Eclipse 4.8. + * Subclasses that want to take advantage of the unsupported workaround for bug 516258 + * can re-implement this method and return true. + * + * @return true iff this class supports the workaround for bug 516258 + * + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + * @since 3.12 + */ + protected boolean internalSupportsZoomedPaint() { + return getClass().getPackage().equals(LineNumberChangeRulerColumn.class.getPackage()); + } + + /** + * This method is not API and it is expected to disappear in Eclipse 4.8. + * Subclasses that want to take advantage of the unsupported workaround for bug 516258 + * can override this method and store the given zoom level for later use. + * + * @param zoom the zoom level to use for drawing operations + * + * @nooverride This method is not intended to be re-implemented or extended by clients. + * @noreference This method is not intended to be referenced by clients. + * @since 3.12 + */ + protected void internalSetZoom(int zoom) { + // callback for subclasses + } + + /** * Returns the view port height in lines. * * @return the view port height in lines @@ -848,7 +957,7 @@ public class LineNumberRulerColumn implements IVerticalRulerColumn { } int indentation= fIndentation[index]; int baselineBias= getBaselineBias(gc, widgetLine); - gc.drawString(s, indentation, y + baselineBias, true); + gc.drawString(s, indentation * fZoom / 100, (y + baselineBias) * fZoom / 100, true); } /** |