Renders a Label and returns it as a BufferedImage. - Java 2D Graphics

Java examples for 2D Graphics:BufferedImage

Description

Renders a Label and returns it as a BufferedImage.

Demo Code

/**/* w  w  w.  j  ava2  s. c  o  m*/
 * This file is part of VoteBox.
 * 
 * VoteBox is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as published by
 * the Free Software Foundation.
 * 
 * You should have received a copy of the GNU General Public License
 * along with VoteBox, found in the root of any distribution or
 * repository containing all or part of VoteBox.
 * 
 * THIS SOFTWARE IS PROVIDED BY WILLIAM MARSH RICE UNIVERSITY, HOUSTON,
 * TX AND IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESS, IMPLIED OR
 * STATUTORY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
 * ACCURACY, COMPLETENESS, AND NONINFRINGEMENT.  THE SOFTWARE USER SHALL
 * INDEMNIFY, DEFEND AND HOLD HARMLESS RICE UNIVERSITY AND ITS FACULTY,
 * STAFF AND STUDENTS FROM ANY AND ALL CLAIMS, ACTIONS, DAMAGES, LOSSES,
 * LIABILITIES, COSTS AND EXPENSES, INCLUDING ATTORNEYS' FEES AND COURT
 * COSTS, DIRECTLY OR INDIRECTLY ARISING OUR OF OR IN CONNECTION WITH
 * ACCESS OR USE OF THE SOFTWARE.
 */
//package com.java2s;
import java.awt.BasicStroke;
import java.awt.Color;

import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

public class Main {
    /**
     * The standard font to use
     */
    public static final String FONT_NAME = "Lucida Sans";

    /**
     * Renders a Label and returns it as a BufferedImage.
     * @param title is the text to be outputted
     * @param instructions are any instructions to be italized, such as '(please
     *            select one)'
     * @param description are any descriptions (such as those used on
     *            propositions)
     * @param fontsize the size of the font
     * @param wrappingWidth is the width at which the label should wrap
     * @param bold whether the label is bold
     * @param color is the color of the text
     * @param boxed is a boolean flag to determine whether or a box should be
     *            placed around the label
     * @param titleCentered is a boolean flag as to whether or not the text
     *            should be centered
     * @return the rendered Label
     */
    public static BufferedImage renderLabel(String title,
            String instructions, String description, int fontsize,
            int wrappingWidth, Color color, boolean bold, boolean boxed,
            boolean titleCentered) {

        Font font = new Font(FONT_NAME, (bold) ? Font.BOLD : Font.PLAIN,
                fontsize);

        Font italicFont = new Font(FONT_NAME, Font.ITALIC, fontsize);
        Font bigBoldFont = new Font(FONT_NAME, Font.BOLD, fontsize + 4);

        BufferedImage wrappedImage = new BufferedImage(1000, 1000,
                BufferedImage.TYPE_INT_ARGB);

        Graphics2D graphs = wrappedImage.createGraphics();
        graphs.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
        graphs.setFont(font);
        graphs.setColor(color);

        int baseline = graphs.getFontMetrics().getAscent();

        String[] titleWords = title.split(" ");
        int padding = 10;
        int heightPos = padding + baseline;
        int writePos = padding;

        int lineWidth = padding;

        int maxWidth = 0; // the max width of any line
        if (titleCentered) {

            graphs.setFont(bigBoldFont);
            String[][] splitText = spliteOnNewLineAndSpace(title);
            for (int y = 0; y < splitText.length; y++) {
                String[] line = splitText[y];
                int margin = (wrappingWidth - 2 * padding - lineWidth(line,
                        bigBoldFont)) / 2;
                graphs.drawString(stringArrayToString(line), writePos
                        + margin, heightPos);
                heightPos += lineHeight("line", bigBoldFont);
            }

        } else {
            for (String word : titleWords) // For each word try placing it on
            // the line,
            // if not jump down a line and then write it
            {
                Rectangle2D measurement = font.getStringBounds(word + " ",
                        new FontRenderContext(new AffineTransform(), true,
                                true));
                int wordWidth = (int) measurement.getWidth();
                int wordHeight = (int) measurement.getHeight();
                writePos = lineWidth;
                lineWidth += wordWidth;

                // TODO: this code does do what the comment above says it does! 
                // It doesn't jump down a line on it's own! add this!

                // if the width of our word is longer than the entire line space,
                // break it up.
                if (wordWidth > wrappedImage.getWidth()) {
                    String remainingStr = word;
                    while (remainingStr.length() > wrappedImage.getWidth()) {
                        graphs.drawString(
                                remainingStr.substring(0,
                                        wrappedImage.getWidth()), writePos,
                                heightPos);
                        remainingStr = remainingStr.substring(wrappedImage
                                .getWidth());
                        // we've just written one whole line. put our position variables back
                        // at the beginning
                        heightPos += wordHeight;
                        writePos = padding;
                        lineWidth = padding;
                    }

                } else if (word.equals("\n") || word.equals("<newline>")) {
                    maxWidth = Math.max(lineWidth, maxWidth);
                    heightPos += wordHeight;
                    writePos = padding;
                    lineWidth = padding;
                }
                graphs.drawString(word + " ", writePos, heightPos);
            }

        }

        if (!instructions.equals("")) // write instructions on how to use
        {
            // heightPos+= lineHeight(instructions.split(" "), italicFont);
            String[][] splitText = spliteOnNewLineAndSpace(instructions);

            for (int y = 0; y < splitText.length; y++) {
                String[] line = splitText[y];
                int margin = (wrappingWidth - 2 * padding - lineWidth(line,
                        italicFont)) / 2;
                graphs.setFont(italicFont);
                graphs.drawString(stringArrayToString(line), writePos
                        + margin, heightPos);
                heightPos += lineHeight("line", italicFont);
            }
        }

        if (!description.equals("")) // write description on how to use
        {
            heightPos += lineHeight("text", font);
            description = addInNewLines(description, font, wrappingWidth,
                    padding);
            String[][] splitText = spliteOnNewLineAndSpace(description);
            graphs.setFont(font);

            for (int y = 0; y < splitText.length; y++) {
                String[] line = splitText[y];
                graphs.drawString(stringArrayToString(line), writePos,
                        heightPos);
                heightPos += lineHeight("line", font);
            }
        }

        maxWidth = Math.max(lineWidth, maxWidth);
        if (wrappingWidth != 0) // then wrap at the wrappingWidth or maxWidth
            maxWidth = Math.max(maxWidth, wrappingWidth);

        if (boxed) {
            graphs.setColor(Color.BLACK);
            graphs.setStroke(new BasicStroke(padding / 2));
            graphs.drawRect(0, 0, maxWidth - 1, heightPos + padding - 1);
        }

        if (maxWidth < wrappedImage.getWidth()) {
            wrappedImage = wrappedImage.getSubimage(0, 0, maxWidth,
                    heightPos + padding);
        } else {
            wrappedImage = wrappedImage.getSubimage(0, 0,
                    wrappedImage.getWidth(), heightPos);
        }
        return copy(wrappedImage);

    }

    /**
     * Splits text on new line and then on white space
     * @param text the text to be split
     * @return the split text
     */
    private static String[][] spliteOnNewLineAndSpace(String text) {

        String[] splitOnNewLine = text.split("<newline>");
        String[][] splitText = new String[splitOnNewLine.length][0];
        for (int x = 0; x < splitOnNewLine.length; x++) {
            splitText[x] = splitOnNewLine[x].split(" ");
        }
        return splitText;
    }

    /**
     * Calculates the line width at a given font
     * @param line is the line
     * @param font is the font
     * @return the width
     */
    private static int lineWidth(String[] line, Font font) {
        int width = 0;
        for (String word : line) {
            Rectangle2D measurement = font
                    .getStringBounds(word + " ", new FontRenderContext(
                            new AffineTransform(), true, true));
            width += measurement.getWidth();
        }

        return width;
    }

    /**
     * Transforms an array of Strings to one string w/ appropriate spacing added
     * in between. Also trims the string to remove useless white sapce
     * @param array the array to be transformed
     * @return the array as a string
     */
    private static String stringArrayToString(String[] array) {
        String currentString = new String(" ");
        for (int x = 0; x < array.length; x++) {
            currentString = currentString.concat(array[x] + " ");
        }
        return currentString.trim();

    }

    /**
     * Calculates the line height at a given font, by looking at the height of
     * the first word
     * @param line is the line
     * @param font is the font
     * @return the height
     */
    private static int lineHeight(String line, Font font) {
        Rectangle2D measurement = font.getStringBounds(line + " ",
                new FontRenderContext(new AffineTransform(), true, true));
        return (int) measurement.getHeight();

    }

    /**
     * A private helper to add in tags of where new lines should be added when a
     * text is rendered with at given font with a set wrappingWidth and padding
     * @param text the text to be redered
     * @param font the font to reder with
     * @param wrappingWidth the width at which to wrap
     * @param padding the padding that should be on the text
     * @return the text with appropriate <newline> tags added in
     */
    private static String addInNewLines(String text, Font font,
            int wrappingWidth, int padding) {
        String copy = new String("");
        String[] splitText = text.split(" ");
        int currentLineWidth = padding;
        for (String word : splitText) {
            Rectangle2D measurement = font
                    .getStringBounds(word + " ", new FontRenderContext(
                            new AffineTransform(), true, true));
            currentLineWidth += measurement.getWidth();

            if (currentLineWidth + padding > wrappingWidth) {
                currentLineWidth = (int) measurement.getWidth() + padding;
                copy = copy.concat(" <newline>");
            }
            copy = copy.concat(word + " ");
        }
        return copy;
    }

    /**
     * Copies a buffered Image. Borrowed 100% from
     * http://cui.unige.ch/~deriazm/javasources/ImgTools.java I really can't
     * think of a better way of writing this code - so i just used theirs
     */
    public static BufferedImage copy(BufferedImage bImage) {
        int w = bImage.getWidth(null);
        int h = bImage.getHeight(null);
        BufferedImage bImage2 = new BufferedImage(w, h,
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2 = bImage2.createGraphics();
        g2.drawImage(bImage, 0, 0, null);
        return bImage2;
    }
}

Related Tutorials