float sideWidth = -1, topWidth = widthScale, leftWidth = widthScale, rightWidth = widthScale;
double rotation = 0;
float interiorWidth = 0, interiorHeight = 0,
exteriorWidth = 0, exteriorHeight = 0;
BorderRadiusCorner leftRadius = null, rightRadius = null;
int xOffset = 0, yOffset = 0;
// check what side of the border we are using, then set local variables to the appropriate values.
// EG: if were doing bottom border then left would be bottom right corner of the rectangle and right would be bottom left...
if ((side & BorderPainter.TOP) == BorderPainter.TOP) {
sideWidth = bounds.width;
topWidth = widthScale*border.top();
leftWidth = widthScale*border.left();
rightWidth = widthScale*border.right();
leftRadius = border.getTopLeft();
rightRadius = border.getTopRight();
interiorWidth = bounds.width - (1+scaledOffset)*widthScale*border.left() - (1+scaledOffset)*widthScale*border.right();
interiorHeight = bounds.height - (1+scaledOffset)*widthScale*border.top() - (1+scaledOffset)*widthScale*border.bottom();
exteriorWidth = bounds.width - scaledOffset*widthScale*border.left() - scaledOffset*widthScale*border.right();
exteriorHeight = bounds.height - scaledOffset*widthScale*border.top() - scaledOffset*widthScale*border.bottom();
rotation = 0;
} else if ((side & BorderPainter.RIGHT) == BorderPainter.RIGHT) {
sideWidth = bounds.height;
topWidth = widthScale*border.right();
leftWidth = widthScale*border.top();
rightWidth = widthScale*border.bottom();
leftRadius = border.getTopRight();
rightRadius = border.getBottomRight();
interiorHeight = bounds.width - (1+scaledOffset)*widthScale*border.left() - (1+scaledOffset)*widthScale*border.right();
interiorWidth = bounds.height - (1+scaledOffset)*widthScale*border.top() - (1+scaledOffset)*widthScale*border.bottom();
exteriorHeight = bounds.width - scaledOffset*widthScale*border.left() - scaledOffset*widthScale*border.right();
exteriorWidth = bounds.height - scaledOffset*widthScale*border.top() - scaledOffset*widthScale*border.bottom();
xOffset = bounds.width;
yOffset = 0;
rotation = Math.PI / 2;
} else if ((side & BorderPainter.BOTTOM) == BorderPainter.BOTTOM) {
sideWidth = bounds.width;
topWidth = widthScale*border.bottom();
leftWidth = widthScale*border.right();
rightWidth = widthScale*border.left();
leftRadius = border.getBottomRight();
rightRadius = border.getBottomLeft();
interiorWidth = bounds.width - (1+scaledOffset)*widthScale*border.left() - (1+scaledOffset)*widthScale*border.right();
interiorHeight = bounds.height - (1+scaledOffset)*widthScale*border.top() - (1+scaledOffset)*widthScale*border.bottom();
exteriorWidth = bounds.width - scaledOffset*widthScale*border.left() - scaledOffset*widthScale*border.right();
exteriorHeight = bounds.height - scaledOffset*widthScale*border.top() - scaledOffset*widthScale*border.bottom();
xOffset = bounds.width;
yOffset = bounds.height;
rotation = Math.PI;
} else if ((side & BorderPainter.LEFT) == BorderPainter.LEFT) {
sideWidth = bounds.height;
topWidth = widthScale*border.left();
leftWidth = widthScale*border.bottom();
rightWidth = widthScale*border.top();
leftRadius = border.getBottomLeft();
rightRadius = border.getTopLeft();
interiorHeight = bounds.width - (1+scaledOffset)*widthScale*border.left() - (1+scaledOffset)*widthScale*border.right();
interiorWidth = bounds.height - (1+scaledOffset)*widthScale*border.top() - (1+scaledOffset)*widthScale*border.bottom();
exteriorHeight = (bounds.width - scaledOffset*widthScale*border.left() - scaledOffset*widthScale*border.right());
exteriorWidth = bounds.height - scaledOffset*widthScale*border.top() - scaledOffset*widthScale*border.bottom();
xOffset = 0;
yOffset = bounds.height;
rotation = 3 * Math.PI / 2;
}
float tco = scaledOffset*topWidth;
float lco = scaledOffset*leftWidth;
float rco = scaledOffset*rightWidth;
// a magic number that represents the curvature of the radius. 0 would be a square corner with no arc at all (0 border radius) and 1 would be a straight angled corner like a /
// somewhere in the middle is an arc. This number is arbitrary. We need this because i used a bezier function because I couldnt figure out the equation for the "perfect" border radius
// so instead I use this silly hack with a bezier curve.
float curveConstant = .44f;
// top left corner % of side space
float lp = 1;
if(leftWidth != 0) {
// subtracting 1 percent causes the borders to overlap slightly, reducing the integer roundoff error in painting. This removes the tiny white line
// between the 2 different borders. The better way would be to calculate the end location of the other border side and use that instead.
lp = leftWidth / (topWidth + leftWidth)-.01f;
} else {
lp = 0;
}
// top right corner % of side space
float rp = 1;
if(rightWidth != 0) {
// subtracting 1 percent causes the borders to overlap slightly, reducing the integer roundoff error in painting. This removes the tiny white line
// between the 2 different borders. The better way would be to calculate the end location of the other border side and use that instead.
rp = rightWidth / (topWidth + rightWidth)-.01f;
} else {
rp = 0;
}
Path2D path = new Path2D.Float();
// top left outside, check that theres a radius to be had
if(leftRadius.getMaxRight(exteriorWidth) > 0) {
Point2D [][] leftCurvePoints = getSubCurve(1-lp,
new Point2D.Double( leftRadius.getMaxRight(exteriorWidth) + lco, tco),
new Point2D.Double( curveConstant*(leftRadius.getMaxRight(exteriorWidth)) + lco, tco),
new Point2D.Double( lco, tco+curveConstant*(leftRadius.getMaxLeft(exteriorHeight))),
new Point2D.Double( lco, tco+leftRadius.getMaxLeft(exteriorHeight)));
path.moveTo( (leftCurvePoints[0][3].getX()), (leftCurvePoints[0][3].getY()));
path.curveTo( leftCurvePoints[0][2].getX(), leftCurvePoints[0][2].getY(),
leftCurvePoints[0][1].getX(), leftCurvePoints[0][1].getY(),
leftCurvePoints[0][0].getX(), leftCurvePoints[0][0].getY());
} else {
path.moveTo( lco, tco);
}
// top right outside
if(rightRadius.getMaxLeft(exteriorWidth) > 0) {
Point2D [][] rightCurvePoints = getSubCurve(1-rp,
new Point2D.Double( sideWidth - rightRadius.getMaxLeft(exteriorWidth) - rco, tco),
new Point2D.Double( sideWidth - curveConstant*(rightRadius.getMaxLeft(exteriorWidth)) - rco, tco),
new Point2D.Double( sideWidth - rco, tco + curveConstant*(rightRadius.getMaxRight(exteriorHeight))),
new Point2D.Double( sideWidth - rco, tco + rightRadius.getMaxRight(exteriorHeight)));
path.lineTo( rightCurvePoints[0][0].getX(), rightCurvePoints[0][0].getY());
path.curveTo( rightCurvePoints[0][1].getX(), rightCurvePoints[0][1].getY(),
rightCurvePoints[0][2].getX(), rightCurvePoints[0][2].getY(),
(rightCurvePoints[0][3].getX()), (rightCurvePoints[0][3].getY()));
} else {
path.lineTo(sideWidth - rightRadius.getMaxLeft(exteriorWidth/2) - rco, tco);
}
// check if we draw the interior
if(drawInterior) {
// start drawing interior
tco = (1+scaledOffset)*topWidth;
lco = (1+scaledOffset)*leftWidth;
rco = (1+scaledOffset)*rightWidth;
// top right interior, check we have a radius
if(rightRadius.getMaxLeft(interiorWidth) > 0) {
Point2D [][] rightCurvePoints = getSubCurve(1-rp,
new Point2D.Double( sideWidth - rightRadius.getMaxLeft(interiorWidth) - rco, tco),
new Point2D.Double( sideWidth - curveConstant*(rightRadius.getMaxLeft(interiorWidth)) - rco, tco),
new Point2D.Double( sideWidth - rco, tco + curveConstant*(rightRadius.getMaxRight(interiorHeight))),
new Point2D.Double( sideWidth - rco, tco + rightRadius.getMaxRight(interiorHeight)));
path.lineTo((rightCurvePoints[0][3].getX()), (rightCurvePoints[0][3].getY()));
path.curveTo( rightCurvePoints[0][2].getX(), rightCurvePoints[0][2].getY(),
rightCurvePoints[0][1].getX(), rightCurvePoints[0][1].getY(),
rightCurvePoints[0][0].getX(), rightCurvePoints[0][0].getY());
} else {
path.lineTo(sideWidth - rco, tco);
}
// top left interior, check we have a radius
if(leftRadius.getMaxRight(interiorWidth) > 0) {
Point2D [][] leftCurvePoints = getSubCurve(1-lp,
new Point2D.Double( leftRadius.getMaxRight(interiorWidth) + lco, tco),
new Point2D.Double( curveConstant*(leftRadius.getMaxRight(interiorWidth)) + lco, tco),
new Point2D.Double( lco, tco + curveConstant*(leftRadius.getMaxLeft(interiorHeight))),
new Point2D.Double( lco, tco + leftRadius.getMaxLeft(interiorHeight)));
path.lineTo(leftCurvePoints[0][0].getX(), leftCurvePoints[0][0].getY());
path.curveTo( leftCurvePoints[0][1].getX(), leftCurvePoints[0][1].getY(),
leftCurvePoints[0][2].getX(), leftCurvePoints[0][2].getY(),
(leftCurvePoints[0][3].getX()), (leftCurvePoints[0][3].getY()));
} else {
path.lineTo(leftRadius.getMaxRight(interiorHeight) + lco, tco);
}
// only close the path if its a full 2d path. If its just the exterior line we leave it open
path.closePath();
}