content: /*
   * Copyright (C) 2016 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.google.android.cameraview;
  
  import android.os.Parcel;
  import android.os.Parcelable;
  
  import androidx.annotation.NonNull;
  import androidx.collection.SparseArrayCompat;
  
  /**
   * Immutable class for describing proportional relationship between width and height.
   */
  public class AspectRatio implements Comparable<AspectRatio>, Parcelable {
  
      private final static SparseArrayCompat<SparseArrayCompat<AspectRatio>> sCache
              = new SparseArrayCompat<>(16);
  
      private final int mX;
      private final int mY;
  
      /**
       * Returns an instance of {@link AspectRatio} specified by {@code x} and {@code y} values.
       * The values {@code x} and {@code} will be reduced by their greatest common divider.
       *
       * @param x The width
       * @param y The height
       * @return An instance of {@link AspectRatio}
       */
      public static AspectRatio of(int x, int y) {
          int gcd = gcd(x, y);
          x /= gcd;
          y /= gcd;
          SparseArrayCompat<AspectRatio> arrayX = sCache.get(x);
          if (arrayX == null) {
              AspectRatio ratio = new AspectRatio(x, y);
              arrayX = new SparseArrayCompat<>();
              arrayX.put(y, ratio);
              sCache.put(x, arrayX);
              return ratio;
          } else {
              AspectRatio ratio = arrayX.get(y);
              if (ratio == null) {
                  ratio = new AspectRatio(x, y);
                  arrayX.put(y, ratio);
              }
              return ratio;
          }
      }
  
      /**
       * Parse an {@link AspectRatio} from a {@link String} formatted like "4:3".
       *
       * @param s The string representation of the aspect ratio
       * @return The aspect ratio
       * @throws IllegalArgumentException when the format is incorrect.
       */
      public static AspectRatio parse(String s) {
          int position = s.indexOf(':');
          if (position == -1) {
              throw new IllegalArgumentException("Malformed aspect ratio: " + s);
          }
          try {
              int x = Integer.parseInt(s.substring(0, position));
              int y = Integer.parseInt(s.substring(position + 1));
              return AspectRatio.of(x, y);
          } catch (NumberFormatException e) {
              throw new IllegalArgumentException("Malformed aspect ratio: " + s, e);
          }
      }
  
      private AspectRatio(int x, int y) {
          mX = x;
          mY = y;
      }
  
      public int getX() {
          return mX;
      }
  
      public int getY() {
          return mY;
      }
  
      public boolean matches(Size size) {
          int gcd = gcd(size.getWidth(), size.getHeight());
          int x = size.getWidth() / gcd;
          int y = size.getHeight() / gcd;
          return mX == x && mY == y;
      }
  
      @Override
      public boolean equals(Object o) {
          if (o == null) {
              return false;
          }
          if (this == o) {
              return true;
          }
          if (o instanceof AspectRatio) {
              AspectRatio ratio = (AspectRatio) o;
              return mX == ratio.mX && mY == ratio.mY;
          }
          return false;
      }
  
      @Override
      public String toString() {
          return mX + ":" + mY;
      }
  
      public float toFloat() {
          return (float) mX / mY;
      }
  
      @Override
      public int hashCode() {
          // assuming most sizes are <2^16, doing a rotate will give us perfect hashing
          return mY ^ ((mX << (Integer.SIZE / 2)) | (mX >>> (Integer.SIZE / 2)));
      }
  
      @Override
      public int compareTo(@NonNull AspectRatio another) {
          if (equals(another)) {
              return 0;
          } else if (toFloat() - another.toFloat() > 0) {
              return 1;
          }
          return -1;
      }
  
      /**
       * @return The inverse of this {@link AspectRatio}.
       */
      public AspectRatio inverse() {
          //noinspection SuspiciousNameCombination
          return AspectRatio.of(mY, mX);
      }
  
      private static int gcd(int a, int b) {
          while (b != 0) {
              int c = b;
              b = a % b;
              a = c;
          }
          return a;
      }
  
      @Override
      public int describeContents() {
          return 0;
      }
  
      @Override
      public void writeToParcel(Parcel dest, int flags) {
          dest.writeInt(mX);
          dest.writeInt(mY);
      }
  
      public static final Parcelable.Creator<AspectRatio> CREATOR
              = new Parcelable.Creator<AspectRatio>() {
  
          @Override
          public AspectRatio createFromParcel(Parcel source) {
              int x = source.readInt();
              int y = source.readInt();
              return AspectRatio.of(x, y);
          }
  
          @Override
          public AspectRatio[] newArray(int size) {
              return new AspectRatio[size];
          }
      };
  
  
  
  
  }
  