/** * 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 Dictionary<string,object>(); image = null; font = PdfFont.DefaultFont; return pc; } else return null; } IHyphenationEvent hyphenationEvent = null; if (noStroke.ContainsKey(Chunk.HYPHENATION)) 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 += GetCharWidth(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 += GetCharWidth(Utilities.ConvertToUtf32(valueArray[currentPosition], valueArray[currentPosition + 1])); else currentWidth += GetCharWidth(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 += GetCharWidth(Utilities.ConvertToUtf32(value, currentPosition)); else currentWidth += GetCharWidth(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; }
// 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 = null; if (attributes.ContainsKey(Chunk.IMAGE)) 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; if (noStroke.ContainsKey(Chunk.SPLITCHARACTER)) splitCharacter = (ISplitCharacter)noStroke[Chunk.SPLITCHARACTER]; else splitCharacter = DefaultSplitCharacter.DEFAULT; }
/** * 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 == iTextSharp.text.Font.UNDEFINED) size = 12; baseFont = f.BaseFont; BaseFont bf = f.BaseFont; int style = f.Style; if (style == iTextSharp.text.Font.UNDEFINED) { style = iTextSharp.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 & iTextSharp.text.Font.BOLD) != 0) attributes[Chunk.TEXTRENDERMODE] = new Object[]{PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, size / 30f, null}; // italic simulation if ((style & iTextSharp.text.Font.ITALIC) != 0) attributes[Chunk.SKEW] = new float[]{0, ITALIC_ANGLE}; } font = new PdfFont(baseFont, size); // other style possibilities Dictionary<string,object> attr = chunk.Attributes; if (attr != null) { foreach (KeyValuePair<string,object> entry in attr) { string name = entry.Key; if (keysAttributes.ContainsKey(name)) { attributes[name] = entry.Value; } else if (keysNoStroke.ContainsKey(name)) { noStroke[name] = entry.Value; } } if (attr.ContainsKey(Chunk.GENERICTAG) && "".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[][] obja = null; if (attributes.ContainsKey(Chunk.UNDERLINE)) obja = (Object[][])attributes[Chunk.UNDERLINE]; Object[][] unders = Utilities.AddToArray(obja, obj); attributes[Chunk.UNDERLINE] = unders; } if (f.IsStrikethru()) { Object[] obj = {null, new float[]{0, 1f / 15, 0, 1f / 3, 0}}; Object[][] obja = null; if (attributes.ContainsKey(Chunk.UNDERLINE)) obja = (Object[][])attributes[Chunk.UNDERLINE]; Object[][] unders = Utilities.AddToArray(obja, 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 = null; if (attributes.ContainsKey(Chunk.IMAGE)) 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.TryGetValue(Chunk.HSCALE, out hs); if (hs != null) font.HorizontalScaling = (float)hs; encoding = font.Font.Encoding; if (noStroke.ContainsKey(Chunk.SPLITCHARACTER)) splitCharacter = (ISplitCharacter)noStroke[Chunk.SPLITCHARACTER]; else 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) { // Image does not fit the line, resize if requested if (image.ScaleToFitLineWhenOverflow) { float scalePercent = width / image.Width * 100; image.ScalePercent(scalePercent); return(null); } 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 += GetCharWidth(Utilities.ConvertToUtf32(value, currentPosition)); } else { currentWidth += GetCharWidth(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); }
internal void WriteLine(PdfLine line, PdfContentByte text, PdfContentByte graphics) { PdfFont currentFont = null; foreach (PdfChunk chunk in line) { if (!chunk.IsImage() && chunk.Font.CompareTo(currentFont) != 0) { currentFont = chunk.Font; text.SetFontAndSize(currentFont.Font, currentFont.Size); } Object[] textRender = (Object[])chunk.GetAttribute(Chunk.TEXTRENDERMODE); int tr = 0; float strokeWidth = 1; BaseColor color = chunk.Color; BaseColor strokeColor = null; if (textRender != null) { tr = (int)textRender[0] & 3; if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL) { text.SetTextRenderingMode(tr); } if (tr == PdfContentByte.TEXT_RENDER_MODE_STROKE || tr == PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE) { strokeWidth = (float)textRender[1]; if (strokeWidth != 1) { text.SetLineWidth(strokeWidth); } strokeColor = (BaseColor)textRender[2]; if (strokeColor == null) { strokeColor = color; } if (strokeColor != null) { text.SetColorStroke(strokeColor); } } } object charSpace = chunk.GetAttribute(Chunk.CHAR_SPACING); // no char space setting means "leave it as is". if (charSpace != null && !curCharSpace.Equals(charSpace)) { curCharSpace = (float)charSpace; text.SetCharacterSpacing(curCharSpace); } if (color != null) { text.SetColorFill(color); } text.ShowText(chunk.ToString()); if (color != null) { text.ResetRGBColorFill(); } if (tr != PdfContentByte.TEXT_RENDER_MODE_FILL) { text.SetTextRenderingMode(PdfContentByte.TEXT_RENDER_MODE_FILL); } if (strokeColor != null) { text.ResetRGBColorStroke(); } if (strokeWidth != 1) { text.SetLineWidth(1); } } }
/** * 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 Dictionary <string, object>(); image = null; font = PdfFont.DefaultFont; return(pc); } else { return(null); } } IHyphenationEvent hyphenationEvent = null; if (noStroke.ContainsKey(Chunk.HYPHENATION)) { 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 += GetCharWidth(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 += GetCharWidth(Utilities.ConvertToUtf32(valueArray[currentPosition], valueArray[currentPosition + 1])); } else { currentWidth += GetCharWidth(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 == iTextSharp.text.Font.UNDEFINED) { size = 12; } baseFont = f.BaseFont; BaseFont bf = f.BaseFont; int style = f.Style; if (style == iTextSharp.text.Font.UNDEFINED) { style = iTextSharp.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 & iTextSharp.text.Font.BOLD) != 0) { attributes[Chunk.TEXTRENDERMODE] = new Object[] { PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, size / 30f, null } } ; // italic simulation if ((style & iTextSharp.text.Font.ITALIC) != 0) { attributes[Chunk.SKEW] = new float[] { 0, ITALIC_ANGLE } } ; } font = new PdfFont(baseFont, size); // other style possibilities Dictionary <string, object> attr = chunk.Attributes; if (attr != null) { foreach (KeyValuePair <string, object> entry in attr) { string name = entry.Key; if (keysAttributes.ContainsKey(name)) { attributes[name] = entry.Value; } else if (keysNoStroke.ContainsKey(name)) { noStroke[name] = entry.Value; } } if (attr.ContainsKey(Chunk.GENERICTAG) && "".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[][] obja = null; if (attributes.ContainsKey(Chunk.UNDERLINE)) { obja = (Object[][])attributes[Chunk.UNDERLINE]; } Object[][] unders = Utilities.AddToArray(obja, obj); attributes[Chunk.UNDERLINE] = unders; } if (f.IsStrikethru()) { Object[] obj = { null, new float[] { 0, 1f / 15, 0, 1f / 3, 0 } }; Object[][] obja = null; if (attributes.ContainsKey(Chunk.UNDERLINE)) { obja = (Object[][])attributes[Chunk.UNDERLINE]; } Object[][] unders = Utilities.AddToArray(obja, 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 lh; if (attributes.TryGetValue(Chunk.LINEHEIGHT, out lh)) { changeLeading = true; leading = (float)lh; } Object[] obj2 = null; if (attributes.ContainsKey(Chunk.IMAGE)) { 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.TryGetValue(Chunk.HSCALE, out hs); if (hs != null) { font.HorizontalScaling = (float)hs; } encoding = font.Font.Encoding; if (noStroke.ContainsKey(Chunk.SPLITCHARACTER)) { splitCharacter = (ISplitCharacter)noStroke[Chunk.SPLITCHARACTER]; } else { 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; char character; while (currentPosition < length) { // the width of every character is added to the currentWidth character = value[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 retVal = value.Substring(currentPosition); value = value.Substring(0, currentPosition); PdfChunk tmp = new PdfChunk(retVal, this); return(tmp); }
/// <summary> /// Constructs a PdfChunk -object. /// </summary> /// <param name="chunk">the original Chunk -object</param> /// <param name="action">the PdfAction if the Chunk comes from an Anchor </param> public PdfChunk(Chunk chunk, PdfAction action) { _thisChunk[0] = this; value = chunk.Content; var f = chunk.Font; var size = f.Size; if (size.ApproxEquals(text.Font.UNDEFINED)) { size = 12; } BaseFont = f.BaseFont; var bf = f.BaseFont; var style = f.Style; if (style == text.Font.UNDEFINED) { style = 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 & text.Font.BOLD) != 0) { Attributes[Chunk.TEXTRENDERMODE] = new object[] { PdfContentByte.TEXT_RENDER_MODE_FILL_STROKE, size / 30f, null }; } // italic simulation if ((style & text.Font.ITALIC) != 0) { Attributes[Chunk.SKEW] = new[] { 0, ItalicAngle }; } } font = new PdfFont(BaseFont, size); // other style possibilities var attr = chunk.Attributes; if (attr != null) { foreach (DictionaryEntry entry in attr) { var 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[] { 0, 1f / 15, 0, -1f / 3, 0 } }; var unders = Utilities.AddToArray((object[][])Attributes[Chunk.UNDERLINE], obj); Attributes[Chunk.UNDERLINE] = unders; } if (f.IsStrikethru()) { object[] obj = { null, new[] { 0, 1f / 15, 0, 1f / 3, 0 } }; var 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; var 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; var 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; } }
/** * Outputs the lines to the document. The output can be simulated. * @param simulate <CODE>true</CODE> to simulate the writting to the document * @return returns the result of the operation. It can be <CODE>NO_MORE_TEXT</CODE> * and/or <CODE>NO_MORE_COLUMN</CODE> * @throws DocumentException on error */ public int go(bool simulate) { bool dirty = false; float ratio = spaceCharRatio; Object[] currentValues = new Object[2]; PdfFont currentFont = null; float lastBaseFactor = 0F; currentValues[1] = lastBaseFactor; PdfDocument pdf = null; PdfContentByte graphics = null; int localRunDirection = PdfWriter.RUN_DIRECTION_NO_BIDI; if (runDirection != PdfWriter.RUN_DIRECTION_DEFAULT) { localRunDirection = runDirection; } if (text != null) { pdf = text.PdfDocument; graphics = text.Duplicate; } else if (!simulate) { throw new Exception("ColumnText.go with simulate==false and text==null."); } if (!simulate) { if (ratio == GLOBAL_SPACE_CHAR_RATIO) { ratio = text.PdfWriter.SpaceCharRatio; } else if (ratio < 0.001f) { ratio = 0.001f; } } float firstIndent = 0; int status = 0; if (rectangularWidth > 0) { for (;;) { firstIndent = (lastWasNewline ? indent : followingIndent); if (rectangularWidth <= firstIndent + rightIndent) { status = NO_MORE_COLUMN; if (bidiLine.isEmpty()) { status |= NO_MORE_TEXT; } break; } if (bidiLine.isEmpty()) { status = NO_MORE_TEXT; break; } float yTemp = yLine; PdfLine line = bidiLine.processLine(rectangularWidth - firstIndent - rightIndent, alignment, localRunDirection); float maxSize = line.MaxSizeSimple; currentLeading = fixedLeading + maxSize * multipliedLeading; float[] xx = findLimitsTwoLines(); if (xx == null) { status = NO_MORE_COLUMN; yLine = yTemp; bidiLine.restore(); break; } float x1 = Math.Max(xx[0], xx[2]); if (!simulate && !dirty) { text.beginText(); dirty = true; } if (!simulate) { currentValues[0] = currentFont; text.setTextMatrix(x1 + (line.IsRTL ? rightIndent : firstIndent) + line.IndentLeft, yLine); pdf.writeLineToContent(line, text, graphics, currentValues, ratio); currentFont = (PdfFont)currentValues[0]; } lastWasNewline = line.isNewlineSplit(); yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0; } } else { currentLeading = fixedLeading; for (;;) { firstIndent = (lastWasNewline ? indent : followingIndent); float yTemp = yLine; float[] xx = findLimitsTwoLines(); if (xx == null) { status = NO_MORE_COLUMN; if (bidiLine.isEmpty()) { status |= NO_MORE_TEXT; } yLine = yTemp; break; } if (bidiLine.isEmpty()) { status = NO_MORE_TEXT; yLine = yTemp; break; } float x1 = Math.Max(xx[0], xx[2]); float x2 = Math.Min(xx[1], xx[3]); if (x2 - x1 <= firstIndent + rightIndent) { continue; } if (!simulate && !dirty) { text.beginText(); dirty = true; } PdfLine line = bidiLine.processLine(x2 - x1 - firstIndent - rightIndent, alignment, localRunDirection); if (!simulate) { currentValues[0] = currentFont; text.setTextMatrix(x1 + (line.IsRTL ? rightIndent : firstIndent) + line.IndentLeft, yLine); pdf.writeLineToContent(line, text, graphics, currentValues, ratio); currentFont = (PdfFont)currentValues[0]; } lastWasNewline = line.isNewlineSplit(); yLine -= line.isNewlineSplit() ? extraParagraphSpace : 0; } } if (dirty) { text.endText(); text.Add(graphics); } return(status); }