| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.inputmethod.keyboard.internal; |
| |
| import android.graphics.Path; |
| import android.graphics.Rect; |
| import android.graphics.RectF; |
| |
| public final class RoundedLine { |
| private final RectF mArc1 = new RectF(); |
| private final RectF mArc2 = new RectF(); |
| private final Path mPath = new Path(); |
| |
| private static final double RADIAN_TO_DEGREE = 180.0d / Math.PI; |
| private static final double RIGHT_ANGLE = Math.PI / 2.0d; |
| |
| /** |
| * Make a rounded line path |
| * |
| * @param p1x the x-coordinate of the start point. |
| * @param p1y the y-coordinate of the start point. |
| * @param r1 the radius at the start point |
| * @param p2x the x-coordinate of the end point. |
| * @param p2y the y-coordinate of the end point. |
| * @param r2 the radius at the end point |
| * @return the path of rounded line |
| */ |
| public Path makePath(final float p1x, final float p1y, final float r1, |
| final float p2x, final float p2y, final float r2) { |
| final double dx = p2x - p1x; |
| final double dy = p2y - p1y; |
| // Distance of the points. |
| final double l = Math.hypot(dx, dy); |
| if (Double.compare(0.0d, l) == 0) { |
| return null; |
| } |
| // Angle of the line p1-p2 |
| final double a = Math.atan2(dy, dx); |
| // Difference of trail cap radius. |
| final double dr = r2 - r1; |
| // Variation of angle at trail cap. |
| final double ar = Math.asin(dr / l); |
| // The start angle of trail cap arc at P1. |
| final double aa = a - (RIGHT_ANGLE + ar); |
| // The end angle of trail cap arc at P2. |
| final double ab = a + (RIGHT_ANGLE + ar); |
| final float cosa = (float)Math.cos(aa); |
| final float sina = (float)Math.sin(aa); |
| final float cosb = (float)Math.cos(ab); |
| final float sinb = (float)Math.sin(ab); |
| // Closing point of arc at P1. |
| final float p1ax = p1x + r1 * cosa; |
| final float p1ay = p1y + r1 * sina; |
| // Opening point of arc at P1. |
| final float p1bx = p1x + r1 * cosb; |
| final float p1by = p1y + r1 * sinb; |
| // Opening point of arc at P2. |
| final float p2ax = p2x + r2 * cosa; |
| final float p2ay = p2y + r2 * sina; |
| // Closing point of arc at P2. |
| final float p2bx = p2x + r2 * cosb; |
| final float p2by = p2y + r2 * sinb; |
| // Start angle of the trail arcs. |
| final float angle = (float)(aa * RADIAN_TO_DEGREE); |
| final float ar2degree = (float)(ar * 2.0d * RADIAN_TO_DEGREE); |
| // Sweep angle of the trail arc at P1. |
| final float a1 = -180.0f + ar2degree; |
| // Sweep angle of the trail arc at P2. |
| final float a2 = 180.0f + ar2degree; |
| mArc1.set(p1x, p1y, p1x, p1y); |
| mArc1.inset(-r1, -r1); |
| mArc2.set(p2x, p2y, p2x, p2y); |
| mArc2.inset(-r2, -r2); |
| |
| mPath.rewind(); |
| // Trail cap at P1. |
| mPath.moveTo(p1x, p1y); |
| mPath.arcTo(mArc1, angle, a1); |
| // Trail cap at P2. |
| mPath.moveTo(p2x, p2y); |
| mPath.arcTo(mArc2, angle, a2); |
| // Two trapezoids connecting P1 and P2. |
| mPath.moveTo(p1ax, p1ay); |
| mPath.lineTo(p1x, p1y); |
| mPath.lineTo(p1bx, p1by); |
| mPath.lineTo(p2bx, p2by); |
| mPath.lineTo(p2x, p2y); |
| mPath.lineTo(p2ax, p2ay); |
| mPath.close(); |
| return mPath; |
| } |
| |
| public void getBounds(final Rect outBounds) { |
| // Reuse mArc1 as working variable |
| mPath.computeBounds(mArc1, true /* unused */); |
| mArc1.roundOut(outBounds); |
| } |
| } |