001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028: package net.sf.jasperreports.engine.export;
029:
030: import java.awt.Graphics2D;
031: import java.awt.font.FontRenderContext;
032: import java.awt.font.LineBreakMeasurer;
033: import java.awt.font.TextLayout;
034: import java.text.AttributedCharacterIterator;
035: import java.text.AttributedString;
036: import java.util.StringTokenizer;
037:
038: import net.sf.jasperreports.engine.JRAlignment;
039: import net.sf.jasperreports.engine.util.JRProperties;
040: import net.sf.jasperreports.engine.util.JRStyledText;
041: import net.sf.jasperreports.engine.util.MaxFontSizeFinder;
042:
043: /**
044: * @author Teodor Danciu (teodord@users.sourceforge.net)
045: * @version $Id: TextRenderer.java 1469 2006-11-08 14:37:14Z teodord $
046: */
047: public class TextRenderer {
048: public static final FontRenderContext LINE_BREAK_FONT_RENDER_CONTEXT = new FontRenderContext(
049: null, true, true);
050:
051: private Graphics2D grx = null;
052: private int x = 0;
053: private int y = 0;
054: private int topPadding = 0;
055: private int leftPadding = 0;
056: private float formatWidth = 0;
057: private float verticalOffset = 0;
058: private float lineSpacingFactor = 0;
059: private float leadingOffset = 0;
060: private float textHeight = 0;
061: private float drawPosY = 0;
062: private float drawPosX = 0;
063: private boolean isMaxHeightReached = false;
064: private byte horizontalAlignment = 0;
065: private int fontSize = 0;
066:
067: /**
068: *
069: */
070: private MaxFontSizeFinder maxFontSizeFinder = null;
071:
072: /**
073: *
074: */
075: private boolean isMinimizePrinterJobSize = true;
076:
077: /**
078: *
079: */
080: public static TextRenderer getInstance() {
081: return new TextRenderer(
082: JRProperties
083: .getBooleanProperty(JRGraphics2DExporter.MINIMIZE_PRINTER_JOB_SIZE));
084: }
085:
086: /**
087: *
088: */
089: public TextRenderer(boolean isMinimizePrinterJobSize) {
090: this .isMinimizePrinterJobSize = isMinimizePrinterJobSize;
091: }
092:
093: /**
094: *
095: */
096: public void render(Graphics2D initGrx, int initX, int initY,
097: int initWidth, int initHeight, int initTopPadding,
098: int initLeftPadding, int initBottomPadding,
099: int initRightPadding, float initTextHeight,
100: byte initHorizontalAlignment, byte initVerticalAlignment,
101: float initLineSpacingFactor, float initLeadingOffset,
102: int initFontSize, boolean isStyledText,
103: JRStyledText styledText, String allText) {
104: /* */
105: initialize(initGrx, initX, initY, initWidth, initHeight,
106: initTopPadding, initLeftPadding, initBottomPadding,
107: initRightPadding, initTextHeight,
108: initHorizontalAlignment, initVerticalAlignment,
109: initLineSpacingFactor, initLeadingOffset, initFontSize,
110: isStyledText);
111:
112: AttributedCharacterIterator allParagraphs = styledText
113: .getAttributedString().getIterator();
114:
115: int tokenPosition = 0;
116: int lastParagraphStart = 0;
117: String lastParagraphText = null;
118:
119: StringTokenizer tkzer = new StringTokenizer(allText, "\n", true);
120:
121: while (tkzer.hasMoreTokens() && !isMaxHeightReached) {
122: String token = tkzer.nextToken();
123:
124: if ("\n".equals(token)) {
125: renderParagraph(allParagraphs, lastParagraphStart,
126: lastParagraphText);
127:
128: lastParagraphStart = tokenPosition;
129: lastParagraphText = null;
130: } else {
131: lastParagraphStart = tokenPosition;
132: lastParagraphText = token;
133: }
134:
135: tokenPosition += token.length();
136: }
137:
138: if (!isMaxHeightReached
139: && lastParagraphStart < allText.length()) {
140: renderParagraph(allParagraphs, lastParagraphStart,
141: lastParagraphText);
142: }
143: }
144:
145: /**
146: *
147: */
148: private void initialize(Graphics2D initGrx, int initX, int initY,
149: int initWidth, int initHeight, int initTopPadding,
150: int initLeftPadding, int initBottomPadding,
151: int initRightPadding, float initTextHeight,
152: byte initHorizontalAlignment, byte initVerticalAlignment,
153: float initLineSpacingFactor, float initLeadingOffset,
154: int initFontSize, boolean isStyledText) {
155: this .grx = initGrx;
156:
157: this .horizontalAlignment = initHorizontalAlignment;
158:
159: verticalOffset = 0f;
160: switch (initVerticalAlignment) {
161: case JRAlignment.VERTICAL_ALIGN_TOP: {
162: verticalOffset = 0f;
163: break;
164: }
165: case JRAlignment.VERTICAL_ALIGN_MIDDLE: {
166: verticalOffset = (initHeight - initTopPadding
167: - initBottomPadding - initTextHeight) / 2f;
168: break;
169: }
170: case JRAlignment.VERTICAL_ALIGN_BOTTOM: {
171: verticalOffset = initHeight - initTopPadding
172: - initBottomPadding - initTextHeight;
173: break;
174: }
175: default: {
176: verticalOffset = 0f;
177: }
178: }
179:
180: this .lineSpacingFactor = initLineSpacingFactor;
181: this .leadingOffset = initLeadingOffset;
182:
183: this .x = initX;
184: this .y = initY;
185: this .topPadding = initTopPadding;
186: this .leftPadding = initLeftPadding;
187: formatWidth = initWidth - initLeftPadding - initRightPadding;
188: formatWidth = formatWidth < 0 ? 0 : formatWidth;
189: this .textHeight = initTextHeight;
190:
191: drawPosY = 0;
192: drawPosX = 0;
193:
194: isMaxHeightReached = false;
195:
196: this .fontSize = initFontSize;
197: maxFontSizeFinder = MaxFontSizeFinder.getInstance(isStyledText);
198: }
199:
200: /**
201: *
202: */
203: private void renderParagraph(
204: AttributedCharacterIterator allParagraphs,
205: int lastParagraphStart, String lastParagraphText) {
206: AttributedCharacterIterator paragraph = null;
207:
208: if (lastParagraphText == null) {
209: paragraph = new AttributedString(" ", new AttributedString(
210: allParagraphs, lastParagraphStart,
211: lastParagraphStart + 1).getIterator()
212: .getAttributes()).getIterator();
213: } else {
214: paragraph = new AttributedString(allParagraphs,
215: lastParagraphStart, lastParagraphStart
216: + lastParagraphText.length()).getIterator();
217: }
218:
219: LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(
220: paragraph, LINE_BREAK_FONT_RENDER_CONTEXT);//grx.getFontRenderContext()
221:
222: while (lineMeasurer.getPosition() < paragraph.getEndIndex()
223: && !isMaxHeightReached) {
224: //eugene fix - start
225: int startIndex = lineMeasurer.getPosition();
226: //eugene fix - end
227:
228: TextLayout layout = lineMeasurer.nextLayout(formatWidth);
229:
230: if (isMinimizePrinterJobSize) {
231: //eugene fix - start
232: AttributedString tmpText = new AttributedString(
233: paragraph, startIndex, startIndex
234: + layout.getCharacterCount());
235: layout = new TextLayout(tmpText.getIterator(), grx
236: .getFontRenderContext());
237: //eugene fix - end
238: }
239:
240: float lineHeight = lineSpacingFactor
241: * maxFontSizeFinder
242: .findMaxFontSize(
243: new AttributedString(
244: paragraph,
245: startIndex,
246: startIndex
247: + layout
248: .getCharacterCount())
249: .getIterator(), fontSize);
250:
251: if (drawPosY + lineHeight <= textHeight) {
252: drawPosY += lineHeight;
253:
254: switch (horizontalAlignment) {
255: case JRAlignment.HORIZONTAL_ALIGN_JUSTIFIED: {
256: if (layout.isLeftToRight()) {
257: drawPosX = 0;
258: } else {
259: drawPosX = formatWidth - layout.getAdvance();
260: }
261: if (lineMeasurer.getPosition() < paragraph
262: .getEndIndex()) {
263: layout = layout.getJustifiedLayout(formatWidth);
264: }
265:
266: break;
267: }
268: case JRAlignment.HORIZONTAL_ALIGN_RIGHT: {
269: drawPosX = formatWidth - layout.getAdvance();
270: break;
271: }
272: case JRAlignment.HORIZONTAL_ALIGN_CENTER: {
273: drawPosX = (formatWidth - layout.getAdvance()) / 2;
274: break;
275: }
276: case JRAlignment.HORIZONTAL_ALIGN_LEFT:
277: default: {
278: drawPosX = 0;
279: }
280: }
281:
282: draw(layout);
283: } else {
284: isMaxHeightReached = true;
285: }
286: }
287: }
288:
289: /**
290: *
291: */
292: public void draw(TextLayout layout) {
293: layout.draw(grx, drawPosX + x + leftPadding, drawPosY + y
294: + topPadding + verticalOffset + leadingOffset);
295: }
296:
297: }
|