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 package com.android.messaging.datamodel.media; 17 18 import android.content.Context; 19 import android.graphics.Bitmap; 20 import android.graphics.Canvas; 21 import android.graphics.Matrix; 22 import android.graphics.Paint; 23 import android.graphics.RectF; 24 import android.media.ExifInterface; 25 26 import com.android.messaging.util.Assert; 27 import com.android.messaging.util.ImageUtils; 28 29 import java.io.FileNotFoundException; 30 import java.io.InputStream; 31 import java.util.List; 32 33 /** 34 * Requests a composite image resource. The composite image resource is constructed by first 35 * sequentially requesting a number of sub image resources specified by 36 * {@link CompositeImageRequestDescriptor#getChildRequestDescriptors()}. After this, the 37 * individual sub images are composed into the final image onto their respective target rects 38 * returned by {@link CompositeImageRequestDescriptor#getChildRequestTargetRects()}. 39 */ 40 public class CompositeImageRequest<D extends CompositeImageRequestDescriptor> 41 extends ImageRequest<D> { 42 private final Bitmap mBitmap; 43 private final Canvas mCanvas; 44 private final Paint mPaint; 45 46 public CompositeImageRequest(final Context context, final D descriptor) { 47 super(context, descriptor); 48 mBitmap = getBitmapPool().createOrReuseBitmap( 49 mDescriptor.desiredWidth, mDescriptor.desiredHeight); 50 mCanvas = new Canvas(mBitmap); 51 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 52 } 53 54 @Override 55 protected ImageResource loadMediaInternal(List<MediaRequest<ImageResource>> chainedTask) { 56 final List<? extends ImageRequestDescriptor> descriptors = 57 mDescriptor.getChildRequestDescriptors(); 58 final List<RectF> targetRects = mDescriptor.getChildRequestTargetRects(); 59 Assert.equals(descriptors.size(), targetRects.size()); 60 Assert.isTrue(descriptors.size() > 1); 61 62 for (int i = 0; i < descriptors.size(); i++) { 63 final MediaRequest<ImageResource> request = 64 descriptors.get(i).buildSyncMediaRequest(mContext); 65 // Synchronously request the child image. 66 final ImageResource resource = 67 MediaResourceManager.get().requestMediaResourceSync(request); 68 if (resource != null) { 69 try { 70 final RectF avatarDestOnGroup = targetRects.get(i); 71 72 // Draw the bitmap into a smaller size with a circle mask. 73 final Bitmap resourceBitmap = resource.getBitmap(); 74 final RectF resourceRect = new RectF( 75 0, 0, resourceBitmap.getWidth(), resourceBitmap.getHeight()); 76 final Bitmap smallCircleBitmap = getBitmapPool().createOrReuseBitmap( 77 Math.round(avatarDestOnGroup.width()), 78 Math.round(avatarDestOnGroup.height())); 79 final RectF smallCircleRect = new RectF( 80 0, 0, smallCircleBitmap.getWidth(), smallCircleBitmap.getHeight()); 81 final Canvas smallCircleCanvas = new Canvas(smallCircleBitmap); 82 ImageUtils.drawBitmapWithCircleOnCanvas(resource.getBitmap(), smallCircleCanvas, 83 resourceRect, smallCircleRect, null /* bitmapPaint */, 84 false /* fillBackground */, 85 ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */, 86 ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */); 87 final Matrix matrix = new Matrix(); 88 matrix.setRectToRect(smallCircleRect, avatarDestOnGroup, 89 Matrix.ScaleToFit.FILL); 90 mCanvas.drawBitmap(smallCircleBitmap, matrix, mPaint); 91 } finally { 92 resource.release(); 93 } 94 } 95 } 96 97 return new DecodedImageResource(getKey(), mBitmap, ExifInterface.ORIENTATION_NORMAL); 98 } 99 100 @Override 101 public int getCacheId() { 102 return BugleMediaCacheManager.AVATAR_IMAGE_CACHE; 103 } 104 105 @Override 106 protected InputStream getInputStreamForResource() throws FileNotFoundException { 107 throw new IllegalStateException("Composite image request doesn't support input stream!"); 108 } 109 } 110