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;
@@ -66,7 +65,6 @@ public final class Bitmap extends _Original_Bitmap {
}; };
} }
@Override @Override
public int getWidth() { public int getWidth() {
return mImage.getWidth(); return mImage.getWidth();
@@ -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);

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,31 +44,54 @@ 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();
} }
@@ -169,6 +185,25 @@ public class BridgeCanvas extends Canvas {
} }
} }
// --------------------
// 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
@@ -176,6 +211,16 @@ public class BridgeCanvas extends Canvas {
// 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)
*/ */
@@ -289,22 +334,35 @@ public class BridgeCanvas extends Canvas {
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.
* *
@@ -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)
@@ -465,27 +548,30 @@ public class BridgeCanvas extends Canvas {
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) { if (paint.getAlpha() != 0xFF) {
c = g.getComposite(); c = g.getComposite();
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
paint.getAlpha()/255.f)); 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);
}
} }
} }
@@ -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

@@ -79,16 +79,10 @@ public class NinePatchDrawable extends Drawable {
@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(); return;
m9Patch.draw(bridgeCanvas.getGraphics2d(), r.left, r.top, r.width(), r.height());
return;
}
throw new UnsupportedOperationException();
} }

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",