Package com.bbn.openmap.omGraphics.awt

Source Code of com.bbn.openmap.omGraphics.awt.TextShapeDecoration

package com.bbn.openmap.omGraphics.awt;

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.LinkedList;

/**
* A ShapeDecoration that draws a text along a path
*
* @author Eric LEPICIER
* @version 16 ao�t 2002
*/
public class TextShapeDecoration extends AbstractShapeDecoration {
    private String text;
    private Font font = null;
    private int verticalAlignment = BASELINE;

    /** Baseline vertical alignment */
    public final static int BASELINE = 1;
    /** Center vertical alignment */
    public final static int CENTER = 2;
    /** Top vertical alignment */
    public final static int TOP = 3;
    /** Bottom vertical alignment */
    public final static int BOTTOM = 4;

    /** Orientation for the shape text decoration: use poly direction */
    public final static int FORWARD = LEFT;
    /**
     * Orientation for the shape text decoration: use reverse poly
     * direction
     */
    public final static int BACKWARD = RIGHT;
    /** Orientation for the shape text decoration: force left to right */
    public final static int LEFT_TO_RIGHT = 3;
    /** Orientation for the shape text decoration: force right to left */
    public final static int RIGHT_TO_LEFT = 4;
    /** Orientation for the shape text decoration: force top to bottom */
    public final static int TOP_TO_BOTTOM = 5;
    /** Orientation for the shape text decoration: force bottom to top */
    public final static int BOTTOM_TO_TOP = 6;
    /**
     * Orientation for the shape text decoration: occidental reading
     * use
     */
    public final static int MOST_READABLE = 7;

    /**
     * Text will follow the poly instead of being written on the
     * segment from begin to end of the poly, also allow text to be
     * uncomplete. You may add this one to the other constants
     */
    public final static int FOLLOW_POLY = 16;

    private transient FontMetrics metrics;
    private transient Graphics2D g2D = null;

    /**
     * Constructor.
     *
     * @param text
     * @param font
     * @param orientation
     * @param verticalAlignment
     */
    public TextShapeDecoration(String text, Font font, int orientation,
            int verticalAlignment) {
        super(0.0f, 0.0f, orientation);
        setVerticalAlignment(verticalAlignment);
        setFont(font);
        setText(text);
        initMetrics();
    }

    /**
     * Constructor.
     *
     * @param text
     */
    public TextShapeDecoration(String text) {
        super(0.0f, 0.0f, FORWARD);
        setVerticalAlignment(BASELINE);
        setText(text);
        initMetrics();
    }

    /**
     * init Metrics used to get string graphic length.
     *
     * @param object
     */
    private void initMetrics() {
        if (g2D == null)
            g2D = (Graphics2D) new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB).getGraphics();
        if (font == null)
            font = g2D.getFont();
        metrics = g2D.getFontMetrics(font);
    }

    /**
     * Draws the text along the polyline
     *
     * @see com.bbn.openmap.omGraphics.awt.ShapeDecoration#draw(Graphics,
     *      Point2D[], boolean)
     */
    public void draw(Graphics g, Point2D[] points, boolean complete) {

        g2D = (Graphics2D) g;
        initMetrics();
        g.setFont(font);

        int x1 = (int) points[0].getX();
        int y1 = (int) points[0].getY();
        int x2 = (int) points[points.length - 1].getX();
        int y2 = (int) points[points.length - 1].getY();

        boolean reverse = needToReverse(x1, y1, x2, y2);

        // draw the text exactly on the curve, even uncomplete
        if ((getOrientation() & FOLLOW_POLY) > 0) {
            drawFollow(g, points, reverse);
            return;
        }

        // if there's not enough room, do nothing
        if (!complete)
            return;

        // else plot the text straight on the half segment
        // from start to end point and away
        int x, y;
        double angle;
        if (reverse) {
            x = x2;
            y = y2;
            angle = Math.atan2(y1 - y2, x1 - x2);
        } else {
            x = x1;
            y = y1;
            angle = Math.atan2(y2 - y1, x2 - x1);
        }

        // adjust vertical alignment
        switch (verticalAlignment) {
        case TOP:
            y += metrics.getAscent();
            break;
        case BOTTOM:
            y -= metrics.getDescent();
            break;
        case CENTER:
            y += metrics.getAscent() - (metrics.getHeight()) / 2;
            break;
        case BASELINE:
            break;
        }

        drawAngledString(g, text, x, y, angle);
    }

    /**
     * Returns true if the polyline need to be reverted for the text
     * to be drawn with the specified orientation.
     *
     * @param x1 starting point x coordinate
     * @param y1 starting point y coordinate
     * @param x2 ending point x coordinate
     * @param y2 ending point y coordinate
     * @return boolean
     */
    protected boolean needToReverse(int x1, int y1, int x2, int y2) {
        boolean reverse = false;
        switch (getOrientation() & ~FOLLOW_POLY) {
        case FORWARD:
            break;
        case BACKWARD:
            reverse = true;
            break;
        case LEFT_TO_RIGHT:
            reverse = x1 > x2;
            break;
        case RIGHT_TO_LEFT:
            reverse = x1 < x2;
            break;
        case TOP_TO_BOTTOM:
            reverse = y1 > y2;
            break;
        case BOTTOM_TO_TOP:
            reverse = y1 < y2;
            break;
        case MOST_READABLE:
            reverse = x2 < x1 || y1 > y2;
            break;
        }
        return reverse;
    }

    /**
     * Draws the text character per character to follow the polyline
     *
     * @param g
     * @param pts
     * @param reverse
     */
    protected void drawFollow(Graphics g, Point2D[] pts, boolean reverse) {
        LinkedList points = new LinkedList();
        if (reverse) {
            for (int i = pts.length - 1; i >= 0; i--)
                points.add(pts[i]);
        } else {
            for (int i = 0; i < pts.length; i++)
                points.add(pts[i]);
        }

        LinkedList polysegment = new LinkedList();
        int l, x1, y1, x2, y2;
        String c;
        Point2D p1, p2;
        double angle;
        for (int i = 0; i < text.length(); i++) {
            c = text.substring(i, i + 1);
            l = metrics.stringWidth(c);
            if (points.size() == 0)
                break;
            LineUtil.retrievePoints(l, points, polysegment);

            p1 = (Point2D) polysegment.getFirst();
            x1 = (int) p1.getX();
            y1 = (int) p1.getY();
            p2 = (Point2D) polysegment.getLast();
            x2 = (int) p2.getX();
            y2 = (int) p2.getY();

            angle = Math.atan2(y2 - y1, x2 - x1);
            drawAngledString(g, c, x1, y1, angle);
        }
    }

    /**
     * Draws the text from a starting point with an angle
     *
     * @param g
     * @param text
     * @param x
     * @param y
     * @param angle
     */
    public static void drawAngledString(Graphics g, String text, int x, int y,
                                        double angle) {

        Graphics2D g2D = (Graphics2D) g;
        AffineTransform oldAt = g2D.getTransform();
        AffineTransform at = new AffineTransform(oldAt);
        at.rotate(angle, x, y);
        g2D.setTransform(at);
        g2D.drawString(text, x, y);
        g2D.setTransform(oldAt);
    }

    /**
     * Returns the font.
     *
     * @return Font
     */
    public Font getFont() {
        return font;
    }

    /**
     * Returns the text.
     *
     * @return String
     */
    public String getText() {
        return text;
    }

    /**
     * Sets the font.
     *
     * @param font The font to set
     */
    public void setFont(Font font) {
        this.font = font;
        initMetrics();
    }

    /**
     * Sets the text.
     *
     * @param text The text to set
     */
    public void setText(String text) {
        this.text = text;
        initMetrics();
        setLength(metrics.stringWidth(text));
        setWidth(metrics.getHeight());
    }

    /**
     * Returns the verticalAlignment.
     *
     * @return int
     */
    public int getVerticalAlignment() {
        return verticalAlignment;
    }

    /**
     * Sets the verticalAlignment.
     *
     * @param verticalAlignment The verticalAlignment to set (TOP,
     *        CENTER, BASELINE, BOTTOM)
     */
    public void setVerticalAlignment(int verticalAlignment) {
        this.verticalAlignment = verticalAlignment;
    }

}
TOP

Related Classes of com.bbn.openmap.omGraphics.awt.TextShapeDecoration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.