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