// Render element elmt onto the page currentPage. // parent refers to the parent element within the current rendered page. When // a page break occurs a new parent hierarchy is build for the new page // and parent will point to the bottom of the new parent hierarchy. // currentPage will refer to the current page being built. It will be updated // inside this routine if elmt spans pages. // top refers to the absolute position in the master rendered document. private decimal RecurseRender(Element elmt, ref Container parent, ref Page currentPage, decimal top, decimal pos ) { decimal elementHeight = CalcHeight(elmt); decimal requiredHeight = elementHeight; decimal elementTop; // If this element has repeated elements associated with it then make sure // that there is room on the page for those repeated elements. if (elmt is Container) { // If this is a toggle item, then determine if we want to include it in the // rendered page. if (((Container)elmt).Toggle != null && ((Container)elmt).Toggle.ToggleState == TextElement.ToggleStateEnum.closed) { return(0); } foreach (Container re in ((Container)elmt).RepeatList) { if (re.AbsoluteTop > elmt.AbsoluteTop) { requiredHeight += CalcHeight(re); } } } // If this element is spanning pages, then calculate the top // based on the starting position of this page. if (elmt.Parent != null && elmt.Parent.AbsoluteTop < currentPage.RelativeTop) { elementTop = pos - (currentPage.RelativeTop - elmt.Parent.AbsoluteTop); } else { elementTop = pos; } bool newPage = false; if (elmt is Container && ((Container)elmt).PageBreakBefore) { newPage = true; } else if (PosOnPage(parent) + elementTop + requiredHeight > currentPage.AvailableHeight) { // If the element doesn't fit entirely on this page and we should keep it on // one page, then create a new page. if (!(elmt is Container) || (elmt is Container && ((Container)elmt).KeepTogether)) { newPage = true; } } if (newPage) { currentPage.AddFooters(parent); currentPage = new Page(PageWidth - RightMargin - LeftMargin, PageHeight - TopMargin - BottomMargin, top, elmt.Parent, ref parent); _pageList.Add(currentPage); } Element newElement = null; if (elmt is Container) { newElement = ((Container)elmt).Copy(false); newElement.CanGrowVertically = true; // Loop through the repeated elements foreach (Container r in ((Container)elmt).RepeatList) { // If the repeated element is below the current element then reserve space for it at the bottom. if (r.AbsoluteTop > elmt.AbsoluteTop) { currentPage.FooterSpace += (r.Top - pos + elementHeight + CalcHeight(r)); } } } if (elmt is TextElement) { newElement = new TextElement((TextElement)elmt); } if (elmt is ImageElement) { newElement = new ImageElement((ImageElement)elmt); } newElement.Parent = parent; newElement.Top = 0; newElement.Height = 0; if (parent != null) { parent.Children.Add(newElement); } // Set the height of this element to either the height of the source element // or the height of the remaining space on the page. Whichever is less. newElement.Top = elementTop; newElement.Height = Math.Min(elementHeight, currentPage.AvailableHeight - PosOnPage(parent)); if (elmt is Container) { Container be = newElement as Container; decimal pos2 = 0; foreach (Element child in ((Container)elmt).Children) { if (elmt is FixedContainer) { pos2 = child.Top; } pos2 += RecurseRender(child, ref be, ref currentPage, top + elmt.Top, pos2); parent = be.Parent; } // Loop through the repeated elements foreach (Container r in be.RepeatList) { // If the repeated element is below the current element then release the reserved space if (r.AbsoluteTop > be.AbsoluteTop) { currentPage.FooterSpace -= (r.Top - elmt.Top + elementHeight + CalcHeight(r)); } } if (be.PageBreakAfter) { currentPage.AddFooters(parent); currentPage = new Page(PageWidth - RightMargin - LeftMargin, PageHeight - TopMargin - BottomMargin, top, elmt.Parent, ref parent); _pageList.Add(currentPage); } } return(elementHeight); }
public ImageElement(ImageElement ie) : base(ie) { }