package greenfoot.util;

import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsConfiguration;
import java.awt.Shape;
import java.awt.Transparency;
import java.awt.Graphics;
import java.awt.GraphicsEnvironment;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;


| <p><code>GraphicsUtilities</code> contains a set of tools to perform | common graphics operations easily. These operations are divided into | several themes, listed below.</p> | <h2>Compatible Images</h2> | <p>Compatible images can, and should, be used to increase drawing | performance. This class provides a number of methods to load compatible | images directly from files or to convert existing images to compatibles | images.</p> | <h2>Creating Thumbnails</h2> | <p>This class provides a number of methods to easily scale down images. | Some of these methods offer a trade-off between speed and result quality and | shouuld be used all the time. They also offer the advantage of producing | compatible images, thus automatically resulting into better runtime | performance.</p> | <p>All these methodes are both faster than | {}link java.awt.Image#getScaledInstance(int, int, int)} and produce | better-looking results than the various <code>drawImage()</code> methods | in {}link java.awt.Graphics}, which can be used for image scaling.</p> | <h2>Image Manipulation</h2> | <p>This class provides two methods to get and set pixels in a buffered image. | These methods try to avoid unmanaging the image in order to keep good | performance.</p> | | @author Romain Guy <romain.guy@mac.com> | public class GraphicsUtilities { private GraphicsUtilities() { } private static GraphicsConfiguration getGraphicsConfiguration() { return GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().getDefaultConfiguration(); }
| <p>Returns a new <code>BufferedImage</code> using the same color model | as the image passed as a parameter. The returned image is only compatible | with the image passed as a parameter. This does not mean the returned | image is compatible with the hardware.</p> | | @param image the reference image from which the color model of the new | image is obtained | @return a new <code>BufferedImage</code>, compatible with the color model | of <code>image</code> | public static BufferedImage createColorModelCompatibleImage(BufferedImage image) { ColorModel cm = image.getColorModel(); return new BufferedImage(cm, cm.createCompatibleWritableRaster(image.getWidth(), image.getHeight()), cm.isAlphaPremultiplied(), null); }
| <p>Returns a new compatible image with the same width, height and | transparency as the image specified as a parameter.</p> | | @see java.awt.Transparency | @see #createCompatibleImage(int, int) | @see #createCompatibleImage(java.awt.image.BufferedImage, int, int) | @see #createCompatibleTranslucentImage(int, int) | @see #loadCompatibleImage(java.net.URL) | @see #toCompatibleImage(java.awt.image.BufferedImage) | @param image the reference image from which the dimension and the | transparency of the new image are obtained | @return a new compatible <code>BufferedImage</code> with the same | dimension and transparency as <code>image</code> | public static BufferedImage createCompatibleImage(BufferedImage image) { return createCompatibleImage(image, image.getWidth(), image.getHeight()); }
| <p>Returns a new compatible image of the specified width and height, and | the same transparency setting as the image specified as a parameter.</p> | | @see java.awt.Transparency | @see #createCompatibleImage(java.awt.image.BufferedImage) | @see #createCompatibleImage(int, int) | @see #createCompatibleTranslucentImage(int, int) | @see #loadCompatibleImage(java.net.URL) | @see #toCompatibleImage(java.awt.image.BufferedImage) | @param width the width of the new image | @param height the height of the new image | @param image the reference image from which the transparency of the new | image is obtained | @return a new compatible <code>BufferedImage</code> with the same | transparency as <code>image</code> and the specified dimension | public static BufferedImage createCompatibleImage(BufferedImage image, int width, int height) { return getGraphicsConfiguration().createCompatibleImage(width, height, image.getTransparency()); }
| <p>Returns a new opaque compatible image of the specified width and | height.</p> | | @see #createCompatibleImage(java.awt.image.BufferedImage) | @see #createCompatibleImage(java.awt.image.BufferedImage, int, int) | @see #createCompatibleTranslucentImage(int, int) | @see #loadCompatibleImage(java.net.URL) | @see #toCompatibleImage(java.awt.image.BufferedImage) | @param width the width of the new image | @param height the height of the new image | @return a new opaque compatible <code>BufferedImage</code> of the | specified width and height | public static BufferedImage createCompatibleImage(int width, int height) { return getGraphicsConfiguration().createCompatibleImage(width, height); }
| <p>Returns a new translucent compatible image of the specified width | and height.</p> | | @see #createCompatibleImage(java.awt.image.BufferedImage) | @see #createCompatibleImage(java.awt.image.BufferedImage, int, int) | @see #createCompatibleImage(int, int) | @see #loadCompatibleImage(java.net.URL) | @see #toCompatibleImage(java.awt.image.BufferedImage) | @param width the width of the new image | @param height the height of the new image | @return a new translucent compatible <code>BufferedImage</code> of the | specified width and height | public static BufferedImage createCompatibleTranslucentImage(int width, int height) { return getGraphicsConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT); }
| <p>Returns a new compatible image from a URL. The image is loaded from the | specified location and then turned, if necessary into a compatible | image.</p> | | @see #createCompatibleImage(java.awt.image.BufferedImage) | @see #createCompatibleImage(java.awt.image.BufferedImage, int, int) | @see #createCompatibleImage(int, int) | @see #createCompatibleTranslucentImage(int, int) | @see #toCompatibleImage(java.awt.image.BufferedImage) | @param resource the URL of the picture to load as a compatible image | @return a new translucent compatible <code>BufferedImage</code> of the | specified width and height | @throws java.io.IOException if the image cannot be read or loaded | public static BufferedImage loadCompatibleImage(URL resource) throws IOException { BufferedImage image = ImageIO.read(resource); if (image == null) { throw new IOException("Image format of resource not supported. Resource: " + resource); } return toCompatibleImage(image); }
| <p>Returns a new compatible image from a URL. The image is loaded from the | specified location and then turned, if necessary into a translucent compatible | image.</p> | | @see #createCompatibleImage(java.awt.image.BufferedImage) | @see #createCompatibleImage(java.awt.image.BufferedImage, int, int) | @see #createCompatibleImage(int, int) | @see #createCompatibleTranslucentImage(int, int) | @see #toCompatibleImage(java.awt.image.BufferedImage) | @param resource the URL of the picture to load as a compatible image | @return a new translucent compatible <code>BufferedImage</code> of the | specified width and height | @throws java.io.IOException if the image cannot be read or loaded | public static BufferedImage loadCompatibleTranslucentImage(URL resource) throws IOException { BufferedImage image = ImageIO.read(resource); if (image == null) { throw new IOException("Image format of resource not supported. Resource: " + resource); } return toCompatibleTranslucentImage(image); } public static BufferedImage loadCompatibleTranslucentImage(byte[] imageData) throws IOException { BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageData)); if (image == null) { throw new IOException("Image format of byte data not supported"); } return toCompatibleTranslucentImage(image); }
| <p>Return a new compatible image that contains a copy of the specified | image. This method ensures an image is compatible with the hardware, | and therefore optimized for fast blitting operations.</p> | | @see #createCompatibleImage(java.awt.image.BufferedImage) | @see #createCompatibleImage(java.awt.image.BufferedImage, int, int) | @see #createCompatibleImage(int, int) | @see #createCompatibleTranslucentImage(int, int) | @see #loadCompatibleImage(java.net.URL) | @param image the image to copy into a new compatible image | @return a new compatible copy, with the | same width and height and transparency and content, of <code>image</code> | public static BufferedImage toCompatibleImage(BufferedImage image) { if (image.getColorModel().equals( getGraphicsConfiguration().getColorModel())) { return image; } BufferedImage compatibleImage = getGraphicsConfiguration().createCompatibleImage( image.getWidth(), image.getHeight(), image.getTransparency()); Graphics g = compatibleImage.getGraphics(); g.drawImage(image, 0, 0, null); g.dispose(); return compatibleImage; }
| | Return a new compatible image that contains a copy of the specified | image. This method ensures an image is compatible with the hardware, and | therefore optimized for fast blitting operations. It also ensures that | the image is translucent. | </p> | | @see #createCompatibleImage(java.awt.image.BufferedImage) | @see #createCompatibleImage(java.awt.image.BufferedImage, int, int) | @see #createCompatibleImage(int, int) | @see #createCompatibleTranslucentImage(int, int) | @see #loadCompatibleImage(java.net.URL) | @param image the image to copy into a new compatible image | @return a new compatible copy, with the same width and height and | transparency and content, of <code>image</code> | public static BufferedImage toCompatibleTranslucentImage(BufferedImage image) { if (image.getColorModel().equals(getGraphicsConfiguration().getColorModel()) && image.getColorModel().hasAlpha()) { return image; } BufferedImage compatibleImage = getGraphicsConfiguration().createCompatibleImage( image.getWidth(), image.getHeight(), Transparency.TRANSLUCENT); Graphics g = compatibleImage.getGraphics(); g.drawImage(image, 0, 0, null); g.dispose(); return compatibleImage; }
| Given the dimensions of a series of lines of text, draws those shapes using the given colours. | @param g The Graphics context to use for drawing. | @param d The dimensions of the lines to be drawn (from getMultiLineStringDimensions) | @param foreground The colour to draw the foreground in. BLACK is used if null | @param outline The colour to draw the outline in. Not drawn if null | public static void drawOutlinedText(Graphics2D g, MultiLineStringDimensions d, Color foreground, Color outline) { if (foreground == null) foreground = Color.BLACK; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); for (int i = 0; i < d.lineShapes.length;i++) { g.setColor(foreground); g.fill(d.lineShapes[i]); if (outline != null) { g.setColor(outline); g.draw(d.lineShapes[i]); } } }
| Sets the font on the given graphics context to have the given style and target size | @param g | @param style The font style (e.g. Font.PLAIN) | @param targetSize The target height of the line | private static void setFontOfPixelHeight(Graphics2D g, int style, double targetSize) { Font font = new Font("SansSerif", style, 1); for (int i = 1; i < targetSize; i++) { Font bigger = font.deriveFont((float)i); g.setFont(bigger); if (bigger.getLineMetrics("WBLMNqpyg", g.getFontRenderContext()).getHeight() < targetSize) font = bigger; } else { break; } } g.setFont(font); } public static String[] splitLines(String string) { return string.replaceAll("\r", "").split("\n"); }
| Given a list of lines, gets the dimensions/outlines of the lines when drawn in the given style, | one above the other, horizontally centred. The shapes will be drawn relative to the | top-left of the image. | | @param lines The text lines to draw. Should be the output of splitLines | @param style The style (e.g. Font.PLAIN) | @param size The height in pixels of each line of text | @return The dimensions of the lines | public static MultiLineStringDimensions getMultiLineStringDimensions(String[] lines, int style, double size) { BufferedImage image = createCompatibleTranslucentImage(1, 1); MultiLineStringDimensions r = new MultiLineStringDimensions(lines.length); Graphics2D g = (Graphics2D)image.getGraphics(); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); setFontOfPixelHeight(g, style, size); FontRenderContext frc = g.getFontRenderContext(); Rectangle2D[] lineBounds = new Rectangle2D[lines.length]; int maxX = 1; int y = 0; for (int i = 0; i < lines.length;i++) { lineBounds[i] = g.getFontMetrics().getStringBounds(lines[i], g); maxX = Math.max(maxX, (int)Math.ceil(lineBounds[i].getWidth())); y += Math.ceil(lineBounds[i].getHeight()); } y = Math.max(y + 1, 1); r.overallBounds = new Dimension(maxX, y); y = 0; for (int i = 0; i < lines.length;i++) { AffineTransform translate = AffineTransform.getTranslateInstance((r.overallBounds.getWidth() - lineBounds[i].getWidth()) / 2, y - lineBounds[i].getMinY() | add on to baseline | ; r.lineShapes[i] = new TextLayout(!lines[i].isEmpty()? lines[i] : " ", g.getFont(), frc).getOutline(translate); y += Math.ceil(lineBounds[i].getHeight()); } g.dispose(); return r; } public static class MultiLineStringDimensions { private Shape[] lineShapes; private Dimension overallBounds; public MultiLineStringDimensions(int length) { lineShapes = new Shape[length]; } public int getWidth() { return overallBounds.width; } public int getHeight() { return overallBounds.height; } } }
top, use, map, class GraphicsUtilities

.   GraphicsUtilities
.   getGraphicsConfiguration
.   createColorModelCompatibleImage
.   createCompatibleImage
.   createCompatibleImage
.   createCompatibleImage
.   createCompatibleTranslucentImage
.   loadCompatibleImage
.   loadCompatibleTranslucentImage
.   loadCompatibleTranslucentImage
.   toCompatibleImage
.   toCompatibleTranslucentImage
.   drawOutlinedText
.   setFontOfPixelHeight
.   splitLines
.   getMultiLineStringDimensions

top, use, map, class MultiLineStringDimensions

.   MultiLineStringDimensions
.   getWidth
.   getHeight




326 neLoCode + 145 LoComm