Home | History | Annotate | Download | only in graphics
      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;
     20 import com.android.layoutlib.bridge.impl.DelegateManager;
     21 import com.android.ninepatch.NinePatchChunk;
     22 import com.android.resources.Density;
     23 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
     24 
     25 import android.content.res.BridgeResources.NinePatchInputStream;
     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 
     44     // ------ Java delegates ------
     45 
     46     @LayoutlibDelegate
     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 
     85     // ------ Native Delegates ------
     86 
     87     @LayoutlibDelegate
     88     /*package*/ static void nativeSetDefaultConfig(int nativeConfig) {
     89         // pass
     90     }
     91 
     92     @LayoutlibDelegate
     93     /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage,
     94             Rect padding, Options opts) {
     95         Bitmap bm = null;
     96 
     97         Density density = Density.MEDIUM;
     98         if (opts != null) {
     99             density = Density.getEnum(opts.inDensity);
    100         }
    101 
    102         try {
    103             if (is instanceof NinePatchInputStream) {
    104                 NinePatchInputStream npis = (NinePatchInputStream) is;
    105                 npis.disableFakeMarkSupport();
    106 
    107                 // load the bitmap as a nine patch
    108                 com.android.ninepatch.NinePatch ninePatch = com.android.ninepatch.NinePatch.load(
    109                         npis, true /*is9Patch*/, false /*convert*/);
    110 
    111                 // get the bitmap and chunk objects.
    112                 bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
    113                         density);
    114                 NinePatchChunk chunk = ninePatch.getChunk();
    115 
    116                 // put the chunk in the bitmap
    117                 bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
    118 
    119                 // read the padding
    120                 int[] paddingarray = chunk.getPadding();
    121                 padding.left = paddingarray[0];
    122                 padding.top = paddingarray[1];
    123                 padding.right = paddingarray[2];
    124                 padding.bottom = paddingarray[3];
    125             } else {
    126                 // load the bitmap directly.
    127                 bm = Bitmap_Delegate.createBitmap(is, true, density);
    128             }
    129         } catch (IOException e) {
    130             Bridge.getLog().error(null,"Failed to load image" , e, null);
    131         }
    132 
    133         return bm;
    134     }
    135 
    136     @LayoutlibDelegate
    137     /*package*/ static Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
    138             Rect padding, Options opts) {
    139         opts.inBitmap = null;
    140         return null;
    141     }
    142 
    143     @LayoutlibDelegate
    144     /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts) {
    145         opts.inBitmap = null;
    146         return null;
    147     }
    148 
    149     @LayoutlibDelegate
    150     /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset,
    151             int length, Options opts) {
    152         opts.inBitmap = null;
    153         return null;
    154     }
    155 
    156     @LayoutlibDelegate
    157     /*package*/ static byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad) {
    158         // don't scale for now. This should not be called anyway since we re-implement
    159         // BitmapFactory.finishDecode();
    160         return chunk;
    161     }
    162 
    163     @LayoutlibDelegate
    164     /*package*/ static boolean nativeIsSeekable(FileDescriptor fd) {
    165         return true;
    166     }
    167 }
    168