1779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet/* 2779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * Copyright (C) 2011 The Android Open Source Project 3779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * 4779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * Licensed under the Apache License, Version 2.0 (the "License"); 5779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * you may not use this file except in compliance with the License. 6779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * You may obtain a copy of the License at 7779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * 8779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 9779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * 10779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * Unless required by applicable law or agreed to in writing, software 11779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 12779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * See the License for the specific language governing permissions and 14779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * limitations under the License. 15779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet */ 16779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 17779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetpackage android.graphics; 18779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 19779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetimport com.android.layoutlib.bridge.Bridge; 20779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetimport com.android.layoutlib.bridge.impl.DelegateManager; 21779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetimport com.android.ninepatch.NinePatchChunk; 22779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetimport com.android.resources.Density; 239a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohetimport com.android.tools.layoutlib.annotations.LayoutlibDelegate; 24779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 25d2f664d42cc29507b01a98622298b69131463825Xavier Ducrohetimport android.content.res.BridgeResources.NinePatchInputStream; 26779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetimport android.graphics.BitmapFactory.Options; 27779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 28779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetimport java.io.FileDescriptor; 29779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetimport java.io.IOException; 30779c906592b67867fee83a6527d474c333a701ffXavier Ducrohetimport java.io.InputStream; 31779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 32779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet/** 33779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * Delegate implementing the native methods of android.graphics.BitmapFactory 34779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * 35779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * Through the layoutlib_create tool, the original native methods of BitmapFactory have been 36779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * replaced by calls to methods of the same name in this delegate class. 37779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * 38779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} 39779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * around to map int to instance of the delegate. 40779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet * 41779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet */ 42779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet/*package*/ class BitmapFactory_Delegate { 43779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 4413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // ------ Java delegates ------ 4513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 469a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 4713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet /*package*/ static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) { 4813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (bm == null || opts == null) { 4913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return bm; 5013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 5113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 5213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet final int density = opts.inDensity; 5313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (density == 0) { 5413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return bm; 5513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 5613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 5713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet bm.setDensity(density); 5813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet final int targetDensity = opts.inTargetDensity; 5913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) { 6013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return bm; 6113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 6213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 6313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet byte[] np = bm.getNinePatchChunk(); 6413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np); 6513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // DELEGATE CHANGE: never scale 9-patch 6613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (opts.inScaled && isNinePatch == false) { 6713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet float scale = targetDensity / (float)density; 6813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // TODO: This is very inefficient and should be done in native by Skia 6913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet final Bitmap oldBitmap = bm; 7013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f), 7113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet (int) (bm.getHeight() * scale + 0.5f), true); 7213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet oldBitmap.recycle(); 7313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 7413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet if (isNinePatch) { 7513bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet np = nativeScaleNinePatch(np, scale, outPadding); 7613bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet bm.setNinePatchChunk(np); 7713bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 7813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet bm.setDensity(targetDensity); 7913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 8013bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 8113bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet return bm; 8213bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet } 8313bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 8413bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet 85779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet // ------ Native Delegates ------ 86779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 879a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 8822f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage, 8922f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet Rect padding, Options opts) { 9022f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet return nativeDecodeStream(is, storage, padding, opts, false, 1.f); 91779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 92779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 939a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 9422f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage, 9522f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet Rect padding, Options opts, boolean applyScale, float scale) { 96779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet Bitmap bm = null; 97779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 9822f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet //TODO support rescaling 9922f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet 100779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet Density density = Density.MEDIUM; 101779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet if (opts != null) { 102779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet density = Density.getEnum(opts.inDensity); 103779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 104779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 105779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet try { 106779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet if (is instanceof NinePatchInputStream) { 107779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet NinePatchInputStream npis = (NinePatchInputStream) is; 108779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet npis.disableFakeMarkSupport(); 109779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 110779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet // load the bitmap as a nine patch 111779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet com.android.ninepatch.NinePatch ninePatch = com.android.ninepatch.NinePatch.load( 112779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet npis, true /*is9Patch*/, false /*convert*/); 113779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 114779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet // get the bitmap and chunk objects. 115779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/, 116779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet density); 117779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet NinePatchChunk chunk = ninePatch.getChunk(); 118779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 119779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet // put the chunk in the bitmap 120779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk)); 121779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 122779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet // read the padding 123779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet int[] paddingarray = chunk.getPadding(); 124779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet padding.left = paddingarray[0]; 125779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet padding.top = paddingarray[1]; 126779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet padding.right = paddingarray[2]; 127779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet padding.bottom = paddingarray[3]; 128779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } else { 129779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet // load the bitmap directly. 130779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet bm = Bitmap_Delegate.createBitmap(is, true, density); 131779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 132779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } catch (IOException e) { 133779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet Bridge.getLog().error(null,"Failed to load image" , e, null); 134779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 135779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 136779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet return bm; 137779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 138779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 1399a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 140779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet /*package*/ static Bitmap nativeDecodeFileDescriptor(FileDescriptor fd, 141779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet Rect padding, Options opts) { 142779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet opts.inBitmap = null; 143779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet return null; 144779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 145779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 1469a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 147779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts) { 148779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet opts.inBitmap = null; 149779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet return null; 150779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 151779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 1529a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 15322f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts, 15422f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet boolean applyScale, float scale) { 15522f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet opts.inBitmap = null; 15622f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet return null; 15722f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet } 15822f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet 15922f700a1b8fb9d2ac7b261e30a46a040928c23bcXavier Ducrohet @LayoutlibDelegate 160779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset, 161779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet int length, Options opts) { 162779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet opts.inBitmap = null; 163779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet return null; 164779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 165779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 1669a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 167779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet /*package*/ static byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad) { 16813bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // don't scale for now. This should not be called anyway since we re-implement 16913bdc3355c781dc2614f2810a42d3a9e73f5bed9Xavier Ducrohet // BitmapFactory.finishDecode(); 170779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet return chunk; 171779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 172779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet 1739a4fe29c8d92014d2d9a848e9116b8cc9d0842f9Xavier Ducrohet @LayoutlibDelegate 174779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet /*package*/ static boolean nativeIsSeekable(FileDescriptor fd) { 175779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet return true; 176779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet } 177779c906592b67867fee83a6527d474c333a701ffXavier Ducrohet} 178