1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.datamodel.media; 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Bitmap; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Canvas; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Matrix; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Paint; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.RectF; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.media.ExifInterface; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.ImageUtils; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.FileNotFoundException; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.InputStream; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.List; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Requests a composite image resource. The composite image resource is constructed by first 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * sequentially requesting a number of sub image resources specified by 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * {@link CompositeImageRequestDescriptor#getChildRequestDescriptors()}. After this, the 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * individual sub images are composed into the final image onto their respective target rects 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * returned by {@link CompositeImageRequestDescriptor#getChildRequestTargetRects()}. 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class CompositeImageRequest<D extends CompositeImageRequestDescriptor> 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd extends ImageRequest<D> { 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final Bitmap mBitmap; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final Canvas mCanvas; 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final Paint mPaint; 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public CompositeImageRequest(final Context context, final D descriptor) { 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super(context, descriptor); 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mBitmap = getBitmapPool().createOrReuseBitmap( 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mDescriptor.desiredWidth, mDescriptor.desiredHeight); 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCanvas = new Canvas(mBitmap); 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected ImageResource loadMediaInternal(List<MediaRequest<ImageResource>> chainedTask) { 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<? extends ImageRequestDescriptor> descriptors = 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mDescriptor.getChildRequestDescriptors(); 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<RectF> targetRects = mDescriptor.getChildRequestTargetRects(); 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.equals(descriptors.size(), targetRects.size()); 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.isTrue(descriptors.size() > 1); 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0; i < descriptors.size(); i++) { 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final MediaRequest<ImageResource> request = 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd descriptors.get(i).buildSyncMediaRequest(mContext); 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Synchronously request the child image. 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ImageResource resource = 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MediaResourceManager.get().requestMediaResourceSync(request); 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (resource != null) { 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd try { 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final RectF avatarDestOnGroup = targetRects.get(i); 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Draw the bitmap into a smaller size with a circle mask. 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Bitmap resourceBitmap = resource.getBitmap(); 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final RectF resourceRect = new RectF( 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 0, 0, resourceBitmap.getWidth(), resourceBitmap.getHeight()); 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Bitmap smallCircleBitmap = getBitmapPool().createOrReuseBitmap( 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Math.round(avatarDestOnGroup.width()), 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Math.round(avatarDestOnGroup.height())); 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final RectF smallCircleRect = new RectF( 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 0, 0, smallCircleBitmap.getWidth(), smallCircleBitmap.getHeight()); 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Canvas smallCircleCanvas = new Canvas(smallCircleBitmap); 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ImageUtils.drawBitmapWithCircleOnCanvas(resource.getBitmap(), smallCircleCanvas, 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd resourceRect, smallCircleRect, null /* bitmapPaint */, 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd false /* fillBackground */, 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */, 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */); 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Matrix matrix = new Matrix(); 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd matrix.setRectToRect(smallCircleRect, avatarDestOnGroup, 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Matrix.ScaleToFit.FILL); 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mCanvas.drawBitmap(smallCircleBitmap, matrix, mPaint); 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } finally { 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd resource.release(); 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return new DecodedImageResource(getKey(), mBitmap, ExifInterface.ORIENTATION_NORMAL); 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public int getCacheId() { 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return BugleMediaCacheManager.AVATAR_IMAGE_CACHE; 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected InputStream getInputStreamForResource() throws FileNotFoundException { 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd throw new IllegalStateException("Composite image request doesn't support input stream!"); 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 110