private ContainerVisual CreatePageVisual(IBlankPage blankPage, Visual contentVisual) { var newPage = new ContainerVisual(); newPage.Children.Add(blankPage.PageVisual); newPage.Children.Add(TransformVisualToBox(contentVisual, blankPage.DataContentBox)); return newPage; }
public override DocumentPage GetPage(int pageNumber) { var page = _paginator.GetPage(pageNumber + _startIndex); // Create a new ContainerVisual as a new parent for page children var cv = new ContainerVisual(); if (page.Visual is FixedPage) { foreach (var child in ((FixedPage)page.Visual).Children) { // Make a shallow clone of the child using reflection var childClone = (UIElement)child.GetType().GetMethod("MemberwiseClone", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(child, null); // Setting the parent of the cloned child to the created ContainerVisual by using Reflection. // WARNING: If we use Add and Remove methods on the FixedPage.Children, for some reason it will // throw an exception concerning event handlers after the printing job has finished. var parentField = childClone.GetType().GetField("_parent", BindingFlags.Instance | BindingFlags.NonPublic); if (parentField != null) { parentField.SetValue(childClone, null); cv.Children.Add(childClone); } } return new DocumentPage(cv, page.Size, page.BleedBox, page.ContentBox); } return page; }
public override DocumentPage GetPage(int pageNumber) { // Get the requested page. DocumentPage page = flowDocumentPaginator.GetPage(pageNumber); // Wrap the page in a Visual. You can then add a transformation and extras. ContainerVisual newVisual = new ContainerVisual(); newVisual.Children.Add(page.Visual); // Create a header. DrawingVisual header = new DrawingVisual(); using (DrawingContext context = header.RenderOpen()) { Typeface typeface = new Typeface("Times New Roman"); FormattedText text = new FormattedText("Page " + (pageNumber + 1).ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 14, Brushes.Black); // Leave a quarter-inch of space between the page edge and this text. context.DrawText(text, new Point(96*0.25, 96*0.25)); } // Add the title to the visual. newVisual.Children.Add(header); // Wrap the visual in a new page. DocumentPage newPage = new DocumentPage(newVisual); return newPage; }
// ------------------------------------------------------------------ // Syncs a floating element para list with a visual collection // ------------------------------------------------------------------ internal static void UpdateFloatingElementVisuals(ContainerVisual visual, List<BaseParaClient> floatingElementList) { VisualCollection visualChildren = visual.Children; int visualIndex = 0; if(floatingElementList == null || floatingElementList.Count == 0) { visualChildren.Clear(); } else { for(int index = 0; index < floatingElementList.Count; index++) { Visual paraVisual = floatingElementList[index].Visual; while(visualIndex < visualChildren.Count && visualChildren[visualIndex] != paraVisual) { visualChildren.RemoveAt(visualIndex); } if(visualIndex == visualChildren.Count) { visualChildren.Add(paraVisual); } visualIndex++; } if(visualChildren.Count > floatingElementList.Count) { visualChildren.RemoveRange(floatingElementList.Count, visualChildren.Count - floatingElementList.Count); } } }
public override DocumentPage GetPage(int pageNumber) { DocumentPage page = m_Paginator.GetPage(pageNumber); // Create a wrapper visual for transformation and add extras ContainerVisual newpage = new ContainerVisual(); DrawingVisual title = new DrawingVisual(); using (DrawingContext ctx = title.RenderOpen()) { if (m_Typeface == null) { m_Typeface = new Typeface("Times New Roman"); } FormattedText text = new FormattedText("Page " + (pageNumber + 1), System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 14, Brushes.Black); ctx.DrawText(text, new Point(0, -96 / 4)); // 1/4 inch above page content } DrawingVisual background = new DrawingVisual(); using (DrawingContext ctx = background.RenderOpen()) { ctx.DrawRectangle(new SolidColorBrush(Color.FromRgb(255, 255, 255)), null, page.ContentBox); } newpage.Children.Add(background); // Scale down page and center ContainerVisual smallerPage = new ContainerVisual(); smallerPage.Children.Add(page.Visual); smallerPage.Transform = new MatrixTransform(0.95, 0, 0, 0.95, 0.025 * page.ContentBox.Width, 0.025 * page.ContentBox.Height); newpage.Children.Add(smallerPage); newpage.Children.Add(title); newpage.Transform = new TranslateTransform(m_Margin.Width, m_Margin.Height); return new DocumentPage(newpage, m_PageSize, Move(page.BleedBox), Move(page.ContentBox)); }
// ------------------------------------------------------------------ // Clips visual children to a specified rect // ------------------------------------------------------------------ internal static void ClipChildrenToRect(ContainerVisual visual, Rect rect) { VisualCollection visualChildren = visual.Children; for(int index = 0; index < visualChildren.Count; index++) { ((ContainerVisual)visualChildren[index]).Clip = new RectangleGeometry(rect); } }
public override DocumentPage GetPage(int pageNumber) { DocumentPage originalPage = _originalPaginator.GetPage(pageNumber); ContainerVisual fixedPage = new ContainerVisual(); fixedPage.Children.Add(originalPage.Visual); fixedPage.Transform = new TranslateTransform(_pageMargin.Width, _pageMargin.Height); Rect bleedBox = AdjustForMargins(originalPage.BleedBox); Rect contentBox = AdjustForMargins(originalPage.ContentBox); return new DocumentPage(fixedPage, _pageSize, bleedBox, contentBox); }
private static Visual TransformVisualToBox(Visual contentVisual, Rect dataContentBox) { var visual = new ContainerVisual { Clip = new RectangleGeometry(new Rect(dataContentBox.Size)) }; visual.Children.Add(contentVisual); visual.Transform = new TranslateTransform(dataContentBox.Left, dataContentBox.Top); return visual; }
public Chart(Window w) { container = new ContainerVisual(); RenderOptions.SetBitmapScalingMode(this, BitmapScalingMode.Linear); RenderOptions.SetEdgeMode(this, EdgeMode.Aliased); core = new ChartCore(w); container.Children.Add(core); AddVisualChild(container); }
// ------------------------------------------------------------------ // // Visual Helpers // // ------------------------------------------------------------------ #region Visual Helpers // ------------------------------------------------------------------ // Update mirroring transform. // ------------------------------------------------------------------ internal static void UpdateMirroringTransform(FlowDirection parentFD, FlowDirection childFD, ContainerVisual visualChild, double width) { // Set mirroring transform if necessary, or clear it just in case it was set in the previous // format process. if (parentFD != childFD) { MatrixTransform transform = new MatrixTransform(-1.0, 0.0, 0.0, 1.0, width, 0.0); visualChild.Transform = transform; visualChild.SetValue(FrameworkElement.FlowDirectionProperty, childFD); } else { visualChild.Transform = null; visualChild.ClearValue(FrameworkElement.FlowDirectionProperty); } }
/// <summary> /// 每次打印一页时,此方法都会被调用一次 /// 打印的内容由它提供 /// </summary> /// <param name="pageNumber"></param> /// <returns></returns> public override DocumentPage GetPage(int pageNumber) { DocumentPage originalPage = _originalPaginator.GetPage(pageNumber); ContainerVisual fixedPage = new ContainerVisual(); // 创建页眉 DrawingVisual header = new DrawingVisual(); using (DrawingContext context = header.RenderOpen()) { Typeface typeface = new Typeface("Times New Roman"); FormattedText text = new FormattedText("第" + (pageNumber + 1).ToString()+"页", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 14, Brushes.Black); context.DrawText(text, new Point(0, 0)); } //将页面主体下移0.25 inch,以腾出空间显示页眉 ContainerVisual PageArea = new ContainerVisual(); PageArea.Children.Add(originalPage.Visual); PageArea.Transform = new TranslateTransform( 0, 0.25*96 ); //组合页眉 fixedPage.Children.Add(header); //组合页主体 fixedPage.Children.Add(PageArea); //平移全页,为Margin腾出空间 fixedPage.Transform = new TranslateTransform( _pageMargin.Width, _pageMargin.Height ); //根据新的纸张可打印区域生成调整后页面 return new DocumentPage( fixedPage, _pageSize, AdjustForMargins(originalPage.BleedBox), AdjustForMargins(originalPage.ContentBox) ); }
public override DocumentPage GetPage(int pageNumber) { DocumentPage page = m_Paginator.GetPage(pageNumber); // Create a wrapper visual for transformation and add extras ContainerVisual newpage = new ContainerVisual(); DrawingVisual title = new DrawingVisual(); using (DrawingContext ctx = title.RenderOpen()) { if (m_Typeface == null) { m_Typeface = new Typeface("Times New Roman"); } LineSegment line = new LineSegment(new Point(100, 570), false); FormattedText titleText = new FormattedText("Список устройств конфигурации", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 20, Brushes.Black); FormattedText text = new FormattedText("Страница " + (pageNumber + 1), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 14, Brushes.Black); FormattedText textDate = new FormattedText(_dateTime.ToString(), CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 14, Brushes.Black); var pen = new Pen(); pen.Brush = Brushes.Black; pen.Thickness = 2; ctx.DrawLine(pen, new Point(10, 570), new Point(650, 570)); ctx.DrawText(text, new Point(580, 580)); ctx.DrawText(textDate, new Point(10, 580)); if (pageNumber == 0) ctx.DrawText(titleText, new Point(200, 5)); } //DrawingVisual background = new DrawingVisual(); //using (DrawingContext ctx = background.RenderOpen()) //{ // ctx.DrawRectangle(new SolidColorBrush(Color.FromRgb(240, 240, 240)), null, page.ContentBox); //} //newpage.Children.Add(background); // Scale down page and center ContainerVisual smallerPage = new ContainerVisual(); smallerPage.Children.Add(page.Visual); smallerPage.Transform = new MatrixTransform(0.95, 0, 0, 0.95, 0.025 * page.ContentBox.Width, 0.025 * page.ContentBox.Height); newpage.Children.Add(smallerPage); newpage.Children.Add(title); newpage.Transform = new TranslateTransform(m_Margin.Width, m_Margin.Height); return new DocumentPage(newpage, m_PageSize, Move(page.BleedBox), Move(page.ContentBox)); }
private void RenderCompositeLines( ContainerVisual visual, ref PTS.FSTEXTDETAILSFULL textDetails, bool ignoreUpdateInfo) { ErrorHandler.Assert(!PTS.ToBoolean(textDetails.fDropCapPresent), ErrorHandler.NotSupportedDropCap); VisualCollection visualChildren = visual.Children; int cpTextParaStart = Paragraph.ParagraphStartCharacterPosition; // Get list of composite lines. PTS.FSLINEDESCRIPTIONCOMPOSITE [] arrayLineDesc; PtsHelper.LineListCompositeFromTextPara(PtsContext, _paraHandle.Value, ref textDetails, out arrayLineDesc); // Create lines and render them if (!PTS.ToBoolean(textDetails.fUpdateInfoForLinesPresent) || ignoreUpdateInfo) { // There is no update information, hence need to recreate // visuals for all lines. visualChildren.Clear(); for (int index = 0; index < arrayLineDesc.Length; index++) { PTS.FSLINEDESCRIPTIONCOMPOSITE lineDesc = arrayLineDesc[index]; int visualIndex; VisualCollection lineVisuals; if (lineDesc.cElements == 1) { visualIndex = index; lineVisuals = visualChildren; } else { visualIndex = 0; ParagraphElementVisual lineVisual = new ParagraphElementVisual(); visualChildren.Add(lineVisual); lineVisuals = lineVisual.Children; } // Get list of line elements PTS.FSLINEELEMENT [] arrayLineElement; PtsHelper.LineElementListFromCompositeLine(PtsContext, ref lineDesc, out arrayLineElement); for (int elIndex = 0; elIndex < arrayLineElement.Length; elIndex++) { PTS.FSLINEELEMENT element = arrayLineElement[elIndex]; // Create and format line Line.FormattingContext ctx = new Line.FormattingContext(false, PTS.ToBoolean(element.fClearOnLeft), PTS.ToBoolean(element.fClearOnRight), TextParagraph.TextRunCache); Line line = new Line(Paragraph.StructuralCache.TextFormatterHost, this, cpTextParaStart); if(IsOptimalParagraph) { ctx.LineFormatLengthTarget = element.dcpLim - element.dcpFirst; } TextParagraph.FormatLineCore(line, element.pfsbreakreclineclient, ctx, element.dcpFirst, element.dur, PTS.ToBoolean(lineDesc.fTreatedAsFirst), element.dcpFirst); // Assert that number of characters in Text line is the same as our expected length Invariant.Assert(line.SafeLength == element.dcpLim - element.dcpFirst, "Line length is out of [....]"); // Create and validate line's visual ContainerVisual lineVisual = line.CreateVisual(); lineVisuals.Insert(visualIndex + elIndex, lineVisual); lineVisual.Offset = new Vector(TextDpi.FromTextDpi(element.urStart), TextDpi.FromTextDpi(lineDesc.vrStart)); // Dispose the line line.Dispose(); } } } else { // Shift lines before change if(textDetails.dvrShiftBeforeChange != 0) { for (int index = 0; index < textDetails.cLinesBeforeChange; index++) { ContainerVisual lineVisual = (ContainerVisual) visualChildren[index]; Vector offset = lineVisual.Offset; offset.Y += TextDpi.FromTextDpi(textDetails.dvrShiftBeforeChange); lineVisual.Offset = offset; } } // Skip not changed lines // Remove changed lines visualChildren.RemoveRange(textDetails.cLinesBeforeChange, textDetails.cLinesChanged - textDetails.dcLinesChanged); // Add new lines for (int index = textDetails.cLinesBeforeChange; index < textDetails.cLinesBeforeChange + textDetails.cLinesChanged; index++) { PTS.FSLINEDESCRIPTIONCOMPOSITE lineDesc = arrayLineDesc[index]; int visualIndex; VisualCollection lineVisuals; if (lineDesc.cElements == 1) { visualIndex = index; lineVisuals = visualChildren; } else { visualIndex = 0; ParagraphElementVisual lineVisual = new ParagraphElementVisual(); visualChildren.Add(lineVisual); lineVisuals = lineVisual.Children; } // Get list of line elements. PTS.FSLINEELEMENT [] arrayLineElement; PtsHelper.LineElementListFromCompositeLine(PtsContext, ref lineDesc, out arrayLineElement); for (int elIndex = 0; elIndex < arrayLineElement.Length; elIndex++) { PTS.FSLINEELEMENT element = arrayLineElement[elIndex]; // Create and format line Line.FormattingContext ctx = new Line.FormattingContext(false, PTS.ToBoolean(element.fClearOnLeft), PTS.ToBoolean(element.fClearOnRight), TextParagraph.TextRunCache); Line line = new Line(Paragraph.StructuralCache.TextFormatterHost, this, cpTextParaStart); if(IsOptimalParagraph) { ctx.LineFormatLengthTarget = element.dcpLim - element.dcpFirst; } TextParagraph.FormatLineCore(line, element.pfsbreakreclineclient, ctx, element.dcpFirst, element.dur, PTS.ToBoolean(lineDesc.fTreatedAsFirst), element.dcpFirst); // Assert that number of characters in Text line is the same as our expected length Invariant.Assert(line.SafeLength == element.dcpLim - element.dcpFirst, "Line length is out of [....]"); // Create and validate line's visual ContainerVisual lineVisual = line.CreateVisual(); lineVisuals.Insert(visualIndex + elIndex, lineVisual); lineVisual.Offset = new Vector(TextDpi.FromTextDpi(element.urStart), TextDpi.FromTextDpi(lineDesc.vrStart)); // Dispose the line line.Dispose(); } } // Shift remaining lines for (int index = textDetails.cLinesBeforeChange + textDetails.cLinesChanged; index < arrayLineDesc.Length; index++) { ContainerVisual lineVisual = (ContainerVisual)visualChildren[index]; Vector offset = lineVisual.Offset; offset.Y += TextDpi.FromTextDpi(textDetails.dvrShiftAfterChange); lineVisual.Offset = offset; } } }
private void UpdateViewportSimpleLines( ContainerVisual visual, ref PTS.FSTEXTDETAILSFULL textDetails, ref PTS.FSRECT viewport) { VisualCollection visualChildren = visual.Children; Debug.Assert(!PTS.ToBoolean(textDetails.fLinesComposite)); try { // Common case, invisible para - Clear our children, _lineIndexFirstVisual will be cleared later if (!IntersectsWithRectOnV(ref viewport)) { visualChildren.Clear(); } else if (ContainedInRectOnV(ref viewport) && _lineIndexFirstVisual == 0 && visualChildren.Count == textDetails.cLines) { // Totally visible para // Nothing to do here, totally visible and lines are updated. Don't query line list } else { // Index of first visible line int lineIndexFirstVisible = -1; // Index of first invisible line - MAY BE EQUAL TO COUNT. int lineIndexFirstInvisible = -1; int cpTextParaStart = Paragraph.ParagraphStartCharacterPosition; PTS.FSLINEDESCRIPTIONSINGLE[] arrayLineDesc; PtsHelper.LineListSimpleFromTextPara(PtsContext, _paraHandle.Value, ref textDetails, out arrayLineDesc); // If this para is totally contained in the viewport, valid range is all lines. if (ContainedInRectOnV(ref viewport)) { lineIndexFirstVisible = 0; lineIndexFirstInvisible = textDetails.cLines; } else { // Subset is valid, walk the lines to determine the first (even partially) visible line int lineIndex; for (lineIndex = 0; lineIndex < arrayLineDesc.Length; lineIndex++) { PTS.FSLINEDESCRIPTIONSINGLE lineDesc = arrayLineDesc[lineIndex]; // Vrstart is top of line, not baseline. if ((lineDesc.vrStart + lineDesc.dvrAscent + lineDesc.dvrDescent) > viewport.v) { break; } } // May be equal to count if no lines are visible lineIndexFirstVisible = lineIndex; // Subset is valid, walk the lines to determine the first totally invisible line for (lineIndex = lineIndexFirstVisible; lineIndex < arrayLineDesc.Length; lineIndex++) { PTS.FSLINEDESCRIPTIONSINGLE lineDesc = arrayLineDesc[lineIndex]; if ((lineDesc.vrStart) > (viewport.v + viewport.dv)) { break; } } // May be equal to count if the remainder of lines is visible. lineIndexFirstInvisible = lineIndex; } // If we have some committed range, but there's no overlap between the previously committed range and the new desired range, // Delete all existing lines. if (_lineIndexFirstVisual != -1 && ((lineIndexFirstVisible > _lineIndexFirstVisual + visualChildren.Count) || (lineIndexFirstInvisible < _lineIndexFirstVisual))) { visualChildren.Clear(); _lineIndexFirstVisual = -1; } // If no existing lines, interate over visible range and add appropriate lines. if (_lineIndexFirstVisual == -1) { for (int index = lineIndexFirstVisible; index < lineIndexFirstInvisible; index++) { PTS.FSLINEDESCRIPTIONSINGLE lineDesc = arrayLineDesc[index]; ContainerVisual lineVisual = CreateLineVisual(ref lineDesc, cpTextParaStart); visualChildren.Add(lineVisual); lineVisual.Offset = new Vector(TextDpi.FromTextDpi(lineDesc.urStart), TextDpi.FromTextDpi(lineDesc.vrStart)); } _lineIndexFirstVisual = lineIndexFirstVisible; } else if (lineIndexFirstVisible != _lineIndexFirstVisual || (lineIndexFirstInvisible - lineIndexFirstVisible) != visualChildren.Count) { // Need to resolve existing list with new list - [....] the beginning of the list // |----------------| (Old committed range) // |-------| (New committed range) // Need to add visuals to the beginning to [....] the start position if (lineIndexFirstVisible < _lineIndexFirstVisual) { for (int index = lineIndexFirstVisible; index < _lineIndexFirstVisual; index++) { PTS.FSLINEDESCRIPTIONSINGLE lineDesc = arrayLineDesc[index]; ContainerVisual lineVisual = CreateLineVisual(ref lineDesc, cpTextParaStart); visualChildren.Insert(index - lineIndexFirstVisible, lineVisual); lineVisual.Offset = new Vector(TextDpi.FromTextDpi(lineDesc.urStart), TextDpi.FromTextDpi(lineDesc.vrStart)); } } else if (lineIndexFirstVisible != _lineIndexFirstVisual) { // |----------------| (Old committed range) // |-------| (New committed range) // Need to remove visuals from the beginning to [....] start positions. visualChildren.RemoveRange(0, lineIndexFirstVisible - _lineIndexFirstVisual); } _lineIndexFirstVisual = lineIndexFirstVisible; } Debug.Assert(_lineIndexFirstVisual == lineIndexFirstVisible); // Now [....] the end of the list, two cases.. // Fewer lines than existed before, remove lines from end // |---------------| // |----------| if (lineIndexFirstInvisible - lineIndexFirstVisible < visualChildren.Count) { int visualsToRemove = visualChildren.Count - (lineIndexFirstInvisible - lineIndexFirstVisible); visualChildren.RemoveRange(visualChildren.Count - visualsToRemove, visualsToRemove); } else if ((lineIndexFirstInvisible - lineIndexFirstVisible) > visualChildren.Count) { // Or we need to add more lines to the end, format and insert those visuals // |--------------| // |----------------------| for (int index = _lineIndexFirstVisual + visualChildren.Count; index < lineIndexFirstInvisible; index++) { PTS.FSLINEDESCRIPTIONSINGLE lineDesc = arrayLineDesc[index]; ContainerVisual lineVisual = CreateLineVisual(ref lineDesc, cpTextParaStart); visualChildren.Add(lineVisual); lineVisual.Offset = new Vector(TextDpi.FromTextDpi(lineDesc.urStart), TextDpi.FromTextDpi(lineDesc.vrStart)); } } Debug.Assert(visualChildren.Count == (lineIndexFirstInvisible - lineIndexFirstVisible)); } } finally { // Ensure the _lineIndexFirstVisual is syncced with visualChildren.Count if (visualChildren.Count == 0) { _lineIndexFirstVisual = -1; } } #if VERIFY_VISUALS // Verify visuals against visuals list. VerifyVisuals(ref textDetails); #endif }
/// <summary> /// This is most important method, modifies the original /// </summary> /// <param name="pageNumber">page number</param> /// <returns></returns> public override DocumentPage GetPage(int pageNumber) { for (int i = 0; i < 2; i++) // do it twice because filling context values could change the page count { // compute page count if (pageNumber == 0) { _paginator.ComputePageCount(); _pageCount = _paginator.PageCount; } // fill context values FillContextValues(_reportContextValues, pageNumber + 1); } DocumentPage page = _paginator.GetPage(pageNumber); if (page == DocumentPage.Missing) return DocumentPage.Missing; // page missing _pageSize = page.Size; // add header block ContainerVisual newPage = new ContainerVisual(); if (_blockPageHeader != null) { ContainerVisual v = CloneVisualBlock(_blockPageHeader, pageNumber + 1); v.Offset = new Vector(0, 0); newPage.Children.Add(v); } // TODO: process ReportContextValues // add content page ContainerVisual smallerPage = new ContainerVisual(); smallerPage.Offset = new Vector(0, _report.PageHeaderHeight / 100d * _report.PageHeight); smallerPage.Children.Add(page.Visual); newPage.Children.Add(smallerPage); // add footer block if (_blockPageFooter != null) { ContainerVisual v = CloneVisualBlock(_blockPageFooter, pageNumber + 1); v.Offset = new Vector(0, _report.PageHeight - _report.PageFooterHeight / 100d * _report.PageHeight); newPage.Children.Add(v); } // create modified BleedBox Rect bleedBox = new Rect(page.BleedBox.Left, page.BleedBox.Top, page.BleedBox.Width, _report.PageHeight - (page.Size.Height - page.BleedBox.Size.Height)); // create modified ContentBox Rect contentBox = new Rect(page.ContentBox.Left, page.ContentBox.Top, page.ContentBox.Width, _report.PageHeight - (page.Size.Height - page.ContentBox.Size.Height)); DocumentPage dp = new DocumentPage(newPage, new Size(_report.PageWidth, _report.PageHeight), bleedBox, contentBox); _report.FireEventGetPageCompleted(new GetPageCompletedEventArgs(page, pageNumber, null, false, null)); return dp; }
/// <summary> /// When overridden in a derived class, gets the <see cref="T:System.Windows.Documents.DocumentPage" /> for the specified page number. /// </summary> /// <param name="pageNumber">The zero-based page number of the document page that is needed.</param> /// <returns>The <see cref="T:System.Windows.Documents.DocumentPage" /> for the specified <paramref name="pageNumber" />, or <see cref="F:System.Windows.Documents.DocumentPage.Missing" /> if the page does not exist.</returns> public override DocumentPage GetPage(int pageNumber) { var realPageNumber = GetTranslatedPageNumber(pageNumber); // Needed if only certain pages are to be printed CurrentPage = realPageNumber + 1; var printPage = new ContainerVisual(); RenderElement(printPage, Watermark, PrintElementType.Watermark); RenderElement(printPage, Header, PrintElementType.Header); var page = _flowDocumentPaginator.GetPage(realPageNumber); if (DocumentPrintMargin.Top > 0 || DocumentPrintMargin.Left > 0) printPage.Transform = new TranslateTransform(DocumentPrintMargin.Left, DocumentPrintMargin.Top); printPage.Children.Add(page.Visual); RenderElement(printPage, Footer, PrintElementType.Footer); return new DocumentPage(printPage); }
public override DocumentPage GetPage(int pageNumber) { // Use default paginator to handle pagination Visual originalPage = paginator.GetPage(pageNumber).Visual; ContainerVisual visual = new ContainerVisual(); ContainerVisual pageVisual = new ContainerVisual() { Transform = new TranslateTransform(definition.ContentOrigin.X, definition.ContentOrigin.Y) }; pageVisual.Children.Add(originalPage); visual.Children.Add(pageVisual); // Create headers and footers if (definition.Header != null) { visual.Children.Add(CreateHeaderFooterVisual(definition.Header, definition.HeaderRect, pageNumber)); } if (definition.Footer != null) { visual.Children.Add(CreateHeaderFooterVisual(definition.Footer, definition.FooterRect, pageNumber)); } return new DocumentPage( visual, definition.PageSize, new Rect(new Point(), definition.PageSize), new Rect(definition.ContentOrigin, definition.ContentSize) ); }
public override DocumentPage GetPage(int pageNumber) { Visual originalPage = _paginator.GetPage(pageNumber).Visual; ContainerVisual visual = new ContainerVisual(); ContainerVisual pageVisual = new ContainerVisual() { Transform = new TranslateTransform(_reportDefinition.ContentOrigin.X, _reportDefinition.ContentOrigin.Y) }; pageVisual.Children.Add(originalPage); visual.Children.Add(pageVisual); if (_reportDefinition.Header != null) { visual.Children.Add(CreateHeaderFooterVisual(_reportDefinition.Header, _reportDefinition.HeaderRect, pageNumber)); } if (_reportDefinition.Footer != null) { visual.Children.Add(CreateHeaderFooterVisual(_reportDefinition.Footer, _reportDefinition.FooterRect, pageNumber)); } if (_reportDefinition.RepeatTableHeaders) { ContainerVisual table; if (PageStartWithTable(originalPage, out table) && _currentHeader != null) { Rect headerBounds = VisualTreeHelper.GetDescendantBounds(_currentHeader); Vector offset = VisualTreeHelper.GetOffset(_currentHeader); ContainerVisual tableHeaderVisual = new ContainerVisual(); tableHeaderVisual.Transform = new ScaleTransform(_reportDefinition.ContentOrigin.X, _reportDefinition.ContentOrigin.Y - headerBounds.Top); double yScale = (_reportDefinition.ContentSize.Height - headerBounds.Height) / _reportDefinition.ContentSize.Height; TransformGroup group = new TransformGroup(); group.Children.Add(new ScaleTransform(1.0, yScale)); group.Children.Add(new TranslateTransform( _reportDefinition.ContentOrigin.X, _reportDefinition.ContentOrigin.Y + headerBounds.Height )); pageVisual.Transform = group; ContainerVisual cp = VisualTreeHelper.GetParent(_currentHeader) as ContainerVisual; if (cp != null) { cp.Children.Remove(_currentHeader); } tableHeaderVisual.Children.Add(_currentHeader); visual.Children.Add(tableHeaderVisual); } ContainerVisual newTable, newHeader; if (PageEndsWithTable(originalPage, out newTable, out newHeader)) { if (newTable == table) { // Still the same table so don't change the repeating header _currentHeader = newHeader; } else { // We've found a new table. Repeat the header on the next page _currentHeader = newHeader; } } else { // There was no table at the end of the page _currentHeader = null; } } return new DocumentPage(visual, _reportDefinition.PageSize, new Rect(new Point(), _reportDefinition.PageSize), new Rect(_reportDefinition.ContentOrigin, _reportDefinition.ContentSize)); }
bool PageEndsWithTable(DependencyObject element, out ContainerVisual tableVisual, out ContainerVisual headerVisual) { tableVisual = null; headerVisual = null; if (element.GetType().Name == "RowVisual") { tableVisual = (ContainerVisual)VisualTreeHelper.GetParent(element); headerVisual = (ContainerVisual)VisualTreeHelper.GetChild(tableVisual, 0); return true; } int children = VisualTreeHelper.GetChildrenCount(element); if (element.GetType() == typeof(ContainerVisual)) { for (int i = children - 1; i >= 0; i--) { DependencyObject child = VisualTreeHelper.GetChild(element, i); if (PageEndsWithTable(child, out tableVisual, out headerVisual)) { return true; } } } else if (children > 0) { DependencyObject child = VisualTreeHelper.GetChild(element, children - 1); if (PageEndsWithTable(child, out tableVisual, out headerVisual)) { return true; } } return false; }
/// <summary> /// Formatoidaan sivu näyttämään järkevältä, lisäten joka sivulle sivunumero sekä teksti Kohde - Päivämäärä - Summa /// </summary> /// <param name="pageNumber">sivunumero, joka on menossa</param> /// <returns>dokumentin sivu</returns> public override DocumentPage GetPage(int pageNumber) { DocumentPage page = m_Paginator.GetPage(pageNumber); ContainerVisual newpage = new ContainerVisual() { Transform = new TranslateTransform(m_Margin.Width, m_Margin.Height) }; DrawingVisual title = new DrawingVisual(); using (DrawingContext ctx = title.RenderOpen()) { FormattedText text = new FormattedText("Kohde - Päivämäärä - Summa", System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 18, Brushes.Black); FormattedText text2 = new FormattedText("" + (pageNumber + 1), System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, m_Typeface, 18, Brushes.Black); ctx.DrawText(text, new Point(m_Margin.Width, -m_Margin.Height)); ctx.DrawText(text2, new Point(m_PageSize.Width - text2.Width - m_Margin.Width, -m_Margin.Height)); } DrawingVisual background = new DrawingVisual(); newpage.Children.Add(background); ContainerVisual smallerPage = new ContainerVisual(); smallerPage.Children.Add(page.Visual); newpage.Children.Add(smallerPage); newpage.Children.Add(title); return new DocumentPage(newpage); }
/// <summary> /// Renders the element to the provided page (container). /// </summary> /// <param name="container">The container.</param> /// <param name="visual">The visual.</param> /// <param name="alignment">The alignment.</param> private void RenderElement(ContainerVisual container, FrameworkElement visual, PrintElementType alignment) { if (visual == null) return; var drawingVisual = new DrawingVisual(); using (var dc = drawingVisual.RenderOpen()) { var visualX = 0d; var visualY = 0d; var visualHeight = visual.DesiredSize.Height; var visualWidth = visual.DesiredSize.Width; switch (alignment) { case PrintElementType.Header: visualY = OriginalPrintMargin.Top; visualX = OriginalPrintMargin.Left; break; case PrintElementType.Footer: visualY = TotalPrintableArea.Height - OriginalPrintMargin.Bottom - visual.DesiredSize.Height; visualX = OriginalPrintMargin.Left; break; case PrintElementType.Watermark: var totalWidth = TotalPrintableArea.Width - OriginalPrintMargin.Left - OriginalPrintMargin.Right; var totalHeight = TotalPrintableArea.Height - OriginalPrintMargin.Top - OriginalPrintMargin.Bottom; visualX = ((totalWidth - visualWidth)/2) + OriginalPrintMargin.Left; visualY = ((totalHeight - visualHeight)/2) + OriginalPrintMargin.Right; break; } if (visual.Margin.Top > 0.0001 || visual.Margin.Left > 0.0001 || visual.Margin.Right > 0.0001 || visual.Margin.Bottom > 0.0001) { visualX += visual.Margin.Left; visualY += visual.Margin.Top; visualHeight -= (visual.Margin.Top + visual.Margin.Bottom); visualWidth -= (visual.Margin.Left + visual.Margin.Right); } // We need to clone the visual, so we can change the same visual individually on each page if need be var xaml = XamlWriter.Save(visual); var stringReader = new StringReader(xaml); var xmlReader = XmlReader.Create(stringReader); var newVisual = (FrameworkElement) XamlReader.Load(xmlReader); newVisual.DataContext = visual.DataContext; newVisual.Resources = visual.Resources; CheckVisualForSpecialRuns(newVisual); var brush = new VisualBrush(newVisual) {Stretch = Stretch.None}; var renderRect = new Rect(visualX, visualY, visualWidth, visualHeight); if (DocumentPrintMargin.Top > 0 || DocumentPrintMargin.Left > 0) dc.PushTransform(new TranslateTransform(DocumentPrintMargin.Left * -1, DocumentPrintMargin.Top * -1)); dc.DrawRectangle(brush, new Pen(Brushes.Transparent, 0d), renderRect); if (DocumentPrintMargin.Top > 0 || DocumentPrintMargin.Left > 0) dc.Pop(); } container.Children.Add(drawingVisual); }
public override DocumentPage GetPage(int pageNumber) { // Use default paginator to handle pagination Visual originalPage = paginator.GetPage(pageNumber).Visual; ContainerVisual visual = new ContainerVisual(); ContainerVisual pageVisual = new ContainerVisual() { Transform = new TranslateTransform( definition.ContentOrigin.X, definition.ContentOrigin.Y ) }; pageVisual.Children.Add(originalPage); visual.Children.Add(pageVisual); // Create headers and footers if (definition.Header != null) { visual.Children.Add(CreateHeaderFooterVisual(definition.Header, definition.HeaderRect, pageNumber)); } if (definition.Footer != null) { visual.Children.Add(CreateHeaderFooterVisual(definition.Footer, definition.FooterRect, pageNumber)); } // Check for repeating table headers if (definition.RepeatTableHeaders) { // Find table header ContainerVisual table; if (PageStartsWithTable(originalPage, out table) && currentHeader != null) { // The page starts with a table and a table header was // found on the previous page. Presumably this table // was started on the previous page, so we'll repeat the // table header. Rect headerBounds = VisualTreeHelper.GetDescendantBounds(currentHeader); Vector offset = VisualTreeHelper.GetOffset(currentHeader); ContainerVisual tableHeaderVisual = new ContainerVisual(); // Translate the header to be at the top of the page // instead of its previous position tableHeaderVisual.Transform = new TranslateTransform( definition.ContentOrigin.X, definition.ContentOrigin.Y - headerBounds.Top ); // Since we've placed the repeated table header on top of the // content area, we'll need to scale down the rest of the content // to accomodate this. Since the table header is relatively small, // this probably is barely noticeable. double yScale = (definition.ContentSize.Height - headerBounds.Height) / definition.ContentSize.Height; TransformGroup group = new TransformGroup(); group.Children.Add(new ScaleTransform(1.0, yScale)); group.Children.Add(new TranslateTransform( definition.ContentOrigin.X, definition.ContentOrigin.Y + headerBounds.Height )); pageVisual.Transform = group; ContainerVisual cp = VisualTreeHelper.GetParent(currentHeader) as ContainerVisual; if (cp != null) { cp.Children.Remove(currentHeader); } tableHeaderVisual.Children.Add(currentHeader); visual.Children.Add(tableHeaderVisual); } // Check if there is a table on the bottom of the page. // If it's there, its header should be repeated ContainerVisual newTable, newHeader; if (PageEndsWithTable(originalPage, out newTable, out newHeader)) { if (newTable == table) { // Still the same table so don't change the repeating header } else { // We've found a new table. Repeat the header on the next page currentHeader = newHeader; } } else { // There was no table at the end of the page currentHeader = null; } } return new DocumentPage( visual, definition.PageSize, new Rect(new Point(), definition.PageSize), new Rect(definition.ContentOrigin, definition.ContentSize) ); }
// ----------------------------------------------------------------- // Arrange content of formatted line. // // vc - Visual collection of the parent. // lineOffset - Offset of the line. // ------------------------------------------------------------------ internal override void Arrange(VisualCollection vc, Vector lineOffset) { // Arrange inline objects int runDcp = _dcp; IList<TextSpan<TextRun>> runs = _line.GetTextRunSpans(); Debug.Assert(runs != null, "Cannot retrieve runs collection."); // Calculate offset shift due to trailing spaces double adjustedXOffset = lineOffset.X + CalculateXOffsetShift(); foreach (TextSpan<TextRun> textSpan in runs) { TextRun run = textSpan.Value; if (run is InlineObject) { InlineObject inlineObject = run as InlineObject; // Disconnect visual from its old parent, if necessary. Visual currentParent = VisualTreeHelper.GetParent(inlineObject.Element) as Visual; if (currentParent != null) { ContainerVisual parent = currentParent as ContainerVisual; Invariant.Assert(parent != null, "parent should always derives from ContainerVisual"); parent.Children.Remove(inlineObject.Element); } // Get position of inline object withing the text line. FlowDirection flowDirection; Rect rect = GetBoundsFromPosition(runDcp, inlineObject.Length, out flowDirection); Debug.Assert(DoubleUtil.GreaterThanOrClose(rect.Width, 0), "Negative inline object's width."); ContainerVisual proxyVisual = new ContainerVisual(); if (inlineObject.Element is FrameworkElement) { FlowDirection parentFlowDirection = _owner.FlowDirection; // Check parent's FlowDirection to determine if mirroring is needed DependencyObject parent = ((FrameworkElement)inlineObject.Element).Parent; if(parent != null) { parentFlowDirection = (FlowDirection)parent.GetValue(FrameworkElement.FlowDirectionProperty); } PtsHelper.UpdateMirroringTransform(_owner.FlowDirection, parentFlowDirection, proxyVisual, rect.Width); } vc.Add(proxyVisual); if (_owner.UseLayoutRounding) { // If using layout rounding, check whether rounding needs to compensate for high DPI proxyVisual.Offset = new Vector(UIElement.RoundLayoutValue(lineOffset.X + rect.Left, FrameworkElement.DpiScaleX), UIElement.RoundLayoutValue(lineOffset.Y + rect.Top, FrameworkElement.DpiScaleY)); } else { proxyVisual.Offset = new Vector(lineOffset.X + rect.Left, lineOffset.Y + rect.Top); } proxyVisual.Children.Add(inlineObject.Element); // Combine text line offset (relative to the Text control) with inline object // offset (relative to the line) and set transorm on the visual. Trailing spaces // shift is not added here because it is returned by GetBoundsFromPosition inlineObject.Element.Arrange(new Rect(inlineObject.Element.DesiredSize)); } // Do not use TextRun.Length, because it gives total length of the run. // So, if the run is broken between lines, it gives incorrect value. // Use length of the TextSpan instead, which gives the correct length here. runDcp += textSpan.Length; } }
/// <summary> /// Public Constructor /// </summary> internal Renderer() { // Initialize the data members. // We intentionally don't use lazy initialization for the core members to avoid // hidden bug situations when one thing has been created while another not. // If the user is looking for lazy initialization, she should do that on her // own and create Renderer only when there's a need for it. // Create visuals that'll be the containers for all other visuals // created by the Renderer. This visuals are created once and are // not supposed to be replaced nor destroyed while the Renderer is alive. _rootVisual = new ContainerVisual(); _highlightersRoot = new ContainerVisual(); _regularInkVisuals = new ContainerVisual(); _incrementalRenderingVisuals = new ContainerVisual(); // Highlighters go to the bottom, then regular ink, and regular // ink' incremental rendering in on top. VisualCollection rootChildren = _rootVisual.Children; rootChildren.Add(_highlightersRoot); rootChildren.Add(_regularInkVisuals); rootChildren.Add(_incrementalRenderingVisuals); // Set the default value of highcontrast to be false. _highContrast = false; // Create a stroke-visual dictionary _visuals = new Dictionary<Stroke, StrokeVisual>(); }
public override DocumentPage GetPage(int pageNumber) { DocumentPage page = m_Paginator.GetPage(pageNumber); ContainerVisual newpage = new ContainerVisual(); // // Header // DrawingVisual header = new DrawingVisual(); using (DrawingContext ctx = header.RenderOpen()) { DrawPath(ctx, m_Margins.Top - 20, m_Title, TextAlignment.Left); DrawText(ctx, m_Margins.Top - 20, String.Format("{0}", DateTime.Now), TextAlignment.Right); DrawLine(ctx, m_Margins.Top - 5, 0.5); } // // Footer // DrawingVisual footer = new DrawingVisual(); using (DrawingContext ctx = footer.RenderOpen()) { DrawText(ctx, m_PageSize.Height - m_Margins.Bottom + 5, "-" + (pageNumber + 1) + "-", TextAlignment.Center); DrawLine(ctx, m_PageSize.Height - m_Margins.Bottom + 5, 0.5); } ContainerVisual pageVisual = new ContainerVisual(); pageVisual.Children.Add(page.Visual); newpage.Children.Add(header); newpage.Children.Add(pageVisual); newpage.Children.Add(footer); return new DocumentPage(newpage, m_PageSize, Move(page.BleedBox), Move(page.ContentBox)); }
private Visual GetVisual(double offsetX, double offsetY) { ContainerVisual root = new ContainerVisual(); DrawingVisual visual = new DrawingVisual(); root.Children.Add(visual); visual.Offset = new Vector(offsetX, offsetY); DrawingContext dc = visual.RenderOpen(); dc.DrawDrawing(_page.GetDrawing()); dc.Close(); UIElementCollection vc = _page.Children; foreach (UIElement child in vc) { CloneVisualTree(visual, child); } return root; }
bool PageStartWithTable(DependencyObject element, out ContainerVisual tableVisual) { tableVisual = null; if (element.GetType().Name == "RowVisual") { tableVisual = (ContainerVisual)VisualTreeHelper.GetParent(element); return true; } int children = VisualTreeHelper.GetChildrenCount(element); if (children > 0) { DependencyObject child = VisualTreeHelper.GetChild(element, 0); if (PageStartWithTable(child, out tableVisual)) { return true; } } return false; }
private void CloneVisualTree(ContainerVisual parent, Visual old) { DrawingVisual visual = new DrawingVisual(); parent.Children.Add(visual); visual.Clip = VisualTreeHelper.GetClip(old); visual.Offset = VisualTreeHelper.GetOffset(old); visual.Transform = VisualTreeHelper.GetTransform(old); visual.Opacity = VisualTreeHelper.GetOpacity(old); visual.OpacityMask = VisualTreeHelper.GetOpacityMask(old); #pragma warning disable 0618 visual.BitmapEffectInput = VisualTreeHelper.GetBitmapEffectInput(old); visual.BitmapEffect = VisualTreeHelper.GetBitmapEffect(old); #pragma warning restore 0618 // snapping guidelines?? DrawingContext dc = visual.RenderOpen(); dc.DrawDrawing(old.GetDrawing()); dc.Close(); int count = VisualTreeHelper.GetChildrenCount(old); for(int i = 0; i < count; i++) { Visual child = old.InternalGetVisualChild(i); CloneVisualTree(visual, child); } }
// ------------------------------------------------------------------ // Get a visual representing the page's content. // ------------------------------------------------------------------ internal ContainerVisual GetPageVisual() { if (_visual == null) { _visual = new ContainerVisual(); } if (!IsEmpty) { UpdatePageVisuals(_calculatedSize); } else { _visual.Children.Clear(); } return _visual; }
//------------------------------------------------------------------- // Disconnect all embedded visuals (UIElements) to make sure that // they are not part of visual tree when page is destroyed. // This is necessary for building proper event route, because // BuildRoute prefers visual tree. //------------------------------------------------------------------- private void DestroyVisualLinks(ContainerVisual visual) { VisualCollection vc = visual.Children; if (vc != null) { for (int index = 0; index < vc.Count; index++) { if (vc[index] is UIElementIsland) { vc.RemoveAt(index); } else { Invariant.Assert(vc[index] is ContainerVisual, "The children should always derive from ContainerVisual"); DestroyVisualLinks((ContainerVisual)(vc[index])); } } } }