package com.xenoage.zong.renderer.awt.symbol;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.font.GraphicAttribute;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import com.xenoage.utils.math.Units;
import com.xenoage.utils.math.geom.Rectangle2f;
import com.xenoage.zong.renderer.awt.path.AwtPath;
import com.xenoage.zong.symbols.PathSymbol;
/**
* This class can draw {@link PathSymbol}s in a {@link TextLayout}.
*
* @author Andreas Wenger
*/
public final class PathSymbolGraphicAttribute
extends GraphicAttribute {
private final PathSymbol symbol;
private final float scaling;
/**
* Creates a new {@link PathSymbolGraphicAttribute} from the given symbol
* using the given scaling.
* @throws IllegalArgumentException if the symbol does not provide a {@link Shape}
*/
public PathSymbolGraphicAttribute(PathSymbol symbol, float scaling) {
super(GraphicAttribute.ROMAN_BASELINE);
this.symbol = symbol;
this.scaling = scaling * Units.mmToPx_1_1;
}
/**
* Returns the distance from the origin to the top bounds of the symbol.
*/
@Override public float getAscent() {
return symbol.ascentHeight * scaling;
}
/**
* Returns the distance from the origin to the bottom bounds of the symbol.
* By convention, this is 0, even if something is painted below the baseline.
*/
@Override public float getDescent() {
return 0;
}
/**
* Returns the distance from the origin to the right side of the bounds of the symbol.
*/
@Override public float getAdvance() {
return (-1 * symbol.getLeftBorder() + symbol.getRightBorder()) * scaling;
}
@Override public void draw(Graphics2D g, float x, float y) {
AffineTransform oldTransform = g.getTransform();
g.translate(x, y);
g.scale(scaling, scaling);
g.translate(-1 * symbol.getLeftBorder(), symbol.baselineOffset);
g.fill(AwtPath.createShape(symbol.getPath()));
g.setTransform(oldTransform);
}
@Override public Rectangle2D getBounds() {
Rectangle2f f = symbol.boundingRect;
f.scale(scaling);
return new Rectangle2D.Float(f.x1(), f.y1(), f.width(), f.height());
}
@Override public Shape getOutline(AffineTransform tx) {
Shape s = AffineTransform.getScaleInstance(scaling, scaling).createTransformedShape(
AwtPath.createShape(symbol.getPath()));
return tx == null ? s : tx.createTransformedShape(s);
}
}