/// <summary>Process the whitespace inside the Text Tree.</summary> /// <remarks> /// Process the whitespace inside the Text Tree. /// Whitespace is collapsed and new lines are handled /// A leading element in each subtree is handled different: the preceding whitespace is trimmed instead of kept /// </remarks> /// <param name="root">root of the text-renderer subtree</param> /// <param name="isLeadingElement">true if this element is a leading element(either the first child or the first element after an absolute position change) /// </param> public static void ProcessWhiteSpace(TextSvgBranchRenderer root, bool isLeadingElement) { // when svg is parsed by jsoup it leaves all whitespace in text element as is. Meaning that // tab/space indented xml files will retain their tabs and spaces. // The following regex replaces all whitespace with a single space. bool performLeadingTrim = isLeadingElement; foreach (ISvgTextNodeRenderer child in root.GetChildren()) { //If leaf, process contents, if branch, call function again if (child is TextSvgBranchRenderer) { //Branch processing ProcessWhiteSpace((TextSvgBranchRenderer)child, child.ContainsAbsolutePositionChange()); ((TextSvgBranchRenderer)child).MarkWhiteSpaceProcessed(); } if (child is TextLeafSvgNodeRenderer) { //Leaf processing TextLeafSvgNodeRenderer leafRend = (TextLeafSvgNodeRenderer)child; //Process text String toProcess = leafRend.GetAttribute(SvgConstants.Attributes.TEXT_CONTENT); toProcess = iText.IO.Util.StringUtil.ReplaceAll(toProcess, "\\s+", " "); toProcess = WhiteSpaceUtil.CollapseConsecutiveSpaces(toProcess); if (performLeadingTrim) { //Trim leading white spaces toProcess = TrimLeadingWhitespace(toProcess); toProcess = TrimTrailingWhitespace(toProcess); performLeadingTrim = false; } else { //only collapse whitespace toProcess = TrimTrailingWhitespace(toProcess); } leafRend.SetAttribute(SvgConstants.Attributes.TEXT_CONTENT, toProcess); } } }
/// <summary>Adds text to the waiting leaves.</summary> /// <param name="text">the text</param> public virtual void Add(String text) { if (!keepLineBreaks && collapseSpaces) { text = WhiteSpaceUtil.CollapseConsecutiveSpaces(text); } else { if (keepLineBreaks && collapseSpaces) { StringBuilder sb = new StringBuilder(text.Length); for (int i = 0; i < text.Length; i++) { if (TrimUtil.IsNonLineBreakSpace(text[i])) { if (sb.Length == 0 || sb[sb.Length - 1] != ' ') { sb.Append(" "); } } else { sb.Append(text[i]); } } text = sb.ToString(); } else { // false == collapseSpaces // prohibit trimming first and last spaces StringBuilder sb = new StringBuilder(text.Length); sb.Append('\u200d'); for (int i = 0; i < text.Length; i++) { sb.Append(text[i]); if ('\n' == text[i] || ('\r' == text[i] && i + 1 < text.Length && '\n' != text[i + 1])) { sb.Append('\u200d'); } } if ('\u200d' == sb[sb.Length - 1]) { sb.Delete(sb.Length - 1, sb.Length); } text = sb.ToString(); } } if (CssConstants.UPPERCASE.Equals(textTransform)) { text = text.ToUpperInvariant(); } else { if (CssConstants.LOWERCASE.Equals(textTransform)) { text = text.ToLowerInvariant(); } } waitingLeaves.Add(new iText.Layout.Element.Text(text)); }