package epson.scan.activity; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.DashPathEffect; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PathEffect; import android.graphics.Rect; import android.support.p000v4.view.GestureDetectorCompat; import android.text.TextPaint; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.View; import java.util.ArrayList; import java.util.Iterator; import epson.common.ImageUtil; import epson.print.R; public class I2ScanAreaView extends View { private static final int CONTOUR_AREA_BACK_COLOR = -1; private final int SCAN_AREA_CORNER_LENGTH_DP = 30; private final int SCAN_AREA_CORNER_LONG_TAP_AREA_WIDTH_DP = 60; private final int SCAN_AREA_CORNER_WIDTH_DP = 4; private final int SCAN_AREA_MOVE_MODE_AREA_MOVE = 3; private final int SCAN_AREA_MOVE_MODE_LEFT_UPPER = 1; private final int SCAN_AREA_MOVE_MODE_NONE = 0; private final int SCAN_AREA_MOVE_MODE_RIGHT_LOWER = 2; private ArrayList mBreakStrings; private float[] mDashInterval; private Rect mDisplayContourArea; private float mDisplayDensity; private Rect mDisplayMovableArea; private Rect mDisplayPreviewImageRect; private double mDisplayRate; private float mDisplayTextLeft; private ArrayList mDisplayTextYPosition; private FlickCallback mFlickCallback; private GestureDetectorCompat mGestureDetectorCompat; private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() { public boolean onDown(MotionEvent motionEvent) { return true; } public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent2, float f, float f2) { return true; } public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent2, float f, float f2) { I2ScanAreaView.this.checkFlick(f); return true; } public void onLongPress(MotionEvent motionEvent) { boolean unused = I2ScanAreaView.this.checkMoveMode(motionEvent.getX(), motionEvent.getY()); } }; private boolean mMovableAreaMode; private int mOrgContourHeight; private int mOrgContourWidth; private Rect mOrgMovableArea; private Rect mOrgPreviewImageRect; private Paint mPaint; private float mPhase; private float mPrevX; private float mPrevY; private Bitmap mPreviewImageBitmap; private String mPreviewImageFile; private int mPromptTextColor = -16776961; private boolean mPromptTextDisplay; private float mPromptTextSize = 10.0f; private Bitmap mScanAreaCenterBitmap; private int mScanAreaCornerLengthPixel; private int mScanAreaCornerLogTapAreaWidthPixel; private int mScanAreaCornerWidthPixel; private boolean mScanAreaModified; private int mScanAreaMoveMode; private final Path mScanAreaPath = new Path(); private String mScanPromptString; private TextPaint mTextPaint; interface FlickCallback { void flick(int i); } public boolean isScanAreaModified() { return mMovableAreaMode && mScanAreaModified; } public Rect getMovableScanArea() { return mOrgMovableArea; } public int[] getOrgContour() { return new int[]{mOrgContourWidth, mOrgContourHeight}; } public I2ScanAreaView(Context context) { super(context); init((AttributeSet) null, 0); } public I2ScanAreaView(Context context, AttributeSet attributeSet) { super(context, attributeSet); init(attributeSet, 0); } public I2ScanAreaView(Context context, AttributeSet attributeSet, int i) { super(context, attributeSet, i); init(attributeSet, i); } private void init(AttributeSet attributeSet, int i) { TypedArray obtainStyledAttributes = getContext().obtainStyledAttributes(attributeSet, R.styleable.I2ScanAreaView, i, 0); mScanPromptString = obtainStyledAttributes.getString(0); mPromptTextColor = obtainStyledAttributes.getColor(1, mPromptTextColor); mPromptTextSize = obtainStyledAttributes.getDimension(2, mPromptTextSize); obtainStyledAttributes.recycle(); mTextPaint = new TextPaint(); mTextPaint.setFlags(1); mTextPaint.setTextAlign(Paint.Align.LEFT); mPaint = new Paint(); mPromptTextDisplay = true; mScanAreaMoveMode = 0; float f = getResources().getDisplayMetrics().density; mScanAreaCornerLengthPixel = Math.round(30.0f * f); mScanAreaCornerWidthPixel = Math.round(4.0f * f); mScanAreaCornerLogTapAreaWidthPixel = Math.round(60.0f * f); mScanAreaCenterBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.area_center); mDashInterval = new float[]{10.0f * f, 2.0f * f}; mDisplayDensity = f; mScanAreaModified = false; mGestureDetectorCompat = new GestureDetectorCompat(getContext(), mGestureListener); invalidateTextPaintAndMeasurements(); } public void setFlickCallback(FlickCallback flickCallback) { mFlickCallback = flickCallback; } private void invalidateTextPaintAndMeasurements() { mTextPaint.setTextSize(mPromptTextSize); mTextPaint.setColor(mPromptTextColor); } protected void onSizeChanged(int i, int i2, int i3, int i4) { super.onSizeChanged(i, i2, i3, i4); calcDrawSize(i, i2); } private void calcDrawSize(int i, int i2) { if (i != 0 && i2 != 0 && mOrgContourWidth != 0 && mOrgContourHeight != 0) { int paddingLeft = (i - getPaddingLeft()) - getPaddingRight(); int paddingTop = (i2 - getPaddingTop()) - getPaddingBottom(); if (paddingLeft <= 0 || paddingTop <= 0) { mDisplayContourArea = null; return; } double max = Math.max((mOrgContourWidth) / (paddingLeft), (mOrgContourHeight) / (paddingTop)); mDisplayRate = max; int i3 = ((mOrgContourWidth) / max); int i4 = ((mOrgContourHeight) / max); mDisplayContourArea = new Rect(0, 0, i3, i4); mDisplayContourArea.offsetTo(getPaddingLeft() + ((paddingLeft - i3) / 2), getPaddingTop() + ((paddingTop - i4) / 2)); if (mMovableAreaMode) { Rect rect = mOrgMovableArea; if (rect != null) { mDisplayMovableArea = new Rect(Math.round((rect.left) / max), Math.round((mOrgMovableArea.top) / max), Math.round((mOrgMovableArea.right) / max), Math.round((mOrgMovableArea.bottom) / max)); mDisplayMovableArea.offset(mDisplayContourArea.left, mDisplayContourArea.top); } } else { mDisplayMovableArea = null; } Rect rect2 = mOrgPreviewImageRect; if (rect2 != null) { mDisplayPreviewImageRect = new Rect(Math.round((rect2.left) / max), Math.round((mOrgPreviewImageRect.top) / max), Math.round((mOrgPreviewImageRect.right) / max), Math.round((mOrgPreviewImageRect.bottom) / max)); if (!mMovableAreaMode) { mDisplayPreviewImageRect.offsetTo((mDisplayContourArea.width() - mDisplayPreviewImageRect.width()) / 2, 0); } mDisplayPreviewImageRect.offset(mDisplayContourArea.left, mDisplayContourArea.top); } readPreviewBitmap(); String str = mScanPromptString; if (str != null && !str.isEmpty()) { calcText(mDisplayContourArea); } } } private void calcText(Rect rect) { float width = ((float) rect.width()) * 0.9f; int length = mScanPromptString.length(); Rect rect2 = new Rect(); mBreakStrings = new ArrayList<>(); ArrayList arrayList = new ArrayList(); int i = 0; float f = 0.0f; while (i < length) { int breakText = mTextPaint.breakText(mScanPromptString.substring(i, length), true, width, (float[]) null); int i2 = i + breakText; String substring = mScanPromptString.substring(i, i2); mTextPaint.getTextBounds(substring, 0, breakText, rect2); f += (float) rect2.height(); arrayList.add(Float.valueOf((float) rect2.height())); mBreakStrings.add(substring); i = i2; } mDisplayTextLeft = ((float) rect.left) + (width * 0.050000012f); float height = ((float) rect.top) + ((((float) rect.height()) - f) / 2.0f); mDisplayTextYPosition = new ArrayList<>(); Iterator it = arrayList.iterator(); while (it.hasNext()) { mDisplayTextYPosition.add(Float.valueOf(height)); height += ((Float) it.next()).floatValue(); } } protected void onDraw(Canvas canvas) { ArrayList arrayList; super.onDraw(canvas); if (mDisplayContourArea != null) { mPaint.setColor(-1); mPaint.setStyle(Paint.Style.FILL); canvas.drawRect(mDisplayContourArea, mPaint); Bitmap bitmap = mPreviewImageBitmap; if (bitmap != null) { canvas.drawBitmap(bitmap, (Rect) null, mDisplayPreviewImageRect, mPaint); } if (mDisplayMovableArea != null) { drawScanArea(canvas); } if (mPromptTextDisplay && mScanPromptString != null && mPreviewImageBitmap == null && mBreakStrings != null && (arrayList = mDisplayTextYPosition) != null) { Iterator it = arrayList.iterator(); Iterator it2 = mBreakStrings.iterator(); while (it2.hasNext()) { String next = it2.next(); if (it.hasNext()) { canvas.drawText(next, mDisplayTextLeft, it.next().floatValue(), mTextPaint); } } } } } private void drawScanArea(Canvas canvas) { if (mDisplayMovableArea != null) { mPaint.setColor(ViewCompat.MEASURED_STATE_MASK); if (mScanAreaMoveMode == 3) { canvas.drawBitmap(mScanAreaCenterBitmap, (float) (mDisplayMovableArea.centerX() - (mScanAreaCenterBitmap.getWidth() / 2)), (float) (mDisplayMovableArea.centerY() - (mScanAreaCenterBitmap.getHeight() / 2)), mPaint); } mScanAreaPath.reset(); mScanAreaPath.moveTo((float) mDisplayMovableArea.left, (float) mDisplayMovableArea.top); mScanAreaPath.lineTo((float) mDisplayMovableArea.left, (float) mDisplayMovableArea.bottom); mScanAreaPath.lineTo((float) mDisplayMovableArea.right, (float) mDisplayMovableArea.bottom); mScanAreaPath.lineTo((float) mDisplayMovableArea.right, (float) mDisplayMovableArea.top); mScanAreaPath.close(); if (mScanAreaMoveMode > 0) { mPaint.setPathEffect(new DashPathEffect(mDashInterval, mPhase)); mPhase += mDisplayDensity; if (mPhase > 10000.0f) { mPhase = 0.0f; } postInvalidate(); } else { mPaint.setPathEffect((PathEffect) null); } mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(1.0f); canvas.drawPath(mScanAreaPath, mPaint); int i = mScanAreaCornerWidthPixel; int i2 = mScanAreaCornerLengthPixel; if (mScanAreaMoveMode == 1) { i *= 2; i2 *= 2; } mPaint.setStrokeWidth((float) i); mPaint.setPathEffect((PathEffect) null); mPaint.setStrokeCap(Paint.Cap.SQUARE); int i3 = i / 2; int i4 = mDisplayMovableArea.left - i3; int i5 = mDisplayMovableArea.top - i3; float f = (float) i4; float f2 = (float) i5; Canvas canvas2 = canvas; float f3 = f; float f4 = f2; canvas2.drawLine(f3, f4, (float) (i4 + i2), f2, mPaint); canvas2.drawLine(f3, f4, f, (float) (i5 + i2), mPaint); int i6 = mScanAreaCornerWidthPixel; int i7 = mScanAreaCornerLengthPixel; if (mScanAreaMoveMode == 2) { i6 *= 2; i7 *= 2; } mPaint.setStrokeWidth((float) i6); int i8 = i6 / 2; int i9 = mDisplayMovableArea.right + i8; int i10 = mDisplayMovableArea.bottom + i8; float f5 = (float) i9; float f6 = (float) i10; Canvas canvas3 = canvas; float f7 = f5; float f8 = f6; canvas3.drawLine(f7, f8, f5, (float) (i10 - i7), mPaint); canvas3.drawLine(f7, f8, (float) (i9 - i7), f6, mPaint); } } public boolean onTouchEvent(MotionEvent motionEvent) { if (mScanAreaMoveMode > 0) { if (checkTouchEvent(motionEvent) || super.onTouchEvent(motionEvent)) { return true; } return false; } else if (mGestureDetectorCompat.onTouchEvent(motionEvent) || super.onTouchEvent(motionEvent)) { return true; } else { return false; } } private boolean checkTouchEvent(MotionEvent motionEvent) { switch (motionEvent.getAction()) { case 0: return true; case 1: if (mScanAreaMoveMode <= 0) { return false; } mScanAreaMoveMode = 0; updateOrgScanArea(); postInvalidate(); return true; case 2: return moveScanArea(motionEvent.getX(), motionEvent.getY()); default: return false; } } private void updateOrgScanArea() { Rect rect = mDisplayMovableArea; if (rect != null) { Rect rect2 = mOrgMovableArea; rect2.left = 0; rect2.top = 0; rect2.right = Math.round(((rect.width() - 1)) * mDisplayRate); mOrgMovableArea.bottom = Math.round(((mDisplayMovableArea.height() - 1)) * mDisplayRate); mOrgMovableArea.offsetTo(Math.round(((mDisplayMovableArea.left - mDisplayContourArea.left)) * mDisplayRate), Math.round(((mDisplayMovableArea.top - mDisplayContourArea.top)) * mDisplayRate)); } } private boolean moveScanArea(float f, float f2) { if (mDisplayMovableArea == null) { return false; } int round = Math.round(f - mPrevX); int round2 = Math.round(f2 - mPrevY); switch (mScanAreaMoveMode) { case 1: mDisplayMovableArea.left += round; mDisplayMovableArea.top += round2; break; case 2: mDisplayMovableArea.right += round; mDisplayMovableArea.bottom += round2; break; case 3: mDisplayMovableArea.left += round; mDisplayMovableArea.top += round2; mDisplayMovableArea.right += round; mDisplayMovableArea.bottom += round2; break; default: return false; } if (mDisplayMovableArea.left > mDisplayMovableArea.right) { int i = mDisplayMovableArea.left; Rect rect = mDisplayMovableArea; rect.left = rect.right; mDisplayMovableArea.right = i; } if (mDisplayMovableArea.top > mDisplayMovableArea.bottom) { int i2 = mDisplayMovableArea.top; Rect rect2 = mDisplayMovableArea; rect2.top = rect2.bottom; mDisplayMovableArea.bottom = i2; } if (mDisplayMovableArea.left < 0) { mDisplayMovableArea.left = 0; } if (mDisplayMovableArea.top < 0) { mDisplayMovableArea.top = 0; } if (mDisplayMovableArea.right >= getWidth()) { mDisplayMovableArea.right = getWidth() - 1; } if (mDisplayMovableArea.bottom >= getHeight()) { mDisplayMovableArea.bottom = getHeight() - 1; } mPrevX = f; mPrevY = f2; postInvalidate(); return false; } public String getPromptString() { return mScanPromptString; } public void setPromptString(String str) { mScanPromptString = str; invalidateTextPaintAndMeasurements(); } public int getPromptTextColor() { return mPromptTextColor; } public void setPromptTextColor(int i) { mPromptTextColor = i; invalidateTextPaintAndMeasurements(); } public float getPromptTextSize() { return mPromptTextSize; } public void setPromptTextSize(float f) { mPromptTextSize = f; invalidateTextPaintAndMeasurements(); } public void setPromptStringVisibility(int i) { mPromptTextDisplay = i == 0; invalidate(); } public void setArea(int i, int i2) { mScanAreaModified = false; mOrgContourWidth = i; mOrgContourHeight = i2; mMovableAreaMode = false; calcDrawSize(getWidth(), getHeight()); } public void setMovableAreaModeSize(int i, int i2, Rect rect) { mScanAreaModified = false; mOrgContourWidth = i; mOrgContourHeight = i2; mMovableAreaMode = true; mOrgMovableArea = new Rect(rect); calcDrawSize(getWidth(), getHeight()); } public void setPreviewImage(String str, int[] iArr) { mPreviewImageFile = str; if (str == null || iArr == null || iArr.length < 4) { mOrgPreviewImageRect = null; mPreviewImageBitmap = null; } else { mOrgPreviewImageRect = new Rect(iArr[2], iArr[3], iArr[2] + iArr[0], iArr[3] + iArr[1]); } calcDrawSize(getWidth(), getHeight()); } public void setPreviewImage(String str) { mPreviewImageFile = str; if (mMovableAreaMode) { mOrgPreviewImageRect = new Rect(mOrgMovableArea); } else { mOrgPreviewImageRect = new Rect(0, 0, mOrgContourWidth, mOrgContourHeight); } calcDrawSize(getWidth(), getHeight()); } private void readPreviewBitmap() { String str = mPreviewImageFile; if (str == null) { mPreviewImageBitmap = null; } else { mPreviewImageBitmap = ImageUtil.loadBitmap(str, mDisplayPreviewImageRect.width(), mDisplayPreviewImageRect.height(), true, false); } } private void checkFlick(float f) { if (mFlickCallback != null) { float min = ((float) Math.min(getWidth(), getHeight())) * 0.1f; if (f < (-min)) { mFlickCallback.flick(1); } else if (f > min) { mFlickCallback.flick(-1); } } } private boolean checkMoveMode(float f, float f2) { Rect rect = mDisplayMovableArea; if (rect == null) { return false; } mPrevX = f; mPrevY = f2; if (Math.hypot((((float) rect.left) - f), (((float) mDisplayMovableArea.top) - f2)) < (mScanAreaCornerLogTapAreaWidthPixel)) { mScanAreaMoveMode = 1; } else if (Math.hypot((((float) mDisplayMovableArea.right) - f), (((float) mDisplayMovableArea.bottom) - f2)) < (mScanAreaCornerLogTapAreaWidthPixel)) { mScanAreaMoveMode = 2; } else if (f < ((float) mDisplayMovableArea.left) || f > ((float) mDisplayMovableArea.right) || f2 < ((float) mDisplayMovableArea.top) || f2 > ((float) mDisplayMovableArea.bottom)) { return false; } else { mScanAreaMoveMode = 3; } mScanAreaModified = true; postInvalidate(); return true; } }