/*******************************************************************************
* Copyright 2012-present Pixate, Inc.
*
* 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.
******************************************************************************/
/**
* Copyright (c) 2012-2013 Pixate, Inc. All rights reserved.
*/
package com.pixate.freestyle.cg.shapes;
import android.graphics.Path;
import android.graphics.RectF;
import com.pixate.freestyle.cg.math.PXEllipticalArc;
import com.pixate.freestyle.util.ObjectPool;
/**
* Pixate arrow rectangle
*/
public class PXArrowRectangle extends PXRectangle {
public enum PXArrowRectangleDirection {
LEFT,
RIGHT
};
private PXArrowRectangleDirection direction;
public PXArrowRectangle(PXArrowRectangleDirection direction) {
this(new RectF(), direction);
}
public PXArrowRectangle(RectF bounds, PXArrowRectangleDirection direction) {
super(bounds);
this.direction = direction;
}
@Override
protected Path newPath() {
float handleOffset = 2.5f;
float arrowWidth = 12.0f;
RectF bounds = getBounds();
float left = bounds.left;
float top = bounds.top;
float right = bounds.right;
float bottom = bounds.bottom;
float arrowLeftY = (top + bottom) * 0.5f;
// create path
Path path = ObjectPool.pathPool.checkOut();
if (!hasRoundedCorners()) {
if (direction == PXArrowRectangleDirection.LEFT) {
float arrowRightX = Math.min(right, left + arrowWidth);
path.moveTo(left, arrowLeftY);
// Move & quad - equivalent to CGPathAddCurveToPoint
path.moveTo(left, arrowLeftY);
path.quadTo(arrowRightX - handleOffset, bottom, arrowRightX, bottom);
path.lineTo(right, bottom);
path.lineTo(right, top);
path.lineTo(arrowRightX, top);
path.moveTo(arrowRightX, top);
path.quadTo(arrowRightX - handleOffset, top, left, arrowLeftY);
path.close();
} else {
float arrowRightX = Math.max(left, right - arrowWidth);
path.moveTo(right, arrowLeftY);
path.moveTo(right, arrowLeftY);
path.quadTo(arrowRightX + handleOffset, bottom, arrowRightX, bottom);
path.lineTo(left, bottom);
path.lineTo(left, top);
path.lineTo(arrowRightX, top);
path.moveTo(arrowRightX, top);
path.quadTo(arrowRightX + handleOffset, top, right, arrowLeftY);
path.close();
}
} else {
// top points
float topLeftX = left + radiusTopLeft.width;
float topRightX = right - radiusTopRight.width;
// right points
float rightTopY = top + radiusTopRight.height;
float rightBottomY = bottom - radiusBottomRight.height;
// bottom points
float bottomLeftX = left + radiusBottomLeft.width;
float bottomRightX = right - radiusBottomRight.width;
// left points
float leftTopY = top + radiusTopLeft.height;
float leftBottomY = bottom - radiusBottomLeft.height;
// create path
if (direction == PXArrowRectangleDirection.LEFT) {
float arrowRightX = Math.min(right, left + arrowWidth);
path.moveTo(left, arrowLeftY);
path.quadTo(arrowRightX - handleOffset, bottom, arrowRightX, bottom);
// add right and bottom-right corner
if (radiusBottomRight.width > 0.0f && radiusBottomRight.height > 0.0f) {
path.lineTo(bottomRightX, bottom);
PXEllipticalArc.pathAddEllipticalArc(path, null, bottomRightX, rightBottomY,
radiusBottomRight.width, radiusBottomRight.height, -3.0f
* PXEllipticalArc.M_PI_2, 0.0f);
} else {
path.lineTo(right, bottom);
}
// add top and top-right corner
if (radiusTopRight.width > 0.0f && radiusTopRight.height > 0.0f) {
path.lineTo(right, rightTopY);
PXEllipticalArc.pathAddEllipticalArc(path, null, topRightX, rightTopY,
radiusTopRight.width, radiusTopRight.height, 0.0f, -PXEllipticalArc.M_PI_2);
} else {
path.lineTo(right, top);
}
path.lineTo(arrowRightX, top);
path.moveTo(arrowRightX, top);
path.quadTo(arrowRightX - handleOffset, top, left, arrowLeftY);
path.close();
} else {
float arrowRightX = Math.max(left, right - arrowWidth);
path.moveTo(right, arrowLeftY);
path.quadTo(arrowRightX + handleOffset, bottom, arrowRightX, bottom);
// add bottom and bottom-left corner
if (radiusBottomLeft.width > 0.0f && radiusBottomLeft.height > 0.0f) {
path.lineTo(bottomLeftX, bottom);
path.moveTo(bottomLeftX, leftBottomY);
path.quadTo(radiusBottomLeft.width, radiusBottomLeft.height, PXEllipticalArc.M_PI_2,
(float) -Math.PI);
} else {
path.lineTo(left, bottom);
}
// add left and top-left corner
if (radiusTopLeft.width > 0.0f && radiusTopLeft.height > 0.0f) {
path.lineTo(left, leftTopY);
path.moveTo(topLeftX, leftTopY);
path.quadTo(radiusTopLeft.width, radiusTopLeft.height, (float) Math.PI,
3.0f * PXEllipticalArc.M_PI_2);
} else {
path.lineTo(left, top);
}
path.lineTo(arrowRightX, top);
path.moveTo(arrowRightX, top);
path.quadTo(arrowRightX + handleOffset, top, right, arrowLeftY);
path.close();
}
}
return path;
}
}