/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo 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, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.fge; import java.awt.Color; import java.awt.geom.AffineTransform; import org.openflexo.fge.geom.FGEGeometricObject; import org.openflexo.fge.geom.FGEPoint; import org.openflexo.toolbox.ColorUtils; public class FGEUtils { public static final double PHI = (Math.sqrt(5) + 1) / 2; public static final Color NICE_RED = new Color(255, 153, 153); public static final Color NICE_BLUE = new Color(153, 153, 255); public static final Color NICE_YELLOW = new Color(255, 255, 153); public static final Color NICE_PINK = new Color(255, 204, 255); public static final Color NICE_GREEN = new Color(153, 255, 153); public static final Color NICE_TURQUOISE = new Color(153, 255, 255); public static final Color NICE_ORANGE = new Color(255, 204, 102); public static final Color NICE_DARK_GREEN = new Color(0, 153, 51); public static final Color NICE_BROWN = new Color(186, 112, 0); public static final Color NICE_BORDEAU = new Color(153, 0, 51); /** * Returns the color that has the best contrast ratio with the oppositeColor. The algorthm used is the one considered by the W3C for * WCAG 2.0. * * @param oppositeColor * - the opposite color to consider * @param colors * - all colors amongst which to choose. * @return the color the best contrast ratio compared to opposite color. See * http://www.w3.org/TR/2007/WD-WCAG20-TECHS-20070517/Overview.html#G18 */ public static Color chooseBestColor(Color oppositeColor, Color... colors) { // int bestContrast = Integer.MIN_VALUE; double contrastRatio = 0; Color returned = null; for (Color c : colors) { /* * int colorConstrastDiff = getColorConstrastDiff(oppositeColor,c); int colorBrightnessDiff = * getColorBrightnessDiff(oppositeColor,c); int colorContrast = colorConstrastDiff+colorBrightnessDiff; if (colorContrast > * bestContrast) { bestContrast = colorContrast; returned = c; } */ double d = ColorUtils.getContrastRatio(oppositeColor, c); if (d > contrastRatio) { contrastRatio = d; returned = c; } } return returned; } public static Color emphasizedColor(Color c) { if (c == null) { return c; } double l = ColorUtils.getRelativeLuminance(c); Color test = c, best = c; double ratio = 0, bestRatio = -1; int count = -1; if (l > 0.5) { do { test = test.darker(); ratio = ColorUtils.getContrastRatio(test, c); if (ratio > bestRatio) { bestRatio = ratio; best = test; } count++; } while (ratio < 5 && count < 10); } else { test = new Color(test.getRed() == 0 ? 5 : test.getRed(), test.getGreen() == 0 ? 5 : test.getGreen(), test.getBlue() == 0 ? 5 : test.getBlue()); do { test = test.brighter(); ratio = ColorUtils.getContrastRatio(test, c); if (ratio > bestRatio) { bestRatio = ratio; best = test; } count++; } while (ratio < 5 && count < 10); } return best; } /** * Return flag indicating if supplied AffineTransform is valid (does not contain Infinity of NaN values) * * @param at * @return */ public static boolean checkAffineTransform(AffineTransform at) { if (!checkDoubleIsAValue(at.getScaleX())) { return false; } if (!checkDoubleIsAValue(at.getScaleY())) { return false; } if (!checkDoubleIsAValue(at.getTranslateX())) { return false; } if (!checkDoubleIsAValue(at.getTranslateY())) { return false; } if (!checkDoubleIsAValue(at.getShearX())) { return false; } if (!checkDoubleIsAValue(at.getShearY())) { return false; } if (!checkDoubleIsAValue(at.getScaleX())) { return false; } if (!checkDoubleIsAValue(at.getScaleX())) { return false; } return true; } public static boolean checkDoubleIsAValue(Double v) { return !(v.isInfinite() || v.isNaN()); } public static final boolean doubleEquals(double v1, double v2) { return Math.abs(v1 - v2) < FGEGeometricObject.EPSILON; } public static final Color mergeColors(Color color1, Color color2) { return new Color((color1.getRed() + color2.getRed()) / 2, (color1.getGreen() + color2.getGreen()) / 2, (color1.getBlue() + color2.getBlue()) / 2); } public static double getSlope(FGEPoint p1, FGEPoint p2) { double x = p2.x - p1.x; double y = p2.y - p1.y; // GPO: In some rare cases, it seems that this returns -PI/2 instead of 3PI/2 // Example: new FGESegment(0.05369127516778524,0.06451612903225806,0.053691275167785234,-0.5806451612903225) // FGESegment.getAngle() has been fixed since but if it re-appears, maybe we should uncomment the code below // Mainly, calling methods should take into account that this method can return a value -PI/2 or 3PI/2 return Math.atan2(/* Math.abs(x)<EPSILON?0:x, Math.abs(y)<EPSILON?0:y */x, y) + Math.PI / 2; } public static void main(String[] args) { Color yellow = new Color(255, 255, 204); Color green = new Color(153, 255, 204); Color grey = new Color(192, 192, 192); System.err.println(emphasizedColor(yellow)); System.err.println(emphasizedColor(green)); System.err.println(emphasizedColor(grey)); } }