Compare commits

...

1 Commits

Author SHA1 Message Date
Alexey Ushakov
e309845093 JBR-1624 Fonts rendering is broken in the 2019.2 EAP (Fira Code)
Screen rendering tests in progress
2019-06-25 01:55:17 +03:00
8 changed files with 364 additions and 141 deletions

2
jb/project/java-gradle/.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,2 @@
# Default ignored files
/workspace.xml

View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

6
jb/project/java-gradle/.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/../../.." vcs="Git" />
</component>
</project>

View File

@@ -82,6 +82,7 @@ test {
// Enable Java2D logging (https://confluence.jetbrains.com/display/JRE/Java2D+Rendering+Logging)
// systemProperty "sun.java2d.trace", "log"
// systemProperty "sun.java2d.debugfonts", "warn"
// systemProperty "sun.java2d.trace", "log,pimpl"
outputs.upToDateWhen { false }

View File

@@ -24,42 +24,26 @@
package performance.rendering;
import org.junit.Test;
import util.Renderer;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.QuadCurve2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
public class RenderPerfTest {
private final static int N = 1000;
private final static float WIDTH = 800;
private final static float HEIGHT = 800;
private final static float R = 25;
private final static int BW = 50;
private final static int BH = 50;
private final static int COUNT = 300;
private final static int DELAY = 10;
private final static int RESOLUTION = 5;
private final static int COLOR_TOLERANCE = 10;
interface Renderable {
void render(Graphics2D g2d);
void update();
}
static class Particles {
private float[] bx;
private float[] by;
@@ -384,113 +368,7 @@ public class RenderPerfTest {
}
}
class PerfMeter {
private int frame = 0;
private JPanel panel;
private long time;
private double execTime = 0;
private Color expColor = Color.RED;
AtomicBoolean waiting = new AtomicBoolean(false);
double exec(final Renderable renderable) throws Exception {
final CountDownLatch latch = new CountDownLatch(COUNT);
final CountDownLatch latchFrame = new CountDownLatch(1);
final JFrame f = new JFrame();
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
latchFrame.countDown();
}
});
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
panel = new JPanel()
{
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
time = System.nanoTime();
Graphics2D g2d = (Graphics2D) g;
renderable.render(g2d);
g2d.setColor(expColor);
g.fillRect(0, 0, BW, BH);
}
};
panel.setPreferredSize(new Dimension((int)(WIDTH + BW), (int)(HEIGHT + BH)));
panel.setBackground(Color.BLACK);
f.add(panel);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
});
Robot robot = new Robot();
Timer timer = new Timer(DELAY, e -> {
if (waiting.compareAndSet(false, true)) {
Color c = robot.getPixelColor(
panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW / 2,
panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BW / 2);
if (isAlmostEqual(c, Color.BLUE)) {
expColor = Color.RED;
} else {
expColor = Color.BLUE;
}
renderable.update();
panel.getParent().repaint();
} else {
while (!isAlmostEqual(
robot.getPixelColor(
panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW/2,
panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BH/2),
expColor))
{
try {
Thread.sleep(RESOLUTION);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
time = System.nanoTime() - time;
execTime += time;
frame++;
waiting.set(false);
}
latch.countDown();
});
timer.start();
latch.await();
SwingUtilities.invokeAndWait(() -> {
timer.stop();
f.setVisible(false);
f.dispose();
});
latchFrame.await();
return 1e9/(execTime / frame);
}
private boolean isAlmostEqual(Color c1, Color c2) {
return Math.abs(c1.getRed() - c2.getRed()) < COLOR_TOLERANCE ||
Math.abs(c1.getGreen() - c2.getGreen()) < COLOR_TOLERANCE ||
Math.abs(c1.getBlue() - c2.getBlue()) < COLOR_TOLERANCE;
}
}
private static final Particles balls = new Particles(N, R, BW, BH, WIDTH, HEIGHT);
private static final Particles balls = new Particles(N, R, 0, 0, Renderer.WIDTH, Renderer.HEIGHT);
private static final ParticleRenderer flatRenderer = new FlatParticleRenderer(N, R);
private static final ParticleRenderer flatOvalRotRenderer = new FlatOvalRotParticleRenderer(N, R);
private static final ParticleRenderer flatBoxRenderer = new FlatBoxParticleRenderer(N, R);
@@ -520,7 +398,7 @@ public class RenderPerfTest {
@Test
public void testFlatBubbles() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.Renderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, flatRenderer);
@@ -530,6 +408,11 @@ public class RenderPerfTest {
public void update() {
balls.update();
}
@Override
public void screenShot(BufferedImage result) {
System.err.println();
}
});
report("FlatOval", fps);
@@ -538,7 +421,7 @@ public class RenderPerfTest {
@Test
public void testFlatBoxBubbles() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, flatBoxRenderer);
@@ -556,7 +439,7 @@ public class RenderPerfTest {
@Test
public void testImgBubbles() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, imgRenderer);
@@ -574,7 +457,7 @@ public class RenderPerfTest {
@Test
public void testFlatBoxRotBubbles() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, flatBoxRotRenderer);
@@ -592,7 +475,7 @@ public class RenderPerfTest {
@Test
public void testFlatOvalRotBubbles() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, flatOvalRotRenderer);
@@ -610,7 +493,7 @@ public class RenderPerfTest {
@Test
public void testLinGradOvalRotBubbles() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, linGradOvalRotRenderer);
@@ -629,7 +512,7 @@ public class RenderPerfTest {
@Test
public void testWiredBubbles() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, wiredRenderer);
@@ -647,7 +530,7 @@ public class RenderPerfTest {
@Test
public void testWiredBoxBubbles() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, wiredBoxRenderer);
@@ -665,7 +548,7 @@ public class RenderPerfTest {
@Test
public void testLines() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, segRenderer);
@@ -683,7 +566,7 @@ public class RenderPerfTest {
@Test
public void testFlatQuad() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, flatQuadRenderer);
@@ -701,7 +584,7 @@ public class RenderPerfTest {
@Test
public void testWiredQuad() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, wiredQuadRenderer);
@@ -719,7 +602,7 @@ public class RenderPerfTest {
@Test
public void testTextBubblesNoAA() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, textRendererNoAA);
@@ -737,7 +620,7 @@ public class RenderPerfTest {
@Test
public void testTextBubblesLCD() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, textRendererLCD);
@@ -755,7 +638,7 @@ public class RenderPerfTest {
@Test
public void testTextBubblesGray() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, textRendererGray);
@@ -773,7 +656,7 @@ public class RenderPerfTest {
@Test
public void testWhiteTextBubblesNoAA() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, whiteTextRendererNoAA);
@@ -791,7 +674,7 @@ public class RenderPerfTest {
@Test
public void testWhiteTextBubblesLCD() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new util.Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, whiteTextRendererLCD);
@@ -809,7 +692,7 @@ public class RenderPerfTest {
@Test
public void testWhiteTextBubblesGray() throws Exception {
double fps = (new PerfMeter()).exec(new Renderable() {
double fps = (new Renderer(COUNT)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
balls.render(g2d, whiteTextRendererGray);

View File

@@ -0,0 +1,37 @@
package quality.text;
import org.junit.Assert;
import org.junit.Test;
import quality.util.RenderUtil;
import util.Renderer;
import java.awt.*;
import java.awt.image.BufferedImage;
public class FiraCodeScrTest {
@Test
public void testRenderText() throws Exception {
String [] testResult = new String[] {null};
(new util.Renderer(2, 300, 30, true)).exec(new Renderer.DefaultRenderable() {
@Override
public void render(Graphics2D g2d) {
g2d.setColor(Color.WHITE);
Font f = new Font("Fira Code", Font.PLAIN, 12);
g2d.setFont(f);
g2d.drawString("The quick brown fox jumps over the lazy dog", 0, 15);
}
@Override
public void screenShot(BufferedImage result) {
try {
RenderUtil.checkImage(result, "text", "firacode.png");
} catch (Exception e) {
testResult[0] = e.getMessage();
}
}
});
if (testResult[0] != null) Assert.fail(testResult[0]);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,170 @@
package util;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
public class Renderer {
public final static int WIDTH = 800;
public final static int HEIGHT = 800;
public final static int BW = 50;
public final static int BH = 50;
private final static int RESOLUTION = 5;
private final static int COLOR_TOLERANCE = 10;
private final static int DELAY = 10;
private int frame = 0;
private final int count;
private final int width;
private final int height;
private final boolean capture;
private JPanel panel;
private long time;
private double execTime = 0;
private Color expColor = Color.RED;
AtomicBoolean waiting = new AtomicBoolean(false);
public Renderer(int count) {
this(count, WIDTH, HEIGHT, false);
}
public Renderer(int count, int width, int height, boolean capture) {
this.count = count;
this.width = width;
this.height = height;
this.capture = capture;
}
public double exec(final Renderable renderable) throws Exception {
final CountDownLatch latch = new CountDownLatch(count);
final CountDownLatch latchFrame = new CountDownLatch(1);
final JFrame f = new JFrame();
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosed(WindowEvent e) {
latchFrame.countDown();
}
});
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
panel = new JPanel()
{
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
time = System.nanoTime();
Graphics2D g2d = (Graphics2D) g;
g2d.translate(BW, BH);
renderable.render(g2d);
g2d.translate(-BW, -BH);
g2d.setColor(expColor);
g.fillRect(0, 0, BW, BH);
}
};
panel.setPreferredSize(new Dimension(width + BW, height + BH));
panel.setBackground(Color.BLACK);
f.add(panel);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
}
});
Robot robot = new Robot();
Timer timer = new Timer(DELAY, e -> {
if (waiting.compareAndSet(false, true)) {
Color c = robot.getPixelColor(
panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW / 2,
panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BH / 2);
if (isAlmostEqual(c, Color.BLUE)) {
expColor = Color.RED;
} else {
expColor = Color.BLUE;
}
if (capture) {
renderable.screenShot(robot.createScreenCapture(
new Rectangle(
panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW,
panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BH,
width, height)));
}
renderable.update();
panel.getParent().repaint();
} else {
while (!isAlmostEqual(
robot.getPixelColor(
panel.getTopLevelAncestor().getX() + panel.getTopLevelAncestor().getInsets().left + BW/2,
panel.getTopLevelAncestor().getY() + panel.getTopLevelAncestor().getInsets().top + BH/2),
expColor))
{
try {
Thread.sleep(RESOLUTION);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
time = System.nanoTime() - time;
execTime += time;
frame++;
waiting.set(false);
}
latch.countDown();
});
timer.start();
latch.await();
SwingUtilities.invokeAndWait(() -> {
timer.stop();
f.setVisible(false);
f.dispose();
});
latchFrame.await();
return 1e9/(execTime / frame);
}
private boolean isAlmostEqual(Color c1, Color c2) {
return Math.abs(c1.getRed() - c2.getRed()) < COLOR_TOLERANCE ||
Math.abs(c1.getGreen() - c2.getGreen()) < COLOR_TOLERANCE ||
Math.abs(c1.getBlue() - c2.getBlue()) < COLOR_TOLERANCE;
}
public interface Renderable {
void render(Graphics2D g2d);
void update();
void screenShot(BufferedImage result);
}
public static class DefaultRenderable implements Renderable {
@Override
public void render(Graphics2D g2d) {
}
@Override
public void update() {
}
@Override
public void screenShot(BufferedImage result) {
}
}
}