mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-12 19:44:05 +09:00
added sources for Slick
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054 Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
This commit is contained in:
152
lib/slick-source/org/newdawn/slick/font/Glyph.java
Normal file
152
lib/slick-source/org/newdawn/slick/font/Glyph.java
Normal file
@@ -0,0 +1,152 @@
|
||||
|
||||
package org.newdawn.slick.font;
|
||||
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Shape;
|
||||
import java.awt.font.GlyphMetrics;
|
||||
import java.awt.font.GlyphVector;
|
||||
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
|
||||
/**
|
||||
* Represents the glyph in a font for a unicode codepoint.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class Glyph {
|
||||
/** The code point in which this glyph is found */
|
||||
private int codePoint;
|
||||
/** The width of this glyph in pixels */
|
||||
private short width;
|
||||
/** The height of this glyph in pixels */
|
||||
private short height;
|
||||
/** The offset on the y axis to draw the glyph at */
|
||||
private short yOffset;
|
||||
/** True if the glyph isn't defined */
|
||||
private boolean isMissing;
|
||||
/** The shape drawn for this glyph */
|
||||
private Shape shape;
|
||||
/** The image generated for this glyph */
|
||||
private Image image;
|
||||
|
||||
/**
|
||||
* Create a new glyph
|
||||
*
|
||||
* @param codePoint The code point in which this glyph can be found
|
||||
* @param bounds The bounds that this glrph can fill
|
||||
* @param vector The vector this glyph is part of
|
||||
* @param index The index of this glyph within the vector
|
||||
* @param unicodeFont The font this glyph forms part of
|
||||
*/
|
||||
public Glyph(int codePoint, Rectangle bounds, GlyphVector vector, int index, UnicodeFont unicodeFont) {
|
||||
this.codePoint = codePoint;
|
||||
|
||||
GlyphMetrics metrics = vector.getGlyphMetrics(index);
|
||||
int lsb = (int)metrics.getLSB();
|
||||
if (lsb > 0) lsb = 0;
|
||||
int rsb = (int)metrics.getRSB();
|
||||
if (rsb > 0) rsb = 0;
|
||||
|
||||
int glyphWidth = bounds.width - lsb - rsb;
|
||||
int glyphHeight = bounds.height;
|
||||
if (glyphWidth > 0 && glyphHeight > 0) {
|
||||
int padTop = unicodeFont.getPaddingTop();
|
||||
int padRight = unicodeFont.getPaddingRight();
|
||||
int padBottom = unicodeFont.getPaddingBottom();
|
||||
int padLeft = unicodeFont.getPaddingLeft();
|
||||
int glyphSpacing = 1; // Needed to prevent filtering problems.
|
||||
width = (short)(glyphWidth + padLeft + padRight + glyphSpacing);
|
||||
height = (short)(glyphHeight + padTop + padBottom + glyphSpacing);
|
||||
yOffset = (short)(unicodeFont.getAscent() + bounds.y - padTop);
|
||||
}
|
||||
|
||||
shape = vector.getGlyphOutline(index, -bounds.x + unicodeFont.getPaddingLeft(), -bounds.y + unicodeFont.getPaddingTop());
|
||||
|
||||
isMissing = !unicodeFont.getFont().canDisplay((char)codePoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* The unicode codepoint the glyph represents.
|
||||
*
|
||||
* @return The codepoint the glyph represents
|
||||
*/
|
||||
public int getCodePoint () {
|
||||
return codePoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the font does not have a glyph for this codepoint.
|
||||
*
|
||||
* @return True if this glyph is not defined in the given code point
|
||||
*/
|
||||
public boolean isMissing () {
|
||||
return isMissing;
|
||||
}
|
||||
|
||||
/**
|
||||
* The width of the glyph's image.
|
||||
*
|
||||
* @return The width in pixels of the glyphs image
|
||||
*/
|
||||
public int getWidth () {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* The height of the glyph's image.
|
||||
*
|
||||
* @return The height in pixels of the glyphs image
|
||||
*/
|
||||
public int getHeight () {
|
||||
return height;
|
||||
}
|
||||
|
||||
/**
|
||||
* The shape to use to draw this glyph. This is set to null after the glyph is stored
|
||||
* in a GlyphPage.
|
||||
*
|
||||
* @return The shape drawn for this glyph
|
||||
*/
|
||||
public Shape getShape () {
|
||||
return shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the shape that should be drawn for this glyph
|
||||
*
|
||||
* @param shape The shape that should be drawn for this glyph
|
||||
*/
|
||||
public void setShape(Shape shape) {
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
/**
|
||||
* The image to use for this glyph. This is null until after the glyph is stored in a
|
||||
* GlyphPage.
|
||||
*
|
||||
* @return The image that has been generated for this glyph
|
||||
*/
|
||||
public Image getImage () {
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image that has been generated for this glyph
|
||||
*
|
||||
* @param image The image that has been generated for this glyph
|
||||
*/
|
||||
public void setImage(Image image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
/**
|
||||
* The distance from drawing y location to top of this glyph, causing the glyph to sit
|
||||
* on the baseline.
|
||||
*
|
||||
* @return The offset on the y axis this glyph should be drawn at
|
||||
*/
|
||||
public int getYOffset() {
|
||||
return yOffset;
|
||||
}
|
||||
}
|
||||
260
lib/slick-source/org/newdawn/slick/font/GlyphPage.java
Normal file
260
lib/slick-source/org/newdawn/slick/font/GlyphPage.java
Normal file
@@ -0,0 +1,260 @@
|
||||
|
||||
package org.newdawn.slick.font;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
import org.newdawn.slick.Color;
|
||||
import org.newdawn.slick.Image;
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
import org.newdawn.slick.font.effects.Effect;
|
||||
import org.newdawn.slick.opengl.TextureImpl;
|
||||
import org.newdawn.slick.opengl.renderer.Renderer;
|
||||
import org.newdawn.slick.opengl.renderer.SGL;
|
||||
|
||||
/**
|
||||
* Stores a number of glyphs on a single texture.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class GlyphPage {
|
||||
/** The interface to OpenGL */
|
||||
private static final SGL GL = Renderer.get();
|
||||
|
||||
/** The maxium size of an individual glyph */
|
||||
public static final int MAX_GLYPH_SIZE = 256;
|
||||
|
||||
/** A temporary working buffer */
|
||||
private static ByteBuffer scratchByteBuffer = ByteBuffer.allocateDirect(MAX_GLYPH_SIZE * MAX_GLYPH_SIZE * 4);
|
||||
|
||||
static {
|
||||
scratchByteBuffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/** A temporary working buffer */
|
||||
private static IntBuffer scratchIntBuffer = scratchByteBuffer.asIntBuffer();
|
||||
|
||||
|
||||
/** A temporary image used to generate the glyph page */
|
||||
private static BufferedImage scratchImage = new BufferedImage(MAX_GLYPH_SIZE, MAX_GLYPH_SIZE, BufferedImage.TYPE_INT_ARGB);
|
||||
/** The graphics context form the temporary image */
|
||||
private static Graphics2D scratchGraphics = (Graphics2D)scratchImage.getGraphics();
|
||||
|
||||
static {
|
||||
scratchGraphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
scratchGraphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
|
||||
scratchGraphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
|
||||
}
|
||||
|
||||
/** The render context in which the glyphs will be generated */
|
||||
public static FontRenderContext renderContext = scratchGraphics.getFontRenderContext();
|
||||
|
||||
/**
|
||||
* Get the scratch graphics used to generate the page of glyphs
|
||||
*
|
||||
* @return The scratch graphics used to build the page
|
||||
*/
|
||||
public static Graphics2D getScratchGraphics() {
|
||||
return scratchGraphics;
|
||||
}
|
||||
|
||||
/** The font this page is part of */
|
||||
private final UnicodeFont unicodeFont;
|
||||
/** The width of this page's image */
|
||||
private final int pageWidth;
|
||||
/** The height of this page's image */
|
||||
private final int pageHeight;
|
||||
/** The image containing the glyphs */
|
||||
private final Image pageImage;
|
||||
/** The x position of the page */
|
||||
private int pageX;
|
||||
/** The y position of the page */
|
||||
private int pageY;
|
||||
/** The height of the last row on the page */
|
||||
private int rowHeight;
|
||||
/** True if the glyphs are ordered */
|
||||
private boolean orderAscending;
|
||||
/** The list of glyphs on this page */
|
||||
private final List pageGlyphs = new ArrayList(32);
|
||||
|
||||
/**
|
||||
* Create a new page of glyphs
|
||||
*
|
||||
* @param unicodeFont The font this page forms part of
|
||||
* @param pageWidth The width of the backing texture.
|
||||
* @param pageHeight The height of the backing texture.
|
||||
* @throws SlickException if the backing texture could not be created.
|
||||
*/
|
||||
public GlyphPage(UnicodeFont unicodeFont, int pageWidth, int pageHeight) throws SlickException {
|
||||
this.unicodeFont = unicodeFont;
|
||||
this.pageWidth = pageWidth;
|
||||
this.pageHeight = pageHeight;
|
||||
|
||||
pageImage = new Image(pageWidth, pageHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads glyphs to the backing texture and sets the image on each loaded glyph. Loaded glyphs are removed from the list.
|
||||
*
|
||||
* If this page already has glyphs and maxGlyphsToLoad is -1, then this method will return 0 if all the new glyphs don't fit.
|
||||
* This reduces texture binds when drawing since glyphs loaded at once are typically displayed together.
|
||||
* @param glyphs The glyphs to load.
|
||||
* @param maxGlyphsToLoad This is the maximum number of glyphs to load from the list. Set to -1 to attempt to load all the
|
||||
* glyphs.
|
||||
* @return The number of glyphs that were actually loaded.
|
||||
* @throws SlickException if the glyph could not be rendered.
|
||||
*/
|
||||
public int loadGlyphs (List glyphs, int maxGlyphsToLoad) throws SlickException {
|
||||
if (rowHeight != 0 && maxGlyphsToLoad == -1) {
|
||||
// If this page has glyphs and we are not loading incrementally, return zero if any of the glyphs don't fit.
|
||||
int testX = pageX;
|
||||
int testY = pageY;
|
||||
int testRowHeight = rowHeight;
|
||||
for (Iterator iter = getIterator(glyphs); iter.hasNext();) {
|
||||
Glyph glyph = (Glyph)iter.next();
|
||||
int width = glyph.getWidth();
|
||||
int height = glyph.getHeight();
|
||||
if (testX + width >= pageWidth) {
|
||||
testX = 0;
|
||||
testY += testRowHeight;
|
||||
testRowHeight = height;
|
||||
} else if (height > testRowHeight) {
|
||||
testRowHeight = height;
|
||||
}
|
||||
if (testY + testRowHeight >= pageWidth) return 0;
|
||||
testX += width;
|
||||
}
|
||||
}
|
||||
|
||||
Color.white.bind();
|
||||
pageImage.bind();
|
||||
|
||||
int i = 0;
|
||||
for (Iterator iter = getIterator(glyphs); iter.hasNext();) {
|
||||
Glyph glyph = (Glyph)iter.next();
|
||||
int width = Math.min(MAX_GLYPH_SIZE, glyph.getWidth());
|
||||
int height = Math.min(MAX_GLYPH_SIZE, glyph.getHeight());
|
||||
|
||||
if (rowHeight == 0) {
|
||||
// The first glyph always fits.
|
||||
rowHeight = height;
|
||||
} else {
|
||||
// Wrap to the next line if needed, or break if no more fit.
|
||||
if (pageX + width >= pageWidth) {
|
||||
if (pageY + rowHeight + height >= pageHeight) break;
|
||||
pageX = 0;
|
||||
pageY += rowHeight;
|
||||
rowHeight = height;
|
||||
} else if (height > rowHeight) {
|
||||
if (pageY + height >= pageHeight) break;
|
||||
rowHeight = height;
|
||||
}
|
||||
}
|
||||
|
||||
renderGlyph(glyph, width, height);
|
||||
pageGlyphs.add(glyph);
|
||||
|
||||
pageX += width;
|
||||
|
||||
iter.remove();
|
||||
i++;
|
||||
if (i == maxGlyphsToLoad) {
|
||||
// If loading incrementally, flip orderAscending so it won't change, since we'll probably load the rest next time.
|
||||
orderAscending = !orderAscending;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
TextureImpl.bindNone();
|
||||
|
||||
// Every other batch of glyphs added to a page are sorted the opposite way to attempt to keep same size glyps together.
|
||||
orderAscending = !orderAscending;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a single glyph to the backing texture, if it fits.
|
||||
*
|
||||
* @param glyph The glyph to be rendered
|
||||
* @param width The expected width of the glyph
|
||||
* @param height The expected height of the glyph
|
||||
* @throws SlickException if the glyph could not be rendered.
|
||||
*/
|
||||
private void renderGlyph(Glyph glyph, int width, int height) throws SlickException {
|
||||
// Draw the glyph to the scratch image using Java2D.
|
||||
scratchGraphics.setComposite(AlphaComposite.Clear);
|
||||
scratchGraphics.fillRect(0, 0, MAX_GLYPH_SIZE, MAX_GLYPH_SIZE);
|
||||
scratchGraphics.setComposite(AlphaComposite.SrcOver);
|
||||
scratchGraphics.setColor(java.awt.Color.white);
|
||||
for (Iterator iter = unicodeFont.getEffects().iterator(); iter.hasNext();)
|
||||
((Effect)iter.next()).draw(scratchImage, scratchGraphics, unicodeFont, glyph);
|
||||
glyph.setShape(null); // The shape will never be needed again.
|
||||
|
||||
WritableRaster raster = scratchImage.getRaster();
|
||||
int[] row = new int[width];
|
||||
for (int y = 0; y < height; y++) {
|
||||
raster.getDataElements(0, y, width, 1, row);
|
||||
scratchIntBuffer.put(row);
|
||||
}
|
||||
GL.glTexSubImage2D(SGL.GL_TEXTURE_2D, 0, pageX, pageY, width, height, SGL.GL_BGRA, SGL.GL_UNSIGNED_BYTE,
|
||||
scratchByteBuffer);
|
||||
scratchIntBuffer.clear();
|
||||
|
||||
glyph.setImage(pageImage.getSubImage(pageX, pageY, width, height));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an iterator for the specified glyphs, sorted either ascending or descending.
|
||||
*
|
||||
* @param glyphs The glyphs to return if present
|
||||
* @return An iterator of the sorted list of glyphs
|
||||
*/
|
||||
private Iterator getIterator(List glyphs) {
|
||||
if (orderAscending) return glyphs.iterator();
|
||||
final ListIterator iter = glyphs.listIterator(glyphs.size());
|
||||
return new Iterator() {
|
||||
public boolean hasNext () {
|
||||
return iter.hasPrevious();
|
||||
}
|
||||
|
||||
public Object next () {
|
||||
return iter.previous();
|
||||
}
|
||||
|
||||
public void remove () {
|
||||
iter.remove();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the glyphs stored on this page.
|
||||
*
|
||||
* @return A list of {@link Glyph} elements on this page
|
||||
*/
|
||||
public List getGlyphs () {
|
||||
return pageGlyphs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the backing texture for this page.
|
||||
*
|
||||
* @return The image of this page of glyphs
|
||||
*/
|
||||
public Image getImage () {
|
||||
return pageImage;
|
||||
}
|
||||
}
|
||||
380
lib/slick-source/org/newdawn/slick/font/HieroSettings.java
Normal file
380
lib/slick-source/org/newdawn/slick/font/HieroSettings.java
Normal file
@@ -0,0 +1,380 @@
|
||||
|
||||
package org.newdawn.slick.font;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.newdawn.slick.SlickException;
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
import org.newdawn.slick.font.effects.ConfigurableEffect;
|
||||
import org.newdawn.slick.font.effects.ConfigurableEffect.Value;
|
||||
import org.newdawn.slick.util.ResourceLoader;
|
||||
|
||||
/**
|
||||
* Holds the settings needed to configure a UnicodeFont.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class HieroSettings {
|
||||
/** The size of the font to be generated */
|
||||
private int fontSize = 12;
|
||||
/** True if the font is rendered bold */
|
||||
private boolean bold = false;
|
||||
/** True fi the font if rendered italic */
|
||||
private boolean italic = false;
|
||||
/** The padding applied in pixels to the top of the glyph rendered area */
|
||||
private int paddingTop;
|
||||
/** The padding applied in pixels to the left of the glyph rendered area */
|
||||
private int paddingLeft;
|
||||
/** The padding applied in pixels to the bottom of the glyph rendered area */
|
||||
private int paddingBottom;
|
||||
/** The padding applied in pixels to the right of the glyph rendered area */
|
||||
private int paddingRight;
|
||||
/** The padding applied in pixels to horizontal advance for each glyph */
|
||||
private int paddingAdvanceX;
|
||||
/** The padding applied in pixels to vertical advance for each glyph */
|
||||
private int paddingAdvanceY;
|
||||
/** The width of the glyph page generated */
|
||||
private int glyphPageWidth = 512;
|
||||
/** The height of the glyph page generated */
|
||||
private int glyphPageHeight = 512;
|
||||
/** The list of effects applied */
|
||||
private final List effects = new ArrayList();
|
||||
|
||||
/**
|
||||
* Default constructor for injection
|
||||
*/
|
||||
public HieroSettings() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new set of configuration from a file
|
||||
*
|
||||
* @param hieroFileRef The file system or classpath location of the Hiero settings file.
|
||||
* @throws SlickException if the file could not be read.
|
||||
*/
|
||||
public HieroSettings(String hieroFileRef) throws SlickException {
|
||||
this(ResourceLoader.getResourceAsStream(hieroFileRef));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new set of configuration from a file
|
||||
*
|
||||
* @param in The stream from which to read the settings from
|
||||
* @throws SlickException if the file could not be read.
|
||||
*/
|
||||
public HieroSettings(InputStream in) throws SlickException {
|
||||
try {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||
while (true) {
|
||||
String line = reader.readLine();
|
||||
if (line == null) break;
|
||||
line = line.trim();
|
||||
if (line.length() == 0) continue;
|
||||
String[] pieces = line.split("=", 2);
|
||||
String name = pieces[0].trim();
|
||||
String value = pieces[1];
|
||||
if (name.equals("font.size")) {
|
||||
fontSize = Integer.parseInt(value);
|
||||
} else if (name.equals("font.bold")) {
|
||||
bold = Boolean.valueOf(value).booleanValue();
|
||||
} else if (name.equals("font.italic")) {
|
||||
italic = Boolean.valueOf(value).booleanValue();
|
||||
} else if (name.equals("pad.top")) {
|
||||
paddingTop = Integer.parseInt(value);
|
||||
} else if (name.equals("pad.right")) {
|
||||
paddingRight = Integer.parseInt(value);
|
||||
} else if (name.equals("pad.bottom")) {
|
||||
paddingBottom = Integer.parseInt(value);
|
||||
} else if (name.equals("pad.left")) {
|
||||
paddingLeft = Integer.parseInt(value);
|
||||
} else if (name.equals("pad.advance.x")) {
|
||||
paddingAdvanceX = Integer.parseInt(value);
|
||||
} else if (name.equals("pad.advance.y")) {
|
||||
paddingAdvanceY = Integer.parseInt(value);
|
||||
} else if (name.equals("glyph.page.width")) {
|
||||
glyphPageWidth = Integer.parseInt(value);
|
||||
} else if (name.equals("glyph.page.height")) {
|
||||
glyphPageHeight = Integer.parseInt(value);
|
||||
} else if (name.equals("effect.class")) {
|
||||
try {
|
||||
effects.add(Class.forName(value).newInstance());
|
||||
} catch (Exception ex) {
|
||||
throw new SlickException("Unable to create effect instance: " + value, ex);
|
||||
}
|
||||
} else if (name.startsWith("effect.")) {
|
||||
// Set an effect value on the last added effect.
|
||||
name = name.substring(7);
|
||||
ConfigurableEffect effect = (ConfigurableEffect)effects.get(effects.size() - 1);
|
||||
List values = effect.getValues();
|
||||
for (Iterator iter = values.iterator(); iter.hasNext();) {
|
||||
Value effectValue = (Value)iter.next();
|
||||
if (effectValue.getName().equals(name)) {
|
||||
effectValue.setString(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
effect.setValues(values);
|
||||
}
|
||||
}
|
||||
reader.close();
|
||||
} catch (Exception ex) {
|
||||
throw new SlickException("Unable to load Hiero font file", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getPaddingTop()
|
||||
*
|
||||
* @return The padding for the top of the glyph area in pixels
|
||||
*/
|
||||
public int getPaddingTop () {
|
||||
return paddingTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#setPaddingTop(int)
|
||||
*
|
||||
* @param paddingTop The padding for the top of the glyph area in pixels
|
||||
*/
|
||||
public void setPaddingTop(int paddingTop) {
|
||||
this.paddingTop = paddingTop;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getPaddingLeft()
|
||||
*
|
||||
* @return The padding for the left of the glyph area in pixels
|
||||
*/
|
||||
public int getPaddingLeft() {
|
||||
return paddingLeft;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#setPaddingLeft(int)
|
||||
*
|
||||
* @param paddingLeft The padding for the left of the glyph area in pixels
|
||||
*/
|
||||
public void setPaddingLeft(int paddingLeft) {
|
||||
this.paddingLeft = paddingLeft;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getPaddingBottom()
|
||||
*
|
||||
* @return The padding for the bottom of the glyph area in pixels
|
||||
*/
|
||||
public int getPaddingBottom() {
|
||||
return paddingBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#setPaddingBottom(int)
|
||||
*
|
||||
* @param paddingBottom The padding for the bottom of the glyph area in pixels
|
||||
*/
|
||||
public void setPaddingBottom(int paddingBottom) {
|
||||
this.paddingBottom = paddingBottom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getPaddingRight()
|
||||
*
|
||||
* @return The padding for the right of the glyph area in pixels
|
||||
*/
|
||||
public int getPaddingRight() {
|
||||
return paddingRight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#setPaddingRight(int)
|
||||
*
|
||||
* @param paddingRight The padding for the right of the glyph area in pixels
|
||||
*/
|
||||
public void setPaddingRight(int paddingRight) {
|
||||
this.paddingRight = paddingRight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getPaddingAdvanceX()
|
||||
*
|
||||
* @return The padding for the horizontal advance of each glyph
|
||||
*/
|
||||
public int getPaddingAdvanceX() {
|
||||
return paddingAdvanceX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#setPaddingAdvanceX(int)
|
||||
*
|
||||
* @param paddingAdvanceX The padding for the horizontal advance of each glyph
|
||||
*/
|
||||
public void setPaddingAdvanceX(int paddingAdvanceX) {
|
||||
this.paddingAdvanceX = paddingAdvanceX;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getPaddingAdvanceY()
|
||||
*
|
||||
* @return The padding for the vertical advance of each glyph
|
||||
*/
|
||||
public int getPaddingAdvanceY() {
|
||||
return paddingAdvanceY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#setPaddingAdvanceY(int)
|
||||
*
|
||||
* @param paddingAdvanceY The padding for the vertical advance of each glyph
|
||||
*/
|
||||
public void setPaddingAdvanceY(int paddingAdvanceY) {
|
||||
this.paddingAdvanceY = paddingAdvanceY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getGlyphPageWidth()
|
||||
*
|
||||
* @return The width of the generate glyph pages
|
||||
*/
|
||||
public int getGlyphPageWidth() {
|
||||
return glyphPageWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#setGlyphPageWidth(int)
|
||||
*
|
||||
* @param glyphPageWidth The width of the generate glyph pages
|
||||
*/
|
||||
public void setGlyphPageWidth(int glyphPageWidth) {
|
||||
this.glyphPageWidth = glyphPageWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getGlyphPageHeight()
|
||||
*
|
||||
* @return The height of the generate glyph pages
|
||||
*/
|
||||
public int getGlyphPageHeight() {
|
||||
return glyphPageHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#setGlyphPageHeight(int)
|
||||
*
|
||||
* @param glyphPageHeight The height of the generate glyph pages
|
||||
*/
|
||||
public void setGlyphPageHeight(int glyphPageHeight) {
|
||||
this.glyphPageHeight = glyphPageHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#UnicodeFont(String, int, boolean, boolean)
|
||||
* @see UnicodeFont#UnicodeFont(java.awt.Font, int, boolean, boolean)
|
||||
*
|
||||
* @return The point size of the font generated
|
||||
*/
|
||||
public int getFontSize() {
|
||||
return fontSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#UnicodeFont(String, int, boolean, boolean)
|
||||
* @see UnicodeFont#UnicodeFont(java.awt.Font, int, boolean, boolean)
|
||||
*
|
||||
* @param fontSize The point size of the font generated
|
||||
*/
|
||||
public void setFontSize (int fontSize) {
|
||||
this.fontSize = fontSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#UnicodeFont(String, int, boolean, boolean)
|
||||
* @see UnicodeFont#UnicodeFont(java.awt.Font, int, boolean, boolean)
|
||||
*
|
||||
* @return True if the font was generated in bold typeface
|
||||
*/
|
||||
public boolean isBold () {
|
||||
return bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#UnicodeFont(String, int, boolean, boolean)
|
||||
* @see UnicodeFont#UnicodeFont(java.awt.Font, int, boolean, boolean)
|
||||
*
|
||||
* @param bold True if the font was generated in bold typeface
|
||||
*/
|
||||
public void setBold (boolean bold) {
|
||||
this.bold = bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#UnicodeFont(String, int, boolean, boolean)
|
||||
* @see UnicodeFont#UnicodeFont(java.awt.Font, int, boolean, boolean)
|
||||
*
|
||||
* @return True if the font was generated in italic typeface
|
||||
*/
|
||||
public boolean isItalic () {
|
||||
return italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#UnicodeFont(String, int, boolean, boolean)
|
||||
* @see UnicodeFont#UnicodeFont(java.awt.Font, int, boolean, boolean)
|
||||
*
|
||||
* @param italic True if the font was generated in italic typeface
|
||||
*/
|
||||
public void setItalic (boolean italic) {
|
||||
this.italic = italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UnicodeFont#getEffects()
|
||||
*
|
||||
* @return The list of effects applied to the text
|
||||
*/
|
||||
public List getEffects() {
|
||||
return effects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the settings to a file.
|
||||
*
|
||||
* @param file The file we're saving to
|
||||
* @throws IOException if the file could not be saved.
|
||||
*/
|
||||
public void save(File file) throws IOException {
|
||||
PrintStream out = new PrintStream(new FileOutputStream(file));
|
||||
out.println("font.size=" + fontSize);
|
||||
out.println("font.bold=" + bold);
|
||||
out.println("font.italic=" + italic);
|
||||
out.println();
|
||||
out.println("pad.top=" + paddingTop);
|
||||
out.println("pad.right=" + paddingRight);
|
||||
out.println("pad.bottom=" + paddingBottom);
|
||||
out.println("pad.left=" + paddingLeft);
|
||||
out.println("pad.advance.x=" + paddingAdvanceX);
|
||||
out.println("pad.advance.y=" + paddingAdvanceY);
|
||||
out.println();
|
||||
out.println("glyph.page.width=" + glyphPageWidth);
|
||||
out.println("glyph.page.height=" + glyphPageHeight);
|
||||
out.println();
|
||||
for (Iterator iter = effects.iterator(); iter.hasNext();) {
|
||||
ConfigurableEffect effect = (ConfigurableEffect)iter.next();
|
||||
out.println("effect.class=" + effect.getClass().getName());
|
||||
for (Iterator iter2 = effect.getValues().iterator(); iter2.hasNext();) {
|
||||
Value value = (Value)iter2.next();
|
||||
out.println("effect." + value.getName() + "=" + value.getString());
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
import org.newdawn.slick.font.Glyph;
|
||||
|
||||
/**
|
||||
* Makes glyphs a solid color.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class ColorEffect implements ConfigurableEffect {
|
||||
/** The colour that will be applied across the text */
|
||||
private Color color = Color.white;
|
||||
|
||||
/**
|
||||
* Default constructor for injection
|
||||
*/
|
||||
public ColorEffect() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new effect to colour the text
|
||||
*
|
||||
* @param color The colour to apply across the text
|
||||
*/
|
||||
public ColorEffect(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.Effect#draw(java.awt.image.BufferedImage, java.awt.Graphics2D, org.newdawn.slick.UnicodeFont, org.newdawn.slick.font.Glyph)
|
||||
*/
|
||||
public void draw(BufferedImage image, Graphics2D g, UnicodeFont unicodeFont, Glyph glyph) {
|
||||
g.setColor(color);
|
||||
g.fill(glyph.getShape());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the colour being applied by this effect
|
||||
*
|
||||
* @return The colour being applied by this effect
|
||||
*/
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the colour being applied by this effect
|
||||
*
|
||||
* @param color The colour being applied by this effect
|
||||
*/
|
||||
public void setColor(Color color) {
|
||||
if (color == null) throw new IllegalArgumentException("color cannot be null.");
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString () {
|
||||
return "Color";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect#getValues()
|
||||
*/
|
||||
public List getValues() {
|
||||
List values = new ArrayList();
|
||||
values.add(EffectUtil.colorValue("Color", color));
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect#setValues(java.util.List)
|
||||
*/
|
||||
public void setValues(List values) {
|
||||
for (Iterator iter = values.iterator(); iter.hasNext();) {
|
||||
Value value = (Value)iter.next();
|
||||
if (value.getName().equals("Color")) {
|
||||
setColor((Color)value.getObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* An effect that has a number of configuration values. This allows the effect to be configured in the Hiero GUI and to be saved
|
||||
* and loaded to and from a file.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public interface ConfigurableEffect extends Effect {
|
||||
/**
|
||||
* Returns the list of {@link Value}s for this effect. This list is not typically backed by the effect, so changes to the
|
||||
* values will not take affect until {@link #setValues(List)} is called.
|
||||
*/
|
||||
public List getValues();
|
||||
|
||||
/**
|
||||
* Sets the list of {@link Value}s for this effect.
|
||||
*/
|
||||
public void setValues(List values);
|
||||
|
||||
/**
|
||||
* Represents a configurable value for an effect.
|
||||
*/
|
||||
static public interface Value {
|
||||
/**
|
||||
* Returns the name of the value.
|
||||
*/
|
||||
public String getName ();
|
||||
|
||||
/**
|
||||
* Sets the string representation of the value.
|
||||
*/
|
||||
public void setString (String value);
|
||||
|
||||
/**
|
||||
* Gets the string representation of the value.
|
||||
*/
|
||||
public String getString ();
|
||||
|
||||
/**
|
||||
* Gets the object representation of the value.
|
||||
*/
|
||||
public Object getObject ();
|
||||
|
||||
/**
|
||||
* Shows a dialog allowing a user to configure this value.
|
||||
*/
|
||||
public void showDialog ();
|
||||
}
|
||||
}
|
||||
25
lib/slick-source/org/newdawn/slick/font/effects/Effect.java
Normal file
25
lib/slick-source/org/newdawn/slick/font/effects/Effect.java
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
import org.newdawn.slick.font.Glyph;
|
||||
|
||||
/**
|
||||
* A graphical effect that is applied to glyphs in a {@link UnicodeFont}.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public interface Effect {
|
||||
/**
|
||||
* Called to draw the effect.
|
||||
*
|
||||
* @param image The image to draw into
|
||||
* @param g The graphics context to use for applying the effect
|
||||
* @param unicodeFont The font being rendered
|
||||
* @param glyph The particular glyph being rendered
|
||||
*/
|
||||
public void draw (BufferedImage image, Graphics2D g, UnicodeFont unicodeFont, Glyph glyph);
|
||||
}
|
||||
368
lib/slick-source/org/newdawn/slick/font/effects/EffectUtil.java
Normal file
368
lib/slick-source/org/newdawn/slick/font/effects/EffectUtil.java
Normal file
@@ -0,0 +1,368 @@
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JColorChooser;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
|
||||
import org.newdawn.slick.font.GlyphPage;
|
||||
import org.newdawn.slick.font.effects.ConfigurableEffect.Value;
|
||||
|
||||
/**
|
||||
* Provides utility methods for effects.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class EffectUtil {
|
||||
/** A graphics 2D temporary surface to be used when generating effects */
|
||||
static private BufferedImage scratchImage = new BufferedImage(GlyphPage.MAX_GLYPH_SIZE, GlyphPage.MAX_GLYPH_SIZE,
|
||||
BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
/**
|
||||
* Returns an image that can be used by effects as a temp image.
|
||||
*
|
||||
* @return The scratch image used for temporary operations
|
||||
*/
|
||||
static public BufferedImage getScratchImage() {
|
||||
Graphics2D g = (Graphics2D)scratchImage.getGraphics();
|
||||
g.setComposite(AlphaComposite.Clear);
|
||||
g.fillRect(0, 0, GlyphPage.MAX_GLYPH_SIZE, GlyphPage.MAX_GLYPH_SIZE);
|
||||
g.setComposite(AlphaComposite.SrcOver);
|
||||
g.setColor(java.awt.Color.white);
|
||||
return scratchImage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user for a colour value
|
||||
*
|
||||
* @param name Thename of the value being configured
|
||||
* @param currentValue The default value that should be selected
|
||||
* @return The value selected
|
||||
*/
|
||||
static public Value colorValue(String name, Color currentValue) {
|
||||
return new DefaultValue(name, EffectUtil.toString(currentValue)) {
|
||||
public void showDialog () {
|
||||
Color newColor = JColorChooser.showDialog(null, "Choose a color", EffectUtil.fromString(value));
|
||||
if (newColor != null) value = EffectUtil.toString(newColor);
|
||||
}
|
||||
|
||||
public Object getObject () {
|
||||
return EffectUtil.fromString(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user for int value
|
||||
*
|
||||
* @param name The name of the dialog to show
|
||||
* @param currentValue The current value to be displayed
|
||||
* @param description The help text to provide
|
||||
* @return The value selected by the user
|
||||
*/
|
||||
static public Value intValue (String name, final int currentValue, final String description) {
|
||||
return new DefaultValue(name, String.valueOf(currentValue)) {
|
||||
public void showDialog () {
|
||||
JSpinner spinner = new JSpinner(new SpinnerNumberModel(currentValue, Short.MIN_VALUE, Short.MAX_VALUE, 1));
|
||||
if (showValueDialog(spinner, description)) value = String.valueOf(spinner.getValue());
|
||||
}
|
||||
|
||||
public Object getObject () {
|
||||
return Integer.valueOf(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user for float value
|
||||
*
|
||||
* @param name The name of the dialog to show
|
||||
* @param currentValue The current value to be displayed
|
||||
* @param description The help text to provide
|
||||
* @param min The minimum value to allow
|
||||
* @param max The maximum value to allow
|
||||
* @return The value selected by the user
|
||||
*/
|
||||
static public Value floatValue (String name, final float currentValue, final float min, final float max,
|
||||
final String description) {
|
||||
return new DefaultValue(name, String.valueOf(currentValue)) {
|
||||
public void showDialog () {
|
||||
JSpinner spinner = new JSpinner(new SpinnerNumberModel(currentValue, min, max, 0.1f));
|
||||
if (showValueDialog(spinner, description)) value = String.valueOf(((Double)spinner.getValue()).floatValue());
|
||||
}
|
||||
|
||||
public Object getObject () {
|
||||
return Float.valueOf(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user for boolean value
|
||||
*
|
||||
* @param name The name of the dialog to show
|
||||
* @param currentValue The current value to be displayed
|
||||
* @param description The help text to provide
|
||||
* @return The value selected by the user
|
||||
*/
|
||||
static public Value booleanValue (String name, final boolean currentValue, final String description) {
|
||||
return new DefaultValue(name, String.valueOf(currentValue)) {
|
||||
public void showDialog () {
|
||||
JCheckBox checkBox = new JCheckBox();
|
||||
checkBox.setSelected(currentValue);
|
||||
if (showValueDialog(checkBox, description)) value = String.valueOf(checkBox.isSelected());
|
||||
}
|
||||
|
||||
public Object getObject () {
|
||||
return Boolean.valueOf(value);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prompts the user for a value that represents a fixed number of options.
|
||||
* All options are strings.
|
||||
*
|
||||
* @param options The first array has an entry for each option. Each entry is either a String[1] that is both the display value
|
||||
* and actual value, or a String[2] whose first element is the display value and second element is the actual value.
|
||||
*
|
||||
* @param name The name of the value being prompted for
|
||||
* @param currentValue The current value to show as default
|
||||
* @param description The description of the value
|
||||
* @return The value selected by the user
|
||||
*/
|
||||
static public Value optionValue (String name, final String currentValue, final String[][] options, final String description) {
|
||||
return new DefaultValue(name, currentValue.toString()) {
|
||||
public void showDialog () {
|
||||
int selectedIndex = -1;
|
||||
DefaultComboBoxModel model = new DefaultComboBoxModel();
|
||||
for (int i = 0; i < options.length; i++) {
|
||||
model.addElement(options[i][0]);
|
||||
if (getValue(i).equals(currentValue)) selectedIndex = i;
|
||||
}
|
||||
JComboBox comboBox = new JComboBox(model);
|
||||
comboBox.setSelectedIndex(selectedIndex);
|
||||
if (showValueDialog(comboBox, description)) value = getValue(comboBox.getSelectedIndex());
|
||||
}
|
||||
|
||||
private String getValue (int i) {
|
||||
if (options[i].length == 1) return options[i][0];
|
||||
return options[i][1];
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
for (int i = 0; i < options.length; i++)
|
||||
if (getValue(i).equals(value)) return options[i][0].toString();
|
||||
return "";
|
||||
}
|
||||
|
||||
public Object getObject () {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convers a color to a string.
|
||||
*
|
||||
* @param color The color to encode to a string
|
||||
* @return The colour as a string
|
||||
*/
|
||||
static public String toString (Color color) {
|
||||
if (color == null) throw new IllegalArgumentException("color cannot be null.");
|
||||
String r = Integer.toHexString(color.getRed());
|
||||
if (r.length() == 1) r = "0" + r;
|
||||
String g = Integer.toHexString(color.getGreen());
|
||||
if (g.length() == 1) g = "0" + g;
|
||||
String b = Integer.toHexString(color.getBlue());
|
||||
if (b.length() == 1) b = "0" + b;
|
||||
return r + g + b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string to a color.
|
||||
*
|
||||
* @param rgb The string encoding the colour
|
||||
* @return The colour represented by the given encoded string
|
||||
*/
|
||||
static public Color fromString (String rgb) {
|
||||
if (rgb == null || rgb.length() != 6) return Color.white;
|
||||
return new Color(Integer.parseInt(rgb.substring(0, 2), 16), Integer.parseInt(rgb.substring(2, 4), 16), Integer.parseInt(rgb
|
||||
.substring(4, 6), 16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides generic functionality for an effect's configurable value.
|
||||
*/
|
||||
static private abstract class DefaultValue implements Value {
|
||||
/** The value being held */
|
||||
String value;
|
||||
/** The key/name of the value */
|
||||
String name;
|
||||
|
||||
/**
|
||||
* Create a default value
|
||||
*
|
||||
* @param name The name of the value being configured
|
||||
* @param value The value to use for the default
|
||||
*/
|
||||
public DefaultValue(String name, String value) {
|
||||
this.value = value;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect.Value#setString(java.lang.String)
|
||||
*/
|
||||
public void setString(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect.Value#getString()
|
||||
*/
|
||||
public String getString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect.Value#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompt the user for a value
|
||||
*
|
||||
* @param component The component to use as parent for the prompting dialog
|
||||
* @param description The description of the value being prompted for
|
||||
* @return True if the value was configured
|
||||
*/
|
||||
public boolean showValueDialog(final JComponent component, String description) {
|
||||
ValueDialog dialog = new ValueDialog(component, name, description);
|
||||
dialog.setTitle(name);
|
||||
dialog.setLocationRelativeTo(null);
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
public void run () {
|
||||
JComponent focusComponent = component;
|
||||
if (focusComponent instanceof JSpinner)
|
||||
focusComponent = ((JSpinner.DefaultEditor)((JSpinner)component).getEditor()).getTextField();
|
||||
focusComponent.requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
dialog.setVisible(true);
|
||||
return dialog.okPressed;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Provides generic functionality for a dialog to configure a value.
|
||||
*/
|
||||
static private class ValueDialog extends JDialog {
|
||||
/** True if OK was pressed */
|
||||
public boolean okPressed = false;
|
||||
|
||||
/**
|
||||
* Create a new dialog to configure a specific value
|
||||
*
|
||||
* @param component The component to use as the parent of the dialog prompting the user
|
||||
* @param name The name of the value being configured
|
||||
* @param description The description of the value being configured
|
||||
*/
|
||||
public ValueDialog(JComponent component, String name, String description) {
|
||||
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
setLayout(new GridBagLayout());
|
||||
setModal(true);
|
||||
|
||||
if (component instanceof JSpinner)
|
||||
((JSpinner.DefaultEditor)((JSpinner)component).getEditor()).getTextField().setColumns(4);
|
||||
|
||||
JPanel descriptionPanel = new JPanel();
|
||||
descriptionPanel.setLayout(new GridBagLayout());
|
||||
getContentPane().add(
|
||||
descriptionPanel,
|
||||
new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0,
|
||||
0), 0, 0));
|
||||
descriptionPanel.setBackground(Color.white);
|
||||
descriptionPanel.setBorder(BorderFactory.createMatteBorder(0, 0, 1, 0, Color.black));
|
||||
{
|
||||
JTextArea descriptionText = new JTextArea(description);
|
||||
descriptionPanel.add(descriptionText, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,
|
||||
GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
|
||||
descriptionText.setWrapStyleWord(true);
|
||||
descriptionText.setLineWrap(true);
|
||||
descriptionText.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
|
||||
descriptionText.setEditable(false);
|
||||
}
|
||||
|
||||
JPanel panel = new JPanel();
|
||||
getContentPane().add(
|
||||
panel,
|
||||
new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(5, 5, 0,
|
||||
5), 0, 0));
|
||||
panel.add(new JLabel(name + ":"));
|
||||
panel.add(component);
|
||||
|
||||
JPanel buttonPanel = new JPanel();
|
||||
getContentPane().add(
|
||||
buttonPanel,
|
||||
new GridBagConstraints(0, 2, 2, 1, 0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE,
|
||||
new Insets(0, 0, 0, 0), 0, 0));
|
||||
{
|
||||
JButton okButton = new JButton("OK");
|
||||
buttonPanel.add(okButton);
|
||||
okButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed (ActionEvent evt) {
|
||||
okPressed = true;
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
{
|
||||
JButton cancelButton = new JButton("Cancel");
|
||||
buttonPanel.add(cancelButton);
|
||||
cancelButton.addActionListener(new ActionListener() {
|
||||
public void actionPerformed (ActionEvent evt) {
|
||||
setVisible(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setSize(new Dimension(320, 175));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.BufferedImageOp;
|
||||
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
import org.newdawn.slick.font.Glyph;
|
||||
|
||||
/**
|
||||
* Applys a {@link BufferedImageOp} filter to glyphs. Many filters can be found
|
||||
* here: http://www.jhlabs.com/ip/filters/index.html
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class FilterEffect implements Effect {
|
||||
/** The filter to be applied */
|
||||
private BufferedImageOp filter;
|
||||
|
||||
/**
|
||||
* Default constructor for injection
|
||||
*/
|
||||
public FilterEffect () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new filtering effect based on a convolution operation
|
||||
*
|
||||
* @param filter The filter to apply
|
||||
*/
|
||||
public FilterEffect (BufferedImageOp filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.Effect#draw(java.awt.image.BufferedImage, java.awt.Graphics2D, org.newdawn.slick.UnicodeFont, org.newdawn.slick.font.Glyph)
|
||||
*/
|
||||
public void draw(BufferedImage image, Graphics2D g, UnicodeFont unicodeFont, Glyph glyph) {
|
||||
BufferedImage scratchImage = EffectUtil.getScratchImage();
|
||||
filter.filter(image, scratchImage);
|
||||
image.getGraphics().drawImage(scratchImage, 0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filter being applied by this effect
|
||||
*
|
||||
* @return The filter being applied by this effect
|
||||
*/
|
||||
public BufferedImageOp getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filter being applied by this effect
|
||||
*
|
||||
* @param filter The filter being used by this effect
|
||||
*/
|
||||
public void setFilter(BufferedImageOp filter) {
|
||||
this.filter = filter;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.GradientPaint;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
import org.newdawn.slick.font.Glyph;
|
||||
|
||||
/**
|
||||
* Paints glyphs with a gradient fill.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class GradientEffect implements ConfigurableEffect {
|
||||
/** The top of gradients colour */
|
||||
private Color topColor = Color.cyan;
|
||||
/** The bottom of the gradient's colour */
|
||||
private Color bottomColor = Color.blue;
|
||||
/** The offset the gradient starts at */
|
||||
private int offset = 0;
|
||||
/** The scaling of the graident */
|
||||
private float scale = 1;
|
||||
/** True if the graident should cycle back and forth across the surface */
|
||||
private boolean cyclic;
|
||||
|
||||
/**
|
||||
* Default constructor for injection
|
||||
*/
|
||||
public GradientEffect() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new effect to apply a graident
|
||||
*
|
||||
* @param topColor The colour at the top of the graident
|
||||
* @param bottomColor The colour at the bottom of the gradient
|
||||
* @param scale The scale of the graident
|
||||
*/
|
||||
public GradientEffect(Color topColor, Color bottomColor, float scale) {
|
||||
this.topColor = topColor;
|
||||
this.bottomColor = bottomColor;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.Effect#draw(java.awt.image.BufferedImage, java.awt.Graphics2D, org.newdawn.slick.UnicodeFont, org.newdawn.slick.font.Glyph)
|
||||
*/
|
||||
public void draw(BufferedImage image, Graphics2D g, UnicodeFont unicodeFont, Glyph glyph) {
|
||||
int ascent = unicodeFont.getAscent();
|
||||
float height = (ascent) * scale;
|
||||
float top = -glyph.getYOffset() + unicodeFont.getDescent() + offset + ascent / 2 - height / 2;
|
||||
g.setPaint(new GradientPaint(0, top, topColor, 0, top + height, bottomColor, cyclic));
|
||||
g.fill(glyph.getShape());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the colour at the top of the graident
|
||||
*
|
||||
* @return The colour at the top of the gradient
|
||||
*/
|
||||
public Color getTopColor() {
|
||||
return topColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the colour at the top of the graident
|
||||
*
|
||||
* @param topColor The colour at the top of the graident
|
||||
*/
|
||||
public void setTopColor(Color topColor) {
|
||||
this.topColor = topColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the colour at the bottom of the graident
|
||||
*
|
||||
* @return The colour at the bottom of the gradient
|
||||
*/
|
||||
public Color getBottomColor () {
|
||||
return bottomColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the colour at the bottom of the graident
|
||||
*
|
||||
* @param bottomColor The colour at the bottom of the graident
|
||||
*/
|
||||
public void setBottomColor(Color bottomColor) {
|
||||
this.bottomColor = bottomColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the offset the gradients starts at
|
||||
*
|
||||
* @return The offset the gradient starts at
|
||||
*/
|
||||
public int getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pixel offset to move the gradient up or down.
|
||||
* The gradient is normally centered on the glyph.
|
||||
*
|
||||
* @param offset The offset the gradient is moved by
|
||||
*/
|
||||
public void setOffset (int offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the percentage scaling being applied to the gradient across the surface
|
||||
*
|
||||
* @return The scale of the graident
|
||||
*/
|
||||
public float getScale() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the height of the gradient by a percentage. The gradient is
|
||||
* normally the height of most glyphs in the font.
|
||||
*
|
||||
* @param scale The scale to apply
|
||||
*/
|
||||
public void setScale (float scale) {
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the graident is repeating
|
||||
*
|
||||
* @return True if the gradient is repeating
|
||||
*/
|
||||
public boolean isCyclic() {
|
||||
return cyclic;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set to true, the gradient will repeat.
|
||||
*
|
||||
* @param cyclic True if the graident repeats
|
||||
*/
|
||||
public void setCyclic(boolean cyclic) {
|
||||
this.cyclic = cyclic;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "Gradient";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect#getValues()
|
||||
*/
|
||||
public List getValues() {
|
||||
List values = new ArrayList();
|
||||
values.add(EffectUtil.colorValue("Top color", topColor));
|
||||
values.add(EffectUtil.colorValue("Bottom color", bottomColor));
|
||||
values.add(EffectUtil.intValue("Offset", offset,
|
||||
"This setting allows you to move the gradient up or down. The gradient is normally centered on the glyph."));
|
||||
values.add(EffectUtil.floatValue("Scale", scale, 0, 1, "This setting allows you to change the height of the gradient by a"
|
||||
+ "percentage. The gradient is normally the height of most glyphs in the font."));
|
||||
values.add(EffectUtil.booleanValue("Cyclic", cyclic, "If this setting is checked, the gradient will repeat."));
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect#setValues(java.util.List)
|
||||
*/
|
||||
public void setValues(List values) {
|
||||
for (Iterator iter = values.iterator(); iter.hasNext();) {
|
||||
Value value = (Value)iter.next();
|
||||
if (value.getName().equals("Top color")) {
|
||||
topColor = (Color)value.getObject();
|
||||
} else if (value.getName().equals("Bottom color")) {
|
||||
bottomColor = (Color)value.getObject();
|
||||
} else if (value.getName().equals("Offset")) {
|
||||
offset = ((Integer)value.getObject()).intValue();
|
||||
} else if (value.getName().equals("Scale")) {
|
||||
scale = ((Float)value.getObject()).floatValue();
|
||||
} else if (value.getName().equals("Cyclic")) {
|
||||
cyclic = ((Boolean)value.getObject()).booleanValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
import org.newdawn.slick.font.Glyph;
|
||||
|
||||
/**
|
||||
* Strokes glyphs with an outline.
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class OutlineEffect implements ConfigurableEffect {
|
||||
/** The width of the outline in pixels */
|
||||
private float width = 2;
|
||||
/** The colour of the outline */
|
||||
private Color color = Color.black;
|
||||
/** The type of join at the line joins of the out line */
|
||||
private int join = BasicStroke.JOIN_BEVEL;
|
||||
/** The stroke used to draw the outline */
|
||||
private Stroke stroke;
|
||||
|
||||
/**
|
||||
* Default constructor for injection
|
||||
*/
|
||||
public OutlineEffect() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new effect to draw the outline of the text
|
||||
*
|
||||
* @param width The width of the outline
|
||||
* @param color The colour of the outline
|
||||
*/
|
||||
public OutlineEffect(int width, Color color) {
|
||||
this.width = width;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.Effect#draw(java.awt.image.BufferedImage, java.awt.Graphics2D, org.newdawn.slick.UnicodeFont, org.newdawn.slick.font.Glyph)
|
||||
*/
|
||||
public void draw(BufferedImage image, Graphics2D g, UnicodeFont unicodeFont, Glyph glyph) {
|
||||
g = (Graphics2D)g.create();
|
||||
if (stroke != null)
|
||||
g.setStroke(stroke);
|
||||
else
|
||||
g.setStroke(getStroke());
|
||||
g.setColor(color);
|
||||
g.draw(glyph.getShape());
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the width of the outline being drawn
|
||||
*
|
||||
* @return The width of the outline being drawn
|
||||
*/
|
||||
public float getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the width of the outline. The glyphs will need padding so the
|
||||
* outline doesn't get clipped.
|
||||
*
|
||||
* @param width The width of the outline being drawn
|
||||
*/
|
||||
public void setWidth (int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the colour of the outline being drawn
|
||||
*
|
||||
* @return The colour of the outline being drawn
|
||||
*/
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the colour of the outline being drawn
|
||||
*
|
||||
* @param color The colour of the outline to draw
|
||||
*/
|
||||
public void setColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the join type as indicated by @see BasicStroke
|
||||
*
|
||||
* @return The join type between segments in the outline
|
||||
*/
|
||||
public int getJoin() {
|
||||
return join;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the stroke being used to draw the outline
|
||||
*
|
||||
* @return The stroke being used to draw the outline
|
||||
*/
|
||||
public Stroke getStroke() {
|
||||
if (stroke == null) {
|
||||
return new BasicStroke(width, BasicStroke.CAP_SQUARE, join);
|
||||
}
|
||||
|
||||
return stroke;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stroke to use for the outline. If this is set,
|
||||
* the other outline settings are ignored.
|
||||
*
|
||||
* @param stroke The stroke to be used to draw the outline
|
||||
*/
|
||||
public void setStroke (Stroke stroke) {
|
||||
this.stroke = stroke;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets how the corners of the outline are drawn. This is usually only noticeable
|
||||
* at large outline widths.
|
||||
*
|
||||
* @param join One of: {@link BasicStroke#JOIN_BEVEL}, {@link BasicStroke#JOIN_MITER}, {@link BasicStroke#JOIN_ROUND}
|
||||
*/
|
||||
public void setJoin (int join) {
|
||||
this.join = join;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString () {
|
||||
return "Outline";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect#getValues()
|
||||
*/
|
||||
public List getValues () {
|
||||
List values = new ArrayList();
|
||||
values.add(EffectUtil.colorValue("Color", color));
|
||||
values.add(EffectUtil.floatValue("Width", width, 0.1f, 999, "This setting controls the width of the outline. "
|
||||
+ "The glyphs will need padding so the outline doesn't get clipped."));
|
||||
values.add(EffectUtil.optionValue("Join", String.valueOf(join), new String[][] { {"Bevel", BasicStroke.JOIN_BEVEL + ""},
|
||||
{"Miter", BasicStroke.JOIN_MITER + ""}, {"Round", BasicStroke.JOIN_ROUND + ""}},
|
||||
"This setting defines how the corners of the outline are drawn. "
|
||||
+ "This is usually only noticeable at large outline widths."));
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect#setValues(java.util.List)
|
||||
*/
|
||||
public void setValues (List values) {
|
||||
for (Iterator iter = values.iterator(); iter.hasNext();) {
|
||||
Value value = (Value)iter.next();
|
||||
if (value.getName().equals("Color")) {
|
||||
color = (Color)value.getObject();
|
||||
} else if (value.getName().equals("Width")) {
|
||||
width = ((Float)value.getObject()).floatValue();
|
||||
} else if (value.getName().equals("Join")) {
|
||||
join = Integer.parseInt((String)value.getObject());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* Copyright 2006 Jerry Huxtable
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
|
||||
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.geom.FlatteningPathIterator;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* An effect that genrates a wobbly line around the outline of the text
|
||||
*
|
||||
* @author Jerry Huxtable
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class OutlineWobbleEffect extends OutlineEffect {
|
||||
/** How often the line wobbles */
|
||||
private float detail = 1;
|
||||
/** The amount of the line wobbles */
|
||||
private float amplitude = 1;
|
||||
|
||||
/**
|
||||
* Default constructor for injection
|
||||
*/
|
||||
public OutlineWobbleEffect () {
|
||||
setStroke(new WobbleStroke());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the detail of the wobble effect.
|
||||
*
|
||||
* @return The detail of the wobble effect
|
||||
*/
|
||||
public float getDetail() {
|
||||
return detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the detail of the wobble effect.
|
||||
*
|
||||
* @param detail The detail of the wobble effect
|
||||
*/
|
||||
public void setDetail(float detail) {
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amplitude of the wobble effect.
|
||||
*
|
||||
* @return The amplitude of the wobble effect
|
||||
*/
|
||||
public float getAmplitude() {
|
||||
return amplitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amplitude of the wobble effect.
|
||||
*
|
||||
* @param amplitude The detail of the wobble effect
|
||||
*/
|
||||
public void setAmplitude(float amplitude) {
|
||||
this.amplitude = amplitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new effect that generates a wobbly line around the text
|
||||
*
|
||||
* @param width The width of the line
|
||||
* @param color The colour of the line
|
||||
*/
|
||||
public OutlineWobbleEffect (int width, Color color) {
|
||||
super(width, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.OutlineEffect#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "Outline (Wobble)";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.OutlineEffect#getValues()
|
||||
*/
|
||||
public List getValues() {
|
||||
List values = super.getValues();
|
||||
values.remove(2); // Remove "Join".
|
||||
values.add(EffectUtil.floatValue("Detail", detail, 1, 50, "This setting controls how detailed the outline will be. "
|
||||
+ "Smaller numbers cause the outline to have more detail."));
|
||||
values.add(EffectUtil.floatValue("Amplitude", amplitude, 0.5f, 50, "This setting controls the amplitude of the outline."));
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.OutlineEffect#setValues(java.util.List)
|
||||
*/
|
||||
public void setValues(List values) {
|
||||
super.setValues(values);
|
||||
for (Iterator iter = values.iterator(); iter.hasNext();) {
|
||||
Value value = (Value)iter.next();
|
||||
if (value.getName().equals("Detail")) {
|
||||
detail = ((Float)value.getObject()).floatValue();
|
||||
} else if (value.getName().equals("Amplitude")) {
|
||||
amplitude = ((Float)value.getObject()).floatValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A stroke that generate a wobbly line
|
||||
*
|
||||
* @author Jerry Huxtable
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
private class WobbleStroke implements Stroke {
|
||||
/** The flattening factor of the stroke */
|
||||
private static final float FLATNESS = 1;
|
||||
|
||||
/**
|
||||
* @see java.awt.Stroke#createStrokedShape(java.awt.Shape)
|
||||
*/
|
||||
public Shape createStrokedShape (Shape shape) {
|
||||
GeneralPath result = new GeneralPath();
|
||||
shape = new BasicStroke(getWidth(), BasicStroke.CAP_SQUARE, getJoin()).createStrokedShape(shape);
|
||||
PathIterator it = new FlatteningPathIterator(shape.getPathIterator(null), FLATNESS);
|
||||
float points[] = new float[6];
|
||||
float moveX = 0, moveY = 0;
|
||||
float lastX = 0, lastY = 0;
|
||||
float thisX = 0, thisY = 0;
|
||||
int type = 0;
|
||||
float next = 0;
|
||||
while (!it.isDone()) {
|
||||
type = it.currentSegment(points);
|
||||
switch (type) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
moveX = lastX = randomize(points[0]);
|
||||
moveY = lastY = randomize(points[1]);
|
||||
result.moveTo(moveX, moveY);
|
||||
next = 0;
|
||||
break;
|
||||
|
||||
case PathIterator.SEG_CLOSE:
|
||||
points[0] = moveX;
|
||||
points[1] = moveY;
|
||||
// Fall into....
|
||||
|
||||
case PathIterator.SEG_LINETO:
|
||||
thisX = randomize(points[0]);
|
||||
thisY = randomize(points[1]);
|
||||
float dx = thisX - lastX;
|
||||
float dy = thisY - lastY;
|
||||
float distance = (float)Math.sqrt(dx * dx + dy * dy);
|
||||
if (distance >= next) {
|
||||
float r = 1.0f / distance;
|
||||
while (distance >= next) {
|
||||
float x = lastX + next * dx * r;
|
||||
float y = lastY + next * dy * r;
|
||||
result.lineTo(randomize(x), randomize(y));
|
||||
next += detail;
|
||||
}
|
||||
}
|
||||
next -= distance;
|
||||
lastX = thisX;
|
||||
lastY = thisY;
|
||||
break;
|
||||
}
|
||||
it.next();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random wobble factor
|
||||
*
|
||||
* @param x The position on the line
|
||||
* @return The wobble factor
|
||||
*/
|
||||
private float randomize(float x) {
|
||||
return x + (float)Math.random() * amplitude * 2 - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright 2006 Jerry Huxtable
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
|
||||
* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
|
||||
* governing permissions and limitations under the License.
|
||||
*/
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.awt.geom.FlatteningPathIterator;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.geom.PathIterator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* An effect to generate a uniformly zigzaging line around text
|
||||
*
|
||||
* @author Jerry Huxtable
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class OutlineZigzagEffect extends OutlineEffect {
|
||||
/** The amount the line moves away from the text */
|
||||
private float amplitude = 1;
|
||||
/** How often the line zigs and zags */
|
||||
private float wavelength = 3;
|
||||
|
||||
/**
|
||||
* Default constructor for injection
|
||||
*/
|
||||
public OutlineZigzagEffect() {
|
||||
setStroke(new ZigzagStroke());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the wavelength of the wobble effect.
|
||||
*
|
||||
* @return The wavelength of the wobble effect
|
||||
*/
|
||||
public float getWavelength() {
|
||||
return wavelength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the wavelength of the wobble effect.
|
||||
*
|
||||
* @param wavelength The wavelength of the wobble effect
|
||||
*/
|
||||
public void setWavelength(float wavelength) {
|
||||
this.wavelength = wavelength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amplitude of the wobble effect.
|
||||
*
|
||||
* @return The amplitude of the wobble effect
|
||||
*/
|
||||
public float getAmplitude() {
|
||||
return amplitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the amplitude of the wobble effect.
|
||||
*
|
||||
* @param amplitude The detail of the wobble effect
|
||||
*/
|
||||
public void setAmplitude(float amplitude) {
|
||||
this.amplitude = amplitude;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new effect to generate a zigzagging line around the text
|
||||
*
|
||||
* @param width The width of the line
|
||||
* @param color The colour of the line
|
||||
*/
|
||||
public OutlineZigzagEffect(int width, Color color) {
|
||||
super(width, color);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.OutlineEffect#toString()
|
||||
*/
|
||||
public String toString () {
|
||||
return "Outline (Zigzag)";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.OutlineEffect#getValues()
|
||||
*/
|
||||
public List getValues() {
|
||||
List values = super.getValues();
|
||||
values.add(EffectUtil.floatValue("Wavelength", wavelength, 1, 100, "This setting controls the wavelength of the outline. "
|
||||
+ "The smaller the value, the more segments will be used to draw the outline."));
|
||||
values.add(EffectUtil.floatValue("Amplitude", amplitude, 0.5f, 50, "This setting controls the amplitude of the outline. "
|
||||
+ "The bigger the value, the more the zigzags will vary."));
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.OutlineEffect#setValues(java.util.List)
|
||||
*/
|
||||
public void setValues(List values) {
|
||||
super.setValues(values);
|
||||
for (Iterator iter = values.iterator(); iter.hasNext();) {
|
||||
Value value = (Value)iter.next();
|
||||
if (value.getName().equals("Wavelength")) {
|
||||
wavelength = ((Float)value.getObject()).floatValue();
|
||||
} else if (value.getName().equals("Amplitude")) {
|
||||
amplitude = ((Float)value.getObject()).floatValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A stroke to generate zigzags
|
||||
*
|
||||
* @author Jerry Huxtable
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
private class ZigzagStroke implements Stroke {
|
||||
/** The flattening factor applied to the path iterator */
|
||||
private static final float FLATNESS = 1;
|
||||
|
||||
/**
|
||||
* @see java.awt.Stroke#createStrokedShape(java.awt.Shape)
|
||||
*/
|
||||
public Shape createStrokedShape (Shape shape) {
|
||||
GeneralPath result = new GeneralPath();
|
||||
PathIterator it = new FlatteningPathIterator(shape.getPathIterator(null), FLATNESS);
|
||||
float points[] = new float[6];
|
||||
float moveX = 0, moveY = 0;
|
||||
float lastX = 0, lastY = 0;
|
||||
float thisX = 0, thisY = 0;
|
||||
int type = 0;
|
||||
float next = 0;
|
||||
int phase = 0;
|
||||
while (!it.isDone()) {
|
||||
type = it.currentSegment(points);
|
||||
switch (type) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
moveX = lastX = points[0];
|
||||
moveY = lastY = points[1];
|
||||
result.moveTo(moveX, moveY);
|
||||
next = wavelength / 2;
|
||||
break;
|
||||
|
||||
case PathIterator.SEG_CLOSE:
|
||||
points[0] = moveX;
|
||||
points[1] = moveY;
|
||||
// Fall into....
|
||||
|
||||
case PathIterator.SEG_LINETO:
|
||||
thisX = points[0];
|
||||
thisY = points[1];
|
||||
float dx = thisX - lastX;
|
||||
float dy = thisY - lastY;
|
||||
float distance = (float)Math.sqrt(dx * dx + dy * dy);
|
||||
if (distance >= next) {
|
||||
float r = 1.0f / distance;
|
||||
while (distance >= next) {
|
||||
float x = lastX + next * dx * r;
|
||||
float y = lastY + next * dy * r;
|
||||
if ((phase & 1) == 0)
|
||||
result.lineTo(x + amplitude * dy * r, y - amplitude * dx * r);
|
||||
else
|
||||
result.lineTo(x - amplitude * dy * r, y + amplitude * dx * r);
|
||||
next += wavelength;
|
||||
phase++;
|
||||
}
|
||||
}
|
||||
next -= distance;
|
||||
lastX = thisX;
|
||||
lastY = thisY;
|
||||
if (type == PathIterator.SEG_CLOSE) result.closePath();
|
||||
break;
|
||||
}
|
||||
it.next();
|
||||
}
|
||||
return new BasicStroke(getWidth(), BasicStroke.CAP_SQUARE, getJoin()).createStrokedShape(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
|
||||
package org.newdawn.slick.font.effects;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Color;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ConvolveOp;
|
||||
import java.awt.image.Kernel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.newdawn.slick.UnicodeFont;
|
||||
import org.newdawn.slick.font.Glyph;
|
||||
|
||||
/**
|
||||
* An effect to generate soft shadows beneath text
|
||||
*
|
||||
* @author Nathan Sweet <misc@n4te.com>
|
||||
*/
|
||||
public class ShadowEffect implements ConfigurableEffect {
|
||||
/** The number of kernels to apply */
|
||||
public static final int NUM_KERNELS = 16;
|
||||
/** The blur kernels applied across the effect */
|
||||
public static final float[][] GAUSSIAN_BLUR_KERNELS = generateGaussianBlurKernels(NUM_KERNELS);
|
||||
|
||||
/** The colour of the shadow to render */
|
||||
private Color color = Color.black;
|
||||
/** The transparency factor of the shadow */
|
||||
private float opacity = 0.6f;
|
||||
/** The distance on the x axis of the shadow from the text */
|
||||
private float xDistance = 2;
|
||||
/** The distance on the y axis of the shadow from the text */
|
||||
private float yDistance = 2;
|
||||
/** The size of the kernel used to blur the shadow */
|
||||
private int blurKernelSize = 0;
|
||||
/** The number of passes applied to create the blur */
|
||||
private int blurPasses = 1;
|
||||
|
||||
/**
|
||||
* Default constructor for injection
|
||||
*/
|
||||
public ShadowEffect() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new effect to apply a drop shadow to text
|
||||
*
|
||||
* @param color The colour of the shadow to generate
|
||||
* @param xDistance The distance from the text on the x axis the shadow should be rendered
|
||||
* @param yDistance The distance from the text on the y axis the shadow should be rendered
|
||||
* @param opacity The transparency factor of the shadow
|
||||
*/
|
||||
public ShadowEffect (Color color, int xDistance, int yDistance, float opacity) {
|
||||
this.color = color;
|
||||
this.xDistance = xDistance;
|
||||
this.yDistance = yDistance;
|
||||
this.opacity = opacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.Effect#draw(java.awt.image.BufferedImage, java.awt.Graphics2D, org.newdawn.slick.UnicodeFont, org.newdawn.slick.font.Glyph)
|
||||
*/
|
||||
public void draw(BufferedImage image, Graphics2D g, UnicodeFont unicodeFont, Glyph glyph) {
|
||||
g = (Graphics2D)g.create();
|
||||
g.translate(xDistance, yDistance);
|
||||
g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), Math.round(opacity * 255)));
|
||||
g.fill(glyph.getShape());
|
||||
|
||||
// Also shadow the outline, if one exists.
|
||||
for (Iterator iter = unicodeFont.getEffects().iterator(); iter.hasNext();) {
|
||||
Effect effect = (Effect)iter.next();
|
||||
if (effect instanceof OutlineEffect) {
|
||||
Composite composite = g.getComposite();
|
||||
g.setComposite(AlphaComposite.Src); // Prevent shadow and outline shadow alpha from combining.
|
||||
|
||||
g.setStroke(((OutlineEffect)effect).getStroke());
|
||||
g.draw(glyph.getShape());
|
||||
|
||||
g.setComposite(composite);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g.dispose();
|
||||
if (blurKernelSize > 1 && blurKernelSize < NUM_KERNELS && blurPasses > 0) blur(image);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply blurring to the generate image
|
||||
*
|
||||
* @param image The image to be blurred
|
||||
*/
|
||||
private void blur(BufferedImage image) {
|
||||
float[] matrix = GAUSSIAN_BLUR_KERNELS[blurKernelSize - 1];
|
||||
Kernel gaussianBlur1 = new Kernel(matrix.length, 1, matrix);
|
||||
Kernel gaussianBlur2 = new Kernel(1, matrix.length, matrix);
|
||||
RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
|
||||
ConvolveOp gaussianOp1 = new ConvolveOp(gaussianBlur1, ConvolveOp.EDGE_NO_OP, hints);
|
||||
ConvolveOp gaussianOp2 = new ConvolveOp(gaussianBlur2, ConvolveOp.EDGE_NO_OP, hints);
|
||||
BufferedImage scratchImage = EffectUtil.getScratchImage();
|
||||
for (int i = 0; i < blurPasses; i++) {
|
||||
gaussianOp1.filter(image, scratchImage);
|
||||
gaussianOp2.filter(scratchImage, image);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the colour of the shadow generated
|
||||
*
|
||||
* @return The colour of the shadow generated
|
||||
*/
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the colour of the shadow to be generated
|
||||
*
|
||||
* @param color The colour ofthe shadow to be generated
|
||||
*/
|
||||
public void setColor(Color color) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance on the X axis from the text the shadow should
|
||||
* be generated at
|
||||
*
|
||||
* @return The distance on the X axis the shadow will be from the text
|
||||
*/
|
||||
public float getXDistance() {
|
||||
return xDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pixels to offset the shadow on the x axis. The glyphs will need padding so the
|
||||
* shadow doesn't get clipped.
|
||||
*
|
||||
* @param distance The offset on the x axis
|
||||
*/
|
||||
public void setXDistance(float distance) {
|
||||
xDistance = distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the distance on the Y axis from the text the shadow should
|
||||
* be generated at
|
||||
*
|
||||
* @return The distance on the Y axis the shadow will be from the text
|
||||
*/
|
||||
public float getYDistance() {
|
||||
return yDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the pixels to offset the shadow on the y axis. The glyphs will need
|
||||
* padding so the shadow doesn't get clipped.
|
||||
*
|
||||
* @param distance The offset on the y axis
|
||||
*/
|
||||
public void setYDistance (float distance) {
|
||||
yDistance = distance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the size of the kernel used to apply the blur
|
||||
*
|
||||
* @return The blur kernel size
|
||||
*/
|
||||
public int getBlurKernelSize() {
|
||||
return blurKernelSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets how many neighboring pixels are used to blur the shadow. Set to 0 for no blur.
|
||||
*
|
||||
* @param blurKernelSize The size of the kernel to apply the blur with
|
||||
*/
|
||||
public void setBlurKernelSize (int blurKernelSize) {
|
||||
this.blurKernelSize = blurKernelSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of passes to apply the kernel for blurring
|
||||
*
|
||||
* @return The number of passes
|
||||
*/
|
||||
public int getBlurPasses() {
|
||||
return blurPasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of times to apply a blur to the shadow. Set to 0 for no blur.
|
||||
*
|
||||
* @param blurPasses The number of passes to apply when blurring
|
||||
*/
|
||||
public void setBlurPasses (int blurPasses) {
|
||||
this.blurPasses = blurPasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the opacity of the shadow, i.e. how transparent it is
|
||||
*
|
||||
* @return The opacity of the shadow
|
||||
*/
|
||||
public float getOpacity() {
|
||||
return opacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the opacity of the shadow, i.e. how transparent it is
|
||||
*
|
||||
* @param opacity The opacity of the shadow
|
||||
*/
|
||||
public void setOpacity(float opacity) {
|
||||
this.opacity = opacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
public String toString() {
|
||||
return "Shadow";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect#getValues()
|
||||
*/
|
||||
public List getValues() {
|
||||
List values = new ArrayList();
|
||||
values.add(EffectUtil.colorValue("Color", color));
|
||||
values.add(EffectUtil.floatValue("Opacity", opacity, 0, 1, "This setting sets the translucency of the shadow."));
|
||||
values.add(EffectUtil.floatValue("X distance", xDistance, Float.MIN_VALUE, Float.MAX_VALUE, "This setting is the amount of pixels to offset the shadow on the"
|
||||
+ " x axis. The glyphs will need padding so the shadow doesn't get clipped."));
|
||||
values.add(EffectUtil.floatValue("Y distance", yDistance, Float.MIN_VALUE, Float.MAX_VALUE, "This setting is the amount of pixels to offset the shadow on the"
|
||||
+ " y axis. The glyphs will need padding so the shadow doesn't get clipped."));
|
||||
|
||||
List options = new ArrayList();
|
||||
options.add(new String[] {"None", "0"});
|
||||
for (int i = 2; i < NUM_KERNELS; i++)
|
||||
options.add(new String[] {String.valueOf(i)});
|
||||
String[][] optionsArray = (String[][])options.toArray(new String[options.size()][]);
|
||||
values.add(EffectUtil.optionValue("Blur kernel size", String.valueOf(blurKernelSize), optionsArray,
|
||||
"This setting controls how many neighboring pixels are used to blur the shadow. Set to \"None\" for no blur."));
|
||||
|
||||
values.add(EffectUtil.intValue("Blur passes", blurPasses,
|
||||
"The setting is the number of times to apply a blur to the shadow. Set to \"0\" for no blur."));
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.newdawn.slick.font.effects.ConfigurableEffect#setValues(java.util.List)
|
||||
*/
|
||||
public void setValues(List values) {
|
||||
for (Iterator iter = values.iterator(); iter.hasNext();) {
|
||||
Value value = (Value)iter.next();
|
||||
if (value.getName().equals("Color")) {
|
||||
color = (Color)value.getObject();
|
||||
} else if (value.getName().equals("Opacity")) {
|
||||
opacity = ((Float)value.getObject()).floatValue();
|
||||
} else if (value.getName().equals("X distance")) {
|
||||
xDistance = ((Float)value.getObject()).floatValue();
|
||||
} else if (value.getName().equals("Y distance")) {
|
||||
yDistance = ((Float)value.getObject()).floatValue();
|
||||
} else if (value.getName().equals("Blur kernel size")) {
|
||||
blurKernelSize = Integer.parseInt((String)value.getObject());
|
||||
} else if (value.getName().equals("Blur passes")) {
|
||||
blurPasses = ((Integer)value.getObject()).intValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the blur kernels which will be repeatedly applied when blurring images
|
||||
*
|
||||
* @param level The number of kernels to generate
|
||||
* @return The kernels generated
|
||||
*/
|
||||
private static float[][] generateGaussianBlurKernels(int level) {
|
||||
float[][] pascalsTriangle = generatePascalsTriangle(level);
|
||||
float[][] gaussianTriangle = new float[pascalsTriangle.length][];
|
||||
for (int i = 0; i < gaussianTriangle.length; i++) {
|
||||
float total = 0.0f;
|
||||
gaussianTriangle[i] = new float[pascalsTriangle[i].length];
|
||||
for (int j = 0; j < pascalsTriangle[i].length; j++)
|
||||
total += pascalsTriangle[i][j];
|
||||
float coefficient = 1 / total;
|
||||
for (int j = 0; j < pascalsTriangle[i].length; j++)
|
||||
gaussianTriangle[i][j] = coefficient * pascalsTriangle[i][j];
|
||||
}
|
||||
return gaussianTriangle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate Pascal's triangle
|
||||
*
|
||||
* @param level The level of the triangle to generate
|
||||
* @return The Pascal's triangle kernel
|
||||
*/
|
||||
private static float[][] generatePascalsTriangle(int level) {
|
||||
if (level < 2) level = 2;
|
||||
float[][] triangle = new float[level][];
|
||||
triangle[0] = new float[1];
|
||||
triangle[1] = new float[2];
|
||||
triangle[0][0] = 1.0f;
|
||||
triangle[1][0] = 1.0f;
|
||||
triangle[1][1] = 1.0f;
|
||||
for (int i = 2; i < level; i++) {
|
||||
triangle[i] = new float[i + 1];
|
||||
triangle[i][0] = 1.0f;
|
||||
triangle[i][i] = 1.0f;
|
||||
for (int j = 1; j < triangle[i].length - 1; j++)
|
||||
triangle[i][j] = triangle[i - 1][j - 1] + triangle[i - 1][j];
|
||||
}
|
||||
return triangle;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user