| /* |
| * 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<? extends ImageRequestDescriptor> descriptors, |
| final int desiredWidth, final int desiredHeight) { |
| super(descriptors, desiredWidth, desiredHeight); |
| Assert.isTrue(descriptors.size() <= MAX_GROUP_SIZE); |
| } |
| |
| private static List<? extends ImageRequestDescriptor> convertToDescriptor(final Uri uri, |
| final int desiredWidth, final int desiredHeight) { |
| final List<String> participantUriStrings = AvatarUriUtil.getGroupParticipantUris(uri); |
| final List<AvatarRequestDescriptor> avatarDescriptors = |
| new ArrayList<AvatarRequestDescriptor>(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<AvatarGroupRequestDescriptor>(context, this); |
| } |
| |
| @Override |
| public List<RectF> 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; |
| } |
| } |