//------------------------------------------------------------------- // // Connstructors // //---------------------------------------------------------------------- #region Constructors internal FlowPosition(FixedTextContainer container, FlowNode node, int offset) { Debug.Assert(!FlowNode.IsNull(node)); _container = container; _flowNode = node; _offset = offset; }
//------------------------------------------------------------------- // // 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); }
//------------------------------------------------------- // Flow Order Helper Functions //------------------------------------------------------- // Insert a flow position before a given flow position // NOTE: flow fp will be modified internal void _FlowOrderInsertBefore(FlowNode nextFlow, FlowNode newFlow) { newFlow.SetFp(nextFlow.Fp); _flowOrder.Insert(newFlow.Fp, newFlow); // update all subsequent fps for (int i = newFlow.Fp + 1, n = _flowOrder.Count; i < n; i++) { _flowOrder[i].IncreaseFp(); } }
//-------------------------------------------------------------------- // // Private Methods // //--------------------------------------------------------------------- #region Private Methods // initialize the maps and edge nodes private void _Init() { // mutable boundary flow nodes _flowStart = new FlowNode(FlowOrderBoundaryScopeId, FlowNodeType.Boundary, null); _flowEnd = new FlowNode(FlowOrderBoundaryScopeId, FlowNodeType.Boundary, null); //_fixedOrder = new List<FixedOrderEntry>(); _flowOrder = new List<FlowNode>(); _flowOrder.Add(_flowStart); _flowStart.SetFp(0); _flowOrder.Add(_flowEnd); _flowEnd.SetFp(1); _mapping = new Hashtable(); }
//------------------------------------------------------- // Flow Order //------------------------------------------------------- // Insert a FlowNode before a given FlowNode // NOTE: FlowNode's Fp will be modified internal FlowNode FlowOrderInsertBefore(FlowNode nextFlow, FlowNode newFlow) { _FlowOrderInsertBefore(nextFlow, newFlow); return newFlow; }
//-------------------------------------------------------------------- // // Public Properties // //--------------------------------------------------------------------- //-------------------------------------------------------------------- // // Public Events // //--------------------------------------------------------------------- //-------------------------------------------------------------------- // // Internal Methods // //--------------------------------------------------------------------- #region Internal Methods //------------------------------------------------------- // Mapping //------------------------------------------------------- // Replace an existing FlowNode with a new set of FlowNode // Each has a mapped FixedNode set. internal void MappingReplace(FlowNode flowOld, List<FlowNode> flowNew) { Debug.Assert(flowOld.Type == FlowNodeType.Virtual || flowNew != null); // Insert a new entry into Flow Order for each new FlowNode int index = flowOld.Fp; _flowOrder.RemoveAt(index); _flowOrder.InsertRange(index, flowNew); for (int i = index; i < _flowOrder.Count; i++) { _flowOrder[i].SetFp(i); } }
internal bool IsVirtual(FlowNode flowNode) { return (flowNode.Type == FlowNodeType.Virtual); }
// return FlowNode within this range internal void GetFlowNodes(FlowPosition pEnd, out FlowNode[] flowNodes, out int offsetStart, out int offsetEnd) { Debug.Assert(this._OverlapAwareCompare(pEnd) < 0); flowNodes = null; offsetStart = 0; offsetEnd = 0; FlowPosition flowScan = GetClingPosition(LogicalDirection.Forward); offsetStart = flowScan._offset; ArrayList ar = new ArrayList(); int distance = GetDistance(pEnd); // keep moving until we hit distance while (distance > 0) { int scan = flowScan._vScan(LogicalDirection.Forward, distance); distance -= scan; if (flowScan.IsRun || flowScan.IsObject) { ar.Add(flowScan._flowNode); offsetEnd = flowScan._offset; } } flowNodes = (FlowNode [])ar.ToArray(typeof(FlowNode)); }
internal void GetFlowNode(LogicalDirection direction, out FlowNode flowNode, out int offsetStart) { FlowPosition fp = GetClingPosition(direction); offsetStart = fp._offset; flowNode = fp._flowNode; }
//-------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region Public Methods // force object comparision public static bool IsNull(FlowNode flow) { return (object)flow == null; }
//------------------------------------- // Flow Order //------------------------------------- internal void SetFlowBoundary(FlowNode flowStart, FlowNode flowEnd) { Debug.Assert(flowStart != null && flowStart.Type != FlowNodeType.Virtual); Debug.Assert(flowEnd != null && flowEnd.Type != FlowNodeType.Virtual); _flowStart = flowStart; _flowEnd = flowEnd; }
// Token: 0x06002D2D RID: 11565 RVA: 0x000CC0C0 File Offset: 0x000CA2C0 internal FlowNode FlowOrderInsertBefore(FlowNode nextFlow, FlowNode newFlow) { this._FlowOrderInsertBefore(nextFlow, newFlow); return(newFlow); }
//-------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region Public Methods // force object comparision public static bool IsNull(FlowNode flow) { return((object)flow == null); }
//-------------------------------------------------------------------- // // Private Methods // //--------------------------------------------------------------------- #region Private Methods //-------------------------------------------------------------------- // Helper functions that could result in de-virtualization //--------------------------------------------------------------------- // scan one node forward, return characters/symbols passed // limit < 0 means scan entire node. private int _vScan(LogicalDirection dir, int limit) { if (limit == 0) { return(0); } FlowNode flowNode = _flowNode; int scanned = 0; if (dir == LogicalDirection.Forward) { if (_offset == _NodeLength || flowNode.Type == FlowNodeType.Boundary) { // This position is at right side of a FlowNode flowNode = _xGetNextFlowNode(); if (FlowNode.IsNull(flowNode)) { return(scanned); } _flowNode = flowNode; scanned = _NodeLength; } else { scanned = _NodeLength - _offset; } _offset = _NodeLength; if (limit > 0 && scanned > limit) { int back = scanned - limit; scanned = limit; _offset -= back; } } else { Debug.Assert(dir == LogicalDirection.Backward); if (_offset == 0 || flowNode.Type == FlowNodeType.Boundary) { // This position is at left side of a FlowNode // look for previous run flowNode = _xGetPreviousFlowNode(); if (FlowNode.IsNull(flowNode)) { return(scanned); } _flowNode = flowNode; scanned = _NodeLength; } else { scanned = _offset; } _offset = 0; if (limit > 0 && scanned > limit) { int back = scanned - limit; scanned = limit; _offset += back; } } return(scanned); }
internal bool IsVirtual(FlowNode flowNode) { return(flowNode.Type == FlowNodeType.Virtual); }
internal void RenderFlowNode(DrawingContext dc) { FormattedText ft; FixedNode fixedNode; FixedSOMElement[] somElements; String ouptputString; FixedElement fixedElement; Random random = new Random(); CultureInfo EnglishCulture = System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS; FixedPage fp = _fixedTextBuilder.FixedTextContainer.FixedDocument.GetFixedPage(PageIndex); // //Iterate through flow node to draw Transparent Rect and draw its index // Point prevTextPoint = new Point(0, 0); DpiScale dpi = fp.GetDpi(); for (int i = FlowStart.Fp; i <= FlowEnd.Fp; i++) { FlowNode fn = _fixedTextBuilder.FixedFlowMap[i]; switch (fn.Type) { case FlowNodeType.Boundary: case FlowNodeType.Virtual: // this two cases won't happen. Debug.Assert(false); break; case FlowNodeType.Start: case FlowNodeType.End: { fixedElement = fn.Cookie as FixedElement; String typeString = fixedElement.Type.ToString(); int indexofDot = typeString.LastIndexOf('.'); ouptputString = String.Format("{0}-{1}", fn.ToString(), typeString.Substring(indexofDot + 1)); ft = new FormattedText(ouptputString, EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkGreen, dpi.PixelsPerDip); // Ideally, for FlowNodeType.Start, this should find next FlowNode with physical location, // and draw it around the physical location. prevTextPoint = CreateFromLastTextPoint(prevTextPoint); dc.DrawText(ft, prevTextPoint); break; } case FlowNodeType.Noop: ft = new FormattedText(fn.ToString(), EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkGreen, dpi.PixelsPerDip); prevTextPoint = CreateFromLastTextPoint(prevTextPoint); dc.DrawText(ft, prevTextPoint); break; case FlowNodeType.Run: // // Paint the region. The rect is the union of child glyphs. // Glyphs glyphs; Rect flowRunBox = Rect.Empty; Rect glyphBox; somElements = _fixedTextBuilder.FixedFlowMap.FlowNodes[fn.Fp].FixedSOMElements; foreach (FixedSOMElement currentSomeElement in somElements) { FixedNode currentFixedNode = currentSomeElement.FixedNode; int startIndex = currentSomeElement.StartIndex; int endIndex = currentSomeElement.EndIndex; // same as (_IsBoundaryFixedNode(currentFixedNode)) if (currentFixedNode.Page == FixedFlowMap.FixedOrderStartPage || currentFixedNode.Page == FixedFlowMap.FixedOrderEndPage || currentFixedNode[1] == FixedFlowMap.FixedOrderStartVisual || currentFixedNode[1] == FixedFlowMap.FixedOrderEndVisual) { continue; } glyphs = fp.GetGlyphsElement(currentFixedNode); Debug.Assert(glyphs != null); glyphBox = FixedTextView._GetGlyphRunDesignRect(glyphs, startIndex, endIndex); if (!glyphBox.IsEmpty) { GeneralTransform g = glyphs.TransformToAncestor(fp); glyphBox = g.TransformBounds(glyphBox); } flowRunBox.Union(glyphBox); } if (flowRunBox.IsEmpty) { Debug.Assert(false); } prevTextPoint.X = flowRunBox.Right; prevTextPoint.Y = flowRunBox.Bottom - random.Next(15); // Draw something the upper left corner of region. ft = new FormattedText(fn.ToString() + "-" + Convert.ToString((int)(fn.Cookie)) + "-" + Convert.ToString(somElements.Length), EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkBlue, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); Pen pen = new Pen(Brushes.Blue, 2); flowRunBox.Inflate(random.Next(3), random.Next(3)); DrawRectOutline(dc, pen, flowRunBox); break; case FlowNodeType.Object: // // Find the mapping fixed node // somElements = _fixedTextBuilder.FixedFlowMap.FlowNodes[fn.Fp].FixedSOMElements; foreach (FixedSOMElement currentSomeElement in somElements) { fixedNode = currentSomeElement.FixedNode; DependencyObject dependencyObject = fp.GetElement(fixedNode); Image image = dependencyObject as Image; Path path = dependencyObject as Path; if (image != null || path != null) { Rect imageRect, boundingRect = Rect.Empty; // // Get Image bounding box. // GeneralTransform transform = ((Visual)dependencyObject).TransformToAncestor(fp); // You can't use GetContentBounds inside OnRender if (image != null) { boundingRect = new Rect(0, 0, image.Width, image.Height); } else { boundingRect = path.Data.Bounds; } if (!boundingRect.IsEmpty) { imageRect = transform.TransformBounds(boundingRect); // Image might overlap, inflate the box. imageRect.Inflate(3, 3); dc.DrawRectangle(Brushes.CadetBlue, null, imageRect); prevTextPoint.X = imageRect.Right; prevTextPoint.Y = imageRect.Top; } } else { // // If the object is the Image type(that is not likey). // Use the last Point to infer a comment area! // Debug.Assert(false); } fixedElement = fn.Cookie as FixedElement; ft = new FormattedText(fn.ToString(), EnglishCulture, FlowDirection.LeftToRight, new Typeface("Courier New"), 8, Brushes.DarkGreen, dpi.PixelsPerDip); dc.DrawText(ft, prevTextPoint); } break; default: Debug.Assert(false); break; } } }