--- /dev/null
+package org.simantics.document.linking.report.pdf;\r
+\r
+import java.awt.Color;\r
+import java.awt.Font;\r
+import java.awt.Graphics2D;\r
+import java.awt.Shape;\r
+import java.awt.font.LineBreakMeasurer;\r
+import java.awt.font.TextAttribute;\r
+import java.awt.font.TextLayout;\r
+import java.net.URL;\r
+import java.text.AttributedCharacterIterator;\r
+import java.text.AttributedString;\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.Hashtable;\r
+import java.util.List;\r
+\r
+import org.simantics.document.linking.report.Document.TextSize;\r
+import org.simantics.document.linking.report.Table;\r
+import org.simantics.document.linking.report.TableColumn;\r
+import org.simantics.document.linking.report.TableColumn.Alignment;\r
+import org.simantics.document.linking.report.TableRow;\r
+import org.simantics.document.linking.report.TextItem;\r
+import org.simantics.document.linking.report.URLItem;\r
+\r
+import com.lowagie.text.pdf.PdfAction;\r
+\r
+\r
+public class PDFTable implements Table, PDFElement {\r
+ PDFDocument writer;\r
+ PDFPageStream stream;\r
+ PDFPage startPage;\r
+ \r
+ int currentLine = 0;\r
+ \r
+ List<TableColumn> columns = new ArrayList<TableColumn>();\r
+ List<String> columnNames = new ArrayList<String>();\r
+ List<Integer> columnSizes = new ArrayList<Integer>();\r
+ List<Integer> columnPositions = new ArrayList<Integer>();\r
+ \r
+ TextItem title = null;\r
+ \r
+ boolean headerVisible = true;\r
+ private boolean linesVisible = true;\r
+ private boolean linesPrevVisible = true;\r
+ boolean clipText = false;\r
+ \r
+ int textOffsetX = 2;\r
+ int textOffsetY = 2;\r
+ \r
+ public PDFTable(PDFDocument writer, PDFPageStream stream) {\r
+ this.writer = writer;\r
+ this.stream = stream;\r
+ this.startPage = stream.getCurrentPage();\r
+ \r
+ }\r
+ \r
+ public PDFTable(PDFTable table) {\r
+ this.writer = table.writer;\r
+ this.stream = table.stream;\r
+ this.startPage = stream.getCurrentPage();\r
+ this.columns.addAll(table.columns);\r
+ this.columnNames.addAll(table.columnNames);\r
+ \r
+ updateColumnPositions();\r
+ }\r
+ \r
+ \r
+ @Override\r
+ public PDFPage getPage() {\r
+ return startPage;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see org.simantics.document.linking.report.Table#addColumn(java.lang.String, double)\r
+ */\r
+ @Override\r
+ public TableColumn addColumn(String name, double width) {\r
+ TableColumn tc = new TableColumn(name, width);\r
+ columns.add(tc);\r
+ columnNames.add(name);\r
+ \r
+ updateColumnPositions();\r
+ return tc;\r
+ }\r
+ \r
+ private void updateColumnPositions() {\r
+ int pos = 0;\r
+ columnSizes.clear();\r
+ columnPositions.clear();\r
+ for (TableColumn c : columns) {\r
+ int size = (int)(c.getWidth()*stream.getContentWidth());\r
+ columnSizes.add(size);\r
+ columnPositions.add(pos);\r
+ pos+=size;\r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public List<TableColumn> getColumns() {\r
+ return columns;\r
+ }\r
+ \r
+ @Override\r
+ public boolean isLinesVisible() {\r
+ return linesVisible;\r
+ }\r
+ \r
+ @Override\r
+ public void setLinesVisible(boolean b) {\r
+ if (this.linesVisible == b)\r
+ return;\r
+ this.linesPrevVisible = linesVisible;\r
+ this.linesVisible = b;\r
+ }\r
+ \r
+ @Override\r
+ public boolean isHeaderVisible() {\r
+ return headerVisible;\r
+ }\r
+ \r
+ @Override\r
+ public void setHeaderVisible(boolean b) {\r
+ this.headerVisible = b;\r
+ }\r
+ \r
+ private boolean isFirstLine() {\r
+ return currentLine == 0 || stream.getCurrentPage().currentLine == 1;\r
+ }\r
+ \r
+ @Override\r
+ public void setTitle(String title) {\r
+ try {\r
+ this.title = writer.newItem(TextItem.class);\r
+ this.title.setText(title);\r
+ } catch (Exception e) {\r
+ \r
+ }\r
+ }\r
+ \r
+ @Override\r
+ public void setTitle(TextItem title){\r
+ this.title = title;\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see org.simantics.document.linking.report.Table#writeRow(java.lang.String[])\r
+ */\r
+ @Override\r
+ public TableRow writeRow(String... line) throws Exception{\r
+ List<String> list = new ArrayList<String>(line.length);\r
+ for (String s : line)\r
+ list.add(s);\r
+ return writeRow(list);\r
+ }\r
+ \r
+ /* (non-Javadoc)\r
+ * @see org.simantics.document.linking.report.Table#writeRow(java.util.List)\r
+ */\r
+ @Override\r
+ public TableRow writeRow(List<String> line) throws Exception{\r
+ if (isFirstLine())\r
+ writeHeader();\r
+ return _writeRow(line);\r
+ }\r
+ \r
+ @Override\r
+ public TableRow writeRowItem(TextItem... line) throws Exception {\r
+ List<TextItem> list = new ArrayList<TextItem>(line.length);\r
+ for (TextItem s : line)\r
+ list.add(s);\r
+ return writeRowItem(list);\r
+ }\r
+ \r
+ @Override\r
+ public TableRow writeRowItem(List<TextItem> line) throws Exception {\r
+ if (isFirstLine())\r
+ writeHeader();\r
+ return _writeRow2(line);\r
+ }\r
+ \r
+ private TableRow _writeRow(List<String> line) throws Exception {\r
+ int h = getTextHeight();\r
+ int ht = getTopHeight();\r
+ int hb = getBottomHeight();\r
+ PDFPage page = getCurrentPage();\r
+ Graphics2D g2d = page.g2d;\r
+ Shape clip = g2d.getClip();\r
+ \r
+ if (clipText) {\r
+ for (int i = 0; i < line.size(); i++) {\r
+ if (line.get(i) == null)\r
+ continue;\r
+ g2d.setClip(columnPositions.get(i),ht-1,columnSizes.get(i),hb-ht+2);\r
+ g2d.drawString(line.get(i), columnPositions.get(i)+textOffsetX, h);\r
+ }\r
+ g2d.setClip(clip);\r
+ if (linesVisible) {\r
+ for (int i = 0; i < line.size(); i++) {\r
+ g2d.drawLine(columnPositions.get(i), ht, columnPositions.get(i), hb);\r
+ }\r
+ if (isFirstLine() || !linesPrevVisible) {\r
+ g2d.drawLine(0, ht, stream.contentWidth, ht);\r
+ linesPrevVisible = true;\r
+ }\r
+ g2d.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
+ g2d.drawLine(0, hb, stream.contentWidth, hb);\r
+ }\r
+ currentLine++;\r
+ page.currentLine++;\r
+ page.availableLines--;\r
+ page.currentPixel += getLineHeight();\r
+ } else {\r
+ PositionedRow row = _getRow(line);\r
+ if (stream.contentHeight-page.currentPixel < row.reservedSpace) {\r
+ stream.nextPage();\r
+ page = getCurrentPage();\r
+ g2d = page.g2d;\r
+ writeHeader();\r
+ row = _getRow(line);\r
+ }\r
+ row.render(g2d);\r
+ currentLine+= row.realLines;\r
+ page.currentLine+= row.realLines;\r
+ page.currentPixel += row.reservedSpace;\r
+ page.estimateAvailableLines();\r
+ }\r
+ \r
+ stream.checkNextPage();\r
+ return new PDFTableRow();\r
+ }\r
+ \r
+ private TableRow _writeRow2(List<TextItem> line) throws Exception {\r
+ int h = getTextHeight();\r
+ int ht = getTopHeight();\r
+ int hb = getBottomHeight();\r
+ PDFPage page = getCurrentPage();\r
+ Graphics2D g2d = page.g2d;\r
+ Shape clip = g2d.getClip();\r
+ \r
+ if (clipText) {\r
+ for (int i = 0; i < line.size(); i++) {\r
+ TextItem text = line.get(i);\r
+ if (text == null)\r
+ continue;\r
+ g2d.setClip(columnPositions.get(i),ht,columnSizes.get(i),hb-ht);\r
+ g2d.drawString(text.getText(), columnPositions.get(i)+textOffsetX, h);\r
+ if (text instanceof URLItem) {\r
+ URL url = ((URLItem)text).getURL();\r
+ if (url != null) {\r
+ addLink(url, columnPositions.get(i),ht,columnSizes.get(i),hb-ht);\r
+ }\r
+ }\r
+ }\r
+ g2d.setClip(clip);\r
+ if (linesVisible) {\r
+ for (int i = 0; i < line.size(); i++) {\r
+ g2d.drawLine(columnPositions.get(i), ht, columnPositions.get(i), hb);\r
+ }\r
+ if (isFirstLine() || !linesPrevVisible) {\r
+ g2d.drawLine(0, ht, stream.contentWidth, ht);\r
+ linesPrevVisible = true;\r
+ }\r
+ g2d.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
+ g2d.drawLine(0, hb, stream.contentWidth, hb);\r
+ }\r
+ currentLine++;\r
+ page.currentLine++;\r
+ page.availableLines--;\r
+ page.currentPixel += getLineHeight();\r
+ } else {\r
+ PositionedRow row = _getRow2(line);\r
+ if (stream.contentHeight-page.currentPixel < row.reservedSpace) {\r
+ stream.nextPage();\r
+ page = getCurrentPage();\r
+ g2d = page.g2d;\r
+ writeHeader();\r
+ row = _getRow2(line);\r
+ }\r
+ row.render(g2d);\r
+ currentLine+= row.realLines;\r
+ page.currentLine+= row.realLines;\r
+ page.currentPixel += row.reservedSpace;\r
+ page.estimateAvailableLines();\r
+ }\r
+ \r
+ stream.checkNextPage();\r
+ return new PDFTableRow();\r
+ }\r
+ \r
+ void writeLine(String line) throws Exception{\r
+ writeLine(line, 0);\r
+ }\r
+ \r
+ void writeLine(TextItem line) throws Exception{\r
+ writeLine(line, 0);\r
+ }\r
+ \r
+ private void writeHeader() throws Exception{\r
+ if (headerVisible) {\r
+ TextSize s = currentTextSize;\r
+ setTextSize(TextSize.MEDIUM);\r
+ if (title != null) {\r
+ boolean b = linesVisible;\r
+ setLinesVisible(false);\r
+ writeLine(title);\r
+ setLinesVisible(b);\r
+ }\r
+ _writeRow(columnNames);\r
+ setTextSize(s);\r
+ }\r
+ }\r
+ \r
+ void writeLine(String line, int x) throws Exception{\r
+ int h = getTextHeight();\r
+ int ht = getTopHeight();\r
+ int hb = getBottomHeight();\r
+ PDFPage page = getCurrentPage();\r
+ Graphics2D g2d = page.g2d;\r
+ g2d.drawString(line, x+textOffsetX, h);\r
+ if (linesVisible) {\r
+ if (isFirstLine() || !linesPrevVisible) {\r
+ g2d.drawLine(0, ht, stream.contentWidth, ht);\r
+ linesPrevVisible = true;\r
+ }\r
+ g2d.drawLine(0, ht, 0, hb);\r
+ g2d.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
+ g2d.drawLine(0, hb, stream.contentWidth, hb);\r
+ }\r
+ currentLine++;\r
+ page.currentLine++;\r
+ page.availableLines--;\r
+ page.currentPixel += getLineHeight();\r
+ stream.checkNextPage();\r
+ }\r
+ \r
+ void writeLine(TextItem line, int x) throws Exception{\r
+ int h = getTextHeight();\r
+ int ht = getTopHeight();\r
+ int hb = getBottomHeight();\r
+ PDFPage page = getCurrentPage();\r
+ Graphics2D g2d = page.g2d;\r
+ g2d.drawString(line.getText(), x+textOffsetX, h);\r
+ if (linesVisible) {\r
+ if (isFirstLine() || !linesPrevVisible) {\r
+ g2d.drawLine(0, ht, stream.contentWidth, ht);\r
+ linesPrevVisible = true;\r
+ }\r
+ g2d.drawLine(0, ht, 0, hb);\r
+ g2d.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
+ g2d.drawLine(0, hb, stream.contentWidth, hb);\r
+ }\r
+ if (line instanceof URLItem) {\r
+ URL url = ((URLItem)line).getURL();\r
+ if (url != null) {\r
+ addLink(url, 0,ht,stream.contentWidth,hb-ht);\r
+ }\r
+ }\r
+ currentLine++;\r
+ page.currentLine++;\r
+ page.availableLines--;\r
+ page.currentPixel += getLineHeight();\r
+ stream.checkNextPage();\r
+ }\r
+ \r
+ int getTopHeight() {\r
+ return getTopHeight(currentLine);\r
+ }\r
+ \r
+ int getTopHeight(int line) {\r
+ return (line-currentLine)*getLineHeight()+getCurrentPage().currentPixel;\r
+ }\r
+ \r
+ int getTextHeight() {\r
+ PDFPage page = getCurrentPage();\r
+ return page.currentPixel+getLineHeight()-page.fm.getDescent()-textOffsetY;\r
+ }\r
+ \r
+ PDFPage getCurrentPage() {\r
+ return stream.getCurrentPage();\r
+ }\r
+ \r
+ int getBottomHeight() {\r
+ return getBottomHeight(currentLine);\r
+ }\r
+ \r
+ protected int getLineHeight() {\r
+ return getCurrentPage().fm.getHeight()+textOffsetY;\r
+ }\r
+ \r
+ private int getBottomHeight(int line) {\r
+ return (line-currentLine+1)*getLineHeight()+getCurrentPage().currentPixel;\r
+ }\r
+ \r
+ public int getAvailableLines() {\r
+ PDFPage page = getCurrentPage();\r
+ int contentHeight = stream.contentHeight;\r
+ int pixelY = page.currentPixel;\r
+ return (int)Math.floor((contentHeight-pixelY)/getLineHeight());\r
+ }\r
+ \r
+ private TextSize currentTextSize = TextSize.SMALL;\r
+ \r
+ @Override\r
+ public void setTextSize(TextSize size) {\r
+ stream.getCurrentPage().setFont(writer.fonts.get(size));\r
+ currentTextSize = size;\r
+ }\r
+ \r
+ @Override\r
+ public TextSize getTextSize() {\r
+ return currentTextSize;\r
+ }\r
+ \r
+ private PositionedRow _getRow(List<String> line) {\r
+ PositionedRow row = new PositionedRow();\r
+ int h = getTextHeight();\r
+ int realLines = 1;\r
+ int reservedSpace = 0;\r
+ List<List<PositionedText>> cells = new ArrayList<List<PositionedText>>(line.size());\r
+ if (line.size() > 1) {\r
+ for (int i = 0; i < line.size(); i++) {\r
+ String text = line.get(i);\r
+ int availableSize = columnSizes.get(i)-textOffsetX;\r
+ if (text != null && text.length() > 0) {\r
+ List<PositionedText> pt = getText(text, columnPositions.get(i)+textOffsetX, h,availableSize, columns.get(i).getAlignment());\r
+ cells.add(pt);\r
+ reservedSpace = Math.max(reservedSpace, getResevedSpace(pt)+getLineHeight());\r
+ realLines = Math.max(realLines, getLineSpace(pt));\r
+ } else {\r
+ cells.add(Collections.<PositionedText> emptyList());\r
+ reservedSpace = Math.max(reservedSpace, getLineHeight());\r
+ }\r
+ }\r
+ } else {\r
+ String text = line.get(0);\r
+ int availableSize = stream.contentWidth;\r
+ if (text != null && text.length() > 0) {\r
+ List<PositionedText> pt = getText(text, textOffsetX, h,availableSize, columns.get(0).getAlignment());\r
+ cells.add(pt);\r
+ reservedSpace = Math.max(reservedSpace, getResevedSpace(pt)+getLineHeight());\r
+ realLines = Math.max(realLines, getLineSpace(pt));\r
+ } else {\r
+ cells.add(Collections.<PositionedText> emptyList());\r
+ reservedSpace = Math.max(reservedSpace, getLineHeight());\r
+ }\r
+ }\r
+ row.reservedSpace = reservedSpace;\r
+ row.startLine = currentLine;\r
+ row.realLines = realLines;\r
+ row.cells = cells;\r
+ return row;\r
+ }\r
+ \r
+ private PositionedRow _getRow2(List<TextItem> line) {\r
+ PositionedRow row = new PositionedRow();\r
+ int h = getTextHeight();\r
+ int realLines = 1;\r
+ int reservedSpace = 0;\r
+ row.cells = new ArrayList<List<PositionedText>>(line.size());\r
+ row.urls = new ArrayList<URL>();\r
+ if (line.size() > 1) {\r
+ for (int i = 0; i < line.size(); i++) {\r
+ TextItem item =line.get(i); \r
+ \r
+ int availableSize = columnSizes.get(i)-textOffsetX;\r
+ if (item != null && item.getText().length() > 0) {\r
+ String text = item.getText();\r
+ List<PositionedText> pt = getText(text, columnPositions.get(i)+textOffsetX, h,availableSize, columns.get(i).getAlignment());\r
+ row.cells.add(pt);\r
+ reservedSpace = Math.max(reservedSpace, getResevedSpace(pt)+getLineHeight());\r
+ realLines = Math.max(realLines, getLineSpace(pt));\r
+ } else {\r
+ row.cells.add(Collections.<PositionedText> emptyList());\r
+ reservedSpace = Math.max(reservedSpace, getLineHeight());\r
+ }\r
+ if (item instanceof URLItem) {\r
+ row.urls.add(((URLItem)item).getURL());\r
+ } else {\r
+ row.urls.add(null);\r
+ }\r
+ }\r
+ \r
+ } else {\r
+ String text = line.get(0).getText();\r
+ int availableSize = stream.contentWidth;\r
+ if (text != null && text.length() > 0) {\r
+ List<PositionedText> pt = getText(text, textOffsetX, h,availableSize, columns.get(0).getAlignment());\r
+ row.cells.add(pt);\r
+ reservedSpace = Math.max(reservedSpace, getResevedSpace(pt)+getLineHeight());\r
+ realLines = Math.max(realLines, getLineSpace(pt));\r
+ } else {\r
+ row.cells.add(Collections.<PositionedText> emptyList());\r
+ reservedSpace = Math.max(reservedSpace, getLineHeight());\r
+ }\r
+ }\r
+ row.reservedSpace = reservedSpace;\r
+ row.startLine = currentLine;\r
+ row.realLines = realLines;\r
+ return row;\r
+ }\r
+ \r
+ private int getResevedSpace(List<PositionedText> pt) {\r
+ float sy = pt.get(0).drawPosY;\r
+ float ey = pt.get(pt.size()-1).drawPosY;\r
+ return (int)Math.ceil(ey-sy);\r
+ }\r
+ /**\r
+ * Usually lines of multi-line cells consume less space than the maximum line height (FontMetrics). This method calculates the exact amount of lines required by a cell. \r
+ * @param pt\r
+ * @return\r
+ */\r
+ private int getLineSpace(List<PositionedText> pt) {\r
+ if (pt.size() < 2)\r
+ return 1;\r
+ \r
+ return (int)(getResevedSpace(pt)/getLineHeight())+1;\r
+ }\r
+ \r
+ private class PositionedRow {\r
+ int startLine;\r
+ int realLines;\r
+ int reservedSpace;\r
+ List<List<PositionedText>> cells;\r
+ List<URL> urls;\r
+ \r
+ void render(Graphics2D g) {\r
+ int ht = getTopHeight(startLine);\r
+ int hb = ht +reservedSpace;\r
+ if (cells.size() > 0) {\r
+ for (int i = 0; i < cells.size(); i++) {\r
+ List<PositionedText> ptl = cells.get(i);\r
+ for (PositionedText pt : ptl)\r
+ pt.render(g);\r
+ if (urls != null) {\r
+ URL url = urls.get(i);\r
+ if (url != null) {\r
+ addLink(url, columnPositions.get(i),ht,columnSizes.get(i),hb-ht);\r
+ }\r
+ }\r
+ }\r
+ } \r
+ if (linesVisible) {\r
+ if (cells.size() > 0) {\r
+ for (int i = 0; i < cells.size(); i++) {\r
+ g.drawLine(columnPositions.get(i), ht, columnPositions.get(i), hb);\r
+ }\r
+ } else {\r
+ g.drawLine(columnPositions.get(0), ht, columnPositions.get(0), hb);\r
+ }\r
+ if (isFirstLine() || !linesPrevVisible) {\r
+ g.drawLine(0, ht, stream.contentWidth, ht);\r
+ linesPrevVisible = true;\r
+ }\r
+ g.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
+ g.drawLine(0, hb, stream.contentWidth, hb);\r
+ \r
+ }\r
+ }\r
+ }\r
+ \r
+ private void addLink(URL url, int x, int y, int w, int h) {\r
+ PDFPage page = getCurrentPage();\r
+ float fx = +page.stream.marginLeft + x;\r
+ float fy = -page.stream.marginTop + page.template.getHeight() - y;\r
+ page.template.setAction(new PdfAction(url), fx, fy-h, fx+w, fy);\r
+ }\r
+ \r
+ private List<PositionedText> getText(String text, int x, int y, int cellWidth, Alignment alignment) {\r
+ List<PositionedText> result = new ArrayList<PositionedText>();\r
+ Hashtable<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>();\r
+ PDFPage page = getCurrentPage();\r
+ Font font = page.getFont();\r
+ for (TextAttribute a : font.getAttributes().keySet()) {\r
+ Object v = font.getAttributes().get(a);\r
+ if (v != null)\r
+ map.put(a, v);\r
+ }\r
+// map.putAll(font.getAttributes());\r
+ map.put(TextAttribute.FOREGROUND, Color.black);\r
+\r
+ AttributedString attributedText = new AttributedString( text, map);\r
+\r
+ AttributedCharacterIterator paragraph = attributedText.getIterator();\r
+ int paragraphStart = paragraph.getBeginIndex();\r
+ int paragraphEnd = paragraph.getEndIndex();\r
+ LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, page.frc);\r
+ lineMeasurer.setPosition(paragraphStart);\r
+ \r
+ // Get lines until the entire paragraph has been displayed.\r
+ int next, limit, charat, position = 0;\r
+ int drawPosY = y;\r
+ while ((position = lineMeasurer.getPosition()) < paragraphEnd) {\r
+\r
+ // Find possible line break and set it as a limit to the next layout\r
+ next = lineMeasurer.nextOffset(cellWidth);\r
+ limit = next;\r
+ charat = text.indexOf(System.getProperty("line.separator"),position+1);\r
+ if(charat < next && charat != -1){\r
+ limit = charat;\r
+ }\r
+\r
+ // Retrieve next layout. A cleverer program would also cache\r
+ // these layouts until the component is re-sized.\r
+ TextLayout layout = lineMeasurer.nextLayout(cellWidth, limit, false);\r
+\r
+ // Compute pen x position. If the paragraph is right-to-left we\r
+ // will align the TextLayouts to the right edge of the panel.\r
+ // Note: this won't occur for the English text in this sample.\r
+ // Note: drawPosX is always where the LEFT of the text is placed.\r
+ float drawPosX = 0;\r
+ switch (alignment) {\r
+ case LEFT: \r
+ drawPosX = layout.isLeftToRight() ? 0 : cellWidth - layout.getAdvance();\r
+ break;\r
+ case CENTER:\r
+ drawPosX = (cellWidth - layout.getAdvance()) / 2;\r
+ break;\r
+ case RIGHT:\r
+ drawPosX = layout.isLeftToRight() ? cellWidth - layout.getAdvance() : 0;\r
+ break;\r
+ }\r
+ \r
+ drawPosX += x;\r
+ \r
+ // If text has been forced to vertical, align it to center\r
+// if(breakWidth < textAreaWidth) {\r
+// float centerCorrection = layout.isLeftToRight() ? \r
+// (float) (layout.getAdvance() / 2) : \r
+// -1 * (float) (layout.getAdvance() / 2);\r
+// drawPosX = textAreaWidth / 2 - centerCorrection;\r
+// }\r
+\r
+ // Stop drawing if the text won't fit\r
+// if (breakHeight < drawPosY + layout.getDescent() + layout.getLeading()) {\r
+// break;\r
+// }\r
+\r
+// drawPosY += layout.getAscent();\r
+\r
+ // Add TextLayout at (drawPosX, drawPosY).\r
+ result.add(new PositionedText(drawPosX, drawPosY, layout));\r
+\r
+ // Move y-coordinate in preparation for next layout.\r
+ //drawPosY += layout.getDescent() + layout.getLeading();\r
+ drawPosY += layout.getDescent() + layout.getLeading() + layout.getAscent();\r
+// drawPosY += getLineHeight();\r
+ }\r
+ return result;\r
+ }\r
+ \r
+ class PositionedText {\r
+ float drawPosX;\r
+ float drawPosY;\r
+ TextLayout layout; \r
+ \r
+ public PositionedText(float drawPosX, float drawPosY, TextLayout layout) {\r
+ this.drawPosX = drawPosX;\r
+ this.drawPosY = drawPosY;\r
+ this.layout = layout;\r
+ }\r
+ \r
+ public void render(Graphics2D g) {\r
+ layout.draw(g, drawPosX, drawPosY);\r
+ }\r
+ }\r
+}\r