/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.messaging.datamodel.media; import android.content.Context; import android.graphics.RectF; import android.net.Uri; import com.android.messaging.util.Assert; import com.android.messaging.util.AvatarUriUtil; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class AvatarGroupRequestDescriptor extends CompositeImageRequestDescriptor { private static final int MAX_GROUP_SIZE = 4; public AvatarGroupRequestDescriptor(final Uri uri, final int desiredWidth, final int desiredHeight) { this(convertToDescriptor(uri, desiredWidth, desiredHeight), desiredWidth, desiredHeight); } public AvatarGroupRequestDescriptor(final List descriptors, final int desiredWidth, final int desiredHeight) { super(descriptors, desiredWidth, desiredHeight); Assert.isTrue(descriptors.size() <= MAX_GROUP_SIZE); } private static List convertToDescriptor(final Uri uri, final int desiredWidth, final int desiredHeight) { final List participantUriStrings = AvatarUriUtil.getGroupParticipantUris(uri); final List avatarDescriptors = new ArrayList(participantUriStrings.size()); for (final String uriString : participantUriStrings) { final AvatarRequestDescriptor descriptor = new AvatarRequestDescriptor( Uri.parse(uriString), desiredWidth, desiredHeight); avatarDescriptors.add(descriptor); } return avatarDescriptors; } @Override public CompositeImageRequest buildBatchImageRequest(final Context context) { return new CompositeImageRequest(context, this); } @Override public List getChildRequestTargetRects() { return Arrays.asList(generateDestRectArray()); } /** * Generates an array of {@link RectF} which represents where each of the individual avatar * should be located in the final group avatar image. The location of each avatar depends on * the size of the group and the size of the overall group avatar size. */ private RectF[] generateDestRectArray() { final int groupSize = mDescriptors.size(); final float width = desiredWidth; final float height = desiredHeight; final float halfWidth = width / 2F; final float halfHeight = height / 2F; final RectF[] destArray = new RectF[groupSize]; switch (groupSize) { case 2: /** * +-------+ * | 0 | | * +-------+ * | | 1 | * +-------+ * * We want two circles which touches in the center. To get this we know that the * diagonal of the overall group avatar is squareRoot(2) * w We also know that the * two circles touches the at the center of the overall group avatar and the * distance from the center of the circle to the corner of the group avatar is * radius * squareRoot(2). Therefore, the following emerges. * * w * squareRoot(2) = 2 (radius + radius * squareRoot(2)) * Solving for radius we get: * d = 2 * radius = ( squareRoot(2) / (squareRoot(2) + 1)) * w * d = (2 - squareRoot(2)) * w */ final float diameter = (float) ((2 - Math.sqrt(2)) * width); destArray[0] = new RectF(0, 0, diameter, diameter); destArray[1] = new RectF(width - diameter, height - diameter, width, height); break; case 3: /** * +-------+ * | | 0 | | * +-------+ * | 1 | 2 | * +-------+ * i0 * |\ * a | \ c * --- i2 * b * * a = radius * squareRoot(3) due to the triangle being a 30-60-90 right triangle. * b = radius of circle * c = 2 * radius of circle * * All three of the images are circles and therefore image zero will not touch * image one or image two. Move image zero down so it touches image one and image * two. This can be done by keeping image zero in the center and moving it down * slightly. The amount to move down can be calculated by solving a right triangle. * We know that the center x of image two to the center x of image zero is the * radius of the circle, this is the length of edge b. Also we know that the * distance from image zero to image two's center is 2 * radius, edge c. From this * we know that the distance from center y of image two to center y of image one, * edge a, is equal to radius * squareRoot(3) due to this triangle being a 30-60-90 * right triangle. */ final float quarterWidth = width / 4F; final float threeQuarterWidth = 3 * quarterWidth; final float radius = height / 4F; final float imageTwoCenterY = height - radius; final float lengthOfEdgeA = (float) (radius * Math.sqrt(3)); final float imageZeroCenterY = imageTwoCenterY - lengthOfEdgeA; final float imageZeroTop = imageZeroCenterY - radius; final float imageZeroBottom = imageZeroCenterY + radius; destArray[0] = new RectF( quarterWidth, imageZeroTop, threeQuarterWidth, imageZeroBottom); destArray[1] = new RectF(0, halfHeight, halfWidth, height); destArray[2] = new RectF(halfWidth, halfHeight, width, height); break; default: /** * +-------+ * | 0 | 1 | * +-------+ * | 2 | 3 | * +-------+ */ destArray[0] = new RectF(0, 0, halfWidth, halfHeight); destArray[1] = new RectF(halfWidth, 0, width, halfHeight); destArray[2] = new RectF(0, halfHeight, halfWidth, height); destArray[3] = new RectF(halfWidth, halfHeight, width, height); break; } return destArray; } }