From 2213da497741033a53f3c43290d76ae7a49c2a04 Mon Sep 17 00:00:00 2001 From: "marcin.sciesinski" Date: Sat, 12 Oct 2019 09:51:52 -0700 Subject: [PATCH] Worked around a Java issue with rendering fonts with AffineTransforms --- .../gempukku/lotro/images/ImageGenerator.java | 4 +- .../lotro/images/recipe/JSONImageRecipe.java | 62 ++--- .../images/recipe/TextBoxLayerRecipe.java | 22 +- .../src/main/resources/cardRecipe.json | 241 ++++++++++++------ 4 files changed, 208 insertions(+), 121 deletions(-) diff --git a/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/ImageGenerator.java b/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/ImageGenerator.java index 0a8792a3b..86d445c7d 100644 --- a/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/ImageGenerator.java +++ b/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/ImageGenerator.java @@ -38,7 +38,7 @@ public class ImageGenerator { final JSONObject cardsObject = (JSONObject) parser.parse(reader); for (Map.Entry cardEntry : (Set>) cardsObject.entrySet()) { final String cardId = cardEntry.getKey(); - if (cardId.equals("40_3") || cardId.equals("40_17") || cardId.equals("40_19")) { +// if (cardId.equals("40_3") || cardId.equals("40_17") || cardId.equals("40_19")) { BufferedImage bufferedImage = new BufferedImage(jsonImageRecipe.getWidth(), jsonImageRecipe.getHeight(), BufferedImage.TYPE_INT_RGB); jsonImageRecipe.renderImage(properties, cardEntry.getValue(), bufferedImage); @@ -52,7 +52,7 @@ public class ImageGenerator { writer.setOutput(outputStream); writer.write(null, new IIOImage(bufferedImage, null, null), jpegParams); } - } +// } } } catch (IOException | ParseException e) { throw new ImageGenerationException("Unable to generate image", e); diff --git a/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/recipe/JSONImageRecipe.java b/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/recipe/JSONImageRecipe.java index bb763a23c..617ac454a 100644 --- a/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/recipe/JSONImageRecipe.java +++ b/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/recipe/JSONImageRecipe.java @@ -27,7 +27,6 @@ public class JSONImageRecipe implements ImageRecipe { private int height; private List layers = new LinkedList<>(); private Map imageCache = new HashMap<>(); - private Map fontCache = new HashMap<>(); private Map> functionMap; public JSONImageRecipe(File file) { @@ -93,14 +92,25 @@ public class JSONImageRecipe implements ImageRecipe { map.put(fontEntry.getKey(), createFontProvider(fontEntry.getValue())); } Map glyphMap = (JSONObject) jsonLayer.get("glyphs"); + Function paint = createPaintProvider(jsonLayer.get("paint"), "black"); Function> fontStyleProvider = map::get; Function textBox = createTextBoxProvider(jsonLayer.get("box")); final Function minYStart = createFloatProvider(jsonLayer.get("minYStart")); + Map yShiftsMap = (JSONObject) jsonLayer.get("yShifts"); return new TextBoxLayerRecipe( fontStyleProvider, - s -> glyphMap.get(s), + s -> glyphMap.get(s), paint, + s -> { + if (yShiftsMap == null) + return 0f; + final Number value = yShiftsMap.get(s); + if (value == null) + return 0f; + else + return value.floatValue(); + }, text, textBox, minYStart); } else if (type.equalsIgnoreCase("rotate")) { final LayerRecipe layer = createLayerRecipe((JSONObject) jsonLayer.get("layer")); @@ -256,16 +266,11 @@ public class JSONImageRecipe implements ImageRecipe { final Path path = pathProvider.apply(renderContext); final float size = sizeProvider.apply(renderContext); final int style = styleProvider.apply(renderContext); - - FontDefinition fontDefinition = new FontDefinition(size, style, path); - return fontCache.computeIfAbsent(fontDefinition, - fontDefinition1 -> { - try { - return Font.createFont(Font.TRUETYPE_FONT, path.toFile()).deriveFont(style, size); - } catch (FontFormatException | IOException e) { - throw new ImageGenerationException("Unable to get font", e); - } - }); + try { + return Font.createFont(Font.TRUETYPE_FONT, path.toFile()).deriveFont(style, size); + } catch (FontFormatException | IOException e) { + throw new ImageGenerationException("Unable to get font", e); + } }; } } @@ -468,6 +473,12 @@ public class JSONImageRecipe implements ImageRecipe { } private Function createFloatProvider(Object value) { + return createFloatProvider(value, null); + } + + private Function createFloatProvider(Object value, Float defaultValue) { + if (value == null && defaultValue != null) + return renderContext -> defaultValue; if (value instanceof Number) { return renderContext -> ((Number) value).floatValue(); } else if (value instanceof JSONObject) { @@ -539,31 +550,4 @@ public class JSONImageRecipe implements ImageRecipe { graphics.dispose(); } } - - private class FontDefinition { - private float size; - private int style; - private Path fontPath; - - public FontDefinition(float size, int style, Path fontPath) { - this.size = size; - this.style = style; - this.fontPath = fontPath; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - FontDefinition that = (FontDefinition) o; - return Float.compare(that.size, size) == 0 && - style == that.style && - fontPath.equals(that.fontPath); - } - - @Override - public int hashCode() { - return Objects.hash(size, style, fontPath); - } - } } diff --git a/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/recipe/TextBoxLayerRecipe.java b/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/recipe/TextBoxLayerRecipe.java index d2b8279eb..5ca290636 100644 --- a/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/recipe/TextBoxLayerRecipe.java +++ b/gemp-lotr/gemp-lotr-images/src/main/java/com/gempukku/lotro/images/recipe/TextBoxLayerRecipe.java @@ -14,6 +14,8 @@ import java.util.function.Function; public class TextBoxLayerRecipe implements LayerRecipe { private Function> fontStyleProvider; private Function glyphProvider; + private Function paint; + private Function yShifts; private Function text; private Function textBox; private Function minYStart; @@ -21,11 +23,15 @@ public class TextBoxLayerRecipe implements LayerRecipe { public TextBoxLayerRecipe( Function> fontStyleProvider, Function glyphProvider, + Function paint, + Function yShifts, Function text, Function textBox, Function minYStart) { this.fontStyleProvider = fontStyleProvider; this.glyphProvider = glyphProvider; + this.paint = paint; + this.yShifts = yShifts; this.text = text; this.textBox = textBox; this.minYStart = minYStart; @@ -46,6 +52,8 @@ public class TextBoxLayerRecipe implements LayerRecipe { // graphics.fillRect(box.getX(), box.getY(), box.getWidth(), box.getHeight()); // graphics.setColor(Color.BLACK); + graphics.setPaint(paint.apply(renderContext)); + FontRenderContext frc = graphics.getFontRenderContext(); // Dry run to check for height @@ -96,21 +104,19 @@ public class TextBoxLayerRecipe implements LayerRecipe { AttributedString string = new AttributedString(resultText.toString()); parseText(text, new TextParsingCallback() { private int index = 0; - private boolean lowered = false; + private float yShift = 0; @Override public void appendText(String text, String style) { String resultStyle = (style != null) ? style : "default"; Font font = fontStyleProvider.apply(resultStyle).apply(renderContext); - if (resultStyle.equals("glyph") && !lowered) { - font = font.deriveFont(AffineTransform.getTranslateInstance(0, 3)); - lowered = true; - } else if (!resultStyle.equals("glyph") && lowered) { - font = font.deriveFont(AffineTransform.getTranslateInstance(0, -3)); - lowered = false; + final float value = yShifts.apply(resultStyle); + float result = value - yShift; + if (result != 0) { + font = font.deriveFont(AffineTransform.getTranslateInstance(0, result)); + yShift = value; } string.addAttribute(TextAttribute.FONT, font, index, index + text.length()); - string.addAttribute(TextAttribute.FOREGROUND, Color.BLACK, index, index + text.length()); index += text.length(); } }); diff --git a/gemp-lotr/gemp-lotr-images/src/main/resources/cardRecipe.json b/gemp-lotr/gemp-lotr-images/src/main/resources/cardRecipe.json index 93d01df31..694cd9f3d 100644 --- a/gemp-lotr/gemp-lotr-images/src/main/resources/cardRecipe.json +++ b/gemp-lotr/gemp-lotr-images/src/main/resources/cardRecipe.json @@ -690,30 +690,11 @@ }, { "comment": "Strength text", - "type": "text", + "type": "textBox", "paint": "white", "dropShadow": true, - "font": { - "type": "ttf", - "path": { - "type": "resolve", - "parent": { - "type": "property", - "name": "lotro.resources.folder" - }, - "child": { - "type": "property", - "name": "numbers.font" - } - }, - "size": { - "type": "property", - "name": "numbers.size" - }, - "style": 0 - }, "text": { - "type": "append", + "type": "appendText", "values": [ { "type": "optional", @@ -727,15 +708,65 @@ "type": "cardPropertyGreaterThanZero", "name": "strength" }, - "value": "+" + "value": "[symbol]+[/symbol]" } }, { - "type": "cardProperty", - "name": "strength" + "type": "replace", + "source": { + "type": "cardProperty", + "name": "strength" + }, + "match": "-", + "with": "[symbol]-[/symbol]" } ] }, + "font": { + "default": { + "type": "ttf", + "path": { + "type": "resolve", + "parent": { + "type": "property", + "name": "lotro.resources.folder" + }, + "child": { + "type": "property", + "name": "numbers.font" + } + }, + "size": { + "type": "property", + "name": "numbers.size" + }, + "style": 0 + }, + "symbol": { + "type": "ttf", + "path": { + "type": "resolve", + "parent": { + "type": "property", + "name": "lotro.resources.folder" + }, + "child": { + "type": "property", + "name": "numbers.font" + } + }, + "size": 29, + "style": 0 + } + }, + "glyphs": { + "shire": "#", + "dwarven": "@" + }, + "yShifts": { + "symbol": -10 + }, + "minYStart": 1, "box": { "type": "box", "x": 45, @@ -773,30 +804,11 @@ }, { "comment": "Vitality text", - "type": "text", + "type": "textBox", "paint": "white", "dropShadow": true, - "font": { - "type": "ttf", - "path": { - "type": "resolve", - "parent": { - "type": "property", - "name": "lotro.resources.folder" - }, - "child": { - "type": "property", - "name": "numbers.font" - } - }, - "size": { - "type": "property", - "name": "numbers.size" - }, - "style": 0 - }, "text": { - "type": "append", + "type": "appendText", "values": [ { "type": "optional", @@ -810,15 +822,65 @@ "type": "cardPropertyGreaterThanZero", "name": "vitality" }, - "value": "+" + "value": "[symbol]+[/symbol]" } }, { - "type": "cardProperty", - "name": "vitality" + "type": "replace", + "source": { + "type": "cardProperty", + "name": "vitality" + }, + "match": "-", + "with": "[symbol]-[/symbol]" } ] }, + "font": { + "default": { + "type": "ttf", + "path": { + "type": "resolve", + "parent": { + "type": "property", + "name": "lotro.resources.folder" + }, + "child": { + "type": "property", + "name": "numbers.font" + } + }, + "size": { + "type": "property", + "name": "numbers.size" + }, + "style": 0 + }, + "symbol": { + "type": "ttf", + "path": { + "type": "resolve", + "parent": { + "type": "property", + "name": "lotro.resources.folder" + }, + "child": { + "type": "property", + "name": "numbers.font" + } + }, + "size": 29, + "style": 0 + } + }, + "glyphs": { + "shire": "#", + "dwarven": "@" + }, + "yShifts": { + "symbol": -10 + }, + "minYStart": 1, "box": { "type": "box", "x": 45, @@ -856,29 +918,11 @@ }, { "comment": "Resistance text", - "type": "text", + "type": "textBox", "paint": "white", - "font": { - "type": "ttf", - "path": { - "type": "resolve", - "parent": { - "type": "property", - "name": "lotro.resources.folder" - }, - "child": { - "type": "property", - "name": "numbers.font" - } - }, - "size": { - "type": "property", - "name": "numbers.size" - }, - "style": 0 - }, + "dropShadow": true, "text": { - "type": "append", + "type": "appendText", "values": [ { "type": "optional", @@ -892,15 +936,65 @@ "type": "cardPropertyGreaterThanZero", "name": "resistance" }, - "value": "+" + "value": "[symbol]+[/symbol]" } }, { - "type": "cardProperty", - "name": "resistance" + "type": "replace", + "source": { + "type": "cardProperty", + "name": "resistance" + }, + "match": "-", + "with": "[symbol]-[/symbol]" } ] }, + "font": { + "default": { + "type": "ttf", + "path": { + "type": "resolve", + "parent": { + "type": "property", + "name": "lotro.resources.folder" + }, + "child": { + "type": "property", + "name": "numbers.font" + } + }, + "size": { + "type": "property", + "name": "numbers.size" + }, + "style": 0 + }, + "symbol": { + "type": "ttf", + "path": { + "type": "resolve", + "parent": { + "type": "property", + "name": "lotro.resources.folder" + }, + "child": { + "type": "property", + "name": "numbers.font" + } + }, + "size": 29, + "style": 0 + } + }, + "glyphs": { + "shire": "#", + "dwarven": "@" + }, + "yShifts": { + "symbol": -10 + }, + "minYStart": 1, "box": { "type": "box", "x": 45, @@ -1028,6 +1122,9 @@ "shire": "#", "dwarven": "@" }, + "yShifts": { + "glyph": 3 + }, "minYStart": 0.10, "box": { "type": "box",