Fix layoutlib to reflect recent changes in platform code

Test: Layoutlib tests
Change-Id: I81964233a9e580ccee9c9e9b0cf3525babf30bd4
This commit is contained in:
Jerome Gaillard
2016-11-24 21:51:22 +00:00
parent d0835e45f7
commit f666c0e2ea
16 changed files with 846 additions and 976 deletions

View File

@@ -0,0 +1,727 @@
/*
* Copyright (C) 2016 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 android.graphics;
import com.android.ide.common.rendering.api.LayoutLog;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.GcSnapshot;
import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.ninepatch.NinePatchChunk;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.text.TextUtils;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Arc2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
public class BaseCanvas_Delegate {
// ---- delegate manager ----
protected static DelegateManager<BaseCanvas_Delegate> sManager =
new DelegateManager<>(BaseCanvas_Delegate.class);
// ---- delegate helper data ----
private final static boolean[] sBoolOut = new boolean[1];
// ---- delegate data ----
protected Bitmap_Delegate mBitmap;
protected GcSnapshot mSnapshot;
// ---- Public Helper methods ----
protected BaseCanvas_Delegate(Bitmap_Delegate bitmap) {
mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
}
protected BaseCanvas_Delegate() {
mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/);
}
/**
* Disposes of the {@link Graphics2D} stack.
*/
protected void dispose() {
mSnapshot.dispose();
}
/**
* Returns the current {@link Graphics2D} used to draw.
*/
public GcSnapshot getSnapshot() {
return mSnapshot;
}
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top,
long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity) {
// get the delegate from the native int.
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (bitmapDelegate == null) {
return;
}
BufferedImage image = bitmapDelegate.getImage();
float right = left + image.getWidth();
float bottom = top + image.getHeight();
drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
0, 0, image.getWidth(), image.getHeight(),
(int)left, (int)top, (int)right, (int)bottom);
}
@LayoutlibDelegate
/*package*/ static void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity) {
// get the delegate from the native int.
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (bitmapDelegate == null) {
return;
}
drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, (int) srcLeft, (int) srcTop,
(int) srcRight, (int) srcBottom, (int) dstLeft, (int) dstTop, (int) dstRight,
(int) dstBottom);
}
@LayoutlibDelegate
/*package*/ static void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
final float x, final float y, int width, int height, boolean hasAlpha,
long nativePaintOrZero) {
// create a temp BufferedImage containing the content.
final BufferedImage image = new BufferedImage(width, height,
hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
image.setRGB(0, 0, width, height, colors, offset, stride);
draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/,
(graphics, paint) -> {
if (paint != null && paint.isFilterBitmap()) {
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
graphics.drawImage(image, (int) x, (int) y, null);
});
}
@LayoutlibDelegate
/*package*/ static void nDrawColor(long nativeCanvas, final int color, final int mode) {
// get the delegate from the native int.
BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
final int w = canvasDelegate.mBitmap.getImage().getWidth();
final int h = canvasDelegate.mBitmap.getImage().getHeight();
draw(nativeCanvas, (graphics, paint) -> {
// reset its transform just in case
graphics.setTransform(new AffineTransform());
// set the color
graphics.setColor(new java.awt.Color(color, true /*alpha*/));
Composite composite = PorterDuffUtility.getComposite(
PorterDuffUtility.getPorterDuffMode(mode), 0xFF);
if (composite != null) {
graphics.setComposite(composite);
}
graphics.fillRect(0, 0, w, h);
});
}
@LayoutlibDelegate
/*package*/ static void nDrawPaint(long nativeCanvas, long paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPaint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
/*package*/ static void nDrawPoint(long nativeCanvas, float x, float y,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPoint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
/*package*/ static void nDrawPoints(long nativeCanvas, float[] pts, int offset, int count,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPoint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
/*package*/ static void nDrawLine(long nativeCanvas,
final float startX, final float startY, final float stopX, final float stopY,
long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
(graphics, paintDelegate) -> graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY));
}
@LayoutlibDelegate
/*package*/ static void nDrawLines(long nativeCanvas,
final float[] pts, final int offset, final int count,
long nativePaint) {
draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
false /*forceSrcMode*/, (graphics, paintDelegate) -> {
for (int i = 0; i < count; i += 4) {
graphics.drawLine((int) pts[i + offset], (int) pts[i + offset + 1],
(int) pts[i + offset + 2], (int) pts[i + offset + 3]);
}
});
}
@LayoutlibDelegate
/*package*/ static void nDrawRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
(graphics, paintDelegate) -> {
int style = paintDelegate.getStyle();
// draw
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fillRect((int)left, (int)top,
(int)(right-left), (int)(bottom-top));
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.drawRect((int)left, (int)top,
(int)(right-left), (int)(bottom-top));
}
});
}
@LayoutlibDelegate
/*package*/ static void nDrawOval(long nativeCanvas, final float left,
final float top, final float right, final float bottom, long paint) {
if (right > left && bottom > top) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
(graphics, paintDelegate) -> {
int style = paintDelegate.getStyle();
// draw
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fillOval((int)left, (int)top,
(int)(right - left), (int)(bottom - top));
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.drawOval((int)left, (int)top,
(int)(right - left), (int)(bottom - top));
}
});
}
}
@LayoutlibDelegate
/*package*/ static void nDrawCircle(long nativeCanvas,
float cx, float cy, float radius, long paint) {
nDrawOval(nativeCanvas,
cx - radius, cy - radius, cx + radius, cy + radius,
paint);
}
@LayoutlibDelegate
/*package*/ static void nDrawArc(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float startAngle, final float sweep,
final boolean useCenter, long paint) {
if (right > left && bottom > top) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
(graphics, paintDelegate) -> {
int style = paintDelegate.getStyle();
Arc2D.Float arc = new Arc2D.Float(
left, top, right - left, bottom - top,
-startAngle, -sweep,
useCenter ? Arc2D.PIE : Arc2D.OPEN);
// draw
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fill(arc);
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.draw(arc);
}
});
}
}
@LayoutlibDelegate
/*package*/ static void nDrawRoundRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float rx, final float ry, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
(graphics, paintDelegate) -> {
int style = paintDelegate.getStyle();
// draw
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fillRoundRect(
(int)left, (int)top,
(int)(right - left), (int)(bottom - top),
2 * (int)rx, 2 * (int)ry);
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.drawRoundRect(
(int)left, (int)top,
(int)(right - left), (int)(bottom - top),
2 * (int)rx, 2 * (int)ry);
}
});
}
@LayoutlibDelegate
public static void nDrawPath(long nativeCanvas, long path, long paint) {
final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
if (pathDelegate == null) {
return;
}
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
(graphics, paintDelegate) -> {
Shape shape = pathDelegate.getJavaShape();
Rectangle2D bounds = shape.getBounds2D();
if (bounds.isEmpty()) {
// Apple JRE 1.6 doesn't like drawing empty shapes.
// http://b.android.com/178278
if (pathDelegate.isEmpty()) {
// This means that the path doesn't have any lines or curves so
// nothing to draw.
return;
}
// The stroke width is not consider for the size of the bounds so,
// for example, a horizontal line, would be considered as an empty
// rectangle.
// If the strokeWidth is not 0, we use it to consider the size of the
// path as well.
float strokeWidth = paintDelegate.getStrokeWidth();
if (strokeWidth <= 0.0f) {
return;
}
bounds.setRect(bounds.getX(), bounds.getY(),
Math.max(strokeWidth, bounds.getWidth()),
Math.max(strokeWidth, bounds.getHeight()));
}
int style = paintDelegate.getStyle();
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fill(shape);
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.draw(shape);
}
});
}
@LayoutlibDelegate
/*package*/ static void nDrawRegion(long nativeCanvas, long nativeRegion,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Some canvas paths may not be drawn", null, null);
}
@LayoutlibDelegate
/*package*/ static void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
final float dstLeft, final float dstTop, final float dstRight, final float dstBottom,
long nativePaintOrZero, final int screenDensity, final int bitmapDensity) {
// get the delegate from the native int.
final Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmap);
if (bitmapDelegate == null) {
return;
}
byte[] c = NinePatch_Delegate.getChunk(ninePatch);
if (c == null) {
// not a 9-patch?
BufferedImage image = bitmapDelegate.getImage();
drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 0, 0, image.getWidth(),
image.getHeight(), (int) dstLeft, (int) dstTop, (int) dstRight,
(int) dstBottom);
return;
}
final NinePatchChunk chunkObject = NinePatch_Delegate.getChunk(c);
assert chunkObject != null;
if (chunkObject == null) {
return;
}
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
// this one can be null
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paint) {
chunkObject.draw(bitmapDelegate.getImage(), graphics, (int) dstLeft, (int) dstTop,
(int) (dstRight - dstLeft), (int) (dstBottom - dstTop), screenDensity,
bitmapDensity);
}
}, paintDelegate, true, false);
}
@LayoutlibDelegate
/*package*/ static void nDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
long nMatrix, long nPaint) {
// get the delegate from the native int.
BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
return;
}
// get the delegate from the native int, which can be null
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
// get the delegate from the native int.
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (bitmapDelegate == null) {
return;
}
final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut);
Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
if (matrixDelegate == null) {
return;
}
final AffineTransform mtx = matrixDelegate.getAffineTransform();
canvasDelegate.getSnapshot().draw((graphics, paint) -> {
if (paint != null && paint.isFilterBitmap()) {
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
//FIXME add support for canvas, screen and bitmap densities.
graphics.drawImage(image, mtx, null);
}, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/);
}
@LayoutlibDelegate
/*package*/ static void nDrawBitmapMesh(long nCanvas, Bitmap bitmap,
int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
int colorOffset, long nPaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawBitmapMesh is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
/*package*/ static void nDrawVertices(long nCanvas, int mode, int n,
float[] verts, int vertOffset,
float[] texs, int texOffset,
int[] colors, int colorOffset,
short[] indices, int indexOffset,
int indexCount, long nPaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawVertices is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
/*package*/ static void nDrawText(long nativeCanvas, char[] text, int index, int count,
float startX, float startY, int flags, long paint, long typeface) {
drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
paint, typeface);
}
@LayoutlibDelegate
/*package*/ static void nDrawText(long nativeCanvas, String text,
int start, int end, float x, float y, final int flags, long paint,
long typeface) {
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
nDrawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface);
}
@LayoutlibDelegate
/*package*/ static void nDrawTextRun(long nativeCanvas, String text,
int start, int end, int contextStart, int contextEnd,
float x, float y, boolean isRtl, long paint, long typeface) {
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
drawText(nativeCanvas, buffer, 0, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
/*package*/ static void nDrawTextRun(long nativeCanvas, char[] text,
int start, int count, int contextStart, int contextCount,
float x, float y, boolean isRtl, long paint, long typeface) {
drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
/*package*/ static void nDrawTextOnPath(long nativeCanvas,
char[] text, int index,
int count, long path,
float hOffset,
float vOffset, int bidiFlags,
long paint, long typeface) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawTextOnPath is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
/*package*/ static void nDrawTextOnPath(long nativeCanvas,
String text, long path,
float hOffset,
float vOffset,
int bidiFlags, long paint,
long typeface) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawTextOnPath is not supported.", null, null /*data*/);
}
// ---- Private delegate/helper methods ----
/**
* Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
* <p>Note that the drawable may actually be executed several times if there are
* layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
*/
private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode,
GcSnapshot.Drawable drawable) {
// get the delegate from the native int.
BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
return;
}
// get the paint which can be null if nPaint is 0;
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode);
}
/**
* Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
* to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
* <p>Note that the drawable may actually be executed several times if there are
* layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
*/
private static void draw(long nCanvas, GcSnapshot.Drawable drawable) {
// get the delegate from the native int.
BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
return;
}
canvasDelegate.mSnapshot.draw(drawable);
}
private static void drawText(long nativeCanvas, final char[] text, final int index,
final int count, final float startX, final float startY, final boolean isRtl,
long paint, final long typeface) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
(graphics, paintDelegate) -> {
// WARNING: the logic in this method is similar to Paint_Delegate.measureText.
// Any change to this method should be reflected in Paint.measureText
// assert that the typeface passed is actually the one stored in paint.
assert (typeface == paintDelegate.mNativeTypeface);
// Paint.TextAlign indicates how the text is positioned relative to X.
// LEFT is the default and there's nothing to do.
float x = startX;
int limit = index + count;
if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
RectF bounds =
paintDelegate.measureText(text, index, count, null, 0, isRtl);
float m = bounds.right - bounds.left;
if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
x -= m / 2;
} else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
x -= m;
}
}
new BidiRenderer(graphics, paintDelegate, text).setRenderLocation(x,
startY).renderText(index, limit, isRtl, null, 0, true);
});
}
private static void drawBitmap(long nativeCanvas, Bitmap_Delegate bitmap,
long nativePaintOrZero, final int sleft, final int stop, final int sright,
final int sbottom, final int dleft, final int dtop, final int dright,
final int dbottom) {
// get the delegate from the native int.
BaseCanvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
// get the paint, which could be null if the int is 0
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut);
draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0],
(graphics, paint) -> {
if (paint != null && paint.isFilterBitmap()) {
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
//FIXME add support for canvas, screen and bitmap densities.
graphics.drawImage(image, dleft, dtop, dright, dbottom, sleft, stop, sright,
sbottom, null);
});
}
/**
* Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate.
* The image returns, through a 1-size boolean array, whether the drawing code should
* use a SRC composite no matter what the paint says.
*
* @param bitmap the bitmap
* @param paint the paint that will be used to draw
* @param forceSrcMode whether the composite will have to be SRC
* @return the image to draw
*/
private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint,
boolean[] forceSrcMode) {
BufferedImage image = bitmap.getImage();
forceSrcMode[0] = false;
// if the bitmap config is alpha_8, then we erase all color value from it
// before drawing it.
if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
fixAlpha8Bitmap(image);
} else if (!bitmap.hasAlpha()) {
// hasAlpha is merely a rendering hint. There can in fact be alpha values
// in the bitmap but it should be ignored at drawing time.
// There is two ways to do this:
// - override the composite to be SRC. This can only be used if the composite
// was going to be SRC or SRC_OVER in the first place
// - Create a different bitmap to draw in which all the alpha channel values is set
// to 0xFF.
if (paint != null) {
PorterDuff.Mode mode = PorterDuff.intToMode(paint.getPorterDuffMode());
forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER || mode == PorterDuff.Mode.SRC;
}
// if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
if (!forceSrcMode[0]) {
image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
}
}
return image;
}
private static void fixAlpha8Bitmap(final BufferedImage image) {
int w = image.getWidth();
int h = image.getHeight();
int[] argb = new int[w * h];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
final int length = argb.length;
for (int i = 0 ; i < length; i++) {
argb[i] &= 0xFF000000;
}
image.setRGB(0, 0, w, h, argb, 0, w);
}
protected int save(int saveFlags) {
// get the current save count
int count = mSnapshot.size();
mSnapshot = mSnapshot.save(saveFlags);
// return the old save count
return count;
}
protected int saveLayerAlpha(RectF rect, int alpha, int saveFlags) {
Paint_Delegate paint = new Paint_Delegate();
paint.setAlpha(alpha);
return saveLayer(rect, paint, saveFlags);
}
protected int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) {
// get the current save count
int count = mSnapshot.size();
mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags);
// return the old save count
return count;
}
/**
* Restores the {@link GcSnapshot} to <var>saveCount</var>
* @param saveCount the saveCount
*/
protected void restoreTo(int saveCount) {
mSnapshot = mSnapshot.restoreTo(saveCount);
}
/**
* Restores the top {@link GcSnapshot}
*/
protected void restore() {
mSnapshot = mSnapshot.restore();
}
protected boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
return mSnapshot.clipRect(left, top, right, bottom, regionOp);
}
}

View File

@@ -55,40 +55,27 @@ import libcore.util.NativeAllocationRegistry_Delegate;
* @see DelegateManager
*
*/
public final class Canvas_Delegate {
public final class Canvas_Delegate extends BaseCanvas_Delegate {
// ---- delegate manager ----
private static final DelegateManager<Canvas_Delegate> sManager =
new DelegateManager<Canvas_Delegate>(Canvas_Delegate.class);
private static long sFinalizer = -1;
// ---- delegate helper data ----
private final static boolean[] sBoolOut = new boolean[1];
// ---- delegate data ----
private Bitmap_Delegate mBitmap;
private GcSnapshot mSnapshot;
private DrawFilter_Delegate mDrawFilter = null;
// ---- Public Helper methods ----
/**
* Returns the native delegate associated to a given {@link Canvas} object.
*/
public static Canvas_Delegate getDelegate(Canvas canvas) {
return sManager.getDelegate(canvas.getNativeCanvasWrapper());
return (Canvas_Delegate) sManager.getDelegate(canvas.getNativeCanvasWrapper());
}
/**
* Returns the native delegate associated to a given an int referencing a {@link Canvas} object.
*/
public static Canvas_Delegate getDelegate(long native_canvas) {
return sManager.getDelegate(native_canvas);
return (Canvas_Delegate) sManager.getDelegate(native_canvas);
}
/**
@@ -143,7 +130,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nSetBitmap(long canvas, Bitmap bitmap) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (canvasDelegate == null || bitmapDelegate==null) {
return;
@@ -155,7 +142,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static boolean nIsOpaque(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return false;
}
@@ -169,7 +156,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static int nGetWidth(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return 0;
}
@@ -180,7 +167,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static int nGetHeight(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return 0;
}
@@ -191,7 +178,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static int nSave(long nativeCanvas, int saveFlags) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return 0;
}
@@ -204,7 +191,7 @@ public final class Canvas_Delegate {
float t, float r, float b,
long paint, int layerFlags) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return 0;
}
@@ -223,7 +210,7 @@ public final class Canvas_Delegate {
float t, float r, float b,
int alpha, int layerFlags) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return 0;
}
@@ -235,7 +222,7 @@ public final class Canvas_Delegate {
public static void nRestore(long nativeCanvas, boolean throwOnUnderflow) {
// FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
@@ -248,7 +235,7 @@ public final class Canvas_Delegate {
boolean throwOnUnderflow) {
// FIXME: implement throwOnUnderflow.
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
@@ -259,7 +246,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static int nGetSaveCount(long nativeCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return 0;
}
@@ -270,7 +257,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nTranslate(long nativeCanvas, float dx, float dy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
@@ -281,7 +268,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nScale(long nativeCanvas, float sx, float sy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
@@ -292,7 +279,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nRotate(long nativeCanvas, float degrees) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
@@ -303,7 +290,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nSkew(long nativeCanvas, float kx, float ky) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
@@ -327,7 +314,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nConcat(long nCanvas, long nMatrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas);
if (canvasDelegate == null) {
return;
}
@@ -355,7 +342,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nSetMatrix(long nCanvas, long nMatrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas);
if (canvasDelegate == null) {
return;
}
@@ -388,7 +375,7 @@ public final class Canvas_Delegate {
float right, float bottom,
int regionOp) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nCanvas);
if (canvasDelegate == null) {
return false;
}
@@ -400,7 +387,7 @@ public final class Canvas_Delegate {
public static boolean nClipPath(long nativeCanvas,
long nativePath,
int regionOp) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return true;
}
@@ -417,7 +404,7 @@ public final class Canvas_Delegate {
public static boolean nClipRegion(long nativeCanvas,
long nativeRegion,
int regionOp) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return true;
}
@@ -432,7 +419,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nSetDrawFilter(long nativeCanvas, long nativeFilter) {
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
@@ -449,7 +436,7 @@ public final class Canvas_Delegate {
public static boolean nGetClipBounds(long nativeCanvas,
Rect bounds) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return false;
}
@@ -469,7 +456,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
public static void nGetCTM(long canvas, long matrix) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(canvas);
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas);
if (canvasDelegate == null) {
return;
}
@@ -498,509 +485,11 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
public static void nDrawColor(long nativeCanvas, final int color, final int mode) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
final int w = canvasDelegate.mBitmap.getImage().getWidth();
final int h = canvasDelegate.mBitmap.getImage().getHeight();
draw(nativeCanvas, new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paint) {
// reset its transform just in case
graphics.setTransform(new AffineTransform());
// set the color
graphics.setColor(new Color(color, true /*alpha*/));
Composite composite = PorterDuffUtility.getComposite(
PorterDuffUtility.getPorterDuffMode(mode), 0xFF);
if (composite != null) {
graphics.setComposite(composite);
}
graphics.fillRect(0, 0, w, h);
}
});
}
@LayoutlibDelegate
public static void nDrawPaint(long nativeCanvas, long paint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPaint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
public static void nDrawPoint(long nativeCanvas, float x, float y,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPoint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
public static void nDrawPoints(long nativeCanvas, float[] pts, int offset, int count,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawPoint is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
public static void nDrawLine(long nativeCanvas,
final float startX, final float startY, final float stopX, final float stopY,
long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
graphics.drawLine((int)startX, (int)startY, (int)stopX, (int)stopY);
}
});
}
@LayoutlibDelegate
public static void nDrawLines(long nativeCanvas,
final float[] pts, final int offset, final int count,
long nativePaint) {
draw(nativeCanvas, nativePaint, false /*compositeOnly*/,
false /*forceSrcMode*/, new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
for (int i = 0; i < count; i += 4) {
graphics.drawLine((int) pts[i + offset], (int) pts[i + offset + 1],
(int) pts[i + offset + 2], (int) pts[i + offset + 3]);
}
}
});
}
@LayoutlibDelegate
public static void nDrawRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
int style = paintDelegate.getStyle();
// draw
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fillRect((int)left, (int)top,
(int)(right-left), (int)(bottom-top));
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.drawRect((int)left, (int)top,
(int)(right-left), (int)(bottom-top));
}
}
});
}
@LayoutlibDelegate
public static void nDrawOval(long nativeCanvas, final float left,
final float top, final float right, final float bottom, long paint) {
if (right > left && bottom > top) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
int style = paintDelegate.getStyle();
// draw
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fillOval((int)left, (int)top,
(int)(right - left), (int)(bottom - top));
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.drawOval((int)left, (int)top,
(int)(right - left), (int)(bottom - top));
}
}
});
}
}
@LayoutlibDelegate
public static void nDrawCircle(long nativeCanvas,
float cx, float cy, float radius, long paint) {
nDrawOval(nativeCanvas,
cx - radius, cy - radius, cx + radius, cy + radius,
paint);
}
@LayoutlibDelegate
public static void nDrawArc(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float startAngle, final float sweep,
final boolean useCenter, long paint) {
if (right > left && bottom > top) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
int style = paintDelegate.getStyle();
Arc2D.Float arc = new Arc2D.Float(
left, top, right - left, bottom - top,
-startAngle, -sweep,
useCenter ? Arc2D.PIE : Arc2D.OPEN);
// draw
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fill(arc);
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.draw(arc);
}
}
});
}
}
@LayoutlibDelegate
public static void nDrawRoundRect(long nativeCanvas,
final float left, final float top, final float right, final float bottom,
final float rx, final float ry, long paint) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
int style = paintDelegate.getStyle();
// draw
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fillRoundRect(
(int)left, (int)top,
(int)(right - left), (int)(bottom - top),
2 * (int)rx, 2 * (int)ry);
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.drawRoundRect(
(int)left, (int)top,
(int)(right - left), (int)(bottom - top),
2 * (int)rx, 2 * (int)ry);
}
}
});
}
@LayoutlibDelegate
public static void nDrawPath(long nativeCanvas, long path, long paint) {
final Path_Delegate pathDelegate = Path_Delegate.getDelegate(path);
if (pathDelegate == null) {
return;
}
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
Shape shape = pathDelegate.getJavaShape();
Rectangle2D bounds = shape.getBounds2D();
if (bounds.isEmpty()) {
// Apple JRE 1.6 doesn't like drawing empty shapes.
// http://b.android.com/178278
if (pathDelegate.isEmpty()) {
// This means that the path doesn't have any lines or curves so
// nothing to draw.
return;
}
// The stroke width is not consider for the size of the bounds so,
// for example, a horizontal line, would be considered as an empty
// rectangle.
// If the strokeWidth is not 0, we use it to consider the size of the
// path as well.
float strokeWidth = paintDelegate.getStrokeWidth();
if (strokeWidth <= 0.0f) {
return;
}
bounds.setRect(bounds.getX(), bounds.getY(),
Math.max(strokeWidth, bounds.getWidth()),
Math.max(strokeWidth, bounds.getHeight()));
}
int style = paintDelegate.getStyle();
if (style == Paint.Style.FILL.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.fill(shape);
}
if (style == Paint.Style.STROKE.nativeInt ||
style == Paint.Style.FILL_AND_STROKE.nativeInt) {
graphics.draw(shape);
}
}
});
}
@LayoutlibDelegate
public static void nDrawRegion(long nativeCanvas, long nativeRegion,
long nativePaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Some canvas paths may not be drawn", null, null);
}
@LayoutlibDelegate
public static void nDrawNinePatch(Canvas thisCanvas, long nativeCanvas,
long nativeBitmap, long ninePatch, final float dstLeft, final float dstTop,
final float dstRight, final float dstBottom, long nativePaintOrZero,
final int screenDensity, final int bitmapDensity) {
// get the delegate from the native int.
final Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(nativeBitmap);
if (bitmapDelegate == null) {
return;
}
byte[] c = NinePatch_Delegate.getChunk(ninePatch);
if (c == null) {
// not a 9-patch?
BufferedImage image = bitmapDelegate.getImage();
drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero, 0, 0, image.getWidth(),
image.getHeight(), (int) dstLeft, (int) dstTop, (int) dstRight,
(int) dstBottom);
return;
}
final NinePatchChunk chunkObject = NinePatch_Delegate.getChunk(c);
assert chunkObject != null;
if (chunkObject == null) {
return;
}
Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
// this one can be null
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paint) {
chunkObject.draw(bitmapDelegate.getImage(), graphics, (int) dstLeft, (int) dstTop,
(int) (dstRight - dstLeft), (int) (dstBottom - dstTop), screenDensity,
bitmapDensity);
}
}, paintDelegate, true, false);
}
@LayoutlibDelegate
public static void nDrawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float left, float top,
long nativePaintOrZero,
int canvasDensity,
int screenDensity,
int bitmapDensity) {
// get the delegate from the native int.
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (bitmapDelegate == null) {
return;
}
BufferedImage image = bitmapDelegate.getImage();
float right = left + image.getWidth();
float bottom = top + image.getHeight();
drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
0, 0, image.getWidth(), image.getHeight(),
(int)left, (int)top, (int)right, (int)bottom);
}
@LayoutlibDelegate
public static void nDrawBitmap(Canvas thisCanvas, long nativeCanvas, Bitmap bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
long nativePaintOrZero, int screenDensity, int bitmapDensity) {
// get the delegate from the native int.
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (bitmapDelegate == null) {
return;
}
drawBitmap(nativeCanvas, bitmapDelegate, nativePaintOrZero,
(int)srcLeft, (int)srcTop, (int)srcRight, (int)srcBottom,
(int)dstLeft, (int)dstTop, (int)dstRight, (int)dstBottom);
}
@LayoutlibDelegate
public static void nDrawBitmap(long nativeCanvas, int[] colors,
int offset, int stride, final float x,
final float y, int width, int height,
boolean hasAlpha,
long nativePaintOrZero) {
// create a temp BufferedImage containing the content.
final BufferedImage image = new BufferedImage(width, height,
hasAlpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB);
image.setRGB(0, 0, width, height, colors, offset, stride);
draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paint) {
if (paint != null && paint.isFilterBitmap()) {
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
graphics.drawImage(image, (int) x, (int) y, null);
}
});
}
@LayoutlibDelegate
public static void nativeDrawBitmapMatrix(long nCanvas, Bitmap bitmap,
long nMatrix, long nPaint) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
return;
}
// get the delegate from the native int, which can be null
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
// get the delegate from the native int.
Bitmap_Delegate bitmapDelegate = Bitmap_Delegate.getDelegate(bitmap);
if (bitmapDelegate == null) {
return;
}
final BufferedImage image = getImageToDraw(bitmapDelegate, paintDelegate, sBoolOut);
Matrix_Delegate matrixDelegate = Matrix_Delegate.getDelegate(nMatrix);
if (matrixDelegate == null) {
return;
}
final AffineTransform mtx = matrixDelegate.getAffineTransform();
canvasDelegate.getSnapshot().draw(new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paint) {
if (paint != null && paint.isFilterBitmap()) {
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
//FIXME add support for canvas, screen and bitmap densities.
graphics.drawImage(image, mtx, null);
}
}, paintDelegate, true /*compositeOnly*/, false /*forceSrcMode*/);
}
@LayoutlibDelegate
public static void nativeDrawBitmapMesh(long nCanvas, Bitmap bitmap,
int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors,
int colorOffset, long nPaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawBitmapMesh is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
public static void nativeDrawVertices(long nCanvas, int mode, int n,
float[] verts, int vertOffset,
float[] texs, int texOffset,
int[] colors, int colorOffset,
short[] indices, int indexOffset,
int indexCount, long nPaint) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawVertices is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
public static void nDrawText(long nativeCanvas, char[] text, int index, int count,
float startX, float startY, int flags, long paint, long typeface) {
drawText(nativeCanvas, text, index, count, startX, startY, (flags & 1) != 0,
paint, typeface);
}
@LayoutlibDelegate
public static void nDrawText(long nativeCanvas, String text,
int start, int end, float x, float y, final int flags, long paint,
long typeface) {
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
nDrawText(nativeCanvas, buffer, 0, count, x, y, flags, paint, typeface);
}
@LayoutlibDelegate
public static void nDrawTextRun(long nativeCanvas, String text,
int start, int end, int contextStart, int contextEnd,
float x, float y, boolean isRtl, long paint, long typeface) {
int count = end - start;
char[] buffer = TemporaryBuffer.obtain(count);
TextUtils.getChars(text, start, end, buffer, 0);
drawText(nativeCanvas, buffer, 0, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
public static void nDrawTextRun(long nativeCanvas, char[] text,
int start, int count, int contextStart, int contextCount,
float x, float y, boolean isRtl, long paint, long typeface) {
drawText(nativeCanvas, text, start, count, x, y, isRtl, paint, typeface);
}
@LayoutlibDelegate
public static void nDrawTextOnPath(long nativeCanvas,
char[] text, int index,
int count, long path,
float hOffset,
float vOffset, int bidiFlags,
long paint, long typeface) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawTextOnPath is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
public static void nDrawTextOnPath(long nativeCanvas,
String text, long path,
float hOffset,
float vOffset,
int bidiFlags, long paint,
long typeface) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
"Canvas.drawTextOnPath is not supported.", null, null /*data*/);
}
@LayoutlibDelegate
/*package*/ static long getNativeFinalizer() {
/*package*/ static long nGetNativeFinalizer() {
synchronized (Canvas_Delegate.class) {
if (sFinalizer == -1) {
sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(nativePtr -> {
Canvas_Delegate delegate = sManager.getDelegate(nativePtr);
Canvas_Delegate delegate = Canvas_Delegate.getDelegate(nativePtr);
if (delegate != null) {
delegate.dispose();
}
@@ -1011,230 +500,12 @@ public final class Canvas_Delegate {
return sFinalizer;
}
// ---- Private delegate/helper methods ----
/**
* Executes a {@link GcSnapshot.Drawable} with a given canvas and paint.
* <p>Note that the drawable may actually be executed several times if there are
* layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
*/
private static void draw(long nCanvas, long nPaint, boolean compositeOnly, boolean forceSrcMode,
GcSnapshot.Drawable drawable) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
return;
}
// get the paint which can be null if nPaint is 0;
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nPaint);
canvasDelegate.getSnapshot().draw(drawable, paintDelegate, compositeOnly, forceSrcMode);
}
/**
* Executes a {@link GcSnapshot.Drawable} with a given canvas. No paint object will be provided
* to {@link GcSnapshot.Drawable#draw(Graphics2D, Paint_Delegate)}.
* <p>Note that the drawable may actually be executed several times if there are
* layers involved (see {@link #saveLayer(RectF, Paint_Delegate, int)}.
*/
private static void draw(long nCanvas, GcSnapshot.Drawable drawable) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nCanvas);
if (canvasDelegate == null) {
return;
}
canvasDelegate.mSnapshot.draw(drawable);
}
private static void drawText(long nativeCanvas, final char[] text, final int index,
final int count, final float startX, final float startY, final boolean isRtl,
long paint, final long typeface) {
draw(nativeCanvas, paint, false /*compositeOnly*/, false /*forceSrcMode*/,
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {
// WARNING: the logic in this method is similar to Paint_Delegate.measureText.
// Any change to this method should be reflected in Paint.measureText
// assert that the typeface passed is actually the one stored in paint.
assert (typeface == paintDelegate.mNativeTypeface);
// Paint.TextAlign indicates how the text is positioned relative to X.
// LEFT is the default and there's nothing to do.
float x = startX;
int limit = index + count;
if (paintDelegate.getTextAlign() != Paint.Align.LEFT.nativeInt) {
RectF bounds = paintDelegate.measureText(text, index, count, null, 0,
isRtl);
float m = bounds.right - bounds.left;
if (paintDelegate.getTextAlign() == Paint.Align.CENTER.nativeInt) {
x -= m / 2;
} else if (paintDelegate.getTextAlign() == Paint.Align.RIGHT.nativeInt) {
x -= m;
}
}
new BidiRenderer(graphics, paintDelegate, text).setRenderLocation(x, startY)
.renderText(index, limit, isRtl, null, 0, true);
}
});
}
private Canvas_Delegate(Bitmap_Delegate bitmap) {
mSnapshot = GcSnapshot.createDefaultSnapshot(mBitmap = bitmap);
super(bitmap);
}
private Canvas_Delegate() {
mSnapshot = GcSnapshot.createDefaultSnapshot(null /*image*/);
}
/**
* Disposes of the {@link Graphics2D} stack.
*/
private void dispose() {
mSnapshot.dispose();
}
private int save(int saveFlags) {
// get the current save count
int count = mSnapshot.size();
mSnapshot = mSnapshot.save(saveFlags);
// return the old save count
return count;
}
private int saveLayerAlpha(RectF rect, int alpha, int saveFlags) {
Paint_Delegate paint = new Paint_Delegate();
paint.setAlpha(alpha);
return saveLayer(rect, paint, saveFlags);
}
private int saveLayer(RectF rect, Paint_Delegate paint, int saveFlags) {
// get the current save count
int count = mSnapshot.size();
mSnapshot = mSnapshot.saveLayer(rect, paint, saveFlags);
// return the old save count
return count;
}
/**
* Restores the {@link GcSnapshot} to <var>saveCount</var>
* @param saveCount the saveCount
*/
private void restoreTo(int saveCount) {
mSnapshot = mSnapshot.restoreTo(saveCount);
}
/**
* Restores the top {@link GcSnapshot}
*/
private void restore() {
mSnapshot = mSnapshot.restore();
}
private boolean clipRect(float left, float top, float right, float bottom, int regionOp) {
return mSnapshot.clipRect(left, top, right, bottom, regionOp);
}
private static void drawBitmap(
long nativeCanvas,
Bitmap_Delegate bitmap,
long nativePaintOrZero,
final int sleft, final int stop, final int sright, final int sbottom,
final int dleft, final int dtop, final int dright, final int dbottom) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
if (canvasDelegate == null) {
return;
}
// get the paint, which could be null if the int is 0
Paint_Delegate paintDelegate = Paint_Delegate.getDelegate(nativePaintOrZero);
final BufferedImage image = getImageToDraw(bitmap, paintDelegate, sBoolOut);
draw(nativeCanvas, nativePaintOrZero, true /*compositeOnly*/, sBoolOut[0],
new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paint) {
if (paint != null && paint.isFilterBitmap()) {
graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
}
//FIXME add support for canvas, screen and bitmap densities.
graphics.drawImage(image, dleft, dtop, dright, dbottom,
sleft, stop, sright, sbottom, null);
}
});
}
/**
* Returns a BufferedImage ready for drawing, based on the bitmap and paint delegate.
* The image returns, through a 1-size boolean array, whether the drawing code should
* use a SRC composite no matter what the paint says.
*
* @param bitmap the bitmap
* @param paint the paint that will be used to draw
* @param forceSrcMode whether the composite will have to be SRC
* @return the image to draw
*/
private static BufferedImage getImageToDraw(Bitmap_Delegate bitmap, Paint_Delegate paint,
boolean[] forceSrcMode) {
BufferedImage image = bitmap.getImage();
forceSrcMode[0] = false;
// if the bitmap config is alpha_8, then we erase all color value from it
// before drawing it.
if (bitmap.getConfig() == Bitmap.Config.ALPHA_8) {
fixAlpha8Bitmap(image);
} else if (!bitmap.hasAlpha()) {
// hasAlpha is merely a rendering hint. There can in fact be alpha values
// in the bitmap but it should be ignored at drawing time.
// There is two ways to do this:
// - override the composite to be SRC. This can only be used if the composite
// was going to be SRC or SRC_OVER in the first place
// - Create a different bitmap to draw in which all the alpha channel values is set
// to 0xFF.
if (paint != null) {
Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
if (xfermodeDelegate instanceof PorterDuffXfermode_Delegate) {
PorterDuff.Mode mode =
((PorterDuffXfermode_Delegate)xfermodeDelegate).getMode();
forceSrcMode[0] = mode == PorterDuff.Mode.SRC_OVER ||
mode == PorterDuff.Mode.SRC;
}
}
// if we can't force SRC mode, then create a temp bitmap of TYPE_RGB
if (!forceSrcMode[0]) {
image = Bitmap_Delegate.createCopy(image, BufferedImage.TYPE_INT_RGB, 0xFF);
}
}
return image;
}
private static void fixAlpha8Bitmap(final BufferedImage image) {
int w = image.getWidth();
int h = image.getHeight();
int[] argb = new int[w * h];
image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
final int length = argb.length;
for (int i = 0 ; i < length; i++) {
argb[i] &= 0xFF000000;
}
image.setRGB(0, 0, w, h, argb, 0, w);
super();
}
}

View File

@@ -63,16 +63,8 @@ public class ComposeShader_Delegate extends Shader_Delegate {
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static long nativeCreate1(long native_shaderA, long native_shaderB,
long native_mode) {
// FIXME not supported yet.
ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
return sManager.addNewDelegate(newDelegate);
}
@LayoutlibDelegate
/*package*/ static long nativeCreate2(long native_shaderA, long native_shaderB,
int porterDuffMode) {
/*package*/ static long nativeCreate(long native_shaderA, long native_shaderB,
int native_mode) {
// FIXME not supported yet.
ComposeShader_Delegate newDelegate = new ComposeShader_Delegate();
return sManager.addNewDelegate(newDelegate);

View File

@@ -90,10 +90,11 @@ public class Paint_Delegate {
private int mHintingMode = Paint.HINTING_ON;
private int mHyphenEdit;
private float mLetterSpacing; // not used in actual text rendering.
private float mWordSpacing; // not used in actual text rendering.
// Variant of the font. A paint's variant can only be compact or elegant.
private FontVariant mFontVariant = FontVariant.COMPACT;
private Xfermode_Delegate mXfermode;
private int mPorterDuffMode = Xfermode.DEFAULT;
private ColorFilter_Delegate mColorFilter;
private Shader_Delegate mShader;
private PathEffect_Delegate mPathEffect;
@@ -206,12 +207,10 @@ public class Paint_Delegate {
}
/**
* Returns the {@link Xfermode} delegate or null if none have been set
*
* @return the delegate or null.
* Returns the {@link PorterDuff.Mode} as an int
*/
public Xfermode_Delegate getXfermode() {
return mXfermode;
public int getPorterDuffMode() {
return mPorterDuffMode;
}
/**
@@ -841,16 +840,12 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static long nSetXfermode(long native_object, long xfermode) {
// get the delegate from the native int.
/*package*/ static void nSetXfermode(long native_object, int xfermode) {
Paint_Delegate delegate = sManager.getDelegate(native_object);
if (delegate == null) {
return xfermode;
return;
}
delegate.mXfermode = Xfermode_Delegate.getDelegate(xfermode);
return xfermode;
delegate.mPorterDuffMode = xfermode;
}
@LayoutlibDelegate
@@ -998,7 +993,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int nGetTextRunCursor(long native_object, char[] text,
/*package*/ static int nGetTextRunCursor(Paint paint, long native_object, char[] text,
int contextStart, int contextLength, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1007,7 +1002,7 @@ public class Paint_Delegate {
}
@LayoutlibDelegate
/*package*/ static int nGetTextRunCursor(long native_object, String text,
/*package*/ static int nGetTextRunCursor(Paint paint, long native_object, String text,
int contextStart, int contextEnd, int flags, int offset, int cursorOpt) {
// FIXME
Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
@@ -1085,6 +1080,26 @@ public class Paint_Delegate {
delegate.mLetterSpacing = letterSpacing;
}
@LayoutlibDelegate
/*package*/ static float nGetWordSpacing(long nativePaint) {
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return 0;
}
return delegate.mWordSpacing;
}
@LayoutlibDelegate
/*package*/ static void nSetWordSpacing(long nativePaint, float wordSpacing) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
"Paint.setWordSpacing() not supported.", null, null);
Paint_Delegate delegate = sManager.getDelegate(nativePaint);
if (delegate == null) {
return;
}
delegate.mWordSpacing = wordSpacing;
}
@LayoutlibDelegate
/*package*/ static void nSetFontFeatureSettings(long nativePaint, String settings) {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_TEXT_RENDERING,
@@ -1215,7 +1230,7 @@ public class Paint_Delegate {
mStrokeWidth = paint.mStrokeWidth;
mStrokeMiter = paint.mStrokeMiter;
mXfermode = paint.mXfermode;
mPorterDuffMode = paint.mPorterDuffMode;
mColorFilter = paint.mColorFilter;
mShader = paint.mShader;
mPathEffect = paint.mPathEffect;
@@ -1242,7 +1257,7 @@ public class Paint_Delegate {
mTextSize = 20.f;
mTextScaleX = 1.f;
mTextSkewX = 0.f;
mXfermode = null;
mPorterDuffMode = Xfermode.DEFAULT;
mColorFilter = null;
mShader = null;
mPathEffect = null;

View File

@@ -1,87 +0,0 @@
/*
* Copyright (C) 2010 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 android.graphics;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.layoutlib.bridge.impl.PorterDuffUtility;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.PorterDuff.Mode;
import java.awt.Composite;
import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;
/**
* Delegate implementing the native methods of android.graphics.PorterDuffXfermode
*
* Through the layoutlib_create tool, the original native methods of PorterDuffXfermode have been
* replaced by calls to methods of the same name in this delegate class.
*
* This class behaves like the original native implementation, but in Java, keeping previously
* native data into its own objects and mapping them to int that are sent back and forth between
* it and the original PorterDuffXfermode class.
*
* Because this extends {@link Xfermode_Delegate}, there's no need to use a
* {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
* {@link Xfermode_Delegate}.
*
*/
public class PorterDuffXfermode_Delegate extends Xfermode_Delegate {
// ---- delegate data ----
private final Mode mMode;
// ---- Public Helper methods ----
public Mode getMode() {
return mMode;
}
@Override
public Composite getComposite(int alpha) {
return PorterDuffUtility.getComposite(mMode, alpha);
}
@Override
public boolean isSupported() {
return true;
}
@Override
public String getSupportMessage() {
// no message since isSupported returns true;
return null;
}
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static long nativeCreateXfermode(int mode) {
PorterDuffXfermode_Delegate newDelegate = new PorterDuffXfermode_Delegate(mode);
return sManager.addNewDelegate(newDelegate);
}
// ---- Private delegate/helper methods ----
private PorterDuffXfermode_Delegate(int mode) {
mMode = getPorterDuffMode(mode);
}
}

View File

@@ -1,69 +0,0 @@
/*
* Copyright (C) 2010 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 android.graphics;
import com.android.layoutlib.bridge.impl.DelegateManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import java.awt.Composite;
/**
* Delegate implementing the native methods of android.graphics.Xfermode
*
* Through the layoutlib_create tool, the original native methods of Xfermode have been replaced
* by calls to methods of the same name in this delegate class.
*
* This class behaves like the original native implementation, but in Java, keeping previously
* native data into its own objects and mapping them to int that are sent back and forth between
* it and the original Xfermode class.
*
* This also serve as a base class for all Xfermode delegate classes.
*
* @see DelegateManager
*
*/
public abstract class Xfermode_Delegate {
// ---- delegate manager ----
protected static final DelegateManager<Xfermode_Delegate> sManager =
new DelegateManager<Xfermode_Delegate>(Xfermode_Delegate.class);
// ---- delegate helper data ----
// ---- delegate data ----
// ---- Public Helper methods ----
public static Xfermode_Delegate getDelegate(long native_instance) {
return sManager.getDelegate(native_instance);
}
public abstract Composite getComposite(int alpha);
public abstract boolean isSupported();
public abstract String getSupportMessage();
// ---- native methods ----
@LayoutlibDelegate
/*package*/ static void finalizer(long native_instance) {
sManager.removeJavaReferenceFor(native_instance);
}
// ---- Private delegate/helper methods ----
}

View File

@@ -57,9 +57,14 @@ public class AnimatedVectorDrawable_Delegate {
return sAnimatorSets.addNewDelegate(new AnimatorSetHolder());
}
@LayoutlibDelegate
/*package*/ static void nSetVectorDrawableTarget(long animatorPtr, long vectorDrawablePtr) {
// TODO: implement
}
@LayoutlibDelegate
/*package*/ static void nAddAnimator(long setPtr, long propertyValuesHolder,
long nativeInterpolator, long startDelay, long duration, int repeatCount) {
long nativeInterpolator, long startDelay, long duration, int repeatCount,
int repeatMode) {
PropertySetter holder = sHolders.getDelegate(propertyValuesHolder);
if (holder == null || holder.getValues() == null) {
return;
@@ -72,6 +77,7 @@ public class AnimatedVectorDrawable_Delegate {
animator.setStartDelay(startDelay);
animator.setDuration(duration);
animator.setRepeatCount(repeatCount);
animator.setRepeatMode(repeatMode);
animator.setTarget(holder);
animator.setPropertyName(holder.getValues().getPropertyName());
@@ -136,6 +142,14 @@ public class AnimatedVectorDrawable_Delegate {
setter.setValues(data);
}
@LayoutlibDelegate
/*package*/ static void nSetPropertyHolderData(long nativePtr, int[] data, int length) {
PropertySetter setter = sHolders.getDelegate(nativePtr);
assert setter != null;
setter.setValues(data);
}
@LayoutlibDelegate
/*package*/ static void nStart(long animatorSetPtr, VectorDrawableAnimatorRT set, int id) {
AnimatorSetHolder animatorSet = sAnimatorSets.getDelegate(animatorSetPtr);

View File

@@ -18,6 +18,7 @@ package android.graphics.drawable;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.Canvas;
import android.graphics.drawable.AnimatedVectorDrawable.VectorDrawableAnimatorRT;
public class AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate {
@@ -25,4 +26,9 @@ public class AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate {
/*package*/ static boolean useLastSeenTarget(VectorDrawableAnimatorRT thisDrawableAnimator) {
return true;
}
@LayoutlibDelegate
/*package*/ static void onDraw(VectorDrawableAnimatorRT thisDrawableAnimator, Canvas canvas) {
// Do not attempt to record as we are not using a DisplayListCanvas
}
}

View File

@@ -23,6 +23,7 @@ import android.annotation.NonNull;
import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.BaseCanvas_Delegate;
import android.graphics.Canvas_Delegate;
import android.graphics.Color;
import android.graphics.Matrix;
@@ -1197,7 +1198,7 @@ public class VectorDrawable_Delegate {
fillPaintDelegate.setColorFilter(filterPtr);
fillPaintDelegate.setShader(fullPath.mFillGradient);
Path_Delegate.native_setFillType(mRenderPath.mNativePath, fullPath.mFillType);
Canvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
BaseCanvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
.getNativeInstance());
}
@@ -1228,7 +1229,7 @@ public class VectorDrawable_Delegate {
final float finalStrokeScale = minScale * matrixScale;
strokePaint.setStrokeWidth(fullPath.mStrokeWidth * finalStrokeScale);
strokePaintDelegate.setShader(fullPath.mStrokeGradient);
Canvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, strokePaint
BaseCanvas_Delegate.nDrawPath(canvasPtr, mRenderPath.mNativePath, strokePaint
.getNativeInstance());
}
}

View File

@@ -30,6 +30,13 @@ public final class ServiceManager {
return null;
}
/**
* Is not supposed to return null, but that is fine for layoutlib.
*/
public static IBinder getServiceOrThrow(String name) throws ServiceNotFoundException {
return null;
}
/**
* Place a new @a service called @a name into the service
* manager.

View File

@@ -102,4 +102,9 @@ public class SystemProperties_Delegate {
/*package*/ static void native_add_change_callback() {
// pass.
}
@LayoutlibDelegate
/*package*/ static void native_report_sysprop_change() {
// pass.
}
}

View File

@@ -21,6 +21,8 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.graphics.Matrix;
import libcore.util.NativeAllocationRegistry_Delegate;
/**
* Delegate implementing the native methods of {@link RenderNode}
* <p/>
@@ -35,7 +37,7 @@ public class RenderNode_Delegate {
// ---- delegate manager ----
private static final DelegateManager<RenderNode_Delegate> sManager =
new DelegateManager<RenderNode_Delegate>(RenderNode_Delegate.class);
private static long sFinalizer = -1;
private float mLift;
private float mTranslationX;
@@ -62,8 +64,13 @@ public class RenderNode_Delegate {
}
@LayoutlibDelegate
/*package*/ static void nDestroyRenderNode(long renderNode) {
sManager.removeJavaReferenceFor(renderNode);
/*package*/ static long nGetNativeFinalizer() {
synchronized (RenderNode_Delegate.class) {
if (sFinalizer == -1) {
sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
}
}
return sFinalizer;
}
@LayoutlibDelegate

View File

@@ -24,12 +24,13 @@ import android.graphics.Canvas;
import android.graphics.ColorFilter_Delegate;
import android.graphics.Paint;
import android.graphics.Paint_Delegate;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Region_Delegate;
import android.graphics.Shader_Delegate;
import android.graphics.Xfermode_Delegate;
import java.awt.AlphaComposite;
import java.awt.Color;
@@ -827,28 +828,9 @@ public class GcSnapshot {
g.setComposite(AlphaComposite.getInstance(forceMode, (float) alpha / 255.f));
return;
}
Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
if (xfermodeDelegate != null) {
if (xfermodeDelegate.isSupported()) {
Composite composite = xfermodeDelegate.getComposite(alpha);
assert composite != null;
if (composite != null) {
g.setComposite(composite);
return;
}
} else {
Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE,
xfermodeDelegate.getSupportMessage(),
null /*throwable*/, null /*data*/);
}
}
// if there was no custom xfermode, but we have alpha (due to a shader and a non
// opaque alpha channel in the paint color), then we create an AlphaComposite anyway
// that will handle the alpha.
if (alpha != 0xFF) {
g.setComposite(AlphaComposite.getInstance(
AlphaComposite.SRC_OVER, (float) alpha / 255.f));
}
Mode mode = PorterDuff.intToMode(paint.getPorterDuffMode());
Composite composite = PorterDuffUtility.getComposite(mode, alpha);
g.setComposite(composite);
}
private void mapRect(AffineTransform matrix, RectF dst, RectF src) {

View File

@@ -24,14 +24,12 @@ import android.graphics.BlendComposite.BlendingMode;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffColorFilter_Delegate;
import android.graphics.PorterDuffXfermode_Delegate;
import java.awt.AlphaComposite;
import java.awt.Composite;
/**
* Provides various utility methods for {@link PorterDuffColorFilter_Delegate} and {@link
* PorterDuffXfermode_Delegate}.
* Provides various utility methods for {@link PorterDuffColorFilter_Delegate}.
*/
public final class PorterDuffUtility {

View File

@@ -180,6 +180,7 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.BitmapFactory#finishDecode",
"android.graphics.BitmapFactory#setDensityFromOptions",
"android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#useLastSeenTarget",
"android.graphics.drawable.AnimatedVectorDrawable$VectorDrawableAnimatorRT#onDraw",
"android.graphics.drawable.GradientDrawable#buildRing",
"android.graphics.FontFamily#addFont",
"android.graphics.Typeface#getSystemFontConfigLocation",
@@ -206,7 +207,7 @@ public final class CreateInfo implements ICreateInfo {
"android.view.MenuInflater#registerMenu",
"android.view.RenderNode#getMatrix",
"android.view.RenderNode#nCreate",
"android.view.RenderNode#nDestroyRenderNode",
"android.view.RenderNode#nGetNativeFinalizer",
"android.view.RenderNode#nSetElevation",
"android.view.RenderNode#nGetElevation",
"android.view.RenderNode#nSetTranslationX",
@@ -247,6 +248,7 @@ public final class CreateInfo implements ICreateInfo {
*/
public final static String[] DELEGATE_CLASS_NATIVES = new String[] {
"android.animation.PropertyValuesHolder",
"android.graphics.BaseCanvas",
"android.graphics.Bitmap",
"android.graphics.BitmapFactory",
"android.graphics.BitmapShader",
@@ -275,7 +277,6 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.PathEffect",
"android.graphics.PathMeasure",
"android.graphics.PorterDuffColorFilter",
"android.graphics.PorterDuffXfermode",
"android.graphics.RadialGradient",
"android.graphics.Rasterizer",
"android.graphics.Region",
@@ -283,7 +284,6 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.SumPathEffect",
"android.graphics.SweepGradient",
"android.graphics.Typeface",
"android.graphics.Xfermode",
"android.graphics.drawable.AnimatedVectorDrawable",
"android.graphics.drawable.VectorDrawable",
"android.os.SystemClock",

View File

@@ -124,6 +124,7 @@ public class Main {
"android.annotation.NonNull", // annotations
"android.annotation.Nullable", // annotations
"com.android.internal.transition.EpicenterTranslateClipReveal",
"com.android.internal.graphics.drawable.AnimationScaleListDrawable",
},
excludeClasses,
new String[] {