1282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/*
2282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Copyright (C) 2010 The Android Open Source Project
3282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
4282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
5282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * you may not use this file except in compliance with the License.
6282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * You may obtain a copy of the License at
7282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
8282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
9282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
10282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Unless required by applicable law or agreed to in writing, software
11282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
12282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * See the License for the specific language governing permissions and
14282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * limitations under the License.
15282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
16282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipackage android.graphics;
18282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
19282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.ide.common.rendering.api.LayoutLog;
20491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Guptaimport com.android.ide.common.rendering.api.RenderResources;
21491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Guptaimport com.android.ide.common.rendering.api.ResourceValue;
22282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.Bridge;
23491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Guptaimport com.android.layoutlib.bridge.android.BridgeContext;
24282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.layoutlib.bridge.impl.DelegateManager;
25491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Guptaimport com.android.layoutlib.bridge.impl.RenderAction;
26282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.resources.Density;
27491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Guptaimport com.android.resources.ResourceType;
28282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport com.android.tools.layoutlib.annotations.LayoutlibDelegate;
29282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
30476e582d2ffdf25102d4c55f8c242baa3d21d37fDeepanshu Guptaimport android.annotation.Nullable;
31282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.graphics.Bitmap.Config;
32282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport android.os.Parcel;
33282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
34282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.Graphics2D;
35282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.awt.image.BufferedImage;
36282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.File;
37282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.IOException;
38282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.InputStream;
39282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.io.OutputStream;
40282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.nio.Buffer;
41282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport java.util.Arrays;
4270f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Guptaimport java.util.EnumSet;
4370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Guptaimport java.util.Set;
44282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
45282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskiimport javax.imageio.ImageIO;
46491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Guptaimport libcore.util.NativeAllocationRegistry_Delegate;
47282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
48282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski/**
49282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Delegate implementing the native methods of android.graphics.Bitmap
50282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
51282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * Through the layoutlib_create tool, the original native methods of Bitmap have been replaced
52282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * by calls to methods of the same name in this delegate class.
53282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
54282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * This class behaves like the original native implementation, but in Java, keeping previously
55282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * native data into its own objects and mapping them to int that are sent back and forth between
56282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * it and the original Bitmap class.
57282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
58282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski * @see DelegateManager
59282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski *
60282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski */
61282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinskipublic final class Bitmap_Delegate {
62282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
6326e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta
6470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    public enum BitmapCreateFlags {
659758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        NONE, PREMULTIPLIED, MUTABLE
6670f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    }
6770f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta
68282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate manager ----
69282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private static final DelegateManager<Bitmap_Delegate> sManager =
70adf62b3ebc8ae5e3e76cf6cfce978e8d1ca5bf8eDiego Perez            new DelegateManager<>(Bitmap_Delegate.class);
71491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta    private static long sFinalizer = -1;
72282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
73282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate helper data ----
74282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
75282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- delegate data ----
76282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private final Config mConfig;
77491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta    private final BufferedImage mImage;
78282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private boolean mHasAlpha = true;
79282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private boolean mHasMipMap = false;      // TODO: check the default.
8026e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    private boolean mIsPremultiplied = true;
81282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private int mGenerationId = 0;
82282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
83282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
84282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Public Helper methods ----
85282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
86282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
87282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the native delegate associated to a given an int referencing a {@link Bitmap} object.
88282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
8988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    public static Bitmap_Delegate getDelegate(long native_bitmap) {
90282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return sManager.getDelegate(native_bitmap);
91282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
92282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
93d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    @Nullable
94d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    public static Bitmap_Delegate getDelegate(@Nullable Bitmap bitmap) {
95906f2ad1c857077368d5ca154d8e849f4ad420fcDiego Perez        return bitmap == null ? null : getDelegate(bitmap.getNativeInstance());
96d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    }
97d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta
98282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
99282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Creates and returns a {@link Bitmap} initialized with the given file content.
100282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
101282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param input the file from which to read the bitmap content
102282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param isMutable whether the bitmap is mutable
103282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param density the density associated with the bitmap
104282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
105282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see Bitmap#isMutable()
106282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see Bitmap#getDensity()
107282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
108282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static Bitmap createBitmap(File input, boolean isMutable, Density density)
109282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            throws IOException {
11070f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
11170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    }
112bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta
11370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    /**
11470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * Creates and returns a {@link Bitmap} initialized with the given file content.
11570f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     *
11670f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @param input the file from which to read the bitmap content
11770f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @param density the density associated with the bitmap
11870f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     *
119bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta     * @see Bitmap#isPremultiplied()
12070f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @see Bitmap#isMutable()
12170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @see Bitmap#getDensity()
12270f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     */
123491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta    private static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
12470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta            Density density) throws IOException {
125282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create a delegate with the content of the file.
126491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta        BufferedImage image = ImageIO.read(input);
127491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta        if (image == null && input.exists()) {
128491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta            // There was a problem decoding the image, or the decoder isn't registered. Webp maybe.
129491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta            // Replace with a broken image icon.
130491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta            BridgeContext currentContext = RenderAction.getCurrentContext();
131491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta            if (currentContext != null) {
132491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta                RenderResources resources = currentContext.getRenderResources();
133491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta                ResourceValue broken = resources.getFrameworkResource(ResourceType.DRAWABLE,
134491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta                        "ic_menu_report_image");
135491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta                File brokenFile = new File(broken.getValue());
136491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta                if (brokenFile.exists()) {
137491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta                    image = ImageIO.read(brokenFile);
138491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta                }
139491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta            }
140491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta        }
141491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
142bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta
14370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(delegate, createFlags, density.getDpiValue());
144282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
145282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
146282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
147282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Creates and returns a {@link Bitmap} initialized with the given stream content.
148282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
149282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param input the stream from which to read the bitmap content
150282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param isMutable whether the bitmap is mutable
151282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param density the density associated with the bitmap
152282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
153282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see Bitmap#isMutable()
154282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see Bitmap#getDensity()
155282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
156282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density)
157282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            throws IOException {
15870f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
15970f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    }
16070f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta
16170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    /**
16270f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * Creates and returns a {@link Bitmap} initialized with the given stream content.
16370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     *
16470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @param input the stream from which to read the bitmap content
16570f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @param density the density associated with the bitmap
16670f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     *
167bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta     * @see Bitmap#isPremultiplied()
16870f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @see Bitmap#isMutable()
16970f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @see Bitmap#getDensity()
17070f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     */
17170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    public static Bitmap createBitmap(InputStream input, Set<BitmapCreateFlags> createFlags,
17270f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta            Density density) throws IOException {
173282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create a delegate with the content of the stream.
174282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
175282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
17670f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(delegate, createFlags, density.getDpiValue());
177282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
178282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
179282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
180282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
181282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
182282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param image the bitmap content
183282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param isMutable whether the bitmap is mutable
184282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param density the density associated with the bitmap
185282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
186282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see Bitmap#isMutable()
187282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see Bitmap#getDensity()
188282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
1899173c8a2e90a48959dedc9d4aa415482f5014844Deepanshu Gupta    public static Bitmap createBitmap(BufferedImage image, boolean isMutable, Density density) {
19070f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(image, getPremultipliedBitmapCreateFlags(isMutable), density);
19170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    }
19270f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta
19370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    /**
19470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
19570f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     *
19670f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @param image the bitmap content
19770f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @param density the density associated with the bitmap
19870f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     *
199bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta     * @see Bitmap#isPremultiplied()
20070f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @see Bitmap#isMutable()
20170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     * @see Bitmap#getDensity()
20270f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta     */
20370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    public static Bitmap createBitmap(BufferedImage image, Set<BitmapCreateFlags> createFlags,
2049173c8a2e90a48959dedc9d4aa415482f5014844Deepanshu Gupta            Density density) {
205282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create a delegate with the given image.
206282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
207282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
20870f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(delegate, createFlags, density.getDpiValue());
209282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
210282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
211d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta    private static int getBufferedImageType() {
212282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return BufferedImage.TYPE_INT_ARGB;
213282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
214282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
215282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
216282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
217282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
218282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public BufferedImage getImage() {
219282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mImage;
220282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
221282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
222282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
223282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the Android bitmap config. Note that this not the config of the underlying
224282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Java2D bitmap.
225282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
226282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public Config getConfig() {
227282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mConfig;
228282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
229282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
230282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
231282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Returns the hasAlpha rendering hint
232282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return true if the bitmap alpha should be used at render time
233282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
234282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public boolean hasAlpha() {
235282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return mHasAlpha && mConfig != Config.RGB_565;
236282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
237282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
238282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
239282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Update the generationId.
240282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
241282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @see Bitmap#getGenerationId()
242282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
243282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    public void change() {
244282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mGenerationId++;
245282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
246282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
247282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- native methods ----
248282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
249282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
250282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
25170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta            int height, int nativeConfig, boolean isMutable) {
252d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        int imageType = getBufferedImageType();
253282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
254282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create the image
255282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image = new BufferedImage(width, height, imageType);
256282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
257282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (colors != null) {
258282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            image.setRGB(0, 0, width, height, colors, offset, stride);
259282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
260282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
261282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create a delegate with the content of the stream.
262282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
263282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
26470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
265bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta                            Bitmap.getDefaultDensity());
266282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
267282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
268282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
26988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static Bitmap nativeCopy(long srcBitmap, int nativeConfig, boolean isMutable) {
270282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap);
271282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (srcBmpDelegate == null) {
272282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
273282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
274282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
275282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage srcImage = srcBmpDelegate.getImage();
276282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
277282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int width = srcImage.getWidth();
278282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int height = srcImage.getHeight();
279282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
280d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        int imageType = getBufferedImageType();
281282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
282282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create the image
283282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image = new BufferedImage(width, height, imageType);
284282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
285282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // copy the source image into the image.
286282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int[] argb = new int[width * height];
287282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        srcImage.getRGB(0, 0, width, height, argb, 0, width);
288282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image.setRGB(0, 0, width, height, argb, 0, width);
289282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
290282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create a delegate with the content of the stream.
291282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
292282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
29370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
29470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta                Bitmap.getDefaultDensity());
295282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
296282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
297282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
298a5e6298b35fa212a7f20740174c553ce4079cce2Deepanshu Gupta    /*package*/ static Bitmap nativeCopyAshmem(long nativeSrcBitmap) {
299a5e6298b35fa212a7f20740174c553ce4079cce2Deepanshu Gupta        // Unused method; no implementation provided.
300a5e6298b35fa212a7f20740174c553ce4079cce2Deepanshu Gupta        assert false;
301a5e6298b35fa212a7f20740174c553ce4079cce2Deepanshu Gupta        return null;
302a5e6298b35fa212a7f20740174c553ce4079cce2Deepanshu Gupta    }
303a5e6298b35fa212a7f20740174c553ce4079cce2Deepanshu Gupta
304a5e6298b35fa212a7f20740174c553ce4079cce2Deepanshu Gupta    @LayoutlibDelegate
305d7d2119fe37f48e4157c3bc471c1153544cf5604Diego Perez    /*package*/ static Bitmap nativeCopyAshmemConfig(long nativeSrcBitmap, int nativeConfig) {
306d7d2119fe37f48e4157c3bc471c1153544cf5604Diego Perez        // Unused method; no implementation provided.
307d7d2119fe37f48e4157c3bc471c1153544cf5604Diego Perez        assert false;
308d7d2119fe37f48e4157c3bc471c1153544cf5604Diego Perez        return null;
309d7d2119fe37f48e4157c3bc471c1153544cf5604Diego Perez    }
310d7d2119fe37f48e4157c3bc471c1153544cf5604Diego Perez
311d7d2119fe37f48e4157c3bc471c1153544cf5604Diego Perez    @LayoutlibDelegate
312491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta    /*package*/ static long nativeGetNativeFinalizer() {
313491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta        synchronized (Bitmap_Delegate.class) {
314491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta            if (sFinalizer == -1) {
315491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta                sFinalizer = NativeAllocationRegistry_Delegate.createFinalizer(sManager::removeJavaReferenceFor);
316491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta            }
317491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta            return sFinalizer;
318491523d52cd8368ef9a92e95fb3e9332bf86a996Deepanshu Gupta        }
319282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
320282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
321282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
322bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta    /*package*/ static boolean nativeRecycle(long nativeBitmap) {
323adf62b3ebc8ae5e3e76cf6cfce978e8d1ca5bf8eDiego Perez        // In our case reycle() is a no-op. We will let the finalizer to dispose the bitmap.
324bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta        return true;
325bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta    }
326bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta
327bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta    @LayoutlibDelegate
328bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta    /*package*/ static void nativeReconfigure(long nativeBitmap, int width, int height,
329a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard            int config, boolean isPremultiplied) {
330bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
331bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta                "Bitmap.reconfigure() is not supported", null /*data*/);
332282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
333282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
334282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
33588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean nativeCompress(long nativeBitmap, int format, int quality,
336282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            OutputStream stream, byte[] tempStorage) {
337282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
338282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Bitmap.compress() is not supported", null /*data*/);
339282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return true;
340282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
341282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
342282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
34388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeErase(long nativeBitmap, int color) {
344282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
345282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
346282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
347282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
348282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
349282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
350282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image = delegate.mImage;
351282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
352282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Graphics2D g = image.createGraphics();
353282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        try {
354282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            g.setColor(new java.awt.Color(color, true));
355282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
356282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            g.fillRect(0, 0, image.getWidth(), image.getHeight());
357282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        } finally {
358282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            g.dispose();
359282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
360282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
361282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
362282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
36388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static int nativeRowBytes(long nativeBitmap) {
364282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
365282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
366282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
367282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
368282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
369282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
370282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return delegate.mImage.getWidth();
371282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
372282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
373282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
37488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static int nativeConfig(long nativeBitmap) {
375282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
376282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
377282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
378282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
379282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
380282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
381282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return delegate.mConfig.nativeInt;
382282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
383282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
384282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
38588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean nativeHasAlpha(long nativeBitmap) {
386282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
387282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
388d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        return delegate == null || delegate.mHasAlpha;
389282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
390282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
391282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
392282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
39388a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean nativeHasMipMap(long nativeBitmap) {
394282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
395282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
396d77b9ed7dcc42efca33b225c4594a30aab9e709cDeepanshu Gupta        return delegate == null || delegate.mHasMipMap;
397282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
398282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
399282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
400282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
40126e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    /*package*/ static int nativeGetPixel(long nativeBitmap, int x, int y) {
402282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
403282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
404282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
405282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
406282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
407282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
408282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return delegate.mImage.getRGB(x, y);
409282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
410282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
411282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
41288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeGetPixels(long nativeBitmap, int[] pixels, int offset,
41326e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta            int stride, int x, int y, int width, int height) {
414282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
415282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
416282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
417282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
418282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
419282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride);
420282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
421282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
422282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
423282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
42426e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    /*package*/ static void nativeSetPixel(long nativeBitmap, int x, int y, int color) {
425282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
426282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
427282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
428282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
429282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
430282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delegate.getImage().setRGB(x, y, color);
431282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
432282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
433282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
43488a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeSetPixels(long nativeBitmap, int[] colors, int offset,
43526e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta            int stride, int x, int y, int width, int height) {
436282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
437282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
438282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
439282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
440282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
441282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delegate.getImage().setRGB(x, y, width, height, colors, offset, stride);
442282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
443282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
444282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
44588a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeCopyPixelsToBuffer(long nativeBitmap, Buffer dst) {
446282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME implement native delegate
447282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
448282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Bitmap.copyPixelsToBuffer is not supported.", null, null /*data*/);
449282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
450282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
451282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
45288a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeCopyPixelsFromBuffer(long nb, Buffer src) {
453282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // FIXME implement native delegate
454282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
455282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "Bitmap.copyPixelsFromBuffer is not supported.", null, null /*data*/);
456282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
457282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
458282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
45988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static int nativeGenerationId(long nativeBitmap) {
460282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
461282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
462282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return 0;
463282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
464282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
465282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return delegate.mGenerationId;
466282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
467282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
468282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
469282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
470282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only
471282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // used during aidl call so really this should not be called.
472282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
473282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.",
474282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                null /*data*/);
475282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return null;
476282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
477282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
478282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
47988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean nativeWriteToParcel(long nativeBitmap, boolean isMutable,
480282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int density, Parcel p) {
481282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // This is only called when sending a bitmap through aidl, so really this should not
482282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // be called.
483282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
484282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.",
485282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                null /*data*/);
486282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return false;
487282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
488282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
489282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
49088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static Bitmap nativeExtractAlpha(long nativeBitmap, long nativePaint,
491282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            int[] offsetXY) {
492282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap);
493282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (bitmap == null) {
494282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return null;
495282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
496282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
497282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the paint which can be null if nativePaint is 0.
498282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
499282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
500282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (paint != null && paint.getMaskFilter() != null) {
501282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
502282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    "MaskFilter not supported in Bitmap.extractAlpha",
503282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    null, null /*data*/);
504282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
505282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
506282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int alpha = paint != null ? paint.getAlpha() : 0xFF;
507282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha);
508282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
509282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // create the delegate. The actual Bitmap config is only an alpha channel
510282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8);
511282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
512282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // the density doesn't matter, it's set by the Java method.
51370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.MUTABLE),
514282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                Density.DEFAULT_DENSITY /*density*/);
515282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
516282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
517282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
51826e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    /*package*/ static boolean nativeIsPremultiplied(long nativeBitmap) {
51926e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        // get the delegate from the native int.
52026e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
52126e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        return delegate != null && delegate.mIsPremultiplied;
52226e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta
52326e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    }
52426e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta
52526e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    @LayoutlibDelegate
52626e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    /*package*/ static void nativeSetPremultiplied(long nativeBitmap, boolean isPremul) {
52726e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        // get the delegate from the native int.
52826e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
52926e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        if (delegate == null) {
53026e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta            return;
53126e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        }
53226e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta
53326e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta        delegate.mIsPremultiplied = isPremul;
53426e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    }
53526e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta
53626e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    @LayoutlibDelegate
53726e32ea559da98dcdebaefb74d4f3c1a5ce705c3Deepanshu Gupta    /*package*/ static void nativeSetHasAlpha(long nativeBitmap, boolean hasAlpha,
538e05bb956ce429618fd4f971a9dc708b9313c59eaDeepanshu Gupta            boolean isPremul) {
539282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
540282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
541282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
542282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
543282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
544282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
545282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delegate.mHasAlpha = hasAlpha;
546282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
547282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
548282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
54988a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap) {
550282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the delegate from the native int.
551282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
552282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate == null) {
553282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return;
554282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
555282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
556282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        delegate.mHasMipMap = hasMipMap;
557282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
558282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
559282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    @LayoutlibDelegate
56088a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath    /*package*/ static boolean nativeSameAs(long nb0, long nb1) {
561282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate1 = sManager.getDelegate(nb0);
562282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate1 == null) {
563282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
564282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
565282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
566282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        Bitmap_Delegate delegate2 = sManager.getDelegate(nb1);
567282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate2 == null) {
568282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
569282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
570282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
571282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image1 = delegate1.getImage();
572282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage image2 = delegate2.getImage();
573282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate1.mConfig != delegate2.mConfig ||
574282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                image1.getWidth() != image2.getWidth() ||
575282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                image1.getHeight() != image2.getHeight()) {
576282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return false;
577282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
578282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
579282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get the internal data
580282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int w = image1.getWidth();
581282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int h = image2.getHeight();
582282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int[] argb1 = new int[w*h];
583282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int[] argb2 = new int[w*h];
584282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
585282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image1.getRGB(0, 0, w, h, argb1, 0, w);
586282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image2.getRGB(0, 0, w, h, argb2, 0, w);
587282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
588282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // compares
589282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (delegate1.mConfig == Config.ALPHA_8) {
590282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            // in this case we have to manually compare the alpha channel as the rest is garbage.
591282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int length = w*h;
592282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int i = 0 ; i < length ; i++) {
593282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) {
594282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                    return false;
595282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                }
596282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
597282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            return true;
598282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
599282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
600282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return Arrays.equals(argb1, argb2);
601282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
602282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
603a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    @LayoutlibDelegate
604a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static int nativeGetAllocationByteCount(long nativeBitmap) {
605a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        // get the delegate from the native int.
606a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
607a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        if (delegate == null) {
608a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard            return 0;
609a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        }
610a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        return nativeRowBytes(nativeBitmap) * delegate.mImage.getHeight();
611a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard
612a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    }
613a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard
614a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    @LayoutlibDelegate
615a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    /*package*/ static void nativePrepareToDraw(long nativeBitmap) {
616a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard        // do nothing as Bitmap_Delegate does not have caches
617a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard    }
618a10973ebd1ca33c14f0cb06c22ea9d2f9828ac99Jerome Gaillard
6199758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard    @LayoutlibDelegate
6209758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard    /*package*/ static Bitmap nativeCopyPreserveInternalConfig(long nativeBitmap) {
6219758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(nativeBitmap);
6229758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        if (srcBmpDelegate == null) {
6239758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard            return null;
6249758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        }
6259758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard
6269758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        BufferedImage srcImage = srcBmpDelegate.getImage();
6279758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard
6289758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        // create the image
6299758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        BufferedImage image = new BufferedImage(srcImage.getColorModel(), srcImage.copyData(null),
6309758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard                srcImage.isAlphaPremultiplied(), null);
6319758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard
6329758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        // create a delegate with the content of the stream.
6339758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        Bitmap_Delegate delegate = new Bitmap_Delegate(image, srcBmpDelegate.getConfig());
6349758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard
6359758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard        return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.NONE),
6369758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard                Bitmap.getDefaultDensity());
6379758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard    }
6389758e22d2c852e9f1152b540775360b28dbc2b3eJerome Gaillard
6392a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez    @LayoutlibDelegate
6402a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez    /*package*/ static Bitmap nativeCreateHardwareBitmap(GraphicBuffer buffer) {
6412a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
6422a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez                "Bitmap.nativeCreateHardwareBitmap() is not supported", null /*data*/);
6432a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez        return null;
6442a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez    }
6452a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez
6462a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez    @LayoutlibDelegate
6472a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez    /*package*/ static GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap) {
6482a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
6492a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez                "Bitmap.nativeCreateGraphicBufferHandle() is not supported", null /*data*/);
6502a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez        return null;
6512a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez    }
6522a1b23966af3a9ee25cd223e1679f08beb8ed072Diego Perez
65380447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard    @LayoutlibDelegate
65480447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard    /*package*/ static boolean nativeIsSRGB(long nativeBitmap) {
65580447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
65680447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard                "Color spaces are not supported", null /*data*/);
65780447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard        return false;
65880447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard    }
65980447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard
66080447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard    @LayoutlibDelegate
66180447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard    /*package*/ static boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params) {
66280447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard        Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
66380447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard                "Color spaces are not supported", null /*data*/);
66480447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard        return false;
66580447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard    }
66680447d42f0c60cfe45a7acf43bd3d8e2c83a18ebJerome Gaillard
667282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    // ---- Private delegate/helper methods ----
668282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
669282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    private Bitmap_Delegate(BufferedImage image, Config config) {
670282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mImage = image;
671282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        mConfig = config;
672282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
673282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
67470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    private static Bitmap createBitmap(Bitmap_Delegate delegate,
67570f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta            Set<BitmapCreateFlags> createFlags, int density) {
676282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // get its native_int
67788a8364c386c694f7ad56662ef89713dbf7c9d63Narayan Kamath        long nativeInt = sManager.addNewDelegate(delegate);
678282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
67970f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        int width = delegate.mImage.getWidth();
68070f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        int height = delegate.mImage.getHeight();
68170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        boolean isMutable = createFlags.contains(BitmapCreateFlags.MUTABLE);
68270f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        boolean isPremultiplied = createFlags.contains(BitmapCreateFlags.PREMULTIPLIED);
68370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta
684282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        // and create/return a new Bitmap with it
6854508218850faedea95371188da587b6734f5f3dasergeyv        return new Bitmap(nativeInt, width, height, density, isMutable,
68670f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta                          isPremultiplied, null /*ninePatchChunk*/, null /* layoutBounds */);
687282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
688282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
68970f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    private static Set<BitmapCreateFlags> getPremultipliedBitmapCreateFlags(boolean isMutable) {
690bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta        Set<BitmapCreateFlags> createFlags = EnumSet.of(BitmapCreateFlags.PREMULTIPLIED);
69170f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        if (isMutable) {
69270f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta            createFlags.add(BitmapCreateFlags.MUTABLE);
69370f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        }
69470f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta        return createFlags;
69570f5cc1d5bb9c67781fa6e076e21547547301a3bDeepanshu Gupta    }
696bd28e2d9d3c2a7e80babd39471d5788843a48d4aDeepanshu Gupta
697282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /**
698282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * Creates and returns a copy of a given BufferedImage.
699282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * <p/>
700282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * if alpha is different than 255, then it is applied to the alpha channel of each pixel.
701282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     *
702282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param image the image to copy
703282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param imageType the type of the new image
704282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @param alpha an optional alpha modifier
705282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     * @return a new BufferedImage
706282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski     */
707282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) {
708282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int w = image.getWidth();
709282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int h = image.getHeight();
710282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
711282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        BufferedImage result = new BufferedImage(w, h, imageType);
712282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
713282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        int[] argb = new int[w * h];
714282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
715282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
716282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        if (alpha != 255) {
717282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            final int length = argb.length;
718282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            for (int i = 0 ; i < length; i++) {
719282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                int a = (argb[i] >>> 24 * alpha) / 255;
720282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski                argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF);
721282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski            }
722282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        }
723282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
724282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        result.setRGB(0, 0, w, h, argb, 0, w);
725282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
726282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski        return result;
727282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski    }
728282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski
729282e181b58cf72b6ca770dc7ca5f91f135444502Adam Lesinski}
730