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 
  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 synchronized static 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 synchronized static 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 synchronized static GraphicsPrimitive locate(int primTypeID,
 137                                                         SurfaceType dsttype)
 138     {
 139         return locate(primTypeID,
 140                       SurfaceType.OpaqueColor,
 141                       CompositeType.Src,
 142                       dsttype);
 143     }
 144 
 145     public synchronized static 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 synchronized static 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 }