/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.image; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.Image; import java.awt.Point; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Stroke; import java.awt.image.IndexColorModel; import java.awt.image.BufferedImage; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import javax.imageio.ImageIO; public class WebImage { ///////////////////////////////////////////////////// // Class static variables protected static final String ARG_CANNOT_BE_NULL = "Argument cannot be null"; private static final String IMAGE_JPEG = "jpeg"; private static final String IMAGE_PNG = "png"; protected static final int DEFAULT_HEIGHT = 300; protected static final int DEFAULT_WIDTH = 755; protected static final Color DEFAULT_BACKGROUND_COLOR = Color.WHITE; protected static final int DEFAULT_BORDER_SIZE = 5; protected static final Color DEFAULT_BORDER_COLOR = Color.LIGHT_GRAY; protected static final Color DEFAULT_TEXT_COLOR = Color.BLACK; protected static final int DEFAULT_SHADOW_WIDTH = 3; protected static final String DEFAULT_BOLD_TYPEFACE = "sansserif.bold"; protected static final String DEFAULT_PLAIN_TYPEFACE = "sansserif.plain"; protected static final Font DEFAULT_FONT = new Font(DEFAULT_PLAIN_TYPEFACE, Font.PLAIN, 11); protected static final FontMetrics DEFAULT_FONT_METRICS; public static final Font SMALL_FONT = new Font(DEFAULT_PLAIN_TYPEFACE, Font.PLAIN, 8); ///////////////////////////////////////////////////// // Object variables private FontMetrics m_fontMetrics; // Set when font is set protected Graphics2D m_graphics; ///////////////////////////////////////////////////// // Public Properties /** * Text font. */ public Font font = DEFAULT_FONT; /** * Height of the image. */ public int height = DEFAULT_HEIGHT; /** * Width of the image. */ public int width = DEFAULT_WIDTH; /** * Width of the image border on the left side of the image */ public int leftBorder = DEFAULT_BORDER_SIZE; /** * Height of the image border on the top side of the image */ public int topBorder = DEFAULT_BORDER_SIZE; /** * Width of the image border on the right side of the image */ public int rightBorder = DEFAULT_BORDER_SIZE; /** * Height of the image border on the bottom side of the image */ public int bottomBorder = DEFAULT_BORDER_SIZE; /** * Draws a two pixel light gray frame at the edge of the image */ public boolean frameImage = false; /** * Background color for the image. */ public Color backgroundColor = DEFAULT_BACKGROUND_COLOR; /** * Color for text in the image. */ public Color textColor = DEFAULT_TEXT_COLOR; /** * Width of the shadow around the image. */ public int shadowWidth = DEFAULT_SHADOW_WIDTH; ///////////////////////////////////////////////////// // Protected Properties /** * Use an IndexColorModel. */ protected boolean antiAliased = true; /** * Anti-alias shapes and text. */ protected boolean indexColors = false; ///////////////////////////////////////////////////// // Static constructor static { // Get Font Metrics Image img = new BufferedImage(1, 1, BufferedImage.TYPE_BYTE_BINARY); java.awt.Graphics g = img.getGraphics(); DEFAULT_FONT_METRICS = g.getFontMetrics(DEFAULT_FONT); g.dispose(); } ///////////////////////////////////////////////////// // Constructors protected WebImage(int width, int height) { this.width = width; this.height = height; m_fontMetrics = DEFAULT_FONT_METRICS; } ///////////////////////////////////////////////////// // Protected Methods protected void draw(Graphics2D g) { g.fillRect(0, 0, this.width + this.shadowWidth, this.height + this.shadowWidth); if(this.frameImage == true) { // Draw the frame Stroke orig = g.getStroke(); g.setStroke( new BasicStroke(2, BasicStroke.CAP_BUTT,BasicStroke.JOIN_MITER) ); g.setColor(DEFAULT_BORDER_COLOR); g.drawRect(0, 0, this.width - 1, this.height - 1); // Draw the shadow if(this.shadowWidth > 0) { int[] x = {this.width + 1, this.width + 1, this.shadowWidth}; int[] y = {this.shadowWidth, this.height + 1, this.height + 1}; g.setColor(Color.BLACK); g.drawPolyline(x, y, x.length); } // Put back the color and stroke we started with g.setColor(Color.WHITE); g.setStroke(orig); } } protected void preInit() {} protected void postInit(Graphics2D graphics) { this.initFontMetrics(); } ///////////////////////////////////////////////////// // Public Methods /** * Sets the size of the top, left, right and bottom borders. * @param border The size to set the borders to. * @see #LeftBorder */ public void setBorder(int border) { this.topBorder = border; this.leftBorder = border; this.rightBorder = border; this.bottomBorder = border; } /** * Retrieves the font metrics. * @return A java.awt.Font object that contains the label font. * @see java.awt.Font */ public FontMetrics getFontMetrics() { return m_fontMetrics; } /** * Retrieves the image as a java.awt.Image object. The image is redrawn with * the latest data and properties each time this method is called. * @return A java.awt.Image that contains the drawn chart image. * @see java.awt.Image */ public Image getImage() { BufferedImage image; Graphics2D g; this.preInit(); image = new BufferedImage(this.width + this.shadowWidth, this.height + this.shadowWidth, BufferedImage.TYPE_INT_RGB); g = m_graphics = (Graphics2D)image.getGraphics(); if(this.antiAliased == true) { g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); } this.postInit(g); g.setColor(this.backgroundColor); this.draw(g); g.dispose(); if(this.indexColors == true) image = ImageUtil.convertToIndexColorImage(image); return image; } /** * Writes the chart image in a JPEG or PNG format. The chart is redrawn * with the latest data and properties each time this method is called. * * @param filename * The path and filename that specifies where the PNG image should be * written. * @param type * The type of image in the format of "image/jpeg" or "image/png". * * @exception FileNotFoundException * If the filename is not a valid name for a file. * @exception IOException * If there is an IO error while writing to the file. * @exception IllegalArgumentException * If the filename parameter is null. */ private void writeImage(String filename, String type) throws FileNotFoundException, IOException { FileOutputStream out = new FileOutputStream(filename); this.writeImage(out, type); out.close(); } /** * Writes the chart image in a JPEG or PNG format. The chart is redrawn * with the latest data and properties each time this method is called. * * @param stream * The java.io.OutputStream to write the PNG image to. * @param type * The type of image in the format of "jpeg" or "png". * * @exception IOException * If there is an IO error while streaming the PNG image. * @exception IllegalArgumentException * If the stream parameter is null. * * @see java.io.OutputStream */ private void writeImage(OutputStream stream, String type) throws IOException { ImageIO.write((BufferedImage)this.getImage(), type, stream); stream.flush(); } /** * Writes the chart image as a JPEG image. The chart is redrawn with the * latest data and properties each time this method is called. * * @param filename * The path and filename that specifies where the PNG image should be * written. * * @exception FileNotFoundException * If the filename is not a valid name for a file. * @exception IOException * If there is an IO error while writing to the file. * @exception IllegalArgumentException * If the filename parameter is null. */ public void writeJpegImage(String filename) throws FileNotFoundException, IOException { if(filename == null) throw new IllegalArgumentException(); this.writeImage(filename, IMAGE_JPEG); } /** * Writes the chart image as a JPEG image. The chart is redrawn with the * latest data and properties each time this method is called. * * @param stream * The java.io.OutputStream to write the PNG image to. * * @exception IOException * If there is an IO error while streaming the PNG image. * @exception IllegalArgumentException * If the stream parameter is null. * * @see java.io.OutputStream */ public void writeJpegImage(OutputStream stream) throws IOException { if(stream == null) throw new IllegalArgumentException(ARG_CANNOT_BE_NULL); this.writeImage(stream, IMAGE_JPEG); } /** * Writes the chart image as a PNG image. The chart is redrawn with the * latest data and properties each time this method is called. * * @param filename * The path and filename that specifies where the PNG image should be * written. * * @exception FileNotFoundException * If the filename is not a valid name for a file. * @exception IOException * If there is an IO error while writing to the file. * @exception IllegalArgumentException * If the filename parameter is null. */ public void writePngImage(String filename) throws FileNotFoundException, IOException { if(filename == null) throw new IllegalArgumentException(ARG_CANNOT_BE_NULL); this.writeImage(filename, IMAGE_PNG); } /** * Writes the chart image as a PNG image. The chart is redrawn with the * latest data and properties each time this method is called. * * @param stream * The java.io.OutputStream to write the PNG image to. * * @exception IOException * If there is an IO error while streaming the PNG image. * @exception IllegalArgumentException * If the stream parameter is null. * * @see java.io.OutputStream */ public void writePngImage(OutputStream stream) throws IOException { if(stream == null) throw new IllegalArgumentException(ARG_CANNOT_BE_NULL); this.writeImage(stream, IMAGE_PNG); } //////////////////////////////////////////////////// // Private Methods private void initFontMetrics() { if(m_graphics != null) this.m_fontMetrics = m_graphics.getFontMetrics(this.font); } //////////////////////////////////////////////////// // Protected Helper Methods protected java.awt.Point getTextCenter(String text) { return this.getTextCenter(text, new Rectangle(0, 0, this.width, this.height)); } protected Point getTextCenter(String text, Rectangle rect) { return WebImage.getTextCenter(text, rect, m_fontMetrics); } //////////////////////////////////////////////////// // Static Methods protected static Point getTextCenter(String text, Rectangle rect, FontMetrics metrics) { return new Point( (rect.width / 2) - (metrics.stringWidth(text) / 2), (rect.height / 2) + (metrics.getAscent() / 2) ); } /** * Determine if a graphics environment is available. The graphics * environment would be X on Unix. GDI on Windows, Mac, etc. This * is primarily used as a check for X because it is very difficult to run * without a graphics environment on the Windows and Mac operating systems. * * @return * A boolean that is true if a graphics environment is available, * false otherwise. */ public static boolean isRunnable() { boolean res; try { GraphicsEnvironment.getLocalGraphicsEnvironment(); res = true; } catch ( InternalError e ) { res = false; } catch ( NoClassDefFoundError e ) { res = false; } return res; } }