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