public static Rect addMiterLimitStrokeToBounds(ShapeRecord segment1,
ShapeRecord segment2, double miterLimit, double halfWeight, Rect pathBBox,
int xPrev, int yPrev, int x, int y)
{
// The tip of the joint
Point jointPoint = new Point(x, y);
//If a joint lies miterLimit*strokeWeight/2 away from pathBox,
//it is considered an inner joint and has no effect on bounds. So stop
//processing in this case.
if (isInnerJoint(jointPoint, pathBBox, miterLimit, halfWeight))
{
return pathBBox;
}
// End tangent for segment1:
Point t0 = getTangent(segment1, false /*start*/, xPrev, yPrev);
// Start tangent for segment2:
Point t1 = getTangent(segment2, true /*start*/, x, y);
// Valid tangents?
if (getPointLength(t0) == 0 || getPointLength(t1) == 0)
{
return pathBBox;
}
// The tip of the stroke lies on the bisector of the angle and lies at
// a distance of weight / sin(A/2), where A is the angle between the
// tangents.
t0 = normalize(t0, 1);
t0.x = -t0.x;
t0.y = -t0.y;
t1 = normalize(t1, 1);
// Find the vector from t0 to the midPoint from t0 to t1
Point halfT0T1 = new Point((t1.x - t0.x) * 0.5, (t1.y - t0.y) * 0.5);
// sin(A/2) == halfT0T1.length / t1.length()
double sinHalfAlpha = getPointLength(halfT0T1);
if (Math.abs(sinHalfAlpha) < 1.0E-9)
{
// Don't count degenerate joints that are close to 0 degrees so
// we avoid cases like this one L 0 0 0 50 100 0 30 0 50 0 Z
return pathBBox;
}
// Find the vector of the bisect
Point bisect = new Point(-0.5 * (t0.x + t1.x), -0.5 * (t0.y + t1.y));
double bisectLength = getPointLength(bisect);
if (bisectLength == 0)
{
// 180 degrees, nothing to contribute
return pathBBox;
}
Rect newRect = pathBBox;
// Is there miter limit at play?
if (sinHalfAlpha == 0 || miterLimit < 1 / sinHalfAlpha)
{
// The miter limit is reached. Calculate two extra points that may
// contribute to the bounds.
// The points lie on the line perpendicular to the bisect and
// intersecting it at offset of miterLimit * weight from the
// joint tip. The points are equally offset from the bisect by a
// factor of X, where X / sinAlpha == (weight / sinAlpha -
// miterLimit * weight) / bisect.lenght.
bisect = normalize(bisect, 1);
halfT0T1 = normalize(halfT0T1, (halfWeight - miterLimit * halfWeight * sinHalfAlpha) / bisectLength);
Point pt0 = new Point(jointPoint.x + miterLimit * halfWeight * bisect.x + halfT0T1.x,
jointPoint.y + miterLimit * halfWeight * bisect.y + halfT0T1.y);
Point pt1 = new Point(jointPoint.x + miterLimit * halfWeight * bisect.x - halfT0T1.x,
jointPoint.y + miterLimit * halfWeight * bisect.y - halfT0T1.y);
// Add it to the rectangle:
newRect = rectUnion((int)StrictMath.rint(pt0.x), (int)StrictMath.rint(pt0.y),
(int)StrictMath.rint(pt0.x), (int)StrictMath.rint(pt0.y), newRect);
newRect = rectUnion((int)StrictMath.rint(pt1.x), (int)StrictMath.rint(pt1.y),
(int)StrictMath.rint(pt1.x), (int)StrictMath.rint(pt1.y), newRect);
}
else
{
// miter limit is not reached, add the tip of the stroke
bisect = normalize(bisect, 1);
Point strokeTip = new Point(jointPoint.x + bisect.x * halfWeight / sinHalfAlpha,
jointPoint.y + bisect.y * halfWeight / sinHalfAlpha);
// Add it to the rectangle:
newRect = rectUnion((int)StrictMath.rint(strokeTip.x), (int)StrictMath.rint(strokeTip.y),
(int)StrictMath.rint(strokeTip.x), (int)StrictMath.rint(strokeTip.y), newRect);