001    /* AlphaComposite.java -- provides a context for performing alpha compositing
002       Copyright (C) 2002, 2005, 2006  Free Software Foundation, Inc.
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    
039    package java.awt;
040    
041    import gnu.java.awt.java2d.AlphaCompositeContext;
042    
043    import java.awt.image.ColorModel;
044    import java.util.LinkedHashMap;
045    import 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     */
055    public 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