Fix layoutlib to reflect recent changes in platform code
Test: Layoutlib tests Change-Id: I81964233a9e580ccee9c9e9b0cf3525babf30bd4
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 ----
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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[] {
|
||||
|
||||
Reference in New Issue
Block a user