001/* AlphaComposite.java -- provides a context for performing alpha compositing
002   Copyright (C) 2002, 2005, 2006  Free Software Foundation, Inc.
003
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038
039package java.awt;
040
041import gnu.java.awt.java2d.AlphaCompositeContext;
042
043import java.awt.image.ColorModel;
044import java.util.LinkedHashMap;
045import java.util.Map;
046
047/**
048 *
049 * @author Eric Blake (ebb9@email.byu.edu)
050 * @see Composite
051 * @see CompositeContext
052 * @since 1.3
053 * @status updated to 1.4 except for createContext, needs documentation
054 */
055public final class AlphaComposite implements Composite
056{
057  /** Map Long to AlphaComposites. See getInstance for details. */
058  private static final LinkedHashMap cache = new LinkedHashMap(11, 0.75f, true)
059  {
060    /** The largest the alpha composite cache can grow. */
061    private static final int MAX_CACHE_SIZE = 2048;
062
063    /** Prune stale entries. */
064    protected boolean removeEldestEntry(Map.Entry eldest)
065    {
066      return size() > MAX_CACHE_SIZE;
067    }
068  };
069
070  public static final int CLEAR = 1;
071  public static final int SRC = 2;
072  public static final int DST = 9;
073  public static final int SRC_OVER = 3;
074  public static final int DST_OVER = 4;
075  public static final int SRC_IN = 5;
076  public static final int DST_IN = 6;
077  public static final int SRC_OUT = 7;
078  public static final int DST_OUT = 8;
079  public static final int SRC_ATOP = 10;
080  public static final int DST_ATOP = 11;
081  public static final int XOR = 12;
082  public static final AlphaComposite Clear = getInstance(CLEAR);
083  public static final AlphaComposite Src = getInstance(SRC);
084  public static final AlphaComposite Dst = getInstance(DST);
085  public static final AlphaComposite SrcOver = getInstance(SRC_OVER);
086  public static final AlphaComposite DstOver = getInstance(DST_OVER);
087  public static final AlphaComposite SrcIn = getInstance(SRC_IN);
088  public static final AlphaComposite DstIn = getInstance(DST_IN);
089  public static final AlphaComposite SrcOut = getInstance(SRC_OUT);
090  public static final AlphaComposite DstOut = getInstance(DST_OUT);
091  public static final AlphaComposite SrcAtop = getInstance(SRC_ATOP);
092  public static final AlphaComposite DstAtop = getInstance(DST_ATOP);
093  public static final AlphaComposite Xor = getInstance(XOR);
094  
095  private final int rule;
096  private final float alpha;
097  private AlphaComposite(int rule, float alpha)
098  {
099    this.rule = rule;
100    this.alpha = alpha;
101  }
102
103  /**
104   * Creates an AlphaComposite object with the specified rule.
105   *
106   * @param rule The compositing rule.
107   *
108   * @exception IllegalArgumentException If rule is not one of the following:
109   * CLEAR, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT,
110   * SRC_ATOP, DST_ATOP, or XOR.
111   */
112  public static AlphaComposite getInstance(int rule)
113  {
114    return getInstance(rule, 1);
115  }
116  
117  /**
118   * Creates an AlphaComposite object with the specified rule and the constant
119   * alpha to multiply with the alpha of the source. The source is multiplied
120   * with the specified alpha before being composited with the destination.
121   *
122   * @param rule The compositing rule.
123   *
124   * @exception IllegalArgumentException If rule is not one of the following:
125   * CLEAR, SRC, DST, SRC_OVER, DST_OVER, SRC_IN, DST_IN, SRC_OUT, DST_OUT,
126   * SRC_ATOP, DST_ATOP, or XOR.
127   */
128  public static AlphaComposite getInstance(int rule, float alpha)
129  {
130    if (rule < CLEAR || rule > XOR || ! (alpha >= 0 && alpha <= 1))
131      throw new IllegalArgumentException();
132    // This long is guaranteed unique for all valid alpha composites.
133    Long l = new Long(rule + Double.doubleToLongBits(alpha));
134    AlphaComposite a = (AlphaComposite) cache.get(l);
135    if (a == null)
136      {
137        a = new AlphaComposite(rule, alpha);
138        cache.put(l, a);
139      }
140    return a;
141  }
142
143  /**
144   * Creates a {@link CompositeContext} that can be used to perform
145   * compositing operations according to this AlphaComposite settings.
146   *
147   * @param srcColorModel the color model of the source raster
148   * @param dstColorModel the color model of the destination raster
149   * @param hints the rendering hints to use
150   *
151   * @return a {@link CompositeContext} that can be used to perform
152   *         compositing operations according to this AlphaComposite settings
153   */
154  public CompositeContext createContext(ColorModel srcColorModel,
155                                        ColorModel dstColorModel,
156                                        RenderingHints hints)
157  {
158    return new AlphaCompositeContext(this, srcColorModel, dstColorModel);
159  }
160
161  /**
162   * Return an <code>AlphaComposite</code> similar to <code>this</code>,
163   * that uses the specified rule. If <code>rule</code> is the same as
164   * <code>this.rule</code>, then <code>this</code> is returned.
165   * 
166   * @since 1.6
167   */
168  public AlphaComposite derive(int rule)
169  {
170    if (this.rule == rule)
171      return this;
172    else
173      return AlphaComposite.getInstance(rule, this.getAlpha());
174  }
175  
176  /**
177   * Return an <code>AlphaComposite</code> similar to <code>this</code>,
178   * that uses the specified <code>alpha</code>.
179   * 
180   * If <code>alph</code> is the same as <code>this.alpha</code>,
181   * then <code>this</code> is returned.
182   * 
183   * @since 1.6
184   */
185  public AlphaComposite derive(float alpha)
186  {
187      if (this.getAlpha() == alpha)
188        return this;
189      else
190        return AlphaComposite.getInstance(this.getRule(), alpha);
191  }
192  
193  public float getAlpha()
194  {
195    return alpha;
196  }
197  
198  public int getRule()
199  {
200    return rule;
201  }
202  
203  public int hashCode()
204  {
205    return 31 * Float.floatToIntBits(alpha) + rule;
206  }
207  
208  public boolean equals(Object o)
209  {
210    if (! (o instanceof AlphaComposite))
211      return false;
212    AlphaComposite a = (AlphaComposite) o;
213    return rule == a.rule && alpha == a.alpha;
214  }
215} // class AlphaComposite