/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.fge.graphics;
import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.PathIterator;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.fge.FGEConstants;
import org.openflexo.fge.GraphicalRepresentation;
import org.openflexo.fge.GraphicalRepresentation.HorizontalTextAlignment;
import org.openflexo.fge.ShapeGraphicalRepresentation;
import org.openflexo.fge.controller.DrawingController;
import org.openflexo.fge.geom.FGECubicCurve;
import org.openflexo.fge.geom.FGEDimension;
import org.openflexo.fge.geom.FGEGeneralShape;
import org.openflexo.fge.geom.FGEGeometricObject.Filling;
import org.openflexo.fge.geom.FGEPoint;
import org.openflexo.fge.geom.FGEPolygon;
import org.openflexo.fge.geom.FGEQuadCurve;
import org.openflexo.fge.geom.FGERectangle;
import org.openflexo.fge.graphics.BackgroundStyle.BackgroundImage.ImageBackgroundType;
public abstract class FGEGraphics {
private static final int TRANSPARENT_COMPOSITE_RULE = AlphaComposite.SRC_OVER;
private static final Logger logger = Logger.getLogger(FGEGraphics.class.getPackage().getName());
private DrawingController<?> _controller;
private GraphicalRepresentation<?> gr;
private Graphics2D g2d;
private ForegroundStyle defaultForeground = ForegroundStyle.makeDefault();
private BackgroundStyle defaultBackground = BackgroundStyle.makeEmptyBackground();
private TextStyle defaultTextStyle = TextStyle.makeDefault();
private ForegroundStyle currentForeground = defaultForeground;
protected BackgroundStyle currentBackground = defaultBackground;
private TextStyle currentTextStyle = defaultTextStyle;
public FGEGraphics(GraphicalRepresentation<?> aGraphicalRepresentation) {
super();
gr = aGraphicalRepresentation;
}
public GraphicalRepresentation<?> getGraphicalRepresentation() {
return gr;
}
public DrawingController<?> getController() {
return _controller;
}
public double getScale() {
return getController().getScale();
}
public void delete() {
gr = null;
_controller = null;
g2d = null;
}
/**
*
* @param graphics2D
* @param controller
*/
public void createGraphics(Graphics2D graphics2D, DrawingController<?> controller) {
g2d = (Graphics2D) graphics2D.create();
_controller = controller;
}
public void releaseGraphics() {
g2d.dispose();
}
/**
* Creates a new <code>Graphics2D</code> object that is a copy of current <code>Graphics2D</code> object.
*
* @return old <code>Graphics2D</code> object
*/
public Graphics2D cloneGraphics() {
Graphics2D returned = g2d;
g2d = (Graphics2D) g2d.create();
return returned;
}
public void releaseClonedGraphics(Graphics2D oldGraphics) {
g2d.dispose();
g2d = oldGraphics;
}
public Graphics2D getGraphics() {
return g2d;
}
public ForegroundStyle getDefaultForeground() {
return defaultForeground;
}
public ForegroundStyle getCurrentForeground() {
return currentForeground;
}
public void setDefaultForeground(ForegroundStyle aForegound) {
defaultForeground = aForegound;
}
public void setStroke(Stroke aStroke) {
g2d.setStroke(aStroke);
}
public void useDefaultForegroundStyle() {
useForegroundStyle(defaultForeground);
}
public void useForegroundStyle(ForegroundStyle aStyle) {
currentForeground = aStyle;
applyCurrentForegroundStyle();
}
private void applyCurrentForegroundStyle() {
if (g2d == null) {
return; // Strange...
}
// logger.info("Apply "+currentForeground);
g2d.setColor(currentForeground.getColor());
g2d.setStroke(currentForeground.getStroke(getScale()));
if (currentForeground.getUseTransparency()) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentForeground.getTransparencyLevel()));
} else {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
}
}
protected String debugForegroundStyle() {
BasicStroke stroke = (BasicStroke) g2d.getStroke();
return "FS-(color=" + g2d.getColor() + ")-(with=" + stroke.getLineWidth() + ")-(transp=" + g2d.getComposite() + ")-(join="
+ stroke.getLineJoin() + ")-(cap=" + stroke.getEndCap() + ")-(dash=" + stroke.getDashPhase() + ")";
}
public TextStyle getCurrentTextStyle() {
return currentTextStyle;
}
public BackgroundStyle getDefaultBackground() {
return defaultBackground;
}
public void setDefaultBackground(BackgroundStyle aBackground) {
defaultBackground = aBackground;
}
public void useDefaultBackgroundStyle() {
useBackgroundStyle(defaultBackground);
}
public void useBackgroundStyle(BackgroundStyle aStyle) {
currentBackground = aStyle;
applyCurrentBackgroundStyle();
}
protected void applyCurrentBackgroundStyle() {
if (g2d == null) {
return; // Strange...
}
if (currentBackground instanceof BackgroundStyle.None) {
// Nothing to do
} else if (currentBackground instanceof BackgroundStyle.Color) {
g2d.setColor(((BackgroundStyle.Color) currentBackground).getColor());
} else if (currentBackground instanceof BackgroundStyle.ColorGradient) {
g2d.setPaint(currentBackground.getPaint(getGraphicalRepresentation(), _controller.getScale()));
} else if (currentBackground instanceof BackgroundStyle.Texture) {
g2d.setPaint(currentBackground.getPaint(getGraphicalRepresentation(), _controller.getScale()));
} else if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
g2d.setPaint(currentBackground.getPaint(getGraphicalRepresentation(), _controller.getScale()));
}
if (currentBackground.getUseTransparency()) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, currentBackground.getTransparencyLevel()));
} else {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC));
}
}
public void setDefaultTextStyle(TextStyle aTextStyle) {
defaultTextStyle = aTextStyle;
}
public void useDefaultTextStyle() {
useTextStyle(defaultTextStyle);
}
public void useTextStyle(TextStyle aStyle) {
currentTextStyle = aStyle;
applyCurrentTextStyle();
}
private void applyCurrentTextStyle() {
g2d.setColor(currentTextStyle.getColor());
g2d.setFont(currentTextStyle.getFont());
}
public FGERectangle getNormalizedBounds() {
return new FGERectangle(0.0, 0.0, 1.0, 1.0);
}
public int getViewWidth() {
return getViewWidth(getScale());
}
public int getViewHeight() {
return getViewHeight(getScale());
}
public int getViewWidth(double scale) {
return getGraphicalRepresentation().getViewWidth(scale);
}
public int getViewHeight(double scale) {
return getGraphicalRepresentation().getViewHeight(scale);
}
public Point convertNormalizedPointToViewCoordinates(double x, double y) {
return getGraphicalRepresentation().convertNormalizedPointToViewCoordinates(x, y, getScale());
}
public final Point convertNormalizedPointToViewCoordinates(FGEPoint p) {
return convertNormalizedPointToViewCoordinates(p.x, p.y);
}
public final Rectangle convertNormalizedRectangleToViewCoordinates(FGERectangle r) {
return convertNormalizedRectangleToViewCoordinates(r.x, r.y, r.width, r.height);
}
public final Rectangle convertNormalizedRectangleToViewCoordinates(double x, double y, double width, double height) {
Point p1 = convertNormalizedPointToViewCoordinates(x, y);
Point p2 = convertNormalizedPointToViewCoordinates(x + width, y + height);
Dimension d = new Dimension(Math.abs(p2.x - p1.x), Math.abs(p2.y - p1.y));
return new Rectangle(p1, d);
}
public FGEPoint convertViewCoordinatesToNormalizedPoint(int x, int y) {
return getGraphicalRepresentation().convertViewCoordinatesToNormalizedPoint(x, y, getScale());
}
public final FGEPoint convertViewCoordinatesToNormalizedPoint(Point p) {
return convertViewCoordinatesToNormalizedPoint(p.x, p.y);
}
public final FGERectangle convertViewCoordinatesToNormalizedRectangle(Rectangle r) {
return convertViewCoordinatesToNormalizedRectangle(r.x, r.y, r.width, r.height);
}
public final FGERectangle convertViewCoordinatesToNormalizedRectangle(int x, int y, int width, int height) {
FGEPoint p1 = convertViewCoordinatesToNormalizedPoint(x, y);
FGEPoint p2 = convertViewCoordinatesToNormalizedPoint(x + width, y + height);
FGEDimension d = new FGEDimension(Math.abs(p2.x - p1.x), Math.abs(p2.y - p1.y));
return new FGERectangle(p1, d, Filling.NOT_FILLED);
}
public Rectangle drawControlPoint(double x, double y, int size) {
if (currentForeground.getNoStroke()) {
return null;
}
Point p = convertNormalizedPointToViewCoordinates(x, y);
p.x -= size;
p.y -= size;
g2d.fillRect(p.x, p.y, size * 2, size * 2);
return new Rectangle(p.x, p.y, size * 2, size * 2);
}
public void drawPoint(FGEPoint p) {
drawPoint(p.x, p.y);
}
public void drawPoint(double x, double y) {
if (currentForeground.getNoStroke()) {
return;
}
Point p1 = convertNormalizedPointToViewCoordinates(x, y);
p1.x -= FGEConstants.POINT_SIZE;
p1.y -= FGEConstants.POINT_SIZE;
Point p2 = convertNormalizedPointToViewCoordinates(x, y);
p2.x += FGEConstants.POINT_SIZE;
p2.y += FGEConstants.POINT_SIZE;
Point p3 = convertNormalizedPointToViewCoordinates(x, y);
p3.x -= FGEConstants.POINT_SIZE;
p3.y += FGEConstants.POINT_SIZE;
Point p4 = convertNormalizedPointToViewCoordinates(x, y);
p4.x += FGEConstants.POINT_SIZE;
p4.y -= FGEConstants.POINT_SIZE;
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
g2d.drawLine(p3.x, p3.y, p4.x, p4.y);
}
public void drawRoundArroundPoint(FGEPoint p, int size) {
drawRoundArroundPoint(p.x, p.y, size);
}
public void drawRoundArroundPoint(double x, double y, int size) {
if (currentForeground.getNoStroke()) {
return;
}
Point p = convertNormalizedPointToViewCoordinates(x, y);
p.x -= size;
p.y -= size;
g2d.drawOval(p.x, p.y, size * 2, size * 2);
}
public Rectangle drawControlPoint(FGEPoint p, int size) {
return drawControlPoint(p.x, p.y, size);
}
public void drawRect(double x, double y, double width, double height) {
if (currentForeground.getNoStroke()) {
return;
}
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
// logger.info("drawRect() with "+debugForegroundStyle());
// SGU: I don't understand why, but is you use non-plain stroke,
// Rendering using drawRect is not correct !!!
// g2d.drawRect(r.x,r.y,r.width,r.height);
if (r.height == 0 || r.width == 0) {
g2d.drawLine(r.x, r.y, r.x + r.width, r.y + r.height);
} else {
g2d.drawLine(r.x, r.y, r.x + r.width - 1, r.y);
g2d.drawLine(r.x + r.width, r.y, r.x + r.width, r.y + r.height - 1);
g2d.drawLine(r.x + r.width, r.y + r.height, r.x + 1, r.y + r.height);
g2d.drawLine(r.x, r.y + r.height, r.x, r.y + 1);
}
if (logger.isLoggable(Level.FINER)) {
logger.finer("drawRect(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
public void drawRect(FGEPoint p, FGEDimension d) {
drawRect(p.x, p.y, d.width, d.height);
}
public void fillRect(double x, double y, double width, double height) {
if (currentBackground instanceof BackgroundStyle.None) {
return;
}
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
fillInShapeWithImage(r);
} else {
g2d.fillRect(r.x, r.y, r.width, r.height);
}
if (logger.isLoggable(Level.FINER)) {
logger.finer("fillRect(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
/**
* This method is used to paint an image or a portion of an image into a supplied shape. Background properties are used, and
* transparency managed here.
*
* @param aShape
*/
private void fillInShapeWithImage(Shape aShape) {
Graphics2D oldGraphics = cloneGraphics();
g2d.clip(aShape);
// g2d.setClip(aShape);
AffineTransform at = AffineTransform.getScaleInstance(getScale(), getScale());
/*if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
at.concatenate(AffineTransform.getScaleInstance(
((BackgroundStyle.BackgroundImage)currentBackground).getScaleX(),
((BackgroundStyle.BackgroundImage)currentBackground).getScaleY()));
}*/
if (getGraphicalRepresentation() instanceof ShapeGraphicalRepresentation) {
ShapeGraphicalRepresentation<?> gr = (ShapeGraphicalRepresentation<?>) getGraphicalRepresentation();
at.concatenate(AffineTransform.getTranslateInstance(gr.getBorder().left, gr.getBorder().top));
}
if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
at.concatenate(AffineTransform.getTranslateInstance(((BackgroundStyle.BackgroundImage) currentBackground).getDeltaX(),
((BackgroundStyle.BackgroundImage) currentBackground).getDeltaY()));
if (((BackgroundStyle.BackgroundImage) currentBackground).getImageBackgroundType() == ImageBackgroundType.OPAQUE) {
g2d.setColor(((BackgroundStyle.BackgroundImage) currentBackground).getImageBackgroundColor());
g2d.fill(aShape);
}
}
if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
at.concatenate(AffineTransform.getScaleInstance(((BackgroundStyle.BackgroundImage) currentBackground).getScaleX(),
((BackgroundStyle.BackgroundImage) currentBackground).getScaleY()));
}
if (currentBackground.getUseTransparency()) {
g2d.setComposite(AlphaComposite.getInstance(TRANSPARENT_COMPOSITE_RULE, currentBackground.getTransparencyLevel()));
} else {
g2d.setComposite(AlphaComposite.getInstance(TRANSPARENT_COMPOSITE_RULE));
}
g2d.drawImage(((BackgroundStyle.BackgroundImage) currentBackground).getImage(), at, null);
releaseClonedGraphics(oldGraphics);
}
/**
* This method is used to paint an image or a portion of an image into a supplied shape. Background properties are used, and
* transparency managed here.
*
* @param aShape
*/
public void drawImage(Image image, FGEPoint p) {
g2d.setComposite(AlphaComposite.getInstance(TRANSPARENT_COMPOSITE_RULE));
Point location = convertNormalizedPointToViewCoordinates(p.x, p.y);
// System.err.println(location);
AffineTransform at = AffineTransform.getScaleInstance(getScale(), getScale());
at.preConcatenate(AffineTransform.getTranslateInstance(location.x, location.y));
g2d.drawImage(image, at, null);
}
public void fillRect(FGEPoint p, FGEDimension d) {
fillRect(p.x, p.y, d.width, d.height);
}
public void drawLine(double x1, double y1, double x2, double y2) {
// logger.info("drawLine("+x1+","+y1+","+x2+","+y2+")"+" with "+debugForegroundStyle());
if (currentForeground.getNoStroke()) {
return;
}
Point p1 = convertNormalizedPointToViewCoordinates(x1, y1);
Point p2 = convertNormalizedPointToViewCoordinates(x2, y2);
// logger.info("drawLine("+p1.x+","+p1.y+","+p2.x+","+p2.y+")");
g2d.drawLine(p1.x, p1.y, p2.x, p2.y);
if (logger.isLoggable(Level.FINE)) {
logger.fine("drawLine(" + p1.x + "," + p1.y + "," + p2.x + "," + p2.y + ")");
}
}
public void drawLine(FGEPoint p1, FGEPoint p2) {
drawLine(p1.x, p1.y, p2.x, p2.y);
}
public void drawRoundRect(double x, double y, double width, double height, double arcwidth, double archeight) {
if (currentForeground.getNoStroke()) {
return;
}
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
Rectangle arcRect = convertNormalizedRectangleToViewCoordinates(0, 0, arcwidth, archeight);
g2d.drawRoundRect(r.x, r.y, r.width, r.height, arcRect.width, arcRect.height);
if (logger.isLoggable(Level.FINER)) {
logger.finer("drawRoundRect(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
public void drawRoundRect(FGEPoint p, FGEDimension d, double arcwidth, double archeight) {
drawRoundRect(p.x, p.y, d.width, d.height, arcwidth, archeight);
}
public void fillRoundRect(double x, double y, double width, double height, double arcwidth, double archeight) {
if (currentBackground instanceof BackgroundStyle.None) {
return;
}
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
Rectangle arcRect = convertNormalizedRectangleToViewCoordinates(0, 0, arcwidth, archeight);
if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
RoundRectangle2D.Double rr = new RoundRectangle2D.Double(r.x, r.y, r.width, r.height, arcRect.width, arcRect.height);
fillInShapeWithImage(rr);
} else {
g2d.fillRoundRect(r.x, r.y, r.width, r.height, arcRect.width, arcRect.height);
}
if (logger.isLoggable(Level.FINER)) {
logger.finer("fillRoundRect(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
public void fillRoundRect(FGEPoint p, FGEDimension d, double arcwidth, double archeight) {
fillRoundRect(p.x, p.y, d.width, d.height, arcwidth, archeight);
}
public void drawPolygon(FGEPolygon polygon) {
drawPolygon(polygon.getPoints().toArray(new FGEPoint[polygon.getPointsNb()]));
}
public void drawPolygon(FGEPoint[] points) {
if (currentForeground.getNoStroke()) {
return;
}
if (points == null || points.length == 0) {
return;
}
int[] xpoints = new int[points.length];
int[] ypoints = new int[points.length];
for (int i = 0; i < points.length; i++) {
Point p = convertNormalizedPointToViewCoordinates(points[i]);
xpoints[i] = p.x;
ypoints[i] = p.y;
}
g2d.drawPolygon(xpoints, ypoints, points.length);
if (logger.isLoggable(Level.FINER)) {
logger.finer("drawPolygon(" + points + ")");
}
}
public void fillPolygon(FGEPolygon polygon) {
fillPolygon(polygon.getPoints().toArray(new FGEPoint[polygon.getPointsNb()]));
}
public void fillPolygon(FGEPoint[] points) {
if (currentBackground instanceof BackgroundStyle.None) {
return;
}
if (points == null || points.length == 0) {
return;
}
int[] xpoints = new int[points.length];
int[] ypoints = new int[points.length];
for (int i = 0; i < points.length; i++) {
Point p = convertNormalizedPointToViewCoordinates(points[i]);
xpoints[i] = p.x;
ypoints[i] = p.y;
}
if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
Polygon p = new Polygon(xpoints, ypoints, points.length);
fillInShapeWithImage(p);
} else {
g2d.fillPolygon(xpoints, ypoints, points.length);
}
if (logger.isLoggable(Level.FINER)) {
logger.finer("fillPolygon(" + points + ")");
}
}
public void drawCircle(double x, double y, double width, double height) {
if (currentForeground.getNoStroke()) {
return;
}
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
g2d.drawArc(r.x, r.y, r.width, r.height, 0, 360);
if (logger.isLoggable(Level.FINER)) {
logger.finer("drawCircle(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
public void drawCircle(double x, double y, double width, double height, Stroke stroke) {
if (currentForeground.getNoStroke()) {
return;
}
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
Stroke back = g2d.getStroke();
g2d.setStroke(stroke);
g2d.drawArc(r.x, r.y, r.width, r.height, 0, 360);
g2d.setStroke(back);
if (logger.isLoggable(Level.FINER)) {
logger.finer("drawCircle(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
public void drawCircle(FGEPoint p, FGEDimension d) {
drawCircle(p.x, p.y, d.width, d.height);
}
public void fillCircle(double x, double y, double width, double height) {
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
Arc2D.Double a = new Arc2D.Double(r.x, r.y, r.width, r.height, 0, 360, Arc2D.CHORD);
fillInShapeWithImage(a);
} else {
g2d.fillArc(r.x, r.y, r.width, r.height, 0, 360);
}
if (logger.isLoggable(Level.FINER)) {
logger.finer("fillCircle(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
public void fillCircle(FGEPoint p, FGEDimension d) {
fillCircle(p.x, p.y, d.width, d.height);
}
public void drawArc(double x, double y, double width, double height, double angleStart, double arcAngle) {
if (currentForeground.getNoStroke()) {
return;
}
// System.out.println("drawArc ("+x+","+y+","+width+","+height+")");
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
g2d.drawArc(r.x, r.y, r.width, r.height, (int) angleStart, (int) arcAngle);
// System.out.println("drawArc("+r.x+","+r.y+","+r.width+","+r.height+")");
if (logger.isLoggable(Level.FINER)) {
logger.finer("drawArc(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
public void drawArc(FGEPoint p, FGEDimension d, double angleStart, double arcAngle) {
drawArc(p.x, p.y, d.width, d.height, angleStart, arcAngle);
}
public void fillArc(double x, double y, double width, double height, double angleStart, double arcAngle) {
fillArc(x, y, width, height, angleStart, arcAngle, false);
}
public void fillArc(double x, double y, double width, double height, double angleStart, double arcAngle, boolean chord) {
Rectangle r = convertNormalizedRectangleToViewCoordinates(x, y, width, height);
if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
Arc2D.Double a = new Arc2D.Double(r.x, r.y, r.width, r.height, (int) angleStart, (int) arcAngle, chord ? Arc2D.CHORD
: Arc2D.PIE);
fillInShapeWithImage(a);
} else {
if (chord) {
Arc2D.Double a = new Arc2D.Double(r.x, r.y, r.width, r.height, (int) angleStart, (int) arcAngle, Arc2D.CHORD);
g2d.setClip(a);
}
g2d.fillArc(r.x, r.y, r.width, r.height, (int) angleStart, (int) arcAngle);
}
if (logger.isLoggable(Level.FINER)) {
logger.finer("fillArc(" + r.x + "," + r.y + "," + r.width + "," + r.height + ")");
}
}
public void fillArc(FGEPoint p, FGEDimension d, double angleStart, double arcAngle) {
fillArc(p.x, p.y, d.width, d.height, angleStart, arcAngle);
}
public FGERectangle drawString(String text, FGEPoint location, int orientation, HorizontalTextAlignment alignment) {
return drawString(text, location.x, location.y, orientation, alignment);
}
public void drawCurve(FGEQuadCurve curve) {
if (currentForeground.getNoStroke()) {
return;
}
Point p1 = convertNormalizedPointToViewCoordinates(curve.getX1(), curve.getY1());
Point ctrl_p = convertNormalizedPointToViewCoordinates(curve.getCtrlX(), curve.getCtrlY());
Point p2 = convertNormalizedPointToViewCoordinates(curve.getX2(), curve.getY2());
QuadCurve2D awtCurve = new QuadCurve2D.Double(p1.x, p1.y, ctrl_p.x, ctrl_p.y, p2.x, p2.y);
g2d.draw(awtCurve);
if (logger.isLoggable(Level.FINE)) {
logger.fine("drawCurve(" + p1.x + "," + p1.y + "," + ctrl_p.x + "," + ctrl_p.y + "," + p2.x + "," + p2.y + ")");
}
}
public void drawCurve(FGECubicCurve curve) {
if (currentForeground.getNoStroke()) {
return;
}
Point p1 = convertNormalizedPointToViewCoordinates(curve.getX1(), curve.getY1());
Point ctrl_p1 = convertNormalizedPointToViewCoordinates(curve.getCtrlX1(), curve.getCtrlY1());
Point ctrl_p2 = convertNormalizedPointToViewCoordinates(curve.getCtrlX2(), curve.getCtrlY2());
Point p2 = convertNormalizedPointToViewCoordinates(curve.getX2(), curve.getY2());
CubicCurve2D awtCurve = new CubicCurve2D.Double(p1.x, p1.y, ctrl_p1.x, ctrl_p1.y, ctrl_p2.x, ctrl_p2.y, p2.x, p2.y);
g2d.draw(awtCurve);
if (logger.isLoggable(Level.FINE)) {
logger.fine("drawCurve(" + p1.x + "," + p1.y + "," + ctrl_p1.x + "," + ctrl_p1.y + "," + p2.x + ctrl_p2.x + "," + ctrl_p2.y
+ "," + p2.x + "," + p2.y + ")");
}
}
public void drawGeneralShape(FGEGeneralShape shape) {
if (currentForeground.getNoStroke()) {
return;
}
PathIterator pi = shape.getPathIterator(null);
FGEPoint current = new FGEPoint();
FGEPoint first = null;
while (!pi.isDone()) {
double[] pts = new double[6];
FGEPoint p2, cp, cp1, cp2;
switch (pi.currentSegment(pts)) {
case PathIterator.SEG_MOVETO:
current.x = pts[0];
current.y = pts[1];
first = current.clone();
break;
case PathIterator.SEG_LINETO:
p2 = new FGEPoint(pts[0], pts[1]);
drawLine(current, p2);
current = p2;
break;
case PathIterator.SEG_QUADTO:
cp = new FGEPoint(pts[0], pts[1]);
p2 = new FGEPoint(pts[2], pts[3]);
drawCurve(new FGEQuadCurve(current, cp, p2));
current = p2;
break;
case PathIterator.SEG_CUBICTO:
cp1 = new FGEPoint(pts[0], pts[1]);
cp2 = new FGEPoint(pts[2], pts[3]);
p2 = new FGEPoint(pts[4], pts[5]);
drawCurve(new FGECubicCurve(current, cp1, cp2, p2));
current = p2;
break;
case PathIterator.SEG_CLOSE:
drawLine(current, first);
current = first;
break;
default:
break;
}
pi.next();
}
}
public void fillGeneralShape(FGEGeneralShape shape) {
GeneralPath p = shape.getGeneralPath();
if (currentBackground instanceof BackgroundStyle.BackgroundImage) {
fillInShapeWithImage(p);
} else {
g2d.fill(p);
}
}
public FGERectangle drawString(String text, double x, double y, int orientation, HorizontalTextAlignment alignment) {
if (text == null || text.length() == 0) {
return new FGERectangle();
}
Point p = convertNormalizedPointToViewCoordinates(x, y);
Font oldFont = g2d.getFont();
AffineTransform at = AffineTransform.getScaleInstance(getScale(), getScale());
if (orientation != 0) {
at.concatenate(AffineTransform.getRotateInstance(Math.toRadians(orientation)));
}
Font font = oldFont.deriveFont(at);
Rectangle2D b = g2d.getFontMetrics().getStringBounds(text, g2d);
g2d.setFont(font);
/*FGERectangle returned = convertViewCoordinatesToNormalizedRectangle(
(int)(bounds.getX()+p.x-bounds.getWidth()/2),
(int)(bounds.getY()+p.y+bounds.getHeight()/2),
(int)bounds.getWidth(),(int)bounds.getHeight());*/
FGERectangle bounds = new FGERectangle(b.getX(), b.getY(), b.getWidth(), b.getHeight());
if (orientation != 0) {
bounds = bounds.transform(AffineTransform.getRotateInstance(Math.toRadians(orientation))).getEmbeddingBounds();
}
int x2 = (int) (p.x - bounds.getWidth() / 2);
int y2 = (int) (p.y + bounds.getHeight() / 2);
switch (alignment) {
case LEFT:
x2 = p.x;
break;
case RIGHT:
x2 = (int) (p.x - bounds.getWidth());
break;
case CENTER:
default:
break;
}
// GPO: Je crois que c'est complètement foireux si le background est "colored"
if (currentTextStyle.getIsBackgroundColored()) {
g2d.setColor(currentTextStyle.getBackgroundColor());
g2d.fillRect((int) (bounds.getX() + p.x - bounds.getWidth() / 2), (int) (bounds.getY() + p.y + bounds.getHeight() / 2),
(int) bounds.getWidth(), (int) bounds.getHeight());
g2d.setColor(currentTextStyle.getColor());
}
g2d.drawString(text, x2, y2);
g2d.setFont(oldFont);
return convertViewCoordinatesToNormalizedRectangle((int) (bounds.getX() + p.x - bounds.getWidth() / 2),
(int) (bounds.getY() + p.y + bounds.getHeight() / 2), (int) bounds.getWidth(), (int) bounds.getHeight());
}
public FGERectangle drawString(String text, FGEPoint location, HorizontalTextAlignment alignment) {
return drawString(text, location.x, location.y, 0, alignment);
}
public FGERectangle drawString(String text, double x, double y, HorizontalTextAlignment alignment) {
return drawString(text, x, y, 0, alignment);
}
}