< prev index next >

src/java.desktop/share/classes/sun/font/SunLayoutEngine.java

Print this page

        

@@ -29,14 +29,16 @@
  */
 
 package sun.font;
 
 import sun.font.GlyphLayout.*;
+import sun.java2d.Disposer;
+import sun.java2d.DisposerRecord;
+
 import java.awt.geom.Point2D;
 import java.lang.ref.SoftReference;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.Locale;
 import java.util.WeakHashMap;
 
 /*
  * different ways to do this
  * 1) each physical font2d keeps a hashtable mapping scripts to layout

@@ -148,12 +150,14 @@
     private SunLayoutEngine(LayoutEngineKey key) {
         this.key = key;
     }
 
     static WeakHashMap<Font2D, Boolean> aatInfo = new WeakHashMap<>();
+    private static final WeakHashMap<Font2D, FaceRef> facePtr =
+            new WeakHashMap<>();
 
-    private boolean isAAT(Font2D font) {
+    private static boolean isAAT(Font2D font) {
        Boolean aatObj;
        synchronized (aatInfo) {
            aatObj = aatInfo.get(font);
        }
        if (aatObj != null) {

@@ -173,32 +177,76 @@
            aatInfo.put(font, Boolean.valueOf(aat));
        }
        return aat;
     }
 
+    private long getFacePtr(Font2D font2D) {
+        FaceRef ref;
+        synchronized (facePtr) {
+            ref = facePtr.computeIfAbsent(font2D, FaceRef::new);
+        }
+        return ref.getNativePtr();
+    }
+
     public void layout(FontStrikeDesc desc, float[] mat, float ptSize, int gmask,
                        int baseIndex, TextRecord tr, int typo_flags,
                        Point2D.Float pt, GVData data) {
         Font2D font = key.font();
         FontStrike strike = font.getStrike(desc);
-        long layoutTables = font.getLayoutTableCache();
         long pNativeFont = font.getPlatformNativeFontPtr(); // used on OSX
         // pScaler probably not needed long term.
         long pScaler = 0L;
         if (font instanceof FileFont) {
             pScaler = ((FileFont)font).getScaler().nativeScaler;
         }
+        long pFace = getFacePtr(font);
+        if (pFace != 0) {
         shape(font, strike, ptSize, mat, pScaler, pNativeFont,
-              layoutTables, isAAT(font),
+                    pFace, isAAT(font),
               tr.text, data, key.script(),
               tr.start, tr.limit, baseIndex, pt,
               typo_flags, gmask);
     }
+    }
 
     /* Native method to invoke harfbuzz layout engine */
     private static native boolean
         shape(Font2D font, FontStrike strike, float ptSize, float[] mat,
-              long pscaler, long pNativeFont, long layoutTables, boolean aat,
+              long pscaler, long pNativeFont, long pFace, boolean aat,
               char[] chars, GVData data,
               int script, int offset, int limit,
               int baseIndex, Point2D.Float pt, int typo_flags, int slot);
+
+    private static native long createFace(Font2D font,
+                                          boolean aat,
+                                          long platformNativeFontPtr,
+                                          long layoutTables);
+
+    private static native void disposeFace(long facePtr);
+
+    private static class FaceRef implements DisposerRecord {
+        private Font2D font;
+        private Long facePtr;
+
+        private FaceRef(Font2D font) {
+            this.font = font;
+        }
+
+        private synchronized long getNativePtr() {
+            if (facePtr == null) {
+                facePtr = createFace(font, isAAT(font),
+                        font.getPlatformNativeFontPtr(),
+                        font.getLayoutTableCache());
+                if (facePtr != 0) {
+                    Disposer.addObjectRecord(font, this);
+                }
+                font = null;
+            }
+            return facePtr;
+        }
+
+        @Override
+        public void dispose() {
+            disposeFace(facePtr);
+        }
+    }
 }
< prev index next >