Home | History | Annotate | Download | only in internal
      1 /*
      2  * Copyright (C) 2012 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.android.inputmethod.keyboard.internal;
     18 
     19 import android.graphics.Path;
     20 import android.graphics.Rect;
     21 import android.graphics.RectF;
     22 
     23 public final class RoundedLine {
     24     private final RectF mArc1 = new RectF();
     25     private final RectF mArc2 = new RectF();
     26     private final Path mPath = new Path();
     27 
     28     private static final double RADIAN_TO_DEGREE = 180.0d / Math.PI;
     29     private static final double RIGHT_ANGLE = Math.PI / 2.0d;
     30 
     31     /**
     32      * Make a rounded line path
     33      *
     34      * @param p1x the x-coordinate of the start point.
     35      * @param p1y the y-coordinate of the start point.
     36      * @param r1 the radius at the start point
     37      * @param p2x the x-coordinate of the end point.
     38      * @param p2y the y-coordinate of the end point.
     39      * @param r2 the radius at the end point
     40      * @return an instance of {@link Path} that holds the result rounded line, or an instance of
     41      * {@link Path} that holds an empty path if the start and end points are equal.
     42      */
     43     public Path makePath(final float p1x, final float p1y, final float r1,
     44             final float p2x, final float p2y, final float r2) {
     45         mPath.rewind();
     46         final double dx = p2x - p1x;
     47         final double dy = p2y - p1y;
     48         // Distance of the points.
     49         final double l = Math.hypot(dx, dy);
     50         if (Double.compare(0.0d, l) == 0) {
     51             return mPath; // Return an empty path
     52         }
     53         // Angle of the line p1-p2
     54         final double a = Math.atan2(dy, dx);
     55         // Difference of trail cap radius.
     56         final double dr = r2 - r1;
     57         // Variation of angle at trail cap.
     58         final double ar = Math.asin(dr / l);
     59         // The start angle of trail cap arc at P1.
     60         final double aa = a - (RIGHT_ANGLE + ar);
     61         // The end angle of trail cap arc at P2.
     62         final double ab = a + (RIGHT_ANGLE + ar);
     63         final float cosa = (float)Math.cos(aa);
     64         final float sina = (float)Math.sin(aa);
     65         final float cosb = (float)Math.cos(ab);
     66         final float sinb = (float)Math.sin(ab);
     67         // Closing point of arc at P1.
     68         final float p1ax = p1x + r1 * cosa;
     69         final float p1ay = p1y + r1 * sina;
     70         // Opening point of arc at P1.
     71         final float p1bx = p1x + r1 * cosb;
     72         final float p1by = p1y + r1 * sinb;
     73         // Opening point of arc at P2.
     74         final float p2ax = p2x + r2 * cosa;
     75         final float p2ay = p2y + r2 * sina;
     76         // Closing point of arc at P2.
     77         final float p2bx = p2x + r2 * cosb;
     78         final float p2by = p2y + r2 * sinb;
     79         // Start angle of the trail arcs.
     80         final float angle = (float)(aa * RADIAN_TO_DEGREE);
     81         final float ar2degree = (float)(ar * 2.0d * RADIAN_TO_DEGREE);
     82         // Sweep angle of the trail arc at P1.
     83         final float a1 = -180.0f + ar2degree;
     84         // Sweep angle of the trail arc at P2.
     85         final float a2 = 180.0f + ar2degree;
     86         mArc1.set(p1x, p1y, p1x, p1y);
     87         mArc1.inset(-r1, -r1);
     88         mArc2.set(p2x, p2y, p2x, p2y);
     89         mArc2.inset(-r2, -r2);
     90 
     91         // Trail cap at P1.
     92         mPath.moveTo(p1x, p1y);
     93         mPath.arcTo(mArc1, angle, a1);
     94         // Trail cap at P2.
     95         mPath.moveTo(p2x, p2y);
     96         mPath.arcTo(mArc2, angle, a2);
     97         // Two trapezoids connecting P1 and P2.
     98         mPath.moveTo(p1ax, p1ay);
     99         mPath.lineTo(p1x, p1y);
    100         mPath.lineTo(p1bx, p1by);
    101         mPath.lineTo(p2bx, p2by);
    102         mPath.lineTo(p2x, p2y);
    103         mPath.lineTo(p2ax, p2ay);
    104         mPath.close();
    105         return mPath;
    106     }
    107 
    108     public void getBounds(final Rect outBounds) {
    109         // Reuse mArc1 as working variable
    110         mPath.computeBounds(mArc1, true /* unused */);
    111         mArc1.roundOut(outBounds);
    112     }
    113 }
    114