Fix layoutlib to reflect recent changes in platform code
Test: Layoutlib tests
Change-Id: I81964233a9e580ccee9c9e9b0cf3525babf30bd4
diff --git a/bridge/src/android/graphics/BaseCanvas_Delegate.java b/bridge/src/android/graphics/BaseCanvas_Delegate.java
new file mode 100644
index 0000000..df85806
--- /dev/null
+++ b/bridge/src/android/graphics/BaseCanvas_Delegate.java
@@ -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);
+ }
+}
diff --git a/bridge/src/android/graphics/Canvas_Delegate.java b/bridge/src/android/graphics/Canvas_Delegate.java
index 94152cd..43a0ff5 100644
--- a/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/bridge/src/android/graphics/Canvas_Delegate.java
@@ -55,40 +55,27 @@
* @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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
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 @@
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 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 @@
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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
@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 @@
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 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 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 @@
@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 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 @@
@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 @@
}
@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 @@
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();
}
}
diff --git a/bridge/src/android/graphics/ComposeShader_Delegate.java b/bridge/src/android/graphics/ComposeShader_Delegate.java
index 59ddcc6..a459734 100644
--- a/bridge/src/android/graphics/ComposeShader_Delegate.java
+++ b/bridge/src/android/graphics/ComposeShader_Delegate.java
@@ -63,16 +63,8 @@
// ---- 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);
diff --git a/bridge/src/android/graphics/Paint_Delegate.java b/bridge/src/android/graphics/Paint_Delegate.java
index 0bbe33d..e68d8b3 100644
--- a/bridge/src/android/graphics/Paint_Delegate.java
+++ b/bridge/src/android/graphics/Paint_Delegate.java
@@ -90,10 +90,11 @@
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 @@
}
/**
- * 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 @@
}
@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 @@
}
@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 @@
}
@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,
@@ -1086,6 +1081,26 @@
}
@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,
"Paint.setFontFeatureSettings() not supported.", null, null);
@@ -1215,7 +1230,7 @@
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 @@
mTextSize = 20.f;
mTextScaleX = 1.f;
mTextSkewX = 0.f;
- mXfermode = null;
+ mPorterDuffMode = Xfermode.DEFAULT;
mColorFilter = null;
mShader = null;
mPathEffect = null;
diff --git a/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
deleted file mode 100644
index 8825f84..0000000
--- a/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ /dev/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);
- }
-
-}
diff --git a/bridge/src/android/graphics/Xfermode_Delegate.java b/bridge/src/android/graphics/Xfermode_Delegate.java
deleted file mode 100644
index 94a6d76..0000000
--- a/bridge/src/android/graphics/Xfermode_Delegate.java
+++ /dev/null
@@ -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 ----
-
-}
diff --git a/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java b/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
index 200fe3b..ad2c564 100644
--- a/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
+++ b/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_Delegate.java
@@ -58,8 +58,13 @@
}
@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 @@
animator.setStartDelay(startDelay);
animator.setDuration(duration);
animator.setRepeatCount(repeatCount);
+ animator.setRepeatMode(repeatMode);
animator.setTarget(holder);
animator.setPropertyName(holder.getValues().getPropertyName());
@@ -137,6 +143,14 @@
}
@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);
assert animatorSet != null;
diff --git a/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java b/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
index 3d78931..fc848d9 100644
--- a/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
+++ b/bridge/src/android/graphics/drawable/AnimatedVectorDrawable_VectorDrawableAnimatorRT_Delegate.java
@@ -18,6 +18,7 @@
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 @@
/*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
+ }
}
diff --git a/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index 9904263..cee679a 100644
--- a/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -23,6 +23,7 @@
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 @@
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 @@
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());
}
}
diff --git a/bridge/src/android/os/ServiceManager.java b/bridge/src/android/os/ServiceManager.java
index 3e1ec07..c96d2ca 100644
--- a/bridge/src/android/os/ServiceManager.java
+++ b/bridge/src/android/os/ServiceManager.java
@@ -31,6 +31,13 @@
}
/**
+ * 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.
*
diff --git a/bridge/src/android/os/SystemProperties_Delegate.java b/bridge/src/android/os/SystemProperties_Delegate.java
index af0c456..d299add 100644
--- a/bridge/src/android/os/SystemProperties_Delegate.java
+++ b/bridge/src/android/os/SystemProperties_Delegate.java
@@ -102,4 +102,9 @@
/*package*/ static void native_add_change_callback() {
// pass.
}
+
+ @LayoutlibDelegate
+ /*package*/ static void native_report_sysprop_change() {
+ // pass.
+ }
}
diff --git a/bridge/src/android/view/RenderNode_Delegate.java b/bridge/src/android/view/RenderNode_Delegate.java
index 24f7887..a801cb0 100644
--- a/bridge/src/android/view/RenderNode_Delegate.java
+++ b/bridge/src/android/view/RenderNode_Delegate.java
@@ -21,6 +21,8 @@
import android.graphics.Matrix;
+import libcore.util.NativeAllocationRegistry_Delegate;
+
/**
* Delegate implementing the native methods of {@link RenderNode}
* <p/>
@@ -35,7 +37,7 @@
// ---- 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 @@
}
@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
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
index e80cbf2..7526e09 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
@@ -24,12 +24,13 @@
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 @@
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) {
diff --git a/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java b/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
index 80d7c68..70e2eb1 100644
--- a/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
+++ b/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
@@ -24,14 +24,12 @@
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 {