123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- package org.apache.poi.sl.draw;
-
- import java.awt.Graphics2D;
- import java.awt.geom.AffineTransform;
- import java.awt.geom.Rectangle2D;
-
- import org.apache.poi.sl.usermodel.PlaceableShape;
- import org.apache.poi.sl.usermodel.Shape;
-
-
- public class DrawShape<T extends Shape> implements Drawable {
-
- protected final T shape;
-
- public DrawShape(T shape) {
- this.shape = shape;
- }
-
- /**
- * Apply 2-D transforms before drawing this shape. This includes rotation and flipping.
- *
- * @param graphics the graphics whos transform matrix will be modified
- */
- public void applyTransform(Graphics2D graphics) {
- if (!(shape instanceof PlaceableShape)) return;
-
- PlaceableShape ps = (PlaceableShape)shape;
- AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);
- final Rectangle2D anchor = (tx != null)
- ? tx.createTransformedShape(ps.getAnchor()).getBounds2D()
- : ps.getAnchor();
-
- // rotation
- double rotation = ps.getRotation();
- if (rotation != 0.) {
- // PowerPoint rotates shapes relative to the geometric center
- double centerX = anchor.getCenterX();
- double centerY = anchor.getCenterY();
-
- // normalize rotation
- rotation %= 360.;
- if (rotation < 0) rotation += 360.;
- int quadrant = (((int)rotation+45)/90)%4;
- double scaleX = 1.0, scaleY = 1.0;
-
- // scale to bounding box (bug #53176)
- if (quadrant == 1 || quadrant == 3) {
- // In quadrant 1 and 3, which is basically a shape in a more or less portrait orientation
- // (45-135 degrees and 225-315 degrees), we need to first rotate the shape by a multiple
- // of 90 degrees and then resize the bounding box to its original bbox. After that we can
- // rotate the shape to the exact rotation amount.
- // It's strange that you'll need to rotate the shape back and forth again, but you can
- // think of it, as if you paint the shape on a canvas. First you rotate the canvas, which might
- // be already (differently) scaled, so you can paint the shape in its default orientation
- // and later on, turn it around again to compare it with its original size ...
-
- // graphics coordinate space
- AffineTransform txg = new AffineTransform();
- txg.translate(centerX, centerY);
- txg.rotate(Math.toRadians(90));
- txg.translate(-centerX, -centerY);
-
- boolean oldVariant = true;
- Rectangle2D anchor2;
-
- if (oldVariant) {
- // shape coordinate space
- AffineTransform txs = new AffineTransform(tx);
- txs.translate(centerX, centerY);
- txs.rotate(Math.toRadians(90));
- txs.translate(-centerX, -centerY);
- txg.concatenate(txs);
- anchor2 = txg.createTransformedShape(ps.getAnchor()).getBounds2D();
- } else {
- anchor2 = txg.createTransformedShape(anchor).getBounds2D();
- }
-
- scaleX = anchor.getWidth() == 0. ? 1.0 : anchor.getWidth() / anchor2.getWidth();
- scaleY = anchor.getHeight() == 0. ? 1.0 : anchor.getHeight() / anchor2.getHeight();
-
- graphics.translate(centerX, centerY);
- graphics.rotate(Math.toRadians(rotation-quadrant*90.));
- graphics.scale(scaleX, scaleY);
- graphics.rotate(Math.toRadians(quadrant*90));
- graphics.translate(-centerX, -centerY);
- } else {
- graphics.translate(centerX, centerY);
- graphics.rotate(Math.toRadians(rotation));
- graphics.scale(scaleX, scaleY);
- graphics.translate(-centerX, -centerY);
- }
- // transformation is applied reversed ...
- }
-
- //flip horizontal
- if (ps.getFlipHorizontal()) {
- graphics.translate(anchor.getX() + anchor.getWidth(), anchor.getY());
- graphics.scale(-1, 1);
- graphics.translate(-anchor.getX(), -anchor.getY());
- }
-
- //flip vertical
- if (ps.getFlipVertical()) {
- graphics.translate(anchor.getX(), anchor.getY() + anchor.getHeight());
- graphics.scale(1, -1);
- graphics.translate(-anchor.getX(), -anchor.getY());
- }
- }
-
-
- public void draw(Graphics2D graphics) {
- }
-
- public void drawContent(Graphics2D context) {
- }
-
- public static Rectangle2D getAnchor(Graphics2D graphics, PlaceableShape shape) {
- return getAnchor(graphics, shape.getAnchor());
- }
-
- public static Rectangle2D getAnchor(Graphics2D graphics, Rectangle2D anchor) {
- if(graphics == null) {
- return anchor;
- }
-
- AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);
- if(tx != null) {
- anchor = tx.createTransformedShape(anchor).getBounds2D();
- }
- return anchor;
- }
- }
|