001    /*
002     * Created on Oct 24, 2010
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     *
013     * Copyright @2010-2011 the original author or authors.
014     */
015    package org.fest.assertions.data;
016    
017    import static java.lang.Math.abs;
018    import static org.fest.util.Objects.HASH_CODE_PRIME;
019    
020    /**
021     * A color.
022     *
023     * @author Yvonne Wang
024     * @author Alex Ruiz
025     */
026    public final class RgbColor {
027    
028      /** The red component of this color. */
029      public final int r;
030    
031      /** The green component of this color. */
032      public final int g;
033    
034      /** The blue component of this color. */
035      public final int b;
036    
037      /**
038       * Creates a new </code>{@link RgbColor}</code>.
039       * @param rgb a value representing a RGB combination.
040       * @return the created color.
041       */
042      public static RgbColor color(int rgb) {
043        return new RgbColor(extract(rgb, 16), extract(rgb, 8), extract(rgb, 0));
044      }
045    
046      private static int extract(int rgb, int value) {
047        return (rgb >> value) & 0xFF;
048      }
049    
050      private RgbColor(int r, int g, int b) {
051        this.r = r;
052        this.g = g;
053        this.b = b;
054      }
055    
056      /**
057       * Indicates whether the given <code>{@link RgbColor}</code> is equal to this one.
058       * @param color the {@code RgbColor} to compare this one to.
059       * @param offset used to tolerate a difference between the individual components of the {@code RgbColor}s to compare.
060       * @return {@code true} if the given {@code RgbColor} is equal to this one; {@code false} otherwise.
061       * @throws NullPointerException if the given offset is {@code null}.
062       */
063      public boolean isEqualTo(RgbColor color, Offset<Integer> offset) {
064        if (offset == null) throw new NullPointerException("The given offset should not be null");
065        if (equals(color)) return true;
066        if (color == null) return false;
067        int offsetValue = offset.value.intValue();
068        if (abs(r - color.r) > offsetValue) return false;
069        if (abs(g - color.g) > offsetValue) return false;
070        return abs(b - color.b) <= offsetValue;
071      }
072    
073      @Override public int hashCode() {
074        int result = 1;
075        result = HASH_CODE_PRIME * result + r;
076        result = HASH_CODE_PRIME * result + g;
077        result = HASH_CODE_PRIME * result + b;
078        return result;
079      }
080    
081      @Override public boolean equals(Object obj) {
082        if (this == obj) return true;
083        if (obj == null) return false;
084        if (getClass() != obj.getClass()) return false;
085        RgbColor other = (RgbColor) obj;
086        if (r != other.r) return false;
087        if (g != other.g) return false;
088        return b == other.b;
089      }
090    
091      @Override public String toString() {
092        return String.format("color[r=%d, g=%d, b=%d]", r, g, b);
093      }
094    }