am ace6a5cf: Merge change 21408 into donut

Merge commit 'ace6a5cfc0d14a909b4b95bdfe16609188125baf' into eclair

* commit 'ace6a5cfc0d14a909b4b95bdfe16609188125baf':
  Improved drawing/matrix support in layoutlib
This commit is contained in:
Xavier Ducrohet
2009-08-18 11:01:19 -07:00
committed by Android Git Automerger
6 changed files with 274 additions and 155 deletions

View File

@@ -16,7 +16,6 @@
package android.graphics; package android.graphics;
import com.android.layoutlib.bridge.BridgeCanvas;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.File; import java.io.File;
@@ -25,15 +24,15 @@ import java.io.IOException;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
public final class Bitmap extends _Original_Bitmap { public final class Bitmap extends _Original_Bitmap {
private BufferedImage mImage; private BufferedImage mImage;
public Bitmap(File input) throws IOException { public Bitmap(File input) throws IOException {
super(1, true, null); super(1, true, null);
mImage = ImageIO.read(input); mImage = ImageIO.read(input);
} }
Bitmap(BufferedImage image) { Bitmap(BufferedImage image) {
super(1, true, null); super(1, true, null);
mImage = image; mImage = image;
@@ -42,9 +41,9 @@ public final class Bitmap extends _Original_Bitmap {
public BufferedImage getImage() { public BufferedImage getImage() {
return mImage; return mImage;
} }
// ----- overriden methods // ----- overriden methods
public enum Config { public enum Config {
// these native values must match up with the enum in SkBitmap.h // these native values must match up with the enum in SkBitmap.h
ALPHA_8 (2), ALPHA_8 (2),
@@ -56,27 +55,26 @@ public final class Bitmap extends _Original_Bitmap {
this.nativeInt = ni; this.nativeInt = ni;
} }
final int nativeInt; final int nativeInt;
/* package */ static Config nativeToConfig(int ni) { /* package */ static Config nativeToConfig(int ni) {
return sConfigs[ni]; return sConfigs[ni];
} }
private static Config sConfigs[] = { private static Config sConfigs[] = {
null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888 null, null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888
}; };
} }
@Override @Override
public int getWidth() { public int getWidth() {
return mImage.getWidth(); return mImage.getWidth();
} }
@Override @Override
public int getHeight() { public int getHeight() {
return mImage.getHeight(); return mImage.getHeight();
} }
/** /**
* Returns an immutable bitmap from the source bitmap. The new bitmap may * Returns an immutable bitmap from the source bitmap. The new bitmap may
* be the same object as source, or a copy may have been made. * be the same object as source, or a copy may have been made.
@@ -100,7 +98,7 @@ public final class Bitmap extends _Original_Bitmap {
int width, int height) { int width, int height) {
return new Bitmap(source.mImage.getSubimage(x, y, width, height)); return new Bitmap(source.mImage.getSubimage(x, y, width, height));
} }
/** /**
* Returns an immutable bitmap from subset of the source bitmap, * Returns an immutable bitmap from subset of the source bitmap,
* transformed by the optional matrix. * transformed by the optional matrix.
@@ -158,7 +156,7 @@ public final class Bitmap extends _Original_Bitmap {
neww = Math.round(deviceR.width()); neww = Math.round(deviceR.width());
newh = Math.round(deviceR.height()); newh = Math.round(deviceR.height());
BridgeCanvas canvas = new BridgeCanvas(neww, newh); Canvas canvas = new Canvas(neww, newh);
canvas.translate(-deviceR.left, -deviceR.top); canvas.translate(-deviceR.left, -deviceR.top);
canvas.concat(m); canvas.concat(m);
@@ -169,10 +167,10 @@ public final class Bitmap extends _Original_Bitmap {
} }
canvas.drawBitmap(source, srcR, dstR, paint); canvas.drawBitmap(source, srcR, dstR, paint);
return new Bitmap(canvas.getImage()); return new Bitmap(canvas.getImage());
} }
/** /**
* Returns a mutable bitmap with the specified width and height. * Returns a mutable bitmap with the specified width and height.
* *
@@ -184,7 +182,7 @@ public final class Bitmap extends _Original_Bitmap {
public static Bitmap createBitmap(int width, int height, Config config) { public static Bitmap createBitmap(int width, int height, Config config) {
return new Bitmap(new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)); return new Bitmap(new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB));
} }
/** /**
* Returns a immutable bitmap with the specified width and height, with each * Returns a immutable bitmap with the specified width and height, with each
* pixel value set to the corresponding value in the colors array. * pixel value set to the corresponding value in the colors array.
@@ -215,7 +213,7 @@ public final class Bitmap extends _Original_Bitmap {
|| (lastScanline + width > length)) { || (lastScanline + width > length)) {
throw new ArrayIndexOutOfBoundsException(); throw new ArrayIndexOutOfBoundsException();
} }
// TODO: create an immutable bitmap... // TODO: create an immutable bitmap...
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@@ -14,24 +14,16 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.layoutlib.bridge; package android.graphics;
import com.android.layoutlib.api.ILayoutLog; import com.android.layoutlib.api.ILayoutLog;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.DrawFilter; import android.graphics.DrawFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Picture; import android.graphics.Picture;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Region; import android.graphics.Region;
import android.graphics.Shader;
import android.graphics.Xfermode; import android.graphics.Xfermode;
import android.graphics.Paint.Align; import android.graphics.Paint.Align;
import android.graphics.Paint.Style; import android.graphics.Paint.Style;
@@ -43,6 +35,7 @@ import java.awt.Composite;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.Rectangle; import java.awt.Rectangle;
import java.awt.RenderingHints; import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.util.Stack; import java.util.Stack;
@@ -51,36 +44,59 @@ import javax.microedition.khronos.opengles.GL;
/** /**
* Re-implementation of the Canvas, 100% in java on top of a BufferedImage. * Re-implementation of the Canvas, 100% in java on top of a BufferedImage.
*/ */
public class BridgeCanvas extends Canvas { public class Canvas extends _Original_Canvas {
private BufferedImage mBufferedImage; private BufferedImage mBufferedImage;
private final Stack<Graphics2D> mGraphicsStack = new Stack<Graphics2D>(); private final Stack<Graphics2D> mGraphicsStack = new Stack<Graphics2D>();
private final ILayoutLog mLogger; private final ILayoutLog mLogger;
public BridgeCanvas(int width, int height, ILayoutLog logger) { public Canvas() {
mLogger = null;
// the mBufferedImage will be taken from a bitmap in #setBitmap()
}
public Canvas(Bitmap bitmap) {
mLogger = null;
mBufferedImage = bitmap.getImage();
mGraphicsStack.push(mBufferedImage.createGraphics());
}
public Canvas(int nativeCanvas) {
mLogger = null;
throw new UnsupportedOperationException("Can't create Canvas(int)");
}
public Canvas(javax.microedition.khronos.opengles.GL gl) {
mLogger = null;
throw new UnsupportedOperationException("Can't create Canvas(javax.microedition.khronos.opengles.GL)");
}
// custom constructors for our use.
public Canvas(int width, int height, ILayoutLog logger) {
mLogger = logger; mLogger = logger;
mBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); mBufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
mGraphicsStack.push(mBufferedImage.createGraphics()); mGraphicsStack.push(mBufferedImage.createGraphics());
} }
public BridgeCanvas(int width, int height) { public Canvas(int width, int height) {
this(width, height, null /* logger*/); this(width, height, null /* logger*/);
} }
// custom mehtods
public BufferedImage getImage() { public BufferedImage getImage() {
return mBufferedImage; return mBufferedImage;
} }
Graphics2D getGraphics2d() { public Graphics2D getGraphics2d() {
return mGraphicsStack.peek(); return mGraphicsStack.peek();
} }
void dispose() { public void dispose() {
while (mGraphicsStack.size() > 0) { while (mGraphicsStack.size() > 0) {
mGraphicsStack.pop().dispose(); mGraphicsStack.pop().dispose();
} }
} }
/** /**
* Creates a new {@link Graphics2D} based on the {@link Paint} parameters. * Creates a new {@link Graphics2D} based on the {@link Paint} parameters.
* <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used. * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used.
@@ -91,11 +107,11 @@ public class BridgeCanvas extends Canvas {
g.setColor(new Color(paint.getColor())); g.setColor(new Color(paint.getColor()));
int alpha = paint.getAlpha(); int alpha = paint.getAlpha();
float falpha = alpha / 255.f; float falpha = alpha / 255.f;
Xfermode xfermode = paint.getXfermode(); Xfermode xfermode = paint.getXfermode();
if (xfermode instanceof PorterDuffXfermode) { if (xfermode instanceof PorterDuffXfermode) {
PorterDuff.Mode mode = ((PorterDuffXfermode)xfermode).getMode(); PorterDuff.Mode mode = ((PorterDuffXfermode)xfermode).getMode();
setModeInGraphics(mode, g, falpha); setModeInGraphics(mode, g, falpha);
} else { } else {
if (mLogger != null && xfermode != null) { if (mLogger != null && xfermode != null) {
@@ -105,7 +121,7 @@ public class BridgeCanvas extends Canvas {
} }
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha)); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha));
} }
Shader shader = paint.getShader(); Shader shader = paint.getShader();
if (shader instanceof LinearGradient) { if (shader instanceof LinearGradient) {
g.setPaint(((LinearGradient)shader).getPaint()); g.setPaint(((LinearGradient)shader).getPaint());
@@ -116,10 +132,10 @@ public class BridgeCanvas extends Canvas {
shader.getClass().getCanonicalName())); shader.getClass().getCanonicalName()));
} }
} }
return g; return g;
} }
private void setModeInGraphics(PorterDuff.Mode mode, Graphics2D g, float falpha) { private void setModeInGraphics(PorterDuff.Mode mode, Graphics2D g, float falpha) {
switch (mode) { switch (mode) {
case CLEAR: case CLEAR:
@@ -168,14 +184,43 @@ public class BridgeCanvas extends Canvas {
break; break;
} }
} }
// -------------------- // --------------------
// OVERRIDEN ENUMS
// This is needed since we rename Canvas into _Original_Canvas
// --------------------
public enum EdgeType {
BW(0), //!< treat edges by just rounding to nearest pixel boundary
AA(1); //!< treat edges by rounding-out, since they may be antialiased
EdgeType(int nativeInt) {
this.nativeInt = nativeInt;
}
final int nativeInt;
}
// --------------------
// OVERRIDEN METHODS
// --------------------
@Override @Override
public void finalize() throws Throwable { public void finalize() throws Throwable {
// pass // pass
} }
/* (non-Javadoc)
* @see android.graphics.Canvas#setBitmap(android.graphics.Bitmap)
*/
@Override
public void setBitmap(Bitmap bitmap) {
mBufferedImage = bitmap.getImage();
mGraphicsStack.push(mBufferedImage.createGraphics());
}
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#translate(float, float) * @see android.graphics.Canvas#translate(float, float)
*/ */
@@ -183,7 +228,7 @@ public class BridgeCanvas extends Canvas {
public void translate(float dx, float dy) { public void translate(float dx, float dy) {
getGraphics2d().translate(dx, dy); getGraphics2d().translate(dx, dy);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#save() * @see android.graphics.Canvas#save()
*/ */
@@ -191,7 +236,7 @@ public class BridgeCanvas extends Canvas {
public int save() { public int save() {
Graphics2D g = (Graphics2D)getGraphics2d().create(); Graphics2D g = (Graphics2D)getGraphics2d().create();
mGraphicsStack.push(g); mGraphicsStack.push(g);
return mGraphicsStack.size() - 1; return mGraphicsStack.size() - 1;
} }
@@ -203,7 +248,7 @@ public class BridgeCanvas extends Canvas {
// For now we ignore saveFlags // For now we ignore saveFlags
return save(); return save();
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#restore() * @see android.graphics.Canvas#restore()
*/ */
@@ -221,7 +266,7 @@ public class BridgeCanvas extends Canvas {
mGraphicsStack.pop(); mGraphicsStack.pop();
} }
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#getSaveCount() * @see android.graphics.Canvas#getSaveCount()
*/ */
@@ -229,8 +274,8 @@ public class BridgeCanvas extends Canvas {
public int getSaveCount() { public int getSaveCount() {
return mGraphicsStack.size() - 1; return mGraphicsStack.size() - 1;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#clipRect(float, float, float, float, android.graphics.Region.Op) * @see android.graphics.Canvas#clipRect(float, float, float, float, android.graphics.Region.Op)
*/ */
@@ -288,23 +333,36 @@ public class BridgeCanvas extends Canvas {
public boolean clipRect(RectF rect) { public boolean clipRect(RectF rect) {
return clipRect(rect.left, rect.top, rect.right, rect.bottom); return clipRect(rect.left, rect.top, rect.right, rect.bottom);
} }
@Override
public boolean quickReject(RectF rect, EdgeType type) { public boolean quickReject(RectF rect, EdgeType type) {
return false; return false;
} }
@Override @Override
public boolean quickReject(RectF rect, _Original_Canvas.EdgeType type) {
throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
}
public boolean quickReject(Path path, EdgeType type) { public boolean quickReject(Path path, EdgeType type) {
return false; return false;
} }
@Override @Override
public boolean quickReject(Path path, _Original_Canvas.EdgeType type) {
throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
}
public boolean quickReject(float left, float top, float right, float bottom, public boolean quickReject(float left, float top, float right, float bottom,
EdgeType type) { EdgeType type) {
return false; return false;
} }
@Override
public boolean quickReject(float left, float top, float right, float bottom,
_Original_Canvas.EdgeType type) {
throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN");
}
/** /**
* Retrieve the clip bounds, returning true if they are non-empty. * Retrieve the clip bounds, returning true if they are non-empty.
* *
@@ -324,31 +382,31 @@ public class BridgeCanvas extends Canvas {
} }
return false; return false;
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawColor(int, android.graphics.PorterDuff.Mode) * @see android.graphics.Canvas#drawColor(int, android.graphics.PorterDuff.Mode)
*/ */
@Override @Override
public void drawColor(int color, PorterDuff.Mode mode) { public void drawColor(int color, PorterDuff.Mode mode) {
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
// save old color // save old color
Color c = g.getColor(); Color c = g.getColor();
Composite composite = g.getComposite(); Composite composite = g.getComposite();
// get the alpha from the color // get the alpha from the color
int alpha = color >>> 24; int alpha = color >>> 24;
float falpha = alpha / 255.f; float falpha = alpha / 255.f;
setModeInGraphics(mode, g, falpha); setModeInGraphics(mode, g, falpha);
g.setColor(new Color(color)); g.setColor(new Color(color));
getGraphics2d().fillRect(0, 0, getWidth(), getHeight()); getGraphics2d().fillRect(0, 0, getWidth(), getHeight());
g.setComposite(composite); g.setComposite(composite);
// restore color // restore color
g.setColor(c); g.setColor(c);
} }
@@ -360,7 +418,7 @@ public class BridgeCanvas extends Canvas {
public void drawColor(int color) { public void drawColor(int color) {
drawColor(color, PorterDuff.Mode.SRC_OVER); drawColor(color, PorterDuff.Mode.SRC_OVER);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawARGB(int, int, int, int) * @see android.graphics.Canvas#drawARGB(int, int, int, int)
*/ */
@@ -368,7 +426,7 @@ public class BridgeCanvas extends Canvas {
public void drawARGB(int a, int r, int g, int b) { public void drawARGB(int a, int r, int g, int b) {
drawColor(a << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER); drawColor(a << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawRGB(int, int, int) * @see android.graphics.Canvas#drawRGB(int, int, int)
*/ */
@@ -377,7 +435,7 @@ public class BridgeCanvas extends Canvas {
drawColor(0xFF << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER); drawColor(0xFF << 24 | r << 16 | g << 8 | b, PorterDuff.Mode.SRC_OVER);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#getWidth() * @see android.graphics.Canvas#getWidth()
*/ */
@@ -385,7 +443,7 @@ public class BridgeCanvas extends Canvas {
public int getWidth() { public int getWidth() {
return mBufferedImage.getWidth(); return mBufferedImage.getWidth();
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#getHeight() * @see android.graphics.Canvas#getHeight()
*/ */
@@ -401,7 +459,7 @@ public class BridgeCanvas extends Canvas {
public void drawPaint(Paint paint) { public void drawPaint(Paint paint) {
drawColor(paint.getColor()); drawColor(paint.getColor());
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint) * @see android.graphics.Canvas#drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint)
*/ */
@@ -417,7 +475,32 @@ public class BridgeCanvas extends Canvas {
*/ */
@Override @Override
public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) { public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
throw new UnsupportedOperationException(); boolean needsRestore = false;
if (matrix.isIdentity() == false) {
// create a new graphics and apply the matrix to it
save(); // this creates a new Graphics2D, and stores it for children call to use
needsRestore = true;
Graphics2D g = getGraphics2d(); // get the newly create Graphics2D
// get the Graphics2D current matrix
AffineTransform currentTx = g.getTransform();
// get the AffineTransform from the matrix
AffineTransform matrixTx = matrix.getTransform();
// combine them so that the matrix is applied after.
currentTx.preConcatenate(matrixTx);
// give it to the graphics as a new matrix replacing all previous transform
g.setTransform(currentTx);
}
// draw the bitmap
drawBitmap(bitmap, 0, 0, paint);
if (needsRestore) {
// remove the new graphics
restore();
}
} }
/* (non-Javadoc) /* (non-Javadoc)
@@ -456,39 +539,42 @@ public class BridgeCanvas extends Canvas {
int height, boolean hasAlpha, Paint paint) { int height, boolean hasAlpha, Paint paint) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
private void drawBitmap(Bitmap bitmap, int sleft, int stop, int sright, int sbottom, int dleft, private void drawBitmap(Bitmap bitmap, int sleft, int stop, int sright, int sbottom, int dleft,
int dtop, int dright, int dbottom, Paint paint) { int dtop, int dright, int dbottom, Paint paint) {
BufferedImage image = bitmap.getImage(); BufferedImage image = bitmap.getImage();
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
Composite c = null; Composite c = null;
if (paint.isFilterBitmap()) { if (paint != null) {
g = (Graphics2D)g.create(); if (paint.isFilterBitmap()) {
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, g = (Graphics2D)g.create();
RenderingHints.VALUE_INTERPOLATION_BILINEAR); g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
if (paint.getAlpha() != 0xFF) {
c = g.getComposite();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
paint.getAlpha()/255.f));
}
} }
if (paint.getAlpha() != 0xFF) {
c = g.getComposite();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
paint.getAlpha()/255.f));
}
g.drawImage(image, dleft, dtop, dright, dbottom, g.drawImage(image, dleft, dtop, dright, dbottom,
sleft, stop, sright, sbottom, null); sleft, stop, sright, sbottom, null);
if (paint.isFilterBitmap()) { if (paint != null) {
g.dispose(); if (paint.isFilterBitmap()) {
} g.dispose();
}
if (c != null) { if (c != null) {
g.setComposite(c); g.setComposite(c);
}
} }
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#rotate(float, float, float) * @see android.graphics.Canvas#rotate(float, float, float)
*/ */
@@ -509,7 +595,7 @@ public class BridgeCanvas extends Canvas {
public void rotate(float degrees) { public void rotate(float degrees) {
getGraphics2d().rotate(Math.toRadians(degrees)); getGraphics2d().rotate(Math.toRadians(degrees));
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#scale(float, float, float, float) * @see android.graphics.Canvas#scale(float, float, float, float)
*/ */
@@ -528,19 +614,19 @@ public class BridgeCanvas extends Canvas {
public void scale(float sx, float sy) { public void scale(float sx, float sy) {
getGraphics2d().scale(sx, sy); getGraphics2d().scale(sx, sy);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawText(char[], int, int, float, float, android.graphics.Paint) * @see android.graphics.Canvas#drawText(char[], int, int, float, float, android.graphics.Paint)
*/ */
@Override @Override
public void drawText(char[] text, int index, int count, float x, float y, Paint paint) { public void drawText(char[] text, int index, int count, float x, float y, Paint paint) {
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
g = (Graphics2D)g.create(); g = (Graphics2D)g.create();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setFont(paint.getFont()); g.setFont(paint.getFont());
// set the color. because this only handles RGB we have to handle the alpha separately // set the color. because this only handles RGB we have to handle the alpha separately
g.setColor(new Color(paint.getColor())); g.setColor(new Color(paint.getColor()));
int alpha = paint.getAlpha(); int alpha = paint.getAlpha();
@@ -557,9 +643,9 @@ public class BridgeCanvas extends Canvas {
x -= m; x -= m;
} }
} }
g.drawChars(text, index, count, (int)x, (int)y); g.drawChars(text, index, count, (int)x, (int)y);
g.dispose(); g.dispose();
} }
@@ -586,7 +672,7 @@ public class BridgeCanvas extends Canvas {
public void drawText(String text, int start, int end, float x, float y, Paint paint) { public void drawText(String text, int start, int end, float x, float y, Paint paint) {
drawText(text.toCharArray(), start, end - start, x, y, paint); drawText(text.toCharArray(), start, end - start, x, y, paint);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawRect(android.graphics.RectF, android.graphics.Paint) * @see android.graphics.Canvas#drawRect(android.graphics.RectF, android.graphics.Paint)
*/ */
@@ -594,7 +680,7 @@ public class BridgeCanvas extends Canvas {
public void drawRect(RectF rect, Paint paint) { public void drawRect(RectF rect, Paint paint) {
doDrawRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), paint); doDrawRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), paint);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawRect(float, float, float, float, android.graphics.Paint) * @see android.graphics.Canvas#drawRect(float, float, float, float, android.graphics.Paint)
*/ */
@@ -614,11 +700,11 @@ public class BridgeCanvas extends Canvas {
private final void doDrawRect(int left, int top, int width, int height, Paint paint) { private final void doDrawRect(int left, int top, int width, int height, Paint paint) {
// get current graphisc // get current graphisc
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
g = getNewGraphics(paint, g); g = getNewGraphics(paint, g);
Style style = paint.getStyle(); Style style = paint.getStyle();
// draw // draw
if (style == Style.FILL || style == Style.FILL_AND_STROKE) { if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
g.fillRect(left, top, width, height); g.fillRect(left, top, width, height);
@@ -639,16 +725,16 @@ public class BridgeCanvas extends Canvas {
public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) { public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
// get current graphisc // get current graphisc
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
g = getNewGraphics(paint, g); g = getNewGraphics(paint, g);
Style style = paint.getStyle(); Style style = paint.getStyle();
// draw // draw
int arcWidth = (int)(rx * 2); int arcWidth = (int)(rx * 2);
int arcHeight = (int)(ry * 2); int arcHeight = (int)(ry * 2);
if (style == Style.FILL || style == Style.FILL_AND_STROKE) { if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
g.fillRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(), g.fillRoundRect((int)rect.left, (int)rect.top, (int)rect.width(), (int)rect.height(),
arcWidth, arcHeight); arcWidth, arcHeight);
@@ -671,7 +757,7 @@ public class BridgeCanvas extends Canvas {
public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) { public void drawLine(float startX, float startY, float stopX, float stopY, Paint paint) {
// get current graphisc // get current graphisc
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
g = getNewGraphics(paint, g); g = getNewGraphics(paint, g);
g.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY); g.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY);
@@ -679,7 +765,7 @@ public class BridgeCanvas extends Canvas {
// dispose Graphics2D object // dispose Graphics2D object
g.dispose(); g.dispose();
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawLines(float[], int, int, android.graphics.Paint) * @see android.graphics.Canvas#drawLines(float[], int, int, android.graphics.Paint)
*/ */
@@ -687,7 +773,7 @@ public class BridgeCanvas extends Canvas {
public void drawLines(float[] pts, int offset, int count, Paint paint) { public void drawLines(float[] pts, int offset, int count, Paint paint) {
// get current graphisc // get current graphisc
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
g = getNewGraphics(paint, g); g = getNewGraphics(paint, g);
for (int i = 0 ; i < count ; i += 4) { for (int i = 0 ; i < count ; i += 4) {
@@ -706,7 +792,7 @@ public class BridgeCanvas extends Canvas {
public void drawLines(float[] pts, Paint paint) { public void drawLines(float[] pts, Paint paint) {
drawLines(pts, 0, pts.length, paint); drawLines(pts, 0, pts.length, paint);
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawCircle(float, float, float, android.graphics.Paint) * @see android.graphics.Canvas#drawCircle(float, float, float, android.graphics.Paint)
*/ */
@@ -714,11 +800,11 @@ public class BridgeCanvas extends Canvas {
public void drawCircle(float cx, float cy, float radius, Paint paint) { public void drawCircle(float cx, float cy, float radius, Paint paint) {
// get current graphisc // get current graphisc
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
g = getNewGraphics(paint, g); g = getNewGraphics(paint, g);
Style style = paint.getStyle(); Style style = paint.getStyle();
int size = (int)(radius * 2); int size = (int)(radius * 2);
// draw // draw
@@ -741,11 +827,11 @@ public class BridgeCanvas extends Canvas {
public void drawOval(RectF oval, Paint paint) { public void drawOval(RectF oval, Paint paint) {
// get current graphics // get current graphics
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
g = getNewGraphics(paint, g); g = getNewGraphics(paint, g);
Style style = paint.getStyle(); Style style = paint.getStyle();
// draw // draw
if (style == Style.FILL || style == Style.FILL_AND_STROKE) { if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
g.fillOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height()); g.fillOval((int)oval.left, (int)oval.top, (int)oval.width(), (int)oval.height());
@@ -758,7 +844,7 @@ public class BridgeCanvas extends Canvas {
// dispose Graphics2D object // dispose Graphics2D object
g.dispose(); g.dispose();
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#drawPath(android.graphics.Path, android.graphics.Paint) * @see android.graphics.Canvas#drawPath(android.graphics.Path, android.graphics.Paint)
*/ */
@@ -766,11 +852,11 @@ public class BridgeCanvas extends Canvas {
public void drawPath(Path path, Paint paint) { public void drawPath(Path path, Paint paint) {
// get current graphics // get current graphics
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
g = getNewGraphics(paint, g); g = getNewGraphics(paint, g);
Style style = paint.getStyle(); Style style = paint.getStyle();
// draw // draw
if (style == Style.FILL || style == Style.FILL_AND_STROKE) { if (style == Style.FILL || style == Style.FILL_AND_STROKE) {
g.fill(path.getAwtShape()); g.fill(path.getAwtShape());
@@ -783,7 +869,7 @@ public class BridgeCanvas extends Canvas {
// dispose Graphics2D object // dispose Graphics2D object
g.dispose(); g.dispose();
} }
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#setMatrix(android.graphics.Matrix) * @see android.graphics.Canvas#setMatrix(android.graphics.Matrix)
*/ */
@@ -795,10 +881,10 @@ public class BridgeCanvas extends Canvas {
// get the new current graphics // get the new current graphics
Graphics2D g = getGraphics2d(); Graphics2D g = getGraphics2d();
// and apply the matrix // and apply the matrix
g.setTransform(matrix.getTransform()); g.setTransform(matrix.getTransform());
if (mLogger != null && matrix.hasPerspective()) { if (mLogger != null && matrix.hasPerspective()) {
mLogger.warning("android.graphics.Canvas#setMatrix(android.graphics.Matrix) only supports affine transformations in the Layout Editor."); mLogger.warning("android.graphics.Canvas#setMatrix(android.graphics.Matrix) only supports affine transformations in the Layout Editor.");
} }
@@ -1058,15 +1144,6 @@ public class BridgeCanvas extends Canvas {
return super.saveLayerAlpha(bounds, alpha, saveFlags); return super.saveLayerAlpha(bounds, alpha, saveFlags);
} }
/* (non-Javadoc)
* @see android.graphics.Canvas#setBitmap(android.graphics.Bitmap)
*/
@Override
public void setBitmap(Bitmap bitmap) {
// TODO Auto-generated method stub
super.setBitmap(bitmap);
}
/* (non-Javadoc) /* (non-Javadoc)
* @see android.graphics.Canvas#setDrawFilter(android.graphics.DrawFilter) * @see android.graphics.Canvas#setDrawFilter(android.graphics.DrawFilter)
*/ */

View File

@@ -17,6 +17,7 @@
package android.graphics; package android.graphics;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
/** /**
@@ -747,7 +748,24 @@ public class Matrix extends _Original_Matrix {
* inverted, ignore inverse and return false. * inverted, ignore inverse and return false.
*/ */
public boolean invert(Matrix inverse) { public boolean invert(Matrix inverse) {
throw new UnsupportedOperationException("STUB NEEDED"); if (inverse == null) {
return false;
}
try {
AffineTransform affineTransform = getTransform();
AffineTransform inverseTransform = affineTransform.createInverse();
inverse.mValues[0] = (float)inverseTransform.getScaleX();
inverse.mValues[1] = (float)inverseTransform.getShearX();
inverse.mValues[2] = (float)inverseTransform.getTranslateX();
inverse.mValues[3] = (float)inverseTransform.getScaleX();
inverse.mValues[4] = (float)inverseTransform.getShearY();
inverse.mValues[5] = (float)inverseTransform.getTranslateY();
return true;
} catch (NoninvertibleTransformException e) {
return false;
}
} }
@Override @Override
@@ -770,7 +788,19 @@ public class Matrix extends _Original_Matrix {
public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex,
int pointCount) { int pointCount) {
checkPointArrays(src, srcIndex, dst, dstIndex, pointCount); checkPointArrays(src, srcIndex, dst, dstIndex, pointCount);
throw new UnsupportedOperationException("STUB NEEDED");
for (int i = 0 ; i < pointCount ; i++) {
// just in case we are doing in place, we better put this in temp vars
float x = mValues[0] * src[i + srcIndex] +
mValues[1] * src[i + srcIndex + 1] +
mValues[2];
float y = mValues[3] * src[i + srcIndex] +
mValues[4] * src[i + srcIndex + 1] +
mValues[5];
dst[i + dstIndex] = x;
dst[i + dstIndex + 1] = y;
}
} }
/** /**
@@ -858,7 +888,26 @@ public class Matrix extends _Original_Matrix {
if (dst == null || src == null) { if (dst == null || src == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
throw new UnsupportedOperationException("STUB NEEDED");
// array with 4 corners
float[] corners = new float[] {
src.left, src.top,
src.right, src.top,
src.right, src.bottom,
src.left, src.bottom,
};
// apply the transform to them.
mapPoints(corners);
// now put the result in the rect. We take the min/max of Xs and min/max of Ys
dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6]));
dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6]));
dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7]));
dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7]));
return rectStaysRect();
} }
/** /**

View File

@@ -31,6 +31,7 @@ import com.android.tools.layoutlib.create.MethodAdapter;
import com.android.tools.layoutlib.create.OverrideMethod; import com.android.tools.layoutlib.create.OverrideMethod;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.Region; import android.graphics.Region;
import android.graphics.Typeface; import android.graphics.Typeface;
@@ -401,8 +402,7 @@ public final class Bridge implements ILayoutBridge {
view.layout(0, screenOffset, screenWidth, screenHeight); view.layout(0, screenOffset, screenWidth, screenHeight);
// draw them // draw them
BridgeCanvas canvas = new BridgeCanvas(screenWidth, screenHeight - screenOffset, Canvas canvas = new Canvas(screenWidth, screenHeight - screenOffset, logger);
logger);
root.draw(canvas); root.draw(canvas);
canvas.dispose(); canvas.dispose();

View File

@@ -30,17 +30,17 @@ public class NinePatchDrawable extends Drawable {
NinePatchDrawable(NinePatch ninePatch) { NinePatchDrawable(NinePatch ninePatch) {
m9Patch = ninePatch; m9Patch = ninePatch;
} }
@Override @Override
public int getMinimumWidth() { public int getMinimumWidth() {
return m9Patch.getWidth(); return m9Patch.getWidth();
} }
@Override @Override
public int getMinimumHeight() { public int getMinimumHeight() {
return m9Patch.getHeight(); return m9Patch.getHeight();
} }
/** /**
* Return the intrinsic width of the underlying drawable object. Returns * Return the intrinsic width of the underlying drawable object. Returns
* -1 if it has no intrinsic width, such as with a solid color. * -1 if it has no intrinsic width, such as with a solid color.
@@ -58,7 +58,7 @@ public class NinePatchDrawable extends Drawable {
public int getIntrinsicHeight() { public int getIntrinsicHeight() {
return m9Patch.getHeight(); return m9Patch.getHeight();
} }
/** /**
* Return in padding the insets suggested by this Drawable for placing * Return in padding the insets suggested by this Drawable for placing
* content inside the drawable's bounds. Positive values move toward the * content inside the drawable's bounds. Positive values move toward the
@@ -76,24 +76,18 @@ public class NinePatchDrawable extends Drawable {
padding.bottom = padd[3]; padding.bottom = padd[3];
return true; return true;
} }
@Override @Override
public void draw(Canvas canvas) { public void draw(Canvas canvas) {
if (canvas instanceof BridgeCanvas) { Rect r = getBounds();
BridgeCanvas bridgeCanvas = (BridgeCanvas)canvas; m9Patch.draw(canvas.getGraphics2d(), r.left, r.top, r.width(), r.height());
Rect r = getBounds();
m9Patch.draw(bridgeCanvas.getGraphics2d(), r.left, r.top, r.width(), r.height());
return;
}
throw new UnsupportedOperationException(); return;
} }
// ----------- Not implemented methods --------------- // ----------- Not implemented methods ---------------
@Override @Override
public int getOpacity() { public int getOpacity() {

View File

@@ -54,18 +54,19 @@ public class Main {
}, },
new String[] { // classes to rename (so that we can replace them in layoutlib) new String[] { // classes to rename (so that we can replace them in layoutlib)
// original-platform-class-name ======> renamed-class-name // original-platform-class-name ======> renamed-class-name
"android.graphics.Bitmap", "android.graphics._Original_Bitmap",
"android.graphics.BitmapShader", "android.graphics._Original_BitmapShader",
"android.graphics.Canvas", "android.graphics._Original_Canvas",
"android.graphics.ComposeShader", "android.graphics._Original_ComposeShader",
"android.graphics.LinearGradient", "android.graphics._Original_LinearGradient",
"android.graphics.Matrix", "android.graphics._Original_Matrix", "android.graphics.Matrix", "android.graphics._Original_Matrix",
"android.graphics.Paint", "android.graphics._Original_Paint", "android.graphics.Paint", "android.graphics._Original_Paint",
"android.graphics.Typeface", "android.graphics._Original_Typeface",
"android.graphics.Bitmap", "android.graphics._Original_Bitmap",
"android.graphics.Path", "android.graphics._Original_Path", "android.graphics.Path", "android.graphics._Original_Path",
"android.graphics.PorterDuffXfermode", "android.graphics._Original_PorterDuffXfermode", "android.graphics.PorterDuffXfermode", "android.graphics._Original_PorterDuffXfermode",
"android.graphics.Shader", "android.graphics._Original_Shader",
"android.graphics.LinearGradient", "android.graphics._Original_LinearGradient",
"android.graphics.BitmapShader", "android.graphics._Original_BitmapShader",
"android.graphics.ComposeShader", "android.graphics._Original_ComposeShader",
"android.graphics.RadialGradient", "android.graphics._Original_RadialGradient", "android.graphics.RadialGradient", "android.graphics._Original_RadialGradient",
"android.graphics.Shader", "android.graphics._Original_Shader",
"android.graphics.SweepGradient", "android.graphics._Original_SweepGradient", "android.graphics.SweepGradient", "android.graphics._Original_SweepGradient",
"android.graphics.Typeface", "android.graphics._Original_Typeface",
"android.os.ServiceManager", "android.os._Original_ServiceManager", "android.os.ServiceManager", "android.os._Original_ServiceManager",
"android.util.FloatMath", "android.util._Original_FloatMath", "android.util.FloatMath", "android.util._Original_FloatMath",
"android.view.SurfaceView", "android.view._Original_SurfaceView", "android.view.SurfaceView", "android.view._Original_SurfaceView",