When using the Graphics2D scale()
function with two different parameters (scaling by different ratios in x- and y-direction), everything drawn later on this Graphic
There is a simpler and less 'hacky' solution than the original TransformedStroke
answer.
I got the idea when I read how the rendering pipeline works:
(from http://docs.oracle.com/javase/7/docs/technotes/guides/2d/spec/j2d-awt.html)
- If the
Shape
is to be stroked, theStroke
attribute in theGraphics2D
context is used to generate a newShape
that encompasses the stroked path.- The coordinates of the
Shape
’s path are transformed from user space into device space according to the transform attribute in theGraphics2D
context.- The
Shape
’s path is clipped using the clip attribute in theGraphics2D
context.- The remaining
Shape
, if any, is filled using thePaint
andComposite
attributes in theGraphics2D
context.
What you, and I, ideally seek is a way to swap the first two steps.
If you look closely at the second step, TransformedStroke
already contains part of the solution.
Shape sTrans = transform.createTransformedShape(s);
In stead of:
g.scale(
...)
, g.transform(
...)
, whatever,
g.draw(new Rectangle( 1, 2, 2, 4));
Or, using TransformedStroke
:
g.setStroke(new TransformedStroke(new BasicStroke(2f), g.getTransform());
g.draw(new Rectangle( 1, 2, 2, 4));
I propose you do:
transform =
whatever,
g.draw(transform.createTransformedShape(new Rectangle( 1, 2, 2, 4));
Don't transform g
anymore. Ever. Transform the shapes instead, using a transform that you make and modify yourself.
TransformedStroke
feels more like a 'hack' than a way the authors of Stroke
meant the interface to be used. It also requires an extra class.
This solution keeps a separate Transform
around and modifies the Shape
instead of transforming the Graphics
object. This is however in no way a hack, because I'm not abusing existing functionality but using API functionality exactly how it's meant to be used. I'm just using the more explicit parts of the API instead of the 'shortcut'/'convenience' methods of the API (g.scale()
etc.).
Performance-wise, this solution can only be more efficient. Effectively one step is now skipped. In the original solution, TransformedStroke
transforms the shape twice and strokes the shape once. This solution transforms the shape explicitly and the *current* stroke strokes the shape once.