aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremias Maerki <jeremias@apache.org>2008-02-19 13:08:39 +0000
committerJeremias Maerki <jeremias@apache.org>2008-02-19 13:08:39 +0000
commitff6ac460f195633039ec5697519a1fa1228a038a (patch)
treefc864a27368217480320525974ed1e44d0049f11
parent8291833b461bfe86052573a4a091dd0a5a9db6ca (diff)
downloadxmlgraphics-fop-ff6ac460f195633039ec5697519a1fa1228a038a.tar.gz
xmlgraphics-fop-ff6ac460f195633039ec5697519a1fa1228a038a.zip
Bugzilla #44451:
The patch fixes two problems: - If distinct fonts declare the same font family name, the resulting font mapping is currently arbitrary; now, a name-similarity heuristic is used to prioritize the font mappings. - "Medium" and "demi" fonts are now recognized as "bold", solving several real-world problems (although this solution may be an oversimplification). Submitted by: Justus Piater <justus-bulk.at.piater.name> Patch modified by jeremias: - Style fixes (tab chars) - Refined font weight identification: medium -> 500, semi/demi -> 600 git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@629093 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--src/java/org/apache/fop/fonts/FontInfo.java42
-rw-r--r--src/java/org/apache/fop/fonts/FontResolver.java2
-rw-r--r--src/java/org/apache/fop/fonts/FontTriplet.java20
-rw-r--r--src/java/org/apache/fop/fonts/FontUtil.java25
-rw-r--r--src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java25
-rw-r--r--src/java/org/apache/fop/render/PrintRenderer.java2
-rw-r--r--status.xml4
7 files changed, 104 insertions, 16 deletions
diff --git a/src/java/org/apache/fop/fonts/FontInfo.java b/src/java/org/apache/fop/fonts/FontInfo.java
index af0fba579..ab11eb768 100644
--- a/src/java/org/apache/fop/fonts/FontInfo.java
+++ b/src/java/org/apache/fop/fonts/FontInfo.java
@@ -52,6 +52,10 @@ public class FontInfo {
/** look up a font-triplet to find a font-name */
private Map triplets; //Map<FontTriplet,String> (String = font key)
+ /** look up a font-triplet to find its priority
+ * (only used inside addFontProperties()) */
+ private Map tripletPriorities; //Map<FontTriplet,Integer>
+
/** look up a font-name to get a font (that implements FontMetrics at least) */
private Map fonts; //Map<String,FontMetrics> (String = font key)
@@ -68,6 +72,7 @@ public class FontInfo {
*/
public FontInfo() {
this.triplets = new java.util.HashMap();
+ this.tripletPriorities = new java.util.HashMap();
this.fonts = new java.util.HashMap();
this.usedFonts = new java.util.HashMap();
}
@@ -78,6 +83,8 @@ public class FontInfo {
* @return True if valid
*/
public boolean isSetupValid() {
+ //We're only called when font setup is done:
+ tripletPriorities = null; // candidate for garbage collection
return triplets.containsKey(Font.DEFAULT_FONT);
}
@@ -105,7 +112,42 @@ public class FontInfo {
if (log.isDebugEnabled()) {
log.debug("Registering: " + triplet + " under " + name);
}
+ String oldName = (String)triplets.get(triplet);
+ int newPriority = triplet.getPriority();
+ if (oldName != null) {
+ int oldPriority = ((Integer)tripletPriorities.get(triplet)).intValue();
+ if (oldPriority < newPriority) {
+ logDuplicateFont(triplet, false, oldName, oldPriority,
+ name, newPriority);
+ return;
+ } else {
+ logDuplicateFont(triplet, true, oldName, oldPriority,
+ name, newPriority);
+ }
+ }
this.triplets.put(triplet, name);
+ this.tripletPriorities.put(triplet, new Integer(newPriority));
+ }
+
+ /** Log warning about duplicate font triplets.
+ * @param triplet the duplicate font triplet
+ * @param replacing true iff the new font will replace the old one
+ * @param oldKey the old internal font name
+ * @param oldPriority the priority of the existing font mapping
+ * @param newKey the new internal font name
+ * @param newPriority the priority of the duplicate font mapping
+ */
+ private void logDuplicateFont(FontTriplet triplet, boolean replacing,
+ String oldKey, int oldPriority,
+ String newKey, int newPriority) {
+ if (log.isDebugEnabled()) {
+ log.debug(triplet
+ + (replacing ? ": Replacing " : ": Not replacing ")
+ + ((FontMetrics)fonts.get(triplets.get(triplet))).getFullName()
+ + " (" + oldPriority + ") by "
+ + ((FontMetrics)fonts.get(newKey)).getFullName()
+ + " (" + newPriority + ")");
+ }
}
/**
diff --git a/src/java/org/apache/fop/fonts/FontResolver.java b/src/java/org/apache/fop/fonts/FontResolver.java
index cd8e965fb..b054b054a 100644
--- a/src/java/org/apache/fop/fonts/FontResolver.java
+++ b/src/java/org/apache/fop/fonts/FontResolver.java
@@ -28,7 +28,7 @@ public interface FontResolver {
/**
* Called to resolve an URI to a Source instance. The base URI needed by the URIResolver's
- * resolve() method is defined to be implicitely available in this case. If the URI cannot
+ * resolve() method is defined to be implicitly available in this case. If the URI cannot
* be resolved, null is returned and it is assumed that the FontResolver implementation
* already warned the user about the problem.
* @param href An href attribute, which may be relative or absolute.
diff --git a/src/java/org/apache/fop/fonts/FontTriplet.java b/src/java/org/apache/fop/fonts/FontTriplet.java
index 66be36bc7..a7890ecbd 100644
--- a/src/java/org/apache/fop/fonts/FontTriplet.java
+++ b/src/java/org/apache/fop/fonts/FontTriplet.java
@@ -32,10 +32,11 @@ public class FontTriplet implements Comparable, Serializable {
private String name;
private String style;
private int weight;
+ private int priority; // priority of this triplet/font mapping
//This is only a cache
private transient String key;
-
+
/**
* Creates a new font triplet.
* @param name font name
@@ -43,9 +44,21 @@ public class FontTriplet implements Comparable, Serializable {
* @param weight font weight (100, 200, 300...800, 900)
*/
public FontTriplet(String name, String style, int weight) {
+ this(name, style, weight, 0);
+ }
+
+ /**
+ * Creates a new font triplet.
+ * @param name font name
+ * @param style font style (normal, italic etc.)
+ * @param weight font weight (100, 200, 300...800, 900)
+ * @param priority priority of this triplet/font mapping
+ */
+ public FontTriplet(String name, String style, int weight, int priority) {
this.name = name;
this.style = style;
this.weight = weight;
+ this.priority = priority;
}
/** @return the font name */
@@ -63,6 +76,11 @@ public class FontTriplet implements Comparable, Serializable {
return weight;
}
+ /** @return the priority of this triplet/font mapping */
+ public int getPriority() {
+ return priority;
+ }
+
private String getKey() {
if (this.key == null) {
//This caches the combined key
diff --git a/src/java/org/apache/fop/fonts/FontUtil.java b/src/java/org/apache/fop/fonts/FontUtil.java
index b9e891c9c..89ea132c0 100644
--- a/src/java/org/apache/fop/fonts/FontUtil.java
+++ b/src/java/org/apache/fop/fonts/FontUtil.java
@@ -77,14 +77,18 @@ public class FontUtil {
}
/** font constituent names which identify a font as being of "italic" style */
- private static final String[] ITALIC_WORDS = {"italic", "oblique"};
+ private static final String[] ITALIC_WORDS = {"italic", "oblique", "inclined"};
/** font constituent names which identify a font as being of "light" weight */
private static final String[] LIGHT_WORDS = {"light"};
+ /** font constituent names which identify a font as being of "medium" weight */
+ private static final String[] MEDIUM_WORDS = {"medium"};
+ /** font constituent names which identify a font as being of "demi/semi" weight */
+ private static final String[] DEMI_WORDS = {"demi", "semi"};
/** font constituent names which identify a font as being of "bold" weight */
private static final String[] BOLD_WORDS = {"bold"};
- /** font constituent names which identify a font as being of "bold" weight */
- private static final String[] EXTRA_BOLD_WORDS = {"extrabold", "black",
+ /** font constituent names which identify a font as being of "extra bold" weight */
+ private static final String[] EXTRA_BOLD_WORDS = {"extrabold", "extra bold", "black",
"heavy", "ultra", "super"};
/**
@@ -109,12 +113,27 @@ public class FontUtil {
public static int guessWeight(String fontName) {
// weight
int weight = Font.WEIGHT_NORMAL;
+
for (int i = 0; i < BOLD_WORDS.length; i++) {
if (fontName.indexOf(BOLD_WORDS[i]) != -1) {
weight = Font.WEIGHT_BOLD;
break;
}
}
+ for (int i = 0; i < MEDIUM_WORDS.length; i++) {
+ if (fontName.indexOf(MEDIUM_WORDS[i]) != -1) {
+ weight = Font.WEIGHT_NORMAL + 100; //500
+ break;
+ }
+ }
+ //Search for "semi/demi" before "light", but after "bold"
+ //(normally semi/demi-bold is meant, but it can also be semi/demi-light)
+ for (int i = 0; i < DEMI_WORDS.length; i++) {
+ if (fontName.indexOf(DEMI_WORDS[i]) != -1) {
+ weight = Font.WEIGHT_BOLD - 100; //600
+ break;
+ }
+ }
for (int i = 0; i < EXTRA_BOLD_WORDS.length; i++) {
if (fontName.indexOf(EXTRA_BOLD_WORDS[i]) != -1) {
weight = Font.WEIGHT_EXTRA_BOLD;
diff --git a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
index aaefc789b..1ec8a5528 100644
--- a/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
+++ b/src/java/org/apache/fop/fonts/autodetect/FontInfoFinder.java
@@ -31,6 +31,7 @@ import java.util.regex.Pattern;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.apache.fop.fonts.CachedFontInfo;
import org.apache.fop.fonts.CustomFont;
import org.apache.fop.fonts.EmbedFontInfo;
@@ -66,28 +67,32 @@ public class FontInfoFinder {
// default style and weight triplet vales (fallback)
String strippedName = stripQuotes(customFont.getStrippedFontName());
- String subName = customFont.getFontSubName();
- String searchName = strippedName.toLowerCase();
- if (subName != null) {
- searchName += subName.toLowerCase();
- }
-
+ //String subName = customFont.getFontSubName();
+ String fullName = stripQuotes(customFont.getFullName());
+ String searchName = fullName.toLowerCase();
+
String style = guessStyle(customFont, searchName);
int weight = FontUtil.guessWeight(searchName);
//Full Name usually includes style/weight info so don't use these traits
//If we still want to use these traits, we have to make FontInfo.fontLookup() smarter
- String fullName = stripQuotes(customFont.getFullName());
- triplets.add(new FontTriplet(fullName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL));
+ triplets.add(new FontTriplet(fullName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, 0));
if (!fullName.equals(strippedName)) {
- triplets.add(new FontTriplet(strippedName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL));
+ triplets.add(new FontTriplet(strippedName, Font.STYLE_NORMAL, Font.WEIGHT_NORMAL, 0));
}
Set familyNames = customFont.getFamilyNames();
Iterator iter = familyNames.iterator();
while (iter.hasNext()) {
String familyName = stripQuotes((String)iter.next());
if (!fullName.equals(familyName)) {
- triplets.add(new FontTriplet(familyName, style, weight));
+ /* Heuristic:
+ * The more similar the family name to the full font name,
+ * the higher the priority of its triplet.
+ * (Lower values indicate higher priorities.) */
+ int priority = fullName.startsWith(familyName)
+ ? fullName.length() - familyName.length()
+ : fullName.length();
+ triplets.add(new FontTriplet(familyName, style, weight, priority));
}
}
}
diff --git a/src/java/org/apache/fop/render/PrintRenderer.java b/src/java/org/apache/fop/render/PrintRenderer.java
index f725bd711..6f1bfeea6 100644
--- a/src/java/org/apache/fop/render/PrintRenderer.java
+++ b/src/java/org/apache/fop/render/PrintRenderer.java
@@ -78,7 +78,7 @@ public abstract class PrintRenderer extends AbstractRenderer {
}
/**
- * Returns the internal font key fot a font triplet coming from the area tree
+ * Returns the internal font key for a font triplet coming from the area tree
* @param area the area from which to retrieve the font triplet information
* @return the internal font key (F1, F2 etc.) or null if not found
*/
diff --git a/status.xml b/status.xml
index d6693d2cd..6236a7c56 100644
--- a/status.xml
+++ b/status.xml
@@ -28,6 +28,10 @@
<changes>
<release version="FOP Trunk">
+ <action context="Fonts" dev="JM" type="fix" fixed-bug="44451" due-to="Justus Piater">
+ Improved the font auto-detection so fonts accessed using the font-family name are
+ selected with higher accuracy.
+ </action>
<action context="API" dev="JM" type="remove">
Removed deprecated methods in the "apps" package that were left-overs from the API
discussions.