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,
2516c050fc5ebba61fe6857b598a89fa9e9bc30aac2Jerome Gaillard            int height, int nativeConfig, boolean isMutable, @Nullable float[] xyzD50,
2526c050fc5ebba61fe6857b598a89fa9e9bc30aac2Jerome Gaillard            @Nullable ColorSpace.Rgb.TransferParameters p) {
2539fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        int imageType = getBufferedImageType();
254ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
255ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the image
256ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image = new BufferedImage(width, height, imageType);
257ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
258ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (colors != null) {
259ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            image.setRGB(0, 0, width, height, colors, offset, stride);
260ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
261ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
262ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create a delegate with the content of the stream.
263ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
264ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
265835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
26669fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta                            Bitmap.getDefaultDensity());
267ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
268ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
269ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
270ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static Bitmap nativeCopy(long srcBitmap, int nativeConfig, boolean isMutable) {
271ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap);
272ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (srcBmpDelegate == null) {
273ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
274ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
275ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
276ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage srcImage = srcBmpDelegate.getImage();
277ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
278ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int width = srcImage.getWidth();
279ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int height = srcImage.getHeight();
280ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
2819fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        int imageType = getBufferedImageType();
282ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
283ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the image
284ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image = new BufferedImage(width, height, imageType);
285ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
286ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // copy the source image into the image.
287ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int[] argb = new int[width * height];
288ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        srcImage.getRGB(0, 0, width, height, argb, 0, width);
289ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        image.setRGB(0, 0, width, height, argb, 0, width);
290ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
291ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create a delegate with the content of the stream.
292ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
293ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
294835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
295835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta                Bitmap.getDefaultDensity());
296ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
297ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
298ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
299b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta    /*package*/ static Bitmap nativeCopyAshmem(long nativeSrcBitmap) {
300b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta        // Unused method; no implementation provided.
301b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta        assert false;
302b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta        return null;
303b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta    }
304b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta
305b8275ed6b07d9a4568faee675101651710f8efc0Deepanshu Gupta    @LayoutlibDelegate
30674065acbaf49f180d061262237e70b92f339bf89Diego Perez    /*package*/ static Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig) {
30774065acbaf49f180d061262237e70b92f339bf89Diego Perez        // Unused method; no implementation provided.
30874065acbaf49f180d061262237e70b92f339bf89Diego Perez        assert false;
30974065acbaf49f180d061262237e70b92f339bf89Diego Perez        return null;
31074065acbaf49f180d061262237e70b92f339bf89Diego Perez    }
31174065acbaf49f180d061262237e70b92f339bf89Diego Perez
31274065acbaf49f180d061262237e70b92f339bf89Diego Perez    @LayoutlibDelegate
313fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta    /*package*/ static long nativeGetNativeFinalizer() {
314fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta        synchronized (Bitmap_Delegate.class) {
315fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            if (sFinalizer == -1) {
316fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
317fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            }
318fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta            return sFinalizer;
319fbe158f5e1f77cea2a335834a1c91fea1c4680aaDeepanshu Gupta        }
320ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
321ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
322ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
32369fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta    /*package*/ static boolean nativeRecycle(long nativeBitmap) {
32442b832b6c5d5bc57886626949f3ed9a219a5f800Diego Perez        // In our case reycle() is a no-op. We will let the finalizer to dispose the bitmap.
32569fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta        return true;
32669fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta    }
32769fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta
32869fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta    @LayoutlibDelegate
32969fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta    /*package*/ static void nativeReconfigure(long nativeBitmap, int width, int height,
3307fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            int config, boolean isPremultiplied) {
33169fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
33269fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta                "Bitmap.reconfigure() is not supported", null /*data*/);
333ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
334ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
335ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
336ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeCompress(long nativeBitmap, int format, int quality,
337ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            OutputStream stream, byte[] tempStorage) {
338ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
339ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Bitmap.compress() is not supported", null /*data*/);
340ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return true;
341ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
342ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
343ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
344ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeErase(long nativeBitmap, int color) {
345ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
346ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
347ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
348ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
349ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
350ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
351ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image = delegate.mImage;
352ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
353ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Graphics2D g = image.createGraphics();
354ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        try {
355ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            g.setColor(new java.awt.Color(color, true));
356ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
357ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            g.fillRect(0, 0, image.getWidth(), image.getHeight());
358ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        } finally {
359ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            g.dispose();
360ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
361ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
362ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
363ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
364ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static int nativeRowBytes(long nativeBitmap) {
365ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
366ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
367ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
368ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
369ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
370ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
371ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.mImage.getWidth();
372ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
373ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
374ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
375ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static int nativeConfig(long nativeBitmap) {
376ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
377ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
378ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
379ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
380ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
381ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
382ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.mConfig.nativeInt;
383ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
384ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
385ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
386ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeHasAlpha(long nativeBitmap) {
387ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
388ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
3899fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        return delegate == null || delegate.mHasAlpha;
390ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
391ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
392ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
393ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
394ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeHasMipMap(long nativeBitmap) {
395ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
396ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
3979fe7fca9bcdceade9c654c6a8dcf0c48be16d78dDeepanshu Gupta        return delegate == null || delegate.mHasMipMap;
398ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
399ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
400ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
401ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
402eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static int nativeGetPixel(long nativeBitmap, int x, int y) {
403ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
404ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
405ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
406ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
407ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
408ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
409ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.mImage.getRGB(x, y);
410ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
411ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
412ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
413ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeGetPixels(long nativeBitmap, int[] pixels, int offset,
414eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta            int stride, int x, int y, int width, int height) {
415ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
416ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
417ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
418ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
419ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
420ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride);
421ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
422ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
423ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
424ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
425eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static void nativeSetPixel(long nativeBitmap, int x, int y, int color) {
426ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
427ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
428ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
429ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
430ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
431ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.getImage().setRGB(x, y, color);
432ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
433ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
434ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
435ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeSetPixels(long nativeBitmap, int[] colors, int offset,
436eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta            int stride, int x, int y, int width, int height) {
437ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
438ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
439ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
440ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
441ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
442ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.getImage().setRGB(x, y, width, height, colors, offset, stride);
443ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
444ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
445ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
446ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeCopyPixelsToBuffer(long nativeBitmap, Buffer dst) {
447ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // FIXME implement native delegate
448ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
449ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Bitmap.copyPixelsToBuffer is not supported.", null, null /*data*/);
450ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
451ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
452ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
453ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeCopyPixelsFromBuffer(long nb, Buffer src) {
454ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // FIXME implement native delegate
455ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
456ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "Bitmap.copyPixelsFromBuffer is not supported.", null, null /*data*/);
457ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
458ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
459ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
460ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static int nativeGenerationId(long nativeBitmap) {
461ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
462ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
463ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return 0;
464ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
465ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
466ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return delegate.mGenerationId;
467ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
468ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
469ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
470ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
471ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only
472ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // used during aidl call so really this should not be called.
473ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
474ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.",
475ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                null /*data*/);
476ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return null;
477ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
478ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
479ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
480ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeWriteToParcel(long nativeBitmap, boolean isMutable,
481ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int density, Parcel p) {
482ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // This is only called when sending a bitmap through aidl, so really this should not
483ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // be called.
484ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
485ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.",
486ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                null /*data*/);
487ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return false;
488ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
489ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
490ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
491ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static Bitmap nativeExtractAlpha(long nativeBitmap, long nativePaint,
492ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            int[] offsetXY) {
493ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap);
494ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (bitmap == null) {
495ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return null;
496ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
497ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
498ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the paint which can be null if nativePaint is 0.
499ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
500ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
501ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (paint != null && paint.getMaskFilter() != null) {
502ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
503ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    "MaskFilter not supported in Bitmap.extractAlpha",
504ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    null, null /*data*/);
505ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
506ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
507ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int alpha = paint != null ? paint.getAlpha() : 0xFF;
508ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha);
509ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
510ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // create the delegate. The actual Bitmap config is only an alpha channel
511ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8);
512ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
513ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // the density doesn't matter, it's set by the Java method.
514835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.MUTABLE),
515ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                Density.DEFAULT_DENSITY /*density*/);
516ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
517ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
518ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
519eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static boolean nativeIsPremultiplied(long nativeBitmap) {
520eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        // get the delegate from the native int.
521eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
522eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        return delegate != null && delegate.mIsPremultiplied;
523eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
524eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    }
525eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
526eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    @LayoutlibDelegate
527eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static void nativeSetPremultiplied(long nativeBitmap, boolean isPremul) {
528eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        // get the delegate from the native int.
529eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
530eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        if (delegate == null) {
531eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta            return;
532eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        }
533eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
534eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta        delegate.mIsPremultiplied = isPremul;
535eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    }
536eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta
537eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    @LayoutlibDelegate
538eeb44a29846ac0d36a1fad1b6869e932d1dc01ceDeepanshu Gupta    /*package*/ static void nativeSetHasAlpha(long nativeBitmap, boolean hasAlpha,
539cd0ed56f8a5f7788bcff050ab8aa42b0504e8535Deepanshu Gupta            boolean isPremul) {
540ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
541ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
542ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
543ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
544ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
545ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
546ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.mHasAlpha = hasAlpha;
547ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
548ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
549ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
550ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap) {
551ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the delegate from the native int.
552ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
553ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate == null) {
554ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return;
555ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
556ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
557ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        delegate.mHasMipMap = hasMipMap;
558ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
559ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
560ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    @LayoutlibDelegate
561ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath    /*package*/ static boolean nativeSameAs(long nb0, long nb1) {
562ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate1 = sManager.getDelegate(nb0);
563ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate1 == null) {
564ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
565ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
566ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
567ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        Bitmap_Delegate delegate2 = sManager.getDelegate(nb1);
568ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate2 == null) {
569ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
570ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
571ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
572ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image1 = delegate1.getImage();
573ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage image2 = delegate2.getImage();
574ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate1.mConfig != delegate2.mConfig ||
575ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                image1.getWidth() != image2.getWidth() ||
576ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                image1.getHeight() != image2.getHeight()) {
577ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return false;
578ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
579ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
580ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get the internal data
581ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int w = image1.getWidth();
582ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int h = image2.getHeight();
583ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int[] argb1 = new int[w*h];
584ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int[] argb2 = new int[w*h];
585ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
586ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        image1.getRGB(0, 0, w, h, argb1, 0, w);
587ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        image2.getRGB(0, 0, w, h, argb2, 0, w);
588ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
589ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // compares
590ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (delegate1.mConfig == Config.ALPHA_8) {
591ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            // in this case we have to manually compare the alpha channel as the rest is garbage.
592ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            final int length = w*h;
593ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int i = 0 ; i < length ; i++) {
594ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) {
595ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                    return false;
596ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                }
597ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
598ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            return true;
599ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
600ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
601ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return Arrays.equals(argb1, argb2);
602ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
603ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
6047fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    @LayoutlibDelegate
6057fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static int nativeGetAllocationByteCount(long nativeBitmap) {
6067fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        // get the delegate from the native int.
6077fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
6087fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        if (delegate == null) {
6097fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard            return 0;
6107fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        }
61128508735a5fb6527d3e87adffe6359cd4ab51a98Jerome Gaillard        int size = nativeRowBytes(nativeBitmap) * delegate.mImage.getHeight();
61228508735a5fb6527d3e87adffe6359cd4ab51a98Jerome Gaillard        return size < 0 ? Integer.MAX_VALUE : size;
6137fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard
6147fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    }
6157fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard
6167fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    @LayoutlibDelegate
6177fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    /*package*/ static void nativePrepareToDraw(long nativeBitmap) {
6187fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard        // do nothing as Bitmap_Delegate does not have caches
6197fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard    }
6207fa71f524c86d6224fb95b571d3a9e32edb32f22Jerome Gaillard
6216d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard    @LayoutlibDelegate
6226d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard    /*package*/ static Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap) {
6236d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(nativeBitmap);
6246d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        if (srcBmpDelegate == null) {
6256d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard            return null;
6266d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        }
6276d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6286d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        BufferedImage srcImage = srcBmpDelegate.getImage();
6296d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6306d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        // create the image
6316d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        BufferedImage image = new BufferedImage(srcImage.getColorModel(), srcImage.copyData(null),
6326d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard                srcImage.isAlphaPremultiplied(), null);
6336d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6346d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        // create a delegate with the content of the stream.
6356d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        Bitmap_Delegate delegate = new Bitmap_Delegate(image, srcBmpDelegate.getConfig());
6366d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6376d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard        return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.NONE),
6386d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard                Bitmap.getDefaultDensity());
6396d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard    }
6406d60df19df21854a555f76ab46d73fa43a9af43fJerome Gaillard
6410cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    @LayoutlibDelegate
6420cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    /*package*/ static Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer) {
6430cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
6440cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez                "Bitmap.nativeCreateHardwareBitmap() is not supported", null /*data*/);
6450cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez        return null;
6460cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    }
6470cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez
6480cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    @LayoutlibDelegate
6490cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    /*package*/ static GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap) {
6500cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
6510cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez                "Bitmap.nativeCreateGraphicBufferHandle() is not supported", null /*data*/);
6520cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez        return null;
6530cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez    }
6540cd6c5b6bcaea7216a444a2729b728846878922eDiego Perez
655ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard    @LayoutlibDelegate
656ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard    /*package*/ static boolean nativeIsSRGB(long nativeBitmap) {
657ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
658ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard                "Color spaces are not supported", null /*data*/);
659ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard        return false;
660ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard    }
661ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard
662ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard    @LayoutlibDelegate
663ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard    /*package*/ static boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params) {
664ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
665ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard                "Color spaces are not supported", null /*data*/);
666ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard        return false;
667ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard    }
668ce2fcba587558e22a3f407b5ed07fcf97f091d41Jerome Gaillard
6696c050fc5ebba61fe6857b598a89fa9e9bc30aac2Jerome Gaillard    @LayoutlibDelegate
6706c050fc5ebba61fe6857b598a89fa9e9bc30aac2Jerome Gaillard    /*package*/ static void nativeCopyColorSpace(long srcBitmap, long dstBitmap) {
6716c050fc5ebba61fe6857b598a89fa9e9bc30aac2Jerome Gaillard        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
6726c050fc5ebba61fe6857b598a89fa9e9bc30aac2Jerome Gaillard                "Color spaces are not supported", null /*data*/);
6736c050fc5ebba61fe6857b598a89fa9e9bc30aac2Jerome Gaillard    }
6746c050fc5ebba61fe6857b598a89fa9e9bc30aac2Jerome Gaillard
675ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    // ---- Private delegate/helper methods ----
676ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
677ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    private Bitmap_Delegate(BufferedImage image, Config config) {
678ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mImage = image;
679ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        mConfig = config;
680ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
681ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
682835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    private static Bitmap createBitmap(Bitmap_Delegate delegate,
683835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta            Set<BitmapCreateFlags> createFlags, int density) {
684ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // get its native_int
685ec4118922fa844ef31b73d16adc76f4da4c6c8e6Narayan Kamath        long nativeInt = sManager.addNewDelegate(delegate);
686ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
687835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        int width = delegate.mImage.getWidth();
688835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        int height = delegate.mImage.getHeight();
689835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        boolean isMutable = createFlags.contains(BitmapCreateFlags.MUTABLE);
690835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        boolean isPremultiplied = createFlags.contains(BitmapCreateFlags.PREMULTIPLIED);
691835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta
692ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        // and create/return a new Bitmap with it
693c6ab3686a244dfc9b05d281c6998652fcc115ce1sergeyv        return new Bitmap(nativeInt, width, height, density, isMutable,
694835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta                          isPremultiplied, null /*ninePatchChunk*/, null /* layoutBounds */);
695ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
696ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
697835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    private static Set<BitmapCreateFlags> getPremultipliedBitmapCreateFlags(boolean isMutable) {
69869fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta        Set<BitmapCreateFlags> createFlags = EnumSet.of(BitmapCreateFlags.PREMULTIPLIED);
699835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        if (isMutable) {
700835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta            createFlags.add(BitmapCreateFlags.MUTABLE);
701835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        }
702835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta        return createFlags;
703835e279c3960664c32b35aa7e3215b13c8fa3be4Deepanshu Gupta    }
70469fea4897f756b9cf489a92b7073554086e6d252Deepanshu Gupta
705ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /**
706ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * Creates and returns a copy of a given BufferedImage.
707ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * <p/>
708ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * if alpha is different than 255, then it is applied to the alpha channel of each pixel.
709ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     *
710ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param image the image to copy
711ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param imageType the type of the new image
712ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @param alpha an optional alpha modifier
713ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     * @return a new BufferedImage
714ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski     */
715ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) {
716ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int w = image.getWidth();
717ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int h = image.getHeight();
718ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
719ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        BufferedImage result = new BufferedImage(w, h, imageType);
720ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
721ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        int[] argb = new int[w * h];
722ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
723ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
724ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        if (alpha != 255) {
725ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            final int length = argb.length;
726ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            for (int i = 0 ; i < length; i++) {
727ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                int a = (argb[i] >>> 24 * alpha) / 255;
728ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski                argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF);
729ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski            }
730ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        }
731ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
732ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        result.setRGB(0, 0, w, h, argb, 0, w);
733ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
734ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski        return result;
735ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski    }
736ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski
737ab775ecdd189b32e35b0d3f4a821502f88b03a4bAdam Lesinski}
738