mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-83645 Editor: Correct '`' (backtick) symbol drawing inside the editor
1. Checking if a font contains invalid glyphs on font info initialisation; 2. Ending painting iteration after the faulty glyphs (if any);
This commit is contained in:
@@ -73,6 +73,8 @@ import org.picocontainer.MutablePicoContainer;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -2628,6 +2628,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
int myCount = 0;
|
||||
@NotNull final FontInfo myFontType;
|
||||
final boolean myHasBreakSymbols;
|
||||
final int spaceWidth;
|
||||
|
||||
@Nullable private char[] myLastData;
|
||||
@@ -2635,6 +2636,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
private CachedFontContent(@NotNull FontInfo fontInfo) {
|
||||
myFontType = fontInfo;
|
||||
spaceWidth = fontInfo.charWidth(' ', myEditorComponent);
|
||||
myHasBreakSymbols = fontInfo.hasGlyphsToBreakDrawingIteration();
|
||||
}
|
||||
|
||||
private void flushContent(@NotNull Graphics g) {
|
||||
@@ -2666,7 +2668,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
final int lastCount = count - 1;
|
||||
final Color lastColor = color[lastCount];
|
||||
if (_data == myLastData && _start == ends[lastCount] && (_color == null || lastColor == null || _color.equals(lastColor))
|
||||
&& _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */)
|
||||
&& _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */
|
||||
&& (!myHasBreakSymbols || !myFontType.getSymbolsToBreakDrawingIteration().contains(_data[ends[lastCount] - 1])))
|
||||
{
|
||||
ends[lastCount] = _end;
|
||||
if (lastColor == null) color[lastCount] = _color;
|
||||
@@ -3054,6 +3057,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
myForceRefreshFont = true;
|
||||
}
|
||||
endX += charWidth;
|
||||
|
||||
if (newFont.hasGlyphsToBreakDrawingIteration() && newFont.getSymbolsToBreakDrawingIteration().contains(c)) {
|
||||
drawCharsCached(g, text, start, j + 1, x, y, fontType, fontColor);
|
||||
x = endX;
|
||||
start = j + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(x < clip.x && endX < clip.x || x > clip.x + clip.width && endX > clip.x + clip.width)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2012 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,14 +17,21 @@ package com.intellij.openapi.editor.impl;
|
||||
|
||||
import gnu.trove.TIntHashSet;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.GlyphVector;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class FontInfo {
|
||||
|
||||
private final TIntHashSet mySymbolsToBreakDrawingIteration = new TIntHashSet();
|
||||
|
||||
private final String myFamilyName;
|
||||
private final Font myFont;
|
||||
private final int mySize;
|
||||
@@ -32,12 +39,63 @@ public class FontInfo {
|
||||
private final TIntHashSet mySafeCharacters = new TIntHashSet();
|
||||
private FontMetrics myFontMetrics = null;
|
||||
private final int[] charWidth = new int[128];
|
||||
private final boolean myHasGlyphsToBreakDrawingIteration;
|
||||
|
||||
public FontInfo(final String familyName, final int size, @JdkConstants.FontStyle int style) {
|
||||
myFamilyName = familyName;
|
||||
mySize = size;
|
||||
myStyle = style;
|
||||
myFont = new Font(familyName, style, size);
|
||||
|
||||
parseProblemGlyphs();
|
||||
myHasGlyphsToBreakDrawingIteration = !mySymbolsToBreakDrawingIteration.isEmpty();
|
||||
}
|
||||
|
||||
private void parseProblemGlyphs() {
|
||||
BufferedImage buffer = new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
|
||||
final Graphics graphics = buffer.getGraphics();
|
||||
if (!(graphics instanceof Graphics2D)) {
|
||||
return;
|
||||
}
|
||||
final FontRenderContext context = ((Graphics2D)graphics).getFontRenderContext();
|
||||
char[] charBuffer = new char[1];
|
||||
for (char c = 0; c < 128; c++) {
|
||||
if (!myFont.canDisplay(c)) {
|
||||
continue;
|
||||
}
|
||||
charBuffer[0] = c;
|
||||
final GlyphVector vector = myFont.createGlyphVector(context, charBuffer);
|
||||
final float y = vector.getGlyphMetrics(0).getAdvanceY();
|
||||
if (Math.round(y) != 0) {
|
||||
mySymbolsToBreakDrawingIteration.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We've experienced a problem that particular symbols from particular font are represented really weird
|
||||
* by the IJ editor (IDEA-83645).
|
||||
* <p/>
|
||||
* Eventually it was found out that outline font glyphs can have a 'y advance', i.e. instruction on how the subsequent
|
||||
* glyphs location should be adjusted after painting the current glyph. In terms of java that means that such a problem
|
||||
* glyph should be the last symbol at the {@link Graphics#drawChars(char[], int, int, int, int) text drawing iteration}.
|
||||
* <p/>
|
||||
* Hopefully, such glyphs are exceptions from the normal processing, so, this method allows to answer whether a font
|
||||
* {@link #getFont() referenced} by the current object has such a glyph.
|
||||
*
|
||||
* @return true if the {@link #getFont() target font} has problem glyphs; <code>false</code> otherwise
|
||||
*/
|
||||
public boolean hasGlyphsToBreakDrawingIteration() {
|
||||
return myHasGlyphsToBreakDrawingIteration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return unicode symbols which glyphs {@link #hasGlyphsToBreakDrawingIteration() have problems}
|
||||
* at the {@link #getFont() target font}.
|
||||
*/
|
||||
@NotNull
|
||||
public TIntHashSet getSymbolsToBreakDrawingIteration() {
|
||||
return mySymbolsToBreakDrawingIteration;
|
||||
}
|
||||
|
||||
public boolean canDisplay(char c) {
|
||||
|
||||
Reference in New Issue
Block a user