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