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 17 package com.google.android.test.handwritingime; 18 19 import static com.google.android.test.handwritingime.HandwritingIme.BOUNDS_INFO_EDITOR_BOUNDS; 20 import static com.google.android.test.handwritingime.HandwritingIme.BOUNDS_INFO_NONE; 21 import static com.google.android.test.handwritingime.HandwritingIme.BOUNDS_INFO_VISIBLE_LINE_BOUNDS; 22 23 import android.graphics.Canvas; 24 import android.graphics.Color; 25 import android.graphics.Matrix; 26 import android.graphics.Paint; 27 import android.graphics.RectF; 28 import android.view.View; 29 import android.view.inputmethod.CursorAnchorInfo; 30 import android.view.inputmethod.EditorBoundsInfo; 31 32 import androidx.annotation.Nullable; 33 34 import com.android.internal.graphics.ColorUtils; 35 36 import java.util.List; 37 38 public class BoundsInfoDrawHelper { 39 private static final Paint sPaint = new Paint(); 40 private static final int EDITOR_BOUNDS_COLOR = 41 ColorUtils.setAlphaComponent(Color.DKGRAY, 128); 42 private static final int HANDWRITING_BOUNDS_COLOR = 43 ColorUtils.setAlphaComponent(Color.BLUE, 128); 44 private static final int VISIBLE_LINE_BOUNDS_COLOR = 45 ColorUtils.setAlphaComponent(Color.MAGENTA, 128); 46 draw(Canvas canvas, View inkView, int boundsInfoMode, CursorAnchorInfo cursorAnchorInfo)47 public static void draw(Canvas canvas, View inkView, int boundsInfoMode, 48 CursorAnchorInfo cursorAnchorInfo) { 49 if (boundsInfoMode == BOUNDS_INFO_NONE || cursorAnchorInfo == null) { 50 return; 51 } 52 53 // The matrix in CursorAnchorInfo transforms the editor coordinates to on-screen 54 // coordinates. We then transform the matrix from the on-screen coordinates to the 55 // inkView's coordinates. So the result matrix transforms the editor coordinates 56 // to the inkView coordinates. 57 final Matrix matrix = cursorAnchorInfo.getMatrix(); 58 inkView.transformMatrixToLocal(matrix); 59 60 if ((boundsInfoMode & BOUNDS_INFO_EDITOR_BOUNDS) != 0) { 61 drawEditorBoundsInfo(canvas, matrix, cursorAnchorInfo.getEditorBoundsInfo()); 62 } 63 64 if ((boundsInfoMode & BOUNDS_INFO_VISIBLE_LINE_BOUNDS) != 0) { 65 drawVisibleLineBounds(canvas, matrix, cursorAnchorInfo.getVisibleLineBounds()); 66 } 67 } 68 setPaintForEditorBoundsInfo()69 private static void setPaintForEditorBoundsInfo() { 70 sPaint.reset(); 71 sPaint.setStyle(Paint.Style.STROKE); 72 sPaint.setStrokeWidth(5f); 73 } 74 drawEditorBoundsInfo(Canvas canvas, Matrix matrix, @Nullable EditorBoundsInfo editorBoundsInfo)75 private static void drawEditorBoundsInfo(Canvas canvas, Matrix matrix, 76 @Nullable EditorBoundsInfo editorBoundsInfo) { 77 if (editorBoundsInfo == null) { 78 return; 79 } 80 final RectF editorBounds = editorBoundsInfo.getEditorBounds(); 81 setPaintForEditorBoundsInfo(); 82 if (editorBounds != null) { 83 final RectF localEditorBounds = new RectF(editorBounds); 84 matrix.mapRect(localEditorBounds); 85 sPaint.setColor(EDITOR_BOUNDS_COLOR); 86 canvas.drawRect(localEditorBounds, sPaint); 87 } 88 89 final RectF handwritingBounds = editorBoundsInfo.getHandwritingBounds(); 90 if (handwritingBounds != null) { 91 final RectF localHandwritingBounds = new RectF(handwritingBounds); 92 matrix.mapRect(localHandwritingBounds); 93 sPaint.setColor(HANDWRITING_BOUNDS_COLOR); 94 canvas.drawRect(localHandwritingBounds, sPaint); 95 } 96 } 97 setPaintForVisibleLineBounds()98 private static void setPaintForVisibleLineBounds() { 99 sPaint.reset(); 100 sPaint.setStyle(Paint.Style.STROKE); 101 sPaint.setStrokeWidth(2f); 102 sPaint.setColor(VISIBLE_LINE_BOUNDS_COLOR); 103 } 104 drawVisibleLineBounds(Canvas canvas, Matrix matrix, List<RectF> visibleLineBounds)105 private static void drawVisibleLineBounds(Canvas canvas, Matrix matrix, 106 List<RectF> visibleLineBounds) { 107 if (visibleLineBounds.isEmpty()) { 108 return; 109 } 110 setPaintForVisibleLineBounds(); 111 for (RectF lineBound : visibleLineBounds) { 112 matrix.mapRect(lineBound); 113 canvas.drawRect(lineBound, sPaint); 114 } 115 } 116 } 117