1 /*
2  * Copyright (c) 1997, 2006, 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 /*
27  * @author Charlton Innovations, Inc.
28  */
29 
30 package sun.java2d.loops;
31 
32 import java.util.Comparator;
33 import java.util.Arrays;
34 import sun.java2d.SunGraphics2D;
35 
36 /**
37  *   GraphicsComponentMgr provides services to
38  *   1. register primitives for later use
39  *   2. locate an instance of a primitve based on characteristics
40  */
41 public final class GraphicsPrimitiveMgr {
42 
43     private static final boolean debugTrace = false;
44     private static GraphicsPrimitive primitives[];
45     private static GraphicsPrimitive generalPrimitives[];
46     private static boolean needssort = true;
47 
initIDs(Class<?> GP, Class<?> ST, Class<?> CT, Class<?> SG2D, Class<?> Color, Class<?> AT, Class<?> XORComp, Class<?> AlphaComp, Class<?> Path2D, Class<?> Path2DFloat, Class<?> SHints)48     private static native void initIDs(Class<?> GP, Class<?> ST, Class<?> CT,
49                                        Class<?> SG2D, Class<?> Color, Class<?> AT,
50                                        Class<?> XORComp, Class<?> AlphaComp,
51                                        Class<?> Path2D, Class<?> Path2DFloat,
52                                        Class<?> SHints);
registerNativeLoops()53     private static native void registerNativeLoops();
54 
55     static {
initIDs(GraphicsPrimitive.class, SurfaceType.class, CompositeType.class, SunGraphics2D.class, java.awt.Color.class, java.awt.geom.AffineTransform.class, XORComposite.class, java.awt.AlphaComposite.class, java.awt.geom.Path2D.class, java.awt.geom.Path2D.Float.class, sun.awt.SunHints.class)56         initIDs(GraphicsPrimitive.class,
57                 SurfaceType.class,
58                 CompositeType.class,
59                 SunGraphics2D.class,
60                 java.awt.Color.class,
61                 java.awt.geom.AffineTransform.class,
62                 XORComposite.class,
63                 java.awt.AlphaComposite.class,
64                 java.awt.geom.Path2D.class,
65                 java.awt.geom.Path2D.Float.class,
66                 sun.awt.SunHints.class);
CustomComponent.register()67         CustomComponent.register();
GeneralRenderer.register()68         GeneralRenderer.register();
registerNativeLoops()69         registerNativeLoops();
70     }
71 
72     private static class PrimitiveSpec {
73         public int uniqueID;
74     }
75 
76     private static Comparator<GraphicsPrimitive> primSorter =
77             new Comparator<GraphicsPrimitive>() {
78         public int compare(GraphicsPrimitive o1, GraphicsPrimitive o2) {
79             int id1 = o1.getUniqueID();
80             int id2 = o2.getUniqueID();
81 
82             return (id1 == id2 ? 0 : (id1 < id2 ? -1 : 1));
83         }
84     };
85 
86     private static Comparator<Object> primFinder = new Comparator<Object>() {
87         public int compare(Object o1, Object o2) {
88             int id1 = ((GraphicsPrimitive) o1).getUniqueID();
89             int id2 = ((PrimitiveSpec) o2).uniqueID;
90 
91             return (id1 == id2 ? 0 : (id1 < id2 ? -1 : 1));
92         }
93     };
94 
95     /**
96      * Ensure that noone can instantiate this class.
97      */
GraphicsPrimitiveMgr()98     private GraphicsPrimitiveMgr() {
99     }
100 
register(GraphicsPrimitive[] newPrimitives)101     public static synchronized void register(GraphicsPrimitive[] newPrimitives)
102     {
103         GraphicsPrimitive[] devCollection = primitives;
104         int oldSize = 0;
105         int newSize = newPrimitives.length;
106         if (debugTrace) {
107             writeLog("Registering " + newSize + " primitives");
108             for (int i = 0; i < newSize; i++) {
109                 writeLog(newPrimitives[i].toString());
110             }
111         }
112         if (devCollection != null) {
113             oldSize = devCollection.length;
114         }
115         GraphicsPrimitive[] temp = new GraphicsPrimitive[oldSize + newSize];
116         if (devCollection != null) {
117             System.arraycopy(devCollection, 0, temp, 0, oldSize);
118         }
119         System.arraycopy(newPrimitives, 0, temp, oldSize, newSize);
120         needssort = true;
121         primitives = temp;
122     }
123 
registerGeneral(GraphicsPrimitive gen)124     public static synchronized void registerGeneral(GraphicsPrimitive gen) {
125         if (generalPrimitives == null) {
126             generalPrimitives = new GraphicsPrimitive[] {gen};
127             return;
128         }
129         int len = generalPrimitives.length;
130         GraphicsPrimitive[] newGen = new GraphicsPrimitive[len + 1];
131         System.arraycopy(generalPrimitives, 0, newGen, 0, len);
132         newGen[len] = gen;
133         generalPrimitives = newGen;
134     }
135 
locate(int primTypeID, SurfaceType dsttype)136     public static synchronized GraphicsPrimitive locate(int primTypeID,
137                                                         SurfaceType dsttype)
138     {
139         return locate(primTypeID,
140                       SurfaceType.OpaqueColor,
141                       CompositeType.Src,
142                       dsttype);
143     }
144 
locate(int primTypeID, SurfaceType srctype, CompositeType comptype, SurfaceType dsttype)145     public static synchronized GraphicsPrimitive locate(int primTypeID,
146                                                         SurfaceType srctype,
147                                                         CompositeType comptype,
148                                                         SurfaceType dsttype)
149     {
150         /*
151           System.out.println("Looking for:");
152           System.out.println("    method: "+signature);
153           System.out.println("    from:   "+srctype);
154           System.out.println("    by:     "+comptype);
155           System.out.println("    to:     "+dsttype);
156         */
157         GraphicsPrimitive prim = locatePrim(primTypeID,
158                                             srctype, comptype, dsttype);
159 
160         if (prim == null) {
161             //System.out.println("Trying general loop");
162             prim = locateGeneral(primTypeID);
163             if (prim != null) {
164                 prim = prim.makePrimitive(srctype, comptype, dsttype);
165                 if (prim != null && GraphicsPrimitive.traceflags != 0) {
166                     prim = prim.traceWrap();
167                 }
168             }
169         }
170         return prim;
171     }
172 
173     public static synchronized GraphicsPrimitive
locatePrim(int primTypeID, SurfaceType srctype, CompositeType comptype, SurfaceType dsttype)174         locatePrim(int primTypeID,
175                    SurfaceType srctype,
176                    CompositeType comptype,
177                    SurfaceType dsttype)
178     {
179         /*
180           System.out.println("Looking for:");
181           System.out.println("    method: "+signature);
182           System.out.println("    from:   "+srctype);
183           System.out.println("    by:     "+comptype);
184           System.out.println("    to:     "+dsttype);
185         */
186         SurfaceType src, dst;
187         CompositeType cmp;
188         GraphicsPrimitive prim;
189         PrimitiveSpec spec = new PrimitiveSpec();
190 
191         for (dst = dsttype; dst != null; dst = dst.getSuperType()) {
192             for (src = srctype; src != null; src = src.getSuperType()) {
193                 for (cmp = comptype; cmp != null; cmp = cmp.getSuperType()) {
194                     /*
195                       System.out.println("Trying:");
196                       System.out.println("    method: "+spec.methodSignature);
197                       System.out.println("    from:   "+spec.sourceType);
198                       System.out.println("    by:     "+spec.compType);
199                       System.out.println("    to:     "+spec.destType);
200                     */
201 
202                     spec.uniqueID =
203                         GraphicsPrimitive.makeUniqueID(primTypeID, src, cmp, dst);
204                     prim = locate(spec);
205                     if (prim != null) {
206                         //System.out.println("<GPMgr> Found: " + prim + " in " + i + " steps");
207                         return prim;
208                     }
209                 }
210             }
211         }
212         return null;
213     }
214 
locateGeneral(int primTypeID)215     private static GraphicsPrimitive locateGeneral(int primTypeID) {
216         if (generalPrimitives == null) {
217             return null;
218         }
219         for (int i = 0; i < generalPrimitives.length; i++) {
220             GraphicsPrimitive prim = generalPrimitives[i];
221             if (prim.getPrimTypeID() == primTypeID) {
222                 return prim;
223             }
224         }
225         return null;
226         //throw new InternalError("No general handler registered for"+signature);
227     }
228 
locate(PrimitiveSpec spec)229     private static GraphicsPrimitive locate(PrimitiveSpec spec) {
230         if (needssort) {
231             if (GraphicsPrimitive.traceflags != 0) {
232                 for (int i = 0; i < primitives.length; i++) {
233                     primitives[i] = primitives[i].traceWrap();
234                 }
235             }
236             Arrays.sort(primitives, primSorter);
237             needssort = false;
238         }
239         GraphicsPrimitive[] devCollection = primitives;
240         if (devCollection == null) {
241             return null;
242         }
243         int index = Arrays.binarySearch(devCollection, spec, primFinder);
244         if (index >= 0) {
245             GraphicsPrimitive prim = devCollection[index];
246             if (prim instanceof GraphicsPrimitiveProxy) {
247                 prim = ((GraphicsPrimitiveProxy) prim).instantiate();
248                 devCollection[index] = prim;
249                 if (debugTrace) {
250                     writeLog("Instantiated graphics primitive " + prim);
251                 }
252             }
253             if (debugTrace) {
254                 writeLog("Lookup found[" + index + "]["+ prim + "]");
255             }
256             return prim;
257         }
258         if (debugTrace) {
259             writeLog("Lookup found nothing for:");
260             writeLog(" " + spec.uniqueID);
261         }
262         return null;
263     }
264 
writeLog(String str)265     private static void writeLog(String str) {
266         if (debugTrace) {
267             System.err.println(str);
268         }
269     }
270 
271     /**
272      * Test that all of the GraphicsPrimitiveProxy objects actually
273      * resolve to something.  Throws a RuntimeException if anything
274      * is wrong, an has no effect if all is well.
275      */
276     // This is only really meant to be called from GraphicsPrimitiveProxyTest
277     // in the regression tests directory, but it has to be here because
278     // it needs access to a private data structure.  It is not very
279     // big, though.
testPrimitiveInstantiation()280     public static void testPrimitiveInstantiation() {
281         testPrimitiveInstantiation(false);
282     }
283 
testPrimitiveInstantiation(boolean verbose)284     public static void testPrimitiveInstantiation(boolean verbose) {
285         int resolved = 0;
286         int unresolved = 0;
287         GraphicsPrimitive[] prims = primitives;
288         for (int j = 0; j < prims.length; j++) {
289             GraphicsPrimitive p = prims[j];
290             if (p instanceof GraphicsPrimitiveProxy) {
291                 GraphicsPrimitive r = ((GraphicsPrimitiveProxy) p).instantiate();
292                 if (!r.getSignature().equals(p.getSignature()) ||
293                     r.getUniqueID() != p.getUniqueID()) {
294                     System.out.println("r.getSignature == "+r.getSignature());
295                     System.out.println("r.getUniqueID == " + r.getUniqueID());
296                     System.out.println("p.getSignature == "+p.getSignature());
297                     System.out.println("p.getUniqueID == " + p.getUniqueID());
298                     throw new RuntimeException("Primitive " + p
299                                                + " returns wrong signature for "
300                                                + r.getClass());
301                 }
302                 // instantiate checks that p.satisfiesSameAs(r)
303                 unresolved++;
304                 p = r;
305                 if (verbose) {
306                     System.out.println(p);
307                 }
308             } else {
309                 if (verbose) {
310                     System.out.println(p + " (not proxied).");
311                 }
312                 resolved++;
313             }
314         }
315         System.out.println(resolved+
316                            " graphics primitives were not proxied.");
317         System.out.println(unresolved+
318                            " proxied graphics primitives resolved correctly.");
319         System.out.println(resolved+unresolved+
320                            " total graphics primitives");
321     }
322 
main(String argv[])323     public static void main(String argv[]) {
324         // REMIND: Should trigger loading of platform primitives somehow...
325         if (needssort) {
326             Arrays.sort(primitives, primSorter);
327             needssort = false;
328         }
329         testPrimitiveInstantiation(argv.length > 0);
330     }
331 }
332