// Copyright 2007, FreeHEP.
package org.freehep.graphicsio.emf.gdi;
import org.freehep.graphicsio.emf.EMFConstants;
import org.freehep.graphicsio.emf.EMFRenderer;
import java.util.logging.Logger;
import java.awt.BasicStroke;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
/**
* @author Steffen Greiffenberg
* @version $Id: freehep-graphicsio-emf/src/main/java/org/freehep/graphicsio/emf/gdi/AbstractPen.java 10ec7516e3ce 2007/02/06 18:42:34 duns $
*/
public abstract class AbstractPen implements EMFConstants, GDIObject {
/**
* Represents a stroke that draws inside the given shape.
* Used if EMFConstants.PS_INSIDEFRAME is used
*/
private class InsideFrameStroke implements Stroke {
private BasicStroke stroke;
public InsideFrameStroke (
float width,
int cap,
int join,
float miterlimit,
float dash[],
float dash_phase) {
stroke = new BasicStroke(width, cap, join, miterlimit, dash, dash_phase);
}
public Shape createStrokedShape(Shape shape) {
if (shape == null) {
return null;
}
Rectangle2D oldBounds = shape.getBounds2D();
float witdh = stroke.getLineWidth();
// calcute a transformation for inside drawing
// based on the stroke width
AffineTransform at = new AffineTransform();
if (oldBounds.getWidth() > 0) {
at.scale(
(oldBounds.getWidth() - witdh) /
oldBounds.getWidth(), 1);
}
if (oldBounds.getHeight() > 0) {
at.scale(1,
(oldBounds.getHeight() - witdh)
/ oldBounds.getHeight());
}
// recalculate shape and its oldBounds
shape = at.createTransformedShape(shape);
Rectangle2D newBounds = shape.getBounds2D();
// move the shape to the old origin + the line width offset
AffineTransform moveBackTransform = AffineTransform.getTranslateInstance(
oldBounds.getX() - newBounds.getX() + witdh / 2,
oldBounds.getY() - newBounds.getY() + witdh / 2);
shape = moveBackTransform.createTransformedShape(shape);
// outline the shape using the simple basic stroke
return stroke.createStrokedShape(shape);
}
}
/**
* logger for all instances
*/
private static final Logger logger = Logger.getLogger("org.freehep.graphicsio.emf");
/**
* returns a BasicStroke JOIN for an EMF pen style
* @param penStyle penstyle
* @return e.g. {@link java.awt.BasicStroke#JOIN_MITER}
*/
protected int getJoin(int penStyle) {
switch (penStyle & 0xF000) {
case EMFConstants.PS_JOIN_ROUND:
return BasicStroke.JOIN_ROUND;
case EMFConstants.PS_JOIN_BEVEL:
return BasicStroke.JOIN_BEVEL;
case EMFConstants.PS_JOIN_MITER:
return BasicStroke.JOIN_MITER;
default:
logger.warning("got unsupported pen style " + penStyle);
return BasicStroke.JOIN_ROUND;
}
}
/**
* returns a BasicStroke JOIN for an EMF pen style
* @param penStyle Style to convert
* @return asicStroke.CAP_ROUND, BasicStroke.CAP_SQUARE, BasicStroke.CAP_BUTT
*/
protected int getCap(int penStyle) {
switch (penStyle & 0xF00) {
case EMFConstants.PS_ENDCAP_ROUND:
return BasicStroke.CAP_ROUND;
case EMFConstants.PS_ENDCAP_SQUARE:
return BasicStroke.CAP_SQUARE;
case EMFConstants.PS_ENDCAP_FLAT:
return BasicStroke.CAP_BUTT;
default:
logger.warning("got unsupported pen style " + penStyle);
return BasicStroke.CAP_ROUND;
}
}
/**
* returns a Dash for an EMF pen style
* @param penStyle Style to convert
* @param style used if EMFConstants#PS_USERSTYLE is set
* @return float[] representing a dash
*/
protected float[] getDash(int penStyle, int[] style) {
switch (penStyle & 0xFF) {
case EMFConstants.PS_SOLID:
// do not use float[] { 1 }
// it's _slow_
return null;
case EMFConstants.PS_DASH:
return new float[] { 5, 5 };
case EMFConstants.PS_DOT:
return new float[] { 1, 2 };
case EMFConstants.PS_DASHDOT:
return new float[] { 5, 2, 1, 2 };
case EMFConstants.PS_DASHDOTDOT:
return new float[] { 5, 2, 1, 2, 1, 2 };
case EMFConstants.PS_INSIDEFRAME:
// Represents a pen style that consists of a solid
// pen that is drawn from within any given bounding rectangle
return null;
case EMFConstants.PS_NULL:
// do not use float[] { 1 }
// it's _slow_
return null;
case EMFConstants.PS_USERSTYLE:
if (style != null && style.length > 0) {
float[] result = new float[style.length];
for (int i = 0; i < style.length; i++) {
result[i] = style[i];
}
return result;
} else {
return null;
}
default:
logger.warning("got unsupported pen style " + penStyle);
// do not use float[] { 1 }
// it's _slow_
return null;
}
}
/**
* @param penStyle stored pen style
* @return true if PS_INSIDEFRAME is set
*/
private boolean isInsideFrameStroke(int penStyle) {
return (penStyle & 0xFF) == EMFConstants.PS_INSIDEFRAME;
}
protected Stroke createStroke(
EMFRenderer renderer,
int penStyle,
int[] style,
float width) {
if (isInsideFrameStroke(penStyle)) {
return new InsideFrameStroke(
width,
getCap(penStyle),
getJoin(penStyle),
renderer.getMeterLimit(),
getDash(penStyle, style),
0);
} else {
return new BasicStroke(
width,
getCap(penStyle),
getJoin(penStyle),
renderer.getMeterLimit(),
getDash(penStyle, style),
0);
}
}
}