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