Bug 562442: [RGraphic] Fix calculation of font metrics on Linux
Change-Id: Ief8d22e4aa534bbd3eca773e05f6aea2959393ff
diff --git a/eclient/org.eclipse.statet.rj.eclient.graphics/src/org/eclipse/statet/internal/rj/eclient/graphics/FontManager.java b/eclient/org.eclipse.statet.rj.eclient.graphics/src/org/eclipse/statet/internal/rj/eclient/graphics/FontManager.java
index 2725bd6..4d56ccb 100644
--- a/eclient/org.eclipse.statet.rj.eclient.graphics/src/org/eclipse/statet/internal/rj/eclient/graphics/FontManager.java
+++ b/eclient/org.eclipse.statet.rj.eclient.graphics/src/org/eclipse/statet/internal/rj/eclient/graphics/FontManager.java
@@ -14,6 +14,7 @@
package org.eclipse.statet.internal.rj.eclient.graphics;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -27,7 +28,11 @@
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.widgets.Display;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+@NonNullByDefault
public class FontManager {
private static final int[] R2SWT_STYLE= new int[] {
@@ -43,6 +48,8 @@
private static final double HR_FACTOR= HR_FONTSIZE;
private static final int HR_MIN_FONTSIZE= HR_FONTSIZE / 2;
+ private static final int[] EMPTY_INT_ARRY= new int[0];
+
private static final class FontInstance {
@@ -58,7 +65,7 @@
private double ascentUp= Integer.MIN_VALUE;
private double ascentLow= Integer.MIN_VALUE;
- private int[] charAbove255;
+ private int[] charAbove255= EMPTY_INT_ARRY;
private double[] charMetrics= UNINITIALIZED;
private double[] strWidth= UNINITIALIZED;
@@ -86,27 +93,24 @@
else if (ch <= 255) {
return ch;
}
- else if (this.charAbove255 == null){
- this.charAbove255= new int[256];
- this.charAbove255[0]= ch;
- return 256 + 0;
- }
else {
- for (int i= 0; i < this.charAbove255.length; i++) {
- final int c= this.charAbove255[i];
- if (c == 0) {
- this.charAbove255[i]= c;
+ int[] charAbove255= this.charAbove255;
+ int i= 0;
+ for (; i < charAbove255.length; i++) {
+ final int c= charAbove255[i];
+ if (c == ch) {
return 256 + i;
}
- else if (c == ch) {
+ if (c == 0) {
+ charAbove255[i]= c;
return 256 + i;
}
}
- final int[] newChar= new int[this.charAbove255.length + 256];
- System.arraycopy(this.charAbove255, 0, newChar, 0, this.charAbove255.length);
- newChar[this.charAbove255.length]= ch;
- this.charAbove255= newChar;
- return this.charAbove255.length - 256;
+ // i == charAbove255.length
+ charAbove255= Arrays.copyOf(charAbove255, i + 256);
+ this.charAbove255= charAbove255;
+ charAbove255[i]= ch;
+ return 256 + i;
}
}
@@ -123,11 +127,12 @@
private final Image image;
private final int imageWidth;
private final int imageHeigth;
- private final int imagePixelBytes;
+ private final int imagePixelBWidth;
+ private final int imagePixelBIndex;
private final int imageLineBytes;
private final byte imageBlankData;
- private ImageData imageData;
+ private @Nullable ImageData imageData;
public TestGC(final Device device) {
@@ -153,10 +158,13 @@
this.font= null;
clearImage();
- this.imageData= this.image.getImageData();
- this.imageLineBytes= this.imageData.bytesPerLine;
- this.imagePixelBytes= Math.max(this.imageData.bytesPerLine / this.imageData.width, 1);
- this.imageBlankData= this.imageData.data[0];
+ final var imageData= this.image.getImageData();
+ this.imageLineBytes= imageData.bytesPerLine;
+ this.imagePixelBWidth= Math.max(imageData.bytesPerLine / imageData.width, 1);
+ this.imagePixelBIndex= (imageData.palette.isDirect) ?
+ this.imagePixelBWidth - 1 + imageData.palette.redShift / 8 :
+ 0;
+ this.imageBlankData= imageData.data[this.imagePixelBIndex];
}
@@ -165,8 +173,8 @@
this.font= font;
this.testGC.setFont(font.swtFont);
// }
- if (this.font.baseLine == 0) {
- this.font.init(this.testGC);
+ if (font.baseLine == 0) {
+ font.init(this.testGC);
this.testGC.setFont(font.swtFont); // E-Bug #319125
}
}
@@ -184,31 +192,38 @@
this.imageData= null;
}
+ private ImageData getImageData() {
+ var imageData= this.imageData;
+ if (imageData == null) {
+ imageData= this.image.getImageData();
+ this.imageData= imageData;
+ }
+ return imageData;
+ }
+
private void drawText(final String txt) {
this.testGC.drawString(txt, 0, 0, true);
}
public int findFirstLine() {
- if (this.imageData == null) {
- this.imageData= this.image.getImageData();
- }
- final byte[] data= this.imageData.data;
- for (int i= 0; i < data.length; i+= this.imagePixelBytes) {
- if (data[i] != this.imageBlankData) {
- return (i / this.imageLineBytes);
+ final var imageData= getImageData();
+ final byte[] data= imageData.data;
+ for (int index= this.imagePixelBIndex;
+ index < data.length; index+= this.imagePixelBWidth) {
+ if (data[index] != this.imageBlankData) {
+ return (index / this.imageLineBytes);
}
}
return -1;
}
public int findLastLine() {
- if (this.imageData == null) {
- this.imageData= this.image.getImageData();
- }
- final byte[] data= this.imageData.data;
- for (int i= data.length - this.imagePixelBytes; i >= 0; i-= this.imagePixelBytes) {
- if (data[i] != this.imageBlankData) {
- return (i / this.imageLineBytes);
+ final var imageData= getImageData();
+ final byte[] data= imageData.data;
+ for (int index= data.length - this.imagePixelBWidth + this.imagePixelBIndex;
+ index >= 0; index-= this.imagePixelBWidth) {
+ if (data[index] != this.imageBlankData) {
+ return (index / this.imageLineBytes);
}
}
return -1;
@@ -253,7 +268,8 @@
private FontInstance get(final int style, final int size) {
FontInstance[] styleFonts= this.fonts[style];
if (styleFonts == null) {
- this.fonts[style]= styleFonts= new FontInstance[4];
+ styleFonts= new FontInstance[8];
+ this.fonts[style]= styleFonts;
}
int idx;
if (size == HR_FONTSIZE) {
@@ -274,17 +290,19 @@
}
}
if (idx >= styleFonts.length) {
- this.fonts[style]= new FontInstance[styleFonts.length+4];
- System.arraycopy(styleFonts, 0, this.fonts[style], 0, styleFonts.length);
- styleFonts= this.fonts[style];
+ styleFonts= Arrays.copyOf(styleFonts, styleFonts.length + 8);
+ this.fonts[style]= styleFonts;
}
}
- if (styleFonts[idx] == null) {
+
+ FontInstance font= styleFonts[idx];
+ if (font == null) {
final FontData fontData= new FontData(this.name, size, R2SWT_STYLE[style]);
- styleFonts[idx]= new FontInstance(size,
- new Font(FontManager.this.display, fontData));
+ font= new FontInstance(size,
+ new Font(FontManager.this.display, fontData) );
+ styleFonts[idx]= font;
}
- return styleFonts[idx];
+ return font;
}
public synchronized Font getSWTFont(final int style, final int size) {
@@ -514,7 +532,7 @@
private final Display display;
private final Object testGCLock= new Object();
- private TestGC testGC;
+ private @Nullable TestGC testGC;
private boolean disposed;
private final Map<String, FontFamily> fontFamilies= new HashMap<>();
@@ -540,17 +558,19 @@
}
protected final TestGC getTestGC() {
- if (this.testGC == null) {
- this.display.syncExec(new Runnable() {
- @Override
- public void run() {
- if (!FontManager.this.disposed) {
- FontManager.this.testGC= new TestGC(FontManager.this.display);
- }
+ TestGC testGC= this.testGC;
+ if (testGC == null) {
+ this.display.syncExec(() -> {
+ if (!this.disposed) {
+ this.testGC= new TestGC(this.display);
}
});
+ testGC= this.testGC;
+ if (testGC == null) {
+ throw new RuntimeException("disposed");
+ }
}
- return this.testGC;
+ return testGC;
}
@@ -561,9 +581,10 @@
}
this.fontFamilies.clear();
- if (this.testGC != null) {
- this.testGC.dispose();
+ final var testGC= this.testGC;
+ if (testGC != null) {
this.testGC= null;
+ testGC.dispose();
}
}