Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / LayoutDump.cs / 1305600 / LayoutDump.cs
//---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // File: LayoutDump.cs // // Description: Set of layout tree verification utilities. // //--------------------------------------------------------------------------- using System; using System.IO; using System.Xml; using System.Windows; using System.Globalization; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Windows.Media; using System.Windows.Documents; using System.Windows.Controls; using System.Windows.Controls.Primitives; using MS.Internal.Documents; using MS.Internal.PtsHost; namespace MS.Internal { ////// Set of layout tree verification utilities. /// internal static class LayoutDump { // ----------------------------------------------------------------- // // High Level Dump Methods // // ----------------------------------------------------------------- #region High Level Dump Methods ////// Dump layout and visual tree starting from specified root. /// /// Name of the root XML element. /// Root of the visual subtree. internal static string DumpLayoutAndVisualTreeToString(string tagName, Visual root) { StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); XmlTextWriter writer = new XmlTextWriter(stringWriter); writer.Formatting = Formatting.Indented; writer.Indentation = 2; DumpLayoutAndVisualTree(writer, tagName, root); // Close dump file writer.Flush(); writer.Close(); return stringWriter.ToString(); } ////// Dump layout and visual tree starting from specified root. /// /// Stream for dump output. /// Name of the root XML element. /// Root of the visual subtree. internal static void DumpLayoutAndVisualTree(XmlTextWriter writer, string tagName, Visual root) { // Write root element writer.WriteStartElement(tagName); // Dump layout tree including all visuals DumpVisual(writer, root, root); // Write end root writer.WriteEndElement(); writer.WriteRaw("\r\n"); // required for bbpack } ////// Dump layout tree starting from specified root. /// /// Name of the root XML element. /// Root of the layout subtree. /// File name to dump to. internal static void DumpLayoutTreeToFile(string tagName, UIElement root, string fileName) { string str = DumpLayoutTreeToString(tagName, root); StreamWriter streamWriter = new StreamWriter(fileName); streamWriter.Write(str); streamWriter.Flush(); streamWriter.Close(); } ////// Dump layout tree starting from specified root. /// /// Name of the root XML element. /// Root of the layout subtree. internal static string DumpLayoutTreeToString(string tagName, UIElement root) { StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); XmlTextWriter writer = new XmlTextWriter(stringWriter); writer.Formatting = Formatting.Indented; writer.Indentation = 2; DumpLayoutTree(writer, tagName, root); // Close dump file writer.Flush(); writer.Close(); return stringWriter.ToString(); } ////// Dump layout tree starting from specified root. /// /// Stream for dump output. /// Name of the root XML element. /// Root of the layout subtree. internal static void DumpLayoutTree(XmlTextWriter writer, string tagName, UIElement root) { // Write root element writer.WriteStartElement(tagName); // Dump layout tree DumpUIElement(writer, root, root, true); // Write end root writer.WriteEndElement(); writer.WriteRaw("\r\n"); // required for bbpack } #endregion High Level Dump Methods // ------------------------------------------------------------------ // // Custom Element Handling // // ----------------------------------------------------------------- #region Custom Element Handling ////// Add new mapping from UIElement type to dump methdod (DumpCustomUIElement). /// internal static void AddUIElementDumpHandler(Type type, DumpCustomUIElement dumper) { _elementToDumpHandler.Add(type, dumper); } ////// Add new mapping from DocumentPage type to dump methdod (DumpCustomDocumentPage). /// internal static void AddDocumentPageDumpHandler(Type type, DumpCustomDocumentPage dumper) { _documentPageToDumpHandler.Add(type, dumper); } ////// Dumper delegate for custom UIElements. /// internal delegate bool DumpCustomUIElement(XmlTextWriter writer, UIElement element, bool uiElementsOnly); ////// Dumper delegate for custom DocumentPages. /// internal delegate void DumpCustomDocumentPage(XmlTextWriter writer, DocumentPage page); ////// Mapping from UIElement type to dump methdod (DumpCustomUIElement). /// private static Hashtable _elementToDumpHandler = new Hashtable(); ////// Mapping from DocumentPage type to dump methdod (DumpCustomUIElement). /// private static Hashtable _documentPageToDumpHandler = new Hashtable(); #endregion Custom Element Handling // ------------------------------------------------------------------ // // Basic UIElement/Visual Dump // // ------------------------------------------------------------------ #region Basic UIElement/Visual Dump // ----------------------------------------------------------------- // Dump content of Visual. // ------------------------------------------------------------------ internal static void DumpVisual(XmlTextWriter writer, Visual visual, Visual parent) { if (visual is UIElement) { DumpUIElement(writer, (UIElement)visual, parent, false); } else { writer.WriteStartElement(visual.GetType().Name); // Dump visual bounds Rect bounds = visual.VisualContentBounds; if(!bounds.IsEmpty) { DumpRect(writer, "ContentRect", bounds); } // Dump clip geometry Geometry clip = VisualTreeHelper.GetClip(visual); if (clip != null) { DumpRect(writer, "Clip.Bounds", clip.Bounds); } // Dump transform relative to its parent GeneralTransform g = visual.TransformToAncestor(parent); Point point = new Point(0, 0); g.TryTransform(point, out point); if (point.X != 0 || point.Y != 0) { DumpPoint(writer, "Position", point); } // Dump visual children DumpVisualChildren(writer, "Children", visual); writer.WriteEndElement(); } } // ----------------------------------------------------------------- // Dump content of UIElement. // ----------------------------------------------------------------- private static void DumpUIElement(XmlTextWriter writer, UIElement element, Visual parent, bool uiElementsOnly) { writer.WriteStartElement(element.GetType().Name); // Dump layout information DumpSize(writer, "DesiredSize", element.DesiredSize); DumpSize(writer, "ComputedSize", element.RenderSize); Geometry clip = VisualTreeHelper.GetClip(element); if (clip != null) { DumpRect(writer, "Clip.Bounds", clip.Bounds); } // Dump transform relative to its parent GeneralTransform g = element.TransformToAncestor(parent); Point point = new Point(0, 0); g.TryTransform(point, out point); if (point.X != 0 || point.Y != 0) { DumpPoint(writer, "Position", point); } // Dump element specific information bool childrenHandled = false; Type t = element.GetType(); DumpCustomUIElement dumpElement = null; while(dumpElement==null && t!=null) { dumpElement = _elementToDumpHandler[t] as DumpCustomUIElement; t = t.BaseType; } if (dumpElement != null) { childrenHandled = dumpElement(writer, element, uiElementsOnly); } if (!childrenHandled) { if (uiElementsOnly) { DumpUIElementChildren(writer, "Children", element); } else { DumpVisualChildren(writer, "Children", element); } } writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump content of DocumentPage. // ------------------------------------------------------------------ internal static void DumpDocumentPage(XmlTextWriter writer, DocumentPage page, Visual parent) { writer.WriteStartElement("DocumentPage"); writer.WriteAttributeString("Type", page.GetType().FullName); if (page != DocumentPage.Missing) { DumpSize(writer, "Size", page.Size); // Dump transform relative to its parent GeneralTransform g = page.Visual.TransformToAncestor(parent); Point point = new Point(0, 0); g.TryTransform(point, out point); if (point.X != 0 || point.Y != 0) { DumpPoint(writer, "Position", point); } // Dump page specific information Type t = page.GetType(); DumpCustomDocumentPage dumpDocumentPage = null; while(dumpDocumentPage==null && t!=null) { dumpDocumentPage = _documentPageToDumpHandler[t] as DumpCustomDocumentPage; t = t.BaseType; } if (dumpDocumentPage != null) { dumpDocumentPage(writer, page); } } writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump visual children. // ------------------------------------------------------------------ private static void DumpVisualChildren(XmlTextWriter writer, string tagName, Visual visualParent) { int count = VisualTreeHelper.GetChildrenCount(visualParent); if (count>0) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Count", count.ToString(CultureInfo.InvariantCulture)); for(int i = 0; i < count; i++) { DumpVisual(writer, visualParent.InternalGetVisualChild(i), visualParent); } writer.WriteEndElement(); } } // ------------------------------------------------------------------ // Dump UIELement children. // ----------------------------------------------------------------- internal static void DumpUIElementChildren(XmlTextWriter writer, string tagName, Visual visualParent) { ListuiElements = new List (); GetUIElementsFromVisual(visualParent, uiElements); // For each found UIElement dump its layout info. if (uiElements.Count > 0) { // Dump UIElement children writer.WriteStartElement(tagName); writer.WriteAttributeString("Count", uiElements.Count.ToString(CultureInfo.InvariantCulture)); for (int index = 0; index < uiElements.Count; index++) { DumpUIElement(writer, uiElements[index], visualParent, true); } writer.WriteEndElement(); } } // ------------------------------------------------------------------ // Dump point. // ----------------------------------------------------------------- internal static void DumpPoint(XmlTextWriter writer, string tagName, Point point) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Left", point.X.ToString("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Top", point.Y.ToString("F", CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump size. // ----------------------------------------------------------------- internal static void DumpSize(XmlTextWriter writer, string tagName, Size size) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Width", size.Width.ToString ("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Height", size.Height.ToString("F", CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump rectangle. // ----------------------------------------------------------------- internal static void DumpRect(XmlTextWriter writer, string tagName, Rect rect) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Left", rect.Left.ToString ("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Top", rect.Top.ToString ("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Width", rect.Width.ToString ("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Height", rect.Height.ToString("F", CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Walk visual children and find children UIElements. Performs deep // walk of visual tree, but stops when runs into a UIElement. // All found UIElements are appended to uiElements collection. // // visual - Visual element from which UIElements are extracted. // uiElements - collection of UIElements. // ------------------------------------------------------------------ internal static void GetUIElementsFromVisual(Visual visual, List uiElements) { int count = VisualTreeHelper.GetChildrenCount(visual); for(int i = 0; i < count; i++) { Visual child = visual.InternalGetVisualChild(i); if (child is UIElement) { uiElements.Add((UIElement)(child)); } else { GetUIElementsFromVisual(child, uiElements); } } } #endregion Basic UIElement/Visual Dump // ----------------------------------------------------------------- // // Custom Dump Handlers // // ------------------------------------------------------------------ #region Custom Dump Handlers // ----------------------------------------------------------------- // Constructor. // ----------------------------------------------------------------- static LayoutDump() { AddUIElementDumpHandler(typeof(System.Windows.Controls.TextBlock), new DumpCustomUIElement(DumpText)); AddUIElementDumpHandler(typeof(FlowDocumentScrollViewer), new DumpCustomUIElement(DumpFlowDocumentScrollViewer)); AddUIElementDumpHandler(typeof(FlowDocumentView), new DumpCustomUIElement(DumpFlowDocumentView)); AddUIElementDumpHandler(typeof(DocumentPageView), new DumpCustomUIElement(DumpDocumentPageView)); AddDocumentPageDumpHandler(typeof(FlowDocumentPage), new DumpCustomDocumentPage(DumpFlowDocumentPage)); } // ----------------------------------------------------------------- // Dump DocumentPageView specific data. // ------------------------------------------------------------------ private static bool DumpDocumentPageView(XmlTextWriter writer, UIElement element, bool uiElementsOnly) { DocumentPageView dpv = element as DocumentPageView; Debug.Assert(dpv != null, "Dump function has to match element type."); // Dump text range if (dpv.DocumentPage != null) { DumpDocumentPage(writer, dpv.DocumentPage, element); } return false; } // ----------------------------------------------------------------- // Dump Text specific data. // ------------------------------------------------------------------ private static bool DumpText(XmlTextWriter writer, UIElement element, bool uiElementsOnly) { System.Windows.Controls.TextBlock text = element as System.Windows.Controls.TextBlock; Debug.Assert(text != null, "Dump function has to match element type."); // Dump text range if (text.HasComplexContent) { DumpTextRange(writer, text.ContentStart, text.ContentEnd); } else { DumpTextRange(writer, text.Text); } // Dump baseline info writer.WriteStartElement("Metrics"); writer.WriteAttributeString("BaselineOffset", ((double)text.GetValue(TextBlock.BaselineOffsetProperty)).ToString("F", CultureInfo.InvariantCulture)); writer.WriteEndElement(); // Dump line array if (text.IsLayoutDataValid) { ReadOnlyCollection lines = text.GetLineResults(); DumpLineResults(writer, lines, element); } return false; } // ------------------------------------------------------------------ // Dump FlowDocumentScrollViewer specific data. // ----------------------------------------------------------------- private static bool DumpFlowDocumentScrollViewer(XmlTextWriter writer, UIElement element, bool uiElementsOnly) { FlowDocumentScrollViewer fdsv = element as FlowDocumentScrollViewer; Debug.Assert(fdsv != null, "Dump function has to match element type."); bool childrenHandled = false; if (fdsv.HorizontalScrollBarVisibility == ScrollBarVisibility.Hidden && fdsv.VerticalScrollBarVisibility == ScrollBarVisibility.Hidden) { FlowDocumentView fdv = null; if (fdsv.ScrollViewer != null) { fdv = fdsv.ScrollViewer.Content as FlowDocumentView; if (fdv != null) { DumpUIElement(writer, fdv, fdsv, uiElementsOnly); childrenHandled = true; } } } return childrenHandled; } // ------------------------------------------------------------------ // Dump FlowDocumentView specific data. // ----------------------------------------------------------------- private static bool DumpFlowDocumentView(XmlTextWriter writer, UIElement element, bool uiElementsOnly) { FlowDocumentView fdView = element as FlowDocumentView; Debug.Assert(fdView != null, "Dump function has to match element type."); // Dump scrolling information IScrollInfo isi = (IScrollInfo)fdView; if (isi.ScrollOwner != null) { Size extent = new Size(isi.ExtentWidth, isi.ExtentHeight); if (DoubleUtil.AreClose(extent, element.DesiredSize)) { DumpSize(writer, "Extent", extent); } Point offset = new Point(isi.HorizontalOffset, isi.VerticalOffset); if (!DoubleUtil.IsZero(offset.X) || !DoubleUtil.IsZero(offset.Y)) { DumpPoint(writer, "Offset", offset); } } FlowDocumentPage documentPage = fdView.Document.BottomlessFormatter.DocumentPage; // Dump transform relative to its parent GeneralTransform gt = documentPage.Visual.TransformToAncestor(fdView); Point point = new Point(0, 0); gt.TryTransform(point, out point); if (!DoubleUtil.IsZero(point.X) && !DoubleUtil.IsZero(point.Y)) { DumpPoint(writer, "PagePosition", point); } DumpFlowDocumentPage(writer, documentPage); return false; } // ----------------------------------------------------------------- // Dump FlowDocumentPage specific data. // ----------------------------------------------------------------- private static void DumpFlowDocumentPage(XmlTextWriter writer, DocumentPage page) { FlowDocumentPage flowDocumentPage = page as FlowDocumentPage; Debug.Assert(flowDocumentPage != null, "Dump function has to match page type."); // Dump private info. writer.WriteStartElement("FormattedLines"); writer.WriteAttributeString("Count", flowDocumentPage.FormattedLinesCount.ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); // Dump columns collection TextDocumentView tv = (TextDocumentView)((IServiceProvider)flowDocumentPage).GetService(typeof(ITextView)); if (tv.IsValid) { DumpColumnResults(writer, tv.Columns, page.Visual); } } // ------------------------------------------------------------------ // Dump TextRange. // ----------------------------------------------------------------- private static void DumpTextRange(XmlTextWriter writer, string content) { int cpStart = 0; int cpEnd = content.Length; writer.WriteStartElement("TextRange"); writer.WriteAttributeString("Start", cpStart.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("Length", (cpEnd - cpStart).ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump TextRange. // ------------------------------------------------------------------ private static void DumpTextRange(XmlTextWriter writer, ITextPointer start, ITextPointer end) { int cpStart = start.TextContainer.Start.GetOffsetToPosition(start); int cpEnd = end.TextContainer.Start.GetOffsetToPosition(end); writer.WriteStartElement("TextRange"); writer.WriteAttributeString("Start", cpStart.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("Length", (cpEnd - cpStart).ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump line range. // ------------------------------------------------------------------ private static void DumpLineRange(XmlTextWriter writer, int cpStart, int cpEnd, int cpContentEnd, int cpEllipses) { writer.WriteStartElement("TextRange"); writer.WriteAttributeString("Start", cpStart.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("Length", (cpEnd - cpStart).ToString(CultureInfo.InvariantCulture)); if (cpEnd != cpContentEnd) { writer.WriteAttributeString("HiddenLength", (cpEnd - cpContentEnd).ToString(CultureInfo.InvariantCulture)); } if (cpEnd != cpEllipses) { writer.WriteAttributeString("EllipsesLength", (cpEnd - cpEllipses).ToString(CultureInfo.InvariantCulture)); } writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump line array. // ----------------------------------------------------------------- private static void DumpLineResults(XmlTextWriter writer, ReadOnlyCollection lines, Visual visualParent) { if (lines != null) { // Dump line array writer.WriteStartElement("Lines"); writer.WriteAttributeString("Count", lines.Count.ToString(CultureInfo.InvariantCulture)); for (int index = 0; index < lines.Count; index++) { writer.WriteStartElement("Line"); // Dump line info LineResult line = lines[index]; DumpRect(writer, "LayoutBox", line.LayoutBox); DumpLineRange(writer, line.StartPositionCP, line.EndPositionCP, line.GetContentEndPositionCP(), line.GetEllipsesPositionCP()); /* // Dump inline objects ReadOnlyCollection inlineObjects = line.InlineObjects; if (inlineObjects != null) { // All inline UIElements are dumped as Children collection of UIElement // that invokes this dump method. Hence, do not dump UIElements here. writer.WriteStartElement("InlineObjects"); writer.WriteAttributeString("Count", inlineObjects.Count.ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } */ writer.WriteEndElement(); } writer.WriteEndElement(); } } #endregion Custom Dump Handlers // ----------------------------------------------------------------- // Dump paragraphs collection. // ------------------------------------------------------------------ private static void DumpParagraphResults(XmlTextWriter writer, string tagName, ReadOnlyCollection paragraphs, Visual visualParent) { if (paragraphs != null) { // Dump paragraphs array writer.WriteStartElement(tagName); writer.WriteAttributeString("Count", paragraphs.Count.ToString(CultureInfo.InvariantCulture)); for (int index = 0; index < paragraphs.Count; index++) { ParagraphResult paragraph = paragraphs[index]; if (paragraph is TextParagraphResult) { DumpTextParagraphResult(writer, (TextParagraphResult)paragraph, visualParent); } else if (paragraph is ContainerParagraphResult) { DumpContainerParagraphResult(writer, (ContainerParagraphResult)paragraph, visualParent); } else if (paragraph is TableParagraphResult) { DumpTableParagraphResult(writer, (TableParagraphResult)paragraph, visualParent); } else if (paragraph is FloaterParagraphResult) { DumpFloaterParagraphResult(writer, (FloaterParagraphResult)paragraph, visualParent); } else if (paragraph is UIElementParagraphResult) { DumpUIElementParagraphResult(writer, (UIElementParagraphResult)paragraph, visualParent); } else if (paragraph is FigureParagraphResult) { DumpFigureParagraphResult(writer, (FigureParagraphResult)paragraph, visualParent); } else if (paragraph is SubpageParagraphResult) { DumpSubpageParagraphResult(writer, (SubpageParagraphResult)paragraph, visualParent); } } writer.WriteEndElement(); } } // ----------------------------------------------------------------- // Dump text paragraph result. // ------------------------------------------------------------------ private static void DumpTextParagraphResult(XmlTextWriter writer, TextParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("TextParagraph"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpTextRange(writer, paragraph.StartPosition, paragraph.EndPosition); DumpLineResults(writer, paragraph.Lines, visual); DumpParagraphResults(writer, "Floaters", paragraph.Floaters, visual); DumpParagraphResults(writer, "Figures", paragraph.Figures, visual); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump container paragraph result. // ----------------------------------------------------------------- private static void DumpContainerParagraphResult(XmlTextWriter writer, ContainerParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("ContainerParagraph"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpParagraphResults(writer, "Paragraphs", paragraph.Paragraphs, visual); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump floater paragraph result. // ----------------------------------------------------------------- private static void DumpFloaterParagraphResult(XmlTextWriter writer, FloaterParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("Floater"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpColumnResults(writer, paragraph.Columns, visual); writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump UIElement paragraph result. // ----------------------------------------------------------------- private static void DumpUIElementParagraphResult(XmlTextWriter writer, UIElementParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("BlockUIContainer"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump figure paragraph result. // ----------------------------------------------------------------- private static void DumpFigureParagraphResult(XmlTextWriter writer, FigureParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("Figure"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpColumnResults(writer, paragraph.Columns, visual); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump table paragraph result. // ------------------------------------------------------------------ private static void DumpTableParagraphResult(XmlTextWriter writer, TableParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("TableParagraph"); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); ReadOnlyCollection rowParagraphs = paragraph.Paragraphs; int count1 = VisualTreeHelper.GetChildrenCount(visual); for(int i = 0; i < count1; i++) { Visual rowVisual = visual.InternalGetVisualChild(i); int count2 = VisualTreeHelper.GetChildrenCount(rowVisual); ReadOnlyCollection cellParagraphs = ((RowParagraphResult)rowParagraphs[i]).CellParagraphs; for(int j = 0; j < count2; j++) { Visual cellVisual = rowVisual.InternalGetVisualChild(j); DumpTableCell(writer, cellParagraphs[j], cellVisual, visual); } } writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump subpage paragraph result. // ------------------------------------------------------------------ private static void DumpSubpageParagraphResult(XmlTextWriter writer, SubpageParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("SubpageParagraph"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpColumnResults(writer, paragraph.Columns, visual); writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump column results. // ----------------------------------------------------------------- private static void DumpColumnResults(XmlTextWriter writer, ReadOnlyCollection columns, Visual visualParent) { if (columns != null) { writer.WriteStartElement("Columns"); writer.WriteAttributeString("Count", columns.Count.ToString(CultureInfo.InvariantCulture)); for (int index = 0; index < columns.Count; index++) { writer.WriteStartElement("Column"); // Dump column info ColumnResult column = columns[index]; DumpRect(writer, "LayoutBox", column.LayoutBox); DumpTextRange(writer, column.StartPosition, column.EndPosition); DumpParagraphResults(writer, "Paragraphs", column.Paragraphs, visualParent); writer.WriteEndElement(); } writer.WriteEndElement(); } } // ----------------------------------------------------------------- // Dump paragraph offset. // ------------------------------------------------------------------ private static Visual DumpParagraphOffset(XmlTextWriter writer, ParagraphResult paragraph, Visual visualParent) { Type paragraphResultType = paragraph.GetType(); System.Reflection.FieldInfo field = paragraphResultType.GetField("_paraClient", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); object paraClient = field.GetValue(paragraph); Type paraClientType = paraClient.GetType(); System.Reflection.PropertyInfo prop = paraClientType.GetProperty("Visual", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); Visual visual = (Visual)prop.GetValue(paraClient, null); // Dump transform relative to its parent if(visualParent.IsAncestorOf(visual)) { GeneralTransform g = visual.TransformToAncestor(visualParent); Point point = new Point(0.0f, 0.0f); g.TryTransform(point, out point); if (point.X != 0 || point.Y != 0) { DumpPoint(writer, "Origin", point); } } return visual; } // ----------------------------------------------------------------- // Dump Table specific data: ColumnCount. // ------------------------------------------------------------------ private static void DumpTableCalculatedMetrics(XmlTextWriter writer, object element) { Type type = typeof(Table); System.Reflection.PropertyInfo prop = type.GetProperty("ColumnCount"); if (prop != null) { int count = (int)prop.GetValue(element, null); writer.WriteStartElement("ColumnCount"); writer.WriteAttributeString("Count", count.ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } } // ------------------------------------------------------------------ // Dump Cell specific data. // ----------------------------------------------------------------- private static void DumpTableCell(XmlTextWriter writer, ParagraphResult paragraph, Visual cellVisual, Visual tableVisual) { Type paragraphResultType = paragraph.GetType(); System.Reflection.FieldInfo fieldOfParaClient = paragraphResultType.GetField("_paraClient", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); if (fieldOfParaClient == null) { return; } CellParaClient cellParaClient = (CellParaClient) fieldOfParaClient.GetValue(paragraph); CellParagraph cellParagraph = cellParaClient.CellParagraph; TableCell cell = cellParagraph.Cell; writer.WriteStartElement("Cell"); Type typeOfCell = cell.GetType(); System.Reflection.PropertyInfo propOfColumnIndex = typeOfCell.GetProperty("ColumnIndex", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.DeclaredOnly); if (propOfColumnIndex != null) { int columnIndex = (int)propOfColumnIndex.GetValue(cell, null); writer.WriteAttributeString("ColumnIndex", columnIndex.ToString(CultureInfo.InvariantCulture)); } System.Reflection.PropertyInfo propOfRowIndex = typeOfCell.GetProperty("RowIndex", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.DeclaredOnly); if (propOfRowIndex != null) { int rowIndex = (int)propOfRowIndex.GetValue(cell, null); writer.WriteAttributeString("RowIndex", rowIndex.ToString(CultureInfo.InvariantCulture)); } writer.WriteAttributeString("ColumnSpan", cell.ColumnSpan.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("RowSpan", cell.RowSpan.ToString(CultureInfo.InvariantCulture)); Rect rect = cellParaClient.Rect.FromTextDpi(); DumpRect(writer, "LayoutBox", rect); bool hasTextContent; DumpParagraphResults(writer, "Paragraphs", cellParaClient.GetColumnResults(out hasTextContent)[0].Paragraphs, cellParaClient.Visual); writer.WriteEndElement(); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // Copyright (C) Microsoft Corporation. All rights reserved. // // File: LayoutDump.cs // // Description: Set of layout tree verification utilities. // //--------------------------------------------------------------------------- using System; using System.IO; using System.Xml; using System.Windows; using System.Globalization; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Windows.Media; using System.Windows.Documents; using System.Windows.Controls; using System.Windows.Controls.Primitives; using MS.Internal.Documents; using MS.Internal.PtsHost; namespace MS.Internal { /// /// Set of layout tree verification utilities. /// internal static class LayoutDump { // ----------------------------------------------------------------- // // High Level Dump Methods // // ----------------------------------------------------------------- #region High Level Dump Methods ////// Dump layout and visual tree starting from specified root. /// /// Name of the root XML element. /// Root of the visual subtree. internal static string DumpLayoutAndVisualTreeToString(string tagName, Visual root) { StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); XmlTextWriter writer = new XmlTextWriter(stringWriter); writer.Formatting = Formatting.Indented; writer.Indentation = 2; DumpLayoutAndVisualTree(writer, tagName, root); // Close dump file writer.Flush(); writer.Close(); return stringWriter.ToString(); } ////// Dump layout and visual tree starting from specified root. /// /// Stream for dump output. /// Name of the root XML element. /// Root of the visual subtree. internal static void DumpLayoutAndVisualTree(XmlTextWriter writer, string tagName, Visual root) { // Write root element writer.WriteStartElement(tagName); // Dump layout tree including all visuals DumpVisual(writer, root, root); // Write end root writer.WriteEndElement(); writer.WriteRaw("\r\n"); // required for bbpack } ////// Dump layout tree starting from specified root. /// /// Name of the root XML element. /// Root of the layout subtree. /// File name to dump to. internal static void DumpLayoutTreeToFile(string tagName, UIElement root, string fileName) { string str = DumpLayoutTreeToString(tagName, root); StreamWriter streamWriter = new StreamWriter(fileName); streamWriter.Write(str); streamWriter.Flush(); streamWriter.Close(); } ////// Dump layout tree starting from specified root. /// /// Name of the root XML element. /// Root of the layout subtree. internal static string DumpLayoutTreeToString(string tagName, UIElement root) { StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); XmlTextWriter writer = new XmlTextWriter(stringWriter); writer.Formatting = Formatting.Indented; writer.Indentation = 2; DumpLayoutTree(writer, tagName, root); // Close dump file writer.Flush(); writer.Close(); return stringWriter.ToString(); } ////// Dump layout tree starting from specified root. /// /// Stream for dump output. /// Name of the root XML element. /// Root of the layout subtree. internal static void DumpLayoutTree(XmlTextWriter writer, string tagName, UIElement root) { // Write root element writer.WriteStartElement(tagName); // Dump layout tree DumpUIElement(writer, root, root, true); // Write end root writer.WriteEndElement(); writer.WriteRaw("\r\n"); // required for bbpack } #endregion High Level Dump Methods // ------------------------------------------------------------------ // // Custom Element Handling // // ----------------------------------------------------------------- #region Custom Element Handling ////// Add new mapping from UIElement type to dump methdod (DumpCustomUIElement). /// internal static void AddUIElementDumpHandler(Type type, DumpCustomUIElement dumper) { _elementToDumpHandler.Add(type, dumper); } ////// Add new mapping from DocumentPage type to dump methdod (DumpCustomDocumentPage). /// internal static void AddDocumentPageDumpHandler(Type type, DumpCustomDocumentPage dumper) { _documentPageToDumpHandler.Add(type, dumper); } ////// Dumper delegate for custom UIElements. /// internal delegate bool DumpCustomUIElement(XmlTextWriter writer, UIElement element, bool uiElementsOnly); ////// Dumper delegate for custom DocumentPages. /// internal delegate void DumpCustomDocumentPage(XmlTextWriter writer, DocumentPage page); ////// Mapping from UIElement type to dump methdod (DumpCustomUIElement). /// private static Hashtable _elementToDumpHandler = new Hashtable(); ////// Mapping from DocumentPage type to dump methdod (DumpCustomUIElement). /// private static Hashtable _documentPageToDumpHandler = new Hashtable(); #endregion Custom Element Handling // ------------------------------------------------------------------ // // Basic UIElement/Visual Dump // // ------------------------------------------------------------------ #region Basic UIElement/Visual Dump // ----------------------------------------------------------------- // Dump content of Visual. // ------------------------------------------------------------------ internal static void DumpVisual(XmlTextWriter writer, Visual visual, Visual parent) { if (visual is UIElement) { DumpUIElement(writer, (UIElement)visual, parent, false); } else { writer.WriteStartElement(visual.GetType().Name); // Dump visual bounds Rect bounds = visual.VisualContentBounds; if(!bounds.IsEmpty) { DumpRect(writer, "ContentRect", bounds); } // Dump clip geometry Geometry clip = VisualTreeHelper.GetClip(visual); if (clip != null) { DumpRect(writer, "Clip.Bounds", clip.Bounds); } // Dump transform relative to its parent GeneralTransform g = visual.TransformToAncestor(parent); Point point = new Point(0, 0); g.TryTransform(point, out point); if (point.X != 0 || point.Y != 0) { DumpPoint(writer, "Position", point); } // Dump visual children DumpVisualChildren(writer, "Children", visual); writer.WriteEndElement(); } } // ----------------------------------------------------------------- // Dump content of UIElement. // ----------------------------------------------------------------- private static void DumpUIElement(XmlTextWriter writer, UIElement element, Visual parent, bool uiElementsOnly) { writer.WriteStartElement(element.GetType().Name); // Dump layout information DumpSize(writer, "DesiredSize", element.DesiredSize); DumpSize(writer, "ComputedSize", element.RenderSize); Geometry clip = VisualTreeHelper.GetClip(element); if (clip != null) { DumpRect(writer, "Clip.Bounds", clip.Bounds); } // Dump transform relative to its parent GeneralTransform g = element.TransformToAncestor(parent); Point point = new Point(0, 0); g.TryTransform(point, out point); if (point.X != 0 || point.Y != 0) { DumpPoint(writer, "Position", point); } // Dump element specific information bool childrenHandled = false; Type t = element.GetType(); DumpCustomUIElement dumpElement = null; while(dumpElement==null && t!=null) { dumpElement = _elementToDumpHandler[t] as DumpCustomUIElement; t = t.BaseType; } if (dumpElement != null) { childrenHandled = dumpElement(writer, element, uiElementsOnly); } if (!childrenHandled) { if (uiElementsOnly) { DumpUIElementChildren(writer, "Children", element); } else { DumpVisualChildren(writer, "Children", element); } } writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump content of DocumentPage. // ------------------------------------------------------------------ internal static void DumpDocumentPage(XmlTextWriter writer, DocumentPage page, Visual parent) { writer.WriteStartElement("DocumentPage"); writer.WriteAttributeString("Type", page.GetType().FullName); if (page != DocumentPage.Missing) { DumpSize(writer, "Size", page.Size); // Dump transform relative to its parent GeneralTransform g = page.Visual.TransformToAncestor(parent); Point point = new Point(0, 0); g.TryTransform(point, out point); if (point.X != 0 || point.Y != 0) { DumpPoint(writer, "Position", point); } // Dump page specific information Type t = page.GetType(); DumpCustomDocumentPage dumpDocumentPage = null; while(dumpDocumentPage==null && t!=null) { dumpDocumentPage = _documentPageToDumpHandler[t] as DumpCustomDocumentPage; t = t.BaseType; } if (dumpDocumentPage != null) { dumpDocumentPage(writer, page); } } writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump visual children. // ------------------------------------------------------------------ private static void DumpVisualChildren(XmlTextWriter writer, string tagName, Visual visualParent) { int count = VisualTreeHelper.GetChildrenCount(visualParent); if (count>0) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Count", count.ToString(CultureInfo.InvariantCulture)); for(int i = 0; i < count; i++) { DumpVisual(writer, visualParent.InternalGetVisualChild(i), visualParent); } writer.WriteEndElement(); } } // ------------------------------------------------------------------ // Dump UIELement children. // ----------------------------------------------------------------- internal static void DumpUIElementChildren(XmlTextWriter writer, string tagName, Visual visualParent) { ListuiElements = new List (); GetUIElementsFromVisual(visualParent, uiElements); // For each found UIElement dump its layout info. if (uiElements.Count > 0) { // Dump UIElement children writer.WriteStartElement(tagName); writer.WriteAttributeString("Count", uiElements.Count.ToString(CultureInfo.InvariantCulture)); for (int index = 0; index < uiElements.Count; index++) { DumpUIElement(writer, uiElements[index], visualParent, true); } writer.WriteEndElement(); } } // ------------------------------------------------------------------ // Dump point. // ----------------------------------------------------------------- internal static void DumpPoint(XmlTextWriter writer, string tagName, Point point) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Left", point.X.ToString("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Top", point.Y.ToString("F", CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump size. // ----------------------------------------------------------------- internal static void DumpSize(XmlTextWriter writer, string tagName, Size size) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Width", size.Width.ToString ("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Height", size.Height.ToString("F", CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump rectangle. // ----------------------------------------------------------------- internal static void DumpRect(XmlTextWriter writer, string tagName, Rect rect) { writer.WriteStartElement(tagName); writer.WriteAttributeString("Left", rect.Left.ToString ("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Top", rect.Top.ToString ("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Width", rect.Width.ToString ("F", CultureInfo.InvariantCulture)); writer.WriteAttributeString("Height", rect.Height.ToString("F", CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Walk visual children and find children UIElements. Performs deep // walk of visual tree, but stops when runs into a UIElement. // All found UIElements are appended to uiElements collection. // // visual - Visual element from which UIElements are extracted. // uiElements - collection of UIElements. // ------------------------------------------------------------------ internal static void GetUIElementsFromVisual(Visual visual, List uiElements) { int count = VisualTreeHelper.GetChildrenCount(visual); for(int i = 0; i < count; i++) { Visual child = visual.InternalGetVisualChild(i); if (child is UIElement) { uiElements.Add((UIElement)(child)); } else { GetUIElementsFromVisual(child, uiElements); } } } #endregion Basic UIElement/Visual Dump // ----------------------------------------------------------------- // // Custom Dump Handlers // // ------------------------------------------------------------------ #region Custom Dump Handlers // ----------------------------------------------------------------- // Constructor. // ----------------------------------------------------------------- static LayoutDump() { AddUIElementDumpHandler(typeof(System.Windows.Controls.TextBlock), new DumpCustomUIElement(DumpText)); AddUIElementDumpHandler(typeof(FlowDocumentScrollViewer), new DumpCustomUIElement(DumpFlowDocumentScrollViewer)); AddUIElementDumpHandler(typeof(FlowDocumentView), new DumpCustomUIElement(DumpFlowDocumentView)); AddUIElementDumpHandler(typeof(DocumentPageView), new DumpCustomUIElement(DumpDocumentPageView)); AddDocumentPageDumpHandler(typeof(FlowDocumentPage), new DumpCustomDocumentPage(DumpFlowDocumentPage)); } // ----------------------------------------------------------------- // Dump DocumentPageView specific data. // ------------------------------------------------------------------ private static bool DumpDocumentPageView(XmlTextWriter writer, UIElement element, bool uiElementsOnly) { DocumentPageView dpv = element as DocumentPageView; Debug.Assert(dpv != null, "Dump function has to match element type."); // Dump text range if (dpv.DocumentPage != null) { DumpDocumentPage(writer, dpv.DocumentPage, element); } return false; } // ----------------------------------------------------------------- // Dump Text specific data. // ------------------------------------------------------------------ private static bool DumpText(XmlTextWriter writer, UIElement element, bool uiElementsOnly) { System.Windows.Controls.TextBlock text = element as System.Windows.Controls.TextBlock; Debug.Assert(text != null, "Dump function has to match element type."); // Dump text range if (text.HasComplexContent) { DumpTextRange(writer, text.ContentStart, text.ContentEnd); } else { DumpTextRange(writer, text.Text); } // Dump baseline info writer.WriteStartElement("Metrics"); writer.WriteAttributeString("BaselineOffset", ((double)text.GetValue(TextBlock.BaselineOffsetProperty)).ToString("F", CultureInfo.InvariantCulture)); writer.WriteEndElement(); // Dump line array if (text.IsLayoutDataValid) { ReadOnlyCollection lines = text.GetLineResults(); DumpLineResults(writer, lines, element); } return false; } // ------------------------------------------------------------------ // Dump FlowDocumentScrollViewer specific data. // ----------------------------------------------------------------- private static bool DumpFlowDocumentScrollViewer(XmlTextWriter writer, UIElement element, bool uiElementsOnly) { FlowDocumentScrollViewer fdsv = element as FlowDocumentScrollViewer; Debug.Assert(fdsv != null, "Dump function has to match element type."); bool childrenHandled = false; if (fdsv.HorizontalScrollBarVisibility == ScrollBarVisibility.Hidden && fdsv.VerticalScrollBarVisibility == ScrollBarVisibility.Hidden) { FlowDocumentView fdv = null; if (fdsv.ScrollViewer != null) { fdv = fdsv.ScrollViewer.Content as FlowDocumentView; if (fdv != null) { DumpUIElement(writer, fdv, fdsv, uiElementsOnly); childrenHandled = true; } } } return childrenHandled; } // ------------------------------------------------------------------ // Dump FlowDocumentView specific data. // ----------------------------------------------------------------- private static bool DumpFlowDocumentView(XmlTextWriter writer, UIElement element, bool uiElementsOnly) { FlowDocumentView fdView = element as FlowDocumentView; Debug.Assert(fdView != null, "Dump function has to match element type."); // Dump scrolling information IScrollInfo isi = (IScrollInfo)fdView; if (isi.ScrollOwner != null) { Size extent = new Size(isi.ExtentWidth, isi.ExtentHeight); if (DoubleUtil.AreClose(extent, element.DesiredSize)) { DumpSize(writer, "Extent", extent); } Point offset = new Point(isi.HorizontalOffset, isi.VerticalOffset); if (!DoubleUtil.IsZero(offset.X) || !DoubleUtil.IsZero(offset.Y)) { DumpPoint(writer, "Offset", offset); } } FlowDocumentPage documentPage = fdView.Document.BottomlessFormatter.DocumentPage; // Dump transform relative to its parent GeneralTransform gt = documentPage.Visual.TransformToAncestor(fdView); Point point = new Point(0, 0); gt.TryTransform(point, out point); if (!DoubleUtil.IsZero(point.X) && !DoubleUtil.IsZero(point.Y)) { DumpPoint(writer, "PagePosition", point); } DumpFlowDocumentPage(writer, documentPage); return false; } // ----------------------------------------------------------------- // Dump FlowDocumentPage specific data. // ----------------------------------------------------------------- private static void DumpFlowDocumentPage(XmlTextWriter writer, DocumentPage page) { FlowDocumentPage flowDocumentPage = page as FlowDocumentPage; Debug.Assert(flowDocumentPage != null, "Dump function has to match page type."); // Dump private info. writer.WriteStartElement("FormattedLines"); writer.WriteAttributeString("Count", flowDocumentPage.FormattedLinesCount.ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); // Dump columns collection TextDocumentView tv = (TextDocumentView)((IServiceProvider)flowDocumentPage).GetService(typeof(ITextView)); if (tv.IsValid) { DumpColumnResults(writer, tv.Columns, page.Visual); } } // ------------------------------------------------------------------ // Dump TextRange. // ----------------------------------------------------------------- private static void DumpTextRange(XmlTextWriter writer, string content) { int cpStart = 0; int cpEnd = content.Length; writer.WriteStartElement("TextRange"); writer.WriteAttributeString("Start", cpStart.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("Length", (cpEnd - cpStart).ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump TextRange. // ------------------------------------------------------------------ private static void DumpTextRange(XmlTextWriter writer, ITextPointer start, ITextPointer end) { int cpStart = start.TextContainer.Start.GetOffsetToPosition(start); int cpEnd = end.TextContainer.Start.GetOffsetToPosition(end); writer.WriteStartElement("TextRange"); writer.WriteAttributeString("Start", cpStart.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("Length", (cpEnd - cpStart).ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump line range. // ------------------------------------------------------------------ private static void DumpLineRange(XmlTextWriter writer, int cpStart, int cpEnd, int cpContentEnd, int cpEllipses) { writer.WriteStartElement("TextRange"); writer.WriteAttributeString("Start", cpStart.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("Length", (cpEnd - cpStart).ToString(CultureInfo.InvariantCulture)); if (cpEnd != cpContentEnd) { writer.WriteAttributeString("HiddenLength", (cpEnd - cpContentEnd).ToString(CultureInfo.InvariantCulture)); } if (cpEnd != cpEllipses) { writer.WriteAttributeString("EllipsesLength", (cpEnd - cpEllipses).ToString(CultureInfo.InvariantCulture)); } writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump line array. // ----------------------------------------------------------------- private static void DumpLineResults(XmlTextWriter writer, ReadOnlyCollection lines, Visual visualParent) { if (lines != null) { // Dump line array writer.WriteStartElement("Lines"); writer.WriteAttributeString("Count", lines.Count.ToString(CultureInfo.InvariantCulture)); for (int index = 0; index < lines.Count; index++) { writer.WriteStartElement("Line"); // Dump line info LineResult line = lines[index]; DumpRect(writer, "LayoutBox", line.LayoutBox); DumpLineRange(writer, line.StartPositionCP, line.EndPositionCP, line.GetContentEndPositionCP(), line.GetEllipsesPositionCP()); /* // Dump inline objects ReadOnlyCollection inlineObjects = line.InlineObjects; if (inlineObjects != null) { // All inline UIElements are dumped as Children collection of UIElement // that invokes this dump method. Hence, do not dump UIElements here. writer.WriteStartElement("InlineObjects"); writer.WriteAttributeString("Count", inlineObjects.Count.ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } */ writer.WriteEndElement(); } writer.WriteEndElement(); } } #endregion Custom Dump Handlers // ----------------------------------------------------------------- // Dump paragraphs collection. // ------------------------------------------------------------------ private static void DumpParagraphResults(XmlTextWriter writer, string tagName, ReadOnlyCollection paragraphs, Visual visualParent) { if (paragraphs != null) { // Dump paragraphs array writer.WriteStartElement(tagName); writer.WriteAttributeString("Count", paragraphs.Count.ToString(CultureInfo.InvariantCulture)); for (int index = 0; index < paragraphs.Count; index++) { ParagraphResult paragraph = paragraphs[index]; if (paragraph is TextParagraphResult) { DumpTextParagraphResult(writer, (TextParagraphResult)paragraph, visualParent); } else if (paragraph is ContainerParagraphResult) { DumpContainerParagraphResult(writer, (ContainerParagraphResult)paragraph, visualParent); } else if (paragraph is TableParagraphResult) { DumpTableParagraphResult(writer, (TableParagraphResult)paragraph, visualParent); } else if (paragraph is FloaterParagraphResult) { DumpFloaterParagraphResult(writer, (FloaterParagraphResult)paragraph, visualParent); } else if (paragraph is UIElementParagraphResult) { DumpUIElementParagraphResult(writer, (UIElementParagraphResult)paragraph, visualParent); } else if (paragraph is FigureParagraphResult) { DumpFigureParagraphResult(writer, (FigureParagraphResult)paragraph, visualParent); } else if (paragraph is SubpageParagraphResult) { DumpSubpageParagraphResult(writer, (SubpageParagraphResult)paragraph, visualParent); } } writer.WriteEndElement(); } } // ----------------------------------------------------------------- // Dump text paragraph result. // ------------------------------------------------------------------ private static void DumpTextParagraphResult(XmlTextWriter writer, TextParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("TextParagraph"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpTextRange(writer, paragraph.StartPosition, paragraph.EndPosition); DumpLineResults(writer, paragraph.Lines, visual); DumpParagraphResults(writer, "Floaters", paragraph.Floaters, visual); DumpParagraphResults(writer, "Figures", paragraph.Figures, visual); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump container paragraph result. // ----------------------------------------------------------------- private static void DumpContainerParagraphResult(XmlTextWriter writer, ContainerParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("ContainerParagraph"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpParagraphResults(writer, "Paragraphs", paragraph.Paragraphs, visual); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump floater paragraph result. // ----------------------------------------------------------------- private static void DumpFloaterParagraphResult(XmlTextWriter writer, FloaterParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("Floater"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpColumnResults(writer, paragraph.Columns, visual); writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump UIElement paragraph result. // ----------------------------------------------------------------- private static void DumpUIElementParagraphResult(XmlTextWriter writer, UIElementParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("BlockUIContainer"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump figure paragraph result. // ----------------------------------------------------------------- private static void DumpFigureParagraphResult(XmlTextWriter writer, FigureParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("Figure"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpColumnResults(writer, paragraph.Columns, visual); writer.WriteEndElement(); } // ------------------------------------------------------------------ // Dump table paragraph result. // ------------------------------------------------------------------ private static void DumpTableParagraphResult(XmlTextWriter writer, TableParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("TableParagraph"); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); ReadOnlyCollection rowParagraphs = paragraph.Paragraphs; int count1 = VisualTreeHelper.GetChildrenCount(visual); for(int i = 0; i < count1; i++) { Visual rowVisual = visual.InternalGetVisualChild(i); int count2 = VisualTreeHelper.GetChildrenCount(rowVisual); ReadOnlyCollection cellParagraphs = ((RowParagraphResult)rowParagraphs[i]).CellParagraphs; for(int j = 0; j < count2; j++) { Visual cellVisual = rowVisual.InternalGetVisualChild(j); DumpTableCell(writer, cellParagraphs[j], cellVisual, visual); } } writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump subpage paragraph result. // ------------------------------------------------------------------ private static void DumpSubpageParagraphResult(XmlTextWriter writer, SubpageParagraphResult paragraph, Visual visualParent) { writer.WriteStartElement("SubpageParagraph"); // Dump paragraph info writer.WriteStartElement("Element"); writer.WriteAttributeString("Type", paragraph.Element.GetType().FullName); writer.WriteEndElement(); DumpRect(writer, "LayoutBox", paragraph.LayoutBox); Visual visual = DumpParagraphOffset(writer, paragraph, visualParent); DumpColumnResults(writer, paragraph.Columns, visual); writer.WriteEndElement(); } // ----------------------------------------------------------------- // Dump column results. // ----------------------------------------------------------------- private static void DumpColumnResults(XmlTextWriter writer, ReadOnlyCollection columns, Visual visualParent) { if (columns != null) { writer.WriteStartElement("Columns"); writer.WriteAttributeString("Count", columns.Count.ToString(CultureInfo.InvariantCulture)); for (int index = 0; index < columns.Count; index++) { writer.WriteStartElement("Column"); // Dump column info ColumnResult column = columns[index]; DumpRect(writer, "LayoutBox", column.LayoutBox); DumpTextRange(writer, column.StartPosition, column.EndPosition); DumpParagraphResults(writer, "Paragraphs", column.Paragraphs, visualParent); writer.WriteEndElement(); } writer.WriteEndElement(); } } // ----------------------------------------------------------------- // Dump paragraph offset. // ------------------------------------------------------------------ private static Visual DumpParagraphOffset(XmlTextWriter writer, ParagraphResult paragraph, Visual visualParent) { Type paragraphResultType = paragraph.GetType(); System.Reflection.FieldInfo field = paragraphResultType.GetField("_paraClient", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); object paraClient = field.GetValue(paragraph); Type paraClientType = paraClient.GetType(); System.Reflection.PropertyInfo prop = paraClientType.GetProperty("Visual", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); Visual visual = (Visual)prop.GetValue(paraClient, null); // Dump transform relative to its parent if(visualParent.IsAncestorOf(visual)) { GeneralTransform g = visual.TransformToAncestor(visualParent); Point point = new Point(0.0f, 0.0f); g.TryTransform(point, out point); if (point.X != 0 || point.Y != 0) { DumpPoint(writer, "Origin", point); } } return visual; } // ----------------------------------------------------------------- // Dump Table specific data: ColumnCount. // ------------------------------------------------------------------ private static void DumpTableCalculatedMetrics(XmlTextWriter writer, object element) { Type type = typeof(Table); System.Reflection.PropertyInfo prop = type.GetProperty("ColumnCount"); if (prop != null) { int count = (int)prop.GetValue(element, null); writer.WriteStartElement("ColumnCount"); writer.WriteAttributeString("Count", count.ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } } // ------------------------------------------------------------------ // Dump Cell specific data. // ----------------------------------------------------------------- private static void DumpTableCell(XmlTextWriter writer, ParagraphResult paragraph, Visual cellVisual, Visual tableVisual) { Type paragraphResultType = paragraph.GetType(); System.Reflection.FieldInfo fieldOfParaClient = paragraphResultType.GetField("_paraClient", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); if (fieldOfParaClient == null) { return; } CellParaClient cellParaClient = (CellParaClient) fieldOfParaClient.GetValue(paragraph); CellParagraph cellParagraph = cellParaClient.CellParagraph; TableCell cell = cellParagraph.Cell; writer.WriteStartElement("Cell"); Type typeOfCell = cell.GetType(); System.Reflection.PropertyInfo propOfColumnIndex = typeOfCell.GetProperty("ColumnIndex", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.DeclaredOnly); if (propOfColumnIndex != null) { int columnIndex = (int)propOfColumnIndex.GetValue(cell, null); writer.WriteAttributeString("ColumnIndex", columnIndex.ToString(CultureInfo.InvariantCulture)); } System.Reflection.PropertyInfo propOfRowIndex = typeOfCell.GetProperty("RowIndex", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.DeclaredOnly); if (propOfRowIndex != null) { int rowIndex = (int)propOfRowIndex.GetValue(cell, null); writer.WriteAttributeString("RowIndex", rowIndex.ToString(CultureInfo.InvariantCulture)); } writer.WriteAttributeString("ColumnSpan", cell.ColumnSpan.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("RowSpan", cell.RowSpan.ToString(CultureInfo.InvariantCulture)); Rect rect = cellParaClient.Rect.FromTextDpi(); DumpRect(writer, "LayoutBox", rect); bool hasTextContent; DumpParagraphResults(writer, "Paragraphs", cellParaClient.GetColumnResults(out hasTextContent)[0].Paragraphs, cellParaClient.Visual); writer.WriteEndElement(); } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- InternalMappingException.cs
- DataServiceConfiguration.cs
- BaseWebProxyFinder.cs
- UInt64.cs
- DockPatternIdentifiers.cs
- FontInfo.cs
- RefreshEventArgs.cs
- Coordinator.cs
- EventDescriptor.cs
- VersionedStream.cs
- UnSafeCharBuffer.cs
- CultureTable.cs
- HMACSHA512.cs
- SectionVisual.cs
- WebPartMenu.cs
- ComplexLine.cs
- Viewport3DVisual.cs
- Drawing.cs
- TextDpi.cs
- Grant.cs
- CodeValidator.cs
- CredentialCache.cs
- RectValueSerializer.cs
- DataColumnPropertyDescriptor.cs
- DataBoundControlHelper.cs
- AlgoModule.cs
- XmlToDatasetMap.cs
- TextEndOfParagraph.cs
- ZipIOLocalFileBlock.cs
- SHA512.cs
- AdPostCacheSubstitution.cs
- SelfIssuedAuthRSAPKCS1SignatureDeformatter.cs
- DocumentSequenceHighlightLayer.cs
- TypeReference.cs
- OpenFileDialog.cs
- XmlStreamStore.cs
- ImageCodecInfo.cs
- OutputCacheSection.cs
- MessageSmuggler.cs
- ListBoxItemWrapperAutomationPeer.cs
- AppDomainUnloadedException.cs
- XmlSchemaGroup.cs
- Rect.cs
- Condition.cs
- IncomingWebResponseContext.cs
- Switch.cs
- CodeAttributeArgumentCollection.cs
- SpellerError.cs
- ArrayList.cs
- UniqueIdentifierService.cs
- ToolStripContainerActionList.cs
- NTAccount.cs
- InfiniteTimeSpanConverter.cs
- PassportAuthenticationEventArgs.cs
- WithParamAction.cs
- TableCell.cs
- ConnectionManagementSection.cs
- ArraySet.cs
- CodeDomSerializationProvider.cs
- PolyQuadraticBezierSegment.cs
- HttpCookie.cs
- _ListenerAsyncResult.cs
- KeyedCollection.cs
- EdmToObjectNamespaceMap.cs
- SortQuery.cs
- ResourceWriter.cs
- HttpHandlersSection.cs
- dsa.cs
- AssertFilter.cs
- GridToolTip.cs
- Attributes.cs
- QuadraticEase.cs
- RadioButtonStandardAdapter.cs
- SchemaNotation.cs
- EventInfo.cs
- DeferredElementTreeState.cs
- Expression.DebuggerProxy.cs
- NullableIntSumAggregationOperator.cs
- SmiEventSink_DeferedProcessing.cs
- PermissionSetTriple.cs
- XsdBuildProvider.cs
- SqlRowUpdatedEvent.cs
- ConfigurationStrings.cs
- SerializationObjectManager.cs
- ProcessHostConfigUtils.cs
- RetrieveVirtualItemEventArgs.cs
- UnsafeMethods.cs
- Composition.cs
- MimeFormatExtensions.cs
- SchemaObjectWriter.cs
- ImageAttributes.cs
- SoapFault.cs
- MTConfigUtil.cs
- ObjectStateManagerMetadata.cs
- XmlChoiceIdentifierAttribute.cs
- EntityTemplateUserControl.cs
- ExpressionHelper.cs
- PlacementWorkspace.cs
- SignatureHelper.cs
- EventWaitHandleSecurity.cs