/** * 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. */ internal PdfChunk Split(float width) { newlineSplit = false; if (image != null) { if (image.ScaledWidth > width) { PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this); value = ""; attributes = new Hashtable(); image = null; font = PdfFont.DefaultFont; return pc; } else return null; } IHyphenationEvent hyphenationEvent = (IHyphenationEvent)noStroke[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 = (char)0; BaseFont ft = font.Font; bool surrogate = false; if (ft.FontType == 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 - lastSpace), font.Font, font.Size, width - lastSpaceWidth); string post = hyphenationEvent.HyphenatedWordPost; 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 retVal = value.Substring(splitPosition); value = Trim(value.Substring(0, splitPosition)); PdfChunk tmp = new PdfChunk(retVal, this); return tmp; }
/** * 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. */ internal PdfChunk Truncate(float width) { if (image != null) { if (image.ScaledWidth > width) { PdfChunk pc = new PdfChunk("", this); value = ""; attributes.Remove(Chunk.IMAGE); image = null; font = PdfFont.DefaultFont; 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; bool surrogate = false; 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[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 retVal = value.Substring(currentPosition); value = value.Substring(0, currentPosition); PdfChunk tmp = new PdfChunk(retVal, this); return tmp; }
/** * 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> */ internal PdfChunk(Chunk chunk, PdfAction action) { thisChunk[0] = this; value = chunk.Content; Font f = chunk.Font; float size = f.Size; if (size == Legacy.Text.Font.UNDEFINED) size = 12; baseFont = f.BaseFont; BaseFont bf = f.BaseFont; int style = f.Style; if (style == Legacy.Text.Font.UNDEFINED) { style = Legacy.Text.Font.NORMAL; } if (baseFont == null) { // translation of the font-family to a PDF font-family baseFont = f.GetCalculatedBaseFont(false); } else{ // bold simulation if ((style & Legacy.Text.Font.BOLD) != 0) attributes[Chunk.TEXTRENDERMODE] = new Object[]{PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, size / 30f, null}; // italic simulation if ((style & Legacy.Text.Font.ITALIC) != 0) attributes[Chunk.SKEW] = new float[]{0, ITALIC_ANGLE}; } font = new PdfFont(baseFont, size); // other style possibilities Hashtable attr = chunk.Attributes; if (attr != null) { foreach (DictionaryEntry entry in attr) { string name = (string)entry.Key; if (keysAttributes.ContainsKey(name)) { attributes[name] = entry.Value; } else if (keysNoStroke.ContainsKey(name)) { noStroke[name] = entry.Value; } } if ("".Equals(attr[Chunk.GENERICTAG])) { attributes[Chunk.GENERICTAG] = chunk.Content; } } if (f.IsUnderlined()) { Object[] obj = {null, new float[]{0, 1f / 15, 0, -1f / 3, 0}}; Object[][] unders = Utilities.AddToArray((Object[][])attributes[Chunk.UNDERLINE], obj); attributes[Chunk.UNDERLINE] = unders; } if (f.IsStrikethru()) { Object[] obj = {null, new float[]{0, 1f / 15, 0, 1f / 3, 0}}; Object[][] unders = Utilities.AddToArray((Object[][])attributes[Chunk.UNDERLINE], obj); attributes[Chunk.UNDERLINE] = unders; } if (action != null) attributes[Chunk.ACTION] = action; // the color can't be stored in a PdfFont noStroke[Chunk.COLOR] = f.Color; noStroke[Chunk.ENCODING] = font.Font.Encoding; Object[] obj2 = (Object[])attributes[Chunk.IMAGE]; if (obj2 == null) image = null; else { attributes.Remove(Chunk.HSCALE); // images are scaled in other ways image = (Image)obj2[0]; offsetX = ((float)obj2[1]); offsetY = ((float)obj2[2]); changeLeading = (bool)obj2[3]; } font.Image = image; object hs = attributes[Chunk.HSCALE]; if (hs != null) font.HorizontalScaling = (float)hs; encoding = font.Font.Encoding; splitCharacter = (ISplitCharacter)noStroke[Chunk.SPLITCHARACTER]; if (splitCharacter == null) splitCharacter = DefaultSplitCharacter.DEFAULT; }
// constructors /** * Constructs a <CODE>PdfChunk</CODE>-object. * * @param string the content of the <CODE>PdfChunk</CODE>-object * @param font the <CODE>PdfFont</CODE> * @param attributes the metrics attributes * @param noStroke the non metric attributes */ internal PdfChunk(string str, PdfChunk other) { thisChunk[0] = this; value = str; this.font = other.font; this.attributes = other.attributes; this.noStroke = other.noStroke; this.baseFont = other.baseFont; Object[] obj = (Object[])attributes[Chunk.IMAGE]; if (obj == null) image = null; else { image = (Image)obj[0]; offsetX = (float)obj[1]; offsetY = (float)obj[2]; changeLeading = (bool)obj[3]; } encoding = font.Font.Encoding; splitCharacter = (ISplitCharacter)noStroke[Chunk.SPLITCHARACTER]; if (splitCharacter == null) splitCharacter = DefaultSplitCharacter.DEFAULT; }
/** * 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. */ internal PdfChunk Truncate(float width) { if (image != null) { if (image.ScaledWidth > width) { PdfChunk pc = new PdfChunk("", this); value = ""; attributes.Remove(Chunk.IMAGE); image = null; font = PdfFont.DefaultFont; 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; bool surrogate = false; 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[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 retVal = value.Substring(currentPosition); value = value.Substring(0, currentPosition); PdfChunk tmp = new PdfChunk(retVal, this); return(tmp); }
/** * 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. */ internal PdfChunk Split(float width) { newlineSplit = false; if (image != null) { if (image.ScaledWidth > width) { PdfChunk pc = new PdfChunk(Chunk.OBJECT_REPLACEMENT_CHARACTER, this); value = ""; attributes = new Hashtable(); image = null; font = PdfFont.DefaultFont; return(pc); } else { return(null); } } IHyphenationEvent hyphenationEvent = (IHyphenationEvent)noStroke[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 = (char)0; BaseFont ft = font.Font; bool surrogate = false; if (ft.FontType == 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 - lastSpace), font.Font, font.Size, width - lastSpaceWidth); string post = hyphenationEvent.HyphenatedWordPost; 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 retVal = value.Substring(splitPosition); value = Trim(value.Substring(0, splitPosition)); PdfChunk tmp = new PdfChunk(retVal, this); return(tmp); }
/** * 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> */ internal PdfChunk(Chunk chunk, PdfAction action) { thisChunk[0] = this; value = chunk.Content; Font f = chunk.Font; float size = f.Size; if (size == Legacy.Text.Font.UNDEFINED) { size = 12; } baseFont = f.BaseFont; BaseFont bf = f.BaseFont; int style = f.Style; if (style == Legacy.Text.Font.UNDEFINED) { style = Legacy.Text.Font.NORMAL; } if (baseFont == null) { // translation of the font-family to a PDF font-family baseFont = f.GetCalculatedBaseFont(false); } else { // bold simulation if ((style & Legacy.Text.Font.BOLD) != 0) { attributes[Chunk.TEXTRENDERMODE] = new Object[] { PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, size / 30f, null } } ; // italic simulation if ((style & Legacy.Text.Font.ITALIC) != 0) { attributes[Chunk.SKEW] = new float[] { 0, ITALIC_ANGLE } } ; } font = new PdfFont(baseFont, size); // other style possibilities Hashtable attr = chunk.Attributes; if (attr != null) { foreach (DictionaryEntry entry in attr) { string name = (string)entry.Key; if (keysAttributes.ContainsKey(name)) { attributes[name] = entry.Value; } else if (keysNoStroke.ContainsKey(name)) { noStroke[name] = entry.Value; } } if ("".Equals(attr[Chunk.GENERICTAG])) { attributes[Chunk.GENERICTAG] = chunk.Content; } } if (f.IsUnderlined()) { Object[] obj = { null, new float[] { 0, 1f / 15, 0, -1f / 3, 0 } }; Object[][] unders = Utilities.AddToArray((Object[][])attributes[Chunk.UNDERLINE], obj); attributes[Chunk.UNDERLINE] = unders; } if (f.IsStrikethru()) { Object[] obj = { null, new float[] { 0, 1f / 15, 0, 1f / 3, 0 } }; Object[][] unders = Utilities.AddToArray((Object[][])attributes[Chunk.UNDERLINE], obj); attributes[Chunk.UNDERLINE] = unders; } if (action != null) { attributes[Chunk.ACTION] = action; } // the color can't be stored in a PdfFont noStroke[Chunk.COLOR] = f.Color; noStroke[Chunk.ENCODING] = font.Font.Encoding; Object[] obj2 = (Object[])attributes[Chunk.IMAGE]; if (obj2 == null) { image = null; } else { attributes.Remove(Chunk.HSCALE); // images are scaled in other ways image = (Image)obj2[0]; offsetX = ((float)obj2[1]); offsetY = ((float)obj2[2]); changeLeading = (bool)obj2[3]; } font.Image = image; object hs = attributes[Chunk.HSCALE]; if (hs != null) { font.HorizontalScaling = (float)hs; } encoding = font.Font.Encoding; splitCharacter = (ISplitCharacter)noStroke[Chunk.SPLITCHARACTER]; if (splitCharacter == null) { splitCharacter = DefaultSplitCharacter.DEFAULT; } }