* Fixed hybrid mana symbol display for characteristic-based card rendering. Removed not used import statements.

This commit is contained in:
LevelX2 2016-09-03 10:52:14 +02:00
parent cb91c5b9aa
commit 720a4457fd
9 changed files with 1490 additions and 1523 deletions

View file

@ -2,7 +2,6 @@ package org.mage.card.arcane;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Point; import java.awt.Point;
@ -20,8 +19,6 @@ import java.awt.image.BufferedImage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -30,7 +27,6 @@ import mage.cards.MagePermanent;
import mage.cards.TextPopup; import mage.cards.TextPopup;
import mage.cards.action.ActionCallback; import mage.cards.action.ActionCallback;
import mage.cards.action.TransferData; import mage.cards.action.TransferData;
import mage.client.components.layout.RelativeLayout;
import mage.client.plugins.adapters.MageActionCallback; import mage.client.plugins.adapters.MageActionCallback;
import mage.client.plugins.impl.Plugins; import mage.client.plugins.impl.Plugins;
import mage.client.util.audio.AudioManager; import mage.client.util.audio.AudioManager;
@ -510,10 +506,10 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
} }
/** /**
* Inheriting classes should implement update(CardView card) by * Inheriting classes should implement update(CardView card) by using this.
* using this. However, they should ALSO call repaint() after the superclass * However, they should ALSO call repaint() after the superclass call to
* call to this function, that can't be done here as the overriders may need * this function, that can't be done here as the overriders may need to do
* to do things both before and after this call before repainting. * things both before and after this call before repainting.
*/ */
@Override @Override
public void update(CardView card) { public void update(CardView card) {
@ -540,9 +536,9 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
this.isSelected = card.isSelected(); this.isSelected = card.isSelected();
// Update art? // Update art?
boolean mustUpdateArt = boolean mustUpdateArt
(!gameCard.getName().equals(card.getName())) || = (!gameCard.getName().equals(card.getName()))
(gameCard.isFaceDown() != card.isFaceDown()); || (gameCard.isFaceDown() != card.isFaceDown());
// Set the new card // Set the new card
this.gameCard = card; this.gameCard = card;

View file

@ -1,8 +1,6 @@
package org.mage.card.arcane; package org.mage.card.arcane;
import com.google.common.base.Function;
import com.google.common.collect.MapMaker; import com.google.common.collect.MapMaker;
import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
@ -12,7 +10,6 @@ import java.io.File;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
import mage.cards.action.ActionCallback; import mage.cards.action.ActionCallback;
import mage.client.util.ImageCaches;
import mage.constants.CardType; import mage.constants.CardType;
import mage.view.CardView; import mage.view.CardView;
import mage.view.CounterView; import mage.view.CounterView;
@ -95,6 +92,7 @@ public class CardPanelRenderImpl extends CardPanel {
} }
class ImageKey { class ImageKey {
final BufferedImage artImage; final BufferedImage artImage;
final int width; final int width;
final int height; final int height;
@ -234,8 +232,8 @@ public class CardPanelRenderImpl extends CardPanel {
// Render the card if we don't have an image ready to use // Render the card if we don't have an image ready to use
if (cardImage == null) { if (cardImage == null) {
// Try to get card image from cache based on our card characteristics // Try to get card image from cache based on our card characteristics
ImageKey key = ImageKey key
new ImageKey(gameCard, artImage, = new ImageKey(gameCard, artImage,
getCardWidth(), getCardHeight(), getCardWidth(), getCardHeight(),
isChoosable(), isSelected()); isChoosable(), isSelected());
cardImage = IMAGE_CACHE.get(key); cardImage = IMAGE_CACHE.get(key);
@ -253,6 +251,7 @@ public class CardPanelRenderImpl extends CardPanel {
/** /**
* Render the card to a new BufferedImage at it's current dimensions * Render the card to a new BufferedImage at it's current dimensions
*
* @return * @return
*/ */
private BufferedImage renderCard() { private BufferedImage renderCard() {
@ -260,16 +259,16 @@ public class CardPanelRenderImpl extends CardPanel {
int cardHeight = getCardHeight(); int cardHeight = getCardHeight();
// Create image to render to // Create image to render to
BufferedImage image = BufferedImage image
GraphicsUtilities.createCompatibleTranslucentImage(cardWidth, cardHeight); = GraphicsUtilities.createCompatibleTranslucentImage(cardWidth, cardHeight);
Graphics2D g2d = image.createGraphics(); Graphics2D g2d = image.createGraphics();
// Render with Antialialsing // Render with Antialialsing
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Attributes // Attributes
CardPanelAttributes attribs = CardPanelAttributes attribs
new CardPanelAttributes(cardWidth, cardHeight, isChoosable(), isSelected()); = new CardPanelAttributes(cardWidth, cardHeight, isChoosable(), isSelected());
// Draw card itself // Draw card itself
cardRenderer.draw(g2d, attribs); cardRenderer.draw(g2d, attribs);
@ -280,6 +279,7 @@ public class CardPanelRenderImpl extends CardPanel {
} }
private int updateArtImageStamp; private int updateArtImageStamp;
@Override @Override
public void updateArtImage() { public void updateArtImage() {
// Invalidate // Invalidate
@ -297,7 +297,6 @@ public class CardPanelRenderImpl extends CardPanel {
// See if the image is already loaded // See if the image is already loaded
//artImage = ImageCache.tryGetImage(gameCard, getCardWidth(), getCardHeight()); //artImage = ImageCache.tryGetImage(gameCard, getCardWidth(), getCardHeight());
//this.cardRenderer.setArtImage(artImage); //this.cardRenderer.setArtImage(artImage);
// Submit a task to draw with the card art when it arrives // Submit a task to draw with the card art when it arrives
if (artImage == null) { if (artImage == null) {
final int stamp = ++updateArtImageStamp; final int stamp = ++updateArtImageStamp;

View file

@ -8,21 +8,15 @@ package org.mage.card.arcane;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.Color; import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image; import java.awt.Image;
import java.awt.Paint; import java.awt.Paint;
import java.awt.Polygon; import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.text.AttributedString;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import mage.client.dialog.PreferencesDialog; import mage.client.dialog.PreferencesDialog;
import mage.constants.AbilityType; import mage.constants.AbilityType;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Rarity;
import mage.counters.Counter;
import mage.utils.CardUtil; import mage.utils.CardUtil;
import mage.view.CardView; import mage.view.CardView;
import mage.view.CounterView; import mage.view.CounterView;
@ -37,23 +31,19 @@ import org.apache.log4j.Logger;
* Follows the template method pattern to implement a new renderer, implement * Follows the template method pattern to implement a new renderer, implement
* the following methods (they are called in the following order): * the following methods (they are called in the following order):
* *
* * drawBorder() * * drawBorder() Draws the outermost border of the card, white border or black
* Draws the outermost border of the card, white border or black border * border
* *
* * drawBackground() * * drawBackground() Draws the background texture / color of the card
* Draws the background texture / color of the card
* *
* * drawArt() * * drawArt() Draws the card's art
* Draws the card's art
* *
* * drawFrame() * * drawFrame() Draws the card frame (over the art and background)
* Draws the card frame (over the art and background)
* *
* * drawOverlays() * * drawOverlays() Draws summoning sickness and possible other overlays
* Draws summoning sickness and possible other overlays
* *
* * drawCounters() * * drawCounters() Draws counters on the card, such as +1/+1 and -1/-1
* Draws counters on the card, such as +1/+1 and -1/-1 counters * counters
* *
* Predefined methods that the implementations can use: * Predefined methods that the implementations can use:
* *
@ -65,11 +55,11 @@ import org.apache.log4j.Logger;
* *
*/ */
public abstract class CardRenderer { public abstract class CardRenderer {
private static final Logger LOGGER = Logger.getLogger(CardPanel.class); private static final Logger LOGGER = Logger.getLogger(CardPanel.class);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Common layout metrics between all cards // Common layout metrics between all cards
// The card to be rendered // The card to be rendered
protected final CardView cardView; protected final CardView cardView;
@ -81,7 +71,6 @@ public abstract class CardRenderer {
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Common layout metrics between all cards // Common layout metrics between all cards
// Polygons for counters // Polygons for counters
private static final Polygon PLUS_COUNTER_POLY = new Polygon(new int[]{ private static final Polygon PLUS_COUNTER_POLY = new Polygon(new int[]{
0, 5, 10, 10, 5, 0 0, 5, 10, 10, 5, 0
@ -199,13 +188,15 @@ public abstract class CardRenderer {
// Template methods to be implemented by sub classes // Template methods to be implemented by sub classes
// For instance, for the Modern vs Old border card frames // For instance, for the Modern vs Old border card frames
protected abstract void drawBorder(Graphics2D g); protected abstract void drawBorder(Graphics2D g);
protected abstract void drawBackground(Graphics2D g); protected abstract void drawBackground(Graphics2D g);
protected abstract void drawArt(Graphics2D g); protected abstract void drawArt(Graphics2D g);
protected abstract void drawFrame(Graphics2D g); protected abstract void drawFrame(Graphics2D g);
// Template methods that are possible to override, but unlikely to be // Template methods that are possible to override, but unlikely to be
// overridden. // overridden.
// Draw the card back // Draw the card back
protected void drawCardBack(Graphics2D g) { protected void drawCardBack(Graphics2D g) {
g.setPaint(BG_TEXTURE_CARDBACK); g.setPaint(BG_TEXTURE_CARDBACK);
@ -328,6 +319,7 @@ public abstract class CardRenderer {
} }
return setSymbolWidth; return setSymbolWidth;
} }
private Color getRarityColor() { private Color getRarityColor() {
switch (cardView.getRarity()) { switch (cardView.getRarity()) {
case RARE: case RARE:

View file

@ -2,20 +2,12 @@ package org.mage.card.arcane;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.collect.MapMaker; import com.google.common.collect.MapMaker;
import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.font.FontRenderContext; import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer; import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute; import java.awt.font.TextAttribute;
import java.awt.font.TextLayout; import java.awt.font.TextLayout;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.text.AttributedCharacterIterator; import java.text.AttributedCharacterIterator;
import java.text.AttributedString; import java.text.AttributedString;
@ -23,10 +15,12 @@ import java.text.BreakIterator;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import javax.swing.*;
import mage.client.util.ImageCaches; import mage.client.util.ImageCaches;
import org.jdesktop.swingx.graphics.GraphicsUtilities; import org.jdesktop.swingx.graphics.GraphicsUtilities;
public class GlowText extends JLabel { public class GlowText extends JLabel {
private static final long serialVersionUID = 1827677946939348001L; private static final long serialVersionUID = 1827677946939348001L;
private int glowSize; private int glowSize;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@ -36,8 +30,8 @@ public class GlowText extends JLabel {
private int lineCount = 0; private int lineCount = 0;
private static Map<Key, BufferedImage> IMAGE_CACHE; private static Map<Key, BufferedImage> IMAGE_CACHE;
private final static class Key private final static class Key {
{
final int width; final int width;
final int height; final int height;
final String text; final String text;
@ -53,8 +47,9 @@ public class GlowText extends JLabel {
Font getFont() { Font getFont() {
Font res = this.originalFont.get(); Font res = this.originalFont.get();
if(res == null) if (res == null) {
res = Font.getFont(this.fontAttributes); res = Font.getFont(this.fontAttributes);
}
return res; return res;
} }

View file

@ -9,21 +9,17 @@ import java.awt.BasicStroke;
import java.awt.Color; import java.awt.Color;
import java.awt.Font; import java.awt.Font;
import java.awt.FontFormatException; import java.awt.FontFormatException;
import java.awt.GradientPaint;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.LinearGradientPaint; import java.awt.LinearGradientPaint;
import java.awt.Paint; import java.awt.Paint;
import java.awt.Polygon; import java.awt.Polygon;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.TexturePaint; import java.awt.TexturePaint;
import java.awt.font.FontRenderContext; import java.awt.font.FontRenderContext;
import java.awt.font.LineBreakMeasurer; import java.awt.font.LineBreakMeasurer;
import java.awt.font.TextAttribute; import java.awt.font.TextAttribute;
import java.awt.font.TextLayout; import java.awt.font.TextLayout;
import java.awt.font.TextMeasurer; import java.awt.font.TextMeasurer;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
@ -40,15 +36,7 @@ import mage.client.dialog.PreferencesDialog;
import mage.constants.CardType; import mage.constants.CardType;
import mage.view.CardView; import mage.view.CardView;
import mage.view.PermanentView; import mage.view.PermanentView;
import net.java.balloontip.styles.RoundedBalloonStyle;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.mage.card.arcane.CardRenderer;
import org.mage.card.arcane.CardRendererUtils;
import org.mage.card.arcane.ManaSymbols;
import org.mage.card.arcane.TextboxLoyaltyRule;
import org.mage.card.arcane.TextboxRule;
import org.mage.card.arcane.TextboxRuleType;
import sun.security.pkcs11.P11TlsKeyMaterialGenerator;
/* /*
@ -70,24 +58,24 @@ import sun.security.pkcs11.P11TlsKeyMaterialGenerator;
render.draw(g, cardWidth, cardHeight); render.draw(g, cardWidth, cardHeight);
} }
*/ */
/** /**
* @author stravant@gmail.com * @author stravant@gmail.com
* *
* Base rendering class for new border cards * Base rendering class for new border cards
*/ */
public class ModernCardRenderer extends CardRenderer { public class ModernCardRenderer extends CardRenderer {
private static Logger LOGGER = Logger.getLogger(ModernCardRenderer.class);
private final static Logger LOGGER = Logger.getLogger(ModernCardRenderer.class);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Textures for modern frame cards // Textures for modern frame cards
private static TexturePaint loadBackgroundTexture(String name) { private static TexturePaint loadBackgroundTexture(String name) {
URL url = ModernCardRenderer.class.getResource("/cardrender/background_texture_" + name + ".png"); URL url = ModernCardRenderer.class.getResource("/cardrender/background_texture_" + name + ".png");
ImageIcon icon = new ImageIcon(url); ImageIcon icon = new ImageIcon(url);
BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage()); BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage());
return new TexturePaint(img, new Rectangle(0, 0, img.getWidth(), img.getHeight())); return new TexturePaint(img, new Rectangle(0, 0, img.getWidth(), img.getHeight()));
} }
private static Font loadFont(String name) { private static Font loadFont(String name) {
try { try {
return Font.createFont( return Font.createFont(
@ -148,10 +136,8 @@ public class ModernCardRenderer extends CardRenderer {
public static Color ERROR_COLOR = new Color(255, 0, 255); public static Color ERROR_COLOR = new Color(255, 0, 255);
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Layout metrics for modern border cards // Layout metrics for modern border cards
// How far the main box, art, and name / type line are inset from the // How far the main box, art, and name / type line are inset from the
// card border. That is, the width of background texture that shows around // card border. That is, the width of background texture that shows around
// the edge of the card. // the edge of the card.
@ -302,8 +288,8 @@ public class ModernCardRenderer extends CardRenderer {
if (artImage != null && !cardView.isFaceDown()) { if (artImage != null && !cardView.isFaceDown()) {
int imgWidth = artImage.getWidth(); int imgWidth = artImage.getWidth();
int imgHeight = artImage.getHeight(); int imgHeight = artImage.getHeight();
BufferedImage subImg = BufferedImage subImg
artImage.getSubimage( = artImage.getSubimage(
(int) (.079 * imgWidth), (int) (.11 * imgHeight), (int) (.079 * imgWidth), (int) (.11 * imgHeight),
(int) (.84 * imgWidth), (int) (.42 * imgHeight)); (int) (.84 * imgWidth), (int) (.42 * imgHeight));
g.drawImage(subImg, g.drawImage(subImg,
@ -542,8 +528,7 @@ public class ModernCardRenderer extends CardRenderer {
x + w / 2, x + w / 2,
(int) (x + w * 0.4), (int) (x + w * 0.4),
x, x,
(int)(x + w*0.1), (int) (x + w * 0.1),},
},
new int[]{ new int[]{
y + h, y + h,
(int) (y + 0.8 * h), (int) (y + 0.8 * h),
@ -552,8 +537,7 @@ public class ModernCardRenderer extends CardRenderer {
y, y,
(int) (y - 0.2 * h), (int) (y - 0.2 * h),
y, y,
(int)(y + 0.8*h), (int) (y + 0.8 * h),},
},
8); 8);
// Draw + stroke // Draw + stroke
@ -598,6 +582,7 @@ public class ModernCardRenderer extends CardRenderer {
// Draw the card's textbox in a given rect // Draw the card's textbox in a given rect
protected boolean loyaltyAbilityColorToggle = false; protected boolean loyaltyAbilityColorToggle = false;
protected void drawRulesText(Graphics2D g, int x, int y, int w, int h) { protected void drawRulesText(Graphics2D g, int x, int y, int w, int h) {
// Initial font size to try to render at // Initial font size to try to render at
Font font = new Font("Arial", Font.PLAIN, 12); Font font = new Font("Arial", Font.PLAIN, 12);
@ -668,9 +653,9 @@ public class ModernCardRenderer extends CardRenderer {
if (remaining <= 0) { if (remaining <= 0) {
spacing = 0; spacing = 0;
} else { } else {
spacing = (int)(remaining / (hasKeywords ? spacing = (int) (remaining / (hasKeywords
(textboxRules.size() + 2) : ? (textboxRules.size() + 2)
(textboxRules.size() + 1))); : (textboxRules.size() + 1)));
} }
// Do the actual draw // Do the actual draw
@ -769,15 +754,13 @@ public class ModernCardRenderer extends CardRenderer {
symbolX + symbolWidth, symbolX + symbolWidth,
symbolX + symbolWidth, symbolX + symbolWidth,
symbolX + symbolWidth / 2, symbolX + symbolWidth / 2,
symbolX, symbolX,},
},
new int[]{ new int[]{
symbolY, symbolY,
symbolY, symbolY,
symbolY + symbolHeight - 3, symbolY + symbolHeight - 3,
symbolY + symbolHeight + 3, symbolY + symbolHeight + 3,
symbolY + symbolHeight - 3, symbolY + symbolHeight - 3,},
},
5); 5);
} else if (loyaltyRule.loyaltyChange > 0) { } else if (loyaltyRule.loyaltyChange > 0) {
symbol = new Polygon( symbol = new Polygon(
@ -786,15 +769,13 @@ public class ModernCardRenderer extends CardRenderer {
symbolX + symbolWidth / 2, symbolX + symbolWidth / 2,
symbolX + symbolWidth, symbolX + symbolWidth,
symbolX + symbolWidth, symbolX + symbolWidth,
symbolX, symbolX,},
},
new int[]{ new int[]{
symbolY + 3, symbolY + 3,
symbolY - 3, symbolY - 3,
symbolY + 3, symbolY + 3,
symbolY + symbolHeight, symbolY + symbolHeight,
symbolY + symbolHeight, symbolY + symbolHeight,},
},
5); 5);
} else { } else {
symbol = new Polygon( symbol = new Polygon(
@ -802,14 +783,12 @@ public class ModernCardRenderer extends CardRenderer {
symbolX, symbolX,
symbolX + symbolWidth, symbolX + symbolWidth,
symbolX + symbolWidth, symbolX + symbolWidth,
symbolX, symbolX,},
},
new int[]{ new int[]{
symbolY, symbolY,
symbolY, symbolY,
symbolY + symbolHeight, symbolY + symbolHeight,
symbolY + symbolHeight, symbolY + symbolHeight,},
},
4); 4);
} }
g.setColor(new Color(0, 0, 0, 128)); g.setColor(new Color(0, 0, 0, 128));
@ -841,9 +820,11 @@ public class ModernCardRenderer extends CardRenderer {
protected boolean isNightCard() { protected boolean isNightCard() {
return isTransformed; return isTransformed;
} }
protected boolean isTransformCard() { protected boolean isTransformCard() {
return cardView.canTransform() || isTransformed; return cardView.canTransform() || isTransformed;
} }
protected int drawTransformationCircle(Graphics2D g, Paint borderPaint) { protected int drawTransformationCircle(Graphics2D g, Paint borderPaint) {
int transformCircleOffset = 0; int transformCircleOffset = 0;
if (isTransformCard()) { if (isTransformCard()) {

View file

@ -5,7 +5,6 @@
*/ */
package org.mage.card.arcane; package org.mage.card.arcane;
import java.text.AttributedString;
import java.util.List; import java.util.List;
/** /**
@ -14,6 +13,7 @@ import java.util.List;
* Level rule associated with leveler cards * Level rule associated with leveler cards
*/ */
public class TextboxLevelRule extends TextboxRule { public class TextboxLevelRule extends TextboxRule {
// The levels that this rule applies to // The levels that this rule applies to
public int levelFrom; public int levelFrom;
public int levelTo; public int levelTo;

View file

@ -5,13 +5,13 @@
*/ */
package org.mage.card.arcane; package org.mage.card.arcane;
import java.text.AttributedString;
import java.util.List; import java.util.List;
/** /**
* @author StravantUser * @author StravantUser
*/ */
public class TextboxLoyaltyRule extends TextboxRule { public class TextboxLoyaltyRule extends TextboxRule {
public int loyaltyChange; public int loyaltyChange;
public static int MINUS_X = 100; public static int MINUS_X = 100;

View file

@ -16,18 +16,21 @@ import java.util.List;
/** /**
* @author stravant@gmail.com * @author stravant@gmail.com
* *
* Class describing parsed & translated rules in the text box of a card, * Class describing parsed & translated rules in the text box of a card, ready
* ready to be rendered. * to be rendered.
*/ */
public class TextboxRule { public class TextboxRule {
// An attributed region in the text, which can be applied to an // An attributed region in the text, which can be applied to an
// attributed string. // attributed string.
public interface AttributeRegion { public interface AttributeRegion {
public void applyToAttributedString(AttributedString str, Font normal, Font italic); public void applyToAttributedString(AttributedString str, Font normal, Font italic);
} }
// A region of italics, or bold text in a // A region of italics, or bold text in a
public static class ItalicRegion implements AttributeRegion { public static class ItalicRegion implements AttributeRegion {
ItalicRegion(int start, int end) { ItalicRegion(int start, int end) {
this.start = start; this.start = start;
this.end = end; this.end = end;
@ -45,6 +48,7 @@ public class TextboxRule {
// A special symbol embedded at some point in a string // A special symbol embedded at some point in a string
public static class EmbeddedSymbol implements AttributeRegion { public static class EmbeddedSymbol implements AttributeRegion {
EmbeddedSymbol(String symbol, int location) { EmbeddedSymbol(String symbol, int location) {
this.symbol = symbol; this.symbol = symbol;
this.location = location; this.location = location;
@ -54,10 +58,10 @@ public class TextboxRule {
@Override @Override
public void applyToAttributedString(AttributedString str, Font normal, Font italic) { public void applyToAttributedString(AttributedString str, Font normal, Font italic) {
Image symbolImage = ManaSymbols.getSizedManaSymbol(symbol, normal.getSize()); Image symbolImage = ManaSymbols.getSizedManaSymbol(symbol.replace("/", ""), normal.getSize());
if (symbolImage != null) { if (symbolImage != null) {
ImageGraphicAttribute imgAttr = ImageGraphicAttribute imgAttr
new ImageGraphicAttribute(symbolImage, GraphicAttribute.BOTTOM_ALIGNMENT); = new ImageGraphicAttribute(symbolImage, GraphicAttribute.BOTTOM_ALIGNMENT);
str.addAttribute(TextAttribute.CHAR_REPLACEMENT, imgAttr, location, location + 1); str.addAttribute(TextAttribute.CHAR_REPLACEMENT, imgAttr, location, location + 1);
} }
} }

View file

@ -5,19 +5,12 @@
*/ */
package org.mage.card.arcane; package org.mage.card.arcane;
import java.awt.Font;
import java.awt.Image; import java.awt.Image;
import java.awt.font.GraphicAttribute;
import java.awt.font.ImageGraphicAttribute;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Deque; import java.util.Deque;
import java.util.List;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import mage.client.dialog.PreferencesDialog;
import mage.view.CardView; import mage.view.CardView;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -26,6 +19,7 @@ import org.apache.log4j.Logger;
* @author StravantUser * @author StravantUser
*/ */
public class TextboxRuleParser { public class TextboxRuleParser {
private static final Logger LOGGER = Logger.getLogger(CardPanel.class); private static final Logger LOGGER = Logger.getLogger(CardPanel.class);
private static final Pattern LevelAbilityPattern = Pattern.compile("Level (\\d+)-?(\\d*)(\\+?)"); private static final Pattern LevelAbilityPattern = Pattern.compile("Level (\\d+)-?(\\d*)(\\+?)");
@ -86,7 +80,8 @@ public class TextboxRuleParser {
while (index < rule.length()) { while (index < rule.length()) {
int initialIndex = index; int initialIndex = index;
char ch = rule.charAt(index); char ch = rule.charAt(index);
if (ch == '{') { switch (ch) {
case '{': {
// Handling for `{this}` // Handling for `{this}`
int closeIndex = rule.indexOf('}', index); int closeIndex = rule.indexOf('}', index);
if (closeIndex == -1) { if (closeIndex == -1) {
@ -103,7 +98,7 @@ public class TextboxRuleParser {
index += contents.length() + 2; index += contents.length() + 2;
outputIndex += cardName.length(); outputIndex += cardName.length();
} else { } else {
Image symbol = ManaSymbols.getSizedManaSymbol(contents, 10); Image symbol = ManaSymbols.getSizedManaSymbol(contents.replace("/", ""), 10);
if (symbol != null) { if (symbol != null) {
// Mana or other inline symbol // Mana or other inline symbol
build.append('#'); build.append('#');
@ -120,8 +115,9 @@ public class TextboxRuleParser {
} }
} }
} }
break;
} else if (ch == '&') { }
case '&':
// Handling for `&mdash;` // Handling for `&mdash;`
if (rule.startsWith("&mdash;", index)) { if (rule.startsWith("&mdash;", index)) {
build.append('—'); build.append('—');
@ -137,9 +133,8 @@ public class TextboxRuleParser {
++index; ++index;
++outputIndex; ++outputIndex;
} }
break;
case '<': {
} else if (ch == '<') {
// Handling for `<i>` and `<br/>` // Handling for `<i>` and `<br/>`
int closeIndex = rule.indexOf('>', index); int closeIndex = rule.indexOf('>', index);
if (closeIndex != -1) { if (closeIndex != -1) {
@ -166,13 +161,14 @@ public class TextboxRuleParser {
} }
// What tag is it? // What tag is it?
if (tag.equals("/i")) { switch (tag) {
case "/i":
// Italics // Italics
regions.add(new TextboxRule.ItalicRegion(openingIndex, outputIndex)); regions.add(new TextboxRule.ItalicRegion(openingIndex, outputIndex));
} else if (tag.equals("/b")) { break;
case "/b":
// Bold, see if it's a level ability // Bold, see if it's a level ability
String content = build.substring(openingIndex); String content = build.substring(openingIndex);
Matcher levelMatch = LevelAbilityPattern.matcher(content); Matcher levelMatch = LevelAbilityPattern.matcher(content);
if (levelMatch.find()) { if (levelMatch.find()) {
try { try {
@ -188,13 +184,15 @@ public class TextboxRuleParser {
LOGGER.error("Bad leveler levels in rule `" + rule + "`."); LOGGER.error("Bad leveler levels in rule `" + rule + "`.");
} }
} }
} else { break;
default:
// Unknown // Unknown
build.append('<').append(tag).append('>'); build.append('<').append(tag).append('>');
outputIndex += (tag.length() + 2); outputIndex += (tag.length() + 2);
break;
} }
} else { } else // Is it a <br> tag special case? [Why can't it have a closing `/`... =( ]
// Is it a <br> tag special case? [Why can't it have a closing `/`... =( ] {
if (tag.equals("br")) { if (tag.equals("br")) {
build.append('\n'); build.append('\n');
++outputIndex; ++outputIndex;
@ -211,12 +209,14 @@ public class TextboxRuleParser {
++outputIndex; ++outputIndex;
++index; ++index;
} }
break;
} else { }
default:
// Normal character // Normal character
++index; ++index;
++outputIndex; ++outputIndex;
build.append(ch); build.append(ch);
break;
} }
if (outputIndex != build.length()) { if (outputIndex != build.length()) {
// Somehow our parsing code output symbols but didn't update the output index correspondingly // Somehow our parsing code output symbols but didn't update the output index correspondingly