You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ja...@apache.org on 2015/07/13 03:11:31 UTC
svn commit: r1690560 - in
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font:
CIDSystemInfo.java FileSystemFontProvider.java FontInfo.java
PDCIDFontType2.java PDPanoseClassification.java
Author: jahewson
Date: Mon Jul 13 01:11:31 2015
New Revision: 1690560
URL: http://svn.apache.org/r1690560
Log:
PDFBOX-2842: Local cache of FontInfo using Preferences API
Added:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDSystemInfo.java (with props)
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDPanoseClassification.java
Added: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDSystemInfo.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDSystemInfo.java?rev=1690560&view=auto
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDSystemInfo.java (added)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDSystemInfo.java Mon Jul 13 01:11:31 2015
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.pdfbox.pdmodel.font;
+
+import java.io.Serializable;
+
+/**
+ * Represents a CIDSystemInfo for the FontMapper API.
+ *
+ * @author John Hewson
+ */
+public final class CIDSystemInfo implements Serializable
+{
+ private final String registry;
+ private final String ordering;
+ private final int supplement;
+
+ CIDSystemInfo(String registry, String ordering, int supplement)
+ {
+ this.registry = registry;
+ this.ordering = ordering;
+ this.supplement = supplement;
+ }
+
+ public String getRegistry()
+ {
+ return registry;
+ }
+
+ public String getOrdering()
+ {
+ return ordering;
+ }
+
+ public int getSupplement()
+ {
+ return supplement;
+ }
+
+ @Override
+ public String toString()
+ {
+ return getRegistry() + "-" + getOrdering() + "-" + getSupplement();
+ }
+}
Propchange: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/CIDSystemInfo.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java?rev=1690560&r1=1690559&r2=1690560&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FileSystemFontProvider.java Mon Jul 13 01:11:31 2015
@@ -16,13 +16,19 @@
*/
package org.apache.pdfbox.pdmodel.font;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
+import java.util.prefs.Preferences;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fontbox.FontBoxFont;
@@ -51,11 +57,11 @@ final class FileSystemFontProvider exten
private final List<FSFontInfo> fontInfoList = new ArrayList<FSFontInfo>();
private final FontCache cache;
- private class FSFontInfo extends FontInfo
+ private static class FSFontInfo extends FontInfo implements Serializable
{
private final String postScriptName;
private final FontFormat format;
- private final PDCIDSystemInfo cidSystemInfo;
+ private final CIDSystemInfo cidSystemInfo;
private final int usWeightClass;
private final int sFamilyClass;
private final int ulCodePageRange1;
@@ -63,10 +69,12 @@ final class FileSystemFontProvider exten
private final int macStyle;
private final PDPanoseClassification panose;
private final File file;
+ private transient FileSystemFontProvider parent;
private FSFontInfo(File file, FontFormat format, String postScriptName,
- PDCIDSystemInfo cidSystemInfo, int usWeightClass, int sFamilyClass,
- int ulCodePageRange1, int ulCodePageRange2, int macStyle, byte[] panose)
+ CIDSystemInfo cidSystemInfo, int usWeightClass, int sFamilyClass,
+ int ulCodePageRange1, int ulCodePageRange2, int macStyle, byte[] panose,
+ FileSystemFontProvider parent)
{
this.file = file;
this.format = format;
@@ -78,6 +86,7 @@ final class FileSystemFontProvider exten
this.ulCodePageRange2 = ulCodePageRange2;
this.macStyle = macStyle;
this.panose = panose != null ? new PDPanoseClassification(panose) : null;
+ this.parent = parent;
}
@Override
@@ -93,7 +102,7 @@ final class FileSystemFontProvider exten
}
@Override
- public PDCIDSystemInfo getCIDSystemInfo()
+ public CIDSystemInfo getCIDSystemInfo()
{
return cidSystemInfo;
}
@@ -101,7 +110,7 @@ final class FileSystemFontProvider exten
@Override
public FontBoxFont getFont()
{
- FontBoxFont cached = cache.getFont(this);
+ FontBoxFont cached = parent.cache.getFont(this);
if (cached != null)
{
return cached;
@@ -111,12 +120,12 @@ final class FileSystemFontProvider exten
FontBoxFont font;
switch (format)
{
- case PFB: font = getType1Font(postScriptName, file); break;
- case TTF: font = getTrueTypeFont(postScriptName, file); break;
- case OTF: font = getOTFFont(postScriptName, file); break;
+ case PFB: font = parent.getType1Font(postScriptName, file); break;
+ case TTF: font = parent.getTrueTypeFont(postScriptName, file); break;
+ case OTF: font = parent.getOTFFont(postScriptName, file); break;
default: throw new RuntimeException("can't happen");
}
- cache.addFont(this, font);
+ parent.cache.addFont(this, font);
return font;
}
}
@@ -165,6 +174,17 @@ final class FileSystemFontProvider exten
}
/**
+ * Represents ignored fonts (i.e. bitmap fonts).
+ */
+ private static class FSIgnored extends FSFontInfo implements Serializable
+ {
+ private FSIgnored(File file, FontFormat format, String postScriptName)
+ {
+ super(file, format, postScriptName, null, 0, 0, 0, 0, 0, null, null);
+ }
+ }
+
+ /**
* Constructor.
*/
FileSystemFontProvider(FontCache cache)
@@ -176,6 +196,7 @@ final class FileSystemFontProvider exten
LOG.trace("Will search the local system for fonts");
}
+ // scan the local system for font files
List<File> files = new ArrayList<File>();
FontFileFinder fontFileFinder = new FontFileFinder();
List<URI> fonts = fontFileFinder.find();
@@ -189,18 +210,33 @@ final class FileSystemFontProvider exten
LOG.trace("Found " + files.size() + " fonts on the local system");
}
- // todo: loading all of these fonts is slow, can we cache this?
+ // load cached FontInfo objects
+ List<FSFontInfo> cachedInfos = loadCache(files);
+ if (cachedInfos.size() > 0)
+ {
+ fontInfoList.addAll(cachedInfos);
+ }
+ else
+ {
+ LOG.warn("Building font cache, this may take a while");
+ scanFonts(files);
+ saveCache();
+ }
+ }
+
+ private void scanFonts(List<File> files)
+ {
for (File file : files)
{
try
{
if (file.getPath().toLowerCase().endsWith(".ttf") ||
- file.getPath().toLowerCase().endsWith(".otf"))
+ file.getPath().toLowerCase().endsWith(".otf"))
{
addTrueTypeFont(file);
}
else if (file.getPath().toLowerCase().endsWith(".ttc") ||
- file.getPath().toLowerCase().endsWith(".otc"))
+ file.getPath().toLowerCase().endsWith(".otc"))
{
addTrueTypeCollection(file);
}
@@ -215,6 +251,73 @@ final class FileSystemFontProvider exten
}
}
}
+
+ private void saveCache()
+ {
+ // Get the preferences database for this package.
+ Preferences prefs = Preferences.userNodeForPackage(FileSystemFontProvider.class);
+
+ // To save, write the object to a byte array.
+ try
+ {
+ for (FSFontInfo fontInfo : fontInfoList)
+ {
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
+ ObjectOutputStream objectOut = new ObjectOutputStream(byteOut);
+ objectOut.writeObject(fontInfo); // write it to the stream
+ prefs.putByteArray(fontInfo.file.getAbsolutePath(), byteOut.toByteArray());
+ }
+ }
+ catch (IOException e)
+ {
+ LOG.error("Could not write to font cache", e);
+ }
+ LOG.warn("Finished building font cache, found " + fontInfoList.size() + " fonts");
+ }
+
+ private List<FSFontInfo> loadCache(List<File> files)
+ {
+ // Get the preferences database for this package.
+ Preferences prefs = Preferences.userNodeForPackage(FileSystemFontProvider.class);
+ List<FSFontInfo> results = new ArrayList<FSFontInfo>();
+ for (File file : files)
+ {
+ // The second argument is the default if the key isn't found.
+ byte[] stored = prefs.getByteArray(file.getAbsolutePath(), null);
+ if (stored != null)
+ {
+ try
+ {
+ ByteArrayInputStream byteIn = new ByteArrayInputStream(stored);
+ ObjectInputStream objectIn = new ObjectInputStream(byteIn);
+ Object object = objectIn.readObject();
+ if (object instanceof FSFontInfo)
+ {
+ FSFontInfo info = (FSFontInfo)object;
+ info.parent = this;
+ results.add(info);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ LOG.error("Error loading font cache, will be re-built", e);
+ break;
+ }
+ catch (IOException e)
+ {
+ LOG.error("Error loading font cache, will be re-built", e);
+ break;
+ }
+ }
+ else
+ {
+ // re-build the entire cache if we encounter un-cached fonts (could be optimised)
+ LOG.warn("New fonts found, font cache will be re-built");
+ return new ArrayList<FSFontInfo>();
+ }
+ }
+ return results;
+ }
/**
* Adds a TTC or OTC to the file cache. To reduce memory, the parsed font is not cached.
@@ -306,6 +409,7 @@ final class FileSystemFontProvider exten
// ignore bitmap fonts
if (ttf.getHeader() == null)
{
+ fontInfoList.add(new FSIgnored(file, FontFormat.TTF, ttf.getName()));
return;
}
int macStyle = ttf.getHeader().getMacStyle();
@@ -315,22 +419,22 @@ final class FileSystemFontProvider exten
{
format = "OTF";
CFFFont cff = ((OpenTypeFont)ttf).getCFF().getFont();
- PDCIDSystemInfo ros = null;
+ CIDSystemInfo ros = null;
if (cff instanceof CFFCIDFont)
{
CFFCIDFont cidFont = (CFFCIDFont)cff;
String registry = cidFont.getRegistry();
String ordering = cidFont.getOrdering();
int supplement = cidFont.getSupplement();
- ros = new PDCIDSystemInfo(registry, ordering, supplement);
+ ros = new CIDSystemInfo(registry, ordering, supplement);
}
fontInfoList.add(new FSFontInfo(file, FontFormat.OTF, ttf.getName(), ros,
usWeightClass, sFamilyClass, ulCodePageRange1, ulCodePageRange2,
- macStyle, panose));
+ macStyle, panose, this));
}
else
{
- PDCIDSystemInfo ros = null;
+ CIDSystemInfo ros = null;
if (ttf.getTableMap().containsKey("gcid"))
{
// Apple's AAT fonts have a "gcid" table with CID info
@@ -338,13 +442,13 @@ final class FileSystemFontProvider exten
String registryName = new String(bytes, 10, 64, Charsets.US_ASCII).trim();
String orderName = new String(bytes, 76, 64, Charsets.US_ASCII).trim();
int supplementVersion = bytes[140] << 8 & bytes[141];
- ros = new PDCIDSystemInfo(registryName, orderName, supplementVersion);
+ ros = new CIDSystemInfo(registryName, orderName, supplementVersion);
}
format = "TTF";
fontInfoList.add(new FSFontInfo(file, FontFormat.TTF, ttf.getName(), ros,
usWeightClass, sFamilyClass, ulCodePageRange1, ulCodePageRange2,
- macStyle, panose));
+ macStyle, panose, this));
}
if (LOG.isTraceEnabled())
@@ -386,7 +490,7 @@ final class FileSystemFontProvider exten
{
Type1Font type1 = Type1Font.createWithPFB(input);
fontInfoList.add(new FSFontInfo(pfbFile, FontFormat.PFB, type1.getName(),
- null, -1, -1, 0, 0, -1, null));
+ null, -1, -1, 0, 0, -1, null, this));
if (LOG.isTraceEnabled())
{
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java?rev=1690560&r1=1690559&r2=1690560&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/FontInfo.java Mon Jul 13 01:11:31 2015
@@ -39,7 +39,7 @@ public abstract class FontInfo
/**
* Returns the CIDSystemInfo associated with the font, if any.
*/
- public abstract PDCIDSystemInfo getCIDSystemInfo();
+ public abstract CIDSystemInfo getCIDSystemInfo();
/**
* Returns a new FontBox font instance for the font. Implementors of this method must not
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java?rev=1690560&r1=1690559&r2=1690560&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDCIDFontType2.java Mon Jul 13 01:11:31 2015
@@ -276,7 +276,7 @@ public class PDCIDFontType2 extends PDCI
LOG.warn("Trying to map multi-byte character using 'cmap', result will be poor");
}
- // a non-embedded font always has a cmap (otherwise ExternalFonts won't load it)
+ // a non-embedded font always has a cmap (otherwise FontMapper won't load it)
return cmap.getGlyphId(unicode.codePointAt(0));
}
}
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDPanoseClassification.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDPanoseClassification.java?rev=1690560&r1=1690559&r2=1690560&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDPanoseClassification.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/PDPanoseClassification.java Mon Jul 13 01:11:31 2015
@@ -17,13 +17,15 @@
package org.apache.pdfbox.pdmodel.font;
+import java.io.Serializable;
+
/**
* Represents a 10-byte PANOSE classification.
*
* @link http://www.monotype.com/services/pan2
* @author John Hewson
*/
-public class PDPanoseClassification
+public class PDPanoseClassification implements Serializable
{
private final byte[] bytes;