Merge PR #615: Fonts: lazy loading

This commit is contained in:
Karl Tauber
2022-11-26 16:24:54 +01:00
25 changed files with 537 additions and 126 deletions

View File

@@ -78,6 +78,7 @@ import com.formdev.flatlaf.ui.FlatPopupFactory;
import com.formdev.flatlaf.ui.FlatRootPaneUI;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
import com.formdev.flatlaf.util.FontUtils;
import com.formdev.flatlaf.util.GrayFilter;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.MultiResolutionImageSupport;
@@ -663,6 +664,9 @@ public abstract class FlatLaf
}
static FontUIResource createCompositeFont( String family, int style, int size ) {
// load lazy font family
FontUtils.loadFontFamily( family );
// using StyleContext.getFont() here because it uses
// sun.font.FontUtilities.getCompositeFontUIResource()
// and creates a composite font that is able to display all Unicode characters

View File

@@ -0,0 +1,153 @@
/*
* Copyright 2022 FormDev Software GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.formdev.flatlaf.util;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.GraphicsEnvironment;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.swing.plaf.UIResource;
import javax.swing.text.StyleContext;
/**
* Utility methods for fonts.
*
* @author Karl Tauber
* @since 3
*/
public class FontUtils
{
private static Map<String, Runnable> loadersMap;
/**
* Gets a composite font for the given family, style and size.
* A composite font that is able to display all Unicode characters.
* The font family is loaded if necessary via {@link #loadFontFamily(String)}.
* <p>
* To get fonts derived from returned fonts, it is recommended to use one of the
* {@link Font#deriveFont} methods instead of invoking this method.
*/
public static Font getCompositeFont( String family, int style, int size ) {
loadFontFamily( family );
// using StyleContext.getFont() here because it uses
// sun.font.FontUtilities.getCompositeFontUIResource()
// and creates a composite font that is able to display all Unicode characters
Font font = StyleContext.getDefaultStyleContext().getFont( family, style, size );
// always return non-UIResource font to avoid side effects when using font
// because Swing uninstalls UIResource fonts when switching L&F
// (StyleContext.getFont() may return a UIResource)
if( font instanceof UIResource )
font = font.deriveFont( font.getStyle() );
return font;
}
/**
* Registers a font family for lazy loading via {@link #loadFontFamily(String)}.
* <p>
* The given runnable is invoked when the given font family should be loaded.
* The runnable should invoke {@link #installFont(URL)} to load and register font(s)
* for the family.
* A family may consist of up to four font files for the supported font styles:
* regular (plain), italic, bold and bold-italic.
*/
public static void registerFontFamilyLoader( String family, Runnable loader ) {
if( loadersMap == null )
loadersMap = new HashMap<>();
loadersMap.put( family, loader );
}
/**
* Loads a font family previously registered via {@link #registerFontFamilyLoader(String, Runnable)}.
* If the family is already loaded or no londer is registered for that family, nothing happens.
*/
public static void loadFontFamily( String family ) {
if( !hasLoaders() )
return;
Runnable loader = loadersMap.remove( family );
if( loader != null )
loader.run();
if( loadersMap.isEmpty() )
loadersMap = null;
}
/**
* Loads a font file from the given url and registers it in the graphics environment.
* Uses {@link Font#createFont(int, InputStream)} and {@link GraphicsEnvironment#registerFont(Font)}.
*/
public static boolean installFont( URL url ) {
try( InputStream in = url.openStream() ) {
Font font = Font.createFont( Font.TRUETYPE_FONT, in );
return GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont( font );
} catch( FontFormatException | IOException ex ) {
LoggingFacade.INSTANCE.logSevere( "FlatLaf: Failed to install font " + url, ex );
return false;
}
}
/**
* Returns all font familiy names available in the graphics environment.
* This invokes {@link GraphicsEnvironment#getAvailableFontFamilyNames()} and
* appends families registered for lazy loading via {@link #registerFontFamilyLoader(String, Runnable)}
* to the result.
*/
public static String[] getAvailableFontFamilyNames() {
String[] availableFontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
if( !hasLoaders() )
return availableFontFamilyNames;
// append families that are not yet loaded
ArrayList<String> result = new ArrayList<>( availableFontFamilyNames.length + loadersMap.size() );
for( String name : availableFontFamilyNames )
result.add( name );
for( String name : loadersMap.keySet() ) {
if( !result.contains( name ) )
result.add( name );
}
return result.toArray( new String[result.size()] );
}
/**
* Returns all fonts available in the graphics environment.
* This first loads all families registered for lazy loading via {@link #registerFontFamilyLoader(String, Runnable)}
* and then invokes {@link GraphicsEnvironment#getAllFonts()}.
*/
public static Font[] getAllFonts() {
if( hasLoaders() ) {
// load all registered families
String[] families = loadersMap.keySet().toArray( new String[loadersMap.size()] );
for( String family : families )
loadFontFamily( family );
}
return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
}
private static boolean hasLoaders() {
return loadersMap != null && !loadersMap.isEmpty();
}
}

View File

@@ -23,6 +23,7 @@ dependencies {
implementation( project( ":flatlaf-core" ) )
implementation( project( ":flatlaf-extras" ) )
implementation( project( ":flatlaf-fonts-inter" ) )
implementation( project( ":flatlaf-fonts-jetbrains-mono" ) )
implementation( project( ":flatlaf-fonts-roboto" ) )
implementation( project( ":flatlaf-intellij-themes" ) )
implementation( "com.miglayout:miglayout-swing:5.3" )
@@ -35,6 +36,7 @@ tasks {
dependsOn( ":flatlaf-core:jar" )
dependsOn( ":flatlaf-extras:jar" )
dependsOn( ":flatlaf-fonts-inter:jar" )
dependsOn( ":flatlaf-fonts-jetbrains-mono:jar" )
dependsOn( ":flatlaf-fonts-roboto:jar" )
dependsOn( ":flatlaf-intellij-themes:jar" )
// dependsOn( ":flatlaf-natives-jna:jar" )

View File

@@ -27,7 +27,6 @@ import java.util.Arrays;
import java.util.prefs.Preferences;
import javax.swing.*;
import javax.swing.text.DefaultEditorKit;
import javax.swing.text.StyleContext;
import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf;
@@ -43,15 +42,13 @@ import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
import com.formdev.flatlaf.extras.components.FlatButton;
import com.formdev.flatlaf.extras.components.FlatButton.ButtonType;
import com.formdev.flatlaf.fonts.inter.FlatInterFont;
import com.formdev.flatlaf.fonts.roboto.FlatRobotoFont;
import com.formdev.flatlaf.icons.FlatAbstractIcon;
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
import com.formdev.flatlaf.themes.FlatMacLightLaf;
import com.formdev.flatlaf.extras.FlatSVGUtils;
import com.formdev.flatlaf.ui.FlatUIUtils;
import com.formdev.flatlaf.ui.JBRCustomDecorations;
import com.formdev.flatlaf.util.ColorFunctions;
import com.formdev.flatlaf.util.FontUtils;
import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.SystemInfo;
import net.miginfocom.layout.ConstraintParser;
@@ -66,15 +63,12 @@ class DemoFrame
extends JFrame
{
private final String[] availableFontFamilyNames;
private boolean interFontInstalled;
private boolean robotoFontInstalled;
private int initialFontMenuItemCount = -1;
DemoFrame() {
int tabIndex = DemoPrefs.getState().getInt( FlatLafDemo.KEY_TAB, 0 );
availableFontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames().clone();
availableFontFamilyNames = FontUtils.getAvailableFontFamilyNames().clone();
Arrays.sort( availableFontFamilyNames );
initComponents();
@@ -284,24 +278,10 @@ class DemoFrame
private void fontFamilyChanged( ActionEvent e ) {
String fontFamily = e.getActionCommand();
// install Inter font on demand
if( fontFamily.equals( FlatInterFont.FAMILY ) && !interFontInstalled ) {
FlatInterFont.install();
interFontInstalled = true;
}
// install Roboto font on demand
if( fontFamily.equals( FlatRobotoFont.FAMILY ) && !robotoFontInstalled ) {
FlatRobotoFont.install();
robotoFontInstalled = true;
}
FlatAnimatedLafChange.showSnapshot();
Font font = UIManager.getFont( "defaultFont" );
Font newFont = StyleContext.getDefaultStyleContext().getFont( fontFamily, font.getStyle(), font.getSize() );
// StyleContext.getFont() may return a UIResource, which would cause loosing user scale factor on Windows
newFont = FlatUIUtils.nonUIResource( newFont );
Font newFont = FontUtils.getCompositeFont( fontFamily, font.getStyle(), font.getSize() );
UIManager.put( "defaultFont", newFont );
FlatLaf.updateUI();
@@ -368,10 +348,8 @@ class DemoFrame
ButtonGroup familiesGroup = new ButtonGroup();
for( String family : families ) {
if( Arrays.binarySearch( availableFontFamilyNames, family ) < 0 &&
!family.equals( FlatInterFont.FAMILY ) &&
!family.equals( FlatRobotoFont.FAMILY ) )
continue; // not available
if( Arrays.binarySearch( availableFontFamilyNames, family ) < 0 )
continue; // not available
JCheckBoxMenuItem item = new JCheckBoxMenuItem( family );
item.setSelected( family.equals( currentFamily ) );

View File

@@ -23,6 +23,9 @@ import javax.swing.SwingUtilities;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.extras.FlatInspector;
import com.formdev.flatlaf.extras.FlatUIDefaultsInspector;
import com.formdev.flatlaf.fonts.inter.FlatInterFont;
import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
import com.formdev.flatlaf.fonts.roboto.FlatRobotoFont;
import com.formdev.flatlaf.util.SystemInfo;
/**
@@ -68,6 +71,24 @@ public class FlatLafDemo
SwingUtilities.invokeLater( () -> {
DemoPrefs.init( PREFS_ROOT_PATH );
// install fonts for lazy loading
FlatInterFont.installLazy();
FlatJetBrainsMonoFont.installLazy();
FlatRobotoFont.installLazy();
// use Inter font by default
// FlatLaf.setPreferredFontFamily( FlatInterFont.FAMILY );
// FlatLaf.setPreferredLightFontFamily( FlatInterFont.FAMILY_LIGHT );
// FlatLaf.setPreferredSemiboldFontFamily( FlatInterFont.FAMILY_SEMIBOLD );
// use Roboto font by default
// FlatLaf.setPreferredFontFamily( FlatRobotoFont.FAMILY );
// FlatLaf.setPreferredLightFontFamily( FlatRobotoFont.FAMILY_LIGHT );
// FlatLaf.setPreferredSemiboldFontFamily( FlatRobotoFont.FAMILY_SEMIBOLD );
// use JetBrains Mono font
// FlatLaf.setPreferredMonospacedFontFamily( FlatJetBrainsMonoFont.FAMILY );
// application specific UI defaults
FlatLaf.registerCustomDefaultsSource( "com.formdev.flatlaf.demo" );

View File

@@ -18,18 +18,29 @@ License:
How to install?
---------------
Invoke the `install()` method once (e.g. in your `main()` method; on AWT
thread):
Invoke following once (e.g. in your `main()` method; on AWT thread).
For lazy loading use:
~~~java
FlatInterFont.installLazy();
~~~
Or load immediately with:
~~~java
FlatInterFont.install();
// or
FlatInterFont.installBasic();
FlatInterFont.installLight();
FlatInterFont.installSemiBold();
~~~
How to use?
-----------
Use as default font:
Use as application font (invoke before setting up FlatLaf):
~~~java
FlatLaf.setPreferredFontFamily( FlatInterFont.FAMILY );
@@ -37,7 +48,7 @@ FlatLaf.setPreferredLightFontFamily( FlatInterFont.FAMILY_LIGHT );
FlatLaf.setPreferredSemiboldFontFamily( FlatInterFont.FAMILY_SEMIBOLD );
~~~
Create fonts:
Create single fonts:
~~~java
// basic styles
@@ -55,6 +66,27 @@ new Font( FlatInterFont.FAMILY_SEMIBOLD, Font.PLAIN, 12 );
new Font( FlatInterFont.FAMILY_SEMIBOLD, Font.ITALIC, 12 );
~~~
If using lazy loading, invoke one of following before creating the font:
~~~java
FontUtils.loadFontFamily( FlatInterFont.FAMILY );
FontUtils.loadFontFamily( FlatInterFont.FAMILY_LIGHT );
FontUtils.loadFontFamily( FlatInterFont.FAMILY_SEMIBOLD );
~~~
E.g.:
~~~java
FontUtils.loadFontFamily( FlatInterFont.FAMILY );
Font font = new Font( FlatInterFont.FAMILY, Font.PLAIN, 12 );
~~~
Or use following:
~~~java
Font font = FontUtils.getCompositeFont( FlatInterFont.FAMILY, Font.PLAIN, 12 );
~~~
Download
--------

View File

@@ -31,11 +31,17 @@ plugins {
}
dependencies {
implementation( project( ":flatlaf-core" ) )
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
testImplementation( "org.junit.jupiter:junit-jupiter-params" )
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
}
flatlafModuleInfo {
dependsOn( ":flatlaf-core:jar" )
}
java {
withSourcesJar()
withJavadocJar()

View File

@@ -16,11 +16,7 @@
package com.formdev.flatlaf.fonts.inter;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.GraphicsEnvironment;
import java.io.IOException;
import java.io.InputStream;
import com.formdev.flatlaf.util.FontUtils;
/**
* The Inter font family.
@@ -31,19 +27,30 @@ import java.io.InputStream;
* Font home page: <a href="https://rsms.me/inter/">https://rsms.me/inter/</a><br>
* GitHub project: <a href="https://github.com/rsms/inter">https://github.com/rsms/inter</a>
* <p>
* To install the font, invoke following once (e.g. in your {@code main()} method; on AWT thread):
* To install the font, invoke following once (e.g. in your {@code main()} method; on AWT thread).
* <p>
* For lazy loading use:
* <pre>{@code
* FlatInterFont.install();
* FlatInterFont.installLazy();
* }</pre>
* <p>
* Use as default font:
* Or load immediately with:
* <pre>{@code
* FlatInterFont.install();
* // or
* FlatInterFont.installBasic();
* FlatInterFont.installLight();
* FlatInterFont.installSemiBold();
* }</pre>
* <p>
* Use as application font (invoke before setting up FlatLaf):
* <pre>{@code
* FlatLaf.setPreferredFontFamily( FlatInterFont.FAMILY );
* FlatLaf.setPreferredLightFontFamily( FlatInterFont.FAMILY_LIGHT );
* FlatLaf.setPreferredSemiboldFontFamily( FlatInterFont.FAMILY_SEMIBOLD );
* }</pre>
* <p>
* Create fonts:
* Create single fonts:
* <pre>{@code
* new Font( FlatInterFont.FAMILY, Font.PLAIN, 12 );
* new Font( FlatInterFont.FAMILY, Font.ITALIC, 12 );
@@ -54,6 +61,24 @@ import java.io.InputStream;
* new Font( FlatInterFont.FAMILY_SEMIBOLD, Font.PLAIN, 12 );
* new Font( FlatInterFont.FAMILY_SEMIBOLD, Font.ITALIC, 12 );
* }</pre>
* <p>
* If using lazy loading, invoke one of following before creating the font:
* <pre>{@code
* FontUtils.loadFontFamily( FlatInterFont.FAMILY );
* FontUtils.loadFontFamily( FlatInterFont.FAMILY_LIGHT );
* FontUtils.loadFontFamily( FlatInterFont.FAMILY_SEMIBOLD );
* }</pre>
* <p>
* E.g.:
* <pre>{@code
* FontUtils.loadFontFamily( FlatInterFont.FAMILY );
* Font font = new Font( FlatInterFont.FAMILY, Font.PLAIN, 12 );
* }</pre>
* <p>
* Or use following:
* <pre>{@code
* Font font = FontUtils.getCompositeFont( FlatInterFont.FAMILY, Font.PLAIN, 12 );
* }</pre>
*
* @author Karl Tauber
*/
@@ -115,21 +140,61 @@ public class FlatInterFont
private FlatInterFont() {}
/**
* Registers the fonts for lazy loading via {@link FontUtils#registerFontFamilyLoader(String, Runnable)}.
* <p>
* This is the preferred method (when using FlatLaf) to avoid unnecessary loading of maybe unused fonts.
* <p>
* <strong>Note</strong>: When using '{@code new Font(...)}', you need to first invoke
* {@link FontUtils#loadFontFamily(String)} to ensure that the font family is loaded.
* When FlatLaf loads a font, or when using {@link FontUtils#getCompositeFont(String, int, int)},
* this is done automatically.
*/
public static void installLazy() {
FontUtils.registerFontFamilyLoader( FAMILY, FlatInterFont::installBasic );
FontUtils.registerFontFamilyLoader( FAMILY_LIGHT, FlatInterFont::installLight );
FontUtils.registerFontFamilyLoader( FAMILY_SEMIBOLD, FlatInterFont::installSemiBold );
}
/**
* Creates and registers the fonts for all styles.
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void install() {
// basic styles
installBasic();
installLight();
installSemiBold();
}
/**
* Creates and registers the fonts for basic styles (regular, italic and bold).
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void installBasic() {
installStyle( STYLE_REGULAR );
installStyle( STYLE_ITALIC );
installStyle( STYLE_BOLD );
installStyle( STYLE_BOLD_ITALIC );
}
// light
/**
* Creates and registers the fonts for light styles.
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void installLight() {
installStyle( STYLE_LIGHT );
installStyle( STYLE_LIGHT_ITALIC );
}
// semibold
/**
* Creates and registers the fonts for semibold styles.
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void installSemiBold() {
installStyle( STYLE_SEMIBOLD );
installStyle( STYLE_SEMIBOLD_ITALIC );
}
@@ -139,15 +204,6 @@ public class FlatInterFont
* See {@code STYLE_} constants.
*/
public static boolean installStyle( String name ) {
try( InputStream in = FlatInterFont.class.getResourceAsStream( name ) ) {
Font font = Font.createFont( Font.TRUETYPE_FONT, in );
return GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont( font );
} catch( FontFormatException ex ) {
ex.printStackTrace();
return false;
} catch( IOException ex ) {
ex.printStackTrace();
return false;
}
return FontUtils.installFont( FlatInterFont.class.getResource( name ) );
}
}

View File

@@ -19,6 +19,7 @@
*/
module com.formdev.flatlaf.fonts.inter {
requires java.desktop;
requires com.formdev.flatlaf;
exports com.formdev.flatlaf.fonts.inter;

View File

@@ -15,8 +15,15 @@ License:
How to install?
---------------
Invoke the `install()` method once (e.g. in your `main()` method; on AWT
thread):
Invoke following once (e.g. in your `main()` method; on AWT thread).
For lazy loading use:
~~~java
FlatJetBrainsMonoFont.installLazy();
~~~
Or load immediately with:
~~~java
FlatJetBrainsMonoFont.install();
@@ -26,13 +33,13 @@ FlatJetBrainsMonoFont.install();
How to use?
-----------
Use as default monospaced font:
Use as application monospaced font (invoke before setting up FlatLaf):
~~~java
FlatLaf.setPreferredMonospacedFontFamily( FlatJetBrainsMonoFont.FAMILY );
~~~
Create fonts:
Create single fonts:
~~~java
// basic styles
@@ -42,6 +49,25 @@ new Font( FlatJetBrainsMonoFont.FAMILY, Font.BOLD, 12 );
new Font( FlatJetBrainsMonoFont.FAMILY, Font.BOLD | Font.ITALIC, 12 );
~~~
If using lazy loading, invoke one of following before creating the font:
~~~java
FontUtils.loadFontFamily( FlatJetBrainsMonoFont.FAMILY );
~~~
E.g.:
~~~java
FontUtils.loadFontFamily( FlatJetBrainsMonoFont.FAMILY );
Font font = new Font( FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, 12 );
~~~
Or use following:
~~~java
Font font = FontUtils.getCompositeFont( FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, 12 );
~~~
Download
--------

View File

@@ -31,11 +31,17 @@ plugins {
}
dependencies {
implementation( project( ":flatlaf-core" ) )
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
testImplementation( "org.junit.jupiter:junit-jupiter-params" )
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
}
flatlafModuleInfo {
dependsOn( ":flatlaf-core:jar" )
}
java {
withSourcesJar()
withJavadocJar()

View File

@@ -16,11 +16,7 @@
package com.formdev.flatlaf.fonts.jetbrains_mono;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.GraphicsEnvironment;
import java.io.IOException;
import java.io.InputStream;
import com.formdev.flatlaf.util.FontUtils;
/**
* The JetBrains Mono font family.
@@ -28,23 +24,46 @@ import java.io.InputStream;
* Font home page: <a href="https://www.jetbrains.com/mono">https://www.jetbrains.com/mono</a><br>
* GitHub project: <a href="https://github.com/JetBrains/JetBrainsMono">https://github.com/JetBrains/JetBrainsMono</a>
* <p>
* To install the font, invoke following once (e.g. in your {@code main()} method; on AWT thread):
* To install the font, invoke following once (e.g. in your {@code main()} method; on AWT thread).
* <p>
* For lazy loading use:
* <pre>{@code
* FlatJetBrainsMonoFont.installLazy();
* }</pre>
* <p>
* Or load immediately with:
* <pre>{@code
* FlatJetBrainsMonoFont.install();
* }</pre>
* <p>
* Use as default monospaced font:
* Use as application monospaced font (invoke before setting up FlatLaf):
* <pre>{@code
* FlatLaf.setPreferredMonospacedFontFamily( FlatJetBrainsMonoFont.FAMILY );
* }</pre>
* <p>
* Create fonts:
* Create single fonts:
* <pre>{@code
* new Font( FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, 12 );
* new Font( FlatJetBrainsMonoFont.FAMILY, Font.ITALIC, 12 );
* new Font( FlatJetBrainsMonoFont.FAMILY, Font.BOLD, 12 );
* new Font( FlatJetBrainsMonoFont.FAMILY, Font.BOLD | Font.ITALIC, 12 );
* }</pre>
* <p>
* If using lazy loading, invoke following before creating the font:
* <pre>{@code
* FontUtils.loadFontFamily( FlatJetBrainsMonoFont.FAMILY );
* }</pre>
* <p>
* E.g.:
* <pre>{@code
* FontUtils.loadFontFamily( FlatJetBrainsMonoFont.FAMILY );
* Font font = new Font( FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, 12 );
* }</pre>
* <p>
* Or use following:
* <pre>{@code
* Font font = FontUtils.getCompositeFont( FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, 12 );
* }</pre>
*
* @author Karl Tauber
*/
@@ -76,8 +95,24 @@ public class FlatJetBrainsMonoFont
private FlatJetBrainsMonoFont() {}
/**
* Registers the fonts for lazy loading via {@link FontUtils#registerFontFamilyLoader(String, Runnable)}.
* <p>
* This is the preferred method (when using FlatLaf) to avoid unnecessary loading of maybe unused fonts.
* <p>
* <strong>Note</strong>: When using '{@code new Font(...)}', you need to first invoke
* {@link FontUtils#loadFontFamily(String)} to ensure that the font family is loaded.
* When FlatLaf loads a font, or when using {@link FontUtils#getCompositeFont(String, int, int)},
* this is done automatically.
*/
public static void installLazy() {
FontUtils.registerFontFamilyLoader( FAMILY, FlatJetBrainsMonoFont::install );
}
/**
* Creates and registers the fonts for all styles.
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void install() {
installStyle( STYLE_REGULAR );
@@ -91,15 +126,6 @@ public class FlatJetBrainsMonoFont
* See {@code STYLE_} constants.
*/
public static boolean installStyle( String name ) {
try( InputStream in = FlatJetBrainsMonoFont.class.getResourceAsStream( name ) ) {
Font font = Font.createFont( Font.TRUETYPE_FONT, in );
return GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont( font );
} catch( FontFormatException ex ) {
ex.printStackTrace();
return false;
} catch( IOException ex ) {
ex.printStackTrace();
return false;
}
return FontUtils.installFont( FlatJetBrainsMonoFont.class.getResource( name ) );
}
}

View File

@@ -19,6 +19,7 @@
*/
module com.formdev.flatlaf.fonts.jetbrains_mono {
requires java.desktop;
requires com.formdev.flatlaf;
exports com.formdev.flatlaf.fonts.jetbrains_mono;

View File

@@ -15,18 +15,29 @@ License:
How to install?
---------------
Invoke the `install()` method once (e.g. in your `main()` method; on AWT
thread):
Invoke following once (e.g. in your `main()` method; on AWT thread).
For lazy loading use:
~~~java
FlatRobotoFont.installLazy();
~~~
Or load immediately with:
~~~java
FlatRobotoFont.install();
// or
FlatRobotoFont.installBasic();
FlatRobotoFont.installLight();
FlatRobotoFont.installSemiBold();
~~~
How to use?
-----------
Use as default font:
Use as application font (invoke before setting up FlatLaf):
~~~java
FlatLaf.setPreferredFontFamily( FlatRobotoFont.FAMILY );
@@ -34,7 +45,7 @@ FlatLaf.setPreferredLightFontFamily( FlatRobotoFont.FAMILY_LIGHT );
FlatLaf.setPreferredSemiboldFontFamily( FlatRobotoFont.FAMILY_SEMIBOLD );
~~~
Create fonts:
Create single fonts:
~~~java
// basic styles
@@ -52,6 +63,27 @@ new Font( FlatRobotoFont.FAMILY_SEMIBOLD, Font.PLAIN, 12 );
new Font( FlatRobotoFont.FAMILY_SEMIBOLD, Font.ITALIC, 12 );
~~~
If using lazy loading, invoke one of following before creating the font:
~~~java
FontUtils.loadFontFamily( FlatRobotoFont.FAMILY );
FontUtils.loadFontFamily( FlatRobotoFont.FAMILY_LIGHT );
FontUtils.loadFontFamily( FlatRobotoFont.FAMILY_SEMIBOLD );
~~~
E.g.:
~~~java
FontUtils.loadFontFamily( FlatRobotoFont.FAMILY );
Font font = new Font( FlatRobotoFont.FAMILY, Font.PLAIN, 12 );
~~~
Or use following:
~~~java
Font font = FontUtils.getCompositeFont( FlatRobotoFont.FAMILY, Font.PLAIN, 12 );
~~~
Download
--------

View File

@@ -31,11 +31,17 @@ plugins {
}
dependencies {
implementation( project( ":flatlaf-core" ) )
testImplementation( "org.junit.jupiter:junit-jupiter-api:5.7.2" )
testImplementation( "org.junit.jupiter:junit-jupiter-params" )
testRuntimeOnly( "org.junit.jupiter:junit-jupiter-engine" )
}
flatlafModuleInfo {
dependsOn( ":flatlaf-core:jar" )
}
java {
withSourcesJar()
withJavadocJar()

View File

@@ -16,11 +16,7 @@
package com.formdev.flatlaf.fonts.roboto;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.GraphicsEnvironment;
import java.io.IOException;
import java.io.InputStream;
import com.formdev.flatlaf.util.FontUtils;
/**
* The Roboto font family.
@@ -28,19 +24,30 @@ import java.io.InputStream;
* Font home page: <a href="https://fonts.google.com/specimen/Roboto">https://fonts.google.com/specimen/Roboto</a><br>
* GitHub project: <a href="https://github.com/googlefonts/roboto">https://github.com/googlefonts/roboto</a>
* <p>
* To install the font, invoke following once (e.g. in your {@code main()} method; on AWT thread):
* To install the font, invoke following once (e.g. in your {@code main()} method; on AWT thread).
* <p>
* For lazy loading use:
* <pre>{@code
* FlatRobotoFont.install();
* FlatRobotoFont.installLazy();
* }</pre>
* <p>
* Use as default font:
* Or load immediately with:
* <pre>{@code
* FlatRobotoFont.install();
* // or
* FlatRobotoFont.installBasic();
* FlatRobotoFont.installLight();
* FlatRobotoFont.installSemiBold();
* }</pre>
* <p>
* Use as application font (invoke before setting up FlatLaf):
* <pre>{@code
* FlatLaf.setPreferredFontFamily( FlatRobotoFont.FAMILY );
* FlatLaf.setPreferredLightFontFamily( FlatRobotoFont.FAMILY_LIGHT );
* FlatLaf.setPreferredSemiboldFontFamily( FlatRobotoFont.FAMILY_SEMIBOLD );
* }</pre>
* <p>
* Create fonts:
* Create single fonts:
* <pre>{@code
* new Font( FlatRobotoFont.FAMILY, Font.PLAIN, 12 );
* new Font( FlatRobotoFont.FAMILY, Font.ITALIC, 12 );
@@ -51,6 +58,24 @@ import java.io.InputStream;
* new Font( FlatRobotoFont.FAMILY_SEMIBOLD, Font.PLAIN, 12 );
* new Font( FlatRobotoFont.FAMILY_SEMIBOLD, Font.ITALIC, 12 );
* }</pre>
* <p>
* If using lazy loading, invoke one of following before creating the font:
* <pre>{@code
* FontUtils.loadFontFamily( FlatRobotoFont.FAMILY );
* FontUtils.loadFontFamily( FlatRobotoFont.FAMILY_LIGHT );
* FontUtils.loadFontFamily( FlatRobotoFont.FAMILY_SEMIBOLD );
* }</pre>
* <p>
* E.g.:
* <pre>{@code
* FontUtils.loadFontFamily( FlatRobotoFont.FAMILY );
* Font font = new Font( FlatRobotoFont.FAMILY, Font.PLAIN, 12 );
* }</pre>
* <p>
* Or use following:
* <pre>{@code
* Font font = FontUtils.getCompositeFont( FlatRobotoFont.FAMILY, Font.PLAIN, 12 );
* }</pre>
*
* @author Karl Tauber
*/
@@ -81,7 +106,7 @@ public class FlatRobotoFont
public static final String FAMILY_LIGHT = "Roboto Light";
/**
* Family name for semibold styles.
* Family name for semibold (medium) styles.
* <p>
* Usage:
* <pre>{@code
@@ -112,21 +137,61 @@ public class FlatRobotoFont
private FlatRobotoFont() {}
/**
* Registers the fonts for lazy loading via {@link FontUtils#registerFontFamilyLoader(String, Runnable)}.
* <p>
* This is the preferred method (when using FlatLaf) to avoid unnecessary loading of maybe unused fonts.
* <p>
* <strong>Note</strong>: When using '{@code new Font(...)}', you need to first invoke
* {@link FontUtils#loadFontFamily(String)} to ensure that the font family is loaded.
* When FlatLaf loads a font, or when using {@link FontUtils#getCompositeFont(String, int, int)},
* this is done automatically.
*/
public static void installLazy() {
FontUtils.registerFontFamilyLoader( FAMILY, FlatRobotoFont::installBasic );
FontUtils.registerFontFamilyLoader( FAMILY_LIGHT, FlatRobotoFont::installLight );
FontUtils.registerFontFamilyLoader( FAMILY_SEMIBOLD, FlatRobotoFont::installSemiBold );
}
/**
* Creates and registers the fonts for all styles.
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void install() {
// basic styles
installBasic();
installLight();
installSemiBold();
}
/**
* Creates and registers the fonts for basic styles (regular, italic and bold).
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void installBasic() {
installStyle( STYLE_REGULAR );
installStyle( STYLE_ITALIC );
installStyle( STYLE_BOLD );
installStyle( STYLE_BOLD_ITALIC );
}
// light
/**
* Creates and registers the fonts for light styles.
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void installLight() {
installStyle( STYLE_LIGHT );
installStyle( STYLE_LIGHT_ITALIC );
}
// semibold
/**
* Creates and registers the fonts for semibold (medium) styles.
* <p>
* When using FlatLaf, consider using {@link #installLazy()}.
*/
public static void installSemiBold() {
installStyle( STYLE_SEMIBOLD );
installStyle( STYLE_SEMIBOLD_ITALIC );
}
@@ -136,15 +201,6 @@ public class FlatRobotoFont
* See {@code STYLE_} constants.
*/
public static boolean installStyle( String name ) {
try( InputStream in = FlatRobotoFont.class.getResourceAsStream( name ) ) {
Font font = Font.createFont( Font.TRUETYPE_FONT, in );
return GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont( font );
} catch( FontFormatException ex ) {
ex.printStackTrace();
return false;
} catch( IOException ex ) {
ex.printStackTrace();
return false;
}
return FontUtils.installFont( FlatRobotoFont.class.getResource( name ) );
}
}

View File

@@ -19,6 +19,7 @@
*/
module com.formdev.flatlaf.fonts.roboto {
requires java.desktop;
requires com.formdev.flatlaf;
exports com.formdev.flatlaf.fonts.roboto;

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.jdt.launching.localJavaApplication">
<booleanAttribute key="org.eclipse.debug.core.ATTR_FORCE_SYSTEM_CONSOLE_ENCODING" value="false"/>
<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
<listEntry value="/flatlaf-testing-modular-app"/>
</listAttribute>
@@ -16,10 +17,11 @@
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="-Ddummy=dummy"/>
<listAttribute key="org.eclipse.jdt.launching.MODULEPATH">
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk-17/&quot; path=&quot;4&quot; type=&quot;4&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/flatlaf-testing-modular-app/build/libs/flatlaf-testing-modular-app-2.5-SNAPSHOT.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/flatlaf-core/build/libs/flatlaf-2.5-SNAPSHOT.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/flatlaf-extras/build/libs/flatlaf-extras-2.5-SNAPSHOT.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry externalArchive=&quot;C:/Users/charly/.gradle/caches/modules-2/files-2.1/com.formdev/svgSalamander/1.1.2.4/828c2ce815bf62031764f5219597948bd2587aa5/svgSalamander-1.1.2.4.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/flatlaf-testing-modular-app/build/libs/flatlaf-testing-modular-app-3.0-SNAPSHOT.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/flatlaf-core/build/libs/flatlaf-3.0-SNAPSHOT.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/flatlaf-extras/build/libs/flatlaf-extras-3.0-SNAPSHOT.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/flatlaf-fonts-inter/build/libs/flatlaf-fonts-inter-3.19-SNAPSHOT.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;runtimeClasspathEntry externalArchive=&quot;C:/Users/charly/.gradle/caches/modules-2/files-2.1/com.formdev/svgSalamander/1.1.4/e61742cb8baaf9ecf57a9779763d1de21ca9db5a/svgSalamander-1.1.4.jar&quot; path=&quot;4&quot; type=&quot;2&quot;/&gt;&#13;&#10;"/>
</listAttribute>
<stringAttribute key="org.eclipse.jdt.launching.MODULE_NAME" value="flatlaf-testing-modular-app"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-m com.formdev.flatlaf.testing.modular.app/com.formdev.flatlaf.testing.modular.app.FlatModularAppTest"/>

View File

@@ -22,9 +22,11 @@ plugins {
dependencies {
implementation( project( ":flatlaf-core" ) )
implementation( project( ":flatlaf-extras" ) )
implementation( project( ":flatlaf-fonts-inter" ) )
}
flatlafModuleInfo {
dependsOn( ":flatlaf-core:jar" )
dependsOn( ":flatlaf-extras:jar" )
dependsOn( ":flatlaf-fonts-inter:jar" )
}

View File

@@ -27,6 +27,7 @@ import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.extras.FlatSVGIcon;
import com.formdev.flatlaf.extras.FlatSVGUtils;
import com.formdev.flatlaf.fonts.inter.FlatInterFont;
/**
* @author Karl Tauber
@@ -35,6 +36,8 @@ public class FlatModularAppTest
{
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatInterFont.installBasic();
FlatLaf.registerCustomDefaultsSource(
FlatModularAppTest.class.getResource( "/com/formdev/flatlaf/testing/modular/app/themes/" ) );
FlatLightLaf.setup();

View File

@@ -21,6 +21,7 @@ module com.formdev.flatlaf.testing.modular.app {
requires java.desktop;
requires com.formdev.flatlaf;
requires com.formdev.flatlaf.extras;
requires com.formdev.flatlaf.fonts.inter;
requires com.kitfox.svg;
exports com.formdev.flatlaf.testing.modular.app.plaf;

View File

@@ -19,13 +19,13 @@ package com.formdev.flatlaf.testing;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.*;
import com.formdev.flatlaf.fonts.inter.FlatInterFont;
import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
import com.formdev.flatlaf.fonts.roboto.FlatRobotoFont;
import com.formdev.flatlaf.util.FontUtils;
import com.formdev.flatlaf.util.UIScale;
import net.miginfocom.swing.*;
@@ -37,9 +37,9 @@ public class FlatFontsTest
{
public static void main( String[] args ) {
SwingUtilities.invokeLater( () -> {
FlatInterFont.install();
FlatJetBrainsMonoFont.install();
FlatRobotoFont.install();
FlatInterFont.installLazy();
FlatJetBrainsMonoFont.installLazy();
FlatRobotoFont.installLazy();
FlatTestFrame frame = FlatTestFrame.create( args, "FlatFontsTest" );
frame.showFrame( FlatFontsTest::new );
@@ -49,7 +49,7 @@ public class FlatFontsTest
FlatFontsTest() {
initComponents();
Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
Font[] allFonts = FontUtils.getAllFonts();
TreeMap<String, TreeMap<String, Font>> familiesMap = new TreeMap<>();
for( Font font : allFonts ) {

View File

@@ -22,17 +22,16 @@ import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.util.Arrays;
import javax.swing.*;
import javax.swing.text.StyleContext;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatSystemProperties;
import com.formdev.flatlaf.fonts.inter.FlatInterFont;
import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
import com.formdev.flatlaf.fonts.roboto.FlatRobotoFont;
import com.formdev.flatlaf.util.FontUtils;
import com.formdev.flatlaf.util.Graphics2DProxy;
import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.JavaCompatibility;
@@ -51,9 +50,9 @@ public class FlatPaintingStringTest
System.setProperty( "FlatLaf.debug.HiDPIUtils.useDebugScaleFactor", "true" );
SwingUtilities.invokeLater( () -> {
FlatInterFont.install();
FlatJetBrainsMonoFont.install();
FlatRobotoFont.install();
FlatInterFont.installLazy();
FlatJetBrainsMonoFont.installLazy();
FlatRobotoFont.installLazy();
FlatTestFrame frame = FlatTestFrame.create( args, "FlatPaintingStringTest" );
@@ -67,8 +66,7 @@ public class FlatPaintingStringTest
FlatPaintingStringTest() {
initComponents();
String[] availableFontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getAvailableFontFamilyNames().clone();
String[] availableFontFamilyNames = FontUtils.getAvailableFontFamilyNames().clone();
Arrays.sort( availableFontFamilyNames );
Font currentFont = UIManager.getFont( "Label.font" );
@@ -194,7 +192,7 @@ public class FlatPaintingStringTest
if( font.getFamily().equals( family ) )
return;
Font newFont = StyleContext.getDefaultStyleContext().getFont( family, font.getStyle(), font.getSize() );
Font newFont = FontUtils.getCompositeFont( family, font.getStyle(), font.getSize() );
UIManager.put( "defaultFont", newFont );
updateFontMetricsLabel();

View File

@@ -34,7 +34,6 @@ import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.text.StyleContext;
import org.fife.ui.autocomplete.AutoCompletion;
import org.fife.ui.autocomplete.CompletionProvider;
import org.fife.ui.rsyntaxtextarea.AbstractTokenMakerFactory;
@@ -50,6 +49,7 @@ import org.fife.ui.rtextarea.RTextArea;
import org.fife.ui.rtextarea.RTextScrollPane;
import org.fife.ui.rtextarea.SearchContext;
import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
import com.formdev.flatlaf.util.FontUtils;
import com.formdev.flatlaf.util.UIScale;
/**
@@ -171,8 +171,7 @@ class FlatThemeEditorPane
private static Font createEditorFont( int sizeIncr ) {
int size = UIManager.getFont( "defaultFont" ).getSize() + sizeIncr;
StyleContext sc = StyleContext.getDefaultStyleContext();
Font font = sc.getFont( FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, size );
Font font = FontUtils.getCompositeFont( FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, size );
if( isFallbackFont( font ) ) {
Font defaultFont = RTextArea.getDefaultFont();
font = defaultFont.deriveFont( (float) size );

View File

@@ -108,10 +108,9 @@ class FlatThemeFileEditor
System.setProperty( "user.language", "en" );
SwingUtilities.invokeLater( () -> {
if( SystemInfo.isJava_11_orLater )
FlatInterFont.install();
FlatJetBrainsMonoFont.install();
FlatRobotoFont.install();
FlatInterFont.installLazy();
FlatJetBrainsMonoFont.installLazy();
FlatRobotoFont.installLazy();
FlatLaf.registerCustomDefaultsSource( "com.formdev.flatlaf.themeeditor" );