package net.pbdavey.awt; import java.util.HashMap; import org.apache.poi.xslf.usermodel.XSLFRenderingHint; import and.awt.BasicStroke; import and.awt.BufferedImage; import and.awt.Color; import and.awt.Graphics; import and.awt.Image; import and.awt.Shape; import and.awt.Stroke; import and.awt.geom.AffineTransform; import and.awt.geom.PathIterator; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Paint.Style; import android.graphics.Path; import android.graphics.Rect; import android.util.Log; /** * So far it appears that Graphics2D is roughly equivalent to a Canvas with Paint. * The Paint object contains information regarding Fonts and FontMetrics, while * the Canvas is a more raw drawing tool. * @author pbdavey * */ public class Graphics2D extends Graphics { Paint paint; public Canvas canvas; Font font = new Font(); Stroke stroke; Color color = Color.white; Color bgColor; AffineTransform transform; public Graphics2D(Canvas canvas) { this.canvas = canvas; this.transform = new AffineTransform(); this.paint = new Paint(); paint.setAntiAlias(true); } public void setColor(Color color) { this.color = color; paint.setColor(this.color.getRGB()); } public Color getColor() { return this.color; } /** * TODO: This shouldn't accept BasicStroke, rather a generic Stroke * The issue here has to do with actually stroking the Shape, which * is delegated to a rendering pipe. See * {@link and.awt.BasicStroke#createStrokedShape} * @param stroke */ public void setStroke(Stroke pStroke) { this.stroke = pStroke; BasicStroke stroke = (BasicStroke) pStroke; Paint.Cap cap = Paint.Cap.BUTT; switch(stroke.getEndCap()) { case BasicStroke.CAP_BUTT: cap = Paint.Cap.BUTT; break; case BasicStroke.CAP_ROUND: cap = Paint.Cap.ROUND; break; case BasicStroke.CAP_SQUARE: cap = Paint.Cap.SQUARE; break; } this.paint.setStrokeCap(cap); Paint.Join join = Paint.Join.BEVEL; switch(stroke.getLineJoin()) { case BasicStroke.JOIN_BEVEL: join = Paint.Join.BEVEL; break; case BasicStroke.JOIN_MITER: join = Paint.Join.MITER; break; case BasicStroke.JOIN_ROUND: join = Paint.Join.ROUND; break; } this.paint.setStrokeJoin(join); this.paint.setStrokeMiter(stroke.getMiterLimit()); this.paint.setStrokeWidth(stroke.getLineWidth()); } public Stroke getStroke() { return this.stroke; } public void draw(Shape s) { PathIterator pi = s.getPathIterator(null); Path path = convertAwtPathToAndroid(pi); // Draw the outline, don't fill paint.setStyle(Style.STROKE); canvas.drawPath(path, paint); } public void fill(Shape s) { PathIterator pi = s.getPathIterator(null); Path path = convertAwtPathToAndroid(pi); // Draw the outline and fill paint.setStyle(Style.FILL_AND_STROKE); canvas.drawPath(path, paint);; } private Path convertAwtPathToAndroid(PathIterator pi) { Path path = new Path(); float [] coords = new float [6]; while (!pi.isDone()) { int windingRule = pi.getWindingRule(); if (windingRule == PathIterator.WIND_EVEN_ODD) { path.setFillType(Path.FillType.EVEN_ODD); } else { path.setFillType(Path.FillType.WINDING); } int pathType = pi.currentSegment(coords); switch (pathType) { case PathIterator.SEG_CLOSE: path.close(); break; case PathIterator.SEG_CUBICTO: path.cubicTo(coords [0], coords [1], coords [2], coords [3], coords [4], coords [5]); break; case PathIterator.SEG_LINETO: path.lineTo(coords [0], coords [1]); break; case PathIterator.SEG_MOVETO: path.moveTo(coords [0], coords [1]); break; case PathIterator.SEG_QUADTO: path.quadTo(coords [0], coords [1], coords [2], coords [3]); break; } pi.next(); } return path; } public void translate(double tx, double ty) { this.transform.translate(tx, ty); canvas.translate((float)tx, (float)ty); } public void rotate(double theta) { this.transform.rotate(theta); canvas.rotate((float)Math.toDegrees(theta)); } public void scale(double sx, double sy) { this.transform.scale(sx, sy); canvas.scale((float)sx, (float)sy); } public void setTransform(AffineTransform Tx) { // XXX: DD this.transform = Tx; } public AffineTransform getTransform() { return this.transform; } public void drawImage(Image img, int x, int y, Object o) { canvas.drawBitmap(img.bm, x, y, paint); } public void drawImage(BufferedImage img, int x, int y, int width, int height, Object o) { canvas.drawBitmap(img.bm, new Rect(0, 0, img.getWidth(), img.getHeight()), new Rect(x, y, width, height), paint); } public void setPaint(Color lineColor) { paint.setColor(lineColor.getRGB()); } public void drawRenderedImage(BufferedImage img, AffineTransform at) { Log.d("drawRenderedImage", "sx: " + at.getScaleX() + ", sy: " + at.getScaleY() + ", tx: " + at.getTranslateX() + ", ty: " + at.getTranslateY()); Matrix m = new Matrix(); float[] values = new float[9]; values[Matrix.MSCALE_X] = (float) at.getScaleX(); values[Matrix.MSCALE_Y] = (float)at.getScaleY(); values[Matrix.MTRANS_X] = (float)at.getTranslateX(); values[Matrix.MTRANS_Y] = (float)at.getTranslateY(); values[Matrix.MSKEW_X] = (float)at.getShearX(); values[Matrix.MSKEW_Y] = (float)at.getShearY(); values[Matrix.MPERSP_2] = 1; m.setValues(values); canvas.drawBitmap(img.bm, m, paint); } public void setPaint(and.awt.Paint fill) { if (fill instanceof Color) { Color c = (Color) fill; paint.setColor(c.getRGB()); } } public AffineTransform getRenderingHint(XSLFRenderingHint groupTransform) { return affineTransformHintMap.get(groupTransform); } HashMap<XSLFRenderingHint, AffineTransform> affineTransformHintMap = new HashMap<XSLFRenderingHint, AffineTransform>(); public void setRenderingHint(XSLFRenderingHint hint, boolean b) { if (hint == XSLFRenderingHint.GSAVE) { canvas.save(); } else if (hint == XSLFRenderingHint.GRESTORE) { canvas.restore(); } } public void setRenderingHint(XSLFRenderingHint groupTransform, AffineTransform tx0) { affineTransformHintMap.put(groupTransform, tx0); } }