Bitmap_Delegate.java revision 0cd6c5b6bcaea7216a444a2729b728846878922e
1ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/*
2ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Copyright (C) 2010 The Android Open Source Project
3ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
4ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * you may not use this file except in compliance with the License.
6ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * You may obtain a copy of the License at
7ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
8ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
10ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Unless required by applicable law or agreed to in writing, software
11ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * See the License for the specific language governing permissions and
14ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * limitations under the License.
15ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
16ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
17ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipackage android.graphics;
18ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
19ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog;
20fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Guptaimport com.android.ide.common.rendering.api.RenderResources;
21fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Guptaimport com.android.ide.common.rendering.api.ResourceValue;
22ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.layoutlib.bridge.Bridge;
23fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Guptaimport com.android.layoutlib.bridge.android.BridgeContext;
24ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.layoutlib.bridge.impl.DelegateManager;
25fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Guptaimport com.android.layoutlib.bridge.impl.RenderAction;
26ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.resources.Density;
27fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Guptaimport com.android.resources.ResourceType;
28ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
29ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
30442aee6bc1abfb143dcfa1ba60d696e576d066c4Deepanshu Guptaimport android.annotation.Nullable;
31ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport android.graphics.Bitmap.Config;
32ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport android.os.Parcel;
33ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
34ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.awt.Graphics2D;
35ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.awt.image.BufferedImage;
36ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.io.File;
37ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.io.IOException;
38ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.io.InputStream;
39ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.io.OutputStream;
40ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.nio.Buffer;
41ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport java.util.Arrays;
42835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Guptaimport java.util.EnumSet;
43835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Guptaimport java.util.Set;
44ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
45ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskiimport javax.imageio.ImageIO;
46fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Guptaimport libcore.util.NativeAllocationRegistry_Delegate;
47ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
48ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski/**
49ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Delegate implementing the native methods of android.graphics.Bitmap
50ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
51ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * Through the layoutlib_create tool, the original native methods of Bitmap have been replaced
52ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * by calls to methods of the same name in this delegate class.
53ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
54ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * This class behaves like the original native implementation, but in Java, keeping previously
55ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * native data into its own objects and mapping them to int that are sent back and forth between
56ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * it and the original Bitmap class.
57ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
58ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski * @see DelegateManager
59ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski *
60ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski */
61ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinskipublic final class Bitmap_Delegate {
62ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
63eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
64835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    public enum BitmapCreateFlags {
656d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        NONE, PREMULTIPLIED, MUTABLE
66835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    }
67835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta
68ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- delegate manager ----
69ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private static final DelegateManager<Bitmap_Delegate> sManager =
7042b832b6c5d5bc57886626949f3ed9a219a5f800Diego Perez            new DelegateManager<>(Bitmap_Delegate.class);
71fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta    private static long sFinalizer = -1;
72ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
73ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- delegate helper data ----
74ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
75ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- delegate data ----
76ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private final Config mConfig;
77fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta    private final BufferedImage mImage;
78ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private boolean mHasAlpha = true;
79ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private boolean mHasMipMap = false;      // TODO: check the default.
80eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    private boolean mIsPremultiplied = true;
81ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private int mGenerationId = 0;
82ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
83ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
84ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- Public Helper methods ----
85ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
86ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
87ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns the native delegate associated to a given an int referencing a {@link Bitmap} object.
88ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
89ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    public static Bitmap_Delegate getDelegate(long native_bitmap) {
90ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return sManager.getDelegate(native_bitmap);
91ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
92ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
939fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta    @Nullable
949fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta    public static Bitmap_Delegate getDelegate(@Nullable Bitmap bitmap) {
95a6897f8507f92267facb6cfe3f53989de35d2d62Diego Perez        return bitmap == null ? null : getDelegate(bitmap.getNativeInstance());
969fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta    }
979fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta
98ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
99ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Creates and returns a {@link Bitmap} initialized with the given file content.
100ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
101ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param input the file from which to read the bitmap content
102ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param isMutable whether the bitmap is mutable
103ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param density the density associated with the bitmap
104ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
105ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see Bitmap#isMutable()
106ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see Bitmap#getDensity()
107ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
108ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static Bitmap createBitmap(File input, boolean isMutable, Density density)
109ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            throws IOException {
110835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
111835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    }
11269fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta
113835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    /**
114835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * Creates and returns a {@link Bitmap} initialized with the given file content.
115835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     *
116835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @param input the file from which to read the bitmap content
117835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @param density the density associated with the bitmap
118835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     *
11969fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta     * @see Bitmap#isPremultiplied()
120835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @see Bitmap#isMutable()
121835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @see Bitmap#getDensity()
122835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     */
123fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta    private static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
124835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta            Density density) throws IOException {
125ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create a delegate with the content of the file.
126fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta        BufferedImage image = ImageIO.read(input);
127fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta        if (image == null && input.exists()) {
128fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            // There was a problem decoding the image, or the decoder isn't registered. Webp maybe.
129fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            // Replace with a broken image icon.
130fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            BridgeContext currentContext = RenderAction.getCurrentContext();
131fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            if (currentContext != null) {
132fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                RenderResources resources = currentContext.getRenderResources();
133fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                ResourceValue broken = resources.getFrameworkResource(ResourceType.DRAWABLE,
134fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                        "ic_menu_report_image");
135fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                File brokenFile = new File(broken.getValue());
136fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                if (brokenFile.exists()) {
137fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                    image = ImageIO.read(brokenFile);
138fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                }
139fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            }
140fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta        }
141fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
14269fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta
143835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, createFlags, density.getDpiValue());
144ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
145ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
146ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
147ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Creates and returns a {@link Bitmap} initialized with the given stream content.
148ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
149ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param input the stream from which to read the bitmap content
150ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param isMutable whether the bitmap is mutable
151ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param density the density associated with the bitmap
152ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
153ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see Bitmap#isMutable()
154ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see Bitmap#getDensity()
155ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
156ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density)
157ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            throws IOException {
158835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
159835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    }
160835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta
161835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    /**
162835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * Creates and returns a {@link Bitmap} initialized with the given stream content.
163835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     *
164835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @param input the stream from which to read the bitmap content
165835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @param density the density associated with the bitmap
166835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     *
16769fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta     * @see Bitmap#isPremultiplied()
168835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @see Bitmap#isMutable()
169835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @see Bitmap#getDensity()
170835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     */
171835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    public static Bitmap createBitmap(InputStream input, Set<BitmapCreateFlags> createFlags,
172835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta            Density density) throws IOException {
173ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create a delegate with the content of the stream.
174ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
175ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
176835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, createFlags, density.getDpiValue());
177ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
178ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
179ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
180ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
181ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
182ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param image the bitmap content
183ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param isMutable whether the bitmap is mutable
184ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param density the density associated with the bitmap
185ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
186ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see Bitmap#isMutable()
187ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see Bitmap#getDensity()
188ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
189c8460df6228766eaf9f1f6e15994f9ba84910a4dDeepanshu Gupta    public static Bitmap createBitmap(BufferedImage image, boolean isMutable, Density density) {
190835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(image, getPremultipliedBitmapCreateFlags(isMutable), density);
191835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    }
192835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta
193835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    /**
194835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
195835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     *
196835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @param image the bitmap content
197835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @param density the density associated with the bitmap
198835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     *
19969fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta     * @see Bitmap#isPremultiplied()
200835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @see Bitmap#isMutable()
201835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     * @see Bitmap#getDensity()
202835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta     */
203835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    public static Bitmap createBitmap(BufferedImage image, Set<BitmapCreateFlags> createFlags,
204c8460df6228766eaf9f1f6e15994f9ba84910a4dDeepanshu Gupta            Density density) {
205ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create a delegate with the given image.
206ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
207ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
208835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, createFlags, density.getDpiValue());
209ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
210ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
2119fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta    private static int getBufferedImageType() {
212ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return BufferedImage.TYPE_INT_ARGB;
213ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
214ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
215ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
216ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
217ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
218ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public BufferedImage getImage() {
219ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mImage;
220ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
221ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
222ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
223ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns the Android bitmap config. Note that this not the config of the underlying
224ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Java2D bitmap.
225ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
226ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public Config getConfig() {
227ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mConfig;
228ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
229ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
230ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
231ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Returns the hasAlpha rendering hint
232ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return true if the bitmap alpha should be used at render time
233ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
234ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public boolean hasAlpha() {
235ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return mHasAlpha && mConfig != Config.RGB_565;
236ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
237ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
238ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
239ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Update the generationId.
240ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
241ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @see Bitmap#getGenerationId()
242ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
243ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    public void change() {
244ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mGenerationId++;
245ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
246ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
247ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- native methods ----
248ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
249ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
250ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
251835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta            int height, int nativeConfig, boolean isMutable) {
2529fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        int imageType = getBufferedImageType();
253ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
254ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the image
255ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image = new BufferedImage(width, height, imageType);
256ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
257ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (colors != null) {
258ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            image.setRGB(0, 0, width, height, colors, offset, stride);
259ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
260ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
261ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create a delegate with the content of the stream.
262ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
263ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
264835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
26569fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta                            Bitmap.getDefaultDensity());
266ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
267ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
268ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
269ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static Bitmap nativeCopy(long srcBitmap, int nativeConfig, boolean isMutable) {
270ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap);
271ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (srcBmpDelegate == null) {
272ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
273ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
274ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
275ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage srcImage = srcBmpDelegate.getImage();
276ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
277ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int width = srcImage.getWidth();
278ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int height = srcImage.getHeight();
279ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
2809fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        int imageType = getBufferedImageType();
281ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
282ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the image
283ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image = new BufferedImage(width, height, imageType);
284ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
285ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // copy the source image into the image.
286ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int[] argb = new int[width * height];
287ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        srcImage.getRGB(0, 0, width, height, argb, 0, width);
288ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        image.setRGB(0, 0, width, height, argb, 0, width);
289ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
290ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create a delegate with the content of the stream.
291ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
292ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
293835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
294835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta                Bitmap.getDefaultDensity());
295ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
296ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
297ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
298b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta    /*package*/ static Bitmap nativeCopyAshmem(long nativeSrcBitmap) {
299b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta        // Unused method; no implementation provided.
300b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta        assert false;
301b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta        return null;
302b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta    }
303b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta
304b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta    @LayoutlibDelegate
30574065acbaf49f180d061262237e70b92f339bf89Diego Perez    /*package*/ static Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig) {
30674065acbaf49f180d061262237e70b92f339bf89Diego Perez        // Unused method; no implementation provided.
30774065acbaf49f180d061262237e70b92f339bf89Diego Perez        assert false;
30874065acbaf49f180d061262237e70b92f339bf89Diego Perez        return null;
30974065acbaf49f180d061262237e70b92f339bf89Diego Perez    }
31074065acbaf49f180d061262237e70b92f339bf89Diego Perez
31174065acbaf49f180d061262237e70b92f339bf89Diego Perez    @LayoutlibDelegate
312fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta    /*package*/ static long nativeGetNativeFinalizer() {
313fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta        synchronized (Bitmap_Delegate.class) {
314fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            if (sFinalizer == -1) {
315fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
316fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            }
317fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            return sFinalizer;
318fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta        }
319ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
320ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
321ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
32269fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta    /*package*/ static boolean nativeRecycle(long nativeBitmap) {
32342b832b6c5d5bc57886626949f3ed9a219a5f800Diego Perez        // In our case reycle() is a no-op. We will let the finalizer to dispose the bitmap.
32469fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta        return true;
32569fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta    }
32669fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta
32769fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta    @LayoutlibDelegate
32869fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta    /*package*/ static void nativeReconfigure(long nativeBitmap, int width, int height,
3297fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            int config, boolean isPremultiplied) {
33069fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
33169fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta                "Bitmap.reconfigure() is not supported", null /*data*/);
332ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
333ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
334ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
335ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeCompress(long nativeBitmap, int format, int quality,
336ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            OutputStream stream, byte[] tempStorage) {
337ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
338ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Bitmap.compress() is not supported", null /*data*/);
339ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
340ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
341ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
342ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
343ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeErase(long nativeBitmap, int color) {
344ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
345ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
346ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
347ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
348ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
349ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
350ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image = delegate.mImage;
351ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
352ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Graphics2D g = image.createGraphics();
353ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
354ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            g.setColor(new java.awt.Color(color, true));
355ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
356ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            g.fillRect(0, 0, image.getWidth(), image.getHeight());
357ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } finally {
358ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            g.dispose();
359ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
360ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
361ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
362ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
363ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static int nativeRowBytes(long nativeBitmap) {
364ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
365ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
366ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
367ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
368ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
369ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
370ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.mImage.getWidth();
371ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
372ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
373ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
374ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static int nativeConfig(long nativeBitmap) {
375ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
376ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
377ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
378ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
379ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
380ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
381ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.mConfig.nativeInt;
382ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
383ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
384ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
385ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeHasAlpha(long nativeBitmap) {
386ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
387ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
3889fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        return delegate == null || delegate.mHasAlpha;
389ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
390ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
391ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
392ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
393ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeHasMipMap(long nativeBitmap) {
394ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
395ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
3969fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        return delegate == null || delegate.mHasMipMap;
397ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
398ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
399ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
400ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
401eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static int nativeGetPixel(long nativeBitmap, int x, int y) {
402ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
403ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
404ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
405ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
406ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
407ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
408ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.mImage.getRGB(x, y);
409ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
410ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
411ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
412ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeGetPixels(long nativeBitmap, int[] pixels, int offset,
413eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta            int stride, int x, int y, int width, int height) {
414ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
415ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
416ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
417ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
418ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
419ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride);
420ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
421ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
422ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
423ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
424eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static void nativeSetPixel(long nativeBitmap, int x, int y, int color) {
425ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
426ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
427ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
428ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
429ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
430ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.getImage().setRGB(x, y, color);
431ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
432ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
433ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
434ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeSetPixels(long nativeBitmap, int[] colors, int offset,
435eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta            int stride, int x, int y, int width, int height) {
436ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
437ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
438ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
439ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
440ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
441ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.getImage().setRGB(x, y, width, height, colors, offset, stride);
442ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
443ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
444ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
445ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeCopyPixelsToBuffer(long nativeBitmap, Buffer dst) {
446ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // FIXME implement native delegate
447ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
448ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Bitmap.copyPixelsToBuffer is not supported.", null, null /*data*/);
449ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
450ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
451ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
452ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeCopyPixelsFromBuffer(long nb, Buffer src) {
453ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // FIXME implement native delegate
454ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
455ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Bitmap.copyPixelsFromBuffer is not supported.", null, null /*data*/);
456ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
457ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
458ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
459ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static int nativeGenerationId(long nativeBitmap) {
460ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
461ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
462ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
463ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
464ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
465ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.mGenerationId;
466ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
467ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
468ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
469ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
470ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only
471ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // used during aidl call so really this should not be called.
472ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
473ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.",
474ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                null /*data*/);
475ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return null;
476ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
477ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
478ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
479ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeWriteToParcel(long nativeBitmap, boolean isMutable,
480ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int density, Parcel p) {
481ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // This is only called when sending a bitmap through aidl, so really this should not
482ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // be called.
483ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
484ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.",
485ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                null /*data*/);
486ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return false;
487ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
488ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
489ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
490ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static Bitmap nativeExtractAlpha(long nativeBitmap, long nativePaint,
491ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int[] offsetXY) {
492ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap);
493ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (bitmap == null) {
494ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
495ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
496ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
497ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the paint which can be null if nativePaint is 0.
498ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
499ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
500ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (paint != null && paint.getMaskFilter() != null) {
501ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
502ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "MaskFilter not supported in Bitmap.extractAlpha",
503ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    null, null /*data*/);
504ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
505ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
506ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int alpha = paint != null ? paint.getAlpha() : 0xFF;
507ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha);
508ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
509ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the delegate. The actual Bitmap config is only an alpha channel
510ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8);
511ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
512ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // the density doesn't matter, it's set by the Java method.
513835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.MUTABLE),
514ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                Density.DEFAULT_DENSITY /*density*/);
515ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
516ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
517ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
518eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static boolean nativeIsPremultiplied(long nativeBitmap) {
519eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        // get the delegate from the native int.
520eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
521eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        return delegate != null && delegate.mIsPremultiplied;
522eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
523eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    }
524eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
525eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    @LayoutlibDelegate
526eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static void nativeSetPremultiplied(long nativeBitmap, boolean isPremul) {
527eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        // get the delegate from the native int.
528eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
529eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        if (delegate == null) {
530eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta            return;
531eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        }
532eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
533eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        delegate.mIsPremultiplied = isPremul;
534eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    }
535eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
536eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    @LayoutlibDelegate
537eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static void nativeSetHasAlpha(long nativeBitmap, boolean hasAlpha,
538cd0ed56f8a5f7788bcff050ab8aa42b0504e8535Deepanshu Gupta            boolean isPremul) {
539ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
540ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
541ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
542ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
543ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
544ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
545ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.mHasAlpha = hasAlpha;
546ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
547ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
548ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
549ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap) {
550ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
551ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
552ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
553ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
554ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
555ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
556ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.mHasMipMap = hasMipMap;
557ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
558ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
559ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
560ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeSameAs(long nb0, long nb1) {
561ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate1 = sManager.getDelegate(nb0);
562ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate1 == null) {
563ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
564ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
565ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
566ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate2 = sManager.getDelegate(nb1);
567ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate2 == null) {
568ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
569ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
570ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
571ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image1 = delegate1.getImage();
572ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image2 = delegate2.getImage();
573ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate1.mConfig != delegate2.mConfig ||
574ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                image1.getWidth() != image2.getWidth() ||
575ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                image1.getHeight() != image2.getHeight()) {
576ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
577ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
578ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
579ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the internal data
580ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int w = image1.getWidth();
581ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int h = image2.getHeight();
582ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int[] argb1 = new int[w*h];
583ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int[] argb2 = new int[w*h];
584ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
585ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        image1.getRGB(0, 0, w, h, argb1, 0, w);
586ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        image2.getRGB(0, 0, w, h, argb2, 0, w);
587ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
588ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // compares
589ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate1.mConfig == Config.ALPHA_8) {
590ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // in this case we have to manually compare the alpha channel as the rest is garbage.
591ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            final int length = w*h;
592ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int i = 0 ; i < length ; i++) {
593ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) {
594ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    return false;
595ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
596ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
597ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return true;
598ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
599ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
600ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return Arrays.equals(argb1, argb2);
601ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
602ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
6037fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    @LayoutlibDelegate
6047fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static int nativeGetAllocationByteCount(long nativeBitmap) {
6057fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        // get the delegate from the native int.
6067fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
6077fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        if (delegate == null) {
6087fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            return 0;
6097fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        }
6107fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        return nativeRowBytes(nativeBitmap) * delegate.mImage.getHeight();
6117fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard
6127fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    }
6137fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard
6147fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    @LayoutlibDelegate
6157fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nativePrepareToDraw(long nativeBitmap) {
6167fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        // do nothing as Bitmap_Delegate does not have caches
6177fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    }
6187fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard
6196d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard    @LayoutlibDelegate
6206d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard    /*package*/ static Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap) {
6216d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(nativeBitmap);
6226d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        if (srcBmpDelegate == null) {
6236d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard            return null;
6246d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        }
6256d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6266d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        BufferedImage srcImage = srcBmpDelegate.getImage();
6276d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6286d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        // create the image
6296d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        BufferedImage image = new BufferedImage(srcImage.getColorModel(), srcImage.copyData(null),
6306d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard                srcImage.isAlphaPremultiplied(), null);
6316d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6326d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        // create a delegate with the content of the stream.
6336d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        Bitmap_Delegate delegate = new Bitmap_Delegate(image, srcBmpDelegate.getConfig());
6346d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6356d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.NONE),
6366d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard                Bitmap.getDefaultDensity());
6376d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard    }
6386d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6390cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    @LayoutlibDelegate
6400cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    /*package*/ static Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer) {
6410cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
6420cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez                "Bitmap.nativeCreateHardwareBitmap() is not supported", null /*data*/);
6430cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez        return null;
6440cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    }
6450cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez
6460cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    @LayoutlibDelegate
6470cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    /*package*/ static GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap) {
6480cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
6490cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez                "Bitmap.nativeCreateGraphicBufferHandle() is not supported", null /*data*/);
6500cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez        return null;
6510cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    }
6520cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez
653ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- Private delegate/helper methods ----
654ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
655ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Bitmap_Delegate(BufferedImage image, Config config) {
656ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mImage = image;
657ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mConfig = config;
658ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
659ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
660835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    private static Bitmap createBitmap(Bitmap_Delegate delegate,
661835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta            Set<BitmapCreateFlags> createFlags, int density) {
662ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get its native_int
663ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath        long nativeInt = sManager.addNewDelegate(delegate);
664ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
665835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        int width = delegate.mImage.getWidth();
666835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        int height = delegate.mImage.getHeight();
667835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        boolean isMutable = createFlags.contains(BitmapCreateFlags.MUTABLE);
668835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        boolean isPremultiplied = createFlags.contains(BitmapCreateFlags.PREMULTIPLIED);
669835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta
670ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // and create/return a new Bitmap with it
671c6ab3686a244dfc9b05d281c6998652fcc115ce1sergeyv        return new Bitmap(nativeInt, width, height, density, isMutable,
672835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta                          isPremultiplied, null /*ninePatchChunk*/, null /* layoutBounds */);
673ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
674ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
675835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    private static Set<BitmapCreateFlags> getPremultipliedBitmapCreateFlags(boolean isMutable) {
67669fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta        Set<BitmapCreateFlags> createFlags = EnumSet.of(BitmapCreateFlags.PREMULTIPLIED);
677835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        if (isMutable) {
678835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta            createFlags.add(BitmapCreateFlags.MUTABLE);
679835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        }
680835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createFlags;
681835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    }
68269fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta
683ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
684ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Creates and returns a copy of a given BufferedImage.
685ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>
686ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * if alpha is different than 255, then it is applied to the alpha channel of each pixel.
687ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
688ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param image the image to copy
689ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param imageType the type of the new image
690ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param alpha an optional alpha modifier
691ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return a new BufferedImage
692ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
693ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) {
694ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int w = image.getWidth();
695ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int h = image.getHeight();
696ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
697ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage result = new BufferedImage(w, h, imageType);
698ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
699ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int[] argb = new int[w * h];
700ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
701ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
702ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (alpha != 255) {
703ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            final int length = argb.length;
704ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int i = 0 ; i < length; i++) {
705ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                int a = (argb[i] >>> 24 * alpha) / 255;
706ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF);
707ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
708ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
709ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
710ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        result.setRGB(0, 0, w, h, argb, 0, w);
711ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
712ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return result;
713ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
714ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
715ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski}
716