TextRenderer.java

00001 package edu.stanford.hci.r3.render.regions;
00002 
00003 import java.awt.Color;
00004 import java.awt.Font;
00005 import java.awt.Graphics2D;
00006 import java.awt.font.FontRenderContext;
00007 import java.awt.font.LineBreakMeasurer;
00008 import java.awt.font.LineMetrics;
00009 import java.awt.font.TextAttribute;
00010 import java.awt.font.TextLayout;
00011 import java.text.AttributedCharacterIterator;
00012 import java.text.AttributedString;
00013 
00014 import edu.stanford.hci.r3.paper.regions.TextRegion;
00015 import edu.stanford.hci.r3.render.RegionRenderer;
00016 import edu.stanford.hci.r3.units.Points;
00017 
00029 public class TextRenderer extends RegionRenderer {
00030 
00031         private Font font;
00032 
00036         private LineMetrics lineMetrics;
00037 
00038         private String text;
00039 
00043         private Color textColor;
00044 
00048         public TextRenderer(TextRegion tr) {
00049                 super(tr);
00050                 region = tr;
00051                 text = tr.getText();
00052                 font = tr.getFont();
00053                 textColor = tr.getColor();
00054                 lineMetrics = font.getLineMetrics(text, new FontRenderContext(null, true, true));
00055         }
00056 
00060         public Points getAscentInPoints() {
00061                 return new Points(lineMetrics.getAscent());
00062         }
00063 
00067         public Points getLineHeightInPoints() {
00068                 return new Points(lineMetrics.getHeight());
00069         }
00070 
00074         public void renderToG2D(Graphics2D g2d) {
00075                 if (RegionRenderer.DEBUG_REGIONS) {
00076                         super.renderToG2D(g2d);
00077                 }
00078 
00079                 final TextRegion tr = (TextRegion) region;
00080 
00081                 // so that we can reset it later
00082                 final Font oldFont = g2d.getFont();
00083 
00084                 g2d.setColor(textColor);
00085                 
00086                 if (!tr.isLineWrapped()) {
00087                         g2d.setFont(tr.getFont());
00088                         // System.out.println(tr.getFont());
00089 
00090                         final double offset = getAscentInPoints().getValue();
00091                         final double textLineHeight = getLineHeightInPoints().getValue();
00092 
00093                         // handle multiple lines
00094                         final String[] linesOfText = tr.getLinesOfText();
00095                         final int xOffset = (int) Math.round(tr.getX().getValueInPoints());
00096                         double yOffset = tr.getY().getValueInPoints() + offset;
00097                         for (String line : linesOfText) {
00098                                 g2d.drawString(line, xOffset, (int) Math.round(yOffset));
00099                                 yOffset += textLineHeight;
00100                         }
00101 
00102                 } else {  // isLineWrapped is true
00103                         float xOffset, yOffset, maxYOffset, wrappingWidth, linebreakOffset;
00104                         xOffset = (float) tr.getX().getValueInPoints();
00105                         yOffset = (float) tr.getY().getValueInPoints();
00106                         maxYOffset = yOffset + (float) tr.getHeight().getValueInPoints();
00107                         wrappingWidth = (float) tr.getWidth().getValueInPoints();
00108                         
00109                         FontRenderContext frc = g2d.getFontRenderContext();
00110                         
00111                         final String[] linesOfText = tr.getLinesOfText();
00112                         
00113                         // We'll be done when any of the following occur:
00114                         //   - We run out of text to set
00115                         //   - Our "pen" moves below the lower bound of the region
00116                         //   - We set the number of lines specified by maxLines (when maxLines > 0)
00117                         boolean done = false;
00118                         int lineCount = 0;
00119                         linebreakOffset = 0.0f;
00120                         for (String line : linesOfText) {
00121                                 // Can't layout an empty string (this will happen with consecutive newlines)
00122                                 // so if we have one, make it a space instead.
00123                                 if (line.length() == 0) line = " ";
00124                                 
00125                                 // Turn the string into an AttributedString, with an Attribute that is the font
00126                                 AttributedString styledText = new AttributedString(line);
00127                                 AttributedCharacterIterator styledTextIterator = styledText.getIterator();
00128                                 styledText.addAttribute(TextAttribute.FONT, tr.getFont());
00129 
00130                                 LineBreakMeasurer measurer = new LineBreakMeasurer(styledTextIterator, frc);
00131 
00132                                 while (measurer.getPosition() < styledTextIterator.getEndIndex()) {
00133                                         // Layout the next line of text
00134                                         TextLayout layout = measurer.nextLayout(wrappingWidth);
00135                                         linebreakOffset = (layout.getAscent() + layout.getDescent() + layout.getLeading())/2;
00136                                         yOffset += (layout.getAscent());
00137                                         float dx = layout.isLeftToRight() ? 0 : (wrappingWidth - layout.getAdvance());
00138 
00139                                         // Determine if the baseline of this line of text would be placed outside the region 
00140                                         if (yOffset > maxYOffset) {
00141                                                 done = true;
00142                                                 break;
00143                                         }
00144 
00145                                         // Draw the text
00146                                         layout.draw(g2d, xOffset + dx, yOffset);
00147                                         
00148                                         // Move the pen down to the next line
00149                                         yOffset += layout.getDescent() + layout.getLeading();
00150                                         lineCount++;
00151                                         if (tr.getMaxLines() > 0 && lineCount >= tr.getMaxLines()) {
00152                                                 done = true;
00153                                                 break;
00154                                         }
00155                                 }
00156                                 
00157                                 yOffset += linebreakOffset;
00158                                 
00159                                 if (done) break;
00160                         }
00161 
00162                 }
00163                 
00164                 // reset the font
00165                 g2d.setFont(oldFont);
00166         }
00167 
00168 }

Generated on Sat Apr 14 18:21:39 2007 for R3 Paper Toolkit by  doxygen 1.4.7