public static string GetBackIterators(Paragraph paragraph) { ParagraphIterator iter = new ParagraphIterator(paragraph.Elements); iter = iter.GetLastLeaf(); string retString = ""; while (iter != null) { retString += "[" + iter.Current.GetType().Name + ":]"; if (iter.Current is Text) retString += ((Text)iter.Current).Content; iter = iter.GetPreviousLeaf(); } return retString; }
/// <summary> /// Returns the previous iterator to a leaf in the document object tree pointing. /// </summary> /// <returns>The previous leaf, null if none exists.</returns> internal ParagraphIterator GetPreviousLeaf() { //Move up to appropriate parent element ParagraphIterator parIterator = GetParentIterator(); if (parIterator == null) { return(null); } int elementIndex = LastIndex; ParagraphElements parEls = (ParagraphElements)parIterator._current; while (elementIndex == 0) { elementIndex = parIterator.LastIndex; parIterator = parIterator.GetParentIterator(); if (parIterator == null) { break; } parEls = (ParagraphElements)parIterator._current; } if (parIterator == null) { return(null); } int newIndex = elementIndex - 1; if (newIndex < 0) { return(null); } List <int> indices = new List <int>(parIterator._positionIndices);//(Array_List)parIterator.positionIndices.Clone(); indices.Add(newIndex); DocumentObject obj = GetNodeObject(parEls[newIndex]); ParagraphIterator iterator = new ParagraphIterator(_rootNode, obj, indices); return(iterator.SeekLastLeaf()); }
/// <summary> /// Returns the next iterator in the tree pointing to a leaf. /// </summary> /// <remarks>This function is intended to receive the renderable objects of a paragraph. /// Thus, empty ParagraphElement objects (which are collections) don't count as leafs.</remarks> internal ParagraphIterator GetNextLeaf() { //Move up to appropriate parent element ParagraphIterator parIterator = GetParentIterator(); if (parIterator == null) { return(null); } int elementIndex = this.LastIndex; ParagraphElements parEls = (ParagraphElements)parIterator.current; while (elementIndex == parEls.Count - 1) { elementIndex = parIterator.LastIndex; parIterator = parIterator.GetParentIterator(); if (parIterator == null) { break; } parEls = (ParagraphElements)parIterator.current; } if (parIterator == null) { return(null); } int newIndex = elementIndex + 1; if (newIndex >= parEls.Count) { return(null); } ArrayList indices = (ArrayList)parIterator.positionIndices.Clone(); indices.Add(newIndex); DocumentObject obj = GetNodeObject(parEls[newIndex]); ParagraphIterator iterator = new ParagraphIterator(this.rootNode, obj, indices); return(iterator.SeekFirstLeaf()); }
/// <summary> /// Initializes this instance for formatting. /// </summary> /// <param name="area">The area for formatting</param> /// <param name="previousFormatInfo">A previous format info.</param> /// <returns>False, if nothing of the paragraph will fit the area any more.</returns> private bool InitFormat(Area area, FormatInfo previousFormatInfo) { this.phase = Phase.Formatting; this.tabOffsets = new ArrayList(); ParagraphFormatInfo prevParaFormatInfo = (ParagraphFormatInfo)previousFormatInfo; if (previousFormatInfo == null || prevParaFormatInfo.LineCount == 0) { ((ParagraphFormatInfo)this.renderInfo.FormatInfo).isStarting = true; ParagraphIterator parIt = new ParagraphIterator(this.paragraph.Elements); this.currentLeaf = parIt.GetFirstLeaf(); this.isFirstLine = true; } else { this.currentLeaf = prevParaFormatInfo.GetLastLineInfo().endIter.GetNextLeaf(); this.isFirstLine = false; ((ParagraphFormatInfo)this.renderInfo.FormatInfo).isStarting = false; } this.startLeaf = this.currentLeaf; this.currentVerticalInfo = CalcCurrentVerticalInfo(); this.currentYPosition = area.Y + TopBorderOffset; this.formattingArea = area; Rectangle rect = this.formattingArea.GetFittingRect(this.currentYPosition, this.currentVerticalInfo.height); if (rect == null) return false; this.currentXPosition = rect.X + LeftIndent; if (this.isFirstLine) FormatListSymbol(); return true; }
/// <summary> /// Returns the previous iterator to a leaf in the document object tree pointing. /// </summary> /// <returns>The previous leaf, null if none exists.</returns> internal ParagraphIterator GetPreviousLeaf() { //Move up to appropriate parent element ParagraphIterator parIterator = GetParentIterator(); if (parIterator == null) return null; int elementIndex = this.LastIndex; ParagraphElements parEls = (ParagraphElements)parIterator.current; while (elementIndex == 0) { elementIndex = parIterator.LastIndex; parIterator = parIterator.GetParentIterator(); if (parIterator == null) break; parEls = (ParagraphElements)parIterator.current; } if (parIterator == null) return null; int newIndex = elementIndex - 1; if (newIndex < 0) return null; ArrayList indices = (ArrayList)parIterator.positionIndices.Clone(); indices.Add(newIndex); DocumentObject obj = GetNodeObject(parEls[newIndex]); ParagraphIterator iterator = new ParagraphIterator(this.rootNode, obj, indices); return iterator.SeekLastLeaf(); }
/// <summary> /// Returns the next iterator in the tree pointing to a leaf. /// </summary> /// <remarks>This function is intended to receive the renderable objects of a paragraph. /// Thus, empty ParagraphElement objects (which are collections) don't count as leafs.</remarks> internal ParagraphIterator GetNextLeaf() { //Move up to appropriate parent element ParagraphIterator parIterator = GetParentIterator(); if (parIterator == null) return null; int elementIndex = LastIndex; ParagraphElements parEls = (ParagraphElements)parIterator._current; while (elementIndex == parEls.Count - 1) { elementIndex = parIterator.LastIndex; parIterator = parIterator.GetParentIterator(); if (parIterator == null) break; parEls = (ParagraphElements)parIterator._current; } if (parIterator == null) return null; int newIndex = elementIndex + 1; if (newIndex >= parEls.Count) return null; List<int> indices = new List<int>(parIterator._positionIndices); //(Array_List)parIterator.positionIndices.Clone(); indices.Add(newIndex); DocumentObject obj = GetNodeObject(parEls[newIndex]); ParagraphIterator iterator = new ParagraphIterator(_rootNode, obj, indices); return iterator.SeekFirstLeaf(); }
FormatResult FormatLineBreak() { if (this.phase != Phase.Rendering) this.currentLeaf = this.currentLeaf.GetNextLeaf(); this.savedWordWidth = 0; return FormatResult.NewLine; }
/// <summary> /// Initializes this instance for formatting. /// </summary> /// <param name="area">The area for formatting</param> /// <param name="previousFormatInfo">A previous format info.</param> /// <returns>False, if nothing of the paragraph will fit the area any more.</returns> private bool InitFormat(Area area, FormatInfo previousFormatInfo) { _phase = Phase.Formatting; _tabOffsets = new List<TabOffset>(); ParagraphFormatInfo prevParaFormatInfo = (ParagraphFormatInfo)previousFormatInfo; if (previousFormatInfo == null || prevParaFormatInfo.LineCount == 0) { ((ParagraphFormatInfo)_renderInfo.FormatInfo)._isStarting = true; ParagraphIterator parIt = new ParagraphIterator(_paragraph.Elements); _currentLeaf = parIt.GetFirstLeaf(); _isFirstLine = true; } else { _currentLeaf = prevParaFormatInfo.GetLastLineInfo().EndIter.GetNextLeaf(); _isFirstLine = false; ((ParagraphFormatInfo)_renderInfo.FormatInfo)._isStarting = false; } _startLeaf = _currentLeaf; _currentVerticalInfo = CalcCurrentVerticalInfo(); _currentYPosition = area.Y + TopBorderOffset; _formattingArea = area; Rectangle rect = _formattingArea.GetFittingRect(_currentYPosition, _currentVerticalInfo.Height); if (rect == null) return false; _currentXPosition = rect.X + LeftIndent; if (_isFirstLine) FormatListSymbol(); return true; }
void SaveBeforeProbing(out ParagraphIterator paragraphIter, out int blankCount, out XUnit wordsWidth, out XUnit xPosition, out XUnit lineWidth, out XUnit blankWidth) { paragraphIter = this.currentLeaf; blankCount = this.currentBlankCount; xPosition = this.currentXPosition; lineWidth = this.currentLineWidth; wordsWidth = this.currentWordsWidth; blankWidth = this.savedBlankWidth; }
/// <summary> /// Renders a single line. /// </summary> /// <param name="lineInfo"></param> void RenderLine(LineInfo lineInfo) { this.currentVerticalInfo = lineInfo.vertical; this.currentLeaf = lineInfo.startIter; this.startLeaf = lineInfo.startIter; this.endLeaf = lineInfo.endIter; this.currentBlankCount = lineInfo.blankCount; this.currentLineWidth = lineInfo.lineWidth; this.currentWordsWidth = lineInfo.wordsWidth; this.currentXPosition = this.StartXPosition; this.tabOffsets = lineInfo.tabOffsets; this.lastTabPassed = lineInfo.lastTab == null; this.lastTab = lineInfo.lastTab; this.tabIdx = 0; bool ready = this.currentLeaf == null; if (this.isFirstLine) RenderListSymbol(); while (!ready) { if (this.currentLeaf.Current == lineInfo.endIter.Current) ready = true; if (this.currentLeaf.Current == lineInfo.lastTab) this.lastTabPassed = true; RenderElement(this.currentLeaf.Current); this.currentLeaf = this.currentLeaf.GetNextLeaf(); } this.currentYPosition += lineInfo.vertical.height; this.isFirstLine = false; }
void ReMeasureLine(ref LineInfo lineInfo) { //--- Save --------------------------------- ParagraphIterator iter; int blankCount; XUnit xPosition; XUnit lineWidth; XUnit wordsWidth; XUnit blankWidth; SaveBeforeProbing(out iter, out blankCount, out wordsWidth, out xPosition, out lineWidth, out blankWidth); bool origLastTabPassed = this.lastTabPassed; //------------------------------------------ this.currentLeaf = lineInfo.startIter; this.endLeaf = lineInfo.endIter; this.formattingArea = this.renderInfo.LayoutInfo.ContentArea; this.tabOffsets = new ArrayList(); this.currentLineWidth = 0; this.currentWordsWidth = 0; Rectangle fittingRect = this.formattingArea.GetFittingRect(this.currentYPosition, this.currentVerticalInfo.height); if (fittingRect == null) GetType(); if (fittingRect != null) { this.currentXPosition = fittingRect.X + this.LeftIndent; FormatListSymbol(); bool goOn = true; while (goOn && this.currentLeaf != null) { if (this.currentLeaf.Current == lineInfo.lastTab) this.lastTabPassed = true; FormatElement(this.currentLeaf.Current); goOn = this.currentLeaf != null && this.currentLeaf.Current != this.endLeaf.Current; if (goOn) this.currentLeaf = this.currentLeaf.GetNextLeaf(); } lineInfo.lineWidth = this.currentLineWidth; lineInfo.wordsWidth = this.currentWordsWidth; lineInfo.blankCount = this.currentBlankCount; lineInfo.tabOffsets = this.tabOffsets; lineInfo.reMeasureLine = false; this.lastTabPassed = origLastTabPassed; } RestoreAfterProbing(iter, blankCount, wordsWidth, xPosition, lineWidth, blankWidth); }
/// <summary> /// Probes the paragraph after a tab. /// Caution: This Function resets the word count and line width before doing its work. /// </summary> /// <returns>True if the tab causes a linebreak.</returns> bool ProbeAfterTab() { this.currentLineWidth = 0; this.currentBlankCount = 0; //Extra for auto tab after list symbol //TODO: KLPO4KLPO: Check if this conditional statement is still required if (this.currentLeaf != null && IsTab(this.currentLeaf.Current)) this.currentLeaf = this.currentLeaf.GetNextLeaf(); bool wordAppeared = false; while (this.currentLeaf != null && !IsLineBreak(this.currentLeaf.Current) && !IsTab(this.currentLeaf.Current)) { FormatResult result = FormatElement(this.currentLeaf.Current); if (result != FormatResult.Continue) break; wordAppeared = wordAppeared || IsWordLikeElement(this.currentLeaf.Current); this.currentLeaf = this.currentLeaf.GetNextLeaf(); } return this.currentLeaf != null && !IsLineBreak(this.currentLeaf.Current) && !IsTab(this.currentLeaf.Current) && !wordAppeared; }
/// <summary> /// Probes the paragraph elements after a right aligned tab stop and returns the vertical text position to start at. /// </summary> /// <param name="tabStopPosition">Position of the tab to probe.</param> /// <param name="notFitting">Out parameter determining whether the tab causes a line break.</param> /// <returns>The new x-position to restart behind the tab.</returns> XUnit ProbeAfterDecimalAlignedTab(XUnit tabStopPosition, out bool notFitting) { notFitting = false; ParagraphIterator savedLeaf = this.currentLeaf; //Extra for auto tab after list symbol if (IsTab(this.currentLeaf.Current)) this.currentLeaf = this.currentLeaf.GetNextLeaf(); if (this.currentLeaf == null) { this.currentLeaf = savedLeaf; return this.currentXPosition + tabStopPosition; } VerticalLineInfo newVerticalInfo = CalcCurrentVerticalInfo(); Rectangle fittingRect = this.formattingArea.GetFittingRect(this.currentYPosition, newVerticalInfo.height); if (fittingRect == null) { notFitting = true; this.currentLeaf = savedLeaf; return this.currentXPosition; } if (IsPlainText(this.currentLeaf.Current)) { Text text = (Text)this.currentLeaf.Current; string word = text.Content; int lastIndex = text.Content.LastIndexOfAny(new char[] { ',', '.' }); if (lastIndex > 0) word = word.Substring(0, lastIndex); XUnit wordLength = MeasureString(word); notFitting = this.currentXPosition + wordLength >= formattingArea.X + formattingArea.Width + Tolerance; if (!notFitting) return this.formattingArea.X + tabStopPosition - wordLength; else return this.currentXPosition; } this.currentLeaf = savedLeaf; return ProbeAfterRightAlignedTab(tabStopPosition, out notFitting); }
void HandleNonFittingLine() { if (this.currentLeaf != null) { if (this.savedWordWidth > 0) { this.currentWordsWidth = this.savedWordWidth; this.currentLineWidth = this.savedWordWidth; } this.currentLeaf = this.currentLeaf.GetNextLeaf(); this.currentYPosition += this.currentVerticalInfo.height; this.currentVerticalInfo = new VerticalLineInfo(); } }
FormatResult FormatSoftHyphen() { if (this.currentLeaf.Current == this.startLeaf.Current) return FormatResult.Continue; ParagraphIterator nextIter = this.currentLeaf.GetNextLeaf(); ParagraphIterator prevIter = this.currentLeaf.GetPreviousLeaf(); if (!IsWordLikeElement(prevIter.Current) || !IsWordLikeElement(nextIter.Current)) return FormatResult.Continue; //--- Save --------------------------------- ParagraphIterator iter; int blankCount; XUnit xPosition; XUnit lineWidth; XUnit wordsWidth; XUnit blankWidth; SaveBeforeProbing(out iter, out blankCount, out wordsWidth, out xPosition, out lineWidth, out blankWidth); //------------------------------------------ this.currentLeaf = nextIter; FormatResult result = FormatElement(nextIter.Current); //--- Restore ------------------------------ RestoreAfterProbing(iter, blankCount, wordsWidth, xPosition, lineWidth, blankWidth); //------------------------------------------ if (result == FormatResult.Continue) return FormatResult.Continue; RestoreAfterProbing(iter, blankCount, wordsWidth, xPosition, lineWidth, blankWidth); Rectangle fittingRect = this.formattingArea.GetFittingRect(this.currentYPosition, this.currentVerticalInfo.height); XUnit hyphenWidth = MeasureString("-"); if (xPosition + hyphenWidth <= fittingRect.X + fittingRect.Width + Tolerance // If one word fits, but not the hyphen, the formatting must continue with the next leaf || prevIter.Current == this.startLeaf.Current) { // For Tabs in justified context if (!IgnoreHorizontalGrowth) { this.currentWordsWidth += hyphenWidth; this.currentLineWidth += hyphenWidth; } this.currentLeaf = nextIter; return FormatResult.NewLine; } else { this.currentWordsWidth -= this.savedWordWidth; this.currentLineWidth -= this.savedWordWidth; this.currentLineWidth -= GetPreviousBlankWidth(prevIter); this.currentLeaf = prevIter; return FormatResult.NewLine; } }
XUnit GetPreviousBlankWidth(ParagraphIterator beforeIter) { XUnit width = 0; ParagraphIterator savedIter = this.currentLeaf; this.currentLeaf = beforeIter.GetPreviousLeaf(); while (this.currentLeaf != null) { if (this.currentLeaf.Current is BookmarkField) this.currentLeaf = this.currentLeaf.GetPreviousLeaf(); else if (IsBlank(this.currentLeaf.Current)) { if (!IgnoreBlank()) width = CurrentWordDistance; break; } else break; } this.currentLeaf = savedIter; return width; }
string GetOutlineTitle() { ParagraphIterator iter = new ParagraphIterator(this.paragraph.Elements); iter = iter.GetFirstLeaf(); bool ignoreBlank = true; string title = ""; while (iter != null) { DocumentObject current = iter.Current; if (!ignoreBlank && (IsBlank(current) || IsTab(current) || IsLineBreak(current))) { title += " "; ignoreBlank = true; } else if (current is Text) { title += ((Text)current).Content; ignoreBlank = false; } else if (IsRenderedField(current)) { title += GetFieldValue(current); ignoreBlank = false; } else if (IsSymbol(current)) { title += GetSymbol((Character)current); ignoreBlank = false; } if (title.Length > 64) break; iter = iter.GetNextLeaf(); } return title; }
/// <summary> /// Starts a new line by resetting measuring values. /// Do not call before the first first line is formatted! /// </summary> /// <returns>True, if the new line may fit the formatting area.</returns> bool StartNewLine() { this.tabOffsets = new ArrayList(); this.lastTab = null; this.lastTabPosition = 0; this.currentYPosition += this.currentVerticalInfo.height; #if true Rectangle rect = this.formattingArea.GetFittingRect(currentYPosition, this.currentVerticalInfo.height + BottomBorderOffset); if (rect == null) return false; this.isFirstLine = false; this.currentXPosition = StartXPosition; // depends on "currentVerticalInfo" this.currentVerticalInfo = new VerticalLineInfo(); this.currentVerticalInfo = CalcCurrentVerticalInfo(); #else if (this.formattingArea.GetFittingRect(currentYPosition, this.currentVerticalInfo.height + BottomBorderOffset) == null) return false; this.currentVerticalInfo = new VerticalLineInfo(); this.currentVerticalInfo = CalcCurrentVerticalInfo(); this.isFirstLine = false; this.currentXPosition = this.StartXPosition; #endif this.startLeaf = this.currentLeaf; this.currentBlankCount = 0; this.currentWordsWidth = 0; this.currentLineWidth = 0; return true; }
void RestoreAfterProbing(ParagraphIterator paragraphIter, int blankCount, XUnit wordsWidth, XUnit xPosition, XUnit lineWidth, XUnit blankWidth) { this.currentLeaf = paragraphIter; this.currentBlankCount = blankCount; this.currentXPosition = xPosition; this.currentLineWidth = lineWidth; this.currentWordsWidth = wordsWidth; this.savedBlankWidth = blankWidth; }
/// <summary> /// Formats the paragraph by performing line breaks etc. /// </summary> /// <param name="area">The area in which to render.</param> /// <param name="previousFormatInfo">The format info that was obtained on formatting the same paragraph on a previous area.</param> internal override void Format(Area area, FormatInfo previousFormatInfo) { ParagraphFormatInfo formatInfo = ((ParagraphFormatInfo)this.renderInfo.FormatInfo); if (!InitFormat(area, previousFormatInfo)) { formatInfo.isStarting = false; return; } formatInfo.isEnding = true; FormatResult lastResult = FormatResult.Continue; while (this.currentLeaf != null) { FormatResult result = FormatElement(this.currentLeaf.Current); switch (result) { case FormatResult.Ignore: this.currentLeaf = this.currentLeaf.GetNextLeaf(); break; case FormatResult.Continue: lastResult = result; this.currentLeaf = this.currentLeaf.GetNextLeaf(); break; case FormatResult.NewLine: lastResult = result; StoreLineInformation(); if (!StartNewLine()) { result = FormatResult.NewArea; formatInfo.isEnding = false; } break; } if (result == FormatResult.NewArea) { lastResult = result; formatInfo.isEnding = false; break; } } if (formatInfo.IsEnding && lastResult != FormatResult.NewLine) StoreLineInformation(); formatInfo.imageRenderInfos = this.imageRenderInfos; FinishLayoutInfo(); }