mirror of
https://github.com/correl/mage.git
synced 2025-01-12 19:25:44 +00:00
* Fixed hybrid mana symbol display for characteristic-based card rendering. Removed not used import statements.
This commit is contained in:
parent
cb91c5b9aa
commit
720a4457fd
9 changed files with 1490 additions and 1523 deletions
|
@ -2,7 +2,6 @@ package org.mage.card.arcane;
|
|||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
|
@ -20,8 +19,6 @@ import java.awt.image.BufferedImage;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
|
@ -30,7 +27,6 @@ import mage.cards.MagePermanent;
|
|||
import mage.cards.TextPopup;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.cards.action.TransferData;
|
||||
import mage.client.components.layout.RelativeLayout;
|
||||
import mage.client.plugins.adapters.MageActionCallback;
|
||||
import mage.client.plugins.impl.Plugins;
|
||||
import mage.client.util.audio.AudioManager;
|
||||
|
@ -205,8 +201,8 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
|
|||
// Position transform and show source buttons
|
||||
buttonPanel.setLocation(cardXOffset, cardYOffset);
|
||||
buttonPanel.setSize(cardWidth, cardHeight);
|
||||
int x = cardWidth/20;
|
||||
int y = cardHeight/10;
|
||||
int x = cardWidth / 20;
|
||||
int y = cardHeight / 10;
|
||||
if (dayNightButton != null) {
|
||||
dayNightButton.setLocation(x, y);
|
||||
y += 25;
|
||||
|
@ -510,10 +506,10 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
|
|||
}
|
||||
|
||||
/**
|
||||
* Inheriting classes should implement update(CardView card) by
|
||||
* using this. However, they should ALSO call repaint() after the superclass
|
||||
* call to this function, that can't be done here as the overriders may need
|
||||
* to do things both before and after this call before repainting.
|
||||
* Inheriting classes should implement update(CardView card) by using this.
|
||||
* However, they should ALSO call repaint() after the superclass call to
|
||||
* this function, that can't be done here as the overriders may need to do
|
||||
* things both before and after this call before repainting.
|
||||
*/
|
||||
@Override
|
||||
public void update(CardView card) {
|
||||
|
@ -540,9 +536,9 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
|
|||
this.isSelected = card.isSelected();
|
||||
|
||||
// Update art?
|
||||
boolean mustUpdateArt =
|
||||
(!gameCard.getName().equals(card.getName())) ||
|
||||
(gameCard.isFaceDown() != card.isFaceDown());
|
||||
boolean mustUpdateArt
|
||||
= (!gameCard.getName().equals(card.getName()))
|
||||
|| (gameCard.isFaceDown() != card.isFaceDown());
|
||||
|
||||
// Set the new card
|
||||
this.gameCard = card;
|
||||
|
@ -742,13 +738,13 @@ public abstract class CardPanel extends MagePermanent implements MouseListener,
|
|||
public void update(PermanentView card) {
|
||||
this.hasSickness = card.hasSummoningSickness();
|
||||
this.showCopySourceButton.setVisible(card.isCopy());
|
||||
update((CardView)card);
|
||||
update((CardView) card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PermanentView getOriginalPermanent() {
|
||||
if (isPermanent) {
|
||||
return (PermanentView)this.gameCard;
|
||||
return (PermanentView) this.gameCard;
|
||||
}
|
||||
throw new IllegalStateException("Is not permanent.");
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package org.mage.card.arcane;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
|
@ -12,7 +10,6 @@ import java.io.File;
|
|||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.cards.action.ActionCallback;
|
||||
import mage.client.util.ImageCaches;
|
||||
import mage.constants.CardType;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CounterView;
|
||||
|
@ -80,8 +77,8 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
return false;
|
||||
}
|
||||
if ((a instanceof PermanentView)) {
|
||||
PermanentView aa = (PermanentView)a;
|
||||
PermanentView bb = (PermanentView)b;
|
||||
PermanentView aa = (PermanentView) a;
|
||||
PermanentView bb = (PermanentView) b;
|
||||
if (aa.hasSummoningSickness() != bb.hasSummoningSickness()) {
|
||||
// Note: b must be a permanentview too as we aleady checked that classes
|
||||
// are the same for a and b
|
||||
|
@ -95,6 +92,7 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
}
|
||||
|
||||
class ImageKey {
|
||||
|
||||
final BufferedImage artImage;
|
||||
final int width;
|
||||
final int height;
|
||||
|
@ -115,17 +113,17 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
|
||||
private int hashCodeImpl() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append((char)(artImage != null ? 1 : 0));
|
||||
sb.append((char)width);
|
||||
sb.append((char)height);
|
||||
sb.append((char)(isSelected ? 1 : 0));
|
||||
sb.append((char)(isChoosable ? 1 : 0));
|
||||
sb.append((char)(this.view.isPlayable() ? 1 : 0));
|
||||
sb.append((char)(this.view.isCanAttack() ? 1 : 0));
|
||||
sb.append((char)(this.view.isFaceDown() ? 1 : 0));
|
||||
sb.append((char) (artImage != null ? 1 : 0));
|
||||
sb.append((char) width);
|
||||
sb.append((char) height);
|
||||
sb.append((char) (isSelected ? 1 : 0));
|
||||
sb.append((char) (isChoosable ? 1 : 0));
|
||||
sb.append((char) (this.view.isPlayable() ? 1 : 0));
|
||||
sb.append((char) (this.view.isCanAttack() ? 1 : 0));
|
||||
sb.append((char) (this.view.isFaceDown() ? 1 : 0));
|
||||
if (this.view instanceof PermanentView) {
|
||||
sb.append((char)(((PermanentView)this.view).hasSummoningSickness() ? 1 : 0));
|
||||
sb.append((char)(((PermanentView)this.view).getDamage()));
|
||||
sb.append((char) (((PermanentView) this.view).hasSummoningSickness() ? 1 : 0));
|
||||
sb.append((char) (((PermanentView) this.view).getDamage()));
|
||||
}
|
||||
sb.append(this.view.getName());
|
||||
sb.append(this.view.getPower());
|
||||
|
@ -133,23 +131,23 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
sb.append(this.view.getLoyalty());
|
||||
sb.append(this.view.getColor().toString());
|
||||
sb.append(this.view.getExpansionSetCode());
|
||||
for (CardType type: this.view.getCardTypes()) {
|
||||
sb.append((char)type.ordinal());
|
||||
for (CardType type : this.view.getCardTypes()) {
|
||||
sb.append((char) type.ordinal());
|
||||
}
|
||||
for (String s: this.view.getSuperTypes()) {
|
||||
for (String s : this.view.getSuperTypes()) {
|
||||
sb.append(s);
|
||||
}
|
||||
for (String s: this.view.getSubTypes()) {
|
||||
for (String s : this.view.getSubTypes()) {
|
||||
sb.append(s);
|
||||
}
|
||||
for (String s: this.view.getManaCost()) {
|
||||
for (String s : this.view.getManaCost()) {
|
||||
sb.append(s);
|
||||
}
|
||||
for (String s: this.view.getRules()) {
|
||||
for (String s : this.view.getRules()) {
|
||||
sb.append(s);
|
||||
}
|
||||
if (this.view.getCounters() != null) {
|
||||
for (CounterView v: this.view.getCounters()) {
|
||||
for (CounterView v : this.view.getCounters()) {
|
||||
sb.append(v.getName()).append(v.getCount());
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +171,7 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
if (!(object instanceof ImageKey)) {
|
||||
return false;
|
||||
}
|
||||
final ImageKey other = (ImageKey)object;
|
||||
final ImageKey other = (ImageKey) object;
|
||||
|
||||
// Compare
|
||||
if ((artImage != null) != (other.artImage != null)) {
|
||||
|
@ -220,7 +218,7 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
@Override
|
||||
public void transferResources(CardPanel panel) {
|
||||
if (panel instanceof CardPanelRenderImpl) {
|
||||
CardPanelRenderImpl impl = (CardPanelRenderImpl)panel;
|
||||
CardPanelRenderImpl impl = (CardPanelRenderImpl) panel;
|
||||
|
||||
// Use the art image and current rendered image from the card
|
||||
artImage = impl.artImage;
|
||||
|
@ -234,8 +232,8 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
// Render the card if we don't have an image ready to use
|
||||
if (cardImage == null) {
|
||||
// Try to get card image from cache based on our card characteristics
|
||||
ImageKey key =
|
||||
new ImageKey(gameCard, artImage,
|
||||
ImageKey key
|
||||
= new ImageKey(gameCard, artImage,
|
||||
getCardWidth(), getCardHeight(),
|
||||
isChoosable(), isSelected());
|
||||
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
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private BufferedImage renderCard() {
|
||||
|
@ -260,16 +259,16 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
int cardHeight = getCardHeight();
|
||||
|
||||
// Create image to render to
|
||||
BufferedImage image =
|
||||
GraphicsUtilities.createCompatibleTranslucentImage(cardWidth, cardHeight);
|
||||
BufferedImage image
|
||||
= GraphicsUtilities.createCompatibleTranslucentImage(cardWidth, cardHeight);
|
||||
Graphics2D g2d = image.createGraphics();
|
||||
|
||||
// Render with Antialialsing
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
// Attributes
|
||||
CardPanelAttributes attribs =
|
||||
new CardPanelAttributes(cardWidth, cardHeight, isChoosable(), isSelected());
|
||||
CardPanelAttributes attribs
|
||||
= new CardPanelAttributes(cardWidth, cardHeight, isChoosable(), isSelected());
|
||||
|
||||
// Draw card itself
|
||||
cardRenderer.draw(g2d, attribs);
|
||||
|
@ -280,6 +279,7 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
}
|
||||
|
||||
private int updateArtImageStamp;
|
||||
|
||||
@Override
|
||||
public void updateArtImage() {
|
||||
// Invalidate
|
||||
|
@ -297,7 +297,6 @@ public class CardPanelRenderImpl extends CardPanel {
|
|||
// See if the image is already loaded
|
||||
//artImage = ImageCache.tryGetImage(gameCard, getCardWidth(), getCardHeight());
|
||||
//this.cardRenderer.setArtImage(artImage);
|
||||
|
||||
// Submit a task to draw with the card art when it arrives
|
||||
if (artImage == null) {
|
||||
final int stamp = ++updateArtImageStamp;
|
||||
|
|
|
@ -8,21 +8,15 @@ package org.mage.card.arcane;
|
|||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.text.AttributedString;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.constants.AbilityType;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Rarity;
|
||||
import mage.counters.Counter;
|
||||
import mage.utils.CardUtil;
|
||||
import mage.view.CardView;
|
||||
import mage.view.CounterView;
|
||||
|
@ -37,23 +31,19 @@ import org.apache.log4j.Logger;
|
|||
* Follows the template method pattern to implement a new renderer, implement
|
||||
* the following methods (they are called in the following order):
|
||||
*
|
||||
* * drawBorder()
|
||||
* Draws the outermost border of the card, white border or black border
|
||||
* * drawBorder() Draws the outermost border of the card, white border or black
|
||||
* border
|
||||
*
|
||||
* * drawBackground()
|
||||
* Draws the background texture / color of the card
|
||||
* * drawBackground() Draws the background texture / color of the card
|
||||
*
|
||||
* * drawArt()
|
||||
* Draws the card's art
|
||||
* * drawArt() Draws the card's art
|
||||
*
|
||||
* * drawFrame()
|
||||
* Draws the card frame (over the art and background)
|
||||
* * drawFrame() Draws the card frame (over the art and background)
|
||||
*
|
||||
* * drawOverlays()
|
||||
* Draws summoning sickness and possible other overlays
|
||||
* * drawOverlays() Draws summoning sickness and possible other overlays
|
||||
*
|
||||
* * drawCounters()
|
||||
* Draws counters on the card, such as +1/+1 and -1/-1 counters
|
||||
* * drawCounters() Draws counters on the card, such as +1/+1 and -1/-1
|
||||
* counters
|
||||
*
|
||||
* Predefined methods that the implementations can use:
|
||||
*
|
||||
|
@ -65,11 +55,11 @@ import org.apache.log4j.Logger;
|
|||
*
|
||||
*/
|
||||
public abstract class CardRenderer {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CardPanel.class);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Common layout metrics between all cards
|
||||
|
||||
// The card to be rendered
|
||||
protected final CardView cardView;
|
||||
|
||||
|
@ -81,7 +71,6 @@ public abstract class CardRenderer {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Common layout metrics between all cards
|
||||
|
||||
// Polygons for counters
|
||||
private static final Polygon PLUS_COUNTER_POLY = new Polygon(new int[]{
|
||||
0, 5, 10, 10, 5, 0
|
||||
|
@ -140,7 +129,7 @@ public abstract class CardRenderer {
|
|||
this.isTransformed = isTransformed;
|
||||
|
||||
// Translate the textbox text
|
||||
for (String rule: card.getRules()) {
|
||||
for (String rule : card.getRules()) {
|
||||
// Kill reminder text
|
||||
if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_CARD_RENDERING_REMINDER_TEXT, "false").equals("false")) {
|
||||
rule = CardRendererUtils.killReminderText(rule).trim();
|
||||
|
@ -167,11 +156,11 @@ public abstract class CardRenderer {
|
|||
this.cardHeight = cardHeight;
|
||||
|
||||
// Corner radius and border width
|
||||
cornerRadius = (int)Math.max(
|
||||
cornerRadius = (int) Math.max(
|
||||
CORNER_RADIUS_MIN,
|
||||
CORNER_RADIUS_FRAC * cardWidth);
|
||||
|
||||
borderWidth = (int)Math.max(
|
||||
borderWidth = (int) Math.max(
|
||||
BORDER_WIDTH_MIN,
|
||||
BORDER_WIDTH_FRAC * cardWidth);
|
||||
}
|
||||
|
@ -199,28 +188,30 @@ public abstract class CardRenderer {
|
|||
// Template methods to be implemented by sub classes
|
||||
// For instance, for the Modern vs Old border card frames
|
||||
protected abstract void drawBorder(Graphics2D g);
|
||||
|
||||
protected abstract void drawBackground(Graphics2D g);
|
||||
|
||||
protected abstract void drawArt(Graphics2D g);
|
||||
|
||||
protected abstract void drawFrame(Graphics2D g);
|
||||
|
||||
// Template methods that are possible to override, but unlikely to be
|
||||
// overridden.
|
||||
|
||||
// Draw the card back
|
||||
protected void drawCardBack(Graphics2D g) {
|
||||
g.setPaint(BG_TEXTURE_CARDBACK);
|
||||
g.fillRect(borderWidth, borderWidth,
|
||||
cardWidth - 2*borderWidth, cardHeight - 2*borderWidth);
|
||||
cardWidth - 2 * borderWidth, cardHeight - 2 * borderWidth);
|
||||
}
|
||||
|
||||
// Draw summoning sickness overlay, and possibly other overlays
|
||||
protected void drawOverlays(Graphics2D g) {
|
||||
if (CardUtil.isCreature(cardView) && cardView instanceof PermanentView) {
|
||||
if (((PermanentView)cardView).hasSummoningSickness()) {
|
||||
int x1 = (int)(0.2*cardWidth);
|
||||
int x2 = (int)(0.8*cardWidth);
|
||||
int y1 = (int)(0.2*cardHeight);
|
||||
int y2 = (int)(0.8*cardHeight);
|
||||
if (((PermanentView) cardView).hasSummoningSickness()) {
|
||||
int x1 = (int) (0.2 * cardWidth);
|
||||
int x2 = (int) (0.8 * cardWidth);
|
||||
int y1 = (int) (0.2 * cardHeight);
|
||||
int y2 = (int) (0.8 * cardHeight);
|
||||
int xPoints[] = {
|
||||
x1, x2, x1, x2
|
||||
};
|
||||
|
@ -235,10 +226,10 @@ public abstract class CardRenderer {
|
|||
g.drawPolygon(xPoints, yPoints, 4);
|
||||
g.setStroke(new BasicStroke(1));
|
||||
int[] xPoints2 = {
|
||||
x1, x2, cardWidth/2
|
||||
x1, x2, cardWidth / 2
|
||||
};
|
||||
int[] yPoints2 = {
|
||||
y1, y1, cardHeight/2
|
||||
y1, y1, cardHeight / 2
|
||||
};
|
||||
g.setColor(new Color(0, 0, 0, 100));
|
||||
g.fillPolygon(xPoints2, yPoints2, 3);
|
||||
|
@ -248,10 +239,10 @@ public abstract class CardRenderer {
|
|||
|
||||
// Draw +1/+1 and other counters
|
||||
protected void drawCounters(Graphics2D g) {
|
||||
int xPos = (int)(0.65*cardWidth);
|
||||
int yPos = (int)(0.15*cardHeight);
|
||||
int xPos = (int) (0.65 * cardWidth);
|
||||
int yPos = (int) (0.15 * cardHeight);
|
||||
if (cardView.getCounters() != null) {
|
||||
for (CounterView v: cardView.getCounters()) {
|
||||
for (CounterView v : cardView.getCounters()) {
|
||||
// Don't render loyalty, we do that in the bottom corner
|
||||
if (!v.getName().equals("loyalty")) {
|
||||
Polygon p;
|
||||
|
@ -264,8 +255,8 @@ public abstract class CardRenderer {
|
|||
} else {
|
||||
p = OTHER_COUNTER_POLY;
|
||||
}
|
||||
double scale = (0.1*0.25*cardWidth);
|
||||
Graphics2D g2 = (Graphics2D)g.create();
|
||||
double scale = (0.1 * 0.25 * cardWidth);
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
g2.translate(xPos, yPos);
|
||||
g2.scale(scale, scale);
|
||||
g2.setColor(Color.white);
|
||||
|
@ -275,9 +266,9 @@ public abstract class CardRenderer {
|
|||
g2.setFont(new Font("Arial", Font.BOLD, 7));
|
||||
String cstr = "" + v.getCount();
|
||||
int strW = g2.getFontMetrics().stringWidth(cstr);
|
||||
g2.drawString(cstr, 5 - strW/2, 8);
|
||||
g2.drawString(cstr, 5 - strW / 2, 8);
|
||||
g2.dispose();
|
||||
yPos += ((int)(0.30*cardWidth));
|
||||
yPos += ((int) (0.30 * cardWidth));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,19 +306,20 @@ public abstract class CardRenderer {
|
|||
int height = setSymbol.getHeight(null);
|
||||
int scale = 1;
|
||||
if (height != -1) {
|
||||
while (height > h+2) {
|
||||
while (height > h + 2) {
|
||||
scale *= 2;
|
||||
height /= 2;
|
||||
}
|
||||
}
|
||||
setSymbolWidth = setSymbol.getWidth(null) / scale;
|
||||
g.drawImage(setSymbol,
|
||||
x + w - setSymbolWidth, y + (h - height)/2,
|
||||
x + w - setSymbolWidth, y + (h - height) / 2,
|
||||
setSymbolWidth, height,
|
||||
null);
|
||||
}
|
||||
return setSymbolWidth;
|
||||
}
|
||||
|
||||
private Color getRarityColor() {
|
||||
switch (cardView.getRarity()) {
|
||||
case RARE:
|
||||
|
|
|
@ -2,20 +2,12 @@ package org.mage.card.arcane;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.MapMaker;
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.LineBreakMeasurer;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.font.TextLayout;
|
||||
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.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedString;
|
||||
|
@ -23,10 +15,12 @@ import java.text.BreakIterator;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import javax.swing.*;
|
||||
import mage.client.util.ImageCaches;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
|
||||
public class GlowText extends JLabel {
|
||||
|
||||
private static final long serialVersionUID = 1827677946939348001L;
|
||||
private int glowSize;
|
||||
@SuppressWarnings("unused")
|
||||
|
@ -36,12 +30,12 @@ public class GlowText extends JLabel {
|
|||
private int lineCount = 0;
|
||||
private static Map<Key, BufferedImage> IMAGE_CACHE;
|
||||
|
||||
private final static class Key
|
||||
{
|
||||
private final static class Key {
|
||||
|
||||
final int width;
|
||||
final int height;
|
||||
final String text;
|
||||
final Map<TextAttribute,?> fontAttributes;
|
||||
final Map<TextAttribute, ?> fontAttributes;
|
||||
final Color color;
|
||||
final int glowSize;
|
||||
final float glowIntensity;
|
||||
|
@ -53,8 +47,9 @@ public class GlowText extends JLabel {
|
|||
|
||||
Font getFont() {
|
||||
Font res = this.originalFont.get();
|
||||
if(res == null)
|
||||
if (res == null) {
|
||||
res = Font.getFont(this.fontAttributes);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -138,18 +133,18 @@ public class GlowText extends JLabel {
|
|||
}));
|
||||
}
|
||||
|
||||
public void setGlow (Color glowColor, int size, float intensity) {
|
||||
public void setGlow(Color glowColor, int size, float intensity) {
|
||||
this.glowColor = glowColor;
|
||||
this.glowSize = size;
|
||||
this.glowIntensity = intensity;
|
||||
}
|
||||
|
||||
public void setWrap (boolean wrap) {
|
||||
public void setWrap(boolean wrap) {
|
||||
this.wrap = wrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize () {
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension size = super.getPreferredSize();
|
||||
size.width += glowSize;
|
||||
size.height += glowSize / 2;
|
||||
|
@ -157,7 +152,7 @@ public class GlowText extends JLabel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void paint (Graphics g) {
|
||||
public void paint(Graphics g) {
|
||||
if (getText().length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -165,7 +160,7 @@ public class GlowText extends JLabel {
|
|||
g.drawImage(IMAGE_CACHE.get(new Key(getWidth(), getHeight(), getText(), getFont(), getForeground(), glowSize, glowIntensity, glowColor, wrap)), 0, 0, null);
|
||||
}
|
||||
|
||||
private static BufferedImage createImage (Key key) {
|
||||
private static BufferedImage createImage(Key key) {
|
||||
Dimension size = new Dimension(key.width, key.height);
|
||||
BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(size.width, size.height);
|
||||
Graphics2D g2d = image.createGraphics();
|
||||
|
|
|
@ -9,21 +9,17 @@ import java.awt.BasicStroke;
|
|||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.GradientPaint;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Image;
|
||||
import java.awt.LinearGradientPaint;
|
||||
import java.awt.Paint;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.TexturePaint;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.LineBreakMeasurer;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.font.TextMeasurer;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.geom.RoundRectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
@ -40,15 +36,7 @@ import mage.client.dialog.PreferencesDialog;
|
|||
import mage.constants.CardType;
|
||||
import mage.view.CardView;
|
||||
import mage.view.PermanentView;
|
||||
import net.java.balloontip.styles.RoundedBalloonStyle;
|
||||
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);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author stravant@gmail.com
|
||||
*
|
||||
* Base rendering class for new border cards
|
||||
*/
|
||||
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
|
||||
|
||||
private static TexturePaint loadBackgroundTexture(String name) {
|
||||
URL url = ModernCardRenderer.class.getResource("/cardrender/background_texture_" + name + ".png");
|
||||
ImageIcon icon = new ImageIcon(url);
|
||||
BufferedImage img = CardRendererUtils.toBufferedImage(icon.getImage());
|
||||
return new TexturePaint(img, new Rectangle(0, 0, img.getWidth(), img.getHeight()));
|
||||
}
|
||||
|
||||
private static Font loadFont(String name) {
|
||||
try {
|
||||
return Font.createFont(
|
||||
|
@ -148,10 +136,8 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
|
||||
public static Color ERROR_COLOR = new Color(255, 0, 255);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Layout metrics for modern border cards
|
||||
|
||||
// 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
|
||||
// the edge of the card.
|
||||
|
@ -208,28 +194,28 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
totalContentInset = borderWidth + contentInset;
|
||||
|
||||
// Content width
|
||||
contentWidth = cardWidth - 2*totalContentInset;
|
||||
contentWidth = cardWidth - 2 * totalContentInset;
|
||||
|
||||
// Box height
|
||||
boxHeight = (int)Math.max(
|
||||
boxHeight = (int) Math.max(
|
||||
BOX_HEIGHT_MIN,
|
||||
BOX_HEIGHT_FRAC * cardHeight);
|
||||
|
||||
// Type line at
|
||||
if (cardView.isToken()) {
|
||||
typeLineY = (int)(TYPE_LINE_Y_FRAC_TOKEN * cardHeight);
|
||||
typeLineY = (int) (TYPE_LINE_Y_FRAC_TOKEN * cardHeight);
|
||||
} else {
|
||||
typeLineY = (int)(TYPE_LINE_Y_FRAC * cardHeight);
|
||||
typeLineY = (int) (TYPE_LINE_Y_FRAC * cardHeight);
|
||||
}
|
||||
|
||||
// Box text height
|
||||
boxTextHeight = getTextHeightForBoxHeight(boxHeight);
|
||||
boxTextOffset = (boxHeight - boxTextHeight)/2;
|
||||
boxTextOffset = (boxHeight - boxTextHeight) / 2;
|
||||
boxTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, boxTextHeight);
|
||||
|
||||
// Box text height
|
||||
ptTextHeight = getPTTextHeightForLineHeight(boxHeight);
|
||||
ptTextOffset = (boxHeight - ptTextHeight)/2;
|
||||
ptTextOffset = (boxHeight - ptTextHeight) / 2;
|
||||
ptTextFont = BASE_BELEREN_FONT.deriveFont(Font.PLAIN, ptTextHeight);
|
||||
}
|
||||
|
||||
|
@ -247,14 +233,14 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
borderColor = new Color(250, 250, 0, 230);
|
||||
} else if (cardView.isPlayable()) {
|
||||
borderColor = new Color(153, 102, 204, 200);
|
||||
} else if (cardView instanceof PermanentView && ((PermanentView)cardView).isCanAttack()) {
|
||||
} else if (cardView instanceof PermanentView && ((PermanentView) cardView).isCanAttack()) {
|
||||
borderColor = new Color(0, 0, 255, 230);
|
||||
} else {
|
||||
borderColor = null;
|
||||
}
|
||||
if (borderColor != null) {
|
||||
float hwidth = borderWidth / 2.0f;
|
||||
Graphics2D g2 = (Graphics2D)g.create();
|
||||
Graphics2D g2 = (Graphics2D) g.create();
|
||||
g2.setColor(borderColor);
|
||||
g2.setStroke(new BasicStroke(borderWidth));
|
||||
RoundRectangle2D.Float rect
|
||||
|
@ -281,19 +267,19 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Draw main part (most of card)
|
||||
g.fillRoundRect(
|
||||
borderWidth, borderWidth,
|
||||
cardWidth - borderWidth*2, cardHeight - borderWidth*4 - cornerRadius*2,
|
||||
cardWidth - borderWidth * 2, cardHeight - borderWidth * 4 - cornerRadius * 2,
|
||||
cornerRadius - 1, cornerRadius - 1);
|
||||
|
||||
// Draw the M15 rounded "swoosh" at the bottom
|
||||
g.fillRoundRect(
|
||||
borderWidth, cardHeight - borderWidth*4 - cornerRadius*4,
|
||||
cardWidth - borderWidth*2, cornerRadius*4,
|
||||
cornerRadius*2, cornerRadius*2);
|
||||
borderWidth, cardHeight - borderWidth * 4 - cornerRadius * 4,
|
||||
cardWidth - borderWidth * 2, cornerRadius * 4,
|
||||
cornerRadius * 2, cornerRadius * 2);
|
||||
|
||||
// Draw the cutout into the "swoosh" for the textbox to lie over
|
||||
g.fillRect(
|
||||
borderWidth + contentInset, cardHeight - borderWidth*5,
|
||||
cardWidth - borderWidth*2 - contentInset*2, borderWidth*2);
|
||||
borderWidth + contentInset, cardHeight - borderWidth * 5,
|
||||
cardWidth - borderWidth * 2 - contentInset * 2, borderWidth * 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,12 +288,12 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
if (artImage != null && !cardView.isFaceDown()) {
|
||||
int imgWidth = artImage.getWidth();
|
||||
int imgHeight = artImage.getHeight();
|
||||
BufferedImage subImg =
|
||||
artImage.getSubimage(
|
||||
(int)(.079*imgWidth), (int)(.11*imgHeight),
|
||||
(int)(.84*imgWidth), (int)(.42*imgHeight));
|
||||
BufferedImage subImg
|
||||
= artImage.getSubimage(
|
||||
(int) (.079 * imgWidth), (int) (.11 * imgHeight),
|
||||
(int) (.84 * imgWidth), (int) (.42 * imgHeight));
|
||||
g.drawImage(subImg,
|
||||
totalContentInset+1, totalContentInset+boxHeight,
|
||||
totalContentInset + 1, totalContentInset + boxHeight,
|
||||
contentWidth - 2, typeLineY - totalContentInset - boxHeight,
|
||||
null);
|
||||
}
|
||||
|
@ -327,27 +313,27 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
g.setPaint(borderPaint);
|
||||
g.drawRect(
|
||||
totalContentInset, totalContentInset,
|
||||
contentWidth - 1, cardHeight - borderWidth*3 - totalContentInset - 1);
|
||||
contentWidth - 1, cardHeight - borderWidth * 3 - totalContentInset - 1);
|
||||
|
||||
// Draw the textbox fill
|
||||
g.setPaint(textboxPaint);
|
||||
g.fillRect(
|
||||
totalContentInset + 1, typeLineY,
|
||||
contentWidth - 2, cardHeight - borderWidth*3 - typeLineY - 1);
|
||||
contentWidth - 2, cardHeight - borderWidth * 3 - typeLineY - 1);
|
||||
|
||||
// If it's a planeswalker, extend the textbox left border by some
|
||||
if (cardView.getCardTypes().contains(CardType.PLANESWALKER)) {
|
||||
g.setPaint(borderPaint);
|
||||
g.fillRect(
|
||||
totalContentInset, typeLineY + boxHeight,
|
||||
cardWidth/16, cardHeight - typeLineY - boxHeight - borderWidth*3);
|
||||
cardWidth / 16, cardHeight - typeLineY - boxHeight - borderWidth * 3);
|
||||
}
|
||||
|
||||
// Draw a shadow highlight at the right edge of the content frame
|
||||
g.setColor(new Color(0, 0, 0, 100));
|
||||
g.fillRect(
|
||||
totalContentInset - 1, totalContentInset,
|
||||
1, cardHeight - borderWidth*3 - totalContentInset - 1);
|
||||
1, cardHeight - borderWidth * 3 - totalContentInset - 1);
|
||||
|
||||
// Draw a shadow highlight separating the card art and rest of frame
|
||||
g.drawRect(
|
||||
|
@ -357,14 +343,14 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Draw the name line box
|
||||
CardRendererUtils.drawRoundedBox(g,
|
||||
borderWidth, totalContentInset,
|
||||
cardWidth - 2*borderWidth, boxHeight,
|
||||
cardWidth - 2 * borderWidth, boxHeight,
|
||||
contentInset,
|
||||
borderPaint, boxColor);
|
||||
|
||||
// Draw the type line box
|
||||
CardRendererUtils.drawRoundedBox(g,
|
||||
borderWidth, typeLineY,
|
||||
cardWidth - 2*borderWidth, boxHeight,
|
||||
cardWidth - 2 * borderWidth, boxHeight,
|
||||
contentInset,
|
||||
borderPaint, boxColor);
|
||||
|
||||
|
@ -379,7 +365,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
contentWidth - 2, 1);
|
||||
g.fillRect(
|
||||
cardWidth - totalContentInset - 1, typeLineY + boxHeight,
|
||||
1, cardHeight - borderWidth*3 - typeLineY - boxHeight);
|
||||
1, cardHeight - borderWidth * 3 - typeLineY - boxHeight);
|
||||
|
||||
// Draw the transform circle
|
||||
int nameOffset = drawTransformationCircle(g, borderPaint);
|
||||
|
@ -397,7 +383,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Draw the textbox rules
|
||||
drawRulesText(g,
|
||||
totalContentInset + 2, typeLineY + boxHeight + 2,
|
||||
contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth*3);
|
||||
contentWidth - 4, cardHeight - typeLineY - boxHeight - 4 - borderWidth * 3);
|
||||
|
||||
// Draw the bottom right stuff
|
||||
drawBottomRight(g, borderPaint, boxColor);
|
||||
|
@ -420,7 +406,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Draw the name
|
||||
String nameStr;
|
||||
if (cardView.isFaceDown()) {
|
||||
if (cardView instanceof PermanentView && ((PermanentView)cardView).isManifested()) {
|
||||
if (cardView instanceof PermanentView && ((PermanentView) cardView).isManifested()) {
|
||||
nameStr = "Manifest: " + cardView.getName();
|
||||
} else {
|
||||
nameStr = "Morph: " + cardView.getName();
|
||||
|
@ -483,10 +469,10 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
}
|
||||
|
||||
// Where to start drawing the things
|
||||
int curY = cardHeight - (int)(0.03f*cardHeight);
|
||||
int curY = cardHeight - (int) (0.03f * cardHeight);
|
||||
|
||||
// Width of the boxes
|
||||
int partWidth = (int)Math.max(30, 0.20f*cardWidth);
|
||||
int partWidth = (int) Math.max(30, 0.20f * cardWidth);
|
||||
|
||||
// Is it a creature?
|
||||
if (cardView.getCardTypes().contains(CardType.CREATURE)) {
|
||||
|
@ -504,7 +490,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
g.setColor(new Color(0, 0, 0, 150));
|
||||
g.fillRect(
|
||||
x + contentInset, curY - boxHeight - 1,
|
||||
partWidth - 2*contentInset, 1);
|
||||
partWidth - 2 * contentInset, 1);
|
||||
|
||||
// Draw text
|
||||
g.setColor(getBoxTextColor());
|
||||
|
@ -512,10 +498,10 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
String ptText = cardView.getPower() + "/" + cardView.getToughness();
|
||||
int ptTextWidth = g.getFontMetrics().stringWidth(ptText);
|
||||
g.drawString(ptText,
|
||||
x + (partWidth - ptTextWidth)/2, curY - ptTextOffset - 1);
|
||||
x + (partWidth - ptTextWidth) / 2, curY - ptTextOffset - 1);
|
||||
|
||||
// Does it have damage on it?
|
||||
if ((cardView instanceof PermanentView) && ((PermanentView)cardView).getDamage() > 0) {
|
||||
if ((cardView instanceof PermanentView) && ((PermanentView) cardView).getDamage() > 0) {
|
||||
// Show marked damage
|
||||
|
||||
}
|
||||
|
@ -529,31 +515,29 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
&& (cardView instanceof PermanentView || !cardView.getStartingLoyalty().equals("0"))) {
|
||||
// Draw the PW loyalty box
|
||||
int w = partWidth;
|
||||
int h = partWidth/2;
|
||||
int h = partWidth / 2;
|
||||
int x = cardWidth - partWidth - borderWidth;
|
||||
int y = curY - h;
|
||||
|
||||
Polygon symbol = new Polygon(
|
||||
new int[]{
|
||||
x + w/2,
|
||||
(int)(x + w*0.9),
|
||||
x + w / 2,
|
||||
(int) (x + w * 0.9),
|
||||
x + w,
|
||||
(int)(x + w*0.6),
|
||||
x + w/2,
|
||||
(int)(x + w*0.4),
|
||||
(int) (x + w * 0.6),
|
||||
x + w / 2,
|
||||
(int) (x + w * 0.4),
|
||||
x,
|
||||
(int)(x + w*0.1),
|
||||
},
|
||||
(int) (x + w * 0.1),},
|
||||
new int[]{
|
||||
y + h,
|
||||
(int)(y + 0.8*h),
|
||||
(int) (y + 0.8 * h),
|
||||
y,
|
||||
(int)(y - 0.2*h),
|
||||
(int) (y - 0.2 * h),
|
||||
y,
|
||||
(int)(y - 0.2*h),
|
||||
(int) (y - 0.2 * h),
|
||||
y,
|
||||
(int)(y + 0.8*h),
|
||||
},
|
||||
(int) (y + 0.8 * h),},
|
||||
8);
|
||||
|
||||
// Draw + stroke
|
||||
|
@ -575,29 +559,30 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
g.setFont(ptTextFont);
|
||||
g.setColor(Color.white);
|
||||
int loyaltyWidth = g.getFontMetrics().stringWidth(loyalty);
|
||||
g.drawString(loyalty, x + (w - loyaltyWidth)/2, y + ptTextHeight + (h - ptTextHeight)/2);
|
||||
g.drawString(loyalty, x + (w - loyaltyWidth) / 2, y + ptTextHeight + (h - ptTextHeight) / 2);
|
||||
|
||||
// Advance
|
||||
curY -= (int)(1.2*y);
|
||||
curY -= (int) (1.2 * y);
|
||||
}
|
||||
|
||||
// does it have damage on it?
|
||||
if ((cardView instanceof PermanentView) && ((PermanentView)cardView).getDamage() > 0) {
|
||||
if ((cardView instanceof PermanentView) && ((PermanentView) cardView).getDamage() > 0) {
|
||||
int x = cardWidth - partWidth - borderWidth;
|
||||
int y = curY - boxHeight;
|
||||
String damage = "" + ((PermanentView)cardView).getDamage();
|
||||
String damage = "" + ((PermanentView) cardView).getDamage();
|
||||
g.setFont(ptTextFont);
|
||||
int txWidth = g.getFontMetrics().stringWidth(damage);
|
||||
g.setColor(Color.red);
|
||||
g.fillRect(x, y, partWidth, boxHeight);
|
||||
g.setColor(Color.white);
|
||||
g.drawRect(x, y, partWidth, boxHeight);
|
||||
g.drawString(damage, x + (partWidth - txWidth)/2, curY - 1);
|
||||
g.drawString(damage, x + (partWidth - txWidth) / 2, curY - 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the card's textbox in a given rect
|
||||
protected boolean loyaltyAbilityColorToggle = false;
|
||||
|
||||
protected void drawRulesText(Graphics2D g, int x, int y, int w, int h) {
|
||||
// Initial font size to try to render at
|
||||
Font font = new Font("Arial", Font.PLAIN, 12);
|
||||
|
@ -619,7 +604,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
if (hasKeywords) {
|
||||
remaining -= drawSingleRule(g, keywordRulesAttributed, null, 0, 0, w, remaining, false);
|
||||
}
|
||||
for (TextboxRule rule: textboxRules) {
|
||||
for (TextboxRule rule : textboxRules) {
|
||||
AttributedString attributed = rule.generateAttributedString(font, fontItalic);
|
||||
attributedRules.add(attributed);
|
||||
remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, false);
|
||||
|
@ -641,7 +626,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
|
||||
// Clear out the attributed rules and reatribute them with the new font size
|
||||
attributedRules.clear();
|
||||
for (TextboxRule rule: textboxRules) {
|
||||
for (TextboxRule rule : textboxRules) {
|
||||
AttributedString attributed = rule.generateAttributedString(font, fontItalic);
|
||||
attributedRules.add(attributed);
|
||||
}
|
||||
|
@ -651,7 +636,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
if (hasKeywords) {
|
||||
remaining -= drawSingleRule(g, keywordRulesAttributed, null, 0, 0, w, remaining, false);
|
||||
}
|
||||
for (TextboxRule rule: textboxRules) {
|
||||
for (TextboxRule rule : textboxRules) {
|
||||
AttributedString attributed = rule.generateAttributedString(font, fontItalic);
|
||||
attributedRules.add(attributed);
|
||||
remaining -= drawSingleRule(g, attributed, rule, 0, 0, w, remaining, false);
|
||||
|
@ -668,9 +653,9 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
if (remaining <= 0) {
|
||||
spacing = 0;
|
||||
} else {
|
||||
spacing = (int)(remaining / (hasKeywords ?
|
||||
(textboxRules.size() + 2) :
|
||||
(textboxRules.size() + 1)));
|
||||
spacing = (int) (remaining / (hasKeywords
|
||||
? (textboxRules.size() + 2)
|
||||
: (textboxRules.size() + 1)));
|
||||
}
|
||||
|
||||
// Do the actual draw
|
||||
|
@ -713,7 +698,7 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Inset, in case we are a leveler or loyalty ability
|
||||
int inset = 0;
|
||||
if (rule != null && rule.type == TextboxRuleType.LOYALTY) {
|
||||
inset = cardWidth/12;
|
||||
inset = cardWidth / 12;
|
||||
}
|
||||
int availWidth = w - inset;
|
||||
|
||||
|
@ -748,19 +733,19 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
}
|
||||
|
||||
// Advance
|
||||
int advance = ((int)Math.ceil(yPos)) - y;
|
||||
int advance = ((int) Math.ceil(yPos)) - y;
|
||||
|
||||
// Is it a loyalty ability?
|
||||
if (rule != null && rule.type == TextboxRuleType.LOYALTY) {
|
||||
TextboxLoyaltyRule loyaltyRule = (TextboxLoyaltyRule)rule;
|
||||
TextboxLoyaltyRule loyaltyRule = (TextboxLoyaltyRule) rule;
|
||||
Polygon symbol;
|
||||
int symbolWidth = (x + inset) - borderWidth - 4;
|
||||
int symbolHeight = (int)(0.7f*symbolWidth);
|
||||
int symbolHeight = (int) (0.7f * symbolWidth);
|
||||
if (symbolHeight > advance) {
|
||||
advance = symbolHeight;
|
||||
}
|
||||
int symbolX = x - borderWidth;
|
||||
int symbolY = y + (advance - symbolHeight)/2;
|
||||
int symbolY = y + (advance - symbolHeight) / 2;
|
||||
if (doDraw) {
|
||||
if (loyaltyRule.loyaltyChange < 0 || loyaltyRule.loyaltyChange == TextboxLoyaltyRule.MINUS_X) {
|
||||
symbol = new Polygon(
|
||||
|
@ -768,33 +753,29 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
symbolX,
|
||||
symbolX + symbolWidth,
|
||||
symbolX + symbolWidth,
|
||||
symbolX + symbolWidth/2,
|
||||
symbolX,
|
||||
},
|
||||
symbolX + symbolWidth / 2,
|
||||
symbolX,},
|
||||
new int[]{
|
||||
symbolY,
|
||||
symbolY,
|
||||
symbolY + symbolHeight - 3,
|
||||
symbolY + symbolHeight + 3,
|
||||
symbolY + symbolHeight - 3,
|
||||
},
|
||||
symbolY + symbolHeight - 3,},
|
||||
5);
|
||||
} else if (loyaltyRule.loyaltyChange > 0) {
|
||||
symbol = new Polygon(
|
||||
new int[]{
|
||||
symbolX,
|
||||
symbolX + symbolWidth/2,
|
||||
symbolX + symbolWidth / 2,
|
||||
symbolX + symbolWidth,
|
||||
symbolX + symbolWidth,
|
||||
symbolX,
|
||||
},
|
||||
symbolX,},
|
||||
new int[]{
|
||||
symbolY + 3,
|
||||
symbolY - 3,
|
||||
symbolY + 3,
|
||||
symbolY + symbolHeight,
|
||||
symbolY + symbolHeight,
|
||||
},
|
||||
symbolY + symbolHeight,},
|
||||
5);
|
||||
} else {
|
||||
symbol = new Polygon(
|
||||
|
@ -802,18 +783,16 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
symbolX,
|
||||
symbolX + symbolWidth,
|
||||
symbolX + symbolWidth,
|
||||
symbolX,
|
||||
},
|
||||
symbolX,},
|
||||
new int[]{
|
||||
symbolY,
|
||||
symbolY,
|
||||
symbolY + symbolHeight,
|
||||
symbolY + symbolHeight,
|
||||
},
|
||||
symbolY + symbolHeight,},
|
||||
4);
|
||||
}
|
||||
g.setColor(new Color(0, 0, 0, 128));
|
||||
g.fillRect(x+2, y+advance+1, w-2, 1);
|
||||
g.fillRect(x + 2, y + advance + 1, w - 2, 1);
|
||||
g.setColor(Color.black);
|
||||
g.fillPolygon(symbol);
|
||||
g.setColor(new Color(200, 200, 200));
|
||||
|
@ -825,8 +804,8 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
String loyaltyString = loyaltyRule.getChangeString();
|
||||
int textWidth = g.getFontMetrics().stringWidth(loyaltyString);
|
||||
g.drawString(loyaltyString,
|
||||
symbolX + (symbolWidth - textWidth)/2,
|
||||
symbolY + symbolHeight - (symbolHeight - boxTextHeight)/2);
|
||||
symbolX + (symbolWidth - textWidth) / 2,
|
||||
symbolY + symbolHeight - (symbolHeight - boxTextHeight) / 2);
|
||||
|
||||
advance += 3;
|
||||
loyaltyAbilityColorToggle = !loyaltyAbilityColorToggle;
|
||||
|
@ -841,9 +820,11 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
protected boolean isNightCard() {
|
||||
return isTransformed;
|
||||
}
|
||||
|
||||
protected boolean isTransformCard() {
|
||||
return cardView.canTransform() || isTransformed;
|
||||
}
|
||||
|
||||
protected int drawTransformationCircle(Graphics2D g, Paint borderPaint) {
|
||||
int transformCircleOffset = 0;
|
||||
if (isTransformCard()) {
|
||||
|
@ -851,14 +832,14 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
g.setPaint(borderPaint);
|
||||
g.drawOval(borderWidth, totalContentInset, boxHeight - 1, boxHeight - 1);
|
||||
g.setColor(Color.black);
|
||||
g.fillOval(borderWidth+1, totalContentInset+1, boxHeight-2, boxHeight-2);
|
||||
g.fillOval(borderWidth + 1, totalContentInset + 1, boxHeight - 2, boxHeight - 2);
|
||||
g.setColor(Color.white);
|
||||
if (isNightCard()) {
|
||||
g.fillArc(borderWidth+3, totalContentInset+3, boxHeight-6, boxHeight-6, 90, 270);
|
||||
g.fillArc(borderWidth + 3, totalContentInset + 3, boxHeight - 6, boxHeight - 6, 90, 270);
|
||||
g.setColor(Color.black);
|
||||
g.fillArc(borderWidth+3+3, totalContentInset+3, boxHeight-6-3, boxHeight-6, 90, 270);
|
||||
g.fillArc(borderWidth + 3 + 3, totalContentInset + 3, boxHeight - 6 - 3, boxHeight - 6, 90, 270);
|
||||
} else {
|
||||
g.fillOval(borderWidth+3, totalContentInset+3, boxHeight-6, boxHeight-6);
|
||||
g.fillOval(borderWidth + 3, totalContentInset + 3, boxHeight - 6, boxHeight - 6);
|
||||
}
|
||||
}
|
||||
return transformCircleOffset;
|
||||
|
@ -867,9 +848,9 @@ public class ModernCardRenderer extends CardRenderer {
|
|||
// Get the text height for a given box height
|
||||
protected static int getTextHeightForBoxHeight(int h) {
|
||||
if (h < 15) {
|
||||
return h-3;
|
||||
return h - 3;
|
||||
} else {
|
||||
return (int)Math.ceil(.6*h);
|
||||
return (int) Math.ceil(.6 * h);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.text.AttributedString;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -14,6 +13,7 @@ import java.util.List;
|
|||
* Level rule associated with leveler cards
|
||||
*/
|
||||
public class TextboxLevelRule extends TextboxRule {
|
||||
|
||||
// The levels that this rule applies to
|
||||
public int levelFrom;
|
||||
public int levelTo;
|
||||
|
|
|
@ -5,13 +5,13 @@
|
|||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.text.AttributedString;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author StravantUser
|
||||
*/
|
||||
public class TextboxLoyaltyRule extends TextboxRule {
|
||||
|
||||
public int loyaltyChange;
|
||||
|
||||
public static int MINUS_X = 100;
|
||||
|
|
|
@ -16,18 +16,21 @@ import java.util.List;
|
|||
/**
|
||||
* @author stravant@gmail.com
|
||||
*
|
||||
* Class describing parsed & translated rules in the text box of a card,
|
||||
* ready to be rendered.
|
||||
* Class describing parsed & translated rules in the text box of a card, ready
|
||||
* to be rendered.
|
||||
*/
|
||||
public class TextboxRule {
|
||||
|
||||
// An attributed region in the text, which can be applied to an
|
||||
// attributed string.
|
||||
public interface AttributeRegion {
|
||||
|
||||
public void applyToAttributedString(AttributedString str, Font normal, Font italic);
|
||||
}
|
||||
|
||||
// A region of italics, or bold text in a
|
||||
public static class ItalicRegion implements AttributeRegion {
|
||||
|
||||
ItalicRegion(int start, int end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
|
@ -37,7 +40,7 @@ public class TextboxRule {
|
|||
|
||||
@Override
|
||||
public void applyToAttributedString(AttributedString str, Font normal, Font italic) {
|
||||
if (end > start+1) {
|
||||
if (end > start + 1) {
|
||||
str.addAttribute(TextAttribute.FONT, italic, start, end);
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +48,7 @@ public class TextboxRule {
|
|||
|
||||
// A special symbol embedded at some point in a string
|
||||
public static class EmbeddedSymbol implements AttributeRegion {
|
||||
|
||||
EmbeddedSymbol(String symbol, int location) {
|
||||
this.symbol = symbol;
|
||||
this.location = location;
|
||||
|
@ -54,11 +58,11 @@ public class TextboxRule {
|
|||
|
||||
@Override
|
||||
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) {
|
||||
ImageGraphicAttribute imgAttr =
|
||||
new ImageGraphicAttribute(symbolImage, GraphicAttribute.BOTTOM_ALIGNMENT);
|
||||
str.addAttribute(TextAttribute.CHAR_REPLACEMENT, imgAttr, location, location+1);
|
||||
ImageGraphicAttribute imgAttr
|
||||
= new ImageGraphicAttribute(symbolImage, GraphicAttribute.BOTTOM_ALIGNMENT);
|
||||
str.addAttribute(TextAttribute.CHAR_REPLACEMENT, imgAttr, location, location + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +89,7 @@ public class TextboxRule {
|
|||
AttributedString attributedRule = new AttributedString(text);
|
||||
if (text.length() != 0) {
|
||||
attributedRule.addAttribute(TextAttribute.FONT, normal);
|
||||
for (int i = regions.size()-1; i >= 0; --i) {
|
||||
for (int i = regions.size() - 1; i >= 0; --i) {
|
||||
regions.get(i).applyToAttributedString(attributedRule, normal, italic);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,19 +5,12 @@
|
|||
*/
|
||||
package org.mage.card.arcane;
|
||||
|
||||
import java.awt.Font;
|
||||
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.ArrayList;
|
||||
import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import mage.client.dialog.PreferencesDialog;
|
||||
import mage.view.CardView;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
|
@ -26,6 +19,7 @@ import org.apache.log4j.Logger;
|
|||
* @author StravantUser
|
||||
*/
|
||||
public class TextboxRuleParser {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(CardPanel.class);
|
||||
|
||||
private static final Pattern LevelAbilityPattern = Pattern.compile("Level (\\d+)-?(\\d*)(\\+?)");
|
||||
|
@ -86,7 +80,8 @@ public class TextboxRuleParser {
|
|||
while (index < rule.length()) {
|
||||
int initialIndex = index;
|
||||
char ch = rule.charAt(index);
|
||||
if (ch == '{') {
|
||||
switch (ch) {
|
||||
case '{': {
|
||||
// Handling for `{this}`
|
||||
int closeIndex = rule.indexOf('}', index);
|
||||
if (closeIndex == -1) {
|
||||
|
@ -95,7 +90,7 @@ public class TextboxRuleParser {
|
|||
++outputIndex;
|
||||
build.append(ch);
|
||||
} else {
|
||||
String contents = rule.substring(index+1, closeIndex);
|
||||
String contents = rule.substring(index + 1, closeIndex);
|
||||
if (contents.equals("this") || contents.equals("source")) {
|
||||
// Replace {this} with the card's name
|
||||
String cardName = source.getName();
|
||||
|
@ -103,25 +98,26 @@ public class TextboxRuleParser {
|
|||
index += contents.length() + 2;
|
||||
outputIndex += cardName.length();
|
||||
} else {
|
||||
Image symbol = ManaSymbols.getSizedManaSymbol(contents, 10);
|
||||
Image symbol = ManaSymbols.getSizedManaSymbol(contents.replace("/", ""), 10);
|
||||
if (symbol != null) {
|
||||
// Mana or other inline symbol
|
||||
build.append('#');
|
||||
regions.add(new TextboxRule.EmbeddedSymbol(contents, outputIndex));
|
||||
++outputIndex;
|
||||
index = closeIndex+1;
|
||||
index = closeIndex + 1;
|
||||
} else {
|
||||
// Bad entry
|
||||
build.append('{');
|
||||
build.append(contents);
|
||||
build.append('}');
|
||||
index = closeIndex+1;
|
||||
index = closeIndex + 1;
|
||||
outputIndex += (contents.length() + 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (ch == '&') {
|
||||
break;
|
||||
}
|
||||
case '&':
|
||||
// Handling for `—`
|
||||
if (rule.startsWith("—", index)) {
|
||||
build.append('—');
|
||||
|
@ -132,20 +128,19 @@ public class TextboxRuleParser {
|
|||
index += 5;
|
||||
++outputIndex;
|
||||
} else {
|
||||
LOGGER.error("Bad &...; sequence `" + rule.substring(index+1, index+10) + "` in rule.");
|
||||
LOGGER.error("Bad &...; sequence `" + rule.substring(index + 1, index + 10) + "` in rule.");
|
||||
build.append('&');
|
||||
++index;
|
||||
++outputIndex;
|
||||
}
|
||||
|
||||
|
||||
} else if (ch == '<') {
|
||||
break;
|
||||
case '<': {
|
||||
// Handling for `<i>` and `<br/>`
|
||||
int closeIndex = rule.indexOf('>', index);
|
||||
if (closeIndex != -1) {
|
||||
// Is a tag
|
||||
String tag = rule.substring(index+1, closeIndex);
|
||||
if (tag.charAt(tag.length()-1) == '/') {
|
||||
String tag = rule.substring(index + 1, closeIndex);
|
||||
if (tag.charAt(tag.length() - 1) == '/') {
|
||||
// Pure closing tag (like <br/>)
|
||||
if (tag.equals("br/")) {
|
||||
build.append('\n');
|
||||
|
@ -166,13 +161,14 @@ public class TextboxRuleParser {
|
|||
}
|
||||
|
||||
// What tag is it?
|
||||
if (tag.equals("/i")) {
|
||||
switch (tag) {
|
||||
case "/i":
|
||||
// Italics
|
||||
regions.add(new TextboxRule.ItalicRegion(openingIndex, outputIndex));
|
||||
} else if (tag.equals("/b")) {
|
||||
break;
|
||||
case "/b":
|
||||
// Bold, see if it's a level ability
|
||||
String content = build.substring(openingIndex);
|
||||
|
||||
Matcher levelMatch = LevelAbilityPattern.matcher(content);
|
||||
if (levelMatch.find()) {
|
||||
try {
|
||||
|
@ -188,13 +184,15 @@ public class TextboxRuleParser {
|
|||
LOGGER.error("Bad leveler levels in rule `" + rule + "`.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
// Unknown
|
||||
build.append('<').append(tag).append('>');
|
||||
outputIndex += (tag.length() + 2);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Is it a <br> tag special case? [Why can't it have a closing `/`... =( ]
|
||||
} else // Is it a <br> tag special case? [Why can't it have a closing `/`... =( ]
|
||||
{
|
||||
if (tag.equals("br")) {
|
||||
build.append('\n');
|
||||
++outputIndex;
|
||||
|
@ -204,19 +202,21 @@ public class TextboxRuleParser {
|
|||
}
|
||||
}
|
||||
// Skip characters
|
||||
index = closeIndex+1;
|
||||
index = closeIndex + 1;
|
||||
} else {
|
||||
// Malformed tag
|
||||
build.append('<');
|
||||
++outputIndex;
|
||||
++index;
|
||||
}
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Normal character
|
||||
++index;
|
||||
++outputIndex;
|
||||
build.append(ch);
|
||||
break;
|
||||
}
|
||||
if (outputIndex != build.length()) {
|
||||
// Somehow our parsing code output symbols but didn't update the output index correspondingly
|
||||
|
|
Loading…
Reference in a new issue