centerVisibleIndex = 0;
double currentCurveDelta = 0.0;
double curveDeltaSignificant = 0.3;
double curveDeltaMax = 0.5;
mxLine nextParallel = null;
// TODO on translation just move the points, don't recalculate
// Might be better than the curve is the only thing updated and
// the curve shapes listen to curve events
// !lastPoints.equals(curve.getGuidePoints())
for (int j = 0; j < labelGlyphs.length; j++)
{
if (currentPos > endPos)
{
labelGlyphs[j].visible = false;
continue;
}
mxLine parallel = nextParallel;
if (currentCurveDelta > curveDeltaSignificant
|| nextParallel == null)
{
parallel = curve.getCurveParallel(mxCurve.LABEL_CURVE,
currentPos);
currentCurveDelta = 0.0;
nextParallel = null;
}
labelGlyphs[j].glyphGeometry = parallel;
if (parallel == mxCurve.INVALID_POSITION)
{
continue;
}
// Get the four corners of the rotated rectangle bounding the glyph
// The drawing bounds of the glyph is the unrotated rect that
// just bounds those four corners
final double w = labelGlyphs[j].labelGlyphBounds.getWidth();
final double h = labelGlyphs[j].labelGlyphBounds.getHeight();
final double x = parallel.getEndPoint().getX();
final double y = parallel.getEndPoint().getY();
// Bottom left
double p1X = parallel.getX() - (descent * y);
double minX = p1X, maxX = p1X;
double p1Y = parallel.getY() + (descent * x);
double minY = p1Y, maxY = p1Y;
// Top left
double p2X = p1X + ((h + descent) * y);
double p2Y = p1Y - ((h + descent) * x);
minX = Math.min(minX, p2X);
maxX = Math.max(maxX, p2X);
minY = Math.min(minY, p2Y);
maxY = Math.max(maxY, p2Y);
// Bottom right
double p3X = p1X + (w * x);
double p3Y = p1Y + (w * y);
minX = Math.min(minX, p3X);
maxX = Math.max(maxX, p3X);
minY = Math.min(minY, p3Y);
maxY = Math.max(maxY, p3Y);
// Top right
double p4X = p2X + (w * x);
double p4Y = p2Y + (w * y);
minX = Math.min(minX, p4X);
maxX = Math.max(maxX, p4X);
minY = Math.min(minY, p4Y);
maxY = Math.max(maxY, p4Y);
minX -= 2 * scale;
minY -= 2 * scale;
maxX += 2 * scale;
maxY += 2 * scale;
// Hook for sub-classers
postprocessGlyph(curve, label, j, currentPos);
// Need to allow for text on inside of curve bends. Need to get the
// parallel for the next section, if there is an excessive
// inner curve, advance the current position accordingly
double currentPosCandidate = currentPos
+ (labelGlyphs[j].labelGlyphBounds.getWidth() + labelPosition.defaultInterGlyphSpace)
/ curveLength;
nextParallel = curve.getCurveParallel(mxCurve.LABEL_CURVE,
currentPosCandidate);
currentPos = currentPosCandidate;
mxPoint nextVector = nextParallel.getEndPoint();
double end2X = nextVector.getX();
double end2Y = nextVector.getY();
if (nextParallel != mxCurve.INVALID_POSITION
&& j + 1 < label.length())
{
// Extend the current parallel line in its direction
// by the length of the next parallel. Use the approximate
// deviation to work out the angle change
double deltaX = Math.abs(x - end2X);
double deltaY = Math.abs(y - end2Y);
// The difference as a proportion of the length of the next
// vector. 1 means a variation of 60 degrees.
currentCurveDelta = Math
.sqrt(deltaX * deltaX + deltaY * deltaY);
}
if (currentCurveDelta > curveDeltaSignificant)
{
// Work out which direction the curve is going in
int ccw = Line2D.relativeCCW(0, 0, x, y, end2X, end2Y);
if (ccw == 1)
{
// Text is on inside of curve
if (currentCurveDelta > curveDeltaMax)
{
// Don't worry about excessive deltas, if they
// are big the label curve will be screwed anyway
currentCurveDelta = curveDeltaMax;
}
double textBuffer = currentCurveDelta
* CURVE_TEXT_STRETCH_FACTOR / curveLength;
currentPos += textBuffer;
endPos += textBuffer;
}
}
if (labelGlyphs[j].drawingBounds != null)
{
labelGlyphs[j].drawingBounds.setRect(minX, minY, maxX - minX,
maxY - minY);
}
else
{
labelGlyphs[j].drawingBounds = new mxRectangle(minX, minY, maxX
- minX, maxY - minY);
}
if (overallLabelBounds == null)
{
overallLabelBounds = (mxRectangle) labelGlyphs[j].drawingBounds
.clone();
}
else
{
overallLabelBounds.add(labelGlyphs[j].drawingBounds);
}
labelGlyphs[j].visible = true;
centerVisibleIndex++;
}
centerVisibleIndex /= 2;
if (overallLabelBounds == null)
{
// Return a small rectangle in the center of the label curve
// Null label bounds causes NPE when editing
mxLine labelCenter = curve.getCurveParallel(mxCurve.LABEL_CURVE,
0.5);
overallLabelBounds = new mxRectangle(labelCenter.getX(),
labelCenter.getY(), 1, 1);
}
this.labelBounds = overallLabelBounds;
return overallLabelBounds;
}