AffineTransform without transforming Stroke?

前端 未结 3 1632
-上瘾入骨i
-上瘾入骨i 2021-02-19 15:20

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

3条回答
  •  名媛妹妹
    2021-02-19 15:28

    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, the Stroke attribute in the Graphics2D context is used to generate a new Shape 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 the Graphics2D context.
    • The Shape’s path is clipped using the clip attribute in the Graphics2D context.
    • The remaining Shape, if any, is filled using the Paint and Composite attributes in the Graphics2D 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);

    solution

    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.

    discussion

    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.

提交回复
热议问题