]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.document.linking.ui/src/org/simantics/document/linking/report/pdf/PDFTable.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.document.linking.ui / src / org / simantics / document / linking / report / pdf / PDFTable.java
1 package org.simantics.document.linking.report.pdf;\r
2 \r
3 import java.awt.Color;\r
4 import java.awt.Font;\r
5 import java.awt.Graphics2D;\r
6 import java.awt.Shape;\r
7 import java.awt.font.LineBreakMeasurer;\r
8 import java.awt.font.TextAttribute;\r
9 import java.awt.font.TextLayout;\r
10 import java.net.URL;\r
11 import java.text.AttributedCharacterIterator;\r
12 import java.text.AttributedString;\r
13 import java.util.ArrayList;\r
14 import java.util.Collections;\r
15 import java.util.Hashtable;\r
16 import java.util.List;\r
17 \r
18 import org.simantics.document.linking.report.Document.TextSize;\r
19 import org.simantics.document.linking.report.Table;\r
20 import org.simantics.document.linking.report.TableColumn;\r
21 import org.simantics.document.linking.report.TableColumn.Alignment;\r
22 import org.simantics.document.linking.report.TableRow;\r
23 import org.simantics.document.linking.report.TextItem;\r
24 import org.simantics.document.linking.report.URLItem;\r
25 \r
26 import com.lowagie.text.pdf.PdfAction;\r
27 \r
28 \r
29 public class PDFTable implements Table, PDFElement {\r
30         PDFDocument writer;\r
31         PDFPageStream stream;\r
32         PDFPage startPage;\r
33         \r
34         int currentLine = 0;\r
35         \r
36         List<TableColumn> columns = new ArrayList<TableColumn>();\r
37         List<String> columnNames = new ArrayList<String>();\r
38         List<Integer> columnSizes = new ArrayList<Integer>();\r
39         List<Integer> columnPositions = new ArrayList<Integer>();\r
40         \r
41         TextItem title = null;\r
42         \r
43         boolean headerVisible = true;\r
44         private boolean linesVisible = true;\r
45         private boolean linesPrevVisible = true;\r
46         boolean clipText = false;\r
47         \r
48         int textOffsetX = 2;\r
49         int textOffsetY = 2;\r
50         \r
51         public PDFTable(PDFDocument writer, PDFPageStream stream) {\r
52                 this.writer = writer;\r
53                 this.stream = stream;\r
54                 this.startPage = stream.getCurrentPage();\r
55                 \r
56         }\r
57         \r
58         public PDFTable(PDFTable table) {\r
59                 this.writer = table.writer;\r
60                 this.stream = table.stream;\r
61                 this.startPage = stream.getCurrentPage();\r
62                 this.columns.addAll(table.columns);\r
63                 this.columnNames.addAll(table.columnNames);\r
64                 \r
65                 updateColumnPositions();\r
66         }\r
67         \r
68         \r
69         @Override\r
70         public PDFPage getPage() {\r
71                 return startPage;\r
72         }\r
73         \r
74         /* (non-Javadoc)\r
75          * @see org.simantics.document.linking.report.Table#addColumn(java.lang.String, double)\r
76          */\r
77         @Override\r
78         public TableColumn addColumn(String name, double width) {\r
79                 TableColumn tc = new TableColumn(name, width);\r
80                 columns.add(tc);\r
81                 columnNames.add(name);\r
82                 \r
83                 updateColumnPositions();\r
84                 return tc;\r
85         }\r
86         \r
87         private void updateColumnPositions() {\r
88                 int pos = 0;\r
89                 columnSizes.clear();\r
90                 columnPositions.clear();\r
91                 for (TableColumn c : columns) {\r
92                         int size = (int)(c.getWidth()*stream.getContentWidth());\r
93                         columnSizes.add(size);\r
94                         columnPositions.add(pos);\r
95                         pos+=size;\r
96                 }\r
97         }\r
98         \r
99         @Override\r
100         public List<TableColumn> getColumns() {\r
101                 return columns;\r
102         }\r
103         \r
104         @Override\r
105         public boolean isLinesVisible() {\r
106                 return linesVisible;\r
107         }\r
108         \r
109         @Override\r
110         public void setLinesVisible(boolean b) {\r
111                 if (this.linesVisible == b)\r
112                         return;\r
113                 this.linesPrevVisible = linesVisible;\r
114                 this.linesVisible = b;\r
115         }\r
116         \r
117         @Override\r
118         public boolean isHeaderVisible() {\r
119                 return headerVisible;\r
120         }\r
121         \r
122         @Override\r
123         public void setHeaderVisible(boolean b) {\r
124                 this.headerVisible = b;\r
125         }\r
126         \r
127         private boolean isFirstLine() {\r
128                 return currentLine == 0 || stream.getCurrentPage().currentLine == 1;\r
129         }\r
130         \r
131         @Override\r
132         public void setTitle(String title) {\r
133                 try {\r
134                         this.title = writer.newItem(TextItem.class);\r
135                         this.title.setText(title);\r
136                 } catch (Exception e) {\r
137                         \r
138                 }\r
139         }\r
140         \r
141         @Override\r
142         public void setTitle(TextItem title){\r
143                 this.title = title;\r
144         }\r
145         \r
146         /* (non-Javadoc)\r
147          * @see org.simantics.document.linking.report.Table#writeRow(java.lang.String[])\r
148          */\r
149         @Override\r
150         public TableRow writeRow(String... line) throws Exception{\r
151                 List<String> list = new ArrayList<String>(line.length);\r
152                 for (String s : line)\r
153                         list.add(s);\r
154                 return writeRow(list);\r
155         }\r
156         \r
157         /* (non-Javadoc)\r
158          * @see org.simantics.document.linking.report.Table#writeRow(java.util.List)\r
159          */\r
160         @Override\r
161         public TableRow writeRow(List<String> line) throws Exception{\r
162                 if (isFirstLine())\r
163                         writeHeader();\r
164                 return _writeRow(line);\r
165         }\r
166         \r
167         @Override\r
168         public TableRow writeRowItem(TextItem... line) throws Exception {\r
169                 List<TextItem> list = new ArrayList<TextItem>(line.length);\r
170                 for (TextItem s : line)\r
171                         list.add(s);\r
172                 return writeRowItem(list);\r
173         }\r
174         \r
175         @Override\r
176         public TableRow writeRowItem(List<TextItem> line) throws Exception {\r
177                 if (isFirstLine())\r
178                         writeHeader();\r
179                 return _writeRow2(line);\r
180         }\r
181         \r
182         private TableRow _writeRow(List<String> line) throws Exception {\r
183                 int h = getTextHeight();\r
184                 int ht = getTopHeight();\r
185                 int hb = getBottomHeight();\r
186                 PDFPage page = getCurrentPage();\r
187                 Graphics2D g2d = page.g2d;\r
188                 Shape clip = g2d.getClip();\r
189                 \r
190                 if (clipText) {\r
191                         for (int i = 0; i < line.size(); i++) {\r
192                                 if (line.get(i) == null)\r
193                                         continue;\r
194                                 g2d.setClip(columnPositions.get(i),ht-1,columnSizes.get(i),hb-ht+2);\r
195                                 g2d.drawString(line.get(i), columnPositions.get(i)+textOffsetX, h);\r
196                         }\r
197                         g2d.setClip(clip);\r
198                         if (linesVisible) {\r
199                                 for (int i = 0; i < line.size(); i++) {\r
200                                         g2d.drawLine(columnPositions.get(i), ht, columnPositions.get(i), hb);\r
201                                 }\r
202                                 if (isFirstLine() || !linesPrevVisible) {\r
203                                         g2d.drawLine(0, ht, stream.contentWidth, ht);\r
204                                         linesPrevVisible = true;\r
205                                 }\r
206                                 g2d.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
207                                 g2d.drawLine(0, hb, stream.contentWidth, hb);\r
208                         }\r
209                         currentLine++;\r
210                         page.currentLine++;\r
211                         page.availableLines--;\r
212                         page.currentPixel += getLineHeight();\r
213                 } else {\r
214                         PositionedRow row = _getRow(line);\r
215                         if (stream.contentHeight-page.currentPixel < row.reservedSpace) {\r
216                                 stream.nextPage();\r
217                                 page = getCurrentPage();\r
218                                 g2d = page.g2d;\r
219                                 writeHeader();\r
220                                 row = _getRow(line);\r
221                         }\r
222                         row.render(g2d);\r
223                         currentLine+= row.realLines;\r
224                         page.currentLine+= row.realLines;\r
225                         page.currentPixel += row.reservedSpace;\r
226                         page.estimateAvailableLines();\r
227                 }\r
228                 \r
229                 stream.checkNextPage();\r
230                 return new PDFTableRow();\r
231         }\r
232         \r
233         private TableRow _writeRow2(List<TextItem> line) throws Exception {\r
234                 int h = getTextHeight();\r
235                 int ht = getTopHeight();\r
236                 int hb = getBottomHeight();\r
237                 PDFPage page = getCurrentPage();\r
238                 Graphics2D g2d = page.g2d;\r
239                 Shape clip = g2d.getClip();\r
240                 \r
241                 if (clipText) {\r
242                         for (int i = 0; i < line.size(); i++) {\r
243                                 TextItem text = line.get(i);\r
244                                 if (text == null)\r
245                                         continue;\r
246                                 g2d.setClip(columnPositions.get(i),ht,columnSizes.get(i),hb-ht);\r
247                                 g2d.drawString(text.getText(), columnPositions.get(i)+textOffsetX, h);\r
248                                 if (text instanceof URLItem) {\r
249                                         URL url = ((URLItem)text).getURL();\r
250                                         if (url != null) {\r
251                                                 addLink(url, columnPositions.get(i),ht,columnSizes.get(i),hb-ht);\r
252                                         }\r
253                                 }\r
254                         }\r
255                         g2d.setClip(clip);\r
256                         if (linesVisible) {\r
257                                 for (int i = 0; i < line.size(); i++) {\r
258                                         g2d.drawLine(columnPositions.get(i), ht, columnPositions.get(i), hb);\r
259                                 }\r
260                                 if (isFirstLine() || !linesPrevVisible) {\r
261                                         g2d.drawLine(0, ht, stream.contentWidth, ht);\r
262                                         linesPrevVisible = true;\r
263                                 }\r
264                                 g2d.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
265                                 g2d.drawLine(0, hb, stream.contentWidth, hb);\r
266                         }\r
267                         currentLine++;\r
268                         page.currentLine++;\r
269                         page.availableLines--;\r
270                         page.currentPixel += getLineHeight();\r
271                 } else {\r
272                         PositionedRow row = _getRow2(line);\r
273                         if (stream.contentHeight-page.currentPixel < row.reservedSpace) {\r
274                                 stream.nextPage();\r
275                                 page = getCurrentPage();\r
276                                 g2d = page.g2d;\r
277                                 writeHeader();\r
278                                 row = _getRow2(line);\r
279                         }\r
280                         row.render(g2d);\r
281                         currentLine+= row.realLines;\r
282                         page.currentLine+= row.realLines;\r
283                         page.currentPixel += row.reservedSpace;\r
284                         page.estimateAvailableLines();\r
285                 }\r
286                 \r
287                 stream.checkNextPage();\r
288                 return new PDFTableRow();\r
289         }\r
290         \r
291         void writeLine(String line) throws Exception{\r
292                 writeLine(line, 0);\r
293         }\r
294         \r
295         void writeLine(TextItem line) throws Exception{\r
296                 writeLine(line, 0);\r
297         }\r
298         \r
299         private void writeHeader() throws Exception{\r
300                 if (headerVisible) {\r
301                         TextSize s = currentTextSize;\r
302                         setTextSize(TextSize.MEDIUM);\r
303                         if (title != null) {\r
304                                 boolean b = linesVisible;\r
305                                 setLinesVisible(false);\r
306                                 writeLine(title);\r
307                                 setLinesVisible(b);\r
308                         }\r
309                         _writeRow(columnNames);\r
310                         setTextSize(s);\r
311                 }\r
312         }\r
313         \r
314         void writeLine(String line, int x) throws Exception{\r
315                 int h = getTextHeight();\r
316                 int ht = getTopHeight();\r
317                 int hb = getBottomHeight();\r
318                 PDFPage page = getCurrentPage();\r
319                 Graphics2D g2d = page.g2d;\r
320                 g2d.drawString(line, x+textOffsetX, h);\r
321                 if (linesVisible) {\r
322                         if (isFirstLine() || !linesPrevVisible) {\r
323                                 g2d.drawLine(0, ht, stream.contentWidth, ht);\r
324                                 linesPrevVisible = true;\r
325                         }\r
326                         g2d.drawLine(0, ht, 0, hb);\r
327                         g2d.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
328                         g2d.drawLine(0, hb, stream.contentWidth, hb);\r
329                 }\r
330                 currentLine++;\r
331                 page.currentLine++;\r
332                 page.availableLines--;\r
333                 page.currentPixel += getLineHeight();\r
334                 stream.checkNextPage();\r
335         }\r
336         \r
337         void writeLine(TextItem line, int x) throws Exception{\r
338                 int h = getTextHeight();\r
339                 int ht = getTopHeight();\r
340                 int hb = getBottomHeight();\r
341                 PDFPage page = getCurrentPage();\r
342                 Graphics2D g2d = page.g2d;\r
343                 g2d.drawString(line.getText(), x+textOffsetX, h);\r
344                 if (linesVisible) {\r
345                         if (isFirstLine() || !linesPrevVisible) {\r
346                                 g2d.drawLine(0, ht, stream.contentWidth, ht);\r
347                                 linesPrevVisible = true;\r
348                         }\r
349                         g2d.drawLine(0, ht, 0, hb);\r
350                         g2d.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
351                         g2d.drawLine(0, hb, stream.contentWidth, hb);\r
352                 }\r
353                 if (line instanceof URLItem) {\r
354                         URL url = ((URLItem)line).getURL();\r
355                         if (url != null) {\r
356                                 addLink(url, 0,ht,stream.contentWidth,hb-ht);\r
357                         }\r
358                 }\r
359                 currentLine++;\r
360                 page.currentLine++;\r
361                 page.availableLines--;\r
362                 page.currentPixel += getLineHeight();\r
363                 stream.checkNextPage();\r
364         }\r
365         \r
366         int getTopHeight() {\r
367                 return getTopHeight(currentLine);\r
368         }\r
369         \r
370         int getTopHeight(int line) {\r
371                 return (line-currentLine)*getLineHeight()+getCurrentPage().currentPixel;\r
372         }\r
373         \r
374         int getTextHeight() {\r
375                 PDFPage page = getCurrentPage();\r
376                 return page.currentPixel+getLineHeight()-page.fm.getDescent()-textOffsetY;\r
377         }\r
378         \r
379         PDFPage getCurrentPage() {\r
380                 return stream.getCurrentPage();\r
381         }\r
382         \r
383         int getBottomHeight() {\r
384                 return getBottomHeight(currentLine);\r
385         }\r
386         \r
387         protected int getLineHeight() {\r
388                 return getCurrentPage().fm.getHeight()+textOffsetY;\r
389         }\r
390         \r
391         private int getBottomHeight(int line) {\r
392                 return (line-currentLine+1)*getLineHeight()+getCurrentPage().currentPixel;\r
393         }\r
394         \r
395         public int getAvailableLines() {\r
396                 PDFPage page = getCurrentPage();\r
397                 int contentHeight = stream.contentHeight;\r
398                 int pixelY = page.currentPixel;\r
399                 return (int)Math.floor((contentHeight-pixelY)/getLineHeight());\r
400         }\r
401         \r
402         private TextSize currentTextSize = TextSize.SMALL;\r
403         \r
404         @Override\r
405         public void setTextSize(TextSize size) {\r
406                 stream.getCurrentPage().setFont(writer.fonts.get(size));\r
407                 currentTextSize = size;\r
408         }\r
409         \r
410         @Override\r
411         public TextSize getTextSize() {\r
412                 return currentTextSize;\r
413         }\r
414         \r
415         private PositionedRow _getRow(List<String> line) {\r
416                 PositionedRow row = new PositionedRow();\r
417                 int h = getTextHeight();\r
418                 int realLines = 1;\r
419                 int reservedSpace = 0;\r
420                 List<List<PositionedText>> cells = new ArrayList<List<PositionedText>>(line.size());\r
421                 if (line.size() > 1) {\r
422                         for (int i = 0; i < line.size(); i++) {\r
423                                 String text = line.get(i);\r
424                                 int availableSize = columnSizes.get(i)-textOffsetX;\r
425                                 if (text != null && text.length() > 0) {\r
426                                         List<PositionedText> pt = getText(text,  columnPositions.get(i)+textOffsetX, h,availableSize, columns.get(i).getAlignment());\r
427                                         cells.add(pt);\r
428                                         reservedSpace = Math.max(reservedSpace, getResevedSpace(pt)+getLineHeight());\r
429                                         realLines = Math.max(realLines, getLineSpace(pt));\r
430                                 } else {\r
431                                         cells.add(Collections.<PositionedText> emptyList());\r
432                                         reservedSpace = Math.max(reservedSpace, getLineHeight());\r
433                                 }\r
434                         }\r
435                 } else {\r
436                         String text = line.get(0);\r
437                         int availableSize = stream.contentWidth;\r
438                         if (text != null && text.length() > 0) {\r
439                                 List<PositionedText> pt = getText(text,  textOffsetX, h,availableSize, columns.get(0).getAlignment());\r
440                                 cells.add(pt);\r
441                                 reservedSpace = Math.max(reservedSpace, getResevedSpace(pt)+getLineHeight());\r
442                                 realLines = Math.max(realLines, getLineSpace(pt));\r
443                         } else {\r
444                                 cells.add(Collections.<PositionedText> emptyList());\r
445                                 reservedSpace = Math.max(reservedSpace, getLineHeight());\r
446                         }\r
447                 }\r
448                 row.reservedSpace = reservedSpace;\r
449                 row.startLine = currentLine;\r
450                 row.realLines = realLines;\r
451                 row.cells = cells;\r
452                 return row;\r
453         }\r
454         \r
455         private PositionedRow _getRow2(List<TextItem> line) {\r
456                 PositionedRow row = new PositionedRow();\r
457                 int h = getTextHeight();\r
458                 int realLines = 1;\r
459                 int reservedSpace = 0;\r
460                 row.cells = new ArrayList<List<PositionedText>>(line.size());\r
461                 row.urls = new ArrayList<URL>();\r
462                 if (line.size() > 1) {\r
463                         for (int i = 0; i < line.size(); i++) {\r
464                                 TextItem item =line.get(i); \r
465                                 \r
466                                 int availableSize = columnSizes.get(i)-textOffsetX;\r
467                                 if (item != null && item.getText().length() > 0) {\r
468                                         String text = item.getText();\r
469                                         List<PositionedText> pt = getText(text,  columnPositions.get(i)+textOffsetX, h,availableSize, columns.get(i).getAlignment());\r
470                                         row.cells.add(pt);\r
471                                         reservedSpace = Math.max(reservedSpace, getResevedSpace(pt)+getLineHeight());\r
472                                         realLines = Math.max(realLines, getLineSpace(pt));\r
473                                 } else {\r
474                                         row.cells.add(Collections.<PositionedText> emptyList());\r
475                                         reservedSpace = Math.max(reservedSpace, getLineHeight());\r
476                                 }\r
477                                 if (item instanceof URLItem) {\r
478                                         row.urls.add(((URLItem)item).getURL());\r
479                                 } else {\r
480                                         row.urls.add(null);\r
481                                 }\r
482                         }\r
483                 \r
484                 } else {\r
485                         String text = line.get(0).getText();\r
486                         int availableSize = stream.contentWidth;\r
487                         if (text != null && text.length() > 0) {\r
488                                 List<PositionedText> pt = getText(text,  textOffsetX, h,availableSize, columns.get(0).getAlignment());\r
489                                 row.cells.add(pt);\r
490                                 reservedSpace = Math.max(reservedSpace, getResevedSpace(pt)+getLineHeight());\r
491                                 realLines = Math.max(realLines, getLineSpace(pt));\r
492                         } else {\r
493                                 row.cells.add(Collections.<PositionedText> emptyList());\r
494                                 reservedSpace = Math.max(reservedSpace, getLineHeight());\r
495                         }\r
496                 }\r
497                 row.reservedSpace = reservedSpace;\r
498                 row.startLine = currentLine;\r
499                 row.realLines = realLines;\r
500                 return row;\r
501         }\r
502         \r
503         private int getResevedSpace(List<PositionedText> pt) {\r
504                 float sy = pt.get(0).drawPosY;\r
505                 float ey = pt.get(pt.size()-1).drawPosY;\r
506                 return (int)Math.ceil(ey-sy);\r
507         }\r
508         /**\r
509          * 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
510          * @param pt\r
511          * @return\r
512          */\r
513         private int getLineSpace(List<PositionedText> pt) {\r
514                 if (pt.size() < 2)\r
515                         return 1;\r
516                 \r
517                 return (int)(getResevedSpace(pt)/getLineHeight())+1;\r
518         }\r
519         \r
520         private class PositionedRow {\r
521                 int startLine;\r
522                 int realLines;\r
523                 int reservedSpace;\r
524                 List<List<PositionedText>> cells;\r
525                 List<URL> urls;\r
526                 \r
527                 void render(Graphics2D g) {\r
528                         int ht = getTopHeight(startLine);\r
529                         int hb = ht +reservedSpace;\r
530                         if (cells.size() > 0) {\r
531                                 for (int i = 0; i < cells.size(); i++) {\r
532                                         List<PositionedText> ptl = cells.get(i);\r
533                                         for (PositionedText pt : ptl)\r
534                                                 pt.render(g);\r
535                                         if (urls != null) {\r
536                                                 URL url = urls.get(i);\r
537                                                 if (url != null) {\r
538                                                         addLink(url, columnPositions.get(i),ht,columnSizes.get(i),hb-ht);\r
539                                                 }\r
540                                         }\r
541                                 }\r
542                         } \r
543                         if (linesVisible) {\r
544                                 if (cells.size() > 0) {\r
545                                         for (int i = 0; i < cells.size(); i++) {\r
546                                                 g.drawLine(columnPositions.get(i), ht, columnPositions.get(i), hb);\r
547                                         }\r
548                                 } else {\r
549                                         g.drawLine(columnPositions.get(0), ht, columnPositions.get(0), hb);\r
550                                 }\r
551                                 if (isFirstLine() || !linesPrevVisible) {\r
552                                         g.drawLine(0, ht, stream.contentWidth, ht);\r
553                                         linesPrevVisible = true;\r
554                                 }\r
555                                 g.drawLine(stream.contentWidth, ht, stream.contentWidth, hb);\r
556                                 g.drawLine(0, hb, stream.contentWidth, hb);\r
557                                 \r
558                         }\r
559                 }\r
560         }\r
561         \r
562         private void addLink(URL url, int x, int y, int w, int h) {\r
563                 PDFPage page = getCurrentPage();\r
564                 float fx = +page.stream.marginLeft + x;\r
565                 float fy = -page.stream.marginTop + page.template.getHeight() - y;\r
566                 page.template.setAction(new PdfAction(url), fx, fy-h, fx+w, fy);\r
567         }\r
568         \r
569         private List<PositionedText> getText(String text, int x, int y, int cellWidth, Alignment alignment) {\r
570                 List<PositionedText> result = new ArrayList<PositionedText>();\r
571                 Hashtable<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>();\r
572                 PDFPage page = getCurrentPage();\r
573                 Font font = page.getFont();\r
574                 for (TextAttribute a : font.getAttributes().keySet()) {\r
575                         Object v = font.getAttributes().get(a);\r
576                         if (v != null)\r
577                                 map.put(a, v);\r
578                 }\r
579 //              map.putAll(font.getAttributes());\r
580                 map.put(TextAttribute.FOREGROUND, Color.black);\r
581 \r
582                 AttributedString attributedText = new AttributedString( text, map);\r
583 \r
584                 AttributedCharacterIterator paragraph = attributedText.getIterator();\r
585                 int paragraphStart = paragraph.getBeginIndex();\r
586                 int paragraphEnd = paragraph.getEndIndex();\r
587                 LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, page.frc);\r
588                 lineMeasurer.setPosition(paragraphStart);\r
589                 \r
590                 // Get lines until the entire paragraph has been displayed.\r
591         int next, limit, charat, position = 0;\r
592         int drawPosY = y;\r
593         while ((position = lineMeasurer.getPosition()) < paragraphEnd) {\r
594 \r
595             // Find possible line break and set it as a limit to the next layout\r
596             next = lineMeasurer.nextOffset(cellWidth);\r
597             limit = next;\r
598             charat = text.indexOf(System.getProperty("line.separator"),position+1);\r
599             if(charat < next && charat != -1){\r
600                limit = charat;\r
601             }\r
602 \r
603             // Retrieve next layout. A cleverer program would also cache\r
604             // these layouts until the component is re-sized.\r
605             TextLayout layout = lineMeasurer.nextLayout(cellWidth, limit, false);\r
606 \r
607                 // Compute pen x position. If the paragraph is right-to-left we\r
608                 // will align the TextLayouts to the right edge of the panel.\r
609                 // Note: this won't occur for the English text in this sample.\r
610                 // Note: drawPosX is always where the LEFT of the text is placed.\r
611                 float drawPosX = 0;\r
612                 switch (alignment) {\r
613                         case LEFT: \r
614                                 drawPosX = layout.isLeftToRight() ? 0 : cellWidth - layout.getAdvance();\r
615                                 break;\r
616                         case CENTER:\r
617                                 drawPosX = (cellWidth - layout.getAdvance()) / 2;\r
618                                 break;\r
619                         case RIGHT:\r
620                                 drawPosX = layout.isLeftToRight() ? cellWidth - layout.getAdvance() : 0;\r
621                                 break;\r
622                 }\r
623                 \r
624                 drawPosX += x;\r
625                 \r
626                 // If text has been forced to vertical, align it to center\r
627 //              if(breakWidth < textAreaWidth) {\r
628 //                      float centerCorrection = layout.isLeftToRight() ? \r
629 //                                      (float) (layout.getAdvance() / 2) : \r
630 //                                              -1 * (float) (layout.getAdvance() / 2);\r
631 //                      drawPosX = textAreaWidth / 2 - centerCorrection;\r
632 //              }\r
633 \r
634                 // Stop drawing if the text won't fit\r
635 //              if (breakHeight < drawPosY + layout.getDescent() + layout.getLeading()) {\r
636 //                  break;\r
637 //              }\r
638 \r
639 //              drawPosY += layout.getAscent();\r
640 \r
641                 // Add TextLayout at (drawPosX, drawPosY).\r
642                 result.add(new PositionedText(drawPosX, drawPosY, layout));\r
643 \r
644                 // Move y-coordinate in preparation for next layout.\r
645                 //drawPosY += layout.getDescent() + layout.getLeading();\r
646                 drawPosY += layout.getDescent() + layout.getLeading() + layout.getAscent();\r
647 //              drawPosY += getLineHeight();\r
648             }\r
649         return result;\r
650         }\r
651         \r
652         class PositionedText {\r
653         float drawPosX;\r
654         float drawPosY;\r
655         TextLayout layout;      \r
656         \r
657         public PositionedText(float drawPosX, float drawPosY, TextLayout layout) {\r
658             this.drawPosX = drawPosX;\r
659             this.drawPosY = drawPosY;\r
660             this.layout = layout;\r
661         }\r
662         \r
663         public void render(Graphics2D g) {\r
664             layout.draw(g, drawPosX, drawPosY);\r
665         }\r
666     }\r
667 }\r