View Javadoc
1   /*
2    * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package sun.java2d.loops;
27  
28  import java.awt.image.BufferedImage;
29  import java.awt.AlphaComposite;
30  import java.util.HashMap;
31  
32  /**
33   * A CompositeType object provides a chained description of a type of
34   * algorithm for color compositing.  The object will provide a single
35   * String constant descriptor which is one way of describing a particular
36   * compositing algorithm as well as a pointer to another CompositeType
37   * which describes a more general algorithm for achieving the same result.
38   * <p>
39   * A description of a more specific algorithm is considered a "subtype"
40   * and a description of a more general algorithm is considered a "supertype".
41   * Thus, the deriveSubType method provides a way to create a new CompositeType
42   * that is related to but more specific than an existing CompositeType and
43   * the getSuperType method provides a way to ask a given CompositeType
44   * for a more general algorithm to achieve the same result.
45   * <p>
46   * Note that you cannot construct a brand new root for a chain since
47   * the constructor is private.  Every chain of types must at some point
48   * derive from the Any node provided here using the deriveSubType()
49   * method.  The presence of this common Any node on every chain
50   * ensures that all chains end with the DESC_ANY descriptor so that
51   * a suitable General GraphicsPrimitive object can be obtained for
52   * the indicated algorithm if all of the more specific searches fail.
53   */
54  public final class CompositeType {
55  
56      private static int unusedUID = 1;
57      private static final HashMap<String,Integer> compositeUIDMap =
58          new HashMap<String,Integer>(100);
59  
60      /*
61       * CONSTANTS USED BY ALL PRIMITIVES TO DESCRIBE THE COMPOSITING
62       * ALGORITHMS THEY CAN PERFORM
63       */
64  
65      /**
66       * algorithm is a general algorithm that uses a CompositeContext
67       * to do the rendering.
68       */
69      public static final String DESC_ANY      = "Any CompositeContext";
70  
71      /**
72       * constant used to describe the Graphics.setXORMode() algorithm
73       */
74      public static final String DESC_XOR      = "XOR mode";
75  
76      /**
77       * constants used to describe the various AlphaComposite
78       * algorithms.
79       */
80      public static final String DESC_CLEAR     = "Porter-Duff Clear";
81      public static final String DESC_SRC       = "Porter-Duff Src";
82      public static final String DESC_DST       = "Porter-Duff Dst";
83      public static final String DESC_SRC_OVER  = "Porter-Duff Src Over Dst";
84      public static final String DESC_DST_OVER  = "Porter-Duff Dst Over Src";
85      public static final String DESC_SRC_IN    = "Porter-Duff Src In Dst";
86      public static final String DESC_DST_IN    = "Porter-Duff Dst In Src";
87      public static final String DESC_SRC_OUT   = "Porter-Duff Src HeldOutBy Dst";
88      public static final String DESC_DST_OUT   = "Porter-Duff Dst HeldOutBy Src";
89      public static final String DESC_SRC_ATOP  = "Porter-Duff Src Atop Dst";
90      public static final String DESC_DST_ATOP  = "Porter-Duff Dst Atop Src";
91      public static final String DESC_ALPHA_XOR = "Porter-Duff Xor";
92  
93      /**
94       * constants used to describe the two common cases of
95       * AlphaComposite algorithms that are simpler if there
96       * is not extraAlpha.
97       */
98      public static final String
99          DESC_SRC_NO_EA      = "Porter-Duff Src, No Extra Alpha";
100     public static final String
101         DESC_SRC_OVER_NO_EA = "Porter-Duff SrcOverDst, No Extra Alpha";
102 
103     /**
104      * constant used to describe an algorithm that implements all 8 of
105      * the Porter-Duff rules in one Primitive.
106      */
107     public static final String DESC_ANY_ALPHA = "Any AlphaComposite Rule";
108 
109     /*
110      * END OF COMPOSITE ALGORITHM TYPE CONSTANTS
111      */
112 
113     /**
114      * The root CompositeType object for all chains of algorithm descriptions.
115      */
116     public static final CompositeType
117         Any           = new CompositeType(null, DESC_ANY);
118 
119     /*
120      * START OF CompositeeType OBJECTS FOR THE VARIOUS CONSTANTS
121      */
122 
123     public static final CompositeType
124         General       = Any;
125 
126     public static final CompositeType
127         AnyAlpha      = General.deriveSubType(DESC_ANY_ALPHA);
128     public static final CompositeType
129         Xor           = General.deriveSubType(DESC_XOR);
130 
131     public static final CompositeType
132         Clear         = AnyAlpha.deriveSubType(DESC_CLEAR);
133     public static final CompositeType
134         Src           = AnyAlpha.deriveSubType(DESC_SRC);
135     public static final CompositeType
136         Dst           = AnyAlpha.deriveSubType(DESC_DST);
137     public static final CompositeType
138         SrcOver       = AnyAlpha.deriveSubType(DESC_SRC_OVER);
139     public static final CompositeType
140         DstOver       = AnyAlpha.deriveSubType(DESC_DST_OVER);
141     public static final CompositeType
142         SrcIn         = AnyAlpha.deriveSubType(DESC_SRC_IN);
143     public static final CompositeType
144         DstIn         = AnyAlpha.deriveSubType(DESC_DST_IN);
145     public static final CompositeType
146         SrcOut        = AnyAlpha.deriveSubType(DESC_SRC_OUT);
147     public static final CompositeType
148         DstOut        = AnyAlpha.deriveSubType(DESC_DST_OUT);
149     public static final CompositeType
150         SrcAtop       = AnyAlpha.deriveSubType(DESC_SRC_ATOP);
151     public static final CompositeType
152         DstAtop       = AnyAlpha.deriveSubType(DESC_DST_ATOP);
153     public static final CompositeType
154         AlphaXor      = AnyAlpha.deriveSubType(DESC_ALPHA_XOR);
155 
156     public static final CompositeType
157         SrcNoEa       = Src.deriveSubType(DESC_SRC_NO_EA);
158     public static final CompositeType
159         SrcOverNoEa   = SrcOver.deriveSubType(DESC_SRC_OVER_NO_EA);
160 
161     /*
162      * A special CompositeType for the case where we are filling in
163      * SrcOverNoEa mode with an opaque color.  In that case then the
164      * best loop for us to use would be a SrcNoEa loop, but what if
165      * there is no such loop?  In that case then we would end up
166      * backing off to a Src loop (which should still be fine) or an
167      * AnyAlpha loop which would be slower than a SrcOver loop in
168      * most cases.
169      * The fix is to use the following chain which looks for loops
170      * in the following order:
171      *    SrcNoEa, Src, SrcOverNoEa, SrcOver, AnyAlpha
172      */
173     public static final CompositeType
174         OpaqueSrcOverNoEa = SrcOverNoEa.deriveSubType(DESC_SRC)
175                                        .deriveSubType(DESC_SRC_NO_EA);
176 
177     /*
178      * END OF CompositeType OBJECTS FOR THE VARIOUS CONSTANTS
179      */
180 
181     /**
182      * Return a new CompositeType object which uses this object as its
183      * more general "supertype" descriptor.  If no operation can be
184      * found that implements the algorithm described more exactly
185      * by desc, then this object will define the more general
186      * compositing algorithm that can be used instead.
187      */
188     public CompositeType deriveSubType(String desc) {
189         return new CompositeType(this, desc);
190     }
191 
192     /**
193      * Return a CompositeType object for the specified AlphaComposite
194      * rule.
195      */
196     public static CompositeType forAlphaComposite(AlphaComposite ac) {
197         switch (ac.getRule()) {
198         case AlphaComposite.CLEAR:
199             return Clear;
200         case AlphaComposite.SRC:
201             if (ac.getAlpha() >= 1.0f) {
202                 return SrcNoEa;
203             } else {
204                 return Src;
205             }
206         case AlphaComposite.DST:
207             return Dst;
208         case AlphaComposite.SRC_OVER:
209             if (ac.getAlpha() >= 1.0f) {
210                 return SrcOverNoEa;
211             } else {
212                 return SrcOver;
213             }
214         case AlphaComposite.DST_OVER:
215             return DstOver;
216         case AlphaComposite.SRC_IN:
217             return SrcIn;
218         case AlphaComposite.DST_IN:
219             return DstIn;
220         case AlphaComposite.SRC_OUT:
221             return SrcOut;
222         case AlphaComposite.DST_OUT:
223             return DstOut;
224         case AlphaComposite.SRC_ATOP:
225             return SrcAtop;
226         case AlphaComposite.DST_ATOP:
227             return DstAtop;
228         case AlphaComposite.XOR:
229             return AlphaXor;
230         default:
231             throw new InternalError("Unrecognized alpha rule");
232         }
233     }
234 
235     private int uniqueID;
236     private String desc;
237     private CompositeType next;
238 
239     private CompositeType(CompositeType parent, String desc) {
240         next = parent;
241         this.desc = desc;
242         this.uniqueID = makeUniqueID(desc);
243     }
244 
245     public synchronized static final int makeUniqueID(String desc) {
246         Integer i = compositeUIDMap.get(desc);
247 
248         if (i == null) {
249             if (unusedUID > 255) {
250                 throw new InternalError("composite type id overflow");
251             }
252             i = unusedUID++;
253             compositeUIDMap.put(desc, i);
254         }
255         return i;
256     }
257 
258     public int getUniqueID() {
259         return uniqueID;
260     }
261 
262     public String getDescriptor() {
263         return desc;
264     }
265 
266     public CompositeType getSuperType() {
267         return next;
268     }
269 
270     public int hashCode() {
271         return desc.hashCode();
272     }
273 
274     public boolean isDerivedFrom(CompositeType other) {
275         CompositeType comptype = this;
276         do {
277             if (comptype.desc == other.desc) {
278                 return true;
279             }
280             comptype = comptype.next;
281         } while (comptype != null);
282         return false;
283     }
284 
285     public boolean equals(Object o) {
286         if (o instanceof CompositeType) {
287             return (((CompositeType) o).uniqueID == this.uniqueID);
288         }
289         return false;
290     }
291 
292     public String toString() {
293         return desc;
294     }
295 }