//-------------------------------------------------------------------- // // Public Properties // //--------------------------------------------------------------------- #region Static methods public static FixedSOMElement CreateFixedSOMElement(FixedPage page, UIElement uiElement, FixedNode fixedNode, int startIndex, int endIndex) { FixedSOMElement element = null; if (uiElement is Glyphs) { Glyphs glyphs = uiElement as Glyphs; if (glyphs.UnicodeString.Length > 0) { GlyphRun glyphRun = glyphs.ToGlyphRun(); Rect alignmentBox = glyphRun.ComputeAlignmentBox(); alignmentBox.Offset(glyphs.OriginX, glyphs.OriginY); GeneralTransform transform = glyphs.TransformToAncestor(page); if (startIndex < 0) { startIndex = 0; } if (endIndex < 0) { endIndex = glyphRun.Characters == null ? 0 : glyphRun.Characters.Count; } element = FixedSOMTextRun.Create(alignmentBox, transform, glyphs, fixedNode, startIndex, endIndex, false); } } else if (uiElement is Image) { element = FixedSOMImage.Create(page, uiElement as Image, fixedNode); } else if (uiElement is Path) { element = FixedSOMImage.Create(page, uiElement as Path, fixedNode); } return element; }
// Token: 0x06002DF8 RID: 11768 RVA: 0x000CE9D4 File Offset: 0x000CCBD4 private void _ProcessImage(DependencyObject obj, FixedNode fixedNode) { Image image; Path path; for (;;) { image = (obj as Image); if (image != null) { break; } path = (obj as Path); if (path != null) { goto Block_1; } } FixedSOMImage image2 = FixedSOMImage.Create(this._fixedPage, image, fixedNode); goto IL_34; Block_1: image2 = FixedSOMImage.Create(this._fixedPage, path, fixedNode); IL_34: FixedSOMFixedBlock fixedSOMFixedBlock = new FixedSOMFixedBlock(this._fixedSOMPage); fixedSOMFixedBlock.AddImage(image2); this._fixedSOMPage.AddFixedBlock(fixedSOMFixedBlock); this._currentFixedBlock = fixedSOMFixedBlock; }
//-------------------------------------------------------------------- // // Private Methods // //--------------------------------------------------------------------- #region Private methods private void _ProcessImage(DependencyObject obj, FixedNode fixedNode) { Debug.Assert(obj is Image || obj is Path); FixedSOMImage somImage = null; while (true) { Image image = obj as Image; if (image != null) { somImage = FixedSOMImage.Create(_fixedPage, image, fixedNode); break; } Path path = obj as Path; if (path != null) { somImage = FixedSOMImage.Create(_fixedPage, path, fixedNode); break; } } //Create a wrapper FixedBlock: FixedSOMFixedBlock fixedBlock = new FixedSOMFixedBlock(_fixedSOMPage); fixedBlock.AddImage(somImage); _fixedSOMPage.AddFixedBlock(fixedBlock); _currentFixedBlock = fixedBlock; }
private void AddChildofFixedNodeinFlow(int[] childIndex, NamedElement ne) { // Create a fake FixedNode to help binary search. FixedNode fn = FixedNode.Create(((FixedNode)_fixedNodes[0]).Page, childIndex); // Launch the binary search to find the matching FixedNode int index = _fixedNodes.BinarySearch(fn); if (index >= 0) { int startIndex; // Search backward for the first Node in this scope for (startIndex = index - 1; startIndex >= 0; startIndex--) { fn = (FixedNode)_fixedNodes[startIndex]; if (fn.ComparetoIndex(childIndex) != 0) { break; } } // Search forward to add all the nodes in order. for (int i = startIndex + 1; i < _fixedNodes.Count; i++) { fn = (FixedNode)_fixedNodes[i]; if (fn.ComparetoIndex(childIndex) == 0) { AddFixedNodeInFlow(i, null); } else { break; } } } }
// Token: 0x06002D93 RID: 11667 RVA: 0x000CD4F0 File Offset: 0x000CB6F0 internal FixedPageStructure(int pageIndex) { this._pageIndex = pageIndex; this._flowStart = new FlowNode(-1, FlowNodeType.Virtual, pageIndex); this._flowEnd = this._flowStart; this._fixedStart = FixedNode.Create(pageIndex, 1, int.MinValue, -1, null); this._fixedEnd = FixedNode.Create(pageIndex, 1, int.MaxValue, -1, null); }
private List <FixedSOMElement> _GetEntry(FixedNode node) { if (_cachedEntry == null || node != _cachedFixedNode) { _cachedEntry = (List <FixedSOMElement>)_mapping[node]; _cachedFixedNode = node; } return(_cachedEntry); }
//-------------------------------------------------------------------- // // Constructors // //--------------------------------------------------------------------- #region Constructors private FixedSOMImage(Rect imageRect, GeneralTransform trans, Uri sourceUri, FixedNode node, DependencyObject o) : base(node, trans) { _boundingRect = trans.TransformBounds(imageRect); _source = sourceUri; _startIndex = 0; _endIndex = 1; _name = AutomationProperties.GetName(o); _helpText = AutomationProperties.GetHelpText(o); }
// Token: 0x06002D35 RID: 11573 RVA: 0x000CC1D8 File Offset: 0x000CA3D8 private List <FixedSOMElement> _GetEntry(FixedNode node) { if (this._cachedEntry == null || node != this._cachedFixedNode) { this._cachedEntry = (List <FixedSOMElement>) this._mapping[node]; this._cachedFixedNode = node; } return(this._cachedEntry); }
// Token: 0x0600350E RID: 13582 RVA: 0x000F0634 File Offset: 0x000EE834 private ITextPointer _GetTextPosition(FixedNode node, int charIndex) { FixedPosition fixedPosition = new FixedPosition(node, charIndex); FlowPosition flowPosition = this._panel.FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition); if (flowPosition != null) { return(new FixedTextPointer(false, LogicalDirection.Forward, flowPosition)); } return(null); }
// Token: 0x06002D4D RID: 11597 RVA: 0x000CC6BF File Offset: 0x000CA8BF internal static FixedNode Create(int pageIndex, int childLevels, int level1Index, int level2Index, int[] childPath) { if (childLevels == 1) { return(new FixedNode(pageIndex, level1Index)); } if (childLevels != 2) { return(FixedNode.Create(pageIndex, childPath)); } return(new FixedNode(pageIndex, level1Index, level2Index)); }
// Token: 0x06002DAA RID: 11690 RVA: 0x000CD8F0 File Offset: 0x000CBAF0 protected FixedSOMElement(FixedNode fixedNode, GeneralTransform transform) { this._fixedNode = fixedNode; Transform affineTransform = transform.AffineTransform; if (affineTransform != null) { this._mat = affineTransform.Value; return; } this._mat = Transform.Identity.Value; }
// Token: 0x06002EF1 RID: 12017 RVA: 0x000D3FAC File Offset: 0x000D21AC private ITextPointer _SnapToText(Point point) { FixedNode[] line = this.Container.FixedTextBuilder.GetLine(this.PageIndex, point); ITextPointer textPointer; if (line != null && line.Length != 0) { double num = double.MaxValue; double xoffset = 0.0; Glyphs glyphs = null; FixedNode fixedNode = line[0]; foreach (FixedNode fixedNode2 in line) { Glyphs glyphsElement = this.FixedPage.GetGlyphsElement(fixedNode2); GeneralTransform generalTransform = this.FixedPage.TransformToDescendant(glyphsElement); Point inPoint = point; if (generalTransform != null) { generalTransform.TryTransform(inPoint, out inPoint); } GlyphRun glyphRun = glyphsElement.ToGlyphRun(); Rect rect = glyphRun.ComputeAlignmentBox(); rect.Offset(glyphsElement.OriginX, glyphsElement.OriginY); double num2 = Math.Max(0.0, (inPoint.X > rect.X) ? (inPoint.X - rect.Right) : (rect.X - inPoint.X)); double num3 = Math.Max(0.0, (inPoint.Y > rect.Y) ? (inPoint.Y - rect.Bottom) : (rect.Y - inPoint.Y)); double num4 = num2 + num3; if (glyphs == null || num4 < num) { num = num4; glyphs = glyphsElement; fixedNode = fixedNode2; xoffset = inPoint.X; } } int offset; LogicalDirection edge; this._GlyphRunHitTest(glyphs, xoffset, out offset, out edge); FixedPosition fixedPosition = new FixedPosition(fixedNode, offset); textPointer = this._CreateTextPointer(fixedPosition, edge); } else if (point.Y < this.FixedPage.Height / 2.0) { textPointer = ((ITextPointer)this.Start).CreatePointer(LogicalDirection.Forward); textPointer.MoveToInsertionPosition(LogicalDirection.Forward); } else { textPointer = ((ITextPointer)this.End).CreatePointer(LogicalDirection.Backward); textPointer.MoveToInsertionPosition(LogicalDirection.Backward); } return(textPointer); }
//-------------------------------------------------------------------- // // Constructors // //--------------------------------------------------------------------- #region Constructors internal FixedPageStructure(int pageIndex) { Debug.Assert(pageIndex >= 0); _pageIndex = pageIndex; // Initialize to virtual _flowStart = new FlowNode(FixedFlowMap.FlowOrderVirtualScopeId, FlowNodeType.Virtual, pageIndex); _flowEnd = _flowStart; // _fixedStart = FixedNode.Create(pageIndex, 1, FixedFlowMap.FixedOrderStartVisual, -1, null); _fixedEnd = FixedNode.Create(pageIndex, 1, FixedFlowMap.FixedOrderEndVisual, -1, null); }
//------------------------------------------------------- // Fixed Order //------------------------------------------------------- #if DEBUG // This is only used in our debug fixed node rendering code // Get a range of fixednode in fixed order between two fixed nodes, inclusive internal FixedNode[] FixedOrderGetRangeNodes(FixedNode start, FixedNode end) { //Debug.Assert(start <= end); if (start == end) { return(new FixedNode[1] { start }); } ArrayList range = new ArrayList(); // will this function be passed boundary nodes?? FlowNode flowNode = ((List <FixedSOMElement>)_GetEntry(start))[0].FlowNode; bool foundEnd = false; while (!foundEnd) { if (flowNode.FixedSOMElements != null) { foreach (FixedSOMElement element in flowNode.FixedSOMElements) { if (range.Count == 0) { if (element.FixedNode == start) { range.Add(start); } } else { if (!element.FixedNode.Equals(range[range.Count - 1])) { range.Add(element.FixedNode); } } if (element.FixedNode == end) { foundEnd = true; break; } } } flowNode = _flowOrder[flowNode.Fp + 1]; } return((FixedNode[])range.ToArray(typeof(FixedNode))); }
protected FixedSOMElement(FixedNode fixedNode, GeneralTransform transform) { _fixedNode = fixedNode; Transform trans = transform.AffineTransform; if (trans != null) { _mat = trans.Value; } else { _mat = Transform.Identity.Value; } }
// Token: 0x06002DA9 RID: 11689 RVA: 0x000CD8A0 File Offset: 0x000CBAA0 protected FixedSOMElement(FixedNode fixedNode, int startIndex, int endIndex, GeneralTransform transform) { this._fixedNode = fixedNode; this._startIndex = startIndex; this._endIndex = endIndex; Transform affineTransform = transform.AffineTransform; if (affineTransform != null) { this._mat = affineTransform.Value; return; } this._mat = Transform.Identity.Value; }
private ITextPointer _GetTextPosition(FixedNode node, int charIndex) { FixedPosition fixedPosition = new FixedPosition(node, charIndex); // Create a FlowPosition to represent this fixed position FlowPosition flowHit = _panel.FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition); if (flowHit != null) { // Create a TextPointer from the flow position return(new FixedTextPointer(false, LogicalDirection.Forward, flowHit)); } return(null); }
//-------------------------------------------------------------------- // // Constructors // //--------------------------------------------------------------------- #region Constructors protected FixedSOMElement(FixedNode fixedNode, int startIndex, int endIndex, GeneralTransform transform) { _fixedNode = fixedNode; _startIndex = startIndex; _endIndex = endIndex; Transform trans = transform.AffineTransform; if (trans != null) { _mat = trans.Value; } else { _mat = Transform.Identity.Value; } }
//-------------------------------------------------------------------- // // Static Method // //--------------------------------------------------------------------- // Factory method to create a fixed node from its path // Avoiding create ArrayList if possible // Most common case childLevel is either 1, 2 level deep. // level 0 is always the page internal static FixedNode Create(int pageIndex, int childLevels, int level1Index, int level2Index, int[] childPath) { Debug.Assert(childLevels >= 1); switch (childLevels) { case 1: return(new FixedNode(pageIndex, level1Index)); case 2: return(new FixedNode(pageIndex, level1Index, level2Index)); default: return(FixedNode.Create(pageIndex, childPath)); } }
// Token: 0x06002D36 RID: 11574 RVA: 0x000CC224 File Offset: 0x000CA424 private void _AddEntry(FixedSOMElement element) { FixedNode fixedNode = element.FixedNode; List <FixedSOMElement> list; if (this._mapping.ContainsKey(fixedNode)) { list = (List <FixedSOMElement>) this._mapping[fixedNode]; } else { list = new List <FixedSOMElement>(); this._mapping.Add(fixedNode, list); } list.Add(element); }
// Token: 0x06002D2C RID: 11564 RVA: 0x000CC054 File Offset: 0x000CA254 internal FixedSOMElement MappingGetFixedSOMElement(FixedNode fixedp, int offset) { List <FixedSOMElement> list = this._GetEntry(fixedp); if (list != null) { foreach (FixedSOMElement fixedSOMElement in list) { if (offset >= fixedSOMElement.StartIndex && offset <= fixedSOMElement.EndIndex) { return(fixedSOMElement); } } } return(null); }
//-------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region Public Methods // IComparable Override public int CompareTo(object o) { if (o == null) { throw new ArgumentNullException("o"); } if (o.GetType() != typeof(FixedNode)) { throw new ArgumentException(SR.Get(SRID.UnexpectedParameterType, o.GetType(), typeof(FixedNode)), "o"); } FixedNode fixedp = (FixedNode)o; return(CompareTo(fixedp)); }
internal FixedSOMElement MappingGetFixedSOMElement(FixedNode fixedp, int offset) { List <FixedSOMElement> entry = _GetEntry(fixedp); if (entry != null) { foreach (FixedSOMElement element in entry) { if (offset >= element.StartIndex && offset <= element.EndIndex) { return(element); } } } return(null); }
private void _AddEntry(FixedSOMElement element) { FixedNode fn = element.FixedNode; List <FixedSOMElement> entry; if (_mapping.ContainsKey(fn)) { entry = (List <FixedSOMElement>)_mapping[fn]; } else { entry = new List <FixedSOMElement>(); _mapping.Add(fn, entry); } entry.Add(element); }
// Token: 0x06002D52 RID: 11602 RVA: 0x000CC760 File Offset: 0x000CA960 public int CompareTo(object o) { if (o == null) { throw new ArgumentNullException("o"); } if (o.GetType() != typeof(FixedNode)) { throw new ArgumentException(SR.Get("UnexpectedParameterType", new object[] { o.GetType(), typeof(FixedNode) }), "o"); } FixedNode fixedNode = (FixedNode)o; return(this.CompareTo(fixedNode)); }
//------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region Public Methods public static FixedSOMImage Create(FixedPage page, Image image, FixedNode fixedNode) { Uri imageUri = null; if (image.Source is BitmapImage) { BitmapImage imageSource = image.Source as BitmapImage; imageUri = imageSource.UriSource; } else if (image.Source is BitmapFrame) { BitmapFrame imageSource = image.Source as BitmapFrame; imageUri = new Uri(imageSource.ToString(), UriKind.RelativeOrAbsolute); } Rect sourceRect = new Rect(image.RenderSize); GeneralTransform transform = image.TransformToAncestor(page); return new FixedSOMImage(sourceRect, transform, imageUri, fixedNode, image); }
// Token: 0x06002DC6 RID: 11718 RVA: 0x000CDF38 File Offset: 0x000CC138 public static FixedSOMImage Create(FixedPage page, Image image, FixedNode fixedNode) { Uri sourceUri = null; if (image.Source is BitmapImage) { BitmapImage bitmapImage = image.Source as BitmapImage; sourceUri = bitmapImage.UriSource; } else if (image.Source is BitmapFrame) { BitmapFrame bitmapFrame = image.Source as BitmapFrame; sourceUri = new Uri(bitmapFrame.ToString(), UriKind.RelativeOrAbsolute); } Rect imageRect = new Rect(image.RenderSize); GeneralTransform trans = image.TransformToAncestor(page); return(new FixedSOMImage(imageRect, trans, sourceUri, fixedNode, image)); }
/// <summary> /// Returns a TextSegment that spans the line on which position is located. /// </summary> /// <param name="position"> /// Any oriented text position on the line. /// </param> /// <returns> /// TextSegment that spans the line on which position is located. /// </returns> /// <exception cref="System.InvalidOperationException"> /// Throws InvalidOperationException if IsValid is false. /// If IsValid returns false, Validate method must be called before /// calling this method. /// </exception> internal override TextSegment GetLineRange(ITextPointer position) { #if DEBUG DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("GetLineRange {0}, {1}", (FixedTextPointer)position, position.LogicalDirection)); #endif FixedTextPointer ftp = Container.VerifyPosition(position); FixedPosition fixedp; if (!_GetFixedPosition(ftp, out fixedp)) { return(new TextSegment(position, position, true)); } int count = 0; FixedNode[] fixedNodes = Container.FixedTextBuilder.GetNextLine(fixedp.Node, true, ref count); if (fixedNodes == null) { // This will happen in the case of images fixedNodes = new FixedNode[] { fixedp.Node }; } FixedNode lastNode = fixedNodes[fixedNodes.Length - 1]; DependencyObject element = FixedPage.GetElement(lastNode); int lastIndex = 1; if (element is Glyphs) { lastIndex = ((Glyphs)element).UnicodeString.Length; } ITextPointer begin = _CreateTextPointer(new FixedPosition(fixedNodes[0], 0), LogicalDirection.Forward); ITextPointer end = _CreateTextPointer(new FixedPosition(lastNode, lastIndex), LogicalDirection.Backward); if (begin.CompareTo(end) > 0) { ITextPointer temp = begin; begin = end; end = temp; } return(new TextSegment(begin, end, true)); }
// Token: 0x06002D19 RID: 11545 RVA: 0x000CB894 File Offset: 0x000C9A94 private void AddChildofFixedNodeinFlow(int[] childIndex, NamedElement ne) { FixedNode item = FixedNode.Create(this._fixedNodes[0].Page, childIndex); int num = this._fixedNodes.BinarySearch(item); if (num >= 0) { int num2 = num - 1; while (num2 >= 0 && this._fixedNodes[num2].ComparetoIndex(childIndex) == 0) { num2--; } int num3 = num2 + 1; while (num3 < this._fixedNodes.Count && this._fixedNodes[num3].ComparetoIndex(childIndex) == 0) { this.AddFixedNodeInFlow(num3, null); num3++; } } }
public static FixedSOMImage Create(FixedPage page, Path path, FixedNode fixedNode) { Debug.Assert(path.Fill is ImageBrush); ImageSource source = ((ImageBrush)(path.Fill)).ImageSource; Uri imageUri = null; if (source is BitmapImage) { BitmapImage imageSource = source as BitmapImage; imageUri = imageSource.UriSource; } else if (source is BitmapFrame) { BitmapFrame imageSource = source as BitmapFrame; imageUri = new Uri(imageSource.ToString(), UriKind.RelativeOrAbsolute); } Rect sourceRect = path.Data.Bounds; GeneralTransform trans = path.TransformToAncestor(page); return new FixedSOMImage(sourceRect, trans, imageUri, fixedNode, path); }
// Token: 0x06002DC7 RID: 11719 RVA: 0x000CDFB0 File Offset: 0x000CC1B0 public static FixedSOMImage Create(FixedPage page, Path path, FixedNode fixedNode) { ImageSource imageSource = ((ImageBrush)path.Fill).ImageSource; Uri sourceUri = null; if (imageSource is BitmapImage) { BitmapImage bitmapImage = imageSource as BitmapImage; sourceUri = bitmapImage.UriSource; } else if (imageSource is BitmapFrame) { BitmapFrame bitmapFrame = imageSource as BitmapFrame; sourceUri = new Uri(bitmapFrame.ToString(), UriKind.RelativeOrAbsolute); } Rect bounds = path.Data.Bounds; GeneralTransform trans = path.TransformToAncestor(page); return(new FixedSOMImage(bounds, trans, sourceUri, fixedNode, path)); }
// Token: 0x06002D17 RID: 11543 RVA: 0x000CB760 File Offset: 0x000C9960 private void AddFixedNodeInFlow(int index, UIElement e) { if (this._visitedArray[index]) { return; } FixedNode fixedNode = this._fixedNodes[index]; if (e == null) { e = (this._fixedPage.GetElement(fixedNode) as UIElement); } this._visitedArray[index] = true; FixedSOMElement fixedSOMElement = FixedSOMElement.CreateFixedSOMElement(this._fixedPage, e, fixedNode, -1, -1); if (fixedSOMElement != null) { this._flowBuilder.AddElement(fixedSOMElement); } }
// Token: 0x06002D53 RID: 11603 RVA: 0x000CC7D4 File Offset: 0x000CA9D4 public int CompareTo(FixedNode fixedNode) { int num = this.Page.CompareTo(fixedNode.Page); if (num == 0) { int num2 = 1; while (num2 <= this.ChildLevels && num2 <= fixedNode.ChildLevels) { int num3 = this[num2]; int num4 = fixedNode[num2]; if (num3 != num4) { return(num3.CompareTo(num4)); } num2++; } } return(num); }
private List<FixedSOMElement> _GetEntry(FixedNode node) { if (_cachedEntry == null || node != _cachedFixedNode) { _cachedEntry = (List<FixedSOMElement>)_mapping[node]; _cachedFixedNode = node; } return _cachedEntry; }
//------------------------------------------------------- // Fixed Order //------------------------------------------------------- #if DEBUG // This is only used in our debug fixed node rendering code // Get a range of fixednode in fixed order between two fixed nodes, inclusive internal FixedNode[] FixedOrderGetRangeNodes(FixedNode start, FixedNode end) { //Debug.Assert(start <= end); if (start == end) { return new FixedNode[1] { start }; } ArrayList range = new ArrayList(); // will this function be passed boundary nodes?? FlowNode flowNode = ((List<FixedSOMElement>) _GetEntry(start))[0].FlowNode; bool foundEnd = false; while (!foundEnd) { if (flowNode.FixedSOMElements != null) { foreach (FixedSOMElement element in flowNode.FixedSOMElements) { if (range.Count == 0) { if (element.FixedNode == start) { range.Add(start); } } else { if (!element.FixedNode.Equals(range[range.Count - 1])) { range.Add(element.FixedNode); } } if (element.FixedNode == end) { foundEnd = true; break; } } } flowNode = _flowOrder[flowNode.Fp + 1]; } return (FixedNode[])range.ToArray(typeof(FixedNode)); }
internal FixedSOMElement MappingGetFixedSOMElement(FixedNode fixedp, int offset) { List<FixedSOMElement> entry = _GetEntry(fixedp); if (entry != null) { foreach (FixedSOMElement element in entry) { if (offset >= element.StartIndex && offset <= element.EndIndex) { return element; } } } return null; }
//Creates a FixedSOMTextRun, and updates containing structures private void _CreateTextRun(Rect boundingRect, GeneralTransform trans, Glyphs glyphs, FixedNode node, int startIndex, int endIndex) { if (startIndex < endIndex) { FixedSOMTextRun textRun = FixedSOMTextRun.Create(boundingRect, trans, glyphs, node, startIndex, endIndex, true); FixedSOMFixedBlock fixedBlock = _GetContainingFixedBlock(textRun); if (fixedBlock == null) { fixedBlock= new FixedSOMFixedBlock(_fixedSOMPage); fixedBlock.AddTextRun(textRun); _fixedSOMPage.AddFixedBlock(fixedBlock); } else { fixedBlock.AddTextRun(textRun); } _currentFixedBlock = fixedBlock; } }
//Processes the Glyphs element, create one or more text runs out of it, add to containing text line and text box private void _ProcessGlyphsElement(Glyphs glyphs, FixedNode node) { Debug.Assert(glyphs != null); string s = glyphs.UnicodeString; if (s.Length == 0 || glyphs.FontRenderingEmSize <= 0) { return; } //Multiple table cells separated by wide spaces should be identified GlyphRun glyphRun = glyphs.ToGlyphRun(); if (glyphRun == null) { //Could not create a GlyphRun out of this Glyphs element //Some key properties might be missing/invalid return; } Rect alignmentBox = glyphRun.ComputeAlignmentBox(); alignmentBox.Offset(glyphs.OriginX, glyphs.OriginY); GlyphTypeface typeFace = glyphRun.GlyphTypeface; GeneralTransform trans = glyphs.TransformToAncestor(_fixedPage); int charIndex= -1; double advWidth = 0; double cumulativeAdvWidth = 0; int lastAdvWidthIndex = 0; int textRunStartIndex = 0; double lastX = alignmentBox.Left; int glyphIndex = charIndex; do { charIndex = s.IndexOf(" ", charIndex+1, s.Length - charIndex -1, StringComparison.Ordinal); if (charIndex >=0 ) { if (glyphRun.ClusterMap != null && glyphRun.ClusterMap.Count > 0) { glyphIndex = glyphRun.ClusterMap[charIndex]; } else { glyphIndex = charIndex; } //Advance width of the space character in the font double advFont = typeFace.AdvanceWidths[glyphRun.GlyphIndices[glyphIndex]] * glyphRun.FontRenderingEmSize; double advSpecified = glyphRun.AdvanceWidths[glyphIndex]; if ((advSpecified / advFont) > 2) { //Are these seperated by a vertical line? advWidth = 0; for (int i=lastAdvWidthIndex; i<glyphIndex; i++) { advWidth += glyphRun.AdvanceWidths[i]; } cumulativeAdvWidth += advWidth; lastAdvWidthIndex = glyphIndex + 1; if (_lines.IsVerticallySeparated(glyphRun.BaselineOrigin.X + cumulativeAdvWidth, alignmentBox.Top, glyphRun.BaselineOrigin.X + cumulativeAdvWidth + advSpecified, alignmentBox.Bottom)) { //Create a new FixedTextRun Rect boundingRect = new Rect(lastX, alignmentBox.Top, advWidth + advFont, alignmentBox.Height); int endIndex = charIndex; if ((charIndex == 0 || s[charIndex-1] == ' ') && (charIndex != s.Length - 1)) { endIndex = charIndex + 1; } _CreateTextRun(boundingRect, trans, glyphs, node, textRunStartIndex, endIndex); lastX = lastX + advWidth + advSpecified; textRunStartIndex = charIndex+1; } cumulativeAdvWidth += advSpecified; } } } while (charIndex >= 0 && charIndex < s.Length-1); if (textRunStartIndex < s.Length) { //Last text run //For non-partitioned elements this will be the whole Glyphs element Rect boundingRect = new Rect(lastX, alignmentBox.Top, alignmentBox.Right-lastX, alignmentBox.Height); _CreateTextRun( boundingRect, trans, glyphs, node, textRunStartIndex, s.Length); } }
// FixedNode represents a leaf node. It contains a path // from root to the leaf in the form of child index. // [Level1 ChildIndex] [Level2 ChildIndex] [Level3 ChildIndex]... internal DependencyObject GetElement(FixedNode node) { int currentLevelIndex = node[1]; if (!(currentLevelIndex >= 0 && currentLevelIndex <= this.Children.Count)) { return null; } #if DEBUG if (node.ChildLevels > 1) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetUIElement {0} is nested element", node)); } #endif DependencyObject element = this.Children[currentLevelIndex]; for (int level = 2; level <= node.ChildLevels; level++) { // Follow the path if necessary currentLevelIndex = node[level]; if (element is Canvas) { // Canvas is a known S0 grouping element. // Boundary Node only would appear in first level! Debug.Assert(currentLevelIndex >= 0 && currentLevelIndex <= ((Canvas)element).Children.Count); element = ((Canvas)element).Children[currentLevelIndex]; } else { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GeElement {0} is non S0 grouping element in L[{1}]!", node, level)); IEnumerable currentChildrens = LogicalTreeHelper.GetChildren((DependencyObject)element); if (currentChildrens == null) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetElement {0} is NOT a grouping element in L[{1}]!!!", node, level)); return null; } // We have no uniform way to do random access for this element. // This should never happen for S0 conforming document. int childIndex = -1; IEnumerator itor = currentChildrens.GetEnumerator(); while (itor.MoveNext()) { childIndex++; if (childIndex == currentLevelIndex) { element = (DependencyObject)itor.Current; break; } } } } #if DEBUG if (!(element is Glyphs)) { DocumentsTrace.FixedFormat.FixedDocument.Trace(string.Format("FixedPage.GetElement{0} is non-Glyphs", node)); } #endif return element; }
//-------------------------------------------------------------------- // // Connstructors // //--------------------------------------------------------------------- #region Constructors internal FixedPosition(FixedNode fixedNode, int offset) { _fixedNode = fixedNode; _offset = offset; }
/// <summary> /// Returns a TextSegment that spans the line on which position is located. /// </summary> /// <param name="position"> /// Any oriented text position on the line. /// </param> /// <returns> /// TextSegment that spans the line on which position is located. /// </returns> /// <exception cref="System.InvalidOperationException"> /// Throws InvalidOperationException if IsValid is false. /// If IsValid returns false, Validate method must be called before /// calling this method. /// </exception> internal override TextSegment GetLineRange(ITextPointer position) { #if DEBUG DocumentsTrace.FixedTextOM.TextView.Trace(string.Format("GetLineRange {0}, {1}", (FixedTextPointer)position, position.LogicalDirection)); #endif FixedTextPointer ftp = Container.VerifyPosition(position); FixedPosition fixedp; if (!_GetFixedPosition(ftp, out fixedp)) { return new TextSegment(position, position, true); } int count = 0; FixedNode[] fixedNodes = Container.FixedTextBuilder.GetNextLine(fixedp.Node, true, ref count); if (fixedNodes == null) { // This will happen in the case of images fixedNodes = new FixedNode[] { fixedp.Node }; } FixedNode lastNode = fixedNodes[fixedNodes.Length - 1]; DependencyObject element = FixedPage.GetElement(lastNode); int lastIndex = 1; if (element is Glyphs) { lastIndex = ((Glyphs)element).UnicodeString.Length; } ITextPointer begin = _CreateTextPointer(new FixedPosition(fixedNodes[0], 0), LogicalDirection.Forward); ITextPointer end = _CreateTextPointer(new FixedPosition(lastNode, lastIndex), LogicalDirection.Backward); if (begin.CompareTo(end) > 0) { ITextPointer temp = begin; begin = end; end = temp; } return new TextSegment(begin, end, true); }
// Strongly typed compare function to avoid boxing // This function wil return 0 if two nodes are parent // and child relationship. // Positive means this node is before the input node. // Negative means this node is after the input node. public int CompareTo(FixedNode fixedNode) { int comp = this.Page.CompareTo(fixedNode.Page); if (comp == 0) { // compare index when two FixedNodes are in the same page int level = 1; while (level <= this.ChildLevels && level <= fixedNode.ChildLevels) { int thisIndex = this[level]; int fixedNodeIndex = fixedNode[level]; if (thisIndex == fixedNodeIndex) { level++; continue; } return thisIndex.CompareTo(fixedNodeIndex); } } return comp; }
// Strongly typed version of Equals to avoid boxing public bool Equals(FixedNode fixedp) { return (this.CompareTo(fixedp) == 0); }
//-------------------------------------------------------------------- // // Connstructors // //--------------------------------------------------------------------- #region Constructors internal FixedLineResult(FixedNode[] nodes, Rect layoutBox) { _nodes = nodes; _layoutBox = layoutBox; }
//-------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region public Methods public static FixedSOMTextRun Create(Rect boundingRect, GeneralTransform transform, Glyphs glyphs, FixedNode fixedNode, int startIndex, int endIndex, bool allowReverseGlyphs) { if (String.IsNullOrEmpty(glyphs.UnicodeString) || glyphs.FontRenderingEmSize <= 0) { return null; } FixedSOMTextRun run = new FixedSOMTextRun(boundingRect, transform, fixedNode, startIndex, endIndex); run._fontUri = glyphs.FontUri; run._cultureInfo = glyphs.Language.GetCompatibleCulture(); run._bidiLevel = glyphs.BidiLevel; run._isSideways = glyphs.IsSideways; run._fontSize = glyphs.FontRenderingEmSize; GlyphRun glyphRun = glyphs.ToGlyphRun(); GlyphTypeface gtf = glyphRun.GlyphTypeface; // Find font family // glyphs.FontUri, glyphRun.glyphTypeface gtf.FamilyNames.TryGetValue(run._cultureInfo, out run._fontFamily); if (run._fontFamily == null) { //Try getting the English name gtf.FamilyNames.TryGetValue(System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS, out run._fontFamily); } // Find font style (normal, italics, Oblique) // need to open Font file. run._fontStyle = gtf.Style; // Find font weight (bold, semibold, ExtraLight) run._fontWeight = gtf.Weight; // Find font stretch (UltraCondensed, SemiExpanded, etc) run._fontStretch = gtf.Stretch; //Height and width should be the same for x character run._defaultCharWidth = gtf.XHeight > 0 ? gtf.XHeight * glyphs.FontRenderingEmSize : glyphRun.AdvanceWidths[startIndex]; Transform trans = transform.AffineTransform; if (trans != null && !(trans.Value.IsIdentity)) { Matrix mat = trans.Value; double yScale = Math.Sqrt(mat.M12*mat.M12 + mat.M22*mat.M22); double xScale = Math.Sqrt(mat.M11 * mat.M11 + mat.M21 * mat.M21); run._fontSize *= yScale; run._defaultCharWidth *= xScale; } run._foreground = glyphs.Fill; String s = glyphs.UnicodeString; run.Text = s.Substring(startIndex, endIndex-startIndex); if (allowReverseGlyphs && run._bidiLevel == 0 && !run._isSideways && startIndex == 0 && endIndex == s.Length && String.IsNullOrEmpty(glyphs.CaretStops) && FixedTextBuilder.MostlyRTL(s)) { char[] chars = new char[run.Text.Length]; for (int i=0; i<run.Text.Length; i++) { chars[i] = run.Text[run.Text.Length - 1 - i]; } run._isReversed = true; run.Text = new string(chars); } if (s == "" && glyphs.Indices != null && glyphs.Indices.Length > 0) { run._isWhiteSpace = false; } else { run._isWhiteSpace = true; for (int i = 0; i < s.Length; i++) { if (!Char.IsWhiteSpace(s[i])) { run._isWhiteSpace = false; break; } } } return run; }
//-------------------------------------------------------------------- // // Constructors // //--------------------------------------------------------------------- #region Constructors private FixedSOMTextRun(Rect boundingRect, GeneralTransform trans, FixedNode fixedNode, int startIndex, int endIndex) : base(fixedNode, startIndex, endIndex, trans) { _boundingRect = trans.TransformBounds(boundingRect); }
private ITextPointer _GetTextPosition(FixedNode node, int charIndex) { FixedPosition fixedPosition = new FixedPosition(node, charIndex); // Create a FlowPosition to represent this fixed position FlowPosition flowHit = _panel.FixedContainer.FixedTextBuilder.CreateFlowPosition(fixedPosition); if (flowHit != null) { // Create a TextPointer from the flow position return new FixedTextPointer(false, LogicalDirection.Forward, flowHit); } return null; }
internal Glyphs GetGlyphsElement(FixedNode node) { return GetElement(node) as Glyphs; }