All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jcckit.renderer.Graphics2DRenderer Maven / Gradle / Ivy

Go to download

PlantUML is a component that allows to quickly write : * sequence diagram, * use case diagram, * class diagram, * activity diagram, * component diagram, * state diagram * object diagram

The newest version!
/*
 * Copyright 2003-2004, Franz-Josef Elmer, All rights reserved
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * 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 Lesser General Public License for more details
 * (http://www.gnu.org/copyleft/lesser.html).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package jcckit.renderer;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;

import jcckit.graphic.BasicGraphicalElement;
import jcckit.graphic.ClippingRectangle;
import jcckit.graphic.ClippingShape;
import jcckit.graphic.FillAttributes;
import jcckit.graphic.FontStyle;
import jcckit.graphic.GraphPoint;
import jcckit.graphic.GraphicAttributes;
import jcckit.graphic.GraphicalComposite;
import jcckit.graphic.GraphicalCompositeRenderer;
import jcckit.graphic.LineAttributes;
import jcckit.graphic.Oval;
import jcckit.graphic.OvalRenderer;
import jcckit.graphic.Polygon;
import jcckit.graphic.PolygonRenderer;
import jcckit.graphic.Rectangle;
import jcckit.graphic.RectangleRenderer;
import jcckit.graphic.Text;
import jcckit.graphic.TextAttributes;
import jcckit.graphic.TextRenderer;

/**
 * Renderer who draws the {@link jcckit.graphic.GraphicalElement
 * GraphicalElements} into a java.awt.Graphics2D context.
 * 

* The default color for lines and texts is determined by the current color of * the Graphics2D context when a new instance of * Graphics2DRenderer is created. *

* The default font is SansSerif-12. * * @author Franz-Josef Elmer */ public class Graphics2DRenderer implements GraphicalCompositeRenderer, PolygonRenderer, OvalRenderer, TextRenderer, RectangleRenderer { private static final int FS = 1; private static final String DEFAULT_FONT_NAME = "SansSerif"; private static final FontStyle DEFAULT_FONT_STYLE = FontStyle.NORMAL; private static final int DEFAULT_FONT_SIZE = 12; private Color _defaultColor; private Graphics2D _graphics; /** * Initializes this instance. During renderering the current transformation * will be leaved unchanged. But the current Clip may be cleared. * * @param graphics * Graphics2D context into which the * {@link BasicGraphicalElement BaiscGraphicalElements} are * painted. * @return this instance. */ public Graphics2DRenderer init(Graphics2D graphics) { _graphics = graphics; _defaultColor = graphics.getColor(); // the foreground color return this; } /** * Starts rendering of the specified composite. Does nothing except if * composite has a {@link ClippingShape}. In this case the Clip * of the Graphics2D context becomes the clipping rectangle * determined by the bounding box of the ClippingShape. */ public void startRendering(GraphicalComposite composite) { ClippingShape shape = composite.getClippingShape(); if (shape != null) { ClippingRectangle rect = shape.getBoundingBox(); _graphics.clip(new Rectangle2D.Double(rect.getMinX(), rect.getMinY(), rect.getMaxX() - rect.getMinX(), rect .getMaxY() - rect.getMinY())); } } /** * Finishes rendering of the specified composite. Does nothing except if * composite has a {@link ClippingShape}. In this case the Clip * of the Graphics2D context will be cleared. */ public void finishRendering(GraphicalComposite composite) { _graphics.setClip(null); } /** Paints the specified polygon into the Graphics2D context. */ public void render(Polygon polygon) { int numberOfPoints = polygon.getNumberOfPoints(); if (numberOfPoints > 0) { Color currentColor = _graphics.getColor(); GeneralPath p = new GeneralPath(GeneralPath.WIND_EVEN_ODD, numberOfPoints); p.moveTo((float) polygon.getPoint(0).getX(), (float) polygon.getPoint(0).getY()); for (int i = 1; i < numberOfPoints; i++) { p.lineTo((float) polygon.getPoint(i).getX(), (float) polygon.getPoint(i).getY()); } if (polygon.isClosed()) { p.closePath(); } drawShape(p, polygon, currentColor); } } /** * Paints the specified rectangle into the current Graphics * context. */ public void render(Rectangle rectangle) { Color currentColor = _graphics.getColor(); GraphPoint center = rectangle.getCenter(); double width = rectangle.getWidth(); double height = rectangle.getHeight(); Rectangle2D rect = new Rectangle2D.Double(center.getX() - 0.5 * width, center.getY() - 0.5 * height, width, height); drawShape(rect, rectangle, currentColor); } /** * Paints the specified oval into the current Graphics context. */ public void render(Oval oval) { Color currentColor = _graphics.getColor(); GraphPoint center = oval.getCenter(); double width = oval.getWidth(); double height = oval.getHeight(); Ellipse2D ellipse = new Ellipse2D.Double(center.getX() - 0.5 * width, center.getY() - 0.5 * height, width, height); drawShape(ellipse, oval, currentColor); } private void drawShape(Shape shape, BasicGraphicalElement element, Color backupColor) { GraphicAttributes attributes = element.getGraphicAttributes(); Color fillColor = null; if (element.isClosed() && attributes instanceof FillAttributes) { fillColor = ((FillAttributes) attributes).getFillColor(); } if (fillColor != null) { _graphics.setColor(fillColor); _graphics.fill(shape); } Color lineColor = _defaultColor; if (attributes instanceof LineAttributes) { LineAttributes la = (LineAttributes) attributes; BasicStroke stroke = new BasicStroke((float) la.getLineThickness()); double[] linePattern = la.getLinePattern(); if (linePattern != null) { float[] dash = new float[linePattern.length]; for (int i = 0; i < dash.length; i++) { dash[i] = (float) la.getLinePattern()[i]; } stroke = new BasicStroke(stroke.getLineWidth(), BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10f, dash, 0f); } _graphics.setStroke(stroke); if (la.getLineColor() != null || fillColor != null) { lineColor = la.getLineColor(); } } if (lineColor != null) { _graphics.setColor(lineColor); _graphics.draw(shape); } _graphics.setColor(backupColor); } /** * Paints the specified text into the current Graphics context. *

* If the font size is zero the default font size will be used. *

* If the orientation angle is unequal zero the text will first be painted * into an off-screen image and rotated. Finally, it will be drawn into the * current Graphics context. Note, that only integer multiples of * 90 degree rotation are performed. Other orientation angles will be * adjusted to the nearest integer multiple of 90 degree. */ public void render(Text text) { final GraphicAttributes ga = text.getGraphicAttributes(); if (ga instanceof TextAttributes) { final TextAttributes ta = (TextAttributes) ga; final Color currentColor = _graphics.getColor(); Color fontColor = ta.getTextColor(); if (fontColor == null) { fontColor = _defaultColor; } _graphics.setColor(fontColor); final double scale = _graphics.getTransform().getScaleX(); final String str = text.getText(); AffineTransform before = _graphics.getTransform(); _graphics.setTransform(new AffineTransform()); double fs = ta.getFontSize(); fs = fs == 0 ? 1 : fs * scale / DEFAULT_FONT_SIZE; Font font = createFont(ta, 0); AffineTransform fontTransform = new AffineTransform(); fontTransform.scale(fs, fs); fontTransform.rotate(-ta.getOrientationAngle() * Math.PI / 180); font = font.deriveFont(fontTransform); _graphics.setFont(font); Rectangle2D bounds = _graphics.getFontMetrics().getStringBounds(str, _graphics); fontTransform.rotate(-ta.getOrientationAngle() * Math.PI / 180); final double yy = bounds.getHeight() + bounds.getY(); Point2D.Double pos = new Point2D.Double(text.getPosition().getX(), text.getPosition().getY()); before.transform(pos, pos); double x = 0; double y = 0; if (ta.getOrientationAngle() == 0) { x = -0.5 * ta.getHorizontalAnchor().getFactor() * bounds.getWidth(); y = 0.5 * ta.getVerticalAnchor().getFactor() * bounds.getHeight() - yy; x = pos.x + x; y = pos.y + y; } else { x = 0.5 * ta.getVerticalAnchor().getFactor() * bounds.getHeight(); y = 0.5 * ta.getHorizontalAnchor().getFactor() * bounds.getWidth(); // System.err.println("yy="+y+" dx="+x+" dy="+y); // x = 0; // y = 0; x = pos.x + x; y = pos.y + y; } // if (ta.getOrientationAngle() == 0) { //// System.err.println("x0=" + x); //// System.err.println("y0=" + y); // } else { // System.err.println("bounds=" + bounds + " y=" + bounds.getY() + " h=" + bounds.getHeight() + " vert=" // + ta.getVerticalAnchor().getFactor()+" horz="+ta.getHorizontalAnchor().getFactor()); // System.err.println("x1=" + x); // System.err.println("y1=" + y); // } _graphics.drawString(str, (float) x, (float) y); // _graphics.fillRect((int)x, (int)y, 5, 5); _graphics.setTransform(before); _graphics.setColor(currentColor); } } /** * Creates a font instance based on the specified text attributes and font * size. * * @param attributes * Text attributes (font name and style). * @param size * Font size in pixel. If 0 {@link #DEFAULT_FONT_SIZE} will be * used. * @return new font instance. */ static Font createFont(TextAttributes attributes, int size) { String fontName = attributes.getFontName(); if (fontName == null) { fontName = DEFAULT_FONT_NAME; } FontStyle fontStyle = attributes.getFontStyle(); if (fontStyle == null) { fontStyle = DEFAULT_FONT_STYLE; } int style = Font.PLAIN; if (fontStyle == FontStyle.BOLD) { style = Font.BOLD; } else if (fontStyle == FontStyle.ITALIC) { style = Font.ITALIC; } else if (fontStyle == FontStyle.BOLD_ITALIC) { style = Font.BOLD + Font.ITALIC; } if (size == 0) { size = DEFAULT_FONT_SIZE; } return new Font(fontName, style, size); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy