/*
* FontSymbol.java
*
* Created on August 10, 2005, 11:48 AM
*
*/
package ika.geo;
import ika.utils.ColorUtils;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
/**
* Font symbol. Default is sans serif with 12 points, scale invariant,
* horizontally and vertically centered, black;
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich
*/
public class FontSymbol extends Symbol implements Cloneable{
private enum HAlign { CENTER, LEFT, RIGHT };
private HAlign hAlign = HAlign.CENTER;
private Font font = new Font("SansSerif", Font.PLAIN, 12);
private boolean scaleInvariant = true; // FIXME ignored for rendering
private boolean centerVer = true;
private Color color = Color.BLACK;
/** Creates a new instance of FontSymbol */
public FontSymbol() {
}
@Override
public Object clone() {
try {
FontSymbol fontSymbol = (FontSymbol)super.clone();
// make deep copy of FontSymbol
fontSymbol.font = this.font.deriveFont(this.font.getSize());
return fontSymbol;
} catch (CloneNotSupportedException exc) {
return null;
}
}
public void drawFontSymbol(RenderParams rp,
boolean drawSelected,
double x, double y,
double dxPx, double dyPx,
String text,
double rotation) {
if (text == null) {
return;
}
// position of the first character
double tx = rp.tX(x);
double ty = rp.tY(y);
final Graphics2D g2d;
if (rotation == 0) {
g2d = rp.g2d;
} else {
// make a copy, as the affine transformation changes for rotated text
g2d = (Graphics2D)(rp.g2d.create());
g2d.translate(tx, ty);
g2d.rotate(Math.toRadians(rotation));
g2d.translate(-tx, -ty);
}
// add the scale-independent offset (after rotation)
tx += dxPx;
ty -= dyPx;
// horizontal alignment
Rectangle2D visualTextBounds = null;
switch (hAlign) {
case CENTER:
visualTextBounds = visualTextBoundsPx(text);
tx -= visualTextBounds.getWidth() / 2;
break;
case RIGHT:
visualTextBounds = visualTextBoundsPx(text);
tx -= visualTextBounds.getWidth();
break;
}
// vertical alignment
if (centerVer) {
if (visualTextBounds == null) {
visualTextBounds = visualTextBoundsPx(text);
}
ty += visualTextBounds.getHeight() / 2;
}
g2d.setColor(drawSelected ? ColorUtils.getSelectionColor() : color);
g2d.setFont(font);
g2d.drawString(text, (float)tx, (float)ty);
// if a copy of Graphics2D was created, release it.
if (g2d != rp.g2d) {
g2d.dispose();
}
}
private Rectangle2D visualTextBoundsPx(String str) {
FontRenderContext frc = new FontRenderContext(null, true, false);
GlyphVector gv = font.createGlyphVector(frc, str);
return gv.getVisualBounds();
}
public Rectangle2D getBounds2D(String str, double x, double y,
double dxPx, double dyPx, double scale) {
if (str == null) {
return null;
}
final Rectangle2D visualBoundsPx = visualTextBoundsPx(str);
double tx = x + dxPx / scale;
double ty = y + dyPx / scale;
// horizontal alignment
switch (hAlign) {
case CENTER:
tx -= visualBoundsPx.getWidth() / 2 / scale;
break;
case RIGHT:
tx -= visualBoundsPx.getWidth() / scale;
break;
}
// vertical alignment
if (centerVer) {
ty -= visualBoundsPx.getHeight() / 2 / scale;
}
double w = visualBoundsPx.getWidth() / scale;
double h = visualBoundsPx.getHeight() / scale;
// FIXME: rotation
return new Rectangle2D.Double(tx, ty, w, h);
}
public Font getFont() {
return font;
}
public void setFont(Font font) {
this.font = font;
}
public boolean isScaleInvariant() {
return scaleInvariant;
}
public void setScaleInvariant(boolean scaleInvariant) {
this.scaleInvariant = scaleInvariant;
}
public boolean isCenterHor() {
return this.hAlign == HAlign.CENTER;
}
public void setCenterHor(boolean centerHor) {
this.hAlign = centerHor ? HAlign.CENTER : HAlign.LEFT;
}
public void setAlignLeft() {
this.hAlign = HAlign.LEFT;
}
public boolean isAlignLeft() {
return this.hAlign == HAlign.LEFT;
}
public void setAlignRight() {
this.hAlign = HAlign.RIGHT;
}
public boolean isAlignRight() {
return this.hAlign == HAlign.RIGHT;
}
public boolean isCenterVer() {
return centerVer;
}
public void setCenterVer(boolean centerVer) {
this.centerVer = centerVer;
}
public int getSize() {
return font.getSize();
}
public void setSize (int size) {
this.font = font.deriveFont((float)size);
}
public Color getColor() {
return color;
}
public void setColor(Color color) {
this.color = color;
}
}