/* */ public void insertChar( AttributedCharacterIterator paramAttributedCharacterIterator, int paramInt) /* */ { /* 499 */ this.measurer.insertChar(paramAttributedCharacterIterator, paramInt); /* */ /* 501 */ this.limit = paramAttributedCharacterIterator.getEndIndex(); /* 502 */ this.pos = (this.start = paramAttributedCharacterIterator.getBeginIndex()); /* */ /* 504 */ this.charIter.reset( this.measurer.getChars(), paramAttributedCharacterIterator.getBeginIndex()); /* 505 */ this.breakIter.setText(this.charIter); /* */ }
/** * 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; }
/** * Called when a user processing input characters and select candidates from input method. * * @param text Text from InputMethodEvent. * @param commited_count Numbers of committed characters in text. */ public void processCompositionText(AttributedCharacterIterator text, int committed_count) { int layoutCaretPosition = initialCaretPosition + committed_count; CompositionTextPainter compositionPainter = textArea.getPainter().getCompositionTextpainter(); compositionPainter.setComposedTextLayout( getTextLayout(text, committed_count), layoutCaretPosition); int textLength = text.getEndIndex() - text.getBeginIndex() - committed_count; StringBuffer unCommitedStringBuf = new StringBuffer(textLength); char c; for (c = text.setIndex(committed_count); c != AttributedCharacterIterator.DONE && textLength > 0; c = text.next(), --textLength) { unCommitedStringBuf.append(c); } String unCommittedString = unCommitedStringBuf.toString(); try { if (canRemovePreviousInput(committed_count)) { textArea.getDocument().remove(layoutCaretPosition, prevComposeString.length()); } textArea.getDocument().insertString(layoutCaretPosition, unCommittedString, null); if (committed_count > 0) { initialCaretPosition = initialCaretPosition + committed_count; } prevComposeString = unCommittedString; prevCommittedCount = committed_count; } catch (BadLocationException e) { e.printStackTrace(); } }
/** * Return a StyledParagraph reflecting the insertion of a single character into the text. This * method will attempt to reuse the given paragraph, but may create a new paragraph. * * @param aci an iterator over the text. The text should be the same as the text used to create * (or most recently update) oldParagraph, with the exception of deleting a single character * at deletePos. * @param chars the characters in aci * @param deletePos the index where a character was removed * @param oldParagraph a StyledParagraph for the text in aci before the insertion */ public static StyledParagraph deleteChar( AttributedCharacterIterator aci, char[] chars, int deletePos, StyledParagraph oldParagraph) { // We will reuse oldParagraph unless there was a length-1 run // at deletePos. We could do more work and check the individual // Font and Decoration runs, but we don't right now... deletePos -= aci.getBeginIndex(); if (oldParagraph.decorations == null && oldParagraph.fonts == null) { oldParagraph.length -= 1; return oldParagraph; } if (oldParagraph.getRunLimit(deletePos) == deletePos + 1) { if (deletePos == 0 || oldParagraph.getRunLimit(deletePos - 1) == deletePos) { return new StyledParagraph(aci, chars); } } oldParagraph.length -= 1; if (oldParagraph.decorations != null) { deleteFrom(deletePos, oldParagraph.decorationStarts, oldParagraph.decorations.size()); } if (oldParagraph.fonts != null) { deleteFrom(deletePos, oldParagraph.fontStarts, oldParagraph.fonts.size()); } return oldParagraph; }
/** * Return a StyledParagraph reflecting the insertion of a single character into the text. This * method will attempt to reuse the given paragraph, but may create a new paragraph. * * @param aci an iterator over the text. The text should be the same as the text used to create * (or most recently update) oldParagraph, with the exception of inserting a single character * at insertPos. * @param chars the characters in aci * @param insertPos the index of the new character in aci * @param oldParagraph a StyledParagraph for the text in aci before the insertion */ public static StyledParagraph insertChar( AttributedCharacterIterator aci, char[] chars, int insertPos, StyledParagraph oldParagraph) { // If the styles at insertPos match those at insertPos-1, // oldParagraph will be reused. Otherwise we create a new // paragraph. char ch = aci.setIndex(insertPos); int relativePos = Math.max(insertPos - aci.getBeginIndex() - 1, 0); Map attributes = addInputMethodAttrs(aci.getAttributes()); Decoration d = Decoration.getDecoration(attributes); if (!oldParagraph.getDecorationAt(relativePos).equals(d)) { return new StyledParagraph(aci, chars); } Object f = getGraphicOrFont(attributes); if (f == null) { FontResolver resolver = FontResolver.getInstance(); int fontIndex = resolver.getFontIndex(ch); f = resolver.getFont(fontIndex, attributes); } if (!oldParagraph.getFontOrGraphicAt(relativePos).equals(f)) { return new StyledParagraph(aci, chars); } // insert into existing paragraph oldParagraph.length += 1; if (oldParagraph.decorations != null) { insertInto(relativePos, oldParagraph.decorationStarts, oldParagraph.decorations.size()); } if (oldParagraph.fonts != null) { insertInto(relativePos, oldParagraph.fontStarts, oldParagraph.fonts.size()); } return oldParagraph; }
/** * Updates the <code>TextMeasurer</code> after a single character has been deleted from the * paragraph currently represented by this <code>TextMeasurer</code>. After this call, this <code> * TextMeasurer</code> is equivalent to a new <code>TextMeasurer</code> created from the text; * however, it will usually be more efficient to update an existing <code>TextMeasurer</code> than * to create a new one from scratch. * * @param newParagraph the text of the paragraph after performing the deletion. Cannot be null. * @param deletePos the position in the text where the character was removed. Must not be less * than the start of <code>newParagraph</code>, and must not be greater than the end of <code> * newParagraph</code>. * @throws IndexOutOfBoundsException if <code>deletePos</code> is less than the start of <code> * newParagraph</code> or greater than the end of <code>newParagraph</code> * @throws NullPointerException if <code>newParagraph</code> is <code>null</code> */ public void deleteChar(AttributedCharacterIterator newParagraph, int deletePos) { fStart = newParagraph.getBeginIndex(); int end = newParagraph.getEndIndex(); if (end - fStart != fChars.length - 1) { initAll(newParagraph); } char[] newChars = new char[end - fStart]; int changedIndex = deletePos - fStart; System.arraycopy(fChars, 0, newChars, 0, deletePos - fStart); System.arraycopy(fChars, changedIndex + 1, newChars, changedIndex, end - deletePos); fChars = newChars; if (fBidi != null) { fBidi = new Bidi(newParagraph); if (fBidi.isLeftToRight()) { fBidi = null; } } fParagraph = StyledParagraph.deleteChar(newParagraph, fChars, deletePos, fParagraph); invalidateComponents(); }
public Format.Field[] getFields(final int offset) { if (format == null) { return null; } Object value = getFormattedTextField().getValue(); if (value == null) { return null; } AttributedCharacterIterator iterator = format.formatToCharacterIterator(value); if (offset < iterator.getBeginIndex() || offset > iterator.getEndIndex()) { return new Format.Field[0]; } iterator.setIndex(offset); Set keys = iterator.getAttributes().keySet(); Set result = new HashSet(); Iterator iter = keys.iterator(); while (iter.hasNext()) { Object key = iter.next(); if (key instanceof Format.Field) { result.add(key); } } return (Format.Field[]) result.toArray(new Format.Field[result.size()]); }
/* */ public void deleteChar( AttributedCharacterIterator paramAttributedCharacterIterator, int paramInt) /* */ { /* 525 */ this.measurer.deleteChar(paramAttributedCharacterIterator, paramInt); /* */ /* 527 */ this.limit = paramAttributedCharacterIterator.getEndIndex(); /* 528 */ this.pos = (this.start = paramAttributedCharacterIterator.getBeginIndex()); /* */ /* 530 */ this.charIter.reset(this.measurer.getChars(), this.start); /* 531 */ this.breakIter.setText(this.charIter); /* */ }
/* */ public LineBreakMeasurer( AttributedCharacterIterator paramAttributedCharacterIterator, BreakIterator paramBreakIterator, FontRenderContext paramFontRenderContext) /* */ { /* 305 */ if (paramAttributedCharacterIterator.getEndIndex() - paramAttributedCharacterIterator.getBeginIndex() < 1) { /* 306 */ throw new IllegalArgumentException("Text must contain at least one character."); /* */ } /* */ /* 309 */ this.breakIter = paramBreakIterator; /* 310 */ this.measurer = new TextMeasurer(paramAttributedCharacterIterator, paramFontRenderContext); /* 311 */ this.limit = paramAttributedCharacterIterator.getEndIndex(); /* 312 */ this.pos = (this.start = paramAttributedCharacterIterator.getBeginIndex()); /* */ /* 314 */ this.charIter = new CharArrayIterator(this.measurer.getChars(), this.start); /* 315 */ this.breakIter.setText(this.charIter); /* */ }
/** * Draws a string at the specified position. * * @param iterator the string. * @param x the x-coordinate. * @param y the y-coordinate. */ @Override public void drawString(AttributedCharacterIterator iterator, int x, int y) { // for now we simply want to extract the chars from the iterator // and call an unstyled text renderer StringBuffer sb = new StringBuffer(); int numChars = iterator.getEndIndex() - iterator.getBeginIndex(); char c = iterator.first(); for (int i = 0; i < numChars; i++) { sb.append(c); c = iterator.next(); } drawString(new String(sb), x, y); }
/** * Create a new StyledParagraph over the given styled text. * * @param aci an iterator over the text * @param chars the characters extracted from aci */ public StyledParagraph(AttributedCharacterIterator aci, char[] chars) { int start = aci.getBeginIndex(); int end = aci.getEndIndex(); length = end - start; int index = start; aci.first(); do { final int nextRunStart = aci.getRunLimit(); final int localIndex = index - start; Map attributes = aci.getAttributes(); attributes = addInputMethodAttrs(attributes); Decoration d = Decoration.getDecoration(attributes); addDecoration(d, localIndex); Object f = getGraphicOrFont(attributes); if (f == null) { addFonts(chars, attributes, localIndex, nextRunStart - start); } else { addFont(f, localIndex); } aci.setIndex(nextRunStart); index = nextRunStart; } while (index < end); // Add extra entries to starts arrays with the length // of the paragraph. 'this' is used as a dummy value // in the Vector. if (decorations != null) { decorationStarts = addToVector(this, length, decorations, decorationStarts); } if (fonts != null) { fontStarts = addToVector(this, length, fonts, fontStarts); } }
// 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; }
/** * Updates the <code>TextMeasurer</code> after a single character has been inserted into the * paragraph currently represented by this <code>TextMeasurer</code>. After this call, this <code> * TextMeasurer</code> is equivalent to a new <code>TextMeasurer</code> created from the text; * however, it will usually be more efficient to update an existing <code>TextMeasurer</code> than * to create a new one from scratch. * * @param newParagraph the text of the paragraph after performing the insertion. Cannot be null. * @param insertPos the position in the text where the character was inserted. Must not be less * than the start of <code>newParagraph</code>, and must be less than the end of <code> * newParagraph</code>. * @throws IndexOutOfBoundsException if <code>insertPos</code> is less than the start of <code> * newParagraph</code> or greater than or equal to the end of <code>newParagraph</code> * @throws NullPointerException if <code>newParagraph</code> is <code>null</code> */ public void insertChar(AttributedCharacterIterator newParagraph, int insertPos) { if (collectStats) { printStats(); } if (wantStats) { collectStats = true; } fStart = newParagraph.getBeginIndex(); int end = newParagraph.getEndIndex(); if (end - fStart != fChars.length + 1) { initAll(newParagraph); } char[] newChars = new char[end - fStart]; int newCharIndex = insertPos - fStart; System.arraycopy(fChars, 0, newChars, 0, newCharIndex); char newChar = newParagraph.setIndex(insertPos); newChars[newCharIndex] = newChar; System.arraycopy(fChars, newCharIndex, newChars, newCharIndex + 1, end - insertPos - 1); fChars = newChars; if (fBidi != null || Bidi.requiresBidi(newChars, newCharIndex, newCharIndex + 1) || newParagraph.getAttribute(TextAttribute.BIDI_EMBEDDING) != null) { fBidi = new Bidi(newParagraph); if (fBidi.isLeftToRight()) { fBidi = null; } } fParagraph = StyledParagraph.insertChar(newParagraph, fChars, insertPos, fParagraph); invalidateComponents(); }
/** Initialize state, including fChars array, direction, and fBidi. */ private void initAll(AttributedCharacterIterator text) { fStart = text.getBeginIndex(); // extract chars fChars = new char[text.getEndIndex() - fStart]; int n = 0; for (char c = text.first(); c != CharacterIterator.DONE; c = text.next()) { fChars[n++] = c; } text.first(); fBidi = new Bidi(text); if (fBidi.isLeftToRight()) { fBidi = null; } text.first(); Map<? extends Attribute, ?> paragraphAttrs = text.getAttributes(); NumericShaper shaper = AttributeValues.getNumericShaping(paragraphAttrs); if (shaper != null) { shaper.shape(fChars, 0, fChars.length); } fParagraph = new StyledParagraph(text, fChars); // set paragraph attributes { // If there's an embedded graphic at the start of the // paragraph, look for the first non-graphic character // and use it and its font to initialize the paragraph. // If not, use the first graphic to initialize. fJustifyRatio = AttributeValues.getJustification(paragraphAttrs); boolean haveFont = TextLine.advanceToFirstFont(text); if (haveFont) { Font defaultFont = TextLine.getFontAtCurrentPos(text); int charsStart = text.getIndex() - text.getBeginIndex(); LineMetrics lm = defaultFont.getLineMetrics(fChars, charsStart, charsStart + 1, fFrc); fBaseline = (byte) lm.getBaselineIndex(); fBaselineOffsets = lm.getBaselineOffsets(); } else { // hmmm what to do here? Just try to supply reasonable // values I guess. GraphicAttribute graphic = (GraphicAttribute) paragraphAttrs.get(TextAttribute.CHAR_REPLACEMENT); fBaseline = TextLayout.getBaselineFromGraphic(graphic); Hashtable<Attribute, ?> fmap = new Hashtable<>(5, (float) 0.9); Font dummyFont = new Font(fmap); LineMetrics lm = dummyFont.getLineMetrics(" ", 0, 1, fFrc); fBaselineOffsets = lm.getBaselineOffsets(); } fBaselineOffsets = TextLine.getNormalizedOffsets(fBaselineOffsets, fBaseline); } invalidateComponents(); }
// handle spaces separately, all others by table // as - Attributed string to attribute with Word extents. public static void findLineBrk(AttributedString as) { AttributedCharacterIterator aci = as.getIterator(); if (aci.getEndIndex() == 0) return; char ch = aci.current(), prevCh = (char) -1; byte cls = getCharCharClass(ch); if (cls == CHAR_CLASS_LF) cls = CHAR_CLASS_BK; byte curCls = cls; byte prevCls = cls; byte prevPrevCls = -1; int wordCnt = 0; int wordBegin = aci.getBeginIndex(); // loop over all pairs in the string int ich = wordBegin + 1; int lineEnd = aci.getRunLimit(lineBrks); // handle case where input starts with an LF if (cls >= CHAR_CLASS_CM) cls = CHAR_CLASS_AL; for (ch = aci.next(); ch != AttributedCharacterIterator.DONE; ich++, prevCh = ch, ch = aci.next(), prevPrevCls = prevCls, prevCls = curCls) { if (ich == lineEnd) { as.addAttribute(WORD_LIMIT, new Integer(wordCnt++), wordBegin, ich); wordBegin = ich; cls = getCharCharClass(ch); curCls = cls; prevCls = cls; if (cls >= CHAR_CLASS_CM) cls = CHAR_CLASS_AL; lineEnd = aci.getRunLimit(lineBrks); continue; } // handle spaces curCls = getCharCharClass(ch); if (curCls == CHAR_CLASS_SP) { // pbrk[ich-1] = BREAK_ACTION_PROHIBITED; continue; } // handle complex scripts if (curCls == CHAR_CLASS_SA) { ich += findComplexBreak(aci); ch = aci.previous(); if (ch != AttributedCharacterIterator.DONE) prevCls = getCharCharClass(ch); ch = aci.next(); if (ch != AttributedCharacterIterator.DONE) curCls = cls = getCharCharClass(ch); continue; } // This isn't in the Unicode line breaking alg. but it // seems needed as otherwise it does produce a break. if ((ch == CHAR_ZERO_WIDTH_JOINER) || (prevCh == CHAR_ZERO_WIDTH_JOINER)) continue; // Don't allow break around JOINER. if ((curCls == CHAR_CLASS_BK) || (curCls == CHAR_CLASS_LF)) { as.addAttribute(WORD_LIMIT, new Integer(wordCnt++), wordBegin, ich); wordBegin = ich; cls = CHAR_CLASS_BK; continue; } if (prevCls == CHAR_CLASS_CR) { as.addAttribute(WORD_LIMIT, new Integer(wordCnt++), wordBegin, ich - 1); wordBegin = ich - 1; cls = CHAR_CLASS_BK; continue; } if (curCls == CHAR_CLASS_CR) { continue; } // handle combining marks if (curCls == CHAR_CLASS_CM) { if (prevCls == CHAR_CLASS_SP) { cls = CHAR_CLASS_ID; if (prevPrevCls != -1) { if (brkPairs[prevPrevCls][CHAR_CLASS_ID] == BREAK_ACTION_DIRECT) { as.addAttribute(WORD_LIMIT, new Integer(wordCnt++), wordBegin, ich - 1); wordBegin = ich - 1; // pbrk[ich-2] = BREAK_ACTION_DIRECT; } else { // pbrk[ich-2] = BREAK_ACTION_PROHIBITED; } } } // pbrk[ich-1] = BREAK_ACTION_PROHIBITED; continue; } if (cls == CHAR_CLASS_BK) { cls = curCls; continue; } // lookup pair table information byte brk = brkPairs[cls][curCls]; if (brk == BREAK_ACTION_DIRECT) { as.addAttribute(WORD_LIMIT, new Integer(wordCnt++), wordBegin, ich); wordBegin = ich; // pbrk[ich-1] = brk; } else if (brk == BREAK_ACTION_INDIRECT) { if (prevCls == CHAR_CLASS_SP) { as.addAttribute(WORD_LIMIT, new Integer(wordCnt++), wordBegin, ich); wordBegin = ich; } // pbrk[ich-1] = ((prevCls == CHAR_CLASS_SP) ? // BREAK_ACTION_INDIRECT : // BREAK_ACTION_PROHIBITED); } cls = curCls; } // always break at the end as.addAttribute(WORD_LIMIT, new Integer(wordCnt++), wordBegin, ich); wordBegin = ich; // pbrk[ich-1] = BREAK_ACTION_DIRECT; return; }
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); }