src/java.desktop/share/classes/sun/font/FontFamily.java
Print this page
@@ -25,10 +25,11 @@
package sun.font;
import java.io.File;
import java.awt.Font;
+import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Locale;
public class FontFamily {
@@ -132,11 +133,102 @@
FileFont newFont = (FileFont)font;
File newDir = (new File(newFont.platName)).getParentFile();
return java.util.Objects.equals(newDir, existDir);
}
+ /*
+ * We want a family to be of the same width and prefer medium/normal width.
+ * Once we find a particular width we accept more of the same width
+ * until we find one closer to normal when we 'evict' all existing fonts.
+ * So once we see a 'normal' width font we evict all members that are not
+ * normal width and then accept only new ones that are normal width.
+ *
+ * Once a font passes the width test we subject it to the weight test.
+ * For Plain we target the weight the closest that is <= NORMAL (400)
+ * For Bold we target the weight that is closest to BOLD (700).
+ *
+ * In the future, rather than discarding these fonts, we should
+ * extend the family to include these so lookups on these properties
+ * can locate them, as presently they will only be located by full name
+ * based lookup.
+ */
+
+ private int familyWidth = 0;
+ private boolean preferredWidth(Font2D font) {
+
+ int newWidth = font.getWidth();
+
+ if (familyWidth == 0) {
+ familyWidth = newWidth;
+ return true;
+ }
+
+ if (newWidth == familyWidth) {
+ return true;
+ }
+
+ if (Math.abs(Font2D.FWIDTH_NORMAL - newWidth) <
+ Math.abs(Font2D.FWIDTH_NORMAL - familyWidth))
+ {
+ if (FontUtilities.debugFonts()) {
+ FontUtilities.getLogger().info(
+ "Found more preferred width. New width = " + newWidth +
+ " Old width = " + familyWidth + " in font " + font +
+ " nulling out fonts plain: " + plain + " bold: " + bold +
+ " italic: " + italic + " bolditalic: " + bolditalic);
+ }
+ familyWidth = newWidth;
+ plain = bold = italic = bolditalic = null;
+ return true;
+ } else if (FontUtilities.debugFonts()) {
+ FontUtilities.getLogger().info(
+ "Family rejecting font " + font +
+ " of less preferred width " + newWidth);
+ }
+ return false;
+ }
+
+ private boolean closerWeight(Font2D currFont, Font2D font, int style) {
+ if (familyWidth != font.getWidth()) {
+ return false;
+ }
+
+ if (currFont == null) {
+ return true;
+ }
+
+ if (FontUtilities.debugFonts()) {
+ FontUtilities.getLogger().info(
+ "New weight for style " + style + ". Curr.font=" + currFont +
+ " New font="+font+" Curr.weight="+ + currFont.getWeight()+
+ " New weight="+font.getWeight());
+ }
+
+ int newWeight = font.getWeight();
+ switch (style) {
+ case Font.PLAIN:
+ case Font.ITALIC:
+ return (newWeight <= Font2D.FWEIGHT_NORMAL &&
+ newWeight > currFont.getWeight());
+
+ case Font.BOLD:
+ case Font.BOLD|Font.ITALIC:
+ return (Math.abs(newWeight - Font2D.FWEIGHT_BOLD) <
+ Math.abs(currFont.getWeight() - Font2D.FWEIGHT_BOLD));
+
+ default:
+ return false;
+ }
+ }
+
public void setFont(Font2D font, int style) {
+
+ if (FontUtilities.isLogging()) {
+ FontUtilities.getLogger().info(
+ "Request to add " + font + " with style " + style +
+ " to family " + this);
+ }
/* Allow a lower-rank font only if its a file font
* from the exact same source as any previous font.
*/
if ((font.getRank() > familyRank) && !isFromSameSource(font)) {
if (FontUtilities.isLogging()) {
@@ -150,23 +242,31 @@
}
switch (style) {
case Font.PLAIN:
+ if (preferredWidth(font) && closerWeight(plain, font, style)) {
plain = font;
+ }
break;
case Font.BOLD:
+ if (preferredWidth(font) && closerWeight(bold, font, style)) {
bold = font;
+ }
break;
case Font.ITALIC:
+ if (preferredWidth(font) && closerWeight(italic, font, style)) {
italic = font;
+ }
break;
case Font.BOLD|Font.ITALIC:
+ if (preferredWidth(font) && closerWeight(bolditalic, font, style)) {
bolditalic = font;
+ }
break;
default:
break;
}
@@ -314,10 +414,15 @@
return null;
}
return allLocaleNames.get(name.toLowerCase());
}
+ public static FontFamily[] getAllFontFamilies() {
+ Collection<FontFamily> families = familyNameMap.values();
+ return families.toArray(new FontFamily[0]);
+ }
+
public String toString() {
return
"Font family: " + familyName +
" plain="+plain+
" bold=" + bold +