content: package com.alimert.passportreader.mlkit.other;
  
  import android.content.Context;
  import android.graphics.Canvas;
  import android.util.AttributeSet;
  import android.view.View;
  
  import com.google.android.gms.vision.CameraSource;
  
  import java.util.HashSet;
  import java.util.Set;
  
  public class GraphicOverlay extends View {
      private final Object lock = new Object();
      private int previewWidth;
      private float widthScaleFactor = 1.0f;
      private int previewHeight;
      private float heightScaleFactor = 1.0f;
      private int facing = CameraSource.CAMERA_FACING_BACK;
      private Set<Graphic> graphics = new HashSet<>();
  
      /**
       * Base class for a custom graphics object to be rendered within the graphic overlay. Subclass
       * this and implement the {@link Graphic#draw(Canvas)} method to define the graphics element. Add
       * instances to the overlay using {@link GraphicOverlay#add(Graphic)}.
       */
      public abstract static class Graphic {
          private GraphicOverlay overlay;
  
          public Graphic(GraphicOverlay overlay) {
              this.overlay = overlay;
          }
  
          /**
           * Draw the graphic on the supplied canvas. Drawing should use the following methods to convert
           * to view coordinates for the graphics that are drawn:
           *
           * <ol>
           *   <li>{@link Graphic#scaleX(float)} and {@link Graphic#scaleY(float)} adjust the size of the
           *       supplied value from the preview scale to the view scale.
           *   <li>{@link Graphic#translateX(float)} and {@link Graphic#translateY(float)} adjust the
           *       coordinate from the preview's coordinate system to the view coordinate system.
           * </ol>
           *
           * @param canvas drawing canvas
           */
          public abstract void draw(Canvas canvas);
  
          /**
           * Adjusts a horizontal value of the supplied value from the preview scale to the view scale.
           */
          public float scaleX(float horizontal) {
              return horizontal * overlay.widthScaleFactor;
          }
  
          /** Adjusts a vertical value of the supplied value from the preview scale to the view scale. */
          public float scaleY(float vertical) {
              return vertical * overlay.heightScaleFactor;
          }
  
          /** Returns the application context of the app. */
          public Context getApplicationContext() {
              return overlay.getContext().getApplicationContext();
          }
  
          /**
           * Adjusts the x coordinate from the preview's coordinate system to the view coordinate system.
           */
          public float translateX(float x) {
              if (overlay.facing == CameraSource.CAMERA_FACING_FRONT) {
                  return overlay.getWidth() - scaleX(x);
              } else {
                  return scaleX(x);
              }
          }
  
          /**
           * Adjusts the y coordinate from the preview's coordinate system to the view coordinate system.
           */
          public float translateY(float y) {
              return scaleY(y);
          }
  
          public void postInvalidate() {
              overlay.postInvalidate();
          }
      }
  
      public GraphicOverlay(Context context, AttributeSet attrs) {
          super(context, attrs);
      }
  
      /** Removes all graphics from the overlay. */
      public void clear() {
          synchronized (lock) {
              graphics.clear();
          }
          postInvalidate();
      }
  
      /** Adds a graphic to the overlay. */
      public void add(Graphic graphic) {
          synchronized (lock) {
              graphics.add(graphic);
          }
          postInvalidate();
      }
  
      /** Removes a graphic from the overlay. */
      public void remove(Graphic graphic) {
          synchronized (lock) {
              graphics.remove(graphic);
          }
          postInvalidate();
      }
  
      /**
       * Sets the camera attributes for size and facing direction, which informs how to transform image
       * coordinates later.
       */
      public void setCameraInfo(int previewWidth, int previewHeight, int facing) {
          synchronized (lock) {
              this.previewWidth = previewWidth;
              this.previewHeight = previewHeight;
              this.facing = facing;
          }
          postInvalidate();
      }
  
      /** Draws the overlay with its associated graphic objects. */
      @Override
      protected void onDraw(Canvas canvas) {
          super.onDraw(canvas);
  
          synchronized (lock) {
              if ((previewWidth != 0) && (previewHeight != 0)) {
                  widthScaleFactor = (float) canvas.getWidth() / (float) previewWidth;
                  heightScaleFactor = (float) canvas.getHeight() / (float) previewHeight;
              }
  
              for (Graphic graphic : graphics) {
                  graphic.draw(canvas);
              }
          }
      }
  }
  