/** * Process the text so that it will render with a combination of fonts if needed. * * @param text the text * @return a <CODE>Phrase</CODE> with one or more chunks */ public Phrase process(String text) { int fsize = fonts.size(); if (fsize == 0) throw new IndexOutOfBoundsException("No font is defined."); char cc[] = text.toCharArray(); int len = cc.length; StringBuffer sb = new StringBuffer(); Font font = null; int lastidx = -1; Phrase ret = new Phrase(); for (int k = 0; k < len; ++k) { char c = cc[k]; if (c == '\n' || c == '\r') { sb.append(c); continue; } if (Utilities.isSurrogatePair(cc, k)) { int u = Utilities.convertToUtf32(cc, k); for (int f = 0; f < fsize; ++f) { font = (Font) fonts.get(f); if (font.getBaseFont().charExists(u)) { if (lastidx != f) { if (sb.length() > 0 && lastidx != -1) { Chunk ck = new Chunk(sb.toString(), (Font) fonts.get(lastidx)); ret.add(ck); sb.setLength(0); } lastidx = f; } sb.append(c); sb.append(cc[++k]); break; } } } else { for (int f = 0; f < fsize; ++f) { font = (Font) fonts.get(f); if (font.getBaseFont().charExists(c)) { if (lastidx != f) { if (sb.length() > 0 && lastidx != -1) { Chunk ck = new Chunk(sb.toString(), (Font) fonts.get(lastidx)); ret.add(ck); sb.setLength(0); } lastidx = f; } sb.append(c); break; } } } } if (sb.length() > 0) { Chunk ck = new Chunk(sb.toString(), (Font) fonts.get(lastidx == -1 ? 0 : lastidx)); ret.add(ck); } return ret; }
/** * Truncates this <CODE>PdfChunk</CODE> if it's too long for the given width. * * <p>Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated. * * @param width a given width * @return the <CODE>PdfChunk</CODE> that doesn't fit into the width. */ PdfChunk truncate(float width) { if (image != null) { if (image.getScaledWidth() > width) { PdfChunk pc = new PdfChunk("", this); value = ""; attributes.remove(Chunk.IMAGE); image = null; font = PdfFont.getDefaultFont(); return pc; } else return null; } int currentPosition = 0; float currentWidth = 0; // it's no use trying to split if there isn't even enough place for a space if (width < font.width()) { String returnValue = value.substring(1); value = value.substring(0, 1); PdfChunk pc = new PdfChunk(returnValue, this); return pc; } // loop over all the characters of a string // or until the totalWidth is reached int length = value.length(); boolean surrogate = false; char character; while (currentPosition < length) { // the width of every character is added to the currentWidth surrogate = Utilities.isSurrogatePair(value, currentPosition); if (surrogate) currentWidth += font.width(Utilities.convertToUtf32(value, currentPosition)); else currentWidth += font.width(value.charAt(currentPosition)); if (currentWidth > width) break; if (surrogate) currentPosition++; currentPosition++; } // if all the characters fit in the total width, null is returned (there is no overflow) if (currentPosition == length) { return null; } // otherwise, the string has to be truncated // currentPosition -= 2; // we have to chop off minimum 1 character from the chunk if (currentPosition == 0) { currentPosition = 1; if (surrogate) ++currentPosition; } String returnValue = value.substring(currentPosition); value = value.substring(0, currentPosition); PdfChunk pc = new PdfChunk(returnValue, this); return pc; }
/** * Splits this <CODE>PdfChunk</CODE> if it's too long for the given width. * * <p>Returns <VAR>null</VAR> if the <CODE>PdfChunk</CODE> wasn't truncated. * * @param width a given width * @return the <CODE>PdfChunk</CODE> that doesn't fit into the width. */ PdfChunk split(float width) { newlineSplit = false; if (image != null) { if (image.getScaledWidth() > width) { PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this); value = ""; attributes = new HashMap(); image = null; font = PdfFont.getDefaultFont(); return pc; } else return null; } HyphenationEvent hyphenationEvent = (HyphenationEvent) noStroke.get(Chunk.HYPHENATION); int currentPosition = 0; int splitPosition = -1; float currentWidth = 0; // loop over all the characters of a string // or until the totalWidth is reached int lastSpace = -1; float lastSpaceWidth = 0; int length = value.length(); char valueArray[] = value.toCharArray(); char character = 0; BaseFont ft = font.getFont(); boolean surrogate = false; if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') { while (currentPosition < length) { // the width of every character is added to the currentWidth char cidChar = valueArray[currentPosition]; character = (char) ft.getUnicodeEquivalent(cidChar); // if a newLine or carriageReturn is encountered if (character == '\n') { newlineSplit = true; String returnValue = value.substring(currentPosition + 1); value = value.substring(0, currentPosition); if (value.length() < 1) { value = "\u0001"; } PdfChunk pc = new PdfChunk(returnValue, this); return pc; } currentWidth += font.width(cidChar); if (character == ' ') { lastSpace = currentPosition + 1; lastSpaceWidth = currentWidth; } if (currentWidth > width) break; // if a split-character is encountered, the splitPosition is altered if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, thisChunk)) splitPosition = currentPosition + 1; currentPosition++; } } else { while (currentPosition < length) { // the width of every character is added to the currentWidth character = valueArray[currentPosition]; // if a newLine or carriageReturn is encountered if (character == '\r' || character == '\n') { newlineSplit = true; int inc = 1; if (character == '\r' && currentPosition + 1 < length && valueArray[currentPosition + 1] == '\n') inc = 2; String returnValue = value.substring(currentPosition + inc); value = value.substring(0, currentPosition); if (value.length() < 1) { value = " "; } PdfChunk pc = new PdfChunk(returnValue, this); return pc; } surrogate = Utilities.isSurrogatePair(valueArray, currentPosition); if (surrogate) currentWidth += font.width( Utilities.convertToUtf32( valueArray[currentPosition], valueArray[currentPosition + 1])); else currentWidth += font.width(character); if (character == ' ') { lastSpace = currentPosition + 1; lastSpaceWidth = currentWidth; } if (surrogate) currentPosition++; if (currentWidth > width) break; // if a split-character is encountered, the splitPosition is altered if (splitCharacter.isSplitCharacter(0, currentPosition, length, valueArray, null)) splitPosition = currentPosition + 1; currentPosition++; } } // if all the characters fit in the total width, null is returned (there is no overflow) if (currentPosition == length) { return null; } // otherwise, the string has to be truncated if (splitPosition < 0) { String returnValue = value; value = ""; PdfChunk pc = new PdfChunk(returnValue, this); return pc; } if (lastSpace > splitPosition && splitCharacter.isSplitCharacter(0, 0, 1, singleSpace, null)) splitPosition = lastSpace; if (hyphenationEvent != null && lastSpace >= 0 && lastSpace < currentPosition) { int wordIdx = getWord(value, lastSpace); if (wordIdx > lastSpace) { String pre = hyphenationEvent.getHyphenatedWordPre( value.substring(lastSpace, wordIdx), font.getFont(), font.size(), width - lastSpaceWidth); String post = hyphenationEvent.getHyphenatedWordPost(); if (pre.length() > 0) { String returnValue = post + value.substring(wordIdx); value = trim(value.substring(0, lastSpace) + pre); PdfChunk pc = new PdfChunk(returnValue, this); return pc; } } } String returnValue = value.substring(splitPosition); value = trim(value.substring(0, splitPosition)); PdfChunk pc = new PdfChunk(returnValue, this); return pc; }
/** * Converts the text into bytes to be placed in the document. The conversion is done according to * the font and the encoding and the characters used are stored. * * @param text the text to convert * @return the conversion */ byte[] convertToBytes(final String text) { byte b[] = null; switch (this.fontType) { case BaseFont.FONT_TYPE_T3: return this.baseFont.convertToBytes(text); case BaseFont.FONT_TYPE_T1: case BaseFont.FONT_TYPE_TT: { b = this.baseFont.convertToBytes(text); final int len = b.length; for (int k = 0; k < len; ++k) { this.shortTag[b[k] & 0xff] = 1; } break; } case BaseFont.FONT_TYPE_CJK: { final int len = text.length(); for (int k = 0; k < len; ++k) { this.cjkTag.put(this.cjkFont.getCidCode(text.charAt(k)), 0); } b = this.baseFont.convertToBytes(text); break; } case BaseFont.FONT_TYPE_DOCUMENT: { b = this.baseFont.convertToBytes(text); break; } case BaseFont.FONT_TYPE_TTUNI: { try { int len = text.length(); int metrics[] = null; final char glyph[] = new char[len]; int i = 0; if (this.symbolic) { b = PdfEncodings.convertToBytes(text, "symboltt"); len = b.length; for (int k = 0; k < len; ++k) { metrics = this.ttu.getMetricsTT(b[k] & 0xff); if (metrics == null) { continue; } this.longTag.put( new Integer(metrics[0]), new int[] { metrics[0], metrics[1], this.ttu.getUnicodeDifferences(b[k] & 0xff) }); glyph[i++] = (char) metrics[0]; } } else { for (int k = 0; k < len; ++k) { int val; if (Utilities.isSurrogatePair(text, k)) { val = Utilities.convertToUtf32(text, k); k++; } else { val = text.charAt(k); } metrics = this.ttu.getMetricsTT(val); if (metrics == null) { continue; } final int m0 = metrics[0]; final Integer gl = new Integer(m0); if (!this.longTag.containsKey(gl)) { this.longTag.put(gl, new int[] {m0, metrics[1], val}); } glyph[i++] = (char) m0; } } final String s = new String(glyph, 0, i); b = s.getBytes(CJKFont.CJK_ENCODING); } catch (final UnsupportedEncodingException e) { throw new ExceptionConverter(e); } break; } } return b; }