diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 6b09222e9..00ed301e6 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -65,6 +65,7 @@ public final class Launcher extends Application { CookieHandler.setDefault(COOKIE_MANAGER); + LOG.info("JavaFX Version: " + System.getProperty("javafx.runtime.version")); try { Object pipeline = Class.forName("com.sun.prism.GraphicsPipeline").getMethod("getPipeline").invoke(null); LOG.info("Prism pipeline: " + (pipeline == null ? "null" : pipeline.getClass().getName())); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java index 857d0fe05..5571a9f6d 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/Theme.java @@ -23,16 +23,21 @@ import com.google.gson.stream.JsonWriter; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.scene.paint.Color; +import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.Logging; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.io.IOUtils; import java.io.File; import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.logging.Level; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static org.jackhuang.hmcl.setting.ConfigHolder.config; @@ -49,6 +54,34 @@ public class Theme { Color.web("#B71C1C") // red }; + private static Charset cssCharset; + + private static Charset getCssCharset() { + if (cssCharset != null) + return cssCharset; + + Charset defaultCharset = Charset.defaultCharset(); + if (defaultCharset != StandardCharsets.UTF_8) { + // https://bugs.openjdk.org/browse/JDK-8279328 + // For JavaFX 17 or earlier, native encoding should be used + String jfxVersion = System.getProperty("javafx.version"); + if (jfxVersion != null) { + Matcher matcher = Pattern.compile("^(?[0-9]+)").matcher(jfxVersion); + if (matcher.find()) { + int v = Lang.parseInt(matcher.group(), -1); + if (v >= 18) { + cssCharset = StandardCharsets.UTF_8; + } + } + } + } + + if (cssCharset == null) + cssCharset = defaultCharset; + + return cssCharset; + } + public static Theme getTheme() { Theme theme = config().getTheme(); return theme == null ? BLUE : theme; @@ -93,7 +126,7 @@ public class Theme { Color textFill = getForegroundColor(); try { File temp = File.createTempFile("hmcl", ".css"); - FileUtils.writeText(temp, IOUtils.readFullyAsString(Theme.class.getResourceAsStream("/assets/css/custom.css")) + String themeText = IOUtils.readFullyAsString(Theme.class.getResourceAsStream("/assets/css/custom.css")) .replace("%base-color%", color) .replace("%base-red%", Integer.toString((int) Math.ceil(paint.getRed() * 256))) .replace("%base-green%", Integer.toString((int) Math.ceil(paint.getGreen() * 256))) @@ -101,7 +134,8 @@ public class Theme { .replace("%base-rippler-color%", String.format("rgba(%d, %d, %d, 0.3)", (int) Math.ceil(paint.getRed() * 256), (int) Math.ceil(paint.getGreen() * 256), (int) Math.ceil(paint.getBlue() * 256))) .replace("%disabled-font-color%", String.format("rgba(%d, %d, %d, 0.7)", (int) Math.ceil(textFill.getRed() * 256), (int) Math.ceil(textFill.getGreen() * 256), (int) Math.ceil(textFill.getBlue() * 256))) .replace("%font-color%", getColorDisplayName(getForegroundColor())) - .replace("%font%", Optional.ofNullable(fontFamily).map(f -> "-fx-font-family: \"" + f + "\";").orElse(""))); + .replace("%font%", Optional.ofNullable(fontFamily).map(f -> "-fx-font-family: \"" + f + "\";").orElse("")); + FileUtils.writeText(temp, themeText, getCssCharset()); temp.deleteOnExit(); css = temp.toURI().toString(); } catch (IOException | NullPointerException e) {