if (lastParagraphText == null)
{
lastParagraphText = " ";
paragraph =
new AttributedString(
lastParagraphText,
new AttributedString(
allParagraphs,
lastParagraphStart,
lastParagraphStart + lastParagraphText.length()
).getIterator().getAttributes()
).getIterator();
}
else
{
paragraph =
new AttributedString(
allParagraphs,
lastParagraphStart,
lastParagraphStart + lastParagraphText.length()
).getIterator();
}
List<Integer> tabIndexes = JRStringUtil.getTabIndexes(lastParagraphText);
int currentTab = 0;
int lines = 0;
float endX = 0;
TabStop nextTabStop = null;
boolean requireNextWord = false;
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, getFontRenderContext());//grx.getFontRenderContext()
// the paragraph is rendered one line at a time
while (lineMeasurer.getPosition() < paragraph.getEndIndex() && !isMaxHeightReached)
{
boolean lineComplete = false;
float maxAscent = 0;
float maxDescent = 0;
float maxLeading = 0;
// each line is split into segments, using the tab character as delimiter
segments = new ArrayList<TabSegment>(1);
TabSegment oldSegment = null;
TabSegment crtSegment = null;
// splitting the current line into tab segments
while (!lineComplete)
{
// the current segment limit is either the next tab character or the paragraph end
int tabIndexOrEndIndex = (tabIndexes == null || currentTab >= tabIndexes.size() ? paragraph.getEndIndex() : tabIndexes.get(currentTab) + 1);
float startX = (lineMeasurer.getPosition() == 0 ? text.getParagraph().getFirstLineIndent() : 0);
endX = width - text.getParagraph().getRightIndent() - rightPadding;
endX = endX < startX ? startX : endX;
//formatWidth = endX - startX;
//formatWidth = endX;
int startIndex = lineMeasurer.getPosition();
int rightX = 0;
if (segments.size() == 0)
{
rightX = (int)startX;
//nextTabStop = nextTabStop;
}
else
{
rightX = oldSegment.rightX;
nextTabStop = ParagraphUtil.getNextTabStop(text.getParagraph(), endX, rightX);
}
//float availableWidth = formatWidth - ParagraphUtil.getSegmentOffset(nextTabStop, rightX); // nextTabStop can be null here; and that's OK
float availableWidth = endX - text.getParagraph().getLeftIndent() - ParagraphUtil.getSegmentOffset(nextTabStop, rightX); // nextTabStop can be null here; and that's OK
// creating a text layout object for each tab segment
TextLayout layout =
lineMeasurer.nextLayout(
availableWidth,
tabIndexOrEndIndex,
requireNextWord
);
if (layout != null)
{
AttributedString tmpText =
new AttributedString(
paragraph,
startIndex,
startIndex + layout.getCharacterCount()
);
if (isMinimizePrinterJobSize)
{
//eugene fix - start
layout = new TextLayout(tmpText.getIterator(), getFontRenderContext());
//eugene fix - end
}
if (
text.getHorizontalAlignmentValue() == HorizontalAlignEnum.JUSTIFIED
&& lineMeasurer.getPosition() < paragraph.getEndIndex()
)
{
layout = layout.getJustifiedLayout(availableWidth);
}
maxAscent = Math.max(maxAscent, layout.getAscent());
maxDescent = Math.max(maxDescent, layout.getDescent());
maxLeading = Math.max(maxLeading, layout.getLeading());
//creating the current segment
crtSegment = new TabSegment();
crtSegment.layout = layout;
crtSegment.as = tmpText;
crtSegment.text = lastParagraphText.substring(startIndex, startIndex + layout.getCharacterCount());
int leftX = ParagraphUtil.getLeftX(nextTabStop, layout.getAdvance()); // nextTabStop can be null here; and that's OK
if (rightX > leftX)
{
crtSegment.leftX = rightX;
crtSegment.rightX = (int)(rightX + layout.getAdvance());//FIXMETAB some rounding issues here
}
else
{
crtSegment.leftX = leftX;
// we need this special tab stop based utility call because adding the advance to leftX causes rounding issues
crtSegment.rightX = ParagraphUtil.getRightX(nextTabStop, layout.getAdvance()); // nextTabStop can be null here; and that's OK
}
segments.add(crtSegment);
}
requireNextWord = true;
if (lineMeasurer.getPosition() == tabIndexOrEndIndex)
{
// the segment limit was a tab; going to the next tab
currentTab++;
}
if (lineMeasurer.getPosition() == paragraph.getEndIndex())
{
// the segment limit was the paragraph end; line completed and next line should start at normal zero x offset
lineComplete = true;
nextTabStop = null;
}
else
{
// there is paragraph text remaining
if (lineMeasurer.getPosition() == tabIndexOrEndIndex)
{
// the segment limit was a tab
if (crtSegment.rightX >= ParagraphUtil.getLastTabStop(text.getParagraph(), endX).getPosition())
{
// current segment stretches out beyond the last tab stop; line complete
lineComplete = true;
// next line should should start at first tab stop indent
nextTabStop = ParagraphUtil.getFirstTabStop(text.getParagraph(), endX);
}
else
{
//nothing; this leaves lineComplete=false
}
}
else
{
// the segment did not fit entirely
lineComplete = true;
if (layout == null)
{
// nothing fitted; next line should start at first tab stop indent
if (nextTabStop.getPosition() == ParagraphUtil.getFirstTabStop(text.getParagraph(), endX).getPosition())//FIXMETAB check based on segments.size()
{
// at second attempt we give up to avoid infinite loop
nextTabStop = null;
requireNextWord = false;
//provide dummy maxFontSize because it is used for the line height of this empty line when attempting drawing below
AttributedString tmpText =
new AttributedString(
paragraph,
startIndex,
startIndex + 1
);
LineBreakMeasurer lbm = new LineBreakMeasurer(tmpText.getIterator(), getFontRenderContext());
TextLayout tlyt = lbm.nextLayout(100);
maxAscent = tlyt.getAscent();
maxDescent = tlyt.getDescent();
maxLeading = tlyt.getLeading();
}