/*
* $Id$
* This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc
*
* Copyright (c) 2000-2012 Stephane GALLAND.
* Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports,
* Universite de Technologie de Belfort-Montbeliard.
* Copyright (c) 2013-2016 The original authors, and other authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.arakhne.afc.ui.vector.awt;
import java.awt.AlphaComposite;
import java.awt.Polygon;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.CubicCurve2D;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.GrayFilter;
import javax.swing.UIManager;
import org.arakhne.afc.math.continous.object2d.Circle2f;
import org.arakhne.afc.math.continous.object2d.Ellipse2f;
import org.arakhne.afc.math.continous.object2d.Path2f;
import org.arakhne.afc.math.continous.object2d.PathIterator2f;
import org.arakhne.afc.math.continous.object2d.Rectangle2f;
import org.arakhne.afc.math.continous.object2d.RoundRectangle2f;
import org.arakhne.afc.math.continous.object2d.Segment2f;
import org.arakhne.afc.math.continous.object2d.Shape2f;
import org.arakhne.afc.math.generic.PathWindingRule;
import org.arakhne.afc.math.matrix.Transform2D;
import org.arakhne.afc.ui.awt.AwtUtil;
import org.arakhne.afc.ui.awt.SupportedShape;
import org.arakhne.afc.ui.awt.VirtualizableShape;
import org.arakhne.afc.ui.vector.Color;
import org.arakhne.afc.ui.vector.Composite;
import org.arakhne.afc.ui.vector.Dimension;
import org.arakhne.afc.ui.vector.Font;
import org.arakhne.afc.ui.vector.FontMetrics;
import org.arakhne.afc.ui.vector.FontStyle;
import org.arakhne.afc.ui.vector.Image;
import org.arakhne.afc.ui.vector.Margins;
import org.arakhne.afc.ui.vector.Paint;
import org.arakhne.afc.ui.vector.Stroke;
import org.arakhne.afc.ui.vector.Stroke.EndCap;
import org.arakhne.afc.ui.vector.Stroke.LineJoin;
import org.arakhne.afc.ui.vector.VectorToolkit;
import org.arakhne.afc.vmutil.OperatingSystem;
/** AWT implementation of the generic Window toolkit.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @deprecated see JavaFX API
*/
@Deprecated
public class AwtVectorToolkit extends VectorToolkit {
/**
*/
public AwtVectorToolkit() {
//
}
@Override
protected boolean isSupported() {
return !OperatingSystem.ANDROID.isCurrentOS();
}
@Override
protected Composite createComposite(float alpha) {
return new AwtComposite(AlphaComposite.SRC_IN, alpha);
}
@Override
protected Paint createPaint(Object paintObject) {
return new AwtPaint((java.awt.Paint)paintObject);
}
@Override
protected Font createFont(String name, FontStyle style, float size) {
return new AwtFont(name, style, size);
}
@Override
protected Image createImage(URL url) {
try {
java.awt.Image awtImage = ImageIO.read(url);
return new AwtImage(awtImage);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected Image createImage(InputStream stream) {
try {
java.awt.Image awtImage = ImageIO.read(stream);
return new AwtImage(awtImage);
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
protected Image createImage(int width, int height, boolean isAlpha) {
return new AwtBufferedImage(width, height, isAlpha);
}
@Override
protected Stroke createStroke(float width, LineJoin lineJoin, EndCap endCap, float mitterLimit, float[] dashes, float dashPhase) {
return new AwtStroke(width, lineJoin, endCap, mitterLimit, dashes, dashPhase);
}
@Override
protected Color createColor(int red, int green, int blue, int alpha) {
return new AwtColor(red, green, blue, alpha);
}
@Override
protected Color createColor(Object rawColorObject) {
java.awt.Color c = (java.awt.Color)rawColorObject;
return new AwtColor(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
}
@Override
protected Dimension createDimension(float width, float height) {
return new AwtDimension(width, height);
}
@Override
protected Margins createMargins(float top, float left, float right,
float bottom) {
return new AwtMargins(top, left, right, bottom);
}
@Override
protected Composite createComposite(Object compositeObject) {
return new AwtComposite((java.awt.Composite)compositeObject);
}
@Override
protected Font createFont(Object fontObject) {
return new AwtFont((java.awt.Font)fontObject);
}
@Override
protected FontMetrics createFontMetrics(Object metricsObject) {
return new AwtFontMetrics((java.awt.FontMetrics)metricsObject);
}
@Override
protected FontMetrics createFontMetrics(Font font) {
AwtFont awtFont = (AwtFont)font;
java.awt.FontMetrics fm = new java.awt.FontMetrics(awtFont.getFont()) {
private static final long serialVersionUID = 3136667595495307776L;
};
return new AwtFontMetrics(fm);
}
@Override
protected Stroke createStroke(Object strokeObject) {
return new AwtStroke((java.awt.BasicStroke)strokeObject);
}
@Override
protected Image createImage(Object imageObject) {
if (imageObject instanceof java.awt.Image) {
return new AwtImage((java.awt.Image)imageObject);
}
else if (imageObject instanceof javax.swing.ImageIcon) {
return new AwtImage(((javax.swing.ImageIcon)imageObject).getImage());
}
else if (imageObject instanceof javax.swing.Icon) {
javax.swing.Icon ic = (javax.swing.Icon)imageObject;
AwtBufferedImage img = new AwtBufferedImage(ic.getIconWidth(), ic.getIconHeight(), true);
java.awt.Graphics g = img.getGraphics();
ic.paintIcon(null, g, 0, 0);
g.dispose();
return img;
}
throw new IllegalArgumentException();
}
@Override
protected Shape2f createShape(Object shapeObject) {
if (shapeObject instanceof Shape2f)
return (Shape2f)shapeObject;
SupportedShape type = SupportedShape.getTypeOf(shapeObject.getClass());
if (type!=null) {
switch(type) {
case RECTANGLE2D:
{
Rectangle2D r = (Rectangle2D)shapeObject;
return new Rectangle2f((float)r.getMinX(), (float)r.getMinY(), (float)r.getWidth(), (float)r.getHeight());
}
case LINE:
{
Line2D l = (Line2D)shapeObject;
return new Segment2f((float)l.getX1(), (float)l.getY1(), (float)l.getX2(), (float)l.getY2());
}
case ELLIPSE:
{
Ellipse2D q = (Ellipse2D)shapeObject;
return new Ellipse2f(
(float)q.getMinX(), (float)q.getMinY(),
(float)q.getWidth(), (float)q.getHeight());
}
case ROUND_RECTANGLE:
{
RoundRectangle2D q = (RoundRectangle2D)shapeObject;
return new RoundRectangle2f(
(float)q.getMinX(), (float)q.getMinY(),
(float)q.getWidth(), (float)q.getHeight(),
(float)q.getArcWidth(), (float)q.getArcHeight());
}
case PATH:
{
Path2D p = (Path2D)shapeObject;
return toPath(p.getPathIterator(null));
}
case POLYGON:
{
Polygon p = (Polygon)shapeObject;
Path2f pp = toPath(p.getPathIterator(null));
pp.closePath();
return pp;
}
case AREA:
{
Area p = (Area)shapeObject;
Path2f pp = toPath(p.getPathIterator(null));
pp.closePath();
return pp;
}
case QUAD_CURVE:
{
QuadCurve2D q = (QuadCurve2D)shapeObject;
Path2f pp = new Path2f();
pp.moveTo((float)q.getX1(), (float)q.getY1());
pp.quadTo(
(float)q.getCtrlX(), (float)q.getCtrlY(),
(float)q.getX2(), (float)q.getY2());
return pp;
}
case CUBIC_CURVE:
{
CubicCurve2D q = (CubicCurve2D)shapeObject;
Path2f pp = new Path2f();
pp.moveTo((float)q.getX1(), (float)q.getY1());
pp.curveTo(
(float)q.getCtrlX1(), (float)q.getCtrlY1(),
(float)q.getCtrlX2(), (float)q.getCtrlY2(),
(float)q.getX2(), (float)q.getY2());
return pp;
}
case ARC:
{
Arc2D arc = (Arc2D)shapeObject;
return toPath(arc.getPathIterator(null));
}
case VIRTUALIZABLE_SHAPE:
{
VirtualizableShape vs = (VirtualizableShape)shapeObject;
return toPath(vs.getPathIterator(null));
}
default:
}
}
throw new IllegalArgumentException();
}
private static Path2f toPath(PathIterator pi) {
Path2f pp = new Path2f(getWindingRule(pi));
float[] coords = new float[6];
while (!pi.isDone()) {
switch(pi.currentSegment(coords)) {
case PathIterator.SEG_MOVETO:
pp.moveTo(coords[0], coords[1]);
break;
case PathIterator.SEG_LINETO:
pp.lineTo(coords[0], coords[1]);
break;
case PathIterator.SEG_QUADTO:
pp.quadTo(coords[0], coords[1], coords[2], coords[3]);
break;
case PathIterator.SEG_CUBICTO:
pp.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
break;
case PathIterator.SEG_CLOSE:
pp.closePath();
break;
default:
}
pi.next();
}
return pp;
}
private static PathWindingRule getWindingRule(PathIterator pi) {
PathWindingRule rule;
switch(pi.getWindingRule()) {
case PathIterator.WIND_NON_ZERO:
rule = PathWindingRule.NON_ZERO;
break;
case PathIterator.WIND_EVEN_ODD:
rule = PathWindingRule.EVEN_ODD;
break;
default:
rule = PathWindingRule.NON_ZERO;
break;
}
return rule;
}
@Override
protected <T> T toNativeUIObject(Class<T> type, Object o) {
if (o instanceof NativeWrapper) {
return ((NativeWrapper)o).getNativeObject(type);
}
if (o instanceof PathIterator2f) {
return type.cast(new AwtPathIterator((PathIterator2f)o));
}
if (o instanceof Rectangle2f) {
Rectangle2f r = (Rectangle2f)o;
return type.cast(new Rectangle2D.Float(
r.getMinX(), r.getMinY(),
r.getWidth(), r.getHeight()));
}
if (o instanceof RoundRectangle2f) {
RoundRectangle2f r = (RoundRectangle2f)o;
return type.cast(new RoundRectangle2D.Float(
r.getMinX(), r.getMinY(),
r.getWidth(), r.getHeight(),
r.getArcWidth(), r.getArcHeight()));
}
if (o instanceof Circle2f) {
Circle2f r = (Circle2f)o;
return type.cast(new Ellipse2D.Float(
r.getX()-r.getRadius(), r.getY()-r.getRadius(),
r.getX()+r.getRadius(), r.getY()+r.getRadius()));
}
if (o instanceof Ellipse2f) {
Ellipse2f r = (Ellipse2f)o;
return type.cast(new Ellipse2D.Float(
r.getMinX(), r.getMinY(),
r.getWidth(), r.getHeight()));
}
if (o instanceof Segment2f) {
Segment2f r = (Segment2f)o;
return type.cast(new Line2D.Float(
r.getX1(), r.getY1(),
r.getX2(), r.getY2()));
}
if (o instanceof Path2f) {
return type.cast(new AwtPath((Path2f)o));
}
return type.cast(o);
}
@Override
protected Font getDefaultFont() {
return new AwtFont(java.awt.Font.decode(null));
}
@Override
protected Image createTransparentImage(Image imageObject, float transparency) {
java.awt.Image aImg = toNativeUIObject(java.awt.Image.class, imageObject);
aImg = AwtUtil.getTransparencyFilteredImage(aImg, transparency);
return new AwtImage(aImg);
}
@Override
protected Image makeTransparentImage(Image imageObject, float transparency) {
java.awt.Image aImg = toNativeUIObject(java.awt.Image.class, imageObject);
aImg = AwtUtil.getTransparencyFilteredImage(aImg, transparency);
return new AwtImage(aImg);
}
@Override
protected Transform2D createTransform(Object affineTransform) {
AffineTransform tr = (AffineTransform)affineTransform;
return new Transform2D(
(float)tr.getScaleX(), (float)tr.getShearX(), (float)tr.getTranslateX(),
(float)tr.getShearY(), (float)tr.getScaleY(), (float)tr.getTranslateY());
}
@Override
protected void write(Image image, String type, OutputStream stream)
throws IOException {
ImageIO.write(toNativeUIObject(RenderedImage.class, image), type, stream);
}
@Override
protected <T> T findObjectWithId(int id, Class<T> type) {
return null;
}
@Override
protected int HSBtoRGB(float hue, float saturation, float brightness) {
return java.awt.Color.HSBtoRGB(hue, saturation, brightness);
}
@Override
protected Image createColorizedImage(Image imageObject,
Color filtering_color, float alpha) {
if (filtering_color==null || imageObject==null) return imageObject;
java.awt.Image source = nativeUIObject(java.awt.Image.class, imageObject);
if (source==null) return null;
java.awt.Image img = ColorFilter.createFilteredImage(
source,
nativeUIObject(java.awt.Color.class, filtering_color),
alpha);
return new AwtImage(img);
}
/** This class permits to filter the color of an icon.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
private static class ColorFilter extends java.awt.image.RGBImageFilter {
/** Indicates the filtering color.
*/
private final int red;
/** Indicates the filtering color.
*/
private final int blue;
/** Indicates the filtering color.
*/
private final int green;
/** Alpha blending value.
*/
private final float alpha;
/**
* Creates a color-filtered image
*
* @param i is the image to filter
* @param filtering_color is the color used to filter.
* @param alpha indicates how the icon and the color are merged. The value
* is in <code>[0;1]</code>. A value of <code>0</code> means that the color
* of the icon is used. A value of <code>1</code> means that the given color
* is used in place of the original colors. A value of <code>0.5</code>
* means that the resulting color is at half way between the icon's color
* and the given color.
* @return the result of the filtering.
*/
public static java.awt.Image createFilteredImage(java.awt.Image i, java.awt.Color filtering_color, float alpha) {
ColorFilter filter = new ColorFilter(filtering_color, alpha);
java.awt.image.ImageProducer prod = new java.awt.image.FilteredImageSource(i.getSource(), filter);
java.awt.Image filteredImage = Toolkit.getDefaultToolkit().createImage(prod);
return filteredImage;
}
/**
* Constructs a ColorFilter object that filters a color image to a
* color-scale image. It is similar to {@link GrayFilter} but not for
* a specifical color.
*
* @param filtering_color is the color used to filter.
* @param alpha indicates how the icon and the color are merged. The value
* is in <code>[0;1]</code>. A value of <code>0</code> means that the color
* of the icon is used. A value of <code>1</code> means that the given color
* is used in place of the original colors. A value of <code>0.5</code>
* means that the resulting color is at half way between the icon's color
* and the given color.
*/
public ColorFilter(java.awt.Color filtering_color, float alpha) {
this.red = filtering_color.getRed();
this.green = filtering_color.getGreen();
this.blue = filtering_color.getBlue();
this.alpha = (alpha<0f) ? 0f : ((alpha>1f) ? 1f : alpha);
// canFilterIndexColorModel indicates whether or not it is acceptable
// to apply the color filtering of the filterRGB method to the color
// table entries of an IndexColorModel object in lieu of pixel by pixel
// filtering.
this.canFilterIndexColorModel = true;
}
/**
* Filter the specified color.
*/
@Override
public int filterRGB(int x, int y, int rgb) {
int color_r = ((rgb >> 16) & 0xff);
int color_g = ((rgb >> 8) & 0xff);
int color_b = (rgb & 0xff);
color_r = (int)((this.red + color_r) * this.alpha);
if (color_r<0) color_r = 0;
if (color_r>255) color_r = 0;
color_g = (int)((this.green + color_g) * this.alpha);
if (color_g<0) color_g = 0;
if (color_g>255) color_g = 0;
color_b = (int)((this.blue + color_b) * this.alpha);
if (color_b<0) color_b = 0;
if (color_b>255) color_b = 0;
return (rgb & 0xff000000) | (color_r << 16) | (color_g << 8) | color_b;
}
}
@Override
protected Color createSelectionBackground() {
return color(UIManager.getColor("Tree.selectionBackground")); //$NON-NLS-1$
}
@Override
protected Color createSelectionForeground() {
return color(UIManager.getColor("Tree.selectionForeground")); //$NON-NLS-1$
}
}