/*******************************************************************************
* Mission Control Technologies, Copyright (c) 2009-2012, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* The MCT platform is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* MCT includes source code licensed under additional open source licenses. See
* the MCT Open Source Licenses file included with this distribution or the About
* MCT Licenses dialog available at runtime from the MCT Help menu for additional
* information.
*******************************************************************************/
package gov.nasa.arc.mct.graphics.brush;
import gov.nasa.arc.mct.graphics.clip.AxisClip;
import gov.nasa.arc.mct.graphics.state.StateSensitive;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import org.testng.Assert;
import org.testng.AssertJUnit;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
public class BrushTest {
private static final Shape ELLIPSE = new Ellipse2D.Double(0,0,1,1);
private static final int WIDTH = 300;
private static final int HEIGHT = 300;
private static final Color BACKGROUND = Color.black;
private static final Color FOREGROUND = Color.ORANGE;
private static final Color CONDITIONAL = Color.green;
/* For testing conditional fills */
private static final String CONDITION_A = "Condition A";
private static final String CONDITION_B = "Condition B";
private BufferedImage image;
private Graphics2D g2;
@BeforeTest
public void setupTest() {
image = new BufferedImage (WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g2 = image.createGraphics();
g2.setClip(0, 0, WIDTH, HEIGHT);
g2.setColor(BACKGROUND);
g2.fillRect(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight());
}
@Test
public void testFill() {
/* Ensure that a fill expands to fit its container */
Brush b = new Fill(FOREGROUND);
b.draw(ELLIPSE, g2, new Rectangle(0,0,WIDTH,HEIGHT));
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
/* Determine whether or not point is in expected circle */
int dx = (WIDTH/2) - x;
int dy = (HEIGHT/2) - y;
double d = Math.sqrt(dx*dx + dy*dy);
/* Check color. Note that for 149.0 <= d <= 151.0 we tolerate uncertainty */
if (d < 149.0) AssertJUnit.assertEquals(image.getRGB(x, y), FOREGROUND.getRGB());
if (d > 151.0) AssertJUnit.assertEquals(image.getRGB(x, y), BACKGROUND.getRGB());
}
}
}
@Test
public void testFillColor() {
Fill b = new Fill(FOREGROUND);
Assert.assertEquals(b.getColor(), FOREGROUND);
b.setColor(CONDITIONAL);
Assert.assertEquals(b.getColor(), CONDITIONAL);
}
@Test
public void testStateSensitiveColor() {
/* Basic fill only stores state if its Color does */
Fill b = new Fill(FOREGROUND);
b.setState("1.0");
Assert.assertEquals(b.getState(), null);
b.setColor(new StateColor());
b.setState("1.0");
Assert.assertEquals(b.getState(), "1.0");
b.setState("2.0");
Assert.assertEquals(b.getState(), "2.0");
}
@Test
public void testClippedFill() {
/* Ensure that a fill grows/shrinks appropriately to fit its container */
int[] axes = { AxisClip.X_AXIS, AxisClip.Y_AXIS };
int[] dirs = { AxisClip.INCREASING, AxisClip.DECREASING };
for (int axis : axes) {
for (int dir : dirs) {
Fill b = new ClippedFill(FOREGROUND, axis, dir);
b.setInterval(0.0, 1.0);
for (double state = 0.25; state <= 0.75; state += 0.25) {
b.setState(Double.toString(state));
Assert.assertEquals(Double.parseDouble(b.getState().toString()), state);
g2.setColor(BACKGROUND);
g2.fillRect(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight());
b.draw(ELLIPSE, g2, new Rectangle(0,0,WIDTH,HEIGHT));
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
/* Determine whether or not we expect to be clipped */
int i = (axis == AxisClip.X_AXIS) ? x : y;
int max = (axis == AxisClip.X_AXIS) ? WIDTH : HEIGHT;
if (dir == AxisClip.DECREASING) i = max - i;
double expectedState = state * (double) max;
if (i > expectedState + 1) {
AssertJUnit.assertEquals(image.getRGB(x,y), BACKGROUND.getRGB());
} else if (i < expectedState - 1){
/* Determine whether or not point is in expected circle */
int dx = (WIDTH/2) - x;
int dy = (HEIGHT/2) - y;
double d = Math.sqrt(dx*dx + dy*dy);
/* Check color. Note that for 149.0 <= d <= 151.0 we tolerate uncertainty */
if (d < 149.0) AssertJUnit.assertEquals(image.getRGB(x, y), FOREGROUND.getRGB());
if (d > 151.0) AssertJUnit.assertEquals(image.getRGB(x, y), BACKGROUND.getRGB());
}
}
}
}
/* Should also clamp to minimum/maximum */
b.setState(Double.toString(1.5));
Assert.assertEquals(Double.parseDouble(b.getState().toString()), 1.0);
b.setState(Double.toString(-0.5));
Assert.assertEquals(Double.parseDouble(b.getState().toString()), 0.0);
}
}
}
@Test
public void testScalingFill() {
/* Ensure that a fill scales appropriately to fit its container */
Fill b = new ScalingFill(FOREGROUND);
b.setInterval(0.0, 1.0);
for (double state = 0.25; state <= 0.75; state += 0.25) {
b.setState(Double.toString(state));
Assert.assertEquals(Double.parseDouble(b.getState().toString()), state);
g2.setColor(BACKGROUND);
g2.fillRect(image.getMinX(), image.getMinY(), image.getWidth(), image.getHeight());
b.draw(ELLIPSE, g2, new Rectangle(0,0,WIDTH,HEIGHT));
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
/* Determine whether or not we expect to be clipped */
double expectedRadius = state * (double) WIDTH / 2;
/* Determine whether or not point is in expected circle */
int dx = (WIDTH/2) - x;
int dy = (HEIGHT/2) - y;
double d = Math.sqrt(dx*dx + dy*dy);
/* Check color. Note that for 149.0 <= d <= 151.0 we tolerate uncertainty */
if (d < expectedRadius - 1) AssertJUnit.assertEquals(image.getRGB(x, y), FOREGROUND.getRGB());
if (d > expectedRadius + 1) AssertJUnit.assertEquals(image.getRGB(x, y), BACKGROUND.getRGB());
}
}
}
/* Should also clamp to minimum/maximum */
b.setState(Double.toString(1.5));
Assert.assertEquals(Double.parseDouble(b.getState().toString()), 1.0);
b.setState(Double.toString(-0.5));
Assert.assertEquals(Double.parseDouble(b.getState().toString()), 0.0);
}
@Test
public void testConditionalFill() {
/* Ensure that conditional fills correspond to enumerated states */
ConditionalBrush a = new ConditionalBrush(new Fill(FOREGROUND), CONDITION_A);
ConditionalBrush b = new ConditionalBrush(new Fill(CONDITIONAL), CONDITION_B);
String[] conditions = { CONDITION_A, CONDITION_B, CONDITION_A, CONDITION_B };
AssertJUnit.assertTrue(a instanceof StateSensitive);
AssertJUnit.assertTrue(b instanceof StateSensitive);
for (String condition : conditions) {
a.setState(condition);
b.setState(condition);
a.draw(ELLIPSE, g2, new Rectangle(0,0,WIDTH,HEIGHT));
b.draw(ELLIPSE, g2, new Rectangle(0,0,WIDTH,HEIGHT));
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
/* Determine whether or not point is in expected circle */
int dx = (WIDTH/2) - x;
int dy = (HEIGHT/2) - y;
double d = Math.sqrt(dx*dx + dy*dy);
Color expected = (condition == CONDITION_A) ? FOREGROUND : CONDITIONAL;
/* Check color. Note that for 149.0 <= d <= 151.0 we tolerate uncertainty */
if (d < 149.0) AssertJUnit.assertEquals(image.getRGB(x, y), expected.getRGB());
if (d > 151.0) AssertJUnit.assertEquals(image.getRGB(x, y), BACKGROUND.getRGB());
}
}
}
}
private class StateColor extends Color implements StateSensitive {
private static final long serialVersionUID = -1060487969568536392L;
private Object storedState = null;
public StateColor() {
super(0,0,0);
}
@Override
public void setState(Object state) {
storedState = state;
}
@Override
public Object getState() {
return storedState;
}
@Override
public void setInterval(Object minimum, Object maximum) {
}
}
}