aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorJana Fabrikova <[email protected]>2013-04-26 20:24:55 +0200
committerJana Fabrikova <[email protected]>2013-04-26 20:24:55 +0200
commit45751bceb7c3402d27402b24131dcebddac762cb (patch)
treefce1ffc527f40fdca54ff8e93d726287bb2f34f3 /tests
parent559dfa4f372f950bd6469e8647bad6798f0993cc (diff)
adding awtframework (without reproducers)
Diffstat (limited to 'tests')
-rw-r--r--tests/test-extensions/net/sourceforge/jnlp/awt/AWTFrameworkException.java66
-rw-r--r--tests/test-extensions/net/sourceforge/jnlp/awt/AWTHelper.java559
-rw-r--r--tests/test-extensions/net/sourceforge/jnlp/awt/awtactions/KeyboardActions.java111
-rw-r--r--tests/test-extensions/net/sourceforge/jnlp/awt/awtactions/MouseActions.java228
-rw-r--r--tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ComponentFinder.java107
-rw-r--r--tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ComponentNotFoundException.java65
-rw-r--r--tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ImageSeeker.java325
-rw-r--r--tests/test-extensions/net/sourceforge/jnlp/closinglisteners/RulesFolowingClosingListener.java4
8 files changed, 1465 insertions, 0 deletions
diff --git a/tests/test-extensions/net/sourceforge/jnlp/awt/AWTFrameworkException.java b/tests/test-extensions/net/sourceforge/jnlp/awt/AWTFrameworkException.java
new file mode 100644
index 0000000..13c0d45
--- /dev/null
+++ b/tests/test-extensions/net/sourceforge/jnlp/awt/AWTFrameworkException.java
@@ -0,0 +1,66 @@
+/* AWTFrameworkException.java
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package net.sourceforge.jnlp.awt;
+
+/**
+ * Class AWTFrameworkException is thrown in the AWTFramework
+ * whenever the framework encounters not enough data specified
+ * to perform an action (for example it is impossible to ascertain
+ * the position of an applet in the screenshot if the width or height
+ * of the applet is not known.
+ *
+ */
+
+public class AWTFrameworkException extends Exception {
+
+ public AWTFrameworkException() {
+ super();
+ }
+
+ public AWTFrameworkException(String s) {
+ super(s);
+ }
+
+ public AWTFrameworkException(String s, Throwable throwable) {
+ super(s, throwable);
+ }
+
+ public AWTFrameworkException(Throwable throwable) {
+ super(throwable);
+ }
+}
diff --git a/tests/test-extensions/net/sourceforge/jnlp/awt/AWTHelper.java b/tests/test-extensions/net/sourceforge/jnlp/awt/AWTHelper.java
new file mode 100644
index 0000000..fb53057
--- /dev/null
+++ b/tests/test-extensions/net/sourceforge/jnlp/awt/AWTHelper.java
@@ -0,0 +1,559 @@
+/* AWTHelper.java
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+package net.sourceforge.jnlp.awt;
+
+import java.awt.AWTException;
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.event.InputEvent;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+
+import net.sourceforge.jnlp.awt.awtactions.KeyboardActions;
+import net.sourceforge.jnlp.awt.awtactions.MouseActions;
+import net.sourceforge.jnlp.awt.imagesearch.ComponentFinder;
+import net.sourceforge.jnlp.awt.imagesearch.ComponentNotFoundException;
+import net.sourceforge.jnlp.awt.imagesearch.ImageSeeker;
+import net.sourceforge.jnlp.closinglisteners.Rule;
+import net.sourceforge.jnlp.closinglisteners.RulesFolowingClosingListener;
+
+public abstract class AWTHelper extends RulesFolowingClosingListener implements Runnable{
+
+ //attributes possibly set by user
+ private String initStr = "";
+ private Color appletColor;
+ private BufferedImage marker;
+ private Rectangle markerPosition;
+ private int appletHeight;
+ private int appletWidth;
+ private int tryKTimes = DEFAULT_K;
+
+ //other
+ protected StringBuilder sb = new StringBuilder();
+ private boolean actionStarted = false;
+ private Rectangle actionArea;
+ private BufferedImage screenshot;
+ private Robot robot;
+ private boolean appletFound = false;
+ private boolean initStrGiven = false; //impossible to find in the output if not given
+ private boolean appletColorGiven = false; //impossible to search for color difference if not given
+ private boolean markerGiven = false; //impossible to find the applet if marker not given
+ private boolean appletDimensionGiven = false;
+ private boolean screenshotTaken = false;
+ private int defaultWaitForApplet = 1000;
+
+ //default number of times the screen is captured and the applet is searched for
+ //in the screenshot
+ public static final int DEFAULT_K = 3;
+
+
+ //several constructors
+ /**
+ * the minimal constructor - use:
+ * - if we do not want to find the bounds of applet area first
+ * - searching for buttons and other components is then done in the whole
+ * screen, confusion with other icons on display is then possible
+ * - less effective, deprecated (better bound the area first)
+ */
+ @Deprecated
+ public AWTHelper() {
+ try {
+ this.robot = new Robot();
+ } catch (AWTException e) {
+ throw new RuntimeException("AWTHelper could not create its Robot instance.",e);
+ }
+ }
+
+ /**
+ * the minimal constructor with initStr - use:
+ * - we want to know from stdout that the applet (or sth else) is ready
+ * - if we do not want to find the bounds of applet area first
+ * - searching for buttons and other components is then done in the whole
+ * screen, confusion with other icons on display is then possible
+ * - less effective, deprecated (better bound the area first)
+ */
+ @Deprecated
+ public AWTHelper(String initStr){
+ this();
+
+ this.initStr = initStr;
+ this.initStrGiven = true;
+ }
+
+ /**
+ * the constructor with icon and its position in applet of given dimension
+ * use:
+ * - we want to find and activate the applet first
+ * - the search for applet will be done via searching for icon
+ * of given position(x,y,w,h) inside applet of given width and height
+ *
+ * @param icon marker by which the applet will be found
+ * @param iconPosition relatively to applet (including icon width and height)
+ * @param appletWidth
+ * @param appletHeight
+ */
+
+ public AWTHelper(BufferedImage icon, Rectangle iconPosition, int appletWidth, int appletHeight){
+ this();
+ this.marker = icon;
+ this.markerPosition = iconPosition;
+ this.markerGiven = true;
+
+ this.appletWidth = appletWidth;
+ this.appletHeight = appletHeight;
+ this.appletDimensionGiven = true;
+ }
+
+ public AWTHelper(String initString, BufferedImage icon, Rectangle iconPosition, int appletWidth, int appletHeight) throws AWTException{
+ this(icon, iconPosition, appletWidth, appletHeight);
+
+ this.initStr = initString;
+ this.initStrGiven = true;
+ }
+
+ /**
+ * the constructor with applet width and height only - use:
+ * - we want to find the applet by finding the default icon
+ * that is located in the upper left corner of applet
+ *
+ * @param appletWidth
+ * @param appletHeight
+ */
+ public AWTHelper(int appletWidth, int appletHeight){
+ this();
+ String test_server_dir_path = System.getProperty("test.server.dir");
+
+ try {
+ this.marker = ImageIO.read(new File(test_server_dir_path + "/marker.png"));
+ this.markerPosition = new Rectangle(0,0,marker.getWidth(),marker.getHeight());
+ this.markerGiven = true;
+ } catch (IOException e) {
+ throw new RuntimeException("AWTHelper could not read marker.png.",e);
+ }
+
+ this.appletWidth = appletWidth;
+ this.appletHeight = appletHeight;
+ this.appletDimensionGiven = true;
+ }
+
+ public AWTHelper(String initString, int appletWidth, int appletHeight){
+ this(appletWidth, appletHeight);
+ this.initStr = initString;
+ this.initStrGiven = true;
+ }
+
+ /**
+ * refers to AWTHelper functioning as RulesFolowingClosingListener
+ *
+ * @param strs array of strings to be added as contains rules
+ */
+ public void addClosingRulesFromStringArray(String [] strs){
+ for(String s : strs){
+ this.addContainsRule(s);
+ }
+ }
+
+ /**
+ * override of method charReaded (from RulesFolowingClosingListener)
+ *
+ * waiting for the applet, when applet is ready run action thread
+ * when all the wanted strings are in the stdout, applet can be closed
+ *
+ * @param ch
+ */
+ @Override
+ public void charReaded(char ch) {
+ sb.append(ch);
+ //is applet ready to start clicking?
+ if (initStrGiven && !actionStarted && appletIsReady(sb.toString())) {
+ try{
+ actionStarted = true;
+ this.findAndActivateApplet();
+ this.run();
+ } catch (ComponentNotFoundException e1) {
+ throw new RuntimeException("AWTHelper problems finding applet.",e1);
+ } catch (AWTFrameworkException e2){
+ throw new RuntimeException("AWTHelper problems with unset attributes.",e2);
+ }
+ }
+ //is all the wanted output in stdout?
+ super.charReaded(ch);
+ }
+
+ /**
+ * method runAWTHelper - we can call run and declared the action as started
+ * without finding out if initStr is in the output, if this method is
+ * called
+ *
+ */
+ public void runAWTHelper(){
+ actionStarted = true;
+ this.run();
+ }
+
+ /**
+ * implementation of AWTHelper should implement the run method
+ */
+ public abstract void run();
+
+
+ /**
+ * method getInitStrAsRule returns the initStr in the form
+ * of Contains rule that can be evaluated on a string
+ *
+ * @return
+ */
+ public Rule getInitStrAsRule(){
+ return new ContainsRule(this.initStr);
+ }
+
+ //boolean controls getters
+ protected boolean appletIsReady(String content) {
+ return (content.contains(initStr));
+ }
+
+ public boolean isActionStarted() {
+ return actionStarted;
+ }
+
+ public boolean isInitStrGiven(){
+ return initStrGiven;
+ }
+
+ public boolean isAppletColorGiven(){
+ return appletColorGiven;
+ }
+
+ public boolean isAppletDimensionGiven(){
+ return appletDimensionGiven;
+ }
+
+ public boolean isMarkerGiven(){
+ return markerGiven;
+ }
+
+ //setters
+ /**
+ * method setDefaultWaitForApplet sets the time (in ms) for which the method
+ * captureScreenAndFindApplet will wait (for the applet to load) before it
+ * gets the screenshot the default time is 1000ms
+ *
+ * @param defaultWaitForApplet
+ */
+ public void setDefaultWaitForApplet(int defaultWaitForApplet) {
+ this.defaultWaitForApplet = defaultWaitForApplet;
+ }
+
+ public void setTryKTimes(int tryKTimes) {
+ this.tryKTimes = tryKTimes;
+ }
+
+ public void setAppletColor(Color appletColor) {
+ this.appletColor = appletColor;
+ this.appletColorGiven = true;
+ }
+
+ public void setInitStr(String initStr) {
+ this.initStr = initStr;
+ this.initStrGiven = true;
+ }
+
+ public void setMarker(BufferedImage marker, Rectangle markerPosition) {
+ this.marker = marker;
+ this.markerPosition = markerPosition;
+ this.markerGiven = true;
+ }
+
+ public void setAppletDimension(int width, int height){
+ this.appletWidth = width;
+ this.appletHeight = height;
+ this.appletDimensionGiven = true;
+ }
+
+
+ //creating screenshots, searching for applet
+ /**
+ * method captureScreenAndFindAppletByIcon
+ * 1. checks that all needed attributes of AWTHelper are given
+ * (marker, its position and applet width and height)
+ * 2. captures screen,
+ * 3. finds the rectangle where applet is and saves it to the attribute
+ * actionArea
+ * 4. sets screenCapture indicator to true (after tryKTimes unsuccessfull
+ * tries an exception "ComponentNotFound" will be raised)
+ *
+ * @throws AWTException
+ * @throws ComponentNotFoundException
+ * @throws AWTFrameworkException
+ */
+ public void captureScreenAndFindAppletByIcon() throws ComponentNotFoundException, AWTFrameworkException {
+ if(!appletDimensionGiven || !markerGiven){
+ throw new AWTFrameworkException("AWTFramework cannot find applet without dimension or marker!");
+ }
+ captureScreenAndFindAppletByIconTryKTimes(marker, markerPosition, appletWidth, appletHeight, tryKTimes);
+ }
+
+ /**
+ ** method captureScreenAndFindAppletByIcon
+ * 1. captures screen,
+ * 2. finds the rectangle where applet is and saves it to the attribute
+ * actionArea
+ * 3. sets screenCapture indicator to true (after tryKTimes unsuccessfull
+ * tries an exception "ComponentNotFound" will be raised)
+ *
+ * @param icon
+ * @param iconPosition
+ * @param width
+ * @param height
+ * @param K
+ * @throws ComponentNotFoundException
+ * @throws AWTFrameworkException
+ */
+ public void captureScreenAndFindAppletByIconTryKTimes(BufferedImage icon, Rectangle iconPosition, int width, int height, int K) throws ComponentNotFoundException, AWTFrameworkException {
+
+ if(!markerGiven){
+ throw new AWTFrameworkException("AWTFramework cannot find applet without marker!");
+ }
+
+ int count = 0;
+ appletFound = false;
+ while ((count < K) && !appletFound) {
+ robot.delay(defaultWaitForApplet);
+ screenshot = robot.createScreenCapture( new Rectangle( Toolkit.getDefaultToolkit().getScreenSize() ) );
+ screenshotTaken = true;
+ actionArea = ComponentFinder.findWindowByIcon(icon, iconPosition, width, height, screenshot);
+ if (ImageSeeker.isRectangleValid(actionArea)) {
+ appletFound = true;
+ }
+ count++;
+ }
+
+ if (ImageSeeker.isRectangleValid(actionArea)) {
+ appletFound = true;
+ } else {
+ throw new ComponentNotFoundException("Applet not found in the screenshot!");
+ }
+
+ }
+
+ /**
+ * auxiliary method writeAppletScreen for writing Buffered image into png
+ *
+ * @param appletScreen
+ * @param filename
+ * @throws IOException
+ */
+ private void writeAppletScreen(BufferedImage appletScreen, String filename) throws IOException {// into png file
+ ImageIO.write(appletScreen, "png", new File(filename+".png"));
+ }
+
+
+ /**
+ * method findAndActivateApplet finds the applet by icon
+ * and clicks in the middle of applet area
+ *
+ * @throws ComponentNotFoundException (applet not found)
+ * @throws AWTFrameworkException
+ */
+ public void findAndActivateApplet() throws ComponentNotFoundException, AWTFrameworkException
+ {
+ captureScreenAndFindAppletByIcon();
+ clickInTheMiddleOfApplet();
+ }
+
+
+ //methods for clicking and typing
+ /**
+ * method clickInTheMiddleOfApplet focuses the applet by clicking in the
+ * middle of its location rectangle
+ */
+ public void clickInTheMiddleOfApplet() {
+ MouseActions.clickInside(this.actionArea, this.robot);
+ }
+
+ /**
+ * Method clickOnIconExact - click in the middle of a rectangle with
+ * given pattern (icon) using specified mouse key.
+ * If the applet has not been found yet, the search includes whole screen.
+ *
+ * @param icon
+ * @param mouseKey
+ * @throws ComponentNotFoundException
+ */
+ public void clickOnIconExact(BufferedImage icon, int mouseKey) throws ComponentNotFoundException{
+ Rectangle areaOfSearch;
+ if(!appletFound){//searching whole screen, less effective
+ areaOfSearch = new Rectangle(0, 0, this.screenshot.getWidth(), this.screenshot.getHeight());
+ }else{
+ areaOfSearch = this.actionArea;
+ }
+ Rectangle iconRectangle = ImageSeeker.findExactImage(icon, this.screenshot, areaOfSearch);
+
+ if (ImageSeeker.isRectangleValid(iconRectangle)) {
+ MouseActions.clickInside(mouseKey, iconRectangle, this.robot);
+ }else{
+ throw new ComponentNotFoundException("Exact icon not found!");
+ }
+ }
+
+ /**
+ * Method clickOnIconBlurred - click in the middle of a rectangle with
+ * given pattern (icon) using specified mouse key.
+ * If the applet has not been found yet, the search includes whole screen.
+ *
+ * @param icon
+ * @param mouseKey
+ * @param precision tolerated minimal correlation (see ImageSeeker methods)
+ * @throws ComponentNotFoundException
+ */
+ public void clickOnIconBlurred(BufferedImage icon, int mouseKey, double precision) throws ComponentNotFoundException{
+ Rectangle areaOfSearch;
+ if(!appletFound){//searching whole screen, less effective
+ areaOfSearch = new Rectangle(0, 0, this.screenshot.getWidth(), this.screenshot.getHeight());
+ }else{
+ areaOfSearch = this.actionArea;
+ }
+ Rectangle iconRectangle = ImageSeeker.findBlurredImage(icon, this.screenshot, precision, areaOfSearch);
+
+ if (ImageSeeker.isRectangleValid(iconRectangle)) {
+ MouseActions.clickInside(mouseKey, iconRectangle, this.robot);
+ }else{
+ throw new ComponentNotFoundException("Blurred icon not found!");
+ }
+ }
+
+ /**
+ * Method clickOnColoredRectangle - click in the middle of a rectangle with
+ * given color (appletColor must be specified as the background) using
+ * specified mouse key.
+ *
+ * @param c
+ * @param mouseKey
+ * @throws ComponentNotFoundException
+ * @throws AWTFrameworkException
+ *
+ */
+ public void clickOnColoredRectangle(Color c, int mouseKey) throws ComponentNotFoundException, AWTFrameworkException {
+ Rectangle buttonRectangle = findColoredRectangle(c);
+
+ if (ImageSeeker.isRectangleValid(buttonRectangle)) {
+ MouseActions.clickInside(mouseKey, buttonRectangle, this.robot);
+ }else{
+ throw new ComponentNotFoundException("Colored rectangle not found!");
+ }
+ }
+
+ public void moveToMiddleOfColoredRectangle(Color c) throws ComponentNotFoundException, AWTFrameworkException {
+
+ Rectangle buttonRectangle = findColoredRectangle(c);
+
+ if (ImageSeeker.isRectangleValid(buttonRectangle)) {
+ MouseActions.moveMouseToMiddle(buttonRectangle, this.robot);
+ }else{
+ throw new ComponentNotFoundException("Colored rectangle not found!");
+ }
+ }
+
+ public void moveOutsideColoredRectangle(Color c) throws ComponentNotFoundException, AWTFrameworkException {
+ Rectangle buttonRectangle = findColoredRectangle(c);
+
+ if (ImageSeeker.isRectangleValid(buttonRectangle)) {
+ MouseActions.moveMouseOutside(buttonRectangle, this.robot);
+ }else{
+ throw new ComponentNotFoundException("Colored rectangle not found!");
+ }
+ }
+
+ public void moveInsideColoredRectangle(Color c) throws ComponentNotFoundException, AWTFrameworkException {
+ Rectangle buttonRectangle = findColoredRectangle(c);
+
+ if (ImageSeeker.isRectangleValid(buttonRectangle)) {
+ MouseActions.moveInsideRectangle(buttonRectangle, this.robot);
+ }else{
+ throw new ComponentNotFoundException("Colored rectangle not found!");
+ }
+ }
+
+ public void dragFromColoredRectangle(Color c) throws ComponentNotFoundException, AWTFrameworkException {
+ Rectangle buttonRectangle = findColoredRectangle(c);
+
+ if (ImageSeeker.isRectangleValid(buttonRectangle)) {
+ MouseActions.dragFromRectangle(buttonRectangle, this.robot);
+ }else{
+ throw new ComponentNotFoundException("Colored rectangle not found!");
+ }
+ }
+
+ public Rectangle findColoredRectangle(Color c) throws AWTFrameworkException {
+ if(!appletColorGiven || !appletFound){
+ throw new AWTFrameworkException("AWTHelper could not search for colored rectangle, needs appletColor and applet position.");
+ }
+
+ Rectangle result;
+
+ int gap = 5;
+ result = ImageSeeker.findColoredAreaGap(this.screenshot, c, appletColor, this.actionArea.y, this.actionArea.y + this.actionArea.height, gap);
+
+ return result;
+ }
+
+ /**
+ * method writeText writes string containing small letters and numbers and
+ * spaces like the keyboard input (using KeyboardActions so delays are
+ * inserted)
+ *
+ * @param text
+ */
+ public void writeText(String text) {
+ KeyboardActions.writeText(this.robot, text);
+ }
+
+ /**
+ * method typeKey writes one key on the keyboard (again using
+ * KeyboardActions)
+ *
+ * @param key
+ */
+ public void typeKey(int key) {
+ KeyboardActions.typeKey(this.robot, key);
+ }
+}
diff --git a/tests/test-extensions/net/sourceforge/jnlp/awt/awtactions/KeyboardActions.java b/tests/test-extensions/net/sourceforge/jnlp/awt/awtactions/KeyboardActions.java
new file mode 100644
index 0000000..1841476
--- /dev/null
+++ b/tests/test-extensions/net/sourceforge/jnlp/awt/awtactions/KeyboardActions.java
@@ -0,0 +1,111 @@
+/* KeyboardActions.java
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+
+package net.sourceforge.jnlp.awt.awtactions;
+
+import java.awt.Robot;
+import java.awt.event.KeyEvent;
+
+public class KeyboardActions {
+
+ private static final int defaultDelay = 250;
+
+ /**
+ * method writeText for simulating typing the
+ * given String text by a user with delays
+ * allowed characters in the text: 0-9, a-z, the space
+ * between the keystrokes
+ *
+ * @param robot
+ * @param text
+ * @param delayMs
+ */
+ public static void writeText(Robot robot, String text, int delayMs){
+ for (int i = 0; i < text.length(); i++){
+ char c = text.charAt(i);
+ typeKey(robot, keyFromChar(c), delayMs);
+ }
+ }
+
+ public static void writeText(Robot robot, String text){
+ writeText(robot,text, defaultDelay);
+ }
+
+ /**
+ * method typeKey for pressing and releasing given key
+ * with a reasonable delay
+ *
+ * @param robot
+ * @param key
+ * @param delayMs
+ */
+
+ public static void typeKey(Robot robot, int key, int delayMs){
+ robot.delay(delayMs);
+ robot.keyPress(key);
+ robot.delay(delayMs);
+ robot.keyRelease(key);
+ }
+
+ public static void typeKey(Robot robot, int key){
+ typeKey(robot, key, defaultDelay);
+ }
+
+ /**
+ * method returning the KeyInput event int
+ * if the character is not from a-b, 0-9, the returned value is
+ * KeyEvent.VK_SPACE
+ *
+ * @param ch
+ * @return
+ */
+ public static int keyFromChar(char ch){
+ int key;
+
+ if( ('0' <= ch) && ('9' >= ch) ){
+ key = (int)(ch - '0') + KeyEvent.VK_0;
+ }else if( ( 'a' <= ch) && ('z' >= ch) ){
+ key = (int)(ch - 'a') + KeyEvent.VK_A;
+ }else{
+ key = KeyEvent.VK_SPACE;
+ }
+
+ return key;
+ }
+
+}
diff --git a/tests/test-extensions/net/sourceforge/jnlp/awt/awtactions/MouseActions.java b/tests/test-extensions/net/sourceforge/jnlp/awt/awtactions/MouseActions.java
new file mode 100644
index 0000000..dd68bb4
--- /dev/null
+++ b/tests/test-extensions/net/sourceforge/jnlp/awt/awtactions/MouseActions.java
@@ -0,0 +1,228 @@
+/* MouseActions.java
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+
+package net.sourceforge.jnlp.awt.awtactions;
+
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+
+/**
+ * class MouseActions
+ *
+ * static methods for manipulating the mouse via AWT robot
+ */
+public class MouseActions {
+ private static final int defaultDelay = 250;
+
+ /**
+ * method click presses and releases given mouse keys
+ * with reasonable delay before the event
+ *
+ * @param mouseKeyMask
+ * @param robot
+ * @param delayMs
+ */
+ public static void click(int mouseKeyMask, Robot robot, int delayMs){
+ robot.delay(delayMs);
+ robot.mousePress(mouseKeyMask);
+ robot.delay(delayMs);
+ robot.mouseRelease(mouseKeyMask);
+ }
+
+ public static void click(int mouseKeyMask, Robot robot){
+ robot.delay(defaultDelay);
+ robot.mousePress(mouseKeyMask);
+ robot.delay(defaultDelay);
+ robot.mouseRelease(mouseKeyMask);
+ }
+
+ /**
+ * method doubleClick presses and releases given mouse keys
+ * two times with reasonable delays
+ *
+ * @param mouseKeyMask
+ * @param robot
+ * @param delayMs
+ */
+
+ public static void doubleClick(int mouseKeyMask, Robot robot, int delayMs){
+ click(mouseKeyMask, robot, delayMs);
+ click(mouseKeyMask, robot, delayMs);
+ }
+
+ public static void doubleClick(int mouseKeyMask, Robot robot){
+ click(mouseKeyMask, robot, defaultDelay);
+ click(mouseKeyMask, robot, defaultDelay);
+ }
+
+ /**
+ * method drag presses the right mouse key,
+ * drags the mouse to a point, and releases the mouse key
+ * with reasonable delays
+ *
+ * @param xTo
+ * @param yTo
+ * @param robot
+ * @param delayMs
+ */
+ public static void drag(int xTo, int yTo, Robot robot, int delayMs){
+ robot.delay(delayMs);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.delay(delayMs);
+ robot.mouseMove(xTo, yTo);
+ }
+
+ public static void drag(int xTo, int yTo, Robot robot){
+ robot.delay(defaultDelay);
+ robot.mousePress(InputEvent.BUTTON1_MASK);
+ robot.delay(defaultDelay);
+ robot.mouseMove(xTo, yTo);
+ }
+
+ /**
+ * method dragFromRectangle clicks in the middle
+ * of the given rectangle and drags the mouse from the rectangle
+ * with reasonable delays
+ *
+ * @param rectangle
+ * @param robot
+ * @param delayMs
+ */
+
+ public static void dragFromRectangle(Rectangle rectangle, Robot robot, int delayMs){
+ int x1 = rectangle.x + rectangle.width/2;
+ int y1 = rectangle.y + rectangle.height/2;
+ int x2 = x1 + 2*rectangle.width;
+ int y2 = y1 + 2*rectangle.height;
+ robot.delay(delayMs);
+ robot.mouseMove(x1, y1);
+ drag(x2,y2, robot);
+ }
+
+ public static void dragFromRectangle(Rectangle rectangle, Robot robot){
+ dragFromRectangle(rectangle, robot, defaultDelay);
+ }
+
+ /**
+ * method moveInsideRectangle places the mouse in the middle
+ * of the given rectangle and moves the mouse inside the rectangle
+ * with reasonable delays
+ *
+ * @param rectangle
+ * @param robot
+ * @param delayMs
+ */
+
+ public static void moveInsideRectangle(Rectangle rectangle, Robot robot, int delayMs){
+ int x1 = rectangle.x + rectangle.width/2;
+ int y1 = rectangle.y + rectangle.height/2;
+ int x2 = x1 + rectangle.width/4;
+ int y2 = y1 + rectangle.height/4;
+ robot.delay(delayMs);
+ robot.mouseMove(x1, y1);
+ robot.delay(delayMs);
+ robot.mouseMove(x2, y2);
+ }
+
+ public static void moveInsideRectangle(Rectangle rectangle, Robot robot){
+ moveInsideRectangle(rectangle, robot, defaultDelay);
+ }
+
+ /**
+ *
+ * @param rectangle
+ * @param robot
+ * @param delayMs
+ */
+ public static void moveMouseToMiddle(Rectangle rectangle, Robot robot, int delayMs){
+ robot.delay(delayMs);
+ int x = rectangle.x + (rectangle.width/2);
+ int y = rectangle.y + (rectangle.height/2);
+ robot.mouseMove(x,y);
+ }
+
+ public static void moveMouseToMiddle(Rectangle rectangle, Robot robot){
+ moveMouseToMiddle(rectangle, robot, defaultDelay);
+ }
+
+ /**
+ *
+ * @param rectangle
+ * @param robot
+ * @param delayMs
+ */
+ public static void moveMouseOutside(Rectangle rectangle, Robot robot, int delayMs){
+ robot.delay(delayMs);
+ int x = rectangle.x + 2*rectangle.width;
+ int y = rectangle.y + 2*rectangle.height;
+ robot.mouseMove(x,y);
+ }
+
+ public static void moveMouseOutside(Rectangle rectangle, Robot robot){
+ moveMouseOutside(rectangle, robot, defaultDelay);
+ }
+
+
+ /**
+ * method clickInside moves the mouse in the middle point
+ * of a given rectangle and clicks with reasonable delay
+
+ *
+ * @param rectangle
+ * @param robot
+ * @param delayMs
+ */
+ public static void clickInside(int mouseKey, Rectangle rectangle, Robot robot, int delayMs){
+ moveMouseToMiddle(rectangle, robot, delayMs);
+ robot.delay(delayMs);
+ click(mouseKey, robot, delayMs);
+ }
+
+ public static void clickInside(int mouseKey, Rectangle rectangle, Robot robot){
+ clickInside(mouseKey, rectangle, robot, defaultDelay);
+ }
+
+ public static void clickInside(Rectangle rectangle, Robot robot, int delayMs){
+ clickInside(InputEvent.BUTTON1_MASK, rectangle, robot, delayMs);
+ }
+
+ public static void clickInside(Rectangle rectangle, Robot robot){
+ clickInside(rectangle, robot, defaultDelay);
+ }
+}
diff --git a/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ComponentFinder.java b/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ComponentFinder.java
new file mode 100644
index 0000000..e28e877
--- /dev/null
+++ b/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ComponentFinder.java
@@ -0,0 +1,107 @@
+/* ComponentFinder.java
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+
+package net.sourceforge.jnlp.awt.imagesearch;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+
+public class ComponentFinder {
+
+ /**
+ * method findColoredRectangle determines coordinates of a rectangle colored
+ * by rectangleColor surrounded by a neighbourhood of surroundingColor
+ *
+ * @param rectangleColor
+ * @param surroundingColor
+ * @param screenshot
+ * @return
+ */
+ public static Rectangle findColoredRectangle(Color rectangleColor, Color surroundingColor, BufferedImage screenshot) {
+
+ Rectangle r = ImageSeeker.findColoredAreaGap(screenshot, rectangleColor, surroundingColor, 0, screenshot.getHeight(), 0);
+ return r;
+ }
+
+ /**
+ * method findColoredRectangle determines coordinates of a rectangle colored
+ * by rectangleColor surrounded by a neighbourhood of surroundingColor with
+ * possible gap of several pixels
+ *
+ * @param rectangleColor
+ * @param surroundingColor
+ * @param screenshot
+ * @param gap
+ * @return
+ */
+ public static Rectangle findColoredRectangle(Color rectangleColor, Color surroundingColor, BufferedImage screenshot, int gap) {
+
+ Rectangle r = ImageSeeker.findColoredAreaGap(screenshot, rectangleColor, surroundingColor, 0, screenshot.getHeight(), gap);
+ return r;
+ }
+
+
+ /**
+ * method findWindowByIcon finds the application area assuming there is a
+ * given icon in given position on the application window
+ * (the left upper corner by default) the dimension of the window has to
+ * be given
+ *
+ * @param icon
+ * @param iconPosition
+ * @param appletWidth
+ * @param appletHeight
+ * @param screenshot
+ * @return Rectangle rectangle where the applet resides
+ */
+ public static Rectangle findWindowByIcon(BufferedImage icon, Rectangle iconPosition, int windowWidth, int windowHeight, BufferedImage screenshot) {
+ Rectangle r = ImageSeeker.findExactImage(icon, screenshot);
+ return windowPositionFromIconPosition(r, iconPosition, windowWidth, windowHeight);
+ }
+
+ public static Rectangle findWindowByIconBlurred(BufferedImage icon, Rectangle iconPosition, int windowWidth, int windowHeight, BufferedImage screenshot, double minCorrelation) {
+ Rectangle r = ImageSeeker.findBlurredImage(icon, screenshot, minCorrelation);
+ return windowPositionFromIconPosition(r, iconPosition, windowWidth, windowHeight);
+ }
+
+ public static Rectangle windowPositionFromIconPosition(Rectangle iconAbsolute, Rectangle iconRelative, int windowWidth, int windowHeight){
+ return new Rectangle( iconAbsolute.x - iconRelative.x, iconAbsolute.y - iconRelative.y,
+ windowWidth, windowHeight);
+ }
+}
diff --git a/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ComponentNotFoundException.java b/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ComponentNotFoundException.java
new file mode 100644
index 0000000..9187d6a
--- /dev/null
+++ b/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ComponentNotFoundException.java
@@ -0,0 +1,65 @@
+/* ComponentNotFoundException.java
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+package net.sourceforge.jnlp.awt.imagesearch;
+
+/**
+ * Class ComponentNotFoundException is thrown in the AWTFramework
+ * in such cases when a position of a component is needed for further
+ * action and the component is not found in the screenshot (for example
+ * a method should click on a button of given colour and the button
+ * is not found, then the method cannot perform its action and
+ * throws ComponentNotFoundException).
+ *
+ */
+public class ComponentNotFoundException extends Exception {
+
+ public ComponentNotFoundException() {
+ super();
+ }
+
+ public ComponentNotFoundException(String s) {
+ super(s);
+ }
+
+ public ComponentNotFoundException(String s, Throwable throwable) {
+ super(s, throwable);
+ }
+
+ public ComponentNotFoundException(Throwable throwable) {
+ super(throwable);
+ }
+}
diff --git a/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ImageSeeker.java b/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ImageSeeker.java
new file mode 100644
index 0000000..89e8c9c
--- /dev/null
+++ b/tests/test-extensions/net/sourceforge/jnlp/awt/imagesearch/ImageSeeker.java
@@ -0,0 +1,325 @@
+/* ImageSeeker.java
+Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+
+package net.sourceforge.jnlp.awt.imagesearch;
+
+import java.awt.Color;
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+
+
+
+public class ImageSeeker
+{
+ public static Rectangle findExactImage(BufferedImage marker, BufferedImage screen){
+ return findExactImage(marker, screen, new Rectangle(0,0,screen.getWidth(), screen.getHeight()));
+ }
+
+ public static Rectangle findExactImage(BufferedImage marker, BufferedImage screen, Rectangle actionArea){
+ Rectangle result = new Rectangle(0,0,0,0);
+ boolean found = false;
+ boolean ok = true;
+
+ for(int x = actionArea.x; (x < (actionArea.x + actionArea.width - marker.getWidth()) ) && !found; x++){
+ for(int y= actionArea.y; (y < (actionArea.y + actionArea.height - marker.getHeight()) ) && !found; y++){
+
+ for(int mx = 0; (mx < marker.getWidth()) && ok; mx++){
+ for(int my = 0; (my < marker.getHeight()) && ok; my++){
+ if(marker.getRGB(mx, my) != screen.getRGB(x+mx,y+my)){
+ ok = false;
+ }
+ }
+ }
+ if( ok ){
+ found = true;
+ result.x = x;
+ result.y = y;
+ result.height = marker.getHeight();
+ result.width = marker.getWidth();
+ }else{
+ ok = true;
+ }
+
+ }
+ }
+
+ return result;
+ }
+
+ public static Rectangle findBlurredImage(BufferedImage marker, BufferedImage testImage, double minCorrelation){
+ return findBlurredImage(marker, testImage, minCorrelation, new Rectangle(0,0,testImage.getWidth(), testImage.getHeight()));
+ }
+
+ public static Rectangle findBlurredImage(BufferedImage marker, BufferedImage testImage, double minCorrelation, Rectangle actionArea)
+ {
+ int maxX = actionArea.width - marker.getWidth() - 1;
+ int maxY = actionArea.height - marker.getHeight() - 1;
+ int markerMaxX = marker.getWidth();
+ int markerMaxY = marker.getHeight();
+
+ // it is much faster to work directly with color components stored as float values
+ float[][][] testImageArray = createArrayForOneColorComponent(actionArea);
+ float[][][] markerImageArray = createArrayForOneColorComponent(marker);
+
+ convertImageToFloatArray(testImage, testImageArray, actionArea);
+ convertImageToFloatArray(marker, markerImageArray);
+
+ int bestX = -1;
+ int bestY = -1;
+ double bestCorrelation = -1;
+
+ for (int yoffset = 0; yoffset < maxY; yoffset++ )
+ {
+ for (int xoffset = 0; xoffset < maxX; xoffset++)
+ {
+ double correlation = computeCorrelation(markerMaxX, markerMaxY, testImageArray, markerImageArray, yoffset, xoffset);
+ if (correlation > bestCorrelation)
+ {
+ bestCorrelation = correlation;
+ bestX = xoffset + actionArea.x;
+ bestY = yoffset + actionArea.y;
+ }
+ }
+ }
+ if(bestCorrelation > minCorrelation){
+ return new Rectangle(bestX, bestY, marker.getWidth(), marker.getHeight());
+ }else{
+ return new Rectangle(0,0,0,0);
+ }
+
+ }
+
+ /**
+ * Create three-dimensional array with the same size as tested image
+ * dimensions (last dimension is used for storing RGB components).
+ *
+ * @param testImage tested image
+ * @return newly created three-dimensional array
+ */
+ private static float[][][] createArrayForOneColorComponent(BufferedImage testImage)
+ {
+ return new float[testImage.getHeight()][testImage.getWidth()][3];
+ }
+
+ /**
+ * Create three-dimensional array with the same size as the given area
+ * dimensions (last dimension is used for storing RGB components).
+ *
+ * @param actionArea
+ * @return newly created three-dimensional array
+ */
+ private static float[][][] createArrayForOneColorComponent(Rectangle actionArea)
+ {
+ return new float[actionArea.height][actionArea.width][3];
+ }
+
+ /**
+ * Conversion from BufferedImage into three dimensional float arrays.
+ * It's much faster to work with float arrays even if it's memory ineficient.
+ *
+ * @param testImage tested image
+ * @param array array to fill
+ */
+ private static void convertImageToFloatArray(BufferedImage testImage, float[][][] array)
+ {
+ for (int y = 0; y < testImage.getHeight(); y++)
+ {
+ for (int x = 0; x < testImage.getWidth(); x++)
+ {
+ int c = testImage.getRGB(x, y);
+ // filter out alpha channel
+ c = c & 0xffffff;
+ array[y][x][0] = ((c >> 16) & 0xff) - 128f;
+ array[y][x][1] = ((c >> 8) & 0xff) - 128f;
+ array[y][x][2] = (c & 0xff) - 128f;
+ }
+ }
+ }
+
+ /**
+ * Conversion from BufferedImage into three dimensional float arrays.
+ * It's much faster to work with float arrays even if it's memory ineficient.
+ * This method converts only a given part of the image (actionArea)
+ *
+ * @param testImage tested image
+ * @param array array to fill
+ * @param actionArea rectangle part of the image to convert
+ */
+ private static void convertImageToFloatArray(BufferedImage testImage, float[][][] array, Rectangle actionArea)
+ {
+ for (int y = actionArea.y; y < (actionArea.height + actionArea.y); y++)
+ {
+ for (int x = actionArea.x; x < (actionArea.width + actionArea.x); x++)
+ {
+ int c = testImage.getRGB(x, y);
+ // filter out alpha channel
+ c = c & 0xffffff;
+ array[y - actionArea.y][x - actionArea.x][0] = ((c >> 16) & 0xff) - 128f;
+ array[y - actionArea.y][x - actionArea.x][1] = ((c >> 8) & 0xff) - 128f;
+ array[y - actionArea.y][x - actionArea.x][2] = (c & 0xff) - 128f;
+ }
+ }
+ }
+
+ /**
+ * Compute correlation for given two images and 2D offset.
+ *
+ * @param maxX
+ * @param maxY
+ * @param testImageArray
+ * @param markerImageArray
+ * @param yoffset
+ * @param xoffset
+ * @return
+ */
+ private static double computeCorrelation(int maxX, int maxY, float[][][] testImageArray,
+ float[][][] markerImageArray, int yoffset, int xoffset)
+ {
+ double correlation = 0;
+ for (int y = 0; y < maxY; y++)
+ {
+ for (int x = 0; x < maxX; x++)
+ {
+ for (int rgbIndex = 0; rgbIndex < 3; rgbIndex++)
+ {
+ float colorComponent1 = markerImageArray[y][x][rgbIndex];
+ float colorComponent2 = testImageArray[yoffset + y][xoffset + x][rgbIndex];
+ correlation += colorComponent1 * colorComponent2;
+ }
+ }
+ }
+ return correlation;
+ }
+
+ public static int findHorizontalRule(BufferedImage screen,
+ Color ruleColor, Color bgColor, boolean fromTop) {
+ final int height = screen.getHeight();
+ int gap = 0;
+
+ if (!fromTop) {
+ return findHorizontalEdgeGap(screen, ruleColor,
+ bgColor, 1, height - 1, gap);
+ } else {
+ return findHorizontalEdgeGap(screen, bgColor,
+ ruleColor, 1, height - 1, gap);
+ }
+ }
+
+ public static int findHorizontalEdgeGap(BufferedImage screen,
+ Color area1Color, Color area2Color, int y1, int y2, int gap) {
+ final int width = screen.getWidth();
+ final int area1RGB = area1Color.getRGB();
+ final int area2RGB = area2Color.getRGB();
+ int edgePosition = Integer.MIN_VALUE;
+ int lastFound = Integer.MIN_VALUE;
+
+ for (int y = y1+1; y < y2 - gap; y++) {
+ int found = 0;
+ for (int x = 0; x < width; x++) {
+ int c1 = screen.getRGB(x, y - 1);
+ int c2 = screen.getRGB(x, y + gap);
+ if (c1 == area1RGB && c2 == area2RGB) {
+ found++;
+ }
+ }
+ if (found > lastFound) {
+ lastFound = found;
+ edgePosition = y;
+ }
+
+ }
+
+ return edgePosition;
+ }
+
+ public static int findVerticalEdgeGap(BufferedImage screen,
+ Color area1Color, Color area2Color, int y1, int y2, int gap) {
+ final int width = screen.getWidth();
+ final int area1RGB = area1Color.getRGB();
+ final int area2RGB = area2Color.getRGB();
+ int edgePosition = Integer.MIN_VALUE;
+ int lastFound = Integer.MIN_VALUE;
+
+ for (int x = 1; x < width - 1 - gap; x++) {
+ int found = 0;
+ for (int y = y1; y < y2; y++) {
+ int c1 = screen.getRGB(x - 1, y);
+ int c2 = screen.getRGB(x + gap, y);
+ if (c1 == area1RGB && c2 == area2RGB) {
+ found++;
+ }
+ }
+ if (found > lastFound) {
+ lastFound = found;
+ edgePosition = x;
+ }
+ }
+
+ return edgePosition;
+ }
+
+ /**
+ * method findColoredAreaGap finds a rectangle of given color surrounded by
+ * area of the second color with a possible gap at the border
+ *
+ * @param screen
+ * @param searchForColor
+ * @param surroundWithColor
+ * @param y1
+ * @param y2
+ * @param gap
+ * @return
+ */
+ public static Rectangle findColoredAreaGap(BufferedImage screen, Color searchForColor, Color surroundWithColor, int y1, int y2, int gap) {
+
+ int ymin = findHorizontalEdgeGap(screen, surroundWithColor, searchForColor, y1, y2, gap);
+ int ymax = findHorizontalEdgeGap(screen, searchForColor, surroundWithColor, y1, y2, gap);
+ int xmin = findVerticalEdgeGap(screen, surroundWithColor, searchForColor, ymin, ymax, gap);
+ int xmax = findVerticalEdgeGap(screen, searchForColor, surroundWithColor, ymin, ymax, gap);
+
+ return new Rectangle(xmin, ymin, xmax - xmin, ymax - ymin);
+ }
+
+ public static boolean isRectangleValid(Rectangle r){
+
+ if (r == null) return false;
+
+ return (r.width != 0)&&(r.height != 0)&&(r.x != Integer.MIN_VALUE)&&(r.y != Integer.MIN_VALUE);
+ }
+
+}
diff --git a/tests/test-extensions/net/sourceforge/jnlp/closinglisteners/RulesFolowingClosingListener.java b/tests/test-extensions/net/sourceforge/jnlp/closinglisteners/RulesFolowingClosingListener.java
index 9eb491c..3e88f06 100644
--- a/tests/test-extensions/net/sourceforge/jnlp/closinglisteners/RulesFolowingClosingListener.java
+++ b/tests/test-extensions/net/sourceforge/jnlp/closinglisteners/RulesFolowingClosingListener.java
@@ -184,6 +184,10 @@ public class RulesFolowingClosingListener extends CountingClosingListener {
addRules(l);
}
+ public List<Rule> getRules() {
+ return rules;
+ }
+
public void setRules(List<Rule> rules) {
if (rules == null) {
throw new NullPointerException("rules cant be null");