Bitmap_Delegate.java revision ffb42f6c5043de226f02318a1311669d35a90711
1/*
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
19import com.android.layoutlib.api.ResourceDensity;
20import com.android.layoutlib.bridge.impl.DelegateManager;
21
22import android.graphics.Bitmap.Config;
23import android.os.Parcel;
24
25import java.awt.Graphics2D;
26import java.awt.image.BufferedImage;
27import java.io.File;
28import java.io.IOException;
29import java.io.InputStream;
30import java.io.OutputStream;
31import java.nio.Buffer;
32
33import javax.imageio.ImageIO;
34
35/**
36 * Delegate implementing the native methods of android.graphics.Bitmap
37 *
38 * Through the layoutlib_create tool, the original native methods of Bitmap have been replaced
39 * by calls to methods of the same name in this delegate class.
40 *
41 * This class behaves like the original native implementation, but in Java, keeping previously
42 * native data into its own objects and mapping them to int that are sent back and forth between
43 * it and the original Bitmap class.
44 *
45 * @see DelegateManager
46 *
47 */
48public class Bitmap_Delegate {
49
50    // ---- delegate manager ----
51    private static final DelegateManager<Bitmap_Delegate> sManager =
52            new DelegateManager<Bitmap_Delegate>();
53
54    // ---- delegate helper data ----
55
56    // ---- delegate data ----
57    private BufferedImage mImage;
58    private boolean mHasAlpha = true;
59
60    // ---- Public Helper methods ----
61
62    /**
63     * Returns the native delegate associated to a given {@link Bitmap_Delegate} object.
64     */
65    public static Bitmap_Delegate getDelegate(Bitmap bitmap) {
66        return sManager.getDelegate(bitmap.mNativeBitmap);
67    }
68
69    /**
70     * Returns the native delegate associated to a given an int referencing a {@link Bitmap} object.
71     */
72    public static Bitmap_Delegate getDelegate(int native_bitmap) {
73        return sManager.getDelegate(native_bitmap);
74    }
75
76    /**
77     * Creates and returns a {@link Bitmap} initialized with the given file content.
78     *
79     * @param input the file from which to read the bitmap content
80     * @param isMutable whether the bitmap is mutable
81     * @param density the density associated with the bitmap
82     *
83     * @see Bitmap#isMutable()
84     * @see Bitmap#getDensity()
85     */
86    public static Bitmap createBitmap(File input, boolean isMutable, ResourceDensity density)
87            throws IOException {
88        // create a delegate with the content of the file.
89        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input));
90
91        return createBitmap(delegate, isMutable, density.getDpi());
92    }
93
94    /**
95     * Creates and returns a {@link Bitmap} initialized with the given stream content.
96     *
97     * @param input the stream from which to read the bitmap content
98     * @param isMutable whether the bitmap is mutable
99     * @param density the density associated with the bitmap
100     *
101     * @see Bitmap#isMutable()
102     * @see Bitmap#getDensity()
103     */
104    public static Bitmap createBitmap(InputStream input, boolean isMutable, ResourceDensity density)
105            throws IOException {
106        // create a delegate with the content of the stream.
107        Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input));
108
109        return createBitmap(delegate, isMutable, density.getDpi());
110    }
111
112    /**
113     * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
114     *
115     * @param image the bitmap content
116     * @param isMutable whether the bitmap is mutable
117     * @param density the density associated with the bitmap
118     *
119     * @see Bitmap#isMutable()
120     * @see Bitmap#getDensity()
121     */
122    public static Bitmap createBitmap(BufferedImage image, boolean isMutable,
123            ResourceDensity density) throws IOException {
124        // create a delegate with the given image.
125        Bitmap_Delegate delegate = new Bitmap_Delegate(image);
126
127        return createBitmap(delegate, isMutable, density.getDpi());
128    }
129
130    /**
131     * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
132     */
133    public static BufferedImage getImage(Bitmap bitmap) {
134        // get the delegate from the native int.
135        Bitmap_Delegate delegate = sManager.getDelegate(bitmap.mNativeBitmap);
136        if (delegate == null) {
137            assert false;
138            return null;
139        }
140
141        return delegate.mImage;
142    }
143
144    public static int getBufferedImageType(int nativeBitmapConfig) {
145        switch (Config.sConfigs[nativeBitmapConfig]) {
146            case ALPHA_8:
147                return BufferedImage.TYPE_INT_ARGB;
148            case RGB_565:
149                return BufferedImage.TYPE_INT_ARGB;
150            case ARGB_4444:
151                return BufferedImage.TYPE_INT_ARGB;
152            case ARGB_8888:
153                return BufferedImage.TYPE_INT_ARGB;
154        }
155
156        return BufferedImage.TYPE_INT_ARGB;
157    }
158
159    /**
160     * Returns the {@link BufferedImage} used by the delegate of the given {@link Bitmap}.
161     */
162    public BufferedImage getImage() {
163        return mImage;
164    }
165
166    // ---- native methods ----
167
168    /*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
169            int height, int nativeConfig, boolean mutable) {
170        int imageType = getBufferedImageType(nativeConfig);
171
172        // create the image
173        BufferedImage image = new BufferedImage(width, height, imageType);
174
175        // FIXME fill the bitmap!
176
177        // create a delegate with the content of the stream.
178        Bitmap_Delegate delegate = new Bitmap_Delegate(image);
179
180        return createBitmap(delegate, mutable, Bitmap.getDefaultDensity());
181    }
182
183    /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) {
184        // FIXME implement native delegate
185        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
186    }
187
188    /*package*/ static void nativeDestructor(int nativeBitmap) {
189        sManager.removeDelegate(nativeBitmap);
190    }
191
192    /*package*/ static void nativeRecycle(int nativeBitmap) {
193        sManager.removeDelegate(nativeBitmap);
194    }
195
196    /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality,
197            OutputStream stream, byte[] tempStorage) {
198        // FIXME implement native delegate
199        throw new UnsupportedOperationException("Native delegate needed for Bitmap");
200    }
201
202    /*package*/ static void nativeErase(int nativeBitmap, int color) {
203        // get the delegate from the native int.
204        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
205        if (delegate == null) {
206            assert false;
207            return;
208        }
209
210        BufferedImage image = delegate.mImage;
211
212        Graphics2D g = image.createGraphics();
213        try {
214            if (delegate.mHasAlpha == false) {
215                color |= color & 0xFF000000;
216            }
217            g.setColor(new java.awt.Color(color));
218
219            g.fillRect(0, 0, image.getWidth(), image.getHeight());
220        } finally {
221            g.dispose();
222        }
223    }
224
225    /*package*/ static int nativeWidth(int nativeBitmap) {
226        // get the delegate from the native int.
227        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
228        if (delegate == null) {
229            assert false;
230            return 0;
231        }
232
233        return delegate.mImage.getWidth();
234    }
235
236    /*package*/ static int nativeHeight(int nativeBitmap) {
237        // get the delegate from the native int.
238        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
239        if (delegate == null) {
240            assert false;
241            return 0;
242        }
243
244        return delegate.mImage.getHeight();
245    }
246
247    /*package*/ static int nativeRowBytes(int nativeBitmap) {
248        // get the delegate from the native int.
249        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
250        if (delegate == null) {
251            assert false;
252            return 0;
253        }
254
255        return delegate.mImage.getWidth();
256    }
257
258    /*package*/ static int nativeConfig(int nativeBitmap) {
259        return Config.ARGB_8888.nativeInt;
260    }
261
262    /*package*/ static boolean nativeHasAlpha(int nativeBitmap) {
263        // get the delegate from the native int.
264        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
265        if (delegate == null) {
266            assert false;
267            return true;
268        }
269
270        return delegate.mHasAlpha;
271    }
272
273    /*package*/ static int nativeGetPixel(int nativeBitmap, int x, int y) {
274        // get the delegate from the native int.
275        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
276        if (delegate == null) {
277            assert false;
278            return 0;
279        }
280
281        return delegate.mImage.getRGB(x, y);
282    }
283
284    /*package*/ static void nativeGetPixels(int nativeBitmap, int[] pixels, int offset,
285            int stride, int x, int y, int width, int height) {
286        // FIXME implement native delegate
287        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGetPixels");
288    }
289
290
291    /*package*/ static void nativeSetPixel(int nativeBitmap, int x, int y, int color) {
292        // FIXME implement native delegate
293        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixel");
294    }
295
296    /*package*/ static void nativeSetPixels(int nativeBitmap, int[] colors, int offset,
297            int stride, int x, int y, int width, int height) {
298        // FIXME implement native delegate
299        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSetPixels");
300    }
301
302    /*package*/ static void nativeCopyPixelsToBuffer(int nativeBitmap, Buffer dst) {
303        // FIXME implement native delegate
304        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCopyPixelsToBuffer");
305    }
306
307    /*package*/ static void nativeCopyPixelsFromBuffer(int nb, Buffer src) {
308        // FIXME implement native delegate
309        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCopyPixelsFromBuffer");
310    }
311
312    /*package*/ static int nativeGenerationId(int nativeBitmap) {
313        // FIXME implement native delegate
314        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeGenerationId");
315    }
316
317    /*package*/ static Bitmap nativeCreateFromParcel(Parcel p) {
318        // FIXME implement native delegate
319        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeCreateFromParcel");
320    }
321
322    /*package*/ static boolean nativeWriteToParcel(int nativeBitmap, boolean isMutable,
323            int density, Parcel p) {
324        // FIXME implement native delegate
325        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeWriteToParcel");
326    }
327
328    /*package*/ static Bitmap nativeExtractAlpha(int nativeBitmap, int nativePaint,
329            int[] offsetXY) {
330        // FIXME implement native delegate
331        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeExtractAlpha");
332    }
333
334
335    /*package*/ static void nativePrepareToDraw(int nativeBitmap) {
336        // FIXME implement native delegate
337        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativePrepareToDraw");
338    }
339
340    /*package*/ static void nativeSetHasAlpha(int nativeBitmap, boolean hasAlpha) {
341        // get the delegate from the native int.
342        Bitmap_Delegate delegate = sManager.getDelegate(nativeBitmap);
343        if (delegate == null) {
344            assert false;
345            return;
346        }
347
348        delegate.mHasAlpha = hasAlpha;
349    }
350
351    /*package*/ static boolean nativeSameAs(int nb0, int nb1) {
352        // FIXME implement native delegate
353        throw new UnsupportedOperationException("Native delegate needed for Bitmap.nativeSameAs");
354    }
355
356    // ---- Private delegate/helper methods ----
357
358    private Bitmap_Delegate(BufferedImage image) {
359        mImage = image;
360    }
361
362    private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
363        // get its native_int
364        int nativeInt = sManager.addDelegate(delegate);
365
366        // and create/return a new Bitmap with it
367        return new Bitmap(nativeInt, isMutable, null /*ninePatchChunk*/, density);
368    }
369}
370