1 /* 2 * Copyright (c) 1997, 2018, 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 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); 53 private static native void registerNativeLoops(); 54 55 static { 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); 67 CustomComponent.register(); 68 GeneralRenderer.register(); 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 */ 98 private GraphicsPrimitiveMgr() { 99 } 100 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 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 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 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 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 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 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 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. 280 public static void testPrimitiveInstantiation() { 281 testPrimitiveInstantiation(false); 282 } 283 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 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 }