Linux: fixed/improved detection of user font settings (issue #309)

This commit is contained in:
Karl Tauber
2021-05-04 22:41:00 +02:00
parent 5000186f85
commit 9edaf58929
2 changed files with 53 additions and 8 deletions

View File

@@ -48,6 +48,7 @@ FlatLaf Change Log
themes. themes.
- Native window decorations: Fixed occasional double window title bar when - Native window decorations: Fixed occasional double window title bar when
creating many frames or dialogs. (issue #315) creating many frames or dialogs. (issue #315)
- Linux: Fixed/improved detection of user font settings. (issue #309)
## 1.1.2 ## 1.1.2

View File

@@ -55,25 +55,39 @@ class LinuxFontPolicy
String family = ""; String family = "";
int style = Font.PLAIN; int style = Font.PLAIN;
int size = 10; double dsize = 10;
// parse pango font description
// see https://developer.gnome.org/pango/1.46/pango-Fonts.html#pango-font-description-from-string
StringTokenizer st = new StringTokenizer( (String) fontName ); StringTokenizer st = new StringTokenizer( (String) fontName );
while( st.hasMoreTokens() ) { while( st.hasMoreTokens() ) {
String word = st.nextToken(); String word = st.nextToken();
if( word.equalsIgnoreCase( "italic" ) ) // remove trailing ',' (e.g. in "Ubuntu Condensed, 11" or "Ubuntu Condensed, Bold 11")
if( word.endsWith( "," ) )
word = word.substring( 0, word.length() - 1 ).trim();
String lword = word.toLowerCase();
if( lword.equals( "italic" ) || lword.equals( "oblique" ) )
style |= Font.ITALIC; style |= Font.ITALIC;
else if( word.equalsIgnoreCase( "bold" ) ) else if( lword.equals( "bold" ) )
style |= Font.BOLD; style |= Font.BOLD;
else if( Character.isDigit( word.charAt( 0 ) ) ) { else if( Character.isDigit( word.charAt( 0 ) ) ) {
try { try {
size = Integer.parseInt( word ); dsize = Double.parseDouble( word );
} catch( NumberFormatException ex ) { } catch( NumberFormatException ex ) {
// ignore // ignore
} }
} else } else {
// remove '-' from "Semi-Bold", "Extra-Light", etc
if( lword.startsWith( "semi-" ) || lword.startsWith( "demi-" ) )
word = word.substring( 0, 4 ) + word.substring( 5 );
else if( lword.startsWith( "extra-" ) || lword.startsWith( "ultra-" ) )
word = word.substring( 0, 5 ) + word.substring( 6 );
family = family.isEmpty() ? word : (family + ' ' + word); family = family.isEmpty() ? word : (family + ' ' + word);
} }
}
// Ubuntu font is rendered poorly (except if running in JetBrains VM) // Ubuntu font is rendered poorly (except if running in JetBrains VM)
// --> use Liberation Sans font // --> use Liberation Sans font
@@ -83,8 +97,8 @@ class LinuxFontPolicy
family = "Liberation Sans"; family = "Liberation Sans";
// scale font size // scale font size
double dsize = size * getGnomeFontScale(); dsize *= getGnomeFontScale();
size = (int) (dsize + 0.5); int size = (int) (dsize + 0.5);
if( size < 1 ) if( size < 1 )
size = 1; size = 1;
@@ -93,7 +107,37 @@ class LinuxFontPolicy
if( logicalFamily != null ) if( logicalFamily != null )
family = logicalFamily; family = logicalFamily;
return createFont( family, style, size, dsize ); return createFontEx( family, style, size, dsize );
}
/**
* Create a font for the given family, style and size.
* If the font family does not match any font on the system,
* then the last word (usually a font weight) from the family name is removed and tried again.
* E.g. family 'URW Bookman Light' is not found, but 'URW Bookman' is found.
* If still not found, then font of family 'Dialog' is returned.
*/
private static Font createFontEx( String family, int style, int size, double dsize ) {
for(;;) {
Font font = createFont( family, style, size, dsize );
// if the font family does not match any font on the system, "Dialog" family is returned
if( !"Dialog".equals( font.getFamily() ) || "Dialog".equals( family ) )
return font;
// find last word in family
int index = family.lastIndexOf( ' ' );
if( index < 0 )
return createFont( "Dialog", style, size, dsize );;
// check whether last work contains some font weight (e.g. Ultra-Bold or Heavy)
String lastWord = family.substring( index + 1 ).toLowerCase();
if( lastWord.contains( "bold" ) || lastWord.contains( "heavy" ) || lastWord.contains( "black" ) )
style |= Font.BOLD;
// remove last word from family and try again
family = family.substring( 0, index );
}
} }
private static Font createFont( String family, int style, int size, double dsize ) { private static Font createFont( String family, int style, int size, double dsize ) {