RoundedLine.java revision e14df775d454cb96b751cf7668df71ce5873930d
1f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka/* 2f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * Copyright (C) 2012 The Android Open Source Project 3f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * 4f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * in compliance with the License. You may obtain a copy of the License at 6f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * 7f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 8f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * 9f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software distributed under the License 10f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * or implied. See the License for the specific language governing permissions and limitations under 12f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka * the License. 13f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka */ 14f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka 15f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaokapackage com.android.inputmethod.keyboard.internal; 16f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka 17f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaokaimport android.graphics.Path; 18f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaokaimport android.graphics.RectF; 19f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka 20f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaokapublic final class RoundedLine { 21e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka private final RectF mArc1 = new RectF(); 22e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka private final RectF mArc2 = new RectF(); 23e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka private final Path mPath = new Path(); 24f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka 25e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka private static final double RADIAN_TO_DEGREE = 180.0d / Math.PI; 26e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka private static final double RIGHT_ANGLE = Math.PI / 2.0d; 27f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka 28e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka /** 29e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * Make a rounded line path 30e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * 31e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * @param p1x the x-coordinate of the start point. 32e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * @param p1y the y-coordinate of the start point. 33e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * @param r1 the radius at the start point 34e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * @param p2x the x-coordinate of the end point. 35e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * @param p2y the y-coordinate of the end point. 36e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * @param r2 the radius at the end point 37e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka * @return the path of rounded line 38e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka */ 39e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka public Path makePath(final float p1x, final float p1y, final float r1, 40e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p2x, final float p2y, final float r2) { 41e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final double dx = p2x - p1x; 42e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final double dy = p2y - p1y; 43f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // Distance of the points. 44f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka final double l = Math.hypot(dx, dy); 45f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka if (Double.compare(0.0d, l) == 0) { 46f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka return null; 47f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka } 48f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // Angle of the line p1-p2 49e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final double a = Math.atan2(dy, dx); 50f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // Difference of trail cap radius. 51e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final double dr = r2 - r1; 52f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // Variation of angle at trail cap. 53e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final double ar = Math.asin(dr / l); 54f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // The start angle of trail cap arc at P1. 55e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final double aa = a - (RIGHT_ANGLE + ar); 56f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // The end angle of trail cap arc at P2. 57e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final double ab = a + (RIGHT_ANGLE + ar); 58f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka final float cosa = (float)Math.cos(aa); 59f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka final float sina = (float)Math.sin(aa); 60f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka final float cosb = (float)Math.cos(ab); 61f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka final float sinb = (float)Math.sin(ab); 62e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka // Closing point of arc at P1. 63e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p1ax = p1x + r1 * cosa; 64e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p1ay = p1y + r1 * sina; 65e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka // Opening point of arc at P1. 66e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p1bx = p1x + r1 * cosb; 67e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p1by = p1y + r1 * sinb; 68e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka // Opening point of arc at P2. 69e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p2ax = p2x + r2 * cosa; 70e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p2ay = p2y + r2 * sina; 71e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka // Closing point of arc at P2. 72e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p2bx = p2x + r2 * cosb; 73e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float p2by = p2y + r2 * sinb; 74e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka // Start angle of the trail arcs. 75e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float angle = (float)(aa * RADIAN_TO_DEGREE); 76e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float ar2degree = (float)(ar * 2.0d * RADIAN_TO_DEGREE); 77e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka // Sweep angle of the trail arc at P1. 78e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float a1 = -180.0f + ar2degree; 79e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka // Sweep angle of the trail arc at P2. 80e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka final float a2 = 180.0f + ar2degree; 81e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mArc1.set(p1x, p1y, p1x, p1y); 82e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mArc1.inset(-r1, -r1); 83e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mArc2.set(p2x, p2y, p2x, p2y); 84e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mArc2.inset(-r2, -r2); 85f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka 86e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.rewind(); 87f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // Trail cap at P1. 88e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.moveTo(p1x, p1y); 89e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.arcTo(mArc1, angle, a1); 90f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // Trail cap at P2. 91e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.moveTo(p2x, p2y); 92e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.arcTo(mArc2, angle, a2); 93f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka // Two trapezoids connecting P1 and P2. 94e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.moveTo(p1ax, p1ay); 95e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.lineTo(p1x, p1y); 96e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.lineTo(p1bx, p1by); 97e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.lineTo(p2bx, p2by); 98e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.lineTo(p2x, p2y); 99e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.lineTo(p2ax, p2ay); 100e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka mPath.close(); 101e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka return mPath; 102f90475b5d4c2f94188ace4b7dd45160a02d1d204Tadashi G. Takaoka } 103e14df775d454cb96b751cf7668df71ce5873930dTadashi G. Takaoka} 104