You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2020/06/13 08:45:37 UTC
svn commit: r1878795 -
/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Standard14Fonts.java
Author: tilman
Date: Sat Jun 13 08:45:36 2020
New Revision: 1878795
URL: http://svn.apache.org/viewvc?rev=1878795&view=rev
Log:
PDFBOX-4875: lazy loading of standard 14 fonts, by Alfred Faltiska
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Standard14Fonts.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Standard14Fonts.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Standard14Fonts.java?rev=1878795&r1=1878794&r2=1878795&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Standard14Fonts.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/font/Standard14Fonts.java Sat Jun 13 08:45:36 2020
@@ -22,7 +22,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.fontbox.afm.AFMParser;
@@ -36,125 +35,183 @@ import org.apache.fontbox.afm.FontMetric
*/
final class Standard14Fonts
{
- private static final Set<String> STANDARD_14_NAMES = new HashSet<>(34);
- private static final Map<String, String> STANDARD_14_MAPPING = new HashMap<>(34);
- private static final Map<String, FontMetrics> STANDARD14_AFM_MAP = new HashMap<>(34);
+ /**
+ * Contains all base names and alias names for the known fonts.
+ * For base fonts both the key and the value will be the base name.
+ * For aliases, the key is an alias, and the value is a base name.
+ * We want a single lookup in the map to find the font both by a base name or an alias.
+ */
+ private static final Map<String, String> ALIASES = new HashMap<>(38);
+
+ /**
+ * Contains the font metrics for the base fonts.
+ * The key is a base font name, value is a FontMetrics instance.
+ * Metrics are loaded into this map on demand, only if needed.
+ * @see #getAFM
+ */
+ private static final Map<String, FontMetrics> FONTS = new HashMap<>(14);
+
static
{
- try
+ // the 14 standard fonts
+ mapName("Courier-Bold");
+ mapName("Courier-BoldOblique");
+ mapName("Courier");
+ mapName("Courier-Oblique");
+ mapName("Helvetica");
+ mapName("Helvetica-Bold");
+ mapName("Helvetica-BoldOblique");
+ mapName("Helvetica-Oblique");
+ mapName("Symbol");
+ mapName("Times-Bold");
+ mapName("Times-BoldItalic");
+ mapName("Times-Italic");
+ mapName("Times-Roman");
+ mapName("ZapfDingbats");
+
+ // alternative names from Adobe Supplement to the ISO 32000
+ mapName("CourierCourierNew", "Courier");
+ mapName("CourierNew", "Courier");
+ mapName("CourierNew,Italic", "Courier-Oblique");
+ mapName("CourierNew,Bold", "Courier-Bold");
+ mapName("CourierNew,BoldItalic", "Courier-BoldOblique");
+ mapName("Arial", "Helvetica");
+ mapName("Arial,Italic", "Helvetica-Oblique");
+ mapName("Arial,Bold", "Helvetica-Bold");
+ mapName("Arial,BoldItalic", "Helvetica-BoldOblique");
+ mapName("TimesNewRoman", "Times-Roman");
+ mapName("TimesNewRoman,Italic", "Times-Italic");
+ mapName("TimesNewRoman,Bold", "Times-Bold");
+ mapName("TimesNewRoman,BoldItalic", "Times-BoldItalic");
+
+ // Acrobat treats these fonts as "standard 14" too (at least Acrobat preflight says so)
+ mapName("Symbol,Italic", "Symbol");
+ mapName("Symbol,Bold", "Symbol");
+ mapName("Symbol,BoldItalic", "Symbol");
+ mapName("Times", "Times-Roman");
+ mapName("Times,Italic", "Times-Italic");
+ mapName("Times,Bold", "Times-Bold");
+ mapName("Times,BoldItalic", "Times-BoldItalic");
+
+ // PDFBOX-3457: PDF.js file bug864847.pdf
+ mapName("ArialMT", "Helvetica");
+ mapName("Arial-ItalicMT", "Helvetica-Oblique");
+ mapName("Arial-BoldMT", "Helvetica-Bold");
+ mapName("Arial-BoldItalicMT", "Helvetica-BoldOblique");
+ }
+
+ private Standard14Fonts()
+ {
+ }
+
+ /**
+ * Loads the metrics for the base font specified by name. Metric file must exist in the pdfbox
+ * jar under /org/apache/pdfbox/resources/afm/
+ *
+ * @param fontName one of the standard 14 font names for which to lod the metrics.
+ * @throws IllegalArgumentException if no metrics exist for that font.
+ */
+ private static void loadMetrics(String fontName)
+ {
+ String resourceName = "/org/apache/pdfbox/resources/afm/" + fontName + ".afm";
+ try (InputStream resourceAsStream = PDType1Font.class.getResourceAsStream(resourceName);
+ InputStream afmStream = new BufferedInputStream(resourceAsStream))
{
- addAFM("Courier-Bold");
- addAFM("Courier-BoldOblique");
- addAFM("Courier");
- addAFM("Courier-Oblique");
- addAFM("Helvetica");
- addAFM("Helvetica-Bold");
- addAFM("Helvetica-BoldOblique");
- addAFM("Helvetica-Oblique");
- addAFM("Symbol");
- addAFM("Times-Bold");
- addAFM("Times-BoldItalic");
- addAFM("Times-Italic");
- addAFM("Times-Roman");
- addAFM("ZapfDingbats");
-
- // alternative names from Adobe Supplement to the ISO 32000
- addAFM("CourierCourierNew", "Courier");
- addAFM("CourierNew", "Courier");
- addAFM("CourierNew,Italic", "Courier-Oblique");
- addAFM("CourierNew,Bold", "Courier-Bold");
- addAFM("CourierNew,BoldItalic", "Courier-BoldOblique");
- addAFM("Arial", "Helvetica");
- addAFM("Arial,Italic", "Helvetica-Oblique");
- addAFM("Arial,Bold", "Helvetica-Bold");
- addAFM("Arial,BoldItalic", "Helvetica-BoldOblique");
- addAFM("TimesNewRoman", "Times-Roman");
- addAFM("TimesNewRoman,Italic", "Times-Italic");
- addAFM("TimesNewRoman,Bold", "Times-Bold");
- addAFM("TimesNewRoman,BoldItalic", "Times-BoldItalic");
-
- // Acrobat treats these fonts as "standard 14" too (at least Acrobat preflight says so)
- addAFM("Symbol,Italic", "Symbol");
- addAFM("Symbol,Bold", "Symbol");
- addAFM("Symbol,BoldItalic", "Symbol");
- addAFM("Times", "Times-Roman");
- addAFM("Times,Italic", "Times-Italic");
- addAFM("Times,Bold", "Times-Bold");
- addAFM("Times,BoldItalic", "Times-BoldItalic");
-
- // PDFBOX-3457: PDF.js file bug864847.pdf
- addAFM("ArialMT", "Helvetica");
- addAFM("Arial-ItalicMT", "Helvetica-Oblique");
- addAFM("Arial-BoldMT", "Helvetica-Bold");
- addAFM("Arial-BoldItalicMT", "Helvetica-BoldOblique");
+ AFMParser parser = new AFMParser(afmStream);
+ FontMetrics metric = parser.parse(true);
+ FONTS.put(fontName, metric);
}
catch (IOException e)
{
- throw new RuntimeException(e);
+ throw new IllegalArgumentException(e);
}
}
- private Standard14Fonts()
+ /**
+ * Adds a standard font name to the map of known aliases, to simplify the logic of finding
+ * font metrics by name. We want a single lookup in the map to find the font both by a base name or
+ * an alias.
+ *
+ * @see #getAFM
+ * @param baseName the base name of the font; must be one of the 14 standard fonts
+ */
+ private static void mapName(String baseName)
{
+ ALIASES.put(baseName, baseName);
}
- private static void addAFM(String fontName) throws IOException
+ /**
+ * Adds an alias name for a standard font to the map of known aliases to the map of aliases
+ * (alias as key, standard name as value). We want a single lookup in the map to find the font
+ * both by a base name or an alias.
+ *
+ * @param alias an alias for the font
+ * @param baseName the base name of the font; must be one of the 14 standard fonts
+ */
+ private static void mapName(String alias, String baseName)
{
- addAFM(fontName, fontName);
+ ALIASES.put(alias, baseName);
}
- private static void addAFM(String fontName, String afmName) throws IOException
+ /**
+ * Returns the metrics for font specified by fontName. Loads the font metrics if not already
+ * loaded.
+ *
+ * @param fontName name of font; either a base name or alias
+ * @return the font metrics or null if the name is not one of the known names
+ * @throws IllegalArgumentException if no metrics exist for that font.
+ */
+ public static FontMetrics getAFM(String fontName)
{
- STANDARD_14_NAMES.add(fontName);
- STANDARD_14_MAPPING.put(fontName, afmName);
-
- if (STANDARD14_AFM_MAP.containsKey(afmName))
+ String baseName = ALIASES.get(fontName);
+ if (baseName == null)
{
- STANDARD14_AFM_MAP.put(fontName, STANDARD14_AFM_MAP.get(afmName));
+ return null;
}
- String resourceName = "/org/apache/pdfbox/resources/afm/" + afmName + ".afm";
- try (InputStream resourceAsStream = PDType1Font.class.getResourceAsStream(resourceName);
- InputStream afmStream = new BufferedInputStream(resourceAsStream))
+ if (FONTS.get(baseName) == null)
{
- AFMParser parser = new AFMParser(afmStream);
- FontMetrics metric = parser.parse(true);
- STANDARD14_AFM_MAP.put(fontName, metric);
+ // baseName is a reference to a string that was statically
+ // put in the ALIASES map so we can safely synchronize on it
+ synchronized (baseName)
+ {
+ if (FONTS.get(baseName) == null)
+ {
+ loadMetrics(baseName);
+ }
+ }
}
- }
- /**
- * Returns the AFM for the given font.
- * @param baseName base name of font
- */
- public static FontMetrics getAFM(String baseName)
- {
- return STANDARD14_AFM_MAP.get(baseName);
+ return FONTS.get(baseName);
}
/**
- * Returns true if the given font name a Standard 14 font.
- * @param baseName base name of font
+ * Returns true if the given font name is one of the known names, including alias.
+ *
+ * @param fontName the name of font, either a base name or alias
+ * @return true if the name is one of the known names
*/
- public static boolean containsName(String baseName)
+ public static boolean containsName(String fontName)
{
- return STANDARD_14_NAMES.contains(baseName);
+ return ALIASES.containsKey(fontName);
}
/**
- * Returns the set of Standard 14 font names, including additional names.
+ * Returns the set of known font names, including aliases.
*/
public static Set<String> getNames()
{
- return Collections.unmodifiableSet(STANDARD_14_NAMES);
+ return Collections.unmodifiableSet(ALIASES.keySet());
}
/**
- * Returns the name of the actual font which the given font name maps to.
- * @param baseName base name of font
+ * Returns the base name of the font which the given font name maps to.
+ *
+ * @param fontName name of font, either a base name or an alias
+ * @return the base name or null if this is not one of the known names
*/
- public static String getMappedFontName(String baseName)
+ public static String getMappedFontName(String fontName)
{
- return STANDARD_14_MAPPING.get(baseName);
+ return ALIASES.get(fontName);
}
}