/** * 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) { /* ssteward: dropped in 1.44 if (image != null) { if (image.scaledWidth() > 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(); char character; while (currentPosition < length) { // the width of every character is added to the currentWidth character = value.charAt(currentPosition); currentWidth += font.width(character); if (currentWidth > width) break; 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; } String returnValue = value.substring(currentPosition); value = value.substring(0, currentPosition); PdfChunk pc = new PdfChunk(returnValue, this); return pc; }
/** * Gets the biggest descender for all the fonts used in this line. Note that this is a negative * number. * * @return maximum size of all the descenders used in this line */ public float getDescender() { float descender = 0; for (int k = 0; k < line.size(); ++k) { PdfChunk ck = line.get(k); if (ck.isImage()) descender = Math.min(descender, ck.getImageOffsetY()); else { PdfFont font = ck.font(); descender = Math.min(descender, font.getFont().getFontDescriptor(BaseFont.DESCENT, font.size())); } } return descender; }
/** * Gets the maximum size of the ascender for all the fonts used in this line. * * @return maximum size of all the ascenders used in this line */ public float getAscender() { float ascender = 0; for (int k = 0; k < line.size(); ++k) { PdfChunk ck = line.get(k); if (ck.isImage()) ascender = Math.max(ascender, ck.getImage().getScaledHeight() + ck.getImageOffsetY()); else { PdfFont font = ck.font(); ascender = Math.max(ascender, font.getFont().getFontDescriptor(BaseFont.ASCENT, font.size())); } } return ascender; }
/** * Trims the last space. * * @return the width of the space trimmed, otherwise 0 */ public float trimLastSpace() { BaseFont ft = font.getFont(); if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') { if (value.length() > 1 && value.endsWith("\u0001")) { value = value.substring(0, value.length() - 1); return font.width('\u0001'); } } else { if (value.length() > 1 && value.endsWith(" ")) { value = value.substring(0, value.length() - 1); return font.width(' '); } } return 0; }
/** * Removes all the <VAR>' '</VAR> and <VAR>'-'</VAR>-characters on the right of a <CODE>String</CODE>. * <P> * @param string the <CODE>String<CODE> that has to be trimmed. * @return the trimmed <CODE>String</CODE> */ String trim(String string) { BaseFont ft = font.getFont(); if (ft.getFontType() == BaseFont.FONT_TYPE_CJK && ft.getUnicodeEquivalent(' ') != ' ') { while (string.endsWith("\u0001")) { string = string.substring(0, string.length() - 1); } } else { while (string.endsWith(" ") || string.endsWith("\t")) { string = string.substring(0, string.length() - 1); } } return string; }
protected void printFooter() throws DocumentException { out(""); out( renderEnd( renderMiddle("", "Page " + (iPageNo + 1)), "<" + iCurrentSubjectArea.getSubjectAreaAbbreviation() + (iCourseNumber != null ? " " + iCourseNumber : "") + "> ")); // FIXME: For some reason when a line starts with space, the line is shifted by one space in the // resulting PDF (when using iText 5.0.2) Paragraph p = new Paragraph(iBuffer.toString().replace("\n ", "\n "), PdfFont.getFixedFont()); p.setLeading(9.5f); // was 13.5f iDoc.add(p); iBuffer = new StringBuffer(); iPageNo++; }
/** * Constructs a <CODE>PdfChunk</CODE>-object. * * @param string the content of the <CODE>PdfChunk</CODE>-object * @param other Chunk with the same style you want for the new Chunk */ PdfChunk(String string, PdfChunk other) { thisChunk[0] = this; value = string; this.font = other.font; this.attributes = other.attributes; this.noStroke = other.noStroke; this.baseFont = other.baseFont; Object obj[] = (Object[]) attributes.get(Chunk.IMAGE); if (obj == null) { // image = null; ssteward: dropped in 1.44 } else { // image = (Image)obj[0]; ssteward: dropped in 1.44 offsetX = ((Float) obj[1]).floatValue(); offsetY = ((Float) obj[2]).floatValue(); changeLeading = ((Boolean) obj[3]).booleanValue(); } encoding = font.getFont().getEncoding(); splitCharacter = (SplitCharacter) noStroke.get(Chunk.SPLITCHARACTER); if (splitCharacter == null) splitCharacter = this; }
float getCharWidth(char c) { if (noPrint(c)) return 0; return font.width(c); }
/** * Returns the width of this <CODE>PdfChunk</CODE>. * * @return a width */ float width() { return font.width(value); }
/** * 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; /* ssteward: dropped in 1.44 if (image != null) { if (image.scaledWidth() > 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(); 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 = 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; } currentWidth += font.width(character); 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, 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 < 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; }
/** * Constructs a <CODE>PdfChunk</CODE>-object. * * @param chunk the original <CODE>Chunk</CODE>-object * @param action the <CODE>PdfAction</CODE> if the <CODE>Chunk</CODE> comes from an <CODE>Anchor * </CODE> */ PdfChunk(Chunk chunk, PdfAction action) { thisChunk[0] = this; value = chunk.content(); Font f = chunk.font(); float size = f.size(); if (size == Font.UNDEFINED) size = 12; baseFont = f.getBaseFont(); int style = f.style(); if (style == Font.UNDEFINED) { style = Font.NORMAL; } if (baseFont == null) { // translation of the font-family to a PDF font-family baseFont = f.getCalculatedBaseFont(false); } else { // bold simulation if ((style & Font.BOLD) != 0) attributes.put( Chunk.TEXTRENDERMODE, new Object[] { new Integer(PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE), new Float(size / 30f), null }); // italic simulation if ((style & Font.ITALIC) != 0) attributes.put(Chunk.SKEW, new float[] {0, ITALIC_ANGLE}); } font = new PdfFont(baseFont, size); // other style possibilities HashMap attr = chunk.getAttributes(); if (attr != null) { for (Iterator i = attr.keySet().iterator(); i.hasNext(); ) { Object name = i.next(); if (keysAttributes.containsKey(name)) { attributes.put(name, attr.get(name)); } else if (keysNoStroke.containsKey(name)) { noStroke.put(name, attr.get(name)); } } if ("".equals(attr.get(Chunk.GENERICTAG))) { attributes.put(Chunk.GENERICTAG, chunk.content()); } } if (f.isUnderlined()) { Object obj[] = {null, new float[] {0, 1f / 15, 0, -1f / 3, 0}}; Object unders[][] = Chunk.addToArray((Object[][]) attributes.get(Chunk.UNDERLINE), obj); attributes.put(Chunk.UNDERLINE, unders); } if (f.isStrikethru()) { Object obj[] = {null, new float[] {0, 1f / 15, 0, 1f / 3, 0}}; Object unders[][] = Chunk.addToArray((Object[][]) attributes.get(Chunk.UNDERLINE), obj); attributes.put(Chunk.UNDERLINE, unders); } if (action != null) attributes.put(Chunk.ACTION, action); // the color can't be stored in a PdfFont noStroke.put(Chunk.COLOR, f.color()); noStroke.put(Chunk.ENCODING, font.getFont().getEncoding()); Object obj[] = (Object[]) attributes.get(Chunk.IMAGE); if (obj == null) { // image = null; ssteward: dropped in 1.44 } else { attributes.remove(Chunk.HSCALE); // images are scaled in other ways // image = (Image)obj[0]; ssteward: dropped in 1.44 offsetX = ((Float) obj[1]).floatValue(); offsetY = ((Float) obj[2]).floatValue(); changeLeading = ((Boolean) obj[3]).booleanValue(); } // font.setImage(image); ssteward: dropped in 1.44 Float hs = (Float) attributes.get(Chunk.HSCALE); if (hs != null) font.setHorizontalScaling(hs.floatValue()); encoding = font.getFont().getEncoding(); splitCharacter = (SplitCharacter) noStroke.get(Chunk.SPLITCHARACTER); if (splitCharacter == null) splitCharacter = this; }