mirror of
https://github.com/correl/mage.git
synced 2025-01-11 19:13:02 +00:00
Draw GlowText to a buffered image and cache it across instances
Speeds up GUI performance.
This commit is contained in:
parent
4b190eeaf4
commit
ffb65d48fe
1 changed files with 133 additions and 17 deletions
|
@ -1,15 +1,30 @@
|
|||
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;
|
||||
import java.text.BreakIterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import mage.client.util.ImageCaches;
|
||||
import org.jdesktop.swingx.graphics.GraphicsUtilities;
|
||||
|
||||
public class GlowText extends JLabel {
|
||||
private static final long serialVersionUID = 1827677946939348001L;
|
||||
|
@ -19,6 +34,109 @@ public class GlowText extends JLabel {
|
|||
private Color glowColor;
|
||||
private boolean wrap;
|
||||
private int lineCount = 0;
|
||||
private static Map<Key, BufferedImage> IMAGE_CACHE;
|
||||
|
||||
private final static class Key
|
||||
{
|
||||
final int width;
|
||||
final int height;
|
||||
final String text;
|
||||
final Map<TextAttribute,?> fontAttributes;
|
||||
final Color color;
|
||||
final int glowSize;
|
||||
final float glowIntensity;
|
||||
final Color glowColor;
|
||||
final boolean wrap;
|
||||
|
||||
// used to pass the native font to the create function so we don't waste performance recreating it, but without holding onto the native object
|
||||
final transient WeakReference<Font> originalFont;
|
||||
|
||||
Font getFont() {
|
||||
Font res = this.originalFont.get();
|
||||
if(res == null)
|
||||
res = Font.getFont(this.fontAttributes);
|
||||
return res;
|
||||
}
|
||||
|
||||
public Key(int width, int height, String text, Font font, Color color, int glowSize, float glowIntensity, Color glowColor, boolean wrap) {
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.text = text;
|
||||
this.originalFont = new WeakReference<>(font);
|
||||
this.fontAttributes = font.getAttributes();
|
||||
this.color = color;
|
||||
this.glowSize = glowSize;
|
||||
this.glowIntensity = glowIntensity;
|
||||
this.glowColor = glowColor;
|
||||
this.wrap = wrap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 23 * hash + this.width;
|
||||
hash = 23 * hash + this.height;
|
||||
hash = 23 * hash + Objects.hashCode(this.text);
|
||||
hash = 23 * hash + Objects.hashCode(this.fontAttributes);
|
||||
hash = 23 * hash + Objects.hashCode(this.color);
|
||||
hash = 23 * hash + this.glowSize;
|
||||
hash = 23 * hash + Float.floatToIntBits(this.glowIntensity);
|
||||
hash = 23 * hash + Objects.hashCode(this.glowColor);
|
||||
hash = 23 * hash + (this.wrap ? 1 : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final Key other = (Key) obj;
|
||||
if (this.width != other.width) {
|
||||
return false;
|
||||
}
|
||||
if (this.height != other.height) {
|
||||
return false;
|
||||
}
|
||||
if (this.glowSize != other.glowSize) {
|
||||
return false;
|
||||
}
|
||||
if (Float.floatToIntBits(this.glowIntensity) != Float.floatToIntBits(other.glowIntensity)) {
|
||||
return false;
|
||||
}
|
||||
if (this.wrap != other.wrap) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.text, other.text)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.fontAttributes, other.fontAttributes)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.color, other.color)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.glowColor, other.glowColor)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
IMAGE_CACHE = ImageCaches.register(new MapMaker().softValues().makeComputingMap(new Function<Key, BufferedImage>() {
|
||||
@Override
|
||||
public BufferedImage apply(Key key) {
|
||||
return createImage(key);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public void setGlow (Color glowColor, int size, float intensity) {
|
||||
this.glowColor = glowColor;
|
||||
|
@ -38,32 +156,32 @@ public class GlowText extends JLabel {
|
|||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setText (String text) {
|
||||
super.setText(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint (Graphics g) {
|
||||
if (getText().length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Graphics2D g2d = (Graphics2D)g;
|
||||
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) {
|
||||
Dimension size = new Dimension(key.width, key.height);
|
||||
BufferedImage image = GraphicsUtilities.createCompatibleTranslucentImage(size.width, size.height);
|
||||
Graphics2D g2d = image.createGraphics();
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
|
||||
Dimension size = getSize();
|
||||
int textX = 0, textY = 0;
|
||||
int wrapWidth = Math.max(0, wrap ? size.width - glowSize : Integer.MAX_VALUE);
|
||||
int wrapWidth = Math.max(0, key.wrap ? size.width - key.glowSize : Integer.MAX_VALUE);
|
||||
|
||||
AttributedString attributedString = new AttributedString(getText());
|
||||
attributedString.addAttribute(TextAttribute.FONT, getFont());
|
||||
AttributedString attributedString = new AttributedString(key.text);
|
||||
attributedString.addAttribute(TextAttribute.FONT, key.getFont());
|
||||
AttributedCharacterIterator charIterator = attributedString.getIterator();
|
||||
FontRenderContext fontContext = g2d.getFontRenderContext();
|
||||
|
||||
LineBreakMeasurer measurer = new LineBreakMeasurer(charIterator, BreakIterator.getWordInstance(Locale.ENGLISH), fontContext);
|
||||
lineCount = 0;
|
||||
int lineCount = 0;
|
||||
while (measurer.getPosition() < charIterator.getEndIndex()) {
|
||||
//TextLayout textLayout = measurer.nextLayout(wrapWidth);
|
||||
lineCount++;
|
||||
|
@ -83,23 +201,21 @@ public class GlowText extends JLabel {
|
|||
float ascent = textLayout.getAscent();
|
||||
textY += ascent; // Move down to baseline.
|
||||
|
||||
g2d.setColor(glowColor);
|
||||
g2d.setColor(key.glowColor);
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.8f));
|
||||
int glowSize = key.glowSize;
|
||||
textLayout.draw(g2d, textX + glowSize / 2 + 1, textY + glowSize / 2 - 1);
|
||||
textLayout.draw(g2d, textX + glowSize / 2 + 1, textY + glowSize / 2 + 1);
|
||||
textLayout.draw(g2d, textX + glowSize / 2 - 1, textY + glowSize / 2 - 1);
|
||||
textLayout.draw(g2d, textX + glowSize / 2 - 1, textY + glowSize / 2 + 1);
|
||||
|
||||
g2d.setColor(getForeground());
|
||||
g2d.setColor(key.color);
|
||||
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f));
|
||||
textLayout.draw(g2d, textX + glowSize / 2, textY + glowSize / 2);
|
||||
|
||||
textY += textLayout.getDescent() + textLayout.getLeading(); // Move down to top of next line.
|
||||
}
|
||||
}
|
||||
|
||||
public int getLineCount() {
|
||||
return this.lineCount;
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setGlowColor(Color glowColor) {
|
||||
|
|
Loading…
Reference in a new issue