1 /* 2 * Copyright (C) 2015 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 com.android.messaging.ui; 18 19 import android.content.res.Resources; 20 import android.graphics.Bitmap; 21 import android.graphics.Canvas; 22 import android.graphics.Matrix; 23 import android.graphics.Rect; 24 import android.graphics.RectF; 25 import android.graphics.drawable.BitmapDrawable; 26 import android.view.Gravity; 27 28 import com.android.messaging.util.exif.ExifInterface; 29 30 /** 31 * A drawable that draws a bitmap in a flipped or rotated orientation without having to adjust the 32 * bitmap 33 */ 34 public class OrientedBitmapDrawable extends BitmapDrawable { 35 private final ExifInterface.OrientationParams mOrientationParams; 36 private final Rect mDstRect; 37 private int mCenterX; 38 private int mCenterY; 39 private boolean mApplyGravity; 40 create(final int orientation, Resources res, Bitmap bitmap)41 public static BitmapDrawable create(final int orientation, Resources res, Bitmap bitmap) { 42 if (orientation <= ExifInterface.Orientation.TOP_LEFT) { 43 // No need to adjust the bitmap, so just use a regular BitmapDrawable 44 return new BitmapDrawable(res, bitmap); 45 } else { 46 // Create an oriented bitmap drawable 47 return new OrientedBitmapDrawable(orientation, res, bitmap); 48 } 49 } 50 OrientedBitmapDrawable(final int orientation, Resources res, Bitmap bitmap)51 private OrientedBitmapDrawable(final int orientation, Resources res, Bitmap bitmap) { 52 super(res, bitmap); 53 mOrientationParams = ExifInterface.getOrientationParams(orientation); 54 mApplyGravity = true; 55 mDstRect = new Rect(); 56 } 57 58 @Override getIntrinsicWidth()59 public int getIntrinsicWidth() { 60 if (mOrientationParams.invertDimensions) { 61 return super.getIntrinsicHeight(); 62 } 63 return super.getIntrinsicWidth(); 64 } 65 66 @Override getIntrinsicHeight()67 public int getIntrinsicHeight() { 68 if (mOrientationParams.invertDimensions) { 69 return super.getIntrinsicWidth(); 70 } 71 return super.getIntrinsicHeight(); 72 } 73 74 @Override onBoundsChange(Rect bounds)75 protected void onBoundsChange(Rect bounds) { 76 super.onBoundsChange(bounds); 77 mApplyGravity = true; 78 } 79 80 @Override draw(Canvas canvas)81 public void draw(Canvas canvas) { 82 if (mApplyGravity) { 83 Gravity.apply(getGravity(), getIntrinsicWidth(), getIntrinsicHeight(), getBounds(), 84 mDstRect); 85 mCenterX = mDstRect.centerX(); 86 mCenterY = mDstRect.centerY(); 87 if (mOrientationParams.invertDimensions) { 88 final Matrix matrix = new Matrix(); 89 matrix.setRotate(mOrientationParams.rotation, mCenterX, mCenterY); 90 final RectF rotatedRect = new RectF(mDstRect); 91 matrix.mapRect(rotatedRect); 92 mDstRect.set((int) rotatedRect.left, (int) rotatedRect.top, (int) rotatedRect.right, 93 (int) rotatedRect.bottom); 94 } 95 96 mApplyGravity = false; 97 } 98 canvas.save(); 99 canvas.scale(mOrientationParams.scaleX, mOrientationParams.scaleY, mCenterX, mCenterY); 100 canvas.rotate(mOrientationParams.rotation, mCenterX, mCenterY); 101 canvas.drawBitmap(getBitmap(), (Rect) null, mDstRect, getPaint()); 102 canvas.restore(); 103 } 104 } 105