1 28 package net.sf.jasperreports.engine.export; 29 30 import java.awt.Graphics2D ; 31 import java.awt.font.FontRenderContext ; 32 import java.awt.font.LineBreakMeasurer ; 33 import java.awt.font.TextLayout ; 34 import java.text.AttributedCharacterIterator ; 35 import java.text.AttributedString ; 36 import java.util.StringTokenizer ; 37 38 import net.sf.jasperreports.engine.JRAlignment; 39 import net.sf.jasperreports.engine.util.JRProperties; 40 import net.sf.jasperreports.engine.util.JRStyledText; 41 import net.sf.jasperreports.engine.util.MaxFontSizeFinder; 42 43 44 48 public class TextRenderer 49 { 50 public static final FontRenderContext LINE_BREAK_FONT_RENDER_CONTEXT = new FontRenderContext (null, true, true); 51 52 private Graphics2D grx = null; 53 private int x = 0; 54 private int y = 0; 55 private int topPadding = 0; 56 private int leftPadding = 0; 57 private float formatWidth = 0; 58 private float verticalOffset = 0; 59 private float lineSpacingFactor = 0; 60 private float leadingOffset = 0; 61 private float textHeight = 0; 62 private float drawPosY = 0; 63 private float drawPosX = 0; 64 private boolean isMaxHeightReached = false; 65 private byte horizontalAlignment = 0; 66 private int fontSize = 0; 67 68 71 private MaxFontSizeFinder maxFontSizeFinder = null; 72 73 76 private boolean isMinimizePrinterJobSize = true; 77 78 79 82 public static TextRenderer getInstance() 83 { 84 return new TextRenderer(JRProperties.getBooleanProperty(JRGraphics2DExporter.MINIMIZE_PRINTER_JOB_SIZE)); 85 } 86 87 88 91 public TextRenderer(boolean isMinimizePrinterJobSize) 92 { 93 this.isMinimizePrinterJobSize = isMinimizePrinterJobSize; 94 } 95 96 97 100 public void render( 101 Graphics2D initGrx, 102 int initX, 103 int initY, 104 int initWidth, 105 int initHeight, 106 int initTopPadding, 107 int initLeftPadding, 108 int initBottomPadding, 109 int initRightPadding, 110 float initTextHeight, 111 byte initHorizontalAlignment, 112 byte initVerticalAlignment, 113 float initLineSpacingFactor, 114 float initLeadingOffset, 115 int initFontSize, 116 boolean isStyledText, 117 JRStyledText styledText, 118 String allText 119 ) 120 { 121 122 initialize( 123 initGrx, 124 initX, 125 initY, 126 initWidth, 127 initHeight, 128 initTopPadding, 129 initLeftPadding, 130 initBottomPadding, 131 initRightPadding, 132 initTextHeight, 133 initHorizontalAlignment, 134 initVerticalAlignment, 135 initLineSpacingFactor, 136 initLeadingOffset, 137 initFontSize, 138 isStyledText 139 ); 140 141 AttributedCharacterIterator allParagraphs = styledText.getAttributedString().getIterator(); 142 143 int tokenPosition = 0; 144 int lastParagraphStart = 0; 145 String lastParagraphText = null; 146 147 StringTokenizer tkzer = new StringTokenizer (allText, "\n", true); 148 149 while(tkzer.hasMoreTokens() && !isMaxHeightReached) 150 { 151 String token = tkzer.nextToken(); 152 153 if ("\n".equals(token)) 154 { 155 renderParagraph(allParagraphs, lastParagraphStart, lastParagraphText); 156 157 lastParagraphStart = tokenPosition; 158 lastParagraphText = null; 159 } 160 else 161 { 162 lastParagraphStart = tokenPosition; 163 lastParagraphText = token; 164 } 165 166 tokenPosition += token.length(); 167 } 168 169 if (!isMaxHeightReached && lastParagraphStart < allText.length()) 170 { 171 renderParagraph(allParagraphs, lastParagraphStart, lastParagraphText); 172 } 173 } 174 175 176 179 private void initialize( 180 Graphics2D initGrx, 181 int initX, 182 int initY, 183 int initWidth, 184 int initHeight, 185 int initTopPadding, 186 int initLeftPadding, 187 int initBottomPadding, 188 int initRightPadding, 189 float initTextHeight, 190 byte initHorizontalAlignment, 191 byte initVerticalAlignment, 192 float initLineSpacingFactor, 193 float initLeadingOffset, 194 int initFontSize, 195 boolean isStyledText 196 ) 197 { 198 this.grx = initGrx; 199 200 this.horizontalAlignment = initHorizontalAlignment; 201 202 verticalOffset = 0f; 203 switch (initVerticalAlignment) 204 { 205 case JRAlignment.VERTICAL_ALIGN_TOP : 206 { 207 verticalOffset = 0f; 208 break; 209 } 210 case JRAlignment.VERTICAL_ALIGN_MIDDLE : 211 { 212 verticalOffset = (initHeight - initTopPadding - initBottomPadding - initTextHeight) / 2f; 213 break; 214 } 215 case JRAlignment.VERTICAL_ALIGN_BOTTOM : 216 { 217 verticalOffset = initHeight - initTopPadding - initBottomPadding - initTextHeight; 218 break; 219 } 220 default : 221 { 222 verticalOffset = 0f; 223 } 224 } 225 226 this.lineSpacingFactor = initLineSpacingFactor; 227 this.leadingOffset = initLeadingOffset; 228 229 this.x = initX; 230 this.y = initY; 231 this.topPadding = initTopPadding; 232 this.leftPadding = initLeftPadding; 233 formatWidth = initWidth - initLeftPadding - initRightPadding; 234 formatWidth = formatWidth < 0 ? 0 : formatWidth; 235 this.textHeight = initTextHeight; 236 237 drawPosY = 0; 238 drawPosX = 0; 239 240 isMaxHeightReached = false; 241 242 this.fontSize = initFontSize; 243 maxFontSizeFinder = MaxFontSizeFinder.getInstance(isStyledText); 244 } 245 246 249 private void renderParagraph( 250 AttributedCharacterIterator allParagraphs, 251 int lastParagraphStart, 252 String lastParagraphText 253 ) 254 { 255 AttributedCharacterIterator paragraph = null; 256 257 if (lastParagraphText == null) 258 { 259 paragraph = 260 new AttributedString ( 261 " ", 262 new AttributedString ( 263 allParagraphs, 264 lastParagraphStart, 265 lastParagraphStart + 1 266 ).getIterator().getAttributes() 267 ).getIterator(); 268 } 269 else 270 { 271 paragraph = 272 new AttributedString ( 273 allParagraphs, 274 lastParagraphStart, 275 lastParagraphStart + lastParagraphText.length() 276 ).getIterator(); 277 } 278 279 LineBreakMeasurer lineMeasurer = new LineBreakMeasurer (paragraph, LINE_BREAK_FONT_RENDER_CONTEXT); 281 while (lineMeasurer.getPosition() < paragraph.getEndIndex() && !isMaxHeightReached) 282 { 283 int startIndex = lineMeasurer.getPosition(); 285 287 TextLayout layout = lineMeasurer.nextLayout(formatWidth); 288 289 if (isMinimizePrinterJobSize) 290 { 291 AttributedString tmpText = 293 new AttributedString ( 294 paragraph, 295 startIndex, 296 startIndex + layout.getCharacterCount() 297 ); 298 layout = new TextLayout (tmpText.getIterator(), grx.getFontRenderContext()); 299 } 301 302 float lineHeight = lineSpacingFactor * 303 maxFontSizeFinder.findMaxFontSize( 304 new AttributedString ( 305 paragraph, 306 startIndex, 307 startIndex + layout.getCharacterCount() 308 ).getIterator(), 309 fontSize 310 ); 311 312 if (drawPosY + lineHeight <= textHeight) 313 { 314 drawPosY += lineHeight; 315 316 switch (horizontalAlignment) 317 { 318 case JRAlignment.HORIZONTAL_ALIGN_JUSTIFIED : 319 { 320 if (layout.isLeftToRight()) 321 { 322 drawPosX = 0; 323 } 324 else 325 { 326 drawPosX = formatWidth - layout.getAdvance(); 327 } 328 if (lineMeasurer.getPosition() < paragraph.getEndIndex()) 329 { 330 layout = layout.getJustifiedLayout(formatWidth); 331 } 332 333 break; 334 } 335 case JRAlignment.HORIZONTAL_ALIGN_RIGHT : 336 { 337 drawPosX = formatWidth - layout.getAdvance(); 338 break; 339 } 340 case JRAlignment.HORIZONTAL_ALIGN_CENTER : 341 { 342 drawPosX = (formatWidth - layout.getAdvance()) / 2; 343 break; 344 } 345 case JRAlignment.HORIZONTAL_ALIGN_LEFT : 346 default : 347 { 348 drawPosX = 0; 349 } 350 } 351 352 draw(layout); 353 } 354 else 355 { 356 isMaxHeightReached = true; 357 } 358 } 359 } 360 361 364 public void draw(TextLayout layout) 365 { 366 layout.draw( 367 grx, 368 drawPosX + x + leftPadding, 369 drawPosY + y + topPadding + verticalOffset + leadingOffset 370 ); 371 } 372 373 } 374 | Popular Tags |