Loading tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +194 −25 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.graphics; import com.android.ide.common.rendering.api.ResourceDensity; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.impl.DelegateManager; import android.graphics.Bitmap.Config; Loading @@ -29,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.Buffer; import java.util.Arrays; import javax.imageio.ImageIO; Loading Loading @@ -57,6 +59,7 @@ public final class Bitmap_Delegate { private final Config mConfig; private BufferedImage mImage; private boolean mHasAlpha = true; private int mGenerationId = 0; // ---- Public Helper methods ---- Loading Loading @@ -173,6 +176,22 @@ public final class Bitmap_Delegate { return mConfig; } /** * Returns the hasAlpha rendering hint * @return true if the bitmap alpha should be used at render time */ public boolean hasAlpha() { return mHasAlpha && mConfig != Config.RGB_565; } /** * Update the generationId. * * @see Bitmap#getGenerationId() */ public void change() { mGenerationId++; } // ---- native methods ---- Loading @@ -183,7 +202,9 @@ public final class Bitmap_Delegate { // create the image BufferedImage image = new BufferedImage(width, height, imageType); // FIXME fill the bitmap! if (colors != null) { image.setRGB(0, 0, width, height, colors, offset, stride); } // create a delegate with the content of the stream. Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]); Loading @@ -192,8 +213,31 @@ public final class Bitmap_Delegate { } /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap"); Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap); if (srcBmpDelegate == null) { assert false; return null; } BufferedImage srcImage = srcBmpDelegate.getImage(); int width = srcImage.getWidth(); int height = srcImage.getHeight(); int imageType = getBufferedImageType(nativeConfig); // create the image BufferedImage image = new BufferedImage(width, height, imageType); // copy the source image into the image. int[] argb = new int[width * height]; srcImage.getRGB(0, 0, width, height, argb, 0, width); image.setRGB(0, 0, width, height, argb, 0, width); // create a delegate with the content of the stream. Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]); return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity()); } /*package*/ static void nativeDestructor(int nativeBitmap) { Loading @@ -206,8 +250,8 @@ public final class Bitmap_Delegate { /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality, OutputStream stream, byte[] tempStorage) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap"); Bridge.getLog().error(null, "Bitmap.compress() is not supported"); return true; } /*package*/ static void nativeErase(int nativeBitmap, int color) { Loading @@ -222,7 +266,7 @@ public final class Bitmap_Delegate { Graphics2D g = image.createGraphics(); try { g.setColor(new java.awt.Color(color, delegate.mHasAlpha)); g.setColor(new java.awt.Color(color, true)); g.fillRect(0, 0, image.getWidth(), image.getHeight()); } finally { Loading Loading @@ -298,20 +342,35 @@ public final class Bitmap_Delegate { /*package*/ static void nativeGetPixels(int nativeBitmap, int[] pixels, int offset, int stride, int x, int y, int width, int height) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGetPixels"); Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { assert false; return; } delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride); } /*package*/ static void nativeSetPixel(int nativeBitmap, int x, int y, int color) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixel"); Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { assert false; return; } delegate.getImage().setRGB(x, y, color); } /*package*/ static void nativeSetPixels(int nativeBitmap, int[] colors, int offset, int stride, int x, int y, int width, int height) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixels"); Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { assert false; return; } delegate.getImage().setRGB(x, y, width, height, colors, offset, stride); } /*package*/ static void nativeCopyPixelsToBuffer(int nativeBitmap, Buffer dst) { Loading @@ -325,31 +384,68 @@ public final class Bitmap_Delegate { } /*package*/ static int nativeGenerationId(int nativeBitmap) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGenerationId"); Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { assert false; return 0; } return delegate.mGenerationId; } /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCreateFromParcel"); // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only // used during aidl call so really this should not be called. Bridge.getLog().error(null, "AIDL is not suppored, and therefore bitmap cannot be created from parcels"); return null; } /*package*/ static boolean nativeWriteToParcel(int nativeBitmap, boolean isMutable, int density, Parcel p) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeWriteToParcel"); // This is only called when sending a bitmap through aidl, so really this should not // be called. Bridge.getLog().error(null, "AIDL is not suppored, and therefore bitmap cannot be written to parcels"); return false; } /*package*/ static Bitmap nativeExtractAlpha(int nativeBitmap, int nativePaint, int[] offsetXY) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeExtractAlpha"); Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap); if (bitmap == null) { assert false; return null; } Paint_Delegate paint = null; if (nativePaint > 0) { paint = Paint_Delegate.getDelegate(nativePaint); if (paint == null) { assert false; return null; } } if (paint != null && paint.getMaskFilter() != 0) { Bridge.getLog().fidelityWarning(null, "MaskFilter not supported in Bitmap.extractAlpha", null); } int alpha = paint != null ? paint.getAlpha() : 0xFF; BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha); // create the delegate. The actual Bitmap config is only an alpha channel Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8); // the density doesn't matter, it's set by the Java method. return createBitmap(delegate, false /*isMutable*/, ResourceDensity.DEFAULT_DENSITY /*density*/); } /*package*/ static void nativePrepareToDraw(int nativeBitmap) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativePrepareToDraw"); // nothing to be done here. } /*package*/ static void nativeSetHasAlpha(int nativeBitmap, boolean hasAlpha) { Loading @@ -364,8 +460,48 @@ public final class Bitmap_Delegate { } /*package*/ static boolean nativeSameAs(int nb0, int nb1) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSameAs"); Bitmap_Delegate delegate1 = sManager.getDelegate(nb0); if (delegate1 == null) { assert false; return false; } Bitmap_Delegate delegate2 = sManager.getDelegate(nb1); if (delegate2 == null) { assert false; return false; } BufferedImage image1 = delegate1.getImage(); BufferedImage image2 = delegate2.getImage(); if (delegate1.mConfig != delegate2.mConfig || image1.getWidth() != image2.getWidth() || image1.getHeight() != image2.getHeight()) { return false; } // get the internal data int w = image1.getWidth(); int h = image2.getHeight(); int[] argb1 = new int[w*h]; int[] argb2 = new int[w*h]; image1.getRGB(0, 0, w, h, argb1, 0, w); image2.getRGB(0, 0, w, h, argb2, 0, w); // compares if (delegate1.mConfig == Config.ALPHA_8) { // in this case we have to manually compare the alpha channel as the rest is garbage. final int length = w*h; for (int i = 0 ; i < length ; i++) { if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) { return false; } } return true; } return Arrays.equals(argb1, argb2); } // ---- Private delegate/helper methods ---- Loading @@ -382,4 +518,37 @@ public final class Bitmap_Delegate { // and create/return a new Bitmap with it return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, density); } /** * Creates and returns a copy of a given BufferedImage. * <p/> * if alpha is different than 255, then it is applied to the alpha channel of each pixel. * * @param image the image to copy * @param imageType the type of the new image * @param alpha an optional alpha modifier * @return a new BufferedImage */ /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) { int w = image.getWidth(); int h = image.getHeight(); BufferedImage result = new BufferedImage(w, h, imageType); int[] argb = new int[w * h]; image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth()); if (alpha != 255) { final int length = argb.length; for (int i = 0 ; i < length; i++) { int a = (argb[i] >>> 24 * alpha) / 255; argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF); } } result.setRGB(0, 0, w, h, argb, 0, w); return result; } } tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +230 −113 File changed.Preview size limit exceeded, changes collapsed. Show changes tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +1 −1 Original line number Diff line number Diff line Loading @@ -164,7 +164,7 @@ public final class NinePatch_Delegate { chunkObject.draw(bitmap_delegate.getImage(), graphics, left, top, right - left, bottom - top, destDensity, srcDensity); } }, paint_delegate, true /*compositeOnly*/); }, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/); } Loading tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java +4 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,10 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate { // ---- Public Helper methods ---- public PorterDuff.Mode getMode() { return getPorterDuffMode(mMode); } @Override public Composite getComposite(int alpha) { return getComposite(getPorterDuffMode(mMode), alpha); Loading tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +83 −45 Original line number Diff line number Diff line Loading @@ -18,12 +18,11 @@ package com.android.layoutlib.bridge.impl; import com.android.layoutlib.bridge.Bridge; import android.graphics.Bitmap_Delegate; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint_Delegate; import android.graphics.PathEffect_Delegate; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode_Delegate; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; Loading Loading @@ -81,11 +80,33 @@ public class GcSnapshot { */ private static class Layer { private final Graphics2D mGraphics; private final Bitmap_Delegate mBitmap; private final BufferedImage mImage; private BufferedImage mOriginalCopy; /** * Creates a layer with a graphics and a bitmap. * * @param graphics the graphics * @param bitmap the bitmap */ Layer(Graphics2D graphics, Bitmap_Delegate bitmap) { mGraphics = graphics; mBitmap = bitmap; mImage = mBitmap.getImage(); } /** * Creates a layer with a graphics and an image. If the image belongs to a * {@link Bitmap_Delegate}, then {@link Layer#Layer(Graphics2D, Bitmap_Delegate)} should * be used. * * @param graphics the graphics * @param image the image */ Layer(Graphics2D graphics, BufferedImage image) { mGraphics = graphics; mBitmap = null; mImage = image; } Loading @@ -100,6 +121,10 @@ public class GcSnapshot { } Layer makeCopy() { if (mBitmap != null) { return new Layer((Graphics2D) mGraphics.create(), mBitmap); } return new Layer((Graphics2D) mGraphics.create(), mImage); } Loading @@ -111,22 +136,28 @@ public class GcSnapshot { BufferedImage getOriginalCopy() { return mOriginalCopy; } void change() { if (mBitmap != null) { mBitmap.change(); } } } /** * Creates the root snapshot associating it with a given image. * Creates the root snapshot associating it with a given bitmap. * <p> * If <var>image</var> is null, then {@link GcSnapshot#setImage(BufferedImage)} must be * If <var>bitmap</var> is null, then {@link GcSnapshot#setBitmap(Bitmap_Delegate)} must be * called before the snapshot can be used to draw. Transform and clip operations are permitted * before. * * @param image the image to associate to the snapshot or null. * @return the root snapshot */ public static GcSnapshot createDefaultSnapshot(BufferedImage image) { public static GcSnapshot createDefaultSnapshot(Bitmap_Delegate bitmap) { GcSnapshot snapshot = new GcSnapshot(); if (image != null) { snapshot.setImage(image); if (bitmap != null) { snapshot.setBitmap(bitmap); } return snapshot; Loading Loading @@ -295,19 +326,19 @@ public class GcSnapshot { } /** * Link the snapshot to a BufferedImage. * Link the snapshot to a Bitmap_Delegate. * <p/> * This is only for the case where the snapshot was created with a null image when calling * {@link #createDefaultSnapshot(BufferedImage)}, and is therefore not yet linked to * {@link #createDefaultSnapshot(Bitmap_Delegate)}, and is therefore not yet linked to * a previous snapshot. * <p/> * If any transform or clip information was set before, they are put into the Graphics object. * @param image the buffered image to link to. * @param bitmap the bitmap to link to. */ public void setImage(BufferedImage image) { public void setBitmap(Bitmap_Delegate bitmap) { assert mLayers.size() == 0; Graphics2D graphics2D = image.createGraphics(); mLayers.add(new Layer(graphics2D, image)); Graphics2D graphics2D = bitmap.getImage().createGraphics(); mLayers.add(new Layer(graphics2D, bitmap)); if (mTransform != null) { graphics2D.setTransform(mTransform); mTransform = null; Loading Loading @@ -483,7 +514,7 @@ public class GcSnapshot { * @param drawable */ public void draw(Drawable drawable) { draw(drawable, null, false /*compositeOnly*/); draw(drawable, null, false /*compositeOnly*/, false /*forceSrcMode*/); } /** Loading @@ -494,30 +525,33 @@ public class GcSnapshot { * @param paint * @param compositeOnly whether the paint is used for composite only. This is typically * the case for bitmaps. * @param forceSrcMode if true, this overrides the composite to be SRC */ public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly) { public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly, boolean forceSrcMode) { // if we clip to the layer, then we only draw in the layer if (mLocalLayer != null && (mFlags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) != 0) { drawInLayer(mLocalLayer, drawable, paint, compositeOnly); drawInLayer(mLocalLayer, drawable, paint, compositeOnly, forceSrcMode); } else { // draw in all the layers for (Layer layer : mLayers) { drawInLayer(layer, drawable, paint, compositeOnly); drawInLayer(layer, drawable, paint, compositeOnly, forceSrcMode); } } } private void drawInLayer(Layer layer, Drawable drawable, Paint_Delegate paint, boolean compositeOnly) { boolean compositeOnly, boolean forceSrcMode) { Graphics2D originalGraphics = layer.getGraphics(); // get a Graphics2D object configured with the drawing parameters. Graphics2D configuredGraphics2D = paint != null ? createCustomGraphics(originalGraphics, paint, compositeOnly) : createCustomGraphics(originalGraphics, paint, compositeOnly, forceSrcMode) : (Graphics2D) originalGraphics.create(); try { drawable.draw(configuredGraphics2D, paint); layer.change(); } finally { // dispose Graphics2D object configuredGraphics2D.dispose(); Loading Loading @@ -557,7 +591,7 @@ public class GcSnapshot { // now draw put the content of the local layer onto the layer, using the paint // information Graphics2D g = createCustomGraphics(baseGfx, mLocalLayerPaint, true /*alphaOnly*/); true /*alphaOnly*/, false /*forceSrcMode*/); g.drawImage(mLocalLayer.getImage(), mLocalLayerRegion.left, mLocalLayerRegion.top, Loading Loading @@ -603,7 +637,7 @@ public class GcSnapshot { * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used. */ private Graphics2D createCustomGraphics(Graphics2D original, Paint_Delegate paint, boolean compositeOnly) { boolean compositeOnly, boolean forceSrcMode) { // make new one graphics Graphics2D g = (Graphics2D) original.create(); Loading Loading @@ -680,10 +714,14 @@ public class GcSnapshot { // it contains the alpha int alpha = (compositeOnly || customShader) ? paint.getAlpha() : 0xFF; if (forceSrcMode) { g.setComposite(AlphaComposite.getInstance( AlphaComposite.SRC, (float) alpha / 255.f)); } else { boolean customXfermode = false; int xfermode = paint.getXfermode(); if (xfermode > 0) { Xfermode_Delegate xfermodeDelegate = Xfermode_Delegate.getDelegate(paint.getXfermode()); Xfermode_Delegate xfermodeDelegate = Xfermode_Delegate.getDelegate(xfermode); assert xfermodeDelegate != null; if (xfermodeDelegate != null) { if (xfermodeDelegate.isSupported()) { Loading @@ -705,14 +743,14 @@ public class GcSnapshot { // opaque alpha channel in the paint color), then we create an AlphaComposite anyway // that will handle the alpha. if (customXfermode == false && alpha != 0xFF) { g.setComposite(PorterDuffXfermode_Delegate.getComposite( PorterDuff.Mode.SRC_OVER, alpha)); g.setComposite(AlphaComposite.getInstance( AlphaComposite.SRC_OVER, (float) alpha / 255.f)); } } return g; } private void mapRect(AffineTransform matrix, RectF dst, RectF src) { // array with 4 corners float[] corners = new float[] { Loading Loading
tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +194 −25 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package android.graphics; import com.android.ide.common.rendering.api.ResourceDensity; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.impl.DelegateManager; import android.graphics.Bitmap.Config; Loading @@ -29,6 +30,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.Buffer; import java.util.Arrays; import javax.imageio.ImageIO; Loading Loading @@ -57,6 +59,7 @@ public final class Bitmap_Delegate { private final Config mConfig; private BufferedImage mImage; private boolean mHasAlpha = true; private int mGenerationId = 0; // ---- Public Helper methods ---- Loading Loading @@ -173,6 +176,22 @@ public final class Bitmap_Delegate { return mConfig; } /** * Returns the hasAlpha rendering hint * @return true if the bitmap alpha should be used at render time */ public boolean hasAlpha() { return mHasAlpha && mConfig != Config.RGB_565; } /** * Update the generationId. * * @see Bitmap#getGenerationId() */ public void change() { mGenerationId++; } // ---- native methods ---- Loading @@ -183,7 +202,9 @@ public final class Bitmap_Delegate { // create the image BufferedImage image = new BufferedImage(width, height, imageType); // FIXME fill the bitmap! if (colors != null) { image.setRGB(0, 0, width, height, colors, offset, stride); } // create a delegate with the content of the stream. Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]); Loading @@ -192,8 +213,31 @@ public final class Bitmap_Delegate { } /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap"); Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap); if (srcBmpDelegate == null) { assert false; return null; } BufferedImage srcImage = srcBmpDelegate.getImage(); int width = srcImage.getWidth(); int height = srcImage.getHeight(); int imageType = getBufferedImageType(nativeConfig); // create the image BufferedImage image = new BufferedImage(width, height, imageType); // copy the source image into the image. int[] argb = new int[width * height]; srcImage.getRGB(0, 0, width, height, argb, 0, width); image.setRGB(0, 0, width, height, argb, 0, width); // create a delegate with the content of the stream. Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.sConfigs[nativeConfig]); return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity()); } /*package*/ static void nativeDestructor(int nativeBitmap) { Loading @@ -206,8 +250,8 @@ public final class Bitmap_Delegate { /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality, OutputStream stream, byte[] tempStorage) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap"); Bridge.getLog().error(null, "Bitmap.compress() is not supported"); return true; } /*package*/ static void nativeErase(int nativeBitmap, int color) { Loading @@ -222,7 +266,7 @@ public final class Bitmap_Delegate { Graphics2D g = image.createGraphics(); try { g.setColor(new java.awt.Color(color, delegate.mHasAlpha)); g.setColor(new java.awt.Color(color, true)); g.fillRect(0, 0, image.getWidth(), image.getHeight()); } finally { Loading Loading @@ -298,20 +342,35 @@ public final class Bitmap_Delegate { /*package*/ static void nativeGetPixels(int nativeBitmap, int[] pixels, int offset, int stride, int x, int y, int width, int height) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGetPixels"); Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { assert false; return; } delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride); } /*package*/ static void nativeSetPixel(int nativeBitmap, int x, int y, int color) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixel"); Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { assert false; return; } delegate.getImage().setRGB(x, y, color); } /*package*/ static void nativeSetPixels(int nativeBitmap, int[] colors, int offset, int stride, int x, int y, int width, int height) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixels"); Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { assert false; return; } delegate.getImage().setRGB(x, y, width, height, colors, offset, stride); } /*package*/ static void nativeCopyPixelsToBuffer(int nativeBitmap, Buffer dst) { Loading @@ -325,31 +384,68 @@ public final class Bitmap_Delegate { } /*package*/ static int nativeGenerationId(int nativeBitmap) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGenerationId"); Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap); if (delegate == null) { assert false; return 0; } return delegate.mGenerationId; } /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCreateFromParcel"); // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only // used during aidl call so really this should not be called. Bridge.getLog().error(null, "AIDL is not suppored, and therefore bitmap cannot be created from parcels"); return null; } /*package*/ static boolean nativeWriteToParcel(int nativeBitmap, boolean isMutable, int density, Parcel p) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeWriteToParcel"); // This is only called when sending a bitmap through aidl, so really this should not // be called. Bridge.getLog().error(null, "AIDL is not suppored, and therefore bitmap cannot be written to parcels"); return false; } /*package*/ static Bitmap nativeExtractAlpha(int nativeBitmap, int nativePaint, int[] offsetXY) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeExtractAlpha"); Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap); if (bitmap == null) { assert false; return null; } Paint_Delegate paint = null; if (nativePaint > 0) { paint = Paint_Delegate.getDelegate(nativePaint); if (paint == null) { assert false; return null; } } if (paint != null && paint.getMaskFilter() != 0) { Bridge.getLog().fidelityWarning(null, "MaskFilter not supported in Bitmap.extractAlpha", null); } int alpha = paint != null ? paint.getAlpha() : 0xFF; BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha); // create the delegate. The actual Bitmap config is only an alpha channel Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8); // the density doesn't matter, it's set by the Java method. return createBitmap(delegate, false /*isMutable*/, ResourceDensity.DEFAULT_DENSITY /*density*/); } /*package*/ static void nativePrepareToDraw(int nativeBitmap) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativePrepareToDraw"); // nothing to be done here. } /*package*/ static void nativeSetHasAlpha(int nativeBitmap, boolean hasAlpha) { Loading @@ -364,8 +460,48 @@ public final class Bitmap_Delegate { } /*package*/ static boolean nativeSameAs(int nb0, int nb1) { // FIXME implement native delegate throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSameAs"); Bitmap_Delegate delegate1 = sManager.getDelegate(nb0); if (delegate1 == null) { assert false; return false; } Bitmap_Delegate delegate2 = sManager.getDelegate(nb1); if (delegate2 == null) { assert false; return false; } BufferedImage image1 = delegate1.getImage(); BufferedImage image2 = delegate2.getImage(); if (delegate1.mConfig != delegate2.mConfig || image1.getWidth() != image2.getWidth() || image1.getHeight() != image2.getHeight()) { return false; } // get the internal data int w = image1.getWidth(); int h = image2.getHeight(); int[] argb1 = new int[w*h]; int[] argb2 = new int[w*h]; image1.getRGB(0, 0, w, h, argb1, 0, w); image2.getRGB(0, 0, w, h, argb2, 0, w); // compares if (delegate1.mConfig == Config.ALPHA_8) { // in this case we have to manually compare the alpha channel as the rest is garbage. final int length = w*h; for (int i = 0 ; i < length ; i++) { if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) { return false; } } return true; } return Arrays.equals(argb1, argb2); } // ---- Private delegate/helper methods ---- Loading @@ -382,4 +518,37 @@ public final class Bitmap_Delegate { // and create/return a new Bitmap with it return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/, density); } /** * Creates and returns a copy of a given BufferedImage. * <p/> * if alpha is different than 255, then it is applied to the alpha channel of each pixel. * * @param image the image to copy * @param imageType the type of the new image * @param alpha an optional alpha modifier * @return a new BufferedImage */ /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) { int w = image.getWidth(); int h = image.getHeight(); BufferedImage result = new BufferedImage(w, h, imageType); int[] argb = new int[w * h]; image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth()); if (alpha != 255) { final int length = argb.length; for (int i = 0 ; i < length; i++) { int a = (argb[i] >>> 24 * alpha) / 255; argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF); } } result.setRGB(0, 0, w, h, argb, 0, w); return result; } }
tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +230 −113 File changed.Preview size limit exceeded, changes collapsed. Show changes
tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +1 −1 Original line number Diff line number Diff line Loading @@ -164,7 +164,7 @@ public final class NinePatch_Delegate { chunkObject.draw(bitmap_delegate.getImage(), graphics, left, top, right - left, bottom - top, destDensity, srcDensity); } }, paint_delegate, true /*compositeOnly*/); }, paint_delegate, true /*compositeOnly*/, false /*forceSrcMode*/); } Loading
tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java +4 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,10 @@ public class PorterDuffXfermode_Delegate extends Xfermode_Delegate { // ---- Public Helper methods ---- public PorterDuff.Mode getMode() { return getPorterDuffMode(mMode); } @Override public Composite getComposite(int alpha) { return getComposite(getPorterDuffMode(mMode), alpha); Loading
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +83 −45 Original line number Diff line number Diff line Loading @@ -18,12 +18,11 @@ package com.android.layoutlib.bridge.impl; import com.android.layoutlib.bridge.Bridge; import android.graphics.Bitmap_Delegate; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint_Delegate; import android.graphics.PathEffect_Delegate; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode_Delegate; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.Region; Loading Loading @@ -81,11 +80,33 @@ public class GcSnapshot { */ private static class Layer { private final Graphics2D mGraphics; private final Bitmap_Delegate mBitmap; private final BufferedImage mImage; private BufferedImage mOriginalCopy; /** * Creates a layer with a graphics and a bitmap. * * @param graphics the graphics * @param bitmap the bitmap */ Layer(Graphics2D graphics, Bitmap_Delegate bitmap) { mGraphics = graphics; mBitmap = bitmap; mImage = mBitmap.getImage(); } /** * Creates a layer with a graphics and an image. If the image belongs to a * {@link Bitmap_Delegate}, then {@link Layer#Layer(Graphics2D, Bitmap_Delegate)} should * be used. * * @param graphics the graphics * @param image the image */ Layer(Graphics2D graphics, BufferedImage image) { mGraphics = graphics; mBitmap = null; mImage = image; } Loading @@ -100,6 +121,10 @@ public class GcSnapshot { } Layer makeCopy() { if (mBitmap != null) { return new Layer((Graphics2D) mGraphics.create(), mBitmap); } return new Layer((Graphics2D) mGraphics.create(), mImage); } Loading @@ -111,22 +136,28 @@ public class GcSnapshot { BufferedImage getOriginalCopy() { return mOriginalCopy; } void change() { if (mBitmap != null) { mBitmap.change(); } } } /** * Creates the root snapshot associating it with a given image. * Creates the root snapshot associating it with a given bitmap. * <p> * If <var>image</var> is null, then {@link GcSnapshot#setImage(BufferedImage)} must be * If <var>bitmap</var> is null, then {@link GcSnapshot#setBitmap(Bitmap_Delegate)} must be * called before the snapshot can be used to draw. Transform and clip operations are permitted * before. * * @param image the image to associate to the snapshot or null. * @return the root snapshot */ public static GcSnapshot createDefaultSnapshot(BufferedImage image) { public static GcSnapshot createDefaultSnapshot(Bitmap_Delegate bitmap) { GcSnapshot snapshot = new GcSnapshot(); if (image != null) { snapshot.setImage(image); if (bitmap != null) { snapshot.setBitmap(bitmap); } return snapshot; Loading Loading @@ -295,19 +326,19 @@ public class GcSnapshot { } /** * Link the snapshot to a BufferedImage. * Link the snapshot to a Bitmap_Delegate. * <p/> * This is only for the case where the snapshot was created with a null image when calling * {@link #createDefaultSnapshot(BufferedImage)}, and is therefore not yet linked to * {@link #createDefaultSnapshot(Bitmap_Delegate)}, and is therefore not yet linked to * a previous snapshot. * <p/> * If any transform or clip information was set before, they are put into the Graphics object. * @param image the buffered image to link to. * @param bitmap the bitmap to link to. */ public void setImage(BufferedImage image) { public void setBitmap(Bitmap_Delegate bitmap) { assert mLayers.size() == 0; Graphics2D graphics2D = image.createGraphics(); mLayers.add(new Layer(graphics2D, image)); Graphics2D graphics2D = bitmap.getImage().createGraphics(); mLayers.add(new Layer(graphics2D, bitmap)); if (mTransform != null) { graphics2D.setTransform(mTransform); mTransform = null; Loading Loading @@ -483,7 +514,7 @@ public class GcSnapshot { * @param drawable */ public void draw(Drawable drawable) { draw(drawable, null, false /*compositeOnly*/); draw(drawable, null, false /*compositeOnly*/, false /*forceSrcMode*/); } /** Loading @@ -494,30 +525,33 @@ public class GcSnapshot { * @param paint * @param compositeOnly whether the paint is used for composite only. This is typically * the case for bitmaps. * @param forceSrcMode if true, this overrides the composite to be SRC */ public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly) { public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly, boolean forceSrcMode) { // if we clip to the layer, then we only draw in the layer if (mLocalLayer != null && (mFlags & Canvas.CLIP_TO_LAYER_SAVE_FLAG) != 0) { drawInLayer(mLocalLayer, drawable, paint, compositeOnly); drawInLayer(mLocalLayer, drawable, paint, compositeOnly, forceSrcMode); } else { // draw in all the layers for (Layer layer : mLayers) { drawInLayer(layer, drawable, paint, compositeOnly); drawInLayer(layer, drawable, paint, compositeOnly, forceSrcMode); } } } private void drawInLayer(Layer layer, Drawable drawable, Paint_Delegate paint, boolean compositeOnly) { boolean compositeOnly, boolean forceSrcMode) { Graphics2D originalGraphics = layer.getGraphics(); // get a Graphics2D object configured with the drawing parameters. Graphics2D configuredGraphics2D = paint != null ? createCustomGraphics(originalGraphics, paint, compositeOnly) : createCustomGraphics(originalGraphics, paint, compositeOnly, forceSrcMode) : (Graphics2D) originalGraphics.create(); try { drawable.draw(configuredGraphics2D, paint); layer.change(); } finally { // dispose Graphics2D object configuredGraphics2D.dispose(); Loading Loading @@ -557,7 +591,7 @@ public class GcSnapshot { // now draw put the content of the local layer onto the layer, using the paint // information Graphics2D g = createCustomGraphics(baseGfx, mLocalLayerPaint, true /*alphaOnly*/); true /*alphaOnly*/, false /*forceSrcMode*/); g.drawImage(mLocalLayer.getImage(), mLocalLayerRegion.left, mLocalLayerRegion.top, Loading Loading @@ -603,7 +637,7 @@ public class GcSnapshot { * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used. */ private Graphics2D createCustomGraphics(Graphics2D original, Paint_Delegate paint, boolean compositeOnly) { boolean compositeOnly, boolean forceSrcMode) { // make new one graphics Graphics2D g = (Graphics2D) original.create(); Loading Loading @@ -680,10 +714,14 @@ public class GcSnapshot { // it contains the alpha int alpha = (compositeOnly || customShader) ? paint.getAlpha() : 0xFF; if (forceSrcMode) { g.setComposite(AlphaComposite.getInstance( AlphaComposite.SRC, (float) alpha / 255.f)); } else { boolean customXfermode = false; int xfermode = paint.getXfermode(); if (xfermode > 0) { Xfermode_Delegate xfermodeDelegate = Xfermode_Delegate.getDelegate(paint.getXfermode()); Xfermode_Delegate xfermodeDelegate = Xfermode_Delegate.getDelegate(xfermode); assert xfermodeDelegate != null; if (xfermodeDelegate != null) { if (xfermodeDelegate.isSupported()) { Loading @@ -705,14 +743,14 @@ public class GcSnapshot { // opaque alpha channel in the paint color), then we create an AlphaComposite anyway // that will handle the alpha. if (customXfermode == false && alpha != 0xFF) { g.setComposite(PorterDuffXfermode_Delegate.getComposite( PorterDuff.Mode.SRC_OVER, alpha)); g.setComposite(AlphaComposite.getInstance( AlphaComposite.SRC_OVER, (float) alpha / 255.f)); } } return g; } private void mapRect(AffineTransform matrix, RectF dst, RectF src) { // array with 4 corners float[] corners = new float[] { Loading