1 /* 2 * Copyright (C) 2023 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.wallpaper.picker.preview.ui.util 17 18 import android.graphics.Point 19 import android.graphics.PointF 20 import android.graphics.Rect 21 import kotlin.math.abs 22 23 /** Util for calculating cropping related size. */ 24 object CropSizeUtil { 25 26 /** 27 * Finds largest possible rectangle in [Rect] with the same aspect ratio in the target 28 * rectangle. 29 * 30 * See [findMaxRectWithRatioIn]. 31 */ Rectnull32 fun Rect.findMaxRectWithRatioIn(rect: Rect): PointF = 33 Point(width(), height()).findMaxRectWithRatioIn(Point(rect.width(), rect.height())) 34 35 /** 36 * Finds largest possible rectangle in [Point] with the same aspect ratio in the target 37 * rectangle. 38 * 39 * Calling rectangle will scale up or down to match the size of the target rectangle, the final 40 * rectangle size is the largest but not exceeding the size of target rectangle. 41 */ 42 fun Point.findMaxRectWithRatioIn(point: Point): PointF { 43 val ratio = 44 if (x <= point.x && y <= point.y) { 45 // Target rect is containing the calling rect 46 if (abs(x - point.x) <= abs(y - point.y)) { 47 point.x.toFloat() / x 48 } else { 49 point.y.toFloat() / y 50 } 51 } else if (x > point.x && y > point.y) { 52 // Calling rect is containing the target rect 53 if (abs(x - point.x) >= abs(y - point.y)) { 54 point.x.toFloat() / x 55 } else { 56 point.y.toFloat() / y 57 } 58 } else { 59 // Target rect and calling rect overlap 60 if (x > point.x) { 61 point.x.toFloat() / x 62 } else { 63 point.y.toFloat() / y 64 } 65 } 66 67 return PointF(x * ratio, y * ratio) 68 } 69 fitCropRectToLayoutDirectionnull70 fun fitCropRectToLayoutDirection( 71 cropRect: Rect, 72 displaySize: Point, 73 isRtl: Boolean, 74 ): Rect { 75 val parallax = cropRect.width() - displaySize.x * cropRect.height() / displaySize.y 76 return Rect(cropRect).apply { if (isRtl) left += parallax else right -= parallax } 77 } 78 } 79