添加字体抗锯齿算法设置选项 (#4118)

This commit is contained in:
Glavo 2025-07-26 01:28:35 +08:00 committed by GitHub
parent 195db2ee6d
commit fd13088726
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 89 additions and 5 deletions

View File

@ -21,10 +21,7 @@ import com.google.gson.*;
import com.google.gson.annotations.JsonAdapter; import com.google.gson.annotations.JsonAdapter;
import javafx.beans.InvalidationListener; import javafx.beans.InvalidationListener;
import javafx.beans.Observable; import javafx.beans.Observable;
import javafx.beans.property.BooleanProperty; import javafx.beans.property.*;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ObservableSet; import javafx.collections.ObservableSet;
import org.jackhuang.hmcl.util.javafx.ObservableHelper; import org.jackhuang.hmcl.util.javafx.ObservableHelper;
@ -57,6 +54,8 @@ public final class GlobalConfig implements Observable {
private final BooleanProperty enableOfflineAccount = new SimpleBooleanProperty(false); private final BooleanProperty enableOfflineAccount = new SimpleBooleanProperty(false);
private final StringProperty fontAntiAliasing = new SimpleStringProperty();
private final ObservableSet<String> userJava = FXCollections.observableSet(new LinkedHashSet<>()); private final ObservableSet<String> userJava = FXCollections.observableSet(new LinkedHashSet<>());
private final ObservableSet<String> disabledJava = FXCollections.observableSet(new LinkedHashSet<>()); private final ObservableSet<String> disabledJava = FXCollections.observableSet(new LinkedHashSet<>());
@ -131,6 +130,18 @@ public final class GlobalConfig implements Observable {
enableOfflineAccount.set(value); enableOfflineAccount.set(value);
} }
public StringProperty fontAntiAliasingProperty() {
return fontAntiAliasing;
}
public String getFontAntiAliasing() {
return fontAntiAliasing.get();
}
public void setFontAntiAliasing(String value) {
this.fontAntiAliasing.set(value);
}
public ObservableSet<String> getUserJava() { public ObservableSet<String> getUserJava() {
return userJava; return userJava;
} }
@ -146,7 +157,8 @@ public final class GlobalConfig implements Observable {
"logRetention", "logRetention",
"userJava", "userJava",
"disabledJava", "disabledJava",
"enableOfflineAccount" "enableOfflineAccount",
"fontAntiAliasing"
)); ));
@Override @Override
@ -159,6 +171,7 @@ public final class GlobalConfig implements Observable {
jsonObject.add("agreementVersion", context.serialize(src.getAgreementVersion())); jsonObject.add("agreementVersion", context.serialize(src.getAgreementVersion()));
jsonObject.add("platformPromptVersion", context.serialize(src.getPlatformPromptVersion())); jsonObject.add("platformPromptVersion", context.serialize(src.getPlatformPromptVersion()));
jsonObject.add("logRetention", context.serialize(src.getLogRetention())); jsonObject.add("logRetention", context.serialize(src.getLogRetention()));
jsonObject.add("fontAntiAliasing", context.serialize(src.getFontAntiAliasing()));
if (src.enableOfflineAccount.get()) if (src.enableOfflineAccount.get())
jsonObject.addProperty("enableOfflineAccount", true); jsonObject.addProperty("enableOfflineAccount", true);
@ -186,6 +199,7 @@ public final class GlobalConfig implements Observable {
config.setPlatformPromptVersion(Optional.ofNullable(obj.get("platformPromptVersion")).map(JsonElement::getAsInt).orElse(0)); config.setPlatformPromptVersion(Optional.ofNullable(obj.get("platformPromptVersion")).map(JsonElement::getAsInt).orElse(0));
config.setLogRetention(Optional.ofNullable(obj.get("logRetention")).map(JsonElement::getAsInt).orElse(20)); config.setLogRetention(Optional.ofNullable(obj.get("logRetention")).map(JsonElement::getAsInt).orElse(20));
config.setEnableOfflineAccount(Optional.ofNullable(obj.get("enableOfflineAccount")).map(JsonElement::getAsBoolean).orElse(false)); config.setEnableOfflineAccount(Optional.ofNullable(obj.get("enableOfflineAccount")).map(JsonElement::getAsBoolean).orElse(false));
config.setFontAntiAliasing(Optional.ofNullable(obj.get("fontAntiAliasing")).map(JsonElement::getAsString).orElse(null));
JsonElement userJava = obj.get("userJava"); JsonElement userJava = obj.get("userJava");
if (userJava != null && userJava.isJsonArray()) { if (userJava != null && userJava.isJsonArray()) {

View File

@ -175,6 +175,18 @@ public final class Controllers {
public static void initialize(Stage stage) { public static void initialize(Stage stage) {
LOG.info("Start initializing application"); LOG.info("Start initializing application");
if (System.getProperty("prism.lcdtext") == null) {
String fontAntiAliasing = globalConfig().getFontAntiAliasing();
if ("lcd".equalsIgnoreCase(fontAntiAliasing)) {
LOG.info("Enable sub-pixel antialiasing");
System.getProperties().put("prism.lcdtext", "true");
} else if ("gray".equalsIgnoreCase(fontAntiAliasing)
|| OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS && SCREEN.getOutputScaleX() > 1) {
LOG.info("Disable sub-pixel antialiasing");
System.getProperties().put("prism.lcdtext", "false");
}
}
Controllers.stage = stage; Controllers.stage = stage;
stageSizeChangeListener = o -> { stageSizeChangeListener = o -> {

View File

@ -18,11 +18,13 @@
package org.jackhuang.hmcl.ui.main; package org.jackhuang.hmcl.ui.main;
import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXComboBox;
import com.jfoenix.controls.JFXTextField; import com.jfoenix.controls.JFXTextField;
import com.jfoenix.effects.JFXDepthManager; import com.jfoenix.effects.JFXDepthManager;
import javafx.application.Platform; import javafx.application.Platform;
import javafx.beans.binding.Bindings; import javafx.beans.binding.Bindings;
import javafx.beans.binding.When; import javafx.beans.binding.When;
import javafx.collections.FXCollections;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.Pos; import javafx.geometry.Pos;
import javafx.scene.control.ColorPicker; import javafx.scene.control.ColorPicker;
@ -34,6 +36,7 @@ import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox; import javafx.scene.layout.VBox;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.text.Font; import javafx.scene.text.Font;
import javafx.scene.text.FontSmoothingType;
import org.jackhuang.hmcl.setting.EnumBackgroundImage; import org.jackhuang.hmcl.setting.EnumBackgroundImage;
import org.jackhuang.hmcl.setting.FontManager; import org.jackhuang.hmcl.setting.FontManager;
import org.jackhuang.hmcl.setting.Theme; import org.jackhuang.hmcl.setting.Theme;
@ -44,8 +47,11 @@ import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.javafx.SafeStringConverter; import org.jackhuang.hmcl.util.javafx.SafeStringConverter;
import java.util.Arrays; import java.util.Arrays;
import java.util.Locale;
import java.util.Optional;
import static org.jackhuang.hmcl.setting.ConfigHolder.config; import static org.jackhuang.hmcl.setting.ConfigHolder.config;
import static org.jackhuang.hmcl.setting.ConfigHolder.globalConfig;
import static org.jackhuang.hmcl.util.i18n.I18n.i18n; import static org.jackhuang.hmcl.util.i18n.I18n.i18n;
public class PersonalizationPage extends StackPane { public class PersonalizationPage extends StackPane {
@ -216,6 +222,46 @@ public class PersonalizationPage extends StackPane {
fontPane.getContent().add(vbox); fontPane.getContent().add(vbox);
} }
{
BorderPane fontAntiAliasingPane = new BorderPane();
{
Label left = new Label(i18n("settings.launcher.font.anti_aliasing"));
BorderPane.setAlignment(left, Pos.CENTER_LEFT);
fontAntiAliasingPane.setLeft(left);
}
{
@SuppressWarnings("unchecked")
JFXComboBox<Optional<FontSmoothingType>> cboAntiAliasing = new JFXComboBox<>(FXCollections.observableArrayList(
Optional.empty(),
Optional.of(FontSmoothingType.LCD),
Optional.of(FontSmoothingType.GRAY)
));
String fontAntiAliasing = globalConfig().getFontAntiAliasing();
if ("lcd".equalsIgnoreCase(fontAntiAliasing)) {
cboAntiAliasing.setValue(Optional.of(FontSmoothingType.LCD));
} else if ("gray".equalsIgnoreCase(fontAntiAliasing)) {
cboAntiAliasing.setValue(Optional.of(FontSmoothingType.GRAY));
} else {
cboAntiAliasing.setValue(Optional.empty());
}
cboAntiAliasing.setConverter(FXUtils.stringConverter(value -> {
if (value.isPresent()) {
return i18n("settings.launcher.font.anti_aliasing." + value.get().name().toLowerCase(Locale.ROOT));
} else {
return i18n("settings.launcher.font.anti_aliasing.auto");
}
}));
FXUtils.onChange(cboAntiAliasing.valueProperty(), value ->
globalConfig().setFontAntiAliasing(value.map(it -> it.name().toLowerCase(Locale.ROOT))
.orElse(null)));
fontAntiAliasingPane.setRight(cboAntiAliasing);
}
fontPane.getContent().add(fontAntiAliasingPane);
}
content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.font")), fontPane); content.getChildren().addAll(ComponentList.createComponentListTitle(i18n("settings.launcher.font")), fontPane);
} }
} }

View File

@ -1321,6 +1321,10 @@ settings.launcher.download_source=Download Source
settings.launcher.download_source.auto=Automatically Choose Download Sources settings.launcher.download_source.auto=Automatically Choose Download Sources
settings.launcher.enable_game_list=Show instance list in homepage settings.launcher.enable_game_list=Show instance list in homepage
settings.launcher.font=Font settings.launcher.font=Font
settings.launcher.font.anti_aliasing=Anti-aliasing
settings.launcher.font.anti_aliasing.auto=Auto
settings.launcher.font.anti_aliasing.gray=Grayscale
settings.launcher.font.anti_aliasing.lcd=Sub-pixel
settings.launcher.general=General settings.launcher.general=General
settings.launcher.language=Language (Applies After Restart) settings.launcher.language=Language (Applies After Restart)
settings.launcher.launcher_log.export=Export Launcher Logs settings.launcher.launcher_log.export=Export Launcher Logs

View File

@ -1118,6 +1118,10 @@ settings.launcher.download_source=下載來源
settings.launcher.download_source.auto=自動選取下載來源 settings.launcher.download_source.auto=自動選取下載來源
settings.launcher.enable_game_list=在首頁內顯示遊戲清單 settings.launcher.enable_game_list=在首頁內顯示遊戲清單
settings.launcher.font=字體 settings.launcher.font=字體
settings.launcher.font.anti_aliasing=抗鋸齒 (重啟後生效)
settings.launcher.font.anti_aliasing.auto=自動
settings.launcher.font.anti_aliasing.gray=灰度
settings.launcher.font.anti_aliasing.lcd=子像素
settings.launcher.general=一般 settings.launcher.general=一般
settings.launcher.language=語言 (重啟後生效) settings.launcher.language=語言 (重啟後生效)
settings.launcher.launcher_log.export=匯出啟動器日誌 settings.launcher.launcher_log.export=匯出啟動器日誌

View File

@ -1128,6 +1128,10 @@ settings.launcher.download_source=下载源
settings.launcher.download_source.auto=自动选择下载源 settings.launcher.download_source.auto=自动选择下载源
settings.launcher.enable_game_list=在主页内显示版本列表 settings.launcher.enable_game_list=在主页内显示版本列表
settings.launcher.font=字体 settings.launcher.font=字体
settings.launcher.font.anti_aliasing=抗锯齿 (重启后生效)
settings.launcher.font.anti_aliasing.auto=自动
settings.launcher.font.anti_aliasing.gray=灰度
settings.launcher.font.anti_aliasing.lcd=子像素
settings.launcher.general=通用 settings.launcher.general=通用
settings.launcher.language=语言 (重启后生效) settings.launcher.language=语言 (重启后生效)
settings.launcher.launcher_log.export=导出启动器日志 settings.launcher.launcher_log.export=导出启动器日志