< prev index next >

modules/graphics/src/main/java/com/sun/javafx/font/PrismFontFactory.java

Print this page

        

@@ -243,11 +243,12 @@
     }
 
     private HashMap<String, PrismFontFile>
         fileNameToFontResourceMap = new HashMap<String, PrismFontFile>();
 
-    protected abstract PrismFontFile createFontFile(String name, String filename,
+    protected abstract PrismFontFile
+          createFontFile(String name, String filename,
                                                     int fIndex, boolean register,
                                                     boolean embedded,
                                                     boolean copy, boolean tracked)
                                                     throws Exception;
 

@@ -255,24 +256,26 @@
 
     // For an caller who has recognised a TTC file and wants to create
     // the instances one at a time so as to have visibility into the
     // contents of the TTC. Onus is on caller to enumerate all the fonts.
     private PrismFontFile createFontResource(String filename, int index) {
-        return createFontResource(filename, index, true, false, false, false);
+        return createFontResource(null, filename, index,
+                                  true, false, false, false);
     }
 
-    private PrismFontFile createFontResource(String filename, int index,
+    private PrismFontFile createFontResource(String name,
+                                             String filename, int index,
                                              boolean register, boolean embedded,
                                              boolean copy, boolean tracked) {
         String key = (filename+index).toLowerCase();
         PrismFontFile fr = fileNameToFontResourceMap.get(key);
         if (fr != null) {
             return fr;
         }
 
         try {
-            fr = createFontFile(null, filename, index, register,
+            fr = createFontFile(name, filename, index, register,
                                 embedded, copy, tracked);
             if (register) {
                 storeInMap(fr.getFullName(), fr);
                 fileNameToFontResourceMap.put(key, fr);
             }

@@ -284,64 +287,80 @@
             return null;
         }
     }
 
     private PrismFontFile createFontResource(String name, String filename) {
-        return createFontResource(name, filename, true, false, false, false);
+        PrismFontFile[] pffArr =
+            createFontResources(name, filename,
+                                true, false, false, false, false);
+        if (pffArr == null || pffArr.length == 0) {
+           return null;
+        } else {
+           return pffArr[0];
+        }
     }
 
-    private PrismFontFile createFontResource(String name, String filename,
+    private PrismFontFile[] createFontResources(String name, String filename,
                                              boolean register,
                                              boolean embedded,
                                              boolean copy,
-                                             boolean tracked) {
+                                                boolean tracked,
+                                                boolean loadAll) {
+
+        PrismFontFile[] fArr = null;
         if (filename == null) {
             return null;
-        } else {
-            String lcFN = filename.toLowerCase();
-            if (lcFN.endsWith(".ttc")) {
-                int index = 0;
-                PrismFontFile fr, namedFR = null;
+        }
+        PrismFontFile fr = createFontResource(name, filename, 0, register,
+                                             embedded, copy, tracked);
+        if (fr == null) {
+            return null;
+        }
+        int cnt = (!loadAll) ? 1 : fr.getFontCount();
+        fArr = new PrismFontFile[cnt];
+        fArr[0] = fr;
+        if (cnt == 1) { // Not a TTC, or only requesting one font.
+            return fArr;
+        }
+        PrismFontFile.FileRefCounter rc = null;
+        if (copy) {
+            rc = fr.createFileRefCounter();
+        }
+        int index = 1;
                 do {
                     String key = (filename+index).toLowerCase();
                     try {
                         fr = fileNameToFontResourceMap.get(key);
                         if (fr != null) {
-                            if (name.equals(fr.getFullName())) {
-                                return fr; // already mapped etc.
-                            } else {
-                                // Already loaded this TTC component, but
-                                // its not the one we are looking for.
+                    fArr[index] = fr;
                                 continue;
-                            }
                         } else {
-                            fr = createFontFile(name, filename, index,
+                    fr = createFontFile(null, filename, index,
                                                 register, embedded,
                                                 copy, tracked);
-                        }
-                    } catch (Exception e) {
-                        if (PrismFontFactory.debugFonts) {
-                            e.printStackTrace();
-                        }
+                    if (fr == null) {
                         return null;
                     }
-
+                    if (rc != null) {
+                        fr.setAndIncFileRefCounter(rc);
+                    }
+                    fArr[index] = fr;
                     String fontname = fr.getFullName();
                     if (register) {
                         storeInMap(fontname, fr);
                         fileNameToFontResourceMap.put(key, fr);
                     }
-                    if (index == 0 || name.equals(fontname)) {
-                        namedFR = fr;
                     }
-                } while (++index < fr.getFontCount());
-                return namedFR;
-            } else {
-                return createFontResource(filename, 0, register,
-                                          embedded, copy, tracked);
+            } catch (Exception e) {
+                if (PrismFontFactory.debugFonts) {
+                    e.printStackTrace();
             }
+                return null;
         }
+
+        } while (++index < cnt);
+        return fArr;
     }
 
     private String dotStyleStr(boolean bold, boolean italic) {
         if (!bold) {
             if (!italic) {

@@ -382,14 +401,20 @@
     private synchronized void addTmpFont(PrismFontFile fr) {
         if (tmpFonts == null) {
             tmpFonts = new ArrayList<WeakReference<PrismFontFile>>();
         }
         WeakReference<PrismFontFile> ref;
+        /* Registered fonts are enumerable by the application and are
+         * expected to persist until VM shutdown.
+         * Other fonts - notably ones temporarily loaded in a web page via
+         * webview - should be eligible to be collected and have their
+         * temp files deleted at any time.
+         */
         if (fr.isRegistered()) {
             ref = new WeakReference<PrismFontFile>(fr);
         } else {
-            ref = fr.createFileDisposer(this);
+            ref = fr.createFileDisposer(this, fr.getFileRefCounter());
         }
         tmpFonts.add(ref);
         addFileCloserHook();
     }
 

@@ -1432,17 +1457,19 @@
         }
     }
 
     private HashMap<String, PrismFontFile> embeddedFonts;
 
-    public PGFont loadEmbeddedFont(String name, InputStream fontStream,
-                                   float size, boolean register) {
+    public PGFont[] loadEmbeddedFont(String name, InputStream fontStream,
+                                     float size,
+                                     boolean register,
+                                     boolean loadAll) {
         if (!hasPermission()) {
-            return createFont(DEFAULT_FULLNAME, size);
+            return new PGFont[] { createFont(DEFAULT_FULLNAME, size) } ;
         }
         if (FontFileWriter.hasTempPermission()) {
-            return loadEmbeddedFont0(name, fontStream, size, register);
+            return loadEmbeddedFont0(name, fontStream, size, register, loadAll);
         }
 
         // Otherwise, be extra conscious of pending temp file creation and
         // resourcefully handle the temp file resources, among other things.
         FontFileWriter.FontTracker tracker =

@@ -1452,24 +1479,26 @@
             acquired = tracker.acquirePermit();
             if (!acquired) {
                 // Timed out waiting for resources.
                 return null;
             }
-            return loadEmbeddedFont0(name, fontStream, size, register);
+            return loadEmbeddedFont0(name, fontStream, size, register, loadAll);
         } catch (InterruptedException e) {
             // Interrupted while waiting to acquire a permit.
             return null;
         } finally {
             if (acquired) {
                 tracker.releasePermit();
             }
         }
     }
 
-    private PGFont loadEmbeddedFont0(String name, InputStream fontStream,
-                                     float size, boolean register) {
-        PrismFontFile fr = null;
+    private PGFont[] loadEmbeddedFont0(String name, InputStream fontStream,
+                                       float size,
+                                       boolean register,
+                                       boolean loadAll) {
+        PrismFontFile[] fr = null;
         FontFileWriter fontWriter = new FontFileWriter();
         try {
             // We use a shutdown hook to close all open tmp files
             // created via this API and delete them.
             final File tFile = fontWriter.openFile();

@@ -1481,17 +1510,17 @@
                 }
                 fontWriter.writeBytes(buf, 0, bytesRead);
             }
             fontWriter.closeFile();
 
-            fr = loadEmbeddedFont(name, tFile.getPath(), register, true,
-                                  fontWriter.isTracking());
+            fr = loadEmbeddedFont1(name, tFile.getPath(), register, true,
+                                   fontWriter.isTracking(), loadAll);
 
-            if (fr != null) {
+            if (fr != null && fr.length > 0) {
                 /* Delete the file downloaded if it was decoded
                  * to another file */
-                if (fr.isDecoded()) {
+                if (fr[0].isDecoded()) {
                     fontWriter.deleteFile();
                 }
             }
 
             /* We don't want to leave the temp files around after exit.

@@ -1517,13 +1546,18 @@
              */
             if (fr == null) {
                 fontWriter.deleteFile();
             }
         }
-        if (fr != null) {
+        if (fr != null && fr.length > 0) {
             if (size <= 0) size = getSystemFontSize();
-            return new PrismFont(fr, fr.getFullName(), size);
+            int num = fr.length;
+            PrismFont[] pFonts = new PrismFont[num];
+            for (int i=0; i<num; i++) {
+                pFonts[i] = new PrismFont(fr[i], fr[i].getFullName(), size);
+            }
+            return pFonts;
         }
         return null;
     }
 
     /**

@@ -1534,22 +1568,32 @@
      *
      * @param name font name
      * @param path Path name to system file
      * @param size font size
      * @param register whether the font should be registered.
+     * @param loadAll whether to load all fonts if it is a TTC
      * @return font name extracted from font file
      */
-    public PGFont loadEmbeddedFont(String name, String path,
-                                   float size, boolean register) {
+    public PGFont[] loadEmbeddedFont(String name, String path,
+                                     float size,
+                                     boolean register,
+                                     boolean loadAll) {
         if (!hasPermission()) {
-            return createFont(DEFAULT_FULLNAME, size);
+            return new PGFont[] { createFont(DEFAULT_FULLNAME, size) };
         }
         addFileCloserHook();
-        FontResource fr = loadEmbeddedFont(name, path, register, false, false);
-        if (fr != null) {
+        FontResource[] frArr =
+          loadEmbeddedFont1(name, path, register, false, false, loadAll);
+        if (frArr != null && frArr.length > 0) {
             if (size <= 0) size = getSystemFontSize();
-            return new PrismFont(fr, fr.getFullName(), size);
+            int num = frArr.length;
+            PGFont[] pgFonts = new PGFont[num];
+            for (int i=0; i<num; i++) {
+                pgFonts[i] =
+                    new PrismFont(frArr[i], frArr[i].getFullName(), size);
+            }
+            return pgFonts;
         }
         return null;
     }
 
     /* This should make the embedded font eligible for reclaimation

@@ -1586,71 +1630,78 @@
     private int numEmbeddedFonts = 0;
     public int test_getNumEmbeddedFonts() {
         return numEmbeddedFonts;
     }
 
-    private synchronized PrismFontFile loadEmbeddedFont(String name, String path,
+    private synchronized
+        PrismFontFile[] loadEmbeddedFont1(String name, String path,
                                                         boolean register, boolean copy,
-                                                        boolean tracked) {
+                                          boolean tracked, boolean loadAll) {
 
         ++numEmbeddedFonts;
-
         /*
          * Fonts that aren't platform installed include those in the
          * application jar, WOFF fonts that are downloaded, and fonts
          * created via Font.loadFont. If copy==true, we can infer its
          * one of these, but its also possible for a font to be file-system
          * installed as part of the application but not known to the
          * platform. In this case copy==false, but we still need to flag
          * to the system its not a platform font so that other pipelines
          * know to reference the file directly.
          */
-        PrismFontFile fr = createFontResource(name, path, register,
-                                              true, copy, tracked);
-        if (fr == null) {
+        PrismFontFile[] frArr = createFontResources(name, path, register,
+                                                    true, copy, tracked,
+                                                    loadAll);
+        if (frArr == null || frArr.length == 0) {
             return null; // yes, this means the caller needs to handle null.
         }
 
+        /* Before we return or register, make sure names are present
+         * check whether any of the fonts duplicate an OS font.
+         */
+
+        if (embeddedFonts == null) {
+            embeddedFonts = new HashMap<String, PrismFontFile>();
+        }
+
+        boolean registerEmbedded = true;
+        for (int i=0; i<frArr.length; i++) {
+            PrismFontFile fr = frArr[i];
         String family = fr.getFamilyName();
         if (family == null || family.length() == 0) return null;
         String fullname = fr.getFullName();
         if (fullname == null || fullname.length() == 0) return null;
         String psname = fr.getPSName();
         if (psname == null || psname.length() == 0) return null;
 
-        boolean registerEmbedded = true;
-        if (embeddedFonts != null) {
             FontResource resource = embeddedFonts.get(fullname);
             if (resource != null && fr.equals(resource)) {
                 /* Do not register the same font twice in the OS */
                 registerEmbedded = false;
             }
         }
 
         if (registerEmbedded) {
             /* Use filename from the resource so woff fonts are handled */
-            if (!registerEmbeddedFont(fr.getFileName())) {
+            if (!registerEmbeddedFont(frArr[0].getFileName())) {
                 /* This font file can't be used by the underlying rasterizer */
                 return null;
             }
         }
 
-        if (!register) {
             /* If a temporary font is a copy but it is not decoded then it
              * will not be anywhere the shutdown hook can see.
              * That means if the font is keep for the entire life of the VM
              * its file will not be deleted.
              * The fix is to add this font to the list of temporary fonts.
              */
-            if (copy && !fr.isDecoded()) {
-                addTmpFont(fr);
-            }
-            return fr;
+        if (copy && !frArr[0].isDecoded()) {
+            addTmpFont(frArr[0]);
         }
 
-        if (embeddedFonts == null) {
-            embeddedFonts = new HashMap<String, PrismFontFile>();
+        if (!register) {
+            return frArr;
         }
 
         /* If a font name is provided then we will also store that in the
          * map as an alias, otherwise should use the only the real name,
          * REMIND: its possible that either name may hide some installed

@@ -1658,14 +1709,18 @@
          * without loading all the platform fonts (expensive) this is
          * difficult to ascertain. A contains() check here is therefore
          * probably mostly futile.
          */
         if (name != null && !name.isEmpty()) {
-            embeddedFonts.put(name, fr);
-            storeInMap(name, fr);
+            embeddedFonts.put(name, frArr[0]);
+            storeInMap(name, frArr[0]);
         }
 
+        for (int i=0; i<frArr.length; i++) {
+            PrismFontFile fr = frArr[i];
+            String family = fr.getFamilyName();
+            String fullname = fr.getFullName();
         removeEmbeddedFont(fullname);
         embeddedFonts.put(fullname, fr);
         storeInMap(fullname, fr);
         family = family + dotStyleStr(fr.isBold(), fr.isItalic());
         storeInMap(family, fr);

@@ -1675,11 +1730,12 @@
          * This can occur when an application requested a bold font before
          * it called Font.loadFont to register the bold font. It won't
          * fix the cases that already happened, but will fix the future ones.
          */
         compResourceMap.remove(family.toLowerCase());
-        return fr;
+        }
+        return frArr;
     }
 
     private void
         logFontInfo(String message,
                     HashMap<String,String> fontToFileMap,
< prev index next >