Fixed a bug that the mana symbols for monocolored hybrid mana were not shown.

This commit is contained in:
LevelX2 2018-03-11 13:03:58 +01:00
parent 2fb8926432
commit fe5743b29e
2 changed files with 82 additions and 83 deletions

View file

@ -1,6 +1,14 @@
package org.mage.card.arcane; package org.mage.card.arcane;
import java.awt.*; import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource; import java.awt.image.FilteredImageSource;
import java.awt.image.ImageProducer; import java.awt.image.ImageProducer;
@ -18,13 +26,18 @@ import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.*; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.*; import javax.swing.*;
import mage.cards.repository.ExpansionRepository; import mage.cards.repository.ExpansionRepository;
import mage.client.constants.Constants;
import mage.client.constants.Constants.ResourceSetSize;
import mage.client.constants.Constants.ResourceSymbolSize;
import mage.client.util.GUISizeHelper; import mage.client.util.GUISizeHelper;
import mage.client.util.ImageHelper; import mage.client.util.ImageHelper;
import mage.client.util.gui.BufferedImageBuilder; import mage.client.util.gui.BufferedImageBuilder;
@ -36,13 +49,6 @@ import org.apache.batik.transcoder.TranscodingHints;
import org.apache.batik.transcoder.image.ImageTranscoder; import org.apache.batik.transcoder.image.ImageTranscoder;
import org.apache.batik.util.SVGConstants; import org.apache.batik.util.SVGConstants;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import mage.client.constants.Constants;
import mage.client.constants.Constants.ResourceSymbolSize;
import mage.client.constants.Constants.ResourceSetSize;
import org.jdesktop.swingx.graphics.ShadowRenderer;
import org.jdesktop.swingx.graphics.GraphicsUtilities;
import org.mage.plugins.card.utils.CardImageUtils; import org.mage.plugins.card.utils.CardImageUtils;
public final class ManaSymbols { public final class ManaSymbols {
@ -71,9 +77,14 @@ public final class ManaSymbols {
private static final Map<String, Dimension> setImagesExist = new HashMap<>(); private static final Map<String, Dimension> setImagesExist = new HashMap<>();
private static final Pattern REPLACE_SYMBOLS_PATTERN = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}"); private static final Pattern REPLACE_SYMBOLS_PATTERN = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}");
private static String cachedPath; private static String cachedPath;
private static final String[] symbols = new String[]{"0", "1", "10", "11", "12", "15", "16", "2", "3", "4", "5", "6", "7", "8", "9", "B", "BG", private static final String[] symbols = new String[]{"0", "1", "10", "11", "12", "15", "16", "2", "3", "4", "5", "6", "7", "8", "9",
"BR", "G", "GU", "GW", "R", "RG", "RW", "S", "T", "U", "UB", "UR", "W", "WB", "WU", "B", "BG", "BR", "BP", "2B",
"WP", "UP", "BP", "RP", "GP", "X", "C", "E"}; "G", "GU", "GW", "GP", "2G",
"R", "RG", "RW", "RP", "2R",
"S", "T",
"U", "UB", "UR", "UP", "2U",
"W", "WB", "WU", "WP", "2W",
"X", "C", "E"};
private static final JLabel labelRender = new JLabel(); // render mana text private static final JLabel labelRender = new JLabel(); // render mana text
@ -93,22 +104,21 @@ public final class ManaSymbols {
// save symbol images in png for html replacement in texts // save symbol images in png for html replacement in texts
// you can add bigger size for better quality // you can add bigger size for better quality
Map<String, BufferedImage> pngImages = manaImages.get(50); Map<String, BufferedImage> pngImages = manaImages.get(50);
if (pngImages != null){ if (pngImages != null) {
File pngPath = new File(getResourceSymbolsPath(ResourceSymbolSize.PNG)); File pngPath = new File(getResourceSymbolsPath(ResourceSymbolSize.PNG));
if (!pngPath.exists()) { if (!pngPath.exists()) {
pngPath.mkdirs(); pngPath.mkdirs();
} }
for(String symbol: symbols){ for (String symbol : symbols) {
try try {
{
BufferedImage image = pngImages.get(symbol); BufferedImage image = pngImages.get(symbol);
if (image != null){ if (image != null) {
File newFile = new File(pngPath.getPath() + File.separator + symbol + ".png"); File newFile = new File(pngPath.getPath() + File.separator + symbol + ".png");
ImageIO.write(image, "png", newFile); ImageIO.write(image, "png", newFile);
} }
}catch (Exception e) { } catch (Exception e) {
LOGGER.warn("Can't generate png image for symbol:" + symbol); LOGGER.warn("Can't generate png image for symbol:" + symbol);
} }
} }
@ -222,8 +232,7 @@ public final class ManaSymbols {
// load SVG image // load SVG image
// base loader code: https://stackoverflow.com/questions/11435671/how-to-get-a-buffererimage-from-a-svg // base loader code: https://stackoverflow.com/questions/11435671/how-to-get-a-buffererimage-from-a-svg
// resize code: https://vibranttechie.wordpress.com/2015/05/15/svg-loading-to-javafx-stage-and-auto-scaling-when-stage-resize/ // resize code: https://vibranttechie.wordpress.com/2015/05/15/svg-loading-to-javafx-stage-and-auto-scaling-when-stage-resize/
if (useShadow && ((resizeToWidth <= 0) || (resizeToHeight <= 0))) {
if (useShadow && ((resizeToWidth <= 0) || (resizeToHeight <= 0))){
throw new IllegalArgumentException("Must use non zero sizes for shadow."); throw new IllegalArgumentException("Must use non zero sizes for shadow.");
} }
@ -234,12 +243,12 @@ public final class ManaSymbols {
// These defaults emphasize quality and precision, and // These defaults emphasize quality and precision, and
// are more similar to the defaults of other SVG viewers. // are more similar to the defaults of other SVG viewers.
// SVG documents can still override these defaults. // SVG documents can still override these defaults.
String css = "svg {" + String css = "svg {"
"shape-rendering: geometricPrecision;" + + "shape-rendering: geometricPrecision;"
"text-rendering: geometricPrecision;" + + "text-rendering: geometricPrecision;"
"color-rendering: optimizeQuality;" + + "color-rendering: optimizeQuality;"
"image-rendering: optimizeQuality;" + + "image-rendering: optimizeQuality;"
"}"; + "}";
File cssFile = File.createTempFile("batik-default-override-", ".css"); File cssFile = File.createTempFile("batik-default-override-", ".css");
FileWriter w = new FileWriter(cssFile); FileWriter w = new FileWriter(cssFile);
w.write(css); w.write(css);
@ -250,7 +259,7 @@ public final class ManaSymbols {
// resize // resize
int shadowX = 0; int shadowX = 0;
int shadowY = 0; int shadowY = 0;
if(useShadow) { if (useShadow) {
// shadow size (16px image: 1px left, 2px bottom) // shadow size (16px image: 1px left, 2px bottom)
shadowX = 1 * Math.round(1f / 16f * resizeToWidth); shadowX = 1 * Math.round(1f / 16f * resizeToWidth);
shadowY = 2 * Math.round(1f / 16f * resizeToHeight); shadowY = 2 * Math.round(1f / 16f * resizeToHeight);
@ -258,11 +267,11 @@ public final class ManaSymbols {
resizeToHeight = resizeToHeight - shadowY; resizeToHeight = resizeToHeight - shadowY;
}; };
if(resizeToWidth > 0){ if (resizeToWidth > 0) {
transcoderHints.put(ImageTranscoder.KEY_WIDTH, (float)resizeToWidth); //your image width transcoderHints.put(ImageTranscoder.KEY_WIDTH, (float) resizeToWidth); //your image width
} }
if(resizeToHeight > 0){ if (resizeToHeight > 0) {
transcoderHints.put(ImageTranscoder.KEY_HEIGHT, (float)resizeToHeight); //your image height transcoderHints.put(ImageTranscoder.KEY_HEIGHT, (float) resizeToHeight); //your image height
} }
transcoderHints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE); transcoderHints.put(ImageTranscoder.KEY_XML_PARSER_VALIDATING, Boolean.FALSE);
@ -293,14 +302,13 @@ public final class ManaSymbols {
t.transcode(input, null); t.transcode(input, null);
} catch (Exception e) { } catch (Exception e) {
throw new IOException("Couldn't convert svg file: " + svgFile + " , reason: " + e.getMessage()); throw new IOException("Couldn't convert svg file: " + svgFile + " , reason: " + e.getMessage());
} } finally {
finally {
cssFile.delete(); cssFile.delete();
} }
BufferedImage originImage = imagePointer[0]; BufferedImage originImage = imagePointer[0];
if(useShadow && (originImage.getWidth() > 0)){ if (useShadow && (originImage.getWidth() > 0)) {
// draw shadow // draw shadow
// origin image was reduces in sizes to fit shadow // origin image was reduces in sizes to fit shadow
// see https://stackoverflow.com/a/40833715/1276632 // see https://stackoverflow.com/a/40833715/1276632
@ -309,10 +317,11 @@ public final class ManaSymbols {
ImageProducer prod = new FilteredImageSource(originImage.getSource(), new RGBImageFilter() { ImageProducer prod = new FilteredImageSource(originImage.getSource(), new RGBImageFilter() {
@Override @Override
public int filterRGB(int x, int y, int rgb) { public int filterRGB(int x, int y, int rgb) {
if (rgb == 0) if (rgb == 0) {
return 0; return 0;
else } else {
return 0xff000000; return 0xff000000;
}
} }
}); });
// create whe black image // create whe black image
@ -325,7 +334,7 @@ public final class ManaSymbols {
// draw original image // draw original image
g.drawImage(originImage, 0, 0, null); g.drawImage(originImage, 0, 0, null);
return result; return result;
}else{ } else {
// return origin image without shadow // return origin image without shadow
return originImage; return originImage;
} }
@ -340,23 +349,22 @@ public final class ManaSymbols {
ShadowRenderer renderer = new ShadowRenderer(shadowSize, 0.5f, ShadowRenderer renderer = new ShadowRenderer(shadowSize, 0.5f,
Color.GRAY); Color.GRAY);
return renderer.createShadow(base); return renderer.createShadow(base);
*/ */
//imagePointer[0]; //imagePointer[0];
} }
public static File getSymbolFileNameAsSVG(String symbol){ public static File getSymbolFileNameAsSVG(String symbol) {
return new File(getResourceSymbolsPath(ResourceSymbolSize.SVG) + symbol + ".svg"); return new File(getResourceSymbolsPath(ResourceSymbolSize.SVG) + symbol + ".svg");
} }
private static BufferedImage loadSymbolAsSVG(String symbol, int resizeToWidth, int resizeToHeight){ private static BufferedImage loadSymbolAsSVG(String symbol, int resizeToWidth, int resizeToHeight) {
File sourceFile = getSymbolFileNameAsSVG(symbol); File sourceFile = getSymbolFileNameAsSVG(symbol);
return loadSymbolAsSVG(sourceFile, resizeToWidth, resizeToHeight); return loadSymbolAsSVG(sourceFile, resizeToWidth, resizeToHeight);
} }
private static BufferedImage loadSymbolAsSVG(File sourceFile, int resizeToWidth, int resizeToHeight){ private static BufferedImage loadSymbolAsSVG(File sourceFile, int resizeToWidth, int resizeToHeight) {
try{ try {
// no need to resize svg (lib already do it on load) // no need to resize svg (lib already do it on load)
return loadSVG(sourceFile, resizeToWidth, resizeToHeight, true); return loadSVG(sourceFile, resizeToWidth, resizeToHeight, true);
@ -366,12 +374,12 @@ public final class ManaSymbols {
} }
} }
private static File getSymbolFileNameAsGIF(String symbol, int size){ private static File getSymbolFileNameAsGIF(String symbol, int size) {
ResourceSymbolSize needSize = null; ResourceSymbolSize needSize = null;
if (size <= 15){ if (size <= 15) {
needSize = ResourceSymbolSize.SMALL; needSize = ResourceSymbolSize.SMALL;
}else if (size <= 25){ } else if (size <= 25) {
needSize = ResourceSymbolSize.MEDIUM; needSize = ResourceSymbolSize.MEDIUM;
} else { } else {
needSize = ResourceSymbolSize.LARGE; needSize = ResourceSymbolSize.LARGE;
@ -380,20 +388,20 @@ public final class ManaSymbols {
return new File(getResourceSymbolsPath(needSize) + symbol + ".gif"); return new File(getResourceSymbolsPath(needSize) + symbol + ".gif");
} }
private static BufferedImage loadSymbolAsGIF(String symbol, int resizeToWidth, int resizeToHeight){ private static BufferedImage loadSymbolAsGIF(String symbol, int resizeToWidth, int resizeToHeight) {
File file = getSymbolFileNameAsGIF(symbol, resizeToWidth); File file = getSymbolFileNameAsGIF(symbol, resizeToWidth);
return loadSymbolAsGIF(file, resizeToWidth, resizeToHeight); return loadSymbolAsGIF(file, resizeToWidth, resizeToHeight);
} }
private static BufferedImage loadSymbolAsGIF(File sourceFile, int resizeToWidth, int resizeToHeight){ private static BufferedImage loadSymbolAsGIF(File sourceFile, int resizeToWidth, int resizeToHeight) {
BufferedImage image = null; BufferedImage image = null;
try { try {
if ((resizeToWidth == 15) || (resizeToWidth == 25)){ if ((resizeToWidth == 15) || (resizeToWidth == 25)) {
// normal size // normal size
image = ImageIO.read(sourceFile); image = ImageIO.read(sourceFile);
}else{ } else {
// resize size // resize size
image = ImageIO.read(sourceFile); image = ImageIO.read(sourceFile);
@ -407,7 +415,7 @@ public final class ManaSymbols {
return null; return null;
} }
return image; return image;
} }
private static boolean loadSymbolImages(int size) { private static boolean loadSymbolImages(int size) {
@ -454,7 +462,7 @@ public final class ManaSymbols {
private static void renameSymbols(String path) { private static void renameSymbols(String path) {
File file = new File(path); File file = new File(path);
if (!file.exists()){ if (!file.exists()) {
return; return;
} }
@ -475,7 +483,7 @@ public final class ManaSymbols {
} }
} }
private static String getResourceSymbolsPath(ResourceSymbolSize needSize){ private static String getResourceSymbolsPath(ResourceSymbolSize needSize) {
// return real path to symbols (default or user defined) // return real path to symbols (default or user defined)
String path = CardImageUtils.getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS + File.separator; String path = CardImageUtils.getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS + File.separator;
@ -503,15 +511,14 @@ public final class ManaSymbols {
} }
// fix double separator if size folder is not set // fix double separator if size folder is not set
while(path.endsWith(File.separator)) while (path.endsWith(File.separator)) {
{
path = path.substring(0, path.length() - 1); path = path.substring(0, path.length() - 1);
} }
return path + File.separator; return path + File.separator;
} }
private static String getResourceSetsPath(ResourceSetSize needSize){ private static String getResourceSetsPath(ResourceSetSize needSize) {
// return real path to sets icons (default or user defined) // return real path to sets icons (default or user defined)
String path = CardImageUtils.getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS + File.separator; String path = CardImageUtils.getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS + File.separator;
@ -533,8 +540,7 @@ public final class ManaSymbols {
} }
// fix double separator if size folder is not set // fix double separator if size folder is not set
while(path.endsWith(File.separator)) while (path.endsWith(File.separator)) {
{
path = path.substring(0, path.length() - 1); path = path.substring(0, path.length() - 1);
} }
@ -592,10 +598,7 @@ public final class ManaSymbols {
Graphics2D gg = image.createGraphics(); Graphics2D gg = image.createGraphics();
manaPanel.paint(gg); manaPanel.paint(gg);
g.drawImage(image, x, y, null); g.drawImage(image, x, y, null);
*/ */
// OLD version with custom draw // OLD version with custom draw
Map<String, BufferedImage> sizedSymbols = manaImages.get(symbolWidth); Map<String, BufferedImage> sizedSymbols = manaImages.get(symbolWidth);
if (manaCost.isEmpty()) { if (manaCost.isEmpty()) {
@ -627,8 +630,8 @@ public final class ManaSymbols {
int stringWidth = labelRender.getFontMetrics(labelFont).stringWidth(labelText); int stringWidth = labelRender.getFontMetrics(labelFont).stringWidth(labelText);
int componentWidth = labelRender.getWidth(); int componentWidth = labelRender.getWidth();
// Find out how much the font can grow in width. // Find out how much the font can grow in width.
double widthRatio = (double)componentWidth / (double)stringWidth; double widthRatio = (double) componentWidth / (double) stringWidth;
int newFontSize = (int)(labelFont.getSize() * widthRatio); int newFontSize = (int) (labelFont.getSize() * widthRatio);
int componentHeight = labelRender.getHeight(); int componentHeight = labelRender.getHeight();
// Pick a new font size so it will not be larger than the height of label. // Pick a new font size so it will not be larger than the height of label.
int fontSizeToUse = Math.min(newFontSize, componentHeight); int fontSizeToUse = Math.min(newFontSize, componentHeight);
@ -638,11 +641,11 @@ public final class ManaSymbols {
// render component to new position // render component to new position
// need to copy graphics, overvise it draw at top left corner // need to copy graphics, overvise it draw at top left corner
// https://stackoverflow.com/questions/4974268/java-paint-problem // https://stackoverflow.com/questions/4974268/java-paint-problem
Graphics2D labelG = (Graphics2D)g.create(x, y, symbolWidth, symbolWidth); Graphics2D labelG = (Graphics2D) g.create(x, y, symbolWidth, symbolWidth);
labelG.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); labelG.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
labelG.fillOval(x + 1, y + 1, symbolWidth - 2, symbolWidth - 2); labelG.fillOval(x + 1, y + 1, symbolWidth - 2, symbolWidth - 2);
labelRender.paint(labelG); labelRender.paint(labelG);
}else { } else {
// ICON draw // ICON draw
g.drawImage(image, x, y, null); g.drawImage(image, x, y, null);
} }
@ -666,12 +669,12 @@ public final class ManaSymbols {
TOOLTIP, TOOLTIP,
} }
private static String filePathToUrl(String path){ private static String filePathToUrl(String path) {
// convert file path to uri path (for html docs) // convert file path to uri path (for html docs)
if((path != null) && (!path.equals(""))){ if ((path != null) && (!path.equals(""))) {
File file = new File(path); File file = new File(path);
return file.toURI().toString(); return file.toURI().toString();
}else{ } else {
return null; return null;
} }
} }
@ -680,7 +683,6 @@ public final class ManaSymbols {
// mana cost to HTML images (urls to files) // mana cost to HTML images (urls to files)
// do not use it for new code - try to suppotr svg render // do not use it for new code - try to suppotr svg render
int symbolSize; int symbolSize;
switch (type) { switch (type) {
case TABLE: case TABLE:
@ -702,22 +704,20 @@ public final class ManaSymbols {
// auto size // auto size
ResourceSymbolSize needSize = null; ResourceSymbolSize needSize = null;
if (symbolSize <= 15){ if (symbolSize <= 15) {
needSize = ResourceSymbolSize.SMALL; needSize = ResourceSymbolSize.SMALL;
}else if (symbolSize <= 25){ } else if (symbolSize <= 25) {
needSize = ResourceSymbolSize.MEDIUM; needSize = ResourceSymbolSize.MEDIUM;
} else { } else {
needSize = ResourceSymbolSize.LARGE; needSize = ResourceSymbolSize.LARGE;
} }
// replace every {symbol} to <img> link // replace every {symbol} to <img> link
// ignore data backup // ignore data backup
String replaced = value String replaced = value
.replace("{source}", "|source|") .replace("{source}", "|source|")
.replace("{this}", "|this|"); .replace("{this}", "|this|");
// not need to add different images (width and height do the work) // not need to add different images (width and height do the work)
// use best png size (generated on startup) TODO: add reload images after update // use best png size (generated on startup) TODO: add reload images after update
String htmlImagesPath = getResourceSymbolsPath(ResourceSymbolSize.PNG); String htmlImagesPath = getResourceSymbolsPath(ResourceSymbolSize.PNG);
@ -725,8 +725,8 @@ public final class ManaSymbols {
.replace("$", "@S@"); // paths with $ will rise error, need escape that .replace("$", "@S@"); // paths with $ will rise error, need escape that
replaced = REPLACE_SYMBOLS_PATTERN.matcher(replaced).replaceAll( replaced = REPLACE_SYMBOLS_PATTERN.matcher(replaced).replaceAll(
"<img src='" + filePathToUrl(htmlImagesPath) + "$1$2" + ".png' alt='$1$2' width=" "<img src='" + filePathToUrl(htmlImagesPath) + "$1$2" + ".png' alt='$1$2' width="
+ symbolSize + " height=" + symbolSize + '>'); + symbolSize + " height=" + symbolSize + '>');
// ignore data restore // ignore data restore
replaced = replaced replaced = replaced
@ -774,4 +774,3 @@ public final class ManaSymbols {
return sizedSymbols.get(symbol); return sizedSymbols.get(symbol);
} }
} }

View file

@ -9,7 +9,6 @@ import com.google.common.collect.AbstractIterator;
import java.io.File; import java.io.File;
import static java.lang.String.format; import static java.lang.String.format;
import java.util.Iterator; import java.util.Iterator;
import mage.client.constants.Constants; import mage.client.constants.Constants;
import org.mage.plugins.card.dl.DownloadJob; import org.mage.plugins.card.dl.DownloadJob;
import static org.mage.plugins.card.dl.DownloadJob.fromURL; import static org.mage.plugins.card.dl.DownloadJob.fromURL;
@ -42,7 +41,7 @@ public class GathererSymbols implements Iterable<DownloadJob> {
public GathererSymbols() { public GathererSymbols() {
outDir = new File(getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS); outDir = new File(getImagesDir() + Constants.RESOURCE_PATH_SYMBOLS);
if (!outDir.exists()){ if (!outDir.exists()) {
outDir.mkdirs(); outDir.mkdirs();
} }
} }
@ -76,8 +75,9 @@ public class GathererSymbols implements Iterable<DownloadJob> {
File dst = new File(dir, symbol + ".gif"); File dst = new File(dir, symbol + ".gif");
/** /**
* Handle a bug on Gatherer where a few symbols are missing at the large size. * Handle a bug on Gatherer where a few symbols are missing
* Fall back to using the medium symbol for those cases. * at the large size. Fall back to using the medium symbol
* for those cases.
*/ */
int modSizeIndex = sizeIndex; int modSizeIndex = sizeIndex;
if (sizeIndex == 2) { if (sizeIndex == 2) {
@ -93,7 +93,7 @@ public class GathererSymbols implements Iterable<DownloadJob> {
break; break;
default: default:
// Nothing to do, symbol is available in the large size // Nothing to do, symbol is available in the large size
} }
} }