private synchronized void addLines() { AttributedString aText = prepareAttributedString(); AttributedCharacterIterator styledTextIterator = aText.getIterator(); List<Integer> newlineLocations = getNewlineLocations(styledTextIterator); LineBreakMeasurer lbm = new LineBreakMeasurer(styledTextIterator, getRenderContext()); float width = (float) consumableArea.width; if (width <= 0) return; TextLayout layout; int startOfNextLayout; int currentLine = 0; int endIndex = styledTextIterator.getEndIndex(); do { if (currentLine < newlineLocations.size()) startOfNextLayout = newlineLocations.get(currentLine) + 1; else startOfNextLayout = endIndex + 1; layout = lbm.nextLayout(width, startOfNextLayout, false); lines.add(layout); if (lbm.getPosition() == startOfNextLayout) currentLine += 1; } while (layout != null && lbm.getPosition() < endIndex); }
/** * Calculates the layout. * * @param fontRenderContext the FontRenderContext * @param font the Font * @param text the text * @param layoutWidth the width of the layout area * @return the layout result */ public MultilineLayout calculateLayout( FontRenderContext fontRenderContext, Font font, String text, double layoutWidth) { // Layout multiline text MultilineLayout result = new MultilineLayout(); if (text == null || text.isEmpty()) return result; Map<TextAttribute, Object> styleMap = new HashMap<TextAttribute, Object>(); styleMap.put(TextAttribute.FONT, font); String[] textlines = text.split("\n"); double height = 0; for (String textline : textlines) { AttributedString attribText = new AttributedString(textline, styleMap); AttributedCharacterIterator iter = attribText.getIterator(); int textStart = iter.getBeginIndex(); int textEnd = iter.getEndIndex(); LineBreakMeasurer measurer = new LineBreakMeasurer(iter, fontRenderContext); measurer.setPosition(textStart); while (measurer.getPosition() < textEnd) { TextLayout line = measurer.nextLayout((float) layoutWidth); result.addLine(line); height += (line.getAscent() + line.getDescent() + line.getLeading()); } } result.setSize(layoutWidth, height); return result; }
/** * @param s * @return */ private String[] splitOnBreaks(String s, double maxSize, Font ft) { List<String> al = new ArrayList<String>(); // check hard break first int i = 0, j; do { j = s.indexOf('\n', i); if (j == -1) { j = s.length(); } String ss = s.substring(i, j); if (ss != null && ss.length() > 0) { al.add(ss); } i = j + 1; } while (j != -1 && j < s.length()); // check wrapping if (maxSize > 0) { List<String> nal = new ArrayList<String>(); for (Iterator<String> itr = al.iterator(); itr.hasNext(); ) { String ns = itr.next(); AttributedString as = new AttributedString(ns, ft.getAttributes()); LineBreakMeasurer lbm = new LineBreakMeasurer(as.getIterator(), g2d.getFontRenderContext()); while (lbm.getPosition() < ns.length()) { int next = lbm.nextOffset((float) maxSize); String ss = ns.substring(lbm.getPosition(), next); lbm.setPosition(next); nal.add(ss); } } al = nal; } final int n = al.size(); if (n == 1 || n == 0) { return null; } final String[] sa = new String[n]; for (i = 0; i < al.size(); i++) { sa[i] = al.get(i); } return sa; }
/** * Get the text layouts for display if the string has changed since last call to this method * regenerate them. * * @param g2d Graphics2D display context * @return a list of text layouts for rendering */ public LinkedList<LineInfo> getLines(Graphics2D g2d) { if (font != g2d.getFont()) { setFont(g2d.getFont()); invalidText = true; } if (invalidText) { styledText = new AttributedString(plainText); setFont(font); applyAttributes(); invalidText = false; invalidLayout = true; } if (invalidLayout) { linesInfo.clear(); if (plainText.length() > 0) { textHeight = 0; maxLineLength = 0; maxLineHeight = 0; nbrLines = 0; AttributedCharacterIterator paragraph = styledText.getIterator(null, 0, plainText.length()); FontRenderContext frc = g2d.getFontRenderContext(); lineMeasurer = new LineBreakMeasurer(paragraph, frc); float yposinpara = 0; int charssofar = 0; while (lineMeasurer.getPosition() < plainText.length()) { TextLayout layout = lineMeasurer.nextLayout(wrapWidth); float advance = layout.getVisibleAdvance(); if (justify) { if (justify && advance > justifyRatio * wrapWidth) { // If advance > breakWidth then we have a line break float jw = (advance > wrapWidth) ? advance - wrapWidth : wrapWidth; layout = layout.getJustifiedLayout(jw); } } // Remember the longest and tallest value for a layout so far. float lh = getHeight(layout); if (lh > maxLineHeight) maxLineHeight = lh; textHeight += lh; if (advance <= wrapWidth && advance > maxLineLength) maxLineLength = advance; // Store layout and line info linesInfo.add( new LineInfo(nbrLines, layout, charssofar, layout.getCharacterCount(), yposinpara)); charssofar += layout.getCharacterCount(); yposinpara += lh; nbrLines++; } } invalidLayout = false; } return linesInfo; }
public static Dimension getPreferredSize(JTextArea textArea, int preferredWidth) { Font font = textArea.getFont(); String text = textArea.getText(); Hashtable<Attribute, Object> attributes = new Hashtable<Attribute, Object>(); attributes.put(TextAttribute.FONT, font); /** * It is crucial this be accurate! I used to have it always true/true, and XP sometimes failed * because of it. */ Graphics2D g = ((Graphics2D) textArea.getGraphics()); FontRenderContext frc = null; if (g != null) frc = g.getFontRenderContext(); if (frc == null) { // on Mac "true, false" seemed to be the right combo. // try testing with QOptionPaneDemo in French and see the // external changes dialog frc = new FontRenderContext(null, true, false); } String[] paragraphs = Text.getParagraphs(text); int rows = 0; for (int a = 0; a < paragraphs.length; a++) { int textLength = paragraphs[a].length(); if (Text.isWhiteSpace(paragraphs[a])) { rows++; } else { AttributedString attrString = new AttributedString(paragraphs[a], attributes); LineBreakMeasurer lbm = new LineBreakMeasurer(attrString.getIterator(), frc); int pos = 0; while (pos < textLength) { pos = lbm.nextOffset(preferredWidth); lbm.setPosition(pos); rows++; } } } int extra = 0; if (JVM.isWindowsXP) { // allow for descents extra = (int) (font.getLineMetrics("g", frc).getDescent() + 1); } FontMetrics metrics = textArea.getFontMetrics(font); int rowHeight = metrics.getHeight(); return new Dimension(preferredWidth, rows * rowHeight + extra); }
public String[] getStringLines(String text, int w, int[] out_para) { try { AttributedString atext = new AttributedString(text); atext.addAttribute(TextAttribute.FONT, m_graphics2d.getFont(), 0, text.length()); atext.addAttribute(TextAttribute.SIZE, m_graphics2d.getFont(), 0, text.length()); Vector<String> lines = new Vector<String>(); LineBreakMeasurer textMeasurer = new LineBreakMeasurer(atext.getIterator(), m_graphics2d.getFontRenderContext()); while (textMeasurer.getPosition() >= 0 && textMeasurer.getPosition() < text.length()) { int curr_pos = textMeasurer.getPosition(); int next_pos = curr_pos; int limit = text.indexOf('\n', curr_pos); if (limit >= curr_pos) { next_pos = textMeasurer.nextOffset(w, limit + 1, false); } else { next_pos = textMeasurer.nextOffset(w); } lines.addElement(text.substring(curr_pos, next_pos)); textMeasurer.setPosition(next_pos); } return lines.toArray(new String[lines.size()]); } catch (Throwable err) { err.printStackTrace(); return new String[] {"(Error !)"}; } }
// counts lines public static int countLines(JTextArea textArea) { AttributedString text = new AttributedString(textArea.getText()); FontRenderContext frc = textArea.getFontMetrics(textArea.getFont()).getFontRenderContext(); int lines = 0; if (!textArea.getText().equals("")) { AttributedCharacterIterator charIt = text.getIterator(); LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(charIt, frc); float formatWidth = (float) textArea.getSize().width; lineMeasurer.setPosition(charIt.getBeginIndex()); while (lineMeasurer.getPosition() < charIt.getEndIndex()) { lineMeasurer.nextLayout(formatWidth); lines++; } for (int i = 0; i < textArea.getText().length(); i++) { if (textArea.getText().charAt(i) == '\r' || textArea.getText().charAt(i) == '\n') lines++; } } else { lines = 1; } return lines; }
public StringLayer[] getStringLines(int w, int[] out_para) { try { Vector<StringLayer> lines = new Vector<StringLayer>(); LineBreakMeasurer textMeasurer = new LineBreakMeasurer(AString.getIterator(), m_graphics2d.getFontRenderContext()); while (textMeasurer.getPosition() >= 0 && textMeasurer.getPosition() < Src.length()) { int curr_pos = textMeasurer.getPosition(); int next_pos = curr_pos; int limit = Src.indexOf('\n', curr_pos); if (limit >= curr_pos) { next_pos = textMeasurer.nextOffset(w, limit + 1, false); } else { next_pos = textMeasurer.nextOffset(w); } lines.addElement(new CStringLayer(this, curr_pos, next_pos)); textMeasurer.setPosition(next_pos); } return lines.toArray(new StringLayer[lines.size()]); } catch (Throwable err) { err.printStackTrace(); return new CStringLayer[] {new CStringLayer("(Error !)", null)}; } // try // { // // calc new text space // char ret = '\n'; // char chars[] = Src.toCharArray(); // int prewPos = 0; // Vector<StringLayer> lines = new Vector<StringLayer>(); // // for (int i = 0; i < chars.length; i++) { // if (chars[i] == ret) { // if (prewPos < i+1) { // lines.addElement(new CStringLayer(this, prewPos, i+1)); // } // prewPos = i + 1; // continue; // } // else if (getStringWidth(new String(chars, prewPos, i - prewPos + 1)) > w) { // if (prewPos < i) { // lines.addElement(new CStringLayer(this, prewPos, i)); // } // prewPos = i + 0; // continue; // } // else if (i == chars.length - 1) { // if (prewPos < chars.length) { // lines.addElement(new CStringLayer(this, prewPos, chars.length)); // } // break; // } // } // // StringLayer[] texts = new StringLayer[lines.size()]; // lines.copyInto(texts); // lines = null; // // return texts; // } // catch(Exception err) // { // err.printStackTrace(); // return new CStringLayer[]{new CStringLayer("(Error !)", null)}; // } }
protected void drawMultilineText(String text, int x, int y, int boxWidth, int boxHeight) { int availableHeight = boxHeight - ICON_SIZE - ICON_PADDING; // Create an attributed string based in input text AttributedString attributedString = new AttributedString(text); attributedString.addAttribute(TextAttribute.FONT, g.getFont()); attributedString.addAttribute(TextAttribute.FOREGROUND, Color.black); AttributedCharacterIterator characterIterator = attributedString.getIterator(); int width = boxWidth - (2 * TEXT_PADDING); int currentHeight = 0; // Prepare a list of lines of text we'll be drawing List<TextLayout> layouts = new ArrayList<TextLayout>(); String lastLine = null; LineBreakMeasurer measurer = new LineBreakMeasurer(characterIterator, g.getFontRenderContext()); TextLayout layout = null; while (measurer.getPosition() < characterIterator.getEndIndex() && currentHeight <= availableHeight) { int previousPosition = measurer.getPosition(); // Request next layout layout = measurer.nextLayout(width); int height = ((Float) (layout.getDescent() + layout.getAscent() + layout.getLeading())).intValue(); if (currentHeight + height > availableHeight) { // The line we're about to add should NOT be added anymore, append three dots to previous // one instead // to indicate more text is truncated layouts.remove(layouts.size() - 1); if (lastLine.length() >= 4) { lastLine = lastLine.substring(0, lastLine.length() - 4) + "..."; } layouts.add(new TextLayout(lastLine, g.getFont(), g.getFontRenderContext())); } else { layouts.add(layout); lastLine = text.substring(previousPosition, measurer.getPosition()); currentHeight += height; } } int currentY = y + ICON_SIZE + ((availableHeight - currentHeight) / 2); int currentX = 0; // Actually draw the lines for (TextLayout textLayout : layouts) { currentY += textLayout.getAscent(); currentX = TEXT_PADDING + x + ((width - ((Double) textLayout.getBounds().getWidth()).intValue()) / 2); textLayout.draw(g, currentX, currentY); currentY += textLayout.getDescent() + textLayout.getLeading(); } }
public void draw(final Graphics2D graphics2D, final Rectangle2D bounds) { Graphics2D g = (Graphics2D) graphics2D.create(); g.setColor((Color) styleSheet.getStyleProperty(ElementStyleKeys.PAINT, Color.BLACK)); if (styleSheet.getBooleanStyleProperty(ElementStyleKeys.DRAW_SHAPE)) { g.draw(bounds); } if (styleSheet.getBooleanStyleProperty(ElementStyleKeys.FILL_SHAPE)) { Graphics2D g2 = (Graphics2D) g.create(); Color fillColor = (Color) styleSheet.getStyleProperty(ElementStyleKeys.FILL_COLOR, Color.WHITE); g2.setColor(fillColor); g2.fill(bounds); g2.dispose(); } if (vectorImageBackground != null) { Graphics2D g2 = (Graphics2D) g.create(); vectorImageBackground.draw(g2, bounds); g2.dispose(); } if (rasterImageBackground != null) { Graphics2D g2 = (Graphics2D) g.create(); Image image = rasterImageBackground.getImage(); WaitingImageObserver obs = new WaitingImageObserver(image); obs.waitImageLoaded(); g.setColor(Color.WHITE); g.setBackground(Color.WHITE); while (g2.drawImage( image, (int) bounds.getX(), (int) bounds.getY(), (int) bounds.getWidth(), (int) bounds.getHeight(), null) == false) { obs.waitImageLoaded(); if (obs.isError()) { logger.warn("Error while loading the image during the rendering."); break; } } g2.dispose(); } if (StringUtils.isEmpty(textToPrint) == false) { AttributedCharacterIterator paragraph = new AttributedString(textToPrint).getIterator(); int paragraphStart = paragraph.getBeginIndex(); int paragraphEnd = paragraph.getEndIndex(); FontRenderContext frc = g.getFontRenderContext(); LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc); float breakWidth = (float) bounds.getWidth(); float drawPosY = 0; // Set position to the index of the first character in the paragraph. lineMeasurer.setPosition(paragraphStart); while (lineMeasurer.getPosition() < paragraphEnd) { TextLayout layout = lineMeasurer.nextLayout(breakWidth).getJustifiedLayout(breakWidth); float drawPosX = layout.isLeftToRight() ? 0 : breakWidth - layout.getAdvance(); drawPosY += layout.getAscent(); layout.draw(g, drawPosX, drawPosY); drawPosY += layout.getDescent() + layout.getLeading(); } } }
public int print(Graphics g, PageFormat pageFormat, int page) throws PrinterException { // Define the origin of the printArea double printAreaX = pageFormat.getImageableX(); double printAreaY = pageFormat.getImageableY(); // Measures the size of strings FontMetrics metrics = g.getFontMetrics(fnt); // Parameters for the layout // Dynamic variable to measure the y-position of each line int intMeasureY = 0; // Others int intMarginLeft = Integer.valueOf((int) Math.round(printAreaX * LMARGINRATIO)); int intSpace = Integer.valueOf((int) Math.round(metrics.getHeight() * SPACERATIO)); int intDefaultHeight = metrics.getHeight(); int intPageWidth = Integer.valueOf((int) Math.round(pageFormat.getImageableWidth())); int pageHeight = Integer.valueOf((int) Math.round(pageFormat.getImageableHeight())); metrics = g.getFontMetrics(fntTitle); int intSpaceBig = metrics.getHeight(); // Graphics object to draw lines etc. Graphics2D g2d; Line2D.Double line = new Line2D.Double(); // Set colour to black g.setColor(Color.black); // Validate the number of pages // Create a graphic2D object a set the default parameters g2d = (Graphics2D) g; g2d.setColor(Color.black); // Translate the origin to be (0,0) // Note: Imageable includes already margins for Headers and Footers g2d.translate(printAreaX, printAreaY); // -- (1) Print the line on the left side line.setLine(0, 0, 0, pageFormat.getHeight() + 500); g2d.draw(line); // -- (2) Print the physicians attributes g.setFont(fntBold); // Measure String height to start drawing at the right place metrics = g.getFontMetrics(fntBold); intMeasureY += metrics.getHeight(); g.drawString( ph.getTitle() + " " + ph.getFirstname() + " " + ph.getLastname(), intMarginLeft, intMeasureY); // Set font to default g.setFont(fnt); // Measure the x-position (Page-Width - length of string) metrics = g.getFontMetrics(fnt); // Draw the date g.drawString(rp.getDate(), intPageWidth - metrics.stringWidth(rp.getDate()), intMeasureY); intMeasureY += metrics.getHeight(); // Draw strings of Address, Phone and insurance information g.drawString(ph.getSpecialty1(), intMarginLeft, intMeasureY); if (ph.getSpecialty2().length() > 0) { intMeasureY += intDefaultHeight; g.drawString(ph.getSpecialty2(), intMarginLeft, intMeasureY); } intMeasureY += intSpace; g.drawString(ph.getStreet() + " " + ph.getPostbox(), intMarginLeft, intMeasureY); intMeasureY += intDefaultHeight; g.drawString(ph.getZip() + " " + ph.getCity(), intMarginLeft, intMeasureY); intMeasureY += intSpace; // Measure the label strings to align the phone and fax numbers int phoneWidth = metrics.stringWidth(PHONE); if (metrics.stringWidth(PHONE) < metrics.stringWidth(FAX) && ph.getFax().length() > 0) phoneWidth = metrics.stringWidth(FAX); g.drawString(PHONE, intMarginLeft, intMeasureY); g.drawString(ph.getPhone(), intMarginLeft + phoneWidth, intMeasureY); if (ph.getFax().length() > 0) { intMeasureY += intDefaultHeight; g.drawString(FAX, intMarginLeft, intMeasureY); g.drawString(ph.getFax(), intMarginLeft + phoneWidth, intMeasureY); } intMeasureY += intSpace; // Measure the label strings to align the ZSR and EAN identifiers int EANWidth = metrics.stringWidth(ZSR); if (metrics.stringWidth(ZSR) < metrics.stringWidth(EAN) && ph.getGlnid().length() > 0) EANWidth = metrics.stringWidth(EAN); g.drawString(ZSR, intMarginLeft, intMeasureY); g.drawString(ph.getZsrid(), intMarginLeft + EANWidth, intMeasureY); if (ph.getGlnid().length() > 0) { intMeasureY += intDefaultHeight; g.drawString(EAN, intMarginLeft, intMeasureY); g.drawString(ph.getGlnid(), intMarginLeft + EANWidth, intMeasureY); } intMeasureY += intSpaceBig; // -- (3) Print the line line.setLine(intMarginLeft, intMeasureY, pageFormat.getWidth(), intMeasureY); g2d.draw(line); intMeasureY += intSpaceBig + intSpace; // -- (4) Title g.setFont(fntTitle); g.drawString(TITLE, intMarginLeft, intMeasureY); intMeasureY += intSpaceBig + intDefaultHeight; // -- (5) Patient g.setFont(fntBold); g.drawString(pat.getName() + " " + pat.getVorname(), intMarginLeft, intMeasureY); metrics = g.getFontMetrics(fntBold); int xPat = intMarginLeft + metrics.stringWidth(pat.getName() + " " + pat.getVorname()); g.setFont(fnt); g.drawString(", " + BORN + pat.getGeburtsdatum(), xPat, intMeasureY); intMeasureY += intSpaceBig + intSpace; // -- (6) Products LineBreakMeasurer lineBreakMeasurer; int intstart, intend; Hashtable hash = new Hashtable(); // Print all the items for (int i = this.firstProd; i <= lastProd; i = i + 1) { ch.elexis.data.Prescription actualLine = rp.getLines().get(i); Artikel article = actualLine.getArtikel(); AttributedString attributedString = new AttributedString("1x " + article.getLabel(), hash); attributedString.addAttribute(TextAttribute.FONT, fntBold); g2d.setFont(fntBold); FontRenderContext frc = g2d.getFontRenderContext(); AttributedCharacterIterator attributedCharacterIterator = attributedString.getIterator(); intstart = attributedCharacterIterator.getBeginIndex(); intend = attributedCharacterIterator.getEndIndex(); lineBreakMeasurer = new LineBreakMeasurer(attributedCharacterIterator, frc); float width = (float) intPageWidth - intMarginLeft; int X = intMarginLeft; lineBreakMeasurer.setPosition(intstart); // Create TextLayout accordingly and draw it while (lineBreakMeasurer.getPosition() < intend) { TextLayout textLayout = lineBreakMeasurer.nextLayout(width); intMeasureY += textLayout.getAscent(); X = intMarginLeft; textLayout.draw(g2d, X, intMeasureY); intMeasureY += textLayout.getDescent() + textLayout.getLeading(); } // Draw the label String label = actualLine.getBemerkung(); if (actualLine.getDosis().length() > 0) { label = actualLine.getDosis() + ", " + label; } // If there is no label specified, go to the next iterations if (label.length() == 0) { intMeasureY += intSpaceBig * 2; continue; } attributedString = new AttributedString(label, hash); attributedString.addAttribute(TextAttribute.FONT, fnt); g2d.setFont(fnt); frc = g2d.getFontRenderContext(); attributedCharacterIterator = attributedString.getIterator(); intstart = attributedCharacterIterator.getBeginIndex(); intend = attributedCharacterIterator.getEndIndex(); lineBreakMeasurer = new LineBreakMeasurer(attributedCharacterIterator, frc); lineBreakMeasurer.setPosition(intstart); // Create TextLayout accordingly and draw it while (lineBreakMeasurer.getPosition() < intend) { // Extra code to determine line breaks in the string --> go on new line, if there is one int next = lineBreakMeasurer.nextOffset(width); int limit = next; if (limit <= label.length()) { for (int k = lineBreakMeasurer.getPosition(); k < next; ++k) { char c = label.charAt(k); if (c == '\n') { limit = k + 1; break; } } } TextLayout textLayout = lineBreakMeasurer.nextLayout(width, limit, false); intMeasureY += textLayout.getAscent(); X = intMarginLeft; textLayout.draw(g2d, X, intMeasureY); intMeasureY += textLayout.getDescent() + textLayout.getLeading(); } intMeasureY += intSpaceBig * 2; } // (7) Draw now the Footer: // Create the barcodes Barcode bc = new Barcode(); this.imgCode128 = bc.getCode128(presID); this.imgQRCode = bc.getQRCode(QRCode); // (a) Code 128 with decoded String g.setFont(fntBold); metrics = g.getFontMetrics(fntBold); int xPrescId = intPageWidth - Code128Width + Integer.valueOf( (int) Math.round((Code128Width - metrics.stringWidth(this.presID)) / 2)); g.drawString(this.presID, xPrescId, pageHeight); g.drawImage( imgCode128, intPageWidth - Code128Width, pageHeight - Code128Height - intDefaultHeight, Code128Width, Code128Height, null); // (b) QR-Code g.drawImage( imgQRCode, intMarginLeft, pageHeight - QRCodeBorder, QRCodeBorder, QRCodeBorder, null); // (c) Promotion-String g.setColor(Color.gray); metrics = g.getFontMetrics(fntItalic); g.setFont(fntItalic); g.drawString( PROMO, Integer.valueOf( (int) Math.round((intMarginLeft + (QRCodeBorder - metrics.stringWidth(PROMO)) / 2))), pageHeight); // set to default g.setColor(Color.black); g.setFont(fnt); // (8) Return, that this page exists and thus will be rendered and printed return (PAGE_EXISTS); }