diff --git a/src/main/java/moe/dituon/petpet/share/element/text/GraphicsAttributedString.java b/src/main/java/moe/dituon/petpet/share/element/text/GraphicsAttributedString.java index 51d53c22..620367b3 100644 --- a/src/main/java/moe/dituon/petpet/share/element/text/GraphicsAttributedString.java +++ b/src/main/java/moe/dituon/petpet/share/element/text/GraphicsAttributedString.java @@ -6,6 +6,7 @@ import javax.swing.text.StyleContext; import java.awt.*; import java.awt.font.TextAttribute; +import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.Map; @@ -22,16 +23,16 @@ public class GraphicsAttributedString extends AttributedString { protected int strokeSize; protected Color strokeColor; - public static Map asAttributeMap(TextData data) { + public static Map asAttributeMap(TextTemplate data) { Font font = new Font(data.getFont(), data.getStyle().getValue(), data.getSize()); return Map.of(TextAttribute.FONT, font); } - public GraphicsAttributedString(TextData data) { + public GraphicsAttributedString(TextTemplate data) { this(data.getText(), data); } - public GraphicsAttributedString(String text, TextData data) { + public GraphicsAttributedString(String text, TextTemplate data) { super(text, asAttributeMap(data)); this.text = text; this.font = StyleContext.getDefaultStyleContext().getFont( @@ -39,6 +40,7 @@ public GraphicsAttributedString(String text, TextData data) { ); this.color = data.getAwtColor(); this.align = data.getAlign(); + //TODO // this.baseline = data.getBaseline(); this.baseline = TextBaseline.TOP; this.wrap = data.getWrap(); diff --git a/src/main/java/moe/dituon/petpet/share/element/text/TextBuilder.java b/src/main/java/moe/dituon/petpet/share/element/text/TextBuilder.java index 2188ab31..42ee609d 100644 --- a/src/main/java/moe/dituon/petpet/share/element/text/TextBuilder.java +++ b/src/main/java/moe/dituon/petpet/share/element/text/TextBuilder.java @@ -11,12 +11,12 @@ public class TextBuilder { public static final List EXPR_LIST = List.of("$txt", "$from", "$to", "$group"); @Getter - protected final TextData data; + protected final TextTemplate data; @Getter protected final boolean dynamic; protected GraphicsParagraph staticParagraph; - public TextBuilder(TextData data) { + public TextBuilder(TextTemplate data) { this.data = data; var text = data.getText(); this.dynamic = EXPR_LIST.stream().anyMatch(text::contains); @@ -36,11 +36,11 @@ public GraphicsParagraph buildParagraph(GraphicsAttributedString string, int wid return buildParagraph(string, data, width); } - public static GraphicsParagraph buildParagraph(GraphicsAttributedString string, TextData data) { + public static GraphicsParagraph buildParagraph(GraphicsAttributedString string, TextTemplate data) { return buildParagraph(string, data.getWrap(), data.getAlign(), data.getBaseline()); } - public static GraphicsParagraph buildParagraph(GraphicsAttributedString string, TextData data, int width) { + public static GraphicsParagraph buildParagraph(GraphicsAttributedString string, TextTemplate data, int width) { return buildParagraph(string, data.getWrap(), data.getAlign(), data.getBaseline(), width); } diff --git a/src/main/java/moe/dituon/petpet/share/element/text/TextDynamicModel.java b/src/main/java/moe/dituon/petpet/share/element/text/TextDynamicModel.java index 812c0d09..82bb05ac 100644 --- a/src/main/java/moe/dituon/petpet/share/element/text/TextDynamicModel.java +++ b/src/main/java/moe/dituon/petpet/share/element/text/TextDynamicModel.java @@ -14,9 +14,9 @@ public class TextDynamicModel extends TextModel { public static final Pattern TEXT_VAR_REGEX = Pattern.compile("\\$txt([1-9]\\d*)\\[(.*?)]"); //$txt(num)[(xxx)] protected String text; - protected TextData data; + protected TextTemplate data; - public TextDynamicModel(TextData textData, TextExtraData extraInfo) { + public TextDynamicModel(TextTemplate textData, TextExtraData extraInfo) { this.data = textData; text = extraInfo != null ? buildText( textData.getText(), extraInfo, textData.getGreedy() diff --git a/src/main/java/moe/dituon/petpet/share/element/text/TextStaticModel.java b/src/main/java/moe/dituon/petpet/share/element/text/TextStaticModel.java index 1d544d9e..500cdaac 100644 --- a/src/main/java/moe/dituon/petpet/share/element/text/TextStaticModel.java +++ b/src/main/java/moe/dituon/petpet/share/element/text/TextStaticModel.java @@ -10,7 +10,7 @@ public class TextStaticModel extends TextModel { protected int y; protected final GraphicsParagraph paragraph; - public TextStaticModel(TextData textData, GraphicsParagraph paragraph) { + public TextStaticModel(TextTemplate textData, GraphicsParagraph paragraph) { var pos = textData.getPos(); x = pos[0]; y = pos[1]; diff --git a/src/main/java/moe/dituon/petpet/share/element/text/TextTemplate.kt b/src/main/java/moe/dituon/petpet/share/element/text/TextTemplate.kt new file mode 100644 index 00000000..0323445a --- /dev/null +++ b/src/main/java/moe/dituon/petpet/share/element/text/TextTemplate.kt @@ -0,0 +1,34 @@ +package moe.dituon.petpet.share.element.text + +import kotlinx.serialization.Serializable +import moe.dituon.petpet.share.* +import java.awt.Color + +@Serializable +data class TextTemplate( + var text: String, + var pos: IntArray = intArrayOf(0, 0), + var angle: Short = 0, + var color: String = TextModel.DEFAULT_COLOR_STR, + var font: String = "simsun", + var size: Int = 16, + var align: TextAlign = TextAlign.LEFT, + var baseline: TextBaseline = TextBaseline.TOP, + var wrap: TextWrap = TextWrap.NONE, + var style: TextStyle = TextStyle.PLAIN, + var position: List? = listOf(Position.LEFT, Position.TOP), + var origin: TransformOrigin = TransformOrigin.DEFAULT, + var strokeColor: String = TextModel.DEFAULT_STROKE_COLOR_STR, + var strokeSize: Short = 0, + var greedy: Boolean = false +) { + fun getAwtColor(): Color { + if (color == moe.dituon.petpet.share.TextModel.DEFAULT_COLOR_STR) return moe.dituon.petpet.share.TextModel.DEFAULT_COLOR + return decodeColor(color) + } + + fun getStrokeAwtColor(): Color { + if (strokeColor == moe.dituon.petpet.share.TextModel.DEFAULT_STROKE_COLOR_STR) return moe.dituon.petpet.share.TextModel.DEFAULT_STROKE_COLOR + return decodeColor(strokeColor) + } +} diff --git a/src/main/java/moe/dituon/petpet/share/service/FontManager.java b/src/main/java/moe/dituon/petpet/share/service/FontManager.java new file mode 100644 index 00000000..b6247dd7 --- /dev/null +++ b/src/main/java/moe/dituon/petpet/share/service/FontManager.java @@ -0,0 +1,68 @@ +package moe.dituon.petpet.share.service; + +import java.awt.*; +import java.util.List; +import java.util.*; +import java.util.stream.Collectors; + +public class FontManager { + protected static class FontManagerInstance { + private static final FontManager INSTANCE = new FontManager(); + } + + public static FontManager getInstance() { + return FontManagerInstance.INSTANCE; + } + + final GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment(); + public final List supportedLanguageList = List.of( + new SupportedLanguage("en", "Latin", new char[]{0x0061}), + new SupportedLanguage("zh", "CJK Unified Ideographs", new char[]{0x4E00}), + new SupportedLanguage("ja", "Hiragana", new char[]{0x3041}), + new SupportedLanguage("ko", "Hangul Syllables", new char[]{0xAC00}), + new SupportedLanguage("th", "Thai", new char[]{0x0E01}), + new SupportedLanguage("ru", "Cyrillic", new char[]{0x0410}), + new SupportedLanguage("ar", "Arabic", new char[]{0x0621}), + new SupportedLanguage("he", "Hebrew", new char[]{0x05D0}), + new SupportedLanguage("vi", "Vietnamese", new char[]{0x0102}) +// , new SupportedLanguage("emoji", "Emoji", Character.toChars(0x1F600)) + ); + final Map> fontSupportedLanguageMap = new HashMap<>(256); + final Map> supportedLanguageFontMap = new HashMap<>(256); + + protected FontManager() { + for (Font font : environment.getAllFonts()) { + addFont(font); + } + } + + public void addFont(Font font) { + var langSet = fontSupportedLanguageMap.compute(font, (f, s) -> + s == null ? new HashSet<>(supportedLanguageList.size()) : s + ); + for (SupportedLanguage language : supportedLanguageList) { + boolean flag = true; + for (char point : language.testPoints) { + if (!font.canDisplay(point)) flag = false; + } + if (flag) { + langSet.add(language); + supportedLanguageFontMap.compute(language, (l, s) -> + s == null ? new HashSet<>(8) : s + ).add(font); + } + } + } + + public static class SupportedLanguage { + protected char[] testPoints; + public final String name; + public final String desc; + + protected SupportedLanguage(String name, String desc, char[] testPoints) { + this.name = name; + this.desc = desc; + this.testPoints = testPoints; + } + } +} diff --git a/src/main/java/moe/dituon/petpet/share/service/TemplateManager.java b/src/main/java/moe/dituon/petpet/share/service/TemplateManager.java index 755fb4db..309f7746 100644 --- a/src/main/java/moe/dituon/petpet/share/service/TemplateManager.java +++ b/src/main/java/moe/dituon/petpet/share/service/TemplateManager.java @@ -4,6 +4,7 @@ import moe.dituon.petpet.share.Type; import moe.dituon.petpet.share.template.PetpetTemplate; import moe.dituon.petpet.share.template.TemplateBuilder; +import moe.dituon.petpet.share.template.TemplateType; import java.io.File; import java.io.IOException; @@ -36,7 +37,7 @@ public void pushBasePath(File basePath) throws IOException { var background = new BackgroundResource(file); resourceManager.pushBackground(id, background); - if (templateConfig.getType() == Type.IMG && background.files.length > 1) { + if (templateConfig.getType() == TemplateType.IMG && background.files.length > 1) { background.randomFlag = true; } var templateBuilder = new TemplateBuilder(templateConfig, background); diff --git a/src/main/java/moe/dituon/petpet/share/template/PetpetTemplate.kt b/src/main/java/moe/dituon/petpet/share/template/PetpetTemplate.kt index 60d690e5..44ebdb4f 100644 --- a/src/main/java/moe/dituon/petpet/share/template/PetpetTemplate.kt +++ b/src/main/java/moe/dituon/petpet/share/template/PetpetTemplate.kt @@ -4,17 +4,20 @@ import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json import moe.dituon.petpet.share.BackgroundData -import moe.dituon.petpet.share.TextData -import moe.dituon.petpet.share.Type import moe.dituon.petpet.share.element.avatar.AvatarTemplate +import moe.dituon.petpet.share.element.text.TextTemplate import moe.dituon.petpet.share.script.LuaTableSerializer import org.luaj.vm2.LuaTable +enum class TemplateType { + GIF, IMG +} + @Serializable data class PetpetTemplate( - val type: Type, + val type: TemplateType, val avatar: List = emptyList(), - val text: List = emptyList(), + val text: List = emptyList(), val background: BackgroundData? = null, val delay: Int = 65, val alias: List = emptyList(),