在 Linux 平台通过 fc-match 查询默认字体 (#3922)

This commit is contained in:
Glavo
2025-05-20 00:25:56 +08:00
committed by GitHub
parent 1ac677365b
commit 4291ae5f16
3 changed files with 55 additions and 14 deletions

View File

@@ -23,10 +23,14 @@ import javafx.scene.text.Font;
import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.Metadata;
import org.jackhuang.hmcl.util.Lazy; import org.jackhuang.hmcl.util.Lazy;
import org.jackhuang.hmcl.util.io.JarUtils; import org.jackhuang.hmcl.util.io.JarUtils;
import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.SystemUtils;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Locale;
import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.util.logging.Logger.LOG; import static org.jackhuang.hmcl.util.logging.Logger.LOG;
@@ -52,15 +56,33 @@ public final class FontManager {
return font; return font;
Path thisJar = JarUtils.thisJarPath(); Path thisJar = JarUtils.thisJarPath();
if (thisJar != null && thisJar.getParent() != null) if (thisJar != null && thisJar.getParent() != null) {
return tryLoadDefaultFont(thisJar.getParent()); font = tryLoadDefaultFont(thisJar.getParent());
if (font != null)
return font;
}
return null; if (OperatingSystem.CURRENT_OS.isLinuxOrBSD()
&& Locale.getDefault() != Locale.ROOT
&& !"en".equals(Locale.getDefault().getLanguage()))
return findByFcMatch();
else
return null;
}); });
private static final ObjectProperty<Font> fontProperty = new SimpleObjectProperty<>(getDefaultFont()); private static final ObjectProperty<Font> fontProperty;
static { static {
String fontFamily = config().getLauncherFontFamily();
if (fontFamily == null)
fontFamily = System.getProperty("hmcl.font.override");
if (fontFamily == null)
fontFamily = System.getenv("HMCL_FONT");
Font font = fontFamily == null ? DEFAULT_FONT.get() : Font.font(fontFamily, DEFAULT_FONT_SIZE);
fontProperty = new SimpleObjectProperty<>(font);
LOG.info("Font: " + (font != null ? font.getName() : Font.getDefault().getName()));
fontProperty.addListener((obs, oldValue, newValue) -> { fontProperty.addListener((obs, oldValue, newValue) -> {
if (newValue != null) if (newValue != null)
config().setLauncherFontFamily(newValue.getFamily()); config().setLauncherFontFamily(newValue.getFamily());
@@ -90,14 +112,29 @@ public final class FontManager {
return null; return null;
} }
private static Font getDefaultFont() { public static Font findByFcMatch() {
String fontFamily = config().getLauncherFontFamily(); Path fcMatch = SystemUtils.which("fc-match");
if (fontFamily == null) if (fcMatch == null)
fontFamily = System.getProperty("hmcl.font.override"); return null;
if (fontFamily == null)
fontFamily = System.getenv("HMCL_FONT");
return fontFamily == null ? DEFAULT_FONT.get() : Font.font(fontFamily, DEFAULT_FONT_SIZE); try {
String path = SystemUtils.run(fcMatch.toString(),
":lang=" + Locale.getDefault().toLanguageTag(),
"--format", "%{file}").trim();
Path file = Paths.get(path).toAbsolutePath().normalize();
if (!Files.isRegularFile(file)) {
LOG.warning("Font file does not exist: " + path);
return null;
}
Font font = Font.loadFont(file.toUri().toURL().toExternalForm(), DEFAULT_FONT_SIZE);
if (font == null)
LOG.warning("Failed to load font from " + path);
return font;
} catch (Throwable e) {
LOG.warning("Failed to get default font with fc-match", e);
return null;
}
} }
public static ObjectProperty<Font> fontProperty() { public static ObjectProperty<Font> fontProperty() {

View File

@@ -21,6 +21,7 @@ import org.jackhuang.hmcl.java.JavaRuntime;
import org.jackhuang.hmcl.task.Schedulers; import org.jackhuang.hmcl.task.Schedulers;
import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.function.ExceptionalFunction; import org.jackhuang.hmcl.util.function.ExceptionalFunction;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.io.File; import java.io.File;
@@ -75,6 +76,11 @@ public final class SystemUtils {
return managedProcess.getProcess().waitFor(); return managedProcess.getProcess().waitFor();
} }
public static String run(String... command) throws Exception {
return run(Arrays.asList(command),
inputStream -> IOUtils.readFullyAsString(inputStream, OperatingSystem.NATIVE_CHARSET));
}
public static <T> T run(List<String> command, ExceptionalFunction<InputStream, T, ?> convert) throws Exception { public static <T> T run(List<String> command, ExceptionalFunction<InputStream, T, ?> convert) throws Exception {
File nul = OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS File nul = OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS
? new File("NUL") ? new File("NUL")

View File

@@ -23,7 +23,6 @@ import com.google.gson.JsonObject;
import org.jackhuang.hmcl.util.KeyValuePairUtils; import org.jackhuang.hmcl.util.KeyValuePairUtils;
import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.gson.JsonUtils;
import org.jackhuang.hmcl.util.io.IOUtils;
import org.jackhuang.hmcl.util.platform.OperatingSystem; import org.jackhuang.hmcl.util.platform.OperatingSystem;
import org.jackhuang.hmcl.util.platform.SystemUtils; import org.jackhuang.hmcl.util.platform.SystemUtils;
import org.jackhuang.hmcl.util.platform.hardware.CentralProcessor; import org.jackhuang.hmcl.util.platform.hardware.CentralProcessor;
@@ -103,8 +102,7 @@ public final class MacOSHardwareDetector extends HardwareDetector {
String json = null; String json = null;
try { try {
json = SystemUtils.run(Arrays.asList("/usr/sbin/system_profiler", "SPDisplaysDataType", "-json"), json = SystemUtils.run("/usr/sbin/system_profiler", "SPDisplaysDataType", "-json");
inputStream -> IOUtils.readFullyAsString(inputStream, OperatingSystem.NATIVE_CHARSET));
JsonObject object = JsonUtils.GSON.fromJson(json, JsonObject.class); JsonObject object = JsonUtils.GSON.fromJson(json, JsonObject.class);
JsonArray spDisplaysDataType = object.getAsJsonArray("SPDisplaysDataType"); JsonArray spDisplaysDataType = object.getAsJsonArray("SPDisplaysDataType");