summaryrefslogtreecommitdiff
path: root/awt/com/android/internal/awt/AndroidGraphics2D.java
diff options
context:
space:
mode:
Diffstat (limited to 'awt/com/android/internal/awt/AndroidGraphics2D.java')
-rw-r--r--awt/com/android/internal/awt/AndroidGraphics2D.java1354
1 files changed, 1354 insertions, 0 deletions
diff --git a/awt/com/android/internal/awt/AndroidGraphics2D.java b/awt/com/android/internal/awt/AndroidGraphics2D.java
new file mode 100644
index 000000000000..9a8ae02a1691
--- /dev/null
+++ b/awt/com/android/internal/awt/AndroidGraphics2D.java
@@ -0,0 +1,1354 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.awt;
+
+import com.android.internal.awt.AndroidGraphicsConfiguration;
+import com.android.internal.graphics.NativeUtils;
+
+import java.awt.AlphaComposite;
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Composite;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.Image;
+import java.awt.Polygon;
+import java.awt.Rectangle;
+import java.awt.RenderingHints;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.font.FontRenderContext;
+import java.awt.font.GlyphVector;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Area;
+import java.awt.geom.GeneralPath;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.PathIterator;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.BufferedImageOp;
+import java.awt.image.DataBuffer;
+import java.awt.image.DirectColorModel;
+import java.awt.image.ImageObserver;
+import java.awt.image.Raster;
+import java.awt.image.RenderedImage;
+import java.awt.image.SinglePixelPackedSampleModel;
+import java.awt.image.WritableRaster;
+import java.awt.image.renderable.RenderableImage;
+import java.text.AttributedCharacterIterator;
+import java.util.Map;
+
+import org.apache.harmony.awt.gl.ImageSurface;
+import org.apache.harmony.awt.gl.MultiRectArea;
+import org.apache.harmony.awt.gl.Surface;
+import org.apache.harmony.awt.gl.font.AndroidGlyphVector;
+import org.apache.harmony.awt.gl.font.FontMetricsImpl;
+import org.apache.harmony.awt.gl.image.OffscreenImage;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Path;
+
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.graphics.Typeface;
+import android.graphics.PixelXorXfermode;
+import android.view.Display;
+import android.view.WindowManager;
+import android.content.Context;
+
+public class AndroidGraphics2D extends Graphics2D {
+
+ private int displayWidth, displayHeight;
+
+ protected Surface dstSurf = null;
+ protected MultiRectArea clip = null;
+
+ protected Composite composite = AlphaComposite.SrcOver;
+ protected AffineTransform transform = new AffineTransform();
+
+ private static AndroidGraphics2D mAg;
+ private static Canvas mC;
+
+ // Android Paint
+ public static Paint mP;
+
+ private static java.awt.Font mFnt;
+
+ // Cached Matrix
+ public static Matrix mM;
+ private static FontMetrics mFm;
+ private static RenderingHints mRh;
+ private static Color mBc;
+
+ private Area mCurrClip;
+
+ public final static double RAD_360 = Math.PI / 180 * 360;
+
+ // Image drawing
+ private AndroidJavaBlitter blitter;
+ private DirectColorModel cm;
+ private SinglePixelPackedSampleModel sm;
+ private WritableRaster wr;
+
+
+ public static AndroidGraphics2D getInstance() {
+ if (mAg == null) {
+ throw new RuntimeException("AndroidGraphics2D not instantiated!");
+ }
+ return mAg;
+ }
+
+ public static AndroidGraphics2D getInstance(Context ctx, Canvas c, Paint p) {
+ if (c == null || ctx == null) {
+ throw new RuntimeException(
+ "Illegal argument, Canvas cannot be null!");
+ }
+ mAg = new AndroidGraphics2D(ctx, c, p);
+ return mAg;
+ }
+
+ private AndroidGraphics2D(Context ctx, Canvas c, Paint p) {
+ super();
+ mC = c;
+ mP = p;
+ mM = new Matrix();
+ mM.reset();
+ mM = mC.getMatrix();
+ Rect r = mC.getClipBounds();
+ int cl[] = {-1, r.top, r.left, -2, r.top, r.right, -2, r.bottom, r.right, -2, r.bottom, r.left};
+ mCurrClip = new Area(createShape(cl));
+ if(ctx != null) {
+ WindowManager wm = (WindowManager)ctx.getSystemService(Context.WINDOW_SERVICE);
+ Display d = wm.getDefaultDisplay();
+ displayWidth = d.getWidth();
+ displayHeight = d.getHeight();
+ }
+ blitter = new AndroidJavaBlitter(c);
+ cm = new DirectColorModel(32, 0xff0000, 0xff00, 0xff, 0xff000000);
+ sm = new SinglePixelPackedSampleModel(
+ DataBuffer.TYPE_INT, displayWidth, displayHeight, cm.getMasks());
+ wr = Raster.createWritableRaster(sm, null);
+ dstSurf = new ImageSurface(cm, wr);
+ }
+
+ @Override
+ public void addRenderingHints(Map<?, ?> hints) {
+ if (mRh == null) {
+ mRh = (RenderingHints) hints;
+ }
+ mRh.add((RenderingHints) hints);
+ }
+
+ public float[] getMatrix() {
+ float[] f = new float[9];
+ mC.getMatrix().getValues(f);
+ return f;
+ }
+
+ /**
+ *
+ * @return a Matrix in Android format
+ */
+ public float[] getInverseMatrix() {
+ AffineTransform af = new AffineTransform(createAWTMatrix(getMatrix()));
+ try {
+ af = af.createInverse();
+ } catch (NoninvertibleTransformException e) {
+ }
+ return createMatrix(af);
+ }
+
+ private Path getPath(Shape s) {
+ Path path = new Path();
+ PathIterator pi = s.getPathIterator(null);
+ while (pi.isDone() == false) {
+ getCurrentSegment(pi, path);
+ pi.next();
+ }
+ return path;
+ }
+
+ private void getCurrentSegment(PathIterator pi, Path path) {
+ float[] coordinates = new float[6];
+ int type = pi.currentSegment(coordinates);
+ switch (type) {
+ case PathIterator.SEG_MOVETO:
+ path.moveTo(coordinates[0], coordinates[1]);
+ break;
+ case PathIterator.SEG_LINETO:
+ path.lineTo(coordinates[0], coordinates[1]);
+ break;
+ case PathIterator.SEG_QUADTO:
+ path.quadTo(coordinates[0], coordinates[1], coordinates[2],
+ coordinates[3]);
+ break;
+ case PathIterator.SEG_CUBICTO:
+ path.cubicTo(coordinates[0], coordinates[1], coordinates[2],
+ coordinates[3], coordinates[4], coordinates[5]);
+ break;
+ case PathIterator.SEG_CLOSE:
+ path.close();
+ break;
+ default:
+ break;
+ }
+ }
+
+ private Shape createShape(int[] arr) {
+ Shape s = new GeneralPath();
+ for(int i = 0; i < arr.length; i++) {
+ int type = arr[i];
+ switch (type) {
+ case -1:
+ //MOVETO
+ ((GeneralPath)s).moveTo(arr[++i], arr[++i]);
+ break;
+ case -2:
+ //LINETO
+ ((GeneralPath)s).lineTo(arr[++i], arr[++i]);
+ break;
+ case -3:
+ //QUADTO
+ ((GeneralPath)s).quadTo(arr[++i], arr[++i], arr[++i],
+ arr[++i]);
+ break;
+ case -4:
+ //CUBICTO
+ ((GeneralPath)s).curveTo(arr[++i], arr[++i], arr[++i],
+ arr[++i], arr[++i], arr[++i]);
+ break;
+ case -5:
+ //CLOSE
+ return s;
+ default:
+ break;
+ }
+ }
+ return s;
+ }
+ /*
+ public int[] getPixels() {
+ return mC.getPixels();
+ }*/
+
+ public static float getRadian(float degree) {
+ return (float) ((Math.PI / 180) * degree);
+ }
+
+ private Shape getShape() {
+ return null;
+ }
+
+ public static float getDegree(float radian) {
+ return (float) ((180 / Math.PI) * radian);
+ }
+
+ /*
+ * Degree in radian
+ */
+ public static float getEllipsisX(float degree, float princAxis) {
+ return (float) Math.cos(degree) * princAxis;
+ }
+
+ public static float getEllipsisY(float degree, float conAxis) {
+ return (float) Math.sin(degree) * conAxis;
+ }
+
+ @Override
+ public void clip(Shape s) {
+ mC.clipPath(getPath(s));
+ }
+
+ public void setCanvas(Canvas c) {
+ mC = c;
+ }
+
+ @Override
+ public void draw(Shape s) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ Paint.Style tmp = mP.getStyle();
+ mP.setStyle(Paint.Style.STROKE);
+ mC.drawPath(getPath(s), mP);
+ mP.setStyle(tmp);
+ }
+/*
+ private ArrayList getSegments(Shape s) {
+ ArrayList arr = new ArrayList();
+ PathIterator pi = s.getPathIterator(null);
+ while (pi.isDone() == false) {
+ getCurrentSegment(pi, arr);
+ pi.next();
+ }
+ return arr;
+ }
+
+ private void getCurrentSegment(PathIterator pi, ArrayList arr) {
+ float[] coordinates = new float[6];
+ int type = pi.currentSegment(coordinates);
+ switch (type) {
+ case PathIterator.SEG_MOVETO:
+ arr.add(new Integer(-1));
+ break;
+ case PathIterator.SEG_LINETO:
+ arr.add(new Integer(-2));
+ break;
+ case PathIterator.SEG_QUADTO:
+ arr.add(new Integer(-3));
+ break;
+ case PathIterator.SEG_CUBICTO:
+ arr.add(new Integer(-4));
+ break;
+ case PathIterator.SEG_CLOSE:
+ arr.add(new Integer(-5));
+ break;
+ default:
+ break;
+ }
+ }
+*/
+ /*
+ * Convenience method, not standard AWT
+ */
+ public void draw(Path s) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ Paint.Style tmp = mP.getStyle();
+ mP.setStyle(Paint.Style.STROKE);
+ s.transform(mM);
+ mC.drawPath(s, mP);
+ mP.setStyle(tmp);
+ }
+
+ @Override
+ public void drawGlyphVector(GlyphVector g, float x, float y) {
+ // TODO draw at x, y
+ // draw(g.getOutline());
+ /*
+ Matrix matrix = new Matrix();
+ matrix.setTranslate(x, y);
+ Path pth = getPath(g.getOutline());
+ pth.transform(matrix);
+ draw(pth);
+ */
+ Path path = new Path();
+ char[] c = ((AndroidGlyphVector)g).getGlyphs();
+ mP.getTextPath(c, 0, c.length, x, y, path);
+ mC.drawPath(path, mP);
+ }
+
+ @Override
+ public void drawRenderableImage(RenderableImage img, AffineTransform xform) {
+ throw new RuntimeException("Not implemented!");
+ }
+
+ @Override
+ public void drawRenderedImage(RenderedImage img, AffineTransform xform) {
+ throw new RuntimeException("Not implemented!");
+ }
+
+ @Override
+ public void drawString(AttributedCharacterIterator iterator, float x,
+ float y) {
+ throw new RuntimeException("AttributedCharacterIterator not supported!");
+
+ }
+
+ @Override
+ public void drawString(AttributedCharacterIterator iterator, int x, int y) {
+ throw new RuntimeException("AttributedCharacterIterator not supported!");
+
+ }
+
+ @Override
+ public void drawString(String s, float x, float y) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ Paint.Style tmp = mP.getStyle();
+
+ mP.setStyle(Paint.Style.FILL);
+ Path pth = new Path();
+ mP.getTextPath(s, 0, s.length(), x, y, pth);
+ mC.drawPath(pth, mP);
+ mP.setStyle(tmp);
+ }
+
+ @Override
+ public void drawString(String str, int x, int y) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ Paint.Style tmp = mP.getStyle();
+ mP.setStrokeWidth(0);
+
+ mC.drawText(str.toCharArray(), 0, str.toCharArray().length, x, y,
+ mP);
+ mP.setStyle(tmp);
+ }
+
+ @Override
+ public void fill(Shape s) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ Paint.Style tmp = mP.getStyle();
+ mP.setStyle(Paint.Style.FILL);
+ mC.drawPath(getPath(s), mP);
+ mP.setStyle(tmp);
+ }
+
+ @Override
+ public Color getBackground() {
+ return mBc;
+ }
+
+ @Override
+ public Composite getComposite() {
+ throw new RuntimeException("Composite not implemented!");
+ }
+
+ @Override
+ public GraphicsConfiguration getDeviceConfiguration() {
+ return new AndroidGraphicsConfiguration();
+ }
+
+ @Override
+ public FontRenderContext getFontRenderContext() {
+ return new FontRenderContext(getTransform(), mP.isAntiAlias(), true);
+ }
+
+ @Override
+ public java.awt.Paint getPaint() {
+ throw new RuntimeException("AWT Paint not implemented in Android!");
+ }
+
+ public static Canvas getAndroidCanvas() {
+ return mC;
+ }
+
+ public static Paint getAndroidPaint() {
+ return mP;
+ }
+
+ @Override
+ public RenderingHints getRenderingHints() {
+ return mRh;
+ }
+
+ @Override
+ public Stroke getStroke() {
+ if (mP != null) {
+ return new BasicStroke(mP.getStrokeWidth(), mP.getStrokeCap()
+ .ordinal(), mP.getStrokeJoin().ordinal());
+ }
+ return null;
+ }
+
+ @Override
+ public AffineTransform getTransform() {
+ return new AffineTransform(createAWTMatrix(getMatrix()));
+ }
+
+ @Override
+ public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
+ // ???AWT TODO check if on stroke
+ return s.intersects(rect.getX(), rect.getY(), rect.getWidth(), rect
+ .getHeight());
+ }
+
+ @Override
+ public void rotate(double theta) {
+ mM.preRotate((float) AndroidGraphics2D
+ .getDegree((float) (RAD_360 - theta)));
+ mC.concat(mM);
+ }
+
+ @Override
+ public void rotate(double theta, double x, double y) {
+ mM.preRotate((float) AndroidGraphics2D.getDegree((float) theta),
+ (float) x, (float) y);
+ mC.concat(mM);
+ }
+
+ @Override
+ public void scale(double sx, double sy) {
+ mM.setScale((float) sx, (float) sy);
+ mC.concat(mM);
+ }
+
+ @Override
+ public void setBackground(Color color) {
+ mBc = color;
+ mC.clipRect(new Rect(0, 0, mC.getWidth(), mC.getHeight()));
+ // TODO don't limit to current clip
+ mC.drawARGB(color.getAlpha(), color.getRed(), color.getGreen(), color
+ .getBlue());
+ }
+
+ @Override
+ public void setComposite(Composite comp) {
+ throw new RuntimeException("Composite not implemented!");
+ }
+
+ public void setSpaint(Paint paint) {
+ mP = paint;
+ }
+
+ @Override
+ public void setPaint(java.awt.Paint paint) {
+ setColor((Color)paint);
+ }
+
+ @Override
+ public Object getRenderingHint(RenderingHints.Key key) {
+ if (mRh == null) {
+ return null;
+ }
+ return mRh.get(key);
+ }
+
+ @Override
+ public void setRenderingHint(RenderingHints.Key hintKey, Object hintValue) {
+ if (mRh == null) {
+ mRh = new RenderingHints(hintKey, hintValue);
+ } else {
+ mRh.put(hintKey, hintValue);
+ }
+ applyHints();
+ }
+
+ @Override
+ public void setRenderingHints(Map<?, ?> hints) {
+ mRh = (RenderingHints) hints;
+ applyHints();
+ }
+
+ private void applyHints() {
+ Object o;
+
+ // TODO do something like this:
+ /*
+ * Set s = mRh.keySet(); Iterator it = s.iterator(); while(it.hasNext()) {
+ * o = it.next(); }
+ */
+
+ // /////////////////////////////////////////////////////////////////////
+ // not supported in skia
+ /*
+ * o = mRh.get(RenderingHints.KEY_ALPHA_INTERPOLATION); if
+ * (o.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_DEFAULT)) { } else
+ * if (o.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY)) { }
+ * else if (o.equals(RenderingHints.VALUE_ALPHA_INTERPOLATION_SPEED)) { }
+ *
+ * o = mRh.get(RenderingHints.KEY_COLOR_RENDERING); if
+ * (o.equals(RenderingHints.VALUE_COLOR_RENDER_DEFAULT)) { } else if
+ * (o.equals(RenderingHints.VALUE_COLOR_RENDER_QUALITY)) { } else if
+ * (o.equals(RenderingHints.VALUE_COLOR_RENDER_SPEED)) { }
+ *
+ * o = mRh.get(RenderingHints.KEY_DITHERING); if
+ * (o.equals(RenderingHints.VALUE_DITHER_DEFAULT)) { } else if
+ * (o.equals(RenderingHints.VALUE_DITHER_DISABLE)) { } else if
+ * (o.equals(RenderingHints.VALUE_DITHER_ENABLE)) { }
+ *
+ * o = mRh.get(RenderingHints.KEY_FRACTIONALMETRICS); if
+ * (o.equals(RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT)) { } else
+ * if (o.equals(RenderingHints.VALUE_FRACTIONALMETRICS_OFF)) { } else if
+ * (o.equals(RenderingHints.VALUE_FRACTIONALMETRICS_ON)) { }
+ *
+ * o = mRh.get(RenderingHints.KEY_INTERPOLATION); if
+ * (o.equals(RenderingHints.VALUE_INTERPOLATION_BICUBIC)) { } else if
+ * (o.equals(RenderingHints.VALUE_INTERPOLATION_BILINEAR)) { } else if
+ * (o .equals(RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)) { }
+ *
+ * o = mRh.get(RenderingHints.KEY_RENDERING); if
+ * (o.equals(RenderingHints.VALUE_RENDER_DEFAULT)) { } else if
+ * (o.equals(RenderingHints.VALUE_RENDER_QUALITY)) { } else if
+ * (o.equals(RenderingHints.VALUE_RENDER_SPEED)) { }
+ *
+ * o = mRh.get(RenderingHints.KEY_STROKE_CONTROL); if
+ * (o.equals(RenderingHints.VALUE_STROKE_DEFAULT)) { } else if
+ * (o.equals(RenderingHints.VALUE_STROKE_NORMALIZE)) { } else if
+ * (o.equals(RenderingHints.VALUE_STROKE_PURE)) { }
+ */
+
+ o = mRh.get(RenderingHints.KEY_ANTIALIASING);
+ if (o != null) {
+ if (o.equals(RenderingHints.VALUE_ANTIALIAS_DEFAULT)) {
+ mP.setAntiAlias(false);
+ } else if (o.equals(RenderingHints.VALUE_ANTIALIAS_OFF)) {
+ mP.setAntiAlias(false);
+ } else if (o.equals(RenderingHints.VALUE_ANTIALIAS_ON)) {
+ mP.setAntiAlias(true);
+ }
+ }
+
+ o = mRh.get(RenderingHints.KEY_TEXT_ANTIALIASING);
+ if (o != null) {
+ if (o.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT)) {
+ mP.setAntiAlias(false);
+ } else if (o.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)) {
+ mP.setAntiAlias(false);
+ } else if (o.equals(RenderingHints.VALUE_TEXT_ANTIALIAS_ON)) {
+ mP.setAntiAlias(true);
+ }
+ }
+ }
+
+ @Override
+ public void setStroke(Stroke s) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ BasicStroke bs = (BasicStroke) s;
+ mP.setStyle(Paint.Style.STROKE);
+ mP.setStrokeWidth(bs.getLineWidth());
+
+ int cap = bs.getEndCap();
+ if (cap == 0) {
+ mP.setStrokeCap(Paint.Cap.BUTT);
+ } else if (cap == 1) {
+ mP.setStrokeCap(Paint.Cap.ROUND);
+ } else if (cap == 2) {
+ mP.setStrokeCap(Paint.Cap.SQUARE);
+ }
+
+ int join = bs.getLineJoin();
+ if (join == 0) {
+ mP.setStrokeJoin(Paint.Join.MITER);
+ } else if (join == 1) {
+ mP.setStrokeJoin(Paint.Join.ROUND);
+ } else if (join == 2) {
+ mP.setStrokeJoin(Paint.Join.BEVEL);
+ }
+ }
+
+ public static float[] createMatrix(AffineTransform Tx) {
+ double[] at = new double[9];
+ Tx.getMatrix(at);
+ float[] f = new float[at.length];
+ f[0] = (float) at[0];
+ f[1] = (float) at[2];
+ f[2] = (float) at[4];
+ f[3] = (float) at[1];
+ f[4] = (float) at[3];
+ f[5] = (float) at[5];
+ f[6] = 0;
+ f[7] = 0;
+ f[8] = 1;
+ return f;
+ }
+
+ private float[] createAWTMatrix(float[] matrix) {
+ float[] at = new float[9];
+ at[0] = matrix[0];
+ at[1] = matrix[3];
+ at[2] = matrix[1];
+ at[3] = matrix[4];
+ at[4] = matrix[2];
+ at[5] = matrix[5];
+ at[6] = 0;
+ at[7] = 0;
+ at[8] = 1;
+ return at;
+ }
+
+ public static Matrix createMatrixObj(AffineTransform Tx) {
+ Matrix m = new Matrix();
+ m.reset();
+ m.setValues(createMatrix(Tx));
+ return m;
+ }
+
+ @Override
+ public void setTransform(AffineTransform Tx) {
+ mM.reset();
+ /*
+ * if(Tx.isIdentity()) { mM = new Matrix(); }
+ */
+ mM.setValues(createMatrix(Tx));
+ Matrix m = new Matrix();
+ m.setValues(getInverseMatrix());
+ mC.concat(m);
+ mC.concat(mM);
+ }
+
+ @Override
+ public void shear(double shx, double shy) {
+ mM.setSkew((float) shx, (float) shy);
+ mC.concat(mM);
+ }
+
+ @Override
+ public void transform(AffineTransform Tx) {
+ Matrix m = new Matrix();
+ m.setValues(createMatrix(Tx));
+ mC.concat(m);
+ }
+
+ @Override
+ public void translate(double tx, double ty) {
+ mM.setTranslate((float) tx, (float) ty);
+ mC.concat(mM);
+ }
+
+ @Override
+ public void translate(int x, int y) {
+ mM.setTranslate((float) x, (float) y);
+ mC.concat(mM);
+ }
+
+ @Override
+ public void clearRect(int x, int y, int width, int height) {
+ mC.clipRect(x, y, x + width, y + height);
+ if (mBc != null) {
+ mC.drawARGB(mBc.getAlpha(), mBc.getBlue(), mBc.getGreen(), mBc
+ .getRed());
+ } else {
+ mC.drawARGB(0xff, 0xff, 0xff, 0xff);
+ }
+ }
+
+ @Override
+ public void clipRect(int x, int y, int width, int height) {
+ int cl[] = {-1, x, y, -2, x, y + width, -2, x + height, y + width, -2, x + height, y};
+ Shape shp = createShape(cl);
+ mCurrClip.intersect(new Area(shp));
+ mC.clipRect(new Rect(x, y, x + width, y + height), Region.Op.INTERSECT);
+ }
+
+ @Override
+ public void copyArea(int sx, int sy, int width, int height, int dx, int dy) {
+ copyArea(mC, sx, sy, width + dx, height + dy, dx, dy);
+ }
+
+ @Override
+ public Graphics create() {
+ return this;
+ }
+
+ @Override
+ public void dispose() {
+ mC = null;
+ mP = null;
+ }
+
+ @Override
+ public void drawArc(int x, int y, int width, int height, int sa, int ea) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mP.setStrokeWidth(0);
+ mC.drawArc(new RectF(x, y, x + width, y + height), 360 - (ea + sa),
+ ea, true, mP);
+ }
+
+
+ // ???AWT: only used for debuging, delete in final version
+ public void drawBitmap(Bitmap bm, float x, float y, Paint p) {
+ mC.drawBitmap(bm, x, y, null);
+ }
+
+ @Override
+ public boolean drawImage(Image image, int x, int y, Color bgcolor,
+ ImageObserver imageObserver) {
+
+ if(image == null) {
+ return true;
+ }
+
+ boolean done = false;
+ boolean somebits = false;
+ Surface srcSurf = null;
+ if(image instanceof OffscreenImage){
+ OffscreenImage oi = (OffscreenImage) image;
+ if((oi.getState() & ImageObserver.ERROR) != 0) {
+ return false;
+ }
+ done = oi.prepareImage(imageObserver);
+ somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0;
+ srcSurf = oi.getImageSurface();
+ }else{
+ done = true;
+ srcSurf = Surface.getImageSurface(image);
+ }
+
+ if(done || somebits) {
+ int w = srcSurf.getWidth();
+ int h = srcSurf.getHeight();
+
+ blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h, (AffineTransform) transform.clone(),
+ composite, bgcolor, clip);
+ }
+ return done;
+ }
+
+ @Override
+ public boolean drawImage(Image image, int x, int y, ImageObserver imageObserver) {
+ return drawImage(image, x, y, null, imageObserver);
+ }
+
+ @Override
+ public boolean drawImage(Image image, int x, int y, int width, int height,
+ Color bgcolor, ImageObserver imageObserver) {
+
+ if(image == null) {
+ return true;
+ }
+ if(width == 0 || height == 0) {
+ return true;
+ }
+
+ boolean done = false;
+ boolean somebits = false;
+ Surface srcSurf = null;
+
+ if(image instanceof OffscreenImage){
+ OffscreenImage oi = (OffscreenImage) image;
+ if((oi.getState() & ImageObserver.ERROR) != 0) {
+ return false;
+ }
+ done = oi.prepareImage(imageObserver);
+ somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0;
+ srcSurf = oi.getImageSurface();
+ }else{
+ done = true;
+ srcSurf = Surface.getImageSurface(image);
+ }
+
+ if(done || somebits) {
+ int w = srcSurf.getWidth();
+ int h = srcSurf.getHeight();
+ if(w == width && h == height){
+ blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
+ (AffineTransform) transform.clone(),
+ composite, bgcolor, clip);
+ }else{
+ AffineTransform xform = new AffineTransform();
+ xform.setToScale((float)width / w, (float)height / h);
+ blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
+ (AffineTransform) transform.clone(),
+ xform, composite, bgcolor, clip);
+ }
+ }
+ return done;
+ }
+
+ @Override
+ public boolean drawImage(Image image, int x, int y, int width, int height,
+ ImageObserver imageObserver) {
+ return drawImage(image, x, y, width, height, null, imageObserver);
+ }
+
+ @Override
+ public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2, Color bgcolor,
+ ImageObserver imageObserver) {
+
+ if(image == null) {
+ return true;
+ }
+ if(dx1 == dx2 || dy1 == dy2 || sx1 == sx2 || sy1 == sy2) {
+ return true;
+ }
+
+ boolean done = false;
+ boolean somebits = false;
+ Surface srcSurf = null;
+ if(image instanceof OffscreenImage){
+ OffscreenImage oi = (OffscreenImage) image;
+ if((oi.getState() & ImageObserver.ERROR) != 0) {
+ return false;
+ }
+ done = oi.prepareImage(imageObserver);
+ somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0;
+ srcSurf = oi.getImageSurface();
+ }else{
+ done = true;
+ srcSurf = Surface.getImageSurface(image);
+ }
+
+ if(done || somebits) {
+
+ int dstX = dx1;
+ int dstY = dy1;
+ int srcX = sx1;
+ int srcY = sy1;
+
+ int dstW = dx2 - dx1;
+ int dstH = dy2 - dy1;
+ int srcW = sx2 - sx1;
+ int srcH = sy2 - sy1;
+
+ if(srcW == dstW && srcH == dstH){
+ blitter.blit(srcX, srcY, srcSurf, dstX, dstY, dstSurf, srcW, srcH,
+ (AffineTransform) transform.clone(),
+ composite, bgcolor, clip);
+ }else{
+ AffineTransform xform = new AffineTransform();
+ xform.setToScale((float)dstW / srcW, (float)dstH / srcH);
+ blitter.blit(srcX, srcY, srcSurf, dstX, dstY, dstSurf, srcW, srcH,
+ (AffineTransform) transform.clone(),
+ xform, composite, bgcolor, clip);
+ }
+ }
+ return done;
+ }
+
+ @Override
+ public boolean drawImage(Image image, int dx1, int dy1, int dx2, int dy2,
+ int sx1, int sy1, int sx2, int sy2, ImageObserver imageObserver) {
+
+ return drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null,
+ imageObserver);
+ }
+
+ @Override
+ public void drawImage(BufferedImage bufImage, BufferedImageOp op,
+ int x, int y) {
+
+ if(bufImage == null) {
+ return;
+ }
+
+ if(op == null) {
+ drawImage(bufImage, x, y, null);
+ } else if(op instanceof AffineTransformOp){
+ AffineTransformOp atop = (AffineTransformOp) op;
+ AffineTransform xform = atop.getTransform();
+ Surface srcSurf = Surface.getImageSurface(bufImage);
+ int w = srcSurf.getWidth();
+ int h = srcSurf.getHeight();
+ blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
+ (AffineTransform) transform.clone(), xform,
+ composite, null, clip);
+ } else {
+ bufImage = op.filter(bufImage, null);
+ Surface srcSurf = Surface.getImageSurface(bufImage);
+ int w = srcSurf.getWidth();
+ int h = srcSurf.getHeight();
+ blitter.blit(0, 0, srcSurf, x, y, dstSurf, w, h,
+ (AffineTransform) transform.clone(),
+ composite, null, clip);
+ }
+ }
+
+ @Override
+ public boolean drawImage(Image image, AffineTransform trans,
+ ImageObserver imageObserver) {
+
+ if(image == null) {
+ return true;
+ }
+ if(trans == null || trans.isIdentity()) {
+ return drawImage(image, 0, 0, imageObserver);
+ }
+
+ boolean done = false;
+ boolean somebits = false;
+ Surface srcSurf = null;
+ if(image instanceof OffscreenImage){
+ OffscreenImage oi = (OffscreenImage) image;
+ if((oi.getState() & ImageObserver.ERROR) != 0) {
+ return false;
+ }
+ done = oi.prepareImage(imageObserver);
+ somebits = (oi.getState() & ImageObserver.SOMEBITS) != 0;
+ srcSurf = oi.getImageSurface();
+ }else{
+ done = true;
+ srcSurf = Surface.getImageSurface(image);
+ }
+
+ if(done || somebits) {
+ int w = srcSurf.getWidth();
+ int h = srcSurf.getHeight();
+ AffineTransform xform = (AffineTransform) transform.clone();
+ xform.concatenate(trans);
+ blitter.blit(0, 0, srcSurf, 0, 0, dstSurf, w, h, xform, composite,
+ null, clip);
+ }
+ return done;
+ }
+
+ @Override
+ public void drawLine(int x1, int y1, int x2, int y2) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mC.drawLine(x1, y1, x2, y2, mP);
+ }
+
+ @Override
+ public void drawOval(int x, int y, int width, int height) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mP.setStyle(Paint.Style.STROKE);
+ mC.drawOval(new RectF(x, y, x + width, y + height), mP);
+ }
+
+ @Override
+ public void drawPolygon(int[] xpoints, int[] ypoints, int npoints) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mC.drawLine(xpoints[npoints - 1], ypoints[npoints - 1], xpoints[0],
+ ypoints[0], mP);
+ for (int i = 0; i < npoints - 1; i++) {
+ mC.drawLine(xpoints[i], ypoints[i], xpoints[i + 1],
+ ypoints[i + 1], mP);
+ }
+ }
+
+ @Override
+ public void drawPolyline(int[] xpoints, int[] ypoints, int npoints) {
+ for (int i = 0; i < npoints - 1; i++) {
+ drawLine(xpoints[i], ypoints[i], xpoints[i + 1], ypoints[i + 1]);
+ }
+
+ }
+
+ @Override
+ public void drawRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mC.drawRoundRect(new RectF(x, y, width, height), arcWidth,
+ arcHeight, mP);
+ }
+
+ @Override
+ public void fillArc(int x, int y, int width, int height, int sa, int ea) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+
+ Paint.Style tmp = mP.getStyle();
+ mP.setStyle(Paint.Style.FILL_AND_STROKE);
+ mC.drawArc(new RectF(x, y, x + width, y + height), 360 - (sa + ea),
+ ea, true, mP);
+
+ mP.setStyle(tmp);
+ }
+
+ @Override
+ public void fillOval(int x, int y, int width, int height) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ Paint.Style tmp = mP.getStyle();
+ mP.setStyle(Paint.Style.FILL);
+ mC.drawOval(new RectF(x, y, x + width, y + height), mP);
+ mP.setStyle(tmp);
+ }
+
+ @Override
+ public void fillPolygon(int[] xpoints, int[] ypoints, int npoints) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ Paint.Style tmp = mP.getStyle();
+ mC.save(Canvas.CLIP_SAVE_FLAG);
+
+ mP.setStyle(Paint.Style.FILL);
+
+ GeneralPath filledPolygon = new GeneralPath(
+ GeneralPath.WIND_EVEN_ODD, npoints);
+ filledPolygon.moveTo(xpoints[0], ypoints[0]);
+ for (int index = 1; index < xpoints.length; index++) {
+ filledPolygon.lineTo(xpoints[index], ypoints[index]);
+ }
+ filledPolygon.closePath();
+ Path path = getPath(filledPolygon);
+ mC.clipPath(path);
+ mC.drawPath(path, mP);
+
+ mP.setStyle(tmp);
+ mC.restore();
+ }
+
+ @Override
+ public void fillRect(int x, int y, int width, int height) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ Paint.Style tmp = mP.getStyle();
+ mP.setStyle(Paint.Style.FILL);
+ mC.drawRect(new Rect(x, y, x + width, y + height), mP);
+ mP.setStyle(tmp);
+ }
+
+ @Override
+ public void drawRect(int x, int y, int width, int height) {
+ int[] xpoints = { x, x, x + width, x + width };
+ int[] ypoints = { y, y + height, y + height, y };
+ drawPolygon(xpoints, ypoints, 4);
+ }
+
+ @Override
+ public void fillRoundRect(int x, int y, int width, int height,
+ int arcWidth, int arcHeight) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mP.setStyle(Paint.Style.FILL);
+ mC.drawRoundRect(new RectF(x, y, x + width, y + height), arcWidth,
+ arcHeight, mP);
+ }
+
+ @Override
+ public Shape getClip() {
+ return mCurrClip;
+ }
+
+ @Override
+ public Rectangle getClipBounds() {
+ Rect r = mC.getClipBounds();
+ return new Rectangle(r.left, r.top, r.width(), r.height());
+ }
+
+ @Override
+ public Color getColor() {
+ if (mP != null) {
+ return new Color(mP.getColor());
+ }
+ return null;
+ }
+
+ @Override
+ public Font getFont() {
+ return mFnt;
+ }
+
+ @Override
+ public FontMetrics getFontMetrics(Font font) {
+ mFm = new FontMetricsImpl(font);
+ return mFm;
+ }
+
+ @Override
+ public void setClip(int x, int y, int width, int height) {
+ int cl[] = {-1, x, y, -2, x, y + width, -2, x + height, y + width, -2, x + height, y};
+ mCurrClip = new Area(createShape(cl));
+ mC.clipRect(x, y, x + width, y + height, Region.Op.REPLACE);
+
+ }
+
+ @Override
+ public void setClip(Shape clip) {
+ mCurrClip = new Area(clip);
+ mC.clipPath(getPath(clip), Region.Op.REPLACE);
+ }
+
+ @Override
+ public void setColor(Color c) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mP.setColor(c.getRGB());
+ }
+
+ /**
+ * Font mapping:
+ *
+ * Family:
+ *
+ * Android AWT
+ * -------------------------------------
+ * serif Serif / TimesRoman
+ * sans-serif SansSerif / Helvetica
+ * monospace Monospaced / Courier
+ *
+ * Style:
+ *
+ * Android AWT
+ * -------------------------------------
+ * normal Plain
+ * bold bold
+ * italic italic
+ *
+ */
+ @Override
+ public void setFont(Font font) {
+ if (font == null) {
+ return;
+ }
+ if (mP == null) {
+ mP = new Paint();
+ }
+
+ mFnt = font;
+ Typeface tf = null;
+ int sty = font.getStyle();
+ String nam = font.getName();
+ String aF = "";
+ if (nam != null) {
+ if (nam.equalsIgnoreCase("Serif")
+ || nam.equalsIgnoreCase("TimesRoman")) {
+ aF = "serif";
+ } else if (nam.equalsIgnoreCase("SansSerif")
+ || nam.equalsIgnoreCase("Helvetica")) {
+ aF = "sans-serif";
+ } else if (nam.equalsIgnoreCase("Monospaced")
+ || nam.equalsIgnoreCase("Courier")) {
+ aF = "monospace";
+ }
+ }
+
+ switch (sty) {
+ case Font.PLAIN:
+ tf = Typeface.create(aF, Typeface.NORMAL);
+ break;
+ case Font.BOLD:
+ tf = Typeface.create(aF, Typeface.BOLD);
+ break;
+ case Font.ITALIC:
+ tf = Typeface.create(aF, Typeface.ITALIC);
+ break;
+ case Font.BOLD | Font.ITALIC:
+ tf = Typeface.create(aF, Typeface.BOLD_ITALIC);
+ break;
+ default:
+ tf = Typeface.DEFAULT;
+ }
+
+ mP.setTextSize(font.getSize());
+ mP.setTypeface(tf);
+ }
+
+ @Override
+ public void drawBytes(byte[] data, int offset, int length, int x, int y) {
+ drawString(new String(data, offset, length), x, y);
+ }
+
+ @Override
+ public void drawPolygon(Polygon p) {
+ drawPolygon(p.xpoints, p.ypoints, p.npoints);
+ }
+
+ @Override
+ public void fillPolygon(Polygon p) {
+ fillPolygon(p.xpoints, p.ypoints, p.npoints);
+ }
+
+ @Override
+ public Rectangle getClipBounds(Rectangle r) {
+ Shape clip = getClip();
+ if (clip != null) {
+ Rectangle b = clip.getBounds();
+ r.x = b.x;
+ r.y = b.y;
+ r.width = b.width;
+ r.height = b.height;
+ }
+ return r;
+ }
+
+ @Override
+ public boolean hitClip(int x, int y, int width, int height) {
+ return getClipBounds().intersects(new Rectangle(x, y, width, height));
+ }
+
+ @Override
+ public void drawChars(char[] data, int offset, int length, int x, int y) {
+ mC.drawText(data, offset, length, x, y, mP);
+ }
+
+ @Override
+ public void setPaintMode() {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mP.setXfermode(null);
+ }
+
+ @Override
+ public void setXORMode(Color color) {
+ if (mP == null) {
+ mP = new Paint();
+ }
+ mP.setXfermode(new PixelXorXfermode(color.getRGB()));
+ }
+
+ @Override
+ public void fill3DRect(int x, int y, int width, int height, boolean raised) {
+ Color color = getColor();
+ Color colorUp, colorDown;
+ if (raised) {
+ colorUp = color.brighter();
+ colorDown = color.darker();
+ setColor(color);
+ } else {
+ colorUp = color.darker();
+ colorDown = color.brighter();
+ setColor(colorUp);
+ }
+
+ width--;
+ height--;
+ fillRect(x+1, y+1, width-1, height-1);
+
+ setColor(colorUp);
+ fillRect(x, y, width, 1);
+ fillRect(x, y+1, 1, height);
+
+ setColor(colorDown);
+ fillRect(x+width, y, 1, height);
+ fillRect(x+1, y+height, width, 1);
+ }
+
+ @Override
+ public void draw3DRect(int x, int y, int width, int height, boolean raised) {
+ Color color = getColor();
+ Color colorUp, colorDown;
+ if (raised) {
+ colorUp = color.brighter();
+ colorDown = color.darker();
+ } else {
+ colorUp = color.darker();
+ colorDown = color.brighter();
+ }
+
+ setColor(colorUp);
+ fillRect(x, y, width, 1);
+ fillRect(x, y+1, 1, height);
+
+ setColor(colorDown);
+ fillRect(x+width, y, 1, height);
+ fillRect(x+1, y+height, width, 1);
+ }
+
+ public void copyArea(Canvas canvas, int sx, int sy, int width, int height, int dx, int dy) {
+ sx += getTransform().getTranslateX();
+ sy += getTransform().getTranslateY();
+
+ NativeUtils.nativeScrollRect(canvas,
+ new Rect(sx, sy, sx + width, sy + height),
+ dx, dy);
+ }
+}