blob: 96616aaeca4fbf6d16fb713cf6f31f8243e5b791 [file] [log] [blame]
Xavier Ducrohet5de11a12010-10-29 16:01:40 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.graphics;
18
Xavier Ducrohet918aaa52011-01-13 10:59:34 -080019import com.android.ide.common.rendering.api.LayoutLog;
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -080020import com.android.layoutlib.bridge.Bridge;
Xavier Ducrohetc2e96512010-11-09 18:25:03 -080021import com.android.layoutlib.bridge.impl.DelegateManager;
Xavier Ducrohet16584222011-01-27 15:30:39 -080022import com.android.resources.Density;
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -080023import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070024
25import android.graphics.Bitmap.Config;
26import android.os.Parcel;
27
28import java.awt.Graphics2D;
29import java.awt.image.BufferedImage;
30import java.io.File;
31import java.io.IOException;
32import java.io.InputStream;
33import java.io.OutputStream;
34import java.nio.Buffer;
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -080035import java.util.Arrays;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070036
37import javax.imageio.ImageIO;
38
39/**
40 * Delegate implementing the native methods of android.graphics.Bitmap
41 *
42 * Through the layoutlib_create tool, the original native methods of Bitmap have been replaced
43 * by calls to methods of the same name in this delegate class.
44 *
45 * This class behaves like the original native implementation, but in Java, keeping previously
46 * native data into its own objects and mapping them to int that are sent back and forth between
47 * it and the original Bitmap class.
48 *
49 * @see DelegateManager
50 *
51 */
Xavier Ducrohetd348b6e2010-12-20 08:22:47 -080052public final class Bitmap_Delegate {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070053
54 // ---- delegate manager ----
55 private static final DelegateManager<Bitmap_Delegate> sManager =
Xavier Ducrohetf0a53432011-02-23 16:51:08 -080056 new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070057
58 // ---- delegate helper data ----
59
60 // ---- delegate data ----
Xavier Ducrohet63fd8712010-12-21 01:33:04 -080061 private final Config mConfig;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070062 private BufferedImage mImage;
63 private boolean mHasAlpha = true;
Deepanshu Gupta279c00e2013-05-23 15:20:04 -070064 private boolean mHasMipMap = false; // TODO: check the default.
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -080065 private int mGenerationId = 0;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070066
Xavier Ducrohet63fd8712010-12-21 01:33:04 -080067
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070068 // ---- Public Helper methods ----
69
70 /**
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -070071 * Returns the native delegate associated to a given {@link Bitmap_Delegate} object.
72 */
73 public static Bitmap_Delegate getDelegate(Bitmap bitmap) {
74 return sManager.getDelegate(bitmap.mNativeBitmap);
75 }
76
77 /**
78 * Returns the native delegate associated to a given an int referencing a {@link Bitmap} object.
79 */
80 public static Bitmap_Delegate getDelegate(int native_bitmap) {
81 return sManager.getDelegate(native_bitmap);
82 }
83
84 /**
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070085 * Creates and returns a {@link Bitmap} initialized with the given file content.
Xavier Ducrohet2d56b272010-11-22 20:09:55 -080086 *
87 * @param input the file from which to read the bitmap content
88 * @param isMutable whether the bitmap is mutable
89 * @param density the density associated with the bitmap
90 *
91 * @see Bitmap#isMutable()
92 * @see Bitmap#getDensity()
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070093 */
Xavier Ducrohet16584222011-01-27 15:30:39 -080094 public static Bitmap createBitmap(File input, boolean isMutable, Density density)
Xavier Ducrohet2d56b272010-11-22 20:09:55 -080095 throws IOException {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070096 // create a delegate with the content of the file.
Xavier Ducrohet63fd8712010-12-21 01:33:04 -080097 Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -070098
Xavier Ducrohet16584222011-01-27 15:30:39 -080099 return createBitmap(delegate, isMutable, density.getDpiValue());
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700100 }
101
102 /**
103 * Creates and returns a {@link Bitmap} initialized with the given stream content.
Xavier Ducrohet2d56b272010-11-22 20:09:55 -0800104 *
105 * @param input the stream from which to read the bitmap content
106 * @param isMutable whether the bitmap is mutable
107 * @param density the density associated with the bitmap
108 *
109 * @see Bitmap#isMutable()
110 * @see Bitmap#getDensity()
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700111 */
Xavier Ducrohet16584222011-01-27 15:30:39 -0800112 public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density)
Xavier Ducrohet2d56b272010-11-22 20:09:55 -0800113 throws IOException {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700114 // create a delegate with the content of the stream.
Xavier Ducrohet63fd8712010-12-21 01:33:04 -0800115 Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700116
Xavier Ducrohet16584222011-01-27 15:30:39 -0800117 return createBitmap(delegate, isMutable, density.getDpiValue());
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700118 }
119
120 /**
121 * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
Xavier Ducrohet2d56b272010-11-22 20:09:55 -0800122 *
123 * @param image the bitmap content
124 * @param isMutable whether the bitmap is mutable
125 * @param density the density associated with the bitmap
126 *
127 * @see Bitmap#isMutable()
128 * @see Bitmap#getDensity()
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700129 */
Xavier Ducrohetffb42f62010-12-09 18:26:01 -0800130 public static Bitmap createBitmap(BufferedImage image, boolean isMutable,
Xavier Ducrohet16584222011-01-27 15:30:39 -0800131 Density density) throws IOException {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700132 // create a delegate with the given image.
Xavier Ducrohet63fd8712010-12-21 01:33:04 -0800133 Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700134
Xavier Ducrohet16584222011-01-27 15:30:39 -0800135 return createBitmap(delegate, isMutable, density.getDpiValue());
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700136 }
137
138 /**
139 * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
140 */
141 public static BufferedImage getImage(Bitmap bitmap) {
142 // get the delegate from the native int.
143 Bitmap_Delegate delegate = sManager.getDelegate(bitmap.mNativeBitmap);
144 if (delegate == null) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700145 return null;
146 }
147
148 return delegate.mImage;
149 }
150
151 public static int getBufferedImageType(int nativeBitmapConfig) {
Xavier Ducrohet7f9f99ea2011-08-11 10:16:17 -0700152 switch (Config.nativeToConfig(nativeBitmapConfig)) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700153 case ALPHA_8:
154 return BufferedImage.TYPE_INT_ARGB;
155 case RGB_565:
156 return BufferedImage.TYPE_INT_ARGB;
157 case ARGB_4444:
158 return BufferedImage.TYPE_INT_ARGB;
159 case ARGB_8888:
160 return BufferedImage.TYPE_INT_ARGB;
161 }
162
163 return BufferedImage.TYPE_INT_ARGB;
164 }
165
Xavier Ducrohet9f63ff22010-10-28 11:52:00 -0700166 /**
167 * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
168 */
169 public BufferedImage getImage() {
170 return mImage;
171 }
172
Xavier Ducrohet63fd8712010-12-21 01:33:04 -0800173 /**
174 * Returns the Android bitmap config. Note that this not the config of the underlying
175 * Java2D bitmap.
176 */
177 public Config getConfig() {
178 return mConfig;
179 }
180
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800181 /**
182 * Returns the hasAlpha rendering hint
183 * @return true if the bitmap alpha should be used at render time
184 */
185 public boolean hasAlpha() {
186 return mHasAlpha && mConfig != Config.RGB_565;
187 }
188
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700189 public boolean hasMipMap() {
190 // TODO: check if more checks are required as in hasAlpha.
191 return mHasMipMap;
192 }
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800193 /**
194 * Update the generationId.
195 *
196 * @see Bitmap#getGenerationId()
197 */
198 public void change() {
199 mGenerationId++;
200 }
Xavier Ducrohet63fd8712010-12-21 01:33:04 -0800201
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700202 // ---- native methods ----
203
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800204 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700205 /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
206 int height, int nativeConfig, boolean mutable) {
207 int imageType = getBufferedImageType(nativeConfig);
208
209 // create the image
210 BufferedImage image = new BufferedImage(width, height, imageType);
211
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800212 if (colors != null) {
213 image.setRGB(0, 0, width, height, colors, offset, stride);
214 }
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700215
216 // create a delegate with the content of the stream.
Xavier Ducrohet7f9f99ea2011-08-11 10:16:17 -0700217 Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700218
Xavier Ducrohet2d56b272010-11-22 20:09:55 -0800219 return createBitmap(delegate, mutable, Bitmap.getDefaultDensity());
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700220 }
221
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800222 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700223 /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800224 Bitmap_Delegate srcBmpDelegate = sManager.getDelegate(srcBitmap);
225 if (srcBmpDelegate == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800226 return null;
227 }
228
229 BufferedImage srcImage = srcBmpDelegate.getImage();
230
231 int width = srcImage.getWidth();
232 int height = srcImage.getHeight();
233
234 int imageType = getBufferedImageType(nativeConfig);
235
236 // create the image
237 BufferedImage image = new BufferedImage(width, height, imageType);
238
239 // copy the source image into the image.
240 int[] argb = new int[width * height];
241 srcImage.getRGB(0, 0, width, height, argb, 0, width);
242 image.setRGB(0, 0, width, height, argb, 0, width);
243
244 // create a delegate with the content of the stream.
Xavier Ducrohet7f9f99ea2011-08-11 10:16:17 -0700245 Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800246
247 return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity());
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700248 }
249
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800250 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700251 /*package*/ static void nativeDestructor(int nativeBitmap) {
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -0800252 sManager.removeJavaReferenceFor(nativeBitmap);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700253 }
254
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800255 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700256 /*package*/ static void nativeRecycle(int nativeBitmap) {
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -0800257 sManager.removeJavaReferenceFor(nativeBitmap);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700258 }
259
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800260 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700261 /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality,
262 OutputStream stream, byte[] tempStorage) {
Xavier Ducrohet918aaa52011-01-13 10:59:34 -0800263 Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
Xavier Ducrohet51a7e542011-01-14 16:40:43 -0800264 "Bitmap.compress() is not supported", null /*data*/);
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800265 return true;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700266 }
267
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800268 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700269 /*package*/ static void nativeErase(int nativeBitmap, int color) {
270 // get the delegate from the native int.
271 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
272 if (delegate == null) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700273 return;
274 }
275
276 BufferedImage image = delegate.mImage;
277
278 Graphics2D g = image.createGraphics();
279 try {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800280 g.setColor(new java.awt.Color(color, true));
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700281
282 g.fillRect(0, 0, image.getWidth(), image.getHeight());
283 } finally {
284 g.dispose();
285 }
286 }
287
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800288 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700289 /*package*/ static int nativeWidth(int nativeBitmap) {
290 // get the delegate from the native int.
291 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
292 if (delegate == null) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700293 return 0;
294 }
295
296 return delegate.mImage.getWidth();
297 }
298
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800299 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700300 /*package*/ static int nativeHeight(int nativeBitmap) {
301 // get the delegate from the native int.
302 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
303 if (delegate == null) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700304 return 0;
305 }
306
307 return delegate.mImage.getHeight();
308 }
309
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800310 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700311 /*package*/ static int nativeRowBytes(int nativeBitmap) {
312 // get the delegate from the native int.
313 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
314 if (delegate == null) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700315 return 0;
316 }
317
318 return delegate.mImage.getWidth();
319 }
320
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800321 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700322 /*package*/ static int nativeConfig(int nativeBitmap) {
Xavier Ducrohet63fd8712010-12-21 01:33:04 -0800323 // get the delegate from the native int.
324 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
325 if (delegate == null) {
Xavier Ducrohet63fd8712010-12-21 01:33:04 -0800326 return 0;
327 }
328
329 return delegate.mConfig.nativeInt;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700330 }
331
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800332 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700333 /*package*/ static boolean nativeHasAlpha(int nativeBitmap) {
334 // get the delegate from the native int.
335 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
336 if (delegate == null) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700337 return true;
338 }
339
340 return delegate.mHasAlpha;
341 }
342
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800343 @LayoutlibDelegate
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700344 /*package*/ static boolean nativeHasMipMap(int nativeBitmap) {
345 // get the delegate from the native int.
346 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
347 if (delegate == null) {
348 return true;
349 }
350
351 return delegate.mHasMipMap;
352 }
353
354 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700355 /*package*/ static int nativeGetPixel(int nativeBitmap, int x, int y) {
356 // get the delegate from the native int.
357 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
358 if (delegate == null) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700359 return 0;
360 }
361
362 return delegate.mImage.getRGB(x, y);
363 }
364
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800365 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700366 /*package*/ static void nativeGetPixels(int nativeBitmap, int[] pixels, int offset,
367 int stride, int x, int y, int width, int height) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800368 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
369 if (delegate == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800370 return;
371 }
372
373 delegate.getImage().getRGB(x, y, width, height, pixels, offset, stride);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700374 }
375
376
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800377 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700378 /*package*/ static void nativeSetPixel(int nativeBitmap, int x, int y, int color) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800379 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
380 if (delegate == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800381 return;
382 }
383
384 delegate.getImage().setRGB(x, y, color);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700385 }
386
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800387 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700388 /*package*/ static void nativeSetPixels(int nativeBitmap, int[] colors, int offset,
389 int stride, int x, int y, int width, int height) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800390 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
391 if (delegate == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800392 return;
393 }
394
395 delegate.getImage().setRGB(x, y, width, height, colors, offset, stride);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700396 }
397
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800398 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700399 /*package*/ static void nativeCopyPixelsToBuffer(int nativeBitmap, Buffer dst) {
400 // FIXME implement native delegate
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800401 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
402 "Bitmap.copyPixelsToBuffer is not supported.", null, null /*data*/);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700403 }
404
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800405 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700406 /*package*/ static void nativeCopyPixelsFromBuffer(int nb, Buffer src) {
407 // FIXME implement native delegate
Xavier Ducrohet8a80a852011-02-09 19:39:52 -0800408 Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
409 "Bitmap.copyPixelsFromBuffer is not supported.", null, null /*data*/);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700410 }
411
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800412 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700413 /*package*/ static int nativeGenerationId(int nativeBitmap) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800414 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
415 if (delegate == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800416 return 0;
417 }
418
419 return delegate.mGenerationId;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700420 }
421
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800422 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700423 /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800424 // This is only called by Bitmap.CREATOR (Parcelable.Creator<Bitmap>), which is only
425 // used during aidl call so really this should not be called.
Xavier Ducrohet918aaa52011-01-13 10:59:34 -0800426 Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
Xavier Ducrohet51a7e542011-01-14 16:40:43 -0800427 "AIDL is not suppored, and therefore Bitmaps cannot be created from parcels.",
428 null /*data*/);
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800429 return null;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700430 }
431
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800432 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700433 /*package*/ static boolean nativeWriteToParcel(int nativeBitmap, boolean isMutable,
434 int density, Parcel p) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800435 // This is only called when sending a bitmap through aidl, so really this should not
436 // be called.
Xavier Ducrohet918aaa52011-01-13 10:59:34 -0800437 Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
Xavier Ducrohet51a7e542011-01-14 16:40:43 -0800438 "AIDL is not suppored, and therefore Bitmaps cannot be written to parcels.",
439 null /*data*/);
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800440 return false;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700441 }
442
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800443 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700444 /*package*/ static Bitmap nativeExtractAlpha(int nativeBitmap, int nativePaint,
445 int[] offsetXY) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800446 Bitmap_Delegate bitmap = sManager.getDelegate(nativeBitmap);
447 if (bitmap == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800448 return null;
449 }
450
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800451 // get the paint which can be null if nativePaint is 0.
452 Paint_Delegate paint = Paint_Delegate.getDelegate(nativePaint);
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800453
Xavier Ducrohetd43909c2010-12-23 07:16:21 -0800454 if (paint != null && paint.getMaskFilter() != null) {
Xavier Ducrohet918aaa52011-01-13 10:59:34 -0800455 Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800456 "MaskFilter not supported in Bitmap.extractAlpha",
Xavier Ducrohet51a7e542011-01-14 16:40:43 -0800457 null, null /*data*/);
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800458 }
459
460 int alpha = paint != null ? paint.getAlpha() : 0xFF;
461 BufferedImage image = createCopy(bitmap.getImage(), BufferedImage.TYPE_INT_ARGB, alpha);
462
463 // create the delegate. The actual Bitmap config is only an alpha channel
464 Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8);
465
466 // the density doesn't matter, it's set by the Java method.
467 return createBitmap(delegate, false /*isMutable*/,
Xavier Ducrohet16584222011-01-27 15:30:39 -0800468 Density.DEFAULT_DENSITY /*density*/);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700469 }
470
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800471 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700472 /*package*/ static void nativePrepareToDraw(int nativeBitmap) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800473 // nothing to be done here.
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700474 }
475
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800476 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700477 /*package*/ static void nativeSetHasAlpha(int nativeBitmap, boolean hasAlpha) {
478 // get the delegate from the native int.
479 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
480 if (delegate == null) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700481 return;
482 }
483
484 delegate.mHasAlpha = hasAlpha;
485 }
486
Xavier Ducrohet9a4fe292011-02-09 17:17:49 -0800487 @LayoutlibDelegate
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700488 /*package*/ static void nativeSetHasMipMap(int nativeBitmap, boolean hasMipMap) {
489 // get the delegate from the native int.
490 Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
491 if (delegate == null) {
492 return;
493 }
494
495 delegate.mHasMipMap = hasMipMap;
496 }
497
498 @LayoutlibDelegate
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700499 /*package*/ static boolean nativeSameAs(int nb0, int nb1) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800500 Bitmap_Delegate delegate1 = sManager.getDelegate(nb0);
501 if (delegate1 == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800502 return false;
503 }
504
505 Bitmap_Delegate delegate2 = sManager.getDelegate(nb1);
506 if (delegate2 == null) {
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800507 return false;
508 }
509
510 BufferedImage image1 = delegate1.getImage();
511 BufferedImage image2 = delegate2.getImage();
512 if (delegate1.mConfig != delegate2.mConfig ||
513 image1.getWidth() != image2.getWidth() ||
514 image1.getHeight() != image2.getHeight()) {
515 return false;
516 }
517
518 // get the internal data
519 int w = image1.getWidth();
520 int h = image2.getHeight();
521 int[] argb1 = new int[w*h];
522 int[] argb2 = new int[w*h];
523
524 image1.getRGB(0, 0, w, h, argb1, 0, w);
525 image2.getRGB(0, 0, w, h, argb2, 0, w);
526
527 // compares
528 if (delegate1.mConfig == Config.ALPHA_8) {
529 // in this case we have to manually compare the alpha channel as the rest is garbage.
530 final int length = w*h;
531 for (int i = 0 ; i < length ; i++) {
532 if ((argb1[i] & 0xFF000000) != (argb2[i] & 0xFF000000)) {
533 return false;
534 }
535 }
536 return true;
537 }
538
539 return Arrays.equals(argb1, argb2);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700540 }
541
542 // ---- Private delegate/helper methods ----
543
Xavier Ducrohet63fd8712010-12-21 01:33:04 -0800544 private Bitmap_Delegate(BufferedImage image, Config config) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700545 mImage = image;
Xavier Ducrohet63fd8712010-12-21 01:33:04 -0800546 mConfig = config;
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700547 }
548
Xavier Ducrohet2d56b272010-11-22 20:09:55 -0800549 private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700550 // get its native_int
Xavier Ducrohetcc4977d2011-02-22 11:54:37 -0800551 int nativeInt = sManager.addNewDelegate(delegate);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700552
553 // and create/return a new Bitmap with it
Deepanshu Gupta279c00e2013-05-23 15:20:04 -0700554 return new Bitmap(nativeInt, null /* buffer */, isMutable, null /*ninePatchChunk*/,
Amith Yamasaniec4a5042012-04-04 10:27:15 -0700555 density);
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700556 }
Xavier Ducrohetb1da1af2010-12-22 10:13:23 -0800557
558 /**
559 * Creates and returns a copy of a given BufferedImage.
560 * <p/>
561 * if alpha is different than 255, then it is applied to the alpha channel of each pixel.
562 *
563 * @param image the image to copy
564 * @param imageType the type of the new image
565 * @param alpha an optional alpha modifier
566 * @return a new BufferedImage
567 */
568 /*package*/ static BufferedImage createCopy(BufferedImage image, int imageType, int alpha) {
569 int w = image.getWidth();
570 int h = image.getHeight();
571
572 BufferedImage result = new BufferedImage(w, h, imageType);
573
574 int[] argb = new int[w * h];
575 image.getRGB(0, 0, image.getWidth(), image.getHeight(), argb, 0, image.getWidth());
576
577 if (alpha != 255) {
578 final int length = argb.length;
579 for (int i = 0 ; i < length; i++) {
580 int a = (argb[i] >>> 24 * alpha) / 255;
581 argb[i] = (a << 24) | (argb[i] & 0x00FFFFFF);
582 }
583 }
584
585 result.setRGB(0, 0, w, h, argb, 0, w);
586
587 return result;
588 }
589
Xavier Ducrohet5de11a12010-10-29 16:01:40 -0700590}