Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2011 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 | |
| 17 | package android.graphics; |
| 18 | |
| 19 | import com.android.layoutlib.bridge.Bridge; |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 20 | import com.android.layoutlib.bridge.impl.DelegateManager; |
| 21 | import com.android.ninepatch.NinePatchChunk; |
| 22 | import com.android.resources.Density; |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 23 | import com.android.tools.layoutlib.annotations.LayoutlibDelegate; |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 24 | |
Xavier Ducrohet | d2f664d | 2011-07-29 17:41:39 -0700 | [diff] [blame] | 25 | import android.content.res.BridgeResources.NinePatchInputStream; |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 26 | import android.graphics.BitmapFactory.Options; |
| 27 | |
| 28 | import java.io.FileDescriptor; |
| 29 | import java.io.IOException; |
| 30 | import java.io.InputStream; |
| 31 | |
| 32 | /** |
| 33 | * Delegate implementing the native methods of android.graphics.BitmapFactory |
| 34 | * |
| 35 | * Through the layoutlib_create tool, the original native methods of BitmapFactory have been |
| 36 | * replaced by calls to methods of the same name in this delegate class. |
| 37 | * |
| 38 | * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} |
| 39 | * around to map int to instance of the delegate. |
| 40 | * |
| 41 | */ |
| 42 | /*package*/ class BitmapFactory_Delegate { |
| 43 | |
Xavier Ducrohet | 13bdc33 | 2011-02-06 10:58:16 -0800 | [diff] [blame] | 44 | // ------ Java delegates ------ |
| 45 | |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 46 | @LayoutlibDelegate |
Xavier Ducrohet | 13bdc33 | 2011-02-06 10:58:16 -0800 | [diff] [blame] | 47 | /*package*/ static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) { |
| 48 | if (bm == null || opts == null) { |
| 49 | return bm; |
| 50 | } |
| 51 | |
| 52 | final int density = opts.inDensity; |
| 53 | if (density == 0) { |
| 54 | return bm; |
| 55 | } |
| 56 | |
| 57 | bm.setDensity(density); |
| 58 | final int targetDensity = opts.inTargetDensity; |
| 59 | if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) { |
| 60 | return bm; |
| 61 | } |
| 62 | |
| 63 | byte[] np = bm.getNinePatchChunk(); |
| 64 | final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np); |
| 65 | // DELEGATE CHANGE: never scale 9-patch |
| 66 | if (opts.inScaled && isNinePatch == false) { |
| 67 | float scale = targetDensity / (float)density; |
| 68 | // TODO: This is very inefficient and should be done in native by Skia |
| 69 | final Bitmap oldBitmap = bm; |
| 70 | bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f), |
| 71 | (int) (bm.getHeight() * scale + 0.5f), true); |
| 72 | oldBitmap.recycle(); |
| 73 | |
| 74 | if (isNinePatch) { |
| 75 | np = nativeScaleNinePatch(np, scale, outPadding); |
| 76 | bm.setNinePatchChunk(np); |
| 77 | } |
| 78 | bm.setDensity(targetDensity); |
| 79 | } |
| 80 | |
| 81 | return bm; |
| 82 | } |
| 83 | |
| 84 | |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 85 | // ------ Native Delegates ------ |
| 86 | |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 87 | @LayoutlibDelegate |
Xavier Ducrohet | 22f700a | 2012-03-23 16:07:23 -0700 | [diff] [blame] | 88 | /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage, |
| 89 | Rect padding, Options opts) { |
| 90 | return nativeDecodeStream(is, storage, padding, opts, false, 1.f); |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 91 | } |
| 92 | |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 93 | @LayoutlibDelegate |
Xavier Ducrohet | 22f700a | 2012-03-23 16:07:23 -0700 | [diff] [blame] | 94 | /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage, |
| 95 | Rect padding, Options opts, boolean applyScale, float scale) { |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 96 | Bitmap bm = null; |
| 97 | |
Xavier Ducrohet | 22f700a | 2012-03-23 16:07:23 -0700 | [diff] [blame] | 98 | //TODO support rescaling |
| 99 | |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 100 | Density density = Density.MEDIUM; |
| 101 | if (opts != null) { |
| 102 | density = Density.getEnum(opts.inDensity); |
| 103 | } |
| 104 | |
| 105 | try { |
| 106 | if (is instanceof NinePatchInputStream) { |
| 107 | NinePatchInputStream npis = (NinePatchInputStream) is; |
| 108 | npis.disableFakeMarkSupport(); |
| 109 | |
| 110 | // load the bitmap as a nine patch |
| 111 | com.android.ninepatch.NinePatch ninePatch = com.android.ninepatch.NinePatch.load( |
| 112 | npis, true /*is9Patch*/, false /*convert*/); |
| 113 | |
| 114 | // get the bitmap and chunk objects. |
| 115 | bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/, |
| 116 | density); |
| 117 | NinePatchChunk chunk = ninePatch.getChunk(); |
| 118 | |
| 119 | // put the chunk in the bitmap |
| 120 | bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk)); |
| 121 | |
| 122 | // read the padding |
| 123 | int[] paddingarray = chunk.getPadding(); |
| 124 | padding.left = paddingarray[0]; |
| 125 | padding.top = paddingarray[1]; |
| 126 | padding.right = paddingarray[2]; |
| 127 | padding.bottom = paddingarray[3]; |
| 128 | } else { |
| 129 | // load the bitmap directly. |
| 130 | bm = Bitmap_Delegate.createBitmap(is, true, density); |
| 131 | } |
| 132 | } catch (IOException e) { |
| 133 | Bridge.getLog().error(null,"Failed to load image" , e, null); |
| 134 | } |
| 135 | |
| 136 | return bm; |
| 137 | } |
| 138 | |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 139 | @LayoutlibDelegate |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 140 | /*package*/ static Bitmap nativeDecodeFileDescriptor(FileDescriptor fd, |
| 141 | Rect padding, Options opts) { |
| 142 | opts.inBitmap = null; |
| 143 | return null; |
| 144 | } |
| 145 | |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 146 | @LayoutlibDelegate |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 147 | /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts) { |
| 148 | opts.inBitmap = null; |
| 149 | return null; |
| 150 | } |
| 151 | |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 152 | @LayoutlibDelegate |
Xavier Ducrohet | 22f700a | 2012-03-23 16:07:23 -0700 | [diff] [blame] | 153 | /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts, |
| 154 | boolean applyScale, float scale) { |
| 155 | opts.inBitmap = null; |
| 156 | return null; |
| 157 | } |
| 158 | |
| 159 | @LayoutlibDelegate |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 160 | /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset, |
| 161 | int length, Options opts) { |
| 162 | opts.inBitmap = null; |
| 163 | return null; |
| 164 | } |
| 165 | |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 166 | @LayoutlibDelegate |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 167 | /*package*/ static byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad) { |
Xavier Ducrohet | 13bdc33 | 2011-02-06 10:58:16 -0800 | [diff] [blame] | 168 | // don't scale for now. This should not be called anyway since we re-implement |
| 169 | // BitmapFactory.finishDecode(); |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 170 | return chunk; |
| 171 | } |
| 172 | |
Xavier Ducrohet | 9a4fe29 | 2011-02-09 17:17:49 -0800 | [diff] [blame] | 173 | @LayoutlibDelegate |
Xavier Ducrohet | 779c906 | 2011-02-04 16:40:49 -0800 | [diff] [blame] | 174 | /*package*/ static boolean nativeIsSeekable(FileDescriptor fd) { |
| 175 | return true; |
| 176 | } |
| 177 | } |