|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package sun.font; |
|
|
|
import java.io.File; |
|
import java.awt.Font; |
|
import java.io.IOException; |
|
import java.util.Collection; |
|
import java.util.HashMap; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
import java.util.Locale; |
|
|
|
public class FontFamily { |
|
|
|
private static ConcurrentHashMap<String, FontFamily> |
|
familyNameMap = new ConcurrentHashMap<String, FontFamily>(); |
|
private static HashMap<String, FontFamily> allLocaleNames; |
|
|
|
protected String familyName; |
|
protected Font2D plain; |
|
protected Font2D bold; |
|
protected Font2D italic; |
|
protected Font2D bolditalic; |
|
protected boolean logicalFont = false; |
|
protected int familyRank; |
|
|
|
public static FontFamily getFamily(String name) { |
|
return familyNameMap.get(name.toLowerCase(Locale.ENGLISH)); |
|
} |
|
|
|
public static String[] getAllFamilyNames() { |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
static void remove(Font2D font2D) { |
|
|
|
String name = font2D.getFamilyName(Locale.ENGLISH); |
|
FontFamily family = getFamily(name); |
|
if (family == null) { |
|
return; |
|
} |
|
if (family.plain == font2D) { |
|
family.plain = null; |
|
} |
|
if (family.bold == font2D) { |
|
family.bold = null; |
|
} |
|
if (family.italic == font2D) { |
|
family.italic = null; |
|
} |
|
if (family.bolditalic == font2D) { |
|
family.bolditalic = null; |
|
} |
|
if (family.plain == null && family.bold == null && |
|
family.plain == null && family.bold == null) { |
|
familyNameMap.remove(name); |
|
} |
|
} |
|
|
|
public FontFamily(String name, boolean isLogFont, int rank) { |
|
logicalFont = isLogFont; |
|
familyName = name; |
|
familyRank = rank; |
|
familyNameMap.put(name.toLowerCase(Locale.ENGLISH), this); |
|
} |
|
|
|
|
|
|
|
*/ |
|
FontFamily(String name) { |
|
logicalFont = false; |
|
familyName = name; |
|
familyRank = Font2D.DEFAULT_RANK; |
|
} |
|
|
|
public String getFamilyName() { |
|
return familyName; |
|
} |
|
|
|
public int getRank() { |
|
return familyRank; |
|
} |
|
|
|
private boolean isFromSameSource(Font2D font) { |
|
if (!(font instanceof FileFont)) { |
|
return false; |
|
} |
|
|
|
FileFont existingFont = null; |
|
if (plain instanceof FileFont) { |
|
existingFont = (FileFont)plain; |
|
} else if (bold instanceof FileFont) { |
|
existingFont = (FileFont)bold; |
|
} else if (italic instanceof FileFont) { |
|
existingFont = (FileFont)italic; |
|
} else if (bolditalic instanceof FileFont) { |
|
existingFont = (FileFont)bolditalic; |
|
} |
|
// A family isn't created until there's a font. |
|
// So if we didn't find a file font it means this |
|
|
|
if (existingFont == null) { |
|
return false; |
|
} |
|
File existDir = (new File(existingFont.platName)).getParentFile(); |
|
|
|
FileFont newFont = (FileFont)font; |
|
File newDir = (new File(newFont.platName)).getParentFile(); |
|
if (existDir != null) { |
|
try { |
|
existDir = existDir.getCanonicalFile(); |
|
} catch (IOException ignored) {} |
|
} |
|
if (newDir != null) { |
|
try { |
|
newDir = newDir.getCanonicalFile(); |
|
} catch (IOException ignored) {} |
|
} |
|
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()) { |
|
String msg; |
|
if (font instanceof CompositeFont) { |
|
msg = "Request to add " + font.getFamilyName(null) + |
|
" with style " + style + " to family " + familyName; |
|
} else { |
|
msg = "Request to add " + font + |
|
" with style " + style + " to family " + this; |
|
} |
|
FontUtilities.getLogger().info(msg); |
|
} |
|
|
|
|
|
*/ |
|
if ((font.getRank() > familyRank) && !isFromSameSource(font)) { |
|
if (FontUtilities.isLogging()) { |
|
FontUtilities.getLogger() |
|
.warning("Rejecting adding " + font + |
|
" of lower rank " + font.getRank() + |
|
" to family " + this + |
|
" of rank " + familyRank); |
|
} |
|
return; |
|
} |
|
|
|
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; |
|
} |
|
} |
|
|
|
public Font2D getFontWithExactStyleMatch(int style) { |
|
|
|
switch (style) { |
|
|
|
case Font.PLAIN: |
|
return plain; |
|
|
|
case Font.BOLD: |
|
return bold; |
|
|
|
case Font.ITALIC: |
|
return italic; |
|
|
|
case Font.BOLD|Font.ITALIC: |
|
return bolditalic; |
|
|
|
default: |
|
return null; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public Font2D getFont(int style) { |
|
|
|
switch (style) { |
|
|
|
case Font.PLAIN: |
|
return plain; |
|
|
|
case Font.BOLD: |
|
if (bold != null) { |
|
return bold; |
|
} else if (plain != null && plain.canDoStyle(style)) { |
|
return plain; |
|
} else { |
|
return null; |
|
} |
|
|
|
case Font.ITALIC: |
|
if (italic != null) { |
|
return italic; |
|
} else if (plain != null && plain.canDoStyle(style)) { |
|
return plain; |
|
} else { |
|
return null; |
|
} |
|
|
|
case Font.BOLD|Font.ITALIC: |
|
if (bolditalic != null) { |
|
return bolditalic; |
|
} else if (bold != null && bold.canDoStyle(style)) { |
|
return bold; |
|
} else if (italic != null && italic.canDoStyle(style)) { |
|
return italic; |
|
} else if (plain != null && plain.canDoStyle(style)) { |
|
return plain; |
|
} else { |
|
return null; |
|
} |
|
default: |
|
return null; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
Font2D getClosestStyle(int style) { |
|
|
|
switch (style) { |
|
|
|
* then a italic one, finally a bold italic one */ |
|
case Font.PLAIN: |
|
if (bold != null) { |
|
return bold; |
|
} else if (italic != null) { |
|
return italic; |
|
} else { |
|
return bolditalic; |
|
} |
|
|
|
|
|
* then a bold italic one, finally an italic one */ |
|
case Font.BOLD: |
|
if (plain != null) { |
|
return plain; |
|
} else if (bolditalic != null) { |
|
return bolditalic; |
|
} else { |
|
return italic; |
|
} |
|
|
|
|
|
* then a plain one, finally an bold one */ |
|
case Font.ITALIC: |
|
if (bolditalic != null) { |
|
return bolditalic; |
|
} else if (plain != null) { |
|
return plain; |
|
} else { |
|
return bold; |
|
} |
|
|
|
case Font.BOLD|Font.ITALIC: |
|
if (italic != null) { |
|
return italic; |
|
} else if (bold != null) { |
|
return bold; |
|
} else { |
|
return plain; |
|
} |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
*/ |
|
static synchronized void addLocaleNames(FontFamily family, String[] names){ |
|
if (allLocaleNames == null) { |
|
allLocaleNames = new HashMap<String, FontFamily>(); |
|
} |
|
for (int i=0; i<names.length; i++) { |
|
allLocaleNames.put(names[i].toLowerCase(), family); |
|
} |
|
} |
|
|
|
public static synchronized FontFamily getLocaleFamily(String name) { |
|
if (allLocaleNames == null) { |
|
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 + |
|
" italic=" + italic + |
|
" bolditalic=" + bolditalic; |
|
|
|
} |
|
|
|
} |